1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #ifdef SC_DLLIMPLEMENTATION
21 #undef SC_DLLIMPLEMENTATION
22 #endif
23
24 #include <com/sun/star/sheet/TableValidationVisibility.hpp>
25 #include <comphelper/string.hxx>
26 #include <vcl/svapp.hxx>
27 #include <svl/aeitem.hxx>
28 #include <svl/stritem.hxx>
29 #include <svl/eitem.hxx>
30 #include <svl/intitem.hxx>
31 #include <sfx2/app.hxx>
32
33 #include <scresid.hxx>
34 #include <strings.hrc>
35
36 #include <stringutil.hxx>
37 #include <validat.hxx>
38 #include <validate.hxx>
39 #include <compiler.hxx>
40 #include <formula/opcode.hxx>
41
42 // cell range picker
43 #include <tabvwsh.hxx>
44 #include <sfx2/viewfrm.hxx>
45 #include <sfx2/childwin.hxx>
46 #include <reffact.hxx>
47
48 /* Position indexes for "Allow" list box.
49 They do not map directly to ScValidationMode and can safely be modified to
50 change the order of the list box entries. */
51 #define SC_VALIDDLG_ALLOW_ANY 0
52 #define SC_VALIDDLG_ALLOW_WHOLE 1
53 #define SC_VALIDDLG_ALLOW_DECIMAL 2
54 #define SC_VALIDDLG_ALLOW_DATE 3
55 #define SC_VALIDDLG_ALLOW_TIME 4
56 #define SC_VALIDDLG_ALLOW_RANGE 5
57 #define SC_VALIDDLG_ALLOW_LIST 6
58 #define SC_VALIDDLG_ALLOW_TEXTLEN 7
59 #define SC_VALIDDLG_ALLOW_CUSTOM 8
60
61 /* Position indexes for "Data" list box.
62 They do not map directly to ScConditionMode and can safely be modified to
63 change the order of the list box entries. */
64 #define SC_VALIDDLG_DATA_EQUAL 0
65 #define SC_VALIDDLG_DATA_LESS 1
66 #define SC_VALIDDLG_DATA_GREATER 2
67 #define SC_VALIDDLG_DATA_EQLESS 3
68 #define SC_VALIDDLG_DATA_EQGREATER 4
69 #define SC_VALIDDLG_DATA_NOTEQUAL 5
70 #define SC_VALIDDLG_DATA_VALIDRANGE 6
71 #define SC_VALIDDLG_DATA_INVALIDRANGE 7
72 #define SC_VALIDDLG_DATA_DIRECT 8
73
74 namespace ValidListType = css::sheet::TableValidationVisibility;
75
76 const sal_uInt16 ScTPValidationValue::pValueRanges[] =
77 {
78 FID_VALID_MODE, FID_VALID_ERRTEXT,
79 FID_VALID_LISTTYPE, FID_VALID_LISTTYPE,
80 0
81 };
82
ScValidationDlg(weld::Window * pParent,const SfxItemSet * pArgSet,ScTabViewShell * pTabViewSh)83 ScValidationDlg::ScValidationDlg(weld::Window* pParent, const SfxItemSet* pArgSet,
84 ScTabViewShell *pTabViewSh)
85 : ScValidationDlgBase(pParent,
86 "modules/scalc/ui/validationdialog.ui", "ValidationDialog", pArgSet, nullptr)
87 , m_pTabVwSh(pTabViewSh)
88 , m_sValuePageId("criteria")
89 , m_bOwnRefHdlr(false)
90 , m_bRefInputting(false)
91 , m_xHBox(m_xBuilder->weld_container("refinputbox"))
92 {
93 AddTabPage(m_sValuePageId, ScTPValidationValue::Create, nullptr);
94 AddTabPage("inputhelp", ScTPValidationHelp::Create, nullptr);
95 AddTabPage("erroralert", ScTPValidationError::Create, nullptr);
96 }
97
~ScValidationDlg()98 ScValidationDlg::~ScValidationDlg()
99 {
100 if (m_bOwnRefHdlr)
101 RemoveRefDlg(false);
102 }
103
SetReferenceHdl(const ScRange & rRange,const ScDocument * pDoc)104 void ScTPValidationValue::SetReferenceHdl( const ScRange&rRange , const ScDocument* pDoc )
105 {
106 if ( rRange.aStart != rRange.aEnd )
107 if ( ScValidationDlg *pValidationDlg = GetValidationDlg() )
108 if( m_pRefEdit )
109 pValidationDlg->RefInputStart( m_pRefEdit );
110
111 if ( m_pRefEdit )
112 {
113 OUString aStr(rRange.Format(ScRefFlags::RANGE_ABS_3D, pDoc, pDoc->GetAddressConvention()));
114 m_pRefEdit->SetRefString( aStr );
115 }
116 }
117
SetActiveHdl()118 void ScTPValidationValue:: SetActiveHdl()
119 {
120 if ( m_pRefEdit ) m_pRefEdit->GrabFocus();
121
122 if ( ScValidationDlg *pValidationDlg = GetValidationDlg() )
123 if( m_pRefEdit )
124 {
125 pValidationDlg->RefInputDone();
126 }
127 }
128
RefInputStartPreHdl(formula::RefEdit * pEdit,const formula::RefButton * pButton)129 void ScTPValidationValue::RefInputStartPreHdl( formula::RefEdit* pEdit, const formula::RefButton* pButton )
130 {
131 if (ScValidationDlg *pValidationDlg = GetValidationDlg())
132 {
133 weld::Container* pNewParent = pValidationDlg->get_refinput_shrink_parent();
134 if (pEdit == m_pRefEdit && pNewParent != m_pRefEditParent)
135 {
136 m_xRefGrid->move(m_pRefEdit->GetWidget(), pNewParent);
137 m_pRefEditParent = pNewParent;
138 }
139
140 if (pNewParent != m_pBtnRefParent)
141 {
142 // if Edit SetParent but button not, the tab order will be
143 // incorrect, so move button anyway, and restore
144 // parent later in order to restore the tab order. But
145 // hide it if it's moved but unwanted.
146 m_xRefGrid->move(m_xBtnRef->GetWidget(), pNewParent);
147 m_xBtnRef->GetWidget()->set_visible(pButton == m_xBtnRef.get());
148 m_pBtnRefParent = pNewParent;
149 }
150
151 pNewParent->show();
152 }
153 }
154
RefInputDonePostHdl()155 void ScTPValidationValue::RefInputDonePostHdl()
156 {
157 if (ScValidationDlg *pValidationDlg = GetValidationDlg())
158 {
159 weld::Container* pOldParent = pValidationDlg->get_refinput_shrink_parent();
160
161 if (m_pRefEdit && m_pRefEditParent != m_xRefGrid.get())
162 {
163 pOldParent->move(m_pRefEdit->GetWidget(), m_xRefGrid.get());
164 m_pRefEditParent = m_xRefGrid.get();
165 }
166
167 if (m_pBtnRefParent != m_xRefGrid.get())
168 {
169 pOldParent->move(m_xBtnRef->GetWidget(), m_xRefGrid.get());
170 m_xBtnRef->GetWidget()->show();
171 m_pBtnRefParent = m_xRefGrid.get();
172 }
173
174 pOldParent->hide();
175 ScViewData& rViewData = pValidationDlg->GetTabViewShell()->GetViewData();
176 SCTAB nCurTab = rViewData.GetTabNo();
177 SCTAB nRefTab = rViewData.GetRefTabNo();
178 // If RefInput switched to a different sheet from the data sheet,
179 // switch back: fdo#53920
180 if ( nCurTab != nRefTab )
181 {
182 rViewData.GetViewShell()->SetTabNo( nRefTab );
183 }
184 }
185
186 if (m_pRefEdit && !m_pRefEdit->GetWidget()->has_focus())
187 m_pRefEdit->GrabFocus();
188 }
189
190 namespace {
191
192 /** Converts the passed ScValidationMode to the position in the list box. */
lclGetPosFromValMode(ScValidationMode eValMode)193 sal_uInt16 lclGetPosFromValMode( ScValidationMode eValMode )
194 {
195 sal_uInt16 nLbPos = SC_VALIDDLG_ALLOW_ANY;
196 switch( eValMode )
197 {
198 case SC_VALID_ANY: nLbPos = SC_VALIDDLG_ALLOW_ANY; break;
199 case SC_VALID_WHOLE: nLbPos = SC_VALIDDLG_ALLOW_WHOLE; break;
200 case SC_VALID_DECIMAL: nLbPos = SC_VALIDDLG_ALLOW_DECIMAL; break;
201 case SC_VALID_DATE: nLbPos = SC_VALIDDLG_ALLOW_DATE; break;
202 case SC_VALID_TIME: nLbPos = SC_VALIDDLG_ALLOW_TIME; break;
203 case SC_VALID_TEXTLEN: nLbPos = SC_VALIDDLG_ALLOW_TEXTLEN; break;
204 case SC_VALID_LIST: nLbPos = SC_VALIDDLG_ALLOW_RANGE; break;
205 case SC_VALID_CUSTOM: nLbPos = SC_VALIDDLG_ALLOW_CUSTOM; break;
206 default: OSL_FAIL( "lclGetPosFromValMode - unknown validity mode" );
207 }
208 return nLbPos;
209 }
210
211 /** Converts the passed list box position to an ScValidationMode. */
lclGetValModeFromPos(sal_uInt16 nLbPos)212 ScValidationMode lclGetValModeFromPos( sal_uInt16 nLbPos )
213 {
214 ScValidationMode eValMode = SC_VALID_ANY;
215 switch( nLbPos )
216 {
217 case SC_VALIDDLG_ALLOW_ANY: eValMode = SC_VALID_ANY; break;
218 case SC_VALIDDLG_ALLOW_WHOLE: eValMode = SC_VALID_WHOLE; break;
219 case SC_VALIDDLG_ALLOW_DECIMAL: eValMode = SC_VALID_DECIMAL; break;
220 case SC_VALIDDLG_ALLOW_DATE: eValMode = SC_VALID_DATE; break;
221 case SC_VALIDDLG_ALLOW_TIME: eValMode = SC_VALID_TIME; break;
222 case SC_VALIDDLG_ALLOW_RANGE: eValMode = SC_VALID_LIST; break;
223 case SC_VALIDDLG_ALLOW_LIST: eValMode = SC_VALID_LIST; break;
224 case SC_VALIDDLG_ALLOW_TEXTLEN: eValMode = SC_VALID_TEXTLEN; break;
225 case SC_VALIDDLG_ALLOW_CUSTOM: eValMode = SC_VALID_CUSTOM; break;
226 default: OSL_FAIL( "lclGetValModeFromPos - invalid list box position" );
227 }
228 return eValMode;
229 }
230
231 /** Converts the passed ScConditionMode to the position in the list box. */
lclGetPosFromCondMode(ScConditionMode eCondMode)232 sal_uInt16 lclGetPosFromCondMode( ScConditionMode eCondMode )
233 {
234 sal_uInt16 nLbPos = SC_VALIDDLG_DATA_EQUAL;
235 switch( eCondMode )
236 {
237 case ScConditionMode::NONE: // may occur in old XML files after Excel import
238 case ScConditionMode::Equal: nLbPos = SC_VALIDDLG_DATA_EQUAL; break;
239 case ScConditionMode::Less: nLbPos = SC_VALIDDLG_DATA_LESS; break;
240 case ScConditionMode::Greater: nLbPos = SC_VALIDDLG_DATA_GREATER; break;
241 case ScConditionMode::EqLess: nLbPos = SC_VALIDDLG_DATA_EQLESS; break;
242 case ScConditionMode::EqGreater: nLbPos = SC_VALIDDLG_DATA_EQGREATER; break;
243 case ScConditionMode::NotEqual: nLbPos = SC_VALIDDLG_DATA_NOTEQUAL; break;
244 case ScConditionMode::Between: nLbPos = SC_VALIDDLG_DATA_VALIDRANGE; break;
245 case ScConditionMode::NotBetween: nLbPos = SC_VALIDDLG_DATA_INVALIDRANGE; break;
246 case ScConditionMode::Direct: nLbPos = SC_VALIDDLG_DATA_DIRECT; break;
247 default: OSL_FAIL( "lclGetPosFromCondMode - unknown condition mode" );
248 }
249 return nLbPos;
250 }
251
252 /** Converts the passed list box position to an ScConditionMode. */
lclGetCondModeFromPos(sal_uInt16 nLbPos)253 ScConditionMode lclGetCondModeFromPos( sal_uInt16 nLbPos )
254 {
255 ScConditionMode eCondMode = ScConditionMode::Equal;
256 switch( nLbPos )
257 {
258 case SC_VALIDDLG_DATA_EQUAL: eCondMode = ScConditionMode::Equal; break;
259 case SC_VALIDDLG_DATA_LESS: eCondMode = ScConditionMode::Less; break;
260 case SC_VALIDDLG_DATA_GREATER: eCondMode = ScConditionMode::Greater; break;
261 case SC_VALIDDLG_DATA_EQLESS: eCondMode = ScConditionMode::EqLess; break;
262 case SC_VALIDDLG_DATA_EQGREATER: eCondMode = ScConditionMode::EqGreater; break;
263 case SC_VALIDDLG_DATA_NOTEQUAL: eCondMode = ScConditionMode::NotEqual; break;
264 case SC_VALIDDLG_DATA_VALIDRANGE: eCondMode = ScConditionMode::Between; break;
265 case SC_VALIDDLG_DATA_INVALIDRANGE: eCondMode = ScConditionMode::NotBetween; break;
266 case SC_VALIDDLG_DATA_DIRECT: eCondMode = ScConditionMode::Direct; break;
267 default: OSL_FAIL( "lclGetCondModeFromPos - invalid list box position" );
268 }
269 return eCondMode;
270 }
271
272 /** Converts line feed separated string to a formula with strings separated by semicolons.
273 @descr Keeps all empty strings.
274 Example: abc\ndef\n\nghi -> "abc";"def";"";"ghi".
275 @param rFmlaStr (out-param) The converted formula string. */
lclGetFormulaFromStringList(OUString & rFmlaStr,const OUString & rStringList,sal_Unicode cFmlaSep)276 void lclGetFormulaFromStringList( OUString& rFmlaStr, const OUString& rStringList, sal_Unicode cFmlaSep )
277 {
278 rFmlaStr.clear();
279 if (!rStringList.isEmpty())
280 {
281 sal_Int32 nIdx {0};
282 do
283 {
284 OUString aToken {rStringList.getToken( 0, '\n', nIdx )};
285 ScGlobal::AddQuotes( aToken, '"' );
286 rFmlaStr = ScGlobal::addToken(rFmlaStr, aToken, cFmlaSep);
287 }
288 while (nIdx>0);
289 }
290 if( rFmlaStr.isEmpty() )
291 rFmlaStr = "\"\"";
292 }
293
294 /** Converts formula with strings separated by semicolons to line feed separated string.
295 @descr Keeps all empty strings. Ignores all empty tokens (multiple semicolons).
296 Example: "abc";;;"def";"";"ghi" -> abc\ndef\n\nghi.
297 @param rStringList (out-param) The converted line feed separated string list.
298 @return true = Conversion successful. */
lclGetStringListFromFormula(OUString & rStringList,const OUString & rFmlaStr,sal_Unicode cFmlaSep)299 bool lclGetStringListFromFormula( OUString& rStringList, const OUString& rFmlaStr, sal_Unicode cFmlaSep )
300 {
301 const OUString aQuotes( "\"\"" );
302
303 rStringList.clear();
304 bool bIsStringList = !rFmlaStr.isEmpty();
305 bool bTokenAdded = false;
306
307 for ( sal_Int32 nStringIx = 0; bIsStringList && nStringIx>=0; )
308 {
309 OUString aToken( ScStringUtil::GetQuotedToken(rFmlaStr, 0, aQuotes, cFmlaSep, nStringIx ) );
310 aToken = comphelper::string::strip(aToken, ' ');
311 if( !aToken.isEmpty() ) // ignore empty tokens, i.e. "a";;"b"
312 {
313 bIsStringList = ScGlobal::IsQuoted( aToken, '"' );
314 if( bIsStringList )
315 {
316 ScGlobal::EraseQuotes( aToken, '"' );
317 rStringList = ScGlobal::addToken(rStringList, aToken, '\n', 1, bTokenAdded);
318 bTokenAdded = true;
319 }
320 }
321 }
322
323 return bIsStringList;
324 }
325
326 } // namespace
327
ScTPValidationValue(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rArgSet)328 ScTPValidationValue::ScTPValidationValue(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
329 : SfxTabPage(pPage, pController, "modules/scalc/ui/validationcriteriapage.ui",
330 "ValidationCriteriaPage", &rArgSet)
331 , maStrMin(ScResId(SCSTR_VALID_MINIMUM))
332 , maStrMax(ScResId(SCSTR_VALID_MAXIMUM))
333 , maStrValue(ScResId(SCSTR_VALID_VALUE))
334 , maStrFormula(ScResId(SCSTR_VALID_FORMULA))
335 , maStrRange(ScResId(SCSTR_VALID_RANGE))
336 , maStrList(ScResId(SCSTR_VALID_LIST))
337 , m_pRefEdit(nullptr)
338 , m_xLbAllow(m_xBuilder->weld_combo_box("allow"))
339 , m_xCbAllow(m_xBuilder->weld_check_button("allowempty"))
340 , m_xCbShow(m_xBuilder->weld_check_button("showlist"))
341 , m_xCbSort(m_xBuilder->weld_check_button("sortascend"))
342 , m_xFtValue(m_xBuilder->weld_label("valueft"))
343 , m_xLbValue(m_xBuilder->weld_combo_box("data"))
344 , m_xFtMin(m_xBuilder->weld_label("minft"))
345 , m_xMinGrid(m_xBuilder->weld_widget("mingrid"))
346 , m_xEdMin(new formula::RefEdit(m_xBuilder->weld_entry("min")))
347 , m_xEdList(m_xBuilder->weld_text_view("minlist"))
348 , m_xFtMax(m_xBuilder->weld_label("maxft"))
349 , m_xEdMax(new formula::RefEdit(m_xBuilder->weld_entry("max")))
350 , m_xFtHint(m_xBuilder->weld_label("hintft"))
351 , m_xBtnRef(new formula::RefButton(m_xBuilder->weld_button("validref")))
352 , m_xRefGrid(m_xBuilder->weld_container("refgrid"))
353 , m_pRefEditParent(m_xRefGrid.get())
354 , m_pBtnRefParent(m_xRefGrid.get())
355 {
356 m_xEdMin->SetReferences(nullptr, m_xFtMin.get());
357
358 Size aSize(m_xEdList->get_approximate_digit_width() * 40,
359 m_xEdList->get_height_rows(25));
360 m_xEdList->set_size_request(aSize.Width(), aSize.Height());
361 m_xEdMax->SetReferences(nullptr, m_xFtMax.get());
362
363 m_xBtnRef->SetClickHdl(LINK(this, ScTPValidationValue, ClickHdl));
364
365 //lock in the max size initial config
366 aSize = m_xContainer->get_preferred_size();
367 m_xContainer->set_size_request(aSize.Width(), aSize.Height());
368
369 Init();
370
371 // list separator in formulas
372 OUString aListSep = ::ScCompiler::GetNativeSymbol( ocSep );
373 OSL_ENSURE( aListSep.getLength() == 1, "ScTPValidationValue::ScTPValidationValue - list separator error" );
374 mcFmlaSep = aListSep.getLength() ? aListSep[0] : ';';
375 m_xBtnRef->GetWidget()->hide(); // cell range picker
376 }
377
~ScTPValidationValue()378 ScTPValidationValue::~ScTPValidationValue()
379 {
380 m_xEdMin.reset();
381 m_xEdMin.reset();
382 m_xEdMax.reset();
383 m_xBtnRef.reset();
384 m_xEdMax.reset();
385 }
386
Init()387 void ScTPValidationValue::Init()
388 {
389 m_xLbAllow->connect_changed( LINK( this, ScTPValidationValue, SelectHdl ) );
390 m_xLbValue->connect_changed( LINK( this, ScTPValidationValue, SelectHdl ) );
391 m_xCbShow->connect_clicked( LINK( this, ScTPValidationValue, CheckHdl ) );
392
393 // cell range picker
394 m_xEdMin->SetGetFocusHdl( LINK( this, ScTPValidationValue, EditSetFocusHdl ) );
395 m_xEdMin->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillEditFocusHdl ) );
396 m_xEdMax->SetGetFocusHdl( LINK( this, ScTPValidationValue, EditSetFocusHdl ) );
397 m_xBtnRef->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillButtonFocusHdl ) );
398 m_xEdMax->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillEditFocusHdl ) );
399
400 m_xLbAllow->set_active( SC_VALIDDLG_ALLOW_ANY );
401 m_xLbValue->set_active( SC_VALIDDLG_DATA_EQUAL );
402
403 SelectHdl( *m_xLbAllow );
404 CheckHdl( *m_xCbShow );
405 }
406
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rArgSet)407 std::unique_ptr<SfxTabPage> ScTPValidationValue::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rArgSet)
408 {
409 return std::make_unique<ScTPValidationValue>(pPage, pController, *rArgSet);
410 }
411
Reset(const SfxItemSet * rArgSet)412 void ScTPValidationValue::Reset( const SfxItemSet* rArgSet )
413 {
414 const SfxPoolItem* pItem;
415
416 sal_uInt16 nLbPos = SC_VALIDDLG_ALLOW_ANY;
417 if( rArgSet->GetItemState( FID_VALID_MODE, true, &pItem ) == SfxItemState::SET )
418 nLbPos = lclGetPosFromValMode( static_cast< ScValidationMode >(
419 static_cast< const SfxUInt16Item* >( pItem )->GetValue() ) );
420 m_xLbAllow->set_active( nLbPos );
421
422 nLbPos = SC_VALIDDLG_DATA_EQUAL;
423 if( rArgSet->GetItemState( FID_VALID_CONDMODE, true, &pItem ) == SfxItemState::SET )
424 nLbPos = lclGetPosFromCondMode( static_cast< ScConditionMode >(
425 static_cast< const SfxUInt16Item* >( pItem )->GetValue() ) );
426 m_xLbValue->set_active( nLbPos );
427
428 // *** check boxes ***
429 bool bCheck = true;
430 if( rArgSet->GetItemState( FID_VALID_BLANK, true, &pItem ) == SfxItemState::SET )
431 bCheck = static_cast< const SfxBoolItem* >( pItem )->GetValue();
432 m_xCbAllow->set_active( bCheck );
433
434 sal_Int32 nListType = ValidListType::UNSORTED;
435 if( rArgSet->GetItemState( FID_VALID_LISTTYPE, true, &pItem ) == SfxItemState::SET )
436 nListType = static_cast< const SfxInt16Item* >( pItem )->GetValue();
437 m_xCbShow->set_active( nListType != ValidListType::INVISIBLE );
438 m_xCbSort->set_active( nListType == ValidListType::SORTEDASCENDING );
439
440 // *** formulas ***
441 OUString aFmlaStr;
442 if ( rArgSet->GetItemState( FID_VALID_VALUE1, true, &pItem ) == SfxItemState::SET )
443 aFmlaStr = static_cast< const SfxStringItem* >( pItem )->GetValue();
444 SetFirstFormula( aFmlaStr );
445
446 aFmlaStr.clear();
447 if ( rArgSet->GetItemState( FID_VALID_VALUE2, true, &pItem ) == SfxItemState::SET )
448 aFmlaStr = static_cast< const SfxStringItem* >( pItem )->GetValue();
449 SetSecondFormula( aFmlaStr );
450
451 SelectHdl( *m_xLbAllow );
452 CheckHdl( *m_xCbShow );
453 }
454
FillItemSet(SfxItemSet * rArgSet)455 bool ScTPValidationValue::FillItemSet( SfxItemSet* rArgSet )
456 {
457 sal_Int16 nListType = m_xCbShow->get_active() ?
458 (m_xCbSort->get_active() ? ValidListType::SORTEDASCENDING : ValidListType::UNSORTED) :
459 ValidListType::INVISIBLE;
460
461 const sal_Int32 nLbPos = m_xLbAllow->get_active();
462 bool bCustom = (nLbPos == SC_VALIDDLG_ALLOW_CUSTOM);
463 ScConditionMode eCondMode = bCustom ?
464 ScConditionMode::Direct : lclGetCondModeFromPos( m_xLbValue->get_active() );
465
466 rArgSet->Put( SfxUInt16Item( FID_VALID_MODE, sal::static_int_cast<sal_uInt16>(
467 lclGetValModeFromPos( nLbPos ) ) ) );
468 rArgSet->Put( SfxUInt16Item( FID_VALID_CONDMODE, sal::static_int_cast<sal_uInt16>( eCondMode ) ) );
469 rArgSet->Put( SfxStringItem( FID_VALID_VALUE1, GetFirstFormula() ) );
470 rArgSet->Put( SfxStringItem( FID_VALID_VALUE2, GetSecondFormula() ) );
471 rArgSet->Put( SfxBoolItem( FID_VALID_BLANK, m_xCbAllow->get_active() ) );
472 rArgSet->Put( SfxInt16Item( FID_VALID_LISTTYPE, nListType ) );
473 return true;
474 }
475
GetFirstFormula() const476 OUString ScTPValidationValue::GetFirstFormula() const
477 {
478 OUString aFmlaStr;
479 if( m_xLbAllow->get_active() == SC_VALIDDLG_ALLOW_LIST )
480 lclGetFormulaFromStringList( aFmlaStr, m_xEdList->get_text(), mcFmlaSep );
481 else
482 aFmlaStr = m_xEdMin->GetText();
483 return aFmlaStr;
484 }
485
GetSecondFormula() const486 OUString ScTPValidationValue::GetSecondFormula() const
487 {
488 return m_xEdMax->GetText();
489 }
490
SetFirstFormula(const OUString & rFmlaStr)491 void ScTPValidationValue::SetFirstFormula( const OUString& rFmlaStr )
492 {
493 // try if formula is a string list, validation mode must already be set
494 OUString aStringList;
495 if( (m_xLbAllow->get_active() == SC_VALIDDLG_ALLOW_RANGE) &&
496 lclGetStringListFromFormula( aStringList, rFmlaStr, mcFmlaSep ) )
497 {
498 m_xEdList->set_text( aStringList );
499 m_xEdMin->SetText( EMPTY_OUSTRING );
500 // change validation mode to string list
501 m_xLbAllow->set_active( SC_VALIDDLG_ALLOW_LIST );
502 }
503 else
504 {
505 m_xEdMin->SetText( rFmlaStr );
506 m_xEdList->set_text( EMPTY_OUSTRING );
507 }
508 }
509
SetSecondFormula(const OUString & rFmlaStr)510 void ScTPValidationValue::SetSecondFormula( const OUString& rFmlaStr )
511 {
512 m_xEdMax->SetText( rFmlaStr );
513 }
514
GetValidationDlg()515 ScValidationDlg * ScTPValidationValue::GetValidationDlg()
516 {
517 return dynamic_cast<ScValidationDlg*>(GetDialogController());
518 }
519
SetupRefDlg()520 void ScTPValidationValue::SetupRefDlg()
521 {
522 if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
523 {
524 if( pValidationDlg->SetupRefDlg() )
525 {
526 pValidationDlg->SetHandler( this );
527 pValidationDlg->SetSetRefHdl( static_cast<ScRefHandlerHelper::PFUNCSETREFHDLTYPE>( &ScTPValidationValue::SetReferenceHdl ) );
528 pValidationDlg->SetSetActHdl( static_cast<ScRefHandlerHelper::PCOMMONHDLTYPE>( &ScTPValidationValue::SetActiveHdl ) );
529 pValidationDlg->SetRefInputStartPreHdl( static_cast<ScRefHandlerHelper::PINPUTSTARTDLTYPE>( &ScTPValidationValue::RefInputStartPreHdl ) );
530 pValidationDlg->SetRefInputDonePostHdl( static_cast<ScRefHandlerHelper::PCOMMONHDLTYPE>( &ScTPValidationValue::RefInputDonePostHdl ) );
531
532 weld::Label* pLabel = nullptr;
533
534 if (m_xEdMax->GetWidget()->get_visible())
535 {
536 m_pRefEdit = m_xEdMax.get();
537 pLabel = m_xFtMax.get();
538 }
539 else if (m_xEdMin->GetWidget()->get_visible())
540 {
541 m_pRefEdit = m_xEdMin.get();
542 pLabel = m_xFtMin.get();
543 }
544
545 if (m_pRefEdit && !m_pRefEdit->GetWidget()->has_focus())
546 m_pRefEdit->GrabFocus();
547
548 if( m_pRefEdit )
549 m_pRefEdit->SetReferences( pValidationDlg, pLabel );
550
551 m_xBtnRef->SetReferences( pValidationDlg, m_pRefEdit );
552 }
553 }
554 }
555
RemoveRefDlg(bool bRestoreModal)556 void ScTPValidationValue::RemoveRefDlg(bool bRestoreModal)
557 {
558 if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
559 {
560 if( pValidationDlg->RemoveRefDlg(bRestoreModal) )
561 {
562 pValidationDlg->SetHandler( nullptr );
563 pValidationDlg->SetSetRefHdl( nullptr );
564 pValidationDlg->SetSetActHdl( nullptr );
565 pValidationDlg->SetRefInputStartPreHdl( nullptr );
566 pValidationDlg->SetRefInputDonePostHdl( nullptr );
567
568 if( m_pRefEdit )
569 m_pRefEdit->SetReferences( nullptr, nullptr );
570 m_pRefEdit = nullptr;
571
572 m_xBtnRef->SetReferences( nullptr, nullptr );
573 }
574 }
575 }
576
IMPL_LINK_NOARG(ScTPValidationValue,EditSetFocusHdl,formula::RefEdit &,void)577 IMPL_LINK_NOARG(ScTPValidationValue, EditSetFocusHdl, formula::RefEdit&, void)
578 {
579 const sal_Int32 nPos = m_xLbAllow->get_active();
580
581 if ( nPos == SC_VALIDDLG_ALLOW_RANGE )
582 {
583 SetupRefDlg();
584 }
585 }
586
IMPL_LINK(ScTPValidationValue,KillEditFocusHdl,formula::RefEdit &,rWnd,void)587 IMPL_LINK( ScTPValidationValue, KillEditFocusHdl, formula::RefEdit&, rWnd, void )
588 {
589 if (&rWnd != m_pRefEdit)
590 return;
591 if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
592 {
593 if (pValidationDlg->IsChildFocus() && !pValidationDlg->IsRefInputting())
594 {
595 if( ( !m_pRefEdit || !m_pRefEdit->GetWidget()->has_focus()) && !m_xBtnRef->GetWidget()->has_focus() )
596 {
597 RemoveRefDlg(true);
598 }
599 }
600 }
601 }
602
IMPL_LINK(ScTPValidationValue,KillButtonFocusHdl,formula::RefButton &,rWnd,void)603 IMPL_LINK( ScTPValidationValue, KillButtonFocusHdl, formula::RefButton&, rWnd, void )
604 {
605 if( &rWnd != m_xBtnRef.get())
606 return;
607 if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
608 if (pValidationDlg->IsChildFocus() && !pValidationDlg->IsRefInputting())
609 if( ( !m_pRefEdit || !m_pRefEdit->GetWidget()->has_focus()) && !m_xBtnRef->GetWidget()->has_focus() )
610 {
611 RemoveRefDlg(true);
612 }
613 }
614
IMPL_LINK_NOARG(ScTPValidationValue,SelectHdl,weld::ComboBox &,void)615 IMPL_LINK_NOARG(ScTPValidationValue, SelectHdl, weld::ComboBox&, void)
616 {
617 const sal_Int32 nLbPos = m_xLbAllow->get_active();
618 bool bEnable = (nLbPos != SC_VALIDDLG_ALLOW_ANY);
619 bool bRange = (nLbPos == SC_VALIDDLG_ALLOW_RANGE);
620 bool bList = (nLbPos == SC_VALIDDLG_ALLOW_LIST);
621 bool bCustom = (nLbPos == SC_VALIDDLG_ALLOW_CUSTOM);
622
623 m_xCbAllow->set_sensitive( bEnable ); // Empty cell
624 m_xFtValue->set_sensitive( bEnable );
625 m_xLbValue->set_sensitive( bEnable );
626 m_xFtMin->set_sensitive( bEnable );
627 m_xEdMin->GetWidget()->set_sensitive( bEnable );
628 m_xEdList->set_sensitive( bEnable );
629 m_xFtMax->set_sensitive( bEnable );
630 m_xEdMax->GetWidget()->set_sensitive( bEnable );
631
632 bool bShowMax = false;
633
634 if( bRange )
635 m_xFtMin->set_label( maStrRange );
636 else if( bList )
637 m_xFtMin->set_label( maStrList );
638 else if( bCustom )
639 m_xFtMin->set_label( maStrFormula );
640 else
641 {
642 switch( m_xLbValue->get_active() )
643 {
644 case SC_VALIDDLG_DATA_EQUAL:
645 case SC_VALIDDLG_DATA_NOTEQUAL: m_xFtMin->set_label( maStrValue ); break;
646
647 case SC_VALIDDLG_DATA_LESS:
648 case SC_VALIDDLG_DATA_EQLESS: m_xFtMin->set_label( maStrMax ); break;
649
650 case SC_VALIDDLG_DATA_VALIDRANGE:
651 case SC_VALIDDLG_DATA_INVALIDRANGE: bShowMax = true;
652 [[fallthrough]];
653 case SC_VALIDDLG_DATA_GREATER:
654 case SC_VALIDDLG_DATA_EQGREATER: m_xFtMin->set_label( maStrMin ); break;
655
656 default:
657 OSL_FAIL( "ScTPValidationValue::SelectHdl - unknown condition mode" );
658 }
659 }
660
661 m_xCbShow->set_visible( bRange || bList );
662 m_xCbSort->set_visible( bRange || bList );
663 m_xFtValue->set_visible( !bRange && !bList && !bCustom);
664 m_xLbValue->set_visible( !bRange && !bList && !bCustom );
665 m_xEdMin->GetWidget()->set_visible( !bList );
666 m_xEdList->set_visible( bList );
667 m_xMinGrid->set_vexpand( bList );
668 m_xFtMax->set_visible( bShowMax );
669 m_xEdMax->GetWidget()->set_visible( bShowMax );
670 m_xFtHint->set_visible( bRange );
671 m_xBtnRef->GetWidget()->set_visible( bRange ); // cell range picker
672 }
673
IMPL_LINK_NOARG(ScTPValidationValue,CheckHdl,weld::Button &,void)674 IMPL_LINK_NOARG(ScTPValidationValue, CheckHdl, weld::Button&, void)
675 {
676 m_xCbSort->set_sensitive( m_xCbShow->get_active() );
677 }
678
679 // Input Help Page
680
ScTPValidationHelp(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rArgSet)681 ScTPValidationHelp::ScTPValidationHelp(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
682 : SfxTabPage(pPage, pController, "modules/scalc/ui/validationhelptabpage.ui", "ValidationHelpTabPage", &rArgSet)
683 , m_xTsbHelp(m_xBuilder->weld_check_button("tsbhelp"))
684 , m_xEdtTitle(m_xBuilder->weld_entry("title"))
685 , m_xEdInputHelp(m_xBuilder->weld_text_view("inputhelp"))
686 {
687 m_xEdInputHelp->set_size_request(m_xEdInputHelp->get_approximate_digit_width() * 40, m_xEdInputHelp->get_height_rows(13));
688 }
689
~ScTPValidationHelp()690 ScTPValidationHelp::~ScTPValidationHelp()
691 {
692 }
693
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rArgSet)694 std::unique_ptr<SfxTabPage> ScTPValidationHelp::Create(weld::Container* pPage, weld::DialogController* pController,
695 const SfxItemSet* rArgSet)
696 {
697 return std::make_unique<ScTPValidationHelp>(pPage, pController, *rArgSet);
698 }
699
Reset(const SfxItemSet * rArgSet)700 void ScTPValidationHelp::Reset( const SfxItemSet* rArgSet )
701 {
702 const SfxPoolItem* pItem;
703
704 if ( rArgSet->GetItemState( FID_VALID_SHOWHELP, true, &pItem ) == SfxItemState::SET )
705 m_xTsbHelp->set_state( static_cast<const SfxBoolItem*>(pItem)->GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE );
706 else
707 m_xTsbHelp->set_state( TRISTATE_FALSE );
708
709 if ( rArgSet->GetItemState( FID_VALID_HELPTITLE, true, &pItem ) == SfxItemState::SET )
710 m_xEdtTitle->set_text( static_cast<const SfxStringItem*>(pItem)->GetValue() );
711 else
712 m_xEdtTitle->set_text( EMPTY_OUSTRING );
713
714 if ( rArgSet->GetItemState( FID_VALID_HELPTEXT, true, &pItem ) == SfxItemState::SET )
715 m_xEdInputHelp->set_text( static_cast<const SfxStringItem*>(pItem)->GetValue() );
716 else
717 m_xEdInputHelp->set_text( EMPTY_OUSTRING );
718 }
719
FillItemSet(SfxItemSet * rArgSet)720 bool ScTPValidationHelp::FillItemSet( SfxItemSet* rArgSet )
721 {
722 rArgSet->Put( SfxBoolItem( FID_VALID_SHOWHELP, m_xTsbHelp->get_state() == TRISTATE_TRUE ) );
723 rArgSet->Put( SfxStringItem( FID_VALID_HELPTITLE, m_xEdtTitle->get_text() ) );
724 rArgSet->Put( SfxStringItem( FID_VALID_HELPTEXT, m_xEdInputHelp->get_text() ) );
725
726 return true;
727 }
728
729 // Error Alert Page
730
ScTPValidationError(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rArgSet)731 ScTPValidationError::ScTPValidationError(weld::Container* pPage, weld::DialogController* pController,
732 const SfxItemSet& rArgSet)
733
734 : SfxTabPage ( pPage, pController,
735 "modules/scalc/ui/erroralerttabpage.ui", "ErrorAlertTabPage",
736 &rArgSet )
737 , m_xTsbShow(m_xBuilder->weld_check_button("tsbshow"))
738 , m_xLbAction(m_xBuilder->weld_combo_box("actionCB"))
739 , m_xBtnSearch(m_xBuilder->weld_button("browseBtn"))
740 , m_xEdtTitle(m_xBuilder->weld_entry("erroralert_title"))
741 , m_xFtError(m_xBuilder->weld_label("errormsg_label"))
742 , m_xEdError(m_xBuilder->weld_text_view("errorMsg"))
743 {
744 m_xEdError->set_size_request(m_xEdError->get_approximate_digit_width() * 40, m_xEdError->get_height_rows(12));
745 Init();
746 }
747
~ScTPValidationError()748 ScTPValidationError::~ScTPValidationError()
749 {
750 }
751
Init()752 void ScTPValidationError::Init()
753 {
754 m_xLbAction->connect_changed(LINK(this, ScTPValidationError, SelectActionHdl));
755 m_xBtnSearch->connect_clicked(LINK( this, ScTPValidationError, ClickSearchHdl));
756
757 m_xLbAction->set_active(0);
758
759 SelectActionHdl(*m_xLbAction);
760 }
761
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rArgSet)762 std::unique_ptr<SfxTabPage> ScTPValidationError::Create(weld::Container* pPage, weld::DialogController* pController,
763 const SfxItemSet* rArgSet)
764 {
765 return std::make_unique<ScTPValidationError>(pPage, pController, *rArgSet);
766 }
767
Reset(const SfxItemSet * rArgSet)768 void ScTPValidationError::Reset( const SfxItemSet* rArgSet )
769 {
770 const SfxPoolItem* pItem;
771
772 if ( rArgSet->GetItemState( FID_VALID_SHOWERR, true, &pItem ) == SfxItemState::SET )
773 m_xTsbShow->set_state( static_cast<const SfxBoolItem*>(pItem)->GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE );
774 else
775 m_xTsbShow->set_state( TRISTATE_TRUE ); // check by default
776
777 if ( rArgSet->GetItemState( FID_VALID_ERRSTYLE, true, &pItem ) == SfxItemState::SET )
778 m_xLbAction->set_active( static_cast<const SfxUInt16Item*>(pItem)->GetValue() );
779 else
780 m_xLbAction->set_active( 0 );
781
782 if ( rArgSet->GetItemState( FID_VALID_ERRTITLE, true, &pItem ) == SfxItemState::SET )
783 m_xEdtTitle->set_text( static_cast<const SfxStringItem*>(pItem)->GetValue() );
784 else
785 m_xEdtTitle->set_text( EMPTY_OUSTRING );
786
787 if ( rArgSet->GetItemState( FID_VALID_ERRTEXT, true, &pItem ) == SfxItemState::SET )
788 m_xEdError->set_text( static_cast<const SfxStringItem*>(pItem)->GetValue() );
789 else
790 m_xEdError->set_text( EMPTY_OUSTRING );
791
792 SelectActionHdl(*m_xLbAction);
793 }
794
FillItemSet(SfxItemSet * rArgSet)795 bool ScTPValidationError::FillItemSet( SfxItemSet* rArgSet )
796 {
797 rArgSet->Put( SfxBoolItem( FID_VALID_SHOWERR, m_xTsbShow->get_state() == TRISTATE_TRUE ) );
798 rArgSet->Put( SfxUInt16Item( FID_VALID_ERRSTYLE, m_xLbAction->get_active() ) );
799 rArgSet->Put( SfxStringItem( FID_VALID_ERRTITLE, m_xEdtTitle->get_text() ) );
800 rArgSet->Put( SfxStringItem( FID_VALID_ERRTEXT, m_xEdError->get_text() ) );
801
802 return true;
803 }
804
IMPL_LINK_NOARG(ScTPValidationError,SelectActionHdl,weld::ComboBox &,void)805 IMPL_LINK_NOARG(ScTPValidationError, SelectActionHdl, weld::ComboBox&, void)
806 {
807 ScValidErrorStyle eStyle = static_cast<ScValidErrorStyle>(m_xLbAction->get_active());
808 bool bMacro = ( eStyle == SC_VALERR_MACRO );
809
810 m_xBtnSearch->set_sensitive( bMacro );
811 m_xFtError->set_sensitive( !bMacro );
812 m_xEdError->set_sensitive( !bMacro );
813 }
814
IMPL_LINK_NOARG(ScTPValidationError,ClickSearchHdl,weld::Button &,void)815 IMPL_LINK_NOARG(ScTPValidationError, ClickSearchHdl, weld::Button&, void)
816 {
817 // Use static SfxApplication method to bring up selector dialog for
818 // choosing a script
819 OUString aScriptURL = SfxApplication::ChooseScript(GetFrameWeld());
820
821 if ( !aScriptURL.isEmpty() )
822 {
823 m_xEdtTitle->set_text( aScriptURL );
824 }
825 }
826
EnterRefStatus()827 bool ScValidationDlg::EnterRefStatus()
828 {
829 ScTabViewShell *pTabViewShell = GetTabViewShell();
830
831 if( !pTabViewShell ) return false;
832
833 sal_uInt16 nId = SLOTID;
834 SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame();
835 SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
836
837 if (pWnd && pWnd->GetController().get() != this) pWnd = nullptr;
838
839 SC_MOD()->SetRefDialog( nId, pWnd == nullptr );
840
841 return true;
842 }
843
LeaveRefStatus()844 bool ScValidationDlg::LeaveRefStatus()
845 {
846 ScTabViewShell *pTabViewShell = GetTabViewShell();
847
848 if( !pTabViewShell ) return false;
849
850 sal_uInt16 nId = SLOTID;
851 SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame();
852 if ( pViewFrm->GetChildWindow( nId ) )
853 {
854 DoClose( nId );
855 }
856 return true;
857 }
858
SetupRefDlg()859 bool ScValidationDlg::SetupRefDlg()
860 {
861 if ( m_bOwnRefHdlr ) return false;
862 if( EnterRefMode() )
863 {
864 SetModal( false );
865 return m_bOwnRefHdlr = true && EnterRefStatus();
866 }
867
868 return false;
869 }
870
RemoveRefDlg(bool bRestoreModal)871 bool ScValidationDlg::RemoveRefDlg( bool bRestoreModal /* = true */ )
872 {
873 bool bVisLock = false;
874 bool bFreeWindowLock = false;
875
876 ScTabViewShell *pTabVwSh = GetTabViewShell();
877
878 if( !pTabVwSh ) return false;
879
880 if ( SfxChildWindow* pWnd = pTabVwSh->GetViewFrame()->GetChildWindow( SID_VALIDITY_REFERENCE ) )
881 {
882 bVisLock = static_cast<ScValidityRefChildWin*>(pWnd)->LockVisible( true );
883 bFreeWindowLock = static_cast<ScValidityRefChildWin*>(pWnd)->LockFreeWindow( true );
884 }
885
886 if ( !m_bOwnRefHdlr ) return false;
887 if( LeaveRefStatus() && LeaveRefMode() )
888 {
889 m_bOwnRefHdlr = false;
890
891 if( bRestoreModal )
892 {
893 SetModal( true );
894 }
895 }
896
897 if ( SfxChildWindow* pWnd = pTabVwSh->GetViewFrame()->GetChildWindow( SID_VALIDITY_REFERENCE ) )
898 {
899 static_cast<ScValidityRefChildWin*>(pWnd)->LockVisible( bVisLock );
900 static_cast<ScValidityRefChildWin*>(pWnd)->LockFreeWindow( bFreeWindowLock );
901 }
902
903 return true;
904 }
905
IMPL_LINK_NOARG(ScTPValidationValue,ClickHdl,formula::RefButton &,void)906 IMPL_LINK_NOARG(ScTPValidationValue, ClickHdl, formula::RefButton&, void)
907 {
908 SetupRefDlg();
909 }
910
IsChildFocus() const911 bool ScValidationDlg::IsChildFocus() const
912 {
913 return m_xDialog->has_toplevel_focus();
914 }
915
916 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
917