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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "reffact.hxx"
22 #include "document.hxx"
23 #include "docfunc.hxx"
24 #include "scresid.hxx"
25 #include "globstr.hrc"
26 #include "namedlg.hxx"
27 #include "viewdata.hxx"
28 #include "tabvwsh.hxx"
30 #include "globalnames.hxx"
31 #include "tokenarray.hxx"
33 #include <sfx2/app.hxx>
35 #include <vcl/msgbox.hxx>
36 #include <vcl/settings.hxx>
38 #include <o3tl/make_unique.hxx>
44 ScNameDlg::ScNameDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
, vcl::Window
* pParent
,
45 ScViewData
* ptrViewData
,
46 const ScAddress
& aCursorPos
,
47 std::map
<OUString
, std::unique_ptr
<ScRangeName
>> *const pRangeMap
)
48 : ScAnyRefDlg(pB
, pCW
, pParent
, "ManageNamesDialog", "modules/scalc/ui/managenamesdialog.ui")
50 , maGlobalNameStr(ScGlobal::GetRscString(STR_GLOBAL_SCOPE
))
51 , maErrInvalidNameStr(ScGlobal::GetRscString(STR_ERR_NAME_INVALID
))
52 , maErrNameInUse(ScGlobal::GetRscString(STR_ERR_NAME_EXISTS
))
53 , maStrMultiSelect(ScGlobal::GetRscString(STR_MULTI_SELECT
))
55 , mpViewData(ptrViewData
)
56 , mpDoc(ptrViewData
->GetDocument())
57 , maCursorPos(aCursorPos
)
59 , mbDataChanged(false)
60 , mbCloseWithoutUndo(false)
62 get(m_pEdName
, "name");
63 get(m_pEdAssign
, "range");
64 m_pEdAssign
->SetReferences(this, m_pEdName
);
65 get(m_pRbAssign
, "assign");
66 m_pRbAssign
->SetReferences(this, m_pEdAssign
);
67 get(m_pLbScope
, "scope");
68 get(m_pBtnPrintArea
, "printrange");
69 get(m_pBtnColHeader
, "colheader");
70 get(m_pBtnCriteria
, "filter");
71 get(m_pBtnRowHeader
, "rowheader");
72 get(m_pBtnAdd
, "add");
73 get(m_pBtnDelete
, "delete");
75 get(m_pBtnCancel
, "cancel");
76 get(m_pFtInfo
, "info");
77 maStrInfoDefault
= m_pFtInfo
->GetText();
78 m_pFtInfo
->SetText(OUString());
82 std::map
<OUString
, ScRangeName
*> aRangeMap
;
83 mpDoc
->GetRangeNameMap(aRangeMap
);
84 std::map
<OUString
, ScRangeName
*>::iterator itr
= aRangeMap
.begin(), itrEnd
= aRangeMap
.end();
85 for (; itr
!= itrEnd
; ++itr
)
87 OUString
aTemp(itr
->first
);
88 m_RangeMap
.insert(std::make_pair(aTemp
,
89 o3tl::make_unique
<ScRangeName
>(*itr
->second
)));
94 m_RangeMap
.swap(*pRangeMap
);
99 ScNameDlg::~ScNameDlg()
104 void ScNameDlg::dispose()
106 m_pRangeManagerTable
.disposeAndClear();
111 m_pBtnPrintArea
.clear();
112 m_pBtnColHeader
.clear();
113 m_pBtnCriteria
.clear();
114 m_pBtnRowHeader
.clear();
116 m_pBtnDelete
.clear();
118 m_pBtnCancel
.clear();
120 ScAnyRefDlg::dispose();
123 void ScNameDlg::Init()
127 OSL_ENSURE( mpViewData
&& mpDoc
, "ViewData oder Document nicht gefunden!" );
130 m_pFtInfo
->SetStyle(WB_VCENTER
);
132 SvSimpleTableContainer
*pCtrl
= get
<SvSimpleTableContainer
>("names");
133 pCtrl
->set_height_request(pCtrl
->GetTextHeight()*12);
135 m_pRangeManagerTable
= VclPtr
<ScRangeManagerTable
>::Create(*pCtrl
, m_RangeMap
, maCursorPos
);
136 m_pRangeManagerTable
->setInitListener(this);
137 m_pRangeManagerTable
->SetSelectHdl( LINK( this, ScNameDlg
, SelectionChangedHdl_Impl
) );
138 m_pRangeManagerTable
->SetDeselectHdl( LINK( this, ScNameDlg
, SelectionChangedHdl_Impl
) );
140 m_pBtnOk
->SetClickHdl ( LINK( this, ScNameDlg
, OkBtnHdl
) );
141 m_pBtnCancel
->SetClickHdl ( LINK( this, ScNameDlg
, CancelBtnHdl
) );
142 m_pBtnAdd
->SetClickHdl ( LINK( this, ScNameDlg
, AddBtnHdl
) );
143 m_pEdAssign
->SetGetFocusHdl( LINK( this, ScNameDlg
, AssignGetFocusHdl
) );
144 m_pEdAssign
->SetModifyHdl ( LINK( this, ScNameDlg
, EdModifyHdl
) );
145 m_pEdName
->SetModifyHdl ( LINK( this, ScNameDlg
, EdModifyHdl
) );
146 m_pLbScope
->SetSelectHdl( LINK(this, ScNameDlg
, ScopeChangedHdl
) );
147 m_pBtnDelete
->SetClickHdl ( LINK( this, ScNameDlg
, RemoveBtnHdl
) );
148 m_pBtnPrintArea
->SetToggleHdl( LINK(this, ScNameDlg
, EdModifyCheckBoxHdl
) );
149 m_pBtnCriteria
->SetToggleHdl( LINK(this, ScNameDlg
, EdModifyCheckBoxHdl
) );
150 m_pBtnRowHeader
->SetToggleHdl( LINK(this, ScNameDlg
, EdModifyCheckBoxHdl
) );
151 m_pBtnColHeader
->SetToggleHdl( LINK(this, ScNameDlg
, EdModifyCheckBoxHdl
) );
153 // Initialize scope list.
154 m_pLbScope
->InsertEntry(maGlobalNameStr
);
155 m_pLbScope
->SelectEntryPos(0);
156 SCTAB n
= mpDoc
->GetTableCount();
157 for (SCTAB i
= 0; i
< n
; ++i
)
160 mpDoc
->GetName(i
, aTabName
);
161 m_pLbScope
->InsertEntry(aTabName
);
164 CheckForEmptyTable();
167 bool ScNameDlg::IsRefInputMode() const
169 return m_pEdAssign
->IsEnabled();
172 void ScNameDlg::RefInputDone( bool bForced
)
174 ScAnyRefDlg::RefInputDone(bForced
);
175 EdModifyHdl(*m_pEdAssign
);
178 void ScNameDlg::SetReference( const ScRange
& rRef
, ScDocument
* pDocP
)
180 if ( m_pEdAssign
->IsEnabled() )
182 if ( rRef
.aStart
!= rRef
.aEnd
)
183 RefInputStart(m_pEdAssign
);
184 OUString
aRefStr(rRef
.Format(ScRefFlags::RANGE_ABS_3D
, pDocP
,
185 ScAddress::Details(pDocP
->GetAddressConvention(), 0, 0)));
186 m_pEdAssign
->SetRefString( aRefStr
);
190 bool ScNameDlg::Close()
192 if (mbDataChanged
&& !mbCloseWithoutUndo
)
193 mpViewData
->GetDocFunc().ModifyAllRangeNames(m_RangeMap
);
194 return DoClose( ScNameDlgWrapper::GetChildWindowId() );
197 void ScNameDlg::tableInitialized()
199 if (m_pRangeManagerTable
->GetSelectionCount())
203 void ScNameDlg::CheckForEmptyTable()
205 if (!m_pRangeManagerTable
->GetEntryCount())
207 m_pBtnDelete
->Disable();
208 m_pEdAssign
->Disable();
209 m_pRbAssign
->Disable();
210 m_pEdName
->Disable();
211 m_pLbScope
->Disable();
213 m_pBtnCriteria
->Disable();
214 m_pBtnPrintArea
->Disable();
215 m_pBtnColHeader
->Disable();
216 m_pBtnRowHeader
->Disable();
220 m_pBtnDelete
->Enable();
221 m_pEdAssign
->Enable();
222 m_pRbAssign
->Enable();
224 m_pLbScope
->Enable();
226 m_pBtnCriteria
->Enable();
227 m_pBtnPrintArea
->Enable();
228 m_pBtnColHeader
->Enable();
229 m_pBtnRowHeader
->Enable();
233 void ScNameDlg::CancelPushed()
235 DoClose( ScNameDlgWrapper::GetChildWindowId() );
238 void ScNameDlg::SetActive()
240 m_pEdAssign
->GrabFocus();
244 void ScNameDlg::UpdateChecks(ScRangeData
* pData
)
246 // remove handlers, we only want the handlers to process
247 // user input and not when we are syncing the controls with our internal
248 // model ( also UpdateChecks is called already from some other event
249 // handlers, triggering handlers while already processing a handler can
250 // ( and does in this case ) corrupt the internal data
252 m_pBtnCriteria
->SetToggleHdl( Link
<CheckBox
&,void>() );
253 m_pBtnPrintArea
->SetToggleHdl( Link
<CheckBox
&,void>() );
254 m_pBtnColHeader
->SetToggleHdl( Link
<CheckBox
&,void>() );
255 m_pBtnRowHeader
->SetToggleHdl( Link
<CheckBox
&,void>() );
257 m_pBtnCriteria
->Check( pData
->HasType( ScRangeData::Type::Criteria
) );
258 m_pBtnPrintArea
->Check( pData
->HasType( ScRangeData::Type::PrintArea
) );
259 m_pBtnColHeader
->Check( pData
->HasType( ScRangeData::Type::ColHeader
) );
260 m_pBtnRowHeader
->Check( pData
->HasType( ScRangeData::Type::RowHeader
) );
262 // Restore handlers so user input is processed again
263 Link
<CheckBox
&,void> aToggleHandler
= LINK( this, ScNameDlg
, EdModifyCheckBoxHdl
);
264 m_pBtnCriteria
->SetToggleHdl( aToggleHandler
);
265 m_pBtnPrintArea
->SetToggleHdl( aToggleHandler
);
266 m_pBtnColHeader
->SetToggleHdl( aToggleHandler
);
267 m_pBtnRowHeader
->SetToggleHdl( aToggleHandler
);
270 bool ScNameDlg::IsNameValid()
272 OUString aScope
= m_pLbScope
->GetSelectEntry();
273 OUString aName
= m_pEdName
->GetText();
274 aName
= aName
.trim();
279 ScRangeName
* pRangeName
= GetRangeName( aScope
);
281 if (!ScRangeData::IsNameValid( aName
, mpDoc
))
283 m_pFtInfo
->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor());
284 m_pFtInfo
->SetText(maErrInvalidNameStr
);
287 else if (pRangeName
&& pRangeName
->findByUpperName(ScGlobal::pCharClass
->uppercase(aName
)))
289 m_pFtInfo
->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor());
290 m_pFtInfo
->SetText(maErrNameInUse
);
293 m_pFtInfo
->SetText( maStrInfoDefault
);
297 bool ScNameDlg::IsFormulaValid()
299 ScCompiler
aComp( mpDoc
, maCursorPos
);
300 aComp
.SetGrammar( mpDoc
->GetGrammar() );
301 ScTokenArray
* pCode
= aComp
.CompileString(m_pEdAssign
->GetText());
302 if (pCode
->GetCodeError())
304 m_pFtInfo
->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor());
315 ScRangeName
* ScNameDlg::GetRangeName(const OUString
& rScope
)
317 if (rScope
== maGlobalNameStr
)
318 return m_RangeMap
.find(OUString(STR_GLOBAL_RANGE_NAME
))->second
.get();
320 return m_RangeMap
.find(rScope
)->second
.get();
323 void ScNameDlg::ShowOptions(const ScRangeNameLine
& rLine
)
325 ScRangeName
* pRangeName
= GetRangeName(rLine
.aScope
);
326 ScRangeData
* pData
= pRangeName
->findByUpperName(ScGlobal::pCharClass
->uppercase(rLine
.aName
));
333 void ScNameDlg::AddPushed()
335 mbCloseWithoutUndo
= true;
336 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
337 pViewSh
->SwitchBetweenRefDialogs(this);
340 void ScNameDlg::SetEntry(const OUString
& rName
, const OUString
& rScope
)
342 if (!rName
.isEmpty())
344 mbDataChanged
= true;
345 ScRangeNameLine aLine
;
347 aLine
.aScope
= rScope
;
348 m_pRangeManagerTable
->SetEntry(aLine
);
352 void ScNameDlg::RemovePushed()
354 std::vector
<ScRangeNameLine
> aEntries
= m_pRangeManagerTable
->GetSelectedEntries();
355 m_pRangeManagerTable
->DeleteSelectedEntries();
356 for (std::vector
<ScRangeNameLine
>::iterator itr
= aEntries
.begin(); itr
!= aEntries
.end(); ++itr
)
358 ScRangeName
* pRangeName
= GetRangeName(itr
->aScope
);
359 ScRangeData
* pData
= pRangeName
->findByUpperName(ScGlobal::pCharClass
->uppercase(itr
->aName
));
360 OSL_ENSURE(pData
, "table and model should be in sync");
361 // be safe and check for possible problems
363 pRangeName
->erase(*pData
);
365 mbDataChanged
= true;
367 CheckForEmptyTable();
370 void ScNameDlg::NameModified()
372 ScRangeNameLine aLine
;
373 m_pRangeManagerTable
->GetCurrentLine(aLine
);
374 OUString aOldName
= aLine
.aName
;
375 OUString aNewName
= m_pEdName
->GetText();
376 aNewName
= aNewName
.trim();
377 m_pFtInfo
->SetControlBackground(GetSettings().GetStyleSettings().GetDialogColor());
378 if (aNewName
!= aOldName
)
385 m_pFtInfo
->SetText( maStrInfoDefault
);
388 if (!IsFormulaValid())
390 //TODO: implement an info text
394 OUString aOldScope
= aLine
.aScope
;
396 if (aOldScope
.isEmpty())
398 OUString aExpr
= m_pEdAssign
->GetText();
399 OUString aNewScope
= m_pLbScope
->GetSelectEntry();
401 ScRangeName
* pOldRangeName
= GetRangeName( aOldScope
);
402 ScRangeData
* pData
= pOldRangeName
->findByUpperName( ScGlobal::pCharClass
->uppercase(aOldName
) );
403 ScRangeName
* pNewRangeName
= GetRangeName( aNewScope
);
404 OSL_ENSURE(pData
, "model and table should be in sync");
405 // be safe and check for range data
408 pOldRangeName
->erase(*pData
);
409 mbNeedUpdate
= false;
410 m_pRangeManagerTable
->DeleteSelectedEntries();
411 ScRangeData::Type nType
= ScRangeData::Type::Name
;
412 if ( m_pBtnRowHeader
->IsChecked() ) nType
|= ScRangeData::Type::RowHeader
;
413 if ( m_pBtnColHeader
->IsChecked() ) nType
|= ScRangeData::Type::ColHeader
;
414 if ( m_pBtnPrintArea
->IsChecked() ) nType
|= ScRangeData::Type::PrintArea
;
415 if ( m_pBtnCriteria
->IsChecked() ) nType
|= ScRangeData::Type::Criteria
;
417 ScRangeData
* pNewEntry
= new ScRangeData( mpDoc
, aNewName
, aExpr
,
419 pNewRangeName
->insert(pNewEntry
);
420 aLine
.aName
= aNewName
;
421 aLine
.aExpression
= aExpr
;
422 aLine
.aScope
= aNewScope
;
423 m_pRangeManagerTable
->addEntry(aLine
);
425 mbDataChanged
= true;
429 void ScNameDlg::SelectionChanged()
431 //don't update if we have just modified due to user input
437 if (m_pRangeManagerTable
->IsMultiSelection())
439 m_pEdName
->SetText(maStrMultiSelect
);
440 m_pEdAssign
->SetText(maStrMultiSelect
);
442 m_pEdName
->Disable();
443 m_pEdAssign
->Disable();
444 m_pRbAssign
->Disable();
445 m_pLbScope
->Disable();
446 m_pBtnRowHeader
->Disable();
447 m_pBtnColHeader
->Disable();
448 m_pBtnPrintArea
->Disable();
449 m_pBtnCriteria
->Disable();
453 ScRangeNameLine aLine
;
454 m_pRangeManagerTable
->GetCurrentLine(aLine
);
455 m_pEdAssign
->SetText(aLine
.aExpression
);
456 m_pEdName
->SetText(aLine
.aName
);
457 m_pLbScope
->SelectEntry(aLine
.aScope
);
459 m_pBtnDelete
->Enable();
461 m_pEdAssign
->Enable();
462 m_pRbAssign
->Enable();
463 m_pLbScope
->Enable();
464 m_pBtnRowHeader
->Enable();
465 m_pBtnColHeader
->Enable();
466 m_pBtnPrintArea
->Enable();
467 m_pBtnCriteria
->Enable();
471 void ScNameDlg::ScopeChanged()
476 void ScNameDlg::GetRangeNames(std::map
<OUString
, std::unique_ptr
<ScRangeName
>>& rRangeMap
)
478 m_RangeMap
.swap(rRangeMap
);
481 IMPL_LINK_NOARG_TYPED(ScNameDlg
, OkBtnHdl
, Button
*, void)
486 IMPL_LINK_NOARG_TYPED(ScNameDlg
, CancelBtnHdl
, Button
*, void)
491 IMPL_LINK_NOARG_TYPED(ScNameDlg
, AddBtnHdl
, Button
*, void)
496 IMPL_LINK_NOARG_TYPED(ScNameDlg
, RemoveBtnHdl
, Button
*, void)
501 IMPL_LINK_NOARG_TYPED(ScNameDlg
, EdModifyCheckBoxHdl
, CheckBox
&, void)
506 IMPL_LINK_NOARG_TYPED(ScNameDlg
, EdModifyHdl
, Edit
&, void)
511 IMPL_LINK_NOARG_TYPED(ScNameDlg
, AssignGetFocusHdl
, Control
&, void)
513 EdModifyHdl(*m_pEdAssign
);
516 IMPL_LINK_NOARG_TYPED(ScNameDlg
, SelectionChangedHdl_Impl
, SvTreeListBox
*, void)
521 IMPL_LINK_NOARG_TYPED(ScNameDlg
, ScopeChangedHdl
, ListBox
&, void)
526 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */