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 <formula/errorcodes.hxx>
13 #include <sfx2/app.hxx>
14 #include <unotools/charclass.hxx>
16 #include <compiler.hxx>
17 #include <document.hxx>
18 #include <globstr.hrc>
19 #include <scresid.hxx>
20 #include <globalnames.hxx>
21 #include <rangenam.hxx>
22 #include <reffact.hxx>
23 #include <undorangename.hxx>
24 #include <tabvwsh.hxx>
25 #include <tokenarray.hxx>
27 ScNameDefDlg::ScNameDefDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
, weld::Window
* pParent
,
28 const ScViewData
& rViewData
, std::map
<OUString
, ScRangeName
*>&& aRangeMap
,
29 const ScAddress
& aCursorPos
, const bool bUndo
)
30 : ScAnyRefDlgController( pB
, pCW
, pParent
, "modules/scalc/ui/definename.ui", "DefineNameDialog")
32 , mrDoc(rViewData
.GetDocument())
33 , mpDocShell ( rViewData
.GetDocShell() )
34 , maCursorPos( aCursorPos
)
35 , maGlobalNameStr ( ScResId(STR_GLOBAL_SCOPE
) )
36 , maErrInvalidNameStr( ScResId(STR_ERR_NAME_INVALID
))
37 , maErrInvalidNameCellRefStr( ScResId(STR_ERR_NAME_INVALID_CELL_REF
))
38 , maErrNameInUse ( ScResId(STR_ERR_NAME_EXISTS
))
39 , maRangeMap( std::move(aRangeMap
) )
40 , m_xEdName(m_xBuilder
->weld_entry("edit"))
41 , m_xEdRange(new formula::RefEdit(m_xBuilder
->weld_entry("range")))
42 , m_xRbRange(new formula::RefButton(m_xBuilder
->weld_button("refbutton")))
43 , m_xLbScope(m_xBuilder
->weld_combo_box("scope"))
44 , m_xBtnRowHeader(m_xBuilder
->weld_check_button("rowheader"))
45 , m_xBtnColHeader(m_xBuilder
->weld_check_button("colheader"))
46 , m_xBtnPrintArea(m_xBuilder
->weld_check_button("printarea"))
47 , m_xBtnCriteria(m_xBuilder
->weld_check_button("filter"))
48 , m_xBtnAdd(m_xBuilder
->weld_button("add"))
49 , m_xBtnCancel(m_xBuilder
->weld_button("cancel"))
50 , m_xFtInfo(m_xBuilder
->weld_label("label"))
51 , m_xFtRange(m_xBuilder
->weld_label("label3"))
53 m_xEdRange
->SetReferences(this, m_xFtRange
.get());
54 m_xRbRange
->SetReferences(this, m_xEdRange
.get());
55 maStrInfoDefault
= m_xFtInfo
->get_label();
57 // Initialize scope list.
58 m_xLbScope
->append_text(maGlobalNameStr
);
59 m_xLbScope
->set_active(0);
60 SCTAB n
= mrDoc
.GetTableCount();
61 for (SCTAB i
= 0; i
< n
; ++i
)
64 mrDoc
.GetName(i
, aTabName
);
65 m_xLbScope
->append_text(aTabName
);
68 m_xBtnCancel
->connect_clicked( LINK( this, ScNameDefDlg
, CancelBtnHdl
));
69 m_xBtnAdd
->connect_clicked( LINK( this, ScNameDefDlg
, AddBtnHdl
));
70 m_xEdName
->connect_changed( LINK( this, ScNameDefDlg
, NameModifyHdl
));
71 m_xEdRange
->SetGetFocusHdl( LINK( this, ScNameDefDlg
, AssignGetFocusHdl
) );
73 m_xBtnAdd
->set_sensitive(false); // empty name is invalid
77 rViewData
.GetSimpleArea( aRange
);
78 OUString
aAreaStr(aRange
.Format(mrDoc
, ScRefFlags::RANGE_ABS_3D
,
79 ScAddress::Details(mrDoc
.GetAddressConvention(), 0, 0)));
81 m_xEdRange
->SetText( aAreaStr
);
83 m_xEdName
->grab_focus();
84 m_xEdName
->select_region(0, -1);
87 ScNameDefDlg::~ScNameDefDlg()
91 void ScNameDefDlg::CancelPushed()
97 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
98 pViewSh
->SwitchBetweenRefDialogs(this);
102 bool ScNameDefDlg::IsFormulaValid()
104 ScCompiler
aComp(mrDoc
, maCursorPos
, mrDoc
.GetGrammar());
105 std::unique_ptr
<ScTokenArray
> pCode
= aComp
.CompileString(m_xEdRange
->GetText());
106 if (pCode
->GetCodeError() != FormulaError::NONE
)
117 bool ScNameDefDlg::IsNameValid()
119 OUString aScope
= m_xLbScope
->get_active_text();
120 OUString aName
= m_xEdName
->get_text();
122 bool bIsNameValid
= true;
123 OUString aHelpText
= maStrInfoDefault
;
125 ScRangeName
* pRangeName
= nullptr;
126 if(aScope
== maGlobalNameStr
)
128 pRangeName
= maRangeMap
.find(OUString(STR_GLOBAL_RANGE_NAME
))->second
;
132 pRangeName
= maRangeMap
.find(aScope
)->second
;
135 ScRangeData::IsNameValidType eType
;
136 if ( aName
.isEmpty() )
138 bIsNameValid
= false;
140 else if ((eType
= ScRangeData::IsNameValid(aName
, mrDoc
))
141 != ScRangeData::IsNameValidType::NAME_VALID
)
143 if (eType
== ScRangeData::IsNameValidType::NAME_INVALID_BAD_STRING
)
145 aHelpText
= maErrInvalidNameStr
;
147 else if (eType
== ScRangeData::IsNameValidType::NAME_INVALID_CELL_REF
)
149 aHelpText
= maErrInvalidNameCellRefStr
;
151 bIsNameValid
= false;
153 else if (pRangeName
->findByUpperName(ScGlobal::getCharClass().uppercase(aName
)))
155 aHelpText
= maErrNameInUse
;
156 bIsNameValid
= false;
159 if (!IsFormulaValid())
161 bIsNameValid
= false;
164 m_xEdName
->set_tooltip_text(aHelpText
);
165 m_xEdName
->set_message_type(bIsNameValid
|| aName
.isEmpty() ? weld::EntryMessageType::Normal
166 : weld::EntryMessageType::Error
);
167 m_xBtnAdd
->set_sensitive(bIsNameValid
);
171 void ScNameDefDlg::AddPushed()
173 OUString aScope
= m_xLbScope
->get_active_text();
174 OUString aName
= m_xEdName
->get_text();
175 OUString aExpression
= m_xEdRange
->GetText();
181 if (aScope
.isEmpty())
186 ScRangeName
* pRangeName
= nullptr;
187 if(aScope
== maGlobalNameStr
)
189 pRangeName
= maRangeMap
.find(OUString(STR_GLOBAL_RANGE_NAME
))->second
;
193 pRangeName
= maRangeMap
.find(aScope
)->second
;
198 if (!IsNameValid()) //should not happen, but make sure we don't break anything
202 ScRangeData::Type nType
= ScRangeData::Type::Name
;
204 ScRangeData
* pNewEntry
= new ScRangeData( mrDoc
,
210 if ( m_xBtnRowHeader
->get_active() ) nType
|= ScRangeData::Type::RowHeader
;
211 if ( m_xBtnColHeader
->get_active() ) nType
|= ScRangeData::Type::ColHeader
;
212 if ( m_xBtnPrintArea
->get_active() ) nType
|= ScRangeData::Type::PrintArea
;
213 if ( m_xBtnCriteria
->get_active() ) nType
|= ScRangeData::Type::Criteria
;
215 pNewEntry
->AddType(nType
);
217 // aExpression valid?
218 if ( FormulaError::NONE
== pNewEntry
->GetErrCode() )
220 if ( !pRangeName
->insert( pNewEntry
, false /*bReuseFreeIndex*/ ) )
225 // this means we called directly through the menu
228 // if no table with that name is found, assume global range name
229 if (!mrDoc
.GetTable(aScope
, nTab
))
232 assert( pNewEntry
); // undo of no insertion smells fishy
234 mpDocShell
->GetUndoManager()->AddUndoAction(
235 std::make_unique
<ScUndoAddRangeData
>( mpDocShell
, pNewEntry
, nTab
) );
237 // set table stream invalid, otherwise RangeName won't be saved if no other
238 // call invalidates the stream
240 mrDoc
.SetStreamValid(nTab
, false);
241 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged
) );
242 mpDocShell
->SetDocumentModified();
249 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
250 pViewSh
->SwitchBetweenRefDialogs(this);
256 m_xEdRange
->GrabFocus();
257 m_xEdRange
->SelectAll();
262 void ScNameDefDlg::GetNewData(OUString
& rName
, OUString
& rScope
)
268 bool ScNameDefDlg::IsRefInputMode() const
270 return m_xEdRange
->GetWidget()->get_sensitive();
273 void ScNameDefDlg::RefInputDone( bool bForced
)
275 ScAnyRefDlgController::RefInputDone(bForced
);
279 void ScNameDefDlg::SetReference( const ScRange
& rRef
, ScDocument
& rDocP
)
281 if (m_xEdRange
->GetWidget()->get_sensitive())
283 if ( rRef
.aStart
!= rRef
.aEnd
)
284 RefInputStart(m_xEdRange
.get());
285 OUString
aRefStr(rRef
.Format(rDocP
, ScRefFlags::RANGE_ABS_3D
,
286 ScAddress::Details(rDocP
.GetAddressConvention(), 0, 0)));
287 m_xEdRange
->SetRefString( aRefStr
);
291 void ScNameDefDlg::Close()
293 DoClose( ScNameDefDlgWrapper::GetChildWindowId() );
296 void ScNameDefDlg::SetActive()
298 m_xEdRange
->GrabFocus();
302 IMPL_LINK_NOARG(ScNameDefDlg
, CancelBtnHdl
, weld::Button
&, void)
307 IMPL_LINK_NOARG(ScNameDefDlg
, AddBtnHdl
, weld::Button
&, void)
312 IMPL_LINK_NOARG(ScNameDefDlg
, NameModifyHdl
, weld::Entry
&, void)
317 IMPL_LINK_NOARG(ScNameDefDlg
, AssignGetFocusHdl
, formula::RefEdit
&, void)
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */