/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifdef SC_DLLIMPLEMENTATION
#undef SC_DLLIMPLEMENTATION
#endif
#include <com/sun/star/sheet/TableValidationVisibility.hpp>
#include <comphelper/string.hxx>
#include <svl/stritem.hxx>
#include <svl/eitem.hxx>
#include <svl/intitem.hxx>
#include <sfx2/app.hxx>
#include <o3tl/string_view.hxx>
#include <scresid.hxx>
#include <strings.hrc>
#include <stringutil.hxx>
#include <validat.hxx>
#include <validate.hxx>
#include <compiler.hxx>
#include <formula/opcode.hxx>
// cell range picker
#include <tabvwsh.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/childwin.hxx>
#include <reffact.hxx>
#include <comphelper/lok.hxx>
/* Position indexes for "Allow" list box.
They do not map directly to ScValidationMode and can safely be modified to
change the order of the list box entries. */
#define SC_VALIDDLG_ALLOW_ANY 0
#define SC_VALIDDLG_ALLOW_WHOLE 1
#define SC_VALIDDLG_ALLOW_DECIMAL 2
#define SC_VALIDDLG_ALLOW_DATE 3
#define SC_VALIDDLG_ALLOW_TIME 4
#define SC_VALIDDLG_ALLOW_RANGE 5
#define SC_VALIDDLG_ALLOW_LIST 6
#define SC_VALIDDLG_ALLOW_TEXTLEN 7
#define SC_VALIDDLG_ALLOW_CUSTOM 8
/* Position indexes for "Data" list box.
They do not map directly to ScConditionMode and can safely be modified to
change the order of the list box entries. */
#define SC_VALIDDLG_DATA_EQUAL 0
#define SC_VALIDDLG_DATA_LESS 1
#define SC_VALIDDLG_DATA_GREATER 2
#define SC_VALIDDLG_DATA_EQLESS 3
#define SC_VALIDDLG_DATA_EQGREATER 4
#define SC_VALIDDLG_DATA_NOTEQUAL 5
#define SC_VALIDDLG_DATA_VALIDRANGE 6
#define SC_VALIDDLG_DATA_INVALIDRANGE 7
#define SC_VALIDDLG_DATA_DIRECT 8
namespace ValidListType = css::sheet::TableValidationVisibility;
const WhichRangesContainer ScTPValidationValue::pValueRanges(svl::Items<
FID_VALID_LISTTYPE, FID_VALID_LISTTYPE,
FID_VALID_MODE, FID_VALID_ERRTEXT
>);
static bool isLOKMobilePhone()
{
if (!comphelper::LibreOfficeKit::isActive())
return false;
SfxViewShell* pViewShell = SfxViewShell::Current();
return pViewShell && pViewShell->isLOKMobilePhone();
}
ScValidationDlg::ScValidationDlg(weld::Window* pParent, const SfxItemSet* pArgSet,
ScTabViewShell *pTabViewSh)
: ScValidationDlgBase(pParent,
u"modules/scalc/ui/validationdialog.ui"_ustr, u"ValidationDialog"_ustr, pArgSet, nullptr)
, m_pTabVwSh(pTabViewSh)
, m_sValuePageId(u"criteria"_ustr)
, m_bOwnRefHdlr(false)
, m_bRefInputting(false)
, m_xHBox(m_xBuilder->weld_container(u"refinputbox"_ustr))
{
AddTabPage(m_sValuePageId, ScTPValidationValue::Create, nullptr);
AddTabPage(u"inputhelp"_ustr, ScTPValidationHelp::Create, nullptr);
AddTabPage(u"erroralert"_ustr, ScTPValidationError::Create, nullptr);
if (isLOKMobilePhone())
{
m_xBuilder->weld_button(u"cancel"_ustr)->hide();
m_xBuilder->weld_button(u"help"_ustr)->hide();
}
}
void ScValidationDlg::EndDialog(int nResponse)
{
// tdf#155708 - do not close, just hide validation window if we click in another sheet
if (nResponse == nCloseResponseToJustHide && getDialog()->get_visible())
{
getDialog()->hide();
return;
}
// tdf#137215 ensure original modality of true is restored before dialog loop ends
if (m_bOwnRefHdlr)
RemoveRefDlg(true);
ScValidationDlgBase::EndDialog(nResponse);
}
ScValidationDlg::~ScValidationDlg()
{
if (m_bOwnRefHdlr)
RemoveRefDlg(false);
}
void ScTPValidationValue::SetReferenceHdl( const ScRange&rRange , const ScDocument& rDoc )
{
if ( rRange.aStart != rRange.aEnd )
if ( ScValidationDlg *pValidationDlg = GetValidationDlg() )
if( m_pRefEdit )
pValidationDlg->RefInputStart( m_pRefEdit );
if ( m_pRefEdit )
{
OUString aStr(rRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
m_pRefEdit->SetRefString( aStr );
}
}
void ScTPValidationValue:: SetActiveHdl()
{
if ( m_pRefEdit ) m_pRefEdit->GrabFocus();
if ( ScValidationDlg *pValidationDlg = GetValidationDlg() )
if( m_pRefEdit )
{
pValidationDlg->RefInputDone();
}
}
void ScTPValidationValue::RefInputStartPreHdl( formula::RefEdit* pEdit, const formula::RefButton* pButton )
{
ScValidationDlg *pValidationDlg = GetValidationDlg();
if (!pValidationDlg)
return;
weld::Container* pNewParent = pValidationDlg->get_refinput_shrink_parent();
if (pEdit == m_pRefEdit && pNewParent != m_pRefEditParent)
{
m_xRefGrid->move(m_pRefEdit->GetWidget(), pNewParent);
m_pRefEditParent = pNewParent;
}
if (pNewParent != m_pBtnRefParent)
{
// if Edit SetParent but button not, the tab order will be
// incorrect, so move button anyway, and restore
// parent later in order to restore the tab order. But
// hide it if it's moved but unwanted.
m_xRefGrid->move(m_xBtnRef->GetWidget(), pNewParent);
m_xBtnRef->GetWidget()->set_visible(pButton == m_xBtnRef.get());
m_pBtnRefParent = pNewParent;
}
pNewParent->show();
}
void ScTPValidationValue::RefInputDonePostHdl()
{
if (ScValidationDlg *pValidationDlg = GetValidationDlg())
{
weld::Container* pOldParent = pValidationDlg->get_refinput_shrink_parent();
if (m_pRefEdit && m_pRefEditParent != m_xRefGrid.get())
{
pOldParent->move(m_pRefEdit->GetWidget(), m_xRefGrid.get());
m_pRefEditParent = m_xRefGrid.get();
}
if (m_pBtnRefParent != m_xRefGrid.get())
{
pOldParent->move(m_xBtnRef->GetWidget(), m_xRefGrid.get());
m_xBtnRef->GetWidget()->show();
m_pBtnRefParent = m_xRefGrid.get();
}
pOldParent->hide();
ScViewData& rViewData = pValidationDlg->GetTabViewShell()->GetViewData();
SCTAB nCurTab = rViewData.GetTabNo();
SCTAB nRefTab = rViewData.GetRefTabNo();
// If RefInput switched to a different sheet from the data sheet,
// switch back: fdo#53920
if ( nCurTab != nRefTab )
{
rViewData.GetViewShell()->SetTabNo( nRefTab );
}
}
if (m_pRefEdit && !m_pRefEdit->GetWidget()->has_focus())
m_pRefEdit->GrabFocus();
}
namespace {
/** Converts the passed ScValidationMode to the position in the list box. */
sal_uInt16 lclGetPosFromValMode( ScValidationMode eValMode )
{
sal_uInt16 nLbPos = SC_VALIDDLG_ALLOW_ANY;
switch( eValMode )
{
case SC_VALID_ANY: nLbPos = SC_VALIDDLG_ALLOW_ANY; break;
case SC_VALID_WHOLE: nLbPos = SC_VALIDDLG_ALLOW_WHOLE; break;
case SC_VALID_DECIMAL: nLbPos = SC_VALIDDLG_ALLOW_DECIMAL; break;
case SC_VALID_DATE: nLbPos = SC_VALIDDLG_ALLOW_DATE; break;
case SC_VALID_TIME: nLbPos = SC_VALIDDLG_ALLOW_TIME; break;
case SC_VALID_TEXTLEN: nLbPos = SC_VALIDDLG_ALLOW_TEXTLEN; break;
case SC_VALID_LIST: nLbPos = SC_VALIDDLG_ALLOW_RANGE; break;
case SC_VALID_CUSTOM: nLbPos = SC_VALIDDLG_ALLOW_CUSTOM; break;
default: OSL_FAIL( "lclGetPosFromValMode - unknown validity mode" );
}
return nLbPos;
}
/** Converts the passed list box position to an ScValidationMode. */
ScValidationMode lclGetValModeFromPos( sal_uInt16 nLbPos )
{
ScValidationMode eValMode = SC_VALID_ANY;
switch( nLbPos )
{
case SC_VALIDDLG_ALLOW_ANY: eValMode = SC_VALID_ANY; break;
case SC_VALIDDLG_ALLOW_WHOLE: eValMode = SC_VALID_WHOLE; break;
case SC_VALIDDLG_ALLOW_DECIMAL: eValMode = SC_VALID_DECIMAL; break;
case SC_VALIDDLG_ALLOW_DATE: eValMode = SC_VALID_DATE; break;
case SC_VALIDDLG_ALLOW_TIME: eValMode = SC_VALID_TIME; break;
case SC_VALIDDLG_ALLOW_RANGE: eValMode = SC_VALID_LIST; break;
case SC_VALIDDLG_ALLOW_LIST: eValMode = SC_VALID_LIST; break;
case SC_VALIDDLG_ALLOW_TEXTLEN: eValMode = SC_VALID_TEXTLEN; break;
case SC_VALIDDLG_ALLOW_CUSTOM: eValMode = SC_VALID_CUSTOM; break;
default: OSL_FAIL( "lclGetValModeFromPos - invalid list box position" );
}
return eValMode;
}
/** Converts the passed ScConditionMode to the position in the list box. */
sal_uInt16 lclGetPosFromCondMode( ScConditionMode eCondMode )
{
sal_uInt16 nLbPos = SC_VALIDDLG_DATA_EQUAL;
switch( eCondMode )
{
case ScConditionMode::NONE: // may occur in old XML files after Excel import
case ScConditionMode::Equal: nLbPos = SC_VALIDDLG_DATA_EQUAL; break;
case ScConditionMode::Less: nLbPos = SC_VALIDDLG_DATA_LESS; break;
case ScConditionMode::Greater: nLbPos = SC_VALIDDLG_DATA_GREATER; break;
case ScConditionMode::EqLess: nLbPos = SC_VALIDDLG_DATA_EQLESS; break;
case ScConditionMode::EqGreater: nLbPos = SC_VALIDDLG_DATA_EQGREATER; break;
case ScConditionMode::NotEqual: nLbPos = SC_VALIDDLG_DATA_NOTEQUAL; break;
case ScConditionMode::Between: nLbPos = SC_VALIDDLG_DATA_VALIDRANGE; break;
case ScConditionMode::NotBetween: nLbPos = SC_VALIDDLG_DATA_INVALIDRANGE; break;
case ScConditionMode::Direct: nLbPos = SC_VALIDDLG_DATA_DIRECT; break;
default: OSL_FAIL( "lclGetPosFromCondMode - unknown condition mode" );
}
return nLbPos;
}
/** Converts the passed list box position to an ScConditionMode. */
ScConditionMode lclGetCondModeFromPos( sal_uInt16 nLbPos )
{
ScConditionMode eCondMode = ScConditionMode::Equal;
switch( nLbPos )
{
case SC_VALIDDLG_DATA_EQUAL: eCondMode = ScConditionMode::Equal; break;
case SC_VALIDDLG_DATA_LESS: eCondMode = ScConditionMode::Less; break;
case SC_VALIDDLG_DATA_GREATER: eCondMode = ScConditionMode::Greater; break;
case SC_VALIDDLG_DATA_EQLESS: eCondMode = ScConditionMode::EqLess; break;
case SC_VALIDDLG_DATA_EQGREATER: eCondMode = ScConditionMode::EqGreater; break;
case SC_VALIDDLG_DATA_NOTEQUAL: eCondMode = ScConditionMode::NotEqual; break;
case SC_VALIDDLG_DATA_VALIDRANGE: eCondMode = ScConditionMode::Between; break;
case SC_VALIDDLG_DATA_INVALIDRANGE: eCondMode = ScConditionMode::NotBetween; break;
case SC_VALIDDLG_DATA_DIRECT: eCondMode = ScConditionMode::Direct; break;
default: OSL_FAIL( "lclGetCondModeFromPos - invalid list box position" );
}
return eCondMode;
}
/** Converts line feed separated string to a formula with strings separated by semicolons.
@descr Keeps all empty strings.
Example: abc\ndef\n\nghi -> "abc";"def";"";"ghi".
@param rFmlaStr (out-param) The converted formula string. */
void lclGetFormulaFromStringList( OUString& rFmlaStr, std::u16string_view rStringList, sal_Unicode cFmlaSep )
{
rFmlaStr.clear();
if (!rStringList.empty())
{
sal_Int32 nIdx {0};
do
{
OUString aToken {o3tl::getToken(rStringList, 0, '\n', nIdx )};
ScGlobal::AddQuotes( aToken, '"' );
rFmlaStr = ScGlobal::addToken(rFmlaStr, aToken, cFmlaSep);
}
while (nIdx>0);
}
if( rFmlaStr.isEmpty() )
rFmlaStr = "\"\"";
}
/** Converts formula with strings separated by semicolons to line feed separated string.
@descr Keeps all empty strings. Ignores all empty tokens (multiple semicolons).
Example: "abc";;;"def";"";"ghi" -> abc\ndef\n\nghi.
@param rStringList (out-param) The converted line feed separated string list.
@return true = Conversion successful. */
bool lclGetStringListFromFormula( OUString& rStringList, const OUString& rFmlaStr, sal_Unicode cFmlaSep )
{
static constexpr OUStringLiteral aQuotes( u"\"\"" );
rStringList.clear();
bool bIsStringList = !rFmlaStr.isEmpty();
bool bTokenAdded = false;
for ( sal_Int32 nStringIx = 0; bIsStringList && nStringIx>=0; )
{
OUString aToken( ScStringUtil::GetQuotedToken(rFmlaStr, 0, aQuotes, cFmlaSep, nStringIx ) );
aToken = comphelper::string::strip(aToken, ' ');
if( !aToken.isEmpty() ) // ignore empty tokens, i.e. "a";;"b"
{
bIsStringList = ScGlobal::IsQuoted( aToken, '"' );
if( bIsStringList )
{
ScGlobal::EraseQuotes( aToken, '"' );
rStringList = ScGlobal::addToken(rStringList, aToken, '\n', 1, bTokenAdded);
bTokenAdded = true;
}
}
}
return bIsStringList;
}
} // namespace
ScTPValidationValue::ScTPValidationValue(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
: SfxTabPage(pPage, pController, u"modules/scalc/ui/validationcriteriapage.ui"_ustr,
u"ValidationCriteriaPage"_ustr, &rArgSet)
, maStrMin(ScResId(SCSTR_VALID_MINIMUM))
, maStrMax(ScResId(SCSTR_VALID_MAXIMUM))
, maStrValue(ScResId(SCSTR_VALID_VALUE))
, maStrFormula(ScResId(SCSTR_VALID_FORMULA))
, maStrRange(ScResId(SCSTR_VALID_RANGE))
, maStrList(ScResId(SCSTR_VALID_LIST))
, m_pRefEdit(nullptr)
, m_xLbAllow(m_xBuilder->weld_combo_box(u"allow"_ustr))
, m_xCbAllow(m_xBuilder->weld_check_button(u"allowempty"_ustr))
, m_xCbCaseSens(m_xBuilder->weld_check_button(u"casesens"_ustr))
, m_xCbShow(m_xBuilder->weld_check_button(u"showlist"_ustr))
, m_xCbSort(m_xBuilder->weld_check_button(u"sortascend"_ustr))
, m_xFtValue(m_xBuilder->weld_label(u"valueft"_ustr))
, m_xLbValue(m_xBuilder->weld_combo_box(u"data"_ustr))
, m_xFtMin(m_xBuilder->weld_label(u"minft"_ustr))
, m_xMinGrid(m_xBuilder->weld_widget(u"mingrid"_ustr))
, m_xEdMin(new formula::RefEdit(m_xBuilder->weld_entry(u"min"_ustr)))
, m_xEdList(m_xBuilder->weld_text_view(u"minlist"_ustr))
, m_xFtMax(m_xBuilder->weld_label(u"maxft"_ustr))
, m_xEdMax(new formula::RefEdit(m_xBuilder->weld_entry(u"max"_ustr)))
, m_xFtHint(m_xBuilder->weld_label(u"hintft"_ustr))
, m_xBtnRef(new formula::RefButton(m_xBuilder->weld_button(u"validref"_ustr)))
, m_xRefGrid(m_xBuilder->weld_container(u"refgrid"_ustr))
, m_pRefEditParent(m_xRefGrid.get())
, m_pBtnRefParent(m_xRefGrid.get())
{
m_xEdMin->SetReferences(nullptr, m_xFtMin.get());
Size aSize(m_xEdList->get_approximate_digit_width() * 40,
m_xEdList->get_height_rows(10));
m_xEdList->set_size_request(aSize.Width(), aSize.Height());
m_xEdMax->SetReferences(nullptr, m_xFtMax.get());
m_xBtnRef->SetClickHdl(LINK(this, ScTPValidationValue, ClickHdl));
//lock in the max size initial config
aSize = m_xContainer->get_preferred_size();
m_xContainer->set_size_request(aSize.Width(), aSize.Height());
Init();
// list separator in formulas
OUString aListSep = ::ScCompiler::GetNativeSymbol( ocSep );
OSL_ENSURE( aListSep.getLength() == 1, "ScTPValidationValue::ScTPValidationValue - list separator error" );
mcFmlaSep = aListSep.getLength() ? aListSep[0] : ';';
m_xBtnRef->GetWidget()->hide(); // cell range picker
}
ScTPValidationValue::~ScTPValidationValue()
{
m_xEdMin.reset();
m_xEdMax.reset();
m_xBtnRef.reset();
}
void ScTPValidationValue::Init()
{
m_xLbAllow->connect_changed( LINK( this, ScTPValidationValue, SelectHdl ) );
m_xLbValue->connect_changed( LINK( this, ScTPValidationValue, SelectHdl ) );
m_xCbShow->connect_toggled( LINK( this, ScTPValidationValue, CheckHdl ) );
// cell range picker
m_xEdMin->SetGetFocusHdl( LINK( this, ScTPValidationValue, EditSetFocusHdl ) );
m_xEdMin->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillEditFocusHdl ) );
m_xEdMax->SetGetFocusHdl( LINK( this, ScTPValidationValue, EditSetFocusHdl ) );
m_xEdMax->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillEditFocusHdl ) );
m_xBtnRef->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillButtonFocusHdl ) );
m_xLbAllow->set_active( SC_VALIDDLG_ALLOW_ANY );
m_xLbValue->set_active( SC_VALIDDLG_DATA_EQUAL );
SelectHdl( *m_xLbAllow );
CheckHdl( *m_xCbShow );
}
std::unique_ptr<SfxTabPage> ScTPValidationValue::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rArgSet)
{
return std::make_unique<ScTPValidationValue>(pPage, pController, *rArgSet);
}
void ScTPValidationValue::Reset( const SfxItemSet* rArgSet )
{
sal_uInt16 nLbPos = SC_VALIDDLG_ALLOW_ANY;
if( const SfxUInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_MODE ) )
nLbPos = lclGetPosFromValMode( static_cast< ScValidationMode >( pItem->GetValue() ) );
m_xLbAllow->set_active( nLbPos );
nLbPos = SC_VALIDDLG_DATA_EQUAL;
if( const SfxUInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_CONDMODE ) )
nLbPos = lclGetPosFromCondMode( static_cast< ScConditionMode >( pItem->GetValue() ) );
m_xLbValue->set_active( nLbPos );
// *** check boxes ***
bool bCheck = true;
if( const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_BLANK ) )
bCheck = pItem->GetValue();
m_xCbAllow->set_active( bCheck );
bool bCaseSensetive = false;
if (const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_CASESENS ) )
bCaseSensetive = pItem->GetValue();
m_xCbCaseSens->set_active( bCaseSensetive );
sal_Int32 nListType = ValidListType::UNSORTED;
if( const SfxInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_LISTTYPE ) )
nListType = pItem->GetValue();
m_xCbShow->set_active( nListType != ValidListType::INVISIBLE );
m_xCbSort->set_active( nListType == ValidListType::SORTEDASCENDING );
// *** formulas ***
OUString aFmlaStr;
if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_VALUE1 ) )
aFmlaStr = pItem->GetValue();
SetFirstFormula( aFmlaStr );
aFmlaStr.clear();
if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_VALUE2 ) )
aFmlaStr = pItem->GetValue();
SetSecondFormula( aFmlaStr );
SelectHdl( *m_xLbAllow );
CheckHdl( *m_xCbShow );
}
bool ScTPValidationValue::FillItemSet( SfxItemSet* rArgSet )
{
sal_Int16 nListType = m_xCbShow->get_active() ?
(m_xCbSort->get_active() ? ValidListType::SORTEDASCENDING : ValidListType::UNSORTED) :
ValidListType::INVISIBLE;
const sal_Int32 nLbPos = m_xLbAllow->get_active();
bool bCustom = (nLbPos == SC_VALIDDLG_ALLOW_CUSTOM);
ScConditionMode eCondMode = bCustom ?
ScConditionMode::Direct : lclGetCondModeFromPos( m_xLbValue->get_active() );
rArgSet->Put( SfxUInt16Item( FID_VALID_MODE, sal::static_int_cast<sal_uInt16>(
lclGetValModeFromPos( nLbPos ) ) ) );
rArgSet->Put( SfxUInt16Item( FID_VALID_CONDMODE, sal::static_int_cast<sal_uInt16>( eCondMode ) ) );
rArgSet->Put( SfxStringItem( FID_VALID_VALUE1, GetFirstFormula() ) );
rArgSet->Put( SfxStringItem( FID_VALID_VALUE2, GetSecondFormula() ) );
rArgSet->Put( SfxBoolItem( FID_VALID_BLANK, m_xCbAllow->get_active() ) );
rArgSet->Put( SfxBoolItem( FID_VALID_CASESENS, m_xCbCaseSens->get_active() ) );
rArgSet->Put( SfxInt16Item( FID_VALID_LISTTYPE, nListType ) );
return true;
}
OUString ScTPValidationValue::GetFirstFormula() const
{
OUString aFmlaStr;
if( m_xLbAllow->get_active() == SC_VALIDDLG_ALLOW_LIST )
lclGetFormulaFromStringList( aFmlaStr, m_xEdList->get_text(), mcFmlaSep );
else
aFmlaStr = m_xEdMin->GetText();
return aFmlaStr;
}
OUString ScTPValidationValue::GetSecondFormula() const
{
return m_xEdMax->GetText();
}
void ScTPValidationValue::SetFirstFormula( const OUString& rFmlaStr )
{
// try if formula is a string list, validation mode must already be set
OUString aStringList;
if( (m_xLbAllow->get_active() == SC_VALIDDLG_ALLOW_RANGE) &&
lclGetStringListFromFormula( aStringList, rFmlaStr, mcFmlaSep ) )
{
m_xEdList->set_text( aStringList );
m_xEdMin->SetText( OUString() );
// change validation mode to string list
m_xLbAllow->set_active( SC_VALIDDLG_ALLOW_LIST );
}
else
{
m_xEdMin->SetText( rFmlaStr );
m_xEdList->set_text( OUString() );
}
}
void ScTPValidationValue::SetSecondFormula( const OUString& rFmlaStr )
{
m_xEdMax->SetText( rFmlaStr );
}
ScValidationDlg * ScTPValidationValue::GetValidationDlg()
{
return dynamic_cast<ScValidationDlg*>(GetDialogController());
}
void ScTPValidationValue::SetupRefDlg()
{
ScValidationDlg *pValidationDlg = GetValidationDlg();
if( !pValidationDlg )
return;
if( !pValidationDlg->SetupRefDlg() )
return;
pValidationDlg->SetHandler( this );
pValidationDlg->SetSetRefHdl( static_cast<ScRefHandlerHelper::PFUNCSETREFHDLTYPE>( &ScTPValidationValue::SetReferenceHdl ) );
pValidationDlg->SetSetActHdl( static_cast<ScRefHandlerHelper::PCOMMONHDLTYPE>( &ScTPValidationValue::SetActiveHdl ) );
pValidationDlg->SetRefInputStartPreHdl( static_cast<ScRefHandlerHelper::PINPUTSTARTDLTYPE>( &ScTPValidationValue::RefInputStartPreHdl ) );
pValidationDlg->SetRefInputDonePostHdl( static_cast<ScRefHandlerHelper::PCOMMONHDLTYPE>( &ScTPValidationValue::RefInputDonePostHdl ) );
weld::Label* pLabel = nullptr;
if (m_xEdMax->GetWidget()->get_visible())
{
m_pRefEdit = m_xEdMax.get();
pLabel = m_xFtMax.get();
}
else if (m_xEdMin->GetWidget()->get_visible())
{
m_pRefEdit = m_xEdMin.get();
pLabel = m_xFtMin.get();
}
if (m_pRefEdit && !m_pRefEdit->GetWidget()->has_focus())
m_pRefEdit->GrabFocus();
if( m_pRefEdit )
m_pRefEdit->SetReferences( pValidationDlg, pLabel );
m_xBtnRef->SetReferences( pValidationDlg, m_pRefEdit );
}
void ScTPValidationValue::RemoveRefDlg(bool bRestoreModal)
{
ScValidationDlg *pValidationDlg = GetValidationDlg();
if( !pValidationDlg )
return;
if( !pValidationDlg->RemoveRefDlg(bRestoreModal) )
return;
pValidationDlg->SetHandler( nullptr );
pValidationDlg->SetSetRefHdl( nullptr );
pValidationDlg->SetSetActHdl( nullptr );
pValidationDlg->SetRefInputStartPreHdl( nullptr );
pValidationDlg->SetRefInputDonePostHdl( nullptr );
if( m_pRefEdit )
m_pRefEdit->SetReferences( nullptr, nullptr );
m_pRefEdit = nullptr;
m_xBtnRef->SetReferences( nullptr, nullptr );
}
IMPL_LINK_NOARG(ScTPValidationValue, EditSetFocusHdl, formula::RefEdit&, void)
{
const sal_Int32 nPos = m_xLbAllow->get_active();
if ( nPos == SC_VALIDDLG_ALLOW_RANGE )
{
SetupRefDlg();
}
}
IMPL_LINK( ScTPValidationValue, KillEditFocusHdl, formula::RefEdit&, rWnd, void )
{
if (&rWnd != m_pRefEdit)
return;
if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
{
if (pValidationDlg->IsChildFocus() && !pValidationDlg->IsRefInputting())
{
if( ( !m_pRefEdit || !m_pRefEdit->GetWidget()->has_focus()) && !m_xBtnRef->GetWidget()->has_focus() )
{
RemoveRefDlg(true);
}
}
}
}
IMPL_LINK( ScTPValidationValue, KillButtonFocusHdl, formula::RefButton&, rWnd, void )
{
if( &rWnd != m_xBtnRef.get())
return;
if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
if (pValidationDlg->IsChildFocus() && !pValidationDlg->IsRefInputting())
if( ( !m_pRefEdit || !m_pRefEdit->GetWidget()->has_focus()) && !m_xBtnRef->GetWidget()->has_focus() )
{
RemoveRefDlg(true);
}
}
IMPL_LINK_NOARG(ScTPValidationValue, SelectHdl, weld::ComboBox&, void)
{
const sal_Int32 nLbPos = m_xLbAllow->get_active();
bool bEnable = (nLbPos != SC_VALIDDLG_ALLOW_ANY);
bool bRange = (nLbPos == SC_VALIDDLG_ALLOW_RANGE);
bool bList = (nLbPos == SC_VALIDDLG_ALLOW_LIST);
bool bCustom = (nLbPos == SC_VALIDDLG_ALLOW_CUSTOM);
m_xCbAllow->set_sensitive( bEnable ); // Empty cell
m_xCbCaseSens->set_sensitive( bEnable &&
(bRange || bList || bCustom) ); // Case Sensitive
m_xFtValue->set_sensitive( bEnable );
m_xLbValue->set_sensitive( bEnable );
m_xFtMin->set_sensitive( bEnable );
m_xEdMin->GetWidget()->set_sensitive( bEnable );
m_xEdList->set_sensitive( bEnable );
m_xFtMax->set_sensitive( bEnable );
m_xEdMax->GetWidget()->set_sensitive( bEnable );
bool bShowMax = false;
if( bRange )
m_xFtMin->set_label( maStrRange );
else if( bList )
m_xFtMin->set_label( maStrList );
else if( bCustom )
m_xFtMin->set_label( maStrFormula );
else
{
switch( m_xLbValue->get_active() )
{
case SC_VALIDDLG_DATA_EQUAL:
case SC_VALIDDLG_DATA_NOTEQUAL: m_xFtMin->set_label( maStrValue ); break;
case SC_VALIDDLG_DATA_LESS:
case SC_VALIDDLG_DATA_EQLESS: m_xFtMin->set_label( maStrMax ); break;
case SC_VALIDDLG_DATA_VALIDRANGE:
case SC_VALIDDLG_DATA_INVALIDRANGE: bShowMax = true;
[[fallthrough]];
case SC_VALIDDLG_DATA_GREATER:
case SC_VALIDDLG_DATA_EQGREATER: m_xFtMin->set_label( maStrMin ); break;
default:
OSL_FAIL( "ScTPValidationValue::SelectHdl - unknown condition mode" );
}
}
m_xCbCaseSens->set_visible( bRange || bList || bCustom ); // Case Sensitive
m_xCbShow->set_visible( bRange || bList );
m_xCbSort->set_visible( bRange || bList );
m_xFtValue->set_visible( !bRange && !bList && !bCustom);
m_xLbValue->set_visible( !bRange && !bList && !bCustom );
m_xEdMin->GetWidget()->set_visible( !bList );
m_xEdList->set_visible( bList );
m_xMinGrid->set_vexpand( bList );
m_xFtMax->set_visible( bShowMax );
m_xEdMax->GetWidget()->set_visible( bShowMax );
m_xFtHint->set_visible( bRange );
m_xBtnRef->GetWidget()->set_visible( bRange ); // cell range picker
}
IMPL_LINK_NOARG(ScTPValidationValue, CheckHdl, weld::Toggleable&, void)
{
m_xCbSort->set_sensitive( m_xCbShow->get_active() );
}
// Input Help Page
ScTPValidationHelp::ScTPValidationHelp(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
: SfxTabPage(pPage, pController, u"modules/scalc/ui/validationhelptabpage.ui"_ustr, u"ValidationHelpTabPage"_ustr, &rArgSet)
, m_xTsbHelp(m_xBuilder->weld_check_button(u"tsbhelp"_ustr))
, m_xEdtTitle(m_xBuilder->weld_entry(u"title"_ustr))
, m_xEdInputHelp(m_xBuilder->weld_text_view(u"inputhelp_text"_ustr))
{
m_xEdInputHelp->set_size_request(m_xEdInputHelp->get_approximate_digit_width() * 40, m_xEdInputHelp->get_height_rows(13));
}
ScTPValidationHelp::~ScTPValidationHelp()
{
}
std::unique_ptr<SfxTabPage> ScTPValidationHelp::Create(weld::Container* pPage, weld::DialogController* pController,
const SfxItemSet* rArgSet)
{
return std::make_unique<ScTPValidationHelp>(pPage, pController, *rArgSet);
}
void ScTPValidationHelp::Reset( const SfxItemSet* rArgSet )
{
if ( const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_SHOWHELP ) )
m_xTsbHelp->set_state( pItem->GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE );
else
m_xTsbHelp->set_state( TRISTATE_FALSE );
if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_HELPTITLE ) )
m_xEdtTitle->set_text( pItem->GetValue() );
else
m_xEdtTitle->set_text( OUString() );
if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_HELPTEXT ) )
m_xEdInputHelp->set_text( pItem->GetValue() );
else
m_xEdInputHelp->set_text( OUString() );
}
bool ScTPValidationHelp::FillItemSet( SfxItemSet* rArgSet )
{
rArgSet->Put( SfxBoolItem( FID_VALID_SHOWHELP, m_xTsbHelp->get_state() == TRISTATE_TRUE ) );
rArgSet->Put( SfxStringItem( FID_VALID_HELPTITLE, m_xEdtTitle->get_text() ) );
rArgSet->Put( SfxStringItem( FID_VALID_HELPTEXT, m_xEdInputHelp->get_text() ) );
return true;
}
// Error Alert Page
ScTPValidationError::ScTPValidationError(weld::Container* pPage, weld::DialogController* pController,
const SfxItemSet& rArgSet)
: SfxTabPage ( pPage, pController,
u"modules/scalc/ui/erroralerttabpage.ui"_ustr, u"ErrorAlertTabPage"_ustr,
&rArgSet )
, m_xTsbShow(m_xBuilder->weld_check_button(u"tsbshow"_ustr))
, m_xLbAction(m_xBuilder->weld_combo_box(u"actionCB"_ustr))
, m_xBtnSearch(m_xBuilder->weld_button(u"browseBtn"_ustr))
, m_xEdtTitle(m_xBuilder->weld_entry(u"erroralert_title"_ustr))
, m_xFtError(m_xBuilder->weld_label(u"errormsg_label"_ustr))
, m_xEdError(m_xBuilder->weld_text_view(u"errorMsg"_ustr))
{
m_xEdError->set_size_request(m_xEdError->get_approximate_digit_width() * 40, m_xEdError->get_height_rows(12));
Init();
}
ScTPValidationError::~ScTPValidationError()
{
}
void ScTPValidationError::Init()
{
m_xLbAction->connect_changed(LINK(this, ScTPValidationError, SelectActionHdl));
m_xBtnSearch->connect_clicked(LINK( this, ScTPValidationError, ClickSearchHdl));
m_xLbAction->set_active(0);
SelectActionHdl(*m_xLbAction);
}
std::unique_ptr<SfxTabPage> ScTPValidationError::Create(weld::Container* pPage, weld::DialogController* pController,
const SfxItemSet* rArgSet)
{
return std::make_unique<ScTPValidationError>(pPage, pController, *rArgSet);
}
void ScTPValidationError::Reset( const SfxItemSet* rArgSet )
{
if ( const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_SHOWERR ) )
m_xTsbShow->set_state( pItem->GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE );
else
m_xTsbShow->set_state( TRISTATE_TRUE ); // check by default
if ( const SfxUInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_ERRSTYLE ) )
m_xLbAction->set_active( pItem->GetValue() );
else
m_xLbAction->set_active( 0 );
if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_ERRTITLE ) )
m_xEdtTitle->set_text( pItem->GetValue() );
else
m_xEdtTitle->set_text( OUString() );
if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_ERRTEXT ) )
m_xEdError->set_text( pItem->GetValue() );
else
m_xEdError->set_text( OUString() );
SelectActionHdl(*m_xLbAction);
}
bool ScTPValidationError::FillItemSet( SfxItemSet* rArgSet )
{
rArgSet->Put( SfxBoolItem( FID_VALID_SHOWERR, m_xTsbShow->get_state() == TRISTATE_TRUE ) );
rArgSet->Put( SfxUInt16Item( FID_VALID_ERRSTYLE, m_xLbAction->get_active() ) );
rArgSet->Put( SfxStringItem( FID_VALID_ERRTITLE, m_xEdtTitle->get_text() ) );
rArgSet->Put( SfxStringItem( FID_VALID_ERRTEXT, m_xEdError->get_text() ) );
return true;
}
IMPL_LINK_NOARG(ScTPValidationError, SelectActionHdl, weld::ComboBox&, void)
{
ScValidErrorStyle eStyle = static_cast<ScValidErrorStyle>(m_xLbAction->get_active());
bool bMacro = ( eStyle == SC_VALERR_MACRO );
m_xBtnSearch->set_sensitive( bMacro );
m_xFtError->set_sensitive( !bMacro );
m_xEdError->set_sensitive( !bMacro );
}
IMPL_LINK_NOARG(ScTPValidationError, ClickSearchHdl, weld::Button&, void)
{
// Use static SfxApplication method to bring up selector dialog for
// choosing a script
OUString aScriptURL = SfxApplication::ChooseScript(GetFrameWeld());
if ( !aScriptURL.isEmpty() )
{
m_xEdtTitle->set_text( aScriptURL );
}
}
bool ScValidationDlg::EnterRefStatus()
{
ScTabViewShell *pTabViewShell = GetTabViewShell();
if( !pTabViewShell ) return false;
sal_uInt16 nId = SLOTID;
SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
if (pWnd && pWnd->GetController().get() != this) pWnd = nullptr;
SC_MOD()->SetRefDialog( nId, pWnd == nullptr );
return true;
}
bool ScValidationDlg::LeaveRefStatus()
{
ScTabViewShell *pTabViewShell = GetTabViewShell();
if( !pTabViewShell ) return false;
sal_uInt16 nId = SLOTID;
SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
if (rViewFrm.GetChildWindow(nId))
{
DoClose( nId );
}
return true;
}
bool ScValidationDlg::SetupRefDlg()
{
if ( m_bOwnRefHdlr ) return false;
if( EnterRefMode() )
{
SetModal( false );
m_bOwnRefHdlr = true;
return EnterRefStatus();
}
return false;
}
bool ScValidationDlg::RemoveRefDlg( bool bRestoreModal /* = true */ )
{
bool bVisLock = false;
bool bFreeWindowLock = false;
ScTabViewShell *pTabVwSh = GetTabViewShell();
if( !pTabVwSh ) return false;
if ( SfxChildWindow* pWnd = pTabVwSh->GetViewFrame().GetChildWindow( SID_VALIDITY_REFERENCE ) )
{
bVisLock = static_cast<ScValidityRefChildWin*>(pWnd)->LockVisible( true );
bFreeWindowLock = static_cast<ScValidityRefChildWin*>(pWnd)->LockFreeWindow( true );
}
if ( !m_bOwnRefHdlr ) return false;
if( LeaveRefStatus() && LeaveRefMode() )
{
m_bOwnRefHdlr = false;
if( bRestoreModal )
{
SetModal( true );
}
}
if ( SfxChildWindow* pWnd = pTabVwSh->GetViewFrame().GetChildWindow( SID_VALIDITY_REFERENCE ) )
{
static_cast<ScValidityRefChildWin*>(pWnd)->LockVisible( bVisLock );
static_cast<ScValidityRefChildWin*>(pWnd)->LockFreeWindow( bFreeWindowLock );
}
return true;
}
IMPL_LINK_NOARG(ScTPValidationValue, ClickHdl, formula::RefButton&, void)
{
SetupRefDlg();
}
bool ScValidationDlg::IsChildFocus() const
{
return m_xDialog->has_toplevel_focus();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V1051 Consider checking for misprints. It's possible that the 'pOldParent' should be checked here.