1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <namedefdlg.hxx>
12 #include <vcl/settings.hxx>
13 #include <formula/errorcodes.hxx>
14 #include <sfx2/app.hxx>
15 #include <unotools/charclass.hxx>
17 #include <compiler.hxx>
18 #include <document.hxx>
19 #include <globstr.hrc>
20 #include <scresid.hxx>
21 #include <globalnames.hxx>
22 #include <rangenam.hxx>
23 #include <reffact.hxx>
24 #include <undorangename.hxx>
25 #include <tabvwsh.hxx>
26 #include <tokenarray.hxx>
28 ScNameDefDlg::ScNameDefDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
, weld::Window
* pParent
,
29 const ScViewData
& rViewData
, const std::map
<OUString
, ScRangeName
*>& aRangeMap
,
30 const ScAddress
& aCursorPos
, const bool bUndo
)
31 : ScAnyRefDlgController( pB
, pCW
, pParent
, "modules/scalc/ui/definename.ui", "DefineNameDialog")
33 , mrDoc(rViewData
.GetDocument())
34 , mpDocShell ( rViewData
.GetDocShell() )
35 , maCursorPos( aCursorPos
)
36 , maGlobalNameStr ( ScResId(STR_GLOBAL_SCOPE
) )
37 , maErrInvalidNameStr( ScResId(STR_ERR_NAME_INVALID
))
38 , maErrInvalidNameCellRefStr( ScResId(STR_ERR_NAME_INVALID_CELL_REF
))
39 , maErrNameInUse ( ScResId(STR_ERR_NAME_EXISTS
))
40 , maRangeMap( aRangeMap
)
41 , m_xEdName(m_xBuilder
->weld_entry("edit"))
42 , m_xEdRange(new formula::RefEdit(m_xBuilder
->weld_entry("range")))
43 , m_xRbRange(new formula::RefButton(m_xBuilder
->weld_button("refbutton")))
44 , m_xLbScope(m_xBuilder
->weld_combo_box("scope"))
45 , m_xBtnRowHeader(m_xBuilder
->weld_check_button("rowheader"))
46 , m_xBtnColHeader(m_xBuilder
->weld_check_button("colheader"))
47 , m_xBtnPrintArea(m_xBuilder
->weld_check_button("printarea"))
48 , m_xBtnCriteria(m_xBuilder
->weld_check_button("filter"))
49 , m_xBtnAdd(m_xBuilder
->weld_button("add"))
50 , m_xBtnCancel(m_xBuilder
->weld_button("cancel"))
51 , m_xFtInfo(m_xBuilder
->weld_label("label"))
52 , m_xExpander(m_xBuilder
->weld_expander("more"))
53 , m_xFtRange(m_xBuilder
->weld_label("label3"))
55 m_xEdRange
->SetReferences(this, m_xFtRange
.get());
56 m_xRbRange
->SetReferences(this, m_xEdRange
.get());
57 maStrInfoDefault
= m_xFtInfo
->get_label();
59 // Initialize scope list.
60 m_xLbScope
->append_text(maGlobalNameStr
);
61 m_xLbScope
->set_active(0);
62 SCTAB n
= mrDoc
.GetTableCount();
63 for (SCTAB i
= 0; i
< n
; ++i
)
66 mrDoc
.GetName(i
, aTabName
);
67 m_xLbScope
->append_text(aTabName
);
70 m_xBtnCancel
->connect_clicked( LINK( this, ScNameDefDlg
, CancelBtnHdl
));
71 m_xBtnAdd
->connect_clicked( LINK( this, ScNameDefDlg
, AddBtnHdl
));
72 m_xEdName
->connect_changed( LINK( this, ScNameDefDlg
, NameModifyHdl
));
73 m_xEdRange
->SetGetFocusHdl( LINK( this, ScNameDefDlg
, AssignGetFocusHdl
) );
75 m_xBtnAdd
->set_sensitive(false); // empty name is invalid
79 rViewData
.GetSimpleArea( aRange
);
80 OUString
aAreaStr(aRange
.Format(mrDoc
, ScRefFlags::RANGE_ABS_3D
,
81 ScAddress::Details(mrDoc
.GetAddressConvention(), 0, 0)));
83 m_xEdRange
->SetText( aAreaStr
);
85 m_xEdName
->grab_focus();
86 m_xEdName
->select_region(0, -1);
89 ScNameDefDlg::~ScNameDefDlg()
93 void ScNameDefDlg::CancelPushed()
99 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
100 pViewSh
->SwitchBetweenRefDialogs(this);
104 bool ScNameDefDlg::IsFormulaValid()
106 ScCompiler
aComp(mrDoc
, maCursorPos
, mrDoc
.GetGrammar());
107 std::unique_ptr
<ScTokenArray
> pCode
= aComp
.CompileString(m_xEdRange
->GetText());
108 if (pCode
->GetCodeError() != FormulaError::NONE
)
119 bool ScNameDefDlg::IsNameValid()
121 OUString aScope
= m_xLbScope
->get_active_text();
122 OUString aName
= m_xEdName
->get_text();
124 ScRangeName
* pRangeName
= nullptr;
125 if(aScope
== maGlobalNameStr
)
127 pRangeName
= maRangeMap
.find(OUString(STR_GLOBAL_RANGE_NAME
))->second
;
131 pRangeName
= maRangeMap
.find(aScope
)->second
;
134 ScRangeData::IsNameValidType eType
;
135 m_xFtInfo
->set_label_type(weld::LabelType::Normal
);
136 if ( aName
.isEmpty() )
138 m_xBtnAdd
->set_sensitive(false);
139 m_xFtInfo
->set_label(maStrInfoDefault
);
142 else if ((eType
= ScRangeData::IsNameValid( aName
, mrDoc
)) != ScRangeData::NAME_VALID
)
144 m_xFtInfo
->set_label_type(weld::LabelType::Error
);
145 if (eType
== ScRangeData::NAME_INVALID_BAD_STRING
)
147 m_xFtInfo
->set_label(maErrInvalidNameStr
);
149 else if (eType
== ScRangeData::NAME_INVALID_CELL_REF
)
151 m_xFtInfo
->set_label(maErrInvalidNameCellRefStr
);
153 m_xBtnAdd
->set_sensitive(false);
156 else if (pRangeName
->findByUpperName(ScGlobal::getCharClassPtr()->uppercase(aName
)))
158 m_xFtInfo
->set_label_type(weld::LabelType::Error
);
159 m_xFtInfo
->set_label(maErrNameInUse
);
160 m_xBtnAdd
->set_sensitive(false);
164 if (!IsFormulaValid())
166 m_xFtInfo
->set_label_type(weld::LabelType::Error
);
167 m_xBtnAdd
->set_sensitive(false);
171 m_xFtInfo
->set_label(maStrInfoDefault
);
172 m_xBtnAdd
->set_sensitive(true);
176 void ScNameDefDlg::AddPushed()
178 OUString aScope
= m_xLbScope
->get_active_text();
179 OUString aName
= m_xEdName
->get_text();
180 OUString aExpression
= m_xEdRange
->GetText();
186 if (aScope
.isEmpty())
191 ScRangeName
* pRangeName
= nullptr;
192 if(aScope
== maGlobalNameStr
)
194 pRangeName
= maRangeMap
.find(OUString(STR_GLOBAL_RANGE_NAME
))->second
;
198 pRangeName
= maRangeMap
.find(aScope
)->second
;
203 if (!IsNameValid()) //should not happen, but make sure we don't break anything
207 ScRangeData::Type nType
= ScRangeData::Type::Name
;
209 ScRangeData
* pNewEntry
= new ScRangeData( mrDoc
,
215 if ( m_xBtnRowHeader
->get_active() ) nType
|= ScRangeData::Type::RowHeader
;
216 if ( m_xBtnColHeader
->get_active() ) nType
|= ScRangeData::Type::ColHeader
;
217 if ( m_xBtnPrintArea
->get_active() ) nType
|= ScRangeData::Type::PrintArea
;
218 if ( m_xBtnCriteria
->get_active() ) nType
|= ScRangeData::Type::Criteria
;
220 pNewEntry
->AddType(nType
);
222 // aExpression valid?
223 if ( FormulaError::NONE
== pNewEntry
->GetErrCode() )
225 if ( !pRangeName
->insert( pNewEntry
, false /*bReuseFreeIndex*/ ) )
230 // this means we called directly through the menu
233 // if no table with that name is found, assume global range name
234 if (!mrDoc
.GetTable(aScope
, nTab
))
237 assert( pNewEntry
); // undo of no insertion smells fishy
239 mpDocShell
->GetUndoManager()->AddUndoAction(
240 std::make_unique
<ScUndoAddRangeData
>( mpDocShell
, pNewEntry
, nTab
) );
242 // set table stream invalid, otherwise RangeName won't be saved if no other
243 // call invalidates the stream
245 mrDoc
.SetStreamValid(nTab
, false);
246 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged
) );
247 mpDocShell
->SetDocumentModified();
254 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
255 pViewSh
->SwitchBetweenRefDialogs(this);
261 m_xEdRange
->GrabFocus();
262 m_xEdRange
->SelectAll();
267 void ScNameDefDlg::GetNewData(OUString
& rName
, OUString
& rScope
)
273 bool ScNameDefDlg::IsRefInputMode() const
275 return m_xEdRange
->GetWidget()->get_sensitive();
278 void ScNameDefDlg::RefInputDone( bool bForced
)
280 ScAnyRefDlgController::RefInputDone(bForced
);
284 void ScNameDefDlg::SetReference( const ScRange
& rRef
, ScDocument
& rDocP
)
286 if (m_xEdRange
->GetWidget()->get_sensitive())
288 if ( rRef
.aStart
!= rRef
.aEnd
)
289 RefInputStart(m_xEdRange
.get());
290 OUString
aRefStr(rRef
.Format(rDocP
, ScRefFlags::RANGE_ABS_3D
,
291 ScAddress::Details(rDocP
.GetAddressConvention(), 0, 0)));
292 m_xEdRange
->SetRefString( aRefStr
);
296 void ScNameDefDlg::Close()
298 DoClose( ScNameDefDlgWrapper::GetChildWindowId() );
301 void ScNameDefDlg::SetActive()
303 m_xEdRange
->GrabFocus();
307 IMPL_LINK_NOARG(ScNameDefDlg
, CancelBtnHdl
, weld::Button
&, void)
312 IMPL_LINK_NOARG(ScNameDefDlg
, AddBtnHdl
, weld::Button
&, void)
317 IMPL_LINK_NOARG(ScNameDefDlg
, NameModifyHdl
, weld::Entry
&, void)
322 IMPL_LINK_NOARG(ScNameDefDlg
, AssignGetFocusHdl
, formula::RefEdit
&, void)
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */