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 .
20 #include <sfx2/dispatch.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/weld.hxx>
24 #include <uiitems.hxx>
25 #include <document.hxx>
26 #include <scresid.hxx>
28 #include <strings.hrc>
29 #include <reffact.hxx>
31 #include <tabopdlg.hxx>
34 ScTabOpDlg::ScTabOpDlg(SfxBindings
* pB
, SfxChildWindow
* pCW
, weld::Window
* pParent
,
35 ScDocument
* pDocument
,
36 const ScRefAddress
& rCursorPos
)
37 : ScAnyRefDlgController(pB
, pCW
, pParent
, u
"modules/scalc/ui/multipleoperationsdialog.ui"_ustr
,
38 u
"MultipleOperationsDialog"_ustr
)
39 , theFormulaCell(rCursorPos
)
41 , nCurTab(theFormulaCell
.Tab())
42 , bDlgLostFocus(false)
43 , errMsgNoFormula(ScResId(STR_NOFORMULASPECIFIED
))
44 , errMsgNoColRow(ScResId(STR_NOCOLROW
))
45 , errMsgWrongFormula(ScResId(STR_WRONGFORMULA
))
46 , errMsgWrongRowCol(ScResId(STR_WRONGROWCOL
))
47 , errMsgNoColFormula(ScResId(STR_NOCOLFORMULA
))
48 , errMsgNoRowFormula(ScResId(STR_NOROWFORMULA
))
49 , m_pEdActive(nullptr)
50 , m_xFtFormulaRange(m_xBuilder
->weld_label(u
"formulasft"_ustr
))
51 , m_xEdFormulaRange(new formula::RefEdit(m_xBuilder
->weld_entry(u
"formulas"_ustr
)))
52 , m_xRBFormulaRange(new formula::RefButton(m_xBuilder
->weld_button(u
"formulasref"_ustr
)))
53 , m_xFtRowCell(m_xBuilder
->weld_label(u
"rowft"_ustr
))
54 , m_xEdRowCell(new formula::RefEdit(m_xBuilder
->weld_entry(u
"row"_ustr
)))
55 , m_xRBRowCell(new formula::RefButton(m_xBuilder
->weld_button(u
"rowref"_ustr
)))
56 , m_xFtColCell(m_xBuilder
->weld_label(u
"colft"_ustr
))
57 , m_xEdColCell(new formula::RefEdit(m_xBuilder
->weld_entry(u
"col"_ustr
)))
58 , m_xRBColCell(new formula::RefButton(m_xBuilder
->weld_button(u
"colref"_ustr
)))
59 , m_xBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
60 , m_xBtnCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
62 m_xEdFormulaRange
->SetReferences(this, m_xFtFormulaRange
.get());
63 m_xRBFormulaRange
->SetReferences(this, m_xEdFormulaRange
.get());
65 m_xEdRowCell
->SetReferences(this, m_xFtRowCell
.get());
66 m_xRBRowCell
->SetReferences(this, m_xEdRowCell
.get());
68 m_xEdColCell
->SetReferences(this, m_xFtColCell
.get());
69 m_xRBColCell
->SetReferences(this, m_xEdColCell
.get());
74 ScTabOpDlg::~ScTabOpDlg()
78 void ScTabOpDlg::Init()
80 m_xBtnOk
->connect_clicked( LINK( this, ScTabOpDlg
, BtnHdl
) );
81 m_xBtnCancel
->connect_clicked( LINK( this, ScTabOpDlg
, BtnHdl
) );
83 Link
<formula::RefEdit
&,void> aEditLink
= LINK( this, ScTabOpDlg
, GetEditFocusHdl
);
84 m_xEdFormulaRange
->SetGetFocusHdl( aEditLink
);
85 m_xEdRowCell
->SetGetFocusHdl( aEditLink
);
86 m_xEdColCell
->SetGetFocusHdl( aEditLink
);
88 Link
<formula::RefButton
&,void> aButtonLink
= LINK( this, ScTabOpDlg
, GetButtonFocusHdl
);
89 m_xRBFormulaRange
->SetGetFocusHdl( aButtonLink
);
90 m_xRBRowCell
->SetGetFocusHdl( aButtonLink
);
91 m_xRBColCell
->SetGetFocusHdl( aButtonLink
);
93 aEditLink
= LINK( this, ScTabOpDlg
, LoseEditFocusHdl
);
94 m_xEdFormulaRange
->SetLoseFocusHdl( aEditLink
);
95 m_xEdRowCell
->SetLoseFocusHdl( aEditLink
);
96 m_xEdColCell
->SetLoseFocusHdl( aEditLink
);
98 aButtonLink
= LINK( this, ScTabOpDlg
, LoseButtonFocusHdl
);
99 m_xRBFormulaRange
->SetLoseFocusHdl( aButtonLink
);
100 m_xRBRowCell
->SetLoseFocusHdl( aButtonLink
);
101 m_xRBColCell
->SetLoseFocusHdl( aButtonLink
);
103 m_xEdFormulaRange
->GrabFocus();
104 m_pEdActive
= m_xEdFormulaRange
.get();
107 void ScTabOpDlg::Close()
109 DoClose( ScTabOpDlgWrapper::GetChildWindowId() );
112 void ScTabOpDlg::SetActive()
116 bDlgLostFocus
= false;
118 m_pEdActive
->GrabFocus();
121 m_xDialog
->grab_focus();
126 void ScTabOpDlg::SetReference( const ScRange
& rRef
, ScDocument
& rDocP
)
131 ScAddress::Details
aDetails(rDocP
.GetAddressConvention(), 0, 0);
133 if ( rRef
.aStart
!= rRef
.aEnd
)
134 RefInputStart(m_pEdActive
);
137 ScRefFlags nFmt
= ( rRef
.aStart
.Tab() == nCurTab
)
138 ? ScRefFlags::RANGE_ABS
139 : ScRefFlags::RANGE_ABS_3D
;
141 if (m_pEdActive
== m_xEdFormulaRange
.get())
143 theFormulaCell
.Set( rRef
.aStart
, false, false, false);
144 theFormulaEnd
.Set( rRef
.aEnd
, false, false, false);
145 aStr
= rRef
.Format(rDocP
, nFmt
, aDetails
);
147 else if (m_pEdActive
== m_xEdRowCell
.get())
149 theRowCell
.Set( rRef
.aStart
, false, false, false);
150 aStr
= rRef
.aStart
.Format(nFmt
, &rDocP
, aDetails
);
152 else if (m_pEdActive
== m_xEdColCell
.get())
154 theColCell
.Set( rRef
.aStart
, false, false, false);
155 aStr
= rRef
.aStart
.Format(nFmt
, &rDocP
, aDetails
);
158 m_pEdActive
->SetRefString( aStr
);
161 void ScTabOpDlg::RaiseError( ScTabOpErr eError
)
163 const OUString
* pMsg
= &errMsgNoFormula
;
164 formula::RefEdit
* pEd
= m_xEdFormulaRange
.get();
168 case TABOPERR_NOFORMULA
:
169 pMsg
= &errMsgNoFormula
;
170 pEd
= m_xEdFormulaRange
.get();
173 case TABOPERR_NOCOLROW
:
174 pMsg
= &errMsgNoColRow
;
175 pEd
= m_xEdRowCell
.get();
178 case TABOPERR_WRONGFORMULA
:
179 pMsg
= &errMsgWrongFormula
;
180 pEd
= m_xEdFormulaRange
.get();
183 case TABOPERR_WRONGROW
:
184 pMsg
= &errMsgWrongRowCol
;
185 pEd
= m_xEdRowCell
.get();
188 case TABOPERR_NOCOLFORMULA
:
189 pMsg
= &errMsgNoColFormula
;
190 pEd
= m_xEdFormulaRange
.get();
193 case TABOPERR_WRONGCOL
:
194 pMsg
= &errMsgWrongRowCol
;
195 pEd
= m_xEdColCell
.get();
198 case TABOPERR_NOROWFORMULA
:
199 pMsg
= &errMsgNoRowFormula
;
200 pEd
= m_xEdFormulaRange
.get();
204 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xDialog
.get(),
205 VclMessageType::Error
, VclButtonsType::OkCancel
, *pMsg
));
210 static bool lcl_Parse( const OUString
& rString
, const ScDocument
& rDoc
, SCTAB nCurTab
,
211 ScRefAddress
& rStart
, ScRefAddress
& rEnd
)
214 const formula::FormulaGrammar::AddressConvention eConv
= rDoc
.GetAddressConvention();
215 if ( rString
.indexOf(':') != -1 )
216 bRet
= ConvertDoubleRef( rDoc
, rString
, nCurTab
, rStart
, rEnd
, eConv
);
219 bRet
= ConvertSingleRef( rDoc
, rString
, nCurTab
, rStart
, eConv
);
227 IMPL_LINK(ScTabOpDlg
, BtnHdl
, weld::Button
&, rBtn
, void)
229 if (&rBtn
== m_xBtnOk
.get())
231 ScTabOpParam::Mode eMode
= ScTabOpParam::Column
;
232 sal_uInt16 nError
= 0;
234 // The following code checks:
235 // 1. do the strings contain correct cell references / defined names?
236 // 2. is formula range row if row is empty or column if column is empty
237 // or single reference if both?
238 // 3. is at least one of row or column non-empty?
240 if (m_xEdFormulaRange
->GetText().isEmpty())
241 nError
= TABOPERR_NOFORMULA
;
242 else if (m_xEdRowCell
->GetText().isEmpty() &&
243 m_xEdColCell
->GetText().isEmpty())
244 nError
= TABOPERR_NOCOLROW
;
245 else if ( !lcl_Parse( m_xEdFormulaRange
->GetText(), *pDoc
, nCurTab
,
246 theFormulaCell
, theFormulaEnd
) )
247 nError
= TABOPERR_WRONGFORMULA
;
250 const formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
251 if (!m_xEdRowCell
->GetText().isEmpty())
253 if (!ConvertSingleRef( *pDoc
, m_xEdRowCell
->GetText(), nCurTab
,
255 nError
= TABOPERR_WRONGROW
;
258 if (m_xEdColCell
->GetText().isEmpty() &&
259 theFormulaCell
.Col() != theFormulaEnd
.Col())
260 nError
= TABOPERR_NOCOLFORMULA
;
262 eMode
= ScTabOpParam::Row
;
265 if (!m_xEdColCell
->GetText().isEmpty())
267 if (!ConvertSingleRef( *pDoc
, m_xEdColCell
->GetText(), nCurTab
,
269 nError
= TABOPERR_WRONGCOL
;
272 if (eMode
== ScTabOpParam::Row
) // both
274 eMode
= ScTabOpParam::Both
;
275 ConvertSingleRef( *pDoc
, m_xEdFormulaRange
->GetText(), nCurTab
,
276 theFormulaCell
, eConv
);
278 else if (theFormulaCell
.Row() != theFormulaEnd
.Row())
279 nError
= TABOPERR_NOROWFORMULA
;
281 eMode
= ScTabOpParam::Column
;
287 RaiseError( static_cast<ScTabOpErr
>(nError
) );
290 ScTabOpParam
aOutParam(theFormulaCell
, theFormulaEnd
, theRowCell
, theColCell
, eMode
);
291 ScTabOpItem
aOutItem( SID_TABOP
, &aOutParam
);
293 SetDispatcherLock( false );
295 GetBindings().GetDispatcher()->ExecuteList(SID_TABOP
,
296 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
301 else if (&rBtn
== m_xBtnCancel
.get())
302 response(RET_CANCEL
);
305 IMPL_LINK( ScTabOpDlg
, GetEditFocusHdl
, formula::RefEdit
&, rCtrl
, void )
307 if (&rCtrl
== m_xEdFormulaRange
.get())
308 m_pEdActive
= m_xEdFormulaRange
.get();
309 else if (&rCtrl
== m_xEdRowCell
.get())
310 m_pEdActive
= m_xEdRowCell
.get();
311 else if (&rCtrl
== m_xEdColCell
.get())
312 m_pEdActive
= m_xEdColCell
.get();
314 m_pEdActive
= nullptr;
317 m_pEdActive
->SelectAll();
320 IMPL_LINK( ScTabOpDlg
, GetButtonFocusHdl
, formula::RefButton
&, rCtrl
, void )
322 if (&rCtrl
== m_xRBFormulaRange
.get())
323 m_pEdActive
= m_xEdFormulaRange
.get();
324 else if (&rCtrl
== m_xRBRowCell
.get())
325 m_pEdActive
= m_xEdRowCell
.get();
326 else if (&rCtrl
== m_xRBColCell
.get())
327 m_pEdActive
= m_xEdColCell
.get();
329 m_pEdActive
= nullptr;
332 m_pEdActive
->SelectAll();
335 IMPL_LINK_NOARG(ScTabOpDlg
, LoseEditFocusHdl
, formula::RefEdit
&, void)
337 bDlgLostFocus
= !m_xDialog
->has_toplevel_focus();
340 IMPL_LINK_NOARG(ScTabOpDlg
, LoseButtonFocusHdl
, formula::RefButton
&, void)
342 bDlgLostFocus
= !m_xDialog
->has_toplevel_focus();
345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */