bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / namedlg / namedlg.cxx
blob51a5ff2a53b3fa19652aba5ceadad6a625e41000
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include "global.hxx"
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>
37 #include <map>
38 #include <memory>
40 // defines -------------------------------------------------------------------
42 #define ABS_SREF SCA_VALID \
43 | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE
44 #define ABS_DREF ABS_SREF \
45 | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE | SCA_TAB2_ABSOLUTE
46 #define ABS_DREF3D ABS_DREF | SCA_TAB_3D
48 //logic
50 ScNameDlg::ScNameDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent,
51 ScViewData* ptrViewData,
52 const ScAddress& aCursorPos, boost::ptr_map<OUString, ScRangeName>* pRangeMap )
53 : ScAnyRefDlg(pB, pCW, pParent, "ManageNamesDialog", "modules/scalc/ui/managenamesdialog.ui")
55 , maGlobalNameStr(ScGlobal::GetRscString(STR_GLOBAL_SCOPE))
56 , maErrInvalidNameStr(ScGlobal::GetRscString(STR_ERR_NAME_INVALID))
57 , maErrNameInUse(ScGlobal::GetRscString(STR_ERR_NAME_EXISTS))
58 , maStrMultiSelect(ScGlobal::GetRscString(STR_MULTI_SELECT))
60 , mpViewData(ptrViewData)
61 , mpDoc(ptrViewData->GetDocument())
62 , maCursorPos(aCursorPos)
63 , mbNeedUpdate(true)
64 , mbDataChanged(false)
65 , mbCloseWithoutUndo(false)
67 get(m_pEdName, "name");
68 get(m_pEdAssign, "range");
69 m_pEdAssign->SetReferences(this, m_pEdName);
70 get(m_pRbAssign, "assign");
71 m_pRbAssign->SetReferences(this, m_pEdAssign);
72 get(m_pLbScope, "scope");
73 get(m_pBtnPrintArea, "printrange");
74 get(m_pBtnColHeader, "colheader");
75 get(m_pBtnCriteria, "filter");
76 get(m_pBtnRowHeader, "rowheader");
77 get(m_pBtnAdd, "add");
78 get(m_pBtnDelete, "delete");
79 get(m_pBtnOk, "ok");
80 get(m_pBtnCancel, "cancel");
81 get(m_pFtInfo, "info");
82 maStrInfoDefault = m_pFtInfo->GetText();
83 m_pFtInfo->SetText(OUString());
85 if (!pRangeMap)
87 std::map<OUString, ScRangeName*> aRangeMap;
88 mpDoc->GetRangeNameMap(aRangeMap);
89 std::map<OUString, ScRangeName*>::iterator itr = aRangeMap.begin(), itrEnd = aRangeMap.end();
90 for (; itr != itrEnd; ++itr)
92 OUString aTemp(itr->first);
93 maRangeMap.insert(aTemp, new ScRangeName(*itr->second));
96 else
98 maRangeMap.swap(*pRangeMap);
100 Init();
103 ScNameDlg::~ScNameDlg()
105 delete m_pRangeManagerTable;
108 void ScNameDlg::Init()
110 ScRange aRange;
112 OSL_ENSURE( mpViewData && mpDoc, "ViewData oder Document nicht gefunden!" );
114 //init UI
115 m_pFtInfo->SetStyle(WB_VCENTER);
117 SvxSimpleTableContainer *pCtrl = get<SvxSimpleTableContainer>("names");
118 pCtrl->set_height_request(pCtrl->GetTextHeight()*12);
120 m_pRangeManagerTable = new ScRangeManagerTable(*pCtrl, maRangeMap, maCursorPos);
121 m_pRangeManagerTable->setInitListener(this);
122 m_pRangeManagerTable->SetSelectHdl( LINK( this, ScNameDlg, SelectionChangedHdl_Impl ) );
123 m_pRangeManagerTable->SetDeselectHdl( LINK( this, ScNameDlg, SelectionChangedHdl_Impl ) );
125 m_pBtnOk->SetClickHdl ( LINK( this, ScNameDlg, OkBtnHdl ) );
126 m_pBtnCancel->SetClickHdl ( LINK( this, ScNameDlg, CancelBtnHdl ) );
127 m_pBtnAdd->SetClickHdl ( LINK( this, ScNameDlg, AddBtnHdl ) );
128 m_pEdAssign->SetGetFocusHdl( LINK( this, ScNameDlg, AssignGetFocusHdl ) );
129 m_pEdAssign->SetModifyHdl ( LINK( this, ScNameDlg, EdModifyHdl ) );
130 m_pEdName->SetModifyHdl ( LINK( this, ScNameDlg, EdModifyHdl ) );
131 m_pLbScope->SetSelectHdl( LINK(this, ScNameDlg, ScopeChangedHdl) );
132 m_pBtnDelete->SetClickHdl ( LINK( this, ScNameDlg, RemoveBtnHdl ) );
133 m_pBtnPrintArea->SetToggleHdl( LINK(this, ScNameDlg, EdModifyHdl ) );
134 m_pBtnCriteria->SetToggleHdl( LINK(this, ScNameDlg, EdModifyHdl ) );
135 m_pBtnRowHeader->SetToggleHdl( LINK(this, ScNameDlg, EdModifyHdl ) );
136 m_pBtnColHeader->SetToggleHdl( LINK(this, ScNameDlg, EdModifyHdl ) );
138 // Initialize scope list.
139 m_pLbScope->InsertEntry(maGlobalNameStr);
140 m_pLbScope->SelectEntryPos(0);
141 SCTAB n = mpDoc->GetTableCount();
142 for (SCTAB i = 0; i < n; ++i)
144 OUString aTabName;
145 mpDoc->GetName(i, aTabName);
146 m_pLbScope->InsertEntry(aTabName);
149 CheckForEmptyTable();
152 sal_Bool ScNameDlg::IsRefInputMode() const
154 return m_pEdAssign->IsEnabled();
157 void ScNameDlg::RefInputDone( sal_Bool bForced)
159 ScAnyRefDlg::RefInputDone(bForced);
160 EdModifyHdl(m_pEdAssign);
163 void ScNameDlg::SetReference( const ScRange& rRef, ScDocument* pDocP )
165 if ( m_pEdAssign->IsEnabled() )
167 if ( rRef.aStart != rRef.aEnd )
168 RefInputStart(m_pEdAssign);
169 String aRefStr;
170 rRef.Format( aRefStr, ABS_DREF3D, pDocP,
171 ScAddress::Details(pDocP->GetAddressConvention(), 0, 0) );
172 m_pEdAssign->SetRefString( aRefStr );
176 sal_Bool ScNameDlg::Close()
178 if (mbDataChanged && !mbCloseWithoutUndo)
179 mpViewData->GetDocFunc().ModifyAllRangeNames(maRangeMap);
180 return DoClose( ScNameDlgWrapper::GetChildWindowId() );
183 void ScNameDlg::tableInitialized()
185 if (m_pRangeManagerTable->GetSelectionCount())
186 SelectionChanged();
189 void ScNameDlg::CheckForEmptyTable()
191 if (!m_pRangeManagerTable->GetEntryCount())
193 m_pBtnDelete->Disable();
194 m_pEdAssign->Disable();
195 m_pRbAssign->Disable();
196 m_pEdName->Disable();
197 m_pLbScope->Disable();
199 m_pBtnCriteria->Disable();
200 m_pBtnPrintArea->Disable();
201 m_pBtnColHeader->Disable();
202 m_pBtnRowHeader->Disable();
204 else
206 m_pBtnDelete->Enable();
207 m_pEdAssign->Enable();
208 m_pRbAssign->Enable();
209 m_pEdName->Enable();
210 m_pLbScope->Enable();
213 m_pBtnCriteria->Enable();
214 m_pBtnPrintArea->Enable();
215 m_pBtnColHeader->Enable();
216 m_pBtnRowHeader->Enable();
220 void ScNameDlg::CancelPushed()
222 DoClose( ScNameDlgWrapper::GetChildWindowId() );
225 void ScNameDlg::SetActive()
227 m_pEdAssign->GrabFocus();
228 RefInputDone();
231 void ScNameDlg::UpdateChecks(ScRangeData* pData)
233 // remove handlers, we only want the handlers to process
234 // user input and not when we are syncing the controls with our internal
235 // model ( also UpdateChecks is called already from some other event
236 // handlers, triggering handlers while already processing a handler can
237 // ( and does in this case ) corrupt the internal data
239 m_pBtnCriteria->SetToggleHdl( Link() );
240 m_pBtnPrintArea->SetToggleHdl( Link() );
241 m_pBtnColHeader->SetToggleHdl( Link() );
242 m_pBtnRowHeader->SetToggleHdl( Link() );
244 m_pBtnCriteria->Check( pData->HasType( RT_CRITERIA ) );
245 m_pBtnPrintArea->Check( pData->HasType( RT_PRINTAREA ) );
246 m_pBtnColHeader->Check( pData->HasType( RT_COLHEADER ) );
247 m_pBtnRowHeader->Check( pData->HasType( RT_ROWHEADER ) );
249 // Restore handlers so user input is processed again
250 Link aToggleHandler = LINK( this, ScNameDlg, EdModifyHdl );
251 m_pBtnCriteria->SetToggleHdl( aToggleHandler );
252 m_pBtnPrintArea->SetToggleHdl( aToggleHandler );
253 m_pBtnColHeader->SetToggleHdl( aToggleHandler );
254 m_pBtnRowHeader->SetToggleHdl( aToggleHandler );
257 bool ScNameDlg::IsNameValid()
259 OUString aScope = m_pLbScope->GetSelectEntry();
260 OUString aName = m_pEdName->GetText();
261 aName = aName.trim();
263 if (aName.isEmpty())
264 return false;
266 ScRangeName* pRangeName = GetRangeName( aScope );
268 if (!ScRangeData::IsNameValid( aName, mpDoc ))
270 m_pFtInfo->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor());
271 m_pFtInfo->SetText(maErrInvalidNameStr);
272 return false;
274 else if (pRangeName && pRangeName->findByUpperName(ScGlobal::pCharClass->uppercase(aName)))
276 m_pFtInfo->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor());
277 m_pFtInfo->SetText(maErrNameInUse);
278 return false;
280 m_pFtInfo->SetText( maStrInfoDefault );
281 return true;
284 bool ScNameDlg::IsFormulaValid()
286 ScCompiler aComp( mpDoc, maCursorPos);
287 aComp.SetGrammar( mpDoc->GetGrammar() );
288 ScTokenArray* pCode = aComp.CompileString(m_pEdAssign->GetText());
289 if (pCode->GetCodeError())
291 m_pFtInfo->SetControlBackground(GetSettings().GetStyleSettings().GetHighlightColor());
292 delete pCode;
293 return false;
295 else
297 delete pCode;
298 return true;
302 ScRangeName* ScNameDlg::GetRangeName(const OUString& rScope)
304 if (rScope == maGlobalNameStr)
305 return maRangeMap.find(OUString(STR_GLOBAL_RANGE_NAME))->second;
306 else
307 return maRangeMap.find(rScope)->second;
310 void ScNameDlg::ShowOptions(const ScRangeNameLine& rLine)
312 ScRangeName* pRangeName = GetRangeName(rLine.aScope);
313 ScRangeData* pData = pRangeName->findByUpperName(ScGlobal::pCharClass->uppercase(rLine.aName));
314 if (pData)
316 UpdateChecks(pData);
321 bool ScNameDlg::AddPushed()
323 mbCloseWithoutUndo = true;
324 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
325 pViewSh->SwitchBetweenRefDialogs(this);
326 return false;
329 void ScNameDlg::SetEntry(const OUString& rName, const OUString& rScope)
331 if (!rName.isEmpty())
333 mbDataChanged = true;
334 ScRangeNameLine aLine;
335 aLine.aName = rName;
336 aLine.aScope = rScope;
337 m_pRangeManagerTable->SetEntry(aLine);
341 void ScNameDlg::RemovePushed()
343 std::vector<ScRangeNameLine> maEntries = m_pRangeManagerTable->GetSelectedEntries();
344 m_pRangeManagerTable->DeleteSelectedEntries();
345 for (std::vector<ScRangeNameLine>::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
347 ScRangeName* pRangeName = GetRangeName(itr->aScope);
348 ScRangeData* pData = pRangeName->findByUpperName(ScGlobal::pCharClass->uppercase(itr->aName));
349 OSL_ENSURE(pData, "table and model should be in sync");
350 // be safe and check for possible problems
351 if (pData)
352 pRangeName->erase(*pData);
354 mbDataChanged = true;
356 CheckForEmptyTable();
359 void ScNameDlg::NameModified()
361 ScRangeNameLine aLine;
362 m_pRangeManagerTable->GetCurrentLine(aLine);
363 OUString aOldName = aLine.aName;
364 OUString aNewName = m_pEdName->GetText();
365 aNewName = aNewName.trim();
366 m_pFtInfo->SetControlBackground(GetSettings().GetStyleSettings().GetDialogColor());
367 if (aNewName != aOldName)
369 if (!IsNameValid())
370 return;
372 else
374 m_pFtInfo->SetText( maStrInfoDefault );
377 if (!IsFormulaValid())
379 //TODO: implement an info text
380 return;
383 OUString aOldScope = aLine.aScope;
384 //empty table
385 if (aOldScope.isEmpty())
386 return;
387 OUString aExpr = m_pEdAssign->GetText();
388 OUString aNewScope = m_pLbScope->GetSelectEntry();
390 ScRangeName* pOldRangeName = GetRangeName( aOldScope );
391 ScRangeData* pData = pOldRangeName->findByUpperName( ScGlobal::pCharClass->uppercase(aOldName) );
392 ScRangeName* pNewRangeName = GetRangeName( aNewScope );
393 OSL_ENSURE(pData, "model and table should be in sync");
394 // be safe and check for range data
395 if (pData)
397 pOldRangeName->erase(*pData);
398 mbNeedUpdate = false;
399 m_pRangeManagerTable->DeleteSelectedEntries();
400 RangeType nType = RT_NAME |
401 (m_pBtnRowHeader->IsChecked() ? RT_ROWHEADER : RangeType(0))
402 |(m_pBtnColHeader->IsChecked() ? RT_COLHEADER : RangeType(0))
403 |(m_pBtnPrintArea->IsChecked() ? RT_PRINTAREA : RangeType(0))
404 |(m_pBtnCriteria->IsChecked() ? RT_CRITERIA : RangeType(0));
406 ScRangeData* pNewEntry = new ScRangeData( mpDoc, aNewName, aExpr,
407 maCursorPos, nType);
408 pNewRangeName->insert(pNewEntry);
409 aLine.aName = aNewName;
410 aLine.aExpression = aExpr;
411 aLine.aScope = aNewScope;
412 m_pRangeManagerTable->addEntry(aLine);
413 mbNeedUpdate = true;
414 mbDataChanged = true;
418 void ScNameDlg::SelectionChanged()
420 //don't update if we have just modified due to user input
421 if (!mbNeedUpdate)
423 return;
426 if (m_pRangeManagerTable->IsMultiSelection())
428 m_pEdName->SetText(maStrMultiSelect);
429 m_pEdAssign->SetText(maStrMultiSelect);
431 m_pEdName->Disable();
432 m_pEdAssign->Disable();
433 m_pRbAssign->Disable();
434 m_pLbScope->Disable();
435 m_pBtnRowHeader->Disable();
436 m_pBtnColHeader->Disable();
437 m_pBtnPrintArea->Disable();
438 m_pBtnCriteria->Disable();
440 else
442 ScRangeNameLine aLine;
443 m_pRangeManagerTable->GetCurrentLine(aLine);
444 m_pEdAssign->SetText(aLine.aExpression);
445 m_pEdName->SetText(aLine.aName);
446 m_pLbScope->SelectEntry(aLine.aScope);
447 ShowOptions(aLine);
448 m_pBtnDelete->Enable();
449 m_pEdName->Enable();
450 m_pEdAssign->Enable();
451 m_pRbAssign->Enable();
452 m_pLbScope->Enable();
453 m_pBtnRowHeader->Enable();
454 m_pBtnColHeader->Enable();
455 m_pBtnPrintArea->Enable();
456 m_pBtnCriteria->Enable();
460 void ScNameDlg::ScopeChanged()
462 NameModified();
465 void ScNameDlg::GetRangeNames(boost::ptr_map<OUString, ScRangeName>& rRangeMap)
467 maRangeMap.swap(rRangeMap);
470 IMPL_LINK_NOARG(ScNameDlg, OkBtnHdl)
472 Close();
473 return 0;
476 IMPL_LINK_NOARG(ScNameDlg, CancelBtnHdl)
478 CancelPushed();
479 return 0;
482 IMPL_LINK_NOARG(ScNameDlg, AddBtnHdl)
484 return AddPushed();
487 IMPL_LINK_NOARG(ScNameDlg, RemoveBtnHdl)
489 RemovePushed();
490 return 0;
493 IMPL_LINK_NOARG(ScNameDlg, EdModifyHdl)
495 NameModified();
496 return 0;
499 IMPL_LINK_NOARG(ScNameDlg, AssignGetFocusHdl)
501 EdModifyHdl(m_pEdAssign);
502 return 0;
505 IMPL_LINK_NOARG(ScNameDlg, SelectionChangedHdl_Impl)
507 SelectionChanged();
508 return 0;
511 IMPL_LINK_NOARG(ScNameDlg, ScopeChangedHdl)
513 ScopeChanged();
514 return 0;
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */