calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / sc / source / ui / namedlg / namedefdlg.cxx
blob40936e378d30d899e3b25c42ee59261816965c31
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/.
8 */
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")
31 , mbUndo( bUndo )
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)
63 OUString aTabName;
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
75 ScRange aRange;
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()
93 if (mbUndo)
94 response(RET_CANCEL);
95 else
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)
108 //TODO: info message
109 return false;
111 else
113 return true;
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;
130 else
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);
168 return 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();
177 if (aName.isEmpty())
179 return;
181 if (aScope.isEmpty())
183 return;
186 ScRangeName* pRangeName = nullptr;
187 if(aScope == maGlobalNameStr)
189 pRangeName = maRangeMap.find(OUString(STR_GLOBAL_RANGE_NAME))->second;
191 else
193 pRangeName = maRangeMap.find(aScope)->second;
195 if (!pRangeName)
196 return;
198 if (!IsNameValid()) //should not happen, but make sure we don't break anything
199 return;
200 else
202 ScRangeData::Type nType = ScRangeData::Type::Name;
204 ScRangeData* pNewEntry = new ScRangeData( mrDoc,
205 aName,
206 aExpression,
207 maCursorPos,
208 nType );
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*/ ) )
221 pNewEntry = nullptr;
223 if (mbUndo)
225 // this means we called directly through the menu
227 SCTAB nTab;
228 // if no table with that name is found, assume global range name
229 if (!mrDoc.GetTable(aScope, nTab))
230 nTab = -1;
232 assert( pNewEntry); // undo of no insertion smells fishy
233 if (pNewEntry)
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
239 if (nTab != -1)
240 mrDoc.SetStreamValid(nTab, false);
241 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) );
242 mpDocShell->SetDocumentModified();
243 Close();
245 else
247 maName = aName;
248 maScope = aScope;
249 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
250 pViewSh->SwitchBetweenRefDialogs(this);
253 else
255 delete pNewEntry;
256 m_xEdRange->GrabFocus();
257 m_xEdRange->SelectAll();
262 void ScNameDefDlg::GetNewData(OUString& rName, OUString& rScope)
264 rName = maName;
265 rScope = maScope;
268 bool ScNameDefDlg::IsRefInputMode() const
270 return m_xEdRange->GetWidget()->get_sensitive();
273 void ScNameDefDlg::RefInputDone( bool bForced)
275 ScAnyRefDlgController::RefInputDone(bForced);
276 IsNameValid();
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();
299 RefInputDone();
302 IMPL_LINK_NOARG(ScNameDefDlg, CancelBtnHdl, weld::Button&, void)
304 CancelPushed();
307 IMPL_LINK_NOARG(ScNameDefDlg, AddBtnHdl, weld::Button&, void)
309 AddPushed();
312 IMPL_LINK_NOARG(ScNameDefDlg, NameModifyHdl, weld::Entry&, void)
314 IsNameValid();
317 IMPL_LINK_NOARG(ScNameDefDlg, AssignGetFocusHdl, formula::RefEdit&, void)
319 IsNameValid();
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */