diff options
Diffstat (limited to '')
36 files changed, 34593 insertions, 0 deletions
diff --git a/cui/source/tabpages/TextColumnsPage.cxx b/cui/source/tabpages/TextColumnsPage.cxx new file mode 100644 index 000000000..5bfd3b47a --- /dev/null +++ b/cui/source/tabpages/TextColumnsPage.cxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <svtools/unitconv.hxx> +#include <svx/dlgutil.hxx> +#include <svx/sdmetitm.hxx> +#include <svx/svddef.hxx> + +#include <TextColumnsPage.hxx> + +const WhichRangesContainer + SvxTextColumnsPage::pRanges(svl::Items<SDRATTR_TEXTCOLUMNS_FIRST, SDRATTR_TEXTCOLUMNS_LAST>); + +SvxTextColumnsPage::SvxTextColumnsPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/textcolumnstabpage.ui", "TextColumnsPage", &rInAttrs) + , m_xColumnsNumber(m_xBuilder->weld_spin_button("FLD_COL_NUMBER")) + , m_xColumnsSpacing( + m_xBuilder->weld_metric_spin_button("MTR_FLD_COL_SPACING", GetModuleFieldUnit(rInAttrs))) +{ +} + +SvxTextColumnsPage::~SvxTextColumnsPage() = default; + +// read the passed item set +void SvxTextColumnsPage::Reset(const SfxItemSet* rAttrs) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + assert(pPool); + + { + auto pItem = GetItem(*rAttrs, SDRATTR_TEXTCOLUMNS_NUMBER); + if (!pItem) + pItem = &pPool->GetDefaultItem(SDRATTR_TEXTCOLUMNS_NUMBER); + m_xColumnsNumber->set_value(pItem->GetValue()); + m_xColumnsNumber->save_value(); + } + + { + MapUnit eUnit = pPool->GetMetric(SDRATTR_TEXTCOLUMNS_SPACING); + auto pItem = GetItem(*rAttrs, SDRATTR_TEXTCOLUMNS_SPACING); + if (!pItem) + pItem = &pPool->GetDefaultItem(SDRATTR_TEXTCOLUMNS_SPACING); + SetMetricValue(*m_xColumnsSpacing, pItem->GetValue(), eUnit); + m_xColumnsSpacing->save_value(); + } +} + +// fill the passed item set with dialog box attributes +bool SvxTextColumnsPage::FillItemSet(SfxItemSet* rAttrs) +{ + if (m_xColumnsNumber->get_value_changed_from_saved()) + rAttrs->Put(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER, m_xColumnsNumber->get_value())); + + if (m_xColumnsSpacing->get_value_changed_from_saved()) + { + SfxItemPool* pPool = rAttrs->GetPool(); + assert(pPool); + MapUnit eUnit = pPool->GetMetric(SDRATTR_TEXTCOLUMNS_SPACING); + sal_Int32 nValue = GetCoreValue(*m_xColumnsSpacing, eUnit); + rAttrs->Put(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING, nValue)); + } + + return true; +} + +std::unique_ptr<SfxTabPage> SvxTextColumnsPage::Create(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxTextColumnsPage>(pPage, pController, *rAttrs); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/tabpages/align.cxx b/cui/source/tabpages/align.cxx new file mode 100644 index 000000000..8d2425e7e --- /dev/null +++ b/cui/source/tabpages/align.cxx @@ -0,0 +1,790 @@ +/* -*- 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 . + */ + +#include <align.hxx> + +#include <editeng/svxenum.hxx> +#include <svx/svxids.hrc> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <bitmaps.hlst> +#include <svx/rotmodit.hxx> +#include <svx/sdangitm.hxx> + +#include <editeng/frmdiritem.hxx> +#include <editeng/justifyitem.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/intitem.hxx> +#include <vcl/image.hxx> + +#define IID_BOTTOMLOCK 1 +#define IID_TOPLOCK 2 +#define IID_CELLLOCK 3 + +namespace svx { + +const WhichRangesContainer AlignmentTabPage::s_pRanges( + svl::Items< + SID_ATTR_ALIGN_STACKED, SID_ATTR_ALIGN_LINEBREAK, // 10229 - 10230 + SID_ATTR_ALIGN_INDENT, SID_ATTR_ALIGN_INDENT, // 10460 - 10460 + SID_ATTR_ALIGN_DEGREES, SID_ATTR_ALIGN_DEGREES, // 10577 - 10577 + SID_ATTR_ALIGN_LOCKPOS, SID_ATTR_ALIGN_LOCKPOS, // 10578 - 10578 + SID_ATTR_ALIGN_HYPHENATION, SID_ATTR_ALIGN_HYPHENATION, // 10931 - 10931 + SID_ATTR_FRAMEDIRECTION, SID_ATTR_FRAMEDIRECTION, // 10944 - 10944 + SID_ATTR_ALIGN_ASIANVERTICAL, SID_ATTR_ALIGN_ASIANVERTICAL, // 10949 - 10949 + SID_ATTR_ALIGN_SHRINKTOFIT, SID_ATTR_ALIGN_SHRINKTOFIT, // 11015 - 11015 + SID_ATTR_ALIGN_HOR_JUSTIFY, SID_ATTR_ALIGN_VER_JUSTIFY>); // 11571 - 11572 + + +namespace { + +template<typename JustContainerType, typename JustEnumType> +void lcl_MaybeResetAlignToDistro( + weld::ComboBox& rLB, sal_uInt16 nListId, const SfxItemSet& rCoreAttrs, TypedWhichId<SfxEnumItemInterface> nWhichAlign, TypedWhichId<SfxEnumItemInterface> nWhichJM, JustEnumType eBlock) +{ + const SfxEnumItemInterface* p = rCoreAttrs.GetItemIfSet(nWhichAlign); + if (!p) + // alignment not set. + return; + + JustContainerType eVal = static_cast<JustContainerType>(p->GetEnumValue()); + if (eVal != eBlock) + // alignment is not 'justify'. No need to go further. + return; + + p = rCoreAttrs.GetItemIfSet(nWhichJM); + if (!p) + // justification method is not set. + return; + + SvxCellJustifyMethod eMethod = static_cast<SvxCellJustifyMethod>(p->GetEnumValue()); + if (eMethod == SvxCellJustifyMethod::Distribute) + { + // Select the 'distribute' entry in the specified list box. + rLB.set_active_id(OUString::number(nListId)); + } +} + +void lcl_SetJustifyMethodToItemSet(SfxItemSet& rSet, const SfxItemSet& rOldSet, sal_uInt16 nWhichJM, const weld::ComboBox& rLB, sal_uInt16 nListId) +{ + // tdf#138698 unsupported, e.g. dbaccess + if (rLB.find_id(OUString::number(nListId)) == -1) + return; + + // feature supported , e.g. calc + SvxCellJustifyMethod eJM = SvxCellJustifyMethod::Auto; + if (rLB.get_active_id().toInt32() == nListId) + eJM = SvxCellJustifyMethod::Distribute; + + // tdf#129300 If it would create no change, don't force it + const SvxJustifyMethodItem& rOldItem = static_cast<const SvxJustifyMethodItem&>(rOldSet.Get(nWhichJM)); + if (rOldItem.GetValue() == eJM) + { + rSet.InvalidateItem(nWhichJM); + return; + } + + SvxJustifyMethodItem aItem(eJM, nWhichJM); + rSet.Put(aItem); +} + +}//namespace + +AlignmentTabPage::AlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : SfxTabPage(pPage, pController, "cui/ui/cellalignment.ui", "CellAlignPage", &rCoreAttrs) + , m_aVsRefEdge(nullptr) + // text alignment + , m_xLbHorAlign(m_xBuilder->weld_combo_box("comboboxHorzAlign")) + , m_xFtIndent(m_xBuilder->weld_label("labelIndent")) + , m_xEdIndent(m_xBuilder->weld_metric_spin_button("spinIndentFrom", FieldUnit::POINT)) + , m_xFtVerAlign(m_xBuilder->weld_label("labelVertAlign")) + , m_xLbVerAlign(m_xBuilder->weld_combo_box("comboboxVertAlign")) + //text rotation + , m_xFtRotate(m_xBuilder->weld_label("labelDegrees")) + , m_xNfRotate(m_xBuilder->weld_metric_spin_button("spinDegrees", FieldUnit::DEGREE)) + , m_xFtRefEdge(m_xBuilder->weld_label("labelRefEdge")) + //Asian mode + , m_xCbStacked(m_xBuilder->weld_check_button("checkVertStack")) + , m_xCbAsianMode(m_xBuilder->weld_check_button("checkAsianMode")) + // Properties + , m_xBoxDirection(m_xBuilder->weld_widget("boxDirection")) + , m_xBtnWrap(m_xBuilder->weld_check_button("checkWrapTextAuto")) + , m_xBtnHyphen(m_xBuilder->weld_check_button("checkHyphActive")) + , m_xBtnShrink(m_xBuilder->weld_check_button("checkShrinkFitCellSize")) + , m_xLbFrameDir(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("comboTextDirBox"))) + //ValueSet hover strings + , m_xFtBotLock(m_xBuilder->weld_label("labelSTR_BOTTOMLOCK")) + , m_xFtTopLock(m_xBuilder->weld_label("labelSTR_TOPLOCK")) + , m_xFtCelLock(m_xBuilder->weld_label("labelSTR_CELLLOCK")) + , m_xFtABCD(m_xBuilder->weld_label("labelABCD")) + , m_xAlignmentFrame(m_xBuilder->weld_widget("alignment")) + , m_xOrientFrame(m_xBuilder->weld_widget("orientation")) + , m_xPropertiesFrame(m_xBuilder->weld_widget("properties")) + , m_xVsRefEdge(new weld::CustomWeld(*m_xBuilder, "references", m_aVsRefEdge)) + , m_xCtrlDial(new DialControl) + , m_xCtrlDialWin(new weld::CustomWeld(*m_xBuilder, "dialcontrol", *m_xCtrlDial)) +{ + m_xCtrlDial->SetLinkedField(m_xNfRotate.get()); + m_xCtrlDial->SetText(m_xFtABCD->get_label()); + + InitVsRefEgde(); + + m_xLbHorAlign->connect_changed(LINK(this, AlignmentTabPage, UpdateEnableHdl)); + + m_xCbStacked->connect_toggled(LINK(this, AlignmentTabPage, StackedClickHdl)); + m_xCbAsianMode->connect_toggled(LINK(this, AlignmentTabPage, AsianModeClickHdl)); + m_xBtnWrap->connect_toggled(LINK(this, AlignmentTabPage, WrapClickHdl)); + m_xBtnHyphen->connect_toggled(LINK(this, AlignmentTabPage, HyphenClickHdl)); + m_xBtnShrink->connect_toggled(LINK(this, AlignmentTabPage, ShrinkClickHdl)); + + // Asian vertical mode + m_xCbAsianMode->set_visible(SvtCJKOptions::IsVerticalTextEnabled()); + + m_xLbFrameDir->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xLbFrameDir->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); + m_xLbFrameDir->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + + // This page needs ExchangeSupport. + SetExchangeSupport(); +} + +AlignmentTabPage::~AlignmentTabPage() +{ + m_xCtrlDialWin.reset(); + m_xCtrlDial.reset(); + m_xVsRefEdge.reset(); + m_xLbFrameDir.reset(); +} + +std::unique_ptr<SfxTabPage> AlignmentTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique<AlignmentTabPage>(pPage, pController, *rAttrSet); +} + +bool AlignmentTabPage::FillItemSet( SfxItemSet* rSet ) +{ + const SfxItemSet& rOldSet = GetItemSet(); + + bool bChanged = SfxTabPage::FillItemSet(rSet); + + sal_uInt16 nWhich = GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY); + if (m_xLbHorAlign->get_value_changed_from_saved()) + { + SvxCellHorJustify eJustify(SvxCellHorJustify::Standard); + switch (m_xLbHorAlign->get_active_id().toInt32()) + { + case ALIGNDLG_HORALIGN_STD: + eJustify = SvxCellHorJustify::Standard; + break; + case ALIGNDLG_HORALIGN_LEFT: + eJustify = SvxCellHorJustify::Left; + break; + case ALIGNDLG_HORALIGN_CENTER: + eJustify = SvxCellHorJustify::Center; + break; + case ALIGNDLG_HORALIGN_RIGHT: + eJustify = SvxCellHorJustify::Right; + break; + case ALIGNDLG_HORALIGN_BLOCK: + case ALIGNDLG_HORALIGN_DISTRIBUTED: + eJustify = SvxCellHorJustify::Block; + break; + case ALIGNDLG_HORALIGN_FILL: + eJustify = SvxCellHorJustify::Repeat; + break; + } + rSet->Put(SvxHorJustifyItem(eJustify, nWhich)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_INDENT); + if (m_xEdIndent->get_value_changed_from_saved()) + { + const SfxUInt16Item* pIndentItem = static_cast<const SfxUInt16Item*>(GetOldItem( + *rSet, SID_ATTR_ALIGN_INDENT)); + assert(pIndentItem); + std::unique_ptr<SfxUInt16Item> pNewIndentItem(pIndentItem->Clone()); + pNewIndentItem->SetValue(m_xEdIndent->get_value(FieldUnit::TWIP)); + rSet->Put(std::move(pNewIndentItem)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY); + if (m_xLbVerAlign->get_value_changed_from_saved()) + { + SvxCellVerJustify eJustify(SvxCellVerJustify::Standard); + switch (m_xLbVerAlign->get_active_id().toInt32()) + { + case ALIGNDLG_VERALIGN_STD: + eJustify = SvxCellVerJustify::Standard; + break; + case ALIGNDLG_VERALIGN_TOP: + eJustify = SvxCellVerJustify::Top; + break; + case ALIGNDLG_VERALIGN_MID: + eJustify = SvxCellVerJustify::Center; + break; + case ALIGNDLG_VERALIGN_BOTTOM: + eJustify = SvxCellVerJustify::Bottom; + break; + case ALIGNDLG_VERALIGN_BLOCK: + case ALIGNDLG_VERALIGN_DISTRIBUTED: + eJustify = SvxCellVerJustify::Block; + break; + } + rSet->Put(SvxVerJustifyItem(eJustify, nWhich)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_DEGREES); + if (m_xNfRotate->get_value_changed_from_saved()) + { + const SdrAngleItem* pAngleItem = static_cast<const SdrAngleItem*>(GetOldItem( + *rSet, SID_ATTR_ALIGN_DEGREES)); + assert(pAngleItem); + std::unique_ptr<SdrAngleItem> pNewAngleItem(pAngleItem->Clone()); + pNewAngleItem->SetValue(m_xCtrlDial->GetRotation()); + rSet->Put(std::move(pNewAngleItem)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + TypedWhichId<SvxRotateModeItem> nWhichLockPos(GetWhich(SID_ATTR_ALIGN_LOCKPOS)); + if (m_aVsRefEdge.IsValueChangedFromSaved()) + { + switch (m_aVsRefEdge.GetSelectedItemId()) + { + case IID_CELLLOCK: + rSet->Put(SvxRotateModeItem(SvxRotateMode::SVX_ROTATE_MODE_STANDARD, nWhichLockPos)); + break; + case IID_TOPLOCK: + rSet->Put(SvxRotateModeItem(SvxRotateMode::SVX_ROTATE_MODE_TOP, nWhichLockPos)); + break; + case IID_BOTTOMLOCK: + rSet->Put(SvxRotateModeItem(SvxRotateMode::SVX_ROTATE_MODE_BOTTOM, nWhichLockPos)); + break; + default: + m_aVsRefEdge.SetNoSelection(); + break; + } + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhichLockPos, false)) + rSet->InvalidateItem(nWhichLockPos); + + nWhich = GetWhich(SID_ATTR_ALIGN_STACKED); + if (m_xCbStacked->get_state_changed_from_saved()) + { + const SfxBoolItem* pStackItem = static_cast<const SfxBoolItem*>(GetOldItem( + *rSet, SID_ATTR_ALIGN_STACKED)); + assert(pStackItem); + std::unique_ptr<SfxBoolItem> pNewStackItem(pStackItem->Clone()); + pNewStackItem->SetValue(m_xCbStacked->get_active()); + rSet->Put(std::move(pNewStackItem)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_ASIANVERTICAL); + if (m_xCbAsianMode->get_state_changed_from_saved()) + { + rSet->Put(SfxBoolItem(nWhich, m_xCbAsianMode->get_active())); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_LINEBREAK); + if (m_xBtnWrap->get_state_changed_from_saved()) + { + const SfxBoolItem* pWrapItem = static_cast<const SfxBoolItem*>(GetOldItem( + *rSet, SID_ATTR_ALIGN_LINEBREAK)); + assert(pWrapItem); + std::unique_ptr<SfxBoolItem> pNewWrapItem(pWrapItem->Clone()); + pNewWrapItem->SetValue(m_xBtnWrap->get_active()); + rSet->Put(std::move(pNewWrapItem)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_HYPHENATION); + if (m_xBtnHyphen->get_state_changed_from_saved()) + { + const SfxBoolItem* pHyphItem = static_cast<const SfxBoolItem*>(GetOldItem( + *rSet, SID_ATTR_ALIGN_HYPHENATION)); + assert(pHyphItem); + std::unique_ptr<SfxBoolItem> pNewHyphItem(pHyphItem->Clone()); + pNewHyphItem->SetValue(m_xBtnHyphen->get_active()); + rSet->Put(std::move(pNewHyphItem)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + nWhich = GetWhich(SID_ATTR_ALIGN_SHRINKTOFIT); + if (m_xBtnShrink->get_state_changed_from_saved()) + { + const SfxBoolItem* pShrinkItem = static_cast<const SfxBoolItem*>(GetOldItem( + *rSet, SID_ATTR_ALIGN_SHRINKTOFIT)); + assert(pShrinkItem); + std::unique_ptr<SfxBoolItem> pNewShrinkItem(pShrinkItem->Clone()); + pNewShrinkItem->SetValue(m_xBtnShrink->get_active()); + rSet->Put(std::move(pNewShrinkItem)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + + if (m_xLbFrameDir->get_visible()) + { + nWhich = GetWhich(SID_ATTR_FRAMEDIRECTION); + if (m_xLbFrameDir->get_value_changed_from_saved()) + { + SvxFrameDirection eDir = m_xLbFrameDir->get_active_id(); + rSet->Put(SvxFrameDirectionItem(eDir, nWhich)); + bChanged = true; + } + else if (SfxItemState::DEFAULT == rOldSet.GetItemState(nWhich, false)) + rSet->InvalidateItem(nWhich); + } + + // Special treatment for distributed alignment; we need to set the justify + // method to 'distribute' to distinguish from the normal justification. + TypedWhichId<SfxEnumItemInterface> nWhichHorJM(GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD)); + lcl_SetJustifyMethodToItemSet(*rSet, rOldSet, nWhichHorJM, *m_xLbHorAlign, ALIGNDLG_HORALIGN_DISTRIBUTED); + if (!bChanged) + bChanged = HasAlignmentChanged(*rSet, nWhichHorJM); + + TypedWhichId<SfxEnumItemInterface> nWhichVerJM(GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY_METHOD)); + lcl_SetJustifyMethodToItemSet(*rSet, rOldSet, nWhichVerJM, *m_xLbVerAlign, ALIGNDLG_VERALIGN_DISTRIBUTED); + if (!bChanged) + bChanged = HasAlignmentChanged(*rSet, nWhichVerJM); + + return bChanged; +} + +namespace +{ + void ResetBool(sal_uInt16 nWhich, const SfxItemSet* pSet, weld::CheckButton& rBtn, weld::TriStateEnabled& rTriState) + { + SfxItemState eState = pSet->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + rBtn.hide(); + rTriState.bTriStateEnabled = false; + break; + case SfxItemState::DISABLED: + rBtn.set_sensitive(false); + rTriState.bTriStateEnabled = false; + break; + case SfxItemState::DONTCARE: + rBtn.set_state(TRISTATE_INDET); + rTriState.bTriStateEnabled = true; + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SfxBoolItem& rItem = static_cast<const SfxBoolItem&>(pSet->Get(nWhich)); + rBtn.set_state(static_cast<TriState>(rItem.GetValue())); + rTriState.bTriStateEnabled = false; + break; + } + } + rBtn.save_state(); + } +} + +void AlignmentTabPage::Reset(const SfxItemSet* pCoreAttrs) +{ + SfxTabPage::Reset(pCoreAttrs); + + ResetBool(GetWhich(SID_ATTR_ALIGN_STACKED), pCoreAttrs, *m_xCbStacked, m_aStackedState); + ResetBool(GetWhich(SID_ATTR_ALIGN_ASIANVERTICAL), pCoreAttrs, *m_xCbAsianMode, m_aAsianModeState); + ResetBool(GetWhich(SID_ATTR_ALIGN_LINEBREAK), pCoreAttrs, *m_xBtnWrap, m_aWrapState); + ResetBool(GetWhich(SID_ATTR_ALIGN_HYPHENATION), pCoreAttrs, *m_xBtnHyphen, m_aHyphenState); + ResetBool(GetWhich(SID_ATTR_ALIGN_SHRINKTOFIT), pCoreAttrs, *m_xBtnShrink, m_aShrinkState); + + sal_uInt16 nWhich = GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY); + SfxItemState eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xLbHorAlign->hide(); + break; + case SfxItemState::DISABLED: + m_xLbHorAlign->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xLbHorAlign->set_active(-1); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxHorJustifyItem& rJustifyItem = static_cast<const SvxHorJustifyItem&>(pCoreAttrs->Get(nWhich)); + switch (rJustifyItem.GetValue()) + { + case SvxCellHorJustify::Standard: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_STD)); + break; + case SvxCellHorJustify::Left: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_LEFT)); + break; + case SvxCellHorJustify::Center: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_CENTER)); + break; + case SvxCellHorJustify::Right: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_RIGHT)); + break; + case SvxCellHorJustify::Block: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_BLOCK)); + break; + case SvxCellHorJustify::Repeat: + m_xLbHorAlign->set_active_id(OUString::number(ALIGNDLG_HORALIGN_FILL)); + break; + } + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_INDENT); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xEdIndent->hide(); + m_xFtIndent->hide(); + break; + case SfxItemState::DISABLED: + m_xEdIndent->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xEdIndent->set_text(""); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SfxUInt16Item& rIndentItem = static_cast<const SfxUInt16Item&>(pCoreAttrs->Get(nWhich)); + m_xEdIndent->set_value(rIndentItem.GetValue(), FieldUnit::TWIP); + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xLbVerAlign->hide(); + m_xFtVerAlign->hide(); + break; + case SfxItemState::DISABLED: + m_xLbVerAlign->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xLbVerAlign->set_active(-1); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxVerJustifyItem& rJustifyItem = static_cast<const SvxVerJustifyItem&>(pCoreAttrs->Get(nWhich)); + switch (rJustifyItem.GetValue()) + { + case SvxCellVerJustify::Standard: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_STD)); + break; + case SvxCellVerJustify::Top: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_TOP)); + break; + case SvxCellVerJustify::Center: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_MID)); + break; + case SvxCellVerJustify::Bottom: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_BOTTOM)); + break; + case SvxCellVerJustify::Block: + m_xLbVerAlign->set_active_id(OUString::number(ALIGNDLG_VERALIGN_BLOCK)); + break; + } + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_DEGREES); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xNfRotate->hide(); + m_xCtrlDialWin->hide(); + break; + case SfxItemState::DISABLED: + m_xNfRotate->set_sensitive(false); + m_xCtrlDialWin->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xCtrlDial->SetNoRotation(); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SdrAngleItem& rAlignItem = static_cast<const SdrAngleItem&>(pCoreAttrs->Get(nWhich)); + m_xCtrlDial->SetRotation(rAlignItem.GetValue()); + break; + } + } + + nWhich = GetWhich(SID_ATTR_ALIGN_LOCKPOS); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xVsRefEdge->hide(); + break; + case SfxItemState::DISABLED: + m_xVsRefEdge->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_aVsRefEdge.SetNoSelection(); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxRotateModeItem& rRotateModeItem = static_cast<const SvxRotateModeItem&>(pCoreAttrs->Get(nWhich)); + switch (rRotateModeItem.GetValue()) + { + case SvxRotateMode::SVX_ROTATE_MODE_STANDARD: + m_aVsRefEdge.SelectItem(IID_CELLLOCK); + break; + case SvxRotateMode::SVX_ROTATE_MODE_TOP: + m_aVsRefEdge.SelectItem(IID_TOPLOCK); + break; + case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM: + m_aVsRefEdge.SelectItem(IID_BOTTOMLOCK); + break; + default: + m_aVsRefEdge.SetNoSelection(); + break; + } + break; + } + } + m_aVsRefEdge.SaveValue(); + + //text direction + nWhich = GetWhich(SID_ATTR_FRAMEDIRECTION); + eState = pCoreAttrs->GetItemState(nWhich); + switch (eState) + { + case SfxItemState::UNKNOWN: + m_xLbFrameDir->hide(); + break; + case SfxItemState::DISABLED: + m_xLbFrameDir->set_sensitive(false); + break; + case SfxItemState::DONTCARE: + m_xLbFrameDir->set_active(-1); + break; + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxFrameDirectionItem& rFrameDirItem = static_cast<const SvxFrameDirectionItem&>(pCoreAttrs->Get(nWhich)); + m_xLbFrameDir->set_active_id(rFrameDirItem.GetValue()); + break; + } + } + + // Special treatment for distributed alignment; we need to set the justify + // method to 'distribute' to distinguish from the normal justification. + TypedWhichId<SfxEnumItemInterface> nHorJustifyMethodWhich(GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD)); + SfxItemState eHorJustifyMethodState = pCoreAttrs->GetItemState(nHorJustifyMethodWhich); + if (eHorJustifyMethodState == SfxItemState::UNKNOWN) + { + // feature unknown, e.g. dbaccess, remove the option + int nDistribId = m_xLbHorAlign->find_id(OUString::number(ALIGNDLG_HORALIGN_DISTRIBUTED)); + if (nDistribId != -1) + m_xLbHorAlign->remove(nDistribId); + } + else + { + // feature known, e.g. calc + lcl_MaybeResetAlignToDistro<SvxCellHorJustify, SvxCellHorJustify>( + *m_xLbHorAlign, ALIGNDLG_HORALIGN_DISTRIBUTED, *pCoreAttrs, + TypedWhichId<SfxEnumItemInterface>(GetWhich(SID_ATTR_ALIGN_HOR_JUSTIFY)), nHorJustifyMethodWhich, + SvxCellHorJustify::Block); + } + + TypedWhichId<SfxEnumItemInterface> nVerJustifyMethodWhich( GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY_METHOD) ); + SfxItemState eVerJustifyMethodState = pCoreAttrs->GetItemState(nVerJustifyMethodWhich); + if (eVerJustifyMethodState == SfxItemState::UNKNOWN) + { + // feature unknown, e.g. dbaccess, remove the option + int nDistribId = m_xLbVerAlign->find_id(OUString::number(ALIGNDLG_VERALIGN_DISTRIBUTED)); + if (nDistribId != -1) + m_xLbVerAlign->remove(nDistribId); + } + else + { + // feature known, e.g. calc + lcl_MaybeResetAlignToDistro<SvxCellVerJustify, SvxCellVerJustify>( + *m_xLbVerAlign, ALIGNDLG_VERALIGN_DISTRIBUTED, *pCoreAttrs, + TypedWhichId<SfxEnumItemInterface>(GetWhich(SID_ATTR_ALIGN_VER_JUSTIFY)), nVerJustifyMethodWhich, + SvxCellVerJustify::Block); + } + + m_xLbHorAlign->save_value(); + m_xLbFrameDir->save_value(); + m_xLbVerAlign->save_value(); + m_xNfRotate->save_value(); + m_xEdIndent->save_value(); + + UpdateEnableControls(); +} + +DeactivateRC AlignmentTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void AlignmentTabPage::InitVsRefEgde() +{ + // remember selection - is deleted in call to ValueSet::Clear() + sal_uInt16 nSel = m_aVsRefEdge.GetSelectedItemId(); + + Image aBottomLock(StockImage::Yes, RID_SVXBMP_BOTTOMLOCK); + Image aTopLock(StockImage::Yes, RID_SVXBMP_TOPLOCK); + Image aCellLock(StockImage::Yes, RID_SVXBMP_CELLLOCK); + + m_aVsRefEdge.Clear(); + m_aVsRefEdge.SetStyle(m_aVsRefEdge.GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER); + + m_aVsRefEdge.SetColCount(3); + m_aVsRefEdge.InsertItem(IID_BOTTOMLOCK, aBottomLock, m_xFtBotLock->get_label()); + m_aVsRefEdge.InsertItem(IID_TOPLOCK, aTopLock, m_xFtTopLock->get_label()); + m_aVsRefEdge.InsertItem(IID_CELLLOCK, aCellLock, m_xFtCelLock->get_label()); + m_aVsRefEdge.SetOptimalSize(); + + m_aVsRefEdge.SelectItem( nSel ); +} + +void AlignmentTabPage::UpdateEnableControls() +{ + const sal_Int32 nHorAlign = m_xLbHorAlign->get_active_id().toInt32(); + bool bHorLeft = (nHorAlign == ALIGNDLG_HORALIGN_LEFT); + bool bHorBlock = (nHorAlign == ALIGNDLG_HORALIGN_BLOCK); + bool bHorFill = (nHorAlign == ALIGNDLG_HORALIGN_FILL); + bool bHorDist = (nHorAlign == ALIGNDLG_HORALIGN_DISTRIBUTED); + + // indent edit field only for left alignment + m_xFtIndent->set_sensitive( bHorLeft ); + m_xEdIndent->set_sensitive( bHorLeft ); + + // stacked disabled for fill alignment + m_xCbStacked->set_sensitive(!bHorFill); + + // hyphenation only for automatic line breaks or for block alignment + m_xBtnHyphen->set_sensitive( m_xBtnWrap->get_active() || bHorBlock ); + + // shrink only without automatic line break, and not for block, fill or distribute. + m_xBtnShrink->set_sensitive( (m_xBtnWrap->get_state() == TRISTATE_FALSE) && !bHorBlock && !bHorFill && !bHorDist ); + + // visibility of frames + m_xAlignmentFrame->set_visible(m_xLbHorAlign->get_visible() || m_xEdIndent->get_visible() || + m_xLbVerAlign->get_visible()); + m_xOrientFrame->set_visible(m_xCtrlDialWin->get_visible() || m_xVsRefEdge->get_visible() || + m_xCbStacked->get_visible() || m_xCbAsianMode->get_visible()); + m_xPropertiesFrame->set_visible(m_xBtnWrap->get_visible() || m_xBtnHyphen->get_visible() || + m_xBtnShrink->get_visible() || m_xLbFrameDir->get_visible()); + + bool bStackedText = m_xCbStacked->get_active(); + // windows to be disabled, if stacked text is turned ON + m_xFtRotate->set_sensitive(!bStackedText); + m_xFtRefEdge->set_sensitive(!bStackedText); + m_xVsRefEdge->set_sensitive(!bStackedText); + // windows to be disabled, if stacked text is turned OFF + m_xCbAsianMode->set_sensitive(bStackedText); + // rotation/stacked disabled for fill alignment/stacked + m_xCtrlDialWin->set_sensitive(!bHorFill && !bStackedText); + m_xNfRotate->set_sensitive(!bHorFill && !bStackedText); +} + +bool AlignmentTabPage::HasAlignmentChanged( const SfxItemSet& rNew, TypedWhichId<SfxEnumItemInterface> nWhich ) const +{ + const SfxItemSet& rOld = GetItemSet(); + SvxCellJustifyMethod eMethodOld = SvxCellJustifyMethod::Auto; + SvxCellJustifyMethod eMethodNew = SvxCellJustifyMethod::Auto; + if (const SfxEnumItemInterface* p = rOld.GetItemIfSet(nWhich)) + { + eMethodOld = static_cast<SvxCellJustifyMethod>(p->GetEnumValue()); + } + + if (const SfxEnumItemInterface* p = rNew.GetItemIfSet(nWhich)) + { + eMethodNew = static_cast<SvxCellJustifyMethod>(p->GetEnumValue()); + } + + return eMethodOld != eMethodNew; +} + +IMPL_LINK(AlignmentTabPage, StackedClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aStackedState.ButtonToggled(rToggle); + UpdateEnableControls(); +} + +IMPL_LINK(AlignmentTabPage, AsianModeClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aAsianModeState.ButtonToggled(rToggle); +} + +IMPL_LINK(AlignmentTabPage, WrapClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aWrapState.ButtonToggled(rToggle); + UpdateEnableControls(); +} + +IMPL_LINK(AlignmentTabPage, HyphenClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aHyphenState.ButtonToggled(rToggle); +} + +IMPL_LINK(AlignmentTabPage, ShrinkClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aShrinkState.ButtonToggled(rToggle); +} + +IMPL_LINK_NOARG(AlignmentTabPage, UpdateEnableHdl, weld::ComboBox&, void) +{ + UpdateEnableControls(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/autocdlg.cxx b/cui/source/tabpages/autocdlg.cxx new file mode 100644 index 000000000..2c978a835 --- /dev/null +++ b/cui/source/tabpages/autocdlg.cxx @@ -0,0 +1,2364 @@ +/* -*- 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 . + */ + +#include <i18nutil/unicode.hxx> +#include <o3tl/safeint.hxx> +#include <utility> +#include <vcl/event.hxx> +#include <vcl/keycodes.hxx> +#include <vcl/settings.hxx> +#include <vcl/transfer.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewsh.hxx> +#include <unotools/charclass.hxx> +#include <unotools/collatorwrapper.hxx> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/module.hxx> +#include <svl/eitem.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <svx/SmartTagMgr.hxx> +#include <com/sun/star/smarttags/XSmartTagRecognizer.hpp> +#include <rtl/strbuf.hxx> +#include <o3tl/temporary.hxx> +#include <osl/diagnose.h> +#include <tools/debug.hxx> + +#include <autocdlg.hxx> +#include <editeng/acorrcfg.hxx> +#include <editeng/svxacorr.hxx> +#include <cui/cuicharmap.hxx> +#include <strings.hrc> +#include <dialmgr.hxx> +#include <svx/svxids.hrc> + +static LanguageType eLastDialogLanguage = LANGUAGE_SYSTEM; + +using namespace ::com::sun::star::util; +using namespace ::com::sun::star; + +OfaAutoCorrDlg::OfaAutoCorrDlg(weld::Window* pParent, const SfxItemSet* _pSet ) + : SfxTabDialogController(pParent, "cui/ui/autocorrectdialog.ui", "AutoCorrectDialog", _pSet) + , m_xLanguageBox(m_xBuilder->weld_widget("langbox")) + , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("lang"))) +{ + bool bShowSWOptions = false; + bool bOpenSmartTagOptions = false; + + if ( _pSet ) + { + const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(_pSet, SID_AUTO_CORRECT_DLG, false); + if ( pItem && pItem->GetValue() ) + bShowSWOptions = true; + + const SfxBoolItem* pItem2 = SfxItemSet::GetItem<SfxBoolItem>(_pSet, SID_OPEN_SMARTTAGOPTIONS, false); + if ( pItem2 && pItem2->GetValue() ) + bOpenSmartTagOptions = true; + } + + AddTabPage("options", OfaAutocorrOptionsPage::Create, nullptr); + AddTabPage("applypage", OfaSwAutoFmtOptionsPage::Create, nullptr); + AddTabPage("wordcompletion", OfaAutoCompleteTabPage::Create, nullptr); + AddTabPage("smarttags", OfaSmartTagOptionsTabPage::Create, nullptr); + + if (!bShowSWOptions) + { + RemoveTabPage("applypage"); + RemoveTabPage("wordcompletion"); + RemoveTabPage("smarttags"); + } + else + { + // remove smart tag tab page if no extensions are installed + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags& rOpt = pAutoCorrect->GetSwFlags(); + if (!rOpt.pSmartTagMgr || 0 == rOpt.pSmartTagMgr->NumberOfRecognizers()) + RemoveTabPage("smarttags"); + + RemoveTabPage("options"); + } + + AddTabPage("replace", OfaAutocorrReplacePage::Create, nullptr); + AddTabPage("exceptions", OfaAutocorrExceptPage::Create, nullptr); + AddTabPage("localized", OfaQuoteTabPage::Create, nullptr); + + // initialize languages + //! LANGUAGE_NONE is displayed as '[All]' and the LanguageType + //! will be set to LANGUAGE_UNDETERMINED + SvxLanguageListFlags nLangList = SvxLanguageListFlags::WESTERN; + + if( SvtCTLOptions().IsCTLFontEnabled() ) + nLangList |= SvxLanguageListFlags::CTL; + if( SvtCJKOptions::IsCJKFontEnabled() ) + nLangList |= SvxLanguageListFlags::CJK; + m_xLanguageLB->SetLanguageList( nLangList, true, true ); + m_xLanguageLB->set_active_id( LANGUAGE_NONE ); + int nPos = m_xLanguageLB->get_active(); + DBG_ASSERT(nPos != -1, "listbox entry missing" ); + m_xLanguageLB->set_id(nPos, LANGUAGE_UNDETERMINED); + + // Initializing doesn't work for static on linux - therefore here + if (LANGUAGE_SYSTEM == eLastDialogLanguage) + eLastDialogLanguage = Application::GetSettings().GetLanguageTag().getLanguageType(); + + LanguageType nSelectLang = LANGUAGE_UNDETERMINED; + nPos = m_xLanguageLB->find_id(eLastDialogLanguage); + if (nPos != -1) + nSelectLang = eLastDialogLanguage; + m_xLanguageLB->set_active_id(nSelectLang); + + m_xLanguageLB->connect_changed(LINK(this, OfaAutoCorrDlg, SelectLanguageHdl)); + + if ( bOpenSmartTagOptions ) + SetCurPageId("smarttags"); +} + +OfaAutoCorrDlg::~OfaAutoCorrDlg() +{ +} + +void OfaAutoCorrDlg::EnableLanguage(bool bEnable) +{ + m_xLanguageBox->set_sensitive(bEnable); +} + +static bool lcl_FindEntry(weld::TreeView& rLB, const OUString& rEntry, + CollatorWrapper const & rCmpClass) +{ + int nCount = rLB.n_children(); + int nSelPos = rLB.get_selected_index(); + for (int i = 0; i < nCount; i++) + { + if (0 == rCmpClass.compareString(rEntry, rLB.get_text(i))) + { + rLB.select(i); + return true; + } + } + if (nSelPos != -1) + rLB.unselect(nSelPos); + return false; +} + +IMPL_LINK_NOARG(OfaAutoCorrDlg, SelectLanguageHdl, weld::ComboBox&, void) +{ + LanguageType eNewLang = m_xLanguageLB->get_active_id(); + // save old settings and fill anew + if(eNewLang == eLastDialogLanguage) + return; + + OString sPageId = GetCurPageId(); + if (sPageId == "replace") + { + OfaAutocorrReplacePage* pPage = static_cast<OfaAutocorrReplacePage*>(GetTabPage(sPageId)); + assert(pPage); + pPage->SetLanguage(eNewLang); + } + else if (sPageId == "exceptions") + { + OfaAutocorrExceptPage* pPage = static_cast<OfaAutocorrExceptPage*>(GetTabPage(sPageId)); + assert(pPage); + pPage->SetLanguage(eNewLang); + } +} + +OfaAutocorrOptionsPage::OfaAutocorrOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acoroptionspage.ui", "AutocorrectOptionsPage", &rSet) + , m_sInput(CuiResId(RID_CUISTR_USE_REPLACE)) + , m_sDoubleCaps(CuiResId(RID_CUISTR_CPTL_STT_WORD)) + , m_sStartCap(CuiResId(RID_CUISTR_CPTL_STT_SENT)) + , m_sBoldUnderline(CuiResId(RID_CUISTR_BOLD_UNDER)) + , m_sURL(CuiResId(RID_CUISTR_DETECT_URL)) + , m_sNoDblSpaces(CuiResId(RID_CUISTR_NO_DBL_SPACES)) + , m_sDash(CuiResId(RID_CUISTR_DASH)) + , m_sAccidentalCaps(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklist")) +{ + m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xCheckLB->set_size_request(-1, m_xCheckLB->get_height_rows(10)); +} + +OfaAutocorrOptionsPage::~OfaAutocorrOptionsPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaAutocorrOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutocorrOptionsPage>(pPage, pController, *rSet); +} + +#define CBCOL_FIRST 0 +#define CBCOL_SECOND 1 +#define CBCOL_BOTH 2 + +bool OfaAutocorrOptionsPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + ACFlags nFlags = pAutoCorrect->GetFlags(); + + int nPos = 0; + pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + + bool bReturn = nFlags != pAutoCorrect->GetFlags(); + if(bReturn ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return bReturn; +} + +void OfaAutocorrOptionsPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false); +} + +void OfaAutocorrOptionsPage::InsertEntry(const OUString& rTxt) +{ + m_xCheckLB->append(); + const int nRow = m_xCheckLB->n_children() - 1; + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE); + m_xCheckLB->set_text(nRow, rTxt, 0); +} + +void OfaAutocorrOptionsPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + InsertEntry(m_sInput); + InsertEntry(m_sDoubleCaps); + InsertEntry(m_sStartCap); + InsertEntry(m_sBoldUnderline); + InsertEntry(m_sURL); + InsertEntry(m_sDash); + InsertEntry(m_sNoDblSpaces); + InsertEntry(m_sAccidentalCaps); + + int nPos = 0; + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE ); + m_xCheckLB->set_toggle( nPos++, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE ); + + m_xCheckLB->thaw(); +} + +/*********************************************************************/ +/* */ +/* helping struct for dUserData of the Checklistbox */ +/* */ +/*********************************************************************/ + +namespace { + +struct ImpUserData +{ + OUString *pString; + vcl::Font *pFont; + + ImpUserData(OUString* pText, vcl::Font* pFnt) + { pString = pText; pFont = pFnt;} +}; + + +/*********************************************************************/ +/* */ +/* dialog for per cent settings */ +/* */ +/*********************************************************************/ + +class OfaAutoFmtPrcntSet : public weld::GenericDialogController +{ + std::unique_ptr<weld::MetricSpinButton> m_xPrcntMF; +public: + explicit OfaAutoFmtPrcntSet(weld::Window* pParent) + : GenericDialogController(pParent, "cui/ui/percentdialog.ui", "PercentDialog") + , m_xPrcntMF(m_xBuilder->weld_metric_spin_button("margin", FieldUnit::PERCENT)) + { + } + + weld::MetricSpinButton& GetPrcntFld() + { + return *m_xPrcntMF; + } +}; + +/*********************************************************************/ +/* */ +/* use TabPage autoformat */ +/* */ +/*********************************************************************/ + +enum OfaAutoFmtOptions +{ + USE_REPLACE_TABLE, + CORR_UPPER, + BEGIN_UPPER, + BOLD_UNDERLINE, + DETECT_URL, + REPLACE_DASHES, + DEL_SPACES_AT_STT_END, + DEL_SPACES_BETWEEN_LINES, + IGNORE_DBLSPACE, + CORRECT_CAPS_LOCK, + APPLY_NUMBERING, + INSERT_BORDER, + CREATE_TABLE, + REPLACE_STYLES, + DEL_EMPTY_NODE, + REPLACE_USER_COLL, + REPLACE_BULLETS, + MERGE_SINGLE_LINE_PARA +}; + +} + +OfaSwAutoFmtOptionsPage::OfaSwAutoFmtOptionsPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet ) + : SfxTabPage(pPage, pController, "cui/ui/applyautofmtpage.ui", "ApplyAutoFmtPage", &rSet) + , sDeleteEmptyPara(CuiResId(RID_CUISTR_DEL_EMPTY_PARA)) + , sUseReplaceTbl(CuiResId(RID_CUISTR_USE_REPLACE)) + , sCapitalStartWord(CuiResId(RID_CUISTR_CPTL_STT_WORD)) + , sCapitalStartSentence(CuiResId(RID_CUISTR_CPTL_STT_SENT)) + , sUserStyle(CuiResId(RID_CUISTR_USER_STYLE)) + , sBullet(CuiResId(RID_CUISTR_BULLET)) + , sBoldUnder(CuiResId(RID_CUISTR_BOLD_UNDER)) + , sNoDblSpaces(CuiResId(RID_CUISTR_NO_DBL_SPACES)) + , sCorrectCapsLock(CuiResId(RID_CUISTR_CORRECT_ACCIDENTAL_CAPS_LOCK)) + , sDetectURL(CuiResId(RID_CUISTR_DETECT_URL)) + , sDash(CuiResId(RID_CUISTR_DASH)) + , sRightMargin(CuiResId(RID_CUISTR_RIGHT_MARGIN)) + , sNum(CuiResId(RID_CUISTR_NUM)) + , sBorder(CuiResId(RID_CUISTR_BORDER)) + , sTable(CuiResId(RID_CUISTR_CREATE_TABLE)) + , sReplaceTemplates(CuiResId(RID_CUISTR_REPLACE_TEMPLATES)) + , sDelSpaceAtSttEnd(CuiResId(RID_CUISTR_DEL_SPACES_AT_STT_END)) + , sDelSpaceBetweenLines(CuiResId(RID_CUISTR_DEL_SPACES_BETWEEN_LINES)) + , nPercent(50) + , m_xCheckLB(m_xBuilder->weld_tree_view("list")) + , m_xEditPB(m_xBuilder->weld_button("edit")) +{ + m_xCheckLB->connect_changed(LINK(this, OfaSwAutoFmtOptionsPage, SelectHdl)); + m_xCheckLB->connect_row_activated(LINK(this, OfaSwAutoFmtOptionsPage, DoubleClickEditHdl)); + m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + + std::vector<int> aWidths + { + o3tl::narrowing<int>(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(0)).Width() * 2), + o3tl::narrowing<int>(m_xCheckLB->get_pixel_size(m_xCheckLB->get_column_title(1)).Width() * 2) + }; + m_xCheckLB->set_column_fixed_widths(aWidths); + + m_xEditPB->connect_clicked(LINK(this, OfaSwAutoFmtOptionsPage, EditHdl)); +} + +void OfaSwAutoFmtOptionsPage::CreateEntry(const OUString& rTxt, sal_uInt16 nCol) +{ + m_xCheckLB->append(); + const int nRow = m_xCheckLB->n_children() - 1; + if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH) + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH) + m_xCheckLB->set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_text(nRow, rTxt, 2); +} + +OfaSwAutoFmtOptionsPage::~OfaSwAutoFmtOptionsPage() +{ + delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(REPLACE_BULLETS)); + delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(APPLY_NUMBERING)); + delete weld::fromId<ImpUserData*>(m_xCheckLB->get_id(MERGE_SINGLE_LINE_PARA)); +} + +std::unique_ptr<SfxTabPage> OfaSwAutoFmtOptionsPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<OfaSwAutoFmtOptionsPage>(pPage, pController, *rAttrSet); +} + +bool OfaSwAutoFmtOptionsPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + ACFlags nFlags = pAutoCorrect->GetFlags(); + + bool bCheck = m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAutoCorrect != bCheck; + pOpt->bAutoCorrect = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::Autocorrect, + m_xCheckLB->get_toggle(USE_REPLACE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bCapitalStartWord != bCheck; + pOpt->bCapitalStartWord = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartWord, + m_xCheckLB->get_toggle(CORR_UPPER, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bCapitalStartSentence != bCheck; + pOpt->bCapitalStartSentence = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::CapitalStartSentence, + m_xCheckLB->get_toggle(BEGIN_UPPER, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgWeightUnderl != bCheck; + pOpt->bChgWeightUnderl = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgWeightUnderl, + m_xCheckLB->get_toggle(BOLD_UNDERLINE, CBCOL_SECOND) == TRISTATE_TRUE); + + pAutoCorrect->SetAutoCorrFlag(ACFlags::IgnoreDoubleSpace, + m_xCheckLB->get_toggle(IGNORE_DBLSPACE, CBCOL_SECOND) == TRISTATE_TRUE); + + pAutoCorrect->SetAutoCorrFlag(ACFlags::CorrectCapsLock, + m_xCheckLB->get_toggle(CORRECT_CAPS_LOCK, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DETECT_URL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bSetINetAttr != bCheck; + pOpt->bSetINetAttr = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::SetINetAttr, + m_xCheckLB->get_toggle(DETECT_URL, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DEL_EMPTY_NODE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bDelEmptyNode != bCheck; + pOpt->bDelEmptyNode = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_USER_COLL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgUserColl != bCheck; + pOpt->bChgUserColl = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_BULLETS, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgEnumNum != bCheck; + pOpt->bChgEnumNum = bCheck; + bModified |= aBulletFont != pOpt->aBulletFont; + pOpt->aBulletFont = aBulletFont; + bModified |= sBulletChar != OUString(&pOpt->cBullet, 1); + pOpt->cBullet = sBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + + bModified |= aByInputBulletFont != pOpt->aByInputBulletFont; + bModified |= sByInputBulletChar != OUString(&pOpt->cByInputBullet, 1); + pOpt->aByInputBulletFont = aByInputBulletFont; + pOpt->cByInputBullet = sByInputBulletChar.iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + + bCheck = m_xCheckLB->get_toggle(MERGE_SINGLE_LINE_PARA, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bRightMargin != bCheck; + pOpt->bRightMargin = bCheck; + bModified |= nPercent != pOpt->nRightMargin; + pOpt->nRightMargin = static_cast<sal_uInt8>(nPercent); + + bCheck = m_xCheckLB->get_toggle(APPLY_NUMBERING, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetNumRule != bCheck; + pOpt->bSetNumRule = bCheck; + + bCheck = m_xCheckLB->get_toggle(INSERT_BORDER, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bSetBorder != bCheck; + pOpt->bSetBorder = bCheck; + + bCheck = m_xCheckLB->get_toggle(CREATE_TABLE, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bCreateTable != bCheck; + pOpt->bCreateTable = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_STYLES, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bReplaceStyles != bCheck; + pOpt->bReplaceStyles = bCheck; + + bCheck = m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgToEnEmDash != bCheck; + pOpt->bChgToEnEmDash = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgToEnEmDash, + m_xCheckLB->get_toggle(REPLACE_DASHES, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatDelSpacesAtSttEnd != bCheck; + pOpt->bAFormatDelSpacesAtSttEnd = bCheck; + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_AT_STT_END, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatByInpDelSpacesAtSttEnd != bCheck; + pOpt->bAFormatByInpDelSpacesAtSttEnd = bCheck; + + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatDelSpacesBetweenLines != bCheck; + pOpt->bAFormatDelSpacesBetweenLines = bCheck; + bCheck = m_xCheckLB->get_toggle(DEL_SPACES_BETWEEN_LINES, CBCOL_SECOND) == TRISTATE_TRUE; + bModified |= pOpt->bAFormatByInpDelSpacesBetweenLines != bCheck; + pOpt->bAFormatByInpDelSpacesBetweenLines = bCheck; + + if(bModified || nFlags != pAutoCorrect->GetFlags()) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + + return true; +} + +void OfaSwAutoFmtOptionsPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false); +} + +void OfaSwAutoFmtOptionsPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + aBulletFont = pOpt->aBulletFont; + sBulletChar = OUString(&pOpt->cBullet, 1); + + aByInputBulletFont = pOpt->aByInputBulletFont; + sByInputBulletChar = OUString(&pOpt->cByInputBullet, 1); + + nPercent = pOpt->nRightMargin; + sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag()); + + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + // The following entries have to be inserted in the same order + // as in the OfaAutoFmtOptions-enum! + CreateEntry(sUseReplaceTbl, CBCOL_BOTH ); + CreateEntry(sCapitalStartWord, CBCOL_BOTH ); + CreateEntry(sCapitalStartSentence, CBCOL_BOTH ); + CreateEntry(sBoldUnder, CBCOL_BOTH ); + CreateEntry(sDetectURL, CBCOL_BOTH ); + CreateEntry(sDash, CBCOL_BOTH ); + CreateEntry(sDelSpaceAtSttEnd, CBCOL_BOTH ); + CreateEntry(sDelSpaceBetweenLines, CBCOL_BOTH ); + + CreateEntry(sNoDblSpaces, CBCOL_SECOND); + CreateEntry(sCorrectCapsLock, CBCOL_SECOND); + CreateEntry(sNum.replaceFirst("%1", sBulletChar), CBCOL_SECOND); + CreateEntry(sBorder, CBCOL_SECOND); + CreateEntry(sTable, CBCOL_SECOND); + CreateEntry(sReplaceTemplates, CBCOL_SECOND); + CreateEntry(sDeleteEmptyPara, CBCOL_FIRST ); + CreateEntry(sUserStyle, CBCOL_FIRST ); + CreateEntry(sBullet.replaceFirst("%1", sByInputBulletChar), CBCOL_FIRST); + CreateEntry(sRightMargin.replaceFirst("%1", sMargin), CBCOL_FIRST); + + m_xCheckLB->set_toggle(USE_REPLACE_TABLE, pOpt->bAutoCorrect ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(USE_REPLACE_TABLE, bool(nFlags & ACFlags::Autocorrect) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CORR_UPPER, pOpt->bCapitalStartWord ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(CORR_UPPER, bool(nFlags & ACFlags::CapitalStartWord) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(BEGIN_UPPER, pOpt->bCapitalStartSentence ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(BEGIN_UPPER, bool(nFlags & ACFlags::CapitalStartSentence) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(BOLD_UNDERLINE, pOpt->bChgWeightUnderl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(BOLD_UNDERLINE, bool(nFlags & ACFlags::ChgWeightUnderl) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DETECT_URL, pOpt->bSetINetAttr ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DETECT_URL, bool(nFlags & ACFlags::SetINetAttr) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(REPLACE_DASHES, pOpt->bChgToEnEmDash ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_DASHES, bool(nFlags & ACFlags::ChgToEnEmDash) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DEL_SPACES_AT_STT_END, pOpt->bAFormatByInpDelSpacesAtSttEnd ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(DEL_SPACES_BETWEEN_LINES, pOpt->bAFormatByInpDelSpacesBetweenLines ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(IGNORE_DBLSPACE, bool(nFlags & ACFlags::IgnoreDoubleSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CORRECT_CAPS_LOCK, bool(nFlags & ACFlags::CorrectCapsLock) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(APPLY_NUMBERING, pOpt->bSetNumRule ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(INSERT_BORDER, pOpt->bSetBorder ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(CREATE_TABLE, pOpt->bCreateTable ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(REPLACE_STYLES, pOpt->bReplaceStyles ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xCheckLB->set_toggle(DEL_EMPTY_NODE, pOpt->bDelEmptyNode ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_USER_COLL, pOpt->bChgUserColl ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(REPLACE_BULLETS, pOpt->bChgEnumNum ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xCheckLB->set_toggle(MERGE_SINGLE_LINE_PARA, pOpt->bRightMargin ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + + ImpUserData* pUserData = new ImpUserData(&sBulletChar, &aBulletFont); + OUString sId(weld::toId(pUserData)); + m_xCheckLB->set_id(REPLACE_BULLETS, sId); + + pUserData = new ImpUserData(&sMargin, nullptr); + sId = weld::toId(pUserData); + m_xCheckLB->set_id(MERGE_SINGLE_LINE_PARA, sId); + + ImpUserData* pUserData2 = new ImpUserData(&sByInputBulletChar, &aByInputBulletFont); + sId = weld::toId(pUserData2); + m_xCheckLB->set_id(APPLY_NUMBERING, sId); + + m_xCheckLB->thaw(); +} + +IMPL_LINK(OfaSwAutoFmtOptionsPage, SelectHdl, weld::TreeView&, rBox, void) +{ + m_xEditPB->set_sensitive(rBox.get_selected_id().toInt64() != 0); +} + +IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, DoubleClickEditHdl, weld::TreeView&, bool) +{ + EditHdl(*m_xEditPB); + return true; +} + +IMPL_LINK_NOARG(OfaSwAutoFmtOptionsPage, EditHdl, weld::Button&, void) +{ + int nSelEntryPos = m_xCheckLB->get_selected_index(); + if (nSelEntryPos == REPLACE_BULLETS || nSelEntryPos == APPLY_NUMBERING) + { + SvxCharacterMap aMapDlg(GetFrameWeld(), nullptr, nullptr); + ImpUserData* pUserData = weld::fromId<ImpUserData*>(m_xCheckLB->get_id(nSelEntryPos)); + aMapDlg.SetCharFont(*pUserData->pFont); + aMapDlg.SetChar( (*pUserData->pString)[0] ); + if (RET_OK == aMapDlg.run()) + { + const vcl::Font& aFont(aMapDlg.GetCharFont()); + *pUserData->pFont = aFont; + sal_UCS4 aChar = aMapDlg.GetChar(); + // using the UCS4 constructor + OUString aOUStr( &aChar, 1 ); + *pUserData->pString = aOUStr; + if (nSelEntryPos == REPLACE_BULLETS) + m_xCheckLB->set_text(nSelEntryPos, sNum.replaceFirst("%1", aOUStr), 2); + else + m_xCheckLB->set_text(nSelEntryPos, sBullet.replaceFirst("%1", aOUStr), 2); + } + } + else if( MERGE_SINGLE_LINE_PARA == nSelEntryPos ) + { + // dialog for per cent settings + OfaAutoFmtPrcntSet aDlg(GetFrameWeld()); + aDlg.GetPrcntFld().set_value(nPercent, FieldUnit::PERCENT); + if (aDlg.run() == RET_OK) + { + nPercent = static_cast<sal_uInt16>(aDlg.GetPrcntFld().get_value(FieldUnit::PERCENT)); + sMargin = unicode::formatPercent(nPercent, Application::GetSettings().GetUILanguageTag()); + m_xCheckLB->set_text(nSelEntryPos, sRightMargin.replaceFirst("%1", sMargin), 2); + } + } +} + + +OfaAutocorrReplacePage::OfaAutocorrReplacePage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acorreplacepage.ui", "AcorReplacePage", &rSet) + , eLang(eLastDialogLanguage) + , bHasSelectionText(false) + , bFirstSelect(true) + , bReplaceEditChanged(false) + , bSWriter(true) + , m_xTextOnlyCB(m_xBuilder->weld_check_button("textonly")) + , m_xShortED(m_xBuilder->weld_entry("origtext")) + , m_xReplaceED(m_xBuilder->weld_entry("newtext")) + , m_xReplaceTLB(m_xBuilder->weld_tree_view("tabview")) + , m_xNewReplacePB(m_xBuilder->weld_button("new")) + , m_xReplacePB(m_xBuilder->weld_button("replace")) + , m_xDeleteReplacePB(m_xBuilder->weld_button("delete")) + , m_xButtonBox(m_xBuilder->weld_container("buttonbox")) +{ + sNew = m_xNewReplacePB->get_label(); + sModify = m_xReplacePB->get_label(); + + // lock down the width of the button box to its max + // desired width + auto nMaxWidth = m_xButtonBox->get_preferred_size().Width(); + m_xButtonBox->set_size_request(nMaxWidth, -1); + m_xReplacePB->hide(); + + // tdf#125348 set some small but fixed initial width size, final width will + // depend on the size of the entry boxes + m_xReplaceTLB->set_size_request(42, m_xReplaceTLB->get_height_rows(10)); + + SfxModule *pMod = SfxApplication::GetModule(SfxToolsModule::Writer); + bSWriter = pMod == SfxModule::GetActiveModule(); + + LanguageTag aLanguageTag( eLastDialogLanguage ); + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( aLanguageTag.getLocale(), 0 ); + pCharClass.reset( new CharClass( std::move(aLanguageTag) ) ); + + auto nColWidth = m_xReplaceTLB->get_approximate_digit_width() * 32; + m_aReplaceFixedWidths.push_back(nColWidth); + m_aReplaceFixedWidths.push_back(nColWidth); + + m_xReplaceTLB->connect_changed( LINK(this, OfaAutocorrReplacePage, SelectHdl) ); + m_xNewReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) ); + m_xDeleteReplacePB->connect_clicked( LINK(this, OfaAutocorrReplacePage, NewDelButtonHdl) ); + m_xShortED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) ); + m_xReplaceED->connect_changed( LINK(this, OfaAutocorrReplacePage, ModifyHdl) ); + m_xShortED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) ); + m_xReplaceED->connect_activate( LINK(this, OfaAutocorrReplacePage, NewDelActionHdl) ); + m_xShortED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl)); + m_xReplaceED->connect_size_allocate(LINK(this, OfaAutocorrReplacePage, EntrySizeAllocHdl)); +} + +OfaAutocorrReplacePage::~OfaAutocorrReplacePage() +{ + aDoubleStringTable.clear(); + aChangesTable.clear(); + + pCompareClass.reset(); + pCharClass.reset(); +} + +std::unique_ptr<SfxTabPage> OfaAutocorrReplacePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutocorrReplacePage>(pPage, pController, *rSet); +} + +void OfaAutocorrReplacePage::ActivatePage( const SfxItemSet& ) +{ + if(eLang != eLastDialogLanguage) + SetLanguage(eLastDialogLanguage); + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(true); +} + +DeactivateRC OfaAutocorrReplacePage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool OfaAutocorrReplacePage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + + for (StringChangeTable::reverse_iterator it = aChangesTable.rbegin(); it != aChangesTable.rend(); ++it) + { + LanguageType eCurrentLang = it->first; + StringChangeList& rStringChangeList = it->second; + std::vector<SvxAutocorrWord> aDeleteWords; + std::vector<SvxAutocorrWord> aNewWords; + + aDeleteWords.reserve( rStringChangeList.aDeletedEntries.size() ); + for (const DoubleString & deleteEntry : rStringChangeList.aDeletedEntries) + { + SvxAutocorrWord aDeleteWord( deleteEntry.sShort, deleteEntry.sLong ); + aDeleteWords.push_back( aDeleteWord ); + } + + aNewWords.reserve( rStringChangeList.aNewEntries.size() ); + for (const DoubleString & newEntry : rStringChangeList.aNewEntries) + { + //fdo#67697 if the user data is set then we want to retain the + //source formatting of the entry, so don't use the optimized + //text-only MakeCombinedChanges for this entry + bool bKeepSourceFormatting = newEntry.pUserData == &bHasSelectionText; + if (bKeepSourceFormatting) + { + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + pAutoCorrect->PutText(newEntry.sShort, *pSh, eCurrentLang); + continue; + } + + SvxAutocorrWord aNewWord( newEntry.sShort, newEntry.sLong ); + aNewWords.push_back( aNewWord ); + } + pAutoCorrect->MakeCombinedChanges( aNewWords, aDeleteWords, eCurrentLang ); + } + aChangesTable.clear(); + return false; +} + +void OfaAutocorrReplacePage::RefillReplaceBox(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage) +{ + eLang = eNewLanguage; + if(bFromReset) + { + aDoubleStringTable.clear(); + aChangesTable.clear(); + } + else + { + DoubleStringArray* pArray; + if(aDoubleStringTable.find(eOldLanguage) != aDoubleStringTable.end()) + { + pArray = &aDoubleStringTable[eOldLanguage]; + pArray->clear(); + } + else + { + pArray = &aDoubleStringTable[eOldLanguage]; // create new array + } + + m_xReplaceTLB->all_foreach([this, &pArray](weld::TreeIter& rIter) { + pArray->push_back(DoubleString(m_xReplaceTLB->get_text(rIter, 0), + m_xReplaceTLB->get_text(rIter, 1))); + DoubleString& rDouble = pArray->back(); + rDouble.pUserData = weld::fromId<void*>(m_xReplaceTLB->get_id(rIter)); + return false; + }); + } + + if( !bSWriter ) + aFormatText.clear(); + + if (aDoubleStringTable.find(eLang) != aDoubleStringTable.end()) + { + DoubleStringArray& rArray = aDoubleStringTable[eNewLanguage]; + + m_xReplaceTLB->bulk_insert_for_each(rArray.size(), [this, &rArray](weld::TreeIter& rIter, int nIndex) { + DoubleString &rDouble = rArray[nIndex]; + bool bTextOnly = nullptr == rDouble.pUserData; + // formatted text is only in Writer + if (bSWriter || bTextOnly) + { + if (!bTextOnly) + { + // that means: with format info or even with selection text + OUString sId = weld::toId(rDouble.pUserData); + m_xReplaceTLB->set_id(rIter, sId); + } + m_xReplaceTLB->set_text(rIter, rDouble.sShort, 0); + m_xReplaceTLB->set_text(rIter, rDouble.sLong, 1); + } + else + { + aFormatText.insert(rDouble.sShort); + } + }, nullptr, &m_aReplaceFixedWidths); + } + else + { + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxAutocorrWordList* pWordList = pAutoCorrect->LoadAutocorrWordList(eLang); + const SvxAutocorrWordList::AutocorrWordSetType & rContent = pWordList->getSortedContent(); + m_xReplaceTLB->bulk_insert_for_each(rContent.size(), [this, rContent](weld::TreeIter& rIter, int nIndex) { + auto const& elem = rContent[nIndex]; + bool bTextOnly = elem.IsTextOnly(); + // formatted text is only in Writer + if (bSWriter || bTextOnly) + { + if (!bTextOnly) + { + // that means: with format info or even with selection text + OUString sId = weld::toId(m_xTextOnlyCB.get()); + m_xReplaceTLB->set_id(rIter, sId); + } + m_xReplaceTLB->set_text(rIter, elem.GetShort(), 0); + m_xReplaceTLB->set_text(rIter, elem.GetLong(), 1); + } + else + { + aFormatText.insert(elem.GetShort()); + } + }, nullptr, &m_aReplaceFixedWidths); + m_xNewReplacePB->set_sensitive(false); + m_xDeleteReplacePB->set_sensitive(false); + } + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (pViewShell && pViewShell->HasSelection()) + { + bHasSelectionText = true; + const OUString sSelection( pViewShell->GetSelectionText() ); + m_xReplaceED->set_text(sSelection); + m_xTextOnlyCB->set_active(!bSWriter); + m_xTextOnlyCB->set_sensitive(bSWriter && !sSelection.isEmpty()); + } + else + { + m_xTextOnlyCB->set_active(true); + m_xTextOnlyCB->set_sensitive(false); + } +} + +void OfaAutocorrReplacePage::Reset( const SfxItemSet* ) +{ + RefillReplaceBox(true, eLang, eLang); + m_xShortED->grab_focus(); +} + +void OfaAutocorrReplacePage::SetLanguage(LanguageType eSet) +{ + //save old settings and refill + if(eSet != eLang) + { + RefillReplaceBox(false, eLang, eSet); + eLastDialogLanguage = eSet; + + LanguageTag aLanguageTag( eLastDialogLanguage ); + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( aLanguageTag.getLocale(), 0 ); + pCharClass.reset( new CharClass( std::move(aLanguageTag) ) ); + ModifyHdl(*m_xShortED); + } +} + +IMPL_LINK(OfaAutocorrReplacePage, SelectHdl, weld::TreeView&, rBox, void) +{ + if(!bFirstSelect || !bHasSelectionText) + { + int nEntry = rBox.get_selected_index(); + OUString sTmpShort(rBox.get_text(nEntry, 0)); + // if the text is set via ModifyHdl, the cursor is always at the beginning + // of a word, although you're editing here + bool bSameContent = 0 == pCompareClass->compareString(sTmpShort, m_xShortED->get_text()); + int nStartPos, nEndPos; + m_xShortED->get_selection_bounds(nStartPos, nEndPos); + if (m_xShortED->get_text() != sTmpShort) + { + m_xShortED->set_text(sTmpShort); + // if it was only a different notation, the selection has to be set again + if (bSameContent) + { + m_xShortED->select_region(nStartPos, nEndPos); + } + } + m_xReplaceED->set_text(rBox.get_text(nEntry, 1)); + // with UserData there is a Formatinfo + m_xTextOnlyCB->set_active(rBox.get_id(nEntry).isEmpty()); + } + else + { + bFirstSelect = false; + } + + m_xNewReplacePB->set_sensitive(false); + m_xDeleteReplacePB->set_sensitive(true); +}; + +void OfaAutocorrReplacePage::NewEntry(const OUString& sShort, const OUString& sLong, bool bKeepSourceFormatting) +{ + DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; + for (size_t i = 0; i < rNewArray.size(); i++) + { + if (rNewArray[i].sShort == sShort) + { + rNewArray.erase(rNewArray.begin() + i); + break; + } + } + + DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; + for (size_t i = 0; i < rDeletedArray.size(); i++) + { + if (rDeletedArray[i].sShort == sShort) + { + rDeletedArray.erase(rDeletedArray.begin() + i); + break; + } + } + + DoubleString aNewString(sShort, sLong); + rNewArray.push_back(aNewString); + if (bKeepSourceFormatting) + rNewArray.back().pUserData = &bHasSelectionText; +} + +void OfaAutocorrReplacePage::DeleteEntry(const OUString& sShort, const OUString& sLong) +{ + DoubleStringArray& rNewArray = aChangesTable[eLang].aNewEntries; + for (size_t i = 0; i < rNewArray.size(); i++) + { + if (rNewArray[i].sShort == sShort) + { + rNewArray.erase(rNewArray.begin() + i); + break; + } + } + + DoubleStringArray& rDeletedArray = aChangesTable[eLang].aDeletedEntries; + for (size_t i = 0; i < rDeletedArray.size(); i++) + { + if (rDeletedArray[i].sShort == sShort) + { + rDeletedArray.erase(rDeletedArray.begin() + i); + break; + } + } + + DoubleString aDeletedString(sShort, sLong); + rDeletedArray.push_back(aDeletedString); +} + +IMPL_LINK(OfaAutocorrReplacePage, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(OfaAutocorrReplacePage, NewDelActionHdl, weld::Entry&, rEdit, bool) +{ + return NewDelHdl(&rEdit); +} + +IMPL_LINK_NOARG(OfaAutocorrReplacePage, EntrySizeAllocHdl, const Size&, void) +{ + m_aReplaceFixedWidths.clear(); + int x, y, width, height; + if (m_xReplaceED->get_extents_relative_to(*m_xReplaceTLB, x, y, width, height)) + { + m_aReplaceFixedWidths.push_back(x); + m_aReplaceFixedWidths.push_back(width - 1); + m_xReplaceTLB->set_column_fixed_widths(m_aReplaceFixedWidths); + } +} + +bool OfaAutocorrReplacePage::NewDelHdl(const weld::Widget* pBtn) +{ + int nEntry = m_xReplaceTLB->get_selected_index(); + if (pBtn == m_xDeleteReplacePB.get()) + { + DBG_ASSERT( nEntry != -1, "no entry selected" ); + if (nEntry != -1) + { + DeleteEntry(m_xReplaceTLB->get_text(nEntry, 0), m_xReplaceTLB->get_text(nEntry, 1)); + m_xReplaceTLB->remove(nEntry); + ModifyHdl(*m_xShortED); + return true; + } + } + + if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive()) + { + OUString sEntry(m_xShortED->get_text()); + if (!sEntry.isEmpty() && (!m_xReplaceED->get_text().isEmpty() || + ( bHasSelectionText && bSWriter ) )) + { + bool bKeepSourceFormatting = !bReplaceEditChanged && !m_xTextOnlyCB->get_active(); + + NewEntry(m_xShortED->get_text(), m_xReplaceED->get_text(), bKeepSourceFormatting); + m_xReplaceTLB->freeze(); + int nPos = -1; + if (nEntry != -1) + { + nPos = nEntry; + m_xReplaceTLB->remove(nEntry); + } + else + { + int j; + int nCount = m_xReplaceTLB->n_children(); + for (j = 0; j < nCount; ++j) + { + if (0 >= pCompareClass->compareString(sEntry, m_xReplaceTLB->get_text(j, 0))) + break; + } + nPos = j; + } + + OUString sId; + if (bKeepSourceFormatting) + { + sId = weld::toId(&bHasSelectionText); // new formatted text + } + + m_xReplaceTLB->insert(nPos, sEntry, &sId, nullptr, nullptr); + m_xReplaceTLB->set_text(nPos, m_xReplaceED->get_text(), 1); + m_xReplaceTLB->thaw(); + m_xReplaceTLB->scroll_to_row(nPos); + // if the request came from the ReplaceEdit, give focus to the ShortEdit + if (m_xReplaceED->has_focus()) + { + m_xShortED->grab_focus(); + } + } + } + else + { + // this can only be an enter in one of the two edit fields + // which means EndDialog() - has to be evaluated in KeyInput + return false; + } + ModifyHdl(*m_xShortED); + return true; +} + +IMPL_LINK(OfaAutocorrReplacePage, ModifyHdl, weld::Entry&, rEdt, void) +{ + std::unique_ptr<weld::TreeIter> xFirstSel(m_xReplaceTLB->make_iterator()); + bool bFirstSelIterSet = m_xReplaceTLB->get_selected(xFirstSel.get()); + bool bShort = &rEdt == m_xShortED.get(); + const OUString rEntry = rEdt.get_text(); + const OUString rRepString = m_xReplaceED->get_text(); + OUString aWordStr(pCharClass->lowercase(rEntry)); + + if(bShort) + { + if(!rEntry.isEmpty()) + { + bool bFound = false; + bool bTmpSelEntry=false; + + m_xReplaceTLB->all_foreach([this, &rEntry, &rRepString, &bFound, + &bTmpSelEntry, &bFirstSelIterSet, + &xFirstSel, &aWordStr](weld::TreeIter& rIter){ + OUString aTestStr = m_xReplaceTLB->get_text(rIter, 0); + if( pCompareClass->compareString(rEntry, aTestStr ) == 0 ) + { + if (!rRepString.isEmpty()) + bFirstSelect = true; + m_xReplaceTLB->set_cursor(rIter); + m_xReplaceTLB->copy_iterator(rIter, *xFirstSel); + bFirstSelIterSet = true; + m_xNewReplacePB->set_label(sModify); + bFound = true; + return true; + } + else + { + aTestStr = pCharClass->lowercase( aTestStr ); + if( aTestStr.startsWith(aWordStr) && !bTmpSelEntry ) + { + m_xReplaceTLB->scroll_to_row(rIter); + bTmpSelEntry = true; + } + } + return false; + }); + if( !bFound ) + { + m_xReplaceTLB->select(-1); + bFirstSelIterSet = false; + m_xNewReplacePB->set_label(sNew); + if( bReplaceEditChanged ) + m_xTextOnlyCB->set_sensitive(false); + } + m_xDeleteReplacePB->set_sensitive(bFound); + } + else if (m_xReplaceTLB->n_children() > 0) + { + m_xReplaceTLB->scroll_to_row(0); + } + + } + else if( !bShort ) + { + bReplaceEditChanged = true; + if (bFirstSelIterSet) + { + m_xNewReplacePB->set_label(sModify); + } + } + + const OUString& rShortTxt = m_xShortED->get_text(); + bool bEnableNew = !rShortTxt.isEmpty() && + ( !rRepString.isEmpty() || + ( bHasSelectionText && bSWriter )) && + ( !bFirstSelIterSet || rRepString != + m_xReplaceTLB->get_text(*xFirstSel, 1) ); + if( bEnableNew ) + { + for (auto const& elem : aFormatText) + { + if(elem == rShortTxt) + { + bEnableNew = false; + break; + } + } + } + m_xNewReplacePB->set_sensitive(bEnableNew); +} + +static bool lcl_FindInArray(std::vector<OUString>& rStrings, std::u16string_view rString) +{ + for (auto const& elem : rStrings) + { + if(elem == rString) + { + return true; + } + } + return false; +} + +OfaAutocorrExceptPage::OfaAutocorrExceptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/acorexceptpage.ui", "AcorExceptPage", &rSet) + , eLang(eLastDialogLanguage) + , m_xAbbrevED(m_xBuilder->weld_entry("abbrev")) + , m_xAbbrevLB(m_xBuilder->weld_tree_view("abbrevlist")) + , m_xNewAbbrevPB(m_xBuilder->weld_button("newabbrev")) + , m_xDelAbbrevPB(m_xBuilder->weld_button("delabbrev")) + , m_xAutoAbbrevCB(m_xBuilder->weld_check_button("autoabbrev")) + , m_xDoubleCapsED(m_xBuilder->weld_entry("double")) + , m_xDoubleCapsLB(m_xBuilder->weld_tree_view("doublelist")) + , m_xNewDoublePB(m_xBuilder->weld_button("newdouble")) + , m_xDelDoublePB(m_xBuilder->weld_button("deldouble")) + , m_xAutoCapsCB(m_xBuilder->weld_check_button("autodouble")) +{ + m_xAbbrevLB->make_sorted(); + m_xAbbrevLB->set_size_request(-1, m_xAbbrevLB->get_height_rows(6)); + + m_xDoubleCapsLB->make_sorted(); + m_xDoubleCapsLB->set_size_request(-1, m_xDoubleCapsLB->get_height_rows(6)); + + css::lang::Locale aLcl( LanguageTag::convertToLocale(eLastDialogLanguage )); + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( aLcl, 0 ); + + m_xNewAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xDelAbbrevPB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xNewDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + m_xDelDoublePB->connect_clicked(LINK(this, OfaAutocorrExceptPage, NewDelButtonHdl)); + + m_xAbbrevLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl)); + m_xDoubleCapsLB->connect_changed(LINK(this, OfaAutocorrExceptPage, SelectHdl)); + m_xAbbrevED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl)); + m_xDoubleCapsED->connect_changed(LINK(this, OfaAutocorrExceptPage, ModifyHdl)); + + m_xAbbrevED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl)); + m_xDoubleCapsED->connect_activate(LINK(this, OfaAutocorrExceptPage, NewDelActionHdl)); +} + +OfaAutocorrExceptPage::~OfaAutocorrExceptPage() +{ + aStringsTable.clear(); + pCompareClass.reset(); +} + +std::unique_ptr<SfxTabPage> OfaAutocorrExceptPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutocorrExceptPage>(pPage, pController, *rSet); +} + +void OfaAutocorrExceptPage::ActivatePage( const SfxItemSet& ) +{ + if(eLang != eLastDialogLanguage) + SetLanguage(eLastDialogLanguage); + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(true); +} + +DeactivateRC OfaAutocorrExceptPage::DeactivatePage( SfxItemSet* ) +{ + return DeactivateRC::LeavePage; +} + +bool OfaAutocorrExceptPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + for(StringsTable::reverse_iterator it1 = aStringsTable.rbegin(); it1 != aStringsTable.rend(); ++it1) + { + LanguageType eCurLang = it1->first; + StringsArrays& rArrays = it1->second; + if(eCurLang != eLang) // current language is treated later + { + SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWordStartExceptList(eCurLang); + + if(pWrdList) + { + size_t nCount = pWrdList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pWrdList)[ --i ]; + + if( !lcl_FindInArray(rArrays.aDoubleCapsStrings, aString)) + { + pWrdList->erase_at(i); + } + } + + for (auto const& elem : rArrays.aDoubleCapsStrings) + { + pWrdList->insert(elem); + } + pAutoCorrect->SaveWordStartExceptList(eCurLang); + } + + SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eCurLang); + + if(pCplList) + { + size_t nCount = pCplList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pCplList)[ --i ]; + if( !lcl_FindInArray(rArrays.aAbbrevStrings, aString)) + { + pCplList->erase_at(i); + } + } + + for (auto const& elem : rArrays.aAbbrevStrings) + { + pCplList->insert(elem); + } + + pAutoCorrect->SaveCplSttExceptList(eCurLang); + } + } + } + aStringsTable.clear(); + + SvStringsISortDtor* pWrdList = pAutoCorrect->LoadWordStartExceptList(eLang); + + if(pWrdList) + { + size_t nCount = pWrdList->size(); + size_t i; + for( i = nCount; i; ) + { + OUString aString = (*pWrdList)[ --i ]; + if (m_xDoubleCapsLB->find_text(aString) == -1) + { + pWrdList->erase_at(i); + } + } + nCount = m_xDoubleCapsLB->n_children(); + for( i = 0; i < nCount; ++i ) + { + pWrdList->insert(m_xDoubleCapsLB->get_text(i)); + } + pAutoCorrect->SaveWordStartExceptList(eLang); + } + + SvStringsISortDtor* pCplList = pAutoCorrect->LoadCplSttExceptList(eLang); + + if(pCplList) + { + size_t nCount = pCplList->size(); + for( size_t i = nCount; i; ) + { + OUString aString = (*pCplList)[ --i ]; + if (m_xAbbrevLB->find_text(aString) == -1) + { + pCplList->erase_at(i); + } + } + sal_Int32 nAbbrevCount = m_xAbbrevLB->n_children(); + for( sal_Int32 ia = 0; ia < nAbbrevCount; ++ia ) + { + pCplList->insert(m_xAbbrevLB->get_text(ia)); + } + pAutoCorrect->SaveCplSttExceptList(eLang); + } + if (m_xAutoAbbrevCB->get_state_changed_from_saved()) + pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordCplSttLst, m_xAutoAbbrevCB->get_active()); + if (m_xAutoCapsCB->get_state_changed_from_saved()) + pAutoCorrect->SetAutoCorrFlag( ACFlags::SaveWordWordStartLst, m_xAutoCapsCB->get_active()); + return false; +} + +void OfaAutocorrExceptPage::SetLanguage(LanguageType eSet) +{ + if(eLang != eSet) + { + // save old settings and fill anew + RefillReplaceBoxes(false, eLang, eSet); + eLastDialogLanguage = eSet; + pCompareClass.reset( new CollatorWrapper( comphelper::getProcessComponentContext() ) ); + pCompareClass->loadDefaultCollator( LanguageTag::convertToLocale( eLastDialogLanguage ), 0 ); + ModifyHdl(*m_xAbbrevED); + ModifyHdl(*m_xDoubleCapsED); + } +} + +void OfaAutocorrExceptPage::RefillReplaceBoxes(bool bFromReset, + LanguageType eOldLanguage, + LanguageType eNewLanguage) +{ + eLang = eNewLanguage; + if(bFromReset) + { + aStringsTable.clear(); + } + else + { + StringsArrays* pArrays; + if(aStringsTable.find(eOldLanguage) != aStringsTable.end()) + { + pArrays = &aStringsTable[eOldLanguage]; + pArrays->aAbbrevStrings.clear(); + pArrays->aDoubleCapsStrings.clear(); + } + else + { + pArrays = &aStringsTable[eOldLanguage]; // create new array + } + + sal_Int32 i, nCount; + nCount = m_xAbbrevLB->n_children(); + for(i = 0; i < nCount; i++) + pArrays->aAbbrevStrings.push_back(m_xAbbrevLB->get_text(i)); + + nCount = m_xDoubleCapsLB->n_children(); + for(i = 0; i < nCount; i++) + pArrays->aDoubleCapsStrings.push_back(m_xDoubleCapsLB->get_text(i)); + } + m_xDoubleCapsLB->clear(); + m_xAbbrevLB->clear(); + m_xAbbrevED->set_text(""); + m_xDoubleCapsED->set_text(""); + + if(aStringsTable.find(eLang) != aStringsTable.end()) + { + StringsArrays& rArrays = aStringsTable[eLang]; + for (auto const& elem : rArrays.aAbbrevStrings) + m_xAbbrevLB->append_text(elem); + + for (auto const& elem : rArrays.aDoubleCapsStrings) + m_xDoubleCapsLB->append_text(elem); + } + else + { + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const SvStringsISortDtor* pCplList = pAutoCorrect->GetCplSttExceptList(eLang); + const SvStringsISortDtor* pWrdList = pAutoCorrect->GetWordStartExceptList(eLang); + size_t i; + for( i = 0; i < pCplList->size(); i++ ) + { + m_xAbbrevLB->append_text((*pCplList)[i]); + } + for( i = 0; i < pWrdList->size(); i++ ) + { + m_xDoubleCapsLB->append_text((*pWrdList)[i]); + } + } +} + +void OfaAutocorrExceptPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + RefillReplaceBoxes(true, eLang, eLang); + m_xAutoAbbrevCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordCplSttLst)); + m_xAutoCapsCB->set_active(pAutoCorrect->IsAutoCorrFlag( ACFlags::SaveWordWordStartLst)); + m_xAutoAbbrevCB->save_state(); + m_xAutoCapsCB->save_state(); +} + +IMPL_LINK(OfaAutocorrExceptPage, NewDelButtonHdl, weld::Button&, rBtn, void) +{ + NewDelHdl(&rBtn); +} + +IMPL_LINK(OfaAutocorrExceptPage, NewDelActionHdl, weld::Entry&, rEdit, bool) +{ + return NewDelHdl(&rEdit); +} + +bool OfaAutocorrExceptPage::NewDelHdl(const weld::Widget* pBtn) +{ + if ((pBtn == m_xNewAbbrevPB.get() || pBtn == m_xAbbrevED.get()) + && !m_xAbbrevED->get_text().isEmpty() && m_xNewAbbrevPB->get_sensitive()) + { + m_xAbbrevLB->append_text(m_xAbbrevED->get_text()); + ModifyHdl(*m_xAbbrevED); + } + else if(pBtn == m_xDelAbbrevPB.get()) + { + m_xAbbrevLB->remove_text(m_xAbbrevED->get_text()); + ModifyHdl(*m_xAbbrevED); + } + else if((pBtn == m_xNewDoublePB.get() || pBtn == m_xDoubleCapsED.get() ) + && !m_xDoubleCapsED->get_text().isEmpty() && m_xNewDoublePB->get_sensitive()) + { + m_xDoubleCapsLB->append_text(m_xDoubleCapsED->get_text()); + ModifyHdl(*m_xDoubleCapsED); + } + else if (pBtn == m_xDelDoublePB.get()) + { + m_xDoubleCapsLB->remove_text(m_xDoubleCapsED->get_text()); + ModifyHdl(*m_xDoubleCapsED); + } + else + { + // we didn't do anything, if this was because of 'activate' in an + // entry then let it continue to close the dialog like the replace + // page does + return false; + } + return true; +} + +IMPL_LINK(OfaAutocorrExceptPage, SelectHdl, weld::TreeView&, rBox, void) +{ + if (&rBox == m_xAbbrevLB.get()) + { + m_xAbbrevED->set_text(rBox.get_selected_text()); + m_xNewAbbrevPB->set_sensitive(false); + m_xDelAbbrevPB->set_sensitive(true); + } + else + { + m_xDoubleCapsED->set_text(rBox.get_selected_text()); + m_xNewDoublePB->set_sensitive(false); + m_xDelDoublePB->set_sensitive(true); + } +} + +IMPL_LINK(OfaAutocorrExceptPage, ModifyHdl, weld::Entry&, rEdt, void) +{ + const OUString& sEntry = rEdt.get_text(); + bool bEntryLen = !sEntry.isEmpty(); + if (&rEdt == m_xAbbrevED.get()) + { + bool bSame = lcl_FindEntry(*m_xAbbrevLB, sEntry, *pCompareClass); + if(bSame && sEntry != m_xAbbrevLB->get_selected_text()) + rEdt.set_text(m_xAbbrevLB->get_selected_text()); + m_xNewAbbrevPB->set_sensitive(!bSame && bEntryLen); + m_xDelAbbrevPB->set_sensitive(bSame && bEntryLen); + } + else + { + bool bSame = lcl_FindEntry(*m_xDoubleCapsLB, sEntry, *pCompareClass); + if(bSame && sEntry != m_xDoubleCapsLB->get_selected_text()) + rEdt.set_text(m_xDoubleCapsLB->get_selected_text()); + m_xNewDoublePB->set_sensitive(!bSame && bEntryLen); + m_xDelDoublePB->set_sensitive(bSame && bEntryLen); + } +} + +namespace { + +enum OfaQuoteOptions +{ + ADD_NONBRK_SPACE, + REPLACE_1ST, + TRANSLITERATE_RTL, + REPLACE_ANGLE_QUOTES +}; + +} + +void OfaQuoteTabPage::CreateEntry(weld::TreeView& rCheckLB, const OUString& rTxt, sal_uInt16 nCol, sal_uInt16 nTextCol) +{ + rCheckLB.append(); + const int nRow = rCheckLB.n_children() - 1; + if (nCol == CBCOL_FIRST || nCol == CBCOL_BOTH) + rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_FIRST); + if (nCol == CBCOL_SECOND || nCol == CBCOL_BOTH) + rCheckLB.set_toggle(nRow, TRISTATE_FALSE, CBCOL_SECOND); + rCheckLB.set_text(nRow, rTxt, nTextCol); +} + +OfaQuoteTabPage::OfaQuoteTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/applylocalizedpage.ui", "ApplyLocalizedPage", &rSet) + , sNonBrkSpace(CuiResId(RID_CUISTR_NON_BREAK_SPACE)) + , sOrdinal(CuiResId(RID_CUISTR_ORDINAL)) + , sTransliterateRTL(CuiResId(RID_CUISTR_OLD_HUNGARIAN)) + , sAngleQuotes(CuiResId(RID_CUISTR_ANGLE_QUOTES)) + , cSglStartQuote(0) + , cSglEndQuote(0) + , cStartQuote(0) + , cEndQuote(0) + , m_xSingleTypoCB(m_xBuilder->weld_check_button("singlereplace")) + , m_xSglStartQuotePB(m_xBuilder->weld_button("startsingle")) + , m_xSglStartExFT(m_xBuilder->weld_label("singlestartex")) + , m_xSglEndQuotePB(m_xBuilder->weld_button("endsingle")) + , m_xSglEndExFT(m_xBuilder->weld_label("singleendex")) + , m_xSglStandardPB(m_xBuilder->weld_button("defaultsingle")) + , m_xDoubleTypoCB(m_xBuilder->weld_check_button("doublereplace")) + , m_xDblStartQuotePB(m_xBuilder->weld_button("startdouble")) + , m_xDblStartExFT(m_xBuilder->weld_label("doublestartex")) + , m_xDblEndQuotePB(m_xBuilder->weld_button("enddouble")) + , m_xDblEndExFT(m_xBuilder->weld_label("doubleendex")) + , m_xDblStandardPB(m_xBuilder->weld_button("defaultdouble")) + , m_sStandard(m_xSglStartExFT->get_label()) + , m_xCheckLB(m_xBuilder->weld_tree_view("checklist")) + , m_xSwCheckLB(m_xBuilder->weld_tree_view("list")) +{ + m_xSwCheckLB->set_size_request(m_xSwCheckLB->get_approximate_digit_width() * 50, + m_xSwCheckLB->get_height_rows(6)); + + bool bShowSWOptions = false; + + const SfxBoolItem* pItem = rSet.GetItem<SfxBoolItem>(SID_AUTO_CORRECT_DLG, false); + if ( pItem && pItem->GetValue() ) + bShowSWOptions = true; + + if ( bShowSWOptions ) + { + m_xSwCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + std::vector<int> aWidths + { + o3tl::narrowing<int>(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(0)).Width() * 2), + o3tl::narrowing<int>(m_xSwCheckLB->get_pixel_size(m_xSwCheckLB->get_column_title(1)).Width() * 2) + }; + m_xSwCheckLB->set_column_fixed_widths(aWidths); + m_xCheckLB->hide(); + } + else + { + m_xCheckLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + m_xSwCheckLB->hide(); + } + + m_xDblStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xDblEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xSglStartQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xSglEndQuotePB->connect_clicked(LINK(this, OfaQuoteTabPage, QuoteHdl)); + m_xDblStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl)); + m_xSglStandardPB->connect_clicked(LINK(this, OfaQuoteTabPage, StdQuoteHdl)); +} + +OfaQuoteTabPage::~OfaQuoteTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaQuoteTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<OfaQuoteTabPage>(pPage, pController, *rAttrSet); +} + +bool OfaQuoteTabPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + + ACFlags nFlags = pAutoCorrect->GetFlags(); + + if (m_xCheckLB->get_visible()) + { + int nPos = 0; + pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, m_xCheckLB->get_toggle(nPos++) == TRISTATE_TRUE); + } + + bool bModified = false; + if (m_xSwCheckLB->get_visible()) + { + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + bool bCheck = m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bAddNonBrkSpace != bCheck; + pOpt->bAddNonBrkSpace = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::AddNonBrkSpace, + m_xSwCheckLB->get_toggle(ADD_NONBRK_SPACE, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgOrdinalNumber != bCheck; + pOpt->bChgOrdinalNumber = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgOrdinalNumber, + m_xSwCheckLB->get_toggle(REPLACE_1ST, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bTransliterateRTL != bCheck; + pOpt->bTransliterateRTL = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::TransliterateRTL, + m_xSwCheckLB->get_toggle(TRANSLITERATE_RTL, CBCOL_SECOND) == TRISTATE_TRUE); + + bCheck = m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_FIRST) == TRISTATE_TRUE; + bModified |= pOpt->bChgAngleQuotes != bCheck; + pOpt->bChgAngleQuotes = bCheck; + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgAngleQuotes, + m_xSwCheckLB->get_toggle(REPLACE_ANGLE_QUOTES, CBCOL_SECOND) == TRISTATE_TRUE); + } + + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgQuotes, m_xDoubleTypoCB->get_active()); + pAutoCorrect->SetAutoCorrFlag(ACFlags::ChgSglQuotes, m_xSingleTypoCB->get_active()); + bool bReturn = nFlags != pAutoCorrect->GetFlags(); + if(cStartQuote != pAutoCorrect->GetStartDoubleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cStartQuote); //TODO + pAutoCorrect->SetStartDoubleQuote(cUCS2); + } + if(cEndQuote != pAutoCorrect->GetEndDoubleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cEndQuote); //TODO + pAutoCorrect->SetEndDoubleQuote(cUCS2); + } + if(cSglStartQuote != pAutoCorrect->GetStartSingleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cSglStartQuote); //TODO + pAutoCorrect->SetStartSingleQuote(cUCS2); + } + if(cSglEndQuote != pAutoCorrect->GetEndSingleQuote()) + { + bReturn = true; + sal_Unicode cUCS2 = static_cast<sal_Unicode>(cSglEndQuote); //TODO + pAutoCorrect->SetEndSingleQuote(cUCS2); + } + + if( bModified || bReturn ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return bReturn; +} + +void OfaQuoteTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage(false); +} + +void OfaQuoteTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + const ACFlags nFlags = pAutoCorrect->GetFlags(); + + // Initialize the Sw options + if (m_xSwCheckLB->get_visible()) + { + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + m_xSwCheckLB->freeze(); + m_xSwCheckLB->clear(); + + CreateEntry(*m_xSwCheckLB, sNonBrkSpace, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sOrdinal, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sTransliterateRTL, CBCOL_BOTH, 2); + CreateEntry(*m_xSwCheckLB, sAngleQuotes, CBCOL_BOTH, 2); + + m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, pOpt->bAddNonBrkSpace ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(ADD_NONBRK_SPACE, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(REPLACE_1ST, pOpt->bChgOrdinalNumber ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(REPLACE_1ST, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, pOpt->bTransliterateRTL ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(TRANSLITERATE_RTL, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, pOpt->bChgAngleQuotes ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_FIRST); + m_xSwCheckLB->set_toggle(REPLACE_ANGLE_QUOTES, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE, CBCOL_SECOND); + + m_xSwCheckLB->thaw(); + } + + // Initialize the non Sw options + if (m_xCheckLB->get_visible()) + { + m_xCheckLB->freeze(); + m_xCheckLB->clear(); + + int nPos = 0; + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::AddNonBrkSpace) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sNonBrkSpace, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgOrdinalNumber) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sOrdinal, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::TransliterateRTL) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sTransliterateRTL, 0); + m_xCheckLB->append(); + m_xCheckLB->set_toggle(nPos, bool(nFlags & ACFlags::ChgAngleQuotes) ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xCheckLB->set_text(nPos++, sAngleQuotes, 0); + + m_xCheckLB->thaw(); + } + + // Initialize the quote stuffs + m_xDoubleTypoCB->set_active(bool(nFlags & ACFlags::ChgQuotes)); + m_xSingleTypoCB->set_active(bool(nFlags & ACFlags::ChgSglQuotes)); + m_xDoubleTypoCB->save_state(); + m_xSingleTypoCB->save_state(); + + cStartQuote = pAutoCorrect->GetStartDoubleQuote(); + cEndQuote = pAutoCorrect->GetEndDoubleQuote(); + cSglStartQuote = pAutoCorrect->GetStartSingleQuote(); + cSglEndQuote = pAutoCorrect->GetEndSingleQuote(); + + m_xSglStartExFT->set_label(ChangeStringExt_Impl(cSglStartQuote)); + m_xSglEndExFT->set_label(ChangeStringExt_Impl(cSglEndQuote)); + m_xDblStartExFT->set_label(ChangeStringExt_Impl(cStartQuote)); + m_xDblEndExFT->set_label(ChangeStringExt_Impl(cEndQuote)); +} + +#define SGL_START 0 +#define DBL_START 1 +#define SGL_END 2 +#define DBL_END 3 + + +IMPL_LINK(OfaQuoteTabPage, QuoteHdl, weld::Button&, rBtn, void) +{ + sal_uInt16 nMode = SGL_START; + if (&rBtn == m_xSglEndQuotePB.get()) + nMode = SGL_END; + else if (&rBtn == m_xDblStartQuotePB.get()) + nMode = DBL_START; + else if (&rBtn == m_xDblEndQuotePB.get()) + nMode = DBL_END; + // start character selection dialog + SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr); + aMap.SetCharFont( OutputDevice::GetDefaultFont(DefaultFontType::LATIN_TEXT, + LANGUAGE_ENGLISH_US, GetDefaultFontFlags::OnlyOne )); + aMap.set_title(nMode < SGL_END ? CuiResId(RID_CUISTR_STARTQUOTE) : CuiResId(RID_CUISTR_ENDQUOTE)); + sal_UCS4 cDlg; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + LanguageType eLang = Application::GetSettings().GetLanguageTag().getLanguageType(); + switch( nMode ) + { + case SGL_START: + cDlg = cSglStartQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\'', true, eLang); + break; + case SGL_END: + cDlg = cSglEndQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\'', false, eLang); + break; + case DBL_START: + cDlg = cStartQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\"', true, eLang); + break; + case DBL_END: + cDlg = cEndQuote; + if(cDlg == 0) + cDlg = pAutoCorrect->GetQuote('\"', false, eLang); + break; + default: + OSL_FAIL("svx::OfaQuoteTabPage::QuoteHdl(), how to initialize cDlg?" ); + cDlg = 0; + break; + + } + aMap.SetChar( cDlg ); + aMap.DisableFontSelection(); + if (aMap.run() != RET_OK) + return; + + sal_UCS4 cNewChar = aMap.GetChar(); + switch( nMode ) + { + case SGL_START: + cSglStartQuote = cNewChar; + m_xSglStartExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case SGL_END: + cSglEndQuote = cNewChar; + m_xSglEndExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case DBL_START: + cStartQuote = cNewChar; + m_xDblStartExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + case DBL_END: + cEndQuote = cNewChar; + m_xDblEndExFT->set_label(ChangeStringExt_Impl(cNewChar)); + break; + } +} + +IMPL_LINK(OfaQuoteTabPage, StdQuoteHdl, weld::Button&, rBtn, void) +{ + if (&rBtn == m_xDblStandardPB.get()) + { + cStartQuote = 0; + m_xDblStartExFT->set_label(ChangeStringExt_Impl(0)); + cEndQuote = 0; + m_xDblEndExFT->set_label(ChangeStringExt_Impl(0)); + + } + else + { + cSglStartQuote = 0; + m_xSglStartExFT->set_label(ChangeStringExt_Impl(0)); + cSglEndQuote = 0; + m_xSglEndExFT->set_label(ChangeStringExt_Impl(0)); + } +} + +OUString OfaQuoteTabPage::ChangeStringExt_Impl( sal_UCS4 cChar ) +{ + if (!cChar) + return m_sStandard; + + // convert codepoint value to unicode-hex string + sal_UCS4 aStrCodes[32] = { 0, ' ', '(', 'U', '+', '0' }; + aStrCodes[0] = cChar; + int nFullLen = 5; + int nHexLen = 4; + while( (cChar >> (4*nHexLen)) != 0 ) + ++nHexLen; + for( int i = nHexLen; --i >= 0;) + { + sal_UCS4 cHexDigit = ((cChar >> (4*i)) & 0x0f) + '0'; + if( cHexDigit > '9' ) + cHexDigit += 'A' - ('9' + 1); + aStrCodes[ nFullLen++ ] = cHexDigit; + } + aStrCodes[ nFullLen++ ] = ')'; + // using the new UCS4 constructor + OUString aOUStr( aStrCodes, nFullLen ); + return aOUStr; +} + +OfaAutoCompleteTabPage::OfaAutoCompleteTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/wordcompletionpage.ui", + "WordCompletionPage", &rSet) + , m_pAutoCompleteList(nullptr) + , m_nAutoCmpltListCnt(0) + , m_xCBActiv(m_xBuilder->weld_check_button("enablewordcomplete")) + , m_xCBAppendSpace(m_xBuilder->weld_check_button("appendspace")) + , m_xCBAsTip(m_xBuilder->weld_check_button("showastip")) + , m_xCBCollect(m_xBuilder->weld_check_button("collectwords")) + , m_xCBRemoveList(m_xBuilder->weld_check_button("whenclosing")) + , m_xDCBExpandKey(m_xBuilder->weld_combo_box("acceptwith")) + , m_xNFMinWordlen(m_xBuilder->weld_spin_button("minwordlen")) + , m_xNFMaxEntries(m_xBuilder->weld_spin_button("maxentries")) + , m_xLBEntries(m_xBuilder->weld_tree_view("entries")) + , m_xPBEntries(m_xBuilder->weld_button("delete")) +{ + //fdo#65595, we need height-for-width support here, but for now we can + //bodge it + Size aPrefSize(m_xCBRemoveList->get_preferred_size()); + int nMaxWidth = m_xCBRemoveList->get_approximate_digit_width() * 40; + if (aPrefSize.Width() > nMaxWidth) + { + m_xCBRemoveList->set_label_wrap(true); + m_xCBRemoveList->set_size_request(nMaxWidth, -1); + } + + m_xLBEntries->set_size_request(m_xLBEntries->get_approximate_digit_width() * 30, + m_xLBEntries->get_height_rows(10)); + m_xLBEntries->set_selection_mode(SelectionMode::Multiple); + + // the defined KEYs + static const sal_uInt16 aKeyCodes[] = { + KEY_END, + KEY_RETURN, + KEY_SPACE, + KEY_RIGHT, + KEY_TAB, + 0 + }; + + for( const sal_uInt16* pKeys = aKeyCodes; *pKeys; ++pKeys ) + { + vcl::KeyCode aKCode(*pKeys); + m_xDCBExpandKey->append(OUString::number(static_cast<sal_Int32>(*pKeys)), aKCode.GetName()); + if (KEY_RETURN == *pKeys) // default to RETURN + m_xDCBExpandKey->set_active(std::distance(aKeyCodes, pKeys)); + } + + m_xPBEntries->connect_clicked(LINK(this, OfaAutoCompleteTabPage, DeleteHdl)); + m_xCBActiv->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl)); + m_xCBCollect->connect_toggled(LINK(this, OfaAutoCompleteTabPage, CheckHdl)); + m_xLBEntries->connect_key_release(LINK(this, OfaAutoCompleteTabPage, KeyReleaseHdl)); +} + +OfaAutoCompleteTabPage::~OfaAutoCompleteTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaAutoCompleteTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet) +{ + return std::make_unique<OfaAutoCompleteTabPage>(pPage, pController, *rSet); +} + +bool OfaAutoCompleteTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false, bCheck; + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + sal_uInt16 nVal; + + bCheck = m_xCBActiv->get_active(); + bModified |= pOpt->bAutoCompleteWords != bCheck; + pOpt->bAutoCompleteWords = bCheck; + bCheck = m_xCBCollect->get_active(); + bModified |= pOpt->bAutoCmpltCollectWords != bCheck; + pOpt->bAutoCmpltCollectWords = bCheck; + bCheck = !m_xCBRemoveList->get_active(); // inverted value! + bModified |= pOpt->bAutoCmpltKeepList != bCheck; + pOpt->bAutoCmpltKeepList = bCheck; + bCheck = m_xCBAppendSpace->get_active(); + bModified |= pOpt->bAutoCmpltAppendBlank != bCheck; + pOpt->bAutoCmpltAppendBlank = bCheck; + bCheck = m_xCBAsTip->get_active(); + bModified |= pOpt->bAutoCmpltShowAsTip != bCheck; + pOpt->bAutoCmpltShowAsTip = bCheck; + + nVal = static_cast<sal_uInt16>(m_xNFMinWordlen->get_value()); + bModified |= nVal != pOpt->nAutoCmpltWordLen; + pOpt->nAutoCmpltWordLen = nVal; + + nVal = static_cast<sal_uInt16>(m_xNFMaxEntries->get_value()); + bModified |= nVal != pOpt->nAutoCmpltListLen; + pOpt->nAutoCmpltListLen = nVal; + + const int nPos = m_xDCBExpandKey->get_active(); + if (nPos != -1) + { + sal_Int32 nKey = m_xDCBExpandKey->get_id(nPos).toInt32(); + bModified |= nKey != pOpt->nAutoCmpltExpandKey; + pOpt->nAutoCmpltExpandKey = static_cast<sal_uInt16>(nKey); + } + + if (m_pAutoCompleteList && m_nAutoCmpltListCnt != m_xLBEntries->n_children()) + { + bModified = true; + pOpt->m_pAutoCompleteList = m_pAutoCompleteList; + } + if( bModified ) + { + SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + rCfg.SetModified(); + rCfg.Commit(); + } + return true; +} + +void OfaAutoCompleteTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + + m_xCBActiv->set_active( pOpt->bAutoCompleteWords ); + m_xCBCollect->set_active( pOpt->bAutoCmpltCollectWords ); + m_xCBRemoveList->set_active( !pOpt->bAutoCmpltKeepList ); //inverted value! + m_xCBAppendSpace->set_active( pOpt->bAutoCmpltAppendBlank ); + m_xCBAsTip->set_active( pOpt->bAutoCmpltShowAsTip ); + + m_xNFMinWordlen->set_value( pOpt->nAutoCmpltWordLen ); + m_xNFMaxEntries->set_value( pOpt->nAutoCmpltListLen ); + + // select the specific KeyCode: + { + sal_Int32 nKey = pOpt->nAutoCmpltExpandKey; + for (int n = 0, nCnt = m_xDCBExpandKey->get_count(); n < nCnt; ++n) + { + if (nKey == m_xDCBExpandKey->get_id(n).toInt32()) + { + m_xDCBExpandKey->set_active(n); + break; + } + } + } + + if (pOpt->m_pAutoCompleteList && !pOpt->m_pAutoCompleteList->empty()) + { + m_pAutoCompleteList = const_cast<editeng::SortedAutoCompleteStrings*>( + pOpt->m_pAutoCompleteList); + pOpt->m_pAutoCompleteList = nullptr; + m_nAutoCmpltListCnt = m_pAutoCompleteList->size(); + for (size_t n = 0; n < m_nAutoCmpltListCnt; ++n) + { + const OUString* pStr = + &(*m_pAutoCompleteList)[n]->GetAutoCompleteString(); + OUString sId(weld::toId(pStr)); + m_xLBEntries->append(sId, *pStr); + } + } + else + { + m_xLBEntries->set_sensitive(false); + m_xPBEntries->set_sensitive(false); + } + + CheckHdl(*m_xCBActiv); + CheckHdl(*m_xCBCollect); +} + +void OfaAutoCompleteTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage( false ); +} + +IMPL_LINK_NOARG(OfaAutoCompleteTabPage, DeleteHdl, weld::Button&, void) +{ + auto rows = m_xLBEntries->get_selected_rows(); + std::sort(rows.begin(), rows.end()); + while (!rows.empty()) + { + sal_Int32 nPos = rows.back(); + OUString* pStr = weld::fromId<OUString*>(m_xLBEntries->get_id(nPos)); + m_xLBEntries->remove(nPos); + editeng::IAutoCompleteString hack(*pStr); // UGLY + m_pAutoCompleteList->erase(&hack); + rows.pop_back(); + } +} + +IMPL_LINK(OfaAutoCompleteTabPage, CheckHdl, weld::Toggleable&, rBox, void) +{ + bool bEnable = rBox.get_active(); + if (&rBox == m_xCBActiv.get()) + { + m_xCBAppendSpace->set_sensitive(bEnable); + m_xCBAppendSpace->set_sensitive(bEnable); + m_xCBAsTip->set_sensitive(bEnable); + m_xDCBExpandKey->set_sensitive(bEnable); + } + else if (&rBox == m_xCBCollect.get()) + m_xCBRemoveList->set_sensitive(bEnable); +} + +void OfaAutoCompleteTabPage::CopyToClipboard() const +{ + auto rows = m_xLBEntries->get_selected_rows(); + if (!m_pAutoCompleteList || rows.empty()) + return; + + rtl::Reference<TransferDataContainer> pCntnr = new TransferDataContainer; + + OStringBuffer sData; + + rtl_TextEncoding nEncode = osl_getThreadTextEncoding(); + + for (auto a : rows) + { + sData.append(OUStringToOString(m_xLBEntries->get_text(a), nEncode)); +#if defined(_WIN32) + sData.append("\015\012"); +#else + sData.append("\012"); +#endif + } + pCntnr->CopyByteString( SotClipboardFormatId::STRING, sData.makeStringAndClear() ); + pCntnr->CopyToClipboard(m_xLBEntries->get_clipboard()); +} + +IMPL_LINK(OfaAutoCompleteTabPage, KeyReleaseHdl, const KeyEvent&, rEvent, bool) +{ + bool bHandled = false; + const vcl::KeyCode& rKeyCode = rEvent.GetKeyCode(); + switch (rKeyCode.GetModifier() | rKeyCode.GetCode()) + { + case KEY_DELETE: + DeleteHdl(*m_xPBEntries); + bHandled = true; + break; + default: + if (KeyFuncType::COPY == rKeyCode.GetFunction()) + { + CopyToClipboard(); + bHandled = true; + } + break; + } + return bHandled; +} + +// class OfaSmartTagOptionsTabPage --------------------------------------------- + +OfaSmartTagOptionsTabPage::OfaSmartTagOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet ) + : SfxTabPage(pPage, pController, "cui/ui/smarttagoptionspage.ui", "SmartTagOptionsPage", &rSet) + , m_xMainCB(m_xBuilder->weld_check_button("main")) + , m_xSmartTagTypesLB(m_xBuilder->weld_tree_view("list")) + , m_xPropertiesPB(m_xBuilder->weld_button("properties")) +{ + m_xSmartTagTypesLB->set_size_request(m_xSmartTagTypesLB->get_approximate_digit_width() * 50, + m_xSmartTagTypesLB->get_height_rows(6)); + + m_xSmartTagTypesLB->enable_toggle_buttons(weld::ColumnToggleType::Check); + + // set the handlers: + m_xMainCB->connect_toggled(LINK(this, OfaSmartTagOptionsTabPage, CheckHdl)); + m_xPropertiesPB->connect_clicked(LINK(this, OfaSmartTagOptionsTabPage, ClickHdl)); + m_xSmartTagTypesLB->connect_changed(LINK(this, OfaSmartTagOptionsTabPage, SelectHdl)); +} + +OfaSmartTagOptionsTabPage::~OfaSmartTagOptionsTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaSmartTagOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<OfaSmartTagOptionsTabPage>(pPage, pController, *rSet); +} + +namespace { + +/** This struct is used to associate list box entries with smart tag data +*/ +struct ImplSmartTagLBUserData +{ + OUString maSmartTagType; + uno::Reference< smarttags::XSmartTagRecognizer > mxRec; + sal_Int32 mnSmartTagIdx; + + ImplSmartTagLBUserData( OUString aSmartTagType, + uno::Reference< smarttags::XSmartTagRecognizer > xRec, + sal_Int32 nSmartTagIdx ) : + maSmartTagType(std::move( aSmartTagType )), + mxRec(std::move( xRec )), + mnSmartTagIdx( nSmartTagIdx ) {} +}; + +} + +/** Clears m_xSmartTagTypesLB +*/ +void OfaSmartTagOptionsTabPage::ClearListBox() +{ + const int nCount = m_xSmartTagTypesLB->n_children(); + for (int i = 0; i < nCount; ++i) + { + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(i)); + delete pUserData; + } + + m_xSmartTagTypesLB->clear(); +} + +/** Inserts items into m_xSmartTagTypesLB +*/ +void OfaSmartTagOptionsTabPage::FillListBox( const SmartTagMgr& rSmartTagMgr ) +{ + // first we have to clear the list box: + ClearListBox(); + + // fill list box: + const sal_uInt32 nNumberOfRecognizers = rSmartTagMgr.NumberOfRecognizers(); + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + + for ( sal_uInt32 i = 0; i < nNumberOfRecognizers; ++i ) + { + const uno::Reference< smarttags::XSmartTagRecognizer >& xRec = rSmartTagMgr.GetRecognizer(i); + + const OUString aName = xRec->getName( aLocale ); + const sal_Int32 nNumberOfSupportedSmartTags = xRec->getSmartTagCount(); + + for ( sal_Int32 j = 0; j < nNumberOfSupportedSmartTags; ++j ) + { + const OUString aSmartTagType = xRec->getSmartTagName(j); + OUString aSmartTagCaption = rSmartTagMgr.GetSmartTagCaption( aSmartTagType, aLocale ); + + if ( aSmartTagCaption.isEmpty() ) + aSmartTagCaption = aSmartTagType; + + const OUString aLBEntry = aSmartTagCaption + " (" + aName + ")"; + + m_xSmartTagTypesLB->append(); + const int nRow = m_xSmartTagTypesLB->n_children() - 1; + const bool bCheck = rSmartTagMgr.IsSmartTagTypeEnabled( aSmartTagType ); + m_xSmartTagTypesLB->set_toggle(nRow, bCheck ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xSmartTagTypesLB->set_text(nRow, aLBEntry, 0); + m_xSmartTagTypesLB->set_id(nRow, weld::toId(new ImplSmartTagLBUserData(aSmartTagType, xRec, j))); + } + } +} + +/** Handler for the push button +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, ClickHdl, weld::Button&, void) +{ + const int nPos = m_xSmartTagTypesLB->get_selected_index(); + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(nPos)); + uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec; + const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx; + + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) ) + xRec->displayPropertyPage( nSmartTagIdx, aLocale ); +} + +/** Handler for the check box +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, CheckHdl, weld::Toggleable&, void) +{ + const bool bEnable = m_xMainCB->get_active(); + m_xSmartTagTypesLB->set_sensitive(bEnable); + m_xPropertiesPB->set_sensitive(false); + + // if the controls are currently enabled, we still have to check + // if the properties button should be disabled because the currently + // selected smart tag type does not have a properties dialog. + // We do this by calling SelectHdl: + if (bEnable) + SelectHdl(*m_xSmartTagTypesLB); +} + +/** Handler for the list box +*/ +IMPL_LINK_NOARG(OfaSmartTagOptionsTabPage, SelectHdl, weld::TreeView&, void) +{ + const int nPos = m_xSmartTagTypesLB->get_selected_index(); + if (nPos == -1) + return; + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(nPos)); + uno::Reference< smarttags::XSmartTagRecognizer > xRec = pUserData->mxRec; + const sal_Int32 nSmartTagIdx = pUserData->mnSmartTagIdx; + + const lang::Locale aLocale( LanguageTag::convertToLocale( eLastDialogLanguage ) ); + if ( xRec->hasPropertyPage( nSmartTagIdx, aLocale ) ) + m_xPropertiesPB->set_sensitive(true); + else + m_xPropertiesPB->set_sensitive(false); +} + +/** Propagates the current settings to the smart tag manager. +*/ +bool OfaSmartTagOptionsTabPage::FillItemSet( SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr; + + // robust! + if ( !pSmartTagMgr ) + return false; + + bool bModifiedSmartTagTypes = false; + std::vector< OUString > aDisabledSmartTagTypes; + + const int nCount = m_xSmartTagTypesLB->n_children(); + + for (int i = 0; i < nCount; ++i) + { + const ImplSmartTagLBUserData* pUserData = weld::fromId<ImplSmartTagLBUserData*>(m_xSmartTagTypesLB->get_id(i)); + const bool bChecked = m_xSmartTagTypesLB->get_toggle(i) == TRISTATE_TRUE; + const bool bIsCurrentlyEnabled = pSmartTagMgr->IsSmartTagTypeEnabled( pUserData->maSmartTagType ); + + bModifiedSmartTagTypes = bModifiedSmartTagTypes || ( !bChecked != !bIsCurrentlyEnabled ); + + if ( !bChecked ) + aDisabledSmartTagTypes.push_back( pUserData->maSmartTagType ); + + delete pUserData; + } + + const bool bModifiedRecognize = ( !m_xMainCB->get_active() != !pSmartTagMgr->IsLabelTextWithSmartTags() ); + if ( bModifiedSmartTagTypes || bModifiedRecognize ) + { + bool bLabelTextWithSmartTags = m_xMainCB->get_active(); + pSmartTagMgr->WriteConfiguration( bModifiedRecognize ? &bLabelTextWithSmartTags : nullptr, + bModifiedSmartTagTypes ? &aDisabledSmartTagTypes : nullptr ); + } + + return true; +} + +/** Sets the controls based on the current settings at SmartTagMgr. +*/ +void OfaSmartTagOptionsTabPage::Reset( const SfxItemSet* ) +{ + SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); + SvxSwAutoFormatFlags *pOpt = &pAutoCorrect->GetSwFlags(); + const SmartTagMgr* pSmartTagMgr = pOpt->pSmartTagMgr; + + // robust, should not happen! + if ( !pSmartTagMgr ) + return; + + FillListBox(*pSmartTagMgr); + m_xSmartTagTypesLB->select(0); + m_xMainCB->set_active(pSmartTagMgr->IsLabelTextWithSmartTags()); + CheckHdl(*m_xMainCB); +} + +void OfaSmartTagOptionsTabPage::ActivatePage( const SfxItemSet& ) +{ + static_cast<OfaAutoCorrDlg*>(GetDialogController())->EnableLanguage( false ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/backgrnd.cxx b/cui/source/tabpages/backgrnd.cxx new file mode 100644 index 000000000..14269ad3c --- /dev/null +++ b/cui/source/tabpages/backgrnd.cxx @@ -0,0 +1,338 @@ +/* -*- 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 . + */ + +#include <memory> +#include <sfx2/objsh.hxx> +#include <svx/svxids.hrc> +#include <editeng/colritem.hxx> +#include <backgrnd.hxx> +#include <svx/drawitem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/flagsdef.hxx> +#include <svl/intitem.hxx> +#include <svx/unobrushitemhelper.hxx> + +using namespace css; + +// table background +#define TBL_DEST_CELL 0 +#define TBL_DEST_ROW 1 +#define TBL_DEST_TBL 2 + +const WhichRangesContainer SvxBkgTabPage::pPageRanges(svl::Items< + SID_ATTR_BRUSH, SID_ATTR_BRUSH, + SID_ATTR_BRUSH_CHAR, SID_ATTR_BRUSH_CHAR +>); + +static sal_uInt16 lcl_GetTableDestSlot(sal_Int32 nTblDest) +{ + switch (nTblDest) + { + default: + case TBL_DEST_CELL: + { + return SID_ATTR_BRUSH; + } + case TBL_DEST_ROW: + { + return SID_ATTR_BRUSH_ROW; + } + case TBL_DEST_TBL: + { + return SID_ATTR_BRUSH_TABLE; + } + } +} + +SvxBkgTabPage::SvxBkgTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxAreaTabPage(pPage, pController, rInAttrs), + bHighlighting(false), + bCharBackColor(false), + maSet(rInAttrs) +{ + m_xBtnGradient->hide(); + m_xBtnHatch->hide(); + m_xBtnBitmap->hide(); + m_xBtnPattern->hide(); + + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + + XColorListRef pColorTable; + if ( pDocSh ) + if (auto pItem = pDocSh->GetItem( SID_COLOR_TABLE )) + pColorTable = pItem->GetColorList(); + + if ( !pColorTable.is() ) + pColorTable = XColorList::CreateStdColorList(); + + XBitmapListRef pBitmapList; + if ( pDocSh ) + if (auto pItem = pDocSh->GetItem( SID_BITMAP_LIST ) ) + pBitmapList = pItem->GetBitmapList(); + + SetColorList(pColorTable); + SetBitmapList(pBitmapList); +} + +SvxBkgTabPage::~SvxBkgTabPage() +{ + m_xTblLBox.reset(); +} + +void SvxBkgTabPage::ActivatePage( const SfxItemSet& ) +{ + SvxAreaTabPage::ActivatePage( maSet ); +} + +DeactivateRC SvxBkgTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( DeactivateRC::KeepPage == SvxAreaTabPage::DeactivatePage( &maSet ) ) + return DeactivateRC::KeepPage; + + if ( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +void SvxBkgTabPage::Reset( const SfxItemSet* ) +{ + maSet.Set( *m_pResetSet ); + if ( m_xTblLBox && m_xTblLBox->get_visible() ) + { + m_nActPos = -1; + if ( const SfxUInt16Item* pDestItem = m_pResetSet->GetItemIfSet( SID_BACKGRND_DESTINATION, false ) ) + { + sal_uInt16 nDestValue = pDestItem->GetValue(); + m_xTblLBox->set_active( nDestValue ); + TblDestinationHdl_Impl( *m_xTblLBox ); + } + m_xTblLBox->save_value(); + } + SvxAreaTabPage::Reset( &maSet ); +} + +bool SvxBkgTabPage::FillItemSet( SfxItemSet* rCoreSet ) +{ + sal_uInt16 nSlot = SID_ATTR_BRUSH; + if (m_xTblLBox && m_xTblLBox->get_visible()) + nSlot = lcl_GetTableDestSlot(m_xTblLBox->get_active()); + else if ( bHighlighting ) + nSlot = SID_ATTR_BRUSH_CHAR; + else if( bCharBackColor ) + nSlot = SID_ATTR_CHAR_BACK_COLOR; + + sal_uInt16 nWhich = GetWhich(nSlot); + + drawing::FillStyle eFillType = maSet.Get( XATTR_FILLSTYLE ).GetValue(); + switch( eFillType ) + { + case drawing::FillStyle_NONE: + { + if ( IsBtnClicked() ) + { + if ( SID_ATTR_CHAR_BACK_COLOR == nSlot ) + { + maSet.Put( SvxColorItem( COL_TRANSPARENT, nWhich ) ); + rCoreSet->Put( SvxColorItem( COL_TRANSPARENT, nWhich ) ); + } + else + { + maSet.Put( SvxBrushItem( COL_TRANSPARENT, nWhich ) ); + rCoreSet->Put( SvxBrushItem( COL_TRANSPARENT, nWhich ) ); + } + } + break; + } + case drawing::FillStyle_SOLID: + { + XFillColorItem aColorItem( maSet.Get( XATTR_FILLCOLOR ) ); + if ( SID_ATTR_CHAR_BACK_COLOR == nSlot ) + { + maSet.Put( SvxColorItem( aColorItem.GetColorValue(), nWhich ) ); + rCoreSet->Put( SvxColorItem( aColorItem.GetColorValue(), nWhich ) ); + } + else + { + maSet.Put( SvxBrushItem( aColorItem.GetColorValue(), nWhich ) ); + rCoreSet->Put( SvxBrushItem( aColorItem.GetColorValue(), nWhich ) ); + } + break; + } + case drawing::FillStyle_BITMAP: + { + std::unique_ptr<SvxBrushItem> aBrushItem( getSvxBrushItemFromSourceSet( maSet, nWhich ) ); + if ( GraphicType::NONE != aBrushItem->GetGraphicObject()->GetType() ) + rCoreSet->Put( std::move(aBrushItem) ); + break; + } + default: + break; + } + + if (!m_xTblLBox || !m_xTblLBox->get_visible()) + return true; + + if (nSlot != SID_ATTR_BRUSH) + { + nWhich = maSet.GetPool()->GetWhich(SID_ATTR_BRUSH); + if (SfxItemState::SET == maSet.GetItemState(nWhich)) + { + SvxBrushItem aBrushItem(static_cast<const SvxBrushItem&>(maSet.Get(nWhich))); + rCoreSet->Put(aBrushItem); + } + } + if (nSlot != SID_ATTR_BRUSH_ROW) + { + if (SfxItemState::SET == maSet.GetItemState(SID_ATTR_BRUSH_ROW)) + { + SvxBrushItem aBrushItem(maSet.Get(SID_ATTR_BRUSH_ROW)); + rCoreSet->Put(aBrushItem); + } + } + if (nSlot != SID_ATTR_BRUSH_TABLE) + { + if (SfxItemState::SET == maSet.GetItemState(SID_ATTR_BRUSH_TABLE)) + { + SvxBrushItem aBrushItem(maSet.Get(SID_ATTR_BRUSH_TABLE)); + rCoreSet->Put(aBrushItem); + } + } + + if (m_xTblLBox->get_value_changed_from_saved()) + { + rCoreSet->Put(SfxUInt16Item(SID_BACKGRND_DESTINATION, m_xTblLBox->get_active())); + } + + return true; +} + +std::unique_ptr<SfxTabPage> SvxBkgTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + auto xRet = std::make_unique<SvxBkgTabPage>(pPage, pController, *rAttrs); + xRet->SetOptimalSize(pController); + return xRet; +} + +void SvxBkgTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false); + if (pFlagItem) + { + SvxBackgroundTabFlags nFlags = static_cast<SvxBackgroundTabFlags>(pFlagItem->GetValue()); + if ( nFlags & SvxBackgroundTabFlags::SHOW_TBLCTL ) + { + m_xBtnBitmap->show(); + m_xTblLBox = m_xBuilder->weld_combo_box("tablelb"); + m_xTblLBox->connect_changed(LINK(this, SvxBkgTabPage, TblDestinationHdl_Impl)); + m_xTblLBox->show(); + } + if ((nFlags & SvxBackgroundTabFlags::SHOW_HIGHLIGHTING) || + (nFlags & SvxBackgroundTabFlags::SHOW_CHAR_BKGCOLOR)) + { + bHighlighting = bool(nFlags & SvxBackgroundTabFlags::SHOW_HIGHLIGHTING); + bCharBackColor = bool(nFlags & SvxBackgroundTabFlags::SHOW_CHAR_BKGCOLOR); + } + if (nFlags & SvxBackgroundTabFlags::SHOW_SELECTOR) + m_xBtnBitmap->show(); + SetOptimalSize(GetDialogController()); + } + + if ( bCharBackColor ) + { + sal_uInt16 nWhich(maSet.GetPool()->GetWhich(SID_ATTR_CHAR_BACK_COLOR)); + Color aBackColor(static_cast<const SvxColorItem&>(maSet.Get(nWhich)).GetValue()); + SvxBrushItem aBrushItem(SvxBrushItem(aBackColor, SID_ATTR_BRUSH_CHAR)); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, maSet); + } + else + { + sal_uInt16 nWhich(maSet.GetPool()->GetWhich(bHighlighting ? SID_ATTR_BRUSH_CHAR : SID_ATTR_BRUSH)); + SvxBrushItem aBrushItem(static_cast<const SvxBrushItem&>(maSet.Get(nWhich))); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, maSet); + } + + m_pResetSet = maSet.Clone(); + + SvxAreaTabPage::PageCreated(aSet); +} + +IMPL_LINK(SvxBkgTabPage, TblDestinationHdl_Impl, weld::ComboBox&, rBox, void) +{ + if (m_nActPos > -1) + { + // fill local item set with XATTR_FILL settings gathered from tab page + // and convert to SvxBrushItem and store in table destination slot Which + SvxAreaTabPage::FillItemSet(&maSet); + maSet.Put(getSvxBrushItemFromSourceSet(maSet, maSet.GetPool()->GetWhich(lcl_GetTableDestSlot(m_nActPos)))); + } + + sal_Int32 nSelPos = rBox.get_active(); + if (m_nActPos == nSelPos) + return; + + m_nActPos = nSelPos; + + // fill local item set with XATTR_FILL created from SvxBushItem for table destination slot Which + sal_uInt16 nWhich = maSet.GetPool()->GetWhich(lcl_GetTableDestSlot(nSelPos)); + if (SfxItemState::SET == maSet.GetItemState(nWhich)) + { + SvxBrushItem aBrushItem(static_cast<const SvxBrushItem&>(maSet.Get(nWhich))); + setSvxBrushItemAsFillAttributesToTargetSet(aBrushItem, maSet); + } + else + { + SelectFillType(*m_xBtnNone, &maSet); + return; + } + + // show tab page + drawing::FillStyle eXFS = drawing::FillStyle_NONE; + if (maSet.GetItemState(XATTR_FILLSTYLE) != SfxItemState::DONTCARE) + { + XFillStyleItem aFillStyleItem(maSet.Get(GetWhich( XATTR_FILLSTYLE))); + eXFS = aFillStyleItem.GetValue(); + } + switch(eXFS) + { + default: + case drawing::FillStyle_NONE: + { + SelectFillType(*m_xBtnNone, &maSet); + break; + } + case drawing::FillStyle_SOLID: + { + SelectFillType(*m_xBtnColor, &maSet); + // color tab page Active and New preview controls are same after SelectFillType + // hack to restore color tab page Active preview + setSvxBrushItemAsFillAttributesToTargetSet(static_cast<const SvxBrushItem&>(m_pResetSet->Get(nWhich)), *m_pResetSet); + static_cast<SvxColorTabPage*>(GetFillTabPage())->SetCtlPreviewOld(*m_pResetSet); + break; + } + case drawing::FillStyle_BITMAP: + { + SelectFillType(*m_xBtnBitmap, &maSet); + break; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/bbdlg.cxx b/cui/source/tabpages/bbdlg.cxx new file mode 100644 index 000000000..488fc5283 --- /dev/null +++ b/cui/source/tabpages/bbdlg.cxx @@ -0,0 +1,89 @@ +/* -*- 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 . + */ + +#include <bbdlg.hxx> +#include <border.hxx> +#include <backgrnd.hxx> +#include <svx/svxids.hrc> +#include <svl/intitem.hxx> +#include <cuitabarea.hxx> + +SvxBorderBackgroundDlg::SvxBorderBackgroundDlg(weld::Window *pParent, + const SfxItemSet& rCoreSet, + bool bEnableSelector, + bool bEnableDrawingLayerFillStyles) + : SfxTabDialogController(pParent, + bEnableDrawingLayerFillStyles + ? OUString("cui/ui/borderareatransparencydialog.ui") + : OUString("cui/ui/borderbackgrounddialog.ui"), + bEnableDrawingLayerFillStyles + ? OString("BorderAreaTransparencyDialog") + : OString("BorderBackgroundDialog"), + &rCoreSet) + , mbEnableBackgroundSelector(bEnableSelector) +{ + AddTabPage("borders", SvxBorderTabPage::Create, nullptr ); + if (bEnableDrawingLayerFillStyles) + { + // Here we want full DrawingLayer FillStyle access, so add Area and Transparency TabPages + AddTabPage("area", SvxAreaTabPage::Create, nullptr); + AddTabPage("transparence", SvxTransparenceTabPage::Create, nullptr); + } + else + { + AddTabPage("background", SvxBkgTabPage::Create, nullptr ); + } +} + +void SvxBorderBackgroundDlg::PageCreated(const OString& rPageId, SfxTabPage& rTabPage) +{ + if (rPageId == "background") + { + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + // allow switching between Color/graphic + if (mbEnableBackgroundSelector) + aSet.Put(SfxUInt32Item(SID_FLAG_TYPE, static_cast<sal_uInt32>(SvxBackgroundTabFlags::SHOW_SELECTOR))); + rTabPage.PageCreated(aSet); + } + // inits for Area and Transparency TabPages + // The selection attribute lists (XPropertyList derivates, e.g. XColorList for + // the color table) need to be added as items (e.g. SvxColorTableItem) to make + // these pages find the needed attributes for fill style suggestions. + // These are added in SwDocStyleSheet::GetItemSet() for the SfxStyleFamily::Para on + // demand, but could also be directly added from the DrawModel. + else if (rPageId == "area") + { + SfxItemSetFixed<SID_COLOR_TABLE, SID_PATTERN_LIST, + SID_OFFER_IMPORT, SID_OFFER_IMPORT> + aNew(*GetInputSetImpl()->GetPool()); + + aNew.Put(*GetInputSetImpl()); + + // add flag for direct graphic content selection + aNew.Put(SfxBoolItem(SID_OFFER_IMPORT, true)); + + rTabPage.PageCreated(aNew); + } + else if (rPageId == "transparence") + { + rTabPage.PageCreated(*GetInputSetImpl()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/border.cxx b/cui/source/tabpages/border.cxx new file mode 100644 index 000000000..30313dfce --- /dev/null +++ b/cui/source/tabpages/border.cxx @@ -0,0 +1,1704 @@ +/* -*- 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 . + */ + +#include <sal/config.h> + +#include <sfx2/objsh.hxx> +#include <svx/strings.hrc> +#include <svx/svxids.hrc> + +#include <strings.hrc> +#include <bitmaps.hlst> + +#include <editeng/boxitem.hxx> +#include <editeng/lineitem.hxx> +#include <border.hxx> +#include <svx/dlgutil.hxx> +#include <dialmgr.hxx> +#include <sfx2/htmlmode.hxx> +#include <vcl/fieldvalues.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <svx/dialmgr.hxx> +#include <svx/flagsdef.hxx> +#include <svl/grabbagitem.hxx> +#include <svl/intitem.hxx> +#include <svl/ilstitem.hxx> +#include <svl/int64item.hxx> +#include <sal/macros.h> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/lok.hxx> +#include <svtools/unitconv.hxx> + +using namespace ::editeng; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::lang::XServiceInfo; +using ::com::sun::star::uno::UNO_QUERY; + + +/* + * [Description:] + * TabPage for setting the border attributes. + * Needs + * a SvxShadowItem: shadow + * a SvxBoxItem: lines left, right, top, bottom, + * a SvxBoxInfo: lines vertical, horizontal, distance, flags + * + * Lines can have three conditions: + * 1. Show ( -> valid values ) + * 2. Hide ( -> NULL-Pointer ) + * 3. DontCare ( -> special Valid-Flags in the InfoItem ) + */ + +// static ---------------------------------------------------------------- + +const WhichRangesContainer SvxBorderTabPage::pRanges( + svl::Items< + SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_SHADOW, + SID_ATTR_ALIGN_MARGIN, SID_ATTR_ALIGN_MARGIN, + SID_ATTR_BORDER_CONNECT, SID_ATTR_BORDER_CONNECT, + SID_SW_COLLAPSING_BORDERS, SID_SW_COLLAPSING_BORDERS, + SID_ATTR_BORDER_DIAG_TLBR, SID_ATTR_BORDER_DIAG_BLTR>); + +namespace +{ +int lcl_twipsToPt(sal_Int64 nTwips) +{ + return vcl::ConvertDoubleValue(nTwips, 0, FieldUnit::TWIP, MapUnit::MapPoint) * 100; +} +} + +const std::vector<int> SvxBorderTabPage::m_aLineWidths = { + lcl_twipsToPt(SvxBorderLineWidth::Hairline), + lcl_twipsToPt(SvxBorderLineWidth::VeryThin), + lcl_twipsToPt(SvxBorderLineWidth::Thin), + lcl_twipsToPt(SvxBorderLineWidth::Medium), + lcl_twipsToPt(SvxBorderLineWidth::Thick), + lcl_twipsToPt(SvxBorderLineWidth::ExtraThick), + -1 +}; + +static void lcl_SetDecimalDigitsTo1(weld::MetricSpinButton& rField) +{ + auto nMin = rField.denormalize(rField.get_min(FieldUnit::TWIP)); + rField.set_digits(1); + rField.set_min(rField.normalize(nMin), FieldUnit::TWIP); +} + +// returns in pt +static sal_Int64 lcl_GetMinLineWidth(SvxBorderLineStyle aStyle) +{ + switch (aStyle) + { + case SvxBorderLineStyle::NONE: + return 0; + + case SvxBorderLineStyle::SOLID: + case SvxBorderLineStyle::DOTTED: + case SvxBorderLineStyle::DASHED: + case SvxBorderLineStyle::FINE_DASHED: + case SvxBorderLineStyle::DASH_DOT: + case SvxBorderLineStyle::DASH_DOT_DOT: + return 15; + + // Double lines + case SvxBorderLineStyle::DOUBLE: return 15; + case SvxBorderLineStyle::DOUBLE_THIN: return 15; + case SvxBorderLineStyle::THINTHICK_SMALLGAP: return 20; + case SvxBorderLineStyle::THINTHICK_MEDIUMGAP: return 15; + case SvxBorderLineStyle::THINTHICK_LARGEGAP: return 15; + case SvxBorderLineStyle::THICKTHIN_SMALLGAP: return 20; + case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP: return 15; + case SvxBorderLineStyle::THICKTHIN_LARGEGAP: return 15; + + case SvxBorderLineStyle::EMBOSSED: return 15; + case SvxBorderLineStyle::ENGRAVED: return 15; + + case SvxBorderLineStyle::OUTSET: return 10; + case SvxBorderLineStyle::INSET: return 10; + + default: + return 15; + } +} + +// number of preset images to show +const sal_uInt16 BORDER_PRESET_COUNT = 5; + +// number of shadow images to show +const sal_uInt16 BORDER_SHADOW_COUNT = 5; + +ShadowControlsWrapper::ShadowControlsWrapper(ValueSet& rVsPos, weld::MetricSpinButton& rMfSize, ColorListBox& rLbColor) + : mrVsPos(rVsPos) + , mrMfSize(rMfSize) + , mrLbColor(rLbColor) +{ +} + +SvxShadowItem ShadowControlsWrapper::GetControlValue(const SvxShadowItem& rItem) const +{ + SvxShadowItem aItem(rItem); + if (!mrVsPos.IsNoSelection()) + { + switch (mrVsPos.GetSelectedItemId()) + { + case 1: + aItem.SetLocation(SvxShadowLocation::NONE); + break; + case 2: + aItem.SetLocation(SvxShadowLocation::BottomRight); + break; + case 3: + aItem.SetLocation(SvxShadowLocation::TopRight); + break; + case 4: + aItem.SetLocation(SvxShadowLocation::BottomLeft); + break; + case 5: + aItem.SetLocation(SvxShadowLocation::TopLeft); + break; + default: + aItem.SetLocation(SvxShadowLocation::NONE); + break; + } + } + // Default value was saved; so don't change the aItem's width if the control + // has not changed its value, to avoid round-trip errors (like twip->cm->twip) + // E.g., initial 100 twip will become 0.18 cm, which will return as 102 twip + if (mrMfSize.get_value_changed_from_saved()) + aItem.SetWidth(mrMfSize.denormalize(mrMfSize.get_value(FieldUnit::TWIP))); + if (!mrLbColor.IsNoSelection()) + aItem.SetColor(mrLbColor.GetSelectEntryColor()); + return aItem; +} + +void ShadowControlsWrapper::SetControlValue(const SvxShadowItem& rItem) +{ + switch (rItem.GetLocation()) + { + case SvxShadowLocation::NONE: + mrVsPos.SelectItem(1); + break; + case SvxShadowLocation::BottomRight: + mrVsPos.SelectItem(2); + break; + case SvxShadowLocation::TopRight: + mrVsPos.SelectItem(3); + break; + case SvxShadowLocation::BottomLeft: + mrVsPos.SelectItem(4); + break; + case SvxShadowLocation::TopLeft: + mrVsPos.SelectItem(5); + break; + default: + mrVsPos.SetNoSelection(); + break; + } + mrVsPos.SaveValue(); + mrMfSize.set_value(mrMfSize.normalize(rItem.GetWidth()), FieldUnit::TWIP); + mrMfSize.save_value(); + mrLbColor.SelectEntry(rItem.GetColor()); + mrLbColor.SaveValue(); +} + +bool ShadowControlsWrapper::get_value_changed_from_saved() const +{ + return mrVsPos.IsValueChangedFromSaved() || + mrMfSize.get_value_changed_from_saved() || + mrLbColor.IsValueChangedFromSaved(); +} + +void ShadowControlsWrapper::SetControlDontKnow() +{ + mrVsPos.SetNoSelection(); + mrMfSize.set_text(""); + mrLbColor.SetNoSelection(); +} + +MarginControlsWrapper::MarginControlsWrapper(weld::MetricSpinButton& rMfLeft, weld::MetricSpinButton& rMfRight, + weld::MetricSpinButton& rMfTop, weld::MetricSpinButton& rMfBottom) + : mrLeftWrp(rMfLeft) + , mrRightWrp(rMfRight) + , mrTopWrp(rMfTop) + , mrBottomWrp(rMfBottom) +{ +} + +SvxMarginItem MarginControlsWrapper::GetControlValue(const SvxMarginItem &rItem) const +{ + SvxMarginItem aItem(rItem); + if (mrLeftWrp.get_sensitive()) + aItem.SetLeftMargin(mrLeftWrp.denormalize(mrLeftWrp.get_value(FieldUnit::TWIP))); + if (mrRightWrp.get_sensitive()) + aItem.SetRightMargin(mrRightWrp.denormalize(mrRightWrp.get_value(FieldUnit::TWIP))); + if (mrTopWrp.get_sensitive()) + aItem.SetTopMargin(mrTopWrp.denormalize(mrTopWrp.get_value(FieldUnit::TWIP))); + if (mrBottomWrp.get_sensitive()) + aItem.SetBottomMargin(mrBottomWrp.denormalize(mrBottomWrp.get_value(FieldUnit::TWIP))); + return aItem; +} + +bool MarginControlsWrapper::get_value_changed_from_saved() const +{ + return mrLeftWrp.get_value_changed_from_saved() || + mrRightWrp.get_value_changed_from_saved() || + mrTopWrp.get_value_changed_from_saved() || + mrBottomWrp.get_value_changed_from_saved(); +} + +void MarginControlsWrapper::SetControlValue(const SvxMarginItem& rItem) +{ + mrLeftWrp.set_value(mrLeftWrp.normalize(rItem.GetLeftMargin()), FieldUnit::TWIP); + mrRightWrp.set_value(mrRightWrp.normalize(rItem.GetRightMargin()), FieldUnit::TWIP); + mrTopWrp.set_value(mrTopWrp.normalize(rItem.GetTopMargin()), FieldUnit::TWIP); + mrBottomWrp.set_value(mrBottomWrp.normalize(rItem.GetBottomMargin()), FieldUnit::TWIP); + mrLeftWrp.save_value(); + mrRightWrp.save_value(); + mrTopWrp.save_value(); + mrBottomWrp.save_value(); +} + +void MarginControlsWrapper::SetControlDontKnow() +{ + const OUString sEmpty; + mrLeftWrp.set_text(sEmpty); + mrRightWrp.set_text(sEmpty); + mrTopWrp.set_text(sEmpty); + mrBottomWrp.set_text(sEmpty); +} + +SvxBorderTabPage::SvxBorderTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs) + : SfxTabPage(pPage, pController, "cui/ui/borderpage.ui", "BorderPage", &rCoreAttrs) + , nMinValue(0) + , nSWMode(SwBorderModes::NONE) + , mnBoxSlot(SID_ATTR_BORDER_OUTER) + , mnShadowSlot(SID_ATTR_BORDER_SHADOW) + , mbHorEnabled(false) + , mbVerEnabled(false) + , mbTLBREnabled(false) + , mbBLTREnabled(false) + , mbUseMarginItem(false) + , mbLeftModified(false) + , mbRightModified(false) + , mbTopModified(false) + , mbBottomModified(false) + , mbSync(true) + , mbRemoveAdjacentCellBorders(false) + , bIsCalcDoc(false) + , m_xWndPresets(new ValueSet(nullptr)) + , m_xWndPresetsWin(new weld::CustomWeld(*m_xBuilder, "presets", *m_xWndPresets)) + , m_xUserDefFT(m_xBuilder->weld_label("userdefft")) + , m_xFrameSelWin(new weld::CustomWeld(*m_xBuilder, "framesel", m_aFrameSel)) + , m_xLbLineStyle(new SvtLineListBox(m_xBuilder->weld_menu_button("linestylelb"))) + , m_xLbLineColor(new ColorListBox(m_xBuilder->weld_menu_button("linecolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xLineWidthLB(m_xBuilder->weld_combo_box("linewidthlb")) + , m_xLineWidthMF(m_xBuilder->weld_metric_spin_button("linewidthmf", FieldUnit::POINT)) + , m_xSpacingFrame(m_xBuilder->weld_container("spacing")) + , m_xLeftFT(m_xBuilder->weld_label("leftft")) + , m_xLeftMF(m_xBuilder->weld_metric_spin_button("leftmf", FieldUnit::MM)) + , m_xRightFT(m_xBuilder->weld_label("rightft")) + , m_xRightMF(m_xBuilder->weld_metric_spin_button("rightmf", FieldUnit::MM)) + , m_xTopFT(m_xBuilder->weld_label("topft")) + , m_xTopMF(m_xBuilder->weld_metric_spin_button("topmf", FieldUnit::MM)) + , m_xBottomFT(m_xBuilder->weld_label("bottomft")) + , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottommf", FieldUnit::MM)) + , m_xSynchronizeCB(m_xBuilder->weld_check_button("sync")) + , m_xShadowFrame(m_xBuilder->weld_container("shadow")) + , m_xWndShadows(new ValueSet(nullptr)) + , m_xWndShadowsWin(new weld::CustomWeld(*m_xBuilder, "shadows", *m_xWndShadows)) + , m_xFtShadowSize(m_xBuilder->weld_label("distanceft")) + , m_xEdShadowSize(m_xBuilder->weld_metric_spin_button("distancemf", FieldUnit::MM)) + , m_xFtShadowColor(m_xBuilder->weld_label("shadowcolorft")) + , m_xLbShadowColor(new ColorListBox(m_xBuilder->weld_menu_button("shadowcolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xPropertiesFrame(m_xBuilder->weld_container("properties")) + , m_xMergeWithNextCB(m_xBuilder->weld_check_button("mergewithnext")) + , m_xMergeAdjacentBordersCB(m_xBuilder->weld_check_button("mergeadjacent")) + , m_xRemoveAdjacentCellBordersCB(m_xBuilder->weld_check_button("rmadjcellborders")) + , m_xRemoveAdjacentCellBordersFT(m_xBuilder->weld_label("rmadjcellbordersft")) +{ + static std::vector<OUString> aBorderImageIds; + + if (aBorderImageIds.empty()) + { + if (comphelper::LibreOfficeKit::isActive()) + { + aBorderImageIds.insert(aBorderImageIds.end(), { + RID_SVXBMP_CELL_NONE_32, + RID_SVXBMP_CELL_ALL_32, + RID_SVXBMP_CELL_LR_32, + RID_SVXBMP_CELL_TB_32, + RID_SVXBMP_CELL_L_32, + RID_SVXBMP_CELL_DIAG_32 + }); + } + else + { + aBorderImageIds.insert(aBorderImageIds.end(), { + RID_SVXBMP_CELL_NONE, + RID_SVXBMP_CELL_ALL, + RID_SVXBMP_CELL_LR, + RID_SVXBMP_CELL_TB, + RID_SVXBMP_CELL_L, + RID_SVXBMP_CELL_DIAG + }); + } + aBorderImageIds.insert(aBorderImageIds.end(), { + RID_SVXBMP_HOR_NONE, + RID_SVXBMP_HOR_OUTER, + RID_SVXBMP_HOR_HOR, + RID_SVXBMP_HOR_ALL, + RID_SVXBMP_HOR_OUTER2, + RID_SVXBMP_VER_NONE, + RID_SVXBMP_VER_OUTER, + RID_SVXBMP_VER_VER, + RID_SVXBMP_VER_ALL, + RID_SVXBMP_VER_OUTER2, + RID_SVXBMP_TABLE_NONE, + RID_SVXBMP_TABLE_OUTER, + RID_SVXBMP_TABLE_OUTERH, + RID_SVXBMP_TABLE_ALL, + RID_SVXBMP_TABLE_OUTER2 + }); + } + + for (auto const & rImageId : aBorderImageIds) + m_aBorderImgVec.emplace_back(StockImage::Yes, rImageId); + + static std::vector<OUString> aShadowImageIds; + if (aShadowImageIds.empty()) + { + if (comphelper::LibreOfficeKit::isActive()) + { + aShadowImageIds.insert(aShadowImageIds.end(), { + RID_SVXBMP_SHADOWNONE_32, + RID_SVXBMP_SHADOW_BOT_RIGHT_32, + RID_SVXBMP_SHADOW_TOP_RIGHT_32, + RID_SVXBMP_SHADOW_BOT_LEFT_32, + RID_SVXBMP_SHADOW_TOP_LEFT_32 + }); + } + else + { + aShadowImageIds.insert(aShadowImageIds.end(), { + RID_SVXBMP_SHADOWNONE, + RID_SVXBMP_SHADOW_BOT_RIGHT, + RID_SVXBMP_SHADOW_TOP_RIGHT, + RID_SVXBMP_SHADOW_BOT_LEFT, + RID_SVXBMP_SHADOW_TOP_LEFT + }); + } + } + + for (auto const & rImageId : aShadowImageIds) + m_aShadowImgVec.emplace_back(StockImage::Yes, rImageId); + + assert(m_aShadowImgVec.size() == BORDER_SHADOW_COUNT); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + /* Use SvxMarginItem instead of margins from SvxBoxItem, if present. + -> Remember this state in mbUseMarginItem, because other special handling + is needed across various functions... */ + mbUseMarginItem = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_ALIGN_MARGIN)) != SfxItemState::UNKNOWN; + + if (const SfxIntegerListItem* p = rCoreAttrs.GetItemIfSet(SID_ATTR_BORDER_STYLES)) + { + std::vector<sal_Int32> aUsedStyles = p->GetList(); + for (int aUsedStyle : aUsedStyles) + maUsedBorderStyles.insert(static_cast<SvxBorderLineStyle>(aUsedStyle)); + } + + if (const SfxInt64Item* p = rCoreAttrs.GetItemIfSet(SID_ATTR_BORDER_DEFAULT_WIDTH)) + { + // The caller specifies default line width. Honor it. + SetLineWidth(p->GetValue()); + } + + // set metric + FieldUnit eFUnit = GetModuleFieldUnit( rCoreAttrs ); + + if( mbUseMarginItem ) + { + // copied from SvxAlignmentTabPage + switch ( eFUnit ) + { + // #103396# the default value (1pt) can't be accurately represented in + // inches or pica with two decimals, so point is used instead. + case FieldUnit::PICA: + case FieldUnit::INCH: + case FieldUnit::FOOT: + case FieldUnit::MILE: + eFUnit = FieldUnit::POINT; + break; + + case FieldUnit::CM: + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + } + else + { + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ; //prevent warning + } + } + + SetFieldUnit(*m_xEdShadowSize, eFUnit); + + sal_uInt16 nWhich = GetWhich( SID_ATTR_BORDER_INNER, false ); + bool bIsDontCare = true; + + if ( rCoreAttrs.GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + // paragraph or table + const SvxBoxInfoItem* pBoxInfo = + static_cast<const SvxBoxInfoItem*>(&( rCoreAttrs.Get( nWhich ) )); + + mbHorEnabled = pBoxInfo->IsHorEnabled(); + mbVerEnabled = pBoxInfo->IsVerEnabled(); + mbTLBREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_TLBR)) != SfxItemState::UNKNOWN; + mbBLTREnabled = rCoreAttrs.GetItemState(GetWhich(SID_ATTR_BORDER_DIAG_BLTR)) != SfxItemState::UNKNOWN; + + if(pBoxInfo->IsDist()) + { + SetFieldUnit(*m_xLeftMF, eFUnit); + SetFieldUnit(*m_xRightMF, eFUnit); + SetFieldUnit(*m_xTopMF, eFUnit); + SetFieldUnit(*m_xBottomMF, eFUnit); + m_xSynchronizeCB->connect_toggled(LINK(this, SvxBorderTabPage, SyncHdl_Impl)); + m_xLeftMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + m_xRightMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + m_xTopMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + m_xBottomMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyDistanceHdl_Impl)); + } + else + { + m_xSpacingFrame->hide(); + } + bIsDontCare = !pBoxInfo->IsValid( SvxBoxInfoItemValidFlags::DISABLE ); + } + if(!mbUseMarginItem && eFUnit == FieldUnit::MM && MapUnit::MapTwip == rCoreAttrs.GetPool()->GetMetric( GetWhich( SID_ATTR_BORDER_INNER ) )) + { + //#i91548# changing the number of decimal digits changes the minimum values, too + lcl_SetDecimalDigitsTo1(*m_xLeftMF); + lcl_SetDecimalDigitsTo1(*m_xRightMF); + lcl_SetDecimalDigitsTo1(*m_xTopMF); + lcl_SetDecimalDigitsTo1(*m_xBottomMF); + lcl_SetDecimalDigitsTo1(*m_xEdShadowSize); + } + + FrameSelFlags nFlags = FrameSelFlags::Outer; + if( mbHorEnabled ) + nFlags |= FrameSelFlags::InnerHorizontal; + if( mbVerEnabled ) + nFlags |= FrameSelFlags::InnerVertical; + if( mbTLBREnabled ) + nFlags |= FrameSelFlags::DiagonalTLBR; + if( mbBLTREnabled ) + nFlags |= FrameSelFlags::DiagonalBLTR; + if( bIsDontCare ) + nFlags |= FrameSelFlags::DontCare; + m_aFrameSel.Initialize( nFlags ); + + m_aFrameSel.SetSelectHdl(LINK(this, SvxBorderTabPage, LinesChanged_Impl)); + m_xLbLineStyle->SetSelectHdl( LINK( this, SvxBorderTabPage, SelStyleHdl_Impl ) ); + m_xLbLineColor->SetSelectHdl( LINK( this, SvxBorderTabPage, SelColHdl_Impl ) ); + m_xLineWidthLB->connect_changed(LINK(this, SvxBorderTabPage, ModifyWidthLBHdl_Impl)); + m_xLineWidthMF->connect_value_changed(LINK(this, SvxBorderTabPage, ModifyWidthMFHdl_Impl)); + m_xWndPresets->SetSelectHdl( LINK( this, SvxBorderTabPage, SelPreHdl_Impl ) ); + m_xWndShadows->SetSelectHdl( LINK( this, SvxBorderTabPage, SelSdwHdl_Impl ) ); + + FillValueSets(); + FillLineListBox_Impl(); + + // Reapply line width: probably one of predefined values should be selected + SetLineWidth(m_xLineWidthMF->get_value(FieldUnit::NONE)); + + // connections + const SfxPoolItem* pItem = nullptr; + if (rCoreAttrs.HasItem(GetWhich(SID_ATTR_PARA_GRABBAG), &pItem)) + { + const SfxGrabBagItem* pGrabBag = static_cast<const SfxGrabBagItem*>(pItem); + auto it = pGrabBag->GetGrabBag().find("DialogUseCharAttr"); + if (it != pGrabBag->GetGrabBag().end()) + { + bool bDialogUseCharAttr = false; + it->second >>= bDialogUseCharAttr; + if (bDialogUseCharAttr) + { + mnShadowSlot = SID_ATTR_CHAR_SHADOW; + mnBoxSlot = SID_ATTR_CHAR_BOX; + } + } + } + + bool bSupportsShadow = !SfxItemPool::IsSlot(GetWhich(mnShadowSlot)); + if( bSupportsShadow ) + m_xShadowControls.reset(new ShadowControlsWrapper(*m_xWndShadows, *m_xEdShadowSize, *m_xLbShadowColor)); + else + HideShadowControls(); + + if (mbUseMarginItem) + m_xMarginControls.reset(new MarginControlsWrapper(*m_xLeftMF, *m_xRightMF, *m_xTopMF, *m_xBottomMF)); + + // checkbox "Merge with next paragraph" only visible for Writer dialog format.paragraph + m_xMergeWithNextCB->hide(); + // checkbox "Merge adjacent line styles" only visible for Writer dialog format.table + m_xMergeAdjacentBordersCB->hide(); + + if (SfxObjectShell* pDocSh = SfxObjectShell::Current()) + { + Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY ); + if ( xSI.is() ) + bIsCalcDoc = xSI->supportsService("com.sun.star.sheet.SpreadsheetDocument"); + } + if( bIsCalcDoc ) + { + m_xRemoveAdjacentCellBordersCB->connect_toggled(LINK(this, SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl)); + m_xRemoveAdjacentCellBordersCB->show(); + m_xRemoveAdjacentCellBordersCB->set_sensitive(false); + } + else + { + m_xRemoveAdjacentCellBordersCB->hide(); + m_xRemoveAdjacentCellBordersFT->hide(); + } +} + +SvxBorderTabPage::~SvxBorderTabPage() +{ + m_xLbShadowColor.reset(); + m_xWndShadowsWin.reset(); + m_xWndShadows.reset(); + m_xLbLineColor.reset(); + m_xLbLineStyle.reset(); + m_xFrameSelWin.reset(); + m_xWndPresetsWin.reset(); + m_xWndPresets.reset(); +} + +std::unique_ptr<SfxTabPage> SvxBorderTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique<SvxBorderTabPage>(pPage, pController, *rAttrSet); +} + +void SvxBorderTabPage::ResetFrameLine_Impl( svx::FrameBorderType eBorder, const SvxBorderLine* pCoreLine, bool bValid ) +{ + if( m_aFrameSel.IsBorderEnabled( eBorder ) ) + { + if( bValid ) + m_aFrameSel.ShowBorder( eBorder, pCoreLine ); + else + m_aFrameSel.SetBorderDontCare( eBorder ); + } +} + +bool SvxBorderTabPage::IsBorderLineStyleAllowed( SvxBorderLineStyle nStyle ) const +{ + if (maUsedBorderStyles.empty()) + // All border styles are allowed. + return true; + + return maUsedBorderStyles.count(nStyle) > 0; +} + +void SvxBorderTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR)) + { + sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_TLBR); + if (const SvxLineItem* pLineItem = static_cast<const SvxLineItem*>(rSet->GetItem(nBorderDiagId))) + m_aFrameSel.ShowBorder(svx::FrameBorderType::TLBR, pLineItem->GetLine()); + else + m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::TLBR); + } + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR)) + { + sal_uInt16 nBorderDiagId = pPool->GetWhich(SID_ATTR_BORDER_DIAG_BLTR); + if (const SvxLineItem* pLineItem = static_cast<const SvxLineItem*>(rSet->GetItem(nBorderDiagId))) + m_aFrameSel.ShowBorder(svx::FrameBorderType::BLTR, pLineItem->GetLine()); + else + m_aFrameSel.SetBorderDontCare(svx::FrameBorderType::BLTR); + } + + if (m_xShadowControls) + { + sal_uInt16 nShadowId = pPool->GetWhich(mnShadowSlot); + const SfxPoolItem* pItem = rSet->GetItem(nShadowId); + if (pItem) + m_xShadowControls->SetControlValue(*static_cast<const SvxShadowItem*>(pItem)); + else + m_xShadowControls->SetControlDontKnow(); + } + + if (m_xMarginControls) + { + sal_uInt16 nAlignMarginId = pPool->GetWhich(SID_ATTR_ALIGN_MARGIN); + const SfxPoolItem* pItem = rSet->GetItem(nAlignMarginId); + if (pItem) + m_xMarginControls->SetControlValue(*static_cast<const SvxMarginItem*>(pItem)); + else + m_xMarginControls->SetControlDontKnow(); + } + + sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhich(SID_SW_COLLAPSING_BORDERS); + const SfxBoolItem *pMergeAdjacentBorders = static_cast<const SfxBoolItem*>(rSet->GetItem(nMergeAdjacentBordersId)); + if (!pMergeAdjacentBorders) + m_xMergeAdjacentBordersCB->set_state(TRISTATE_INDET); + else + m_xMergeAdjacentBordersCB->set_active(pMergeAdjacentBorders->GetValue()); + m_xMergeAdjacentBordersCB->save_state(); + + sal_uInt16 nMergeWithNextId = pPool->GetWhich(SID_ATTR_BORDER_CONNECT); + const SfxBoolItem *pMergeWithNext = static_cast<const SfxBoolItem*>(rSet->GetItem(nMergeWithNextId)); + if (!pMergeWithNext) + m_xMergeWithNextCB->set_state(TRISTATE_INDET); + else + m_xMergeWithNextCB->set_active(pMergeWithNext->GetValue()); + m_xMergeWithNextCB->save_state(); + + const SvxBoxItem* pBoxItem; + const SvxBoxInfoItem* pBoxInfoItem; + sal_uInt16 nWhichBox = GetWhich(mnBoxSlot); + MapUnit eCoreUnit; + + pBoxItem = static_cast<const SvxBoxItem*>(GetItem( *rSet, mnBoxSlot )); + + pBoxInfoItem = GetItem( *rSet, SID_ATTR_BORDER_INNER, false ); + + eCoreUnit = pPool->GetMetric( nWhichBox ); + + if ( pBoxItem && pBoxInfoItem ) // -> Don't Care + { + ResetFrameLine_Impl( svx::FrameBorderType::Left, pBoxItem->GetLeft(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::LEFT ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Right, pBoxItem->GetRight(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::RIGHT ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Top, pBoxItem->GetTop(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::TOP ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Bottom, pBoxItem->GetBottom(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Vertical, pBoxInfoItem->GetVert(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::VERT ) ); + ResetFrameLine_Impl( svx::FrameBorderType::Horizontal, pBoxInfoItem->GetHori(), pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::HORI ) ); + + + // distance inside + + if( !mbUseMarginItem ) + { + if (m_xLeftMF->get_visible()) + { + SetMetricValue(*m_xLeftMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + SetMetricValue(*m_xRightMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + SetMetricValue(*m_xTopMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + SetMetricValue(*m_xBottomMF, pBoxInfoItem->GetDefDist(), eCoreUnit); + + nMinValue = m_xLeftMF->get_value(FieldUnit::NONE); + + if ( pBoxInfoItem->IsDist() ) + { + if( rSet->GetItemState( nWhichBox ) >= SfxItemState::DEFAULT ) + { + bool bIsAnyBorderVisible = m_aFrameSel.IsAnyBorderVisible(); + if( !bIsAnyBorderVisible || !pBoxInfoItem->IsMinDist() ) + { + m_xLeftMF->set_min(0, FieldUnit::NONE); + m_xRightMF->set_min(0, FieldUnit::NONE); + m_xTopMF->set_min(0, FieldUnit::NONE); + m_xBottomMF->set_min(0, FieldUnit::NONE); + } + tools::Long nLeftDist = pBoxItem->GetDistance( SvxBoxItemLine::LEFT); + SetMetricValue(*m_xLeftMF, nLeftDist, eCoreUnit); + tools::Long nRightDist = pBoxItem->GetDistance( SvxBoxItemLine::RIGHT); + SetMetricValue(*m_xRightMF, nRightDist, eCoreUnit); + tools::Long nTopDist = pBoxItem->GetDistance( SvxBoxItemLine::TOP); + SetMetricValue( *m_xTopMF, nTopDist, eCoreUnit ); + tools::Long nBottomDist = pBoxItem->GetDistance( SvxBoxItemLine::BOTTOM); + SetMetricValue( *m_xBottomMF, nBottomDist, eCoreUnit ); + + // if the distance is set with no active border line + // or it is null with an active border line + // no automatic changes should be made + const tools::Long nDefDist = bIsAnyBorderVisible ? pBoxInfoItem->GetDefDist() : 0; + bool bDiffDist = (nDefDist != nLeftDist || + nDefDist != nRightDist || + nDefDist != nTopDist || + nDefDist != nBottomDist); + if ((pBoxItem->GetSmallestDistance() || bIsAnyBorderVisible) && bDiffDist ) + { + mbLeftModified = true; + mbRightModified = true; + mbTopModified = true; + mbBottomModified = true; + } + } + else + { + // #106224# different margins -> do not fill the edits + m_xLeftMF->set_text( OUString() ); + m_xRightMF->set_text( OUString() ); + m_xTopMF->set_text( OUString() ); + m_xBottomMF->set_text( OUString() ); + } + } + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + } + } + } + else + { + // avoid ResetFrameLine-calls: + m_aFrameSel.HideAllBorders(); + } + + if( !m_aFrameSel.IsAnyBorderVisible() ) + m_aFrameSel.DeselectAllBorders(); + + // depict line (color) in controllers if unambiguous: + + { + // Do all visible lines show the same line widths? + tools::Long nWidth; + SvxBorderLineStyle nStyle; + bool bWidthEq = m_aFrameSel.GetVisibleWidth( nWidth, nStyle ); + if( bWidthEq ) + { + // Determine the width first as some styles can be missing depending on it + sal_Int64 nWidthPt = static_cast<sal_Int64>(vcl::ConvertDoubleValue( + sal_Int64( nWidth ), m_xLineWidthMF->get_digits(), + MapUnit::MapTwip, FieldUnit::POINT )); + SetLineWidth(nWidthPt); + m_xLbLineStyle->SetWidth(nWidth); + + // then set the style + m_xLbLineStyle->SelectEntry( nStyle ); + } + else + m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID); + + // Do all visible lines show the same line color? + Color aColor; + bool bColorEq = m_aFrameSel.GetVisibleColor( aColor ); + if( !bColorEq ) + aColor = COL_BLACK; + + m_xLbLineColor->SelectEntry(aColor); + auto nTextColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor(); + m_xLbLineStyle->SetColor(nTextColor); + + // Select all visible lines, if they are all equal. + if( bWidthEq && bColorEq ) + m_aFrameSel.SelectAllVisibleBorders(); + + // set the current style and color (caches style in control even if nothing is selected) + SelStyleHdl_Impl(*m_xLbLineStyle); + SelColHdl_Impl(*m_xLbLineColor); + } + + bool bEnable = m_xWndShadows->GetSelectedItemId() > 1 ; + m_xFtShadowSize->set_sensitive(bEnable); + m_xEdShadowSize->set_sensitive(bEnable); + m_xFtShadowColor->set_sensitive(bEnable); + m_xLbShadowColor->set_sensitive(bEnable); + + m_xWndPresets->SetNoSelection(); + + // - no line - should not be selected + + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE) + { + m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID); + SelStyleHdl_Impl(*m_xLbLineStyle); + } + + const SfxUInt16Item* pHtmlModeItem = rSet->GetItemIfSet(SID_HTML_MODE, false); + if(!pHtmlModeItem) + { + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + pHtmlModeItem = pShell->GetItem(SID_HTML_MODE); + } + if(pHtmlModeItem) + { + sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue(); + if(nHtmlMode & HTMLMODE_ON) + { + // there are no shadows in Html-mode and only complete borders + m_xShadowFrame->set_sensitive(false); + + if( !(nSWMode & SwBorderModes::TABLE) ) + { + m_xUserDefFT->set_sensitive(false); + m_xFrameSelWin->set_sensitive(false); + m_xWndPresets->RemoveItem(3); + m_xWndPresets->RemoveItem(4); + m_xWndPresets->RemoveItem(5); + } + } + } + + LinesChanged_Impl( nullptr ); + if (m_xLeftMF->get_value(FieldUnit::NONE) == m_xRightMF->get_value(FieldUnit::NONE) && + m_xTopMF->get_value(FieldUnit::NONE) == m_xBottomMF->get_value(FieldUnit::NONE) && + m_xTopMF->get_value(FieldUnit::NONE) == m_xLeftMF->get_value(FieldUnit::NONE)) + { + mbSync = true; + } + else + mbSync = false; + m_xSynchronizeCB->set_active(mbSync); + + mbRemoveAdjacentCellBorders = false; + m_xRemoveAdjacentCellBordersCB->set_active(false); + m_xRemoveAdjacentCellBordersCB->set_sensitive(false); +} + +void SvxBorderTabPage::ChangesApplied() +{ + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + m_xMergeWithNextCB->save_state(); + m_xMergeAdjacentBordersCB->save_state(); +} + +DeactivateRC SvxBorderTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +bool SvxBorderTabPage::FillItemSet( SfxItemSet* rCoreAttrs ) +{ + bool bAttrsChanged = false; + + SfxItemPool* pPool = rCoreAttrs->GetPool(); + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::TLBR) && + m_aFrameSel.GetFrameBorderState(svx::FrameBorderType::TLBR) != svx::FrameBorderState::DontCare) + { + if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_DIAG_TLBR)) + { + SvxLineItem aLineItem(*static_cast<const SvxLineItem*>(pOldItem)); + aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::TLBR)); + rCoreAttrs->Put(aLineItem); + bAttrsChanged = true; + } + } + + if (m_aFrameSel.IsBorderEnabled(svx::FrameBorderType::BLTR) && + m_aFrameSel.GetFrameBorderState(svx::FrameBorderType::BLTR) != svx::FrameBorderState::DontCare) + { + if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_DIAG_BLTR)) + { + SvxLineItem aLineItem(*static_cast<const SvxLineItem*>(pOldItem)); + aLineItem.SetLine(m_aFrameSel.GetFrameBorderStyle(svx::FrameBorderType::BLTR)); + rCoreAttrs->Put(aLineItem); + bAttrsChanged = true; + } + } + + if (m_xShadowControls && m_xShadowControls->get_value_changed_from_saved()) + { + if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, mnShadowSlot)) + { + const SvxShadowItem& rOldShadowItem = *static_cast<const SvxShadowItem*>(pOldItem); + rCoreAttrs->Put(m_xShadowControls->GetControlValue(rOldShadowItem)); + bAttrsChanged = true; + } + } + + if (m_xMarginControls && m_xMarginControls->get_value_changed_from_saved()) + { + if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_ALIGN_MARGIN)) + { + const SvxMarginItem& rOldMarginItem = *static_cast<const SvxMarginItem*>(pOldItem); + rCoreAttrs->Put(m_xMarginControls->GetControlValue(rOldMarginItem)); + bAttrsChanged = true; + } + } + + if (m_xMergeAdjacentBordersCB->get_state_changed_from_saved()) + { + auto nState = m_xMergeAdjacentBordersCB->get_state(); + if (nState == TRISTATE_INDET) + { + sal_uInt16 nMergeAdjacentBordersId = pPool->GetWhich(SID_SW_COLLAPSING_BORDERS); + rCoreAttrs->ClearItem(nMergeAdjacentBordersId); + } + else + { + if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_SW_COLLAPSING_BORDERS)) + { + std::unique_ptr<SfxBoolItem> xNewItem(static_cast<SfxBoolItem*>(pOldItem->Clone())); + xNewItem->SetValue(static_cast<bool>(nState)); + rCoreAttrs->Put(std::move(xNewItem)); + } + } + bAttrsChanged = true; + } + + if (m_xMergeWithNextCB->get_state_changed_from_saved()) + { + auto nState = m_xMergeWithNextCB->get_state(); + if (nState == TRISTATE_INDET) + { + sal_uInt16 nMergeWithNextId = pPool->GetWhich(SID_ATTR_BORDER_CONNECT); + rCoreAttrs->ClearItem(nMergeWithNextId); + } + else + { + if (const SfxPoolItem* pOldItem = GetOldItem(*rCoreAttrs, SID_ATTR_BORDER_CONNECT)) + { + std::unique_ptr<SfxBoolItem> xNewItem(static_cast<SfxBoolItem*>(pOldItem->Clone())); + xNewItem->SetValue(static_cast<bool>(nState)); + rCoreAttrs->Put(std::move(xNewItem)); + } + } + bAttrsChanged = true; + } + + bool bPut = true; + sal_uInt16 nBoxWhich = GetWhich( mnBoxSlot ); + sal_uInt16 nBoxInfoWhich = pPool->GetWhich( SID_ATTR_BORDER_INNER, false ); + const SfxItemSet& rOldSet = GetItemSet(); + SvxBoxItem aBoxItem ( nBoxWhich ); + SvxBoxInfoItem aBoxInfoItem ( nBoxInfoWhich ); + const SvxBoxItem* pOldBoxItem = static_cast<const SvxBoxItem*>(GetOldItem( *rCoreAttrs, mnBoxSlot )); + + MapUnit eCoreUnit = rOldSet.GetPool()->GetMetric( nBoxWhich ); + + + // outer border: + + std::pair<svx::FrameBorderType,SvxBoxItemLine> eTypes1[] = { + { svx::FrameBorderType::Top,SvxBoxItemLine::TOP }, + { svx::FrameBorderType::Bottom,SvxBoxItemLine::BOTTOM }, + { svx::FrameBorderType::Left,SvxBoxItemLine::LEFT }, + { svx::FrameBorderType::Right,SvxBoxItemLine::RIGHT }, + }; + + for (std::pair<svx::FrameBorderType,SvxBoxItemLine> const & i : eTypes1) + aBoxItem.SetLine( m_aFrameSel.GetFrameBorderStyle( i.first ), i.second ); + + + aBoxItem.SetRemoveAdjacentCellBorder( mbRemoveAdjacentCellBorders ); + // border hor/ver and TableFlag + + std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> eTypes2[] = { + { svx::FrameBorderType::Horizontal,SvxBoxInfoItemLine::HORI }, + { svx::FrameBorderType::Vertical,SvxBoxInfoItemLine::VERT } + }; + for (std::pair<svx::FrameBorderType,SvxBoxInfoItemLine> const & j : eTypes2) + aBoxInfoItem.SetLine( m_aFrameSel.GetFrameBorderStyle( j.first ), j.second ); + + aBoxInfoItem.EnableHor( mbHorEnabled ); + aBoxInfoItem.EnableVer( mbVerEnabled ); + + + // inner distance + + if (m_xLeftMF->get_visible()) + { + // #i40405# enable distance controls for next dialog call + aBoxInfoItem.SetDist( true ); + + if( !mbUseMarginItem ) + { + // #106224# all edits empty: do nothing + if( !m_xLeftMF->get_text().isEmpty() || !m_xRightMF->get_text().isEmpty() || + !m_xTopMF->get_text().isEmpty() || !m_xBottomMF->get_text().isEmpty() ) + { + const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER ); + if ( + !pOldBoxItem || + m_xLeftMF->get_value_changed_from_saved() || + m_xRightMF->get_value_changed_from_saved() || + m_xTopMF->get_value_changed_from_saved() || + m_xBottomMF->get_value_changed_from_saved() || + nMinValue == m_xLeftMF->get_value(FieldUnit::NONE) || + nMinValue == m_xRightMF->get_value(FieldUnit::NONE) || + nMinValue == m_xTopMF->get_value(FieldUnit::NONE) || + nMinValue == m_xBottomMF->get_value(FieldUnit::NONE) || + (pOldBoxInfoItem && !pOldBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::DISTANCE)) + ) + { + aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xLeftMF, eCoreUnit )), SvxBoxItemLine::LEFT ); + aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xRightMF, eCoreUnit )), SvxBoxItemLine::RIGHT ); + aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xTopMF, eCoreUnit )), SvxBoxItemLine::TOP ); + aBoxItem.SetDistance( static_cast<sal_uInt16>(GetCoreValue(*m_xBottomMF, eCoreUnit )), SvxBoxItemLine::BOTTOM); + } + else + { + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::LEFT ), SvxBoxItemLine::LEFT); + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::RIGHT), SvxBoxItemLine::RIGHT); + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::TOP ), SvxBoxItemLine::TOP); + aBoxItem.SetDistance(pOldBoxItem->GetDistance(SvxBoxItemLine::BOTTOM), SvxBoxItemLine::BOTTOM); + } + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); + } + } + } + + + // note Don't Care Status in the Info-Item: + + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::TOP, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Top ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Bottom ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::LEFT, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Left ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::RIGHT, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Right ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::HORI, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Horizontal ) != svx::FrameBorderState::DontCare ); + aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::VERT, m_aFrameSel.GetFrameBorderState( svx::FrameBorderType::Vertical ) != svx::FrameBorderState::DontCare ); + + + // Put or Clear of the border? + + bPut = true; + + if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxWhich, false )) + { + bPut = aBoxItem != static_cast<const SvxBoxItem&>(rOldSet.Get(nBoxWhich)); + } + if( SfxItemState::DEFAULT == rOldSet.GetItemState( nBoxInfoWhich, false ) ) + { + const SvxBoxInfoItem& rOldBoxInfo = static_cast<const SvxBoxInfoItem&>( + rOldSet.Get(nBoxInfoWhich)); + + aBoxInfoItem.SetMinDist( rOldBoxInfo.IsMinDist() ); + aBoxInfoItem.SetDefDist( rOldBoxInfo.GetDefDist() ); + bPut |= (aBoxInfoItem != rOldBoxInfo ); + } + + if ( bPut ) + { + if ( !pOldBoxItem || *pOldBoxItem != aBoxItem ) + { + rCoreAttrs->Put( aBoxItem ); + bAttrsChanged = true; + } + const SfxPoolItem* pOld = GetOldItem( *rCoreAttrs, SID_ATTR_BORDER_INNER, false ); + + if ( !pOld || *static_cast<const SvxBoxInfoItem*>(pOld) != aBoxInfoItem ) + { + rCoreAttrs->Put( aBoxInfoItem ); + bAttrsChanged = true; + } + } + else + { + rCoreAttrs->ClearItem( nBoxWhich ); + rCoreAttrs->ClearItem( nBoxInfoWhich ); + } + + return bAttrsChanged; +} + +void SvxBorderTabPage::HideShadowControls() +{ + m_xShadowFrame->hide(); +} + +#define IID_PRE_CELL_NONE 1 +#define IID_PRE_CELL_ALL 2 +#define IID_PRE_CELL_LR 3 +#define IID_PRE_CELL_TB 4 +#define IID_PRE_CELL_L 5 +#define IID_PRE_CELL_DIAG 6 +#define IID_PRE_HOR_NONE 7 +#define IID_PRE_HOR_OUTER 8 +#define IID_PRE_HOR_HOR 9 +#define IID_PRE_HOR_ALL 10 +#define IID_PRE_HOR_OUTER2 11 +#define IID_PRE_VER_NONE 12 +#define IID_PRE_VER_OUTER 13 +#define IID_PRE_VER_VER 14 +#define IID_PRE_VER_ALL 15 +#define IID_PRE_VER_OUTER2 16 +#define IID_PRE_TABLE_NONE 17 +#define IID_PRE_TABLE_OUTER 18 +#define IID_PRE_TABLE_OUTERH 19 +#define IID_PRE_TABLE_ALL 20 +#define IID_PRE_TABLE_OUTER2 21 + +IMPL_LINK_NOARG(SvxBorderTabPage, SelPreHdl_Impl, ValueSet*, void) +{ + const svx::FrameBorderState SHOW = svx::FrameBorderState::Show; + const svx::FrameBorderState HIDE = svx::FrameBorderState::Hide; + const svx::FrameBorderState DONT = svx::FrameBorderState::DontCare; + + static const svx::FrameBorderState ppeStates[][ svx::FRAMEBORDERTYPE_COUNT ] = + { /* Left Right Top Bot Hor Ver TLBR BLTR */ +/* ---------------------+--------------------------------------------------- */ +/* IID_PRE_CELL_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_ALL */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_LR */ { SHOW, SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_TB */ { HIDE, HIDE, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_L */ { SHOW, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_CELL_DIAG */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, SHOW, SHOW }, +/* IID_PRE_HOR_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_OUTER */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_HOR */ { HIDE, HIDE, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_ALL */ { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE }, +/* IID_PRE_HOR_OUTER2 */ { SHOW, SHOW, SHOW, SHOW, DONT, HIDE, HIDE, HIDE }, +/* IID_PRE_VER_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_VER_OUTER */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_VER_VER */ { SHOW, SHOW, HIDE, HIDE, HIDE, SHOW, HIDE, HIDE }, +/* IID_PRE_VER_ALL */ { SHOW, SHOW, SHOW, SHOW, HIDE, SHOW, HIDE, HIDE }, +/* IID_PRE_VER_OUTER2 */ { SHOW, SHOW, SHOW, SHOW, HIDE, DONT, HIDE, HIDE }, +/* IID_PRE_TABLE_NONE */ { HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_TABLE_OUTER */ { SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE, HIDE }, +/* IID_PRE_TABLE_OUTERH */ { SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE, HIDE }, +/* IID_PRE_TABLE_ALL */ { SHOW, SHOW, SHOW, SHOW, SHOW, SHOW, HIDE, HIDE }, +/* IID_PRE_TABLE_OUTER2 */ { SHOW, SHOW, SHOW, SHOW, DONT, DONT, HIDE, HIDE } + }; + + // first hide and deselect all frame borders + m_aFrameSel.HideAllBorders(); + m_aFrameSel.DeselectAllBorders(); + + // Using image ID to find correct line in table above. + sal_uInt16 nLine = GetPresetImageId( m_xWndPresets->GetSelectedItemId() ) - 1; + + // Apply all styles from the table + for( int nBorder = 0; nBorder < svx::FRAMEBORDERTYPE_COUNT; ++nBorder ) + { + svx::FrameBorderType eBorder = svx::GetFrameBorderTypeFromIndex( nBorder ); + switch( ppeStates[ nLine ][ nBorder ] ) + { + case SHOW: m_aFrameSel.SelectBorder( eBorder ); break; + case HIDE: /* nothing to do */ break; + case DONT: m_aFrameSel.SetBorderDontCare( eBorder ); break; + } + } + + // Show all lines that have been selected above + if( m_aFrameSel.IsAnyBorderSelected() ) + { + // any visible style, but "no-line" in line list box? -> use hair-line + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::NONE) + m_xLbLineStyle->SelectEntry(SvxBorderLineStyle::SOLID); + + // set current style to all previously selected lines + SelStyleHdl_Impl(*m_xLbLineStyle); + SelColHdl_Impl(*m_xLbLineColor); + } + + // Presets ValueSet does not show a selection (used as push buttons). + m_xWndPresets->SetNoSelection(); + + LinesChanged_Impl( nullptr ); + UpdateRemoveAdjCellBorderCB( nLine + 1 ); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, SelSdwHdl_Impl, ValueSet*, void) +{ + bool bEnable = m_xWndShadows->GetSelectedItemId() > 1; + m_xFtShadowSize->set_sensitive(bEnable); + m_xEdShadowSize->set_sensitive(bEnable); + m_xFtShadowColor->set_sensitive(bEnable); + m_xLbShadowColor->set_sensitive(bEnable); +} + +IMPL_LINK(SvxBorderTabPage, SelColHdl_Impl, ColorListBox&, rColorBox, void) +{ + Color aColor = rColorBox.GetSelectEntryColor(); + m_aFrameSel.SetColorToSelection(aColor); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, ModifyWidthLBHdl_Impl, weld::ComboBox&, void) +{ + sal_Int32 nPos = m_xLineWidthLB->get_active(); + sal_Int32 nRemovedType = 0; + if (m_xLineWidthLB->get_values_changed_from_saved()) { + nRemovedType = m_aLineWidths.size() - m_xLineWidthLB->get_count(); + } + + SetLineWidth(m_aLineWidths[nPos + nRemovedType], nRemovedType); + + // Call the spinner handler to trigger all related modifications + ModifyWidthMFHdl_Impl(*m_xLineWidthMF); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, ModifyWidthMFHdl_Impl, weld::MetricSpinButton&, void) +{ + sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE); + + // for DOUBLE_THIN line style we cannot allow thinner line width then 1.10pt + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN) + m_xLineWidthMF->set_min(110, FieldUnit::NONE); + else + m_xLineWidthMF->set_min(5, FieldUnit::NONE); + + nVal = static_cast<sal_Int64>(vcl::ConvertDoubleValue( + nVal, + m_xLineWidthMF->get_digits(), + FieldUnit::POINT, MapUnit::MapTwip )); + m_xLbLineStyle->SetWidth( nVal ); + + m_aFrameSel.SetStyleToSelection( nVal, + m_xLbLineStyle->GetSelectEntryStyle() ); +} + +IMPL_LINK_NOARG(SvxBorderTabPage, SelStyleHdl_Impl, SvtLineListBox&, void) +{ + sal_Int64 nOldWidth = m_xLineWidthMF->get_value(FieldUnit::NONE); + + // for DOUBLE_THIN line style we cannot allow thinner line width then 1.10pt + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN) + m_xLineWidthMF->set_min(110, FieldUnit::NONE); + else + m_xLineWidthMF->set_min(5, FieldUnit::NONE); + + nOldWidth = static_cast<sal_Int64>(vcl::ConvertDoubleValue( + nOldWidth, + m_xLineWidthMF->get_digits(), + FieldUnit::POINT, + MapUnit::MapTwip)); + + const sal_Int64 nOldMinWidth = lcl_GetMinLineWidth(m_aFrameSel.getCurrentStyleLineStyle()); + const sal_Int64 nNewMinWidth = lcl_GetMinLineWidth(m_xLbLineStyle->GetSelectEntryStyle()); + + // auto change line-width if it doesn't correspond to minimal value + // let's change only in case when user has not changed the line-width into some custom value + sal_Int64 nNewWidth = (nOldMinWidth == nOldWidth) ? nNewMinWidth : nOldWidth; + + // if we had selected a predefined border width under SvxBorderLineWidth::Medium set the Medium as default + // otherwise if we had a cusom border width under 1.10pt then set the spinner to the maximum allowed value for double border styles + bool bNewDoubleHairline = m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN && !m_xLineWidthMF->get_visible() && + (nOldWidth == SvxBorderLineWidth::Hairline || nOldWidth == SvxBorderLineWidth::VeryThin || nOldWidth == SvxBorderLineWidth::Thin); + if (bNewDoubleHairline && nNewWidth < SvxBorderLineWidth::Medium) + nNewWidth = SvxBorderLineWidth::Medium; + + // set value inside edit box + if (nOldWidth != nNewWidth) + { + const sal_Int64 nNewWidthPt = static_cast<sal_Int64>(vcl::ConvertDoubleValue( + nNewWidth, + m_xLineWidthMF->get_digits(), + MapUnit::MapTwip, + FieldUnit::POINT)); + SetLineWidth(nNewWidthPt); + } + + if (m_xLbLineStyle->GetSelectEntryStyle() == SvxBorderLineStyle::DOUBLE_THIN) + { + for (size_t i = 0; i < 3; i++) + { + m_xLineWidthLB->save_values_by_id(OUString::number(i)); + m_xLineWidthLB->remove_id(OUString::number(i)); + } + if (m_xLineWidthLB->get_active_id().isEmpty()) + m_xLineWidthLB->set_active_id("3"); + } + else + { + if (m_xLineWidthLB->get_values_changed_from_saved()) + { + for (size_t i = 0; i < 3; i++) + m_xLineWidthLB->append(i, OUString::number(i), m_xLineWidthLB->get_saved_values(i)); + m_xLineWidthLB->removeSavedValues(); + } + } + + // set value inside style box + m_aFrameSel.SetStyleToSelection( nNewWidth, + m_xLbLineStyle->GetSelectEntryStyle() ); +} + + +// ValueSet handling +sal_uInt16 SvxBorderTabPage::GetPresetImageId( sal_uInt16 nValueSetIdx ) const +{ + // table with all sets of predefined border styles + static const sal_uInt16 ppnImgIds[][ BORDER_PRESET_COUNT ] = + { + // simple cell without diagonal frame borders + { IID_PRE_CELL_NONE, IID_PRE_CELL_ALL, IID_PRE_CELL_LR, IID_PRE_CELL_TB, IID_PRE_CELL_L }, + // simple cell with diagonal frame borders + { IID_PRE_CELL_NONE, IID_PRE_CELL_ALL, IID_PRE_CELL_LR, IID_PRE_CELL_TB, IID_PRE_CELL_DIAG }, + // with horizontal inner frame border + { IID_PRE_HOR_NONE, IID_PRE_HOR_OUTER, IID_PRE_HOR_HOR, IID_PRE_HOR_ALL, IID_PRE_HOR_OUTER2 }, + // with vertical inner frame border + { IID_PRE_VER_NONE, IID_PRE_VER_OUTER, IID_PRE_VER_VER, IID_PRE_VER_ALL, IID_PRE_VER_OUTER2 }, + // with horizontal and vertical inner frame borders + { IID_PRE_TABLE_NONE, IID_PRE_TABLE_OUTER, IID_PRE_TABLE_OUTERH, IID_PRE_TABLE_ALL, IID_PRE_TABLE_OUTER2 } + }; + + // find correct set of presets + int nLine = 0; + if( !mbHorEnabled && !mbVerEnabled ) + nLine = (mbTLBREnabled || mbBLTREnabled) ? 1 : 0; + else if( mbHorEnabled && !mbVerEnabled ) + nLine = 2; + else if( !mbHorEnabled && mbVerEnabled ) + nLine = 3; + else + nLine = 4; + + DBG_ASSERT( (1 <= nValueSetIdx) && (nValueSetIdx <= BORDER_PRESET_COUNT), + "SvxBorderTabPage::GetPresetImageId - wrong index" ); + return ppnImgIds[ nLine ][ nValueSetIdx - 1 ]; +} + +TranslateId SvxBorderTabPage::GetPresetStringId( sal_uInt16 nValueSetIdx ) const +{ + // string resource IDs for each image (in order of the IID_PRE_* image IDs) + static const TranslateId pnStrIds[] = + { + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_PARA_PRESET_ALL, + RID_SVXSTR_PARA_PRESET_LEFTRIGHT, + RID_SVXSTR_PARA_PRESET_TOPBOTTOM, + RID_SVXSTR_PARA_PRESET_ONLYLEFT, + RID_SVXSTR_PARA_PRESET_DIAGONAL, + + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_TABLE_PRESET_ONLYOUTER, + RID_SVXSTR_HOR_PRESET_ONLYHOR, + RID_SVXSTR_TABLE_PRESET_OUTERALL, + RID_SVXSTR_TABLE_PRESET_OUTERINNER, + + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_TABLE_PRESET_ONLYOUTER, + RID_SVXSTR_VER_PRESET_ONLYVER, + RID_SVXSTR_TABLE_PRESET_OUTERALL, + RID_SVXSTR_TABLE_PRESET_OUTERINNER, + + RID_SVXSTR_TABLE_PRESET_NONE, + RID_SVXSTR_TABLE_PRESET_ONLYOUTER, + RID_SVXSTR_TABLE_PRESET_OUTERHORI, + RID_SVXSTR_TABLE_PRESET_OUTERALL, + RID_SVXSTR_TABLE_PRESET_OUTERINNER + }; + return pnStrIds[ GetPresetImageId( nValueSetIdx ) - 1 ]; +} + +void SvxBorderTabPage::FillPresetVS() +{ + // basic initialization of the ValueSet + m_xWndPresets->SetStyle( m_xWndPresets->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER ); + m_xWndPresets->SetColCount( BORDER_PRESET_COUNT ); + + // insert images and help texts + for( sal_uInt16 nVSIdx = 1; nVSIdx <= BORDER_PRESET_COUNT; ++nVSIdx ) + { + m_xWndPresets->InsertItem( nVSIdx ); + m_xWndPresets->SetItemImage(nVSIdx, m_aBorderImgVec[GetPresetImageId(nVSIdx) - 1]); + m_xWndPresets->SetItemText( nVSIdx, SvxResId( GetPresetStringId( nVSIdx ) ) ); + } + + // show the control + m_xWndPresets->SetNoSelection(); + m_xWndPresets->SetOptimalSize(); + m_xWndPresets->Show(); +} + +void SvxBorderTabPage::FillShadowVS() +{ + // basic initialization of the ValueSet + m_xWndShadows->SetStyle( m_xWndShadows->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER ); + m_xWndShadows->SetColCount( BORDER_SHADOW_COUNT ); + + // string resource IDs for each image + static const TranslateId pnStrIds[ BORDER_SHADOW_COUNT ] = + { RID_CUISTR_SHADOW_STYLE_NONE, RID_CUISTR_SHADOW_STYLE_BOTTOMRIGHT, RID_CUISTR_SHADOW_STYLE_TOPRIGHT, RID_CUISTR_SHADOW_STYLE_BOTTOMLEFT, RID_CUISTR_SHADOW_STYLE_TOPLEFT }; + + // insert images and help texts + for( sal_uInt16 nVSIdx = 1; nVSIdx <= BORDER_SHADOW_COUNT; ++nVSIdx ) + { + m_xWndShadows->InsertItem( nVSIdx ); + m_xWndShadows->SetItemImage(nVSIdx, m_aShadowImgVec[nVSIdx-1]); + m_xWndShadows->SetItemText( nVSIdx, CuiResId( pnStrIds[ nVSIdx - 1 ] ) ); + } + + // show the control + m_xWndShadows->SelectItem( 1 ); + m_xWndShadows->SetOptimalSize(); + m_xWndShadows->Show(); +} + + +void SvxBorderTabPage::FillValueSets() +{ + FillPresetVS(); + FillShadowVS(); +} + +void SvxBorderTabPage::SetLineWidth( sal_Int64 nWidth, sal_Int32 nRemovedType ) +{ + if ( nWidth >= 0 ) + m_xLineWidthMF->set_value( nWidth, FieldUnit::POINT ); + + auto it = std::find_if( m_aLineWidths.begin(), m_aLineWidths.end(), + [nWidth](const int val) -> bool { return val == nWidth; } ); + + if ( it != m_aLineWidths.end() && *it >= 0 ) + { + // Select predefined value in combobox + m_xLineWidthMF->hide(); + m_xLineWidthLB->set_active(std::distance(m_aLineWidths.begin(), it) - nRemovedType); + } + else + { + // This is not one of predefined values. Show spinner + m_xLineWidthLB->set_active(m_aLineWidths.size() - nRemovedType -1); + m_xLineWidthMF->show(); + } +} + +static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ ) +{ + return SvxBorderLine::threeDMediumColor( aMain ); +} + +void SvxBorderTabPage::FillLineListBox_Impl() +{ + using namespace ::com::sun::star::table::BorderLineStyle; + + static struct { + SvxBorderLineStyle mnStyle; + SvtLineListBox::ColorFunc mpColor1Fn; + SvtLineListBox::ColorFunc mpColor2Fn; + SvtLineListBox::ColorDistFunc mpColorDistFn; + } const aLines[] = { + // Simple lines + { SvxBorderLineStyle::SOLID, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DOTTED, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DASHED, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::FINE_DASHED, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DASH_DOT, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DASH_DOT_DOT, &sameColor, &sameColor, &sameDistColor }, + + // Double lines + { SvxBorderLineStyle::DOUBLE, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::DOUBLE_THIN, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THINTHICK_SMALLGAP, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THINTHICK_MEDIUMGAP, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THINTHICK_LARGEGAP, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THICKTHIN_SMALLGAP, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THICKTHIN_MEDIUMGAP, &sameColor, &sameColor, &sameDistColor }, + { SvxBorderLineStyle::THICKTHIN_LARGEGAP, &sameColor, &sameColor, &sameDistColor }, + + { SvxBorderLineStyle::EMBOSSED, &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, &lcl_mediumColor }, + { SvxBorderLineStyle::ENGRAVED, &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, &lcl_mediumColor }, + + { SvxBorderLineStyle::OUTSET, &SvxBorderLine::lightColor, &SvxBorderLine::darkColor, &sameDistColor }, + { SvxBorderLineStyle::INSET, &SvxBorderLine::darkColor, &SvxBorderLine::lightColor, &sameDistColor } + }; + + m_xLbLineStyle->SetSourceUnit( FieldUnit::TWIP ); + + for (size_t i = 0; i < std::size(aLines); ++i) + { + if (!IsBorderLineStyleAllowed(aLines[i].mnStyle)) + continue; + + m_xLbLineStyle->InsertEntry( + SvxBorderLine::getWidthImpl(aLines[i].mnStyle), + aLines[i].mnStyle, + lcl_GetMinLineWidth(aLines[i].mnStyle), + aLines[i].mpColor1Fn, + aLines[i].mpColor2Fn, + aLines[i].mpColorDistFn); + } + + sal_Int64 nVal = m_xLineWidthMF->get_value(FieldUnit::NONE); + nVal = static_cast<sal_Int64>(vcl::ConvertDoubleValue(nVal, m_xLineWidthMF->get_digits(), + m_xLineWidthMF->get_unit(), MapUnit::MapTwip)); + m_xLbLineStyle->SetWidth( nVal ); +} + + +IMPL_LINK_NOARG(SvxBorderTabPage, LinesChanged_Impl, LinkParamNone*, void) +{ + if (!mbUseMarginItem && m_xLeftMF->get_visible()) + { + bool bLineSet = m_aFrameSel.IsAnyBorderVisible(); + bool bSpaceModified = mbLeftModified || + mbRightModified || + mbTopModified || + mbBottomModified; + + if(bLineSet) + { + if(!bSpaceModified) + { + m_xLeftMF->set_value(nMinValue, FieldUnit::NONE); + m_xRightMF->set_value(nMinValue, FieldUnit::NONE); + m_xTopMF->set_value(nMinValue, FieldUnit::NONE); + m_xBottomMF->set_value(nMinValue, FieldUnit::NONE); + } + } + else + { + m_xLeftMF->set_min(0, FieldUnit::NONE); + m_xRightMF->set_min(0, FieldUnit::NONE); + m_xTopMF->set_min(0, FieldUnit::NONE); + m_xBottomMF->set_min(0, FieldUnit::NONE); + } + // for tables everything is allowed + SvxBoxInfoItemValidFlags nValid = SvxBoxInfoItemValidFlags::TOP|SvxBoxInfoItemValidFlags::BOTTOM|SvxBoxInfoItemValidFlags::LEFT|SvxBoxInfoItemValidFlags::RIGHT; + + m_xLeftFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) ); + m_xRightFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) ); + m_xTopFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) ); + m_xBottomFT->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) ); + m_xLeftMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::LEFT) ); + m_xRightMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::RIGHT) ); + m_xTopMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::TOP) ); + m_xBottomMF->set_sensitive( bool(nValid & SvxBoxInfoItemValidFlags::BOTTOM) ); + m_xSynchronizeCB->set_sensitive(m_xRightMF->get_sensitive() || m_xTopMF->get_sensitive() || + m_xBottomMF->get_sensitive() || m_xLeftMF->get_sensitive()); + } + UpdateRemoveAdjCellBorderCB( SAL_MAX_UINT16 ); +} + + +IMPL_LINK( SvxBorderTabPage, ModifyDistanceHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + if (&rField == m_xLeftMF.get()) + mbLeftModified = true; + else if (&rField == m_xRightMF.get()) + mbRightModified = true; + else if (&rField == m_xTopMF.get()) + mbTopModified = true; + else if (&rField == m_xBottomMF.get()) + mbBottomModified = true; + + if (mbSync) + { + const auto nVal = rField.get_value(FieldUnit::NONE); + if (&rField != m_xLeftMF.get()) + m_xLeftMF->set_value(nVal, FieldUnit::NONE); + if (&rField != m_xRightMF.get()) + m_xRightMF->set_value(nVal, FieldUnit::NONE); + if (&rField != m_xTopMF.get()) + m_xTopMF->set_value(nVal, FieldUnit::NONE); + if (&rField != m_xBottomMF.get()) + m_xBottomMF->set_value(nVal, FieldUnit::NONE); + } +} + +IMPL_LINK( SvxBorderTabPage, SyncHdl_Impl, weld::Toggleable&, rBox, void) +{ + mbSync = rBox.get_active(); +} + +IMPL_LINK( SvxBorderTabPage, RemoveAdjacentCellBorderHdl_Impl, weld::Toggleable&, rBox, void) +{ + mbRemoveAdjacentCellBorders = rBox.get_active(); +} + +void SvxBorderTabPage::UpdateRemoveAdjCellBorderCB( sal_uInt16 nPreset ) +{ + if( !bIsCalcDoc ) + return; + const SfxItemSet& rOldSet = GetItemSet(); + const SvxBoxInfoItem* pOldBoxInfoItem = GetOldItem( rOldSet, SID_ATTR_BORDER_INNER ); + const SvxBoxItem* pOldBoxItem = static_cast<const SvxBoxItem*>(GetOldItem( rOldSet, mnBoxSlot )); + if( !pOldBoxInfoItem || !pOldBoxItem ) + return; + std::pair<svx::FrameBorderType, SvxBoxInfoItemValidFlags> eTypes1[] = { + { svx::FrameBorderType::Top,SvxBoxInfoItemValidFlags::TOP }, + { svx::FrameBorderType::Bottom,SvxBoxInfoItemValidFlags::BOTTOM }, + { svx::FrameBorderType::Left,SvxBoxInfoItemValidFlags::LEFT }, + { svx::FrameBorderType::Right,SvxBoxInfoItemValidFlags::RIGHT }, + }; + SvxBoxItemLine const eTypes2[] = { + SvxBoxItemLine::TOP, + SvxBoxItemLine::BOTTOM, + SvxBoxItemLine::LEFT, + SvxBoxItemLine::RIGHT, + }; + + // Check if current selection involves deletion of at least one border + bool bBorderDeletionReq = false; + for ( size_t i=0; i < std::size( eTypes1 ); ++i ) + { + if( pOldBoxItem->GetLine( eTypes2[i] ) || !( pOldBoxInfoItem->IsValid( eTypes1[i].second ) ) ) + { + if( m_aFrameSel.GetFrameBorderState( eTypes1[i].first ) == svx::FrameBorderState::Hide ) + { + bBorderDeletionReq = true; + break; + } + } + } + + if( !bBorderDeletionReq && ( nPreset == IID_PRE_CELL_NONE || nPreset == IID_PRE_TABLE_NONE ) ) + bBorderDeletionReq = true; + + m_xRemoveAdjacentCellBordersCB->set_sensitive(bBorderDeletionReq); + + if( !bBorderDeletionReq ) + { + mbRemoveAdjacentCellBorders = false; + m_xRemoveAdjacentCellBordersCB->set_active(false); + } +} + +void SvxBorderTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pSWModeItem = aSet.GetItem<SfxUInt16Item>(SID_SWMODE_TYPE, false); + const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false); + if (pSWModeItem) + { + nSWMode = static_cast<SwBorderModes>(pSWModeItem->GetValue()); + // #i43593# + // show checkbox <m_xMergeWithNextCB> for format.paragraph + if ( nSWMode == SwBorderModes::PARA ) + { + m_xMergeWithNextCB->show(); + m_xPropertiesFrame->show(); + } + // show checkbox <m_xMergeAdjacentBordersCB> for format.paragraph + else if ( nSWMode == SwBorderModes::TABLE ) + { + m_xMergeAdjacentBordersCB->show(); + m_xPropertiesFrame->show(); + } + } + if (pFlagItem) + if ( ( pFlagItem->GetValue() & SVX_HIDESHADOWCTL ) == SVX_HIDESHADOWCTL ) + HideShadowControls(); +} + +void SvxBorderTabPage::SetTableMode() +{ + nSWMode = SwBorderModes::TABLE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/chardlg.cxx b/cui/source/tabpages/chardlg.cxx new file mode 100644 index 000000000..5bf0975bb --- /dev/null +++ b/cui/source/tabpages/chardlg.cxx @@ -0,0 +1,3230 @@ +/* -*- 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 . + */ + +#include <vcl/svapp.hxx> +#include <vcl/idle.hxx> +#include <svtools/ctrltool.hxx> +#include <sfx2/objsh.hxx> +#include <svx/svxids.hrc> +#include <svtools/unitconv.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <chardlg.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/contouritem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/escapementitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/cmapitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/flstitem.hxx> +#include <editeng/autokernitem.hxx> +#include <editeng/colritem.hxx> +#include <dialmgr.hxx> +#include <sfx2/htmlmode.hxx> +#include <cui/cuicharmap.hxx> +#include "chardlg.h" +#include <editeng/emphasismarkitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/twolinesitem.hxx> +#include <editeng/charhiddenitem.hxx> +#include <editeng/charscaleitem.hxx> +#include <editeng/charrotateitem.hxx> +#include <officecfg/Office/Common.hxx> +#include <strings.hrc> +#include <twolines.hrc> +#include <svl/intitem.hxx> +#include <svx/flagsdef.hxx> +#include <FontFeatures.hxx> +#include <FontFeaturesDialog.hxx> +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <o3tl/unit_conversion.hxx> +#include <o3tl/string_view.hxx> + +using namespace ::com::sun::star; + +// static ---------------------------------------------------------------- + +const WhichRangesContainer SvxCharNamePage::pNameRanges(svl::Items< + SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_WEIGHT, + SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_FONTHEIGHT, + SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_LANGUAGE, SID_ATTR_CHAR_LANGUAGE, + SID_ATTR_CHAR_CJK_FONT, SID_ATTR_CHAR_CJK_WEIGHT, + SID_ATTR_CHAR_CTL_FONT, SID_ATTR_CHAR_CTL_WEIGHT +>); + +const WhichRangesContainer SvxCharEffectsPage::pEffectsRanges(svl::Items< + SID_ATTR_CHAR_SHADOWED, SID_ATTR_CHAR_UNDERLINE, + SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_CASEMAP, + SID_ATTR_FLASH, SID_ATTR_FLASH, + SID_ATTR_CHAR_EMPHASISMARK, SID_ATTR_CHAR_EMPHASISMARK, + SID_ATTR_CHAR_RELIEF, SID_ATTR_CHAR_RELIEF, + SID_ATTR_CHAR_HIDDEN, SID_ATTR_CHAR_HIDDEN, + SID_ATTR_CHAR_OVERLINE, SID_ATTR_CHAR_OVERLINE +>); + +const WhichRangesContainer SvxCharPositionPage::pPositionRanges(svl::Items< + SID_ATTR_CHAR_KERNING, SID_ATTR_CHAR_KERNING, + SID_ATTR_CHAR_ESCAPEMENT, SID_ATTR_CHAR_ESCAPEMENT, + SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_AUTOKERN, + SID_ATTR_CHAR_ROTATED, SID_ATTR_CHAR_SCALEWIDTH, + SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE +>); + +const WhichRangesContainer SvxCharTwoLinesPage::pTwoLinesRanges(svl::Items< + SID_ATTR_CHAR_TWO_LINES, SID_ATTR_CHAR_TWO_LINES +>); + +// C-Function ------------------------------------------------------------ + +static bool StateToAttr( TriState aState ) +{ + return ( TRISTATE_TRUE == aState ); +} + +namespace +{ + void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ) + { + _rFont.SetPropr( nProp ); + _rFont.SetProprRel( nEscProp ); + _rFont.SetEscapement( nEsc ); + } +} + +inline SvxFont& SvxCharBasePage::GetPreviewFont() +{ + return m_aPreviewWin.GetFont(); +} + +inline SvxFont& SvxCharBasePage::GetPreviewCJKFont() +{ + return m_aPreviewWin.GetCJKFont(); +} + +inline SvxFont& SvxCharBasePage::GetPreviewCTLFont() +{ + return m_aPreviewWin.GetCTLFont(); +} + +SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OString& rID, const SfxItemSet& rItemset) + : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset) + , m_bPreviewBackgroundToCharacter( false ) +{ +} + +SvxCharBasePage::~SvxCharBasePage() +{ +} + +void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet) +{ + m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter); +} + +void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet ) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH ); + if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT) + { + const SvxCharScaleWidthItem &rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) ); + m_aPreviewWin.SetFontWidthScale(rItem.GetValue()); + } +} + +void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ) +{ + setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc); + setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc); + setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc); + m_aPreviewWin.Invalidate(); +} + + +// SvxCharNamePage_Impl -------------------------------------------------- + +struct SvxCharNamePage_Impl +{ + Idle m_aUpdateIdle { "cui SvxCharNamePage_Impl m_aUpdateIdle" }; + OUString m_aNoStyleText; + std::unique_ptr<FontList> m_pFontList; + int m_nExtraEntryPos; + bool m_bInSearchMode; + + SvxCharNamePage_Impl() + : m_nExtraEntryPos(std::numeric_limits<int>::max()) + , m_bInSearchMode(false) + + { + m_aUpdateIdle.SetPriority( TaskPriority::LOWEST ); + } +}; + +// class SvxCharNamePage ------------------------------------------------- + +SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/charnamepage.ui", "CharNamePage", rInSet) + , m_pImpl(new SvxCharNamePage_Impl) + // Western + , m_xWestern(m_xBuilder->weld_notebook("nbWestern")) + , m_xWestFontNameFT(m_xBuilder->weld_label("lbWestFontname")) + , m_xWestFontStyleFT(m_xBuilder->weld_label("lbWestStyle")) + , m_xWestFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbWestStyle"))) + , m_xWestFontSizeFT(m_xBuilder->weld_label("lbWestSize")) + , m_xWestFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbWestSize"))) + , m_xWestFontLanguageFT(m_xBuilder->weld_label("lbWestLanguage")) + , m_xWestFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbWestLanguage"))) + , m_xWestFontFeaturesButton(m_xBuilder->weld_button("btnWestFeatures")) + , m_xWestFontTypeFT(m_xBuilder->weld_label("lbWestFontinfo")) + , m_xCJK_CTL(m_xBuilder->weld_notebook("nbCJKCTL")) + // CJK + , m_xEastFontNameFT(m_xBuilder->weld_label("lbCJKFontname")) + , m_xEastFontStyleFT(m_xBuilder->weld_label("lbCJKStyle")) + , m_xEastFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbCJKStyle"))) + , m_xEastFontSizeFT(m_xBuilder->weld_label("lbCJKSize")) + , m_xEastFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbCJKSize"))) + , m_xEastFontLanguageFT(m_xBuilder->weld_label("lbCJKLanguage")) + , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbCJKLanguage"))) + , m_xEastFontFeaturesButton(m_xBuilder->weld_button("btnCJKFeatures")) + , m_xEastFontTypeFT(m_xBuilder->weld_label("lbCJKFontinfo")) + // CTL + , m_xCTLFontNameFT(m_xBuilder->weld_label("lbCTLFontname")) + // tree + , m_xCTLFontStyleFT(m_xBuilder->weld_label("lbCTLStyle")) + , m_xCTLFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box("cbCTLStyle"))) + , m_xCTLFontSizeFT(m_xBuilder->weld_label("lbCTLSize")) + , m_xCTLFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box("cbCTLSize"))) + , m_xCTLFontLanguageFT(m_xBuilder->weld_label("lbCTLLanguage")) + , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("cbCTLLanguage"))) + , m_xCTLFontFeaturesButton(m_xBuilder->weld_button("btnCTLFeatures")) + , m_xCTLFontTypeFT(m_xBuilder->weld_label("lbCTLFontinfo")) + + , m_xVDev(*Application::GetDefaultDevice(), DeviceFormat::DEFAULT, DeviceFormat::DEFAULT) +{ + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + m_pImpl->m_aNoStyleText = CuiResId( RID_CUISTR_CHARNAME_NOSTYLE ); + + std::unique_ptr<weld::EntryTreeView> xWestFontName = m_xBuilder->weld_entry_tree_view("gdWestern", "edWestFontName", "trWestFontName"); + std::unique_ptr<weld::EntryTreeView> xCJKFontName = m_xBuilder->weld_entry_tree_view("gdCJK", "edCJKFontName", "trCJKFontName"); + std::unique_ptr<weld::EntryTreeView> xCTLFontName = m_xBuilder->weld_entry_tree_view("gdCTL", "edCTLFontName", "trCTLFontName"); + + // 7 lines in the treeview + xWestFontName->set_height_request_by_rows(7); + xCJKFontName->set_height_request_by_rows(7); + xCTLFontName->set_height_request_by_rows(7); + + m_xWestFontNameLB = std::move(xWestFontName); + m_xEastFontNameLB = std::move(xCJKFontName); + m_xCTLFontNameLB = std::move(xCTLFontName); + + SvtCTLOptions aCTLLanguageOptions; + bool bShowCJK = SvtCJKOptions::IsCJKFontEnabled(); + bool bShowCTL = aCTLLanguageOptions.IsCTLFontEnabled(); + bool bShowNonWestern = bShowCJK || bShowCTL; + if (!bShowNonWestern) + { + m_xCJK_CTL->hide(); + m_xWestern->set_show_tabs(false); //hide single tab in case of Western only + } + else if (!bShowCJK) m_xCJK_CTL->remove_page("nbCJK"); + else if (!bShowCTL) m_xCJK_CTL->remove_page("nbCTL"); + + + //In MacOSX the standard dialogs name font-name, font-style as + //Family, Typeface + //In GNOME the standard dialogs name font-name, font-style as + //Family, Style + //In Windows the standard dialogs name font-name, font-style as + //Font, Style +#ifdef _WIN32 + OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FONT)); +#else + OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FAMILY)); +#endif + m_xWestFontNameFT->set_label(sFontFamilyString); + m_xCTLFontNameFT->set_label(sFontFamilyString); + m_xEastFontNameFT->set_label(sFontFamilyString); + +#ifdef MACOSX + OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_TYPEFACE)); +#else + OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_STYLE)); +#endif + m_xWestFontStyleFT->set_label(sFontStyleString); + m_xEastFontStyleFT->set_label(sFontStyleString); + m_xCTLFontStyleFT->set_label(sFontStyleString); + + m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN); + m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN); + m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX); + int nVisibleChars = 15; + // read-only combobox / HasEntry asserts on set_width_char() + m_xWestFontLanguageLB->set_width_chars(nVisibleChars); + m_xEastFontLanguageLB->set_width_chars(nVisibleChars); + m_xCTLFontLanguageLB->set_width_chars(nVisibleChars); + + Initialize(); +} + +SvxCharNamePage::~SvxCharNamePage() +{ + m_pImpl.reset(); + m_xCTLFontStyleLB.reset(); + m_xEastFontLanguageLB.reset(); + m_xWestFontStyleLB.reset(); + m_xCTLFontSizeLB.reset(); + m_xEastFontSizeLB.reset(); + m_xWestFontSizeLB.reset(); + m_xWestFontLanguageLB.reset(); + m_xPreviewWin.reset(); + m_xCTLFontLanguageLB.reset(); + m_xEastFontLanguageLB.reset(); +} + +void SvxCharNamePage::Initialize() +{ + // to handle the changes of the other pages + SetExchangeSupport(); + + Link<weld::ComboBox&,void> aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl); + m_xWestFontNameLB->connect_changed(aLink); + m_xWestFontStyleLB->connect_changed(aLink); + m_xWestFontSizeLB->connect_changed(aLink); + m_xWestFontLanguageLB->connect_changed(aLink); + + m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked)); + + m_xEastFontNameLB->connect_changed(aLink); + m_xEastFontStyleLB->connect_changed(aLink); + m_xEastFontSizeLB->connect_changed(aLink); + m_xEastFontLanguageLB->connect_changed(aLink); + m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked)); + + m_xCTLFontNameLB->connect_changed(aLink); + m_xCTLFontStyleLB->connect_changed(aLink); + m_xCTLFontSizeLB->connect_changed(aLink); + m_xCTLFontLanguageLB->connect_changed(aLink); + m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked)); + + m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) ); +} + +const FontList* SvxCharNamePage::GetFontList() const +{ + if ( !m_pImpl->m_pFontList ) + { + /* #110771# SvxFontListItem::GetFontList can return NULL */ + if (SfxObjectShell* pDocSh = SfxObjectShell::Current()) + { + const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ); + if ( pItem != nullptr ) + { + DBG_ASSERT(nullptr != static_cast<const SvxFontListItem*>(pItem)->GetFontList(), + "Where is the font list?"); + m_pImpl->m_pFontList = static_cast<const SvxFontListItem*>(pItem )->GetFontList()->Clone(); + } + } + if(!m_pImpl->m_pFontList) + { + m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() )); + } + } + + return m_pImpl->m_pFontList.get(); +} + + +namespace +{ + FontMetric calcFontMetrics( SvxFont& _rFont, + SvxCharNamePage const * _pPage, + const weld::ComboBox* _pFontNameLB, + const FontStyleBox* _pFontStyleLB, + const FontSizeBox* _pFontSizeLB, + const SvxLanguageBox* _pLanguageLB, + const FontList* _pFontList, + sal_uInt16 _nFontWhich, + sal_uInt16 _nFontHeightWhich) + { + Size aSize = _rFont.GetFontSize(); + aSize.setWidth( 0 ); + FontMetric aFontMetrics; + OUString sFontName(_pFontNameLB->get_active_text()); + bool bFontAvailable = _pFontList->IsAvailable( sFontName ); + if (bFontAvailable || _pFontNameLB->get_value_changed_from_saved()) + aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text()); + else + { + //get the font from itemset + SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich ); + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&( _pPage->GetItemSet().Get( _nFontWhich ) )); + aFontMetrics.SetFamilyName(pFontItem->GetFamilyName()); + aFontMetrics.SetStyleName(pFontItem->GetStyleName()); + aFontMetrics.SetFamily(pFontItem->GetFamily()); + aFontMetrics.SetPitch(pFontItem->GetPitch()); + aFontMetrics.SetCharSet(pFontItem->GetCharSet()); + } + } + if ( _pFontSizeLB->IsRelative() ) + { + DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" ); + const SvxFontHeightItem& rOldItem = static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich )); + + // old value, scaled + tools::Long nHeight; + if ( _pFontSizeLB->IsPtRelative() ) + nHeight = rOldItem.GetHeight() + + o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt, + o3tl::Length::twip) / 10; + else + nHeight = static_cast<tools::Long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100); + + // conversion twips for the example-window + aSize.setHeight( + ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) ); + } + else if ( !_pFontSizeLB->get_active_text().isEmpty() ) + aSize.setHeight(o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt, + o3tl::Length::twip) / 10); + else + aSize.setHeight( 200 ); // default 10pt + aFontMetrics.SetFontSize( aSize ); + + _rFont.SetLanguage(_pLanguageLB->get_active_id()); + + _rFont.SetFamily( aFontMetrics.GetFamilyType() ); + _rFont.SetFamilyName( aFontMetrics.GetFamilyName() ); + _rFont.SetStyleName( aFontMetrics.GetStyleName() ); + _rFont.SetPitch( aFontMetrics.GetPitch() ); + _rFont.SetCharSet( aFontMetrics.GetCharSet() ); + _rFont.SetWeight( aFontMetrics.GetWeight() ); + _rFont.SetItalic( aFontMetrics.GetItalic() ); + _rFont.SetFontSize( aFontMetrics.GetFontSize() ); + + return aFontMetrics; + } +} + + +void SvxCharNamePage::UpdatePreview_Impl() +{ + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + // Font + const FontList* pFontList = GetFontList(); + + FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(), + m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(), + pFontList, GetWhich(SID_ATTR_CHAR_FONT), + GetWhich(SID_ATTR_CHAR_FONTHEIGHT)); + + m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric)); + + FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(), + m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(), + pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT), + GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT)); + + m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric)); + + FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont, + this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(), + m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT), + GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT)); + + m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric)); + + m_aPreviewWin.Invalidate(); +} +void SvxCharNamePage::EnableFeatureButton(const weld::Widget& rNameBox) +{ + OUString sFontName; + weld::Button* pButton= nullptr; + if (m_xWestFontNameLB.get() == &rNameBox) + { + sFontName = m_xWestFontNameLB->get_active_text(); + pButton= m_xWestFontFeaturesButton.get(); + } + else if (m_xEastFontNameLB.get() == &rNameBox) + { + sFontName = m_xEastFontNameLB->get_active_text(); + pButton=m_xEastFontFeaturesButton.get(); + } + else if (m_xCTLFontNameLB.get() == &rNameBox) + { + sFontName = m_xCTLFontNameLB->get_active_text(); + pButton= m_xCTLFontFeaturesButton.get(); + } + else + { + SAL_WARN( "cui.tabpages", "invalid font name box" ); + return; + } + + bool bEnable = !getFontFeatureList(sFontName, *m_xVDev).empty(); + + pButton->set_sensitive(bEnable); +} + +void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox) +{ + const FontList* pFontList = GetFontList(); + DBG_ASSERT( pFontList, "no fontlist" ); + + FontStyleBox* pStyleBox = nullptr; + OUString sFontName; + + if (m_xWestFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xWestFontStyleLB.get(); + sFontName = m_xWestFontNameLB->get_active_text(); + } + else if (m_xEastFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xEastFontStyleLB.get(); + sFontName = m_xEastFontStyleLB->get_active_text(); + } + else if (m_xCTLFontNameLB.get() == &rNameBox) + { + pStyleBox = m_xCTLFontStyleLB.get(); + sFontName = m_xCTLFontNameLB->get_active_text(); + } + else + { + SAL_WARN( "cui.tabpages", "invalid font name box" ); + return; + } + + pStyleBox->Fill(sFontName, pFontList); + + if ( !m_pImpl->m_bInSearchMode ) + return; + + // additional entries for the search: + // "not bold" and "not italic" + OUString aEntry = m_pImpl->m_aNoStyleText; + const char sS[] = "%1"; + aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() ); + m_pImpl->m_nExtraEntryPos = pStyleBox->get_count(); + pStyleBox->append_text( aEntry ); + aEntry = m_pImpl->m_aNoStyleText; + aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() ); + pStyleBox->append_text(aEntry); +} + +void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox) +{ + const FontList* pFontList = GetFontList(); + DBG_ASSERT( pFontList, "no fontlist" ); + + FontSizeBox* pSizeBox = nullptr; + + if (m_xWestFontNameLB.get() == &rNameBox) + { + pSizeBox = m_xWestFontSizeLB.get(); + } + else if (m_xEastFontNameLB.get() == &rNameBox) + { + pSizeBox = m_xEastFontSizeLB.get(); + } + else if (m_xCTLFontNameLB.get() == &rNameBox) + { + pSizeBox = m_xCTLFontSizeLB.get(); + } + else + { + SAL_WARN( "cui.tabpages", "invalid font name box" ); + return; + } + + pSizeBox->Fill( pFontList ); +} + +namespace +{ + void FillFontNames(weld::ComboBox& rBox, const FontList& rList) + { + // insert fonts + sal_uInt16 nFontCount = rList.GetFontNameCount(); + std::vector<weld::ComboBoxEntry> aVector; + aVector.reserve(nFontCount); + for (sal_uInt16 i = 0; i < nFontCount; ++i) + { + const FontMetric& rFontMetric = rList.GetFontName(i); + aVector.emplace_back(rFontMetric.GetFamilyName()); + } + rBox.insert_vector(aVector, false); + } +} + +void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp ) +{ + weld::ComboBox* pNameBox = nullptr; + weld::Label* pStyleLabel = nullptr; + FontStyleBox* pStyleBox = nullptr; + weld::Label* pSizeLabel = nullptr; + FontSizeBox* pSizeBox = nullptr; + weld::Label* pLangFT = nullptr; + SvxLanguageBox* pLangBox = nullptr; + sal_uInt16 nWhich = 0; + + switch ( eLangGrp ) + { + case Western : + pNameBox = m_xWestFontNameLB.get(); + pStyleLabel = m_xWestFontStyleFT.get(); + pStyleBox = m_xWestFontStyleLB.get(); + pSizeLabel = m_xWestFontSizeFT.get(); + pSizeBox = m_xWestFontSizeLB.get(); + pLangFT = m_xWestFontLanguageFT.get(); + pLangBox = m_xWestFontLanguageLB.get(); + nWhich = GetWhich( SID_ATTR_CHAR_FONT ); + break; + + case Asian : + pNameBox = m_xEastFontNameLB.get(); + pStyleLabel = m_xEastFontStyleFT.get(); + pStyleBox = m_xEastFontStyleLB.get(); + pSizeLabel = m_xEastFontSizeFT.get(); + pSizeBox = m_xEastFontSizeLB.get(); + pLangFT = m_xEastFontLanguageFT.get(); + pLangBox = m_xEastFontLanguageLB.get(); + nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT ); + break; + + case Ctl : + pNameBox = m_xCTLFontNameLB.get(); + pStyleLabel = m_xCTLFontStyleFT.get(); + pStyleBox = m_xCTLFontStyleLB.get(); + pSizeLabel = m_xCTLFontSizeFT.get(); + pSizeBox = m_xCTLFontSizeLB.get(); + pLangFT = m_xCTLFontLanguageFT.get(); + pLangBox = m_xCTLFontLanguageLB.get(); + nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT ); + break; + } + + const FontList* pFontList = GetFontList(); + FillFontNames(*pNameBox, *pFontList); + + const SvxFontItem* pFontItem = nullptr; + SfxItemState eState = rSet.GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + pFontItem = static_cast<const SvxFontItem*>(&( rSet.Get( nWhich ) )); + const OUString &rName = pFontItem->GetFamilyName(); + int nIndex = pNameBox->find_text(rName); + pNameBox->set_active(nIndex); + // tdf#122992 if it didn't exist in the list, set the entry text to it anyway + if (nIndex == -1) + pNameBox->set_entry_text(rName); + } + else + { + pNameBox->set_active_text( OUString() ); + } + + FillStyleBox_Impl(*pNameBox); + + bool bStyle = false; + bool bStyleAvailable = true; + FontItalic eItalic = ITALIC_NONE; + FontWeight eWeight = WEIGHT_NORMAL; + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break; + } + eState = rSet.GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>(rSet.Get( nWhich )); + eItalic = rItem.GetValue(); + bStyle = true; + } + bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE); + + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break; + } + eState = rSet.GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>(rSet.Get( nWhich )); + eWeight = rItem.GetValue(); + } + else + bStyle = false; + bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::DONTCARE); + + // currently chosen font + if ( bStyle && pFontItem ) + { + FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic ); + pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) ); + } + else if ( !m_pImpl->m_bInSearchMode || !bStyle ) + { + pStyleBox->set_active_text( OUString() ); + } + else if ( bStyle ) + { + FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic ); + pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) ); + } + if (!bStyleAvailable) + { + pStyleBox->set_sensitive(false); + pStyleLabel->set_sensitive(false); + } + + FillSizeBox_Impl(*pNameBox); + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break; + } + eState = rSet.GetItemState( nWhich ); + + if ( pSizeBox->IsRelativeMode() ) + { + MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich ); + const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich )); + + if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() ) + { + bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit(); + pSizeBox->SetPtRelative( bPtRel ); + pSizeBox->set_value( bPtRel ? static_cast<short>(rItem.GetProp()) * 10 : rItem.GetProp() ); + } + else + { + pSizeBox->SetRelative(false); + pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) ); + } + } + else if ( eState >= SfxItemState::DEFAULT ) + { + MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich ); + const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich )); + pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) ); + } + else + { + pSizeBox->set_active_or_entry_text(OUString()); + if ( eState <= SfxItemState::DISABLED ) + { + pSizeBox->set_sensitive(false); + pSizeLabel->set_sensitive(false); + } + } + + switch ( eLangGrp ) + { + case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break; + case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break; + case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break; + } + pLangBox->set_active(-1); + eState = rSet.GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + pLangFT->hide(); + pLangBox->hide(); + break; + + case SfxItemState::DISABLED: + pLangFT->set_sensitive(false); + pLangBox->set_sensitive(false); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxLanguageItem& rItem = static_cast<const SvxLanguageItem&>(rSet.Get( nWhich )); + LanguageType eLangType = rItem.GetValue(); + DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" ); + if (eLangType != LANGUAGE_DONTKNOW) + pLangBox->set_active_id(eLangType); + break; + } + case SfxItemState::DONTCARE: + break; + } + + OUString sMapText(pFontList->GetFontMapText( + pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text()))); + + switch (eLangGrp) + { + case Western: + m_xWestFontTypeFT->set_label(sMapText); + break; + case Asian: + m_xEastFontTypeFT->set_label(sMapText); + break; + case Ctl: + m_xCTLFontTypeFT->set_label(sMapText); + break; + } + + EnableFeatureButton(*pNameBox); + + // save these settings + pNameBox->save_value(); + pStyleBox->save_value(); + pSizeBox->save_value(); + pLangBox->save_active_id(); +} + +bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp ) +{ + bool bModified = false; + + weld::ComboBox* pNameBox = nullptr; + FontStyleBox* pStyleBox = nullptr; + FontSizeBox* pSizeBox = nullptr; + SvxLanguageBox* pLangBox = nullptr; + sal_uInt16 nWhich = 0; + sal_uInt16 nSlot = 0; + + switch ( eLangGrp ) + { + case Western : + pNameBox = m_xWestFontNameLB.get(); + pStyleBox = m_xWestFontStyleLB.get(); + pSizeBox = m_xWestFontSizeLB.get(); + pLangBox = m_xWestFontLanguageLB.get(); + nSlot = SID_ATTR_CHAR_FONT; + break; + + case Asian : + pNameBox = m_xEastFontNameLB.get(); + pStyleBox = m_xEastFontStyleLB.get(); + pSizeBox = m_xEastFontSizeLB.get(); + pLangBox = m_xEastFontLanguageLB.get(); + nSlot = SID_ATTR_CHAR_CJK_FONT; + break; + + case Ctl : + pNameBox = m_xCTLFontNameLB.get(); + pStyleBox = m_xCTLFontStyleLB.get(); + pSizeBox = m_xCTLFontSizeLB.get(); + pLangBox = m_xCTLFontLanguageLB.get(); + nSlot = SID_ATTR_CHAR_CTL_FONT; + break; + } + + nWhich = GetWhich( nSlot ); + const SfxPoolItem* pItem = nullptr; + const SfxItemSet& rOldSet = GetItemSet(); + const SfxPoolItem* pOld = nullptr; + + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + + bool bChanged = true; + const OUString& rFontName = pNameBox->get_active_text(); + const FontList* pFontList = GetFontList(); + OUString aStyleBoxText = pStyleBox->get_active_text(); + int nEntryPos = pStyleBox->find_text(aStyleBoxText); + if (nEntryPos >= m_pImpl->m_nExtraEntryPos) + aStyleBoxText.clear(); + FontMetric aInfo( pFontList->Get( rFontName, aStyleBoxText ) ); + SvxFontItem aFontItem( aInfo.GetFamilyType(), aInfo.GetFamilyName(), aInfo.GetStyleName(), + aInfo.GetPitch(), aInfo.GetCharSet(), nWhich ); + pOld = GetOldItem( rSet, nSlot ); + + if ( pOld ) + { + const SvxFontItem& rItem = *static_cast<const SvxFontItem*>(pOld); + + if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() ) + bChanged = false; + } + + if ( !bChanged ) + bChanged = pNameBox->get_saved_value().isEmpty(); + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + static_cast<const SvxFontItem*>(pItem)->GetFamilyName() != aFontItem.GetFamilyName() ) + bChanged = true; + + if ( bChanged && !rFontName.isEmpty() ) + { + rSet.Put( aFontItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.ClearItem( nWhich ); + + + bChanged = true; + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break; + } + nWhich = GetWhich( nSlot ); + FontWeight eWeight = aInfo.GetWeight(); + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + eWeight = WEIGHT_NORMAL; + SvxWeightItem aWeightItem( eWeight, nWhich ); + pOld = GetOldItem( rSet, nSlot ); + + if ( pOld ) + { + const SvxWeightItem& rItem = *static_cast<const SvxWeightItem*>(pOld); + + if ( rItem.GetValue() == aWeightItem.GetValue() ) + bChanged = false; + } + + if ( !bChanged ) + { + bChanged = pStyleBox->get_saved_value().isEmpty(); + + if ( m_pImpl->m_bInSearchMode && bChanged && + aInfo.GetWeight() == WEIGHT_NORMAL && aInfo.GetItalic() != ITALIC_NONE ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + static_cast<const SvxWeightItem*>(pItem)->GetValue() != aWeightItem.GetValue() ) + bChanged = true; + + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos ); + + OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty + + if ( bChanged && !aText.isEmpty() ) + { + rSet.Put( aWeightItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + bChanged = true; + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_POSTURE; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break; + } + nWhich = GetWhich( nSlot ); + FontItalic eItalic = aInfo.GetItalic(); + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + eItalic = ITALIC_NONE; + SvxPostureItem aPostureItem( eItalic, nWhich ); + pOld = GetOldItem( rSet, nSlot ); + + if ( pOld ) + { + const SvxPostureItem& rItem = *static_cast<const SvxPostureItem*>(pOld); + + if ( rItem.GetValue() == aPostureItem.GetValue() ) + bChanged = false; + } + + if ( !bChanged ) + { + bChanged = pStyleBox->get_saved_value().isEmpty(); + + if ( m_pImpl->m_bInSearchMode && bChanged && + aInfo.GetItalic() == ITALIC_NONE && aInfo.GetWeight() != WEIGHT_NORMAL ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + static_cast<const SvxPostureItem*>(pItem)->GetValue() != aPostureItem.GetValue() ) + bChanged = true; + + if ( nEntryPos >= m_pImpl->m_nExtraEntryPos ) + bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) ); + + if ( bChanged && !aText.isEmpty() ) + { + rSet.Put( aPostureItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + // FontSize + tools::Long nSize = pSizeBox->get_value(); + + if ( pSizeBox->get_active_text().isEmpty() ) // GetValue() returns the min-value + nSize = 0; + tools::Long nSavedSize = pSizeBox->get_saved_value(); + const bool bRel = pSizeBox->IsRelative(); + + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break; + } + nWhich = GetWhich( nSlot ); + const SvxFontHeightItem* pOldHeight = static_cast<const SvxFontHeightItem*>(GetOldItem( rSet, nSlot )); + bChanged = ( nSize != nSavedSize ); + + if ( !bChanged && pExampleSet && + pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET ) + { + float fSize = static_cast<float>(nSize) / 10; + tools::Long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) ); + if ( static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != static_cast<sal_uInt32>(nVal) ) + bChanged = true; + } + + if ( bChanged || !pOldHeight || + bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) ) + { + MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich ); + if ( pSizeBox->IsRelative() ) + { + DBG_ASSERT( GetItemSet().GetParent(), "No parent set" ); + const SvxFontHeightItem& rOldItem = + static_cast<const SvxFontHeightItem&>(GetItemSet().GetParent()->Get( nWhich )); + + SvxFontHeightItem aHeight( 240, 100, nWhich ); + if ( pSizeBox->IsPtRelative() ) + aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>( nSize / 10 ), MapUnit::MapPoint, eUnit ); + else + aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>(nSize) ); + rSet.Put( aHeight ); + } + else + { + float fSize = static_cast<float>(nSize) / 10; + rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) ); + } + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + bChanged = true; + switch ( eLangGrp ) + { + case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break; + case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break; + case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break; + } + nWhich = GetWhich( nSlot ); + pOld = GetOldItem( rSet, nSlot ); + + // For language list boxes acting as ComboBox, check for, add and select an + // edited entry. + if (pLangBox == m_xWestFontLanguageLB.get()) + { + switch (pLangBox->GetEditedAndValid()) + { + case SvxLanguageBox::EditedAndValid::No: + ; // nothing to do + break; + case SvxLanguageBox::EditedAndValid::Valid: + { + const int nPos = pLangBox->SaveEditedAsEntry(); + if (nPos != -1) + pLangBox->set_active(nPos); + } + break; + case SvxLanguageBox::EditedAndValid::Invalid: + pLangBox->set_active_id(pLangBox->get_saved_active_id()); + break; + } + } + + int nLangPos = pLangBox->get_active(); + LanguageType eLangType = pLangBox->get_active_id(); + + if (pOld) + { + const SvxLanguageItem& rItem = *static_cast<const SvxLanguageItem*>(pOld); + if (nLangPos == -1 || eLangType == rItem.GetValue()) + bChanged = false; + } + + if (!bChanged) + bChanged = pLangBox->get_active_id_changed_from_saved(); + + if (bChanged && nLangPos != -1) + { + rSet.Put(SvxLanguageItem(eLangType, nWhich)); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + return bModified; +} + +IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void) +{ + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void) +{ + FontModifyHdl_Impl(rBox); +} + +IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void) +{ + OUString sFontName; + weld::ComboBox* pNameBox = nullptr; + + if (&rButton == m_xWestFontFeaturesButton.get()) + { + pNameBox = m_xWestFontNameLB.get(); + sFontName = GetPreviewFont().GetFamilyName(); + } + else if (&rButton == m_xEastFontFeaturesButton.get()) + { + pNameBox = m_xEastFontNameLB.get(); + sFontName = GetPreviewCJKFont().GetFamilyName(); + } + else if (&rButton == m_xCTLFontFeaturesButton.get()) + { + pNameBox = m_xCTLFontNameLB.get(); + sFontName = GetPreviewCTLFont().GetFamilyName(); + } + + if (!sFontName.isEmpty() && pNameBox) + { + cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName); + if (aDialog.run() == RET_OK) + { + pNameBox->set_entry_text(aDialog.getResultFontName()); + UpdatePreview_Impl(); + } + } +} + +void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox) +{ + m_pImpl->m_aUpdateIdle.Start(); + + if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox) + { + FillStyleBox_Impl(rNameBox); + FillSizeBox_Impl(rNameBox); + EnableFeatureButton(rNameBox); + } +} + +void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet ) +{ + SvxCharBasePage::ActivatePage( rSet ); + + UpdatePreview_Impl(); // instead of asynchronous calling in ctor +} + +DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxCharNamePage>(pPage, pController, *rSet ); +} + +void SvxCharNamePage::Reset( const SfxItemSet* rSet ) +{ + Reset_Impl( *rSet, Western ); + Reset_Impl( *rSet, Asian ); + Reset_Impl( *rSet, Ctl ); + + SetPrevFontWidthScale( *rSet ); + UpdatePreview_Impl(); +} + +void SvxCharNamePage::ChangesApplied() +{ + m_xWestFontNameLB->save_value(); + m_xWestFontStyleLB->save_value(); + m_xWestFontSizeLB->save_value(); + m_xWestFontLanguageLB->save_active_id(); + m_xEastFontNameLB->save_value(); + m_xEastFontStyleLB->save_value(); + m_xEastFontSizeLB->save_value(); + m_xEastFontLanguageLB->save_active_id(); + m_xCTLFontNameLB->save_value(); + m_xCTLFontStyleLB->save_value(); + m_xCTLFontSizeLB->save_value(); + m_xCTLFontLanguageLB->save_active_id(); +} + +bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = FillItemSet_Impl( *rSet, Western ); + bModified |= FillItemSet_Impl( *rSet, Asian ); + bModified |= FillItemSet_Impl( *rSet, Ctl ); + return bModified; +} + +void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem ) +{ + m_pImpl->m_pFontList = rItem.GetFontList()->Clone(); +} + +namespace +{ + void enableRelativeMode( SvxCharNamePage const * _pPage, FontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich ) + { + _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5 + + const SvxFontHeightItem& rHeightItem = + static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich )); + MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich ); + short nCurHeight = + static_cast< short >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 ); + + // based on the current height: + // - negative until minimum of 2 pt + // - positive until maximum of 999 pt + _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) ); + } +} + +void SvxCharNamePage::EnableRelativeMode() +{ + DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" ); + enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT )); + enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT )); + enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT )); +} + +void SvxCharNamePage::EnableSearchMode() +{ + m_pImpl->m_bInSearchMode = true; +} + +void SvxCharNamePage::DisableControls( sal_uInt16 nDisable ) +{ + if ( DISABLE_HIDE_LANGUAGE & nDisable ) + { + if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide(); + if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide(); + if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide(); + if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide(); + if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide(); + if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide(); + } +} + +void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxFontListItem* pFontListItem = aSet.GetItem<SvxFontListItem>(SID_ATTR_CHAR_FONTLIST, false); + const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false); + const SfxUInt16Item* pDisableItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false); + if (pFontListItem) + SetFontList(*pFontListItem); + + if (pFlagItem) + { + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE ) + EnableRelativeMode(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + } + if (pDisableItem) + DisableControls(pDisableItem->GetValue()); +} +// class SvxCharEffectsPage ---------------------------------------------- + +SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/effectspage.ui", "EffectsPage", rInSet) + , m_bOrigFontColor(false) + , m_bNewFontColor(false) + , m_bEnableNoneFontColor(false) + , m_xFontColorFT(m_xBuilder->weld_label("fontcolorft")) + , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button("fontcolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xFontTransparencyFT(m_xBuilder->weld_label("fonttransparencyft")) + , m_xFontTransparencyMtr( + m_xBuilder->weld_metric_spin_button("fonttransparencymtr", FieldUnit::PERCENT)) + , m_xEffectsFT(m_xBuilder->weld_label("effectsft")) + , m_xEffectsLB(m_xBuilder->weld_combo_box("effectslb")) + , m_xReliefFT(m_xBuilder->weld_label("reliefft")) + , m_xReliefLB(m_xBuilder->weld_combo_box("relieflb")) + , m_xOutlineBtn(m_xBuilder->weld_check_button("outlinecb")) + , m_xShadowBtn(m_xBuilder->weld_check_button("shadowcb")) + , m_xHiddenBtn(m_xBuilder->weld_check_button("hiddencb")) + , m_xOverlineLB(m_xBuilder->weld_combo_box("overlinelb")) + , m_xOverlineColorFT(m_xBuilder->weld_label("overlinecolorft")) + , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("overlinecolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xStrikeoutLB(m_xBuilder->weld_combo_box("strikeoutlb")) + , m_xUnderlineLB(m_xBuilder->weld_combo_box("underlinelb")) + , m_xUnderlineColorFT(m_xBuilder->weld_label("underlinecolorft")) + , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button("underlinecolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xIndividualWordsBtn(m_xBuilder->weld_check_button("individualwordscb")) + , m_xEmphasisFT(m_xBuilder->weld_label("emphasisft")) + , m_xEmphasisLB(m_xBuilder->weld_combo_box("emphasislb")) + , m_xPositionFT(m_xBuilder->weld_label("positionft")) + , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb")) + , m_xA11yWarningFT(m_xBuilder->weld_label("a11ywarning")) +{ + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR); + Initialize(); +} + +void SvxCharEffectsPage::EnableNoneFontColor() +{ + m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true); + m_bEnableNoneFontColor = true; +} + +SvxCharEffectsPage::~SvxCharEffectsPage() +{ + m_xUnderlineColorLB.reset(); + m_xOverlineColorLB.reset(); + m_xFontTransparencyMtr.reset(); + m_xFontColorLB.reset(); +} + +void SvxCharEffectsPage::Initialize() +{ + // to handle the changes of the other pages + SetExchangeSupport(); + + // HTML-Mode + const SfxUInt16Item* pHtmlModeItem = GetItemSet().GetItemIfSet( SID_HTML_MODE, false ); + if ( !pHtmlModeItem) + { + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + pHtmlModeItem = pShell->GetItem( SID_HTML_MODE ); + } + if (pHtmlModeItem) + { + m_nHtmlMode = pHtmlModeItem->GetValue(); + if ( ( m_nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON ) + { + //!!! hide some controls please + } + } + + m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl)); + m_xFontTransparencyMtr->connect_value_changed( + LINK(this, SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl)); + + // handler + Link<weld::ComboBox&,void> aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl ); + m_xUnderlineLB->connect_changed( aLink ); + m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl)); + m_xOverlineLB->connect_changed( aLink ); + m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl)); + m_xStrikeoutLB->connect_changed( aLink ); + m_xEmphasisLB->connect_changed( aLink ); + m_xPositionLB->connect_changed( aLink ); + m_xEffectsLB->connect_changed( aLink ); + m_xReliefLB->connect_changed( aLink ); + + m_xUnderlineLB->set_active( 0 ); + m_xOverlineLB->set_active( 0 ); + m_xStrikeoutLB->set_active( 0 ); + m_xEmphasisLB->set_active( 0 ); + m_xPositionLB->set_active( 0 ); + SelectHdl_Impl(nullptr); + SelectHdl_Impl(m_xEmphasisLB.get()); + + m_xEffectsLB->set_active( 0 ); + + m_xHiddenBtn->connect_toggled(LINK(this, SvxCharEffectsPage, HiddenBtnClickHdl)); + m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl)); + m_xOutlineBtn->connect_toggled(LINK(this, SvxCharEffectsPage, OutlineBtnClickHdl)); + m_xShadowBtn->connect_toggled(LINK(this, SvxCharEffectsPage, ShadowBtnClickHdl)); + + if ( !SvtCJKOptions::IsAsianTypographyEnabled() ) + { + m_xEmphasisFT->hide(); + m_xEmphasisLB->hide(); + m_xPositionFT->hide(); + m_xPositionLB->hide(); + } + + m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get()); +} + +void SvxCharEffectsPage::UpdatePreview_Impl() +{ + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor(); + rFont.SetColor(rSelectedColor); + rCJKFont.SetColor(rSelectedColor); + rCTLFont.SetColor(rSelectedColor); + m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO + + FontLineStyle eUnderline = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32()); + FontLineStyle eOverline = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32()); + FontStrikeout eStrikeout = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32()); + rFont.SetUnderline( eUnderline ); + rCJKFont.SetUnderline( eUnderline ); + rCTLFont.SetUnderline( eUnderline ); + m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() ); + rFont.SetOverline( eOverline ); + rCJKFont.SetOverline( eOverline ); + rCTLFont.SetOverline( eOverline ); + m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() ); + rFont.SetStrikeout( eStrikeout ); + rCJKFont.SetStrikeout( eStrikeout ); + rCTLFont.SetStrikeout( eStrikeout ); + + auto nEmphasis = m_xEmphasisLB->get_active(); + if (nEmphasis != -1) + { + bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32()); + FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nEmphasis); + eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove; + rFont.SetEmphasisMark( eMark ); + rCJKFont.SetEmphasisMark( eMark ); + rCTLFont.SetEmphasisMark( eMark ); + } + + auto nRelief = m_xReliefLB->get_active(); + if (nRelief != -1) + { + rFont.SetRelief( static_cast<FontRelief>(nRelief) ); + rCJKFont.SetRelief( static_cast<FontRelief>(nRelief) ); + rCTLFont.SetRelief( static_cast<FontRelief>(nRelief) ); + } + + rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) ); + rCJKFont.SetOutline( rFont.IsOutline() ); + rCTLFont.SetOutline( rFont.IsOutline() ); + + rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) ); + rCJKFont.SetShadow( rFont.IsShadow() ); + rCTLFont.SetShadow( rFont.IsShadow() ); + + auto nCapsPos = m_xEffectsLB->get_active(); + if (nCapsPos != -1) + { + SvxCaseMap eCaps = static_cast<SvxCaseMap>(nCapsPos); + rFont.SetCaseMap( eCaps ); + rCJKFont.SetCaseMap( eCaps ); + // #i78474# small caps do not exist in CTL fonts + rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps ); + } + + bool bWordLine = StateToAttr( m_xIndividualWordsBtn->get_state() ); + rFont.SetWordLineMode( bWordLine ); + rCJKFont.SetWordLineMode( bWordLine ); + rCTLFont.SetWordLineMode( bWordLine ); + + m_aPreviewWin.Invalidate(); +} + +void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap ) +{ + if ( SvxCaseMap::End > eCaseMap ) + m_xEffectsLB->set_active( + sal::static_int_cast< sal_Int32 >( eCaseMap ) ); + else + { + // not mapped + m_xEffectsLB->set_active(-1); + } + + UpdatePreview_Impl(); +} + +void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet ) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR ); + SfxItemState eState = rSet.GetItemState( nWhich ); + + m_bOrigFontColor = false; + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_xFontColorFT->hide(); + m_xFontColorLB->hide(); + break; + + case SfxItemState::DISABLED: + m_xFontColorFT->set_sensitive(false); + m_xFontColorLB->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + //Related: tdf#106080 if there is no font color, then allow "none" + //as a color so the listbox can display that state. + EnableNoneFontColor(); + m_xFontColorLB->SetNoSelection(); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + const SvxColorItem& rItem = static_cast<const SvxColorItem&>(rSet.Get( nWhich )); + Color aColor = rItem.GetValue(); + rFont.SetColor(aColor); + rCJKFont.SetColor(aColor); + rCTLFont.SetColor(aColor); + m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO + + m_aPreviewWin.Invalidate(); + + Color aRGBColor = aColor; + if (aRGBColor.IsTransparent() && aColor != COL_AUTO) + { + aRGBColor.SetAlpha(255); + } + m_xFontColorLB->SelectEntry(aRGBColor); + + if (m_xFontTransparencyMtr->get_visible() && aColor != COL_AUTO) + { + double fTransparency = (255 - aColor.GetAlpha()) * 100.0 / 255; + m_xFontTransparencyMtr->set_value(basegfx::fround(fTransparency), + FieldUnit::PERCENT); + } + + m_aOrigFontColor = aColor; + m_bOrigFontColor = true; + break; + } + } + m_bNewFontColor = false; +} + +bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet ) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR ); + const SfxItemSet& rOldSet = GetItemSet(); + + svx::NamedThemedColor aSelectedColor; + bool bChanged = m_bNewFontColor; + + if (bChanged) + { + aSelectedColor = m_xFontColorLB->GetSelectedEntryThemedColor(); + + if (m_xFontTransparencyMtr->get_value_changed_from_saved()) + { + double fTransparency + = m_xFontTransparencyMtr->get_value(FieldUnit::PERCENT) * 255.0 / 100; + aSelectedColor.m_aColor.SetAlpha(255 - static_cast<sal_uInt8>(basegfx::fround(fTransparency))); + } + + if (m_bOrigFontColor) + bChanged = aSelectedColor.m_aColor != m_aOrigFontColor; + if (m_bEnableNoneFontColor && bChanged && aSelectedColor.m_aColor == COL_NONE_COLOR) + bChanged = false; + } + + if (bChanged) + { + SvxColorItem aItem( aSelectedColor.m_aColor, nWhich ); + + if (aSelectedColor.m_nThemeIndex != -1) + { + // The color was picked from the theme palette, remember its index. + aItem.GetThemeColor().SetThemeIndex(aSelectedColor.m_nThemeIndex); + aItem.GetThemeColor().SetLumMod(aSelectedColor.m_nLumMod); + aItem.GetThemeColor().SetLumOff(aSelectedColor.m_nLumOff); + } + + rSet.Put(aItem); + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet.InvalidateItem(nWhich); + + return bChanged; +} + +IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void ) +{ + SelectHdl_Impl(&rBox); +} + +void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox) +{ + if (m_xEmphasisLB.get() == pBox) + { + auto nEPos = m_xEmphasisLB->get_active(); + bool bEnable = nEPos > 0; + m_xPositionFT->set_sensitive( bEnable ); + m_xPositionLB->set_sensitive( bEnable ); + } + else if (m_xReliefLB.get() == pBox) + { + bool bEnable = ( pBox->get_active() == 0 ); + m_xOutlineBtn->set_sensitive( bEnable ); + m_xShadowBtn->set_sensitive( bEnable ); + } + else if (m_xPositionLB.get() != pBox) + { + auto nUPos = m_xUnderlineLB->get_active(); + bool bUEnable = nUPos > 0; + m_xUnderlineColorFT->set_sensitive(bUEnable); + m_xUnderlineColorLB->set_sensitive(bUEnable); + + auto nOPos = m_xOverlineLB->get_active(); + bool bOEnable = nOPos > 0; + m_xOverlineColorFT->set_sensitive(bOEnable); + m_xOverlineColorLB->set_sensitive(bOEnable); + + auto nSPos = m_xStrikeoutLB->get_active(); + m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0); + } + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharEffectsPage, CbClickHdl_Impl, weld::Toggleable&, rToggle, void) +{ + m_aIndividualWordsState.ButtonToggled(rToggle); + UpdatePreview_Impl(); + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void) +{ + if (m_xFontColorLB.get() == &rBox) + m_bNewFontColor = true; + UpdatePreview_Impl(); +} + +IMPL_LINK_NOARG(SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void) +{ + m_bNewFontColor = true; +} + +DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique<SvxCharEffectsPage>( pPage, pController, *rSet ); +} + +void SvxCharEffectsPage::Reset( const SfxItemSet* rSet ) +{ + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + bool bEnable = false; + + // Underline + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE ); + rFont.SetUnderline( LINESTYLE_NONE ); + rCJKFont.SetUnderline( LINESTYLE_NONE ); + rCTLFont.SetUnderline( LINESTYLE_NONE ); + + m_xUnderlineLB->set_active( 0 ); + SfxItemState eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + if ( eState == SfxItemState::DONTCARE ) + m_xUnderlineLB->set_active(-1); + else + { + const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>(rSet->Get( nWhich )); + FontLineStyle eUnderline = rItem.GetValue(); + rFont.SetUnderline( eUnderline ); + rCJKFont.SetUnderline( eUnderline ); + rCTLFont.SetUnderline( eUnderline ); + + if ( eUnderline != LINESTYLE_NONE ) + { + auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline)); + if (nPos != -1) + { + m_xUnderlineLB->set_active(nPos); + bEnable = true; + } + Color aColor = rItem.GetColor(); + m_xUnderlineColorLB->SelectEntry(aColor); + } + else + { + m_xUnderlineColorLB->SelectEntry(COL_AUTO); + m_xUnderlineColorLB->set_sensitive(false); + } + } + } + + // Overline + nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE ); + rFont.SetOverline( LINESTYLE_NONE ); + rCJKFont.SetOverline( LINESTYLE_NONE ); + rCTLFont.SetOverline( LINESTYLE_NONE ); + + m_xOverlineLB->set_active( 0 ); + eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + if ( eState == SfxItemState::DONTCARE ) + m_xOverlineLB->set_active(-1); + else + { + const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>(rSet->Get( nWhich )); + FontLineStyle eOverline = rItem.GetValue(); + rFont.SetOverline( eOverline ); + rCJKFont.SetOverline( eOverline ); + rCTLFont.SetOverline( eOverline ); + + if ( eOverline != LINESTYLE_NONE ) + { + auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline)); + if (nPos != -1) + { + m_xOverlineLB->set_active(nPos); + bEnable = true; + } + Color aColor = rItem.GetColor(); + m_xOverlineColorLB->SelectEntry(aColor); + } + else + { + m_xOverlineColorLB->SelectEntry(COL_AUTO); + m_xOverlineColorLB->set_sensitive(false); + } + } + } + + // Strikeout + nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT ); + rFont.SetStrikeout( STRIKEOUT_NONE ); + rCJKFont.SetStrikeout( STRIKEOUT_NONE ); + rCTLFont.SetStrikeout( STRIKEOUT_NONE ); + + m_xStrikeoutLB->set_active( 0 ); + eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + if ( eState == SfxItemState::DONTCARE ) + m_xStrikeoutLB->set_active(-1); + else + { + const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>(rSet->Get( nWhich )); + FontStrikeout eStrikeout = rItem.GetValue(); + rFont.SetStrikeout( eStrikeout ); + rCJKFont.SetStrikeout( eStrikeout ); + rCTLFont.SetStrikeout( eStrikeout ); + + if ( eStrikeout != STRIKEOUT_NONE ) + { + auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout)); + if (nPos != -1) + { + m_xStrikeoutLB->set_active(nPos); + bEnable = true; + } + } + } + } + + // WordLineMode + nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE ); + eState = rSet->GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aIndividualWordsState.bTriStateEnabled = false; + m_xIndividualWordsBtn->hide(); + break; + + case SfxItemState::DISABLED: + m_aIndividualWordsState.bTriStateEnabled = false; + m_xIndividualWordsBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aIndividualWordsState.bTriStateEnabled = true; + m_xIndividualWordsBtn->set_state( TRISTATE_INDET ); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>(rSet->Get( nWhich )); + rFont.SetWordLineMode( rItem.GetValue() ); + rCJKFont.SetWordLineMode( rItem.GetValue() ); + rCTLFont.SetWordLineMode( rItem.GetValue() ); + + m_aIndividualWordsState.bTriStateEnabled = false; + m_xIndividualWordsBtn->set_active(rItem.GetValue()); + m_xIndividualWordsBtn->set_sensitive(bEnable); + break; + } + } + + // Emphasis + nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK ); + eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DEFAULT ) + { + const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>(rSet->Get( nWhich )); + FontEmphasisMark eMark = rItem.GetEmphasisMark(); + rFont.SetEmphasisMark( eMark ); + rCJKFont.SetEmphasisMark( eMark ); + rCTLFont.SetEmphasisMark( eMark ); + + m_xEmphasisLB->set_active( static_cast<sal_Int32>(FontEmphasisMark( eMark & FontEmphasisMark::Style )) ); + eMark &= ~FontEmphasisMark::Style; + int nEntryData = ( eMark == FontEmphasisMark::PosAbove ) + ? CHRDLG_POSITION_OVER + : ( eMark == FontEmphasisMark::PosBelow ) ? CHRDLG_POSITION_UNDER : 0; + + auto nPos = m_xPositionLB->find_id(OUString::number(nEntryData)); + if (nPos != -1) + m_xPositionLB->set_active(nPos); + } + else if ( eState == SfxItemState::DONTCARE ) + m_xEmphasisLB->set_active(-1); + else if ( eState == SfxItemState::UNKNOWN ) + { + m_xEmphasisFT->hide(); + m_xEmphasisLB->hide(); + } + else // SfxItemState::DISABLED + { + m_xEmphasisFT->set_sensitive(false); + m_xEmphasisLB->set_sensitive(false); + } + + // the select handler for the underline/overline/strikeout list boxes + SelectHdl_Impl(m_xUnderlineLB.get()); + + // the select handler for the emphasis listbox + SelectHdl_Impl(m_xEmphasisLB.get()); + + // Effects + SvxCaseMap eCaseMap = SvxCaseMap::End; + nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP ); + eState = rSet->GetItemState( nWhich ); + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_xEffectsFT->hide(); + m_xEffectsLB->hide(); + break; + + case SfxItemState::DISABLED: + m_xEffectsFT->set_sensitive(false); + m_xEffectsLB->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_xEffectsLB->set_active(-1); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>(rSet->Get( nWhich )); + eCaseMap = rItem.GetValue(); + break; + } + } + SetCaseMap_Impl( eCaseMap ); + + //Relief + nWhich = GetWhich(SID_ATTR_CHAR_RELIEF); + eState = rSet->GetItemState( nWhich ); + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_xReliefFT->hide(); + m_xReliefLB->hide(); + break; + + case SfxItemState::DISABLED: + m_xReliefFT->set_sensitive(false); + m_xReliefLB->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_xReliefLB->set_active(-1); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>(rSet->Get( nWhich )); + m_xReliefLB->set_active(static_cast<sal_Int32>(rItem.GetValue())); + SelectHdl_Impl(m_xReliefLB.get()); + break; + } + } + + // Outline + nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR ); + eState = rSet->GetItemState( nWhich ); + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aOutlineState.bTriStateEnabled = false; + m_xOutlineBtn->hide(); + break; + + case SfxItemState::DISABLED: + m_aOutlineState.bTriStateEnabled = false; + m_xOutlineBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aOutlineState.bTriStateEnabled = true; + m_xOutlineBtn->set_state(TRISTATE_INDET); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxContourItem& rItem = static_cast<const SvxContourItem&>(rSet->Get( nWhich )); + m_aOutlineState.bTriStateEnabled = false; + m_xOutlineBtn->set_state(static_cast<TriState>(rItem.GetValue())); + break; + } + } + + // Shadow + nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED ); + eState = rSet->GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aShadowState.bTriStateEnabled = false; + m_xShadowBtn->hide(); + break; + + case SfxItemState::DISABLED: + m_aShadowState.bTriStateEnabled = false; + m_xShadowBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aShadowState.bTriStateEnabled = true; + m_xShadowBtn->set_state( TRISTATE_INDET ); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>(rSet->Get( nWhich )); + m_aShadowState.bTriStateEnabled = false; + m_xShadowBtn->set_state( static_cast<TriState>(rItem.GetValue()) ); + break; + } + } + + // Hidden + nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN ); + eState = rSet->GetItemState( nWhich ); + + switch ( eState ) + { + case SfxItemState::UNKNOWN: + m_aHiddenState.bTriStateEnabled = false; + m_xHiddenBtn->hide(); + break; + + case SfxItemState::DISABLED: + m_aHiddenState.bTriStateEnabled = false; + m_xHiddenBtn->set_sensitive(false); + break; + + case SfxItemState::DONTCARE: + m_aHiddenState.bTriStateEnabled = true; + m_xHiddenBtn->set_state(TRISTATE_INDET); + break; + + case SfxItemState::DEFAULT: + case SfxItemState::SET: + { + const SvxCharHiddenItem& rItem = static_cast<const SvxCharHiddenItem&>(rSet->Get( nWhich )); + m_aHiddenState.bTriStateEnabled = false; + m_xHiddenBtn->set_state(static_cast<TriState>(rItem.GetValue())); + break; + } + } + + SetPrevFontWidthScale( *rSet ); + ResetColor_Impl( *rSet ); + + // preview update + m_aPreviewWin.Invalidate(); + + // save this settings + ChangesApplied(); +} + +IMPL_LINK(SvxCharEffectsPage, HiddenBtnClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aHiddenState.ButtonToggled(rToggle); +} + +IMPL_LINK(SvxCharEffectsPage, OutlineBtnClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aOutlineState.ButtonToggled(rToggle); + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharEffectsPage, ShadowBtnClickHdl, weld::Toggleable&, rToggle, void) +{ + m_aShadowState.ButtonToggled(rToggle); + UpdatePreview_Impl(); +} + +void SvxCharEffectsPage::ChangesApplied() +{ + m_xUnderlineLB->save_value(); + m_xOverlineLB->save_value(); + m_xStrikeoutLB->save_value(); + m_xIndividualWordsBtn->save_state(); + m_xEmphasisLB->save_value(); + m_xPositionLB->save_value(); + m_xEffectsLB->save_value(); + m_xReliefLB->save_value(); + m_xOutlineBtn->save_state(); + m_xShadowBtn->save_state(); + m_xHiddenBtn->save_state(); + m_xFontTransparencyMtr->save_value(); +} + +bool SvxCharEffectsPage::FillItemSet( SfxItemSet* rSet ) +{ + const SfxPoolItem* pOld = nullptr; + const SfxItemSet& rOldSet = GetItemSet(); + bool bModified = false; + bool bChanged = true; + + // Underline + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_UNDERLINE ); + auto nPos = m_xUnderlineLB->get_active(); + FontLineStyle eUnder = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32()); + + if ( pOld ) + { + //! if there are different underline styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the underline style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxUnderlineItem& rItem = *static_cast<const SvxUnderlineItem*>(pOld); + if ( rItem.GetValue() == eUnder && + ( LINESTYLE_NONE == eUnder || rItem.GetColor() == m_xUnderlineColorLB->GetSelectEntryColor() ) && + ! bAllowChg ) + bChanged = false; + } + + if ( bChanged ) + { + SvxUnderlineItem aNewItem( eUnder, nWhich ); + aNewItem.SetColor( m_xUnderlineColorLB->GetSelectEntryColor() ); + rSet->Put( aNewItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Overline + nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_OVERLINE ); + nPos = m_xOverlineLB->get_active(); + FontLineStyle eOver = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32()); + + if ( pOld ) + { + //! if there are different underline styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the underline style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxOverlineItem& rItem = *static_cast<const SvxOverlineItem*>(pOld); + if ( rItem.GetValue() == eOver && + ( LINESTYLE_NONE == eOver || rItem.GetColor() == m_xOverlineColorLB->GetSelectEntryColor() ) && + ! bAllowChg ) + bChanged = false; + } + + if ( bChanged ) + { + SvxOverlineItem aNewItem( eOver, nWhich ); + aNewItem.SetColor( m_xOverlineColorLB->GetSelectEntryColor() ); + rSet->Put( aNewItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Strikeout + nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_STRIKEOUT ); + nPos = m_xStrikeoutLB->get_active(); + FontStrikeout eStrike = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32()); + + if ( pOld ) + { + //! if there are different strikeout styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the strikeout style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxCrossedOutItem& rItem = *static_cast<const SvxCrossedOutItem*>(pOld); + if ( !m_xStrikeoutLB->get_sensitive() + || (rItem.GetValue() == eStrike && !bAllowChg) ) + bChanged = false; + } + + if ( bChanged ) + { + rSet->Put( SvxCrossedOutItem( eStrike, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Individual words + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_WORDLINEMODE ); + TriState eState = m_xIndividualWordsBtn->get_state(); + const SfxPoolItem* pItem; + + if ( pOld ) + { + const SvxWordLineModeItem& rItem = *static_cast<const SvxWordLineModeItem*>(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xIndividualWordsBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast<const SvxWordLineModeItem*>(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxWordLineModeItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Emphasis + nWhich = GetWhich( SID_ATTR_CHAR_EMPHASISMARK ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_EMPHASISMARK ); + int nMarkPos = m_xEmphasisLB->get_active(); + OUString sMarkPos = m_xEmphasisLB->get_active_text(); + OUString sPosPos = m_xPositionLB->get_active_text(); + FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nMarkPos); + if (m_xPositionLB->get_sensitive()) + { + eMark |= (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32()) + ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove; + } + + if ( pOld ) + { + if( rOldSet.GetItemState( nWhich ) != SfxItemState::DONTCARE ) + { + const SvxEmphasisMarkItem& rItem = *static_cast<const SvxEmphasisMarkItem*>(pOld); + if ( rItem.GetEmphasisMark() == eMark ) + bChanged = false; + } + } + + if (rOldSet.GetItemState( nWhich ) == SfxItemState::DONTCARE && + m_xEmphasisLB->get_saved_value() == sMarkPos && m_xPositionLB->get_saved_value() == sPosPos) + { + bChanged = false; + } + + if (bChanged) + { + rSet->Put( SvxEmphasisMarkItem( eMark, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Effects + nWhich = GetWhich( SID_ATTR_CHAR_CASEMAP ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CASEMAP ); + SvxCaseMap eCaseMap = SvxCaseMap::NotMapped; + bool bChecked = false; + auto nCapsPos = m_xEffectsLB->get_active(); + if (nCapsPos != -1) + { + eCaseMap = static_cast<SvxCaseMap>(nCapsPos); + bChecked = true; + } + + if ( pOld ) + { + //! if there are different effect styles in the selection the + //! item-state in the 'rOldSet' will be invalid. In this case + //! changing the effect style will be allowed if a style is + //! selected in the listbox. + bool bAllowChg = nPos != -1 && + SfxItemState::DEFAULT > rOldSet.GetItemState( nWhich ); + + const SvxCaseMapItem& rItem = *static_cast<const SvxCaseMapItem*>(pOld); + if ( rItem.GetValue() == eCaseMap && !bAllowChg ) + bChanged = false; + } + + if ( bChanged && bChecked ) + { + rSet->Put( SvxCaseMapItem( eCaseMap, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + //Relief + nWhich = GetWhich(SID_ATTR_CHAR_RELIEF); + if (m_xReliefLB->get_value_changed_from_saved()) + { + m_xReliefLB->save_value(); + SvxCharReliefItem aRelief(static_cast<FontRelief>(m_xReliefLB->get_active()), nWhich); + rSet->Put(aRelief); + } + + // Outline + nWhich = GetWhich( SID_ATTR_CHAR_CONTOUR ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_CONTOUR ); + eState = m_xOutlineBtn->get_state(); + + if ( pOld ) + { + const SvxContourItem& rItem = *static_cast<const SvxContourItem*>(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xOutlineBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast<const SvxContourItem*>(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxContourItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Shadow + nWhich = GetWhich( SID_ATTR_CHAR_SHADOWED ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_SHADOWED ); + eState = m_xShadowBtn->get_state(); + + if ( pOld ) + { + const SvxShadowedItem& rItem = *static_cast<const SvxShadowedItem*>(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xShadowBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast<const SvxShadowedItem*>(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxShadowedItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Hidden + nWhich = GetWhich( SID_ATTR_CHAR_HIDDEN ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_HIDDEN ); + eState = m_xHiddenBtn->get_state(); + bChanged = true; + + if ( pOld ) + { + const SvxCharHiddenItem& rItem = *static_cast<const SvxCharHiddenItem*>(pOld); + if ( rItem.GetValue() == StateToAttr( eState ) && m_xHiddenBtn->get_saved_state() == eState ) + bChanged = false; + } + + if ( !bChanged && pExampleSet && pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET && + !StateToAttr( eState ) && static_cast<const SvxCharHiddenItem*>(pItem)->GetValue() ) + bChanged = true; + + if ( bChanged && eState != TRISTATE_INDET ) + { + rSet->Put( SvxCharHiddenItem( StateToAttr( eState ), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bModified |= FillItemSetColor_Impl( *rSet ); + + return bModified; +} + +void SvxCharEffectsPage::DisableControls( sal_uInt16 nDisable ) +{ + if ( ( DISABLE_CASEMAP & nDisable ) == DISABLE_CASEMAP ) + { + m_xEffectsFT->set_sensitive(false); + m_xEffectsLB->set_sensitive(false); + } +} + +void SvxCharEffectsPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pDisableCtlItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false); + const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false); + if (pDisableCtlItem) + DisableControls(pDisableCtlItem->GetValue()); + + if (!pFlagItem) + return; + + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + if ((nFlags & SVX_ENABLE_CHAR_TRANSPARENCY) != SVX_ENABLE_CHAR_TRANSPARENCY) + { + // Only show these in case client code explicitly wants this. + m_xFontTransparencyFT->hide(); + m_xFontTransparencyMtr->hide(); + } +} + +// class SvxCharPositionPage --------------------------------------------- + +SvxCharPositionPage::SvxCharPositionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/positionpage.ui", "PositionPage", rInSet) + , m_nSuperEsc(short(DFLT_ESC_SUPER)) + , m_nSubEsc(short(DFLT_ESC_SUB)) + , m_nScaleWidthItemSetVal(100) + , m_nScaleWidthInitialVal(100) + , m_nSuperProp(sal_uInt8(DFLT_ESC_PROP)) + , m_nSubProp(sal_uInt8(DFLT_ESC_PROP)) + , m_xHighPosBtn(m_xBuilder->weld_radio_button("superscript")) + , m_xNormalPosBtn(m_xBuilder->weld_radio_button("normal")) + , m_xLowPosBtn(m_xBuilder->weld_radio_button("subscript")) + , m_xHighLowFT(m_xBuilder->weld_label("raiselower")) + , m_xHighLowMF(m_xBuilder->weld_metric_spin_button("raiselowersb", FieldUnit::PERCENT)) + , m_xHighLowRB(m_xBuilder->weld_check_button("automatic")) + , m_xFontSizeFT(m_xBuilder->weld_label("relativefontsize")) + , m_xFontSizeMF(m_xBuilder->weld_metric_spin_button("fontsizesb", FieldUnit::PERCENT)) + , m_xRotationContainer(m_xBuilder->weld_widget("rotationcontainer")) + , m_xScalingFT(m_xBuilder->weld_label("scale")) + , m_xScalingAndRotationFT(m_xBuilder->weld_label("rotateandscale")) + , m_x0degRB(m_xBuilder->weld_radio_button("0deg")) + , m_x90degRB(m_xBuilder->weld_radio_button("90deg")) + , m_x270degRB(m_xBuilder->weld_radio_button("270deg")) + , m_xFitToLineCB(m_xBuilder->weld_check_button("fittoline")) + , m_xScaleWidthMF(m_xBuilder->weld_metric_spin_button("scalewidthsb", FieldUnit::PERCENT)) + , m_xKerningMF(m_xBuilder->weld_metric_spin_button("kerningsb", FieldUnit::POINT)) + , m_xPairKerningBtn(m_xBuilder->weld_check_button("pairkerning")) +{ + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + Initialize(); +} + +SvxCharPositionPage::~SvxCharPositionPage() +{ +} + + +void SvxCharPositionPage::Initialize() +{ + // to handle the changes of the other pages + SetExchangeSupport(); + + GetPreviewFont().SetFontSize( Size( 0, 240 ) ); + GetPreviewCJKFont().SetFontSize( Size( 0, 240 ) ); + GetPreviewCTLFont().SetFontSize( Size( 0, 240 ) ); + + m_xNormalPosBtn->set_active(true); + PositionHdl_Impl(*m_xNormalPosBtn); + + Link<weld::Toggleable&,void> aLink2 = LINK(this, SvxCharPositionPage, PositionHdl_Impl); + m_xHighPosBtn->connect_toggled(aLink2); + m_xNormalPosBtn->connect_toggled(aLink2); + m_xLowPosBtn->connect_toggled(aLink2); + + aLink2 = LINK( this, SvxCharPositionPage, RotationHdl_Impl ); + m_x0degRB->connect_toggled(aLink2); + m_x90degRB->connect_toggled(aLink2); + m_x270degRB->connect_toggled(aLink2); + + Link<weld::MetricSpinButton&,void> aLink3 = LINK(this, SvxCharPositionPage, ValueChangedHdl_Impl); + m_xHighLowMF->connect_value_changed(aLink3); + m_xFontSizeMF->connect_value_changed(aLink3); + + m_xHighLowRB->connect_toggled(LINK(this, SvxCharPositionPage, AutoPositionHdl_Impl)); + m_xFitToLineCB->connect_toggled(LINK(this, SvxCharPositionPage, FitToLineHdl_Impl)); + m_xKerningMF->connect_value_changed(LINK(this, SvxCharPositionPage, KerningModifyHdl_Impl)); + m_xScaleWidthMF->connect_value_changed(LINK(this, SvxCharPositionPage, ScaleWidthModifyHdl_Impl)); +} + +void SvxCharPositionPage::UpdatePreview_Impl( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc ) +{ + SetPrevFontEscapement( nProp, nEscProp, nEsc ); +} + + +void SvxCharPositionPage::SetEscapement_Impl( SvxEscapement nEsc ) +{ + SvxEscapementItem aEscItm( nEsc, SID_ATTR_CHAR_ESCAPEMENT ); + + if ( SvxEscapement::Superscript == nEsc ) + { + aEscItm.GetEsc() = m_nSuperEsc; + aEscItm.GetProportionalHeight() = m_nSuperProp; + } + else if ( SvxEscapement::Subscript == nEsc ) + { + aEscItm.GetEsc() = m_nSubEsc; + aEscItm.GetProportionalHeight() = m_nSubProp; + } + + short nFac = aEscItm.GetEsc() < 0 ? -1 : 1; + + m_xHighLowMF->set_value(aEscItm.GetEsc() * nFac, FieldUnit::PERCENT); + m_xFontSizeMF->set_value(aEscItm.GetProportionalHeight(), FieldUnit::PERCENT); + + if ( SvxEscapement::Off == nEsc ) + { + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + m_xFontSizeFT->set_sensitive(false); + m_xFontSizeMF->set_sensitive(false); + m_xHighLowRB->set_sensitive(false); + } + else + { + m_xFontSizeFT->set_sensitive(true); + m_xFontSizeMF->set_sensitive(true); + m_xHighLowRB->set_sensitive(true); + + if (!m_xHighLowRB->get_active()) + { + m_xHighLowFT->set_sensitive(true); + m_xHighLowMF->set_sensitive(true); + } + else + AutoPositionHdl_Impl(*m_xHighLowRB); + } + + UpdatePreview_Impl( 100, aEscItm.GetProportionalHeight(), aEscItm.GetEsc() ); +} + + +IMPL_LINK_NOARG(SvxCharPositionPage, PositionHdl_Impl, weld::Toggleable&, void) +{ + SvxEscapement nEsc = SvxEscapement::Off; // also when pBtn == NULL + + if (m_xHighPosBtn->get_active()) + nEsc = SvxEscapement::Superscript; + else if (m_xLowPosBtn->get_active()) + nEsc = SvxEscapement::Subscript; + + SetEscapement_Impl( nEsc ); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, RotationHdl_Impl, weld::Toggleable&, void) +{ + bool bEnable = false; + if (m_x90degRB->get_active() || m_x270degRB->get_active()) + bEnable = true; + else + OSL_ENSURE(m_x0degRB->get_active(), "unexpected button"); + m_xFitToLineCB->set_sensitive(bEnable); +} + +void SvxCharPositionPage::FontModifyHdl_Impl() +{ + sal_uInt8 nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT)); + short nEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)); + nEsc *= m_xLowPosBtn->get_active() ? -1 : 1; + UpdatePreview_Impl( 100, nEscProp, nEsc ); +} + +IMPL_LINK(SvxCharPositionPage, AutoPositionHdl_Impl, weld::Toggleable&, rBox, void) +{ + if (rBox.get_active()) + { + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + } + else + PositionHdl_Impl(m_xHighPosBtn->get_active() ? *m_xHighPosBtn + : m_xLowPosBtn->get_active() ? *m_xLowPosBtn + : *m_xNormalPosBtn); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, FitToLineHdl_Impl, weld::Toggleable&, void) +{ + sal_uInt16 nVal = m_nScaleWidthInitialVal; + if (m_xFitToLineCB->get_active()) + nVal = m_nScaleWidthItemSetVal; + m_xScaleWidthMF->set_value(nVal, FieldUnit::PERCENT); + m_aPreviewWin.SetFontWidthScale( nVal ); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, KerningModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT)); + nVal = o3tl::convert(nVal, o3tl::Length::pt, o3tl::Length::twip); + + tools::Long nKern = static_cast<short>(m_xKerningMF->denormalize(nVal)); + + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + + rFont.SetFixKerning( static_cast<short>(nKern) ); + rCJKFont.SetFixKerning( static_cast<short>(nKern) ); + rCTLFont.SetFixKerning( static_cast<short>(nKern) ); + m_aPreviewWin.Invalidate(); +} + +IMPL_LINK(SvxCharPositionPage, ValueChangedHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + bool bHigh = m_xHighPosBtn->get_active(); + bool bLow = m_xLowPosBtn->get_active(); + DBG_ASSERT( bHigh || bLow, "normal position is not valid" ); + + if (m_xHighLowMF.get() == &rField) + { + if ( bLow ) + m_nSubEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)) * -1; + else + m_nSuperEsc = static_cast<short>(m_xHighLowMF->get_value(FieldUnit::PERCENT)); + } + else if (m_xFontSizeMF.get() == &rField) + { + if ( bLow ) + m_nSubProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT)); + else + m_nSuperProp = static_cast<sal_uInt8>(m_xFontSizeMF->get_value(FieldUnit::PERCENT)); + } + + FontModifyHdl_Impl(); +} + +IMPL_LINK_NOARG(SvxCharPositionPage, ScaleWidthModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + m_aPreviewWin.SetFontWidthScale(sal_uInt16(m_xScaleWidthMF->get_value(FieldUnit::PERCENT))); +} + +DeactivateRC SvxCharPositionPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SvxCharPositionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxCharPositionPage>(pPage, pController, *rSet); +} + +void SvxCharPositionPage::Reset( const SfxItemSet* rSet ) +{ + OUString sUser = GetUserData(); + + if ( !sUser.isEmpty() ) + { + sal_Int32 nIdx {0}; + m_nSuperEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx ))); + m_nSubEsc = static_cast<short>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx ))); + m_nSuperProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx ))); + m_nSubProp = static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(sUser, 0, ';', nIdx ))); + + m_xHighLowMF->set_max(MAX_ESC_POS, FieldUnit::PERCENT); + + //fdo#75307 validate all the entries and discard all of them if any are + //out of range + bool bValid = true; + if (m_nSuperEsc < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSuperEsc > m_xHighLowMF->get_max(FieldUnit::PERCENT)) + bValid = false; + if (m_nSubEsc*-1 < m_xHighLowMF->get_min(FieldUnit::PERCENT) || m_nSubEsc*-1 > m_xHighLowMF->get_max(FieldUnit::PERCENT)) + bValid = false; + if (m_nSuperProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSuperProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT)) + bValid = false; + if (m_nSubProp < m_xFontSizeMF->get_min(FieldUnit::PERCENT) || m_nSubProp > m_xFontSizeMF->get_max(FieldUnit::PERCENT)) + bValid = false; + + if (!bValid) + { + m_nSuperEsc = DFLT_ESC_SUPER; + m_nSubEsc = DFLT_ESC_SUB; + m_nSuperProp = DFLT_ESC_PROP; + m_nSubProp = DFLT_ESC_PROP; + } + } + + short nEsc = 0; + sal_uInt8 nEscProp = 100; + + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + m_xFontSizeFT->set_sensitive(false); + m_xFontSizeMF->set_sensitive(false); + + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT ); + + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>(rSet->Get( nWhich )); + nEsc = rItem.GetEsc(); + nEscProp = rItem.GetProportionalHeight(); + + if ( nEsc != 0 ) + { + m_xHighLowFT->set_sensitive(true); + m_xHighLowMF->set_sensitive(true); + m_xFontSizeFT->set_sensitive(true); + m_xFontSizeMF->set_sensitive(true); + + short nFac; + bool bAutomatic(false); + + if ( nEsc > 0 ) + { + nFac = 1; + m_xHighPosBtn->set_active(true); + if ( nEsc == DFLT_ESC_AUTO_SUPER ) + { + nEsc = .8 * (100 - nEscProp); //approximation of actual percentage used + bAutomatic = true; + } + } + else + { + nFac = -1; + m_xLowPosBtn->set_active(true); + if ( nEsc == DFLT_ESC_AUTO_SUB ) + { + nEsc = .2 * -(100 - nEscProp); //approximation of actual percentage used + bAutomatic = true; + } + } + if (!m_xHighLowRB->get_sensitive()) + { + m_xHighLowRB->set_sensitive(true); + } + m_xHighLowRB->set_active(bAutomatic); + + if (m_xHighLowRB->get_active()) + { + m_xHighLowFT->set_sensitive(false); + m_xHighLowMF->set_sensitive(false); + } + m_xHighLowMF->set_value(m_xHighLowMF->normalize(nFac * nEsc), FieldUnit::PERCENT); + } + else + { + m_xNormalPosBtn->set_active(true); + m_xHighLowRB->set_active(true); + PositionHdl_Impl(*m_xNormalPosBtn); + } + //the height has to be set after the handler is called to keep the value also if the escapement is zero + m_xFontSizeMF->set_value(m_xFontSizeMF->normalize(nEscProp), FieldUnit::PERCENT); + } + else + { + m_xHighPosBtn->set_active(false); + m_xNormalPosBtn->set_active(false); + m_xLowPosBtn->set_active(false); + } + + // set BspFont + SetPrevFontEscapement( 100, nEscProp, nEsc ); + + // Kerning + nWhich = GetWhich( SID_ATTR_CHAR_KERNING ); + + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>(rSet->Get( nWhich )); + MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich ); + tools::Long nBig = static_cast<tools::Long>(m_xKerningMF->normalize( static_cast<tools::Long>(rItem.GetValue()) )); + tools::Long nKerning = OutputDevice::LogicToLogic(nBig, eUnit, MapUnit::MapPoint); + + // set Kerning at the Font, convert into Twips before + tools::Long nKern = OutputDevice::LogicToLogic(rItem.GetValue(), eUnit, MapUnit::MapTwip); + rFont.SetFixKerning( static_cast<short>(nKern) ); + rCJKFont.SetFixKerning( static_cast<short>(nKern) ); + rCTLFont.SetFixKerning( static_cast<short>(nKern) ); + + //the attribute value must be displayed also if it's above/below the maximum allowed value + tools::Long nVal = static_cast<tools::Long>(m_xKerningMF->get_max(FieldUnit::POINT)); + if(nVal < nKerning) + m_xKerningMF->set_max(nKerning, FieldUnit::POINT); + nVal = static_cast<tools::Long>(m_xKerningMF->get_min(FieldUnit::POINT)); + if (nVal > nKerning) + m_xKerningMF->set_min(nKerning, FieldUnit::POINT); + m_xKerningMF->set_value(nKerning, FieldUnit::POINT); + } + else + m_xKerningMF->set_text(OUString()); + + // Pair kerning + nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN ); + + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxAutoKernItem& rItem = static_cast<const SvxAutoKernItem&>(rSet->Get( nWhich )); + m_xPairKerningBtn->set_active(rItem.GetValue()); + } + else + m_xPairKerningBtn->set_active(false); + + // Scale Width + nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH ); + if ( rSet->GetItemState( nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxCharScaleWidthItem& rItem = static_cast<const SvxCharScaleWidthItem&>( rSet->Get( nWhich ) ); + m_nScaleWidthInitialVal = rItem.GetValue(); + m_xScaleWidthMF->set_value(m_nScaleWidthInitialVal, FieldUnit::PERCENT); + } + else + m_xScaleWidthMF->set_value(100, FieldUnit::PERCENT); + + if ( rSet->GetItemState( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE ) >= SfxItemState::DEFAULT ) + m_nScaleWidthItemSetVal = static_cast<const SfxUInt16Item&>( rSet->Get( SID_ATTR_CHAR_WIDTH_FIT_TO_LINE )).GetValue(); + + // Rotation + nWhich = GetWhich( SID_ATTR_CHAR_ROTATED ); + SfxItemState eState = rSet->GetItemState( nWhich ); + if( SfxItemState::UNKNOWN == eState ) + { + m_xRotationContainer->hide(); + m_xScalingAndRotationFT->hide(); + m_xScalingFT->show(); + } + else + { + m_xRotationContainer->show(); + m_xScalingAndRotationFT->show(); + m_xScalingFT->hide(); + + if( eState >= SfxItemState::DEFAULT ) + { + const SvxCharRotateItem& rItem = + static_cast<const SvxCharRotateItem&>( rSet->Get( nWhich )); + if (rItem.IsBottomToTop()) + m_x90degRB->set_active(true); + else if (rItem.IsTopToBottom()) + m_x270degRB->set_active(true); + else + { + DBG_ASSERT( 0_deg10 == rItem.GetValue(), "incorrect value" ); + m_x0degRB->set_active(true); + } + m_xFitToLineCB->set_active(rItem.IsFitToLine()); + } + else + { + if( eState == SfxItemState::DONTCARE ) + { + m_x0degRB->set_active(false); + m_x90degRB->set_active(false); + m_x270degRB->set_active(false); + } + else + m_x0degRB->set_active(true); + + m_xFitToLineCB->set_active(false); + } + m_xFitToLineCB->set_sensitive(!m_x0degRB->get_active()); + + // is this value set? + if( SfxItemState::UNKNOWN == rSet->GetItemState( + SID_ATTR_CHAR_WIDTH_FIT_TO_LINE )) + m_xFitToLineCB->hide(); + } + ChangesApplied(); +} + +void SvxCharPositionPage::ChangesApplied() +{ + m_xHighPosBtn->save_state(); + m_xNormalPosBtn->save_state(); + m_xLowPosBtn->save_state(); + m_xHighLowRB->save_state(); + m_x0degRB->save_state(); + m_x90degRB->save_state(); + m_x270degRB->save_state(); + m_xFitToLineCB->save_state(); + m_xScaleWidthMF->save_value(); + m_xKerningMF->save_value(); + m_xPairKerningBtn->save_state(); +} + +bool SvxCharPositionPage::FillItemSet( SfxItemSet* rSet ) +{ + // Position (high, normal or low) + const SfxItemSet& rOldSet = GetItemSet(); + bool bModified = false, bChanged = true; + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_ESCAPEMENT ); + const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_ESCAPEMENT ); + const bool bHigh = m_xHighPosBtn->get_active(); + short nEsc; + sal_uInt8 nEscProp; + + if (bHigh || m_xLowPosBtn->get_active()) + { + if (m_xHighLowRB->get_active()) + nEsc = bHigh ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB; + else + { + nEsc = static_cast<short>(m_xHighLowMF->denormalize(m_xHighLowMF->get_value(FieldUnit::PERCENT))); + nEsc *= (bHigh ? 1 : -1); + } + nEscProp = static_cast<sal_uInt8>(m_xFontSizeMF->denormalize(m_xFontSizeMF->get_value(FieldUnit::PERCENT))); + } + else + { + nEsc = 0; + nEscProp = 100; + } + + if ( pOld ) + { + const SvxEscapementItem& rItem = *static_cast<const SvxEscapementItem*>(pOld); + if (rItem.GetEsc() == nEsc && rItem.GetProportionalHeight() == nEscProp) + bChanged = false; + } + + if ( !bChanged && !m_xHighPosBtn->get_saved_state() && + !m_xNormalPosBtn->get_saved_state() && !m_xLowPosBtn->get_saved_state() ) + bChanged = true; + + if ( bChanged && + ( m_xHighPosBtn->get_active() || m_xNormalPosBtn->get_active() || m_xLowPosBtn->get_active() ) ) + { + rSet->Put( SvxEscapementItem( nEsc, nEscProp, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + bChanged = true; + + // Kerning + nWhich = GetWhich( SID_ATTR_CHAR_KERNING ); + pOld = GetOldItem( *rSet, SID_ATTR_CHAR_KERNING ); + short nKerning = 0; + MapUnit eUnit = rSet->GetPool()->GetMetric( nWhich ); + + tools::Long nTmp = static_cast<tools::Long>(m_xKerningMF->get_value(FieldUnit::POINT)); + tools::Long nVal = OutputDevice::LogicToLogic(nTmp, MapUnit::MapPoint, eUnit); + nKerning = static_cast<short>(m_xKerningMF->denormalize( nVal )); + + SfxItemState eOldKernState = rOldSet.GetItemState( nWhich, false ); + if ( pOld ) + { + const SvxKerningItem& rItem = *static_cast<const SvxKerningItem*>(pOld); + if ( (eOldKernState >= SfxItemState::DEFAULT || m_xKerningMF->get_text().isEmpty()) && rItem.GetValue() == nKerning ) + bChanged = false; + } + + if ( bChanged ) + { + rSet->Put( SvxKerningItem( nKerning, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == eOldKernState ) + rSet->InvalidateItem(nWhich); + + // Pair-Kerning + nWhich = GetWhich( SID_ATTR_CHAR_AUTOKERN ); + + if (m_xPairKerningBtn->get_state_changed_from_saved()) + { + rSet->Put( SvxAutoKernItem( m_xPairKerningBtn->get_active(), nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + // Scale Width + nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH ); + if (m_xScaleWidthMF->get_value_changed_from_saved()) + { + rSet->Put(SvxCharScaleWidthItem(static_cast<sal_uInt16>(m_xScaleWidthMF->get_value(FieldUnit::PERCENT)), nWhich)); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + // Rotation + nWhich = GetWhich( SID_ATTR_CHAR_ROTATED ); + if ( m_x0degRB->get_state_changed_from_saved() || + m_x90degRB->get_state_changed_from_saved() || + m_x270degRB->get_state_changed_from_saved() || + m_xFitToLineCB->get_state_changed_from_saved() ) + { + SvxCharRotateItem aItem( 0_deg10, m_xFitToLineCB->get_active(), nWhich ); + if (m_x90degRB->get_active()) + aItem.SetBottomToTop(); + else if (m_x270degRB->get_active()) + aItem.SetTopToBottom(); + rSet->Put( aItem ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + return bModified; +} + + +void SvxCharPositionPage::FillUserData() +{ + static const OUStringLiteral cTok( u";" ); + + OUString sUser = OUString::number( m_nSuperEsc ) + cTok + + OUString::number( m_nSubEsc ) + cTok + + OUString::number( m_nSuperProp ) + cTok + + OUString::number( m_nSubProp ); + SetUserData( sUser ); +} + + +void SvxCharPositionPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false); + if (pFlagItem) + { + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + } +} +// class SvxCharTwoLinesPage ------------------------------------------------ + +SvxCharTwoLinesPage::SvxCharTwoLinesPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet) + : SvxCharBasePage(pPage, pController, "cui/ui/twolinespage.ui", "TwoLinesPage", rInSet) + , m_nStartBracketPosition( 0 ) + , m_nEndBracketPosition( 0 ) + , m_xTwoLinesBtn(m_xBuilder->weld_check_button("twolines")) + , m_xEnclosingFrame(m_xBuilder->weld_widget("enclosing")) + , m_xStartBracketLB(m_xBuilder->weld_tree_view("startbracket")) + , m_xEndBracketLB(m_xBuilder->weld_tree_view("endbracket")) +{ + for (size_t i = 0; i < std::size(TWOLINE_OPEN); ++i) + m_xStartBracketLB->append(OUString::number(TWOLINE_OPEN[i].second), CuiResId(TWOLINE_OPEN[i].first)); + for (size_t i = 0; i < std::size(TWOLINE_CLOSE); ++i) + m_xEndBracketLB->append(OUString::number(TWOLINE_CLOSE[i].second), CuiResId(TWOLINE_CLOSE[i].first)); + + m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin)); +#ifdef IOS + m_xPreviewWin->hide(); +#endif + Initialize(); +} + +SvxCharTwoLinesPage::~SvxCharTwoLinesPage() +{ +} + +void SvxCharTwoLinesPage::Initialize() +{ + m_xTwoLinesBtn->set_active(false); + TwoLinesHdl_Impl(*m_xTwoLinesBtn); + + m_xTwoLinesBtn->connect_toggled(LINK(this, SvxCharTwoLinesPage, TwoLinesHdl_Impl)); + + Link<weld::TreeView&,void> aLink = LINK(this, SvxCharTwoLinesPage, CharacterMapHdl_Impl); + m_xStartBracketLB->connect_changed(aLink); + m_xEndBracketLB->connect_changed(aLink); + + SvxFont& rFont = GetPreviewFont(); + SvxFont& rCJKFont = GetPreviewCJKFont(); + SvxFont& rCTLFont = GetPreviewCTLFont(); + rFont.SetFontSize( Size( 0, 220 ) ); + rCJKFont.SetFontSize( Size( 0, 220 ) ); + rCTLFont.SetFontSize( Size( 0, 220 ) ); +} + +void SvxCharTwoLinesPage::SelectCharacter(weld::TreeView* pBox) +{ + bool bStart = pBox == m_xStartBracketLB.get(); + SvxCharacterMap aDlg(GetFrameWeld(), nullptr, nullptr); + aDlg.DisableFontSelection(); + + if (aDlg.run() == RET_OK) + { + sal_Unicode cChar = static_cast<sal_Unicode>(aDlg.GetChar()); + SetBracket( cChar, bStart ); + } + else + { + pBox->select(bStart ? m_nStartBracketPosition : m_nEndBracketPosition); + } +} + + +void SvxCharTwoLinesPage::SetBracket( sal_Unicode cBracket, bool bStart ) +{ + int nEntryPos = 0; + weld::TreeView* pBox = bStart ? m_xStartBracketLB.get() : m_xEndBracketLB.get(); + if (cBracket == 0) + pBox->select(0); + else + { + bool bFound = false; + for (int i = 1; i < pBox->n_children(); ++i) + { + if (pBox->get_id(i).toInt32() != CHRDLG_ENCLOSE_SPECIAL_CHAR) + { + const sal_Unicode cChar = pBox->get_text(i)[0]; + if (cChar == cBracket) + { + pBox->select(i); + nEntryPos = i; + bFound = true; + break; + } + } + } + + if (!bFound) + { + pBox->append_text(OUString(cBracket)); + nEntryPos = pBox->n_children() - 1; + pBox->select(nEntryPos); + } + } + if (bStart) + m_nStartBracketPosition = nEntryPos; + else + m_nEndBracketPosition = nEntryPos; +} + +IMPL_LINK_NOARG(SvxCharTwoLinesPage, TwoLinesHdl_Impl, weld::Toggleable&, void) +{ + bool bChecked = m_xTwoLinesBtn->get_active(); + m_xEnclosingFrame->set_sensitive(bChecked); + UpdatePreview_Impl(); +} + +IMPL_LINK(SvxCharTwoLinesPage, CharacterMapHdl_Impl, weld::TreeView&, rBox, void) +{ + int nPos = rBox.get_selected_index(); + if (rBox.get_id(nPos).toInt32() == CHRDLG_ENCLOSE_SPECIAL_CHAR) + SelectCharacter( &rBox ); + else + { + bool bStart = &rBox == m_xStartBracketLB.get(); + if (bStart) + m_nStartBracketPosition = nPos; + else + m_nEndBracketPosition = nPos; + } + UpdatePreview_Impl(); +} + +void SvxCharTwoLinesPage::ActivatePage( const SfxItemSet& rSet ) +{ + SvxCharBasePage::ActivatePage(rSet); +} + +DeactivateRC SvxCharTwoLinesPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SvxCharTwoLinesPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxCharTwoLinesPage>(pPage, pController, *rSet); +} + +void SvxCharTwoLinesPage::Reset( const SfxItemSet* rSet ) +{ + m_xTwoLinesBtn->set_active(false); + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES ); + SfxItemState eState = rSet->GetItemState( nWhich ); + + if ( eState >= SfxItemState::DONTCARE ) + { + const SvxTwoLinesItem& rItem = static_cast<const SvxTwoLinesItem&>(rSet->Get( nWhich )); + m_xTwoLinesBtn->set_active(rItem.GetValue()); + + if ( rItem.GetValue() ) + { + SetBracket( rItem.GetStartBracket(), true ); + SetBracket( rItem.GetEndBracket(), false ); + } + } + TwoLinesHdl_Impl(*m_xTwoLinesBtn); + + SetPrevFontWidthScale( *rSet ); +} + +bool SvxCharTwoLinesPage::FillItemSet( SfxItemSet* rSet ) +{ + const SfxItemSet& rOldSet = GetItemSet(); + bool bModified = false, bChanged = true; + sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_TWO_LINES ); + const SfxPoolItem* pOld = GetOldItem( *rSet, SID_ATTR_CHAR_TWO_LINES ); + bool bOn = m_xTwoLinesBtn->get_active(); + sal_Unicode cStart = ( bOn && m_xStartBracketLB->get_selected_index() > 0 ) + ? m_xStartBracketLB->get_selected_text()[0] : 0; + sal_Unicode cEnd = ( bOn && m_xEndBracketLB->get_selected_index() > 0 ) + ? m_xEndBracketLB->get_selected_text()[0] : 0; + + if ( pOld ) + { + const SvxTwoLinesItem& rItem = *static_cast<const SvxTwoLinesItem*>(pOld); + if ( rItem.GetValue() == bOn && + ( !bOn || ( rItem.GetStartBracket() == cStart && rItem.GetEndBracket() == cEnd ) ) ) + bChanged = false; + } + + if ( bChanged ) + { + rSet->Put( SvxTwoLinesItem( bOn, cStart, cEnd, nWhich ) ); + bModified = true; + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) ) + rSet->InvalidateItem(nWhich); + + return bModified; +} + +void SvxCharTwoLinesPage::UpdatePreview_Impl() +{ + sal_Unicode cStart = m_xStartBracketLB->get_selected_index() > 0 + ? m_xStartBracketLB->get_selected_text()[0] : 0; + sal_Unicode cEnd = m_xEndBracketLB->get_selected_index() > 0 + ? m_xEndBracketLB->get_selected_text()[0] : 0; + m_aPreviewWin.SetBrackets(cStart, cEnd); + m_aPreviewWin.SetTwoLines(m_xTwoLinesBtn->get_active()); + m_aPreviewWin.Invalidate(); +} + +void SvxCharTwoLinesPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false); + if (pFlagItem) + { + sal_uInt32 nFlags=pFlagItem->GetValue(); + if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER ) + // the writer uses SID_ATTR_BRUSH as font background + m_bPreviewBackgroundToCharacter = true; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/chardlg.h b/cui/source/tabpages/chardlg.h new file mode 100644 index 000000000..4a52cb24b --- /dev/null +++ b/cui/source/tabpages/chardlg.h @@ -0,0 +1,26 @@ +/* -*- 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 . + */ +#pragma once + +// define ---------------------------------------------------------------- + +#define CHRDLG_POSITION_OVER 0 +#define CHRDLG_POSITION_UNDER 1 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/connect.cxx b/cui/source/tabpages/connect.cxx new file mode 100644 index 000000000..d668a2a6b --- /dev/null +++ b/cui/source/tabpages/connect.cxx @@ -0,0 +1,415 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include <dialmgr.hxx> + +#include <svx/connctrl.hxx> +#include <svx/svxids.hrc> +#include <svx/dlgutil.hxx> +#include <svx/ofaitem.hxx> + +#include <svx/svdview.hxx> +#include <svx/sxekitm.hxx> +#include <svx/sxelditm.hxx> +#include <svx/sxenditm.hxx> +#include <svtools/unitconv.hxx> + +#include <connect.hxx> + +const WhichRangesContainer SvxConnectionPage::pRanges( + svl::Items<SDRATTR_EDGE_FIRST, SDRATTR_EDGE_LAST>); + +/************************************************************************* +|* +|* dialog for changing connectors +|* +\************************************************************************/ +SvxConnectionDialog::SvxConnectionDialog(weld::Window* pParent, const SfxItemSet& rInAttrs, const SdrView* pSdrView) + : SfxSingleTabDialogController(pParent, &rInAttrs) +{ + auto xPage = std::make_unique<SvxConnectionPage>(get_content_area(), this, rInAttrs); + + xPage->SetView(pSdrView); + xPage->Construct(); + + SetTabPage(std::move(xPage)); + m_xDialog->set_title(CuiResId(RID_CUISTR_CONNECTOR)); +} + +/************************************************************************* +|* +|* page for changing connectors +|* +\************************************************************************/ + +SvxConnectionPage::SvxConnectionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/connectortabpage.ui", "ConnectorTabPage", &rInAttrs) + , rOutAttrs(rInAttrs) + , aAttrSet(*rInAttrs.GetPool()) + , pView(nullptr) + , m_xLbType(m_xBuilder->weld_combo_box("LB_TYPE")) + , m_xFtLine1(m_xBuilder->weld_label("FT_LINE_1")) + , m_xMtrFldLine1(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_1", FieldUnit::CM)) + , m_xFtLine2(m_xBuilder->weld_label("FT_LINE_2")) + , m_xMtrFldLine2(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_2", FieldUnit::CM)) + , m_xFtLine3(m_xBuilder->weld_label("FT_LINE_3")) + , m_xMtrFldLine3(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_3", FieldUnit::CM)) + , m_xMtrFldHorz1(m_xBuilder->weld_metric_spin_button("MTR_FLD_HORZ_1", FieldUnit::MM)) + , m_xMtrFldVert1(m_xBuilder->weld_metric_spin_button("MTR_FLD_VERT_1", FieldUnit::MM)) + , m_xMtrFldHorz2(m_xBuilder->weld_metric_spin_button("MTR_FLD_HORZ_2", FieldUnit::MM)) + , m_xMtrFldVert2(m_xBuilder->weld_metric_spin_button("MTR_FLD_VERT_2", FieldUnit::MM)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + SfxItemPool* pPool = rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool" ); + eUnit = pPool->GetMetric( SDRATTR_EDGENODE1HORZDIST ); + + FillTypeLB(); + + const FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xMtrFldHorz1, eFUnit ); + SetFieldUnit( *m_xMtrFldHorz2, eFUnit ); + SetFieldUnit( *m_xMtrFldVert1, eFUnit ); + SetFieldUnit( *m_xMtrFldVert2, eFUnit ); + SetFieldUnit( *m_xMtrFldLine1, eFUnit ); + SetFieldUnit( *m_xMtrFldLine2, eFUnit ); + SetFieldUnit( *m_xMtrFldLine3, eFUnit ); + if( eFUnit == FieldUnit::MM ) + { + m_xMtrFldHorz1->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHorz2->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldVert1->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldVert2->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldLine1->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldLine2->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldLine3->set_increments(50, 500, FieldUnit::NONE); + } + + Link<weld::MetricSpinButton&,void> aLink(LINK(this, SvxConnectionPage, ChangeAttrEditHdl_Impl)); + m_xMtrFldHorz1->connect_value_changed(aLink); + m_xMtrFldVert1->connect_value_changed(aLink); + m_xMtrFldHorz2->connect_value_changed(aLink); + m_xMtrFldVert2->connect_value_changed(aLink); + m_xMtrFldLine1->connect_value_changed(aLink); + m_xMtrFldLine2->connect_value_changed(aLink); + m_xMtrFldLine3->connect_value_changed(aLink); + m_xLbType->connect_changed(LINK(this, SvxConnectionPage, ChangeAttrListBoxHdl_Impl)); +} + +SvxConnectionPage::~SvxConnectionPage() +{ + m_xCtlPreview.reset(); +} + +/************************************************************************* +|* +|* reads passed Item-Set +|* +\************************************************************************/ + +void SvxConnectionPage::Reset( const SfxItemSet* rAttrs ) +{ + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_EDGENODE1HORZDIST ); + const SfxItemPool* pPool = rAttrs->GetPool(); + + // SdrEdgeNode1HorzDistItem + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE1HORZDIST ); + SetMetricValue(*m_xMtrFldHorz1, static_cast<const SdrEdgeNode1HorzDistItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldHorz1->save_value(); + + // SdrEdgeNode2HorzDistItem + pItem = GetItem( *rAttrs, SDRATTR_EDGENODE2HORZDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE2HORZDIST ); + SetMetricValue(*m_xMtrFldHorz2, static_cast<const SdrEdgeNode2HorzDistItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldHorz2->save_value(); + + // SdrEdgeNode1VertDistItem + pItem = GetItem( *rAttrs, SDRATTR_EDGENODE1VERTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE1VERTDIST ); + SetMetricValue(*m_xMtrFldVert1, static_cast<const SdrEdgeNode1VertDistItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldVert1->save_value(); + + // SdrEdgeNode2VertDistItem + pItem = GetItem( *rAttrs, SDRATTR_EDGENODE2VERTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGENODE2VERTDIST ); + SetMetricValue(*m_xMtrFldVert2, static_cast<const SdrEdgeNode2VertDistItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldVert2->save_value(); + + // SdrEdgeLine1DeltaItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINE1DELTA ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINE1DELTA ); + SetMetricValue(*m_xMtrFldLine1, static_cast<const SdrMetricItem*>(pItem)->GetValue(), eUnit); + m_xMtrFldLine1->save_value(); + + // SdrEdgeLine2DeltaItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINE2DELTA ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINE2DELTA ); + SetMetricValue(*m_xMtrFldLine2, static_cast<const SdrMetricItem*>(pItem)->GetValue(), eUnit); + m_xMtrFldLine2->save_value(); + + // SdrEdgeLine3DeltaItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINE3DELTA ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINE3DELTA ); + SetMetricValue(*m_xMtrFldLine3, static_cast<const SdrMetricItem*>(pItem)->GetValue(), eUnit); + m_xMtrFldLine3->save_value(); + + // SdrEdgeLineDeltaAnzItem + pItem = GetItem( *rAttrs, SDRATTR_EDGELINEDELTACOUNT ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGELINEDELTACOUNT ); + switch (static_cast<const SdrEdgeLineDeltaCountItem*>(pItem)->GetValue()) + { + case 0: + m_xFtLine1->set_sensitive(false); + m_xMtrFldLine1->set_sensitive(false); + m_xMtrFldLine1->set_text(""); + [[fallthrough]]; + case 1: + m_xFtLine2->set_sensitive(false); + m_xMtrFldLine2->set_sensitive(false); + m_xMtrFldLine2->set_text(""); + [[fallthrough]]; + case 2: + m_xFtLine3->set_sensitive(false); + m_xMtrFldLine3->set_sensitive(false); + m_xMtrFldLine3->set_text(""); + break; + } + + // SdrEdgeKindItem + pItem = GetItem( *rAttrs, SDRATTR_EDGEKIND ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGEKIND ); + m_xLbType->set_active( + sal::static_int_cast<sal_uInt16>(static_cast<const SdrEdgeKindItem*>(pItem)->GetValue())); + m_xLbType->save_value(); +} + +/************************************************************************* +|* +|* fills the passed Item-Set width Dialogbox attributes +|* +\************************************************************************/ + +bool SvxConnectionPage::FillItemSet( SfxItemSet* rAttrs) +{ + bool bModified = false; + sal_Int32 nValue; + + if (m_xMtrFldHorz1->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldHorz1, eUnit); + rAttrs->Put( SdrEdgeNode1HorzDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldHorz2->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldHorz2, eUnit); + rAttrs->Put( SdrEdgeNode2HorzDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldVert1->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldVert1, eUnit); + rAttrs->Put( SdrEdgeNode1VertDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldVert2->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldVert2, eUnit); + rAttrs->Put( SdrEdgeNode2VertDistItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldLine1->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldLine1, eUnit); + rAttrs->Put( makeSdrEdgeLine1DeltaItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldLine2->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldLine2, eUnit); + rAttrs->Put( makeSdrEdgeLine2DeltaItem( nValue ) ); + bModified = true; + } + + if (m_xMtrFldLine3->get_value_changed_from_saved()) + { + nValue = GetCoreValue(*m_xMtrFldLine3, eUnit); + rAttrs->Put( makeSdrEdgeLine3DeltaItem( nValue ) ); + bModified = true; + } + + int nPos = m_xLbType->get_active(); + if (m_xLbType->get_value_changed_from_saved()) + { + if (nPos != -1) + { + rAttrs->Put( SdrEdgeKindItem( static_cast<SdrEdgeKind>(nPos) ) ); + bModified = true; + } + } + + return bModified; +} + +void SvxConnectionPage::Construct() +{ + DBG_ASSERT( pView, "No valid View transfer!" ); + + m_aCtlPreview.SetView(pView); + m_aCtlPreview.Construct(); +} + +/************************************************************************* +|* +|* creates the page +|* +\************************************************************************/ +std::unique_ptr<SfxTabPage> SvxConnectionPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxConnectionPage>(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxConnectionPage, ChangeAttrListBoxHdl_Impl, weld::ComboBox&, void) +{ + int nPos = m_xLbType->get_active(); + if (nPos != -1) + { + aAttrSet.Put( SdrEdgeKindItem( static_cast<SdrEdgeKind>(nPos) ) ); + } + + m_aCtlPreview.SetAttributes(aAttrSet); + + // get the number of line displacements + sal_uInt16 nCount = m_aCtlPreview.GetLineDeltaCount(); + + m_xFtLine3->set_sensitive( nCount > 2 ); + m_xMtrFldLine3->set_sensitive( nCount > 2 ); + if( nCount > 2 ) + m_xMtrFldLine3->set_value(m_xMtrFldLine3->get_value(FieldUnit::NONE), FieldUnit::NONE); + else + m_xMtrFldLine3->set_text(""); + + m_xFtLine2->set_sensitive( nCount > 1 ); + m_xMtrFldLine2->set_sensitive( nCount > 1 ); + if( nCount > 1 ) + m_xMtrFldLine2->set_value(m_xMtrFldLine2->get_value(FieldUnit::NONE), FieldUnit::NONE); + else + m_xMtrFldLine2->set_text(""); + + m_xFtLine1->set_sensitive( nCount > 0 ); + m_xMtrFldLine1->set_sensitive( nCount > 0 ); + if( nCount > 0 ) + m_xMtrFldLine1->set_value(m_xMtrFldLine1->get_value(FieldUnit::NONE), FieldUnit::NONE); + else + m_xMtrFldLine1->set_text(""); +} + +IMPL_LINK(SvxConnectionPage, ChangeAttrEditHdl_Impl, weld::MetricSpinButton&, r, void) +{ + if (&r == m_xMtrFldHorz1.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldHorz1, eUnit); + aAttrSet.Put( SdrEdgeNode1HorzDistItem( nValue ) ); + } + + if (&r == m_xMtrFldHorz2.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHorz2, eUnit ); + aAttrSet.Put( SdrEdgeNode2HorzDistItem( nValue ) ); + } + + if (&r == m_xMtrFldVert1.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldVert1, eUnit); + aAttrSet.Put( SdrEdgeNode1VertDistItem( nValue ) ); + } + + if (&r == m_xMtrFldVert2.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldVert2, eUnit); + aAttrSet.Put( SdrEdgeNode2VertDistItem( nValue ) ); + } + + if (&r == m_xMtrFldLine1.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldLine1, eUnit); + aAttrSet.Put( makeSdrEdgeLine1DeltaItem( nValue ) ); + } + + if (&r == m_xMtrFldLine2.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldLine2, eUnit); + aAttrSet.Put( makeSdrEdgeLine2DeltaItem( nValue ) ); + } + + if (&r == m_xMtrFldLine3.get()) + { + sal_Int32 nValue = GetCoreValue(*m_xMtrFldLine3, eUnit); + aAttrSet.Put( makeSdrEdgeLine3DeltaItem( nValue ) ); + } + + m_aCtlPreview.SetAttributes(aAttrSet); +} + +void SvxConnectionPage::FillTypeLB() +{ + // fill ListBox with connector names + const SfxPoolItem* pItem = GetItem( rOutAttrs, SDRATTR_EDGEKIND ); + const SfxItemPool* pPool = rOutAttrs.GetPool(); + + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_EDGEKIND ); + const SdrEdgeKindItem* pEdgeKindItem = static_cast<const SdrEdgeKindItem*>(pItem); + const sal_uInt16 nCount = pEdgeKindItem->GetValueCount(); + for (sal_uInt16 i = 0; i < nCount; i++) + { + OUString aStr = SdrEdgeKindItem::GetValueTextByPos(i); + m_xLbType->append_text(aStr); + } +} +void SvxConnectionPage::PageCreated(const SfxAllItemSet& aSet) +{ + const OfaPtrItem* pOfaPtrItem = aSet.GetItem<OfaPtrItem>(SID_OBJECT_LIST, false); + if (pOfaPtrItem) + SetView( static_cast<SdrView *>(pOfaPtrItem->GetValue()) ); + + Construct(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/grfpage.cxx b/cui/source/tabpages/grfpage.cxx new file mode 100644 index 000000000..1bbc73c3a --- /dev/null +++ b/cui/source/tabpages/grfpage.cxx @@ -0,0 +1,806 @@ +/* -*- 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 . + */ + +#include <memory> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <dialmgr.hxx> +#include <svx/dlgutil.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/brushitem.hxx> +#include <grfpage.hxx> +#include <svx/grfcrop.hxx> +#include <rtl/ustring.hxx> +#include <tools/debug.hxx> +#include <tools/fract.hxx> +#include <svx/svxids.hrc> +#include <strings.hrc> +#include <vcl/fieldvalues.hxx> +#include <vcl/outdev.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <svtools/unitconv.hxx> +#include <svtools/optionsdrawinglayer.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <o3tl/unit_conversion.hxx> + +constexpr auto CM_1_TO_TWIP = o3tl::convert(1, o3tl::Length::cm, o3tl::Length::twip); // 567 + + +static int lcl_GetValue(const weld::MetricSpinButton& rMetric, FieldUnit eUnit) +{ + return rMetric.denormalize(rMetric.get_value(eUnit)); +} + +/*-------------------------------------------------------------------- + description: crop graphic + --------------------------------------------------------------------*/ + +SvxGrfCropPage::SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "cui/ui/croppage.ui", "CropPage", &rSet) + , m_nOldWidth(0) + , m_nOldHeight(0) + , m_bSetOrigSize(false) + , m_aPreferredDPI(0) + , m_xCropFrame(m_xBuilder->weld_widget("cropframe")) + , m_xZoomConstRB(m_xBuilder->weld_radio_button("keepscale")) + , m_xSizeConstRB(m_xBuilder->weld_radio_button("keepsize")) + , m_xLeftMF(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM)) + , m_xRightMF(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM)) + , m_xTopMF(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM)) + , m_xBottomMF(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM)) + , m_xScaleFrame(m_xBuilder->weld_widget("scaleframe")) + , m_xWidthZoomMF(m_xBuilder->weld_metric_spin_button("widthzoom", FieldUnit::PERCENT)) + , m_xHeightZoomMF(m_xBuilder->weld_metric_spin_button("heightzoom", FieldUnit::PERCENT)) + , m_xSizeFrame(m_xBuilder->weld_widget("sizeframe")) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM)) + , m_xHeightMF(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM)) + , m_xOrigSizeGrid(m_xBuilder->weld_widget("origsizegrid")) + , m_xOrigSizeFT(m_xBuilder->weld_label("origsizeft")) + , m_xOrigSizePB(m_xBuilder->weld_button("origsize")) + , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN)) +{ + SetExchangeSupport(); + + // set the correct metric + const FieldUnit eMetric = GetModuleFieldUnit( rSet ); + + SetFieldUnit( *m_xWidthMF, eMetric ); + SetFieldUnit( *m_xHeightMF, eMetric ); + SetFieldUnit( *m_xLeftMF, eMetric ); + SetFieldUnit( *m_xRightMF, eMetric ); + SetFieldUnit( *m_xTopMF , eMetric ); + SetFieldUnit( *m_xBottomMF, eMetric ); + + Link<weld::MetricSpinButton&,void> aLk = LINK(this, SvxGrfCropPage, SizeHdl); + m_xWidthMF->connect_value_changed( aLk ); + m_xHeightMF->connect_value_changed( aLk ); + + aLk = LINK(this, SvxGrfCropPage, ZoomHdl); + m_xWidthZoomMF->connect_value_changed( aLk ); + m_xHeightZoomMF->connect_value_changed( aLk ); + + aLk = LINK(this, SvxGrfCropPage, CropModifyHdl); + m_xLeftMF->connect_value_changed( aLk ); + m_xRightMF->connect_value_changed( aLk ); + m_xTopMF->connect_value_changed( aLk ); + m_xBottomMF->connect_value_changed( aLk ); + + m_xOrigSizePB->connect_clicked(LINK(this, SvxGrfCropPage, OrigSizeHdl)); +} + +SvxGrfCropPage::~SvxGrfCropPage() +{ + m_xExampleWN.reset(); +} + +std::unique_ptr<SfxTabPage> SvxGrfCropPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SvxGrfCropPage>(pPage, pController, *rSet); +} + +void SvxGrfCropPage::Reset( const SfxItemSet *rSet ) +{ + const SfxPoolItem* pItem; + const SfxItemPool& rPool = *rSet->GetPool(); + + if(SfxItemState::SET == rSet->GetItemState( rPool.GetWhich( + SID_ATTR_GRAF_KEEP_ZOOM ), true, &pItem )) + { + if( static_cast<const SfxBoolItem*>(pItem)->GetValue() ) + m_xZoomConstRB->set_active(true); + else + m_xSizeConstRB->set_active(true); + m_xZoomConstRB->save_state(); + } + + sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP ); + if( SfxItemState::SET == rSet->GetItemState( nW, true, &pItem)) + { + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + + const SvxGrfCrop* pCrop = static_cast<const SvxGrfCrop*>(pItem); + + m_aExampleWN.SetLeft(pCrop->GetLeft()); + m_aExampleWN.SetRight(pCrop->GetRight()); + m_aExampleWN.SetTop(pCrop->GetTop()); + m_aExampleWN.SetBottom(pCrop->GetBottom()); + + m_xLeftMF->set_value( m_xLeftMF->normalize( pCrop->GetLeft()), eUnit ); + m_xRightMF->set_value( m_xRightMF->normalize( pCrop->GetRight()), eUnit ); + m_xTopMF->set_value( m_xTopMF->normalize( pCrop->GetTop()), eUnit ); + m_xBottomMF->set_value( m_xBottomMF->normalize( pCrop->GetBottom()), eUnit ); + } + else + { + m_xLeftMF->set_value(0, FieldUnit::NONE); + m_xRightMF->set_value(0, FieldUnit::NONE); + m_xTopMF->set_value(0, FieldUnit::NONE); + m_xBottomMF->set_value(0, FieldUnit::NONE); + } + + m_xLeftMF->save_value(); + m_xRightMF->save_value(); + m_xTopMF->save_value(); + m_xBottomMF->save_value(); + + nW = rPool.GetWhich( SID_ATTR_PAGE_SIZE ); + if ( SfxItemState::SET == rSet->GetItemState( nW, false, &pItem ) ) + { + // orientation and size from the PageItem + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + + m_aPageSize = static_cast<const SvxSizeItem*>(pItem)->GetSize(); + + auto nMin = m_xWidthMF->normalize( 23 ); + auto nMax = m_xHeightMF->normalize(m_aPageSize.Height()); + m_xHeightMF->set_range(nMin, nMax, eUnit); + nMax = m_xWidthMF->normalize(m_aPageSize.Width()); + m_xWidthMF->set_range(nMin, nMax, eUnit); + } + else + { + m_aPageSize = OutputDevice::LogicToLogic( + Size( CM_1_TO_TWIP, CM_1_TO_TWIP ), + MapMode( MapUnit::MapTwip ), + MapMode( rSet->GetPool()->GetMetric( nW ) ) ); + } + + bool bFound = false; + if( const SvxBrushItem* pGraphicItem = rSet->GetItemIfSet( SID_ATTR_GRAF_GRAPHIC, false ) ) + { + OUString referer; + SfxStringItem const * it = static_cast<SfxStringItem const *>( + rSet->GetItem(SID_REFERER)); + if (it != nullptr) { + referer = it->GetValue(); + } + const Graphic* pGrf = pGraphicItem->GetGraphic(referer); + if( pGrf ) + { + m_aOrigSize = GetGrfOrigSize( *pGrf ); + if (pGrf->GetType() == GraphicType::Bitmap && m_aOrigSize.Width() && m_aOrigSize.Height()) + { + m_aOrigPixelSize = pGrf->GetSizePixel(); + } + + if( m_aOrigSize.Width() && m_aOrigSize.Height() ) + { + CalcMinMaxBorder(); + m_aExampleWN.SetGraphic( *pGrf ); + m_aExampleWN.SetFrameSize( m_aOrigSize ); + + bFound = true; + if( !pGraphicItem->GetGraphicLink().isEmpty() ) + m_aGraphicName = pGraphicItem->GetGraphicLink(); + } + } + } + + GraphicHasChanged( bFound ); + ActivatePage( *rSet ); +} + +bool SvxGrfCropPage::FillItemSet(SfxItemSet *rSet) +{ + const SfxItemPool& rPool = *rSet->GetPool(); + bool bModified = false; + if( m_xWidthMF->get_value_changed_from_saved() || + m_xHeightMF->get_value_changed_from_saved() ) + { + constexpr TypedWhichId<SvxSizeItem> nW = SID_ATTR_GRAF_FRMSIZE; + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + + std::shared_ptr<SvxSizeItem> aSz(std::make_shared<SvxSizeItem>(nW)); + + // size could already have been set from another page + const SfxItemSet* pExSet = GetDialogExampleSet(); + const SvxSizeItem* pSizeItem = nullptr; + if( pExSet && (pSizeItem = pExSet->GetItemIfSet( nW, false )) ) + { + aSz.reset(pSizeItem->Clone()); + } + else + { + aSz.reset(GetItemSet().Get(nW).Clone()); + } + + Size aTmpSz( aSz->GetSize() ); + if( m_xWidthMF->get_value_changed_from_saved() ) + aTmpSz.setWidth( lcl_GetValue( *m_xWidthMF, eUnit ) ); + if( m_xHeightMF->get_value_changed_from_saved() ) + aTmpSz.setHeight( lcl_GetValue( *m_xHeightMF, eUnit ) ); + aSz->SetSize( aTmpSz ); + m_xWidthMF->save_value(); + m_xHeightMF->save_value(); + + bModified |= nullptr != rSet->Put( *aSz ); + + if (m_bSetOrigSize) + { + bModified |= nullptr != rSet->Put( SvxSizeItem( rPool.GetWhich( + SID_ATTR_GRAF_FRMSIZE_PERCENT ), Size( 0, 0 )) ); + } + } + if( m_xLeftMF->get_value_changed_from_saved() || m_xRightMF->get_value_changed_from_saved() || + m_xTopMF->get_value_changed_from_saved() || m_xBottomMF->get_value_changed_from_saved() ) + { + sal_uInt16 nW = rPool.GetWhich( SID_ATTR_GRAF_CROP ); + FieldUnit eUnit = MapToFieldUnit( rSet->GetPool()->GetMetric( nW )); + std::unique_ptr<SvxGrfCrop> pNew(static_cast<SvxGrfCrop*>(rSet->Get( nW ).Clone())); + + pNew->SetLeft( lcl_GetValue( *m_xLeftMF, eUnit ) ); + pNew->SetRight( lcl_GetValue( *m_xRightMF, eUnit ) ); + pNew->SetTop( lcl_GetValue( *m_xTopMF, eUnit ) ); + pNew->SetBottom( lcl_GetValue( *m_xBottomMF, eUnit ) ); + bModified |= nullptr != rSet->Put( std::move(pNew) ); + } + + if( m_xZoomConstRB->get_state_changed_from_saved() ) + { + bModified |= nullptr != rSet->Put( SfxBoolItem( rPool.GetWhich( + SID_ATTR_GRAF_KEEP_ZOOM), m_xZoomConstRB->get_active() ) ); + } + + return bModified; +} + +void SvxGrfCropPage::ActivatePage(const SfxItemSet& rSet) +{ +#ifdef DBG_UTIL + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); +#endif + + auto& aProperties = getAdditionalProperties(); + auto aIterator = aProperties.find("PreferredDPI"); + if (aIterator != aProperties.end()) + m_aPreferredDPI = aIterator->second.get<sal_Int32>(); + + m_bSetOrigSize = false; + + // Size + Size aSize; + if( const SvxSizeItem* pFrmSizeItem = rSet.GetItemIfSet( SID_ATTR_GRAF_FRMSIZE, false ) ) + aSize = pFrmSizeItem->GetSize(); + + m_nOldWidth = aSize.Width(); + m_nOldHeight = aSize.Height(); + + auto nWidth = m_xWidthMF->normalize(m_nOldWidth); + auto nHeight = m_xHeightMF->normalize(m_nOldHeight); + + if (nWidth != m_xWidthMF->get_value(FieldUnit::TWIP)) + m_xWidthMF->set_value(nWidth, FieldUnit::TWIP); + m_xWidthMF->save_value(); + + if (nHeight != m_xHeightMF->get_value(FieldUnit::TWIP)) + m_xHeightMF->set_value(nHeight, FieldUnit::TWIP); + m_xHeightMF->save_value(); + + if( const SvxBrushItem* pBrushItem = rSet.GetItemIfSet( SID_ATTR_GRAF_GRAPHIC, false ) ) + { + if( !pBrushItem->GetGraphicLink().isEmpty() && + m_aGraphicName != pBrushItem->GetGraphicLink() ) + m_aGraphicName = pBrushItem->GetGraphicLink(); + + OUString referer; + SfxStringItem const * it = static_cast<SfxStringItem const *>( + rSet.GetItem(SID_REFERER)); + if (it != nullptr) { + referer = it->GetValue(); + } + const Graphic* pGrf = pBrushItem->GetGraphic(referer); + if( pGrf ) + { + m_aExampleWN.SetGraphic( *pGrf ); + m_aOrigSize = GetGrfOrigSize( *pGrf ); + if (pGrf->GetType() == GraphicType::Bitmap && m_aOrigSize.Width() > 1 && m_aOrigSize.Height() > 1) { + m_aOrigPixelSize = pGrf->GetSizePixel(); + } + m_aExampleWN.SetFrameSize(m_aOrigSize); + GraphicHasChanged( m_aOrigSize.Width() && m_aOrigSize.Height() ); + CalcMinMaxBorder(); + } + else + GraphicHasChanged( false ); + } + + CalcZoom(); +} + +DeactivateRC SvxGrfCropPage::DeactivatePage(SfxItemSet *_pSet) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +/*-------------------------------------------------------------------- + description: scale changed, adjust size + --------------------------------------------------------------------*/ + +IMPL_LINK( SvxGrfCropPage, ZoomHdl, weld::MetricSpinButton&, rField, void ) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + if (&rField == m_xWidthZoomMF.get()) + { + tools::Long nLRBorders = lcl_GetValue(*m_xLeftMF, eUnit) + +lcl_GetValue(*m_xRightMF, eUnit); + m_xWidthMF->set_value( m_xWidthMF->normalize( + ((m_aOrigSize.Width() - nLRBorders) * rField.get_value(FieldUnit::NONE))/100), + eUnit); + } + else + { + tools::Long nULBorders = lcl_GetValue(*m_xTopMF, eUnit) + +lcl_GetValue(*m_xBottomMF, eUnit); + m_xHeightMF->set_value( m_xHeightMF->normalize( + ((m_aOrigSize.Height() - nULBorders ) * rField.get_value(FieldUnit::NONE))/100) , + eUnit ); + } +} + +/*-------------------------------------------------------------------- + description: change size, adjust scale + --------------------------------------------------------------------*/ + +IMPL_LINK( SvxGrfCropPage, SizeHdl, weld::MetricSpinButton&, rField, void ) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + Size aSize( lcl_GetValue(*m_xWidthMF, eUnit), + lcl_GetValue(*m_xHeightMF, eUnit) ); + + if(&rField == m_xWidthMF.get()) + { + tools::Long nWidth = m_aOrigSize.Width() - + ( lcl_GetValue(*m_xLeftMF, eUnit) + + lcl_GetValue(*m_xRightMF, eUnit) ); + if(!nWidth) + nWidth++; + sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Width() * 100 / nWidth); + m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE); + } + else + { + tools::Long nHeight = m_aOrigSize.Height() - + ( lcl_GetValue(*m_xTopMF, eUnit) + + lcl_GetValue(*m_xBottomMF, eUnit)); + if(!nHeight) + nHeight++; + sal_uInt16 nZoom = static_cast<sal_uInt16>( aSize.Height() * 100 / nHeight); + m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE); + } +} + +/*-------------------------------------------------------------------- + description: evaluate border + --------------------------------------------------------------------*/ + +IMPL_LINK( SvxGrfCropPage, CropModifyHdl, weld::MetricSpinButton&, rField, void ) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + bool bZoom = m_xZoomConstRB->get_active(); + if (&rField == m_xLeftMF.get() || &rField == m_xRightMF.get()) + { + tools::Long nLeft = lcl_GetValue( *m_xLeftMF, eUnit ); + tools::Long nRight = lcl_GetValue( *m_xRightMF, eUnit ); + tools::Long nWidthZoom = static_cast<tools::Long>(m_xWidthZoomMF->get_value(FieldUnit::NONE)); + if (bZoom && nWidthZoom != 0 && ( ( ( m_aOrigSize.Width() - (nLeft + nRight )) * nWidthZoom ) + / 100 >= m_aPageSize.Width() ) ) + { + if (&rField == m_xLeftMF.get()) + { + nLeft = m_aOrigSize.Width() - + ( m_aPageSize.Width() * 100 / nWidthZoom + nRight ); + m_xLeftMF->set_value( m_xLeftMF->normalize( nLeft ), eUnit ); + } + else + { + nRight = m_aOrigSize.Width() - + ( m_aPageSize.Width() * 100 / nWidthZoom + nLeft ); + m_xRightMF->set_value( m_xRightMF->normalize( nRight ), eUnit ); + } + } + if (AllSettings::GetLayoutRTL()) + { + m_aExampleWN.SetLeft(nRight); + m_aExampleWN.SetRight(nLeft); + } + else + { + m_aExampleWN.SetLeft(nLeft); + m_aExampleWN.SetRight(nRight); + } + if(bZoom) + { + // scale stays, recompute width + ZoomHdl(*m_xWidthZoomMF); + } + } + else + { + tools::Long nTop = lcl_GetValue( *m_xTopMF, eUnit ); + tools::Long nBottom = lcl_GetValue( *m_xBottomMF, eUnit ); + tools::Long nHeightZoom = static_cast<tools::Long>(m_xHeightZoomMF->get_value(FieldUnit::NONE)); + if(bZoom && ( ( ( m_aOrigSize.Height() - (nTop + nBottom )) * nHeightZoom) + / 100 >= m_aPageSize.Height())) + { + assert(nHeightZoom && "div-by-zero"); + if(&rField == m_xTopMF.get()) + { + nTop = m_aOrigSize.Height() - + ( m_aPageSize.Height() * 100 / nHeightZoom + nBottom); + m_xTopMF->set_value( m_xWidthMF->normalize( nTop ), eUnit ); + } + else + { + nBottom = m_aOrigSize.Height() - + ( m_aPageSize.Height() * 100 / nHeightZoom + nTop); + m_xBottomMF->set_value( m_xWidthMF->normalize( nBottom ), eUnit ); + } + } + m_aExampleWN.SetTop( nTop ); + m_aExampleWN.SetBottom( nBottom ); + if(bZoom) + { + // scale stays, recompute height + ZoomHdl(*m_xHeightZoomMF); + } + } + m_aExampleWN.Invalidate(); + // size and border changed -> recompute scale + if(!bZoom) + CalcZoom(); + CalcMinMaxBorder(); +} +/*-------------------------------------------------------------------- + description: set original size + --------------------------------------------------------------------*/ + +IMPL_LINK_NOARG(SvxGrfCropPage, OrigSizeHdl, weld::Button&, void) +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + tools::Long nWidth = m_aOrigSize.Width() - + lcl_GetValue( *m_xLeftMF, eUnit ) - + lcl_GetValue( *m_xRightMF, eUnit ); + m_xWidthMF->set_value( m_xWidthMF->normalize( nWidth ), eUnit ); + tools::Long nHeight = m_aOrigSize.Height() - + lcl_GetValue( *m_xTopMF, eUnit ) - + lcl_GetValue( *m_xBottomMF, eUnit ); + m_xHeightMF->set_value( m_xHeightMF->normalize( nHeight ), eUnit ); + m_xWidthZoomMF->set_value(100, FieldUnit::NONE); + m_xHeightZoomMF->set_value(100, FieldUnit::NONE); + m_bSetOrigSize = true; +} +/*-------------------------------------------------------------------- + description: compute scale + --------------------------------------------------------------------*/ + +void SvxGrfCropPage::CalcZoom() +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + + tools::Long nWidth = lcl_GetValue( *m_xWidthMF, eUnit ); + tools::Long nHeight = lcl_GetValue( *m_xHeightMF, eUnit ); + tools::Long nLRBorders = lcl_GetValue( *m_xLeftMF, eUnit ) + + lcl_GetValue( *m_xRightMF, eUnit ); + tools::Long nULBorders = lcl_GetValue( *m_xTopMF, eUnit ) + + lcl_GetValue( *m_xBottomMF, eUnit ); + sal_uInt16 nZoom = 0; + tools::Long nDen; + if( (nDen = m_aOrigSize.Width() - nLRBorders) > 0) + nZoom = static_cast<sal_uInt16>((( nWidth * 1000 / nDen )+5)/10); + m_xWidthZoomMF->set_value(nZoom, FieldUnit::NONE); + if( (nDen = m_aOrigSize.Height() - nULBorders) > 0) + nZoom = static_cast<sal_uInt16>((( nHeight * 1000 / nDen )+5)/10); + else + nZoom = 0; + m_xHeightZoomMF->set_value(nZoom, FieldUnit::NONE); +} + +/*-------------------------------------------------------------------- + description: set minimum/maximum values for the margins + --------------------------------------------------------------------*/ + +void SvxGrfCropPage::CalcMinMaxBorder() +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) ) ); + tools::Long nR = lcl_GetValue(*m_xRightMF, eUnit ); + tools::Long nMinWidth = (m_aOrigSize.Width() * 10) /11; + tools::Long nMin = nMinWidth - (nR >= 0 ? nR : 0); + m_xLeftMF->set_max( m_xLeftMF->normalize(nMin), eUnit ); + + tools::Long nL = lcl_GetValue(*m_xLeftMF, eUnit ); + nMin = nMinWidth - (nL >= 0 ? nL : 0); + m_xRightMF->set_max( m_xRightMF->normalize(nMin), eUnit ); + + tools::Long nUp = lcl_GetValue( *m_xTopMF, eUnit ); + tools::Long nMinHeight = (m_aOrigSize.Height() * 10) /11; + nMin = nMinHeight - (nUp >= 0 ? nUp : 0); + m_xBottomMF->set_max( m_xBottomMF->normalize(nMin), eUnit ); + + tools::Long nLow = lcl_GetValue(*m_xBottomMF, eUnit ); + nMin = nMinHeight - (nLow >= 0 ? nLow : 0); + m_xTopMF->set_max( m_xTopMF->normalize(nMin), eUnit ); +} +/*-------------------------------------------------------------------- + description: set spinsize to 1/20 of the original size, + fill FixedText with the original size + --------------------------------------------------------------------*/ + +void SvxGrfCropPage::GraphicHasChanged( bool bFound ) +{ + if( bFound ) + { + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( pPool->GetWhich( + SID_ATTR_GRAF_CROP ) )); + + sal_Int64 nSpin = m_xLeftMF->normalize(m_aOrigSize.Width()) / 20; + nSpin = vcl::ConvertValue( nSpin, m_aOrigSize.Width(), 0, + eUnit, m_xLeftMF->get_unit()); + + // if the margin is too big, it is set to 1/3 on both pages + tools::Long nR = lcl_GetValue( *m_xRightMF, eUnit ); + tools::Long nL = lcl_GetValue( *m_xLeftMF, eUnit ); + if((nL + nR) < - m_aOrigSize.Width()) + { + tools::Long nVal = m_aOrigSize.Width() / -3; + m_xRightMF->set_value( m_xRightMF->normalize( nVal ), eUnit ); + m_xLeftMF->set_value( m_xLeftMF->normalize( nVal ), eUnit ); + m_aExampleWN.SetLeft(nVal); + m_aExampleWN.SetRight(nVal); + } + tools::Long nUp = lcl_GetValue(*m_xTopMF, eUnit ); + tools::Long nLow = lcl_GetValue(*m_xBottomMF, eUnit ); + if((nUp + nLow) < - m_aOrigSize.Height()) + { + tools::Long nVal = m_aOrigSize.Height() / -3; + m_xTopMF->set_value( m_xTopMF->normalize( nVal ), eUnit ); + m_xBottomMF->set_value( m_xBottomMF->normalize( nVal ), eUnit ); + m_aExampleWN.SetTop(nVal); + m_aExampleWN.SetBottom(nVal); + } + + m_xLeftMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + m_xRightMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + nSpin = m_xTopMF->normalize(m_aOrigSize.Height()) / 20; + nSpin = vcl::ConvertValue( nSpin, m_aOrigSize.Width(), 0, + eUnit, m_xLeftMF->get_unit() ); + m_xTopMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + m_xBottomMF->set_increments(nSpin, nSpin * 10, FieldUnit::NONE); + + // display original size + const FieldUnit eMetric = GetModuleFieldUnit( GetItemSet() ); + + OUString sTemp; + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/spinbox.ui")); + std::unique_ptr<weld::Dialog> xTopLevel(xBuilder->weld_dialog("SpinDialog")); + std::unique_ptr<weld::MetricSpinButton> xFld(xBuilder->weld_metric_spin_button("spin", FieldUnit::CM)); + SetFieldUnit( *xFld, eMetric ); + xFld->set_digits(m_xWidthMF->get_digits()); + xFld->set_max(INT_MAX - 1, FieldUnit::NONE); + + xFld->set_value(xFld->normalize(m_aOrigSize.Width()), eUnit); + sTemp = xFld->get_text(); + xFld->set_value(xFld->normalize(m_aOrigSize.Height()), eUnit); + // multiplication sign (U+00D7) + sTemp += u"\u00D7" + xFld->get_text(); + } + + if ( m_aOrigPixelSize.Width() && m_aOrigPixelSize.Height() ) { + sal_Int32 ax = 0.5 + m_aOrigPixelSize.Width() / + o3tl::convert<double>(m_aOrigSize.Width(), o3tl::Length::twip, + o3tl::Length::in); + sal_Int32 ay = 0.5 + m_aOrigPixelSize.Height() / + o3tl::convert<double>(m_aOrigSize.Height(), o3tl::Length::twip, + o3tl::Length::in); + OUString sPPI = OUString::number(ax); + if (abs(ax - ay) > 1) { + sPPI += u"\u00D7" + OUString::number(ay); + } + sTemp += " " + CuiResId(RID_CUISTR_PPI).replaceAll("%1", sPPI); + } + sTemp += "\n" + OUString::number(m_aOrigPixelSize.Width()) + u"\u00D7" + OUString::number(m_aOrigPixelSize.Height()) + " px"; + m_xOrigSizeFT->set_label(sTemp); + } + + m_xCropFrame->set_sensitive(bFound); + m_xScaleFrame->set_sensitive(bFound); + m_xSizeFrame->set_sensitive(bFound); + m_xOrigSizeGrid->set_sensitive(bFound); + m_xZoomConstRB->set_sensitive(bFound); +} + +Size SvxGrfCropPage::GetGrfOrigSize(const Graphic& rGrf) +{ + Size aSize; + + if (m_aPreferredDPI > 0) + { + Size aPixelSize = rGrf.GetSizePixel(); + double fWidth = aPixelSize.Width() / double(m_aPreferredDPI); + double fHeight = aPixelSize.Height() / double(m_aPreferredDPI); + fWidth = o3tl::convert(fWidth, o3tl::Length::in, o3tl::Length::twip); + fHeight = o3tl::convert(fHeight, o3tl::Length::in, o3tl::Length::twip); + aSize = Size(fWidth, fHeight); + } + else + { + const MapMode aMapTwip( MapUnit::MapTwip ); + aSize = rGrf.GetPrefSize(); + if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() ) + aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip); + else + aSize = OutputDevice::LogicToLogic( aSize, + rGrf.GetPrefMapMode(), aMapTwip ); + } + return aSize; +} + +/*****************************************************************/ + +SvxCropExample::SvxCropExample() + : m_aTopLeft(0, 0) + , m_aBottomRight(0, 0) +{ +} + +void SvxCropExample::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + OutputDevice& rDevice = pDrawingArea->get_ref_device(); + Size aSize(rDevice.LogicToPixel(Size(78, 78), MapMode(MapUnit::MapAppFont))); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + + m_aMapMode = rDevice.GetMapMode(); + m_aFrameSize = OutputDevice::LogicToLogic( + Size(CM_1_TO_TWIP / 2, CM_1_TO_TWIP / 2), + MapMode(MapUnit::MapTwip), m_aMapMode); +} + +void SvxCropExample::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.Push(vcl::PushFlags::MAPMODE); + rRenderContext.SetMapMode(m_aMapMode); + + // Win BG + const Size aWinSize(rRenderContext.PixelToLogic(GetOutputSizePixel())); + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor()); + rRenderContext.DrawRect(::tools::Rectangle(Point(), aWinSize)); + + // use AA, the Graphic may be a metafile/svg and would then look ugly + rRenderContext.SetAntialiasing(AntialiasingFlags::Enable); + + // draw Graphic + ::tools::Rectangle aRect( + Point((aWinSize.Width() - m_aFrameSize.Width())/2, (aWinSize.Height() - m_aFrameSize.Height())/2), + m_aFrameSize); + m_aGrf.Draw(rRenderContext, aRect.TopLeft(), aRect.GetSize()); + + // Remove one more case that uses XOR paint (RasterOp::Invert). + // Get colors and logic DashLength from settings, use equal to + // PolygonMarkerPrimitive2D, may be changed to that primitive later. + // Use this to guarantee good visibility - that was the purpose of + // the former used XOR paint. + const Color aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor()); + const Color aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor()); + const double fStripeLength(SvtOptionsDrawinglayer::GetStripeLength()); + const basegfx::B2DVector aDashVector(rRenderContext.GetInverseViewTransformation() * basegfx::B2DVector(fStripeLength, 0.0)); + const double fLogicDashLength(aDashVector.getX()); + + // apply current crop settings + aRect.AdjustLeft(m_aTopLeft.Y()); + aRect.AdjustTop(m_aTopLeft.X()); + aRect.AdjustRight(-m_aBottomRight.Y()); + aRect.AdjustBottom(-m_aBottomRight.X()); + + // apply dash with direct paint callbacks + basegfx::utils::applyLineDashing( + basegfx::utils::createPolygonFromRect( + basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom())), + std::vector< double >(2, fLogicDashLength), + [&aColA,&rRenderContext](const basegfx::B2DPolygon& rSnippet) + { + rRenderContext.SetLineColor(aColA); + rRenderContext.DrawPolyLine(rSnippet); + }, + [&aColB,&rRenderContext](const basegfx::B2DPolygon& rSnippet) + { + rRenderContext.SetLineColor(aColB); + rRenderContext.DrawPolyLine(rSnippet); + }, + 2.0 * fLogicDashLength); + + rRenderContext.Pop(); +} + +void SvxCropExample::Resize() +{ + SetFrameSize(m_aFrameSize); +} + +void SvxCropExample::SetFrameSize( const Size& rSz ) +{ + m_aFrameSize = rSz; + if (!m_aFrameSize.Width()) + m_aFrameSize.setWidth( 1 ); + if (!m_aFrameSize.Height()) + m_aFrameSize.setHeight( 1 ); + Size aWinSize( GetOutputSizePixel() ); + Fraction aXScale( aWinSize.Width() * 4, m_aFrameSize.Width() * 5 ); + Fraction aYScale( aWinSize.Height() * 4, m_aFrameSize.Height() * 5 ); + + if( aYScale < aXScale ) + aXScale = aYScale; + + m_aMapMode.SetScaleX(aXScale); + m_aMapMode.SetScaleY(aXScale); + + Invalidate(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/labdlg.cxx b/cui/source/tabpages/labdlg.cxx new file mode 100644 index 000000000..cb048426c --- /dev/null +++ b/cui/source/tabpages/labdlg.cxx @@ -0,0 +1,507 @@ +/* -*- 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 . + */ + +#include <swpossizetabpage.hxx> +#include <svtools/unitconv.hxx> + +#include <svx/svddef.hxx> +#include <svx/sxcecitm.hxx> +#include <svx/sxcgitm.hxx> +#include <svx/sxcllitm.hxx> +#include <svx/sxctitm.hxx> + +#include <svx/dlgutil.hxx> +#include <labdlg.hxx> +#include <transfrm.hxx> +#include <bitmaps.hlst> + +// define ---------------------------------------------------------------- + +#define EXT_OPTIMAL 0 +#define EXT_FROM_TOP 1 +#define EXT_FROM_LEFT 2 +#define EXT_HORIZONTAL 3 +#define EXT_VERTICAL 4 + +#define POS_TOP 0 +#define POS_MIDDLE 1 +#define POS_BOTTOM 2 + +#define BMP_CAPTTYPE_1 1 +#define BMP_CAPTTYPE_2 2 +#define BMP_CAPTTYPE_3 3 + +// static ---------------------------------------------------------------- + +const WhichRangesContainer SvxCaptionTabPage::pCaptionRanges( + svl::Items< + SDRATTR_CAPTIONTYPE, SDRATTR_CAPTIONFIXEDANGLE, + SDRATTR_CAPTIONANGLE, SDRATTR_CAPTIONGAP, + SDRATTR_CAPTIONESCDIR, SDRATTR_CAPTIONESCISREL, + SDRATTR_CAPTIONESCREL, SDRATTR_CAPTIONESCABS, + SDRATTR_CAPTIONLINELEN, SDRATTR_CAPTIONFITLINELEN>); + +SvxCaptionTabPage::SvxCaptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/calloutpage.ui", "CalloutPage", &rInAttrs) + , nCaptionType(SdrCaptionType::Type1) + , nGap(0) + , nEscDir(SdrCaptionEscDir::Horizontal) + , bEscRel(false) + , nEscAbs(0) + , nEscRel(0) + , nLineLen(0) + , bFitLineLen(false) + , nPosition(0) + , nExtension(0) + , rOutAttrs(rInAttrs) + , pView(nullptr) + , m_xMF_SPACING(m_xBuilder->weld_metric_spin_button("spacing", FieldUnit::MM)) + , m_xLB_EXTENSION(m_xBuilder->weld_combo_box("extension")) + , m_xFT_BYFT(m_xBuilder->weld_label("byft")) + , m_xMF_BY(m_xBuilder->weld_metric_spin_button("by", FieldUnit::MM)) + , m_xFT_POSITIONFT(m_xBuilder->weld_label("positionft")) + , m_xLB_POSITION(m_xBuilder->weld_combo_box("position")) + , m_xLineTypes(m_xBuilder->weld_combo_box("linetypes")) + , m_xFT_LENGTHFT(m_xBuilder->weld_label("lengthft")) + , m_xMF_LENGTH(m_xBuilder->weld_metric_spin_button("length", FieldUnit::MM)) + , m_xCB_OPTIMAL(m_xBuilder->weld_check_button("optimal")) + , m_xCT_CAPTTYPE(new ValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true))) + , m_xCT_CAPTTYPEWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xCT_CAPTTYPE)) +{ + Size aSize(m_xCT_CAPTTYPE->GetDrawingArea()->get_ref_device().LogicToPixel(Size(187, 38), MapMode(MapUnit::MapAppFont))); + m_xCT_CAPTTYPEWin->set_size_request(aSize.Width(), aSize.Height()); + + assert(m_xLB_POSITION->get_count() == 6); + for (int i = 0; i < 3; ++i) + m_aStrHorzList.push_back(m_xLB_POSITION->get_text(i)); + for (int i = 3; i < 6; ++i) + m_aStrVertList.push_back(m_xLB_POSITION->get_text(i)); + m_xLB_POSITION->clear(); + + assert(m_xLineTypes->get_count() == 3); + std::vector<OUString> aLineTypes; + aLineTypes.reserve(3); + for (int i = 0; i < 3; ++i) + aLineTypes.push_back(m_xLineTypes->get_text(i)); + + static_assert(CAPTYPE_BITMAPS_COUNT == 3, "unexpected"); + m_aBmpCapTypes[0] = Image(StockImage::Yes, RID_SVXBMP_LEGTYP1); + m_aBmpCapTypes[1] = Image(StockImage::Yes, RID_SVXBMP_LEGTYP2); + m_aBmpCapTypes[2] = Image(StockImage::Yes, RID_SVXBMP_LEGTYP3); + + //------------install ValueSet-------------------------- + m_xCT_CAPTTYPE->SetStyle( m_xCT_CAPTTYPE->GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER | WB_NAMEFIELD ); + m_xCT_CAPTTYPE->SetColCount(5);//XXX + m_xCT_CAPTTYPE->SetLineCount(1); + m_xCT_CAPTTYPE->SetSelectHdl(LINK( this, SvxCaptionTabPage, SelectCaptTypeHdl_Impl)); + + Image aImage; + m_xCT_CAPTTYPE->InsertItem(BMP_CAPTTYPE_1, aImage, aLineTypes[0]); + m_xCT_CAPTTYPE->InsertItem(BMP_CAPTTYPE_2, aImage, aLineTypes[1]); + m_xCT_CAPTTYPE->InsertItem(BMP_CAPTTYPE_3, aImage, aLineTypes[2]); + + FillValueSet(); + + m_xLB_EXTENSION->connect_changed(LINK(this, SvxCaptionTabPage, ExtensionSelectHdl_Impl)); + m_xLB_POSITION->connect_changed(LINK(this, SvxCaptionTabPage, PositionSelectHdl_Impl)); + m_xCB_OPTIMAL->connect_toggled(LINK(this, SvxCaptionTabPage, LineOptHdl_Impl)); +} + +SvxCaptionTabPage::~SvxCaptionTabPage() +{ + m_xCT_CAPTTYPEWin.reset(); + m_xCT_CAPTTYPE.reset(); +} + +void SvxCaptionTabPage::Construct() +{ + // set rectangle and working area + DBG_ASSERT( pView, "No valid View transferred!" ); +} + +bool SvxCaptionTabPage::FillItemSet( SfxItemSet* _rOutAttrs) +{ + SfxItemPool* pPool = _rOutAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + MapUnit eUnit; + + nCaptionType = static_cast<SdrCaptionType>(m_xCT_CAPTTYPE->GetSelectedItemId()-1); + + _rOutAttrs->Put( SdrCaptionTypeItem( nCaptionType ) ); + + if (m_xMF_SPACING->get_value_changed_from_saved()) + { + eUnit = pPool->GetMetric( GetWhich( SDRATTR_CAPTIONGAP ) ); + _rOutAttrs->Put( SdrCaptionGapItem( GetCoreValue(*m_xMF_SPACING, eUnit ) ) ); + } + + // special treatment!!! XXX + if( nCaptionType==SdrCaptionType::Type1 ) + { + switch( nEscDir ) + { + case SdrCaptionEscDir::Horizontal: nEscDir=SdrCaptionEscDir::Vertical;break; + case SdrCaptionEscDir::Vertical: nEscDir=SdrCaptionEscDir::Horizontal;break; + default: break; + } + } + + _rOutAttrs->Put( SdrCaptionEscDirItem( nEscDir ) ); + + bEscRel = m_xLB_POSITION->get_visible(); + _rOutAttrs->Put( SdrCaptionEscIsRelItem( bEscRel ) ); + + if( bEscRel ) + { + tools::Long nVal = 0; + + switch (m_xLB_POSITION->get_active()) + { + case POS_TOP: nVal=0;break; + case POS_MIDDLE: nVal=5000;break; + case POS_BOTTOM: nVal=10000;break; + } + _rOutAttrs->Put( SdrCaptionEscRelItem( nVal ) ); + } + else + { + if (m_xMF_BY->get_value_changed_from_saved()) + { + eUnit = pPool->GetMetric( GetWhich( SDRATTR_CAPTIONESCABS ) ); + _rOutAttrs->Put( SdrCaptionEscAbsItem( GetCoreValue(*m_xMF_BY, eUnit ) ) ); + } + } + + bFitLineLen = m_xCB_OPTIMAL->get_active(); + _rOutAttrs->Put( SdrCaptionFitLineLenItem( bFitLineLen ) ); + + if( ! bFitLineLen ) + { + if (m_xMF_LENGTH->get_value_changed_from_saved()) + { + eUnit = pPool->GetMetric( GetWhich( SDRATTR_CAPTIONLINELEN ) ); + _rOutAttrs->Put( SdrCaptionLineLenItem( GetCoreValue(*m_xMF_LENGTH, eUnit ) ) ); + } + } + +//NYI-------------the angles have to be added here!!! XXX---------------------- + + return true; +} + +void SvxCaptionTabPage::Reset( const SfxItemSet* ) +{ + + //------------set metric----------------------------- + + FieldUnit eFUnit = GetModuleFieldUnit( rOutAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::CM: + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + SetFieldUnit( *m_xMF_SPACING, eFUnit ); + SetFieldUnit( *m_xMF_BY, eFUnit ); + SetFieldUnit( *m_xMF_LENGTH, eFUnit ); + + SfxItemPool* pPool = rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + sal_uInt16 nWhich; + MapUnit eUnit; + + nWhich = GetWhich( SDRATTR_CAPTIONESCABS ); + eUnit = pPool->GetMetric( nWhich ); + nEscAbs = static_cast<const SdrCaptionEscAbsItem&>( rOutAttrs.Get( nWhich ) ).GetValue(); + SetMetricValue( *m_xMF_BY, nEscAbs, eUnit ); + nEscAbs = m_xMF_BY->get_value(FieldUnit::NONE); + + nWhich = GetWhich( SDRATTR_CAPTIONESCREL ); + nEscRel = static_cast<tools::Long>(static_cast<const SdrCaptionEscRelItem&>( rOutAttrs.Get( nWhich ) ).GetValue()); + + //------- line length ---------- + nWhich = GetWhich( SDRATTR_CAPTIONLINELEN ); + eUnit = pPool->GetMetric( nWhich ); + nLineLen = static_cast<const SdrCaptionLineLenItem&>( rOutAttrs.Get( nWhich ) ).GetValue(); + SetMetricValue( *m_xMF_LENGTH, nLineLen, eUnit ); + nLineLen = m_xMF_LENGTH->get_value(FieldUnit::NONE); + + //------- distance to box ---------- + nWhich = GetWhich( SDRATTR_CAPTIONGAP ); + eUnit = pPool->GetMetric( nWhich ); + nGap = static_cast<const SdrCaptionGapItem&>( rOutAttrs.Get( nWhich ) ).GetValue(); + SetMetricValue( *m_xMF_SPACING, nGap, eUnit ); + nGap = m_xMF_SPACING->get_value(FieldUnit::NONE); + + nCaptionType = rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONTYPE ) ).GetValue(); + bFitLineLen = static_cast<const SfxBoolItem&>( rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONFITLINELEN ) ) ).GetValue(); + nEscDir = rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONESCDIR ) ).GetValue(); + bEscRel = static_cast<const SfxBoolItem&>( rOutAttrs.Get( GetWhich( SDRATTR_CAPTIONESCISREL ) ) ).GetValue(); + + // special treatment!!! XXX + if( nCaptionType==SdrCaptionType::Type1 ) + { + switch( nEscDir ) + { + case SdrCaptionEscDir::Horizontal: nEscDir=SdrCaptionEscDir::Vertical;break; + case SdrCaptionEscDir::Vertical: nEscDir=SdrCaptionEscDir::Horizontal;break; + default: break; + } + } + + nPosition = POS_MIDDLE; + nExtension = EXT_OPTIMAL; + + m_xMF_SPACING->set_value(nGap, FieldUnit::NONE); + + if( nEscDir == SdrCaptionEscDir::Horizontal ) + { + if( bEscRel ) + { + if( nEscRel < 3333 ) + nPosition = POS_TOP; + if( nEscRel > 6666 ) + nPosition = POS_BOTTOM; + nExtension = EXT_HORIZONTAL; + } + else + { + nExtension = EXT_FROM_TOP; + m_xMF_BY->set_value(nEscAbs, FieldUnit::NONE); + } + } + else if( nEscDir == SdrCaptionEscDir::Vertical ) + { + if( bEscRel ) + { + if( nEscRel < 3333 ) + nPosition = POS_TOP; + if( nEscRel > 6666 ) + nPosition = POS_BOTTOM; + nExtension = EXT_VERTICAL; + } + else + { + nExtension = EXT_FROM_LEFT; + m_xMF_BY->set_value(nEscAbs, FieldUnit::NONE); + } + } + else if( nEscDir == SdrCaptionEscDir::BestFit ) + { + nExtension = EXT_OPTIMAL; + } + + m_xCB_OPTIMAL->set_active(bFitLineLen); + m_xMF_LENGTH->set_value(nLineLen, FieldUnit::NONE); + + m_xLB_EXTENSION->set_active(nExtension); + + SetupExtension_Impl( nExtension ); + m_xCT_CAPTTYPE->SelectItem( static_cast<int>(nCaptionType)+1 ); // Enum starts at 0! + SetupType_Impl( nCaptionType ); +} + +std::unique_ptr<SfxTabPage> SvxCaptionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SvxCaptionTabPage>(pPage, pController, *rOutAttrs); +} + +void SvxCaptionTabPage::SetupExtension_Impl( sal_uInt16 nType ) +{ + switch( nType ) + { + case EXT_OPTIMAL: + m_xMF_BY->show(); + m_xFT_BYFT->show(); + m_xFT_POSITIONFT->hide(); + m_xLB_POSITION->hide(); + nEscDir = SdrCaptionEscDir::BestFit; + break; + + case EXT_FROM_TOP: + m_xMF_BY->show(); + m_xFT_BYFT->show(); + m_xFT_POSITIONFT->hide(); + m_xLB_POSITION->hide(); + nEscDir = SdrCaptionEscDir::Horizontal; + break; + + case EXT_FROM_LEFT: + m_xMF_BY->show(); + m_xFT_BYFT->show(); + m_xFT_POSITIONFT->hide(); + m_xLB_POSITION->hide(); + nEscDir = SdrCaptionEscDir::Vertical; + break; + + case EXT_HORIZONTAL: + m_xLB_POSITION->clear(); + for (const OUString & i : m_aStrHorzList) + m_xLB_POSITION->append_text(i); + m_xLB_POSITION->set_active(nPosition); + + m_xMF_BY->hide(); + m_xFT_BYFT->hide(); + m_xFT_POSITIONFT->show(); + m_xLB_POSITION->show(); + nEscDir = SdrCaptionEscDir::Horizontal; + break; + + case EXT_VERTICAL: + m_xLB_POSITION->clear(); + for (const OUString & i : m_aStrVertList) + m_xLB_POSITION->append_text(i); + m_xLB_POSITION->set_active(nPosition); + + m_xMF_BY->hide(); + m_xFT_BYFT->hide(); + m_xFT_POSITIONFT->show(); + m_xLB_POSITION->show(); + nEscDir = SdrCaptionEscDir::Vertical; + break; + } +} + +IMPL_LINK(SvxCaptionTabPage, ExtensionSelectHdl_Impl, weld::ComboBox&, rListBox, void) +{ + if (&rListBox == m_xLB_EXTENSION.get()) + { + SetupExtension_Impl(m_xLB_EXTENSION->get_active()); + } +} + +IMPL_LINK(SvxCaptionTabPage, PositionSelectHdl_Impl, weld::ComboBox&, rListBox, void) +{ + if (&rListBox == m_xLB_POSITION.get()) + { + nPosition = m_xLB_POSITION->get_active(); + } +} + +IMPL_LINK( SvxCaptionTabPage, LineOptHdl_Impl, weld::Toggleable&, rButton, void ) +{ + if (&rButton != m_xCB_OPTIMAL.get()) + return; + + if (m_xCB_OPTIMAL->get_active() || !m_xCB_OPTIMAL->get_sensitive()) + { + m_xFT_LENGTHFT->set_sensitive(false); + m_xMF_LENGTH->set_sensitive(false); + } + else + { + m_xFT_LENGTHFT->set_sensitive(true); + m_xMF_LENGTH->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxCaptionTabPage, SelectCaptTypeHdl_Impl, ValueSet*, void) +{ + SetupType_Impl( static_cast<SdrCaptionType>(m_xCT_CAPTTYPE->GetSelectedItemId()) ); +} + +void SvxCaptionTabPage::SetupType_Impl( SdrCaptionType nType ) +{ + switch( nType ) + { + case SdrCaptionType::Type1: + case SdrCaptionType::Type2: + m_xFT_LENGTHFT->set_sensitive(false); + m_xCB_OPTIMAL->set_sensitive(false); + LineOptHdl_Impl(*m_xCB_OPTIMAL); + break; + case SdrCaptionType::Type3: + case SdrCaptionType::Type4: + m_xFT_LENGTHFT->set_sensitive(true); + m_xCB_OPTIMAL->set_sensitive(true); + LineOptHdl_Impl(*m_xCB_OPTIMAL); + break; + } +} + +void SvxCaptionTabPage::FillValueSet() +{ + m_xCT_CAPTTYPE->SetItemImage(BMP_CAPTTYPE_1, m_aBmpCapTypes[0] ); + m_xCT_CAPTTYPE->SetItemImage(BMP_CAPTTYPE_2, m_aBmpCapTypes[1] ); + m_xCT_CAPTTYPE->SetItemImage(BMP_CAPTTYPE_3, m_aBmpCapTypes[2] ); +} + +SvxCaptionTabDialog::SvxCaptionTabDialog(weld::Window* pParent, const SdrView* pSdrView, + SvxAnchorIds nAnchorTypes) + : SfxTabDialogController(pParent, "cui/ui/calloutdialog.ui", "CalloutDialog") + , pView(pSdrView) + , nAnchorCtrls(nAnchorTypes) +{ + assert(pView); // No valid View transferred! + + //different positioning page in Writer + if (nAnchorCtrls & (SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page | SvxAnchorIds::Fly)) + { + AddTabPage("RID_SVXPAGE_SWPOSSIZE", SvxSwPosSizeTabPage::Create, + SvxSwPosSizeTabPage::GetRanges ); + RemoveTabPage("RID_SVXPAGE_POSITION_SIZE"); + } + else + { + AddTabPage("RID_SVXPAGE_POSITION_SIZE", SvxPositionSizeTabPage::Create, + SvxPositionSizeTabPage::GetRanges ); + RemoveTabPage("RID_SVXPAGE_SWPOSSIZE"); + } + AddTabPage("RID_SVXPAGE_CAPTION", SvxCaptionTabPage::Create, + SvxCaptionTabPage::GetRanges ); +} + +void SvxCaptionTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_POSITION_SIZE") + { + static_cast<SvxPositionSizeTabPage&>( rPage ).SetView( pView ); + static_cast<SvxPositionSizeTabPage&>( rPage ).Construct(); + if( nAnchorCtrls & SvxAnchorIds::NoResize ) + static_cast<SvxPositionSizeTabPage&>( rPage ).DisableResize(); + + if( nAnchorCtrls & SvxAnchorIds::NoProtect ) + static_cast<SvxPositionSizeTabPage&>( rPage ).DisableProtect(); + } + else if (rId == "RID_SVXPAGE_SWPOSSIZE") + { + SvxSwPosSizeTabPage& rSwPage = static_cast<SvxSwPosSizeTabPage&>(rPage); + rSwPage.EnableAnchorTypes(nAnchorCtrls); + rSwPage.SetValidateFramePosLink( aValidateLink ); + } + else if (rId == "RID_SVXPAGE_CAPTION") + { + static_cast<SvxCaptionTabPage&>( rPage ).SetView( pView ); + static_cast<SvxCaptionTabPage&>( rPage ).Construct(); + } +} + +void SvxCaptionTabDialog::SetValidateFramePosLink( const Link<SvxSwFrameValidation&,void>& rLink ) +{ + aValidateLink = rLink; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx new file mode 100644 index 000000000..e80e471ff --- /dev/null +++ b/cui/source/tabpages/macroass.cxx @@ -0,0 +1,397 @@ +/* -*- 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 . + */ + +#include <macroass.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> +#include <comphelper/string.hxx> +#include <comphelper/processfactory.hxx> +#include <svl/macitem.hxx> +#include <svx/svxids.hrc> +#include <tools/debug.hxx> +#include <vcl/idle.hxx> +#include <cfgutil.hxx> +#include <sfx2/evntconf.hxx> +#include <headertablistbox.hxx> + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::frame::XFrame; + +class SfxMacroTabPage_Impl +{ +public: + SfxMacroTabPage_Impl(); + + OUString m_aStaticMacroLBLabel; + std::unique_ptr<weld::Button> m_xAssignPB; + std::unique_ptr<weld::Button> m_xDeletePB; + std::unique_ptr<MacroEventListBox> m_xEventLB; + std::unique_ptr<weld::Widget> m_xGroupFrame; + std::unique_ptr<CuiConfigGroupListBox> m_xGroupLB; + std::unique_ptr<weld::Frame> m_xMacroFrame; + std::unique_ptr<CuiConfigFunctionListBox> m_xMacroLB; + + Idle m_aFillGroupIdle { "cui SfxMacroTabPage m_aFillGroupIdle" }; + bool m_bGotEvents; +}; + +SfxMacroTabPage_Impl::SfxMacroTabPage_Impl() + : m_bGotEvents(false) +{ +} + +static sal_uInt16 aPageRg[] = { + SID_ATTR_MACROITEM, SID_ATTR_MACROITEM, + 0 +}; + +static OUString ConvertToUIName_Impl( SvxMacro const *pMacro ) +{ + OUString aName( pMacro->GetMacName() ); + if ( pMacro->GetLanguage() != "JavaScript" ) + { + const sal_Int32 nCount = comphelper::string::getTokenCount(aName, '.'); + OUString aEntry = aName.getToken( nCount-1, '.' ); + if ( nCount > 2 ) + { + aEntry += OUString::Concat("(") + o3tl::getToken(aName, 0, '.' ) + "." + o3tl::getToken(aName, nCount-2, '.' ) + ")"; + } + return aEntry; + } + else + return aName; +} + +void SfxMacroTabPage::EnableButtons() +{ + // don't do anything as long as the eventbox is empty + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rTreeView.get_selected_index(); + if (nSelected != -1) + { + // get bound macro + const SvxMacro* pM = aTbl.Get(static_cast<SvMacroItemId>(rTreeView.get_selected_id().toInt32())); + mpImpl->m_xDeletePB->set_sensitive(nullptr != pM); + + OUString sEventMacro = rTreeView.get_text(nSelected, 1); + + OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + mpImpl->m_xAssignPB->set_sensitive(!sScriptURI.equalsIgnoreAsciiCase(sEventMacro)); + } + else + mpImpl->m_xAssignPB->set_sensitive(false); +} + +SfxMacroTabPage::SfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet ) + : SfxTabPage(pPage, pController, "cui/ui/eventassignpage.ui", "EventAssignPage", &rAttrSet) +{ + mpImpl.reset(new SfxMacroTabPage_Impl); + + mpImpl->m_aFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) ); + mpImpl->m_aFillGroupIdle.SetPriority( TaskPriority::HIGHEST ); + + mpImpl->m_xEventLB.reset(new MacroEventListBox(m_xBuilder->weld_tree_view("assignments"))); + mpImpl->m_xAssignPB = m_xBuilder->weld_button("assign"); + mpImpl->m_xDeletePB = m_xBuilder->weld_button("delete"); + mpImpl->m_xGroupFrame = m_xBuilder->weld_widget("groupframe"); + mpImpl->m_xGroupLB.reset(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("libraries"))); + mpImpl->m_xMacroFrame = m_xBuilder->weld_frame("macroframe"); + mpImpl->m_aStaticMacroLBLabel = mpImpl->m_xMacroFrame->get_label(); + mpImpl->m_xMacroLB.reset(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("macros"))); + + SetFrame( rxDocumentFrame ); + + InitAndSetHandler(); + + ScriptChanged(); +} + +SfxMacroTabPage::~SfxMacroTabPage() +{ + mpImpl.reset(); +} + +void SfxMacroTabPage::AddEvent(const OUString& rEventName, SvMacroItemId nEventId) +{ + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + rTreeView.append(OUString::number(static_cast<sal_Int32>(nEventId)), rEventName); + + // if the table is valid already + SvxMacro* pM = aTbl.Get(nEventId); + if (pM) + { + OUString sNew(ConvertToUIName_Impl(pM)); + rTreeView.set_text(rTreeView.n_children() - 1, sNew, 1); + } +} + +void SfxMacroTabPage::ScriptChanged() +{ + // get new areas and their functions + mpImpl->m_xGroupFrame->show(); + mpImpl->m_xMacroFrame->show(); + + EnableButtons(); +} + +bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet ) +{ + SvxMacroItem aItem( GetWhich( aPageRg[0] ) ); + const_cast<SvxMacroTableDtor&>(aItem.GetMacroTable()) = aTbl; + + const SfxPoolItem* pItem = nullptr; + SfxItemState eState = GetItemSet().GetItemState(aItem.Which(), true, &pItem); + if (eState == SfxItemState::DEFAULT && aTbl.empty()) + { + // Don't touch the item set if there was no input and our table is empty. + return false; + } + if (SfxItemState::SET != eState || aItem != *static_cast<const SvxMacroItem*>(pItem)) + { + rSet->Put( aItem ); + return true; + } + return false; +} + +void SfxMacroTabPage::LaunchFillGroup() +{ + if (! mpImpl->m_aFillGroupIdle.IsActive() ) + mpImpl->m_aFillGroupIdle.Start(); +} + +void SfxMacroTabPage::ActivatePage( const SfxItemSet& ) +{ + LaunchFillGroup(); +} + +void SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + if( mpImpl->m_bGotEvents ) + return; + if( const SfxEventNamesItem* pEventsItem = aSet.GetItemIfSet( SID_EVENTCONFIG ) ) + { + mpImpl->m_bGotEvents = true; + const SfxEventNamesList& rList = pEventsItem->GetEvents(); + for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) + { + const SfxEventName &rOwn = rList.at(nNo); + AddEvent( rOwn.maUIName, rOwn.mnId ); + } + } +} + +void SfxMacroTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + if( SfxItemState::SET == rSet->GetItemState( GetWhich( aPageRg[0] ), true, &pItem )) + aTbl = static_cast<const SvxMacroItem*>(pItem)->GetMacroTable(); + + const SfxEventNamesItem* pEventsItem; + if( !mpImpl->m_bGotEvents && (pEventsItem = rSet->GetItemIfSet( SID_EVENTCONFIG ) ) ) + { + mpImpl->m_bGotEvents = true; + const SfxEventNamesList& rList = pEventsItem->GetEvents(); + for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) + { + const SfxEventName &rOwn = rList.at(nNo); + AddEvent( rOwn.maUIName, rOwn.mnId ); + } + } + + FillEvents(); + + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + std::unique_ptr<weld::TreeIter> xIter(rListBox.make_iterator()); + if (rListBox.get_iter_first(*xIter)) + rListBox.set_cursor(*xIter); +} + +bool SfxMacroTabPage::IsReadOnly() const +{ + return false; +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectEvent_Impl, weld::TreeView&, void) +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) + { + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); + return; + } + + ScriptChanged(); + EnableButtons(); +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectGroup_Impl, weld::TreeView&, void) +{ + mpImpl->m_xGroupLB->GroupSelected(); + const OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + OUString aLabelText; + if( !sScriptURI.isEmpty() ) + aLabelText = mpImpl->m_aStaticMacroLBLabel; + mpImpl->m_xMacroFrame->set_label( aLabelText ); + + EnableButtons(); +} + +IMPL_LINK_NOARG(SfxMacroTabPage, SelectMacro_Impl, weld::TreeView&, void) +{ + EnableButtons(); +} + +IMPL_LINK(SfxMacroTabPage, AssignDeleteClickHdl_Impl, weld::Button&, rBtn, void) +{ + AssignDeleteHdl(&rBtn); +} + +IMPL_LINK(SfxMacroTabPage, AssignDeleteHdl_Impl, weld::TreeView&, rBtn, bool) +{ + AssignDeleteHdl(&rBtn); + return true; +} + +void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget* pBtn) +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) + { + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); + return; + } + + const bool bAssEnabled = pBtn != mpImpl->m_xDeletePB.get() && mpImpl->m_xAssignPB->get_sensitive(); + + // remove from the table + SvMacroItemId nEvent = static_cast<SvMacroItemId>(rListBox.get_selected_id().toInt32()); + aTbl.Erase( nEvent ); + + OUString sScriptURI; + if( bAssEnabled ) + { + sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + if( sScriptURI.startsWith( "vnd.sun.star.script:" ) ) + { + aTbl.Insert( + nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_SF ) ); + } + else + { + OSL_ENSURE( false, "SfxMacroTabPage::AssignDeleteHdl_Impl: this branch is *not* dead? (out of interest: tell fs, please!)" ); + aTbl.Insert( + nEvent, SvxMacro( sScriptURI, SVX_MACRO_LANGUAGE_STARBASIC ) ); + } + } + + rListBox.set_text(nSelected, sScriptURI, 1); + + EnableButtons(); +} + +IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void ) +{ + // FillMacroList() can take a long time -> show wait cursor and disable input + weld::Window* pDialog = GetFrameWeld(); + // perhaps the tabpage is part of a SingleTabDialog then pDialog == nullptr + std::unique_ptr<weld::WaitObject> xWait(pDialog ? new weld::WaitObject(pDialog) : nullptr); + // fill macro list + mpImpl->m_xGroupLB->Init(comphelper::getProcessComponentContext(), GetFrame(), + OUString(), false); +} + +void SfxMacroTabPage::InitAndSetHandler() +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + Link<weld::TreeView&,bool> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl)); + mpImpl->m_xMacroLB->connect_row_activated( aLnk); + mpImpl->m_xDeletePB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + mpImpl->m_xAssignPB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + rListBox.connect_row_activated(aLnk); + + rListBox.connect_changed(LINK(this, SfxMacroTabPage, SelectEvent_Impl)); + mpImpl->m_xGroupLB->connect_changed(LINK(this, SfxMacroTabPage, SelectGroup_Impl)); + mpImpl->m_xMacroLB->connect_changed(LINK(this, SfxMacroTabPage, SelectMacro_Impl)); + + std::vector<int> aWidths + { + o3tl::narrowing<int>(rListBox.get_approximate_digit_width() * 35) + }; + rListBox.set_column_fixed_widths(aWidths); + + mpImpl->m_xEventLB->show(); + + mpImpl->m_xEventLB->set_sensitive(true); + mpImpl->m_xGroupLB->set_sensitive(true); + mpImpl->m_xMacroLB->set_sensitive(true); + + mpImpl->m_xGroupLB->SetFunctionListBox(mpImpl->m_xMacroLB.get()); +} + +void SfxMacroTabPage::FillEvents() +{ + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + + int nEntryCnt = rListBox.n_children(); + + // get events from the table and fill the EventListBox respectively + for (int n = 0 ; n < nEntryCnt; ++n) + { + OUString sOld = rListBox.get_text(n, 1); + OUString sNew; + SvMacroItemId nEventId = static_cast<SvMacroItemId>(rListBox.get_id(n).toInt32()); + if (aTbl.IsKeyValid(nEventId)) + sNew = ConvertToUIName_Impl(aTbl.Get(nEventId)); + + if (sOld == sNew) + continue; + + rListBox.set_text(n, sNew, 1); + } +} + +namespace +{ + std::unique_ptr<SfxMacroTabPage> CreateSfxMacroTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttrSet) + { + return std::make_unique<SfxMacroTabPage>( pPage, pController, nullptr, rAttrSet ); + } +} + +std::unique_ptr<SfxTabPage> SfxMacroTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return CreateSfxMacroTabPage(pPage, pController, *rAttrSet); +} + +SfxMacroAssignDlg::SfxMacroAssignDlg(weld::Widget* pParent, + const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet,"cui/ui/eventassigndialog.ui", + "EventAssignDialog") +{ + std::unique_ptr<SfxMacroTabPage> xPage = CreateSfxMacroTabPage(get_content_area(), this, rSet); + xPage->SetFrame(rxDocumentFrame); + SetTabPage(std::move(xPage)); + GetTabPage()->LaunchFillGroup(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/measure.cxx b/cui/source/tabpages/measure.cxx new file mode 100644 index 000000000..fe61ed53a --- /dev/null +++ b/cui/source/tabpages/measure.cxx @@ -0,0 +1,755 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include <dialmgr.hxx> + +#include <svx/svxids.hrc> +#include <svx/dlgutil.hxx> +#include <svx/measctrl.hxx> +#include <svx/ofaitem.hxx> +#include <svx/strarray.hxx> +#include <svx/svdview.hxx> +#include <svx/sxmbritm.hxx> +#include <svx/sxmlhitm.hxx> +#include <svx/sxmtfitm.hxx> +#include <svx/sxmtpitm.hxx> +#include <svx/sxmtritm.hxx> +#include <svx/sxmuitm.hxx> +#include <svtools/unitconv.hxx> + +#include <measure.hxx> + +const WhichRangesContainer SvxMeasurePage::pRanges( + svl::Items<SDRATTR_MEASURE_FIRST, SDRATTR_MEASURE_LAST>); + +/************************************************************************* +|* +|* Dialog to change measure-attributes +|* +\************************************************************************/ +SvxMeasureDialog::SvxMeasureDialog(weld::Window* pParent, const SfxItemSet& rInAttrs, + const SdrView* pSdrView) + : SfxSingleTabDialogController(pParent, &rInAttrs) +{ + auto xPage = std::make_unique<SvxMeasurePage>(get_content_area(), this, rInAttrs); + + xPage->SetView(pSdrView); + xPage->Construct(); + + SetTabPage(std::move(xPage)); + m_xDialog->set_title(CuiResId(RID_CUISTR_DIMENSION_LINE)); +} + +/************************************************************************* +|* +|* Tabpage for changing measure-attributes +|* +\************************************************************************/ + +SvxMeasurePage::SvxMeasurePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/dimensionlinestabpage.ui", "DimensionLinesTabPage", rInAttrs) + , rOutAttrs(rInAttrs) + , aAttrSet(*rInAttrs.GetPool()) + , pView(nullptr) + , eUnit(MapUnit::Map100thMM) + , bPositionModified(false) + , m_aCtlPosition(this) + , m_xMtrFldLineDist(m_xBuilder->weld_metric_spin_button("MTR_LINE_DIST", FieldUnit::MM)) + , m_xMtrFldHelplineOverhang(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE_OVERHANG", FieldUnit::MM)) + , m_xMtrFldHelplineDist(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE_DIST", FieldUnit::MM)) + , m_xMtrFldHelpline1Len(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE1_LEN", FieldUnit::MM)) + , m_xMtrFldHelpline2Len(m_xBuilder->weld_metric_spin_button("MTR_FLD_HELPLINE2_LEN", FieldUnit::MM)) + , m_xTsbBelowRefEdge(m_xBuilder->weld_check_button("TSB_BELOW_REF_EDGE")) + , m_xMtrFldDecimalPlaces(m_xBuilder->weld_spin_button("MTR_FLD_DECIMALPLACES")) + , m_xTsbAutoPosV(m_xBuilder->weld_check_button("TSB_AUTOPOSV")) + , m_xTsbAutoPosH(m_xBuilder->weld_check_button("TSB_AUTOPOSH")) + , m_xTsbShowUnit(m_xBuilder->weld_check_button("TSB_SHOW_UNIT")) + , m_xLbUnit(m_xBuilder->weld_combo_box("LB_UNIT")) + , m_xTsbParallel(m_xBuilder->weld_check_button("TSB_PARALLEL")) + , m_xFtAutomatic(m_xBuilder->weld_label("STR_MEASURE_AUTOMATIC")) + , m_xCtlPosition(new weld::CustomWeld(*m_xBuilder, "CTL_POSITION", m_aCtlPosition)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + m_aCtlPreview.SetAttributes(rInAttrs); + + FillUnitLB(); + + const FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xMtrFldLineDist, eFUnit ); + SetFieldUnit( *m_xMtrFldHelplineOverhang, eFUnit ); + SetFieldUnit( *m_xMtrFldHelplineDist, eFUnit ); + SetFieldUnit( *m_xMtrFldHelpline1Len, eFUnit ); + SetFieldUnit( *m_xMtrFldHelpline2Len, eFUnit ); + if( eFUnit == FieldUnit::MM ) + { + m_xMtrFldLineDist->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelplineOverhang->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelplineDist->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelpline1Len->set_increments(50, 500, FieldUnit::NONE); + m_xMtrFldHelpline2Len->set_increments(50, 500, FieldUnit::NONE); + } + + m_xTsbAutoPosV->connect_toggled(LINK( this, SvxMeasurePage, ClickAutoPosHdl_Impl)); + m_xTsbAutoPosH->connect_toggled(LINK(this, SvxMeasurePage, ClickAutoPosHdl_Impl)); + + Link<weld::MetricSpinButton&,void> aLink(LINK(this, SvxMeasurePage, ChangeAttrEditHdl_Impl)); + m_xMtrFldLineDist->set_range(-10000, 10000, FieldUnit::MM); + m_xMtrFldLineDist->connect_value_changed(aLink); + m_xMtrFldHelplineOverhang->connect_value_changed(aLink); + m_xMtrFldHelplineOverhang->set_range(-10000, 10000, FieldUnit::MM); + m_xMtrFldHelplineDist->connect_value_changed(aLink); + m_xMtrFldHelplineDist->set_range(-10000, 10000, FieldUnit::MM); + m_xMtrFldHelpline1Len->connect_value_changed(aLink); + m_xMtrFldHelpline1Len->set_range(-10000, 10000, FieldUnit::MM); + m_xMtrFldHelpline2Len->connect_value_changed(aLink); + m_xMtrFldHelpline2Len->set_range(-10000, 10000, FieldUnit::MM); + m_xMtrFldDecimalPlaces->connect_value_changed(LINK(this, SvxMeasurePage, ChangeAttrSpinHdl_Impl)); + m_xTsbBelowRefEdge->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); + m_xTsbParallel->connect_toggled( LINK( this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); + m_xTsbShowUnit->connect_toggled(LINK(this, SvxMeasurePage, ChangeAttrClickHdl_Impl)); + m_xLbUnit->connect_changed(LINK(this, SvxMeasurePage, ChangeAttrListBoxHdl_Impl)); +} + +SvxMeasurePage::~SvxMeasurePage() +{ + m_xCtlPreview.reset(); + m_xCtlPosition.reset(); +} + +/************************************************************************* +|* +|* read the delivered Item-Set +|* +\************************************************************************/ + +void SvxMeasurePage::Reset( const SfxItemSet* rAttrs ) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + eUnit = pPool->GetMetric( SDRATTR_MEASURELINEDIST ); + + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_MEASURELINEDIST ); + + // SdrMeasureLineDistItem + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASURELINEDIST ); + SetMetricValue(*m_xMtrFldLineDist, static_cast<const SdrMetricItem*>(pItem)->GetValue(), eUnit); + m_xMtrFldLineDist->save_value(); + + // SdrMeasureHelplineOverhangItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINEOVERHANG ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINEOVERHANG ); + SetMetricValue(*m_xMtrFldHelplineOverhang, static_cast<const SdrMetricItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldHelplineOverhang->save_value(); + + // SdrMeasureHelplineDistItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINEDIST ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINEDIST ); + SetMetricValue(*m_xMtrFldHelplineDist, static_cast<const SdrMetricItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldHelplineDist->save_value(); + + // SdrMeasureHelpline1LenItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINE1LEN ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINE1LEN ); + SetMetricValue(*m_xMtrFldHelpline1Len, static_cast<const SdrMetricItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldHelpline1Len->save_value(); + + // SdrMeasureHelpline2LenItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREHELPLINE2LEN ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREHELPLINE2LEN ); + SetMetricValue(*m_xMtrFldHelpline2Len, static_cast<const SdrMetricItem*>(pItem)->GetValue(), + eUnit); + m_xMtrFldHelpline2Len->save_value(); + + // SdrMeasureBelowRefEdgeItem + if( rAttrs->GetItemState( SDRATTR_MEASUREBELOWREFEDGE ) != SfxItemState::DONTCARE ) + { + m_xTsbBelowRefEdge->set_state( rAttrs->Get( SDRATTR_MEASUREBELOWREFEDGE ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + { + m_xTsbBelowRefEdge->set_state( TRISTATE_INDET ); + } + m_xTsbBelowRefEdge->save_state(); + + // SdrMeasureDecimalPlacesItem + pItem = GetItem( *rAttrs, SDRATTR_MEASUREDECIMALPLACES ); + if( pItem == nullptr ) + pItem = &pPool->GetDefaultItem( SDRATTR_MEASUREDECIMALPLACES ); + m_xMtrFldDecimalPlaces->set_value( + static_cast<const SdrMeasureDecimalPlacesItem*>(pItem)->GetValue()); + m_xMtrFldDecimalPlaces->save_value(); + + // SdrMeasureTextRota90Item + // Attention: negate ! + if( rAttrs->GetItemState( SDRATTR_MEASURETEXTROTA90 ) != SfxItemState::DONTCARE ) + { + m_xTsbParallel->set_state( rAttrs->Get( SDRATTR_MEASURETEXTROTA90 ). + GetValue() ? TRISTATE_FALSE : TRISTATE_TRUE ); + } + else + { + m_xTsbParallel->set_state( TRISTATE_INDET ); + } + m_xTsbParallel->save_state(); + + // SdrMeasureShowUnitItem + if( rAttrs->GetItemState( SDRATTR_MEASURESHOWUNIT ) != SfxItemState::DONTCARE ) + { + m_xTsbShowUnit->set_state( rAttrs->Get( SDRATTR_MEASURESHOWUNIT ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + { + m_xTsbShowUnit->set_state( TRISTATE_INDET ); + } + m_xTsbShowUnit->save_state(); + + // SdrMeasureUnitItem + if( rAttrs->GetItemState( SDRATTR_MEASUREUNIT ) != SfxItemState::DONTCARE ) + { + tools::Long nFieldUnit = static_cast<tools::Long>(rAttrs->Get( SDRATTR_MEASUREUNIT ).GetValue()); + + for (sal_Int32 i = 0; i < m_xLbUnit->get_count(); ++i) + { + if (m_xLbUnit->get_id(i).toInt32() == nFieldUnit) + { + m_xLbUnit->set_active(i); + break; + } + } + } + else + { + m_xLbUnit->set_active(-1); + } + m_xLbUnit->save_value(); + + // Position + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTVPOS ) != SfxItemState::DONTCARE ) + { + css::drawing::MeasureTextVertPos eVPos = + rAttrs->Get( SDRATTR_MEASURETEXTVPOS ).GetValue(); + { + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTHPOS ) != SfxItemState::DONTCARE ) + { + css::drawing::MeasureTextHorzPos eHPos = + rAttrs->Get( SDRATTR_MEASURETEXTHPOS ).GetValue(); + RectPoint eRP = RectPoint::MM; + switch( eVPos ) + { + case css::drawing::MeasureTextVertPos_EAST: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LT; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MT; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RT; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MT; break; + default: break; + } + break; + case css::drawing::MeasureTextVertPos_CENTERED: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LM; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MM; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RM; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MM; break; + default: break; + } + break; + case css::drawing::MeasureTextVertPos_WEST: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LB; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MB; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RB; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MB; break; + default: break; + } + break; + case css::drawing::MeasureTextVertPos_AUTO: + switch( eHPos ) + { + case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: eRP = RectPoint::LM; break; + case css::drawing::MeasureTextHorzPos_INSIDE: eRP = RectPoint::MM; break; + case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: eRP = RectPoint::RM; break; + case css::drawing::MeasureTextHorzPos_AUTO: eRP = RectPoint::MM; break; + default: break; + } + break; + default: ;//prevent warning + } + + CTL_STATE nState = CTL_STATE::NONE; + + if (eHPos == css::drawing::MeasureTextHorzPos_AUTO) + { + m_xTsbAutoPosH->set_state( TRISTATE_TRUE ); + nState = CTL_STATE::NOHORZ; + } + + if (eVPos == css::drawing::MeasureTextVertPos_AUTO) + { + m_xTsbAutoPosV->set_state( TRISTATE_TRUE ); + nState |= CTL_STATE::NOVERT; + } + + m_aCtlPosition.SetState(nState); + m_aCtlPosition.SetActualRP(eRP); + } + } + } + else + { + m_aCtlPosition.Reset(); + m_xTsbAutoPosV->set_state( TRISTATE_INDET ); + m_xTsbAutoPosH->set_state( TRISTATE_INDET ); + } + + // put the attributes to the preview-control, + // otherwise the control don't know about + // the settings of the dialog (#67930) + ChangeAttrHdl_Impl(m_xTsbShowUnit.get()); + m_aCtlPreview.SetAttributes(*rAttrs); + + bPositionModified = false; +} + +/************************************************************************* +|* +|* Fill the delivered Item-Set with dialogbox-attributes +|* +\************************************************************************/ + +bool SvxMeasurePage::FillItemSet( SfxItemSet* rAttrs) +{ + bool bModified = false; + sal_Int32 nValue; + TriState eState; + + if( m_xMtrFldLineDist->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldLineDist, eUnit ); + rAttrs->Put( makeSdrMeasureLineDistItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelplineOverhang->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelplineOverhang, eUnit ); + rAttrs->Put( makeSdrMeasureHelplineOverhangItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelplineDist->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelplineDist, eUnit ); + rAttrs->Put( makeSdrMeasureHelplineDistItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelpline1Len->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelpline1Len, eUnit ); + rAttrs->Put( makeSdrMeasureHelpline1LenItem( nValue ) ); + bModified = true; + } + + if( m_xMtrFldHelpline2Len->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldHelpline2Len, eUnit ); + rAttrs->Put( makeSdrMeasureHelpline2LenItem( nValue ) ); + bModified = true; + } + + eState = m_xTsbBelowRefEdge->get_state(); + if( m_xTsbBelowRefEdge->get_state_changed_from_saved() ) + { + rAttrs->Put( SdrMeasureBelowRefEdgeItem( TRISTATE_TRUE == eState ) ); + bModified = true; + } + + if( m_xMtrFldDecimalPlaces->get_value_changed_from_saved() ) + { + nValue = m_xMtrFldDecimalPlaces->get_value(); + rAttrs->Put( + SdrMeasureDecimalPlacesItem( + sal::static_int_cast< sal_Int16 >( nValue ) ) ); + bModified = true; + } + + eState = m_xTsbParallel->get_state(); + if( m_xTsbParallel->get_state_changed_from_saved() ) + { + rAttrs->Put( SdrMeasureTextRota90Item( TRISTATE_FALSE == eState ) ); + bModified = true; + } + + eState = m_xTsbShowUnit->get_state(); + if( m_xTsbShowUnit->get_state_changed_from_saved() ) + { + rAttrs->Put( SdrYesNoItem(SDRATTR_MEASURESHOWUNIT, TRISTATE_TRUE == eState ) ); + bModified = true; + } + + int nPos = m_xLbUnit->get_active(); + if( m_xLbUnit->get_value_changed_from_saved() ) + { + if (nPos != -1) + { + sal_uInt16 nFieldUnit = m_xLbUnit->get_id(nPos).toUInt32(); + FieldUnit _eUnit = static_cast<FieldUnit>(nFieldUnit); + rAttrs->Put( SdrMeasureUnitItem( _eUnit ) ); + bModified = true; + } + } + + if( bPositionModified ) + { + // Position + css::drawing::MeasureTextVertPos eVPos; + css::drawing::MeasureTextHorzPos eHPos; + + RectPoint eRP = m_aCtlPosition.GetActualRP(); + switch( eRP ) + { + default: + case RectPoint::LT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::MT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::RT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + } + if (m_xTsbAutoPosH->get_state() == TRISTATE_TRUE) + eHPos = css::drawing::MeasureTextHorzPos_AUTO; + + if (m_xTsbAutoPosV->get_state() == TRISTATE_TRUE) + eVPos = css::drawing::MeasureTextVertPos_AUTO; + + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTVPOS ) != SfxItemState::DONTCARE ) + { + css::drawing::MeasureTextVertPos eOldVPos = rOutAttrs.Get(SDRATTR_MEASURETEXTVPOS).GetValue(); + if( eOldVPos != eVPos ) + { + rAttrs->Put( SdrMeasureTextVPosItem( eVPos ) ); + bModified = true; + } + } + else + { + rAttrs->Put( SdrMeasureTextVPosItem( eVPos ) ); + bModified = true; + } + + if ( rAttrs->GetItemState( SDRATTR_MEASURETEXTHPOS ) != SfxItemState::DONTCARE ) + { + css::drawing::MeasureTextHorzPos eOldHPos = rOutAttrs.Get( SDRATTR_MEASURETEXTHPOS ).GetValue(); + if( eOldHPos != eHPos ) + { + rAttrs->Put( SdrMeasureTextHPosItem( eHPos ) ); + bModified = true; + } + } + else + { + rAttrs->Put( SdrMeasureTextHPosItem( eHPos ) ); + bModified = true; + } + } + + return bModified; +} + +/************************************************************************* +|* +|* The View have to set at the measure-object to be able to notify +|* unit and floatingpoint-values +|* +\************************************************************************/ + +void SvxMeasurePage::Construct() +{ + DBG_ASSERT( pView, "No valid View transferred!" ); + + // TTTT + // pMeasureObj is member of SvxXMeasurePreview and can only be accessed due to + // SvxMeasurePage being a friend. It has its own SdrModel (also in SvxXMeasurePreview) + // and 'setting' the SdrModel is a hack. The comment above about 'notify unit and + // floatingpoint-values' is not clear, but has to be done another way - if needed. + // Checked on original aw080, is just commented out there, too. + + m_aCtlPreview.Invalidate(); +} + +std::unique_ptr<SfxTabPage> SvxMeasurePage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxMeasurePage>(pPage, pController, *rAttrs); +} + +void SvxMeasurePage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint /*eRP*/) +{ + ChangeAttrHdl_Impl(pDrawingArea); +} + +IMPL_LINK( SvxMeasurePage, ClickAutoPosHdl_Impl, weld::Toggleable&, rBox, void ) +{ + if (m_xTsbAutoPosH->get_state() == TRISTATE_TRUE) + { + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::RT: + m_aCtlPosition.SetActualRP( RectPoint::MT ); + break; + + case RectPoint::LM: + case RectPoint::RM: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::LB: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::MB ); + break; + default: ;//prevent warning + } + } + if (m_xTsbAutoPosV->get_state() == TRISTATE_TRUE) + { + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::LB: + m_aCtlPosition.SetActualRP( RectPoint::LM ); + break; + + case RectPoint::MT: + case RectPoint::MB: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::RT: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::RM ); + break; + default: ;//prevent warning + } + } + ChangeAttrHdl_Impl(&rBox); +} + +IMPL_LINK(SvxMeasurePage, ChangeAttrClickHdl_Impl, weld::Toggleable&, r, void) +{ + ChangeAttrHdl_Impl(&r); +} + +IMPL_LINK(SvxMeasurePage, ChangeAttrListBoxHdl_Impl, weld::ComboBox&, rBox, void) +{ + ChangeAttrHdl_Impl(&rBox); +} + +IMPL_LINK(SvxMeasurePage, ChangeAttrEditHdl_Impl, weld::MetricSpinButton&, rBox, void) +{ + ChangeAttrHdl_Impl(&rBox); +} + +IMPL_LINK( SvxMeasurePage, ChangeAttrSpinHdl_Impl, weld::SpinButton&, rBox, void ) +{ + ChangeAttrHdl_Impl(&rBox); +} + +void SvxMeasurePage::ChangeAttrHdl_Impl( void const * p ) +{ + if (p == m_xMtrFldLineDist.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldLineDist, eUnit ); + aAttrSet.Put( makeSdrMeasureLineDistItem( nValue ) ); + } + + if (p == m_xMtrFldHelplineOverhang.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelplineOverhang, eUnit ); + aAttrSet.Put( makeSdrMeasureHelplineOverhangItem( nValue) ); + } + + if (p == m_xMtrFldHelplineDist.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelplineDist, eUnit ); + aAttrSet.Put( makeSdrMeasureHelplineDistItem( nValue) ); + } + + if (p == m_xMtrFldHelpline1Len.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelpline1Len, eUnit ); + aAttrSet.Put( makeSdrMeasureHelpline1LenItem( nValue ) ); + } + + if (p == m_xMtrFldHelpline2Len.get()) + { + sal_Int32 nValue = GetCoreValue( *m_xMtrFldHelpline2Len, eUnit ); + aAttrSet.Put( makeSdrMeasureHelpline2LenItem( nValue ) ); + } + + if (p == m_xTsbBelowRefEdge.get()) + { + TriState eState = m_xTsbBelowRefEdge->get_state(); + if( eState != TRISTATE_INDET ) + aAttrSet.Put( SdrMeasureBelowRefEdgeItem( TRISTATE_TRUE == eState ) ); + } + + if (p == m_xMtrFldDecimalPlaces.get()) + { + sal_Int16 nValue = sal::static_int_cast< sal_Int16 >( + m_xMtrFldDecimalPlaces->get_value() ); + aAttrSet.Put( SdrMeasureDecimalPlacesItem( nValue ) ); + } + + if (p == m_xTsbParallel.get()) + { + TriState eState = m_xTsbParallel->get_state(); + if( eState != TRISTATE_INDET ) + aAttrSet.Put( SdrMeasureTextRota90Item( TRISTATE_FALSE == eState ) ); + } + + if (p == m_xTsbShowUnit.get()) + { + TriState eState = m_xTsbShowUnit->get_state(); + if( eState != TRISTATE_INDET ) + aAttrSet.Put( SdrYesNoItem( SDRATTR_MEASURESHOWUNIT, TRISTATE_TRUE == eState ) ); + } + + if (p == m_xLbUnit.get()) + { + int nPos = m_xLbUnit->get_active(); + if (nPos != -1) + { + sal_uInt16 nFieldUnit = m_xLbUnit->get_id(nPos).toUInt32(); + FieldUnit _eUnit = static_cast<FieldUnit>(nFieldUnit); + aAttrSet.Put( SdrMeasureUnitItem( _eUnit ) ); + } + } + + if (p == m_xTsbAutoPosV.get() || p == m_xTsbAutoPosH.get() || p == m_aCtlPosition.GetDrawingArea()) + { + bPositionModified = true; + + // Position + RectPoint eRP = m_aCtlPosition.GetActualRP(); + css::drawing::MeasureTextVertPos eVPos; + css::drawing::MeasureTextHorzPos eHPos; + + switch( eRP ) + { + default: + case RectPoint::LT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::LB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_LEFTOUTSIDE; break; + case RectPoint::MT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::MB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_INSIDE; break; + case RectPoint::RT: eVPos = css::drawing::MeasureTextVertPos_EAST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RM: eVPos = css::drawing::MeasureTextVertPos_CENTERED; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + case RectPoint::RB: eVPos = css::drawing::MeasureTextVertPos_WEST; + eHPos = css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE; break; + } + + CTL_STATE nState = CTL_STATE::NONE; + + if (m_xTsbAutoPosH->get_state() == TRISTATE_TRUE) + { + eHPos = css::drawing::MeasureTextHorzPos_AUTO; + nState = CTL_STATE::NOHORZ; + } + + if (m_xTsbAutoPosV->get_state() == TRISTATE_TRUE) + { + eVPos = css::drawing::MeasureTextVertPos_AUTO; + nState |= CTL_STATE::NOVERT; + } + + if (p == m_xTsbAutoPosV.get() || p == m_xTsbAutoPosH.get()) + m_aCtlPosition.SetState( nState ); + + aAttrSet.Put( SdrMeasureTextVPosItem( eVPos ) ); + aAttrSet.Put( SdrMeasureTextHPosItem( eHPos ) ); + } + + m_aCtlPreview.SetAttributes(aAttrSet); + m_aCtlPreview.Invalidate(); +} + +void SvxMeasurePage::FillUnitLB() +{ + // fill ListBox with metrics + + FieldUnit nUnit = FieldUnit::NONE; + OUString aStrMetric(m_xFtAutomatic->get_label()); + m_xLbUnit->append(OUString::number(sal_uInt32(nUnit)), aStrMetric); + + for( sal_uInt32 i = 0; i < SvxFieldUnitTable::Count(); ++i ) + { + aStrMetric = SvxFieldUnitTable::GetString(i); + nUnit = SvxFieldUnitTable::GetValue(i); + m_xLbUnit->append(OUString::number(sal_uInt32(nUnit)), aStrMetric); + } +} + +void SvxMeasurePage::PageCreated(const SfxAllItemSet& aSet) +{ + const OfaPtrItem* pOfaPtrItem = aSet.GetItem<OfaPtrItem>(SID_OBJECT_LIST, false); + + if (pOfaPtrItem) + SetView( static_cast<SdrView *>(pOfaPtrItem->GetValue())); + + Construct(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/numfmt.cxx b/cui/source/tabpages/numfmt.cxx new file mode 100644 index 000000000..4e804bc44 --- /dev/null +++ b/cui/source/tabpages/numfmt.cxx @@ -0,0 +1,1746 @@ +/* -*- 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 . + */ + +#include <sal/config.h> + +#include <o3tl/safeint.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <sfx2/objsh.hxx> +#include <vcl/outdev.hxx> +#include <i18nlangtag/lang.h> +#include <svx/svxids.hrc> +#include <svtools/colorcfg.hxx> + +#include <numcategories.hrc> +#include <strings.hrc> + +#include <svx/numinf.hxx> + +#include <numfmt.hxx> +#include <svx/numfmtsh.hxx> +#include <dialmgr.hxx> +#include <sfx2/basedlgs.hxx> +#include <svx/flagsdef.hxx> +#include <vector> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <limits> +#include <memory> + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::lang::XServiceInfo; +using ::com::sun::star::uno::UNO_QUERY; + +#define NUMKEY_UNDEFINED SAL_MAX_UINT32 + +// static ---------------------------------------------------------------- + +const WhichRangesContainer SvxNumberFormatTabPage::pRanges( + svl::Items< + SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, // 10085 - 10086 + SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA, // 10580 - 10580 + SID_ATTR_NUMBERFORMAT_NOLANGUAGE, SID_ATTR_NUMBERFORMAT_NOLANGUAGE, // 10700 - 10700 + SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE>); // 10932 - 10932 + +/************************************************************************* +#* Method: SvxNumberPreview +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberPreview +#* Function: Constructor of the class SvxNumberPreview +#* Input: Window, Resource-ID +#* Output: --- +#* +#************************************************************************/ + +SvxNumberPreview::SvxNumberPreview() + : mnPos(-1) + , mnChar(0x0) +{ +} + +/************************************************************************* +#* Method: NotifyChange +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberPreview +#* Function: Function for changing the preview string +#* Input: String, color +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberPreview::NotifyChange( const OUString& rPrevStr, + const Color* pColor ) +{ + // detect and strip out '*' related placeholders + aPrevStr = rPrevStr; + mnPos = aPrevStr.indexOf( 0x1B ); + if ( mnPos != -1 ) + { + // Right during user input the star symbol is the very + // last character before the user enters another one. + if (mnPos < aPrevStr.getLength() - 1) + { + mnChar = aPrevStr[ mnPos + 1 ]; + // delete placeholder and char to repeat + aPrevStr = aPrevStr.replaceAt( mnPos, 2, u"" ); + } + else + { + // delete placeholder + aPrevStr = aPrevStr.replaceAt( mnPos, 1, u"" ); + // do not attempt to draw a 0 fill character + mnPos = -1; + } + } + svtools::ColorConfig aColorConfig; + Color aWindowTextColor( aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor ); + aPrevCol = pColor ? *pColor : aWindowTextColor; + Invalidate(); +} + +/************************************************************************* +#* Method: Paint +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberPreview +#* Function: Function for repainting the window. +#* Input: --- +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberPreview::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.Push(vcl::PushFlags::ALL); + + svtools::ColorConfig aColorConfig; + rRenderContext.SetTextColor(aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor); + rRenderContext.SetBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor); + + vcl::Font aDrawFont = rRenderContext.GetFont(); + Size aSzWnd(GetOutputSizePixel()); + OUString aTmpStr(aPrevStr); + tools::Long nLeadSpace = (aSzWnd.Width() - rRenderContext.GetTextWidth(aTmpStr)) / 2; + + aDrawFont.SetTransparent(true); + aDrawFont.SetColor(aPrevCol); + rRenderContext.SetFont(aDrawFont); + + if (mnPos != -1) + { + tools::Long nCharWidth = rRenderContext.GetTextWidth(OUString(mnChar)); + + int nNumCharsToInsert = 0; + if (nCharWidth > 0) + nNumCharsToInsert = nLeadSpace / nCharWidth; + + if (nNumCharsToInsert > 0) + { + for (int i = 0; i < nNumCharsToInsert; ++i) + aTmpStr = aTmpStr.replaceAt(mnPos, 0, rtl::OUStringChar(mnChar)); + } + } + + tools::Long nX = 0; + if (mnPos == -1 && nLeadSpace > 0) //tdf#122120 if it won't fit anyway, then left align it + { + nX = nLeadSpace; + } + + Point aPosText(nX, (aSzWnd.Height() - GetTextHeight()) / 2); + rRenderContext.DrawText(aPosText, aTmpStr); + rRenderContext.Pop(); +} + +// class SvxNumberFormatTabPage ------------------------------------------ + +#define REMOVE_DONTKNOW() \ + if (!m_xFtLanguage->get_sensitive()) \ + { \ + m_xFtLanguage->set_sensitive(true); \ + m_xLbLanguage->set_sensitive(true); \ + m_xLbLanguage->set_active_id(pNumFmtShell->GetCurLanguage()); \ + } + +SvxNumberFormatTabPage::SvxNumberFormatTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rCoreAttrs) + : SfxTabPage(pPage, pController, "cui/ui/numberingformatpage.ui", "NumberingFormatPage", &rCoreAttrs) + , nInitFormat(std::numeric_limits<sal_uInt32>::max()) + , m_nLbFormatSelPosEdComment(SELPOS_NONE) + , bLegacyAutomaticCurrency(false) + , sAutomaticLangEntry(CuiResId(RID_CUISTR_AUTO_ENTRY)) + , m_xFtCategory(m_xBuilder->weld_label("categoryft")) + , m_xLbCategory(m_xBuilder->weld_tree_view("categorylb")) + , m_xFtFormat(m_xBuilder->weld_label("formatft")) + , m_xLbCurrency(m_xBuilder->weld_combo_box("currencylb")) + , m_xLbFormat(m_xBuilder->weld_tree_view("formatlb")) + , m_xFtLanguage(m_xBuilder->weld_label("languageft")) + , m_xCbSourceFormat(m_xBuilder->weld_check_button("sourceformat")) + , m_xFtOptions(m_xBuilder->weld_label("optionsft")) + , m_xFtDecimals(m_xBuilder->weld_label("decimalsft")) + , m_xEdDecimals(m_xBuilder->weld_spin_button("decimalsed")) + , m_xFtDenominator(m_xBuilder->weld_label("denominatorft")) + , m_xEdDenominator(m_xBuilder->weld_spin_button("denominatored")) + , m_xBtnNegRed(m_xBuilder->weld_check_button("negnumred")) + , m_xFtLeadZeroes(m_xBuilder->weld_label("leadzerosft")) + , m_xEdLeadZeroes(m_xBuilder->weld_spin_button("leadzerosed")) + , m_xBtnThousand(m_xBuilder->weld_check_button("thousands")) + , m_xBtnEngineering(m_xBuilder->weld_check_button("engineering")) + , m_xFormatCodeFrame(m_xBuilder->weld_widget("formatcode")) + , m_xEdFormat(m_xBuilder->weld_entry("formatted")) + , m_xIbAdd(m_xBuilder->weld_button("add")) + , m_xIbInfo(m_xBuilder->weld_button("edit")) + , m_xIbRemove(m_xBuilder->weld_button("delete")) + , m_xFtComment(m_xBuilder->weld_label("commentft")) + , m_xEdComment(m_xBuilder->weld_entry("commented")) + , m_xLbLanguage(new SvxLanguageBox(m_xBuilder->weld_combo_box("languagelb"))) + , m_xWndPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aWndPreview)) +{ + for (size_t i = 0; i < std::size(NUM_CATEGORIES); ++i) + m_xLbCategory->append_text(CuiResId(NUM_CATEGORIES[i])); + + auto nWidth = m_xLbCategory->get_approximate_digit_width() * 22; + m_xLbCategory->set_size_request(nWidth, m_xLbCategory->get_height_rows(7)); + m_xLbFormat->set_size_request(nWidth, m_xLbFormat->get_height_rows(5)); + m_xLbCurrency->set_size_request(nWidth, -1); // force using (narrower) width of its LbFormat sibling + + // Initially remove the "Automatically" entry. + m_xLbCurrency->set_active(-1); // First ensure that nothing is selected. + sAutomaticCurrencyEntry = m_xLbCurrency->get_text(0); + m_xLbCurrency->remove(0); + + Init_Impl(); + SetExchangeSupport(); // this page needs ExchangeSupport + nFixedCategory=-1; +} + +SvxNumberFormatTabPage::~SvxNumberFormatTabPage() +{ + pNumFmtShell.reset(); + pNumItem.reset(); + m_xWndPreview.reset(); + m_xLbLanguage.reset(); +} + +void SvxNumberFormatTabPage::Init_Impl() +{ + bNumItemFlag=true; + bOneAreaFlag=false; + + m_xIbAdd->set_sensitive(false ); + m_xIbRemove->set_sensitive(false ); + m_xIbInfo->set_sensitive(false ); + + m_xEdComment->set_text(m_xLbCategory->get_text(1)); // string for user defined + + m_xEdComment->hide(); + + m_xCbSourceFormat->set_active( false ); + m_xCbSourceFormat->set_sensitive(false); + m_xCbSourceFormat->hide(); + + Link<weld::TreeView&,void> aLink2 = LINK(this, SvxNumberFormatTabPage, SelFormatTreeListBoxHdl_Impl); + Link<weld::ComboBox&,void> aLink3 = LINK(this, SvxNumberFormatTabPage, SelFormatListBoxHdl_Impl); + m_xLbCategory->connect_changed(aLink2); + m_xLbCategory->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbFormat->connect_changed(aLink2); + m_xLbFormat->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbLanguage->connect_changed(aLink3); + m_xLbLanguage->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbCurrency->connect_changed(aLink3); + m_xLbCurrency->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xCbSourceFormat->connect_toggled(LINK(this, SvxNumberFormatTabPage, SelFormatClickHdl_Impl)); + m_xCbSourceFormat->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + + Link<weld::SpinButton&,void> aLink = LINK( this, SvxNumberFormatTabPage, OptEditHdl_Impl ); + + m_xEdDecimals->connect_value_changed(aLink); + m_xEdDecimals->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xEdDenominator->connect_value_changed(aLink); + m_xEdDenominator->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xEdLeadZeroes->connect_value_changed(aLink); + m_xEdLeadZeroes->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + + m_xBtnNegRed->connect_toggled(LINK(this, SvxNumberFormatTabPage, OptClickHdl_Impl)); + m_xBtnNegRed->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xBtnThousand->connect_toggled(LINK(this, SvxNumberFormatTabPage, OptClickHdl_Impl)); + m_xBtnThousand->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xBtnEngineering->connect_toggled(LINK(this, SvxNumberFormatTabPage, OptClickHdl_Impl)); + m_xBtnEngineering->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xLbFormat->connect_row_activated(LINK(this, SvxNumberFormatTabPage, DoubleClickHdl_Impl)); + m_xEdFormat->connect_changed(LINK(this, SvxNumberFormatTabPage, EditModifyHdl_Impl)); + m_xEdFormat->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xIbAdd->connect_clicked(LINK(this, SvxNumberFormatTabPage, ClickHdl_Impl)); + m_xIbAdd->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xIbRemove->connect_clicked(LINK(this, SvxNumberFormatTabPage, ClickHdl_Impl)); + m_xIbRemove->connect_focus_in(LINK(this, SvxNumberFormatTabPage, LostFocusHdl_Impl)); + m_xIbInfo->connect_clicked(LINK(this, SvxNumberFormatTabPage, ClickHdl_Impl)); + UpdateThousandEngineeringCheckBox(); + UpdateDecimalsDenominatorEditBox(); + + // initialize language ListBox + + m_xLbLanguage->SetLanguageList(SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, + false, false, false, true, LANGUAGE_SYSTEM, + css::i18n::ScriptType::WEAK); +} + +std::unique_ptr<SfxTabPage> SvxNumberFormatTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet ) +{ + return std::make_unique<SvxNumberFormatTabPage>(pPage, pController, *rAttrSet); +} + + +/************************************************************************* +#* Method: Reset +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: The dialog's attributes are reset +#* using the Itemset. +#* Input: SfxItemSet +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::set_active_currency(sal_Int32 nPos) +{ + static_assert(SELPOS_NONE == -1, "SELPOS_NONE was -1 at time of writing"); + if (nPos == 0 && !bLegacyAutomaticCurrency) + { + // Insert "Automatically" if currently used so it is selectable. + m_xLbCurrency->insert_text(0, sAutomaticCurrencyEntry); + bLegacyAutomaticCurrency = true; + } + if (nPos != -1 && !bLegacyAutomaticCurrency) + --nPos; + m_xLbCurrency->set_active(nPos); +} + +sal_uInt32 SvxNumberFormatTabPage::get_active_currency() const +{ + static_assert(SELPOS_NONE == -1, "SELPOS_NONE was -1 at time of writing"); + sal_Int32 nCurrencyPos = m_xLbCurrency->get_active(); + if (nCurrencyPos != -1 && !bLegacyAutomaticCurrency) + ++nCurrencyPos; + return nCurrencyPos; +} + +void SvxNumberFormatTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxUInt32Item* pValFmtAttr = nullptr; + const SfxPoolItem* pItem = nullptr; + const SfxBoolItem* pAutoEntryAttr = nullptr; + + sal_uInt16 nCatLbSelPos = 0; + sal_uInt16 nFmtLbSelPos = 0; + LanguageType eLangType = LANGUAGE_DONTKNOW; + std::vector<OUString> aFmtEntryList; + SvxNumberValueType eValType = SvxNumberValueType::Undefined; + double nValDouble = 0; + OUString aValString; + + if(const SfxBoolItem* pBoolLangItem = rSet->GetItemIfSet( SID_ATTR_NUMBERFORMAT_NOLANGUAGE )) + { + if(pBoolLangItem->GetValue()) + { + HideLanguage(); + } + else + { + HideLanguage(false); + } + + } + + SfxItemState eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_INFO ),true,&pItem); + + if(eState==SfxItemState::SET) + { + if(pNumItem==nullptr) + { + bNumItemFlag=true; + pNumItem.reset( static_cast<SvxNumberInfoItem *>(pItem->Clone()) ); + } + else + { + bNumItemFlag=false; + } + } + else + { + bNumItemFlag=false; + } + + + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_ONE_AREA )); + + if(eState==SfxItemState::SET) + { + const SfxBoolItem* pBoolItem = static_cast<const SfxBoolItem*>( + GetItem( *rSet, SID_ATTR_NUMBERFORMAT_ONE_AREA)); + + if(pBoolItem!=nullptr) + { + bOneAreaFlag= pBoolItem->GetValue(); + } + } + + eState = rSet->GetItemState( SID_ATTR_NUMBERFORMAT_SOURCE ); + + if ( eState == SfxItemState::SET ) + { + const SfxBoolItem* pBoolItem = + GetItem( *rSet, SID_ATTR_NUMBERFORMAT_SOURCE ); + if ( pBoolItem ) + m_xCbSourceFormat->set_active(pBoolItem->GetValue()); + else + m_xCbSourceFormat->set_active( false ); + m_xCbSourceFormat->set_sensitive(true); + m_xCbSourceFormat->show(); + } + else + { + bool bInit = false; // set to sal_True for debug test + m_xCbSourceFormat->set_active( bInit ); + m_xCbSourceFormat->set_sensitive( bInit ); + m_xCbSourceFormat->set_visible( bInit ); + } + + // pNumItem must have been set from outside! + DBG_ASSERT( pNumItem, "No NumberInfo, no NumberFormatter, goodbye. CRASH. :-(" ); + + eState = rSet->GetItemState( GetWhich( SID_ATTR_NUMBERFORMAT_VALUE ) ); + + if ( SfxItemState::DONTCARE != eState ) + pValFmtAttr = GetItem( *rSet, SID_ATTR_NUMBERFORMAT_VALUE ); + + eValType = pNumItem->GetValueType(); + + switch ( eValType ) + { + case SvxNumberValueType::String: + aValString = pNumItem->GetValueString(); + break; + case SvxNumberValueType::Number: + // #50441# string may be set in addition to the value + aValString = pNumItem->GetValueString(); + nValDouble = pNumItem->GetValueDouble(); + break; + case SvxNumberValueType::Undefined: + default: + break; + } + + pNumFmtShell.reset(); // delete old shell if applicable (== reset) + + nInitFormat = pValFmtAttr // memorize init key + ? pValFmtAttr->GetValue() // (for FillItemSet()) + : std::numeric_limits<sal_uInt32>::max(); // == DONT_KNOW + + + if ( eValType == SvxNumberValueType::String ) + pNumFmtShell.reset( SvxNumberFormatShell::Create( + pNumItem->GetNumberFormatter(), + pValFmtAttr ? nInitFormat : 0, + eValType, + aValString ) ); + else + pNumFmtShell.reset( SvxNumberFormatShell::Create( + pNumItem->GetNumberFormatter(), + pValFmtAttr ? nInitFormat : 0, + eValType, + nValDouble, + &aValString ) ); + + + bool bUseStarFormat = false; + if (SfxObjectShell* pDocSh = SfxObjectShell::Current()) + { + // is this a calc document + Reference< XServiceInfo > xSI( pDocSh->GetModel(), UNO_QUERY ); + if ( xSI.is() ) + bUseStarFormat = xSI->supportsService("com.sun.star.sheet.SpreadsheetDocument"); + } + pNumFmtShell->SetUseStarFormat( bUseStarFormat ); + + FillCurrencyBox(); + + OUString aPrevString; + const Color* pDummy = nullptr; + pNumFmtShell->GetInitSettings( nCatLbSelPos, eLangType, nFmtLbSelPos, + aFmtEntryList, aPrevString, pDummy ); + + if (nCatLbSelPos==CAT_CURRENCY) + set_active_currency(pNumFmtShell->GetCurrencySymbol()); + + nFixedCategory=nCatLbSelPos; + if(bOneAreaFlag) + { + OUString sFixedCategory = m_xLbCategory->get_text(nFixedCategory); + m_xLbCategory->clear(); + m_xLbCategory->append_text(sFixedCategory); + SetCategory(0); + } + else + { + SetCategory(nCatLbSelPos ); + } + eState = rSet->GetItemState( SID_ATTR_NUMBERFORMAT_ADD_AUTO ); + if(SfxItemState::SET == eState) + pAutoEntryAttr = GetItem( *rSet, SID_ATTR_NUMBERFORMAT_ADD_AUTO ); + // no_NO is an alias for nb_NO and normally isn't listed, we need it for + // backwards compatibility, but only if the format passed is of + // LanguageType no_NO. + if ( eLangType == LANGUAGE_NORWEGIAN ) + { + m_xLbLanguage->remove_id(eLangType); // in case we're already called + m_xLbLanguage->InsertLanguage( eLangType ); + } + m_xLbLanguage->set_active_id(eLangType); + if(pAutoEntryAttr) + AddAutomaticLanguage_Impl(eLangType, pAutoEntryAttr->GetValue()); + UpdateFormatListBox_Impl(false,true); + +//! This spoils everything because it rematches currency formats based on +//! the selected m_xLbCurrency entry instead of the current format. +//! Besides that everything seems to be initialized by now, so why call it? +// SelFormatHdl_Impl(m_xLbCategory.get()); + + if ( pValFmtAttr ) + { + EditHdl_Impl(m_xEdFormat.get()); // UpdateOptions_Impl() as a side effect + } + else // DONT_KNOW + { + // everything disabled except direct input or changing the category + Obstructing(); + } + + if ( m_xCbSourceFormat->get_active() ) + { + // everything disabled except SourceFormat checkbox + EnableBySourceFormat_Impl(); + } +} + +/************************************************************************* +#* Method: Obstructing +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Disable the controls except from changing the category +#* and direct input. +#* Input: --- +#* Output: --- +#* +#************************************************************************/ +void SvxNumberFormatTabPage::Obstructing() +{ + m_xLbFormat->select(-1); + m_xLbLanguage->set_active(-1); + m_xFtLanguage->set_sensitive(false); + m_xLbLanguage->set_sensitive(false); + + m_xIbAdd->set_sensitive(false ); + m_xIbRemove->set_sensitive(false ); + m_xIbInfo->set_sensitive(false ); + + m_xBtnNegRed->set_sensitive(false); + m_xBtnThousand->set_sensitive(false); + m_xBtnEngineering->set_sensitive(false); + m_xFtLeadZeroes->set_sensitive(false); + m_xFtDecimals->set_sensitive(false); + m_xFtDenominator->set_sensitive(false); + m_xEdLeadZeroes->set_sensitive(false); + m_xEdDecimals->set_sensitive(false); + m_xEdDenominator->set_sensitive(false); + m_xFtOptions->set_sensitive(false); + m_xEdDecimals->set_text( OUString() ); + m_xEdLeadZeroes->set_text( OUString() ); + m_xBtnNegRed->set_active( false ); + m_xBtnThousand->set_active( false ); + m_xBtnEngineering->set_active( false ); + m_aWndPreview.NotifyChange( OUString() ); + + m_xLbCategory->select(0); + m_xEdFormat->set_text( OUString() ); + m_xFtComment->set_label( OUString() ); + m_xEdComment->set_text(m_xLbCategory->get_text(1)); // string for user defined + + m_xEdFormat->grab_focus(); +} + + +/************************************************************************* +#* Enable/Disable dialog parts depending on the value of the SourceFormat +#* checkbox. +#************************************************************************/ +void SvxNumberFormatTabPage::EnableBySourceFormat_Impl() +{ + bool bEnable = !m_xCbSourceFormat->get_active(); + if ( !bEnable ) + m_xCbSourceFormat->grab_focus(); + m_xFtCategory->set_sensitive( bEnable ); + m_xLbCategory->set_sensitive( bEnable ); + m_xFtFormat->set_sensitive( bEnable ); + m_xLbCurrency->set_sensitive( bEnable ); + m_xLbFormat->set_sensitive( bEnable ); + m_xFtLanguage->set_sensitive( bEnable ); + m_xLbLanguage->set_sensitive( bEnable ); + m_xFtDecimals->set_sensitive( bEnable ); + m_xEdDecimals->set_sensitive( bEnable ); + m_xFtDenominator->set_sensitive( bEnable ); + m_xEdDenominator->set_sensitive( bEnable ); + m_xFtLeadZeroes->set_sensitive( bEnable ); + m_xEdLeadZeroes->set_sensitive( bEnable ); + m_xBtnNegRed->set_sensitive( bEnable ); + m_xBtnThousand->set_sensitive( bEnable ); + m_xBtnEngineering->set_sensitive( bEnable ); + m_xFtOptions->set_sensitive( bEnable ); + m_xFormatCodeFrame->set_sensitive( bEnable ); +} + + +/************************************************************************* +#* Method: HideLanguage +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Hides the language settings: +#* Input: sal_Bool nFlag +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::HideLanguage(bool bFlag) +{ + m_xFtLanguage->set_visible(!bFlag); + m_xLbLanguage->set_visible(!bFlag); +} + +/************************************************************************* +#* Method: FillItemSet +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Adjusts the attributes in the ItemSet, +#* and - if bNumItemFlag is not set - the +#* numItem in the DocShell. +#* Input: SfxItemSet +#* Output: --- +#* +#************************************************************************/ + +bool SvxNumberFormatTabPage::FillItemSet( SfxItemSet* rCoreAttrs ) +{ + bool bDataChanged = m_xFtLanguage->get_sensitive() || m_xCbSourceFormat->get_sensitive(); + if ( bDataChanged ) + { + const SfxItemSet& rMyItemSet = GetItemSet(); + sal_uInt16 nWhich = GetWhich( SID_ATTR_NUMBERFORMAT_VALUE ); + SfxItemState eItemState = rMyItemSet.GetItemState( nWhich, false ); + + // OK chosen - Is format code input entered already taken over? + // If not, simulate Add. Upon syntax error ignore input and prevent Put. + OUString aFormat = m_xEdFormat->get_text(); + sal_uInt32 nCurKey = pNumFmtShell->GetCurNumFmtKey(); + + if ( m_xIbAdd->get_sensitive() || pNumFmtShell->IsTmpCurrencyFormat(aFormat) ) + { // #79599# It is not sufficient to just add the format code (or + // delete it in case of bOneAreaFlag and resulting category change). + // Upon switching tab pages we need all settings to be consistent + // in case this page will be redisplayed later. + bDataChanged = Click_Impl(*m_xIbAdd); + nCurKey = pNumFmtShell->GetCurNumFmtKey(); + } + else if(nCurKey == NUMKEY_UNDEFINED) + { // something went wrong, e.g. in Writer #70281# + pNumFmtShell->FindEntry(aFormat, &nCurKey); + } + + + // Chosen format: + + if ( bDataChanged ) + { + bDataChanged = ( nInitFormat != nCurKey ); + + if (bDataChanged) + { + rCoreAttrs->Put( SfxUInt32Item( nWhich, nCurKey ) ); + } + else if(SfxItemState::DEFAULT == eItemState) + { + rCoreAttrs->ClearItem( nWhich ); + } + } + + + // List of changed user defined formats: + + std::vector<sal_uInt32> const & aDelFormats = pNumFmtShell->GetUpdateData(); + + if ( !aDelFormats.empty() ) + { + + pNumItem->SetDelFormats( std::vector(aDelFormats) ); + + if(bNumItemFlag) + { + rCoreAttrs->Put( *pNumItem ); + } + else + { + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + DBG_ASSERT( pDocSh, "DocShell not found!" ); + if (pDocSh) + pDocSh->PutItem( *pNumItem ); + } + } + + + // Whether source format is to be taken or not: + + if ( m_xCbSourceFormat->get_sensitive() ) + { + SfxItemState _eItemState = rMyItemSet.GetItemState( SID_ATTR_NUMBERFORMAT_SOURCE, false ); + const SfxBoolItem* pBoolItem = + GetItem( rMyItemSet, SID_ATTR_NUMBERFORMAT_SOURCE ); + bool bOld = pBoolItem && pBoolItem->GetValue(); + rCoreAttrs->Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE, m_xCbSourceFormat->get_active() ) ); + if ( !bDataChanged ) + bDataChanged = (bOld != m_xCbSourceFormat->get_active() || + _eItemState != SfxItemState::SET); + } + + // FillItemSet is only called on OK, here we can notify the + // NumberFormatShell that all new user defined formats are valid. + pNumFmtShell->ValidateNewEntries(); + if(m_xLbLanguage->get_visible() && + m_xLbLanguage->find_text(sAutomaticLangEntry) != -1) + rCoreAttrs->Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ADD_AUTO, + m_xLbLanguage->get_active_text() == sAutomaticLangEntry)); + } + + return bDataChanged; +} + + +DeactivateRC SvxNumberFormatTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void SvxNumberFormatTabPage::FillFormatListBox_Impl( std::vector<OUString>& rEntries ) +{ + OUString aEntry; + OUString aTmpString; + size_t i = 0; + short nTmpCatPos; + + m_xLbFormat->clear(); + if (rEntries.empty()) + return; + + m_xLbFormat->freeze(); + + if(bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=m_xLbCategory->get_selected_index(); + } + + switch (nTmpCatPos) + { + case CAT_ALL: + case CAT_TEXT: + case CAT_NUMBER: i=1; + aEntry=rEntries[0]; + if (nTmpCatPos == CAT_TEXT) + aTmpString=aEntry; + else + aTmpString = pNumFmtShell->GetStandardName(); + m_xLbFormat->append_text(aTmpString); + break; + + default: break; + } + + if(pNumFmtShell!=nullptr) + { + for ( ; i < rEntries.size(); ++i ) + { + aEntry = rEntries[i]; + short aPrivCat = pNumFmtShell->GetCategory4Entry( static_cast<short>(i) ); + if(aPrivCat!=CAT_TEXT) + { + const Color* pPreviewColor = nullptr; + OUString aPreviewString( GetExpColorString( pPreviewColor, aEntry, aPrivCat ) ); + m_xLbFormat->append_text(aPreviewString); + if (pPreviewColor) + m_xLbFormat->set_font_color(m_xLbFormat->n_children() - 1, *pPreviewColor); + } + else + { + m_xLbFormat->append_text(aEntry); + } + } + } + m_xLbFormat->thaw(); + rEntries.clear(); +} + +/************************************************************************* +#* Method: UpdateOptions_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Adjusts the options attributes +#* depending on the selected format. +#* Input: Flag, whether the category has changed. +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::UpdateOptions_Impl( bool bCheckCatChange /*= sal_False*/ ) +{ + OUString theFormat = m_xEdFormat->get_text(); + sal_Int32 nCurCategory = m_xLbCategory->get_selected_index(); + sal_uInt16 nCategory = static_cast<sal_uInt16>(nCurCategory); + sal_uInt16 nDecimals = 0; + sal_uInt16 nZeroes = 0; + bool bNegRed = false; + bool bThousand = false; + sal_Int32 nCurrencyPos = get_active_currency(); + + if(bOneAreaFlag) + nCurCategory=nFixedCategory; + + + pNumFmtShell->GetOptions( theFormat, + bThousand, bNegRed, + nDecimals, nZeroes, + nCategory ); + bool bDoIt=false; + if(nCategory==CAT_CURRENCY) + { + sal_uInt16 nTstPos=pNumFmtShell->FindCurrencyFormat(theFormat); + if(nCurrencyPos!=static_cast<sal_Int32>(nTstPos) && nTstPos!=sal_uInt16(-1)) + { + set_active_currency(nTstPos); + pNumFmtShell->SetCurrencySymbol(nTstPos); + bDoIt=true; + } + } + + if ( nCategory != nCurCategory || bDoIt) + { + if ( bCheckCatChange ) + { + if(bOneAreaFlag) + SetCategory(0); + else + SetCategory(nCategory ); + + UpdateFormatListBox_Impl( true, false ); + } + } + else if ( m_xLbFormat->n_children() > 0 ) + { + sal_uInt32 nCurEntryKey=NUMKEY_UNDEFINED; + if(!pNumFmtShell->FindEntry( m_xEdFormat->get_text(),&nCurEntryKey)) + { + m_xLbFormat->select(-1); + } + } + if(bOneAreaFlag) + { + nCategory=nFixedCategory; + } + + UpdateThousandEngineeringCheckBox(); + UpdateDecimalsDenominatorEditBox(); + switch ( nCategory ) + { + case CAT_SCIENTIFIC: // bThousand is for Engineering notation + { + sal_uInt16 nIntDigits = pNumFmtShell->GetFormatIntegerDigits(theFormat); + bThousand = (nIntDigits > 0) && (nIntDigits % 3 == 0); + m_xBtnEngineering->set_sensitive(true); + m_xBtnEngineering->set_active( bThousand ); + } + [[fallthrough]]; + case CAT_NUMBER: + case CAT_PERCENT: + case CAT_CURRENCY: + case CAT_FRACTION: + case CAT_TIME: + m_xFtOptions->set_sensitive(true); + if ( nCategory == CAT_FRACTION ) + { + m_xFtDenominator->set_sensitive(true); + m_xEdDenominator->set_sensitive(true); + } + else + { + m_xFtDecimals->set_sensitive(true); + m_xEdDecimals->set_sensitive(true); + } + m_xFtLeadZeroes->set_sensitive( nCategory != CAT_TIME ); + m_xEdLeadZeroes->set_sensitive( nCategory != CAT_TIME ); + m_xBtnNegRed->set_sensitive(true); + if ( nCategory == CAT_NUMBER && m_xLbFormat->get_selected_index() == 0 ) + m_xEdDecimals->set_text( "" ); //General format tdf#44399 + else + if ( nCategory == CAT_FRACTION ) + m_xEdDenominator->set_value( nDecimals ); + else + m_xEdDecimals->set_value( nDecimals ); + if ( nCategory != CAT_TIME ) + m_xEdLeadZeroes->set_value( nZeroes ); + m_xBtnNegRed->set_active( bNegRed ); + if ( nCategory != CAT_SCIENTIFIC ) + { + m_xBtnThousand->set_sensitive( nCategory != CAT_TIME ); + m_xBtnThousand->set_active( bThousand && nCategory != CAT_TIME ); + } + break; + + case CAT_ALL: + case CAT_USERDEFINED: + case CAT_TEXT: + case CAT_DATE: + case CAT_BOOLEAN: + default: + m_xFtOptions->set_sensitive(false); + m_xFtDecimals->set_sensitive(false); + m_xEdDecimals->set_sensitive(false); + m_xFtDenominator->set_sensitive(false); + m_xEdDenominator->set_sensitive(false); + m_xFtLeadZeroes->set_sensitive(false); + m_xEdLeadZeroes->set_sensitive(false); + m_xBtnNegRed->set_sensitive(false); + m_xBtnThousand->set_sensitive(false); + m_xBtnEngineering->set_sensitive(false); + m_xEdDecimals->set_text( OUString() ); + m_xEdLeadZeroes->set_text( OUString() ); + m_xBtnNegRed->set_active( false ); + m_xBtnThousand->set_active( false ); + m_xBtnEngineering->set_active( false ); + } +} + + +/************************************************************************* +#* Method: UpdateFormatListBox_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Updates the format listbox and additionally the +#* string in the editbox is changed depending on +#* the bUpdateEdit flag. +#* Input: Flags for category and editbox. +#* Output: --- +#* +#************************************************************************/ + +void SvxNumberFormatTabPage::UpdateFormatListBox_Impl + ( + bool bCat, // Category or country/language ListBox? + bool bUpdateEdit + ) +{ + std::vector<OUString> aEntryList; + short nFmtLbSelPos = 0; + short nTmpCatPos; + + if(bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=m_xLbCategory->get_selected_index(); + } + + + if ( bCat ) + { + if(nTmpCatPos!=CAT_CURRENCY) + m_xLbCurrency->hide(); + else + m_xLbCurrency->show(); + + pNumFmtShell->CategoryChanged(nTmpCatPos,nFmtLbSelPos, aEntryList); + } + else + pNumFmtShell->LanguageChanged(m_xLbLanguage->get_active_id(), + nFmtLbSelPos,aEntryList); + + REMOVE_DONTKNOW() // possibly UI-Enable + + + if ( (!aEntryList.empty()) && (nFmtLbSelPos != SELPOS_NONE) ) + { + if(bUpdateEdit) + { + OUString aFormat=aEntryList[nFmtLbSelPos]; + m_xEdFormat->set_text(aFormat); + m_xFtComment->set_label(pNumFmtShell->GetComment4Entry(nFmtLbSelPos)); + } + + if(!bOneAreaFlag || !bCat) + { + FillFormatListBox_Impl( aEntryList ); + m_xLbFormat->select(nFmtLbSelPos); + + m_xFtComment->set_label(pNumFmtShell->GetComment4Entry(nFmtLbSelPos)); + if(pNumFmtShell->GetUserDefined4Entry(nFmtLbSelPos)) + { + if(pNumFmtShell->GetComment4Entry(nFmtLbSelPos).isEmpty()) + { + m_xFtComment->set_label(m_xLbCategory->get_text(1)); + } + } + ChangePreviewText( static_cast<sal_uInt16>(nFmtLbSelPos) ); + } + + } + else + { + FillFormatListBox_Impl( aEntryList ); + if(nFmtLbSelPos != SELPOS_NONE) + { + m_xLbFormat->select(static_cast<sal_uInt16>(nFmtLbSelPos)); + + m_xFtComment->set_label(pNumFmtShell->GetComment4Entry(nFmtLbSelPos)); + if(pNumFmtShell->GetUserDefined4Entry(nFmtLbSelPos)) + { + if(pNumFmtShell->GetComment4Entry(nFmtLbSelPos).isEmpty()) + { + m_xFtComment->set_label(m_xLbCategory->get_text(1)); + } + } + } + else + { + m_xLbFormat->select(-1); + } + + if ( bUpdateEdit ) + { + m_xEdFormat->set_text( OUString() ); + m_aWndPreview.NotifyChange( OUString() ); + } + } + + aEntryList.clear(); +} + + +/** + * Change visible checkbox according to category format + * if scientific format "Engineering notation" + * else "Thousands separator" + */ + +void SvxNumberFormatTabPage::UpdateThousandEngineeringCheckBox() +{ + bool bIsScientific = m_xLbCategory->get_selected_index() == CAT_SCIENTIFIC; + m_xBtnThousand->set_visible( !bIsScientific ); + m_xBtnEngineering->set_visible( bIsScientific ); +} + + +/** + * Change visible Edit box and Fixed text according to category format + * if fraction format "Denominator places" + * else "Decimal places" + */ + +void SvxNumberFormatTabPage::UpdateDecimalsDenominatorEditBox() +{ + bool bIsFraction = m_xLbCategory->get_selected_index() == CAT_FRACTION; + m_xFtDecimals->set_visible( !bIsFraction ); + m_xEdDecimals->set_visible( !bIsFraction ); + m_xFtDenominator->set_visible( bIsFraction ); + m_xEdDenominator->set_visible( bIsFraction ); +} + + +/************************************************************************* +#* Handle: DoubleClickHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: On a double click in the format listbox the +#* value is adopted and the OK button pushed. +#* Input: Pointer on the Listbox +#* Output: --- +#* +#************************************************************************/ +IMPL_LINK(SvxNumberFormatTabPage, DoubleClickHdl_Impl, weld::TreeView&, rLb, bool) +{ + SelFormatHdl_Impl(&rLb); + + SfxOkDialogController* pController = GetDialogController(); + assert(pController); + weld::Button& rOkButton = pController->GetOKButton(); + rOkButton.clicked(); + + return true; +} + +/************************************************************************* +#* Method: SelFormatHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Is called when the language, the category or the format +#* is changed. Accordingly the settings are adjusted. +#* Input: Pointer on the Listbox +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK(SvxNumberFormatTabPage, SelFormatClickHdl_Impl, weld::Toggleable&, rLb, void) +{ + SelFormatHdl_Impl(&rLb); +} + +IMPL_LINK(SvxNumberFormatTabPage, SelFormatTreeListBoxHdl_Impl, weld::TreeView&, rLb, void) +{ + SelFormatHdl_Impl(&rLb); +} + +IMPL_LINK(SvxNumberFormatTabPage, SelFormatListBoxHdl_Impl, weld::ComboBox&, rLb, void) +{ + SelFormatHdl_Impl(&rLb); +} + +void SvxNumberFormatTabPage::SelFormatHdl_Impl(weld::Widget* pLb) +{ + if (m_nLbFormatSelPosEdComment != SELPOS_NONE) + { + // Click handler is called before focus change handler, so finish + // comment editing of previous format, otherwise a new format will have + // the old comment displayed after LostFocusHdl_Impl() is called + // later. Also, clicking into another category invalidates the format + // list and SvxNumberFormatShell::SetComment4Entry() could either + // access a wrong format from aCurEntryList[nEntry] or crash there if + // the new vector has less elements. + LostFocusHdl_Impl(*pLb); + } + + if (pLb == m_xCbSourceFormat.get()) + { + EnableBySourceFormat_Impl(); // enable/disable everything else + if ( m_xCbSourceFormat->get_active() ) + return; // just disabled everything else + + // Reinit options enable/disable for current selection. + + // Current category may be UserDefined with no format entries defined. + if (m_xLbFormat->get_selected_index() == -1) + pLb = m_xLbCategory.get(); // continue with the current category selected + else + pLb = m_xLbFormat.get(); // continue with the current format selected + } + + sal_Int32 nTmpCatPos; + + if(bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=m_xLbCategory->get_selected_index(); + } + + if (nTmpCatPos==CAT_CURRENCY && pLb == m_xLbCurrency.get()) + pNumFmtShell->SetCurrencySymbol(get_active_currency()); + + // Format-ListBox ---------------------------------------------------- + if (pLb == m_xLbFormat.get()) + { + int nSelPos = m_xLbFormat->get_selected_index(); + short nFmtLbSelPos = static_cast<short>(nSelPos); + + OUString aFormat = pNumFmtShell->GetFormat4Entry(nFmtLbSelPos); + OUString aComment = pNumFmtShell->GetComment4Entry(nFmtLbSelPos); + + if(pNumFmtShell->GetUserDefined4Entry(nFmtLbSelPos)) + { + if(aComment.isEmpty()) + { + aComment = m_xLbCategory->get_text(1); + } + } + + if ( !aFormat.isEmpty() ) + { + if (!m_xEdFormat->has_focus()) + m_xEdFormat->set_text( aFormat ); + m_xFtComment->set_label(aComment); + ChangePreviewText( static_cast<sal_uInt16>(nSelPos) ); + } + + REMOVE_DONTKNOW() // possibly UI-Enable + + if ( pNumFmtShell->FindEntry( aFormat) ) + { + m_xIbAdd->set_sensitive(false ); + bool bIsUserDef=pNumFmtShell->IsUserDefined( aFormat ); + m_xIbRemove->set_sensitive(bIsUserDef); + m_xIbInfo->set_sensitive(bIsUserDef); + + } + else + { + m_xIbAdd->set_sensitive(true); + m_xIbInfo->set_sensitive(true); + m_xIbRemove->set_sensitive(false ); + m_xFtComment->set_label(m_xEdComment->get_text()); + + } + UpdateOptions_Impl( false ); + + return; + } + + + // category-ListBox ------------------------------------------------- + if (pLb == m_xLbCategory.get() || pLb == m_xLbCurrency.get()) + { + UpdateFormatListBox_Impl( true, true ); + EditHdl_Impl( nullptr ); + UpdateOptions_Impl( false ); + + return; + } + + + // language/country-ListBox ---------------------------------------------- + if (pLb == m_xLbLanguage->get_widget()) + { + UpdateFormatListBox_Impl( false, true ); + EditHdl_Impl(m_xEdFormat.get()); + + return; + } +} + + +/************************************************************************* +#* Method: ClickHdl_Impl, weld::Button& rIB +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Called when the add or delete button is pushed, +#* adjusts the number format list. +#* Input: Toolbox- Button +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK( SvxNumberFormatTabPage, ClickHdl_Impl, weld::Button&, rIB, void) +{ + Click_Impl(rIB); +} + +bool SvxNumberFormatTabPage::Click_Impl(const weld::Button& rIB) +{ + sal_uInt8 nReturn = 0; + constexpr sal_uInt8 nReturnChanged = 0x1; // THE boolean return value + constexpr sal_uInt8 nReturnAdded = 0x2; // temp: format added + constexpr sal_uInt8 nReturnOneArea = 0x4; // temp: one area but category changed => ignored + + if (&rIB == m_xIbAdd.get()) + { // Also called from FillItemSet() if a temporary currency format has + // to be added, not only if the Add button is enabled. + OUString aFormat = m_xEdFormat->get_text(); + std::vector<OUString> aEntryList; + std::vector<OUString> a2EntryList; + sal_uInt16 nCatLbSelPos = 0; + short nFmtLbSelPos = SELPOS_NONE; + sal_Int32 nErrPos=0; + + pNumFmtShell->SetCurCurrencyEntry(nullptr); + bool bAdded = pNumFmtShell->AddFormat( aFormat, nErrPos, + nCatLbSelPos, nFmtLbSelPos, + aEntryList); + if ( bAdded ) + nReturn |= nReturnChanged | nReturnAdded; + + if (m_xEdComment->get_visible()) + { + m_xEdFormat->grab_focus(); + m_xEdComment->hide(); + m_xFtComment->show(); + m_xFtComment->set_label(m_xEdComment->get_text()); + } + + if ( !nErrPos ) // Syntax ok? + { + // May be sorted under a different locale if LCID was parsed. + if (bAdded) + m_xLbLanguage->set_active_id(pNumFmtShell->GetCurLanguage()); + + if (nCatLbSelPos==CAT_CURRENCY) + set_active_currency(pNumFmtShell->GetCurrencySymbol()); + + if(bOneAreaFlag && (nFixedCategory!=nCatLbSelPos)) + { + if(bAdded) aEntryList.clear(); + pNumFmtShell->RemoveFormat( aFormat, + nCatLbSelPos, + nFmtLbSelPos, + a2EntryList); + a2EntryList.clear(); + m_xEdFormat->grab_focus(); + m_xEdFormat->select_region(0, -1); + nReturn |= nReturnOneArea; + } + else + { + if ( bAdded && (nFmtLbSelPos != SELPOS_NONE) ) + { + // everything all right + if(bOneAreaFlag) //@@ ??? + SetCategory(0); + else + SetCategory(nCatLbSelPos ); + + FillFormatListBox_Impl( aEntryList ); + if (m_xEdComment->get_text()!=m_xLbCategory->get_text(1)) + { + pNumFmtShell->SetComment4Entry(nFmtLbSelPos, + m_xEdComment->get_text()); + } + else + { + pNumFmtShell->SetComment4Entry(nFmtLbSelPos, + OUString()); + } + m_xLbFormat->select(static_cast<sal_uInt16>(nFmtLbSelPos)); + m_xEdFormat->set_text( aFormat ); + + m_xEdComment->set_text(m_xLbCategory->get_text(1)); // String for user defined + + ChangePreviewText( static_cast<sal_uInt16>(nFmtLbSelPos) ); + } + } + } + else // syntax error + { + m_xEdFormat->grab_focus(); + m_xEdFormat->select_region(nErrPos == -1 ? m_xEdFormat->get_text().getLength() : nErrPos, -1); + } + EditHdl_Impl(m_xEdFormat.get()); + nReturn = ((nReturn & nReturnOneArea) ? 0 : (nReturn & nReturnChanged)); + + aEntryList.clear(); + a2EntryList.clear(); + } + else if (&rIB == m_xIbRemove.get()) + { + OUString aFormat = m_xEdFormat->get_text(); + std::vector<OUString> aEntryList; + sal_uInt16 nCatLbSelPos = 0; + short nFmtLbSelPos = SELPOS_NONE; + + pNumFmtShell->RemoveFormat( aFormat, + nCatLbSelPos, + nFmtLbSelPos, + aEntryList ); + + m_xEdComment->set_text(m_xLbCategory->get_text(1)); + + if( nFmtLbSelPos>=0 && o3tl::make_unsigned(nFmtLbSelPos)<aEntryList.size() ) + { + aFormat = aEntryList[nFmtLbSelPos]; + } + + FillFormatListBox_Impl( aEntryList ); + + if ( nFmtLbSelPos != SELPOS_NONE ) + { + if(bOneAreaFlag) //@@ ??? + SetCategory(0); + else + SetCategory(nCatLbSelPos ); + + m_xLbFormat->select(static_cast<sal_uInt16>(nFmtLbSelPos)); + m_xEdFormat->set_text( aFormat ); + ChangePreviewText( static_cast<sal_uInt16>(nFmtLbSelPos) ); + } + else + { + // set to "all/standard" + SetCategory(0); + SelFormatHdl_Impl(m_xLbCategory.get()); + } + + EditHdl_Impl(m_xEdFormat.get()); + + aEntryList.clear(); + } + else if (&rIB == m_xIbInfo.get()) + { + if (!m_xEdComment->get_visible()) + { + if (!m_xIbAdd->get_sensitive()) + // Editing for existing format. + m_nLbFormatSelPosEdComment = m_xLbFormat->get_selected_index(); + + m_xEdComment->set_text(m_xFtComment->get_label()); + m_xEdComment->show(); + m_xFtComment->hide(); + m_xEdComment->grab_focus(); + } + else + { + m_xEdFormat->grab_focus(); + m_xFtComment->set_label( m_xEdComment->get_text()); + m_xEdComment->hide(); + m_xFtComment->show(); + } + } + + return nReturn; +} + + +/************************************************************************* +#* Method: EditHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: When the entry in the edit field is changed +#* the preview is updated and +#* Input: Pointer on Editbox +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK(SvxNumberFormatTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +{ + EditHdl_Impl(&rEdit); +} + +void SvxNumberFormatTabPage::EditHdl_Impl(const weld::Entry* pEdFormat) +{ + sal_uInt32 nCurKey = NUMKEY_UNDEFINED; + + if ( m_xEdFormat->get_text().isEmpty() ) + { + m_xIbAdd->set_sensitive(false ); + m_xIbRemove->set_sensitive(false ); + m_xIbInfo->set_sensitive(false ); + m_xFtComment->set_label(OUString()); + } + else + { + OUString aFormat = m_xEdFormat->get_text(); + MakePreviewText( aFormat ); + + if ( pNumFmtShell->FindEntry( aFormat, &nCurKey ) ) + { + m_xIbAdd->set_sensitive(false ); + bool bUserDef=pNumFmtShell->IsUserDefined( aFormat ); + + m_xIbRemove->set_sensitive(bUserDef); + m_xIbInfo->set_sensitive(bUserDef); + + if(bUserDef) + { + sal_uInt16 nTmpCurPos=pNumFmtShell->FindCurrencyFormat(aFormat ); + if (nTmpCurPos != sal_uInt16(-1)) + set_active_currency(nTmpCurPos); + } + short nPosi=pNumFmtShell->GetListPos4Entry( nCurKey, aFormat); + if(nPosi>=0) + m_xLbFormat->select(static_cast<sal_uInt16>(nPosi)); + + } + else + { + + m_xIbAdd->set_sensitive(true); + m_xIbInfo->set_sensitive(true); + m_xIbRemove->set_sensitive(false ); + + m_xFtComment->set_label(m_xEdComment->get_text()); + + } + } + + if (pEdFormat) + { + pNumFmtShell->SetCurNumFmtKey( nCurKey ); + UpdateOptions_Impl( true ); + } +} + + +/************************************************************************* +#* Method: NotifyChange +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Does changes in the number attributes. +#* Input: Options- Controls +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK(SvxNumberFormatTabPage, OptClickHdl_Impl, weld::Toggleable&, rOptCtrl, void) +{ + OptHdl_Impl(&rOptCtrl); +} + +IMPL_LINK(SvxNumberFormatTabPage, OptEditHdl_Impl, weld::SpinButton&, rEdit, void) +{ + OptHdl_Impl(&rEdit); +} + +void SvxNumberFormatTabPage::OptHdl_Impl(const weld::Widget* pOptCtrl) +{ + if ( !(pOptCtrl == m_xEdLeadZeroes.get() + || pOptCtrl == m_xEdDecimals.get() + || pOptCtrl == m_xEdDenominator.get() + || pOptCtrl == m_xBtnNegRed.get() + || pOptCtrl == m_xBtnThousand.get() + || pOptCtrl == m_xBtnEngineering.get())) + return; + + OUString aFormat; + bool bThousand = ( m_xBtnThousand->get_visible() && m_xBtnThousand->get_sensitive() && m_xBtnThousand->get_active() ) + || ( m_xBtnEngineering->get_visible() && m_xBtnEngineering->get_sensitive() && m_xBtnEngineering->get_active() ); + bool bNegRed = m_xBtnNegRed->get_sensitive() && m_xBtnNegRed->get_active(); + sal_uInt16 nPrecision = (m_xEdDecimals->get_sensitive() && m_xEdDecimals->get_visible()) + ? static_cast<sal_uInt16>(m_xEdDecimals->get_value()) + : ( (m_xEdDenominator->get_sensitive() && m_xEdDenominator->get_visible()) + ? static_cast<sal_uInt16>(m_xEdDenominator->get_value()) + : sal_uInt16(0) ); + sal_uInt16 nLeadZeroes = (m_xEdLeadZeroes->get_sensitive()) + ? static_cast<sal_uInt16>(m_xEdLeadZeroes->get_value()) + : sal_uInt16(0); + if ( pNumFmtShell->GetStandardName() == m_xEdFormat->get_text() ) + { + m_xEdDecimals->set_value(nPrecision); + } + + pNumFmtShell->MakeFormat( aFormat, + bThousand, bNegRed, + nPrecision, nLeadZeroes, + static_cast<sal_uInt16>(m_xLbFormat->get_selected_index()) ); + + m_xEdFormat->set_text( aFormat ); + MakePreviewText( aFormat ); + + if ( pNumFmtShell->FindEntry( aFormat ) ) + { + m_xIbAdd->set_sensitive(false ); + bool bUserDef=pNumFmtShell->IsUserDefined( aFormat ); + m_xIbRemove->set_sensitive(bUserDef); + m_xIbInfo->set_sensitive(bUserDef); + EditHdl_Impl(m_xEdFormat.get()); + + } + else + { + EditHdl_Impl( nullptr ); + m_xLbFormat->select(-1); + } +} + +/************************************************************************* +#* Method: LostFocusHdl_Impl +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Does changes in the number attributes. +#* Input: Options- Controls +#* Output: --- +#* +#************************************************************************/ + +IMPL_LINK_NOARG(SvxNumberFormatTabPage, LostFocusHdl_Impl, weld::Widget&, void) +{ + if (!pNumFmtShell) + return; + + const bool bAddSensitive = m_xIbAdd->get_sensitive(); + if (bAddSensitive || m_nLbFormatSelPosEdComment != SELPOS_NONE) + // Comment editing was possible. + m_xFtComment->set_label(m_xEdComment->get_text()); + + m_xEdComment->hide(); + m_xFtComment->show(); + if (m_nLbFormatSelPosEdComment != SELPOS_NONE) + { + // Save edited comment of existing format. + pNumFmtShell->SetComment4Entry( m_nLbFormatSelPosEdComment, m_xEdComment->get_text()); + m_nLbFormatSelPosEdComment = SELPOS_NONE; + } + if (!bAddSensitive) + { + // String for user defined, if present + OUString sEntry = m_xLbCategory->n_children() > 1 ? m_xLbCategory->get_text(1) : OUString(); + m_xEdComment->set_text(sEntry); + } +} + +/************************************************************************* +#* Method: NotifyChange +#*------------------------------------------------------------------------ +#* +#* Class: SvxNumberFormatTabPage +#* Function: Does changes in the number attributes. +#* Input: Options- Controls +#* Output: --- +#* +#************************************************************************/ + +OUString SvxNumberFormatTabPage::GetExpColorString( + const Color*& rpPreviewColor, const OUString& rFormatStr, short nTmpCatPos) +{ + SvxNumValCategory i; + switch (nTmpCatPos) + { + case CAT_ALL: i=SvxNumValCategory::Standard; break; + + case CAT_NUMBER: i=SvxNumValCategory::Standard; break; + + case CAT_PERCENT: i=SvxNumValCategory::Percent; break; + + case CAT_CURRENCY: i=SvxNumValCategory::Currency; break; + + case CAT_DATE: i=SvxNumValCategory::Date; break; + + case CAT_TIME: i=SvxNumValCategory::Time; break; + + case CAT_SCIENTIFIC: i=SvxNumValCategory::Scientific; break; + + case CAT_FRACTION: i=SvxNumValCategory::Fraction; break; + + case CAT_BOOLEAN: i=SvxNumValCategory::Boolean; break; + + case CAT_USERDEFINED: i=SvxNumValCategory::Standard; break; + + case CAT_TEXT: + default: i=SvxNumValCategory::NoValue;break; + } + double fVal = fSvxNumValConst[i]; + + OUString aPreviewString; + pNumFmtShell->MakePrevStringFromVal( rFormatStr, aPreviewString, rpPreviewColor, fVal ); + return aPreviewString; +} + +void SvxNumberFormatTabPage::MakePreviewText( const OUString& rFormat ) +{ + OUString aPreviewString; + const Color* pPreviewColor = nullptr; + pNumFmtShell->MakePreviewString( rFormat, aPreviewString, pPreviewColor ); + m_aWndPreview.NotifyChange( aPreviewString, pPreviewColor ); +} + +void SvxNumberFormatTabPage::ChangePreviewText( sal_uInt16 nPos ) +{ + OUString aPreviewString; + const Color* pPreviewColor = nullptr; + pNumFmtShell->FormatChanged( nPos, aPreviewString, pPreviewColor ); + m_aWndPreview.NotifyChange( aPreviewString, pPreviewColor ); +} + +void SvxNumberFormatTabPage::FillCurrencyBox() +{ + std::vector<OUString> aList; + + sal_uInt16 nSelPos=0; + pNumFmtShell->GetCurrencySymbols(aList, &nSelPos); + + m_xLbCurrency->freeze(); + m_xLbCurrency->clear(); + bLegacyAutomaticCurrency = false; + for (std::vector<OUString>::iterator i = aList.begin() + 1;i != aList.end(); ++i) + m_xLbCurrency->append_text(*i); + m_xLbCurrency->thaw(); + + set_active_currency(nSelPos); +} + +void SvxNumberFormatTabPage::SetCategory(sal_uInt16 nPos) +{ + int nCurCategory = m_xLbCategory->get_selected_index(); + sal_uInt16 nTmpCatPos; + + if (bOneAreaFlag) + { + nTmpCatPos=nFixedCategory; + } + else + { + nTmpCatPos=nPos; + } + + if(m_xLbCategory->n_children()==1 || nCurCategory!=nPos) + { + if(nTmpCatPos!=CAT_CURRENCY) + m_xLbCurrency->hide(); + else + m_xLbCurrency->show(); + } + m_xLbCategory->select(nPos); +} + +/* to support Writer text field language handling an + additional entry needs to be inserted into the ListBox + which marks a certain language as automatically detected + Additionally the "Default" language is removed +*/ +void SvxNumberFormatTabPage::AddAutomaticLanguage_Impl(LanguageType eAutoLang, bool bSelect) +{ + m_xLbLanguage->remove_id(LANGUAGE_SYSTEM); + m_xLbLanguage->append(eAutoLang, sAutomaticLangEntry); + if (bSelect) + m_xLbLanguage->set_active_id(eAutoLang); +} + +void SvxNumberFormatTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxNumberInfoItem* pNumberInfoItem = aSet.GetItem<SvxNumberInfoItem>(SID_ATTR_NUMBERFORMAT_INFO, false); + if (pNumberInfoItem && !pNumItem) + pNumItem.reset(pNumberInfoItem->Clone()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx new file mode 100644 index 000000000..0c66f69ee --- /dev/null +++ b/cui/source/tabpages/numpages.cxx @@ -0,0 +1,3355 @@ +/* -*- 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 . + */ + +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> + +#include <numpages.hxx> +#include <dialmgr.hxx> +#include <tools/mapunit.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <editeng/numitem.hxx> +#include <svl/eitem.hxx> +#include <vcl/svapp.hxx> +#include <svx/colorbox.hxx> +#include <svx/dlgutil.hxx> +#include <svx/strarray.hxx> +#include <svx/gallery.hxx> +#include <editeng/brushitem.hxx> +#include <svl/intitem.hxx> +#include <sfx2/objsh.hxx> +#include <vcl/graph.hxx> +#include <vcl/settings.hxx> +#include <cui/cuicharmap.hxx> +#include <editeng/flstitem.hxx> +#include <svx/numvset.hxx> +#include <sfx2/htmlmode.hxx> +#include <unotools/pathoptions.hxx> +#include <svtools/ctrltool.hxx> +#include <svtools/unitconv.hxx> +#include <com/sun/star/style/NumberingType.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/text/XDefaultNumberingProvider.hpp> +#include <com/sun/star/text/XNumberingFormatter.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <svx/svxids.hrc> +#include <o3tl/string_view.hxx> + +#include <algorithm> +#include <memory> +#include <vector> +#include <sfx2/opengrf.hxx> + +#include <strings.hrc> +#include <svl/stritem.hxx> +#include <svl/slstitm.hxx> +#include <sfx2/filedlghelper.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> +#include <sal/log.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/graphicfilter.hxx> +#include <svx/SvxNumOptionsTabPageHelper.hxx> +#include <tools/urlobj.hxx> +#include <o3tl/temporary.hxx> +#include <osl/diagnose.h> + +using namespace css; +using namespace css::uno; +using namespace css::beans; +using namespace css::lang; +using namespace css::text; +using namespace css::container; +using namespace css::style; + +#define SHOW_NUMBERING 0 +#define SHOW_BULLET 1 +#define SHOW_BITMAP 2 + +#define MAX_BMP_WIDTH 16 +#define MAX_BMP_HEIGHT 16 +#define SEARCHPATH_DELIMITER u';' +#define SEARCHFILENAME_DELIMITER u'/' + +static bool bLastRelative = false; + +static SvxNumSettings_Impl* lcl_CreateNumSettingsPtr(const Sequence<PropertyValue>& rLevelProps) +{ + const PropertyValue* pValues = rLevelProps.getConstArray(); + SvxNumSettings_Impl* pNew = new SvxNumSettings_Impl; + for(sal_Int32 j = 0; j < rLevelProps.getLength(); j++) + { + if ( pValues[j].Name == "NumberingType" ) + { + sal_Int16 nTmp; + if (pValues[j].Value >>= nTmp) + pNew->nNumberType = static_cast<SvxNumType>(nTmp); + } + else if ( pValues[j].Name == "Prefix" ) + pValues[j].Value >>= pNew->sPrefix; + else if ( pValues[j].Name == "Suffix" ) + pValues[j].Value >>= pNew->sSuffix; + else if ( pValues[j].Name == "ParentNumbering" ) + pValues[j].Value >>= pNew->nParentNumbering; + else if ( pValues[j].Name == "BulletChar" ) + pValues[j].Value >>= pNew->sBulletChar; + else if ( pValues[j].Name == "BulletFontName" ) + pValues[j].Value >>= pNew->sBulletFont; + } + return pNew; +} + +// the selection of bullets from the OpenSymbol +const sal_Unicode aBulletTypes[] = +{ + 0x2022, + 0x25cf, + 0xe00c, + 0xe00a, + 0x2794, + 0x27a2, + 0x2717, + 0x2714 +}; + +// Is one of the masked formats set? +static bool lcl_IsNumFmtSet(SvxNumRule const * pNum, sal_uInt16 nLevelMask) +{ + bool bRet = false; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < SVX_MAX_NUM && !bRet; i++ ) + { + if(nLevelMask & nMask) + bRet |= nullptr != pNum->Get( i ); + nMask <<= 1 ; + } + return bRet; +} + +static const vcl::Font& lcl_GetDefaultBulletFont() +{ + static vcl::Font aDefBulletFont = []() + { + vcl::Font tmp("OpenSymbol", "", Size(0, 14)); + tmp.SetCharSet( RTL_TEXTENCODING_SYMBOL ); + tmp.SetFamily( FAMILY_DONTKNOW ); + tmp.SetPitch( PITCH_DONTKNOW ); + tmp.SetWeight( WEIGHT_DONTKNOW ); + tmp.SetTransparent( true ); + return tmp; + }(); + return aDefBulletFont; +} + +SvxSingleNumPickTabPage::SvxSingleNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/picknumberingpage.ui", "PickNumberingPage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , bModified(false) + , bPreset(false) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + m_xExamplesVS->init(NumberingPageType::SINGLENUM); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxSingleNumPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxSingleNumPickTabPage, DoubleClickHdl_Impl)); + + Reference<XDefaultNumberingProvider> xDefNum = SvxNumOptionsTabPageHelper::GetNumberingProvider(); + if(!xDefNum.is()) + return; + + Sequence< Sequence< PropertyValue > > aNumberings; + const Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale(); + try + { + aNumberings = + xDefNum->getDefaultContinuousNumberingLevels( rLocale ); + + + sal_Int32 nLength = std::min<sal_Int32>(aNumberings.getLength(), NUM_VALUSET_COUNT); + + const Sequence<PropertyValue>* pValuesArr = aNumberings.getConstArray(); + for(sal_Int32 i = 0; i < nLength; i++) + { + SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(pValuesArr[i]); + aNumSettingsArr.push_back(std::unique_ptr<SvxNumSettings_Impl>(pNew)); + } + } + catch(const Exception&) + { + } + Reference<XNumberingFormatter> xFormat(xDefNum, UNO_QUERY); + m_xExamplesVS->SetNumberingSettings(aNumberings, xFormat, rLocale); +} + +SvxSingleNumPickTabPage::~SvxSingleNumPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr<SfxTabPage> SvxSingleNumPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SvxSingleNumPickTabPage>(pPage, pController, *rAttrSet); +} + +bool SvxSingleNumPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( (bPreset || bModified) && pSaveNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + + return bModified; +} + +void SvxSingleNumPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false)) + bIsPreset = pPresetItem->GetValue(); + if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nActNumLvl = pLevelItem->GetValue(); + } + if(const SvxNumBulletItem* pNumItem = rSet.GetItemIfSet(nNumItemId, false)) + { + pSaveNum.reset( new SvxNumRule(pNumItem->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + + bModified = false; +} + +DeactivateRC SvxSingleNumPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +void SvxSingleNumPickTabPage::Reset( const SfxItemSet* rSet ) +{ + const SfxPoolItem* pItem; + + // in Draw the item exists as WhichId, in Writer only as SlotId + SfxItemState eState = rSet->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem); + if(eState != SfxItemState::SET) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + eState = rSet->GetItemState(nNumItemId, false, &pItem); + + if( eState != SfxItemState::SET ) + { + pItem = & rSet->Get( nNumItemId ); + eState = SfxItemState::SET; + } + } + DBG_ASSERT(eState == SfxItemState::SET, "no item found!"); + pSaveNum.reset( new SvxNumRule(static_cast<const SvxNumBulletItem*>(pItem)->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; +} + +IMPL_LINK_NOARG(SvxSingleNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + sal_uInt16 nIdx = m_xExamplesVS->GetSelectedItemId() - 1; + DBG_ASSERT(aNumSettingsArr.size() > nIdx, "wrong index"); + if(aNumSettingsArr.size() <= nIdx) + return; + SvxNumSettings_Impl* _pSet = aNumSettingsArr[nIdx].get(); + SvxNumType eNewType = _pSet->nNumberType; + const sal_Unicode cLocalPrefix = !_pSet->sPrefix.isEmpty() ? _pSet->sPrefix[0] : 0; + const sal_Unicode cLocalSuffix = !_pSet->sSuffix.isEmpty() ? _pSet->sSuffix[0] : 0; + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType(eNewType); + aFmt.SetListFormat(cLocalPrefix == ' ' ? "" : _pSet->sPrefix, + cLocalSuffix == ' ' ? "" : _pSet->sSuffix, i); + aFmt.SetCharFormatName(""); + aFmt.SetBulletRelSize(100); + pActNum->SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +IMPL_LINK_NOARG(SvxSingleNumPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +SvxBulletPickTabPage::SvxBulletPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/pickbulletpage.ui", "PickBulletPage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , bModified(false) + , bPreset(false) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + m_xExamplesVS->init(NumberingPageType::BULLET); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxBulletPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBulletPickTabPage, DoubleClickHdl_Impl)); +} + +SvxBulletPickTabPage::~SvxBulletPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr<SfxTabPage> SvxBulletPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SvxBulletPickTabPage>(pPage, pController, *rAttrSet); +} + +bool SvxBulletPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( (bPreset || bModified) && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + return bModified; +} + +void SvxBulletPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false)) + bIsPreset = pPresetItem->GetValue(); + if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nActNumLvl = pLevelItem->GetValue(); + } + if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false)) + { + pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + bModified = false; +} + +DeactivateRC SvxBulletPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +void SvxBulletPickTabPage::Reset( const SfxItemSet* rSet ) +{ + // in Draw the item exists as WhichId, in Writer only as SlotId + const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false); + if(!pItem) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + pItem = rSet->GetItemIfSet(nNumItemId, false); + + if( !pItem ) + { + pItem = & rSet->Get( nNumItemId ); + } + + } + pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; +} + +IMPL_LINK_NOARG(SvxBulletPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + sal_Unicode cChar = aBulletTypes[m_xExamplesVS->GetSelectedItemId() - 1]; + const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType( SVX_NUM_CHAR_SPECIAL ); + // #i93908# clear suffix for bullet lists + aFmt.SetListFormat("", "", i); + aFmt.SetBulletFont(&rActBulletFont); + aFmt.SetBulletChar(cChar ); + aFmt.SetCharFormatName(sBulletCharFormatName); + aFmt.SetBulletRelSize(45); + pActNum->SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +IMPL_LINK_NOARG(SvxBulletPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +void SvxBulletPickTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false); + + if (pBulletCharFmt) + sBulletCharFormatName = pBulletCharFmt->GetValue(); +} + +SvxNumPickTabPage::SvxNumPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/pickoutlinepage.ui", "PickOutlinePage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , bModified(false) + , bPreset(false) + , m_xExamplesVS(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + + m_xExamplesVS->init(NumberingPageType::OUTLINE); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxNumPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxNumPickTabPage, DoubleClickHdl_Impl)); + + Reference<XDefaultNumberingProvider> xDefNum = SvxNumOptionsTabPageHelper::GetNumberingProvider(); + if(!xDefNum.is()) + return; + + Sequence<Reference<XIndexAccess> > aOutlineAccess; + const Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale(); + try + { + aOutlineAccess = xDefNum->getDefaultOutlineNumberings( rLocale ); + + for(sal_Int32 nItem = 0; + nItem < aOutlineAccess.getLength() && nItem < NUM_VALUSET_COUNT; + nItem++ ) + { + SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[ nItem ]; + + Reference<XIndexAccess> xLevel = aOutlineAccess.getConstArray()[nItem]; + for(sal_Int32 nLevel = 0; nLevel < xLevel->getCount() && nLevel < 5; nLevel++) + { + Any aValueAny = xLevel->getByIndex(nLevel); + Sequence<PropertyValue> aLevelProps; + aValueAny >>= aLevelProps; + SvxNumSettings_Impl* pNew = lcl_CreateNumSettingsPtr(aLevelProps); + rItemArr.push_back( std::unique_ptr<SvxNumSettings_Impl>(pNew) ); + } + } + } + catch(const Exception&) + { + } + Reference<XNumberingFormatter> xFormat(xDefNum, UNO_QUERY); + m_xExamplesVS->SetOutlineNumberingSettings(aOutlineAccess, xFormat, rLocale); +} + +SvxNumPickTabPage::~SvxNumPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr<SfxTabPage> SvxNumPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SvxNumPickTabPage>(pPage, pController, *rAttrSet); +} + +bool SvxNumPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( (bPreset || bModified) && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + return bModified; +} + +void SvxNumPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false)) + bIsPreset = pPresetItem->GetValue(); + if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nActNumLvl = pLevelItem->GetValue(); + } + if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false)) + { + pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset)) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + bModified = false; +} + +DeactivateRC SvxNumPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +void SvxNumPickTabPage::Reset( const SfxItemSet* rSet ) +{ + // in Draw the item exists as WhichId, in Writer only as SlotId + const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false); + if(!pItem) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + pItem = rSet->GetItemIfSet(nNumItemId, false); + + if( !pItem ) + { + pItem = & rSet->Get( nNumItemId ); + } + } + pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; + +} + +// all levels are changed here +IMPL_LINK_NOARG(SvxNumPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + + const FontList* pList = nullptr; + + SvxNumSettingsArr_Impl& rItemArr = aNumSettingsArrays[m_xExamplesVS->GetSelectedItemId() - 1]; + + const vcl::Font& rActBulletFont = lcl_GetDefaultBulletFont(); + SvxNumSettings_Impl* pLevelSettings = nullptr; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(rItemArr.size() > i) + pLevelSettings = rItemArr[i].get(); + if(!pLevelSettings) + break; + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType( pLevelSettings->nNumberType ); + sal_uInt16 nUpperLevelOrChar = static_cast<sal_uInt16>(pLevelSettings->nParentNumbering); + if(aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL) + { + // #i93908# clear suffix for bullet lists + aFmt.SetListFormat("", "", i); + if( !pLevelSettings->sBulletFont.isEmpty() && + pLevelSettings->sBulletFont != rActBulletFont.GetFamilyName()) + { + //search for the font + if(!pList) + { + if (SfxObjectShell* pCurDocShell = SfxObjectShell::Current()) + { + const SvxFontListItem* pFontListItem = + static_cast<const SvxFontListItem*>( pCurDocShell + ->GetItem( SID_ATTR_CHAR_FONTLIST )); + pList = pFontListItem ? pFontListItem->GetFontList() : nullptr; + } + } + if(pList && pList->IsAvailable( pLevelSettings->sBulletFont ) ) + { + FontMetric aFontMetric = pList->Get( + pLevelSettings->sBulletFont,WEIGHT_NORMAL, ITALIC_NONE); + vcl::Font aFont(aFontMetric); + aFmt.SetBulletFont(&aFont); + } + else + { + //if it cannot be found then create a new one + vcl::Font aCreateFont( pLevelSettings->sBulletFont, + OUString(), Size( 0, 14 ) ); + aCreateFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); + aCreateFont.SetFamily( FAMILY_DONTKNOW ); + aCreateFont.SetPitch( PITCH_DONTKNOW ); + aCreateFont.SetWeight( WEIGHT_DONTKNOW ); + aCreateFont.SetTransparent( true ); + aFmt.SetBulletFont( &aCreateFont ); + } + } + else + aFmt.SetBulletFont( &rActBulletFont ); + + aFmt.SetBulletChar( !pLevelSettings->sBulletChar.isEmpty() + ? pLevelSettings->sBulletChar.iterateCodePoints( + &o3tl::temporary(sal_Int32(0))) + : 0 ); + aFmt.SetCharFormatName( sBulletCharFormatName ); + aFmt.SetBulletRelSize(45); + } + else + { + aFmt.SetIncludeUpperLevels(sal::static_int_cast< sal_uInt8 >(0 != nUpperLevelOrChar ? pActNum->GetLevelCount() : 1)); + aFmt.SetCharFormatName(sNumCharFmtName); + aFmt.SetBulletRelSize(100); + // #i93908# + aFmt.SetListFormat(pLevelSettings->sPrefix, pLevelSettings->sSuffix, i); + } + pActNum->SetLevel(i, aFmt); + } +} + +IMPL_LINK_NOARG(SvxNumPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +void SvxNumPickTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false); + const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false); + + + if (pNumCharFmt &&pBulletCharFmt) + SetCharFormatNames( pNumCharFmt->GetValue(),pBulletCharFmt->GetValue()); +} + +SvxBitmapPickTabPage::SvxBitmapPickTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/pickgraphicpage.ui", "PickGraphicPage", &rSet) + , nActNumLvl(SAL_MAX_UINT16) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , bModified(false) + , bPreset(false) + , m_xErrorText(m_xBuilder->weld_label("errorft")) + , m_xBtBrowseFile(m_xBuilder->weld_button("browseBtn")) + , m_xExamplesVS(new SvxBmpNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true))) + , m_xExamplesVSWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xExamplesVS)) +{ + SetExchangeSupport(); + + m_xExamplesVS->init(); + m_xExamplesVS->SetSelectHdl(LINK(this, SvxBitmapPickTabPage, NumSelectHdl_Impl)); + m_xExamplesVS->SetDoubleClickHdl(LINK(this, SvxBitmapPickTabPage, DoubleClickHdl_Impl)); + m_xBtBrowseFile->connect_clicked(LINK(this, SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl)); + + eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); + + // determine graphic name + GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames); + + size_t i = 0; + for (auto & grfName : aGrfNames) + { + m_xExamplesVS->InsertItem( i + 1, i); + + INetURLObject aObj(grfName); + if (aObj.GetProtocol() == INetProtocol::File) + { + // tdf#114070 - only show the last name of the filename without its extension + aObj.removeExtension(); + grfName = aObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous); + } + + m_xExamplesVS->SetItemText( i + 1, grfName ); + ++i; + } + + if(aGrfNames.empty()) + { + m_xErrorText->show(); + } + else + { + m_xExamplesVS->Show(); + m_xExamplesVS->SetFormat(); + m_xExamplesVS->Invalidate(); + } +} + +SvxBitmapPickTabPage::~SvxBitmapPickTabPage() +{ + m_xExamplesVSWin.reset(); + m_xExamplesVS.reset(); +} + +std::unique_ptr<SfxTabPage> SvxBitmapPickTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SvxBitmapPickTabPage>(pPage, pController, *rAttrSet); +} + +void SvxBitmapPickTabPage::ActivatePage(const SfxItemSet& rSet) +{ + bPreset = false; + bool bIsPreset = false; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false)) + bIsPreset = pPresetItem->GetValue(); + if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nActNumLvl = pLevelItem->GetValue(); + } + if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false)) + { + pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) ); + } + if(pActNum && *pSaveNum != *pActNum) + { + *pActNum = *pSaveNum; + m_xExamplesVS->SetNoSelection(); + } + + if(!aGrfNames.empty() && + (pActNum && (!lcl_IsNumFmtSet(pActNum.get(), nActNumLvl) || bIsPreset))) + { + m_xExamplesVS->SelectItem(1); + NumSelectHdl_Impl(m_xExamplesVS.get()); + bPreset = true; + } + bPreset |= bIsPreset; + bModified = false; +} + +DeactivateRC SvxBitmapPickTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +bool SvxBitmapPickTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if ( aGrfNames.empty() ) + { + return false; + } + if( (bPreset || bModified) && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId ) ); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, bPreset)); + } + + return bModified; +} + +void SvxBitmapPickTabPage::Reset( const SfxItemSet* rSet ) +{ + // in Draw the item exists as WhichId, in Writer only as SlotId + const SvxNumBulletItem* pItem = rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false); + if(!pItem) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + pItem = rSet->GetItemIfSet(nNumItemId, false); + + if( !pItem ) + { + pItem = & rSet->Get( nNumItemId ); + } + + } + DBG_ASSERT(pItem, "no item found!"); + pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) ); + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; +} + +IMPL_LINK_NOARG(SvxBitmapPickTabPage, NumSelectHdl_Impl, ValueSet*, void) +{ + if(!pActNum) + return; + + bPreset = false; + bModified = true; + sal_uInt16 nIdx = m_xExamplesVS->GetSelectedItemId() - 1; + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aFmt(pActNum->GetLevel(i)); + aFmt.SetNumberingType(SVX_NUM_BITMAP); + aFmt.SetListFormat("", "", i); + aFmt.SetCharFormatName( "" ); + + Graphic aGraphic; + if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, nIdx, &aGraphic)) + { + Size aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic); + sal_Int16 eOrient = text::VertOrientation::LINE_CENTER; + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit)); + SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH ); + aFmt.SetGraphicBrush( &aBrush, &aSize, &eOrient ); + } + else if(aGrfNames.size() > nIdx) + aFmt.SetGraphic( aGrfNames[nIdx] ); + pActNum->SetLevel(i, aFmt); + } + nMask <<= 1; + } +} + +IMPL_LINK_NOARG(SvxBitmapPickTabPage, DoubleClickHdl_Impl, ValueSet*, void) +{ + NumSelectHdl_Impl(m_xExamplesVS.get()); + weld::Button& rOk = GetDialogController()->GetOKButton(); + rOk.clicked(); +} + +IMPL_LINK_NOARG(SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl, weld::Button&, void) +{ + sfx2::FileDialogHelper aFileDialog(0, FileDialogFlags::NONE, GetFrameWeld()); + aFileDialog.SetContext(sfx2::FileDialogHelper::BulletsAddImage); + aFileDialog.SetTitle(CuiResId(RID_CUISTR_ADD_IMAGE)); + if ( aFileDialog.Execute() != ERRCODE_NONE ) + return; + + OUString aPath = SvtPathOptions().GetGalleryPath(); + std::u16string_view aPathToken = o3tl::getToken(aPath, 1 , SEARCHPATH_DELIMITER ); + + OUString aUserImageURL = aFileDialog.GetPath(); + + OUString aFileName; + const sal_Int32 nPos {aUserImageURL.lastIndexOf(SEARCHFILENAME_DELIMITER)+1}; + if (nPos<=0) + aFileName = aUserImageURL; + else if (nPos<aUserImageURL.getLength()) + aFileName = aUserImageURL.copy(nPos); + + OUString aUserGalleryURL = OUString::Concat(aPathToken) + "/" + aFileName; + INetURLObject aURL( aUserImageURL ); + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + GraphicDescriptor aDescriptor(aURL); + if (!aDescriptor.Detect()) + return; + + uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess( + ucb::SimpleFileAccess::create( ::comphelper::getComponentContext(xFactory) ) ); + if ( !xSimpleFileAccess->exists( aUserImageURL )) + return; + + xSimpleFileAccess->copy( aUserImageURL, aUserGalleryURL ); + INetURLObject gURL( aUserGalleryURL ); + std::unique_ptr<SvStream> pIn(::utl::UcbStreamHelper::CreateStream( + gURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ )); + if ( !pIn ) + return; + + Graphic aGraphic; + GraphicConverter::Import( *pIn, aGraphic ); + + BitmapEx aBitmap = aGraphic.GetBitmapEx(); + tools::Long nPixelX = aBitmap.GetSizePixel().Width(); + tools::Long nPixelY = aBitmap.GetSizePixel().Height(); + double ratio = nPixelY/static_cast<double>(nPixelX); + if(nPixelX > 30) + { + nPixelX = 30; + nPixelY = static_cast<tools::Long>(nPixelX*ratio); + } + if(nPixelY > 30) + { + nPixelY = 30; + nPixelX = static_cast<tools::Long>(nPixelY/ratio); + } + + aBitmap.Scale( Size( nPixelX, nPixelY ), BmpScaleFlag::Fast ); + Graphic aScaledGraphic( aBitmap ); + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + + Sequence< PropertyValue > aFilterData{ + comphelper::makePropertyValue("Compression", sal_Int32(-1)), + comphelper::makePropertyValue("Quality", sal_Int32(1)) + }; + + sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( gURL.GetFileExtension() ); + rFilter.ExportGraphic( aScaledGraphic, gURL , nFilterFormat, &aFilterData ); + GalleryExplorer::InsertURL( GALLERY_THEME_BULLETS, aUserGalleryURL ); + + aGrfNames.push_back(aUserGalleryURL); + size_t i = 0; + for (auto & grfName : aGrfNames) + { + m_xExamplesVS->InsertItem( i + 1, i); + INetURLObject aObj(grfName); + if (aObj.GetProtocol() == INetProtocol::File) + { + // tdf#114070 - only show the last name of the filename without its extension + aObj.removeExtension(); + grfName = aObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous); + } + m_xExamplesVS->SetItemText( i + 1, grfName ); + ++i; + } + + if(aGrfNames.empty()) + { + m_xErrorText->show(); + } + else + { + m_xExamplesVS->Show(); + m_xExamplesVS->SetFormat(); + } +} + +// tabpage numbering options +SvxNumOptionsTabPage::SvxNumOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/numberingoptionspage.ui", "NumberingOptionsPage", &rSet) + , aInvalidateTimer("cui SvxNumOptionsTabPage aInvalidateTimer") + , m_pLevelHdlEvent(nullptr) + , bLastWidthModified(false) + , bModified(false) + , bPreset(false) + , bAutomaticCharStyles(true) + , bHTMLMode(false) + , nBullet(0xff) + , nActNumLvl(1) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , m_xGrid(m_xBuilder->weld_widget("grid2")) + , m_xLevelLB(m_xBuilder->weld_tree_view("levellb")) + , m_xFmtLB(m_xBuilder->weld_combo_box("numfmtlb")) + , m_xSeparatorFT(m_xBuilder->weld_label("separator")) + , m_xPrefixFT(m_xBuilder->weld_label("prefixft")) + , m_xPrefixED(m_xBuilder->weld_entry("prefix")) + , m_xSuffixFT(m_xBuilder->weld_label("suffixft")) + , m_xSuffixED(m_xBuilder->weld_entry("suffix")) + , m_xCharFmtFT(m_xBuilder->weld_label("charstyleft")) + , m_xCharFmtLB(m_xBuilder->weld_combo_box("charstyle")) + , m_xBulColorFT(m_xBuilder->weld_label("colorft")) + , m_xBulColLB(new ColorListBox(m_xBuilder->weld_menu_button("color"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xBulRelSizeFT(m_xBuilder->weld_label("relsizeft")) + , m_xBulRelSizeMF(m_xBuilder->weld_metric_spin_button("relsize", FieldUnit::PERCENT)) + , m_xAllLevelFT(m_xBuilder->weld_label("sublevelsft")) + , m_xAllLevelNF(m_xBuilder->weld_spin_button("sublevels")) + , m_xStartFT(m_xBuilder->weld_label("startatft")) + , m_xStartED(m_xBuilder->weld_spin_button("startat")) + , m_xBulletFT(m_xBuilder->weld_label("bulletft")) + , m_xBulletPB(m_xBuilder->weld_button("bullet")) + , m_xBitmapFT(m_xBuilder->weld_label("bitmapft")) + , m_xBitmapMB(m_xBuilder->weld_menu_button("bitmap")) + , m_xWidthFT(m_xBuilder->weld_label("widthft")) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("widthmf", FieldUnit::CM)) + , m_xHeightFT(m_xBuilder->weld_label("heightft")) + , m_xHeightMF(m_xBuilder->weld_metric_spin_button("heightmf", FieldUnit::CM)) + , m_xRatioCB(m_xBuilder->weld_check_button("keepratio")) + , m_xOrientFT(m_xBuilder->weld_label("orientft")) + , m_xOrientLB(m_xBuilder->weld_combo_box("orientlb")) + , m_xAllLevelsFrame(m_xBuilder->weld_widget("levelsframe")) + , m_xSameLevelCB(m_xBuilder->weld_check_button("allsame")) + , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN)) +{ + m_xBulColLB->SetSlotId(SID_ATTR_CHAR_COLOR); + m_xBulRelSizeMF->set_min(SVX_NUM_REL_SIZE_MIN, FieldUnit::PERCENT); + m_xBulRelSizeMF->set_increments(5, 50, FieldUnit::PERCENT); + SetExchangeSupport(); + aActBulletFont = lcl_GetDefaultBulletFont(); + + m_xBulletPB->connect_clicked(LINK(this, SvxNumOptionsTabPage, BulletHdl_Impl)); + m_xFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl)); + m_xBitmapMB->connect_selected(LINK(this, SvxNumOptionsTabPage, GraphicHdl_Impl)); + m_xBitmapMB->connect_toggled(LINK(this, SvxNumOptionsTabPage, PopupActivateHdl_Impl)); + m_xLevelLB->set_selection_mode(SelectionMode::Multiple); + m_xLevelLB->connect_changed(LINK(this, SvxNumOptionsTabPage, LevelHdl_Impl)); + m_xCharFmtLB->connect_changed(LINK(this, SvxNumOptionsTabPage, CharFmtHdl_Impl)); + m_xWidthMF->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SizeHdl_Impl)); + m_xHeightMF->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SizeHdl_Impl)); + m_xRatioCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, RatioHdl_Impl)); + m_xStartED->connect_value_changed(LINK(this, SvxNumOptionsTabPage, SpinModifyHdl_Impl)); + m_xPrefixED->connect_changed(LINK(this, SvxNumOptionsTabPage, EditModifyHdl_Impl)); + m_xSuffixED->connect_changed(LINK(this, SvxNumOptionsTabPage, EditModifyHdl_Impl)); + m_xAllLevelNF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, AllLevelHdl_Impl)); + m_xOrientLB->connect_changed(LINK(this, SvxNumOptionsTabPage, OrientHdl_Impl)); + m_xSameLevelCB->connect_toggled(LINK(this, SvxNumOptionsTabPage, SameLevelHdl_Impl)); + m_xBulRelSizeMF->connect_value_changed(LINK(this,SvxNumOptionsTabPage, BulRelSizeHdl_Impl)); + m_xBulColLB->SetSelectHdl(LINK(this, SvxNumOptionsTabPage, BulColorHdl_Impl)); + aInvalidateTimer.SetInvokeHandler(LINK(this, SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl)); + aInvalidateTimer.SetTimeout(50); + + eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); + + // Fill ListBox with predefined / translated numbering types. + sal_uInt32 nCount = SvxNumberingTypeTable::Count(); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + m_xFmtLB->append(OUString::number(SvxNumberingTypeTable::GetValue(i)), SvxNumberingTypeTable::GetString(i)); + } + + // Get advanced numbering types from the component. + // Watch out for the ugly + // 136 == 0x88 == SVX_NUM_BITMAP|0x80 == SVX_NUM_BITMAP|LINK_TOKEN + // to not remove that. + SvxNumOptionsTabPageHelper::GetI18nNumbering( *m_xFmtLB, (SVX_NUM_BITMAP | LINK_TOKEN)); + + m_xFmtLB->set_active(0); + + m_xCharFmtLB->set_size_request(m_xCharFmtLB->get_approximate_digit_width() * 10, -1); + Size aSize(m_xGrid->get_preferred_size()); + m_xGrid->set_size_request(aSize.Width(), -1); +} + +SvxNumOptionsTabPage::~SvxNumOptionsTabPage() +{ + m_xPreviewWIN.reset(); + m_xBulColLB.reset(); + pActNum.reset(); + pSaveNum.reset(); + if (m_pLevelHdlEvent) + { + Application::RemoveUserEvent(m_pLevelHdlEvent); + m_pLevelHdlEvent = nullptr; + } +} + +void SvxNumOptionsTabPage::SetMetric(FieldUnit eMetric) +{ + if(eMetric == FieldUnit::MM) + { + m_xWidthMF->set_digits(1); + m_xHeightMF->set_digits(1); + } + m_xWidthMF->set_unit(eMetric); + m_xHeightMF->set_unit(eMetric); +} + +std::unique_ptr<SfxTabPage> SvxNumOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SvxNumOptionsTabPage>(pPage, pController, *rAttrSet); +}; + +void SvxNumOptionsTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + sal_uInt16 nTmpNumLvl = 1; + if(pExampleSet) + { + if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false)) + bPreset = pPresetItem->GetValue(); + if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nTmpNumLvl = pLevelItem->GetValue(); + } + if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false)) + { + pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) ); + } + + bModified = (!pActNum->Get( 0 ) || bPreset); + if(*pActNum == *pSaveNum && nActNumLvl == nTmpNumLvl) + return; + + nActNumLvl = nTmpNumLvl; + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + m_xLevelLB->select(pActNum->GetLevelCount()); + if(nActNumLvl != SAL_MAX_UINT16) + { + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + m_xLevelLB->select(i); + nMask <<= 1 ; + } + } + *pActNum = *pSaveNum; + + InitControls(); +} + +DeactivateRC SvxNumOptionsTabPage::DeactivatePage(SfxItemSet * _pSet) +{ + if(_pSet) + FillItemSet(_pSet); + return DeactivateRC::LeavePage; +} + +bool SvxNumOptionsTabPage::FillItemSet( SfxItemSet* rSet ) +{ + rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl)); + if(bModified && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false)); + } + return bModified; +}; + +void SvxNumOptionsTabPage::Reset( const SfxItemSet* rSet ) +{ + // in Draw the item exists as WhichId, in Writer only as SlotId + const SvxNumBulletItem* pBulletItem = + rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false); + if(!pBulletItem) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + pBulletItem = rSet->GetItemIfSet(nNumItemId, false); + + if( !pBulletItem ) + { + pBulletItem = & rSet->Get( nNumItemId ); + } + } + DBG_ASSERT(pBulletItem, "no item found!"); + pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) ); + + // insert levels + if (!m_xLevelLB->n_children()) + { + for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++) + m_xLevelLB->append_text(OUString::number(i)); + if(pSaveNum->GetLevelCount() > 1) + { + OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() ); + m_xLevelLB->append_text(sEntry); + m_xLevelLB->select_text(sEntry); + } + else + m_xLevelLB->select(0); + } + else + m_xLevelLB->select(m_xLevelLB->n_children() - 1); + + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + { + m_xLevelLB->select( pSaveNum->GetLevelCount() ); + } + else + { + for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + m_xLevelLB->select( i ); + nMask <<= 1 ; + } + } + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; + m_aPreviewWIN.SetNumRule(pActNum.get()); + m_xSameLevelCB->set_active(pActNum->IsContinuousNumbering()); + + const SfxUInt16Item* pHtmlModeItem = + rSet->GetItemIfSet( SID_HTML_MODE, false ); + if (!pHtmlModeItem) + { + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + pHtmlModeItem = pShell->GetItem( SID_HTML_MODE ); + } + if ( pHtmlModeItem ) + { + sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue(); + bHTMLMode = 0 != (nHtmlMode&HTMLMODE_ON); + } + + bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE); + m_xCharFmtFT->set_visible(bCharFmt); + m_xCharFmtLB->set_visible(bCharFmt); + + bool bContinuous = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS); + + bool bAllLevel = bContinuous && !bHTMLMode; + m_xAllLevelFT->set_visible(bAllLevel); + m_xAllLevelNF->set_visible(bAllLevel); + + m_xAllLevelsFrame->set_visible(bContinuous); + + // again misusage: in Draw there is numeration only until the bitmap + // without SVX_NUM_NUMBER_NONE + //remove types that are unsupported by Draw/Impress + if(!bContinuous) + { + sal_Int32 nFmtCount = m_xFmtLB->get_count(); + for(sal_Int32 i = nFmtCount; i; i--) + { + sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32(); + if(/*SVX_NUM_NUMBER_NONE == nEntryData ||*/ + (SVX_NUM_BITMAP|LINK_TOKEN) == nEntryData) + m_xFmtLB->remove(i - 1); + } + } + //one must be enabled + if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_LINKED_BMP)) + { + auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP|LINK_TOKEN)); + if (nPos != -1) + m_xFmtLB->remove(nPos); + } + else if(!pActNum->IsFeatureSupported(SvxNumRuleFlags::ENABLE_EMBEDDED_BMP)) + { + auto nPos = m_xFmtLB->find_id(OUString::number(SVX_NUM_BITMAP)); + if (nPos != -1) + m_xFmtLB->remove(nPos); + } + + // MegaHack: because of a not-fixable 'design mistake/error' in Impress + // delete all kinds of numeric enumerations + if(pActNum->IsFeatureSupported(SvxNumRuleFlags::NO_NUMBERS)) + { + sal_Int32 nFmtCount = m_xFmtLB->get_count(); + for(sal_Int32 i = nFmtCount; i; i--) + { + sal_uInt16 nEntryData = m_xFmtLB->get_id(i - 1).toUInt32(); + if( /*nEntryData >= SVX_NUM_CHARS_UPPER_LETTER &&*/ nEntryData <= SVX_NUM_NUMBER_NONE) + m_xFmtLB->remove(i - 1); + } + } + + InitControls(); + bModified = false; +} + +void SvxNumOptionsTabPage::InitControls() +{ + bool bShowBullet = true; + bool bShowBitmap = true; + bool bSameType = true; + bool bSameStart = true; + bool bSamePrefix = true; + bool bSameSuffix = true; + bool bAllLevel = true; + bool bSameCharFmt = true; + bool bSameVOrient = true; + bool bSameSize = true; + bool bSameBulColor = true; + bool bSameBulRelSize= true; + + const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM]; + OUString sFirstCharFmt; + sal_Int16 eFirstOrient = text::VertOrientation::NONE; + Size aFirstSize(0,0); + sal_uInt16 nMask = 1; + sal_uInt16 nLvl = SAL_MAX_UINT16; + sal_uInt16 nHighestLevel = 0; + + bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR); + bool bBullRelSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE); + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + aNumFmtArr[i] = &pActNum->GetLevel(i); + bShowBullet &= aNumFmtArr[i]->GetNumberingType() == SVX_NUM_CHAR_SPECIAL; + bShowBitmap &= (aNumFmtArr[i]->GetNumberingType()&(~LINK_TOKEN)) == SVX_NUM_BITMAP; + if(SAL_MAX_UINT16 == nLvl) + { + nLvl = i; + sFirstCharFmt = aNumFmtArr[i]->GetCharFormatName(); + eFirstOrient = aNumFmtArr[i]->GetVertOrient(); + if(bShowBitmap) + aFirstSize = aNumFmtArr[i]->GetGraphicSize(); + } + if( i > nLvl) + { + bSameType &= aNumFmtArr[i]->GetNumberingType() == aNumFmtArr[nLvl]->GetNumberingType(); + bSameStart = aNumFmtArr[i]->GetStart() == aNumFmtArr[nLvl]->GetStart(); + + bSamePrefix = aNumFmtArr[i]->GetPrefix() == aNumFmtArr[nLvl]->GetPrefix(); + bSameSuffix = aNumFmtArr[i]->GetSuffix() == aNumFmtArr[nLvl]->GetSuffix(); + bAllLevel &= aNumFmtArr[i]->GetIncludeUpperLevels() == aNumFmtArr[nLvl]->GetIncludeUpperLevels(); + bSameCharFmt &= sFirstCharFmt == aNumFmtArr[i]->GetCharFormatName(); + bSameVOrient &= eFirstOrient == aNumFmtArr[i]->GetVertOrient(); + if(bShowBitmap && bSameSize) + bSameSize &= aNumFmtArr[i]->GetGraphicSize() == aFirstSize; + bSameBulColor &= aNumFmtArr[i]->GetBulletColor() == aNumFmtArr[nLvl]->GetBulletColor(); + bSameBulRelSize &= aNumFmtArr[i]->GetBulletRelSize() == aNumFmtArr[nLvl]->GetBulletRelSize(); + } + nHighestLevel = i; + } + else + aNumFmtArr[i] = nullptr; + + nMask <<= 1 ; + } + SwitchNumberType(bShowBullet ? 1 : bShowBitmap ? 2 : 0); + + sal_uInt16 nNumberingType; + if (nLvl != SAL_MAX_UINT16) + nNumberingType = aNumFmtArr[nLvl]->GetNumberingType(); + else + { + nNumberingType = SVX_NUM_NUMBER_NONE; + bAllLevel = false; + bSameBulRelSize = false; + bSameBulColor = false; + bSameStart = false; + bSamePrefix = false; + bSameSuffix = false; + } + + CheckForStartValue_Impl(nNumberingType); + + if(bShowBitmap) + { + if(!bSameVOrient || eFirstOrient == text::VertOrientation::NONE) + m_xOrientLB->set_active(-1); + else + m_xOrientLB->set_active( + sal::static_int_cast< sal_Int32 >(eFirstOrient - 1)); + // no text::VertOrientation::NONE + + if(bSameSize) + { + SetMetricValue(*m_xHeightMF, aFirstSize.Height(), eCoreUnit); + SetMetricValue(*m_xWidthMF, aFirstSize.Width(), eCoreUnit); + } + else + { + m_xHeightMF->set_text(""); + m_xWidthMF->set_text(""); + } + } + + if(bSameType) + { + sal_uInt16 nLBData = nNumberingType; + m_xFmtLB->set_active_id(OUString::number(nLBData)); + } + else + m_xFmtLB->set_active(-1); + + m_xAllLevelNF->set_sensitive(nHighestLevel > 0 && !m_xSameLevelCB->get_active()); + m_xAllLevelNF->set_max(nHighestLevel + 1); + if(bAllLevel) + { + m_xAllLevelNF->set_value(aNumFmtArr[nLvl]->GetIncludeUpperLevels()); + } + else + { + m_xAllLevelNF->set_text(""); + } + + if(bBullRelSize) + { + if(bSameBulRelSize) + m_xBulRelSizeMF->set_value(aNumFmtArr[nLvl]->GetBulletRelSize(), FieldUnit::PERCENT); + else + m_xBulRelSizeMF->set_text(""); + } + if(bBullColor) + { + if(bSameBulColor) + m_xBulColLB->SelectEntry(aNumFmtArr[nLvl]->GetBulletColor()); + else + m_xBulColLB->SetNoSelection(); + } + switch(nBullet) + { + case SHOW_NUMBERING: + if(bSameStart) + { + m_xStartED->set_value(aNumFmtArr[nLvl]->GetStart()); + } + else + m_xStartED->set_text(""); + break; + case SHOW_BULLET: + break; + case SHOW_BITMAP: + break; + } + + if(bSamePrefix) + m_xPrefixED->set_text(aNumFmtArr[nLvl]->GetPrefix()); + else + m_xPrefixED->set_text(""); + if(bSameSuffix) + m_xSuffixED->set_text(aNumFmtArr[nLvl]->GetSuffix()); + else + m_xSuffixED->set_text(""); + + if(bSameCharFmt) + { + if (!sFirstCharFmt.isEmpty()) + m_xCharFmtLB->set_active_text(sFirstCharFmt); + else + m_xCharFmtLB->set_active(0); + } + else + m_xCharFmtLB->set_active(-1); + + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); +} + +// 0 - Number; 1 - Bullet; 2 - Bitmap +void SvxNumOptionsTabPage::SwitchNumberType( sal_uInt8 nType ) +{ + if(nBullet == nType) + return; + nBullet = nType; + bool bBullet = (nType == SHOW_BULLET); + bool bBitmap = (nType == SHOW_BITMAP); + bool bEnableBitmap = (nType == SHOW_BITMAP); + bool bNumeric = !(bBitmap||bBullet); + m_xSeparatorFT->set_visible(bNumeric); + m_xPrefixFT->set_visible(bNumeric); + m_xPrefixED->set_visible(bNumeric); + m_xSuffixFT->set_visible(bNumeric); + m_xSuffixED->set_visible(bNumeric); + + bool bCharFmt = pActNum->IsFeatureSupported(SvxNumRuleFlags::CHAR_STYLE); + m_xCharFmtFT->set_visible(!bBitmap && bCharFmt); + m_xCharFmtLB->set_visible(!bBitmap && bCharFmt); + + // this is rather misusage, as there is no own flag + // for complete numeration + bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS); + bool bAllLevel = bNumeric && bAllLevelFeature && !bHTMLMode; + m_xAllLevelFT->set_visible(bAllLevel); + m_xAllLevelNF->set_visible(bAllLevel); + + m_xStartFT->set_visible(!(bBullet||bBitmap)); + m_xStartED->set_visible(!(bBullet||bBitmap)); + + m_xBulletFT->set_visible(bBullet); + m_xBulletPB->set_visible(bBullet); + bool bBullColor = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_COLOR); + m_xBulColorFT->set_visible(!bBitmap && bBullColor); + m_xBulColLB->set_visible(!bBitmap && bBullColor); + bool bBullResSize = pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE); + m_xBulRelSizeFT->set_visible(!bBitmap && bBullResSize); + m_xBulRelSizeMF->set_visible(!bBitmap && bBullResSize); + + m_xBitmapFT->set_visible(bBitmap); + m_xBitmapMB->set_visible(bBitmap); + + m_xWidthFT->set_visible(bBitmap); + m_xWidthMF->set_visible(bBitmap); + m_xHeightFT->set_visible(bBitmap); + m_xHeightMF->set_visible(bBitmap); + m_xRatioCB->set_visible(bBitmap); + + m_xOrientFT->set_visible(bBitmap && bAllLevelFeature); + m_xOrientLB->set_visible(bBitmap && bAllLevelFeature); + + m_xWidthFT->set_sensitive(bEnableBitmap); + m_xWidthMF->set_sensitive(bEnableBitmap); + m_xHeightFT->set_sensitive(bEnableBitmap); + m_xHeightMF->set_sensitive(bEnableBitmap); + m_xRatioCB->set_sensitive(bEnableBitmap); + m_xOrientFT->set_sensitive(bEnableBitmap); + m_xOrientLB->set_sensitive(bEnableBitmap); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl_Impl, weld::TreeView&, void) +{ + if (m_pLevelHdlEvent) + return; + // tdf#127112 (borrowing tdf#127120 solution) multiselection may be implemented by deselect follow by select so + // fire off the handler to happen on next event loop and only process the + // final state + m_pLevelHdlEvent = Application::PostUserEvent(LINK(this, SvxNumOptionsTabPage, LevelHdl)); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, LevelHdl, void*, void) +{ + m_pLevelHdlEvent = nullptr; + + sal_uInt16 nSaveNumLvl = nActNumLvl; + nActNumLvl = 0; + std::vector<int> aSelectedRows = m_xLevelLB->get_selected_rows(); + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() && + (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff)) + { + nActNumLvl = 0xFFFF; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + m_xLevelLB->unselect(i); + } + else if (!aSelectedRows.empty()) + { + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end()) + nActNumLvl |= nMask; + nMask <<= 1; + } + m_xLevelLB->unselect(pActNum->GetLevelCount()); + } + else + { + nActNumLvl = nSaveNumLvl; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if(nActNumLvl & nMask) + { + m_xLevelLB->select(i); + break; + } + nMask <<=1; + } + } + InitControls(); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, PreviewInvalidateHdl_Impl, Timer *, void) +{ + m_aPreviewWIN.Invalidate(); +} + +IMPL_LINK(SvxNumOptionsTabPage, AllLevelHdl_Impl, weld::SpinButton&, rBox, void) +{ + sal_uInt16 nMask = 1; + for(sal_uInt16 e = 0; e < pActNum->GetLevelCount(); e++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(e)); + aNumFmt.SetIncludeUpperLevels(static_cast<sal_uInt8>(std::min(rBox.get_value(), sal_Int64(e + 1))) ); + // Set the same prefix/suffix to generate list format with changed IncludedUpperLevels + aNumFmt.SetListFormat(aNumFmt.GetPrefix(), aNumFmt.GetSuffix(), e); + pActNum->SetLevel(e, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK(SvxNumOptionsTabPage, NumberTypeSelectHdl_Impl, weld::ComboBox&, rBox, void) +{ + OUString sSelectStyle; + bool bShowOrient = false; + bool bBmp = false; + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + // PAGEDESC does not exist + SvxNumType nNumType = static_cast<SvxNumType>(rBox.get_active_id().toUInt32()); + aNumFmt.SetNumberingType(nNumType); + sal_uInt16 nNumberingType = aNumFmt.GetNumberingType(); + if(SVX_NUM_BITMAP == (nNumberingType&(~LINK_TOKEN))) + { + bBmp |= nullptr != aNumFmt.GetBrush(); + aNumFmt.SetIncludeUpperLevels( 1 ); + aNumFmt.SetListFormat("", "", i); + if(!bBmp) + aNumFmt.SetGraphic(""); + pActNum->SetLevel(i, aNumFmt); + SwitchNumberType(SHOW_BITMAP); + bShowOrient = true; + } + else if( SVX_NUM_CHAR_SPECIAL == nNumberingType ) + { + aNumFmt.SetIncludeUpperLevels( 1 ); + aNumFmt.SetListFormat("", "", i); + if( !aNumFmt.GetBulletFont() ) + aNumFmt.SetBulletFont(&aActBulletFont); + if( !aNumFmt.GetBulletChar() ) + aNumFmt.SetBulletChar( SVX_DEF_BULLET ); + pActNum->SetLevel(i, aNumFmt); + SwitchNumberType(SHOW_BULLET); + // allocation of the drawing pattern is automatic + if(bAutomaticCharStyles) + { + sSelectStyle = m_sBulletCharFormatName; + } + } + else + { + aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i); + + SwitchNumberType(SHOW_NUMBERING); + pActNum->SetLevel(i, aNumFmt); + CheckForStartValue_Impl(nNumberingType); + + // allocation of the drawing pattern is automatic + if(bAutomaticCharStyles) + { + sSelectStyle = m_sNumCharFmtName; + } + } + } + nMask <<= 1; + } + bool bAllLevelFeature = pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS); + if(bShowOrient && bAllLevelFeature) + { + m_xOrientFT->show(); + m_xOrientLB->show(); + } + else + { + m_xOrientFT->hide(); + m_xOrientLB->hide(); + } + SetModified(); + if(!sSelectStyle.isEmpty()) + { + m_xCharFmtLB->set_active_text(sSelectStyle); + CharFmtHdl_Impl(*m_xCharFmtLB); + bAutomaticCharStyles = true; + } +} + +void SvxNumOptionsTabPage::CheckForStartValue_Impl(sal_uInt16 nNumberingType) +{ + bool bIsNull = m_xStartED->get_value() == 0; + bool bNoZeroAllowed = nNumberingType < SVX_NUM_ARABIC || + SVX_NUM_CHARS_UPPER_LETTER_N == nNumberingType || + SVX_NUM_CHARS_LOWER_LETTER_N == nNumberingType; + m_xStartED->set_min(bNoZeroAllowed ? 1 : 0); + if (bIsNull && bNoZeroAllowed) + EditModifyHdl_Impl(*m_xStartED); +} + +IMPL_LINK(SvxNumOptionsTabPage, OrientHdl_Impl, weld::ComboBox&, rBox, void) +{ + sal_Int32 nPos = rBox.get_active(); + nPos ++; // no VERT_NONE + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN))) + { + const SvxBrushItem* pBrushItem = aNumFmt.GetBrush(); + const Size& rSize = aNumFmt.GetGraphicSize(); + sal_Int16 eOrient = static_cast<sal_Int16>(nPos); + aNumFmt.SetGraphicBrush( pBrushItem, &rSize, &eOrient ); + pActNum->SetLevel(i, aNumFmt); + } + } + nMask <<= 1; + } + SetModified(false); +} + +IMPL_LINK(SvxNumOptionsTabPage, SameLevelHdl_Impl, weld::Toggleable&, rBox, void) +{ + bool bSet = rBox.get_active(); + pActNum->SetContinuousNumbering(bSet); + bool bRepaint = false; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(aNumFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE) + { + bRepaint = true; + break; + } + } + SetModified(bRepaint); + InitControls(); +} + +IMPL_LINK(SvxNumOptionsTabPage, BulColorHdl_Impl, ColorListBox&, rColorBox, void) +{ + Color nSetColor = rColorBox.GetSelectEntryColor(); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetBulletColor(nSetColor); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK(SvxNumOptionsTabPage, BulRelSizeHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + sal_uInt16 nRelSize = rField.get_value(FieldUnit::PERCENT); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetBulletRelSize(nRelSize); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK(SvxNumOptionsTabPage, GraphicHdl_Impl, const OString&, rIdent, void) +{ + OUString aGrfName; + Size aSize; + bool bSucc(false); + SvxOpenGraphicDialog aGrfDlg(CuiResId(RID_CUISTR_EDIT_GRAPHIC), GetFrameWeld()); + + OString sNumber; + if (rIdent.startsWith("gallery", &sNumber)) + { + auto idx = sNumber.toUInt32(); + if (idx < aGrfNames.size()) + { + aGrfName = aGrfNames[idx]; + Graphic aGraphic; + if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, idx, &aGraphic)) + { + aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic); + bSucc = true; + } + } + } + else if (rIdent == "fromfile") + { + aGrfDlg.EnableLink( false ); + aGrfDlg.AsLink( false ); + if ( !aGrfDlg.Execute() ) + { + // memorize selected filter + aGrfName = aGrfDlg.GetPath(); + + Graphic aGraphic; + if( !aGrfDlg.GetGraphic(aGraphic) ) + { + aSize = SvxNumberFormat::GetGraphicSizeMM100(&aGraphic); + bSucc = true; + } + } + } + if(!bSucc) + return; + + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(eCoreUnit)); + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetCharFormatName(m_sNumCharFmtName); + aNumFmt.SetGraphic(aGrfName); + + // set size for a later comparison + const SvxBrushItem* pBrushItem = aNumFmt.GetBrush(); + // initiate asynchronous loading + sal_Int16 eOrient = aNumFmt.GetVertOrient(); + aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient ); + aInitSize[i] = aNumFmt.GetGraphicSize(); + + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + m_xRatioCB->set_sensitive(true); + m_xWidthFT->set_sensitive(true); + m_xHeightFT->set_sensitive(true); + m_xWidthMF->set_sensitive(true); + m_xHeightMF->set_sensitive(true); + SetMetricValue(*m_xWidthMF, aSize.Width(), eCoreUnit); + SetMetricValue(*m_xHeightMF, aSize.Height(), eCoreUnit); + m_xOrientFT->set_sensitive(true); + m_xOrientLB->set_sensitive(true); + SetModified(); + //needed due to asynchronous loading of graphics in the SvxBrushItem + aInvalidateTimer.Start(); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, PopupActivateHdl_Impl, weld::Toggleable&, void) +{ + if (m_xGalleryMenu) + return; + + m_xGalleryMenu = m_xBuilder->weld_menu("gallerysubmenu"); + weld::WaitObject aWait(GetFrameWeld()); + + if (!GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, aGrfNames)) + return; + + GalleryExplorer::BeginLocking(GALLERY_THEME_BULLETS); + + Graphic aGraphic; + OUString sGrfName; + ScopedVclPtrInstance< VirtualDevice > pVD; + size_t i = 0; + for (const auto & grfName : aGrfNames) + { + sGrfName = grfName; + OUString sItemId = "gallery" + OUString::number(i); + INetURLObject aObj(sGrfName); + if (aObj.GetProtocol() == INetProtocol::File) + { + // tdf#141334 - only show the last name of the filename without its extension + aObj.removeExtension(); + sGrfName = aObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous); + } + if(GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, i, &aGraphic)) + { + BitmapEx aBitmap(aGraphic.GetBitmapEx()); + Size aSize(aBitmap.GetSizePixel()); + if(aSize.Width() > MAX_BMP_WIDTH || + aSize.Height() > MAX_BMP_HEIGHT) + { + bool bWidth = aSize.Width() > aSize.Height(); + double nScale = bWidth ? + double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width()): + double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height()); + aBitmap.Scale(nScale, nScale); + } + pVD->SetOutputSizePixel(aBitmap.GetSizePixel(), false); + pVD->DrawBitmapEx(Point(), aBitmap); + m_xGalleryMenu->append(sItemId, sGrfName, *pVD); + } + else + { + m_xGalleryMenu->append(sItemId, sGrfName); + } + ++i; + } + GalleryExplorer::EndLocking(GALLERY_THEME_BULLETS); +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, BulletHdl_Impl, weld::Button&, void) +{ + SvxCharacterMap aMap(GetFrameWeld(), nullptr, nullptr); + + sal_uInt16 nMask = 1; + std::optional<vcl::Font> pFmtFont; + bool bSameBullet = true; + sal_UCS4 cBullet = 0; + bool bFirst = true; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + const SvxNumberFormat& rCurFmt = pActNum->GetLevel(i); + if(bFirst) + { + cBullet = rCurFmt.GetBulletChar(); + } + else if(rCurFmt.GetBulletChar() != cBullet ) + { + bSameBullet = false; + break; + } + if(!pFmtFont) + pFmtFont = rCurFmt.GetBulletFont(); + bFirst = false; + } + nMask <<= 1; + + } + + if (pFmtFont) + aMap.SetCharFont(*pFmtFont); + else + aMap.SetCharFont(aActBulletFont); + if (bSameBullet) + aMap.SetChar(cBullet); + if (aMap.run() != RET_OK) + return; + + // change Font Numrules + aActBulletFont = aMap.GetCharFont(); + + sal_uInt16 _nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & _nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + aNumFmt.SetBulletFont(&aActBulletFont); + aNumFmt.SetBulletChar(aMap.GetChar()); + pActNum->SetLevel(i, aNumFmt); + } + _nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK( SvxNumOptionsTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + bool bWidth = &rField == m_xWidthMF.get(); + bLastWidthModified = bWidth; + bool bRatio = m_xRatioCB->get_active(); + tools::Long nWidthVal = static_cast<tools::Long>(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::MM_100TH))); + tools::Long nHeightVal = static_cast<tools::Long>(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::MM_100TH))); + nWidthVal = OutputDevice::LogicToLogic( nWidthVal , + MapUnit::Map100thMM, eCoreUnit ); + nHeightVal = OutputDevice::LogicToLogic( nHeightVal, + MapUnit::Map100thMM, eCoreUnit); + double fSizeRatio; + + bool bRepaint = false; + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if(SVX_NUM_BITMAP == (aNumFmt.GetNumberingType()&(~LINK_TOKEN))) + { + Size aSize(aNumFmt.GetGraphicSize() ); + Size aSaveSize(aSize); + + if (aInitSize[i].Height()) + fSizeRatio = static_cast<double>(aInitSize[i].Width()) / static_cast<double>(aInitSize[i].Height()); + else + fSizeRatio = double(1); + + if(bWidth) + { + tools::Long nDelta = nWidthVal - aInitSize[i].Width(); + aSize.setWidth( nWidthVal ); + if (bRatio) + { + aSize.setHeight( aInitSize[i].Height() + static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio) ); + m_xHeightMF->set_value(m_xHeightMF->normalize( + OutputDevice::LogicToLogic( aSize.Height(), eCoreUnit, MapUnit::Map100thMM )), + FieldUnit::MM_100TH); + } + } + else + { + tools::Long nDelta = nHeightVal - aInitSize[i].Height(); + aSize.setHeight( nHeightVal ); + if (bRatio) + { + aSize.setWidth( aInitSize[i].Width() + static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio) ); + m_xWidthMF->set_value(m_xWidthMF->normalize( + OutputDevice::LogicToLogic( aSize.Width(), eCoreUnit, MapUnit::Map100thMM )), + FieldUnit::MM_100TH); + } + } + const SvxBrushItem* pBrushItem = aNumFmt.GetBrush(); + sal_Int16 eOrient = aNumFmt.GetVertOrient(); + if(aSize != aSaveSize) + bRepaint = true; + aNumFmt.SetGraphicBrush( pBrushItem, &aSize, &eOrient ); + pActNum->SetLevel(i, aNumFmt); + } + } + nMask <<= 1; + } + SetModified(bRepaint); +} + +IMPL_LINK(SvxNumOptionsTabPage, RatioHdl_Impl, weld::Toggleable&, rBox, void) +{ + if (rBox.get_active()) + { + if (bLastWidthModified) + SizeHdl_Impl(*m_xWidthMF); + else + SizeHdl_Impl(*m_xHeightMF); + } +} + +IMPL_LINK_NOARG(SvxNumOptionsTabPage, CharFmtHdl_Impl, weld::ComboBox&, void) +{ + bAutomaticCharStyles = false; + sal_Int32 nEntryPos = m_xCharFmtLB->get_active(); + OUString sEntry = m_xCharFmtLB->get_active_text(); + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if( 0 == nEntryPos ) + aNumFmt.SetCharFormatName(""); + else + { + if(SVX_NUM_BITMAP != (aNumFmt.GetNumberingType()&(~LINK_TOKEN))) + aNumFmt.SetCharFormatName(sEntry); + } + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(false); +}; + +IMPL_LINK(SvxNumOptionsTabPage, EditModifyHdl_Impl, weld::Entry&, rEdit, void) +{ + EditModifyHdl_Impl(&rEdit); +} + +IMPL_LINK(SvxNumOptionsTabPage, SpinModifyHdl_Impl, weld::SpinButton&, rSpinButton, void) +{ + EditModifyHdl_Impl(&rSpinButton); +} + +void SvxNumOptionsTabPage::EditModifyHdl_Impl(const weld::Entry* pEdit) +{ + bool bPrefixSuffix = (pEdit == m_xPrefixED.get())|| (pEdit == m_xSuffixED.get()); + bool bStart = pEdit == m_xStartED.get(); + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + if (bPrefixSuffix) + aNumFmt.SetListFormat(m_xPrefixED->get_text(), m_xSuffixED->get_text(), i); + else if(bStart) + aNumFmt.SetStart(m_xStartED->get_value()); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +static tools::Long lcl_DrawGraphic(VirtualDevice& rVDev, const SvxNumberFormat &rFmt, tools::Long nXStart, + tools::Long nYMiddle, tools::Long nDivision) +{ + const SvxBrushItem* pBrushItem = rFmt.GetBrush(); + tools::Long nRet = 0; + if(pBrushItem) + { + const Graphic* pGrf = pBrushItem->GetGraphic(); + if(pGrf) + { + Size aGSize( rFmt.GetGraphicSize() ); + aGSize.setWidth( aGSize.Width() / nDivision ); + nRet = aGSize.Width(); + aGSize.setHeight( aGSize.Height() / nDivision ); + pGrf->Draw(rVDev, Point(nXStart,nYMiddle - ( aGSize.Height() / 2) ), + rVDev.PixelToLogic( aGSize ) ); + } + } + return nRet; + +} + +static tools::Long lcl_DrawBullet(VirtualDevice* pVDev, + const SvxNumberFormat& rFmt, tools::Long nXStart, + tools::Long nYStart, const Size& rSize) +{ + vcl::Font aTmpFont(pVDev->GetFont()); + + // via Uno it's possible that no font has been set! + vcl::Font aFont(rFmt.GetBulletFont() ? *rFmt.GetBulletFont() : aTmpFont); + Size aTmpSize(rSize); + aTmpSize.setWidth( aTmpSize.Width() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setWidth( aTmpSize.Width() / 100 ) ; + aTmpSize.setHeight( aTmpSize.Height() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setHeight( aTmpSize.Height() / 100 ) ; + // in case of a height of zero it is drawn in original height + if(!aTmpSize.Height()) + aTmpSize.setHeight( 1 ); + aFont.SetFontSize(aTmpSize); + aFont.SetTransparent(true); + Color aBulletColor = rFmt.GetBulletColor(); + if(aBulletColor == COL_AUTO) + aBulletColor = pVDev->GetFillColor().IsDark() ? COL_WHITE : COL_BLACK; + else if(aBulletColor == pVDev->GetFillColor()) + aBulletColor.Invert(); + aFont.SetColor(aBulletColor); + pVDev->SetFont( aFont ); + sal_UCS4 cChar = rFmt.GetBulletChar(); + OUString aText(&cChar, 1); + tools::Long nY = nYStart; + nY -= ((aTmpSize.Height() - rSize.Height())/ 2); + pVDev->DrawText( Point(nXStart, nY), aText ); + tools::Long nRet = pVDev->GetTextWidth(aText); + + pVDev->SetFont(aTmpFont); + return nRet; +} + +SvxNumberingPreview::SvxNumberingPreview() + : pActNum(nullptr) + , bPosition(false) + , nActLevel(SAL_MAX_UINT16) +{ +} + +// paint preview of numeration +void SvxNumberingPreview::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& /*rRect*/) +{ + Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel())); + + const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); + const Color aBackColor = rStyleSettings.GetFieldColor(); + const Color aTextColor = rStyleSettings.GetFieldTextColor(); + + ScopedVclPtrInstance<VirtualDevice> pVDev(rRenderContext); + pVDev->EnableRTL(rRenderContext.IsRTLEnabled()); + pVDev->SetMapMode(rRenderContext.GetMapMode()); + pVDev->SetOutputSize(aSize); + + Color aLineColor(COL_LIGHTGRAY); + if (aLineColor == aBackColor) + aLineColor.Invert(); + pVDev->SetLineColor(aLineColor); + pVDev->SetFillColor(aBackColor); + + if (pActNum) + { + tools::Long nWidthRelation = 30; // chapter dialog + + // height per level + tools::Long nXStep = aSize.Width() / (pActNum->GetLevelCount() > 1 ? 3 * pActNum->GetLevelCount() : 3); + if (pActNum->GetLevelCount() < 10) + nXStep /= 2; + tools::Long nYStart = 4; + // the whole height mustn't be used for a single level + tools::Long nYStep = (aSize.Height() - 6)/ (pActNum->GetLevelCount() > 1 ? pActNum->GetLevelCount() : 5); + + aStdFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, MsLangId::getConfiguredSystemLanguage(), GetDefaultFontFlags::OnlyOne); + aStdFont.SetColor(aTextColor); + aStdFont.SetFillColor(aBackColor); + + tools::Long nFontHeight = nYStep * 6 / 10; + if (bPosition) + nFontHeight = nYStep * 15 / 10; + aStdFont.SetFontSize(Size( 0, nFontHeight )); + + SvxNodeNum aNum; + sal_uInt16 nPreNum = pActNum->GetLevel(0).GetStart(); + + if (bPosition) + { + tools::Long nLineHeight = nFontHeight * 8 / 7; + sal_uInt8 nStart = 0; + while (!(nActLevel & (1<<nStart))) + { + nStart++; + } + if (nStart) + nStart--; + sal_uInt8 nEnd = std::min(sal_uInt8(nStart + 3), sal_uInt8(pActNum->GetLevelCount())); + for (sal_uInt8 nLevel = nStart; nLevel < nEnd; ++nLevel) + { + const SvxNumberFormat &rFmt = pActNum->GetLevel(nLevel); + aNum.GetLevelVal()[nLevel] = rFmt.GetStart(); + + tools::Long nXStart( 0 ); + short nTextOffset( 0 ); + tools::Long nNumberXPos( 0 ); + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nXStart = rFmt.GetAbsLSpace() / nWidthRelation; + nTextOffset = rFmt.GetCharTextDistance() / nWidthRelation; + nNumberXPos = nXStart; + tools::Long nFirstLineOffset = (-rFmt.GetFirstLineOffset()) / nWidthRelation; + + if (nFirstLineOffset <= nNumberXPos) + nNumberXPos = nNumberXPos - nFirstLineOffset; + else + nNumberXPos = 0; + // in draw this is valid + if (nTextOffset < 0) + nNumberXPos = nNumberXPos + nTextOffset; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + const tools::Long nTmpNumberXPos((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent() ) / nWidthRelation); + if (nTmpNumberXPos < 0) + { + nNumberXPos = 0; + } + else + { + nNumberXPos = nTmpNumberXPos; + } + } + + tools::Long nBulletWidth = 0; + if (SVX_NUM_BITMAP == (rFmt.GetNumberingType() &(~LINK_TOKEN))) + { + tools::Long nYMiddle = nYStart + ( nFontHeight / 2 ); + nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawGraphic(*pVDev, rFmt, nNumberXPos, nYMiddle, nWidthRelation) : 0; + } + else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) + { + nBulletWidth = rFmt.IsShowSymbol() ? lcl_DrawBullet(pVDev.get(), rFmt, nNumberXPos, nYStart, aStdFont.GetFontSize()) : 0; + } + else + { + pVDev->SetFont(aStdFont); + aNum.SetLevel(nLevel); + if (pActNum->IsContinuousNumbering()) + aNum.GetLevelVal()[nLevel] = nPreNum; + OUString aText(pActNum->MakeNumString( aNum )); + vcl::Font aSaveFont = pVDev->GetFont(); + vcl::Font aColorFont(aSaveFont); + Color aTmpBulletColor = rFmt.GetBulletColor(); + if (aTmpBulletColor == COL_AUTO) + aTmpBulletColor = aBackColor.IsDark() ? COL_WHITE : COL_BLACK; + else if (aTmpBulletColor == aBackColor) + aTmpBulletColor.Invert(); + aColorFont.SetColor(aTmpBulletColor); + pVDev->SetFont(aColorFont); + pVDev->DrawText(Point(nNumberXPos, nYStart), aText); + pVDev->SetFont(aSaveFont); + nBulletWidth = pVDev->GetTextWidth(aText); + nPreNum++; + } + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT && + rFmt.GetLabelFollowedBy() == SvxNumberFormat::SPACE ) + { + pVDev->SetFont(aStdFont); + OUString aText(' '); + pVDev->DrawText( Point(nNumberXPos, nYStart), aText ); + nBulletWidth = nBulletWidth + pVDev->GetTextWidth(aText); + } + + tools::Long nTextXPos( 0 ); + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nTextXPos = nXStart; + if (nTextOffset < 0) + nTextXPos = nTextXPos + nTextOffset; + if (nNumberXPos + nBulletWidth + nTextOffset > nTextXPos) + nTextXPos = nNumberXPos + nBulletWidth + nTextOffset; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + switch (rFmt.GetLabelFollowedBy()) + { + case SvxNumberFormat::LISTTAB: + { + nTextXPos = rFmt.GetListtabPos() / nWidthRelation; + if (nTextXPos < nNumberXPos + nBulletWidth) + { + nTextXPos = nNumberXPos + nBulletWidth; + } + } + break; + case SvxNumberFormat::SPACE: + case SvxNumberFormat::NOTHING: + case SvxNumberFormat::NEWLINE: + { + nTextXPos = nNumberXPos + nBulletWidth; + } + break; + } + + nXStart = rFmt.GetIndentAt() / nWidthRelation; + } + + ::tools::Rectangle aRect1(Point(nTextXPos, nYStart + nFontHeight / 2), Size(aSize.Width() / 2, 2)); + pVDev->SetFillColor(aBackColor); + pVDev->DrawRect(aRect1); + + ::tools::Rectangle aRect2(Point(nXStart, nYStart + nLineHeight + nFontHeight / 2 ), Size(aSize.Width() / 2, 2)); + pVDev->DrawRect(aRect2); + nYStart += 2 * nLineHeight; + } + } + else + { + //#i5153# painting gray or black rectangles as 'normal' numbering text + tools::Long nWidth = pVDev->GetTextWidth("Preview"); + tools::Long nTextHeight = pVDev->GetTextHeight(); + tools::Long nRectHeight = nTextHeight * 2 / 3; + tools::Long nTopOffset = nTextHeight - nRectHeight; + Color aBlackColor(COL_BLACK); + if (aBlackColor == aBackColor) + aBlackColor.Invert(); + + for (sal_uInt16 nLevel = 0; nLevel < pActNum->GetLevelCount(); ++nLevel, nYStart = nYStart + nYStep) + { + const SvxNumberFormat &rFmt = pActNum->GetLevel(nLevel); + aNum.GetLevelVal()[ nLevel ] = rFmt.GetStart(); + tools::Long nXStart( 0 ); + pVDev->SetFillColor( aBackColor ); + + if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION) + { + nXStart = rFmt.GetAbsLSpace() / nWidthRelation; + } + else if (rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT) + { + const tools::Long nTmpXStart((rFmt.GetIndentAt() + rFmt.GetFirstLineIndent() ) / nWidthRelation); + if (nTmpXStart < 0) + { + nXStart = 0; + } + else + { + nXStart = nTmpXStart; + } + } + nXStart /= 2; + nXStart += 2; + tools::Long nTextOffset = 2 * nXStep; + if (SVX_NUM_BITMAP == (rFmt.GetNumberingType()&(~LINK_TOKEN))) + { + if (rFmt.IsShowSymbol()) + { + tools::Long nYMiddle = nYStart + ( nFontHeight / 2 ); + nTextOffset = lcl_DrawGraphic(*pVDev, rFmt, nXStart, nYMiddle, nWidthRelation); + nTextOffset = nTextOffset + nXStep; + } + } + else if (SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) + { + if (rFmt.IsShowSymbol()) + { + nTextOffset = lcl_DrawBullet(pVDev.get(), rFmt, nXStart, nYStart, aStdFont.GetFontSize()); + nTextOffset = nTextOffset + nXStep; + } + } + else + { + vcl::Font aFont(aStdFont); + Size aTmpSize(aStdFont.GetFontSize()); + if(pActNum->IsFeatureSupported(SvxNumRuleFlags::BULLET_REL_SIZE)) + { + aTmpSize.setWidth( aTmpSize.Width() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setWidth( aTmpSize.Width() / 100 ) ; + aTmpSize.setHeight( aTmpSize.Height() * ( rFmt.GetBulletRelSize()) ); + aTmpSize.setHeight( aTmpSize.Height() / 100 ) ; + } + if(!aTmpSize.Height()) + aTmpSize.setHeight( 1 ); + aFont.SetFontSize(aTmpSize); + Color aTmpBulletColor = rFmt.GetBulletColor(); + if (aTmpBulletColor == COL_AUTO) + aTmpBulletColor = aBackColor.IsDark() ? COL_WHITE : COL_BLACK; + else if (aTmpBulletColor == aBackColor) + aTmpBulletColor.Invert(); + aFont.SetColor(aTmpBulletColor); + pVDev->SetFont(aFont); + aNum.SetLevel( nLevel ); + if (pActNum->IsContinuousNumbering()) + aNum.GetLevelVal()[nLevel] = nPreNum; + OUString aText(pActNum->MakeNumString(aNum)); + tools::Long nY = nYStart; + nY -= (pVDev->GetTextHeight() - nTextHeight - pVDev->GetFontMetric().GetDescent()); + pVDev->DrawText(Point(nXStart, nY), aText); + nTextOffset = pVDev->GetTextWidth(aText); + nTextOffset = nTextOffset + nXStep; + nPreNum++; + pVDev->SetFont(aStdFont); + } + //#i5153# the selected rectangle(s) should be black + if (0 != (nActLevel & (1<<nLevel))) + { + pVDev->SetFillColor( aBlackColor ); + pVDev->SetLineColor( aBlackColor ); + } + else + { + //#i5153# unselected levels are gray + pVDev->SetFillColor( aLineColor ); + pVDev->SetLineColor( aLineColor ); + } + ::tools::Rectangle aRect1(Point(nXStart + nTextOffset, nYStart + nTopOffset), Size(nWidth, nRectHeight)); + pVDev->DrawRect(aRect1); + } + } + } + rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *pVDev); +} + + +//See uiconfig/swriter/ui/outlinepositionpage.ui for effectively a duplicate +//dialog to this one, except with a different preview window impl. +//TODO, determine if SwNumPositionTabPage and SvxNumPositionTabPage can be +//merged +SvxNumPositionTabPage::SvxNumPositionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/numberingpositionpage.ui", "NumberingPositionPage", &rSet) + , m_pLevelHdlEvent(nullptr) + , nActNumLvl(1) + , nNumItemId(SID_ATTR_NUMBERING_RULE) + , bModified(false) + , bPreset(false) + , bInInintControl(false) + , bLabelAlignmentPosAndSpaceModeActive(false) + , m_xLevelLB(m_xBuilder->weld_tree_view("levellb")) + , m_xDistBorderFT(m_xBuilder->weld_label("indent")) + , m_xDistBorderMF(m_xBuilder->weld_metric_spin_button("indentmf", FieldUnit::CM)) + , m_xRelativeCB(m_xBuilder->weld_check_button("relative")) + , m_xIndentFT(m_xBuilder->weld_label("numberingwidth")) + , m_xIndentMF(m_xBuilder->weld_metric_spin_button("numberingwidthmf", FieldUnit::CM)) + , m_xDistNumFT(m_xBuilder->weld_label("numdist")) + , m_xDistNumMF(m_xBuilder->weld_metric_spin_button("numdistmf", FieldUnit::CM)) + , m_xAlignFT(m_xBuilder->weld_label("numalign")) + , m_xAlignLB(m_xBuilder->weld_combo_box("numalignlb")) + , m_xLabelFollowedByFT(m_xBuilder->weld_label("numfollowedby")) + , m_xLabelFollowedByLB(m_xBuilder->weld_combo_box("numfollowedbylb")) + , m_xListtabFT(m_xBuilder->weld_label("at")) + , m_xListtabMF(m_xBuilder->weld_metric_spin_button("atmf", FieldUnit::CM)) + , m_xAlign2FT(m_xBuilder->weld_label("num2align")) + , m_xAlign2LB(m_xBuilder->weld_combo_box("num2alignlb")) + , m_xAlignedAtFT(m_xBuilder->weld_label("alignedat")) + , m_xAlignedAtMF(m_xBuilder->weld_metric_spin_button("alignedatmf", FieldUnit::CM)) + , m_xIndentAtFT(m_xBuilder->weld_label("indentat")) + , m_xIndentAtMF(m_xBuilder->weld_metric_spin_button("indentatmf", FieldUnit::CM)) + , m_xStandardPB(m_xBuilder->weld_button("standard")) + , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN)) +{ + SetExchangeSupport(); + + // set metric + FieldUnit eFUnit = GetModuleFieldUnit(rSet); + + SetFieldUnit( *m_xDistBorderMF, eFUnit ); + SetFieldUnit( *m_xIndentMF, eFUnit ); + SetFieldUnit( *m_xDistNumMF, eFUnit ); + + m_xAlignedAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE); + m_xListtabMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE); + m_xIndentAtMF->set_range(0, SAL_MAX_INT32, FieldUnit::NONE); + + m_xRelativeCB->set_active(true); + m_xAlignLB->connect_changed(LINK(this, SvxNumPositionTabPage, EditModifyHdl_Impl)); + m_xAlign2LB->connect_changed(LINK(this, SvxNumPositionTabPage, EditModifyHdl_Impl)); + for ( sal_Int32 i = 0; i < m_xAlignLB->get_count(); ++i ) + { + m_xAlign2LB->append_text(m_xAlignLB->get_text(i)); + } + + Link<weld::MetricSpinButton&,void> aLk3 = LINK(this, SvxNumPositionTabPage, DistanceHdl_Impl); + m_xDistBorderMF->connect_value_changed(aLk3); + m_xDistNumMF->connect_value_changed(aLk3); + m_xIndentMF->connect_value_changed(aLk3); + + m_xLabelFollowedByLB->connect_changed(LINK(this, SvxNumPositionTabPage, LabelFollowedByHdl_Impl)); + + m_xListtabMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, ListtabPosHdl_Impl)); + m_xAlignedAtMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, AlignAtHdl_Impl)); + m_xIndentAtMF->connect_value_changed(LINK(this, SvxNumPositionTabPage, IndentAtHdl_Impl)); + + m_xLevelLB->set_selection_mode(SelectionMode::Multiple); + m_xLevelLB->connect_changed(LINK(this, SvxNumPositionTabPage, LevelHdl_Impl)); + m_xRelativeCB->connect_toggled(LINK(this, SvxNumPositionTabPage, RelativeHdl_Impl)); + m_xStandardPB->connect_clicked(LINK(this, SvxNumPositionTabPage, StandardHdl_Impl)); + + m_xRelativeCB->set_active(bLastRelative); + m_aPreviewWIN.SetPositionMode(); + eCoreUnit = rSet.GetPool()->GetMetric(rSet.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE)); +} + +SvxNumPositionTabPage::~SvxNumPositionTabPage() +{ + if (m_pLevelHdlEvent) + { + Application::RemoveUserEvent(m_pLevelHdlEvent); + m_pLevelHdlEvent = nullptr; + } + m_xPreviewWIN.reset(); +} + +/*-------------------------------------------------------*/ + +void SvxNumPositionTabPage::InitControls() +{ + bInInintControl = true; + const bool bRelative = !bLabelAlignmentPosAndSpaceModeActive && + m_xRelativeCB->get_sensitive() && m_xRelativeCB->get_active(); + const bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 && + SAL_MAX_UINT16 != nActNumLvl; + + m_xDistBorderMF->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive && + ( bSingleSelection || bRelative ) ); + m_xDistBorderFT->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive && + ( bSingleSelection || bRelative ) ); + + bool bSetDistEmpty = false; + bool bSameDistBorderNum = !bLabelAlignmentPosAndSpaceModeActive; + bool bSameDist = !bLabelAlignmentPosAndSpaceModeActive; + bool bSameIndent = !bLabelAlignmentPosAndSpaceModeActive; + bool bSameAdjust = true; + + bool bSameLabelFollowedBy = bLabelAlignmentPosAndSpaceModeActive; + bool bSameListtab = bLabelAlignmentPosAndSpaceModeActive; + bool bSameAlignAt = bLabelAlignmentPosAndSpaceModeActive; + bool bSameIndentAt = bLabelAlignmentPosAndSpaceModeActive; + + const SvxNumberFormat* aNumFmtArr[SVX_MAX_NUM]; + sal_uInt16 nMask = 1; + sal_uInt16 nLvl = SAL_MAX_UINT16; + tools::Long nFirstBorderTextRelative = -1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + aNumFmtArr[i] = &pActNum->GetLevel(i); + if(nActNumLvl & nMask) + { + if(SAL_MAX_UINT16 == nLvl) + nLvl = i; + + if( i > nLvl) + { + bSameAdjust &= aNumFmtArr[i]->GetNumAdjust() == aNumFmtArr[nLvl]->GetNumAdjust(); + if ( !bLabelAlignmentPosAndSpaceModeActive ) + { + if(bRelative) + { + if(nFirstBorderTextRelative == -1) + nFirstBorderTextRelative = + (aNumFmtArr[i]->GetAbsLSpace() + aNumFmtArr[i]->GetFirstLineOffset() - + aNumFmtArr[i - 1]->GetAbsLSpace() + aNumFmtArr[i - 1]->GetFirstLineOffset()); + else + bSameDistBorderNum &= nFirstBorderTextRelative == + (aNumFmtArr[i]->GetAbsLSpace() + aNumFmtArr[i]->GetFirstLineOffset() - + aNumFmtArr[i - 1]->GetAbsLSpace() + aNumFmtArr[i - 1]->GetFirstLineOffset()); + } + else + bSameDistBorderNum &= + aNumFmtArr[i]->GetAbsLSpace() - aNumFmtArr[i]->GetFirstLineOffset() == + aNumFmtArr[i - 1]->GetAbsLSpace() - aNumFmtArr[i - 1]->GetFirstLineOffset(); + + bSameDist &= aNumFmtArr[i]->GetCharTextDistance() == aNumFmtArr[nLvl]->GetCharTextDistance(); + bSameIndent &= aNumFmtArr[i]->GetFirstLineOffset() == aNumFmtArr[nLvl]->GetFirstLineOffset(); + } + else + { + bSameLabelFollowedBy &= + aNumFmtArr[i]->GetLabelFollowedBy() == aNumFmtArr[nLvl]->GetLabelFollowedBy(); + bSameListtab &= + aNumFmtArr[i]->GetListtabPos() == aNumFmtArr[nLvl]->GetListtabPos(); + bSameAlignAt &= + ( ( aNumFmtArr[i]->GetIndentAt() + aNumFmtArr[i]->GetFirstLineIndent() ) + == ( aNumFmtArr[nLvl]->GetIndentAt() + aNumFmtArr[nLvl]->GetFirstLineIndent() ) ); + bSameIndentAt &= + aNumFmtArr[i]->GetIndentAt() == aNumFmtArr[nLvl]->GetIndentAt(); + } + } + } + nMask <<= 1; + + } + if (SVX_MAX_NUM <= nLvl) + { + OSL_ENSURE(false, "cannot happen."); + return; + } + + if(bSameDistBorderNum) + { + tools::Long nDistBorderNum; + if(bRelative) + { + nDistBorderNum = static_cast<tools::Long>(aNumFmtArr[nLvl]->GetAbsLSpace())+ aNumFmtArr[nLvl]->GetFirstLineOffset(); + if(nLvl) + nDistBorderNum -= static_cast<tools::Long>(aNumFmtArr[nLvl - 1]->GetAbsLSpace())+ aNumFmtArr[nLvl - 1]->GetFirstLineOffset(); + } + else + { + nDistBorderNum = static_cast<tools::Long>(aNumFmtArr[nLvl]->GetAbsLSpace())+ aNumFmtArr[nLvl]->GetFirstLineOffset(); + } + SetMetricValue(*m_xDistBorderMF, nDistBorderNum, eCoreUnit); + } + else + bSetDistEmpty = true; + + if(bSameDist) + SetMetricValue(*m_xDistNumMF, aNumFmtArr[nLvl]->GetCharTextDistance(), eCoreUnit); + else + m_xDistNumMF->set_text(""); + if(bSameIndent) + SetMetricValue(*m_xIndentMF, - aNumFmtArr[nLvl]->GetFirstLineOffset(), eCoreUnit); + else + m_xIndentMF->set_text(""); + + if(bSameAdjust) + { + sal_Int32 nPos = 1; // centered + if(aNumFmtArr[nLvl]->GetNumAdjust() == SvxAdjust::Left) + nPos = 0; + else if(aNumFmtArr[nLvl]->GetNumAdjust() == SvxAdjust::Right) + nPos = 2; + m_xAlignLB->set_active(nPos); + m_xAlign2LB->set_active(nPos); + } + else + { + m_xAlignLB->set_active(-1); + m_xAlign2LB->set_active(-1); + } + + if ( bSameLabelFollowedBy ) + { + sal_Int32 nPos = 0; // LISTTAB + if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::SPACE ) + { + nPos = 1; + } + else if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NOTHING ) + { + nPos = 2; + } + else if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NEWLINE ) + { + nPos = 3; + } + m_xLabelFollowedByLB->set_active(nPos); + } + else + { + m_xLabelFollowedByLB->set_active(-1); + } + + if ( aNumFmtArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::LISTTAB ) + { + m_xListtabFT->set_sensitive(true); + m_xListtabMF->set_sensitive(true); + if ( bSameListtab ) + { + SetMetricValue(*m_xListtabMF, aNumFmtArr[nLvl]->GetListtabPos(), eCoreUnit); + } + else + { + m_xListtabMF->set_text(""); + } + } + else + { + m_xListtabFT->set_sensitive(false); + m_xListtabMF->set_sensitive(false); + m_xListtabMF->set_text(""); + } + + if ( bSameAlignAt ) + { + SetMetricValue(*m_xAlignedAtMF, + aNumFmtArr[nLvl]->GetIndentAt() + aNumFmtArr[nLvl]->GetFirstLineIndent(), + eCoreUnit); + } + else + { + m_xAlignedAtMF->set_text(""); + } + + if ( bSameIndentAt ) + { + SetMetricValue(*m_xIndentAtMF, aNumFmtArr[nLvl]->GetIndentAt(), eCoreUnit); + } + else + { + m_xIndentAtMF->set_text(""); + } + + if ( bSetDistEmpty ) + m_xDistBorderMF->set_text(""); + + bInInintControl = false; +} + +void SvxNumPositionTabPage::ActivatePage(const SfxItemSet& rSet) +{ + sal_uInt16 nTmpNumLvl = 1; + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if(pExampleSet) + { + if(const SfxBoolItem* pPresetItem = pExampleSet->GetItemIfSet(SID_PARAM_NUM_PRESET, false)) + bPreset = pPresetItem->GetValue(); + if(const SfxUInt16Item* pLevelItem = pExampleSet->GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nTmpNumLvl = pLevelItem->GetValue(); + } + if(const SvxNumBulletItem* pBulletItem = rSet.GetItemIfSet(nNumItemId, false)) + { + pSaveNum.reset( new SvxNumRule(pBulletItem->GetNumRule()) ); + } + bModified = (!pActNum->Get( 0 ) || bPreset); + if(*pSaveNum != *pActNum || + nActNumLvl != nTmpNumLvl ) + { + *pActNum = *pSaveNum; + nActNumLvl = nTmpNumLvl; + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + m_xLevelLB->select(pActNum->GetLevelCount()); + if (nActNumLvl != SAL_MAX_UINT16) + for (sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if (nActNumLvl & nMask) + m_xLevelLB->select(i); + nMask <<= 1 ; + } + m_xRelativeCB->set_sensitive(nActNumLvl != 1); + + InitPosAndSpaceMode(); + ShowControlsDependingOnPosAndSpaceMode(); + + InitControls(); + } + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); +} + +DeactivateRC SvxNumPositionTabPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + { + if (m_xDistBorderMF->get_sensitive()) + DistanceHdl_Impl(*m_xDistBorderMF); + DistanceHdl_Impl(*m_xIndentMF); + FillItemSet(_pSet); + } + return DeactivateRC::LeavePage; +} + +bool SvxNumPositionTabPage::FillItemSet( SfxItemSet* rSet ) +{ + rSet->Put(SfxUInt16Item(SID_PARAM_CUR_NUM_LEVEL, nActNumLvl)); + + if(bModified && pActNum) + { + *pSaveNum = *pActNum; + rSet->Put(SvxNumBulletItem( *pSaveNum, nNumItemId )); + rSet->Put(SfxBoolItem(SID_PARAM_NUM_PRESET, false)); + } + return bModified; +} + +void SvxNumPositionTabPage::Reset( const SfxItemSet* rSet ) +{ + // in Draw the item exists as WhichId, in Writer only as SlotId + const SvxNumBulletItem* pItem = + rSet->GetItemIfSet(SID_ATTR_NUMBERING_RULE, false); + if(!pItem) + { + nNumItemId = rSet->GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + pItem = rSet->GetItemIfSet(nNumItemId, false); + + if( !pItem ) + { + pItem = & rSet->Get( nNumItemId ); + } + } + DBG_ASSERT(pItem, "no item found!"); + pSaveNum.reset( new SvxNumRule(pItem->GetNumRule()) ); + + // insert levels + if (!m_xLevelLB->count_selected_rows()) + { + for(sal_uInt16 i = 1; i <= pSaveNum->GetLevelCount(); i++) + m_xLevelLB->append_text(OUString::number(i)); + if(pSaveNum->GetLevelCount() > 1) + { + OUString sEntry = "1 - " + OUString::number( pSaveNum->GetLevelCount() ); + m_xLevelLB->append_text(sEntry); + m_xLevelLB->select_text(sEntry); + } + else + m_xLevelLB->select(0); + } + else + m_xLevelLB->select(m_xLevelLB->count_selected_rows() - 1); + sal_uInt16 nMask = 1; + m_xLevelLB->unselect_all(); + if (nActNumLvl == SAL_MAX_UINT16) + { + m_xLevelLB->select(pSaveNum->GetLevelCount()); + } + else + { + for(sal_uInt16 i = 0; i < pSaveNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + m_xLevelLB->select(i); + nMask <<= 1; + } + } + + if(!pActNum) + pActNum.reset( new SvxNumRule(*pSaveNum) ); + else if(*pSaveNum != *pActNum) + *pActNum = *pSaveNum; + m_aPreviewWIN.SetNumRule(pActNum.get()); + + InitPosAndSpaceMode(); + ShowControlsDependingOnPosAndSpaceMode(); + + InitControls(); + bModified = false; +} + +void SvxNumPositionTabPage::InitPosAndSpaceMode() +{ + if ( pActNum == nullptr ) + { + SAL_WARN( "cui.tabpages", + "<SvxNumPositionTabPage::InitPosAndSpaceMode()> - misusage of method -> <pAktNum> has to be already set!" ); + return; + } + + SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode = + SvxNumberFormat::LABEL_ALIGNMENT; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + ePosAndSpaceMode = aNumFmt.GetPositionAndSpaceMode(); + if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT ) + { + break; + } + } + nMask <<= 1; + } + + bLabelAlignmentPosAndSpaceModeActive = + ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT; +} + +void SvxNumPositionTabPage::ShowControlsDependingOnPosAndSpaceMode() +{ + m_xDistBorderFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xDistBorderMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xRelativeCB->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xDistNumFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive && + pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS) ); + m_xDistNumMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive && + pActNum->IsFeatureSupported(SvxNumRuleFlags::CONTINUOUS)); + m_xAlignFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + m_xAlignLB->set_visible( !bLabelAlignmentPosAndSpaceModeActive ); + + m_xLabelFollowedByFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xLabelFollowedByLB->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xListtabFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xListtabMF->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlign2FT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlign2LB->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlignedAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xAlignedAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive ); + m_xIndentAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive ); +} + +std::unique_ptr<SfxTabPage> SvxNumPositionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet) +{ + return std::make_unique<SvxNumPositionTabPage>(pPage, pController, *rAttrSet); +} + +void SvxNumPositionTabPage::SetMetric(FieldUnit eMetric) +{ + if (eMetric == FieldUnit::MM) + { + m_xDistBorderMF->set_digits(1); + m_xDistNumMF->set_digits(1); + m_xIndentMF->set_digits(1); + m_xListtabMF->set_digits(1); + m_xAlignedAtMF->set_digits(1); + m_xIndentAtMF->set_digits(1); + } + m_xDistBorderMF->set_unit(eMetric); + m_xDistNumMF->set_unit(eMetric); + m_xIndentMF->set_unit(eMetric); + m_xListtabMF->set_unit(eMetric); + m_xAlignedAtMF->set_unit(eMetric); + m_xIndentAtMF->set_unit(eMetric); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, EditModifyHdl_Impl, weld::ComboBox&, void) +{ + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt(pActNum->GetLevel(i)); + + const sal_Int32 nPos = m_xAlignLB->get_visible() + ? m_xAlignLB->get_active() + : m_xAlign2LB->get_active(); + SvxAdjust eAdjust = SvxAdjust::Center; + if(nPos == 0) + eAdjust = SvxAdjust::Left; + else if(nPos == 2) + eAdjust = SvxAdjust::Right; + aNumFmt.SetNumAdjust( eAdjust ); + pActNum->SetLevel(i, aNumFmt); + } + nMask <<= 1; + } + SetModified(); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, LevelHdl_Impl, weld::TreeView&, void) +{ + if (m_pLevelHdlEvent) + return; + // tdf#127120 multiselection may be implemented by deselect follow by select so + // fire off the handler to happen on next event loop and only process the + // final state + m_pLevelHdlEvent = Application::PostUserEvent(LINK(this, SvxNumPositionTabPage, LevelHdl)); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, LevelHdl, void*, void) +{ + m_pLevelHdlEvent = nullptr; + + sal_uInt16 nSaveNumLvl = nActNumLvl; + nActNumLvl = 0; + std::vector<int> aSelectedRows = m_xLevelLB->get_selected_rows(); + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), pActNum->GetLevelCount()) != aSelectedRows.end() && + (aSelectedRows.size() == 1 || nSaveNumLvl != 0xffff)) + { + nActNumLvl = 0xFFFF; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + m_xLevelLB->unselect(i); + } + else if (!aSelectedRows.empty()) + { + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if (std::find(aSelectedRows.begin(), aSelectedRows.end(), i) != aSelectedRows.end()) + nActNumLvl |= nMask; + nMask <<= 1; + } + m_xLevelLB->unselect(pActNum->GetLevelCount()); + } + else + { + nActNumLvl = nSaveNumLvl; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++ ) + { + if(nActNumLvl & nMask) + { + m_xLevelLB->select(i); + break; + } + nMask <<=1; + } + } + m_xRelativeCB->set_sensitive(nActNumLvl != 1); + SetModified(); + InitPosAndSpaceMode(); + ShowControlsDependingOnPosAndSpaceMode(); + InitControls(); +} + +IMPL_LINK(SvxNumPositionTabPage, DistanceHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + if(bInInintControl) + return; + tools::Long nValue = GetCoreValue(rFld, eCoreUnit); + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel( i ) ); + if (&rFld == m_xDistBorderMF.get()) + { + + if (m_xRelativeCB->get_active()) + { + if(0 == i) + { + auto const nTmp = aNumFmt.GetFirstLineOffset(); + aNumFmt.SetAbsLSpace( nValue - nTmp); + } + else + { + tools::Long nTmp = pActNum->GetLevel( i - 1 ).GetAbsLSpace() + + pActNum->GetLevel( i - 1 ).GetFirstLineOffset() - + pActNum->GetLevel( i ).GetFirstLineOffset(); + + aNumFmt.SetAbsLSpace( nValue + nTmp); + } + } + else + { + aNumFmt.SetAbsLSpace( nValue - aNumFmt.GetFirstLineOffset()); + } + } + else if (&rFld == m_xDistNumMF.get()) + { + aNumFmt.SetCharTextDistance( static_cast<short>(nValue) ); + } + else if (&rFld == m_xIndentMF.get()) + { + // together with the FirstLineOffset the AbsLSpace must be changed, too + tools::Long nDiff = nValue + aNumFmt.GetFirstLineOffset(); + auto const nAbsLSpace = aNumFmt.GetAbsLSpace(); + aNumFmt.SetAbsLSpace(nAbsLSpace + nDiff); + aNumFmt.SetFirstLineOffset( -nValue ); + } + + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); + if (!m_xDistBorderMF->get_sensitive()) + { + m_xDistBorderMF->set_text(""); + } +} + +IMPL_LINK(SvxNumPositionTabPage, RelativeHdl_Impl, weld::Toggleable&, rBox, void) +{ + bool bOn = rBox.get_active(); + bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 && SAL_MAX_UINT16 != nActNumLvl; + bool bSetValue = false; + tools::Long nValue = 0; + if(bOn || bSingleSelection) + { + sal_uInt16 nMask = 1; + bool bFirst = true; + bSetValue = true; + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + const SvxNumberFormat &rNumFmt = pActNum->GetLevel(i); + if(bFirst) + { + nValue = rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset(); + if(bOn && i) + nValue -= (pActNum->GetLevel(i - 1).GetAbsLSpace() + pActNum->GetLevel(i - 1).GetFirstLineOffset()); + } + else + bSetValue = nValue == + (rNumFmt.GetAbsLSpace() + rNumFmt.GetFirstLineOffset()) - + (pActNum->GetLevel(i - 1).GetAbsLSpace() + pActNum->GetLevel(i - 1).GetFirstLineOffset()); + bFirst = false; + } + nMask <<= 1; + } + + } + if(bSetValue) + SetMetricValue(*m_xDistBorderMF, nValue, eCoreUnit); + else + m_xDistBorderMF->set_text(""); + m_xDistBorderMF->set_sensitive(bOn || bSingleSelection); + m_xDistBorderFT->set_sensitive(bOn || bSingleSelection); + bLastRelative = bOn; +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, LabelFollowedByHdl_Impl, weld::ComboBox&, void) +{ + // determine value to be set at the chosen list levels + SvxNumberFormat::LabelFollowedBy eLabelFollowedBy = SvxNumberFormat::LISTTAB; + { + const auto nPos = m_xLabelFollowedByLB->get_active(); + if ( nPos == 1 ) + { + eLabelFollowedBy = SvxNumberFormat::SPACE; + } + else if ( nPos == 2 ) + { + eLabelFollowedBy = SvxNumberFormat::NOTHING; + } + else if ( nPos == 3 ) + { + eLabelFollowedBy = SvxNumberFormat::NEWLINE; + } + } + + // set value at the chosen list levels + bool bSameListtabPos = true; + sal_uInt16 nFirstLvl = SAL_MAX_UINT16; + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + aNumFmt.SetLabelFollowedBy( eLabelFollowedBy ); + pActNum->SetLevel( i, aNumFmt ); + + if ( nFirstLvl == SAL_MAX_UINT16 ) + { + nFirstLvl = i; + } + else + { + bSameListtabPos &= aNumFmt.GetListtabPos() == + pActNum->GetLevel( nFirstLvl ).GetListtabPos(); + } + } + nMask <<= 1; + } + + // enable/disable metric field for list tab stop position depending on + // selected item following the list label. + m_xListtabFT->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB ); + m_xListtabMF->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB ); + if ( bSameListtabPos && eLabelFollowedBy == SvxNumberFormat::LISTTAB ) + { + SetMetricValue(*m_xListtabMF, pActNum->GetLevel( nFirstLvl ).GetListtabPos(), eCoreUnit); + } + else + { + m_xListtabMF->set_text(OUString()); + } + + SetModified(); +} + +IMPL_LINK(SvxNumPositionTabPage, ListtabPosHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + // determine value to be set at the chosen list levels + const tools::Long nValue = GetCoreValue(rFld, eCoreUnit); + + // set value at the chosen list levels + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + aNumFmt.SetListtabPos( nValue ); + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK(SvxNumPositionTabPage, AlignAtHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + // determine value to be set at the chosen list levels + const tools::Long nValue = GetCoreValue(rFld, eCoreUnit); + + // set value at the chosen list levels + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + const tools::Long nFirstLineIndent = nValue - aNumFmt.GetIndentAt(); + aNumFmt.SetFirstLineIndent( nFirstLineIndent ); + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK(SvxNumPositionTabPage, IndentAtHdl_Impl, weld::MetricSpinButton&, rFld, void) +{ + // determine value to be set at the chosen list levels + const tools::Long nValue = GetCoreValue(rFld, eCoreUnit); + + // set value at the chosen list levels + sal_uInt16 nMask = 1; + for( sal_uInt16 i = 0; i < pActNum->GetLevelCount(); ++i ) + { + if ( nActNumLvl & nMask ) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel(i) ); + const tools::Long nAlignedAt = aNumFmt.GetIndentAt() + + aNumFmt.GetFirstLineIndent(); + aNumFmt.SetIndentAt( nValue ); + const tools::Long nNewFirstLineIndent = nAlignedAt - nValue; + aNumFmt.SetFirstLineIndent( nNewFirstLineIndent ); + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + SetModified(); +} + +IMPL_LINK_NOARG(SvxNumPositionTabPage, StandardHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nMask = 1; + SvxNumRule aTmpNumRule( pActNum->GetFeatureFlags(), + pActNum->GetLevelCount(), + pActNum->IsContinuousNumbering(), + SvxNumRuleType::NUMBERING, + pActNum->GetLevel( 0 ).GetPositionAndSpaceMode() ); + for(sal_uInt16 i = 0; i < pActNum->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + SvxNumberFormat aNumFmt( pActNum->GetLevel( i ) ); + const SvxNumberFormat& aTempFmt(aTmpNumRule.GetLevel( i )); + aNumFmt.SetPositionAndSpaceMode( aTempFmt.GetPositionAndSpaceMode() ); + if ( aTempFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) + { + aNumFmt.SetAbsLSpace( aTempFmt.GetAbsLSpace() ); + aNumFmt.SetCharTextDistance( aTempFmt.GetCharTextDistance() ); + aNumFmt.SetFirstLineOffset( aTempFmt.GetFirstLineOffset() ); + } + else if ( aTempFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) + { + aNumFmt.SetNumAdjust( aTempFmt.GetNumAdjust() ); + aNumFmt.SetLabelFollowedBy( aTempFmt.GetLabelFollowedBy() ); + aNumFmt.SetListtabPos( aTempFmt.GetListtabPos() ); + aNumFmt.SetFirstLineIndent( aTempFmt.GetFirstLineIndent() ); + aNumFmt.SetIndentAt( aTempFmt.GetIndentAt() ); + } + + pActNum->SetLevel( i, aNumFmt ); + } + nMask <<= 1; + } + + InitControls(); + SetModified(); +} + +void SvxNumPositionTabPage::SetModified() +{ + bModified = true; + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); +} + +void SvxNumOptionsTabPage::SetModified(bool bRepaint) +{ + bModified = true; + if (bRepaint) + { + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); + } +} + +void SvxNumOptionsTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxStringListItem* pListItem = aSet.GetItem<SfxStringListItem>(SID_CHAR_FMT_LIST_BOX, false); + const SfxStringItem* pNumCharFmt = aSet.GetItem<SfxStringItem>(SID_NUM_CHAR_FMT, false); + const SfxStringItem* pBulletCharFmt = aSet.GetItem<SfxStringItem>(SID_BULLET_CHAR_FMT, false); + const SfxUInt16Item* pMetricItem = aSet.GetItem<SfxUInt16Item>(SID_METRIC_ITEM, false); + + if (pNumCharFmt &&pBulletCharFmt) + SetCharFmts( pNumCharFmt->GetValue(),pBulletCharFmt->GetValue()); + + if (pListItem) + { + const std::vector<OUString> &aList = pListItem->GetList(); + sal_uInt32 nCount = aList.size(); + for(sal_uInt32 i = 0; i < nCount; i++) + m_xCharFmtLB->append_text(aList[i]); + } + if (pMetricItem) + SetMetric(static_cast<FieldUnit>(pMetricItem->GetValue())); +} + +void SvxNumPositionTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pMetricItem = aSet.GetItem<SfxUInt16Item>(SID_METRIC_ITEM, false); + + if (pMetricItem) + SetMetric(static_cast<FieldUnit>(pMetricItem->GetValue())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/page.cxx b/cui/source/tabpages/page.cxx new file mode 100644 index 000000000..bb4976324 --- /dev/null +++ b/cui/source/tabpages/page.cxx @@ -0,0 +1,1667 @@ +/* -*- 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 . + */ + +#include <memory> +#include <o3tl/unit_conversion.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/viewsh.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <svtools/unitconv.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sfx2/htmlmode.hxx> +#include <sal/macros.h> +#include <osl/diagnose.h> + +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <page.hxx> +#include <svx/pageitem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/pbinitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/dlgutil.hxx> +#include <editeng/paperinf.hxx> +#include <svl/stritem.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/editrids.hrc> +#include <svx/svxids.hrc> +#include <svtools/optionsdrawinglayer.hxx> +#include <svl/slstitm.hxx> +#include <svx/xdef.hxx> +#include <svx/unobrushitemhelper.hxx> +#include <svx/SvxNumOptionsTabPageHelper.hxx> +#include <sal/log.hxx> +#include <svl/grabbagitem.hxx> + +// static ---------------------------------------------------------------- + +// #i19922# - tdf#126051 see svx/source/dialog/hdft.cxx and sw/source/uibase/sidebar/PageMarginControl.hxx +constexpr tools::Long MINBODY = o3tl::toTwips(1, o3tl::Length::mm); // 1mm in twips rounded + +const WhichRangesContainer SvxPageDescPage::pRanges( + svl::Items< + SID_ATTR_BORDER_OUTER, SID_ATTR_BORDER_SHADOW, + SID_ATTR_LRSPACE, SID_ATTR_PAGE_SHARED, + SID_SWREGISTER_COLLECTION, SID_SWREGISTER_MODE>); +// ------- Mapping page layout ------------------------------------------ + +const SvxPageUsage aArr[] = +{ + SvxPageUsage::All, + SvxPageUsage::Mirror, + SvxPageUsage::Right, + SvxPageUsage::Left +}; + + +static sal_uInt16 PageUsageToPos_Impl( SvxPageUsage nUsage ) +{ + for ( size_t i = 0; i < std::size(aArr); ++i ) + if ( aArr[i] == nUsage ) + return i; + return 3; +} + + +static SvxPageUsage PosToPageUsage_Impl( sal_uInt16 nPos ) +{ + if ( nPos >= std::size(aArr) ) + return SvxPageUsage::NONE; + return aArr[nPos]; +} + + +static Size GetMinBorderSpace_Impl( const SvxShadowItem& rShadow, const SvxBoxItem& rBox ) +{ + Size aSz; + aSz.setHeight( rShadow.CalcShadowSpace( SvxShadowItemSide::BOTTOM ) + rBox.CalcLineSpace( SvxBoxItemLine::BOTTOM ) ); + aSz.AdjustHeight(rShadow.CalcShadowSpace( SvxShadowItemSide::TOP ) + rBox.CalcLineSpace( SvxBoxItemLine::TOP ) ); + aSz.setWidth( rShadow.CalcShadowSpace( SvxShadowItemSide::LEFT ) + rBox.CalcLineSpace( SvxBoxItemLine::LEFT ) ); + aSz.AdjustWidth(rShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT ) + rBox.CalcLineSpace( SvxBoxItemLine::RIGHT ) ); + return aSz; +} + + +static tools::Long ConvertLong_Impl( const tools::Long nIn, MapUnit eUnit ) +{ + return OutputDevice::LogicToLogic( nIn, eUnit, MapUnit::MapTwip ); +} + +static bool IsEqualSize_Impl( const SvxSizeItem* pSize, const Size& rSize ) +{ + if ( pSize ) + { + Size aSize = pSize->GetSize(); + tools::Long nDiffW = std::abs( rSize.Width () - aSize.Width () ); + tools::Long nDiffH = std::abs( rSize.Height() - aSize.Height() ); + return ( nDiffW < 10 && nDiffH < 10 ); + } + else + return false; +} + + +#define MARGIN_LEFT ( MarginPosition(0x0001) ) +#define MARGIN_RIGHT ( MarginPosition(0x0002) ) +#define MARGIN_TOP ( MarginPosition(0x0004) ) +#define MARGIN_BOTTOM ( MarginPosition(0x0008) ) + +// class SvxPageDescPage -------------------------------------------------- + +std::unique_ptr<SfxTabPage> SvxPageDescPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet ) +{ + return std::make_unique<SvxPageDescPage>(pPage, pController, *rSet); +} + +SvxPageDescPage::SvxPageDescPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/pageformatpage.ui", "PageFormatPage", &rAttr) + , bLandscape(false) + , eMode(SVX_PAGE_MODE_STANDARD) + , ePaperStart(PAPER_A3) + , m_nPos(0) + , mpDefPrinter(nullptr) + , mbDelPrinter(false) + , mbEnableDrawingLayerFillStyles(false) + , m_xPaperSizeBox(new SvxPaperSizeListBox(m_xBuilder->weld_combo_box("comboPageFormat"))) + , m_xPaperWidthEdit(m_xBuilder->weld_metric_spin_button("spinWidth", FieldUnit::CM)) + , m_xPaperHeightEdit(m_xBuilder->weld_metric_spin_button("spinHeight", FieldUnit::CM)) + , m_xOrientationFT(m_xBuilder->weld_label("labelOrientation")) + , m_xPortraitBtn(m_xBuilder->weld_radio_button("radiobuttonPortrait")) + , m_xLandscapeBtn(m_xBuilder->weld_radio_button("radiobuttonLandscape")) + , m_xTextFlowLbl(m_xBuilder->weld_label("labelTextFlow")) + , m_xTextFlowBox(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("comboTextFlowBox"))) + , m_xPaperTrayBox(m_xBuilder->weld_combo_box("comboPaperTray")) + , m_xLeftMarginLbl(m_xBuilder->weld_label("labelLeftMargin")) + , m_xLeftMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargLeft", FieldUnit::CM)) + , m_xRightMarginLbl(m_xBuilder->weld_label("labelRightMargin")) + , m_xRightMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargRight", FieldUnit::CM)) + , m_xTopMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargTop", FieldUnit::CM)) + , m_xBottomMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargBot", FieldUnit::CM)) + , m_xGutterMarginLbl(m_xBuilder->weld_label("labelGutterMargin")) + , m_xGutterMarginEdit(m_xBuilder->weld_metric_spin_button("spinMargGut", FieldUnit::CM)) + , m_xPageText(m_xBuilder->weld_label("labelPageLayout")) + , m_xLayoutBox(m_xBuilder->weld_combo_box("comboPageLayout")) + , m_xNumberFormatText(m_xBuilder->weld_label("labelPageNumbers")) + , m_xNumberFormatBox(new SvxPageNumberListBox(m_xBuilder->weld_combo_box("comboLayoutFormat"))) + , m_xTblAlignFT(m_xBuilder->weld_label("labelTblAlign")) + , m_xHorzBox(m_xBuilder->weld_check_button("checkbuttonHorz")) + , m_xVertBox(m_xBuilder->weld_check_button("checkbuttonVert")) + , m_xAdaptBox(m_xBuilder->weld_check_button("checkAdaptBox")) + , m_xRegisterCB(m_xBuilder->weld_check_button("checkRegisterTrue")) + , m_xRegisterFT(m_xBuilder->weld_label("labelRegisterStyle")) + , m_xRegisterLB(m_xBuilder->weld_combo_box("comboRegisterStyle")) + , m_xGutterPositionFT(m_xBuilder->weld_label("labelGutterPosition")) + , m_xGutterPositionLB(m_xBuilder->weld_combo_box("comboGutterPosition")) + , m_xRtlGutterCB(m_xBuilder->weld_check_button("checkRtlGutter")) + , m_xBackgroundFullSizeCB(m_xBuilder->weld_check_button("checkBackgroundFullSize")) + // Strings stored in UI + , m_xInsideLbl(m_xBuilder->weld_label("labelInner")) + , m_xOutsideLbl(m_xBuilder->weld_label("labelOuter")) + , m_xPrintRangeQueryText(m_xBuilder->weld_label("labelMsg")) + , m_xBspWin(new weld::CustomWeld(*m_xBuilder, "drawingareaPageDirection", m_aBspWin)) +{ + m_xRegisterLB->set_size_request(m_xRegisterLB->get_approximate_digit_width() * 20, -1); + + bBorderModified = false; + m_aBspWin.EnableRTL(false); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + SvtCTLOptions aCTLLanguageOptions; + bool bCJK = SvtCJKOptions::IsAsianTypographyEnabled(); + bool bCTL = aCTLLanguageOptions.IsCTLFontEnabled(); + bool bWeb = false; + + const SfxUInt16Item* pHtmlModeItem = rAttr.GetItemIfSet(SID_HTML_MODE, false); + if (!pHtmlModeItem) + { + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + pHtmlModeItem = pShell->GetItem(SID_HTML_MODE); + } + if (pHtmlModeItem) + bWeb = 0 != (pHtmlModeItem->GetValue() & HTMLMODE_ON); + + // fill text flow listbox with valid entries + + m_xTextFlowBox->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_PAGEDIR_LTR_HORI)); + + if (bCTL) + m_xTextFlowBox->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_PAGEDIR_RTL_HORI)); + + + // #109989# do not show vertical directions in Writer/Web + if( !bWeb && bCJK ) + { + m_xTextFlowBox->append(SvxFrameDirection::Vertical_RL_TB, SvxResId(RID_SVXSTR_PAGEDIR_RTL_VERT)); + m_xTextFlowBox->append(SvxFrameDirection::Vertical_LR_TB, SvxResId(RID_SVXSTR_PAGEDIR_LTR_VERT)); + } + + // #109989# show the text direction box in Writer/Web too + if( (bCJK || bCTL) && + SfxItemState::UNKNOWN < rAttr.GetItemState(GetWhich( SID_ATTR_FRAMEDIRECTION ))) + { + m_xTextFlowLbl->show(); + m_xTextFlowBox->show(); + m_xTextFlowBox->connect_changed(LINK(this, SvxPageDescPage, FrameDirectionModify_Impl)); + + m_aBspWin.EnableFrameDirection(true); + } + Init_Impl(); + + FieldUnit eFUnit = GetModuleFieldUnit( rAttr ); + SetFieldUnit( *m_xLeftMarginEdit, eFUnit ); + SetFieldUnit( *m_xRightMarginEdit, eFUnit ); + SetFieldUnit( *m_xTopMarginEdit, eFUnit ); + SetFieldUnit( *m_xBottomMarginEdit, eFUnit ); + SetFieldUnit(*m_xGutterMarginEdit, eFUnit); + SetFieldUnit( *m_xPaperWidthEdit, eFUnit ); + SetFieldUnit( *m_xPaperHeightEdit, eFUnit ); + + if ( SfxViewShell::Current() && SfxViewShell::Current()->GetPrinter() ) + { + mpDefPrinter = SfxViewShell::Current()->GetPrinter(); + } + else + { + mpDefPrinter = VclPtr<Printer>::Create(); + mbDelPrinter = true; + } + + MapMode aOldMode = mpDefPrinter->GetMapMode(); + mpDefPrinter->SetMapMode(MapMode(MapUnit::MapTwip)); + + // set first- and last-values for the margins + Size aPaperSize = mpDefPrinter->GetPaperSize(); + Size aPrintSize = mpDefPrinter->GetOutputSize(); + + /* + * To convert a point ( 0,0 ) into logic coordinates + * looks like nonsense; but it makes sense when the + * coordinate system's origin has been moved. + */ + Point aPrintOffset = mpDefPrinter->GetPageOffset() - mpDefPrinter->PixelToLogic( Point() ); + mpDefPrinter->SetMapMode( aOldMode ); + + nFirstLeftMargin = m_xLeftMarginEdit->convert_value_from(m_xLeftMarginEdit->normalize(aPrintOffset.X()), FieldUnit::TWIP); + nFirstRightMargin = m_xRightMarginEdit->convert_value_from(m_xRightMarginEdit->normalize(aPaperSize.Width() - aPrintSize.Width() - aPrintOffset.X()), FieldUnit::TWIP); + nFirstTopMargin = m_xTopMarginEdit->convert_value_from(m_xTopMarginEdit->normalize(aPrintOffset.Y() ), FieldUnit::TWIP); + nFirstBottomMargin = m_xBottomMarginEdit->convert_value_from(m_xBottomMarginEdit->normalize(aPaperSize.Height() - aPrintSize.Height() - aPrintOffset.Y()), FieldUnit::TWIP ); + nLastLeftMargin = m_xLeftMarginEdit->convert_value_from(m_xLeftMarginEdit->normalize(aPrintOffset.X() + aPrintSize.Width()), FieldUnit::TWIP); + nLastRightMargin = m_xRightMarginEdit->convert_value_from(m_xRightMarginEdit->normalize(aPrintOffset.X() + aPrintSize.Width()), FieldUnit::TWIP); + nLastTopMargin = m_xTopMarginEdit->convert_value_from(m_xTopMarginEdit->normalize(aPrintOffset.Y() + aPrintSize.Height()), FieldUnit::TWIP); + nLastBottomMargin = m_xBottomMarginEdit->convert_value_from(m_xBottomMarginEdit->normalize(aPrintOffset.Y() + aPrintSize.Height()), FieldUnit::TWIP); + + // #i4219# take Maximum now from configuration (1/100th cm) + // was: 11900 -> 119 cm ;new value 3 meters -> 300 cm -> 30000 + m_xPaperWidthEdit->set_max(m_xPaperWidthEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperWidth()), FieldUnit::CM); + m_xPaperHeightEdit->set_max(m_xPaperHeightEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperHeight()), FieldUnit::CM); + + // #i4219# also for margins (1/100th cm). Was: 9999, keeping. + m_xLeftMarginEdit->set_max(m_xLeftMarginEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperLeftMargin()), FieldUnit::MM); + m_xRightMarginEdit->set_max(m_xRightMarginEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperRightMargin()), FieldUnit::MM); + m_xTopMarginEdit->set_max(m_xTopMarginEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperTopMargin()), FieldUnit::MM); + m_xBottomMarginEdit->set_max(m_xBottomMarginEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperBottomMargin()), FieldUnit::MM); + m_xGutterMarginEdit->set_max( + m_xGutterMarginEdit->normalize(SvtOptionsDrawinglayer::GetMaximumPaperLeftMargin()), + FieldUnit::MM); + + // Get the i18n framework numberings and add them to the listbox. + SvxNumOptionsTabPageHelper::GetI18nNumbering(m_xNumberFormatBox->get_widget(), std::numeric_limits<sal_uInt16>::max()); +} + +SvxPageDescPage::~SvxPageDescPage() +{ + if(mbDelPrinter) + { + mpDefPrinter.disposeAndClear(); + mbDelPrinter = false; + } +} + +void SvxPageDescPage::Init_Impl() +{ + // adjust the handler + m_xLayoutBox->connect_changed(LINK(this, SvxPageDescPage, LayoutHdl_Impl)); + m_xGutterPositionLB->connect_changed(LINK(this, SvxPageDescPage, GutterPositionHdl_Impl)); + + m_xPaperSizeBox->connect_changed(LINK(this, SvxPageDescPage, PaperSizeSelect_Impl)); + m_xPaperWidthEdit->connect_value_changed( LINK(this, SvxPageDescPage, PaperSizeModify_Impl)); + m_xPaperHeightEdit->connect_value_changed(LINK(this, SvxPageDescPage, PaperSizeModify_Impl)); + m_xLandscapeBtn->connect_toggled(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + m_xPortraitBtn->connect_toggled(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + + Link<weld::MetricSpinButton&, void> aLink = LINK(this, SvxPageDescPage, BorderModify_Impl); + m_xLeftMarginEdit->connect_value_changed(aLink); + m_xRightMarginEdit->connect_value_changed(aLink); + m_xTopMarginEdit->connect_value_changed(aLink); + m_xBottomMarginEdit->connect_value_changed(aLink); + m_xGutterMarginEdit->connect_value_changed(aLink); + + m_xHorzBox->connect_toggled(LINK(this, SvxPageDescPage, CenterHdl_Impl)); + m_xVertBox->connect_toggled(LINK(this, SvxPageDescPage, CenterHdl_Impl)); +} + +void SvxPageDescPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + SAL_WARN_IF(!pPool, "cui.tabpages", "Where is the pool?"); + MapUnit eUnit = pPool->GetMetric( GetWhich( SID_ATTR_LRSPACE ) ); + + // adjust margins (right/left) + const SfxPoolItem* pItem = GetItem( *rSet, SID_ATTR_LRSPACE ); + + if ( pItem ) + { + const SvxLRSpaceItem& rLRSpace = static_cast<const SvxLRSpaceItem&>(*pItem); + SetMetricValue( *m_xLeftMarginEdit, rLRSpace.GetLeft(), eUnit ); + SetMetricValue(*m_xGutterMarginEdit, rLRSpace.GetGutterMargin(), eUnit); + m_aBspWin.SetLeft( + static_cast<sal_uInt16>(ConvertLong_Impl( rLRSpace.GetLeft(), eUnit )) ); + SetMetricValue( *m_xRightMarginEdit, rLRSpace.GetRight(), eUnit ); + m_aBspWin.SetRight( + static_cast<sal_uInt16>(ConvertLong_Impl( rLRSpace.GetRight(), eUnit )) ); + } + + // adjust margins (top/bottom) + pItem = GetItem( *rSet, SID_ATTR_ULSPACE ); + + if ( pItem ) + { + const SvxULSpaceItem& rULSpace = static_cast<const SvxULSpaceItem&>(*pItem); + SetMetricValue( *m_xTopMarginEdit, rULSpace.GetUpper(), eUnit ); + m_aBspWin.SetTop( + static_cast<sal_uInt16>(ConvertLong_Impl( static_cast<tools::Long>(rULSpace.GetUpper()), eUnit )) ); + SetMetricValue( *m_xBottomMarginEdit, rULSpace.GetLower(), eUnit ); + m_aBspWin.SetBottom( + static_cast<sal_uInt16>(ConvertLong_Impl( static_cast<tools::Long>(rULSpace.GetLower()), eUnit )) ); + } + + if (const SfxGrabBagItem* pGragbagItem = rSet->GetItemIfSet(SID_ATTR_CHAR_GRABBAG)) + { + bool bGutterAtTop{}; + auto it = pGragbagItem->GetGrabBag().find("GutterAtTop"); + if (it != pGragbagItem->GetGrabBag().end()) + { + it->second >>= bGutterAtTop; + } + + if (bGutterAtTop) + { + m_xGutterPositionLB->set_active(1); + } + else + { + // Left. + m_xGutterPositionLB->set_active(0); + } + it = pGragbagItem->GetGrabBag().find("RtlGutter"); + bool bRtlGutter{}; + if (it != pGragbagItem->GetGrabBag().end()) + { + it->second >>= bRtlGutter; + m_xRtlGutterCB->set_active(bRtlGutter); + m_xRtlGutterCB->show(); + } + it = pGragbagItem->GetGrabBag().find("BackgroundFullSize"); + bool isBackgroundFullSize{}; + if (it != pGragbagItem->GetGrabBag().end()) + { + it->second >>= isBackgroundFullSize; + m_xBackgroundFullSizeCB->set_active(isBackgroundFullSize); + m_xBackgroundFullSizeCB->show(); + } + } + + // general page data + SvxNumType eNumType = SVX_NUM_ARABIC; + bLandscape = ( mpDefPrinter->GetOrientation() == Orientation::Landscape ); + SvxPageUsage nUse = SvxPageUsage::All; + pItem = GetItem( *rSet, SID_ATTR_PAGE ); + + if ( pItem ) + { + const SvxPageItem& rItem = static_cast<const SvxPageItem&>(*pItem); + eNumType = rItem.GetNumType(); + nUse = rItem.GetPageUsage(); + bLandscape = rItem.IsLandscape(); + } + + // alignment + m_xLayoutBox->set_active(::PageUsageToPos_Impl(nUse)); + m_aBspWin.SetUsage( nUse ); + LayoutHdl_Impl( *m_xLayoutBox ); + + //adjust numeration type of the page style + m_xNumberFormatBox->set_active_id(eNumType); + + m_xPaperTrayBox->clear(); + sal_uInt8 nPaperBin = PAPERBIN_PRINTER_SETTINGS; + pItem = GetItem( *rSet, SID_ATTR_PAGE_PAPERBIN ); + + if ( pItem ) + { + nPaperBin = static_cast<const SvxPaperBinItem*>(pItem)->GetValue(); + + if ( nPaperBin >= mpDefPrinter->GetPaperBinCount() ) + nPaperBin = PAPERBIN_PRINTER_SETTINGS; + } + + OUString aBinName; + + if ( PAPERBIN_PRINTER_SETTINGS == nPaperBin ) + aBinName = EditResId(RID_SVXSTR_PAPERBIN_SETTINGS); + else + aBinName = mpDefPrinter->GetPaperBinName( static_cast<sal_uInt16>(nPaperBin) ); + + m_xPaperTrayBox->append(OUString::number(nPaperBin), aBinName); + m_xPaperTrayBox->set_active_text(aBinName); + // reset focus handler to default first so know none already connected + m_xPaperTrayBox->connect_focus_in(Link<weld::Widget&, void>()); + // update the list when widget gets focus + m_xPaperTrayBox->connect_focus_in(LINK(this, SvxPageDescPage, PaperBinHdl_Impl)); + + Size aPaperSize = SvxPaperInfo::GetPaperSize( mpDefPrinter ); + pItem = GetItem( *rSet, SID_ATTR_PAGE_SIZE ); + + if ( pItem ) + aPaperSize = static_cast<const SvxSizeItem*>(pItem)->GetSize(); + + bool bOrientationSupport = + mpDefPrinter->HasSupport( PrinterSupport::SetOrientation ); + + if ( !bOrientationSupport && + aPaperSize.Width() > aPaperSize.Height() ) + bLandscape = true; + + // tdf#130548 disable callbacks on the other of a pair of the radiogroup + // when toggling its partner + m_xLandscapeBtn->connect_toggled(Link<weld::Toggleable&, void>()); + m_xPortraitBtn->connect_toggled(Link<weld::Toggleable&, void>()); + + m_xLandscapeBtn->set_active(bLandscape); + m_xPortraitBtn->set_active(!bLandscape); + + m_xLandscapeBtn->connect_toggled(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + m_xPortraitBtn->connect_toggled(LINK(this, SvxPageDescPage, SwapOrientation_Impl)); + + m_aBspWin.SetSize( Size( ConvertLong_Impl( aPaperSize.Width(), eUnit ), + ConvertLong_Impl( aPaperSize.Height(), eUnit ) ) ); + + aPaperSize = OutputDevice::LogicToLogic(aPaperSize, MapMode(eUnit), MapMode(MapUnit::Map100thMM)); + if ( bLandscape ) + Swap( aPaperSize ); + + // Actual Paper Format + Paper ePaper = SvxPaperInfo::GetSvxPaper( aPaperSize, MapUnit::Map100thMM ); + + if ( PAPER_USER != ePaper ) + aPaperSize = SvxPaperInfo::GetPaperSize( ePaper, MapUnit::Map100thMM ); + + if ( bLandscape ) + Swap( aPaperSize ); + + // write values into the edits + SetMetricValue( *m_xPaperHeightEdit, aPaperSize.Height(), MapUnit::Map100thMM ); + SetMetricValue( *m_xPaperWidthEdit, aPaperSize.Width(), MapUnit::Map100thMM ); + m_xPaperSizeBox->clear(); + + m_xPaperSizeBox->FillPaperSizeEntries( ( ePaperStart == PAPER_A3 ) ? PaperSizeApp::Std : PaperSizeApp::Draw ); + m_xPaperSizeBox->set_active_id( ePaper ); + + // application specific + + switch ( eMode ) + { + case SVX_PAGE_MODE_CENTER: + { + m_xTblAlignFT->show(); + m_xHorzBox->show(); + m_xVertBox->show(); + DisableVerticalPageDir(); + + // horizontal alignment + pItem = GetItem( *rSet, SID_ATTR_PAGE_EXT1 ); + m_xHorzBox->set_active(pItem && static_cast<const SfxBoolItem*>(pItem)->GetValue()); + + // vertical alignment + pItem = GetItem( *rSet, SID_ATTR_PAGE_EXT2 ); + m_xVertBox->set_active(pItem && static_cast<const SfxBoolItem*>(pItem)->GetValue()); + + // set example window on the table + m_aBspWin.SetTable( true ); + m_aBspWin.SetHorz(m_xHorzBox->get_active()); + m_aBspWin.SetVert(m_xVertBox->get_active()); + + m_xGutterMarginLbl->hide(); + m_xGutterMarginEdit->hide(); + m_xGutterPositionFT->hide(); + m_xGutterPositionLB->hide(); + + break; + } + + case SVX_PAGE_MODE_PRESENTATION: + { + DisableVerticalPageDir(); + m_xAdaptBox->show(); + pItem = GetItem( *rSet, SID_ATTR_PAGE_EXT1 ); + m_xAdaptBox->set_active( pItem && + static_cast<const SfxBoolItem*>(pItem)->GetValue() ); + + //!!! hidden, because not implemented by StarDraw + m_xLayoutBox->hide(); + m_xPageText->hide(); + + m_xGutterMarginLbl->hide(); + m_xGutterMarginEdit->hide(); + m_xGutterPositionFT->hide(); + m_xGutterPositionLB->hide(); + + break; + } + default: ;//prevent warning + } + + + // display background and border in the example + ResetBackground_Impl( *rSet ); +//! UpdateExample_Impl(); + RangeHdl_Impl(); + + InitHeadFoot_Impl( *rSet ); + + bBorderModified = false; + SwapFirstValues_Impl( false ); + UpdateExample_Impl(); + + m_xLeftMarginEdit->save_value(); + m_xRightMarginEdit->save_value(); + m_xTopMarginEdit->save_value(); + m_xBottomMarginEdit->save_value(); + m_xGutterMarginEdit->save_value(); + m_xLayoutBox->save_value(); + m_xNumberFormatBox->save_value(); + m_xPaperSizeBox->save_value(); + m_xPaperWidthEdit->save_value(); + m_xPaperHeightEdit->save_value(); + m_xPortraitBtn->save_state(); + m_xLandscapeBtn->save_state(); + m_xPaperTrayBox->save_value(); + m_xVertBox->save_state(); + m_xHorzBox->save_state(); + m_xAdaptBox->save_state(); + m_xGutterPositionLB->save_value(); + m_xRtlGutterCB->save_state(); + m_xBackgroundFullSizeCB->save_state(); + + CheckMarginEdits( true ); + + + if(SfxItemState::SET == rSet->GetItemState(SID_SWREGISTER_MODE)) + { + m_xRegisterCB->set_active(rSet->Get(SID_SWREGISTER_MODE).GetValue()); + m_xRegisterCB->save_state(); + RegisterModify(*m_xRegisterCB); + } + if(SfxItemState::SET == rSet->GetItemState(SID_SWREGISTER_COLLECTION)) + { + m_xRegisterLB->set_active_text( + rSet->Get(SID_SWREGISTER_COLLECTION).GetValue()); + m_xRegisterLB->save_value(); + } + + SfxItemState eState = rSet->GetItemState( GetWhich( SID_ATTR_FRAMEDIRECTION ), + true, &pItem ); + if( SfxItemState::UNKNOWN != eState ) + { + SvxFrameDirection nVal = SfxItemState::SET == eState + ? static_cast<const SvxFrameDirectionItem*>(pItem)->GetValue() + : SvxFrameDirection::Horizontal_LR_TB; + m_xTextFlowBox->set_active_id(nVal); + + m_xTextFlowBox->save_value(); + m_aBspWin.SetFrameDirection(nVal); + } +} + +void SvxPageDescPage::FillUserData() +{ + if (SVX_PAGE_MODE_PRESENTATION == eMode) + SetUserData(m_xAdaptBox->get_active() ? OUString("1") : OUString("0")) ; + +} + +bool SvxPageDescPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + const SfxItemSet& rOldSet = GetItemSet(); + SfxItemPool* pPool = rOldSet.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + sal_uInt16 nWhich = GetWhich( SID_ATTR_LRSPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + const SfxPoolItem* pOld = nullptr; + + // copy old left and right margins + SvxLRSpaceItem aMargin( static_cast<const SvxLRSpaceItem&>(rOldSet.Get( nWhich )) ); + + // copy old top and bottom margins + nWhich = GetWhich( SID_ATTR_ULSPACE ); + SvxULSpaceItem aTopMargin( static_cast<const SvxULSpaceItem&>(rOldSet.Get( nWhich )) ); + + if (m_xLeftMarginEdit->get_value_changed_from_saved()) + { + aMargin.SetLeft( static_cast<sal_uInt16>(GetCoreValue( *m_xLeftMarginEdit, eUnit )) ); + bModified = true; + } + + if (m_xRightMarginEdit->get_value_changed_from_saved()) + { + aMargin.SetRight( static_cast<sal_uInt16>(GetCoreValue( *m_xRightMarginEdit, eUnit )) ); + bModified = true; + } + + if (m_xGutterMarginEdit->get_value_changed_from_saved()) + { + aMargin.SetGutterMargin(static_cast<sal_uInt16>(GetCoreValue(*m_xGutterMarginEdit, eUnit))); + bModified = true; + } + + // set left and right margins + if (bModified) + { + pOld = GetOldItem( *rSet, SID_ATTR_LRSPACE ); + + if ( !pOld || *static_cast<const SvxLRSpaceItem*>(pOld) != aMargin ) + rSet->Put( aMargin ); + else + bModified = false; + } + + if (rOldSet.HasItem(SID_ATTR_CHAR_GRABBAG)) + { + // Set gutter position. + SfxGrabBagItem aGrabBagItem(rOldSet.Get(SID_ATTR_CHAR_GRABBAG)); + if (m_xGutterPositionLB->get_value_changed_from_saved()) + { + bool bGutterAtTop = m_xGutterPositionLB->get_active() == 1; + aGrabBagItem.GetGrabBag()["GutterAtTop"] <<= bGutterAtTop; + bModified = true; + } + if (m_xRtlGutterCB->get_state_changed_from_saved()) + { + bool const bRtlGutter(m_xRtlGutterCB->get_active()); + aGrabBagItem.GetGrabBag()["RtlGutter"] <<= bRtlGutter; + bModified = true; + } + if (m_xBackgroundFullSizeCB->get_state_changed_from_saved()) + { + bool const isBackgroundFullSize(m_xBackgroundFullSizeCB->get_active()); + aGrabBagItem.GetGrabBag()["BackgroundFullSize"] <<= isBackgroundFullSize; + bModified = true; + } + + if (bModified) + { + pOld = rOldSet.GetItem(SID_ATTR_CHAR_GRABBAG); + + if (!pOld || static_cast<const SfxGrabBagItem&>(*pOld) != aGrabBagItem) + rSet->Put(aGrabBagItem); + else + bModified = false; + } + } + + bool bMod = false; + + if (m_xTopMarginEdit->get_value_changed_from_saved()) + { + aTopMargin.SetUpper( static_cast<sal_uInt16>(GetCoreValue( *m_xTopMarginEdit, eUnit )) ); + bMod = true; + } + + if (m_xBottomMarginEdit->get_value_changed_from_saved()) + { + aTopMargin.SetLower( static_cast<sal_uInt16>(GetCoreValue( *m_xBottomMarginEdit, eUnit )) ); + bMod = true; + } + + // set top and bottom margins + + if ( bMod ) + { + pOld = GetOldItem( *rSet, SID_ATTR_ULSPACE ); + + if ( !pOld || *static_cast<const SvxULSpaceItem*>(pOld) != aTopMargin ) + { + bModified = true; + rSet->Put( aTopMargin ); + } + } + + // paper tray + nWhich = GetWhich( SID_ATTR_PAGE_PAPERBIN ); + sal_Int32 nPos = m_xPaperTrayBox->get_active(); + sal_uInt16 nBin = m_xPaperTrayBox->get_id(nPos).toInt32(); + pOld = GetOldItem( *rSet, SID_ATTR_PAGE_PAPERBIN ); + + if ( !pOld || static_cast<const SvxPaperBinItem*>(pOld)->GetValue() != nBin ) + { + rSet->Put( SvxPaperBinItem( nWhich, static_cast<sal_uInt8>(nBin) ) ); + bModified = true; + } + + Paper ePaper = m_xPaperSizeBox->get_active_id(); + bool bChecked = m_xLandscapeBtn->get_active(); + + if ( PAPER_USER == ePaper ) + { + if ( m_xPaperSizeBox->get_value_changed_from_saved() || + m_xPaperWidthEdit->get_value_changed_from_saved() || + m_xPaperHeightEdit->get_value_changed_from_saved() || + m_xLandscapeBtn->get_state_changed_from_saved() ) + { + Size aSize( GetCoreValue( *m_xPaperWidthEdit, eUnit ), + GetCoreValue( *m_xPaperHeightEdit, eUnit ) ); + pOld = GetOldItem( *rSet, SID_ATTR_PAGE_SIZE ); + + if ( !pOld || static_cast<const SvxSizeItem*>(pOld)->GetSize() != aSize ) + { + rSet->Put( SvxSizeItem( GetWhich(SID_ATTR_PAGE_SIZE), aSize ) ); + bModified = true; + } + } + } + else + { + if (m_xPaperSizeBox->get_value_changed_from_saved() || m_xLandscapeBtn->get_state_changed_from_saved()) + { + Size aSize( SvxPaperInfo::GetPaperSize( ePaper, eUnit ) ); + + if ( bChecked ) + Swap( aSize ); + + pOld = GetOldItem( *rSet, SID_ATTR_PAGE_SIZE ); + + if ( !pOld || static_cast<const SvxSizeItem*>(pOld)->GetSize() != aSize ) + { + rSet->Put( SvxSizeItem( GetWhich(SID_ATTR_PAGE_SIZE), aSize ) ); + bModified = true; + } + } + } + + nWhich = GetWhich( SID_ATTR_PAGE ); + SvxPageItem aPage( static_cast<const SvxPageItem&>(rOldSet.Get( nWhich )) ); + bMod = m_xLayoutBox->get_value_changed_from_saved(); + + if ( bMod ) + aPage.SetPageUsage(::PosToPageUsage_Impl(m_xLayoutBox->get_active())); + + if (m_xLandscapeBtn->get_state_changed_from_saved()) + { + aPage.SetLandscape(bChecked); + bMod = true; + } + + //Get the NumType value + if (m_xNumberFormatBox->get_value_changed_from_saved()) + { + SvxNumType nEntryData = m_xNumberFormatBox->get_active_id(); + aPage.SetNumType( nEntryData ); + bMod = true; + } + + if ( bMod ) + { + pOld = GetOldItem( *rSet, SID_ATTR_PAGE ); + + if ( !pOld || *static_cast<const SvxPageItem*>(pOld) != aPage ) + { + rSet->Put( aPage ); + bModified = true; + } + } + else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich ) ) + rSet->ClearItem( nWhich ); + else + rSet->Put( rOldSet.Get( nWhich ) ); + + // evaluate mode specific controls + + switch ( eMode ) + { + case SVX_PAGE_MODE_CENTER: + { + if (m_xHorzBox->get_state_changed_from_saved()) + { + SfxBoolItem aHorz( GetWhich( SID_ATTR_PAGE_EXT1 ), + m_xHorzBox->get_active() ); + rSet->Put( aHorz ); + bModified = true; + } + + if (m_xVertBox->get_state_changed_from_saved()) + { + SfxBoolItem aVert( GetWhich( SID_ATTR_PAGE_EXT2 ), + m_xVertBox->get_active() ); + rSet->Put( aVert ); + bModified = true; + } + break; + } + + case SVX_PAGE_MODE_PRESENTATION: + { + // always put so that draw can evaluate this + rSet->Put( SfxBoolItem( GetWhich( SID_ATTR_PAGE_EXT1 ), + m_xAdaptBox->get_active() ) ); + bModified = true; + break; + } + default: ;//prevent warning + + } + + if (m_xRegisterCB->get_visible() && + (m_xRegisterCB->get_active() || m_xRegisterCB->get_state_changed_from_saved())) + { + const SfxBoolItem& rRegItem = rOldSet.Get(SID_SWREGISTER_MODE); + std::unique_ptr<SfxBoolItem> pRegItem(rRegItem.Clone()); + bool bCheck = m_xRegisterCB->get_active(); + pRegItem->SetValue(bCheck); + rSet->Put(std::move(pRegItem)); + bModified = true; + if(bCheck) + { + bModified = true; + rSet->Put(SfxStringItem(SID_SWREGISTER_COLLECTION, + m_xRegisterLB->get_active_text())); + } + } + + if (m_xTextFlowBox->get_visible() && m_xTextFlowBox->get_value_changed_from_saved()) + { + SvxFrameDirection eDirection = m_xTextFlowBox->get_active_id(); + rSet->Put( SvxFrameDirectionItem( eDirection, GetWhich( SID_ATTR_FRAMEDIRECTION ) ) ); + bModified = true; + } + + return bModified; +} + +IMPL_LINK_NOARG(SvxPageDescPage, LayoutHdl_Impl, weld::ComboBox&, void) +{ + // switch inside outside + const SvxPageUsage nUsage = PosToPageUsage_Impl(m_xLayoutBox->get_active()); + + if (nUsage == SvxPageUsage::Mirror) + { + m_xLeftMarginLbl->hide(); + m_xRightMarginLbl->hide(); + m_xInsideLbl->show(); + m_xOutsideLbl->show(); + } + else + { + m_xLeftMarginLbl->show(); + m_xRightMarginLbl->show(); + m_xInsideLbl->hide(); + m_xOutsideLbl->hide(); + } + UpdateExample_Impl( true ); +} + +IMPL_LINK_NOARG(SvxPageDescPage, GutterPositionHdl_Impl, weld::ComboBox&, void) +{ + UpdateExample_Impl(true); +} + +IMPL_LINK_NOARG(SvxPageDescPage, PaperBinHdl_Impl, weld::Widget&, void) +{ + // tdf#124226 disconnect so not called again, unless Reset occurs + m_xPaperTrayBox->connect_focus_in(Link<weld::Widget&, void>()); + + OUString aOldName = m_xPaperTrayBox->get_active_text(); + m_xPaperTrayBox->freeze(); + m_xPaperTrayBox->clear(); + m_xPaperTrayBox->append(OUString::number(PAPERBIN_PRINTER_SETTINGS), EditResId(RID_SVXSTR_PAPERBIN_SETTINGS)); + OUString aPaperBin(EditResId(RID_SVXSTR_PAPERBIN)); + const sal_uInt16 nBinCount = mpDefPrinter->GetPaperBinCount(); + + for (sal_uInt16 i = 0; i < nBinCount; ++i) + { + OUString aName = mpDefPrinter->GetPaperBinName(i); + if (aName.isEmpty()) + { + aName = aPaperBin + " " + OUString::number( i+1 ); + } + m_xPaperTrayBox->append(OUString::number(i), aName); + } + m_xPaperTrayBox->set_active_text(aOldName); + m_xPaperTrayBox->thaw(); + + // tdf#123650 explicitly grab-focus after the modification otherwise gtk loses track + // of there the focus should be + m_xPaperTrayBox->grab_focus(); +} + +IMPL_LINK_NOARG(SvxPageDescPage, PaperSizeSelect_Impl, weld::ComboBox&, void) +{ + Paper ePaper = m_xPaperSizeBox->get_active_id(); + + if ( ePaper == PAPER_USER ) + return; + + Size aSize( SvxPaperInfo::GetPaperSize( ePaper, MapUnit::Map100thMM ) ); + + if (m_xLandscapeBtn->get_active()) + Swap( aSize ); + + if ( aSize.Height() < m_xPaperHeightEdit->get_min( FieldUnit::MM_100TH ) ) + m_xPaperHeightEdit->set_min( + m_xPaperHeightEdit->normalize( aSize.Height() ), FieldUnit::MM_100TH ); + if ( aSize.Width() < m_xPaperWidthEdit->get_min( FieldUnit::MM_100TH ) ) + m_xPaperWidthEdit->set_min( + m_xPaperWidthEdit->normalize( aSize.Width() ), FieldUnit::MM_100TH ); + SetMetricValue( *m_xPaperHeightEdit, aSize.Height(), MapUnit::Map100thMM ); + SetMetricValue( *m_xPaperWidthEdit, aSize.Width(), MapUnit::Map100thMM ); + + CalcMargin_Impl(); + + RangeHdl_Impl(); + UpdateExample_Impl( true ); + + if ( eMode != SVX_PAGE_MODE_PRESENTATION ) + return; + + // Draw: if paper format the margin shall be 1 cm + tools::Long nTmp = 0; + bool bScreen = (( PAPER_SCREEN_4_3 == ePaper )||( PAPER_SCREEN_16_9 == ePaper)||( PAPER_SCREEN_16_10 == ePaper)||( PAPER_WIDESCREEN == ePaper)||( PAPER_ONSCREENSHOW_4_3 == ePaper)||( PAPER_ONSCREENSHOW_16_9 == ePaper)||( PAPER_ONSCREENSHOW_16_10 == ePaper)); + + if ( !bScreen ) + // no margin if screen + nTmp = 1; // accordingly 1 cm + + if ( bScreen || m_xRightMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xRightMarginEdit, nTmp, MapUnit::MapCM ); + if ( bScreen || m_xLeftMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xLeftMarginEdit, nTmp, MapUnit::MapCM ); + if ( bScreen || m_xBottomMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xBottomMarginEdit, nTmp, MapUnit::MapCM ); + if ( bScreen || m_xTopMarginEdit->get_value(FieldUnit::NONE) == 0 ) + SetMetricValue( *m_xTopMarginEdit, nTmp, MapUnit::MapCM ); + UpdateExample_Impl( true ); +} + +IMPL_LINK_NOARG(SvxPageDescPage, PaperSizeModify_Impl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nWhich = GetWhich( SID_ATTR_LRSPACE ); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( nWhich ); + Size aSize( GetCoreValue( *m_xPaperWidthEdit, eUnit ), + GetCoreValue( *m_xPaperHeightEdit, eUnit ) ); + + if ( aSize.Width() > aSize.Height() ) + { + m_xLandscapeBtn->set_active(true); + bLandscape = true; + } + else + { + m_xPortraitBtn->set_active(true); + bLandscape = false; + } + + Paper ePaper = SvxPaperInfo::GetSvxPaper( aSize, eUnit ); + m_xPaperSizeBox->set_active_id( ePaper ); + UpdateExample_Impl( true ); + + RangeHdl_Impl(); +} + +IMPL_LINK(SvxPageDescPage, SwapOrientation_Impl, weld::Toggleable&, rBtn, void) +{ + if (!rBtn.get_active()) + return; + + bLandscape = m_xLandscapeBtn->get_active(); + + const tools::Long lWidth = GetCoreValue( *m_xPaperWidthEdit, MapUnit::Map100thMM ); + const tools::Long lHeight = GetCoreValue( *m_xPaperHeightEdit, MapUnit::Map100thMM ); + + // swap width and height + SetMetricValue(*m_xPaperWidthEdit, lHeight, MapUnit::Map100thMM); + SetMetricValue(*m_xPaperHeightEdit, lWidth, MapUnit::Map100thMM); + + // recalculate margins if necessary + CalcMargin_Impl(); + + PaperSizeSelect_Impl(m_xPaperSizeBox->get_widget()); + RangeHdl_Impl(); + SwapFirstValues_Impl(bBorderModified); + UpdateExample_Impl(true); +} + +void SvxPageDescPage::SwapFirstValues_Impl( bool bSet ) +{ + MapMode aOldMode = mpDefPrinter->GetMapMode(); + Orientation eOri = Orientation::Portrait; + + if ( bLandscape ) + eOri = Orientation::Landscape; + Orientation eOldOri = mpDefPrinter->GetOrientation(); + mpDefPrinter->SetOrientation( eOri ); + mpDefPrinter->SetMapMode(MapMode(MapUnit::MapTwip)); + + // set first- and last-values for margins + Size aPaperSize = mpDefPrinter->GetPaperSize(); + Size aPrintSize = mpDefPrinter->GetOutputSize(); + /* + * To convert a point ( 0,0 ) into logic coordinates + * looks like nonsense; but it makes sense if the + * coordinate system's origin has been moved. + */ + Point aPrintOffset = mpDefPrinter->GetPageOffset() - mpDefPrinter->PixelToLogic( Point() ); + mpDefPrinter->SetMapMode( aOldMode ); + mpDefPrinter->SetOrientation( eOldOri ); + + sal_Int64 nSetL = m_xLeftMarginEdit->denormalize( + m_xLeftMarginEdit->get_value( FieldUnit::TWIP ) ); + sal_Int64 nSetR = m_xRightMarginEdit->denormalize( + m_xRightMarginEdit->get_value( FieldUnit::TWIP ) ); + sal_Int64 nSetT = m_xTopMarginEdit->denormalize( + m_xTopMarginEdit->get_value( FieldUnit::TWIP ) ); + sal_Int64 nSetB = m_xBottomMarginEdit->denormalize( + m_xBottomMarginEdit->get_value( FieldUnit::TWIP ) ); + + tools::Long nNewL = aPrintOffset.X(); + tools::Long nNewR = aPaperSize.Width() - aPrintSize.Width() - aPrintOffset.X(); + tools::Long nNewT = aPrintOffset.Y(); + tools::Long nNewB = aPaperSize.Height() - aPrintSize.Height() - aPrintOffset.Y(); + + nFirstLeftMargin = m_xLeftMarginEdit->convert_value_from(m_xLeftMarginEdit->normalize(nNewL), FieldUnit::TWIP); + nFirstRightMargin = m_xRightMarginEdit->convert_value_from(m_xRightMarginEdit->normalize(nNewR), FieldUnit::TWIP); + nFirstTopMargin = m_xTopMarginEdit->convert_value_from(m_xTopMarginEdit->normalize(nNewT), FieldUnit::TWIP); + nFirstBottomMargin = m_xBottomMarginEdit->convert_value_from(m_xBottomMarginEdit->normalize(nNewB), FieldUnit::TWIP); + + if ( !bSet ) + return; + + if ( nSetL < nNewL ) + m_xLeftMarginEdit->set_value( m_xLeftMarginEdit->normalize( nNewL ), + FieldUnit::TWIP ); + if ( nSetR < nNewR ) + m_xRightMarginEdit->set_value( m_xRightMarginEdit->normalize( nNewR ), + FieldUnit::TWIP ); + if ( nSetT < nNewT ) + m_xTopMarginEdit->set_value( m_xTopMarginEdit->normalize( nNewT ), + FieldUnit::TWIP ); + if ( nSetB < nNewB ) + m_xBottomMarginEdit->set_value( m_xBottomMarginEdit->normalize( nNewB ), + FieldUnit::TWIP ); +} + +IMPL_LINK_NOARG(SvxPageDescPage, BorderModify_Impl, weld::MetricSpinButton&, void) +{ + if ( !bBorderModified ) + bBorderModified = true; + UpdateExample_Impl(); + + RangeHdl_Impl(); +} + +void SvxPageDescPage::UpdateExample_Impl( bool bResetbackground ) +{ + // Size + Size aSize( GetCoreValue( *m_xPaperWidthEdit, MapUnit::MapTwip ), + GetCoreValue( *m_xPaperHeightEdit, MapUnit::MapTwip ) ); + + m_aBspWin.SetSize( aSize ); + + // Margins + bool bGutterAtTop = m_xGutterPositionLB->get_active() == 1; + tools::Long nTop = GetCoreValue(*m_xTopMarginEdit, MapUnit::MapTwip); + if (bGutterAtTop) + { + nTop += GetCoreValue(*m_xGutterMarginEdit, MapUnit::MapTwip); + } + m_aBspWin.SetTop(nTop); + m_aBspWin.SetBottom( GetCoreValue( *m_xBottomMarginEdit, MapUnit::MapTwip ) ); + tools::Long nLeft = GetCoreValue(*m_xLeftMarginEdit, MapUnit::MapTwip); + if (!bGutterAtTop) + { + nLeft += GetCoreValue(*m_xGutterMarginEdit, MapUnit::MapTwip); + } + m_aBspWin.SetLeft(nLeft); + m_aBspWin.SetRight( GetCoreValue( *m_xRightMarginEdit, MapUnit::MapTwip ) ); + + // Layout + m_aBspWin.SetUsage(PosToPageUsage_Impl(m_xLayoutBox->get_active())); + if ( bResetbackground ) + m_aBspWin.ResetBackground(); + m_aBspWin.Invalidate(); +} + + +void SvxPageDescPage::ResetBackground_Impl(const SfxItemSet& rSet) +{ + sal_uInt16 nWhich(GetWhich(SID_ATTR_PAGE_HEADERSET)); + + if (SfxItemState::SET == rSet.GetItemState(nWhich, false)) + { + const SvxSetItem& rSetItem = static_cast< const SvxSetItem& >(rSet.Get(nWhich, false)); + const SfxItemSet& rTmpSet = rSetItem.GetItemSet(); + const SfxBoolItem& rOn = rTmpSet.Get(GetWhich(SID_ATTR_PAGE_ON)); + + if(rOn.GetValue()) + { + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aHeaderFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aHeaderFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(rTmpSet); + } + else + { + nWhich = GetWhich(SID_ATTR_BRUSH); + + if(SfxItemState::SET == rTmpSet.GetItemState(nWhich)) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rTmpSet.Get(nWhich)); + SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rTmpSet.GetPool()); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aHeaderFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(aTempSet); + } + } + + m_aBspWin.setHeaderFillAttributes(aHeaderFillAttributes); + } + } + + nWhich = GetWhich(SID_ATTR_PAGE_FOOTERSET); + + if (SfxItemState::SET == rSet.GetItemState(nWhich, false)) + { + const SvxSetItem& rSetItem = static_cast< const SvxSetItem& >(rSet.Get(nWhich,false)); + const SfxItemSet& rTmpSet = rSetItem.GetItemSet(); + const SfxBoolItem& rOn = rTmpSet.Get(GetWhich(SID_ATTR_PAGE_ON)); + + if(rOn.GetValue()) + { + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFooterFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aFooterFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(rTmpSet); + } + else + { + nWhich = GetWhich(SID_ATTR_BRUSH); + + if(SfxItemState::SET == rTmpSet.GetItemState(nWhich)) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rTmpSet.Get(nWhich)); + SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rTmpSet.GetPool()); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aFooterFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(aTempSet); + } + } + + m_aBspWin.setFooterFillAttributes(aFooterFillAttributes); + } + } + + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aPageFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aPageFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(rSet); + } + else + { + const SfxPoolItem* pItem = GetItem(rSet, SID_ATTR_BRUSH); + + if(pItem) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(*pItem); + SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rSet.GetPool()); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aPageFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(aTempSet); + } + } + + m_aBspWin.setPageFillAttributes(aPageFillAttributes); +} + +void SvxPageDescPage::InitHeadFoot_Impl( const SfxItemSet& rSet ) +{ + bLandscape = m_xLandscapeBtn->get_active(); + const SfxPoolItem* pItem = GetItem( rSet, SID_ATTR_PAGE_SIZE ); + + if ( pItem ) + m_aBspWin.SetSize( static_cast<const SvxSizeItem*>(pItem)->GetSize() ); + + const SvxSetItem* pSetItem = nullptr; + + // evaluate header attributes + + if ( SfxItemState::SET == + rSet.GetItemState( GetWhich( SID_ATTR_PAGE_HEADERSET ), + false, reinterpret_cast<const SfxPoolItem**>(&pSetItem) ) ) + { + const SfxItemSet& rHeaderSet = pSetItem->GetItemSet(); + const SfxBoolItem& rHeaderOn = + rHeaderSet.Get( GetWhich( SID_ATTR_PAGE_ON ) ); + + if ( rHeaderOn.GetValue() ) + { + const SvxSizeItem& rSize = + rHeaderSet.Get( GetWhich( SID_ATTR_PAGE_SIZE ) ); + const SvxULSpaceItem& rUL = static_cast<const SvxULSpaceItem&>( + rHeaderSet.Get( GetWhich( SID_ATTR_ULSPACE ) )); + tools::Long nDist = rUL.GetLower(); + m_aBspWin.SetHdHeight( rSize.GetSize().Height() - nDist ); + m_aBspWin.SetHdDist( nDist ); + const SvxLRSpaceItem& rLR = static_cast<const SvxLRSpaceItem&>( + rHeaderSet.Get( GetWhich( SID_ATTR_LRSPACE ) )); + m_aBspWin.SetHdLeft( rLR.GetLeft() ); + m_aBspWin.SetHdRight( rLR.GetRight() ); + m_aBspWin.SetHeader( true ); + } + else + m_aBspWin.SetHeader( false ); + + // show background and border in the example + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aHeaderFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aHeaderFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(rHeaderSet); + } + else + { + const sal_uInt16 nWhich(GetWhich(SID_ATTR_BRUSH)); + + if(rHeaderSet.GetItemState(nWhich) >= SfxItemState::DEFAULT) + { + // aBspWin.SetHdColor(rItem.GetColor()); + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(rHeaderSet.Get(nWhich)); + SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rHeaderSet.GetPool()); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aHeaderFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(aTempSet); + } + } + + m_aBspWin.setHeaderFillAttributes(aHeaderFillAttributes); + } + + // evaluate footer attributes + + if ( SfxItemState::SET != + rSet.GetItemState( GetWhich( SID_ATTR_PAGE_FOOTERSET ), + false, reinterpret_cast<const SfxPoolItem**>(&pSetItem) ) ) + return; + + const SfxItemSet& rFooterSet = pSetItem->GetItemSet(); + const SfxBoolItem& rFooterOn = + rFooterSet.Get( GetWhich( SID_ATTR_PAGE_ON ) ); + + if ( rFooterOn.GetValue() ) + { + const SvxSizeItem& rSize = + rFooterSet.Get( GetWhich( SID_ATTR_PAGE_SIZE ) ); + const SvxULSpaceItem& rUL = static_cast<const SvxULSpaceItem&>( + rFooterSet.Get( GetWhich( SID_ATTR_ULSPACE ) )); + tools::Long nDist = rUL.GetUpper(); + m_aBspWin.SetFtHeight( rSize.GetSize().Height() - nDist ); + m_aBspWin.SetFtDist( nDist ); + const SvxLRSpaceItem& rLR = static_cast<const SvxLRSpaceItem&>( + rFooterSet.Get( GetWhich( SID_ATTR_LRSPACE ) )); + m_aBspWin.SetFtLeft( rLR.GetLeft() ); + m_aBspWin.SetFtRight( rLR.GetRight() ); + m_aBspWin.SetFooter( true ); + } + else + m_aBspWin.SetFooter( false ); + + // show background and border in the example + drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFooterFillAttributes; + + if(mbEnableDrawingLayerFillStyles) + { + // create FillAttributes directly from DrawingLayer FillStyle entries + aFooterFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(rFooterSet); + } + else + { + const sal_uInt16 nWhich(GetWhich(SID_ATTR_BRUSH)); + + if(rFooterSet.GetItemState(nWhich) >= SfxItemState::DEFAULT) + { + // aBspWin.SetFtColor(rItem.GetColor()); + const SvxBrushItem& rItem = static_cast<const SvxBrushItem&>(rFooterSet.Get(nWhich)); + SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aTempSet(*rFooterSet.GetPool()); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + aFooterFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(aTempSet); + } + } + + m_aBspWin.setFooterFillAttributes(aFooterFillAttributes); +} + +void SvxPageDescPage::ActivatePage( const SfxItemSet& rSet ) +{ + InitHeadFoot_Impl( rSet ); + UpdateExample_Impl(); + ResetBackground_Impl( rSet ); + RangeHdl_Impl(); +} + +DeactivateRC SvxPageDescPage::DeactivatePage( SfxItemSet* _pSet ) +{ + // Inquiry whether the page margins are beyond the printing area. + // If not, ask user whether they shall be taken. + // If not, stay on the TabPage. + Paper ePaper = m_xPaperSizeBox->get_active_id(); + + if ( ePaper != PAPER_SCREEN_4_3 && ePaper != PAPER_SCREEN_16_9 && ePaper != PAPER_SCREEN_16_10 && ePaper != PAPER_WIDESCREEN && ePaper != PAPER_ONSCREENSHOW_4_3 && ePaper != PAPER_ONSCREENSHOW_16_9 && ePaper != PAPER_ONSCREENSHOW_16_10 && IsMarginOutOfRange() ) + { + std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + m_xPrintRangeQueryText->get_label())); + xQueryBox->set_default_response(RET_NO); + if (xQueryBox->run() == RET_NO) + { + weld::MetricSpinButton* pField = nullptr; + if ( IsPrinterRangeOverflow( *m_xLeftMarginEdit, nFirstLeftMargin, nLastLeftMargin, MARGIN_LEFT ) ) + pField = m_xLeftMarginEdit.get(); + if ( IsPrinterRangeOverflow( *m_xRightMarginEdit, nFirstRightMargin, nLastRightMargin, MARGIN_RIGHT ) + && !pField ) + pField = m_xRightMarginEdit.get(); + if ( IsPrinterRangeOverflow( *m_xTopMarginEdit, nFirstTopMargin, nLastTopMargin, MARGIN_TOP ) + && !pField ) + pField = m_xTopMarginEdit.get(); + if ( IsPrinterRangeOverflow( *m_xBottomMarginEdit, nFirstBottomMargin, nLastBottomMargin, MARGIN_BOTTOM ) + && !pField ) + pField = m_xBottomMarginEdit.get(); + if ( pField ) + pField->grab_focus(); + UpdateExample_Impl(); + return DeactivateRC::KeepPage; + } + else + CheckMarginEdits( false ); + } + + if ( _pSet ) + { + FillItemSet( _pSet ); + + // put portray/landscape if applicable + sal_uInt16 nWh = GetWhich( SID_ATTR_PAGE_SIZE ); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( nWh ); + Size aSize( GetCoreValue( *m_xPaperWidthEdit, eUnit ), + GetCoreValue( *m_xPaperHeightEdit, eUnit ) ); + + // put, if current size is different to the value in _pSet + const SvxSizeItem* pSize = GetItem( *_pSet, SID_ATTR_PAGE_SIZE ); + if ( aSize.Width() && ( !pSize || !IsEqualSize_Impl( pSize, aSize ) ) ) + _pSet->Put( SvxSizeItem( nWh, aSize ) ); + } + + return DeactivateRC::LeavePage; +} + +void SvxPageDescPage::RangeHdl_Impl() +{ + // example window + tools::Long nHHeight = m_aBspWin.GetHdHeight(); + tools::Long nHDist = m_aBspWin.GetHdDist(); + + tools::Long nFHeight = m_aBspWin.GetFtHeight(); + tools::Long nFDist = m_aBspWin.GetFtDist(); + + tools::Long nHFLeft = std::max(m_aBspWin.GetHdLeft(), m_aBspWin.GetFtLeft()); + tools::Long nHFRight = std::max(m_aBspWin.GetHdRight(), m_aBspWin.GetFtRight()); + + // current values for page margins + tools::Long nBT = static_cast<tools::Long>(m_xTopMarginEdit->denormalize(m_xTopMarginEdit->get_value(FieldUnit::TWIP))); + tools::Long nBB = static_cast<tools::Long>(m_xBottomMarginEdit->denormalize(m_xBottomMarginEdit->get_value(FieldUnit::TWIP))); + tools::Long nBL = static_cast<tools::Long>(m_xLeftMarginEdit->denormalize(m_xLeftMarginEdit->get_value(FieldUnit::TWIP))); + tools::Long nBR = static_cast<tools::Long>(m_xRightMarginEdit->denormalize(m_xRightMarginEdit->get_value(FieldUnit::TWIP))); + + // calculate width of page border + const SfxItemSet* _pSet = &GetItemSet(); + Size aBorder; + + if ( _pSet->GetItemState( GetWhich(SID_ATTR_BORDER_SHADOW) ) >= + SfxItemState::DEFAULT && + _pSet->GetItemState( GetWhich(SID_ATTR_BORDER_OUTER) ) >= + SfxItemState::DEFAULT ) + { + aBorder = GetMinBorderSpace_Impl( + static_cast<const SvxShadowItem&>(_pSet->Get(GetWhich(SID_ATTR_BORDER_SHADOW))), + static_cast<const SvxBoxItem&>(_pSet->Get(GetWhich(SID_ATTR_BORDER_OUTER)))); + } + + // limits paper + // maximum is 54 cm + + tools::Long nMin = nHHeight + nHDist + nFDist + nFHeight + nBT + nBB + + MINBODY + aBorder.Height(); + m_xPaperHeightEdit->set_min(m_xPaperHeightEdit->normalize(nMin), FieldUnit::TWIP); + + nMin = MINBODY + nBL + nBR + aBorder.Width(); + m_xPaperWidthEdit->set_min(m_xPaperWidthEdit->normalize(nMin), FieldUnit::TWIP); + + tools::Long nH = static_cast<tools::Long>(m_xPaperHeightEdit->denormalize(m_xPaperHeightEdit->get_value(FieldUnit::TWIP))); + tools::Long nW = static_cast<tools::Long>(m_xPaperWidthEdit->denormalize(m_xPaperWidthEdit->get_value(FieldUnit::TWIP))); + + // Top + tools::Long nMax = nH - nBB - aBorder.Height() - MINBODY - + nFDist - nFHeight - nHDist - nHHeight; + + m_xTopMarginEdit->set_max(m_xTopMarginEdit->normalize(nMax), FieldUnit::TWIP); + + // Bottom + nMax = nH - nBT - aBorder.Height() - MINBODY - + nFDist - nFHeight - nHDist - nHHeight; + + m_xBottomMarginEdit->set_max(m_xTopMarginEdit->normalize(nMax), FieldUnit::TWIP); + + // Left + nMax = nW - nBR - MINBODY - aBorder.Width() - nHFLeft - nHFRight; + m_xLeftMarginEdit->set_max(m_xLeftMarginEdit->normalize(nMax), FieldUnit::TWIP); + + // Right + nMax = nW - nBL - MINBODY - aBorder.Width() - nHFLeft - nHFRight; + m_xRightMarginEdit->set_max(m_xRightMarginEdit->normalize(nMax), FieldUnit::TWIP); +} + +void SvxPageDescPage::CalcMargin_Impl() +{ + // current values for page margins + tools::Long nBT = GetCoreValue( *m_xTopMarginEdit, MapUnit::MapTwip ); + tools::Long nBB = GetCoreValue( *m_xBottomMarginEdit, MapUnit::MapTwip ); + + tools::Long nBL = GetCoreValue( *m_xLeftMarginEdit, MapUnit::MapTwip ); + tools::Long nBR = GetCoreValue( *m_xRightMarginEdit, MapUnit::MapTwip ); + + tools::Long nH = GetCoreValue( *m_xPaperHeightEdit, MapUnit::MapTwip ); + tools::Long nW = GetCoreValue( *m_xPaperWidthEdit, MapUnit::MapTwip ); + + tools::Long nWidth = nBL + nBR + MINBODY; + tools::Long nHeight = nBT + nBB + MINBODY; + + if ( nWidth <= nW && nHeight <= nH ) + return; + + if ( nWidth > nW ) + { + tools::Long nTmp = nBL <= nBR ? nBR : nBL; + nTmp -= nWidth - nW; + + if ( nBL <= nBR ) + SetMetricValue( *m_xRightMarginEdit, nTmp, MapUnit::MapTwip ); + else + SetMetricValue( *m_xLeftMarginEdit, nTmp, MapUnit::MapTwip ); + } + + if ( nHeight > nH ) + { + tools::Long nTmp = nBT <= nBB ? nBB : nBT; + nTmp -= nHeight - nH; + + if ( nBT <= nBB ) + SetMetricValue( *m_xBottomMarginEdit, nTmp, MapUnit::MapTwip ); + else + SetMetricValue( *m_xTopMarginEdit, nTmp, MapUnit::MapTwip ); + } +} + +IMPL_LINK_NOARG(SvxPageDescPage, CenterHdl_Impl, weld::Toggleable&, void) +{ + m_aBspWin.SetHorz(m_xHorzBox->get_active()); + m_aBspWin.SetVert(m_xVertBox->get_active()); + UpdateExample_Impl(); +} + +void SvxPageDescPage::SetCollectionList(const std::vector<OUString> &aList) +{ + OSL_ENSURE(!aList.empty(), "Empty string list"); + + sStandardRegister = aList[0]; + m_xRegisterLB->freeze(); + for (size_t i = 1; i < aList.size(); ++i) + m_xRegisterLB->append_text(aList[i]); + m_xRegisterLB->thaw(); + + m_xRegisterCB->show(); + m_xRegisterFT->show(); + m_xRegisterLB->show(); + m_xRegisterCB->connect_toggled(LINK(this, SvxPageDescPage, RegisterModify)); +} + +IMPL_LINK(SvxPageDescPage, RegisterModify, weld::Toggleable&, rBox, void) +{ + bool bEnable = false; + if (rBox.get_active()) + { + bEnable = true; + if (m_xRegisterLB->get_active() == -1) + m_xRegisterLB->set_active_text(sStandardRegister); + } + m_xRegisterFT->set_sensitive(bEnable); + m_xRegisterLB->set_sensitive(bEnable); +} + +void SvxPageDescPage::DisableVerticalPageDir() +{ + m_xTextFlowBox->remove_id(SvxFrameDirection::Vertical_RL_TB); + m_xTextFlowBox->remove_id(SvxFrameDirection::Vertical_LR_TB); + if (m_xTextFlowBox->get_count() < 2) + { + m_xTextFlowLbl->hide(); + m_xTextFlowBox->hide(); + m_aBspWin.EnableFrameDirection( false ); + } +} + +IMPL_LINK_NOARG(SvxPageDescPage, FrameDirectionModify_Impl, weld::ComboBox&, void) +{ + m_aBspWin.SetFrameDirection(m_xTextFlowBox->get_active_id()); + m_aBspWin.Invalidate(); +} + +bool SvxPageDescPage::IsPrinterRangeOverflow( + weld::MetricSpinButton& rField, tools::Long nFirstMargin, tools::Long nLastMargin, MarginPosition nPos ) +{ + bool bRet = false; + bool bCheck = ( ( m_nPos & nPos ) == 0 ); + tools::Long nValue = rField.get_value(FieldUnit::NONE); + if ( bCheck && + ( nValue < nFirstMargin || nValue > nLastMargin ) && + rField.get_value_changed_from_saved() ) + { + rField.set_value(nValue < nFirstMargin ? nFirstMargin : nLastMargin, FieldUnit::NONE); + bRet = true; + } + + return bRet; +} + +/** Check if a value of a margin edit is outside the printer paper margins + and save this information. +*/ +void SvxPageDescPage::CheckMarginEdits( bool _bClear ) +{ + if ( _bClear ) + m_nPos = 0; + + sal_Int64 nValue = m_xLeftMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstLeftMargin || nValue > nLastLeftMargin ) + m_nPos |= MARGIN_LEFT; + nValue = m_xRightMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstRightMargin || nValue > nLastRightMargin ) + m_nPos |= MARGIN_RIGHT; + nValue = m_xTopMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstTopMargin || nValue > nLastTopMargin ) + m_nPos |= MARGIN_TOP; + nValue = m_xBottomMarginEdit->get_value(FieldUnit::NONE); + if ( nValue < nFirstBottomMargin || nValue > nLastBottomMargin ) + m_nPos |= MARGIN_BOTTOM; +} + +bool SvxPageDescPage::IsMarginOutOfRange() const +{ + bool bRet = ( ( ( !( m_nPos & MARGIN_LEFT ) && + m_xLeftMarginEdit->get_value_changed_from_saved() ) && + ( m_xLeftMarginEdit->get_value(FieldUnit::NONE) < nFirstLeftMargin || + m_xLeftMarginEdit->get_value(FieldUnit::NONE) > nLastLeftMargin ) ) || + ( ( !( m_nPos & MARGIN_RIGHT ) && + m_xRightMarginEdit->get_value_changed_from_saved() ) && + ( m_xRightMarginEdit->get_value(FieldUnit::NONE) < nFirstRightMargin || + m_xRightMarginEdit->get_value(FieldUnit::NONE) > nLastRightMargin ) ) || + ( ( !( m_nPos & MARGIN_TOP ) && + m_xTopMarginEdit->get_value_changed_from_saved() ) && + ( m_xTopMarginEdit->get_value(FieldUnit::NONE) < nFirstTopMargin || + m_xTopMarginEdit->get_value(FieldUnit::NONE) > nLastTopMargin ) ) || + ( ( !( m_nPos & MARGIN_BOTTOM ) && + m_xBottomMarginEdit->get_value_changed_from_saved() ) && + ( m_xBottomMarginEdit->get_value(FieldUnit::NONE) < nFirstBottomMargin || + m_xBottomMarginEdit->get_value(FieldUnit::NONE) > nLastBottomMargin ) ) ); + return bRet; +} + +void SvxPageDescPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pModeItem = aSet.GetItem(SID_ENUM_PAGE_MODE, false); + const SfxUInt16Item* pPaperStartItem = aSet.GetItem(SID_PAPER_START, false); + const SfxUInt16Item* pPaperEndItem = aSet.GetItem(SID_PAPER_END, false); + const SfxStringListItem* pCollectListItem = aSet.GetItem<SfxStringListItem>(SID_COLLECT_LIST, false); + const SfxBoolItem* pSupportDrawingLayerFillStyleItem = aSet.GetItem<SfxBoolItem>(SID_DRAWINGLAYER_FILLSTYLES, false); + const SfxBoolItem* pIsImpressDoc = aSet.GetItem<SfxBoolItem>(SID_IMPRESS_DOC, false); + + if (pModeItem) + { + eMode = static_cast<SvxModeType>(pModeItem->GetValue()); + } + + if(pPaperStartItem && pPaperEndItem) + { + SetPaperFormatRanges(static_cast<Paper>(pPaperStartItem->GetValue())); + } + + if(pCollectListItem) + { + SetCollectionList(pCollectListItem->GetList()); + } + + if(pSupportDrawingLayerFillStyleItem) + { + const bool bNew(pSupportDrawingLayerFillStyleItem->GetValue()); + + mbEnableDrawingLayerFillStyles = bNew; + } + + if (pIsImpressDoc) + m_xNumberFormatText->set_label(SvxResId(STR_SLIDE_NUMBERS)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx new file mode 100644 index 000000000..b2cd167a5 --- /dev/null +++ b/cui/source/tabpages/paragrph.cxx @@ -0,0 +1,2330 @@ +/* -*- 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 . + */ + +#include <memory> +#include <osl/diagnose.h> +#include <svl/style.hxx> +#include <sfx2/objsh.hxx> +#include <vcl/mnemonic.hxx> +#include <vcl/settings.hxx> +#include <svx/flagsdef.hxx> +#include <svx/svxids.hrc> + +#include <svl/cjkoptions.hxx> +#include <editeng/pgrditem.hxx> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <paragrph.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/lspcitem.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/orphitem.hxx> +#include <editeng/widwitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/pmdlitem.hxx> +#include <editeng/spltitem.hxx> +#include <editeng/hyphenzoneitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/formatbreakitem.hxx> +#include <editeng/keepitem.hxx> +#include <svx/dlgutil.hxx> +#include <sfx2/htmlmode.hxx> +#include <editeng/paravertalignitem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> + +const WhichRangesContainer SvxStdParagraphTabPage::pStdRanges( + svl::Items< + SID_ATTR_PARA_LINESPACE, SID_ATTR_PARA_LINESPACE, // 10033 + SID_ATTR_LRSPACE, SID_ATTR_ULSPACE, // 10048 - 10049 + SID_ATTR_PARA_REGISTER, SID_ATTR_PARA_REGISTER // 10413 + >); + +const WhichRangesContainer SvxParaAlignTabPage::pAlignRanges( + svl::Items<SID_ATTR_PARA_ADJUST, SID_ATTR_PARA_ADJUST>); // 10027 + +const WhichRangesContainer SvxExtParagraphTabPage::pExtRanges(svl::Items< + SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_WIDOWS, // 10037 - 10041 + SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP // 10065 - 10066 +>); + +#define MAX_DURCH 31680 // tdf#68335: 1584 pt for UX interoperability with Word +#define FIX_DIST_DEF 283 // standard fix distance 0,5 cm + +namespace { + +enum LineSpaceList +{ + LLINESPACE_1 = 0, + LLINESPACE_115 = 1, + LLINESPACE_15 = 2, + LLINESPACE_2 = 3, + LLINESPACE_PROP = 4, + LLINESPACE_MIN = 5, + LLINESPACE_DURCH= 6, + LLINESPACE_FIX = 7 +}; + +} + +static void SetLineSpace_Impl( SvxLineSpacingItem&, int, tools::Long lValue = 0 ); + +void SetLineSpace_Impl( SvxLineSpacingItem& rLineSpace, + int eSpace, tools::Long lValue ) +{ + switch ( eSpace ) + { + case LLINESPACE_1: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + + case LLINESPACE_115: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( 115 ); + break; + + case LLINESPACE_15: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( 150 ); + break; + + case LLINESPACE_2: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( 200 ); + break; + + case LLINESPACE_PROP: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetPropLineSpace( static_cast<sal_uInt16>(lValue) ); + break; + + case LLINESPACE_MIN: + rLineSpace.SetLineHeight( static_cast<sal_uInt16>(lValue) ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + + case LLINESPACE_DURCH: + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto ); + rLineSpace.SetInterLineSpace( static_cast<sal_uInt16>(lValue) ); + break; + + case LLINESPACE_FIX: + rLineSpace.SetLineHeight(static_cast<sal_uInt16>(lValue)); + rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Fix ); + rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off ); + break; + } +} + +static sal_uInt16 GetHtmlMode_Impl(const SfxItemSet& rSet) +{ + sal_uInt16 nHtmlMode = 0; + const SfxUInt16Item* pItem = rSet.GetItemIfSet(SID_HTML_MODE, false); + if (!pItem) + { + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + pItem = pShell->GetItem(SID_HTML_MODE); + } + if(pItem) + { + nHtmlMode = pItem->GetValue(); + } + return nHtmlMode; + +} + +void SvxStdParagraphTabPage::ELRLoseFocus() +{ + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = + MapToFieldUnit( pPool->GetMetric( GetWhich( SID_ATTR_LRSPACE ) ) ); + + sal_Int64 nL = m_xLeftIndent->denormalize(m_xLeftIndent->get_value(eUnit)); + sal_Int64 nR = m_xRightIndent->denormalize(m_xRightIndent->get_value(eUnit)); + OUString aTmp = m_xFLineIndent->get_text(); + + if (m_xLeftIndent->get_min(FieldUnit::NONE) < 0) + m_xFLineIndent->set_min(-99999, FieldUnit::MM); + else + m_xFLineIndent->set_min(m_xFLineIndent->normalize(-nL), eUnit); + + // Check only for concrete width (Shell) + sal_Int64 nTmp = nWidth - nL - nR - MM50; + m_xFLineIndent->set_max(m_xFLineIndent->normalize(nTmp), eUnit); + + if (aTmp.isEmpty()) + m_xFLineIndent->set_text(OUString()); + // maximum left right + aTmp = m_xLeftIndent->get_text(); + nTmp = nWidth - nR - MM50; + m_xLeftIndent->set_max(m_xLeftIndent->normalize(nTmp), eUnit); + + if ( aTmp.isEmpty() ) + m_xLeftIndent->set_text(OUString()); + aTmp = m_xRightIndent->get_text(); + nTmp = nWidth - nL - MM50; + m_xRightIndent->set_max(m_xRightIndent->normalize(nTmp), eUnit); + + if ( aTmp.isEmpty() ) + m_xRightIndent->set_text(OUString()); + + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxStdParagraphTabPage, ELRLoseFocusHdl, weld::MetricSpinButton&, void) +{ + ELRLoseFocus(); +} + +std::unique_ptr<SfxTabPage> SvxStdParagraphTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxStdParagraphTabPage>(pPage, pController, *rSet); +} + +bool SvxStdParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) +{ + const SfxPoolItem* pOld = nullptr; + SfxItemPool* pPool = rOutSet->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + bool bModified = false; + sal_uInt16 nWhich; + int nPos = m_xLineDist->get_active(); + + if ( nPos != -1 && + ( m_bLineDistToggled || + m_xLineDist->get_value_changed_from_saved() || + m_xLineDistAtPercentBox->get_value_changed_from_saved() || + m_xLineDistAtMetricBox->get_value_changed_from_saved() ) ) + { + nWhich = GetWhich( SID_ATTR_PARA_LINESPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + SvxLineSpacingItem aSpacing( + static_cast<const SvxLineSpacingItem&>(GetItemSet().Get( nWhich )) ); + + switch ( nPos ) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + SetLineSpace_Impl( aSpacing, nPos ); + break; + + case LLINESPACE_PROP: + SetLineSpace_Impl( aSpacing, nPos, + static_cast<tools::Long>(m_xLineDistAtPercentBox->denormalize( + m_xLineDistAtPercentBox->get_value(FieldUnit::NONE) )) ); + break; + + case LLINESPACE_MIN: + case LLINESPACE_DURCH: + case LLINESPACE_FIX: + SetLineSpace_Impl( aSpacing, nPos, + GetCoreValue( *m_xLineDistAtMetricBox, eUnit ) ); + break; + + default: + OSL_FAIL( "unknown LineDist entry" ); + break; + } + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_LINESPACE ); + + if ( m_bLineDistToggled || + !pOld || !( *static_cast<const SvxLineSpacingItem*>(pOld) == aSpacing ) || + SfxItemState::DONTCARE == GetItemSet().GetItemState( nWhich ) ) + { + rOutSet->Put( aSpacing ); + bModified = true; + } + } + + if ( m_xTopDist->get_value_changed_from_saved() || m_xBottomDist->get_value_changed_from_saved() + || m_xContextualCB->get_state_changed_from_saved()) + { + nWhich = GetWhich( SID_ATTR_ULSPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_ULSPACE ); + SvxULSpaceItem aMargin( nWhich ); + + if ( bRelativeMode ) + { + DBG_ASSERT( GetItemSet().GetParent(), "No ParentSet" ); + + const SvxULSpaceItem& rOldItem = + static_cast<const SvxULSpaceItem&>(GetItemSet().GetParent()->Get( nWhich )); + + if ( m_xTopDist->IsRelative() ) + aMargin.SetUpper( rOldItem.GetUpper(), + static_cast<sal_uInt16>(m_xTopDist->get_value(FieldUnit::NONE)) ); + else + aMargin.SetUpper( static_cast<sal_uInt16>(m_xTopDist->GetCoreValue(eUnit)) ); + + if ( m_xBottomDist->IsRelative() ) + aMargin.SetLower( rOldItem.GetLower(), + static_cast<sal_uInt16>(m_xBottomDist->get_value(FieldUnit::NONE)) ); + else + aMargin.SetLower( static_cast<sal_uInt16>(m_xBottomDist->GetCoreValue(eUnit)) ); + + } + else + { + aMargin.SetUpper(static_cast<sal_uInt16>(m_xTopDist->GetCoreValue(eUnit))); + aMargin.SetLower(static_cast<sal_uInt16>(m_xBottomDist->GetCoreValue(eUnit))); + } + aMargin.SetContextValue(m_xContextualCB->get_active()); + + if ( !pOld || *static_cast<const SvxULSpaceItem*>(pOld) != aMargin || + SfxItemState::DONTCARE == GetItemSet().GetItemState( nWhich ) ) + { + rOutSet->Put( aMargin ); + bModified = true; + } + } + bool bNullTab = false; + + if ( m_xLeftIndent->get_value_changed_from_saved() || + m_xFLineIndent->get_value_changed_from_saved() || + m_xRightIndent->get_value_changed_from_saved() || + m_xAutoCB->get_state_changed_from_saved() ) + { + nWhich = GetWhich( SID_ATTR_LRSPACE ); + MapUnit eUnit = pPool->GetMetric( nWhich ); + SvxLRSpaceItem aMargin( nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_LRSPACE ); + + if ( bRelativeMode ) + { + DBG_ASSERT( GetItemSet().GetParent(), "No ParentSet" ); + + const SvxLRSpaceItem& rOldItem = + static_cast<const SvxLRSpaceItem&>(GetItemSet().GetParent()->Get( nWhich )); + + if (m_xLeftIndent->IsRelative()) + aMargin.SetTextLeft( rOldItem.GetTextLeft(), + static_cast<sal_uInt16>(m_xLeftIndent->get_value(FieldUnit::NONE)) ); + else + aMargin.SetTextLeft(m_xLeftIndent->GetCoreValue(eUnit)); + + if ( m_xRightIndent->IsRelative() ) + aMargin.SetRight( rOldItem.GetRight(), + static_cast<sal_uInt16>(m_xRightIndent->get_value(FieldUnit::NONE)) ); + else + aMargin.SetRight(m_xRightIndent->GetCoreValue(eUnit)); + + if ( m_xFLineIndent->IsRelative() ) + aMargin.SetTextFirstLineOffset( rOldItem.GetTextFirstLineOffset(), + static_cast<sal_uInt16>(m_xFLineIndent->get_value(FieldUnit::NONE)) ); + else + aMargin.SetTextFirstLineOffset(static_cast<sal_uInt16>(m_xFLineIndent->GetCoreValue(eUnit))); + } + else + { + aMargin.SetTextLeft(m_xLeftIndent->GetCoreValue(eUnit)); + aMargin.SetRight(m_xRightIndent->GetCoreValue(eUnit)); + aMargin.SetTextFirstLineOffset(static_cast<sal_uInt16>(m_xFLineIndent->GetCoreValue(eUnit))); + } + aMargin.SetAutoFirst(m_xAutoCB->get_active()); + if ( aMargin.GetTextFirstLineOffset() < 0 ) + bNullTab = true; + + if ( !pOld || *static_cast<const SvxLRSpaceItem*>(pOld) != aMargin || + SfxItemState::DONTCARE == GetItemSet().GetItemState( nWhich ) ) + { + rOutSet->Put( aMargin ); + bModified = true; + } + } + + if ( bNullTab ) + { + MapUnit eUnit = pPool->GetMetric( GetWhich( SID_ATTR_TABSTOP ) ); + if ( MapUnit::Map100thMM != eUnit ) + { + + // negative first line indent -> set null default tabstob if applicable + sal_uInt16 _nWhich = GetWhich( SID_ATTR_TABSTOP ); + const SfxItemSet& rInSet = GetItemSet(); + + if ( rInSet.GetItemState( _nWhich ) >= SfxItemState::DEFAULT ) + { + const SvxTabStopItem& rTabItem = + static_cast<const SvxTabStopItem&>(rInSet.Get( _nWhich )); + SvxTabStopItem aNullTab( rTabItem ); + SvxTabStop aNull( 0, SvxTabAdjust::Default ); + aNullTab.Insert( aNull ); + rOutSet->Put( aNullTab ); + } + } + } + if (m_xRegisterCB->get_visible()) + { + const SfxBoolItem* pBoolItem = static_cast<const SfxBoolItem*>(GetOldItem( + *rOutSet, SID_ATTR_PARA_REGISTER)); + if (!pBoolItem) + return bModified; + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_REGISTER ); + bool bSet = pBoolItem->GetValue(); + + if (m_xRegisterCB->get_active() != bSet) + { + std::unique_ptr<SfxBoolItem> pRegItem(pBoolItem->Clone()); + pRegItem->SetValue(!bSet); + rOutSet->Put(std::move(pRegItem)); + bModified = true; + } + else if ( SfxItemState::DEFAULT == GetItemSet().GetItemState( _nWhich, false ) ) + rOutSet->ClearItem(_nWhich); + } + + return bModified; +} + +void SvxStdParagraphTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( *rSet ); + + bool bApplyCharUnit = GetApplyCharUnit( *rSet ); + + if(SvtCJKOptions::IsAsianTypographyEnabled() && bApplyCharUnit ) + eFUnit = FieldUnit::CHAR; + + m_xLeftIndent->SetFieldUnit(eFUnit); + m_xRightIndent->SetFieldUnit(eFUnit); + m_xFLineIndent->SetFieldUnit(eFUnit); + if ( eFUnit == FieldUnit::CHAR ) + { + m_xTopDist->SetFieldUnit(FieldUnit::LINE); + m_xBottomDist->SetFieldUnit(FieldUnit::LINE); + SetFieldUnit(*m_xLineDistAtMetricBox, FieldUnit::POINT); + } + else + { + m_xTopDist->SetFieldUnit(eFUnit); + m_xBottomDist->SetFieldUnit(eFUnit); + SetFieldUnit(*m_xLineDistAtMetricBox, eFUnit); + } + + sal_uInt16 _nWhich = GetWhich( SID_ATTR_LRSPACE ); + SfxItemState eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + MapUnit eUnit = pPool->GetMetric( _nWhich ); + + if ( bRelativeMode ) + { + const SvxLRSpaceItem& rOldItem = + static_cast<const SvxLRSpaceItem&>(rSet->Get( _nWhich )); + + if ( rOldItem.GetPropLeft() != 100 ) + { + m_xLeftIndent->SetRelative( true ); + m_xLeftIndent->set_value(rOldItem.GetPropLeft(), FieldUnit::NONE); + } + else + { + m_xLeftIndent->SetRelative(false); + m_xLeftIndent->SetFieldUnit(eFUnit); + m_xLeftIndent->SetMetricValue(rOldItem.GetTextLeft(), eUnit); + } + + if ( rOldItem.GetPropRight() != 100 ) + { + m_xRightIndent->SetRelative( true ); + m_xRightIndent->set_value(rOldItem.GetPropRight(), FieldUnit::NONE); + } + else + { + m_xRightIndent->SetRelative(false); + m_xRightIndent->SetFieldUnit(eFUnit); + m_xRightIndent->SetMetricValue(rOldItem.GetRight(), eUnit); + } + + if ( rOldItem.GetPropTextFirstLineOffset() != 100 ) + { + m_xFLineIndent->SetRelative(true); + m_xFLineIndent->set_value(rOldItem.GetPropTextFirstLineOffset(), FieldUnit::NONE); + } + else + { + m_xFLineIndent->SetRelative(false); + m_xFLineIndent->set_min(-9999, FieldUnit::NONE); + m_xFLineIndent->SetFieldUnit(eFUnit); + m_xFLineIndent->SetMetricValue(rOldItem.GetTextFirstLineOffset(), eUnit); + } + m_xAutoCB->set_active(rOldItem.IsAutoFirst()); + } + else + { + const SvxLRSpaceItem& rSpace = + static_cast<const SvxLRSpaceItem&>(rSet->Get( _nWhich )); + + m_xLeftIndent->SetMetricValue(rSpace.GetTextLeft(), eUnit); + m_xRightIndent->SetMetricValue(rSpace.GetRight(), eUnit); + m_xFLineIndent->SetMetricValue(rSpace.GetTextFirstLineOffset(), eUnit); + m_xAutoCB->set_active(rSpace.IsAutoFirst()); + } + AutoHdl_Impl(*m_xAutoCB); + } + else + { + m_xLeftIndent->set_text(OUString()); + m_xRightIndent->set_text(OUString()); + m_xFLineIndent->set_text(OUString()); + } + + _nWhich = GetWhich( SID_ATTR_ULSPACE ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + MapUnit eUnit = pPool->GetMetric( _nWhich ); + + const SvxULSpaceItem& rOldItem = + static_cast<const SvxULSpaceItem&>(rSet->Get( _nWhich )); + if ( bRelativeMode ) + { + + if ( rOldItem.GetPropUpper() != 100 ) + { + m_xTopDist->SetRelative( true ); + m_xTopDist->set_value(rOldItem.GetPropUpper(), FieldUnit::NONE); + } + else + { + m_xTopDist->SetRelative(false); + if (eFUnit == FieldUnit::CHAR) + m_xTopDist->SetFieldUnit(FieldUnit::LINE); + else + m_xTopDist->SetFieldUnit(eFUnit); + m_xTopDist->SetMetricValue(rOldItem.GetUpper(), eUnit); + } + + if ( rOldItem.GetPropLower() != 100 ) + { + m_xBottomDist->SetRelative( true ); + m_xBottomDist->set_value(rOldItem.GetPropLower(), FieldUnit::NONE); + } + else + { + m_xBottomDist->SetRelative(false); + if (eFUnit == FieldUnit::CHAR) + m_xBottomDist->SetFieldUnit(FieldUnit::LINE); + else + m_xBottomDist->SetFieldUnit(eFUnit); + m_xBottomDist->SetMetricValue(rOldItem.GetLower(), eUnit); + } + } + else + { + m_xTopDist->SetMetricValue(rOldItem.GetUpper(), eUnit); + m_xBottomDist->SetMetricValue(rOldItem.GetLower(), eUnit); + } + m_xContextualCB->set_active(rOldItem.GetContext()); + } + else + { + m_xTopDist->set_text(OUString()); + m_xBottomDist->set_text(OUString()); + } + + _nWhich = GetWhich( SID_ATTR_PARA_LINESPACE ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + SetLineSpacing_Impl( static_cast<const SvxLineSpacingItem &>(rSet->Get( _nWhich )) ); + else + m_xLineDist->set_active(-1); + + _nWhich = GetWhich( SID_ATTR_PARA_REGISTER ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + m_xRegisterCB->set_active( static_cast<const SfxBoolItem &>(rSet->Get( _nWhich )).GetValue()); + m_xRegisterCB->save_state(); + sal_uInt16 nHtmlMode = GetHtmlMode_Impl(*rSet); + if(nHtmlMode & HTMLMODE_ON) + { + m_xRegisterCB->hide(); + m_xAutoCB->hide(); + } + + // this sets the min/max limits; do this _after_ setting the values, + // because for Impress the min of first-line indent depends on value of + // left-indent! + ELRLoseFocus(); + ChangesApplied(); +} + +void SvxStdParagraphTabPage::ChangesApplied() +{ + m_xLeftIndent->save_value(); + m_xRightIndent->save_value(); + m_xFLineIndent->save_value(); + m_xLineDist->save_value(); + m_xLineDistAtPercentBox->save_value(); + m_xLineDistAtMetricBox->save_value(); + m_xRegisterCB->save_state(); + m_xTopDist->save_value(); + m_xBottomDist->save_value(); + m_xContextualCB->save_state(); + m_xAutoCB->save_state(); +} + +void SvxStdParagraphTabPage::EnableRelativeMode() +{ + DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no parent-set!" ); + + m_xLeftIndent->EnableRelativeMode( 0, 999 ); + m_xFLineIndent->EnableRelativeMode( 0, 999 ); + m_xRightIndent->EnableRelativeMode( 0, 999 ); + m_xTopDist->EnableRelativeMode( 0, 999 ); + m_xBottomDist->EnableRelativeMode( 0, 999 ); + bRelativeMode = true; +} + +void SvxStdParagraphTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST ); + SfxItemState eItemState = rSet.GetItemState( _nWhich ); + + if ( eItemState < SfxItemState::DEFAULT ) + return; + + const SvxAdjustItem& rAdj = static_cast<const SvxAdjustItem&>( rSet.Get( _nWhich ) ); + SvxAdjust eAdjust = rAdj.GetAdjust(); + if ( eAdjust == SvxAdjust::Center || eAdjust == SvxAdjust::Block ) + { + _nWhich = GetWhich( SID_ATTR_FRAMEDIRECTION ); + eItemState = rSet.GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxFrameDirectionItem& rFrameDirItem = static_cast<const SvxFrameDirectionItem&>( rSet.Get( _nWhich ) ); + SvxFrameDirection eFrameDirection = rFrameDirItem.GetValue(); + + m_aExampleWin.EnableRTL( SvxFrameDirection::Horizontal_RL_TB == eFrameDirection ); + + if ( eAdjust == SvxAdjust::Block ) + m_aExampleWin.SetLastLine( rAdj.GetLastBlock() ); + } + } + else + { + m_aExampleWin.EnableRTL( eAdjust == SvxAdjust::Right ); + eAdjust = SvxAdjust::Left; //required for correct preview display + m_aExampleWin.SetLastLine( eAdjust ); + } + m_aExampleWin.SetAdjust( eAdjust ); + + UpdateExample_Impl(); +} + +DeactivateRC SvxStdParagraphTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + ELRLoseFocus(); + + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +SvxStdParagraphTabPage::SvxStdParagraphTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/paraindentspacing.ui", "ParaIndentSpacing", &rAttr) + , nWidth(11905 /*567 * 50*/) + , nMinFixDist(0) + , bRelativeMode(false) + , m_xLeftIndent(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_LEFTINDENT", FieldUnit::CM))) + , m_xRightLabel(m_xBuilder->weld_label("labelFT_RIGHTINDENT")) + , m_xRightIndent(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_RIGHTINDENT", FieldUnit::CM))) + , m_xFLineLabel(m_xBuilder->weld_label("labelFT_FLINEINDENT")) + , m_xFLineIndent(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_FLINEINDENT", FieldUnit::CM))) + , m_xAutoCB(m_xBuilder->weld_check_button("checkCB_AUTO")) + , m_xTopDist(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_TOPDIST", FieldUnit::CM))) + , m_xBottomDist(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinED_BOTTOMDIST", FieldUnit::CM))) + , m_xContextualCB(m_xBuilder->weld_check_button("checkCB_CONTEXTUALSPACING")) + , m_xLineDist(m_xBuilder->weld_combo_box("comboLB_LINEDIST")) + , m_xLineDistAtPercentBox(m_xBuilder->weld_metric_spin_button("spinED_LINEDISTPERCENT", FieldUnit::PERCENT)) + , m_xLineDistAtMetricBox(m_xBuilder->weld_metric_spin_button("spinED_LINEDISTMETRIC", FieldUnit::CM)) + , m_xLineDistAtLabel(m_xBuilder->weld_label("labelFT_LINEDIST")) + , m_xAbsDist(m_xBuilder->weld_label("labelST_LINEDIST_ABS")) + , m_xRegisterCB(m_xBuilder->weld_check_button("checkCB_REGISTER")) + , m_xExampleWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWN_EXAMPLE", m_aExampleWin)) +{ + sAbsDist = m_xAbsDist->get_label(); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + m_xLineDistAtMetricBox->hide(); + + Init_Impl(); + m_xFLineIndent->set_min(-9999, FieldUnit::NONE); // is set to 0 on default +} + +SvxStdParagraphTabPage::~SvxStdParagraphTabPage() +{ +} + +void SvxStdParagraphTabPage::EnableNegativeMode() +{ + m_xLeftIndent->set_min(-9999, FieldUnit::NONE); + m_xRightIndent->set_min(-9999, FieldUnit::NONE); + m_xRightIndent->EnableNegativeMode(); + m_xLeftIndent->EnableNegativeMode(); +} + +void SvxStdParagraphTabPage::SetLineSpacing_Impl +( + const SvxLineSpacingItem &rAttr +) +{ + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( rAttr.Which() ); + + switch( rAttr.GetLineSpaceRule() ) + { + case SvxLineSpaceRule::Auto: + { + SvxInterLineSpaceRule eInter = rAttr.GetInterLineSpaceRule(); + + switch( eInter ) + { + // Default single line spacing + case SvxInterLineSpaceRule::Off: + m_xLineDist->set_active( LLINESPACE_1 ); + break; + + // Default single line spacing + case SvxInterLineSpaceRule::Prop: + if ( 100 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_1 ); + break; + } + // 1.15 line spacing + if ( 115 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_115 ); + break; + } + // 1.5 line spacing + if ( 150 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_15 ); + break; + } + // double line spacing + if ( 200 == rAttr.GetPropLineSpace() ) + { + m_xLineDist->set_active( LLINESPACE_2 ); + break; + } + // the set per cent value + m_xLineDistAtPercentBox->set_value(m_xLineDistAtPercentBox->normalize(rAttr.GetPropLineSpace()), FieldUnit::NONE); + m_xLineDist->set_active( LLINESPACE_PROP ); + break; + + case SvxInterLineSpaceRule::Fix: + SetMetricValue( *m_xLineDistAtMetricBox, rAttr.GetInterLineSpace(), eUnit ); + m_xLineDist->set_active( LLINESPACE_DURCH ); + break; + default: ;//prevent warning + } + } + break; + case SvxLineSpaceRule::Fix: + SetMetricValue(*m_xLineDistAtMetricBox, rAttr.GetLineHeight(), eUnit); + m_xLineDist->set_active( LLINESPACE_FIX ); + break; + + case SvxLineSpaceRule::Min: + SetMetricValue(*m_xLineDistAtMetricBox, rAttr.GetLineHeight(), eUnit); + m_xLineDist->set_active( LLINESPACE_MIN ); + break; + default: ;//prevent warning + } + LineDistHdl_Impl( *m_xLineDist ); +} + +IMPL_LINK_NOARG(SvxStdParagraphTabPage, LineDistPopupHdl_Impl, weld::ComboBox&, void) +{ + m_bLineDistToggled = true; +} + +IMPL_LINK(SvxStdParagraphTabPage, LineDistHdl_Impl, weld::ComboBox&, rBox, void) +{ + switch (rBox.get_active()) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + m_xLineDistAtLabel->set_sensitive(false); + m_xLineDistAtPercentBox->set_sensitive(false); + m_xLineDistAtPercentBox->set_text(OUString()); + m_xLineDistAtMetricBox->set_sensitive(false); + m_xLineDistAtMetricBox->set_text(OUString()); + break; + + case LLINESPACE_DURCH: + // setting a sensible default? + // limit MS min(10, aPageSize) + m_xLineDistAtMetricBox->set_min(0, FieldUnit::NONE); + + if (m_xLineDistAtMetricBox->get_text().isEmpty()) + m_xLineDistAtMetricBox->set_value(m_xLineDistAtMetricBox->normalize(1), FieldUnit::NONE); + m_xLineDistAtPercentBox->hide(); + m_xLineDistAtMetricBox->show(); + m_xLineDistAtMetricBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + break; + + case LLINESPACE_MIN: + m_xLineDistAtMetricBox->set_min(0, FieldUnit::NONE); + + if (m_xLineDistAtMetricBox->get_text().isEmpty()) + m_xLineDistAtMetricBox->set_value(m_xLineDistAtMetricBox->normalize(10), FieldUnit::TWIP); + m_xLineDistAtPercentBox->hide(); + m_xLineDistAtMetricBox->show(); + m_xLineDistAtMetricBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + break; + + case LLINESPACE_PROP: + + if (m_xLineDistAtPercentBox->get_text().isEmpty()) + m_xLineDistAtPercentBox->set_value(m_xLineDistAtPercentBox->normalize(100), FieldUnit::TWIP); + m_xLineDistAtMetricBox->hide(); + m_xLineDistAtPercentBox->show(); + m_xLineDistAtPercentBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + break; + case LLINESPACE_FIX: + { + auto nTemp = m_xLineDistAtMetricBox->get_value(FieldUnit::NONE); + m_xLineDistAtMetricBox->set_min(m_xLineDistAtMetricBox->normalize(nMinFixDist), FieldUnit::TWIP); + + // if the value has been changed at SetMin, + // it is time for the default + if (m_xLineDistAtMetricBox->get_value(FieldUnit::NONE) != nTemp) + SetMetricValue( *m_xLineDistAtMetricBox, FIX_DIST_DEF, MapUnit::MapTwip ); // fix is only in Writer + m_xLineDistAtPercentBox->hide(); + m_xLineDistAtMetricBox->show(); + m_xLineDistAtMetricBox->set_sensitive(true); + m_xLineDistAtLabel->set_sensitive(true); + } + break; + } + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxStdParagraphTabPage, ModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + UpdateExample_Impl(); +} + +void SvxStdParagraphTabPage::Init_Impl() +{ + m_xLineDist->connect_popup_toggled(LINK(this, SvxStdParagraphTabPage, LineDistPopupHdl_Impl)); + m_xLineDist->connect_changed(LINK(this, SvxStdParagraphTabPage, LineDistHdl_Impl)); + + Link<weld::MetricSpinButton&,void> aLink2 = LINK(this, SvxStdParagraphTabPage, ELRLoseFocusHdl); + m_xFLineIndent->connect_value_changed(aLink2); + m_xLeftIndent->connect_value_changed(aLink2); + m_xRightIndent->connect_value_changed(aLink2); + + Link<weld::MetricSpinButton&,void> aLink = LINK(this, SvxStdParagraphTabPage, ModifyHdl_Impl); + m_xTopDist->connect_value_changed(aLink); + m_xBottomDist->connect_value_changed(aLink); + + m_xAutoCB->connect_toggled(LINK(this, SvxStdParagraphTabPage, AutoHdl_Impl)); + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = MapToFieldUnit( pPool->GetMetric( GetWhich( SID_ATTR_LRSPACE ) ) ); + + m_xTopDist->set_max( m_xTopDist->normalize( MAX_DURCH ), eUnit ); + m_xBottomDist->set_max( m_xBottomDist->normalize( MAX_DURCH ), eUnit ); + m_xLineDistAtMetricBox->set_max( m_xLineDistAtMetricBox->normalize( MAX_DURCH ), eUnit ); +} + +void SvxStdParagraphTabPage::UpdateExample_Impl() +{ + m_aExampleWin.SetFirstLineOffset( static_cast<short>(m_xFLineIndent->denormalize( m_xFLineIndent->get_value( FieldUnit::TWIP ) )) ); + m_aExampleWin.SetLeftMargin( static_cast<tools::Long>(m_xLeftIndent->denormalize( m_xLeftIndent->get_value( FieldUnit::TWIP ) ) ) ); + m_aExampleWin.SetRightMargin( static_cast<tools::Long>(m_xRightIndent->denormalize( m_xRightIndent->get_value( FieldUnit::TWIP ) ) ) ); + m_aExampleWin.SetUpper( static_cast<sal_uInt16>(m_xTopDist->denormalize( m_xTopDist->get_value( FieldUnit::TWIP ) )) ); + m_aExampleWin.SetLower( static_cast<sal_uInt16>(m_xBottomDist->denormalize( m_xBottomDist->get_value( FieldUnit::TWIP ) )) ); + + int nPos = m_xLineDist->get_active(); + + switch ( nPos ) + { + case LLINESPACE_1: + case LLINESPACE_115: + case LLINESPACE_15: + case LLINESPACE_2: + case LLINESPACE_PROP: + case LLINESPACE_MIN: + case LLINESPACE_DURCH: + case LLINESPACE_FIX: + m_aExampleWin.SetLineSpace( static_cast<SvxPrevLineSpace>(nPos) ); + break; + } + m_aExampleWin.Invalidate(); +} + +void SvxStdParagraphTabPage::EnableRegisterMode() +{ + m_xRegisterCB->show(); +} + +void SvxStdParagraphTabPage::EnableContextualMode() +{ + m_xContextualCB->show(); +} + +IMPL_LINK(SvxStdParagraphTabPage, AutoHdl_Impl, weld::Toggleable&, rBox, void) +{ + bool bEnable = !rBox.get_active(); + m_xFLineLabel->set_sensitive(bEnable); + m_xFLineIndent->set_sensitive(bEnable); +} + +void SvxStdParagraphTabPage::EnableAutoFirstLine() +{ + m_xAutoCB->show(); +} + +void SvxStdParagraphTabPage::EnableAbsLineDist(tools::Long nMinTwip) +{ + m_xLineDist->append_text(sAbsDist); + nMinFixDist = nMinTwip; +} + +void SvxStdParagraphTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + +/* different bit represent call to different method of SvxStdParagraphTabPage + 0x0001 --->EnableRelativeMode() + 0x0002 --->EnableRegisterMode() + 0x0004 --->EnableAutoFirstLine() + 0x0008 --->EnableNegativeMode() + 0x0010 --->EnableContextualMode() + */ + const SfxUInt16Item* pPageWidthItem = aSet.GetItem<SfxUInt16Item>(SID_SVXSTDPARAGRAPHTABPAGE_PAGEWIDTH, false); + const SfxUInt32Item* pFlagSetItem = aSet.GetItem<SfxUInt32Item>(SID_SVXSTDPARAGRAPHTABPAGE_FLAGSET, false); + const SfxUInt32Item* pLineDistItem = aSet.GetItem<SfxUInt32Item>(SID_SVXSTDPARAGRAPHTABPAGE_ABSLINEDIST, false); + + if (pPageWidthItem) + nWidth = pPageWidthItem->GetValue(); + + if (pFlagSetItem ) + { + if (( 0x0001 & pFlagSetItem->GetValue())== 0x0001 ) + EnableRelativeMode(); + + if (( 0x0002 & pFlagSetItem->GetValue())== 0x0002 ) + EnableRegisterMode(); + + if ( ( 0x0004 & pFlagSetItem->GetValue())== 0x0004 ) + EnableAutoFirstLine(); + } + + if(pLineDistItem) + EnableAbsLineDist(pLineDistItem->GetValue()); + + if (pFlagSetItem) + { + if (( 0x0008 & pFlagSetItem->GetValue()) == 0x0008 ) + EnableNegativeMode(); + + if (( 0x0010 & pFlagSetItem->GetValue()) == 0x0010 ) + EnableContextualMode(); + } +} + +#define LASTLINEPOS_DEFAULT 0 +#define LASTLINEPOS_LEFT 1 + +#define LASTLINECOUNT_OLD 3 +#define LASTLINECOUNT_NEW 4 + +SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/paragalignpage.ui", "ParaAlignPage", &rSet) + , m_xLeft(m_xBuilder->weld_radio_button("radioBTN_LEFTALIGN")) + , m_xRight(m_xBuilder->weld_radio_button("radioBTN_RIGHTALIGN")) + , m_xCenter(m_xBuilder->weld_radio_button("radioBTN_CENTERALIGN")) + , m_xJustify(m_xBuilder->weld_radio_button("radioBTN_JUSTIFYALIGN")) + , m_xLeftBottom(m_xBuilder->weld_label("labelST_LEFTALIGN_ASIAN")) + , m_xRightTop(m_xBuilder->weld_label("labelST_RIGHTALIGN_ASIAN")) + , m_xLastLineFT(m_xBuilder->weld_label("labelLB_LASTLINE")) + , m_xLastLineLB(m_xBuilder->weld_combo_box("comboLB_LASTLINE")) + , m_xExpandCB(m_xBuilder->weld_check_button("checkCB_EXPAND")) + , m_xSnapToGridCB(m_xBuilder->weld_check_button("checkCB_SNAP")) + , m_xExampleWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWN_EXAMPLE", m_aExampleWin)) + , m_xVertAlignFL(m_xBuilder->weld_widget("frameFL_VERTALIGN")) + , m_xVertAlignLB(m_xBuilder->weld_combo_box("comboLB_VERTALIGN")) + , m_xPropertiesFL(m_xBuilder->weld_widget("framePROPERTIES")) + , m_xTextDirectionLB(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("comboLB_TEXTDIRECTION"))) +{ + SetExchangeSupport(); + + sal_uInt16 nLastLinePos = LASTLINEPOS_DEFAULT; + + if ( SvtCJKOptions::IsAsianTypographyEnabled() ) + { + m_xLeft->set_label(m_xLeftBottom->get_label()); + m_xRight->set_label(m_xRightTop->get_label()); + + OUString sLeft(m_xLeft->get_label()); + sLeft = MnemonicGenerator::EraseAllMnemonicChars( sLeft ); + + if (m_xLastLineLB->get_count() == LASTLINECOUNT_OLD) + { + m_xLastLineLB->remove(0); + m_xLastLineLB->insert_text(0, sLeft); + } + else + nLastLinePos = LASTLINEPOS_LEFT; + } + + // remove "Default" or "Left" entry, depends on CJKOptions + if (m_xLastLineLB->get_count() == LASTLINECOUNT_NEW) + m_xLastLineLB->remove(nLastLinePos); + + Link<weld::Toggleable&, void> aLink = LINK( this, SvxParaAlignTabPage, AlignHdl_Impl ); + m_xLeft->connect_toggled(aLink); + m_xRight->connect_toggled(aLink); + m_xCenter->connect_toggled(aLink); + m_xJustify->connect_toggled(aLink); + m_xLastLineLB->connect_changed(LINK(this, SvxParaAlignTabPage, LastLineHdl_Impl)); + m_xTextDirectionLB->connect_changed(LINK(this, SvxParaAlignTabPage, TextDirectionHdl_Impl)); + + m_xTextDirectionLB->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); +} + +SvxParaAlignTabPage::~SvxParaAlignTabPage() +{ +} + +DeactivateRC SvxParaAlignTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SvxParaAlignTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxParaAlignTabPage>(pPage, pController, *rSet); +} + +bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet ) +{ + bool bModified = false; + + bool bAdj = false; + SvxAdjust eAdjust = SvxAdjust::Left; + + if (m_xLeft->get_active()) + { + eAdjust = SvxAdjust::Left; + bAdj = m_xLeft->get_saved_state() == TRISTATE_FALSE; + } + else if (m_xRight->get_active()) + { + eAdjust = SvxAdjust::Right; + bAdj = m_xRight->get_saved_state() == TRISTATE_FALSE; + } + else if (m_xCenter->get_active()) + { + eAdjust = SvxAdjust::Center; + bAdj = m_xCenter->get_saved_state() == TRISTATE_FALSE; + } + else if (m_xJustify->get_active()) + { + eAdjust = SvxAdjust::Block; + bAdj = m_xJustify->get_saved_state() == TRISTATE_FALSE || + m_xExpandCB->get_state_changed_from_saved() || + m_xLastLineLB->get_value_changed_from_saved(); + } + + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST ); + + if (bAdj) + { + SvxAdjust eOneWord = m_xExpandCB->get_active() ? SvxAdjust::Block : SvxAdjust::Left; + + int nLBPos = m_xLastLineLB->get_active(); + SvxAdjust eLastBlock = SvxAdjust::Left; + if ( 1 == nLBPos ) + eLastBlock = SvxAdjust::Center; + else if ( 2 == nLBPos ) + eLastBlock = SvxAdjust::Block; + + SvxAdjustItem aAdj( static_cast<const SvxAdjustItem&>(GetItemSet().Get( _nWhich )) ); + aAdj.SetAdjust( eAdjust ); + aAdj.SetOneWord( eOneWord ); + aAdj.SetLastBlock( eLastBlock ); + rOutSet->Put( aAdj ); + bModified = true; + } + + if (m_xSnapToGridCB->get_state_changed_from_saved()) + { + rOutSet->Put(SvxParaGridItem(m_xSnapToGridCB->get_active(), GetWhich( SID_ATTR_PARA_SNAPTOGRID ))); + bModified = true; + } + + if (m_xVertAlignLB->get_value_changed_from_saved()) + { + rOutSet->Put(SvxParaVertAlignItem(static_cast<SvxParaVertAlignItem::Align>(m_xVertAlignLB->get_active()), GetWhich( SID_PARA_VERTALIGN ))); + bModified = true; + } + + if (m_xTextDirectionLB->get_visible()) + { + if (m_xTextDirectionLB->get_value_changed_from_saved()) + { + SvxFrameDirection eDir = m_xTextDirectionLB->get_active_id(); + rOutSet->Put( SvxFrameDirectionItem( eDir, GetWhich( SID_ATTR_FRAMEDIRECTION ) ) ); + bModified = true; + } + } + + return bModified; +} + +void SvxParaAlignTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + Reset( &rSet ); +} + +void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet ) +{ + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_ADJUST ); + SfxItemState eItemState = rSet->GetItemState( _nWhich ); + + sal_Int32 nLBSelect = 0; + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxAdjustItem& rAdj = static_cast<const SvxAdjustItem&>(rSet->Get( _nWhich )); + + switch ( rAdj.GetAdjust() /*!!! ask VB rAdj.GetLastBlock()*/ ) + { + case SvxAdjust::Left: m_xLeft->set_active(true); break; + + case SvxAdjust::Right: m_xRight->set_active(true); break; + + case SvxAdjust::Center: m_xCenter->set_active(true); break; + + case SvxAdjust::Block: m_xJustify->set_active(true); break; + default: ; //prevent warning + } + bool bEnable = m_xJustify->get_active(); + m_xLastLineFT->set_sensitive(bEnable); + m_xLastLineLB->set_sensitive(bEnable); + + switch(rAdj.GetLastBlock()) + { + case SvxAdjust::Left: nLBSelect = 0; break; + + case SvxAdjust::Center: nLBSelect = 1; break; + + case SvxAdjust::Block: nLBSelect = 2; break; + default: ; //prevent warning + } + m_xExpandCB->set_sensitive(bEnable && nLBSelect == 2); + m_xExpandCB->set_active(SvxAdjust::Block == rAdj.GetOneWord()); + } + else + { + m_xLeft->set_active(false); + m_xRight->set_active(false); + m_xCenter->set_active(false); + m_xJustify->set_active(false); + } + m_xLastLineLB->set_active(nLBSelect); + + sal_uInt16 nHtmlMode = GetHtmlMode_Impl(*rSet); + if(nHtmlMode & HTMLMODE_ON) + { + m_xLastLineLB->hide(); + m_xLastLineFT->hide(); + m_xExpandCB->hide(); + if(!(nHtmlMode & HTMLMODE_FULL_STYLES) ) + m_xJustify->set_sensitive(false); + m_xSnapToGridCB->hide(); + } + _nWhich = GetWhich(SID_ATTR_PARA_SNAPTOGRID); + eItemState = rSet->GetItemState( _nWhich ); + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxParaGridItem& rSnap = static_cast<const SvxParaGridItem&>(rSet->Get( _nWhich )); + m_xSnapToGridCB->set_active(rSnap.GetValue()); + } + + _nWhich = GetWhich( SID_PARA_VERTALIGN ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + m_xVertAlignFL->show(); + + const SvxParaVertAlignItem& rAlign = static_cast<const SvxParaVertAlignItem&>(rSet->Get( _nWhich )); + + m_xVertAlignLB->set_active(static_cast<sal_Int32>(rAlign.GetValue())); + } + + _nWhich = GetWhich( SID_ATTR_FRAMEDIRECTION ); + //text direction + if( SfxItemState::DEFAULT <= rSet->GetItemState( _nWhich ) ) + { + const SvxFrameDirectionItem& rFrameDirItem = static_cast<const SvxFrameDirectionItem&>( rSet->Get( _nWhich ) ); + m_xTextDirectionLB->set_active_id(rFrameDirItem.GetValue()); + m_xTextDirectionLB->save_value(); + } + + m_xSnapToGridCB->save_state(); + m_xVertAlignLB->save_value(); + m_xLeft->save_state(); + m_xRight->save_state(); + m_xCenter->save_state(); + m_xJustify->save_state(); + m_xLastLineLB->save_value(); + m_xExpandCB->save_state(); + + UpdateExample_Impl(); +} + +void SvxParaAlignTabPage::ChangesApplied() +{ + m_xTextDirectionLB->save_value(); + m_xSnapToGridCB->save_state(); + m_xVertAlignLB->save_value(); + m_xLeft->save_state(); + m_xRight->save_state(); + m_xCenter->save_state(); + m_xJustify->save_state(); + m_xLastLineLB->save_value(); + m_xExpandCB->save_state(); +} + +IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, weld::Toggleable&, void) +{ + bool bJustify = m_xJustify->get_active(); + m_xLastLineFT->set_sensitive(bJustify); + m_xLastLineLB->set_sensitive(bJustify); + bool bLastLineIsBlock = m_xLastLineLB->get_active() == 2; + m_xExpandCB->set_sensitive(bJustify && bLastLineIsBlock); + //set last line listbox to entry position 0 if not enabled + if (!m_xLastLineLB->get_sensitive()) + m_xLastLineLB->set_active(0); + //uncheck 'Expand ... word' when check box is not enabled + if (!m_xExpandCB->get_sensitive()) + m_xExpandCB->set_active(false); + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxParaAlignTabPage, LastLineHdl_Impl, weld::ComboBox&, void) +{ + //fdo#41350 only enable 'Expand last word' if last line is also justified + bool bLastLineIsBlock = m_xLastLineLB->get_active() == 2; + m_xExpandCB->set_sensitive(bLastLineIsBlock); + //uncheck 'Expand ... word' when check box is not enabled + if (!m_xExpandCB->get_sensitive()) + m_xExpandCB->set_active(false); + UpdateExample_Impl(); +} + +IMPL_LINK_NOARG(SvxParaAlignTabPage, TextDirectionHdl_Impl, weld::ComboBox&, void) +{ + UpdateExample_Impl(); +} + +void SvxParaAlignTabPage::UpdateExample_Impl() +{ + if (m_xLeft->get_active()) + { + m_aExampleWin.EnableRTL(false); + m_aExampleWin.SetAdjust(SvxAdjust::Left); + m_aExampleWin.SetLastLine(SvxAdjust::Left); + } + else if (m_xRight->get_active()) + { + m_aExampleWin.EnableRTL(true); + m_aExampleWin.SetAdjust(SvxAdjust::Left); + m_aExampleWin.SetLastLine(SvxAdjust::Left); + } + else + { + SvxFrameDirection eDir = m_xTextDirectionLB->get_active_id(); + switch ( eDir ) + { + case SvxFrameDirection::Environment : + if ( !m_xRight->get_active() ) + m_aExampleWin.EnableRTL( AllSettings::GetLayoutRTL() ); + break; + case SvxFrameDirection::Horizontal_RL_TB : + if ( !m_xLeft->get_active() ) + m_aExampleWin.EnableRTL( true ); + break; + case SvxFrameDirection::Horizontal_LR_TB : + if ( !m_xRight->get_active() ) + m_aExampleWin.EnableRTL( false ); + break; + default: ; //prevent warning + } + if (m_xCenter->get_active()) + m_aExampleWin.SetAdjust( SvxAdjust::Center ); + else if (m_xJustify->get_active()) + { + m_aExampleWin.SetAdjust( SvxAdjust::Block ); + int nLBPos = m_xLastLineLB->get_active(); + if (nLBPos == 0) + m_aExampleWin.SetLastLine(SvxAdjust::Left); + else if (nLBPos == 1) + m_aExampleWin.SetLastLine(SvxAdjust::Center); + else if (nLBPos == 2) + m_aExampleWin.SetLastLine(SvxAdjust::Block); + } + } + + m_aExampleWin.Invalidate(); +} + +void SvxParaAlignTabPage::EnableJustifyExt() +{ + m_xLastLineFT->show(); + m_xLastLineLB->show(); + m_xExpandCB->show(); + if (SvtCJKOptions::IsAsianTypographyEnabled()) + m_xSnapToGridCB->show(); + +} + +void SvxParaAlignTabPage::PageCreated (const SfxAllItemSet& aSet) +{ + const SfxBoolItem* pBoolItem = aSet.GetItem<SfxBoolItem>(SID_SVXPARAALIGNTABPAGE_ENABLEJUSTIFYEXT, false); + if (pBoolItem && pBoolItem->GetValue()) + EnableJustifyExt(); +} + +std::unique_ptr<SfxTabPage> SvxExtParagraphTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxExtParagraphTabPage>(pPage, pController, *rSet); +} + +bool SvxExtParagraphTabPage::FillItemSet( SfxItemSet* rOutSet ) +{ + bool bModified = false; + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_HYPHENZONE ); + const TriState eHyphenState = m_xHyphenBox->get_state(); + const SfxPoolItem* pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_HYPHENZONE ); + + if ( m_xHyphenBox->get_state_changed_from_saved() || + m_xHyphenNoCapsBox->get_state_changed_from_saved() || + m_xHyphenNoLastWordBox->get_state_changed_from_saved() || + m_xExtHyphenBeforeBox->get_value_changed_from_saved() || + m_xExtHyphenAfterBox->get_value_changed_from_saved() || + m_xMaxHyphenEdit->get_value_changed_from_saved() || + m_xMinWordLength->get_value_changed_from_saved() || + m_xHyphenZone->get_value_changed_from_saved() ) + { + SvxHyphenZoneItem aHyphen( + static_cast<const SvxHyphenZoneItem&>(GetItemSet().Get( _nWhich )) ); + aHyphen.SetHyphen( eHyphenState == TRISTATE_TRUE ); + aHyphen.SetNoCapsHyphenation(m_xHyphenNoCapsBox->get_state() == TRISTATE_TRUE); + aHyphen.SetNoLastWordHyphenation(m_xHyphenNoLastWordBox->get_state() == TRISTATE_TRUE); + + if ( eHyphenState == TRISTATE_TRUE ) + { + aHyphen.GetMinLead() = static_cast<sal_uInt8>(m_xExtHyphenBeforeBox->get_value()); + aHyphen.GetMinTrail() = static_cast<sal_uInt8>(m_xExtHyphenAfterBox->get_value()); + aHyphen.GetMinWordLength() = static_cast<sal_uInt8>(m_xMinWordLength->get_value()); + } + aHyphen.GetMaxHyphens() = static_cast<sal_uInt8>(m_xMaxHyphenEdit->get_value()); + + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + MapUnit eUnit = pPool->GetMetric( _nWhich ); + aHyphen.GetTextHyphenZone() = static_cast<sal_uInt16>(m_xHyphenZone->GetCoreValue(eUnit)); + + if ( !pOld || + *static_cast<const SvxHyphenZoneItem*>(pOld) != aHyphen || + m_xHyphenBox->get_state_changed_from_saved()) + { + rOutSet->Put( aHyphen ); + bModified = true; + } + } + + if (m_xPageNumBox->get_sensitive() + && (m_xPageNumBox->get_state_changed_from_saved() || m_xPagenumEdit->get_value_changed_from_saved())) + { + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_PAGENUM ); + + if (TRISTATE_TRUE == m_xPageNumBox->get_state() + && (!pOld || IsInvalidItem(pOld) + || static_cast<const SfxUInt16Item*>(pOld)->GetValue() != m_xPagenumEdit->get_value())) + { + SfxUInt16Item aPageNum(SID_ATTR_PARA_PAGENUM, + static_cast<sal_uInt16>(m_xPagenumEdit->get_value())); + rOutSet->Put( aPageNum ); + bModified = true; + } + else if (TRISTATE_FALSE == m_xPageNumBox->get_state() + && (pOld || IsInvalidItem(pOld))) + { + // need to tell sw to remove the item + rOutSet->DisableItem(SID_ATTR_PARA_PAGENUM); + bModified = true; + } + } + + // pagebreak + + TriState eState = m_xApplyCollBtn->get_state(); + bool bIsPageModel = false; + + OUString sPage; + if ( m_xApplyCollBtn->get_state_changed_from_saved() || + ( TRISTATE_TRUE == eState && + m_xApplyCollBox->get_value_changed_from_saved() ) ) + { + if ( eState == TRISTATE_TRUE ) + { + sPage = m_xApplyCollBox->get_active_text(); + bIsPageModel = !sPage.isEmpty(); + } + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_MODEL ); + + if ( !pOld || static_cast<const SvxPageModelItem*>(pOld)->GetValue() != sPage ) + { + rOutSet->Put( SvxPageModelItem( sPage, false, SID_ATTR_PARA_MODEL ) ); + bModified = true; + } + else + bIsPageModel = false; + } + else if(TRISTATE_TRUE == eState && m_xApplyCollBtn->get_sensitive()) + bIsPageModel = true; + else + rOutSet->Put( SvxPageModelItem( sPage, false, SID_ATTR_PARA_MODEL ) ); + + _nWhich = GetWhich( SID_ATTR_PARA_PAGEBREAK ); + + if ( bIsPageModel ) + // if PageModel is turned on, always turn off PageBreak + rOutSet->Put( SvxFormatBreakItem( SvxBreak::NONE, _nWhich ) ); + else + { + eState = m_xPageBreakBox->get_state(); + SfxItemState eModelState = GetItemSet().GetItemState(SID_ATTR_PARA_MODEL, false); + + if ( (eModelState == SfxItemState::SET && TRISTATE_TRUE == m_xPageBreakBox->get_state()) || + m_xPageBreakBox->get_state_changed_from_saved() || + m_xBreakTypeLB->get_value_changed_from_saved() || + m_xBreakPositionLB->get_value_changed_from_saved() ) + { + const SvxFormatBreakItem rOldBreak( + static_cast<const SvxFormatBreakItem&>(GetItemSet().Get( _nWhich ))); + SvxFormatBreakItem aBreak(rOldBreak.GetBreak(), rOldBreak.Which()); + + switch ( eState ) + { + case TRISTATE_TRUE: + { + bool bBefore = m_xBreakPositionLB->get_active() == 0; + + if (m_xBreakTypeLB->get_active() == 0) + { + if ( bBefore ) + aBreak.SetValue( SvxBreak::PageBefore ); + else + aBreak.SetValue( SvxBreak::PageAfter ); + } + else + { + if ( bBefore ) + aBreak.SetValue( SvxBreak::ColumnBefore ); + else + aBreak.SetValue( SvxBreak::ColumnAfter ); + } + break; + } + + case TRISTATE_FALSE: + aBreak.SetValue( SvxBreak::NONE ); + break; + default: ; //prevent warning + } + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_PAGEBREAK ); + + if ( eState != m_xPageBreakBox->get_saved_state() || + !pOld || !( *static_cast<const SvxFormatBreakItem*>(pOld) == aBreak ) ) + { + bModified = true; + rOutSet->Put( aBreak ); + } + } + } + + // paragraph split + _nWhich = GetWhich( SID_ATTR_PARA_SPLIT ); + eState = m_xKeepTogetherBox->get_state(); + + if (m_xKeepTogetherBox->get_state_changed_from_saved()) + { + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_SPLIT ); + + if ( !pOld || static_cast<const SvxFormatSplitItem*>(pOld)->GetValue() != + ( eState == TRISTATE_FALSE ) ) + { + rOutSet->Put( SvxFormatSplitItem( eState == TRISTATE_FALSE, _nWhich ) ); + bModified = true; + } + } + + // keep paragraphs + _nWhich = GetWhich( SID_ATTR_PARA_KEEP ); + eState = m_xKeepParaBox->get_state(); + + if (m_xKeepParaBox->get_state_changed_from_saved()) + { + // if the status has changed, putting is necessary + rOutSet->Put( SvxFormatKeepItem( eState == TRISTATE_TRUE, _nWhich ) ); + bModified = true; + } + + // widows and orphans + _nWhich = GetWhich( SID_ATTR_PARA_WIDOWS ); + eState = m_xWidowBox->get_state(); + + if ( m_xWidowBox->get_state_changed_from_saved() || + m_xWidowRowNo->get_value_changed_from_saved() ) + { + SvxWidowsItem rItem( eState == TRISTATE_TRUE ? + static_cast<sal_uInt8>(m_xWidowRowNo->get_value()) : 0, _nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_WIDOWS ); + + if ( m_xWidowBox->get_state_changed_from_saved() || !pOld || !( *static_cast<const SvxWidowsItem*>(pOld) == rItem ) ) + { + rOutSet->Put( rItem ); + bModified = true; + } + } + + _nWhich = GetWhich( SID_ATTR_PARA_ORPHANS ); + eState = m_xOrphanBox->get_state(); + + if ( m_xOrphanBox->get_state_changed_from_saved() || + m_xOrphanRowNo->get_value_changed_from_saved() ) + { + SvxOrphansItem rItem( eState == TRISTATE_TRUE ? + static_cast<sal_uInt8>(m_xOrphanRowNo->get_value()) : 0, _nWhich ); + pOld = GetOldItem( *rOutSet, SID_ATTR_PARA_ORPHANS ); + + if ( m_xOrphanBox->get_state_changed_from_saved() || + !pOld || + !( *static_cast<const SvxOrphansItem*>(pOld) == rItem ) ) + { + rOutSet->Put( rItem ); + bModified = true; + } + } + + return bModified; +} +void SvxExtParagraphTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemPool* pPool = rSet->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( *rSet ); + + bool bApplyCharUnit = GetApplyCharUnit( *rSet ); + + if( SvtCJKOptions::IsAsianTypographyEnabled() && bApplyCharUnit ) + eFUnit = FieldUnit::CHAR; + + sal_uInt16 _nWhich = GetWhich( SID_ATTR_PARA_HYPHENZONE ); + SfxItemState eItemState = rSet->GetItemState( _nWhich ); + + bool bItemAvailable = eItemState >= SfxItemState::DEFAULT; + bool bIsHyphen = false; + if( !bHtmlMode && bItemAvailable ) + { + const SvxHyphenZoneItem& rHyphen = + static_cast<const SvxHyphenZoneItem&>(rSet->Get( _nWhich )); + aHyphenState.bTriStateEnabled = false; + + bIsHyphen = rHyphen.IsHyphen(); + m_xHyphenBox->set_state(bIsHyphen ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xHyphenNoCapsBox->set_state(rHyphen.IsNoCapsHyphenation() ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xHyphenNoLastWordBox->set_state(rHyphen.IsNoLastWordHyphenation() ? TRISTATE_TRUE : TRISTATE_FALSE); + + m_xExtHyphenBeforeBox->set_value(rHyphen.GetMinLead()); + m_xExtHyphenAfterBox->set_value(rHyphen.GetMinTrail()); + m_xMaxHyphenEdit->set_value(rHyphen.GetMaxHyphens()); + m_xMinWordLength->set_value(rHyphen.GetMinWordLength()); + m_xHyphenZone->SetFieldUnit(eFUnit); + m_xHyphenZone->SetMetricValue(rHyphen.GetTextHyphenZone(), MapUnit::MapTwip); + } + else + { + m_xHyphenBox->set_state(TRISTATE_INDET); + m_xHyphenNoCapsBox->set_state(TRISTATE_INDET); + m_xHyphenNoLastWordBox->set_state(TRISTATE_INDET); + } + bool bEnable = bItemAvailable && bIsHyphen; + m_xHyphenNoCapsBox->set_sensitive(bEnable); + m_xHyphenNoLastWordBox->set_sensitive(bEnable); + m_xExtHyphenBeforeBox->set_sensitive(bEnable); + m_xExtHyphenAfterBox->set_sensitive(bEnable); + m_xBeforeText->set_sensitive(bEnable); + m_xAfterText->set_sensitive(bEnable); + m_xMaxHyphenLabel->set_sensitive(bEnable); + m_xMaxHyphenEdit->set_sensitive(bEnable); + m_xMinWordLabel->set_sensitive(bEnable); + m_xMinWordLength->set_sensitive(bEnable); + m_xHyphenZoneLabel->set_sensitive(bEnable); + m_xHyphenZone->set_sensitive(bEnable); + + switch (rSet->GetItemState(SID_ATTR_PARA_PAGENUM)) + { + case SfxItemState::SET: + { + aPageNumState.bTriStateEnabled = false; + m_xPageNumBox->set_state(TRISTATE_TRUE); + SfxUInt16Item const*const pItem(rSet->GetItem<SfxUInt16Item>(SID_ATTR_PARA_PAGENUM)); + const sal_uInt16 nPageNum(pItem->GetValue()); + m_xPagenumEdit->set_value(nPageNum); + break; + } + case SfxItemState::DONTCARE: + { + aPageNumState.bTriStateEnabled = true; + m_xPageNumBox->set_state(TRISTATE_INDET); + break; + } + case SfxItemState::UNKNOWN: + case SfxItemState::DEFAULT: + case SfxItemState::DISABLED: + { + aPageNumState.bTriStateEnabled = false; + m_xPageNumBox->set_state(TRISTATE_FALSE); + break; + } + default: + assert(false); // unexpected + break; + } + + if ( bPageBreak ) + { + // first handle PageModel + bool bIsPageModel = false; + eItemState = rSet->GetItemState( SID_ATTR_PARA_MODEL ); + + if ( eItemState >= SfxItemState::SET ) + { + aApplyCollState.bTriStateEnabled = false; + + const SvxPageModelItem& rModel = rSet->Get( SID_ATTR_PARA_MODEL ); + const OUString& aStr( rModel.GetValue() ); + + if (!aStr.isEmpty() && m_xApplyCollBox->find_text(aStr) != -1) + { + m_xApplyCollBox->set_active_text(aStr); + m_xApplyCollBtn->set_state(TRISTATE_TRUE); + bIsPageModel = true; + + m_xPageBreakBox->set_sensitive(true); + aPageBreakState.bTriStateEnabled = false; + m_xBreakTypeFT->set_sensitive(true); + m_xBreakTypeLB->set_sensitive(true); + m_xBreakPositionFT->set_sensitive(true); + m_xBreakPositionLB->set_sensitive(true); + m_xApplyCollBtn->set_sensitive(false); + m_xPageBreakBox->set_state(TRISTATE_TRUE); + + //select page break + m_xBreakTypeLB->set_active(0); + //select break before + m_xBreakPositionLB->set_active(0); + } + else + { + m_xApplyCollBox->set_active(-1); + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + } + } + else if ( SfxItemState::DONTCARE == eItemState ) + { + aApplyCollState.bTriStateEnabled = true; + m_xApplyCollBtn->set_state(TRISTATE_INDET); + m_xApplyCollBox->set_active(-1); + } + else + { + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + } + + if ( !bIsPageModel ) + { + _nWhich = GetWhich( SID_ATTR_PARA_PAGEBREAK ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxFormatBreakItem& rPageBreak = + static_cast<const SvxFormatBreakItem&>(rSet->Get( _nWhich )); + + SvxBreak eBreak = rPageBreak.GetBreak(); + + // PageBreak not via CTRL-RETURN, + // then CheckBox can be freed + m_xPageBreakBox->set_sensitive(true); + aPageBreakState.bTriStateEnabled = false; + m_xBreakTypeFT->set_sensitive(true); + m_xBreakTypeLB->set_sensitive(true); + m_xBreakPositionFT->set_sensitive(true); + m_xBreakPositionLB->set_sensitive(true); + + m_xPageBreakBox->set_state(TRISTATE_TRUE); + + bool _bEnable = eBreak != SvxBreak::NONE && + eBreak != SvxBreak::ColumnBefore && + eBreak != SvxBreak::ColumnAfter; + m_xApplyCollBtn->set_sensitive(_bEnable); + if (!_bEnable) + { + m_xApplyCollBox->set_sensitive(_bEnable); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(_bEnable); + } + + if ( eBreak == SvxBreak::NONE ) + m_xPageBreakBox->set_state(TRISTATE_FALSE); + + sal_Int32 nType = 0; // selection position in break type ListBox : Page + sal_Int32 nPosition = 0; // selection position in break position ListBox : Before + switch ( eBreak ) + { + case SvxBreak::PageBefore: + break; + case SvxBreak::PageAfter: + nPosition = 1; + break; + case SvxBreak::ColumnBefore: + nType = 1; + break; + case SvxBreak::ColumnAfter: + nType = 1; + nPosition = 1; + break; + default: ;//prevent warning + } + m_xBreakTypeLB->set_active(nType); + m_xBreakPositionLB->set_active(nPosition); + } + else if ( SfxItemState::DONTCARE == eItemState ) + m_xPageBreakBox->set_state(TRISTATE_INDET); + else + { + m_xPageBreakBox->set_sensitive(false); + m_xBreakTypeFT->set_sensitive(false); + m_xBreakTypeLB->set_sensitive(false); + m_xBreakPositionFT->set_sensitive(false); + m_xBreakPositionLB->set_sensitive(false); + } + } + + PageBreakPosHdl_Impl(*m_xBreakPositionLB); + PageBreakHdl(); + } + + _nWhich = GetWhich( SID_ATTR_PARA_KEEP ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + aKeepParaState.bTriStateEnabled = false; + const SvxFormatKeepItem& rKeep = + static_cast<const SvxFormatKeepItem&>(rSet->Get( _nWhich )); + + if ( rKeep.GetValue() ) + m_xKeepParaBox->set_state(TRISTATE_TRUE); + else + m_xKeepParaBox->set_state(TRISTATE_FALSE); + } + else if ( SfxItemState::DONTCARE == eItemState ) + m_xKeepParaBox->set_state(TRISTATE_INDET); + else + m_xKeepParaBox->set_sensitive(false); + + _nWhich = GetWhich( SID_ATTR_PARA_SPLIT ); + eItemState = rSet->GetItemState( _nWhich ); + + if ( eItemState >= SfxItemState::DEFAULT ) + { + const SvxFormatSplitItem& rSplit = + static_cast<const SvxFormatSplitItem&>(rSet->Get( _nWhich )); + aKeepTogetherState.bTriStateEnabled = false; + + if ( !rSplit.GetValue() ) + m_xKeepTogetherBox->set_state(TRISTATE_TRUE); + else + { + m_xKeepTogetherBox->set_state(TRISTATE_FALSE); + // default widows and orphans to enabled + m_xWidowBox->set_sensitive(true); + m_xOrphanBox->set_sensitive(true); + } + + // widows and orphans + _nWhich = GetWhich( SID_ATTR_PARA_WIDOWS ); + SfxItemState eTmpState = rSet->GetItemState( _nWhich ); + + if ( eTmpState >= SfxItemState::DEFAULT ) + { + const SvxWidowsItem& rWidow = + static_cast<const SvxWidowsItem&>(rSet->Get( _nWhich )); + aWidowState.bTriStateEnabled = false; + const sal_uInt16 nLines = rWidow.GetValue(); + + bool _bEnable = nLines > 0; + m_xWidowRowNo->set_value(m_xWidowRowNo->normalize(nLines)); + m_xWidowBox->set_state(_bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xWidowRowNo->set_sensitive(_bEnable); + } + else if ( SfxItemState::DONTCARE == eTmpState ) + m_xWidowBox->set_state( TRISTATE_INDET ); + else + m_xWidowBox->set_sensitive(false); + + _nWhich = GetWhich( SID_ATTR_PARA_ORPHANS ); + eTmpState = rSet->GetItemState( _nWhich ); + + if ( eTmpState >= SfxItemState::DEFAULT ) + { + const SvxOrphansItem& rOrphan = + static_cast<const SvxOrphansItem&>(rSet->Get( _nWhich )); + const sal_uInt16 nLines = rOrphan.GetValue(); + aOrphanState.bTriStateEnabled = false; + + bool _bEnable = nLines > 0; + m_xOrphanBox->set_state(_bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xOrphanRowNo->set_value(m_xOrphanRowNo->normalize(nLines)); + m_xOrphanRowNo->set_sensitive(_bEnable); + m_xOrphanRowLabel->set_sensitive(_bEnable); + + } + else if ( SfxItemState::DONTCARE == eTmpState ) + m_xOrphanBox->set_state(TRISTATE_INDET); + else + m_xOrphanBox->set_sensitive(false); + aOrphanState.eState = m_xOrphanBox->get_state(); + } + else if ( SfxItemState::DONTCARE == eItemState ) + m_xKeepTogetherBox->set_state(TRISTATE_INDET); + else + m_xKeepTogetherBox->set_sensitive(false); + + // so that everything is enabled correctly + KeepTogetherHdl(); + WidowHdl(); + OrphanHdl(); + ChangesApplied(); +} +void SvxExtParagraphTabPage::ChangesApplied() +{ + m_xHyphenBox->save_state(); + m_xHyphenNoCapsBox->save_state(); + m_xHyphenNoLastWordBox->save_state(); + m_xExtHyphenBeforeBox->set_value(m_xExtHyphenBeforeBox->get_value()); + m_xExtHyphenAfterBox->set_value(m_xExtHyphenAfterBox->get_value()); + m_xMaxHyphenEdit->set_value(m_xMaxHyphenEdit->get_value()); + m_xMinWordLength->set_value(m_xMinWordLength->get_value()); + SfxItemPool* pPool = GetItemSet().GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + FieldUnit eUnit = + MapToFieldUnit( pPool->GetMetric( GetWhich( SID_ATTR_PARA_HYPHENZONE ) ) ); + m_xHyphenZone->set_value(m_xHyphenZone->get_value(eUnit), eUnit); + m_xPageBreakBox->save_state(); + m_xBreakPositionLB->save_value(); + m_xBreakTypeLB->save_value(); + m_xApplyCollBtn->save_state(); + m_xApplyCollBox->save_value(); + m_xPageNumBox->save_state(); + m_xPagenumEdit->save_value(); + m_xKeepTogetherBox->save_state(); + m_xKeepParaBox->save_state(); + m_xWidowBox->save_state(); + m_xOrphanBox->save_state(); + m_xOrphanRowNo->save_value(); + m_xWidowRowNo->save_value(); +} + +DeactivateRC SvxExtParagraphTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void SvxExtParagraphTabPage::DisablePageBreak() +{ + bPageBreak = false; + m_xPageBreakBox->set_sensitive(false); + m_xBreakTypeLB->remove(0); + m_xBreakPositionFT->set_sensitive(false); + m_xBreakPositionLB->set_sensitive(false); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); +} + +SvxExtParagraphTabPage::SvxExtParagraphTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/textflowpage.ui", "TextFlowPage", &rAttr) + , bPageBreak(true) + , bHtmlMode(false) + , nStdPos(0) + // Hyphenation + , m_xHyphenBox(m_xBuilder->weld_check_button("checkAuto")) + , m_xHyphenNoCapsBox(m_xBuilder->weld_check_button("checkNoCaps")) + , m_xHyphenNoLastWordBox(m_xBuilder->weld_check_button("checkNoLastWord")) + , m_xBeforeText(m_xBuilder->weld_label("labelLineBegin")) + , m_xExtHyphenBeforeBox(m_xBuilder->weld_spin_button("spinLineEnd")) + , m_xAfterText(m_xBuilder->weld_label("labelLineEnd")) + , m_xExtHyphenAfterBox(m_xBuilder->weld_spin_button("spinLineBegin")) + , m_xMaxHyphenLabel(m_xBuilder->weld_label("labelMaxNum")) + , m_xMaxHyphenEdit(m_xBuilder->weld_spin_button("spinMaxNum")) + , m_xMinWordLabel(m_xBuilder->weld_label("labelMinLen")) + , m_xMinWordLength(m_xBuilder->weld_spin_button("spinMinLen")) + , m_xHyphenZoneLabel(m_xBuilder->weld_label("labelHyphenZone")) + , m_xHyphenZone(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("spinHyphenZone", FieldUnit::CM))) + //Page break + , m_xPageBreakBox(m_xBuilder->weld_check_button("checkInsert")) + , m_xBreakTypeFT(m_xBuilder->weld_label("labelType")) + , m_xBreakTypeLB(m_xBuilder->weld_combo_box("comboBreakType")) + , m_xBreakPositionFT(m_xBuilder->weld_label("labelPosition")) + , m_xBreakPositionLB(m_xBuilder->weld_combo_box("comboBreakPosition")) + , m_xApplyCollBtn(m_xBuilder->weld_check_button("checkPageStyle")) + , m_xApplyCollBox(m_xBuilder->weld_combo_box("comboPageStyle")) + , m_xPageNumBox(m_xBuilder->weld_check_button("labelPageNum")) + , m_xPagenumEdit(m_xBuilder->weld_spin_button("spinPageNumber")) + // Options + , m_xKeepTogetherBox(m_xBuilder->weld_check_button("checkSplitPara")) + , m_xKeepParaBox(m_xBuilder->weld_check_button("checkKeepPara")) + , m_xOrphanBox(m_xBuilder->weld_check_button("checkOrphan")) + , m_xOrphanRowNo(m_xBuilder->weld_spin_button("spinOrphan")) + , m_xOrphanRowLabel(m_xBuilder->weld_label("labelOrphan")) + , m_xWidowBox(m_xBuilder->weld_check_button("checkWidow")) + , m_xWidowRowNo(m_xBuilder->weld_spin_button("spinWidow")) + , m_xWidowRowLabel(m_xBuilder->weld_label("labelWidow")) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + m_xHyphenBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, HyphenClickHdl_Impl)); + m_xPageBreakBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, PageBreakHdl_Impl)); + m_xKeepTogetherBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, KeepTogetherHdl_Impl)); + m_xWidowBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, WidowHdl_Impl)); + m_xOrphanBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, OrphanHdl_Impl)); + m_xApplyCollBtn->connect_toggled(LINK(this, SvxExtParagraphTabPage, ApplyCollClickHdl_Impl)); + m_xBreakTypeLB->connect_changed(LINK(this, SvxExtParagraphTabPage, PageBreakTypeHdl_Impl)); + m_xBreakPositionLB->connect_changed(LINK(this, SvxExtParagraphTabPage, PageBreakPosHdl_Impl)); + m_xPageNumBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, PageNumBoxClickHdl_Impl)); + m_xKeepParaBox->connect_toggled(LINK(this, SvxExtParagraphTabPage, KeepParaBoxClickHdl_Impl)); + + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + { + SfxStyleSheetBasePool* pPool = pSh->GetStyleSheetPool(); + SfxStyleSheetBase* pStyle = pPool->First(SfxStyleFamily::Page); + OUString aStdName; + + // tdf139131 - sort page styles + m_xApplyCollBox->make_sorted(); + while( pStyle ) + { + if ( aStdName.isEmpty() ) + // first style == standard style + aStdName = pStyle->GetName(); + m_xApplyCollBox->append_text(pStyle->GetName()); + pStyle = pPool->Next(); + } + nStdPos = m_xApplyCollBox->find_text(aStdName); + } + + sal_uInt16 nHtmlMode = GetHtmlMode_Impl( rAttr ); + if ( !(nHtmlMode & HTMLMODE_ON) ) + return; + + bHtmlMode = true; + m_xHyphenBox->set_sensitive(false); + m_xHyphenNoCapsBox->set_sensitive(false); + m_xHyphenNoLastWordBox->set_sensitive(false); + m_xBeforeText->set_sensitive(false); + m_xExtHyphenBeforeBox->set_sensitive(false); + m_xAfterText->set_sensitive(false); + m_xExtHyphenAfterBox->set_sensitive(false); + m_xMaxHyphenLabel->set_sensitive(false); + m_xMaxHyphenEdit->set_sensitive(false); + m_xMinWordLabel->set_sensitive(false); + m_xMinWordLength->set_sensitive(false); + m_xHyphenZoneLabel->set_sensitive(false); + m_xHyphenZone->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + // no column break in HTML + m_xBreakTypeLB->remove(1); +} + +SvxExtParagraphTabPage::~SvxExtParagraphTabPage() +{ +} + +void SvxExtParagraphTabPage::PageBreakHdl() +{ + switch (m_xPageBreakBox->get_state()) + { + case TRISTATE_TRUE: + m_xBreakTypeFT->set_sensitive(true); + m_xBreakTypeLB->set_sensitive(true); + m_xBreakPositionFT->set_sensitive(true); + m_xBreakPositionLB->set_sensitive(true); + + if (0 == m_xBreakTypeLB->get_active() && 0 == m_xBreakPositionLB->get_active()) + { + m_xApplyCollBtn->set_sensitive(true); + + bool bEnable = TRISTATE_TRUE == m_xApplyCollBtn->get_state() && + m_xApplyCollBox->get_count(); + m_xApplyCollBox->set_sensitive(bEnable); + if(!bHtmlMode) + { + m_xPageNumBox->set_sensitive(bEnable); + m_xPagenumEdit->set_sensitive(bEnable && m_xPageNumBox->get_state() == TRISTATE_TRUE); + } + } + break; + + case TRISTATE_FALSE: + case TRISTATE_INDET: + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + m_xBreakTypeFT->set_sensitive(false); + m_xBreakTypeLB->set_sensitive(false); + m_xBreakPositionFT->set_sensitive(false); + m_xBreakPositionLB->set_sensitive(false); + break; + } +} + +IMPL_LINK(SvxExtParagraphTabPage, PageBreakHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aPageBreakState.ButtonToggled(rToggle); + PageBreakHdl(); +} + +void SvxExtParagraphTabPage::KeepTogetherHdl() +{ + bool bEnable = m_xKeepTogetherBox->get_state() == TRISTATE_FALSE; + m_xWidowBox->set_sensitive(bEnable); + m_xOrphanBox->set_sensitive(bEnable); +} + +IMPL_LINK(SvxExtParagraphTabPage, KeepTogetherHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aKeepTogetherState.ButtonToggled(rToggle); + KeepTogetherHdl(); +} + +void SvxExtParagraphTabPage::WidowHdl() +{ + switch (m_xWidowBox->get_state()) + { + case TRISTATE_TRUE: + m_xWidowRowNo->set_sensitive(true); + m_xWidowRowLabel->set_sensitive(true); + m_xKeepTogetherBox->set_sensitive(false); + break; + case TRISTATE_FALSE: + if (m_xOrphanBox->get_state() == TRISTATE_FALSE) + m_xKeepTogetherBox->set_sensitive(true); + [[fallthrough]]; + case TRISTATE_INDET: + m_xWidowRowNo->set_sensitive(false); + m_xWidowRowLabel->set_sensitive(false); + break; + } +} + +IMPL_LINK(SvxExtParagraphTabPage, WidowHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aWidowState.ButtonToggled(rToggle); + WidowHdl(); +} + +IMPL_LINK(SvxExtParagraphTabPage, OrphanHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aOrphanState.ButtonToggled(rToggle); + OrphanHdl(); +} + +void SvxExtParagraphTabPage::OrphanHdl() +{ + switch (m_xOrphanBox->get_state()) + { + case TRISTATE_TRUE: + m_xOrphanRowNo->set_sensitive(true); + m_xOrphanRowLabel->set_sensitive(true); + m_xKeepTogetherBox->set_sensitive(false); + break; + + case TRISTATE_FALSE: + if (m_xWidowBox->get_state() == TRISTATE_FALSE) + m_xKeepTogetherBox->set_sensitive(true); + [[fallthrough]]; + case TRISTATE_INDET: + m_xOrphanRowNo->set_sensitive(false); + m_xOrphanRowLabel->set_sensitive(false); + break; + } +} + +void SvxExtParagraphTabPage::HyphenClickHdl() +{ + bool bEnable = m_xHyphenBox->get_state() == TRISTATE_TRUE; + m_xHyphenNoCapsBox->set_sensitive(bEnable); + m_xHyphenNoLastWordBox->set_sensitive(bEnable); + m_xBeforeText->set_sensitive(bEnable); + m_xExtHyphenBeforeBox->set_sensitive(bEnable); + m_xAfterText->set_sensitive(bEnable); + m_xExtHyphenAfterBox->set_sensitive(bEnable); + m_xMaxHyphenLabel->set_sensitive(bEnable); + m_xMaxHyphenEdit->set_sensitive(bEnable); + m_xMinWordLabel->set_sensitive(bEnable); + m_xMinWordLength->set_sensitive(bEnable); + m_xHyphenZoneLabel->set_sensitive(bEnable); + m_xHyphenZone->set_sensitive(bEnable); + m_xHyphenBox->set_state(bEnable ? TRISTATE_TRUE : TRISTATE_FALSE); +} + +IMPL_LINK(SvxExtParagraphTabPage, HyphenClickHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aHyphenState.ButtonToggled(rToggle); + HyphenClickHdl(); +} + +void SvxExtParagraphTabPage::ApplyCollClickHdl() +{ + bool bEnable = false; + if (m_xApplyCollBtn->get_state() == TRISTATE_TRUE && m_xApplyCollBox->get_count()) + { + bEnable = true; + m_xApplyCollBox->set_active(nStdPos); + } + else + { + m_xApplyCollBox->set_active(-1); + } + m_xApplyCollBox->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNumBox->set_sensitive(bEnable); + m_xPagenumEdit->set_sensitive(bEnable && m_xPageNumBox->get_state() == TRISTATE_TRUE); + } +} + +IMPL_LINK(SvxExtParagraphTabPage, ApplyCollClickHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aApplyCollState.ButtonToggled(rToggle); + ApplyCollClickHdl(); +} + +IMPL_LINK(SvxExtParagraphTabPage, PageBreakPosHdl_Impl, weld::ComboBox&, rListBox, void) +{ + if (0 == rListBox.get_active()) + { + m_xApplyCollBtn->set_sensitive(true); + + bool bEnable = m_xApplyCollBtn->get_state() == TRISTATE_TRUE && m_xApplyCollBox->get_count(); + + m_xApplyCollBox->set_sensitive(bEnable); + if (!bHtmlMode) + { + m_xPageNumBox->set_sensitive(bEnable); + m_xPagenumEdit->set_sensitive(bEnable && m_xPageNumBox->get_state() == TRISTATE_TRUE); + } + } + else if (1 == rListBox.get_active()) + { + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + } +} + +IMPL_LINK(SvxExtParagraphTabPage, PageBreakTypeHdl_Impl, weld::ComboBox&, rListBox, void) +{ + //column break or break after + int nBreakPos = m_xBreakPositionLB->get_active(); + if (rListBox.get_active() == 1 || 1 == nBreakPos) + { + m_xApplyCollBtn->set_state(TRISTATE_FALSE); + m_xApplyCollBtn->set_sensitive(false); + m_xApplyCollBox->set_sensitive(false); + m_xPageNumBox->set_sensitive(false); + m_xPagenumEdit->set_sensitive(false); + } + else + PageBreakPosHdl_Impl(*m_xBreakPositionLB); +} + +void SvxExtParagraphTabPage::PageNumBoxClickHdl() +{ + m_xPagenumEdit->set_sensitive(m_xPageNumBox->get_state() == TRISTATE_TRUE); +} + +IMPL_LINK(SvxExtParagraphTabPage, PageNumBoxClickHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aPageNumState.ButtonToggled(rToggle); + PageNumBoxClickHdl(); +} + +IMPL_LINK(SvxExtParagraphTabPage, KeepParaBoxClickHdl_Impl, weld::Toggleable&, rToggle, void) +{ + aKeepParaState.ButtonToggled(rToggle); +} + +void SvxExtParagraphTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxBoolItem* pDisablePageBreakItem = aSet.GetItem<SfxBoolItem>(SID_DISABLE_SVXEXTPARAGRAPHTABPAGE_PAGEBREAK, false); + + if (pDisablePageBreakItem) + if ( pDisablePageBreakItem->GetValue()) + DisablePageBreak(); +} + +SvxAsianTabPage::SvxAsianTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/asiantypography.ui", "AsianTypography", &rSet) + , m_xForbiddenRulesCB(m_xBuilder->weld_check_button("checkForbidList")) + , m_xHangingPunctCB(m_xBuilder->weld_check_button("checkHangPunct")) + , m_xScriptSpaceCB(m_xBuilder->weld_check_button("checkApplySpacing")) +{ +} + +SvxAsianTabPage::~SvxAsianTabPage() +{ +} + +std::unique_ptr<SfxTabPage> SvxAsianTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxAsianTabPage>(pPage, pController, *rSet); +} + +WhichRangesContainer SvxAsianTabPage::GetRanges() +{ + return WhichRangesContainer(svl::Items<SID_ATTR_PARA_SCRIPTSPACE, SID_ATTR_PARA_FORBIDDEN_RULES>); +} + +bool SvxAsianTabPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bRet = false; + SfxItemPool* pPool = rSet->GetPool(); + if (m_xScriptSpaceCB->get_sensitive() && m_xScriptSpaceCB->get_state_changed_from_saved()) + { + std::unique_ptr<SfxBoolItem> pNewItem(static_cast<SfxBoolItem*>(rSet->Get( + pPool->GetWhich(SID_ATTR_PARA_SCRIPTSPACE)).Clone())); + pNewItem->SetValue(m_xScriptSpaceCB->get_active()); + rSet->Put(std::move(pNewItem)); + bRet = true; + } + if (m_xHangingPunctCB->get_sensitive() && m_xHangingPunctCB->get_state_changed_from_saved()) + { + std::unique_ptr<SfxBoolItem> pNewItem(static_cast<SfxBoolItem*>(rSet->Get( + pPool->GetWhich(SID_ATTR_PARA_HANGPUNCTUATION)).Clone())); + pNewItem->SetValue(m_xHangingPunctCB->get_active()); + rSet->Put(std::move(pNewItem)); + bRet = true; + } + if (m_xForbiddenRulesCB->get_sensitive() && m_xForbiddenRulesCB->get_state_changed_from_saved()) + { + std::unique_ptr<SfxBoolItem> pNewItem(static_cast<SfxBoolItem*>(rSet->Get( + pPool->GetWhich(SID_ATTR_PARA_FORBIDDEN_RULES)).Clone())); + pNewItem->SetValue(m_xForbiddenRulesCB->get_active()); + rSet->Put(std::move(pNewItem)); + bRet = true; + } + return bRet; +} + +static void lcl_SetBox(const SfxItemSet& rSet, sal_uInt16 nSlotId, weld::CheckButton& rBox) +{ + sal_uInt16 _nWhich = rSet.GetPool()->GetWhich(nSlotId); + SfxItemState eState = rSet.GetItemState(_nWhich); + if( eState == SfxItemState::UNKNOWN || eState == SfxItemState::DISABLED ) + rBox.set_sensitive(false); + else if(eState >= SfxItemState::DEFAULT) + rBox.set_active(static_cast<const SfxBoolItem&>(rSet.Get(_nWhich)).GetValue()); + else + rBox.set_state(TRISTATE_INDET); + rBox.save_state(); +} + +void SvxAsianTabPage::Reset( const SfxItemSet* rSet ) +{ + lcl_SetBox(*rSet, SID_ATTR_PARA_FORBIDDEN_RULES, *m_xForbiddenRulesCB ); + lcl_SetBox(*rSet, SID_ATTR_PARA_HANGPUNCTUATION, *m_xHangingPunctCB ); + + //character distance not yet available + lcl_SetBox(*rSet, SID_ATTR_PARA_SCRIPTSPACE, *m_xScriptSpaceCB ); +} + +void SvxAsianTabPage::ChangesApplied() +{ + m_xForbiddenRulesCB->save_state(); + m_xHangingPunctCB->save_state(); + m_xScriptSpaceCB->save_state(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/swpossizetabpage.cxx b/cui/source/tabpages/swpossizetabpage.cxx new file mode 100644 index 000000000..e8a1e4eb9 --- /dev/null +++ b/cui/source/tabpages/swpossizetabpage.cxx @@ -0,0 +1,1878 @@ +/* -*- 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 . + */ + +#include <memory> +#include <cstddef> +#include <swpossizetabpage.hxx> +#include <svx/dlgutil.hxx> +#include <svx/anchorid.hxx> +#include <svl/intitem.hxx> +#include <svx/swframevalidation.hxx> +#include <sfx2/htmlmode.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <svx/swframeposstrings.hxx> +#include <svx/rectenum.hxx> +#include <sal/macros.h> +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/RelOrientation.hpp> +#include <svx/svxids.hrc> +#include <svtools/unitconv.hxx> +#include <osl/diagnose.h> + +using namespace ::com::sun::star::text; + +namespace { + +enum class LB; + +} + +struct FrmMap +{ + SvxSwFramePosString::StringId eStrId; + SvxSwFramePosString::StringId eMirrorStrId; + short nAlign; + LB nLBRelations; +}; + +namespace { + +struct RelationMap +{ + SvxSwFramePosString::StringId eStrId; + SvxSwFramePosString::StringId eMirrorStrId; + LB nLBRelation; + short nRelation; +}; +struct StringIdPair_Impl +{ + SvxSwFramePosString::StringId eHori; + SvxSwFramePosString::StringId eVert; +}; + +enum class LB { + NONE = 0x000000, + Frame = 0x000001, // paragraph text area + PrintArea = 0x000002, // paragraph text area + indents + VertFrame = 0x000004, // vertical paragraph text area + VertPrintArea = 0x000008, // vertical paragraph text area + indents + RelFrameLeft = 0x000010, // left paragraph margin + RelFrameRight = 0x000020, // right paragraph margin + + RelPageLeft = 0x000040, // left page margin + RelPageRight = 0x000080, // right page margin + RelPageFrame = 0x000100, // complete page + RelPagePrintArea = 0x000200, // text area of page + + FlyRelPageLeft = 0x000400, // left frame margin + FlyRelPageRight = 0x000800, // right frame margin + FlyRelPageFrame = 0x001000, // complete frame + FlyRelPagePrintArea = 0x002000, // frame interior + + RelBase = 0x004000, // as char, relative to baseline + RelChar = 0x008000, // as char, relative to character + RelRow = 0x010000, // as char, relative to line + +// #i22305# + FlyVertFrame = 0x020000, // vertical entire frame + FlyVertPrintArea = 0x040000, // vertical frame text area + +// #i22341# + VertLine = 0x080000, // vertical text line + + RelPagePrintAreaBottom = 0x100000, // bottom of text area of page + RelPagePrintAreaTop = 0x200000, + + LAST = 0x400000 +}; + +} + +namespace o3tl { + template<> struct typed_flags<LB> : is_typed_flags<LB, 0x3fffff> {}; +} + +RelationMap const aRelationMap[] = +{ + {SvxSwFramePosString::FRAME, SvxSwFramePosString::FRAME, LB::Frame, RelOrientation::FRAME}, + {SvxSwFramePosString::PRTAREA, SvxSwFramePosString::PRTAREA, LB::PrintArea, RelOrientation::PRINT_AREA}, + {SvxSwFramePosString::REL_PG_LEFT, SvxSwFramePosString::MIR_REL_PG_LEFT, LB::RelPageLeft, RelOrientation::PAGE_LEFT}, + {SvxSwFramePosString::REL_PG_RIGHT, SvxSwFramePosString::MIR_REL_PG_RIGHT, LB::RelPageRight, RelOrientation::PAGE_RIGHT}, + {SvxSwFramePosString::REL_FRM_LEFT, SvxSwFramePosString::MIR_REL_FRM_LEFT, LB::RelFrameLeft, RelOrientation::FRAME_LEFT}, + {SvxSwFramePosString::REL_FRM_RIGHT, SvxSwFramePosString::MIR_REL_FRM_RIGHT, LB::RelFrameRight, RelOrientation::FRAME_RIGHT}, + {SvxSwFramePosString::REL_PG_FRAME, SvxSwFramePosString::REL_PG_FRAME, LB::RelPageFrame, RelOrientation::PAGE_FRAME}, + {SvxSwFramePosString::REL_PG_PRTAREA,SvxSwFramePosString::REL_PG_PRTAREA, LB::RelPagePrintArea, RelOrientation::PAGE_PRINT_AREA}, + {SvxSwFramePosString::REL_PG_PRTAREA_TOP,SvxSwFramePosString::REL_PG_PRTAREA_TOP, LB::RelPagePrintAreaTop, RelOrientation::PAGE_PRINT_AREA_TOP}, + {SvxSwFramePosString::REL_PG_PRTAREA_BOTTOM,SvxSwFramePosString::REL_PG_PRTAREA_BOTTOM, LB::RelPagePrintAreaBottom, RelOrientation::PAGE_PRINT_AREA_BOTTOM}, + {SvxSwFramePosString::REL_CHAR, SvxSwFramePosString::REL_CHAR, LB::RelChar, RelOrientation::CHAR}, + + {SvxSwFramePosString::FLY_REL_PG_LEFT, SvxSwFramePosString::FLY_MIR_REL_PG_LEFT, LB::FlyRelPageLeft, RelOrientation::PAGE_LEFT}, + {SvxSwFramePosString::FLY_REL_PG_RIGHT, SvxSwFramePosString::FLY_MIR_REL_PG_RIGHT, LB::FlyRelPageRight, RelOrientation::PAGE_RIGHT}, + {SvxSwFramePosString::FLY_REL_PG_FRAME, SvxSwFramePosString::FLY_REL_PG_FRAME, LB::FlyRelPageFrame, RelOrientation::PAGE_FRAME}, + {SvxSwFramePosString::FLY_REL_PG_PRTAREA, SvxSwFramePosString::FLY_REL_PG_PRTAREA, LB::FlyRelPagePrintArea, RelOrientation::PAGE_PRINT_AREA}, + + {SvxSwFramePosString::REL_BORDER, SvxSwFramePosString::REL_BORDER, LB::VertFrame, RelOrientation::FRAME}, + {SvxSwFramePosString::REL_PRTAREA, SvxSwFramePosString::REL_PRTAREA, LB::VertPrintArea, RelOrientation::PRINT_AREA}, + + // #i22305# + {SvxSwFramePosString::FLY_REL_PG_FRAME, SvxSwFramePosString::FLY_REL_PG_FRAME, LB::FlyVertFrame, RelOrientation::FRAME}, + {SvxSwFramePosString::FLY_REL_PG_PRTAREA, SvxSwFramePosString::FLY_REL_PG_PRTAREA, LB::FlyVertPrintArea, RelOrientation::PRINT_AREA}, + + // #i22341# + {SvxSwFramePosString::REL_LINE, SvxSwFramePosString::REL_LINE, LB::VertLine, RelOrientation::TEXT_LINE} +}; + +RelationMap const aAsCharRelationMap[] = +{ + {SvxSwFramePosString::REL_BASE, SvxSwFramePosString::REL_BASE, LB::RelBase, RelOrientation::FRAME}, + {SvxSwFramePosString::REL_CHAR, SvxSwFramePosString::REL_CHAR, LB::RelChar, RelOrientation::FRAME}, + {SvxSwFramePosString::REL_ROW, SvxSwFramePosString::REL_ROW, LB::RelRow, RelOrientation::FRAME} +}; + +/*-------------------------------------------------------------------- + Anchored at page + --------------------------------------------------------------------*/ + +constexpr auto HORI_PAGE_REL = LB::RelPageFrame|LB::RelPagePrintArea|LB::RelPageLeft| + LB::RelPageRight; + +FrmMap const aHPageMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_PAGE_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_PAGE_REL}, + {SvxSwFramePosString::CENTER_HORI,SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_PAGE_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_PAGE_REL} +}; + +FrmMap const aHPageHtmlMap[] = +{ + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, LB::RelPageFrame} +}; + +#define VERT_PAGE_REL (LB::RelPageFrame|LB::RelPagePrintArea) + +FrmMap const aVPageMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_PAGE_REL}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_PAGE_REL}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_PAGE_REL}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_PAGE_REL} +}; + +FrmMap const aVPageHtmlMap[] = +{ + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, LB::RelPageFrame} +}; + +/*-------------------------------------------------------------------- + Anchored at frame + --------------------------------------------------------------------*/ + +constexpr auto HORI_FRAME_REL = LB::FlyRelPageFrame|LB::FlyRelPagePrintArea| + LB::FlyRelPageLeft|LB::FlyRelPageRight; + +FrmMap const aHFrameMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_FRAME_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_FRAME_REL}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_FRAME_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_FRAME_REL} +}; + +FrmMap const aHFlyHtmlMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, LB::FlyRelPageFrame}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, LB::FlyRelPageFrame} +}; + +// #i18732# - own vertical alignment map for to frame anchored objects +// #i22305# +#define VERT_FRAME_REL (LB::FlyVertFrame|LB::FlyVertPrintArea) + +FrmMap const aVFrameMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_FRAME_REL}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_FRAME_REL}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_FRAME_REL}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_FRAME_REL} +}; + +FrmMap const aVFlyHtmlMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::FlyVertFrame}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, LB::FlyVertFrame} +}; + +FrmMap const aVMultiSelectionMap[] = +{ + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, LB::NONE} +}; +FrmMap const aHMultiSelectionMap[] = +{ + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::FROMLEFT, HoriOrientation::NONE, LB::NONE} +}; + +/*-------------------------------------------------------------------- + Anchored at paragraph + --------------------------------------------------------------------*/ + +constexpr auto HORI_PARA_REL = LB::Frame|LB::PrintArea|LB::RelPageLeft|LB::RelPageRight| + LB::RelPageFrame|LB::RelPagePrintArea|LB::RelFrameLeft| + LB::RelFrameRight; + +FrmMap const aHParaMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_PARA_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_PARA_REL}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_PARA_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_PARA_REL} +}; + +#define HTML_HORI_PARA_REL (LB::Frame|LB::PrintArea) + +FrmMap const aHParaHtmlMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::LEFT, HoriOrientation::LEFT, HTML_HORI_PARA_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::RIGHT, HoriOrientation::RIGHT, HTML_HORI_PARA_REL} +}; + +FrmMap const aHParaHtmlAbsMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HTML_HORI_PARA_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HTML_HORI_PARA_REL} +}; + + +constexpr auto VERT_PARA_REL = LB::VertFrame|LB::VertPrintArea| + LB::RelPageFrame|LB::RelPagePrintArea| LB::RelPagePrintAreaTop |LB::RelPagePrintAreaBottom; + +FrmMap const aVParaMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_PARA_REL}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_PARA_REL}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_PARA_REL}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_PARA_REL} +}; + +FrmMap const aVParaHtmlMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::VertPrintArea} +}; + +/*-------------------------------------------------------------------- + Anchored at character + --------------------------------------------------------------------*/ + +constexpr auto HORI_CHAR_REL = LB::Frame|LB::PrintArea|LB::RelPageLeft|LB::RelPageRight| + LB::RelPageFrame|LB::RelPagePrintArea|LB::RelFrameLeft| + LB::RelFrameRight|LB::RelChar; + +static FrmMap aHCharMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, HORI_CHAR_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, HORI_CHAR_REL}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_HORI, HoriOrientation::CENTER, HORI_CHAR_REL}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, HORI_CHAR_REL} +}; + +#define HTML_HORI_CHAR_REL (LB::Frame|LB::PrintArea|LB::RelChar) + +static FrmMap aHCharHtmlMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::LEFT, HoriOrientation::LEFT, HTML_HORI_CHAR_REL}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::RIGHT, HoriOrientation::RIGHT, HTML_HORI_CHAR_REL} +}; + +static FrmMap aHCharHtmlAbsMap[] = +{ + {SvxSwFramePosString::LEFT, SvxSwFramePosString::MIR_LEFT, HoriOrientation::LEFT, LB::PrintArea|LB::RelChar}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::MIR_RIGHT, HoriOrientation::RIGHT, LB::PrintArea}, + {SvxSwFramePosString::FROMLEFT, SvxSwFramePosString::MIR_FROMLEFT, HoriOrientation::NONE, LB::RelPageFrame} +}; + +// #i18732# - allow vertical alignment at page areas +// #i22341# - handle <LB::RelChar> on its own +constexpr auto VERT_CHAR_REL = LB::VertFrame|LB::VertPrintArea| + LB::RelPageFrame|LB::RelPagePrintArea|LB::RelPagePrintAreaBottom; + +static FrmMap aVCharMap[] = +{ + // #i22341# + // introduce mappings for new vertical alignment at top of line <LB::VertLine> + // and correct mapping for vertical alignment at character for position <FROM_BOTTOM> + // Note: because of these adjustments the map becomes ambiguous in its values + // <eStrId>/<eMirrorStrId> and <nAlign>. These ambiguities are considered + // in the methods <SwFrmPage::FillRelLB(..)>, <SwFrmPage::GetAlignment(..)> + // and <SwFrmPage::FillPosLB(..)> + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, VERT_CHAR_REL|LB::RelChar}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, VERT_CHAR_REL|LB::RelChar}, + {SvxSwFramePosString::BELOW, SvxSwFramePosString::BELOW, VertOrientation::CHAR_BOTTOM, LB::RelChar}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, VERT_CHAR_REL|LB::RelChar}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMTOP, VertOrientation::NONE, VERT_CHAR_REL}, + {SvxSwFramePosString::FROMBOTTOM, SvxSwFramePosString::FROMBOTTOM, VertOrientation::NONE, LB::RelChar|LB::VertLine}, + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::LINE_TOP, LB::VertLine}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::LINE_BOTTOM, LB::VertLine}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::LINE_CENTER, LB::VertLine} +}; + + +FrmMap const aVCharHtmlMap[] = +{ + {SvxSwFramePosString::BELOW, SvxSwFramePosString::BELOW, VertOrientation::CHAR_BOTTOM, LB::RelChar} +}; + +FrmMap const aVCharHtmlAbsMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::RelChar}, + {SvxSwFramePosString::BELOW, SvxSwFramePosString::BELOW, VertOrientation::CHAR_BOTTOM, LB::RelChar} +}; +/*-------------------------------------------------------------------- + anchored as character + --------------------------------------------------------------------*/ + +FrmMap const aVAsCharMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::RelBase}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::BOTTOM, LB::RelBase}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, LB::RelBase}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::CHAR_TOP, LB::RelChar}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::CHAR_BOTTOM, LB::RelChar}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CHAR_CENTER, LB::RelChar}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::LINE_TOP, LB::RelRow}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::LINE_BOTTOM, LB::RelRow}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::LINE_CENTER, LB::RelRow}, + + {SvxSwFramePosString::FROMBOTTOM, SvxSwFramePosString::FROMBOTTOM, VertOrientation::NONE, LB::RelBase} +}; + +FrmMap const aVAsCharHtmlMap[] = +{ + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::TOP, LB::RelBase}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::CENTER, LB::RelBase}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::CHAR_TOP, LB::RelChar}, + + {SvxSwFramePosString::TOP, SvxSwFramePosString::TOP, VertOrientation::LINE_TOP, LB::RelRow}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::BOTTOM, VertOrientation::LINE_BOTTOM, LB::RelRow}, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_VERT, VertOrientation::LINE_CENTER, LB::RelRow} +}; + +static std::size_t lcl_GetFrmMapCount(const FrmMap* pMap) +{ + if( !pMap ) + return 0; + + if( pMap == aVParaHtmlMap ) + return std::size(aVParaHtmlMap); + if( pMap == aVAsCharHtmlMap ) + return std::size( aVAsCharHtmlMap ); + if( pMap == aHParaHtmlMap ) + return std::size( aHParaHtmlMap ); + if( pMap == aHParaHtmlAbsMap ) + return std::size( aHParaHtmlAbsMap ); + if( pMap == aVPageMap ) + return std::size( aVPageMap ); + if( pMap == aVPageHtmlMap ) + return std::size( aVPageHtmlMap ); + if( pMap == aVAsCharMap ) + return std::size( aVAsCharMap ); + if( pMap == aVParaMap ) + return std::size( aVParaMap ); + if( pMap == aHParaMap ) + return std::size( aHParaMap ); + if( pMap == aHFrameMap ) + return std::size( aHFrameMap ); + if( pMap == aVFrameMap ) + return std::size( aVFrameMap ); + if( pMap == aHCharMap ) + return std::size( aHCharMap ); + if( pMap == aHCharHtmlMap ) + return std::size( aHCharHtmlMap ); + if( pMap == aHCharHtmlAbsMap ) + return std::size( aHCharHtmlAbsMap ); + if( pMap == aVCharMap ) + return std::size( aVCharMap ); + if( pMap == aVCharHtmlMap ) + return std::size( aVCharHtmlMap ); + if( pMap == aVCharHtmlAbsMap ) + return std::size( aVCharHtmlAbsMap ); + if( pMap == aHPageHtmlMap ) + return std::size( aHPageHtmlMap ); + if( pMap == aHFlyHtmlMap ) + return std::size( aHFlyHtmlMap ); + if( pMap == aVFlyHtmlMap ) + return std::size( aVFlyHtmlMap ); + if( pMap == aVMultiSelectionMap ) + return std::size( aVMultiSelectionMap ); + if( pMap == aHMultiSelectionMap ) + return std::size( aHMultiSelectionMap ); + return std::size(aHPageMap); +} + +static SvxSwFramePosString::StringId lcl_ChangeResIdToVerticalOrRTL( + SvxSwFramePosString::StringId eStringId, bool bVertical, bool bRTL) +{ + //special handling of STR_FROMLEFT + if(SvxSwFramePosString::FROMLEFT == eStringId) + { + eStringId = bVertical ? + bRTL ? SvxSwFramePosString::FROMBOTTOM : SvxSwFramePosString::FROMTOP : + bRTL ? SvxSwFramePosString::FROMRIGHT : SvxSwFramePosString::FROMLEFT; + return eStringId; + } + if(bVertical) + { + //exchange horizontal strings with vertical strings and vice versa + static const StringIdPair_Impl aHoriIds[] = + { + {SvxSwFramePosString::LEFT, SvxSwFramePosString::TOP}, + {SvxSwFramePosString::RIGHT, SvxSwFramePosString::BOTTOM}, + {SvxSwFramePosString::CENTER_HORI, SvxSwFramePosString::CENTER_VERT}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMRIGHT}, + {SvxSwFramePosString::REL_PG_LEFT, SvxSwFramePosString::REL_PG_TOP}, + {SvxSwFramePosString::REL_PG_RIGHT, SvxSwFramePosString::REL_PG_BOTTOM} , + {SvxSwFramePosString::REL_FRM_LEFT, SvxSwFramePosString::REL_FRM_TOP}, + {SvxSwFramePosString::REL_FRM_RIGHT, SvxSwFramePosString::REL_FRM_BOTTOM} + }; + static const StringIdPair_Impl aVertIds[] = + { + {SvxSwFramePosString::TOP, SvxSwFramePosString::RIGHT}, + {SvxSwFramePosString::BOTTOM, SvxSwFramePosString::LEFT }, + {SvxSwFramePosString::CENTER_VERT, SvxSwFramePosString::CENTER_HORI}, + {SvxSwFramePosString::FROMTOP, SvxSwFramePosString::FROMRIGHT }, + {SvxSwFramePosString::REL_PG_TOP, SvxSwFramePosString::REL_PG_LEFT }, + {SvxSwFramePosString::REL_PG_BOTTOM, SvxSwFramePosString::REL_PG_RIGHT } , + {SvxSwFramePosString::REL_FRM_TOP, SvxSwFramePosString::REL_FRM_LEFT }, + {SvxSwFramePosString::REL_FRM_BOTTOM, SvxSwFramePosString::REL_FRM_RIGHT } + }; + for(const auto &a : aHoriIds) + { + if(a.eHori == eStringId) + { + eStringId = a.eVert; + return eStringId; + } + } + for(const auto &a : aVertIds) + { + if(a.eHori == eStringId) + { + eStringId = a.eVert; + break; + } + } + } + return eStringId; +} +// #i22341# - helper method in order to determine all possible +// listbox relations in a relation map for a given relation +static LB lcl_GetLBRelationsForRelations( const sal_uInt16 _nRel ) +{ + LB nLBRelations = LB::NONE; + + for (RelationMap const & nRelMapPos : aRelationMap) + { + if ( nRelMapPos.nRelation == _nRel ) + { + nLBRelations |= nRelMapPos.nLBRelation; + } + } + + return nLBRelations; +} + +// #i22341# - helper method on order to determine all possible +// listbox relations in a relation map for a given string ID +static LB lcl_GetLBRelationsForStrID(const FrmMap* _pMap, + const SvxSwFramePosString::StringId _eStrId, + const bool _bUseMirrorStr ) +{ + LB nLBRelations = LB::NONE; + + std::size_t nRelMapSize = lcl_GetFrmMapCount( _pMap ); + for ( std::size_t nRelMapPos = 0; nRelMapPos < nRelMapSize; ++nRelMapPos ) + { + if ( ( !_bUseMirrorStr && _pMap[nRelMapPos].eStrId == _eStrId ) || + ( _bUseMirrorStr && _pMap[nRelMapPos].eMirrorStrId == _eStrId ) ) + { + nLBRelations |= _pMap[nRelMapPos].nLBRelations; + } + } + + return nLBRelations; +} + +SvxSwPosSizeTabPage::SvxSwPosSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/swpossizepage.ui", "SwPosSizePage", &rInAttrs) + , m_pVMap(nullptr) + , m_pHMap(nullptr) + , m_pSdrView(nullptr) + , m_nOldH(HoriOrientation::CENTER) + , m_nOldHRel(RelOrientation::FRAME) + , m_nOldV(VertOrientation::TOP) + , m_nOldVRel(RelOrientation::PRINT_AREA) + , m_fWidthHeightRatio(1.0) + , m_bHtmlMode(false) + , m_bIsVerticalFrame(false) + , m_bPositioningDisabled(false) + , m_bIsMultiSelection(false) + , m_bIsInRightToLeft(false) + , m_nProtectSizeState(TRISTATE_FALSE) + , m_xWidthMF(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM)) + , m_xHeightMF(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM)) + , m_xKeepRatioCB(m_xBuilder->weld_check_button("ratio")) + , m_xToPageRB(m_xBuilder->weld_radio_button("topage")) + , m_xToParaRB(m_xBuilder->weld_radio_button("topara")) + , m_xToCharRB(m_xBuilder->weld_radio_button("tochar")) + , m_xAsCharRB(m_xBuilder->weld_radio_button("aschar")) + , m_xToFrameRB(m_xBuilder->weld_radio_button("toframe")) + , m_xPositionCB(m_xBuilder->weld_check_button("pos")) + , m_xSizeCB(m_xBuilder->weld_check_button("size")) + , m_xPosFrame(m_xBuilder->weld_widget("posframe")) + , m_xHoriFT(m_xBuilder->weld_label("horiposft")) + , m_xHoriLB(m_xBuilder->weld_combo_box("horipos")) + , m_xHoriByFT(m_xBuilder->weld_label("horibyft")) + , m_xHoriByMF(m_xBuilder->weld_metric_spin_button("byhori", FieldUnit::CM)) + , m_xHoriToFT(m_xBuilder->weld_label("horitoft")) + , m_xHoriToLB(m_xBuilder->weld_combo_box("horianchor")) + , m_xHoriMirrorCB(m_xBuilder->weld_check_button("mirror")) + , m_xVertFT(m_xBuilder->weld_label("vertposft")) + , m_xVertLB(m_xBuilder->weld_combo_box("vertpos")) + , m_xVertByFT(m_xBuilder->weld_label("vertbyft")) + , m_xVertByMF(m_xBuilder->weld_metric_spin_button("byvert", FieldUnit::CM)) + , m_xVertToFT(m_xBuilder->weld_label("verttoft")) + , m_xVertToLB(m_xBuilder->weld_combo_box("vertanchor")) + , m_xFollowCB(m_xBuilder->weld_check_button("followtextflow")) + , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN)) +{ + setOptimalFrmWidth(); + setOptimalRelWidth(); + + FieldUnit eDlgUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit(*m_xHoriByMF, eDlgUnit, true); + SetFieldUnit(*m_xVertByMF, eDlgUnit, true); + SetFieldUnit(*m_xWidthMF , eDlgUnit, true); + SetFieldUnit(*m_xHeightMF, eDlgUnit, true); + + SetExchangeSupport(); + + Link<weld::Widget&,void> aLk3 = LINK(this, SvxSwPosSizeTabPage, RangeModifyHdl); + m_xWidthMF->connect_focus_out(aLk3); + m_xHeightMF->connect_focus_out(aLk3); + m_xHoriByMF->connect_focus_out(aLk3); + m_xVertByMF->connect_focus_out(aLk3); + m_xFollowCB->connect_toggled(LINK(this, SvxSwPosSizeTabPage, RangeModifyClickHdl)); + + Link<weld::MetricSpinButton&,void> aLk = LINK(this, SvxSwPosSizeTabPage, ModifyHdl); + m_xWidthMF->connect_value_changed( aLk ); + m_xHeightMF->connect_value_changed( aLk ); + m_xHoriByMF->connect_value_changed( aLk ); + m_xVertByMF->connect_value_changed( aLk ); + + Link<weld::Toggleable&,void> aLk2 = LINK(this, SvxSwPosSizeTabPage, AnchorTypeHdl); + m_xToPageRB->connect_toggled( aLk2 ); + m_xToParaRB->connect_toggled( aLk2 ); + m_xToCharRB->connect_toggled( aLk2 ); + m_xAsCharRB->connect_toggled( aLk2 ); + m_xToFrameRB->connect_toggled( aLk2 ); + + m_xHoriLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, PosHdl)); + m_xVertLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, PosHdl)); + + m_xHoriToLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, RelHdl)); + m_xVertToLB->connect_changed(LINK(this, SvxSwPosSizeTabPage, RelHdl)); + + m_xHoriMirrorCB->connect_toggled(LINK(this, SvxSwPosSizeTabPage, MirrorHdl)); + m_xPositionCB->connect_toggled(LINK(this, SvxSwPosSizeTabPage, ProtectHdl)); +} + +SvxSwPosSizeTabPage::~SvxSwPosSizeTabPage() +{ + m_xWidthMF.reset(); + m_xHeightMF.reset(); + m_xHoriByMF.reset(); + m_xVertByMF.reset(); +} + +namespace +{ + struct FrmMaps + { + FrmMap const *pMap; + size_t nCount; + }; +} + +void SvxSwPosSizeTabPage::setOptimalFrmWidth() +{ + static const FrmMaps aMaps[] = { + { aHPageMap, std::size(aHPageMap) }, + { aHPageHtmlMap, std::size(aHPageHtmlMap) }, + { aVPageMap, std::size(aVPageMap) }, + { aVPageHtmlMap, std::size(aVPageHtmlMap) }, + { aHFrameMap, std::size(aHFrameMap) }, + { aHFlyHtmlMap, std::size(aHFlyHtmlMap) }, + { aVFrameMap, std::size(aVFrameMap) }, + { aVFlyHtmlMap, std::size(aVFlyHtmlMap) }, + { aHParaMap, std::size(aHParaMap) }, + { aHParaHtmlMap, std::size(aHParaHtmlMap) }, + { aHParaHtmlAbsMap, std::size(aHParaHtmlAbsMap) }, + { aVParaMap, std::size(aVParaMap) }, + { aVParaHtmlMap, std::size(aVParaHtmlMap) }, + { aHCharMap, std::size(aHCharMap) }, + { aHCharHtmlMap, std::size(aHCharHtmlMap) }, + { aHCharHtmlAbsMap, std::size(aHCharHtmlAbsMap) }, + { aVCharMap, std::size(aVCharMap) }, + { aVCharHtmlMap, std::size(aVCharHtmlMap) }, + { aVCharHtmlAbsMap, std::size(aVCharHtmlAbsMap) }, + { aVAsCharMap, std::size(aVAsCharMap) }, + { aVAsCharHtmlMap, std::size(aVAsCharHtmlMap) } + }; + + std::vector<SvxSwFramePosString::StringId> aFrames; + for (const FrmMaps& aMap : aMaps) + { + for (size_t j = 0; j < aMap.nCount; ++j) + { + aFrames.push_back(aMap.pMap[j].eStrId); + aFrames.push_back(aMap.pMap[j].eMirrorStrId); + } + } + + std::sort(aFrames.begin(), aFrames.end()); + aFrames.erase(std::unique(aFrames.begin(), aFrames.end()), aFrames.end()); + + for (auto const& frame : aFrames) + { + m_xHoriLB->append_text(SvxSwFramePosString::GetString(frame)); + } + + Size aBiggest(m_xHoriLB->get_preferred_size()); + m_xHoriLB->set_size_request(aBiggest.Width(), -1); + m_xVertLB->set_size_request(aBiggest.Width(), -1); + m_xHoriLB->clear(); +} + +namespace +{ + struct RelationMaps + { + RelationMap const *pMap; + size_t nCount; + }; +} + +void SvxSwPosSizeTabPage::setOptimalRelWidth() +{ + static const RelationMaps aMaps[] = { + { aRelationMap, std::size(aRelationMap) }, + { aAsCharRelationMap, std::size(aAsCharRelationMap) } + }; + + std::vector<SvxSwFramePosString::StringId> aRels; + for (const RelationMaps& aMap : aMaps) + { + for (size_t j = 0; j < aMap.nCount; ++j) + { + aRels.push_back(aMap.pMap[j].eStrId); + aRels.push_back(aMap.pMap[j].eMirrorStrId); + } + } + + std::sort(aRels.begin(), aRels.end()); + aRels.erase(std::unique(aRels.begin(), aRels.end()), aRels.end()); + + for (auto const& elem : aRels) + { + m_xHoriLB->append_text(SvxSwFramePosString::GetString(elem)); + } + + Size aBiggest(m_xHoriLB->get_preferred_size()); + m_xHoriLB->set_size_request(aBiggest.Width(), -1); + m_xVertLB->set_size_request(aBiggest.Width(), -1); + m_xHoriLB->clear(); +} + +std::unique_ptr<SfxTabPage> SvxSwPosSizeTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxSwPosSizeTabPage>(pPage, pController, *rSet); +} + +WhichRangesContainer SvxSwPosSizeTabPage::GetRanges() +{ + static const WhichRangesContainer ranges(svl::Items< + SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_POS_Y, + SID_ATTR_TRANSFORM_WIDTH, SID_ATTR_TRANSFORM_SIZE_POINT, + SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_AUTOWIDTH, SID_ATTR_TRANSFORM_VERT_ORIENT, + SID_HTML_MODE, SID_HTML_MODE, + SID_SW_FOLLOW_TEXT_FLOW, SID_SW_FOLLOW_TEXT_FLOW, + SID_ATTR_TRANSFORM_HORI_POSITION, SID_ATTR_TRANSFORM_VERT_POSITION + >); + return ranges; +} + +bool SvxSwPosSizeTabPage::FillItemSet( SfxItemSet* rSet) +{ + bool bAnchorChanged = false; + RndStdIds nAnchor = GetAnchorType(&bAnchorChanged); + bool bModified = false; + if(bAnchorChanged) + { + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_ANCHOR, static_cast<sal_Int16>(nAnchor))); + bModified = true; + } + if (m_xPositionCB->get_state_changed_from_saved()) + { + if (m_xPositionCB->get_inconsistent()) + rSet->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_POS ); + else + rSet->Put( + SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_POS, + m_xPositionCB->get_state() == TRISTATE_TRUE ) ); + bModified = true; + } + + if (m_xSizeCB->get_state_changed_from_saved()) + { + if (m_xSizeCB->get_inconsistent()) + rSet->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_SIZE ); + else + rSet->Put( + SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_SIZE, + m_xSizeCB->get_state() == TRISTATE_TRUE ) ); + bModified = true; + } + + const SfxItemSet& rOldSet = GetItemSet(); + + if(!m_bPositioningDisabled) + { + //on multiple selections the positioning is set via SdrView + if (m_bIsMultiSelection) + { + if (m_xHoriByMF->get_value_changed_from_saved() || m_xVertByMF->get_value_changed_from_saved()) + { + auto nHoriByPos = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + auto nVertByPos = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + + // old rectangle with CoreUnit + m_aRect = m_pSdrView->GetAllMarkedRect(); + m_pSdrView->GetSdrPageView()->LogicToPagePos( m_aRect ); + + nHoriByPos += m_aAnchorPos.X(); + nVertByPos += m_aAnchorPos.Y(); + + rSet->Put( SfxInt32Item( SID_ATTR_TRANSFORM_POS_X, nHoriByPos ) ); + rSet->Put( SfxInt32Item( SID_ATTR_TRANSFORM_POS_Y, nVertByPos ) ); + + bModified = true; + } + } + else + { + if ( m_pHMap ) + { + const SfxInt16Item& rHoriOrient = + rOldSet.Get( SID_ATTR_TRANSFORM_HORI_ORIENT ); + const SfxInt16Item& rHoriRelation = + rOldSet.Get( SID_ATTR_TRANSFORM_HORI_RELATION); + const SfxInt32Item& rHoriPosition = + rOldSet.Get( SID_ATTR_TRANSFORM_HORI_POSITION); + + sal_uInt16 nMapPos = GetMapPos(m_pHMap, *m_xHoriLB); + short nAlign = GetAlignment(m_pHMap, nMapPos, *m_xHoriToLB); + short nRel = GetRelation(*m_xHoriToLB); + const auto nHoriByPos = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + if ( + nAlign != rHoriOrient.GetValue() || + nRel != rHoriRelation.GetValue() || + (m_xHoriByMF->get_sensitive() && nHoriByPos != rHoriPosition.GetValue()) + ) + { + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_ORIENT, nAlign)); + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_RELATION, nRel)); + if(m_xHoriByMF->get_sensitive()) + rSet->Put(SfxInt32Item(SID_ATTR_TRANSFORM_HORI_POSITION, nHoriByPos)); + bModified = true; + } + } + if (m_xHoriMirrorCB->get_sensitive() && m_xHoriMirrorCB->get_state_changed_from_saved()) + bModified |= nullptr != rSet->Put(SfxBoolItem(SID_ATTR_TRANSFORM_HORI_MIRROR, m_xHoriMirrorCB->get_active())); + + if ( m_pVMap ) + { + const SfxInt16Item& rVertOrient = + rOldSet.Get( SID_ATTR_TRANSFORM_VERT_ORIENT); + const SfxInt16Item& rVertRelation = + rOldSet.Get( SID_ATTR_TRANSFORM_VERT_RELATION); + const SfxInt32Item& rVertPosition = + rOldSet.Get( SID_ATTR_TRANSFORM_VERT_POSITION); + + sal_uInt16 nMapPos = GetMapPos(m_pVMap, *m_xVertLB); + short nAlign = GetAlignment(m_pVMap, nMapPos, *m_xVertToLB); + short nRel = GetRelation(*m_xVertToLB); + // #i34055# - convert vertical position for + // as-character anchored objects + auto nVertByPos = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + if (GetAnchorType() == RndStdIds::FLY_AS_CHAR) + { + nVertByPos *= -1; + } + if ( nAlign != rVertOrient.GetValue() || + nRel != rVertRelation.GetValue() || + ( m_xVertByMF->get_sensitive() && + nVertByPos != rVertPosition.GetValue() ) ) + { + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_ORIENT, nAlign)); + rSet->Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_RELATION, nRel)); + if(m_xVertByMF->get_sensitive()) + rSet->Put(SfxInt32Item(SID_ATTR_TRANSFORM_VERT_POSITION, nVertByPos)); + bModified = true; + } + } + + // #i18732# + if (m_xFollowCB->get_state_changed_from_saved()) + { + //Writer internal type - based on SfxBoolItem + const SfxPoolItem* pItem = GetItem( rOldSet, SID_SW_FOLLOW_TEXT_FLOW); + if(pItem) + { + std::unique_ptr<SfxBoolItem> pFollow(static_cast<SfxBoolItem*>(pItem->Clone())); + pFollow->SetValue(m_xFollowCB->get_active()); + bModified |= nullptr != rSet->Put(std::move(pFollow)); + } + } + } + } + if (m_xWidthMF->get_value_changed_from_saved() || m_xHeightMF->get_value_changed_from_saved()) + { + sal_uInt32 nWidth = static_cast<sal_uInt32>(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP))); + sal_uInt32 nHeight = static_cast<sal_uInt32>(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::TWIP))); + rSet->Put( SfxUInt32Item( SID_ATTR_TRANSFORM_WIDTH, nWidth ) ); + rSet->Put( SfxUInt32Item( SID_ATTR_TRANSFORM_HEIGHT, nHeight ) ); + //this item is required by SdrEditView::SetGeoAttrToMarked() + rSet->Put( SfxUInt16Item( SID_ATTR_TRANSFORM_SIZE_POINT, sal_uInt16(RectPoint::LT) ) ); + + bModified = true; + } + + return bModified; +} + +void SvxSwPosSizeTabPage::Reset( const SfxItemSet* rSet) +{ + const SfxPoolItem* pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_ANCHOR ); + bool bInvalidateAnchor = false; + RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA; + if(pItem) + { + nAnchorType = static_cast<RndStdIds>(static_cast<const SfxInt16Item*>(pItem)->GetValue()); + switch(nAnchorType) + { + case RndStdIds::FLY_AT_PAGE: m_xToPageRB->set_active(true); break; + case RndStdIds::FLY_AT_PARA: m_xToParaRB->set_active(true); break; + case RndStdIds::FLY_AT_CHAR: m_xToCharRB->set_active(true); break; + case RndStdIds::FLY_AS_CHAR: m_xAsCharRB->set_active(true); break; + case RndStdIds::FLY_AT_FLY: m_xToFrameRB->set_active(true); break; + default : bInvalidateAnchor = true; + } + m_xToPageRB->save_state(); + m_xToParaRB->save_state(); + m_xToCharRB->save_state(); + m_xAsCharRB->save_state(); + m_xToFrameRB->save_state(); + } + if (bInvalidateAnchor) + { + m_xToPageRB->set_sensitive( false ); + m_xToParaRB->set_sensitive( false ); + m_xToCharRB->set_sensitive( false ); + m_xAsCharRB->set_sensitive( false ); + m_xToFrameRB->set_sensitive( false ); + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_PROTECT_POS ); + if (pItem) + { + bool bProtected = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + m_xPositionCB->set_active(bProtected); + m_xSizeCB->set_sensitive(!bProtected); + } + else + { + m_xPositionCB->set_inconsistent(true); + } + + m_xPositionCB->save_state(); + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_PROTECT_SIZE ); + + if (pItem) + { + m_xSizeCB->set_active(static_cast<const SfxBoolItem*>(pItem)->GetValue()); + } + else + m_xSizeCB->set_inconsistent(true); + m_xSizeCB->save_state(); + + pItem = GetItem( *rSet, SID_HTML_MODE ); + if(pItem) + { + m_bHtmlMode = + (static_cast<const SfxUInt16Item*>(pItem)->GetValue() & HTMLMODE_ON) + != 0; + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_IN_VERTICAL_TEXT ); + if(pItem && static_cast<const SfxBoolItem*>(pItem)->GetValue()) + { + OUString sHLabel = m_xHoriFT->get_label(); + m_xHoriFT->set_label(m_xVertFT->get_label()); + m_xVertFT->set_label(sHLabel); + m_bIsVerticalFrame = true; + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_IN_RTL_TEXT); + if(pItem) + m_bIsInRightToLeft = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + + pItem = GetItem( *rSet, SID_SW_FOLLOW_TEXT_FLOW); + if(pItem) + { + const bool bFollowTextFlow = + static_cast<const SfxBoolItem*>(pItem)->GetValue(); + m_xFollowCB->set_active(bFollowTextFlow); + } + m_xFollowCB->save_state(); + + if(m_bHtmlMode) + { + m_xHoriMirrorCB->hide(); + m_xKeepRatioCB->set_sensitive(false); + // #i18732# - hide checkbox in HTML mode + m_xFollowCB->hide(); + } + else + { + // #i18732# correct enable/disable of check box 'Mirror on..' + m_xHoriMirrorCB->set_sensitive(!m_xAsCharRB->get_active() && !m_bIsMultiSelection); + + // #i18732# - enable/disable check box 'Follow text flow'. + m_xFollowCB->set_sensitive(m_xToParaRB->get_active() || + m_xToCharRB->get_active()); + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_WIDTH ); + sal_Int32 nWidth = std::max( pItem ? ( static_cast<const SfxUInt32Item*>(pItem)->GetValue()) : 0, sal_uInt32(1) ); + + m_xWidthMF->set_value(m_xWidthMF->normalize(nWidth), FieldUnit::TWIP); + m_xWidthMF->save_value(); + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HEIGHT ); + sal_Int32 nHeight = std::max( pItem ? ( static_cast<const SfxUInt32Item*>(pItem)->GetValue()) : 0, sal_uInt32(1) ); + m_xHeightMF->set_value(m_xHeightMF->normalize(nHeight), FieldUnit::TWIP); + m_xHeightMF->save_value(); + m_fWidthHeightRatio = double(nWidth) / double(nHeight); + + if(m_bPositioningDisabled) + return; + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_ORIENT); + if(pItem) + { + short nHoriOrientation = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + m_nOldH = nHoriOrientation; + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_VERT_ORIENT); + if(pItem) + { + short nVertOrientation = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + m_nOldV = nVertOrientation; + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_RELATION); + if(pItem) + { + m_nOldHRel = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + } + + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_VERT_RELATION); + if(pItem) + { + m_nOldVRel = static_cast< const SfxInt16Item*>(pItem)->GetValue(); + } + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_MIRROR); + if(pItem) + m_xHoriMirrorCB->set_active(static_cast<const SfxBoolItem*>(pItem)->GetValue()); + m_xHoriMirrorCB->save_state(); + + sal_Int32 nHoriPos = 0; + sal_Int32 nVertPos = 0; + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_HORI_POSITION); + if(pItem) + nHoriPos = static_cast<const SfxInt32Item*>(pItem)->GetValue(); + pItem = GetItem( *rSet, SID_ATTR_TRANSFORM_VERT_POSITION); + if(pItem) + nVertPos = static_cast<const SfxInt32Item*>(pItem)->GetValue(); + + InitPos(nAnchorType, m_nOldH, m_nOldHRel, m_nOldV, m_nOldVRel, nHoriPos, nVertPos); + + m_xVertByMF->save_value(); + m_xHoriByMF->save_value(); + // #i18732# + m_xFollowCB->save_state(); + + RangeModifyHdl(m_xWidthMF->get_widget()); // initially set maximum values +} + +DeactivateRC SvxSwPosSizeTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + { + _pSet->Put(SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_POS, + m_xPositionCB->get_active())); + _pSet->Put(SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_SIZE, + m_xSizeCB->get_active())); + FillItemSet( _pSet ); + } + return DeactivateRC::LeavePage; +} + +void SvxSwPosSizeTabPage::EnableAnchorTypes(SvxAnchorIds nAnchorEnable) +{ + if (nAnchorEnable & SvxAnchorIds::Fly) + m_xToFrameRB->show(); + if (!(nAnchorEnable & SvxAnchorIds::Page)) + m_xToPageRB->set_sensitive(false); +} + +RndStdIds SvxSwPosSizeTabPage::GetAnchorType(bool* pbHasChanged) +{ + RndStdIds nRet = RndStdIds::UNKNOWN; + weld::RadioButton* pCheckedButton = nullptr; + if(m_xToParaRB->get_sensitive()) + { + if(m_xToPageRB->get_active()) + { + nRet = RndStdIds::FLY_AT_PAGE; + pCheckedButton = m_xToPageRB.get(); + } + else if(m_xToParaRB->get_active()) + { + nRet = RndStdIds::FLY_AT_PARA; + pCheckedButton = m_xToParaRB.get(); + } + else if(m_xToCharRB->get_active()) + { + nRet = RndStdIds::FLY_AT_CHAR; + pCheckedButton = m_xToCharRB.get(); + } + else if(m_xAsCharRB->get_active()) + { + nRet = RndStdIds::FLY_AS_CHAR; + pCheckedButton = m_xAsCharRB.get(); + } + else if(m_xToFrameRB->get_active()) + { + nRet = RndStdIds::FLY_AT_FLY; + pCheckedButton = m_xToFrameRB.get(); + } + } + if(pbHasChanged) + { + if(pCheckedButton) + *pbHasChanged = pCheckedButton->get_state_changed_from_saved(); + else + *pbHasChanged = false; + } + return nRet; +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, RangeModifyClickHdl, weld::Toggleable&, void) +{ + RangeModifyHdl(m_xWidthMF->get_widget()); +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, RangeModifyHdl, weld::Widget&, void) +{ + if (m_bPositioningDisabled) + return; + SvxSwFrameValidation aVal; + + aVal.nAnchorType = GetAnchorType(); + aVal.bAutoHeight = false; + aVal.bMirror = m_xHoriMirrorCB->get_active(); + // #i18732# + aVal.bFollowTextFlow = m_xFollowCB->get_active(); + + if ( m_pHMap ) + { + // horizontal alignment + sal_uInt16 nMapPos = GetMapPos(m_pHMap, *m_xHoriToLB); + sal_uInt16 nAlign = GetAlignment(m_pHMap, nMapPos, *m_xHoriToLB); + sal_uInt16 nRel = GetRelation(*m_xHoriToLB); + + aVal.nHoriOrient = static_cast<short>(nAlign); + aVal.nHRelOrient = static_cast<short>(nRel); + } + else + aVal.nHoriOrient = HoriOrientation::NONE; + + if ( m_pVMap ) + { + // vertical alignment + sal_uInt16 nMapPos = GetMapPos(m_pVMap, *m_xVertLB); + sal_uInt16 nAlign = GetAlignment(m_pVMap, nMapPos, *m_xVertToLB); + sal_uInt16 nRel = GetRelation(*m_xVertToLB); + + aVal.nVertOrient = static_cast<short>(nAlign); + aVal.nVRelOrient = static_cast<short>(nRel); + } + else + aVal.nVertOrient = VertOrientation::NONE; + + const auto nAtHorzPosVal = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + const auto nAtVertPosVal = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + + aVal.nHPos = nAtHorzPosVal; + aVal.nVPos = nAtVertPosVal; + + sal_Int32 nWidth = static_cast<sal_uInt32>(m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP))); + sal_Int32 nHeight = static_cast<sal_uInt32>(m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::TWIP))); + aVal.nWidth = nWidth; + aVal.nHeight = nHeight; + + m_aValidateLink.Call(aVal); + + // minimum width also for style + m_xHeightMF->set_min(m_xHeightMF->normalize(aVal.nMinHeight), FieldUnit::TWIP); + m_xWidthMF->set_min(m_xWidthMF->normalize(aVal.nMinWidth), FieldUnit::TWIP); + + sal_Int32 nMaxWidth(aVal.nMaxWidth); + sal_Int32 nMaxHeight(aVal.nMaxHeight); + + sal_Int64 nTmp = m_xHeightMF->normalize(nMaxHeight); + m_xHeightMF->set_max(nTmp, FieldUnit::TWIP); + + nTmp = m_xWidthMF->normalize(nMaxWidth); + m_xWidthMF->set_max(nTmp, FieldUnit::TWIP); + + m_xHoriByMF->set_range(m_xHoriByMF->normalize(aVal.nMinHPos), + m_xHoriByMF->normalize(aVal.nMaxHPos), FieldUnit::TWIP); + if ( aVal.nHPos != nAtHorzPosVal ) + m_xHoriByMF->set_value(m_xHoriByMF->normalize(aVal.nHPos), FieldUnit::TWIP); + + m_xVertByMF->set_range(m_xVertByMF->normalize(aVal.nMinVPos), + m_xVertByMF->normalize(aVal.nMaxVPos), FieldUnit::TWIP); + if ( aVal.nVPos != nAtVertPosVal ) + m_xVertByMF->set_value(m_xVertByMF->normalize(aVal.nVPos), FieldUnit::TWIP); +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, AnchorTypeHdl, weld::Toggleable&, void) +{ + m_xHoriMirrorCB->set_sensitive(!m_xAsCharRB->get_active() && !m_bIsMultiSelection); + + // #i18732# - enable check box 'Follow text flow' for anchor + // type to-paragraph' and to-character + m_xFollowCB->set_sensitive(m_xToParaRB->get_active() || m_xToCharRB->get_active()); + + RndStdIds nId = GetAnchorType(); + + InitPos( nId, USHRT_MAX, 0, USHRT_MAX, 0, LONG_MAX, LONG_MAX); + RangeModifyHdl(m_xWidthMF->get_widget()); + + if(m_bHtmlMode) + { + PosHdl(*m_xHoriLB); + PosHdl(*m_xVertLB); + } +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, MirrorHdl, weld::Toggleable&, void) +{ + RndStdIds nId = GetAnchorType(); + InitPos( nId, USHRT_MAX, 0, USHRT_MAX, 0, LONG_MAX, LONG_MAX); +} + +IMPL_LINK( SvxSwPosSizeTabPage, RelHdl, weld::ComboBox&, rLB, void ) +{ + bool bHori = &rLB == m_xHoriToLB.get(); + + UpdateExample(); + + if (m_bHtmlMode && RndStdIds::FLY_AT_CHAR == GetAnchorType()) // again special treatment + { + if(bHori) + { + sal_uInt16 nRel = GetRelation(*m_xHoriToLB); + if(RelOrientation::PRINT_AREA == nRel && 0 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(1); + } + else if(RelOrientation::CHAR == nRel && 1 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(0); + } + } + } + RangeModifyHdl(m_xWidthMF->get_widget()); +} + +IMPL_LINK(SvxSwPosSizeTabPage, PosHdl, weld::ComboBox&, rLB, void) +{ + bool bHori = &rLB == m_xHoriLB.get(); + weld::ComboBox* pRelLB = bHori ? m_xHoriToLB.get() : m_xVertToLB.get(); + weld::Label* pRelFT = bHori ? m_xHoriToFT.get() : m_xVertToFT.get(); + FrmMap const *pMap = bHori ? m_pHMap : m_pVMap; + + + sal_uInt16 nMapPos = GetMapPos(pMap, rLB); + sal_uInt16 nAlign = GetAlignment(pMap, nMapPos, *pRelLB); + + if (bHori) + { + bool bEnable = HoriOrientation::NONE == nAlign; + m_xHoriByMF->set_sensitive( bEnable ); + m_xHoriByFT->set_sensitive( bEnable ); + } + else + { + bool bEnable = VertOrientation::NONE == nAlign; + m_xVertByMF->set_sensitive( bEnable ); + m_xVertByFT->set_sensitive( bEnable ); + } + + RangeModifyHdl(m_xWidthMF->get_widget()); + + short nRel = 0; + if (rLB.get_active() != -1) + { + if (pRelLB->get_active() != -1) + nRel = weld::fromId<RelationMap*>(pRelLB->get_active_id())->nRelation; + + FillRelLB(pMap, nMapPos, nAlign, nRel, *pRelLB, *pRelFT); + } + else + pRelLB->clear(); + + UpdateExample(); + + // special treatment for HTML-Mode with horz-vert-dependencies + if (!(m_bHtmlMode && RndStdIds::FLY_AT_CHAR == GetAnchorType())) + return; + + bool bSet = false; + if(bHori) + { + // on the right only below is allowed - from the left only at the top + // from the left at the character -> below + if((HoriOrientation::LEFT == nAlign || HoriOrientation::RIGHT == nAlign) && + 0 == m_xVertLB->get_active()) + { + if(RelOrientation::FRAME == nRel) + m_xVertLB->set_active(1); + else + m_xVertLB->set_active(0); + bSet = true; + } + else if(HoriOrientation::LEFT == nAlign && 1 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(0); + bSet = true; + } + else if(HoriOrientation::NONE == nAlign && 1 == m_xVertLB->get_active()) + { + m_xVertLB->set_active(0); + bSet = true; + } + if(bSet) + PosHdl(*m_xVertLB); + } + else + { + if(VertOrientation::TOP == nAlign) + { + if(1 == m_xHoriLB->get_active()) + { + m_xHoriLB->set_active(0); + bSet = true; + } + m_xHoriToLB->set_active(1); + } + else if(VertOrientation::CHAR_BOTTOM == nAlign) + { + if(2 == m_xHoriLB->get_active()) + { + m_xHoriLB->set_active(0); + bSet = true; + } + m_xHoriToLB->set_active(0) ; + } + if(bSet) + PosHdl(*m_xHoriLB); + } +} + +IMPL_LINK( SvxSwPosSizeTabPage, ModifyHdl, weld::MetricSpinButton&, rEdit, void ) +{ + auto nWidth = m_xWidthMF->denormalize(m_xWidthMF->get_value(FieldUnit::TWIP)); + auto nHeight = m_xHeightMF->denormalize(m_xHeightMF->get_value(FieldUnit::TWIP)); + if (m_xKeepRatioCB->get_active()) + { + if ( &rEdit == m_xWidthMF.get() ) + { + nHeight = int(static_cast<double>(nWidth) / m_fWidthHeightRatio); + m_xHeightMF->set_value(m_xHeightMF->normalize(nHeight), FieldUnit::TWIP); + } + else if(&rEdit == m_xHeightMF.get()) + { + nWidth = int(static_cast<double>(nHeight) * m_fWidthHeightRatio); + m_xWidthMF->set_value(m_xWidthMF->normalize(nWidth), FieldUnit::TWIP); + } + } + m_fWidthHeightRatio = nHeight ? double(nWidth) / double(nHeight) : 1.0; + UpdateExample(); +} + +IMPL_LINK_NOARG(SvxSwPosSizeTabPage, ProtectHdl, weld::Toggleable&, void) +{ + if (m_xSizeCB->get_sensitive()) + { + m_nProtectSizeState = m_xSizeCB->get_state(); + } + + m_xSizeCB->set_state(m_xPositionCB->get_state() == TRISTATE_TRUE ? TRISTATE_TRUE : m_nProtectSizeState); + m_xSizeCB->set_sensitive(m_xPositionCB->get_sensitive() && !m_xPositionCB->get_active()); +} + +short SvxSwPosSizeTabPage::GetRelation(const weld::ComboBox& rRelationLB) +{ + short nRel = 0; + int nPos = rRelationLB.get_active(); + if (nPos != -1) + { + RelationMap *pEntry = weld::fromId<RelationMap*>(rRelationLB.get_id(nPos)); + nRel = pEntry->nRelation; + } + + return nRel; +} + +short SvxSwPosSizeTabPage::GetAlignment(FrmMap const *pMap, sal_uInt16 nMapPos, const weld::ComboBox& rRelationLB) +{ + short nAlign = 0; + + // #i22341# - special handling also for map <aVCharMap>, + // because it contains ambiguous items for alignment + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap || + pMap == aVCharMap ) + { + if (rRelationLB.get_active() != -1) + { + LB nRel = weld::fromId<RelationMap*>(rRelationLB.get_active_id())->nLBRelation; + std::size_t nMapCount = ::lcl_GetFrmMapCount(pMap); + SvxSwFramePosString::StringId eStrId = pMap[nMapPos].eStrId; + + for (std::size_t i = 0; i < nMapCount; i++) + { + if (pMap[i].eStrId == eStrId) + { + LB nLBRelations = pMap[i].nLBRelations; + if (nLBRelations & nRel) + { + nAlign = pMap[i].nAlign; + break; + } + } + } + } + } + else if (pMap) + nAlign = pMap[nMapPos].nAlign; + + return nAlign; +} + +sal_uInt16 SvxSwPosSizeTabPage::GetMapPos(FrmMap const *pMap, const weld::ComboBox& rAlignLB) +{ + sal_uInt16 nMapPos = 0; + int nLBSelPos = rAlignLB.get_active(); + + if (nLBSelPos != -1) + { + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap) + { + std::size_t nMapCount = ::lcl_GetFrmMapCount(pMap); + OUString sSelEntry(rAlignLB.get_active_text()); + + for (std::size_t i = 0; i < nMapCount; i++) + { + SvxSwFramePosString::StringId eResId = pMap[i].eStrId; + + OUString sEntry = SvxSwFramePosString::GetString(eResId); + + if (sEntry == sSelEntry) + { + nMapPos = sal::static_int_cast< sal_uInt16 >(i); + break; + } + } + } + else + nMapPos = nLBSelPos; + } + + return nMapPos; +} + +void SvxSwPosSizeTabPage::InitPos(RndStdIds nAnchor, + sal_uInt16 nH, + sal_uInt16 nHRel, + sal_uInt16 nV, + sal_uInt16 nVRel, + tools::Long nX, + tools::Long nY) +{ + int nPos = m_xVertLB->get_active(); + if (nPos != -1 && m_pVMap) + { + m_nOldV = m_pVMap[nPos].nAlign; + nPos = m_xVertToLB->get_active(); + if (nPos != -1) + m_nOldVRel = weld::fromId<RelationMap*>(m_xVertToLB->get_id(nPos))->nRelation; + } + + nPos = m_xHoriLB->get_active(); + if (nPos != -1 && m_pHMap) + { + m_nOldH = m_pHMap[nPos].nAlign; + + nPos = m_xHoriToLB->get_active(); + if (nPos != -1) + m_nOldHRel = weld::fromId<RelationMap*>(m_xHoriToLB->get_id(nPos))->nRelation; + } + + bool bEnable = true; + if( m_bIsMultiSelection ) + { + m_pVMap = aVMultiSelectionMap; + m_pHMap = aHMultiSelectionMap; + } + else if (nAnchor == RndStdIds::FLY_AT_PAGE) + { + m_pVMap = m_bHtmlMode ? aVPageHtmlMap : aVPageMap; + m_pHMap = m_bHtmlMode ? aHPageHtmlMap : aHPageMap; + } + else if (nAnchor == RndStdIds::FLY_AT_FLY) + { + // #i18732# - own vertical alignment map for to frame + // anchored objects. + m_pVMap = m_bHtmlMode ? aVFlyHtmlMap : aVFrameMap; + m_pHMap = m_bHtmlMode ? aHFlyHtmlMap : aHFrameMap; + } + else if (nAnchor == RndStdIds::FLY_AT_PARA) + { + if(m_bHtmlMode) + { + m_pVMap = aVParaHtmlMap; + m_pHMap = aHParaHtmlAbsMap; + } + else + { + m_pVMap = aVParaMap; + m_pHMap = aHParaMap; + } + } + else if (nAnchor == RndStdIds::FLY_AT_CHAR) + { + if(m_bHtmlMode) + { + m_pVMap = aVCharHtmlAbsMap; + m_pHMap = aHCharHtmlAbsMap; + } + else + { + m_pVMap = aVCharMap; + m_pHMap = aHCharMap; + } + } + else if (nAnchor == RndStdIds::FLY_AS_CHAR) + { + m_pVMap = m_bHtmlMode ? aVAsCharHtmlMap : aVAsCharMap; + m_pHMap = nullptr; + bEnable = false; + } + m_xHoriLB->set_sensitive(bEnable); + m_xHoriFT->set_sensitive(bEnable); + + // select current Pos + // horizontal + if ( nH == USHRT_MAX ) + { + nH = m_nOldH; + nHRel = m_nOldHRel; + } + // #i22341# - pass <nHRel> as 3rd parameter to method <FillPosLB> + sal_uInt16 nMapPos = FillPosLB(m_pHMap, nH, nHRel, *m_xHoriLB); + FillRelLB(m_pHMap, nMapPos, nH, nHRel, *m_xHoriToLB, *m_xHoriToFT); + + // vertical + if ( nV == USHRT_MAX ) + { + nV = m_nOldV; + nVRel = m_nOldVRel; + } + // #i22341# - pass <nVRel> as 3rd parameter to method <FillPosLB> + nMapPos = FillPosLB(m_pVMap, nV, nVRel, *m_xVertLB); + FillRelLB(m_pVMap, nMapPos, nV, nVRel, *m_xVertToLB, *m_xVertToFT); + + // Edits init + bEnable = nH == HoriOrientation::NONE && nAnchor != RndStdIds::FLY_AS_CHAR; //#61359# why not in formats&& !bFormat; + if (!bEnable) + { + m_xHoriByMF->set_value(0, FieldUnit::TWIP); + } + else if(m_bIsMultiSelection) + { + m_xHoriByMF->set_value(m_xHoriByMF->normalize(m_aRect.Left()), FieldUnit::TWIP); + } + else + { + if (nX != LONG_MAX) + m_xHoriByMF->set_value(m_xHoriByMF->normalize(nX), FieldUnit::TWIP); + } + m_xHoriByFT->set_sensitive(bEnable); + m_xHoriByMF->set_sensitive(bEnable); + + bEnable = nV == VertOrientation::NONE; + if ( !bEnable ) + { + m_xVertByMF->set_value( 0, FieldUnit::TWIP ); + } + else if(m_bIsMultiSelection) + { + m_xVertByMF->set_value(m_xVertByMF->normalize(m_aRect.Top()), FieldUnit::TWIP); + } + else + { + if (nAnchor == RndStdIds::FLY_AS_CHAR) + { + if ( nY == LONG_MAX ) + nY = 0; + else + nY *= -1; + } + if ( nY != LONG_MAX ) + m_xVertByMF->set_value( m_xVertByMF->normalize(nY), FieldUnit::TWIP ); + } + m_xVertByFT->set_sensitive( bEnable ); + m_xVertByMF->set_sensitive( bEnable ); + UpdateExample(); +} + +void SvxSwPosSizeTabPage::UpdateExample() +{ + int nPos = m_xHoriLB->get_active(); + if (m_pHMap && nPos != -1) + { + sal_uInt16 nMapPos = GetMapPos(m_pHMap, *m_xHoriLB); + short nAlign = GetAlignment(m_pHMap, nMapPos, *m_xHoriToLB); + short nRel = GetRelation(*m_xHoriToLB); + + m_aExampleWN.SetHAlign(nAlign); + m_aExampleWN.SetHoriRel(nRel); + } + + nPos = m_xVertLB->get_active(); + if (m_pVMap && nPos != -1) + { + sal_uInt16 nMapPos = GetMapPos(m_pVMap, *m_xVertLB); + sal_uInt16 nAlign = GetAlignment(m_pVMap, nMapPos, *m_xVertToLB); + sal_uInt16 nRel = GetRelation(*m_xVertToLB); + + m_aExampleWN.SetVAlign(nAlign); + m_aExampleWN.SetVertRel(nRel); + } + + // Size + auto nXPos = m_xHoriByMF->denormalize(m_xHoriByMF->get_value(FieldUnit::TWIP)); + auto nYPos = m_xVertByMF->denormalize(m_xVertByMF->get_value(FieldUnit::TWIP)); + m_aExampleWN.SetRelPos(Point(nXPos, nYPos)); + + m_aExampleWN.SetAnchor( GetAnchorType() ); + m_aExampleWN.Invalidate(); +} + +void SvxSwPosSizeTabPage::FillRelLB(FrmMap const *pMap, sal_uInt16 nMapPos, sal_uInt16 nAlign, + sal_uInt16 nRel, weld::ComboBox& rLB, weld::Label& rFT) +{ + OUString sSelEntry; + LB nLBRelations = LB::NONE; + std::size_t nMapCount = ::lcl_GetFrmMapCount(pMap); + + rLB.clear(); + + if (nMapPos < nMapCount) + { + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap) + { + OUString sOldEntry(rLB.get_active_text()); + SvxSwFramePosString::StringId eStrId = pMap[nMapPos].eStrId; + + for (std::size_t _nMapPos = 0; _nMapPos < nMapCount; _nMapPos++) + { + if (pMap[_nMapPos].eStrId == eStrId) + { + nLBRelations = pMap[_nMapPos].nLBRelations; + for (size_t nRelPos = 0; nRelPos < std::size(aAsCharRelationMap); nRelPos++) + { + if (nLBRelations & aAsCharRelationMap[nRelPos].nLBRelation) + { + SvxSwFramePosString::StringId sStrId1 = aAsCharRelationMap[nRelPos].eStrId; + + sStrId1 = lcl_ChangeResIdToVerticalOrRTL(sStrId1, m_bIsVerticalFrame, m_bIsInRightToLeft); + OUString sEntry = SvxSwFramePosString::GetString(sStrId1); + rLB.append(weld::toId(&aAsCharRelationMap[nRelPos]), sEntry); + if (pMap[_nMapPos].nAlign == nAlign) + sSelEntry = sEntry; + break; + } + } + } + } + if (!sSelEntry.isEmpty()) + rLB.set_active_text(sSelEntry); + else + { + rLB.set_active_text(sOldEntry); + if (rLB.get_active() == -1) + { + for (int i = 0; i < rLB.get_count(); i++) + { + RelationMap *pEntry = weld::fromId<RelationMap*>(rLB.get_id(i)); + if (pEntry->nLBRelation == LB::RelChar) // Default + { + rLB.set_active(i); + break; + } + } + } + } + } + else + { + // #i22341# - special handling for map <aVCharMap>, + // because its ambiguous in its <eStrId>/<eMirrorStrId>. + if ( pMap == aVCharMap ) + { + nLBRelations = ::lcl_GetLBRelationsForStrID( pMap, + ( m_xHoriMirrorCB->get_active() + ? pMap[nMapPos].eMirrorStrId + : pMap[nMapPos].eStrId ), + m_xHoriMirrorCB->get_active() ); + } + else + { + nLBRelations = pMap[nMapPos].nLBRelations; + } + + for (sal_uLong nBit = 1; nBit < sal_uLong(LB::LAST); nBit <<= 1) + { + if (nLBRelations & static_cast<LB>(nBit)) + { + for (size_t nRelPos = 0; nRelPos < std::size(aRelationMap); nRelPos++) + { + if (aRelationMap[nRelPos].nLBRelation == static_cast<LB>(nBit)) + { + SvxSwFramePosString::StringId sStrId1 = m_xHoriMirrorCB->get_active() ? aRelationMap[nRelPos].eMirrorStrId : aRelationMap[nRelPos].eStrId; + sStrId1 = lcl_ChangeResIdToVerticalOrRTL(sStrId1, m_bIsVerticalFrame, m_bIsInRightToLeft); + OUString sEntry = SvxSwFramePosString::GetString(sStrId1); + rLB.append(weld::toId(&aRelationMap[nRelPos]), sEntry); + if (sSelEntry.isEmpty() && aRelationMap[nRelPos].nRelation == nRel) + sSelEntry = sEntry; + } + } + } + } + if (!sSelEntry.isEmpty()) + rLB.set_active_text(sSelEntry); + else + { + // Probably anchor change. So look for a similar relation. + switch (nRel) + { + case RelOrientation::FRAME: nRel = RelOrientation::PAGE_FRAME; break; + case RelOrientation::PRINT_AREA: nRel = RelOrientation::PAGE_PRINT_AREA; break; + case RelOrientation::PAGE_LEFT: nRel = RelOrientation::FRAME_LEFT; break; + case RelOrientation::PAGE_RIGHT: nRel = RelOrientation::FRAME_RIGHT; break; + case RelOrientation::FRAME_LEFT: nRel = RelOrientation::PAGE_LEFT; break; + case RelOrientation::FRAME_RIGHT: nRel = RelOrientation::PAGE_RIGHT; break; + case RelOrientation::PAGE_FRAME: nRel = RelOrientation::FRAME; break; + case RelOrientation::PAGE_PRINT_AREA: nRel = RelOrientation::PRINT_AREA; break; + + default: + if (rLB.get_count()) + { + RelationMap *pEntry = weld::fromId<RelationMap*>(rLB.get_id(rLB.get_count() - 1)); + nRel = pEntry->nRelation; + } + break; + } + + for (int i = 0; i < rLB.get_count(); ++i) + { + RelationMap *pEntry = weld::fromId<RelationMap*>(rLB.get_id(i)); + if (pEntry->nRelation == nRel) + { + rLB.set_active(i); + break; + } + } + + if (rLB.get_active() == -1) + rLB.set_active(0); + } + } + } + + rLB.set_sensitive(rLB.get_count() != 0); + rFT.set_sensitive(rLB.get_count() != 0); + + RelHdl(rLB); +} + +sal_uInt16 SvxSwPosSizeTabPage::FillPosLB(FrmMap const *_pMap, + sal_uInt16 _nAlign, + const sal_uInt16 _nRel, + weld::ComboBox& _rLB) +{ + OUString sSelEntry, sOldEntry; + sOldEntry = _rLB.get_active_text(); + + _rLB.clear(); + + // #i22341# - determine all possible listbox relations for + // given relation for map <aVCharMap> + const LB nLBRelations = (_pMap != aVCharMap) + ? LB::NONE + : ::lcl_GetLBRelationsForRelations( _nRel ); + + // fill listbox + std::size_t nCount = ::lcl_GetFrmMapCount(_pMap); + for (std::size_t i = 0; _pMap && i < nCount; ++i) + { + SvxSwFramePosString::StringId eStrId = m_xHoriMirrorCB->get_active() ? _pMap[i].eMirrorStrId : _pMap[i].eStrId; + eStrId = lcl_ChangeResIdToVerticalOrRTL(eStrId, m_bIsVerticalFrame, m_bIsInRightToLeft); + OUString sEntry(SvxSwFramePosString::GetString(eStrId)); + if (_rLB.find_text(sEntry) == -1) + { + // don't insert duplicate entries at character wrapped borders + _rLB.append_text(sEntry); + } + // #i22341# - add condition to handle map <aVCharMap> + // that is ambiguous in the alignment. + if ( _pMap[i].nAlign == _nAlign && + ( _pMap != aVCharMap || _pMap[i].nLBRelations & nLBRelations ) ) + { + sSelEntry = sEntry; + } + } + + _rLB.set_active_text(sSelEntry); + if (_rLB.get_active() == -1) + _rLB.set_active_text(sOldEntry); + + if (_rLB.get_active() == -1) + _rLB.set_active(0); + + PosHdl(_rLB); + + return GetMapPos(_pMap, _rLB); +} + +void SvxSwPosSizeTabPage::SetView( const SdrView* pSdrView ) +{ + m_pSdrView = pSdrView; + if(!m_pSdrView) + { + OSL_FAIL("No SdrView* set"); + return; + } + + // setting of the rectangle and the working area + m_aRect = m_pSdrView->GetAllMarkedRect(); + m_pSdrView->GetSdrPageView()->LogicToPagePos( m_aRect ); + + // get WorkArea + m_aWorkArea = m_pSdrView->GetWorkArea(); + + // consider anchor position (for Writer) + const SdrMarkList& rMarkList = m_pSdrView->GetMarkedObjectList(); + if( rMarkList.GetMarkCount() > 0 ) + { + const SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + m_aAnchorPos = pObj->GetAnchorPos(); + + if( m_aAnchorPos != Point(0,0) ) // -> Writer + { + for( size_t i = 1; i < rMarkList.GetMarkCount(); ++i ) + { + pObj = rMarkList.GetMark( i )->GetMarkedSdrObj(); + if( m_aAnchorPos != pObj->GetAnchorPos() ) + { + // different anchor positions -> disable positioning + m_xPosFrame->set_sensitive(false); + m_bPositioningDisabled = true; + return; + } + } + } + Point aPt = m_aAnchorPos * -1; + Point aPt2 = aPt; + + aPt += m_aWorkArea.TopLeft(); + m_aWorkArea.SetPos( aPt ); + + aPt2 += m_aRect.TopLeft(); + m_aRect.SetPos( aPt2 ); + } + + // this should happen via SID_ATTR_TRANSFORM_AUTOSIZE + if( rMarkList.GetMarkCount() != 1 ) + m_bIsMultiSelection = true; +#if OSL_DEBUG_LEVEL > 1 + else + { + const SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + SdrObjKind eKind = (SdrObjKind) pObj->GetObjIdentifier(); + if( ( pObj->GetObjInventor() == SdrInventor::Default ) && + ( eKind==SdrObjKind::Text || eKind==SdrObjKind::TitleText || eKind==SdrObjKind::OutlineText) && + pObj->HasText() ) + { + OSL_FAIL("AutoWidth/AutoHeight should be enabled"); + } + } +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tabarea.cxx b/cui/source/tabpages/tabarea.cxx new file mode 100644 index 000000000..d03199c7b --- /dev/null +++ b/cui/source/tabpages/tabarea.cxx @@ -0,0 +1,252 @@ +/* -*- 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 . + */ + +#include <sfx2/objsh.hxx> +#include <unotools/pathoptions.hxx> +#include <svx/svxids.hrc> + +#include <svx/xtable.hxx> +#include <svx/svdmodel.hxx> +#include <svx/drawitem.hxx> +#include <cuitabarea.hxx> + +SvxAreaTabDialog::SvxAreaTabDialog +( + weld::Window* pParent, + const SfxItemSet* pAttr, + SdrModel* pModel, + bool bShadow, + bool bSlideBackground +) + : SfxTabDialogController(pParent, "cui/ui/areadialog.ui", "AreaDialog", pAttr) + , mpDrawModel ( pModel ), + mpColorList ( pModel->GetColorList() ), + mpNewColorList ( pModel->GetColorList() ), + mpGradientList ( pModel->GetGradientList() ), + mpNewGradientList ( pModel->GetGradientList() ), + mpHatchingList ( pModel->GetHatchList() ), + mpNewHatchingList ( pModel->GetHatchList() ), + mpBitmapList ( pModel->GetBitmapList() ), + mpNewBitmapList ( pModel->GetBitmapList() ), + mpPatternList ( pModel->GetPatternList() ), + mpNewPatternList ( pModel->GetPatternList() ), + + mnColorListState ( ChangeType::NONE ), + mnBitmapListState ( ChangeType::NONE ), + mnPatternListState ( ChangeType::NONE ), + mnGradientListState ( ChangeType::NONE ), + mnHatchingListState ( ChangeType::NONE ) +{ + if (bSlideBackground) + AddTabPage("RID_SVXPAGE_AREA", SvxAreaTabPage::CreateWithSlideBackground, nullptr); + else + AddTabPage("RID_SVXPAGE_AREA", SvxAreaTabPage::Create, nullptr); + + if (bShadow) + { + AddTabPage("RID_SVXPAGE_SHADOW", SvxShadowTabPage::Create, nullptr); + } + else + { + RemoveTabPage( "RID_SVXPAGE_SHADOW" ); + } + + AddTabPage( "RID_SVXPAGE_TRANSPARENCE", SvxTransparenceTabPage::Create, nullptr); + + weld::Button& rBtnCancel = GetCancelButton(); + rBtnCancel.connect_clicked(LINK(this, SvxAreaTabDialog, CancelHdlImpl)); +} + +void SvxAreaTabDialog::SavePalettes() +{ + SfxObjectShell* pShell = SfxObjectShell::Current(); + if( mpNewColorList != mpDrawModel->GetColorList() ) + { + mpDrawModel->SetPropertyList( static_cast<XPropertyList *>(mpNewColorList.get()) ); + SvxColorListItem aColorListItem( mpNewColorList, SID_COLOR_TABLE ); + if ( pShell ) + pShell->PutItem( aColorListItem ); + else + mpDrawModel->GetItemPool().Put(aColorListItem,SID_COLOR_TABLE); + mpColorList = mpDrawModel->GetColorList(); + } + if( mpNewGradientList != mpDrawModel->GetGradientList() ) + { + mpDrawModel->SetPropertyList( static_cast<XPropertyList *>(mpNewGradientList.get()) ); + SvxGradientListItem aItem( mpNewGradientList, SID_GRADIENT_LIST ); + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_GRADIENT_LIST); + mpGradientList = mpDrawModel->GetGradientList(); + } + if( mpNewHatchingList != mpDrawModel->GetHatchList() ) + { + mpDrawModel->SetPropertyList( static_cast<XPropertyList *>(mpNewHatchingList.get()) ); + SvxHatchListItem aItem( mpNewHatchingList, SID_HATCH_LIST ); + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_HATCH_LIST); + mpHatchingList = mpDrawModel->GetHatchList(); + } + if( mpNewBitmapList != mpDrawModel->GetBitmapList() ) + { + mpDrawModel->SetPropertyList( static_cast<XPropertyList *>(mpNewBitmapList.get()) ); + SvxBitmapListItem aItem( mpNewBitmapList, SID_BITMAP_LIST ); + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_BITMAP_LIST); + mpBitmapList = mpDrawModel->GetBitmapList(); + } + if( mpNewPatternList != mpDrawModel->GetPatternList() ) + { + mpDrawModel->SetPropertyList( static_cast<XPropertyList *>(mpNewPatternList.get()) ); + SvxPatternListItem aItem( mpNewPatternList, SID_PATTERN_LIST ); + if( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem,SID_PATTERN_LIST); + mpPatternList = mpDrawModel->GetPatternList(); + } + + // save the tables when they have been changed + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aPath; + sal_Int32 nIndex = 0; + do + { + aPath = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + if( mnHatchingListState & ChangeType::MODIFIED ) + { + mpHatchingList->SetPath( aPath ); + mpHatchingList->Save(); + + SvxHatchListItem aItem( mpHatchingList, SID_HATCH_LIST ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem); + } + + if( mnBitmapListState & ChangeType::MODIFIED ) + { + mpBitmapList->SetPath( aPath ); + mpBitmapList->Save(); + + SvxBitmapListItem aItem( mpBitmapList, SID_BITMAP_LIST ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + { + mpDrawModel->GetItemPool().Put(aItem); + } + } + + if( mnPatternListState & ChangeType::MODIFIED ) + { + mpPatternList->SetPath( aPath ); + mpPatternList->Save(); + + SvxPatternListItem aItem( mpPatternList, SID_PATTERN_LIST ); + // ToolBoxControls are informed: + if( pShell ) + pShell->PutItem( aItem ); + else + mpDrawModel->GetItemPool().Put(aItem); + } + + if( mnGradientListState & ChangeType::MODIFIED ) + { + mpGradientList->SetPath( aPath ); + mpGradientList->Save(); + + SvxGradientListItem aItem( mpGradientList, SID_GRADIENT_LIST ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + { + mpDrawModel->GetItemPool().Put(aItem); + } + } + + if (mnColorListState & ChangeType::MODIFIED && mpColorList.is()) + { + SvxColorListItem aItem( mpColorList, SID_COLOR_TABLE ); + // ToolBoxControls are informed: + if ( pShell ) + pShell->PutItem( aItem ); + else + { + mpDrawModel->GetItemPool().Put(aItem); + } + } +} + +short SvxAreaTabDialog::Ok() +{ + SavePalettes(); + // RET_OK is returned, if at least one + // TabPage returns sal_True in FillItemSet(). + // This happens by default at the moment. + return SfxTabDialogController::Ok(); +} + +IMPL_LINK_NOARG(SvxAreaTabDialog, CancelHdlImpl, weld::Button&, void) +{ + SavePalettes(); + m_xDialog->response(RET_CANCEL); +} + +void SvxAreaTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_AREA") + { + static_cast<SvxAreaTabPage&>(rPage).SetColorList( mpColorList ); + static_cast<SvxAreaTabPage&>(rPage).SetGradientList( mpGradientList ); + static_cast<SvxAreaTabPage&>(rPage).SetHatchingList( mpHatchingList ); + static_cast<SvxAreaTabPage&>(rPage).SetBitmapList( mpBitmapList ); + static_cast<SvxAreaTabPage&>(rPage).SetPatternList( mpPatternList ); + static_cast<SvxAreaTabPage&>(rPage).SetGrdChgd( &mnGradientListState ); + static_cast<SvxAreaTabPage&>(rPage).SetHtchChgd( &mnHatchingListState ); + static_cast<SvxAreaTabPage&>(rPage).SetBmpChgd( &mnBitmapListState ); + static_cast<SvxAreaTabPage&>(rPage).SetPtrnChgd( &mnPatternListState ); + static_cast<SvxAreaTabPage&>(rPage).SetColorChgd( &mnColorListState ); + } + else if (rId == "RID_SVXPAGE_SHADOW") + { + static_cast<SvxShadowTabPage&>(rPage).SetColorList( mpColorList ); + static_cast<SvxShadowTabPage&>(rPage).SetColorChgd( &mnColorListState ); + } + else if (rId == "RID_SVXPAGE_TRANSPARENCE") + { + static_cast<SvxTransparenceTabPage&>(rPage).SetPageType( PageType::Area ); + static_cast<SvxTransparenceTabPage&>(rPage).SetDlgType( 0 ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tabline.cxx b/cui/source/tabpages/tabline.cxx new file mode 100644 index 000000000..1cf548850 --- /dev/null +++ b/cui/source/tabpages/tabline.cxx @@ -0,0 +1,207 @@ +/* -*- 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 . + */ + +#include <unotools/pathoptions.hxx> +#include <sfx2/objsh.hxx> +#include <svx/svxids.hrc> +#include <cuitabarea.hxx> +#include <cuitabline.hxx> +#include <svx/svdmodel.hxx> +#include <svx/xtable.hxx> +#include <svx/drawitem.hxx> + +SvxLineTabDialog::SvxLineTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + SdrModel* pModel, const SdrObject* pSdrObj, bool bHasObj) + : SfxTabDialogController(pParent, "cui/ui/linedialog.ui", "LineDialog", pAttr) + , pDrawModel(pModel) + , pObj(pSdrObj) + , pColorList(pModel->GetColorList()) + , mpNewColorList(pModel->GetColorList()) + , pDashList(pModel->GetDashList()) + , pNewDashList(pModel->GetDashList()) + , pLineEndList(pModel->GetLineEndList()) + , pNewLineEndList(pModel->GetLineEndList()) + , bObjSelected(bHasObj) + , nLineEndListState(ChangeType::NONE) + , nDashListState(ChangeType::NONE) + , mnColorListState(ChangeType::NONE) + , nPageType(PageType::Area) // We use it here primarily to get the right attributes with FillItemSet + , nPosDashLb(0) + , nPosLineEndLb(0) +{ + bool bLineOnly = false; + if( pObj && pObj->GetObjInventor() == SdrInventor::Default ) + { + switch( pObj->GetObjIdentifier() ) + { + case SdrObjKind::Line: + case SdrObjKind::PolyLine: + case SdrObjKind::PathLine: + case SdrObjKind::FreehandLine: + case SdrObjKind::Measure: + case SdrObjKind::Edge: + bLineOnly = true; + break; + + default: + break; + } + + } + + AddTabPage("RID_SVXPAGE_LINE", SvxLineTabPage::Create, nullptr); + if( bLineOnly ) + AddTabPage("RID_SVXPAGE_SHADOW", SvxShadowTabPage::Create, nullptr); + else + RemoveTabPage( "RID_SVXPAGE_SHADOW" ); + + AddTabPage("RID_SVXPAGE_LINE_DEF", SvxLineDefTabPage::Create, nullptr); + AddTabPage("RID_SVXPAGE_LINEEND_DEF", SvxLineEndDefTabPage::Create, nullptr); + + weld::Button& rBtnCancel = GetCancelButton(); + rBtnCancel.connect_clicked(LINK(this, SvxLineTabDialog, CancelHdlImpl)); +} + +void SvxLineTabDialog::SavePalettes() +{ + SfxObjectShell* pShell = SfxObjectShell::Current(); + if( mpNewColorList != pDrawModel->GetColorList() ) + { + pDrawModel->SetPropertyList( static_cast<XPropertyList *>(mpNewColorList.get()) ); + if ( pShell ) + pShell->PutItem( SvxColorListItem( mpNewColorList, SID_COLOR_TABLE ) ); + pColorList = pDrawModel->GetColorList(); + } + if( pNewDashList != pDrawModel->GetDashList() ) + { + pDrawModel->SetPropertyList( static_cast<XPropertyList *>(pNewDashList.get()) ); + if ( pShell ) + pShell->PutItem( SvxDashListItem( pNewDashList, SID_DASH_LIST ) ); + pDashList = pDrawModel->GetDashList(); + } + if( pNewLineEndList != pDrawModel->GetLineEndList() ) + { + pDrawModel->SetPropertyList( static_cast<XPropertyList *>(pNewLineEndList.get()) ); + if ( pShell ) + pShell->PutItem( SvxLineEndListItem( pNewLineEndList, SID_LINEEND_LIST ) ); + pLineEndList = pDrawModel->GetLineEndList(); + } + + // Save the tables when they have been changed + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aPath; + sal_Int32 nIndex = 0; + do + { + aPath = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + if( nDashListState & ChangeType::MODIFIED ) + { + pDashList->SetPath( aPath ); + pDashList->Save(); + + // Notify ToolBoxControls + if ( pShell ) + pShell->PutItem( SvxDashListItem( pDashList, SID_DASH_LIST ) ); + } + + if( nLineEndListState & ChangeType::MODIFIED ) + { + pLineEndList->SetPath( aPath ); + pLineEndList->Save(); + + // Notify ToolBoxControls + if ( pShell ) + pShell->PutItem( SvxLineEndListItem( pLineEndList, SID_LINEEND_LIST ) ); + } + + if( mnColorListState & ChangeType::MODIFIED ) + { + pColorList->SetPath( aPath ); + pColorList->Save(); + + // Notify ToolBoxControls + if ( pShell ) + pShell->PutItem( SvxColorListItem( pColorList, SID_COLOR_TABLE ) ); + } +} + +short SvxLineTabDialog::Ok() +{ + SavePalettes(); + + // We return RET_OK if at least one TabPage in FillItemSet() returns sal_True. + // We do this by default at the moment. + return SfxTabDialogController::Ok(); +} + +IMPL_LINK_NOARG(SvxLineTabDialog, CancelHdlImpl, weld::Button&, void) +{ + SavePalettes(); + + m_xDialog->response(RET_CANCEL); +} + +void SvxLineTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_LINE") + { + static_cast<SvxLineTabPage&>(rPage).SetDashList( pDashList ); + static_cast<SvxLineTabPage&>(rPage).SetLineEndList( pLineEndList ); + static_cast<SvxLineTabPage&>(rPage).SetDlgType( 0 ); + static_cast<SvxLineTabPage&>(rPage).SetPageType( nPageType ); + static_cast<SvxLineTabPage&>(rPage).SetPosDashLb( &nPosDashLb ); + static_cast<SvxLineTabPage&>(rPage).SetPosLineEndLb( &nPosLineEndLb ); + static_cast<SvxLineTabPage&>(rPage).SetDashChgd( &nDashListState ); + static_cast<SvxLineTabPage&>(rPage).SetLineEndChgd( &nLineEndListState ); + static_cast<SvxLineTabPage&>(rPage).SetObjSelected( bObjSelected ); + static_cast<SvxLineTabPage&>(rPage).Construct(); + static_cast<SvxLineTabPage&>(rPage).SetColorChgd( &mnColorListState ); + } + else if (rId == "RID_SVXPAGE_LINE_DEF") + { + static_cast<SvxLineDefTabPage&>(rPage).SetDashList( pDashList ); + static_cast<SvxLineDefTabPage&>(rPage).SetDlgType( 0 ); + static_cast<SvxLineDefTabPage&>(rPage).SetPageType( &nPageType ); + static_cast<SvxLineDefTabPage&>(rPage).SetPosDashLb( &nPosDashLb ); + static_cast<SvxLineDefTabPage&>(rPage).SetDashChgd( &nDashListState ); + static_cast<SvxLineDefTabPage&>(rPage).Construct(); + } + else if (rId == "RID_SVXPAGE_LINEEND_DEF") + { + static_cast<SvxLineEndDefTabPage&>(rPage).SetLineEndList( pLineEndList ); + static_cast<SvxLineEndDefTabPage&>(rPage).SetPolyObj( pObj ); + static_cast<SvxLineEndDefTabPage&>(rPage).SetDlgType( 0 ); + static_cast<SvxLineEndDefTabPage&>(rPage).SetPageType( &nPageType ); + static_cast<SvxLineEndDefTabPage&>(rPage).SetPosLineEndLb( &nPosLineEndLb ); + static_cast<SvxLineEndDefTabPage&>(rPage).SetLineEndChgd( &nLineEndListState ); + static_cast<SvxLineEndDefTabPage&>(rPage).Construct(); + } + else if (rId == "RID_SVXPAGE_SHADOW") + { + static_cast<SvxShadowTabPage&>(rPage).SetColorList( pColorList ); + static_cast<SvxShadowTabPage&>(rPage).SetPageType( nPageType ); + static_cast<SvxShadowTabPage&>(rPage).SetDlgType( 0 ); + static_cast<SvxShadowTabPage&>(rPage).SetColorChgd( &mnColorListState ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tabstpge.cxx b/cui/source/tabpages/tabstpge.cxx new file mode 100644 index 000000000..b3a1745c2 --- /dev/null +++ b/cui/source/tabpages/tabstpge.cxx @@ -0,0 +1,663 @@ +/* -*- 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 . + */ + +#include <svtools/ruler.hxx> +#include <svtools/unitconv.hxx> +#include <svx/svxids.hrc> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +#include <editeng/lrspitem.hxx> +#include <tabstpge.hxx> +#include <svx/dlgutil.hxx> +#include <svl/cjkoptions.hxx> +#include <unotools/localedatawrapper.hxx> +#include <svl/intitem.hxx> + +constexpr FieldUnit eDefUnit = FieldUnit::MM_100TH; + +const WhichRangesContainer SvxTabulatorTabPage::pRanges( + svl::Items<SID_ATTR_TABSTOP, SID_ATTR_TABSTOP_OFFSET>); + +static void FillUpWithDefTabs_Impl( tools::Long nDefDist, SvxTabStopItem& rTabs ) +{ + if( rTabs.Count() ) + return; + { + SvxTabStop aSwTabStop( nDefDist, SvxTabAdjust::Default ); + rTabs.Insert( aSwTabStop ); + } +} + +void TabWin_Impl::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + // Paint tabulators + Point aPoint; + Size aSize(GetOutputSizePixel()); + aPoint.setX( aSize.Width() / 2 ); + aPoint.setY( aSize.Height() / 2 ); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + rRenderContext.SetLineColor(rStyleSettings.GetShadowColor()); + rRenderContext.SetFillColor(rStyleSettings.GetDialogColor()); + rRenderContext.DrawRect(tools::Rectangle(Point(0,0), rRenderContext.GetOutputSize())); + Ruler::DrawTab(rRenderContext, rStyleSettings.GetDialogTextColor(), aPoint, nTabStyle); +} + +SvxTabulatorTabPage::SvxTabulatorTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "cui/ui/paratabspage.ui", "ParagraphTabsPage", &rAttr) + , aCurrentTab(0) + , aNewTabs(std::make_unique<SvxTabStopItem>(0, 0, SvxTabAdjust::Left, GetWhich(SID_ATTR_TABSTOP))) + , nDefDist(0) + , m_xTabSpin(m_xBuilder->weld_metric_spin_button("SP_TABPOS", FieldUnit::CM)) + , m_xTabBox(m_xBuilder->weld_entry_tree_view("tabgrid", "ED_TABPOS", "LB_TABPOS")) + , m_xCenterTab(m_xBuilder->weld_radio_button("radiobuttonBTN_TABTYPE_CENTER")) + , m_xDezTab(m_xBuilder->weld_radio_button("radiobuttonBTN_TABTYPE_DECIMAL")) + , m_xDezChar(m_xBuilder->weld_entry("entryED_TABTYPE_DECCHAR")) + , m_xDezCharLabel(m_xBuilder->weld_label("labelFT_TABTYPE_DECCHAR")) + // lower radio buttons + , m_xNoFillChar(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_NO")) + , m_xFillPoints(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_POINTS")) + , m_xFillDashLine(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_DASHLINE")) + , m_xFillSolidLine(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_UNDERSCORE")) + , m_xFillSpecial(m_xBuilder->weld_radio_button("radiobuttonBTN_FILLCHAR_OTHER")) + , m_xFillChar(m_xBuilder->weld_entry("entryED_FILLCHAR_OTHER")) + // button bar + , m_xNewBtn(m_xBuilder->weld_button("buttonBTN_NEW")) + , m_xDelAllBtn(m_xBuilder->weld_button("buttonBTN_DELALL")) + , m_xDelBtn(m_xBuilder->weld_button("buttonBTN_DEL")) + , m_xTypeFrame(m_xBuilder->weld_container("frameFL_TABTYPE")) + , m_xFillFrame(m_xBuilder->weld_container("frameFL_FILLCHAR")) + // the tab images + , m_xLeftWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABLEFT", m_aLeftWin)) + , m_xRightWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABRIGHT", m_aRightWin)) + , m_xCenterWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABCENTER", m_aCenterWin)) + , m_xDezWin(new weld::CustomWeld(*m_xBuilder, "drawingareaWIN_TABDECIMAL", m_aDezWin)) +{ + m_aLeftWin.SetTabStyle(sal_uInt16(RULER_TAB_LEFT|WB_HORZ)); + m_aRightWin.SetTabStyle(sal_uInt16(RULER_TAB_RIGHT|WB_HORZ)); + m_aCenterWin.SetTabStyle(sal_uInt16(RULER_TAB_CENTER|WB_HORZ)); + m_aDezWin.SetTabStyle(sal_uInt16(RULER_TAB_DECIMAL|WB_HORZ)); + //upper radiobuttons + m_xLeftTab = m_xBuilder->weld_radio_button(SvtCJKOptions::IsAsianTypographyEnabled() ? "radiobuttonST_LEFTTAB_ASIAN" : "radiobuttonBTN_TABTYPE_LEFT"); + m_xRightTab = m_xBuilder->weld_radio_button(SvtCJKOptions::IsAsianTypographyEnabled() ? "radiobuttonST_RIGHTTAB_ASIAN" : "radiobuttonBTN_TABTYPE_RIGHT"); + m_xLeftTab->show(); + m_xRightTab->show(); + + // This page needs ExchangeSupport + SetExchangeSupport(); + + // Set metric + FieldUnit eFUnit = GetModuleFieldUnit( rAttr ); + SetFieldUnit(*m_xTabSpin, eFUnit); + + // Initialize buttons + m_xNewBtn->connect_clicked(LINK(this,SvxTabulatorTabPage, NewHdl_Impl)); + m_xDelBtn->connect_clicked(LINK(this,SvxTabulatorTabPage, DelHdl_Impl)); + m_xDelAllBtn->connect_clicked(LINK(this,SvxTabulatorTabPage, DelAllHdl_Impl)); + + Link<weld::Toggleable&,void> aLink = LINK(this, SvxTabulatorTabPage, TabTypeCheckHdl_Impl); + m_xLeftTab->connect_toggled(aLink); + m_xRightTab->connect_toggled(aLink); + m_xDezTab->connect_toggled(aLink); + m_xCenterTab->connect_toggled(aLink); + + m_xDezChar->connect_focus_out(LINK(this, SvxTabulatorTabPage, GetDezCharHdl_Impl)); + m_xDezChar->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + + aLink = LINK(this, SvxTabulatorTabPage, FillTypeCheckHdl_Impl); + m_xNoFillChar->connect_toggled(aLink); + m_xFillPoints->connect_toggled(aLink); + m_xFillDashLine->connect_toggled(aLink); + m_xFillSolidLine->connect_toggled(aLink); + m_xFillSpecial->connect_toggled(aLink); + m_xFillChar->connect_focus_out(LINK(this, SvxTabulatorTabPage, GetFillCharHdl_Impl)); + m_xFillChar->set_sensitive(false); + + m_xTabBox->connect_row_activated(LINK(this, SvxTabulatorTabPage, SelectHdl_Impl)); + m_xTabBox->connect_changed(LINK(this, SvxTabulatorTabPage, ModifyHdl_Impl)); + m_xTabBox->connect_focus_out(LINK(this, SvxTabulatorTabPage, ReformatHdl_Impl)); + + // Get the default decimal char from the system + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + aCurrentTab.GetDecimal() = rLocaleWrapper.getNumDecimalSep()[0]; +} + +SvxTabulatorTabPage::~SvxTabulatorTabPage() +{ + m_xDezWin.reset(); + m_xCenterWin.reset(); + m_xRightWin.reset(); + m_xLeftWin.reset(); + m_xFillChar.reset(); + m_xDezChar.reset(); + m_xTabBox.reset(); +} + +bool SvxTabulatorTabPage::FillItemSet(SfxItemSet* rSet) +{ + bool bModified = false; + + // Put the controls' values in here + if (m_xNewBtn->get_sensitive()) + NewHdl_Impl(nullptr); + + // Call the LoseFocus-Handler first + GetDezCharHdl_Impl(*m_xDezChar); + GetFillCharHdl_Impl(*m_xFillChar); + + FillUpWithDefTabs_Impl(nDefDist, *aNewTabs); + SfxItemPool* pPool = rSet->GetPool(); + MapUnit eUnit = pPool->GetMetric(GetWhich(SID_ATTR_TABSTOP)); + const SfxPoolItem* pOld = GetOldItem(*rSet, SID_ATTR_TABSTOP); + + if (MapUnit::Map100thMM != eUnit) + { + // If the ItemSet contains a LRSpaceItem with negative first line indent, + // the TabStopItem needs to have a DefTab at position 0. + const SfxPoolItem* pLRSpace; + // If not in the new set, then maybe in the old one + if (SfxItemState::SET != rSet->GetItemState(GetWhich(SID_ATTR_LRSPACE), true, &pLRSpace)) + pLRSpace = GetOldItem(*rSet, SID_ATTR_LRSPACE); + + if (pLRSpace && static_cast<const SvxLRSpaceItem*>(pLRSpace)->GetTextFirstLineOffset() < 0) + { + SvxTabStop aNull(0, SvxTabAdjust::Default); + aNewTabs->Insert(aNull); + } + + std::unique_ptr<SvxTabStopItem> aTmp(aNewTabs->Clone()); + aTmp->Remove(0, aTmp->Count()); + + for (sal_uInt16 i = 0; i < aNewTabs->Count(); ++i) + { + SvxTabStop aTmpStop = (*aNewTabs)[i]; + aTmpStop.GetTabPos() = OutputDevice::LogicToLogic(aTmpStop.GetTabPos(), MapUnit::Map100thMM, eUnit); + aTmp->Insert(aTmpStop); + } + + if (!pOld || *static_cast<const SvxTabStopItem*>(pOld) != *aTmp) + { + rSet->Put(std::move(aTmp)); + bModified = true; + } + } + else if (!pOld || *static_cast<const SvxTabStopItem*>(pOld) != *aNewTabs) + { + rSet->Put(*aNewTabs); + bModified = true; + } + + return bModified; +} + +std::unique_ptr<SfxTabPage> SvxTabulatorTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxTabulatorTabPage>(pPage, pController, *rSet); +} + +void SvxTabulatorTabPage::Reset(const SfxItemSet* rSet) +{ + SfxItemPool* pPool = rSet->GetPool(); + MapUnit eUnit = pPool->GetMetric(GetWhich(SID_ATTR_TABSTOP)); + + // Current tabs + const SfxPoolItem* pItem = GetItem(*rSet, SID_ATTR_TABSTOP); + + if (pItem) + { + if (MapUnit::Map100thMM != eUnit) + { + std::unique_ptr<SvxTabStopItem> aTmp(static_cast<SvxTabStopItem*>(pItem->Clone())); + aNewTabs->Remove(0, aNewTabs->Count()); + + for (sal_uInt16 i = 0; i < aTmp->Count(); ++i) + { + SvxTabStop aTmpStop = (*aTmp)[i]; + aTmpStop.GetTabPos() = OutputDevice::LogicToLogic(aTmpStop.GetTabPos(), eUnit, MapUnit::Map100thMM); + aNewTabs->Insert(aTmpStop); + } + } + else + { + aNewTabs.reset(static_cast<SvxTabStopItem*>(pItem->Clone())); + } + } + else + { + aNewTabs->Remove(0, aNewTabs->Count()); + } + + // Default tab distance + nDefDist = SVX_TAB_DEFDIST; + pItem = GetItem(*rSet, SID_ATTR_TABSTOP_DEFAULTS); + + if (pItem) + nDefDist = OutputDevice::LogicToLogic(tools::Long(static_cast<const SfxUInt16Item*>(pItem)->GetValue()), eUnit, MapUnit::Map100thMM); + + // Tab pos currently selected + sal_uInt16 nTabPos = 0; + pItem = GetItem(*rSet, SID_ATTR_TABSTOP_POS); + + if (pItem) + nTabPos = static_cast<const SfxUInt16Item*>(pItem)->GetValue(); + + InitTabPos_Impl(nTabPos); +} + +void SvxTabulatorTabPage::DisableControls(const TabulatorDisableFlags nFlag) +{ + if (TabulatorDisableFlags::TypeLeft & nFlag) + { + m_xLeftTab->set_sensitive(false); + m_xLeftWin->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeRight & nFlag) + { + m_xRightTab->set_sensitive(false); + m_xRightWin->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeCenter & nFlag) + { + m_xCenterTab->set_sensitive(false); + m_xCenterWin->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeDecimal & nFlag) + { + m_xDezTab->set_sensitive(false); + m_xDezWin->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + m_xDezChar->set_sensitive(false); + } + if (TabulatorDisableFlags::TypeMask & nFlag) + m_xTypeFrame->set_sensitive(false); + if (TabulatorDisableFlags::FillNone & nFlag) + m_xNoFillChar->set_sensitive(false); + if (TabulatorDisableFlags::FillPoint & nFlag) + m_xFillPoints->set_sensitive(false); + if (TabulatorDisableFlags::FillDashLine & nFlag) + m_xFillDashLine->set_sensitive(false); + if (TabulatorDisableFlags::FillSolidLine & nFlag) + m_xFillSolidLine->set_sensitive(false); + if (TabulatorDisableFlags::FillSpecial & nFlag) + { + m_xFillSpecial->set_sensitive(false); + m_xFillChar->set_sensitive(false); + } + if (TabulatorDisableFlags::FillMask & nFlag) + m_xFillFrame->set_sensitive(false); +} + +DeactivateRC SvxTabulatorTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if ( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +void SvxTabulatorTabPage::InitTabPos_Impl( sal_uInt16 nTabPos ) +{ + m_xTabBox->clear(); + + tools::Long nOffset = 0; + if (const SfxInt32Item* pOffSetItem = GetItemSet().GetItemIfSet(SID_ATTR_TABSTOP_OFFSET)) + { + nOffset = pOffSetItem->GetValue(); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric(GetWhich(SID_ATTR_TABSTOP)); + nOffset = OutputDevice::LogicToLogic(nOffset, eUnit, MapUnit::Map100thMM); + } + + // Correct current TabPos and default tabs + for ( sal_uInt16 i = 0; i < aNewTabs->Count(); i++ ) + { + if ( (*aNewTabs)[i].GetAdjustment() != SvxTabAdjust::Default ) + { + m_xTabSpin->set_value(m_xTabSpin->normalize((*aNewTabs)[i].GetTabPos() + nOffset ), eDefUnit); + m_xTabBox->append_text(m_xTabSpin->get_text()); + } + else + { + aNewTabs->Remove( i-- ); + } + } + + // Select current tabulator + const sal_uInt16 nSize = aNewTabs->Count(); + + if ( nTabPos >= nSize ) + nTabPos = 0; + + // Switch off all RadioButtons for a start + m_xLeftTab->set_active(true); + m_xNoFillChar->set_active(true); + + if (m_xTabBox->get_count() > 0) + { + m_xTabBox->set_active(nTabPos); + aCurrentTab = (*aNewTabs)[nTabPos]; + + SetFillAndTabType_Impl(); + m_xNewBtn->set_sensitive(false); + m_xDelBtn->set_sensitive(true); + } + else + { // If no entry, 0 is the default value + m_xTabSpin->set_value(0, eDefUnit); + m_xTabBox->set_entry_text(m_xTabSpin->get_text()); + + m_xNewBtn->set_sensitive(true); + m_xDelBtn->set_sensitive(false); + } +} + +void SvxTabulatorTabPage::SetFillAndTabType_Impl() +{ + weld::RadioButton* pTypeBtn = nullptr; + weld::RadioButton* pFillBtn = nullptr; + + m_xDezChar->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + + if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Left ) + pTypeBtn = m_xLeftTab.get(); + else if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Right ) + pTypeBtn = m_xRightTab.get(); + else if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Decimal ) + { + pTypeBtn = m_xDezTab.get(); + m_xDezChar->set_sensitive(true); + m_xDezCharLabel->set_sensitive(true); + m_xDezChar->set_text(OUString(aCurrentTab.GetDecimal())); + } + else if ( aCurrentTab.GetAdjustment() == SvxTabAdjust::Center ) + pTypeBtn = m_xCenterTab.get(); + + if (pTypeBtn) + pTypeBtn->set_active(true); + + m_xFillChar->set_sensitive(false); + m_xFillChar->set_text(""); + + if ( aCurrentTab.GetFill() == ' ' ) + pFillBtn = m_xNoFillChar.get(); + else if ( aCurrentTab.GetFill() == '-' ) + pFillBtn = m_xFillDashLine.get(); + else if ( aCurrentTab.GetFill() == '_' ) + pFillBtn = m_xFillSolidLine.get(); + else if ( aCurrentTab.GetFill() == '.' ) + pFillBtn = m_xFillPoints.get(); + else + { + pFillBtn = m_xFillSpecial.get(); + m_xFillChar->set_sensitive(true); + m_xFillChar->set_text(OUString(aCurrentTab.GetFill())); + } + pFillBtn->set_active(true); +} + +IMPL_LINK(SvxTabulatorTabPage, NewHdl_Impl, weld::Button&, rBtn, void) +{ + NewHdl_Impl(&rBtn); +} + +void SvxTabulatorTabPage::NewHdl_Impl(const weld::Button* pBtn) +{ + // Add a new one and select it + // Get the value from the display + ReformatHdl_Impl(*m_xTabBox); + m_xTabSpin->set_text(m_xTabBox->get_active_text()); + auto nVal = m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); + + // If the pBtn == 0 && the value == 0 then do not create a tab, because we create via OK + if (nVal == 0 && pBtn == nullptr) + return; + + tools::Long nOffset = 0; + + if ( const SfxInt32Item* pOffsetItem = GetItemSet().GetItemIfSet( SID_ATTR_TABSTOP_OFFSET ) ) + { + nOffset = pOffsetItem->GetValue(); + MapUnit eUnit = GetItemSet().GetPool()->GetMetric( GetWhich( SID_ATTR_TABSTOP ) ); + nOffset = OutputDevice::LogicToLogic( nOffset, eUnit, MapUnit::Map100thMM ); + } + const tools::Long nReal = nVal - nOffset; + sal_Int32 nSize = m_xTabBox->get_count(); + + sal_Int32 i; + for( i = 0; i < nSize; i++ ) + { + if ( nReal < (*aNewTabs)[i].GetTabPos() ) + break; + } + + // Make ListBox entry + m_xTabSpin->set_value(m_xTabSpin->normalize(nVal), eDefUnit); + m_xTabBox->insert_text(i, m_xTabSpin->get_text()); + + aCurrentTab.GetTabPos() = nReal; + SvxTabAdjust eAdj = SvxTabAdjust::Left; + + if (m_xRightTab->get_active()) + eAdj = SvxTabAdjust::Right; + else if (m_xCenterTab->get_active()) + eAdj = SvxTabAdjust::Center; + else if (m_xDezTab->get_active()) + eAdj = SvxTabAdjust::Decimal; + + aCurrentTab.GetAdjustment() = eAdj; + aNewTabs->Insert( aCurrentTab ); + + m_xNewBtn->set_sensitive(false); + m_xDelBtn->set_sensitive(true); + m_xTabBox->grab_focus(); + + // Set the selection into the position Edit + m_xTabBox->select_entry_region(0, -1); +} + +int SvxTabulatorTabPage::FindCurrentTab() +{ + return m_xTabBox->find_text(FormatTab()); +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, DelHdl_Impl, weld::Button&, void) +{ + int nPos = FindCurrentTab(); + if (nPos == -1) + return; + + if (m_xTabBox->get_count() == 1) + { + DelAllHdl_Impl(*m_xDelAllBtn); + return; + } + + // Delete Tab + m_xTabBox->remove(nPos); + aNewTabs->Remove( nPos ); + + // Reset aCurrentTab + const sal_uInt16 nSize = aNewTabs->Count(); + + if ( nSize > 0 ) + { + // Correct Pos + nPos = ( ( nSize - 1 ) >= nPos) ? nPos : nPos - 1; + m_xTabBox->set_active(nPos); + aCurrentTab = (*aNewTabs)[nPos]; + } + + // If no Tabs Enable Disable Controls + if (m_xTabBox->get_count() == 0) + { + m_xDelBtn->set_sensitive(false); + m_xNewBtn->set_sensitive(true); + m_xTabBox->grab_focus(); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, DelAllHdl_Impl, weld::Button&, void) +{ + if ( aNewTabs->Count() ) + { + aNewTabs = std::make_unique<SvxTabStopItem>(GetWhich(SID_ATTR_TABSTOP)); + InitTabPos_Impl(); + } +} + +IMPL_LINK(SvxTabulatorTabPage, TabTypeCheckHdl_Impl, weld::Toggleable&, rBox, void) +{ + if (!rBox.get_active()) + return; + + SvxTabAdjust eAdj; + m_xDezChar->set_sensitive(false); + m_xDezCharLabel->set_sensitive(false); + m_xDezChar->set_text(""); + + if (&rBox == m_xLeftTab.get()) + eAdj = SvxTabAdjust::Left; + else if (&rBox == m_xRightTab.get()) + eAdj = SvxTabAdjust::Right; + else if (&rBox == m_xCenterTab.get()) + eAdj = SvxTabAdjust::Center; + else + { + eAdj = SvxTabAdjust::Decimal; + m_xDezChar->set_sensitive(true); + m_xDezCharLabel->set_sensitive(true); + m_xDezChar->set_text(OUString(aCurrentTab.GetDecimal())); + } + + aCurrentTab.GetAdjustment() = eAdj; + int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK(SvxTabulatorTabPage, FillTypeCheckHdl_Impl, weld::Toggleable&, rBox, void) +{ + if (!rBox.get_active()) + return; + + sal_uInt8 cFill = ' '; + m_xFillChar->set_text( "" ); + m_xFillChar->set_sensitive(false); + + if (&rBox == m_xFillSpecial.get()) + m_xFillChar->set_sensitive(true); + else if (&rBox == m_xNoFillChar.get()) + cFill = ' '; + else if (&rBox == m_xFillSolidLine.get()) + cFill = '_'; + else if (&rBox == m_xFillPoints.get()) + cFill = '.'; + else if (&rBox == m_xFillDashLine.get()) + cFill = '-'; + + aCurrentTab.GetFill() = cFill; + int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, GetFillCharHdl_Impl, weld::Widget&, void) +{ + OUString aChar(m_xFillChar->get_text()); + if ( !aChar.isEmpty() ) + aCurrentTab.GetFill() = aChar[0]; + + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, GetDezCharHdl_Impl, weld::Widget&, void) +{ + OUString aChar(m_xDezChar->get_text()); + if ( !aChar.isEmpty() && ( aChar[0] >= ' ')) + aCurrentTab.GetDecimal() = aChar[0]; + + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aNewTabs->Remove( nPos ); + aNewTabs->Insert( aCurrentTab ); + } +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, SelectHdl_Impl, weld::TreeView&, bool) +{ + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aCurrentTab = (*aNewTabs)[nPos]; + m_xNewBtn->set_sensitive(false); + SetFillAndTabType_Impl(); + } + return true; +} + +OUString SvxTabulatorTabPage::FormatTab() +{ + m_xTabSpin->set_text(m_xTabBox->get_active_text()); + m_xTabSpin->reformat(); + return m_xTabSpin->get_text(); +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, ReformatHdl_Impl, weld::Widget&, void) +{ + m_xTabBox->set_entry_text(FormatTab()); +} + +IMPL_LINK_NOARG(SvxTabulatorTabPage, ModifyHdl_Impl, weld::ComboBox&, void) +{ + const int nPos = FindCurrentTab(); + if (nPos != -1) + { + aCurrentTab = (*aNewTabs)[nPos]; + SetFillAndTabType_Impl(); + + m_xTabSpin->set_text(m_xTabBox->get_active_text()); + aCurrentTab.GetTabPos() = m_xTabSpin->denormalize(m_xTabSpin->get_value(eDefUnit)); + m_xNewBtn->set_sensitive(false); + m_xDelBtn->set_sensitive(true); + return; + } + m_xNewBtn->set_sensitive(true); + m_xDelBtn->set_sensitive(false); +} + +void SvxTabulatorTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pControlItem = aSet.GetItem<SfxUInt16Item>(SID_SVXTABULATORTABPAGE_DISABLEFLAGS, false); + if (pControlItem) + DisableControls(static_cast<TabulatorDisableFlags>(pControlItem->GetValue())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/textanim.cxx b/cui/source/tabpages/textanim.cxx new file mode 100644 index 000000000..e086969bb --- /dev/null +++ b/cui/source/tabpages/textanim.cxx @@ -0,0 +1,534 @@ +/* -*- 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 . + */ + +#include <textanim.hxx> +#include <textattr.hxx> +#include <TextColumnsPage.hxx> +#include <svx/dlgutil.hxx> +#include <svx/svdmark.hxx> +#include <svx/svdview.hxx> +#include <svx/sdtaaitm.hxx> +#include <svx/sdtacitm.hxx> +#include <svx/sdtaiitm.hxx> +#include <svx/sdtayitm.hxx> +#include <svtools/unitconv.hxx> + +const WhichRangesContainer SvxTextAnimationPage::pRanges( + svl::Items<SDRATTR_TEXT_ANIKIND, SDRATTR_TEXT_ANIAMOUNT>); + +/************************************************************************* +|* +|* constructor of the tab dialog: adds pages to the dialog +|* +\************************************************************************/ + +SvxTextTabDialog::SvxTextTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, const SdrView* pSdrView) + : SfxTabDialogController(pParent, "cui/ui/textdialog.ui", "TextDialog", pAttr) + , pView(pSdrView) +{ + AddTabPage("RID_SVXPAGE_TEXTATTR", SvxTextAttrPage::Create, nullptr); + AddTabPage("RID_SVXPAGE_TEXTANIMATION", SvxTextAnimationPage::Create, nullptr); + AddTabPage("RID_SVXPAGE_TEXTCOLUMNS", SvxTextColumnsPage::Create, nullptr); +} + +/************************************************************************* +|* +|* PageCreated() +|* +\************************************************************************/ + +void SvxTextTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId != "RID_SVXPAGE_TEXTATTR") + return; + + SdrObjKind eKind = SdrObjKind::NONE; + if (pView) + { + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + bool bHasMarked = rMarkList.GetMarkCount() > 0; + if (bHasMarked) + { + if (rMarkList.GetMarkCount() == 1) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + eKind = pObj->GetObjIdentifier(); + } + } + } + static_cast<SvxTextAttrPage&>(rPage).SetObjKind(eKind); + static_cast<SvxTextAttrPage&>(rPage).Construct(); +} + +/************************************************************************* +|* +|* Page +|* +\************************************************************************/ +SvxTextAnimationPage::SvxTextAnimationPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/textanimtabpage.ui", "TextAnimation", &rInAttrs) + , eAniKind(SdrTextAniKind::NONE) + , m_aUpState(TRISTATE_INDET) + , m_aLeftState(TRISTATE_INDET) + , m_aRightState(TRISTATE_INDET) + , m_aDownState(TRISTATE_INDET) + , m_xLbEffect(m_xBuilder->weld_combo_box("LB_EFFECT")) + , m_xBoxDirection(m_xBuilder->weld_widget("boxDIRECTION")) + , m_xBtnUp(m_xBuilder->weld_toggle_button("BTN_UP")) + , m_xBtnLeft(m_xBuilder->weld_toggle_button("BTN_LEFT")) + , m_xBtnRight(m_xBuilder->weld_toggle_button("BTN_RIGHT")) + , m_xBtnDown(m_xBuilder->weld_toggle_button("BTN_DOWN")) + , m_xFlProperties(m_xBuilder->weld_frame("FL_PROPERTIES")) + , m_xTsbStartInside(m_xBuilder->weld_check_button("TSB_START_INSIDE")) + , m_xTsbStopInside(m_xBuilder->weld_check_button("TSB_STOP_INSIDE")) + , m_xBoxCount(m_xBuilder->weld_widget("boxCOUNT")) + , m_xTsbEndless(m_xBuilder->weld_check_button("TSB_ENDLESS")) + , m_xNumFldCount(m_xBuilder->weld_spin_button("NUM_FLD_COUNT")) + , m_xTsbPixel(m_xBuilder->weld_check_button("TSB_PIXEL")) + , m_xMtrFldAmount(m_xBuilder->weld_metric_spin_button("MTR_FLD_AMOUNT", FieldUnit::PIXEL)) + , m_xTsbAuto(m_xBuilder->weld_check_button("TSB_AUTO")) + , m_xMtrFldDelay(m_xBuilder->weld_metric_spin_button("MTR_FLD_DELAY", FieldUnit::MILLISECOND)) +{ + eFUnit = GetModuleFieldUnit( rInAttrs ); + SfxItemPool* pPool = rInAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + eUnit = pPool->GetMetric( SDRATTR_TEXT_LEFTDIST ); + + m_xLbEffect->connect_changed( LINK( this, SvxTextAnimationPage, SelectEffectHdl_Impl ) ); + m_xTsbEndless->connect_toggled( LINK( this, SvxTextAnimationPage, ClickEndlessHdl_Impl ) ); + m_xTsbAuto->connect_toggled( LINK( this, SvxTextAnimationPage, ClickAutoHdl_Impl ) ); + m_xTsbPixel->connect_toggled( LINK( this, SvxTextAnimationPage, ClickPixelHdl_Impl ) ); + + Link<weld::Button&,void> aLink( LINK( this, SvxTextAnimationPage, ClickDirectionHdl_Impl ) ); + m_xBtnUp->connect_clicked( aLink ); + m_xBtnLeft->connect_clicked( aLink ); + m_xBtnRight->connect_clicked( aLink ); + m_xBtnDown->connect_clicked( aLink ); +} + +SvxTextAnimationPage::~SvxTextAnimationPage() +{ +} + +/************************************************************************* +|* +|* reads the passed item set +|* +\************************************************************************/ + +void SvxTextAnimationPage::Reset( const SfxItemSet* rAttrs ) +{ + const SfxItemPool* pPool = rAttrs->GetPool(); + + // animation type + const SfxPoolItem* pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIKIND ); + + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIKIND ); + + eAniKind = static_cast<const SdrTextAniKindItem*>(pItem)->GetValue(); + m_xLbEffect->set_active(sal::static_int_cast<sal_Int32>(eAniKind)); + m_xLbEffect->save_value(); + + // animation direction + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIDIRECTION ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIDIRECTION ); + + SelectDirection(static_cast<const SdrTextAniDirectionItem*>(pItem)->GetValue()); + m_aUpState = m_xBtnUp->get_state(); + m_aLeftState = m_xBtnLeft->get_state(); + m_aRightState = m_xBtnRight->get_state(); + m_aDownState = m_xBtnDown->get_state(); + + // Start inside + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANISTARTINSIDE ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANISTARTINSIDE ); + + if (static_cast<const SdrTextAniStartInsideItem*>(pItem)->GetValue()) + m_xTsbStartInside->set_state(TRISTATE_TRUE); + else + m_xTsbStartInside->set_state(TRISTATE_FALSE); + m_xTsbStartInside->save_state(); + + // Stop inside + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANISTOPINSIDE ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANISTOPINSIDE ); + + if (static_cast<const SdrTextAniStopInsideItem*>(pItem)->GetValue()) + m_xTsbStopInside->set_state(TRISTATE_TRUE); + else + m_xTsbStopInside->set_state(TRISTATE_FALSE); + m_xTsbStopInside->save_state(); + + // quantity + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANICOUNT ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANICOUNT ); + + tools::Long nValue = static_cast<tools::Long>(static_cast<const SdrTextAniCountItem*>(pItem)->GetValue()); + m_xNumFldCount->set_value(nValue); + if (nValue == 0) + { + if (eAniKind == SdrTextAniKind::Slide) + { + m_xTsbEndless->set_state(TRISTATE_FALSE); + m_xTsbEndless->set_sensitive(false); + } + else + { + m_xTsbEndless->set_state(TRISTATE_TRUE); + m_xNumFldCount->set_text(""); + } + } + else + m_xTsbEndless->set_state(TRISTATE_FALSE); + m_xTsbEndless->save_state(); + m_xNumFldCount->save_value(); + + // delay + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIDELAY ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIDELAY ); + + nValue = static_cast<tools::Long>(static_cast<const SdrTextAniDelayItem*>(pItem)->GetValue()); + m_xMtrFldDelay->set_value(nValue, FieldUnit::NONE); + if (nValue == 0) + { + m_xTsbAuto->set_state(TRISTATE_TRUE); + m_xMtrFldDelay->set_text(""); + } + else + m_xTsbAuto->set_state(TRISTATE_FALSE); + m_xTsbAuto->save_state(); + m_xMtrFldDelay->save_value(); + + // step size + pItem = GetItem( *rAttrs, SDRATTR_TEXT_ANIAMOUNT ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_ANIAMOUNT ); + + nValue = static_cast<tools::Long>(static_cast<const SdrTextAniAmountItem*>(pItem)->GetValue()); + if (nValue <= 0) + { + m_xTsbPixel->set_state(TRISTATE_TRUE); + nValue = -nValue; + if (nValue == 0) + nValue++; + m_xMtrFldAmount->set_unit(FieldUnit::CUSTOM); + m_xMtrFldAmount->set_digits(0); + + m_xMtrFldAmount->set_increments(1, 10, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 100, FieldUnit::NONE); + m_xMtrFldAmount->set_value(nValue, FieldUnit::NONE); + } + else + { + m_xTsbPixel->set_state(TRISTATE_FALSE); + m_xMtrFldAmount->set_unit(eFUnit); + m_xMtrFldAmount->set_digits(2); + + m_xMtrFldAmount->set_increments(10, 100, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 10000, FieldUnit::NONE); + + SetMetricValue(*m_xMtrFldAmount, nValue, eUnit); + } + m_xTsbPixel->save_state(); + m_xMtrFldAmount->save_value(); + + SelectEffectHdl_Impl(*m_xLbEffect); + ClickEndlessHdl_Impl(*m_xTsbEndless); + ClickAutoHdl_Impl(*m_xTsbAuto); +} + +/************************************************************************* +|* +|* fills the passed item set with dialog box attributes +|* +\************************************************************************/ + +bool SvxTextAnimationPage::FillItemSet( SfxItemSet* rAttrs) +{ + bool bModified = false; + TriState eState; + + // animation type + int nPos = m_xLbEffect->get_active(); + if( nPos != -1 && + m_xLbEffect->get_value_changed_from_saved() ) + { + rAttrs->Put( SdrTextAniKindItem( static_cast<SdrTextAniKind>(nPos) ) ); + bModified = true; + } + + // animation direction + if (m_aUpState != m_xBtnUp->get_state() || + m_aLeftState != m_xBtnLeft->get_state() || + m_aRightState != m_xBtnRight->get_state() || + m_aDownState != m_xBtnDown->get_state()) + { + SdrTextAniDirection eValue = static_cast<SdrTextAniDirection>(GetSelectedDirection()); + rAttrs->Put( SdrTextAniDirectionItem( eValue ) ); + bModified = true; + } + + // Start inside + eState = m_xTsbStartInside->get_state(); + if (m_xTsbStartInside->get_state_changed_from_saved()) + { + rAttrs->Put( SdrTextAniStartInsideItem( TRISTATE_TRUE == eState ) ); + bModified = true; + } + + // Stop inside + eState = m_xTsbStopInside->get_state(); + if (m_xTsbStopInside->get_state_changed_from_saved()) + { + rAttrs->Put( SdrTextAniStopInsideItem( TRISTATE_TRUE == eState ) ); + bModified = true; + } + + // quantity + eState = m_xTsbEndless->get_state(); + if (m_xTsbEndless->get_state_changed_from_saved() || + m_xNumFldCount->get_value_changed_from_saved()) + { + sal_Int64 nValue = 0; + if( eState == TRISTATE_TRUE /*#89844#*/ && m_xTsbEndless->get_sensitive()) + bModified = true; + else + { + if( m_xNumFldCount->get_value_changed_from_saved() ) + { + nValue = m_xNumFldCount->get_value(); + bModified = true; + } + } + if( bModified ) + rAttrs->Put( SdrTextAniCountItem( static_cast<sal_uInt16>(nValue) ) ); + } + + // delay + eState = m_xTsbAuto->get_state(); + if (m_xTsbAuto->get_state_changed_from_saved() || + m_xMtrFldDelay->get_value_changed_from_saved()) + { + sal_Int64 nValue = 0; + if( eState == TRISTATE_TRUE ) + bModified = true; + else + { + if( m_xMtrFldDelay->get_value_changed_from_saved() ) + { + nValue = m_xMtrFldDelay->get_value(FieldUnit::NONE); + bModified = true; + } + } + if( bModified ) + rAttrs->Put( SdrTextAniDelayItem( static_cast<sal_uInt16>(nValue) ) ); + } + + // step size + eState = m_xTsbPixel->get_state(); + if (m_xTsbPixel->get_state_changed_from_saved() || + m_xMtrFldAmount->get_value_changed_from_saved()) + { + sal_Int64 nValue = 0; + if( eState == TRISTATE_TRUE ) + { + nValue = m_xMtrFldAmount->get_value(FieldUnit::NONE); + nValue = -nValue; + } + else + { + nValue = GetCoreValue( *m_xMtrFldAmount, eUnit ); + } + rAttrs->Put( SdrTextAniAmountItem( static_cast<sal_Int16>(nValue) ) ); + + bModified = true; + } + + return bModified; +} + +/************************************************************************* +|* +|* creates the page +|* +\************************************************************************/ + +std::unique_ptr<SfxTabPage> SvxTextAnimationPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxTextAnimationPage>(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, SelectEffectHdl_Impl, weld::ComboBox&, void) +{ + int nPos = m_xLbEffect->get_active(); + if (nPos == -1) + return; + + eAniKind = static_cast<SdrTextAniKind>(nPos); + switch( eAniKind ) + { + case SdrTextAniKind::NONE: + { + m_xBoxDirection->set_sensitive(false); + m_xFlProperties->set_sensitive(false); + } + break; + + case SdrTextAniKind::Blink: + case SdrTextAniKind::Scroll: + case SdrTextAniKind::Alternate: + case SdrTextAniKind::Slide: + { + m_xFlProperties->set_sensitive(true); + if( eAniKind == SdrTextAniKind::Slide ) + { + m_xTsbStartInside->set_sensitive(false); + m_xTsbStopInside->set_sensitive(false); + m_xTsbEndless->set_sensitive(false); + m_xNumFldCount->set_sensitive(true); + m_xNumFldCount->set_value(m_xNumFldCount->get_value()); + } + else + { + m_xTsbStartInside->set_sensitive(true); + m_xTsbStopInside->set_sensitive(true); + m_xTsbEndless->set_sensitive(true); + ClickEndlessHdl_Impl(*m_xTsbEndless); + } + + m_xTsbAuto->set_sensitive(true); + ClickAutoHdl_Impl(*m_xTsbAuto); + + if( eAniKind == SdrTextAniKind::Blink ) + { + m_xBoxDirection->set_sensitive(false); + m_xBoxCount->set_sensitive(false); + } + else + { + m_xBoxDirection->set_sensitive(true); + m_xBoxCount->set_sensitive(true); + } + } + break; + } +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, ClickEndlessHdl_Impl, weld::Toggleable&, void) +{ + if( eAniKind == SdrTextAniKind::Slide ) + return; + + TriState eState = m_xTsbEndless->get_state(); + if( eState != TRISTATE_FALSE ) + { + m_xNumFldCount->set_sensitive(false); + m_xNumFldCount->set_text(""); + } + else + { + m_xNumFldCount->set_sensitive(true); + m_xNumFldCount->set_value(m_xNumFldCount->get_value()); + } +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, ClickAutoHdl_Impl, weld::Toggleable&, void) +{ + TriState eState = m_xTsbAuto->get_state(); + if( eState != TRISTATE_FALSE ) + { + m_xMtrFldDelay->set_sensitive(false); + m_xMtrFldDelay->set_text(""); + } + else + { + m_xMtrFldDelay->set_sensitive(true); + m_xMtrFldDelay->set_value(m_xMtrFldDelay->get_value(FieldUnit::NONE), FieldUnit::NONE); //to-do + } +} + +IMPL_LINK_NOARG(SvxTextAnimationPage, ClickPixelHdl_Impl, weld::Toggleable&, void) +{ + TriState eState = m_xTsbPixel->get_state(); + if (eState == TRISTATE_TRUE) + { + int nValue = m_xMtrFldAmount->get_value(FieldUnit::NONE) / 10; + m_xMtrFldAmount->set_sensitive(true); + m_xMtrFldAmount->set_unit(FieldUnit::CUSTOM); + m_xMtrFldAmount->set_digits(0); + + m_xMtrFldAmount->set_increments(1, 10, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 100, FieldUnit::NONE); + + m_xMtrFldAmount->set_value(nValue, FieldUnit::NONE); + } + else if( eState == TRISTATE_FALSE ) + { + int nValue = m_xMtrFldAmount->get_value(FieldUnit::NONE) * 10; + m_xMtrFldAmount->set_sensitive(true); + m_xMtrFldAmount->set_unit(eFUnit); + m_xMtrFldAmount->set_digits(2); + + m_xMtrFldAmount->set_increments(10, 100, FieldUnit::NONE); + m_xMtrFldAmount->set_range(1, 10000, FieldUnit::NONE); + + m_xMtrFldAmount->set_value(nValue, FieldUnit::NONE); + } +} + +IMPL_LINK(SvxTextAnimationPage, ClickDirectionHdl_Impl, weld::Button&, rBtn, void) +{ + m_xBtnUp->set_active(&rBtn == m_xBtnUp.get()); + m_xBtnLeft->set_active(&rBtn == m_xBtnLeft.get()); + m_xBtnRight->set_active(&rBtn == m_xBtnRight.get()); + m_xBtnDown->set_active(&rBtn == m_xBtnDown.get()); +} + +void SvxTextAnimationPage::SelectDirection( SdrTextAniDirection nValue ) +{ + m_xBtnUp->set_active( nValue == SdrTextAniDirection::Up ); + m_xBtnLeft->set_active( nValue == SdrTextAniDirection::Left ); + m_xBtnRight->set_active( nValue == SdrTextAniDirection::Right ); + m_xBtnDown->set_active( nValue == SdrTextAniDirection::Down ); +} + +sal_uInt16 SvxTextAnimationPage::GetSelectedDirection() const +{ + SdrTextAniDirection nValue = SdrTextAniDirection::Left; + + if( m_xBtnUp->get_active() ) + nValue = SdrTextAniDirection::Up; + else if( m_xBtnLeft->get_active() ) + nValue = SdrTextAniDirection::Left; + else if( m_xBtnRight->get_active() ) + nValue = SdrTextAniDirection::Right; + else if( m_xBtnDown->get_active() ) + nValue = SdrTextAniDirection::Down; + + return static_cast<sal_uInt16>(nValue); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/textattr.cxx b/cui/source/tabpages/textattr.cxx new file mode 100644 index 000000000..f773be6b8 --- /dev/null +++ b/cui/source/tabpages/textattr.cxx @@ -0,0 +1,665 @@ +/* -*- 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 . + */ + +#include <svx/svddef.hxx> +#include <svx/sdasitm.hxx> +#include <svx/sdtditm.hxx> +#include <svx/sdtagitm.hxx> +#include <svx/sdtaitm.hxx> +#include <svx/sdtfsitm.hxx> +#include <svx/sdtcfitm.hxx> +#include <svx/svxids.hrc> + +#include <textattr.hxx> +#include <svx/dlgutil.hxx> +#include <editeng/writingmodeitem.hxx> +#include <svtools/unitconv.hxx> +#include <osl/diagnose.h> + +using namespace ::com::sun::star; + +const WhichRangesContainer SvxTextAttrPage::pRanges( + svl::Items< + SDRATTR_MISC_FIRST ,SDRATTR_TEXT_HORZADJUST, + SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_WORDWRAP +>); + +/************************************************************************* +|* +|* dialog (page) for copying objects +|* +\************************************************************************/ +SvxTextAttrPage::SvxTextAttrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/textattrtabpage.ui", "TextAttributesPage", rInAttrs) + , rOutAttrs(rInAttrs) + , m_eObjKind(SdrObjKind::NONE) + , bAutoGrowSizeEnabled(false) + , bContourEnabled(false) + , bAutoGrowWidthEnabled(false) + , bAutoGrowHeightEnabled(false) + , bWordWrapTextEnabled(false) + , bFitToSizeEnabled(false) + , m_aCtlPosition(this) + , m_xDrawingText(m_xBuilder->weld_widget("drawingtext")) + , m_xCustomShapeText(m_xBuilder->weld_widget("customshapetext")) + , m_xTsbAutoGrowWidth(m_xBuilder->weld_check_button("TSB_AUTOGROW_WIDTH")) + , m_xTsbAutoGrowHeight(m_xBuilder->weld_check_button("TSB_AUTOGROW_HEIGHT")) + , m_xTsbFitToSize(m_xBuilder->weld_check_button("TSB_FIT_TO_SIZE")) + , m_xTsbContour(m_xBuilder->weld_check_button("TSB_CONTOUR")) + , m_xTsbWordWrapText(m_xBuilder->weld_check_button("TSB_WORDWRAP_TEXT")) + , m_xTsbAutoGrowSize(m_xBuilder->weld_check_button("TSB_AUTOGROW_SIZE")) + , m_xFlDistance(m_xBuilder->weld_frame("FL_DISTANCE")) + , m_xMtrFldLeft(m_xBuilder->weld_metric_spin_button("MTR_FLD_LEFT", FieldUnit::CM)) + , m_xMtrFldRight(m_xBuilder->weld_metric_spin_button("MTR_FLD_RIGHT", FieldUnit::CM)) + , m_xMtrFldTop(m_xBuilder->weld_metric_spin_button("MTR_FLD_TOP", FieldUnit::CM)) + , m_xMtrFldBottom(m_xBuilder->weld_metric_spin_button("MTR_FLD_BOTTOM", FieldUnit::CM)) + , m_xFlPosition(m_xBuilder->weld_frame("FL_POSITION")) + , m_xCtlPosition(new weld::CustomWeld(*m_xBuilder, "CTL_POSITION", m_aCtlPosition)) + , m_xTsbFullWidth(m_xBuilder->weld_check_button("TSB_FULL_WIDTH")) +{ + m_aCtlPosition.SetControlSettings(RectPoint::MM, 240); + + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xMtrFldLeft, eFUnit ); + SetFieldUnit( *m_xMtrFldRight, eFUnit ); + SetFieldUnit( *m_xMtrFldTop, eFUnit ); + SetFieldUnit( *m_xMtrFldBottom, eFUnit ); + + Link<weld::Toggleable&,void> aLink( LINK( this, SvxTextAttrPage, ClickHdl_Impl ) ); + m_xTsbAutoGrowWidth->connect_toggled( aLink ); + m_xTsbAutoGrowHeight->connect_toggled( aLink ); + m_xTsbAutoGrowSize->connect_toggled( aLink ); + m_xTsbFitToSize->connect_toggled( aLink ); + m_xTsbContour->connect_toggled( aLink ); + + m_xTsbFullWidth->connect_toggled(LINK( this, SvxTextAttrPage, ClickFullWidthHdl_Impl ) ); +} + +SvxTextAttrPage::~SvxTextAttrPage() +{ +} + +/************************************************************************* +|* +|* reads the passed item set +|* +\************************************************************************/ + +void SvxTextAttrPage::Reset( const SfxItemSet* rAttrs ) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + MapUnit eUnit = pPool->GetMetric( SDRATTR_TEXT_LEFTDIST ); + + const SdrMetricItem* pItem = GetItem(*rAttrs, SDRATTR_TEXT_LEFTDIST); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_LEFTDIST ); + + SetMetricValue(*m_xMtrFldLeft, pItem->GetValue(), eUnit); + m_xMtrFldLeft->save_value(); + + pItem = GetItem( *rAttrs, SDRATTR_TEXT_RIGHTDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_RIGHTDIST ); + + SetMetricValue(*m_xMtrFldRight, pItem->GetValue(), eUnit); + m_xMtrFldRight->save_value(); + + pItem = GetItem( *rAttrs, SDRATTR_TEXT_UPPERDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_UPPERDIST ); + + SetMetricValue(*m_xMtrFldTop, pItem->GetValue(), eUnit); + m_xMtrFldTop->save_value(); + + pItem = GetItem( *rAttrs, SDRATTR_TEXT_LOWERDIST ); + if( !pItem ) + pItem = &pPool->GetDefaultItem( SDRATTR_TEXT_LOWERDIST ); + + SetMetricValue(*m_xMtrFldBottom, pItem->GetValue(), eUnit); + m_xMtrFldBottom->save_value(); + + // adjust to height and autogrowsize + if ( rAttrs->GetItemState( SDRATTR_TEXT_AUTOGROWHEIGHT ) != SfxItemState::DONTCARE ) + { + m_xTsbAutoGrowHeight->set_state( rAttrs->Get( SDRATTR_TEXT_AUTOGROWHEIGHT ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + + m_xTsbAutoGrowSize->set_state( rAttrs->Get( SDRATTR_TEXT_AUTOGROWHEIGHT ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + { + m_xTsbAutoGrowHeight->set_state( TRISTATE_INDET ); + m_xTsbAutoGrowSize->set_state( TRISTATE_INDET ); + } + m_xTsbAutoGrowHeight->save_state(); + m_xTsbAutoGrowSize->save_state(); + + // adjust to width + if ( rAttrs->GetItemState( SDRATTR_TEXT_AUTOGROWWIDTH ) != SfxItemState::DONTCARE ) + { + m_xTsbAutoGrowWidth->set_state( rAttrs->Get( SDRATTR_TEXT_AUTOGROWWIDTH ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xTsbAutoGrowWidth->set_state( TRISTATE_INDET ); + m_xTsbAutoGrowWidth->save_state(); + + // wordwrap text + if ( rAttrs->GetItemState( SDRATTR_TEXT_WORDWRAP ) != SfxItemState::DONTCARE ) + { + m_xTsbWordWrapText->set_state( rAttrs->Get( SDRATTR_TEXT_WORDWRAP ). + GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xTsbWordWrapText->set_state( TRISTATE_INDET ); + m_xTsbWordWrapText->save_state(); + + + // #103516# Do the setup based on states of hor/ver adjust + // Setup center field and FullWidth + SfxItemState eVState = rAttrs->GetItemState( SDRATTR_TEXT_VERTADJUST ); + SfxItemState eHState = rAttrs->GetItemState( SDRATTR_TEXT_HORZADJUST ); + + if(SfxItemState::DONTCARE != eVState && SfxItemState::DONTCARE != eHState) + { + // VertAdjust and HorAdjust are unequivocal, thus + SdrTextVertAdjust eTVA = rAttrs->Get(SDRATTR_TEXT_VERTADJUST).GetValue(); + SdrTextHorzAdjust eTHA = rAttrs->Get(SDRATTR_TEXT_HORZADJUST).GetValue(); + RectPoint eRP = RectPoint::LB; + + if (m_xTsbFullWidth->get_state() == TRISTATE_INDET) + m_xTsbFullWidth->set_state(TRISTATE_FALSE); + + // Translate item values into local anchor position. + switch (eTVA) + { + case SDRTEXTVERTADJUST_TOP: + { + switch (eTHA) + { + case SDRTEXTHORZADJUST_LEFT: eRP = RectPoint::LT; break; + case SDRTEXTHORZADJUST_BLOCK: + case SDRTEXTHORZADJUST_CENTER: eRP = RectPoint::MT; break; + case SDRTEXTHORZADJUST_RIGHT: eRP = RectPoint::RT; break; + } + break; + } + case SDRTEXTVERTADJUST_BLOCK: + case SDRTEXTVERTADJUST_CENTER: + { + switch (eTHA) + { + case SDRTEXTHORZADJUST_LEFT: eRP = RectPoint::LM; break; + case SDRTEXTHORZADJUST_BLOCK: + case SDRTEXTHORZADJUST_CENTER: eRP = RectPoint::MM; break; + case SDRTEXTHORZADJUST_RIGHT: eRP = RectPoint::RM; break; + } + break; + } + case SDRTEXTVERTADJUST_BOTTOM: + { + switch (eTHA) + { + case SDRTEXTHORZADJUST_LEFT: eRP = RectPoint::LB; break; + case SDRTEXTHORZADJUST_BLOCK: + case SDRTEXTHORZADJUST_CENTER: eRP = RectPoint::MB; break; + case SDRTEXTHORZADJUST_RIGHT: eRP = RectPoint::RB; break; + } + break; + } + default: + break; + } + + // See if we have to check the "full width" check button. + bool bLeftToRight(IsTextDirectionLeftToRight()); + + if((bLeftToRight && (SDRTEXTHORZADJUST_BLOCK == eTHA)) || (!bLeftToRight && (SDRTEXTVERTADJUST_BLOCK == eTVA))) + { + // Move anchor to valid position. + ClickFullWidthHdl_Impl(*m_xTsbFullWidth); + m_xTsbFullWidth->set_state(TRISTATE_TRUE); + } + + m_aCtlPosition.SetActualRP( eRP ); + } + else + { + // VertAdjust or HorAdjust is not unequivocal + m_aCtlPosition.Reset(); + + m_aCtlPosition.SetState(CTL_STATE::NOVERT); + m_aCtlPosition.DoCompletelyDisable(true); + + m_xTsbFullWidth->set_state(TRISTATE_INDET); + m_xFlPosition->set_sensitive( false ); + } + + // adjust to border + if (rAttrs->GetItemState(SDRATTR_TEXT_FITTOSIZE) != SfxItemState::DONTCARE) + { + drawing::TextFitToSizeType const eFTS = + rAttrs->Get( SDRATTR_TEXT_FITTOSIZE ).GetValue(); + if (eFTS == drawing::TextFitToSizeType_AUTOFIT || eFTS == drawing::TextFitToSizeType_NONE) + m_xTsbFitToSize->set_state( TRISTATE_FALSE ); + else + m_xTsbFitToSize->set_state( TRISTATE_TRUE ); + } + else + m_xTsbFitToSize->set_state( TRISTATE_INDET ); + m_xTsbFitToSize->save_state(); + + if( rAttrs->GetItemState( SDRATTR_TEXT_CONTOURFRAME ) != SfxItemState::DONTCARE ) + { + bool bContour = rAttrs->Get( SDRATTR_TEXT_CONTOURFRAME ).GetValue(); + m_xTsbContour->set_state( bContour ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xTsbContour->set_state( TRISTATE_INDET ); + m_xTsbContour->save_state(); + + ClickHdl_Impl(*m_xTsbContour); +} + +/************************************************************************* +|* +|* fills the passed item set with dialog box attributes +|* +\************************************************************************/ + +bool SvxTextAttrPage::FillItemSet( SfxItemSet* rAttrs) +{ + SfxItemPool* pPool = rAttrs->GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + MapUnit eUnit = pPool->GetMetric( SDRATTR_TEXT_LEFTDIST ); + + sal_Int32 nValue; + TriState eState; + + if( m_xMtrFldLeft->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldLeft, eUnit ); + rAttrs->Put( makeSdrTextLeftDistItem( nValue ) ); + } + + if( m_xMtrFldRight->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldRight, eUnit ); + rAttrs->Put( makeSdrTextRightDistItem( nValue ) ); + } + + if( m_xMtrFldTop->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldTop, eUnit ); + rAttrs->Put( makeSdrTextUpperDistItem( nValue ) ); + } + + if( m_xMtrFldBottom->get_value_changed_from_saved() ) + { + nValue = GetCoreValue( *m_xMtrFldBottom, eUnit ); + rAttrs->Put( makeSdrTextLowerDistItem( nValue ) ); + } + + eState = m_xTsbAutoGrowHeight->get_state(); + if( m_xTsbAutoGrowHeight->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextAutoGrowHeightItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbAutoGrowWidth->get_state(); + if( m_xTsbAutoGrowWidth->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextAutoGrowWidthItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbAutoGrowSize->get_state(); + if( m_xTsbAutoGrowSize->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextAutoGrowHeightItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbWordWrapText->get_state(); + if( m_xTsbWordWrapText->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextWordWrapItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbContour->get_state(); + if( m_xTsbContour->get_state_changed_from_saved() ) + { + rAttrs->Put( makeSdrTextContourFrameItem( TRISTATE_TRUE == eState ) ); + } + + eState = m_xTsbFitToSize->get_state(); + if( m_xTsbFitToSize->get_state_changed_from_saved() ) + { + drawing::TextFitToSizeType eFTS; + switch( eState ) + { + default: ; //prevent warning + OSL_FAIL( "svx::SvxTextAttrPage::FillItemSet(), unhandled state!" ); + [[fallthrough]]; + case TRISTATE_FALSE: eFTS = drawing::TextFitToSizeType_AUTOFIT; break; + case TRISTATE_TRUE: eFTS = drawing::TextFitToSizeType_PROPORTIONAL; break; + } + rAttrs->Put( SdrTextFitToSizeTypeItem( eFTS ) ); + } + + // centered + RectPoint eRP = m_aCtlPosition.GetActualRP(); + SdrTextVertAdjust eTVA; + SdrTextHorzAdjust eTHA; + + switch( eRP ) + { + default: + case RectPoint::LT: eTVA = SDRTEXTVERTADJUST_TOP; + eTHA = SDRTEXTHORZADJUST_LEFT; break; + case RectPoint::LM: eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_LEFT; break; + case RectPoint::LB: eTVA = SDRTEXTVERTADJUST_BOTTOM; + eTHA = SDRTEXTHORZADJUST_LEFT; break; + case RectPoint::MT: eTVA = SDRTEXTVERTADJUST_TOP; + eTHA = SDRTEXTHORZADJUST_CENTER; break; + case RectPoint::MM: eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_CENTER; break; + case RectPoint::MB: eTVA = SDRTEXTVERTADJUST_BOTTOM; + eTHA = SDRTEXTHORZADJUST_CENTER; break; + case RectPoint::RT: eTVA = SDRTEXTVERTADJUST_TOP; + eTHA = SDRTEXTHORZADJUST_RIGHT; break; + case RectPoint::RM: eTVA = SDRTEXTVERTADJUST_CENTER; + eTHA = SDRTEXTHORZADJUST_RIGHT; break; + case RectPoint::RB: eTVA = SDRTEXTVERTADJUST_BOTTOM; + eTHA = SDRTEXTHORZADJUST_RIGHT; break; + } + + // #103516# Do not change values if adjust controls were disabled. + bool bIsDisabled(m_aCtlPosition.IsCompletelyDisabled()); + + if(bIsDisabled) + return true; + + if( m_xTsbFullWidth->get_state() == TRISTATE_TRUE ) + { + if (IsTextDirectionLeftToRight()) + eTHA = SDRTEXTHORZADJUST_BLOCK; + else + eTVA = SDRTEXTVERTADJUST_BLOCK; + } + + if ( rOutAttrs.GetItemState( SDRATTR_TEXT_VERTADJUST ) != SfxItemState::DONTCARE ) + { + SdrTextVertAdjust eOldTVA = rOutAttrs.Get( SDRATTR_TEXT_VERTADJUST ).GetValue(); + if( eOldTVA != eTVA ) + rAttrs->Put( SdrTextVertAdjustItem( eTVA ) ); + } + else + rAttrs->Put( SdrTextVertAdjustItem( eTVA ) ); + + if ( rOutAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST ) != SfxItemState::DONTCARE ) + { + SdrTextHorzAdjust eOldTHA = rOutAttrs.Get( SDRATTR_TEXT_HORZADJUST ).GetValue(); + if( eOldTHA != eTHA ) + rAttrs->Put( SdrTextHorzAdjustItem( eTHA ) ); + } + else + rAttrs->Put( SdrTextHorzAdjustItem( eTHA ) ); + + return true; +} + +void SvxTextAttrPage::Construct() +{ + switch (m_eObjKind) + { + case SdrObjKind::NONE: + // indeterminate, show them all + bFitToSizeEnabled = bContourEnabled = bWordWrapTextEnabled = + bAutoGrowSizeEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = true; + m_xCustomShapeText->show(); + m_xDrawingText->show(); + break; + case SdrObjKind::Text: + case SdrObjKind::TitleText: + case SdrObjKind::OutlineText: + case SdrObjKind::Caption: + // contour NOT possible for pure text objects + bContourEnabled = bWordWrapTextEnabled = bAutoGrowSizeEnabled = false; + + // adjusting width and height is ONLY possible for pure text objects + bFitToSizeEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = true; + m_xCustomShapeText->hide(); + m_xDrawingText->show(); + break; + case SdrObjKind::CustomShape: + bFitToSizeEnabled = bContourEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = false; + bWordWrapTextEnabled = bAutoGrowSizeEnabled = true; + m_xDrawingText->hide(); + m_xCustomShapeText->show(); + break; + default: + bFitToSizeEnabled = bContourEnabled = true; + bWordWrapTextEnabled = bAutoGrowSizeEnabled = bAutoGrowWidthEnabled = bAutoGrowHeightEnabled = false; + m_xCustomShapeText->hide(); + m_xDrawingText->show(); + break; + } + + m_xTsbAutoGrowHeight->set_visible( bAutoGrowHeightEnabled ); + m_xTsbAutoGrowWidth->set_visible( bAutoGrowWidthEnabled ); + m_xTsbFitToSize->set_visible( bFitToSizeEnabled ); + m_xTsbContour->set_visible( bContourEnabled ); + m_xTsbAutoGrowSize->set_visible( bAutoGrowSizeEnabled ); + m_xTsbWordWrapText->set_visible( bWordWrapTextEnabled ); +} + +std::unique_ptr<SfxTabPage> SvxTextAttrPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxTextAttrPage>(pPage, pController, *rAttrs); +} + +/** Check whether we have to uncheck the "Full width" check box. +*/ +void SvxTextAttrPage::PointChanged(weld::DrawingArea*, RectPoint eRP) +{ + if (m_xTsbFullWidth->get_state() != TRISTATE_TRUE) + return; + + // Depending on write direction and currently checked anchor we have + // to uncheck the "full width" button. + if (IsTextDirectionLeftToRight()) + switch( eRP ) + { + case RectPoint::LT: + case RectPoint::LM: + case RectPoint::LB: + case RectPoint::RT: + case RectPoint::RM: + case RectPoint::RB: + m_xTsbFullWidth->set_state( TRISTATE_FALSE ); + break; + default: ;//prevent warning + } + else + switch (eRP) + { + case RectPoint::LT: + case RectPoint::MT: + case RectPoint::RT: + case RectPoint::LB: + case RectPoint::MB: + case RectPoint::RB: + m_xTsbFullWidth->set_state( TRISTATE_FALSE ); + break; + default: ;//prevent warning + } +} + + +/************************************************************************* +|* +|* possibly changes the position of the position-control +|* +\************************************************************************/ + +/** When switching the "full width" check button on the text anchor may have + to be moved to a valid and adjacent position. This position depends on + the current anchor position and the text writing direction. +*/ +IMPL_LINK_NOARG(SvxTextAttrPage, ClickFullWidthHdl_Impl, weld::Toggleable&, void) +{ + if( m_xTsbFullWidth->get_state() != TRISTATE_TRUE ) + return; + + if (IsTextDirectionLeftToRight()) + { + // Move text anchor to horizontal middle axis. + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::RT: + m_aCtlPosition.SetActualRP( RectPoint::MT ); + break; + + case RectPoint::LM: + case RectPoint::RM: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::LB: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::MB ); + break; + default: ;//prevent warning + } + } + else + { + // Move text anchor to vertical middle axis. + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: + case RectPoint::LB: + m_aCtlPosition.SetActualRP( RectPoint::LM ); + break; + + case RectPoint::MT: + case RectPoint::MB: + m_aCtlPosition.SetActualRP( RectPoint::MM ); + break; + + case RectPoint::RT: + case RectPoint::RB: + m_aCtlPosition.SetActualRP( RectPoint::RM ); + break; + default: ;//prevent warning + } + } +} + +/************************************************************************* +|* +|* enables/disables "size at text" or "adjust to frame" +|* +\************************************************************************/ + +IMPL_LINK(SvxTextAttrPage, ClickHdl_Impl, weld::Toggleable&, rButton, void) +{ + if (&rButton == m_xTsbAutoGrowSize.get()) + { + m_xTsbAutoGrowHeight->set_state(m_xTsbAutoGrowSize->get_state()); + if (m_xTsbAutoGrowSize->get_state() == TRISTATE_TRUE) + { + m_xTsbFitToSize->set_state(TRISTATE_FALSE); + m_xTsbContour->set_state(TRISTATE_FALSE); + } + } + else if (&rButton == m_xTsbAutoGrowHeight.get()) + m_xTsbAutoGrowSize->set_state(m_xTsbAutoGrowHeight->get_state()); + + bool bAutoGrowWidth = m_xTsbAutoGrowWidth->get_state() == TRISTATE_TRUE; + bool bAutoGrowHeight = m_xTsbAutoGrowHeight->get_state() == TRISTATE_TRUE; + bool bFitToSize = m_xTsbFitToSize->get_state() == TRISTATE_TRUE; + bool bContour = m_xTsbContour->get_state() == TRISTATE_TRUE; + + m_xTsbContour->set_sensitive( !bFitToSize && + !( ( bAutoGrowWidth && bAutoGrowWidthEnabled ) || ( bAutoGrowHeight && bAutoGrowHeightEnabled ) ) && + bContourEnabled ); + + m_xTsbAutoGrowWidth->set_sensitive( !bFitToSize && + !( bContour && bContourEnabled ) && + bAutoGrowWidthEnabled ); + + m_xTsbAutoGrowHeight->set_sensitive( !bFitToSize && + !( bContour && bContourEnabled ) && + bAutoGrowHeightEnabled ); + + m_xTsbFitToSize->set_sensitive( !( ( bAutoGrowWidth && bAutoGrowWidthEnabled ) || ( bAutoGrowHeight && bAutoGrowHeightEnabled ) ) && + !( bContour && bContourEnabled ) && + bFitToSizeEnabled ); + + // #101901# enable/disable metric fields and decorations dependent of contour + m_xFlDistance->set_sensitive(!bContour); + + if( bContour && bContourEnabled ) + { + m_xMtrFldLeft->set_value(0, FieldUnit::NONE); + m_xMtrFldRight->set_value(0, FieldUnit::NONE); + m_xMtrFldTop->set_value(0, FieldUnit::NONE); + m_xMtrFldBottom->set_value(0, FieldUnit::NONE); + } + + // #103516# Do the setup based on states of hor/ver adjust + SfxItemState eVState = rOutAttrs.GetItemState( SDRATTR_TEXT_VERTADJUST ); + SfxItemState eHState = rOutAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST ); + bool bHorAndVer(SfxItemState::DONTCARE == eVState || SfxItemState::DONTCARE == eHState); + + // #83698# enable/disable text anchoring dependent of contour + m_xFlPosition->set_sensitive(!bContour && !bHorAndVer); +} + + +bool SvxTextAttrPage::IsTextDirectionLeftToRight() const +{ + // Determine the text writing direction with left to right as default. + bool bLeftToRightDirection = true; + SfxItemState eState = rOutAttrs.GetItemState(SDRATTR_TEXTDIRECTION); + + if(SfxItemState::DONTCARE != eState) + { + const SvxWritingModeItem& rItem = rOutAttrs.Get(SDRATTR_TEXTDIRECTION); + if (rItem.GetValue() == css::text::WritingMode_TB_RL) + bLeftToRightDirection = false; + } + return bLeftToRightDirection; +} + +void SvxTextAttrPage::PageCreated(const SfxAllItemSet& aSet) +{ + const CntUInt16Item* pObjTypeItem = aSet.GetItem<CntUInt16Item>(SID_SVXTEXTATTRPAGE_OBJKIND, false); + + if (pObjTypeItem) + SetObjKind(static_cast<SdrObjKind>(pObjTypeItem->GetValue())); + + Construct(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/themepage.cxx b/cui/source/tabpages/themepage.cxx new file mode 100644 index 000000000..a7ea42801 --- /dev/null +++ b/cui/source/tabpages/themepage.cxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <themepage.hxx> + +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/util/Color.hpp> + +#include <comphelper/sequence.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <editeng/editids.hrc> +#include <sal/log.hxx> +#include <svl/grabbagitem.hxx> +#include <svx/colorbox.hxx> + +using namespace com::sun::star; + +const WhichRangesContainer + SvxThemePage::m_pRanges(svl::Items<SID_ATTR_CHAR_GRABBAG, SID_ATTR_CHAR_GRABBAG>); + +SvxThemePage::SvxThemePage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/themetabpage.ui", "ThemePage", &rInAttrs) + , m_xThemeName(m_xBuilder->weld_entry("themeName")) + , m_xColorSetName(m_xBuilder->weld_entry("colorSetName")) + , m_xDk1(new ColorListBox(m_xBuilder->weld_menu_button("btnDk1"), + [this] { return GetDialogController()->getDialog(); })) + , m_xLt1(new ColorListBox(m_xBuilder->weld_menu_button("btnLt1"), + [this] { return GetDialogController()->getDialog(); })) + , m_xDk2(new ColorListBox(m_xBuilder->weld_menu_button("btnDk2"), + [this] { return GetDialogController()->getDialog(); })) + , m_xLt2(new ColorListBox(m_xBuilder->weld_menu_button("btnLt2"), + [this] { return GetDialogController()->getDialog(); })) + , m_xAccent1(new ColorListBox(m_xBuilder->weld_menu_button("btnAccent1"), + [this] { return GetDialogController()->getDialog(); })) + , m_xAccent2(new ColorListBox(m_xBuilder->weld_menu_button("btnAccent2"), + [this] { return GetDialogController()->getDialog(); })) + , m_xAccent3(new ColorListBox(m_xBuilder->weld_menu_button("btnAccent3"), + [this] { return GetDialogController()->getDialog(); })) + , m_xAccent4(new ColorListBox(m_xBuilder->weld_menu_button("btnAccent4"), + [this] { return GetDialogController()->getDialog(); })) + , m_xAccent5(new ColorListBox(m_xBuilder->weld_menu_button("btnAccent5"), + [this] { return GetDialogController()->getDialog(); })) + , m_xAccent6(new ColorListBox(m_xBuilder->weld_menu_button("btnAccent6"), + [this] { return GetDialogController()->getDialog(); })) + , m_xHlink(new ColorListBox(m_xBuilder->weld_menu_button("btnHlink"), + [this] { return GetDialogController()->getDialog(); })) + , m_xFolHlink(new ColorListBox(m_xBuilder->weld_menu_button("btnFolHlink"), + [this] { return GetDialogController()->getDialog(); })) +{ +} + +SvxThemePage::~SvxThemePage() = default; + +void SvxThemePage::Reset(const SfxItemSet* pAttrs) +{ + const SfxGrabBagItem* pGrabBagItem = pAttrs->GetItemIfSet(SID_ATTR_CHAR_GRABBAG); + if (!pGrabBagItem) + { + SAL_WARN("cui.tabpages", "SvxThemePage::Reset: no SfxGrabBagItem"); + return; + } + + auto itTheme = pGrabBagItem->GetGrabBag().find("Theme"); + if (itTheme == pGrabBagItem->GetGrabBag().end()) + { + // No theme was defined previously, allow specifying colors. + m_xDk1->set_sensitive(true); + m_xLt1->set_sensitive(true); + m_xDk2->set_sensitive(true); + m_xLt2->set_sensitive(true); + m_xAccent1->set_sensitive(true); + m_xAccent2->set_sensitive(true); + m_xAccent3->set_sensitive(true); + m_xAccent4->set_sensitive(true); + m_xAccent5->set_sensitive(true); + m_xAccent6->set_sensitive(true); + m_xHlink->set_sensitive(true); + m_xFolHlink->set_sensitive(true); + return; + } + + comphelper::SequenceAsHashMap aMap(itTheme->second); + auto it = aMap.find("Name"); + if (it != aMap.end()) + { + OUString aName; + it->second >>= aName; + m_xThemeName->set_text(aName); + } + + it = aMap.find("ColorSchemeName"); + if (it != aMap.end()) + { + OUString aName; + it->second >>= aName; + m_xColorSetName->set_text(aName); + } + + it = aMap.find("ColorScheme"); + if (it != aMap.end()) + { + uno::Sequence<util::Color> aColors; + it->second >>= aColors; + m_xDk1->SelectEntry(Color(ColorTransparency, aColors[0])); + m_xLt1->SelectEntry(Color(ColorTransparency, aColors[1])); + m_xDk2->SelectEntry(Color(ColorTransparency, aColors[2])); + m_xLt2->SelectEntry(Color(ColorTransparency, aColors[3])); + m_xAccent1->SelectEntry(Color(ColorTransparency, aColors[4])); + m_xAccent2->SelectEntry(Color(ColorTransparency, aColors[5])); + m_xAccent3->SelectEntry(Color(ColorTransparency, aColors[6])); + m_xAccent4->SelectEntry(Color(ColorTransparency, aColors[7])); + m_xAccent5->SelectEntry(Color(ColorTransparency, aColors[8])); + m_xAccent6->SelectEntry(Color(ColorTransparency, aColors[9])); + m_xHlink->SelectEntry(Color(ColorTransparency, aColors[10])); + m_xFolHlink->SelectEntry(Color(ColorTransparency, aColors[11])); + } +} + +bool SvxThemePage::FillItemSet(SfxItemSet* pAttrs) +{ + const SfxItemSet& rOldSet = GetItemSet(); + + if (!rOldSet.HasItem(SID_ATTR_CHAR_GRABBAG)) + return true; + + SfxGrabBagItem aGrabBagItem(rOldSet.Get(SID_ATTR_CHAR_GRABBAG)); + + comphelper::SequenceAsHashMap aMap; + auto it = aGrabBagItem.GetGrabBag().find("Theme"); + if (it != aGrabBagItem.GetGrabBag().end()) + { + aMap << it->second; + } + + aMap["Name"] <<= m_xThemeName->get_text(); + aMap["ColorSchemeName"] <<= m_xColorSetName->get_text(); + std::vector<util::Color> aColorScheme = { + static_cast<sal_Int32>(m_xDk1->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xLt1->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xDk2->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xLt2->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xAccent1->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xAccent2->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xAccent3->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xAccent4->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xAccent5->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xAccent6->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xHlink->GetSelectEntryColor()), + static_cast<sal_Int32>(m_xFolHlink->GetSelectEntryColor()), + }; + aMap["ColorScheme"] <<= comphelper::containerToSequence(aColorScheme); + + beans::PropertyValues aTheme = aMap.getAsConstPropertyValueList(); + aGrabBagItem.GetGrabBag()["Theme"] <<= aTheme; + pAttrs->Put(aGrabBagItem); + + return true; +} + +std::unique_ptr<SfxTabPage> SvxThemePage::Create(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxThemePage>(pPage, pController, *rAttrs); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/tabpages/tparea.cxx b/cui/source/tabpages/tparea.cxx new file mode 100644 index 000000000..bbdb9733a --- /dev/null +++ b/cui/source/tabpages/tparea.cxx @@ -0,0 +1,510 @@ +/* -*- 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 . + */ + +#include <svx/svxids.hrc> +#include <svx/xfillit0.hxx> +#include <svx/xfilluseslidebackgrounditem.hxx> +#include <svx/xflbckit.hxx> +#include <svx/drawitem.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <cuitabarea.hxx> +#include <sfx2/tabdlg.hxx> + +using namespace com::sun::star; + +// static ---------------------------------------------------------------- + +namespace { + +enum FillType +{ + TRANSPARENT, + SOLID, + GRADIENT, + HATCH, + BITMAP, + PATTERN, + USE_BACKGROUND_FILL +}; + +} + +const WhichRangesContainer SvxAreaTabPage::pAreaRanges( + svl::Items< + XATTR_GRADIENTSTEPCOUNT, XATTR_GRADIENTSTEPCOUNT, + SID_ATTR_FILL_STYLE, SID_ATTR_FILL_BITMAP>); + +namespace +{ + +void lclExtendSize(Size& rSize, const Size& rInputSize) +{ + if (rSize.Width() < rInputSize.Width()) + rSize.setWidth( rInputSize.Width() ); + if (rSize.Height() < rInputSize.Height()) + rSize.setHeight( rInputSize.Height() ); +} + +} // end anonymous namespace + +/************************************************************************* +|* +|* Dialog to modify fill-attributes +|* +\************************************************************************/ + +SvxAreaTabPage::SvxAreaTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rInAttrs, bool bSlideBackground) + : SfxTabPage(pPage, pController, "cui/ui/areatabpage.ui", "AreaTabPage", &rInAttrs) + // local fixed not o be changed values for local pointers + , maFixed_ChangeType(ChangeType::NONE) + // init with pointers to fixed ChangeType + , m_pnColorListState(&maFixed_ChangeType) + , m_pnBitmapListState(&maFixed_ChangeType) + , m_pnPatternListState(&maFixed_ChangeType) + , m_pnGradientListState(&maFixed_ChangeType) + , m_pnHatchingListState(&maFixed_ChangeType) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xFillTab(m_xBuilder->weld_container("fillstylebox")) + , m_xBtnNone(m_xBuilder->weld_toggle_button("btnnone")) + , m_xBtnColor(m_xBuilder->weld_toggle_button("btncolor")) + , m_xBtnGradient(m_xBuilder->weld_toggle_button("btngradient")) + , m_xBtnHatch(m_xBuilder->weld_toggle_button("btnhatch")) + , m_xBtnBitmap(m_xBuilder->weld_toggle_button("btnbitmap")) + , m_xBtnPattern(m_xBuilder->weld_toggle_button("btnpattern")) + , m_xBtnUseBackground(m_xBuilder->weld_toggle_button("btnusebackground")) +{ + maBox.AddButton(m_xBtnNone.get()); + maBox.AddButton(m_xBtnColor.get()); + maBox.AddButton(m_xBtnGradient.get()); + maBox.AddButton(m_xBtnHatch.get()); + maBox.AddButton(m_xBtnBitmap.get()); + maBox.AddButton(m_xBtnPattern.get()); + + Link<weld::Toggleable&, void> aLink = LINK(this, SvxAreaTabPage, SelectFillTypeHdl_Impl); + m_xBtnNone->connect_toggled(aLink); + m_xBtnColor->connect_toggled(aLink); + m_xBtnGradient->connect_toggled(aLink); + m_xBtnHatch->connect_toggled(aLink); + m_xBtnBitmap->connect_toggled(aLink); + m_xBtnPattern->connect_toggled(aLink); + if (bSlideBackground) + { + maBox.AddButton(m_xBtnUseBackground.get()); + m_xBtnUseBackground->connect_toggled(aLink); + } + else + m_xBtnUseBackground->hide(); + + SetExchangeSupport(); +} + +void SvxAreaTabPage::SetOptimalSize(weld::DialogController* pController) +{ + m_xFillTab->set_size_request(-1, -1); + + // Calculate optimal size of all pages... + m_xFillTabPage = SvxColorTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aSize(m_xFillTab->get_preferred_size()); + + if (m_xBtnGradient->get_visible()) + { + m_xFillTabPage = SvxGradientTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aGradientSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aGradientSize); + } + if (m_xBtnBitmap->get_visible()) + { + m_xFillTabPage = SvxBitmapTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aBitmapSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aBitmapSize); + } + if (m_xBtnHatch->get_visible()) + { + m_xFillTabPage = SvxHatchTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aHatchSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aHatchSize); + } + if (m_xBtnPattern->get_visible()) + { + m_xFillTabPage = SvxPatternTabPage::Create(m_xFillTab.get(), pController, &m_rXFSet); + Size aPatternSize = m_xFillTab->get_preferred_size(); + lclExtendSize(aSize, aPatternSize); + } + m_xFillTabPage.reset(); + + aSize.extendBy(10, 10); // apply a bit of margin + + m_xFillTab->set_size_request(aSize.Width(), aSize.Height()); +} + +SvxAreaTabPage::~SvxAreaTabPage() +{ + m_xFillTabPage.reset(); +} + +void SvxAreaTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + drawing::FillStyle eXFS = drawing::FillStyle_NONE; + if( rSet.GetItemState( XATTR_FILLSTYLE ) != SfxItemState::DONTCARE ) + { + XFillStyleItem aFillStyleItem( rSet.Get( GetWhich( XATTR_FILLSTYLE ) ) ); + eXFS = aFillStyleItem.GetValue(); + m_rXFSet.Put( aFillStyleItem ); + } + + switch(eXFS) + { + default: + case drawing::FillStyle_NONE: + { + XFillUseSlideBackgroundItem aBckItem( rSet.Get(XATTR_FILLUSESLIDEBACKGROUND)); + if (aBckItem.GetValue()) + SelectFillType(*m_xBtnUseBackground); + else + SelectFillType(*m_xBtnNone); + break; + } + case drawing::FillStyle_SOLID: + { + m_rXFSet.Put( rSet.Get( GetWhich( XATTR_FILLCOLOR ) ) ); + SelectFillType(*m_xBtnColor); + break; + } + case drawing::FillStyle_GRADIENT: + { + m_rXFSet.Put( rSet.Get( GetWhich( XATTR_FILLGRADIENT ) ) ); + SelectFillType(*m_xBtnGradient); + break; + } + case drawing::FillStyle_HATCH: + { + m_rXFSet.Put( rSet.Get(XATTR_FILLHATCH) ); + m_rXFSet.Put( rSet.Get(XATTR_FILLUSESLIDEBACKGROUND) ); + m_rXFSet.Put( rSet.Get(XATTR_FILLCOLOR) ); + SelectFillType(*m_xBtnHatch); + break; + } + case drawing::FillStyle_BITMAP: + { + const bool bPattern = rSet.Get(GetWhich(XATTR_FILLBITMAP)).isPattern(); + // pass full item set here, bitmap fill has many attributes (tiling, size, offset etc.) + m_rXFSet.Put( rSet ); + if (!bPattern) + SelectFillType(*m_xBtnBitmap); + else + SelectFillType(*m_xBtnPattern); + break; + } + } +} + +template< typename TTabPage > +DeactivateRC SvxAreaTabPage::DeactivatePage_Impl( SfxItemSet* _pSet ) +{ + return static_cast<TTabPage&>(*m_xFillTabPage).DeactivatePage(_pSet); +} + +DeactivateRC SvxAreaTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + FillType eFillType = static_cast<FillType>(maBox.GetCurrentButtonPos()); + switch( eFillType ) + { + case TRANSPARENT: + { + // Fill: None doesn't have its own tabpage and thus + // implementation of FillItemSet, so we supply it here + if ( m_bBtnClicked ) + { + XFillStyleItem aStyleItem( drawing::FillStyle_NONE ); + _pSet->Put( aStyleItem ); + if (_pSet->HasItem(XATTR_FILLUSESLIDEBACKGROUND)) + { + XFillUseSlideBackgroundItem aFillBgItem( false ); + _pSet->Put( aFillBgItem ); + } + } + break; + } + case SOLID: + return DeactivatePage_Impl<SvxColorTabPage>(_pSet); + case GRADIENT: + return DeactivatePage_Impl<SvxGradientTabPage>(_pSet); + case HATCH: + return DeactivatePage_Impl<SvxHatchTabPage>(_pSet); + case BITMAP: + return DeactivatePage_Impl<SvxBitmapTabPage&>(_pSet); + case PATTERN: + return DeactivatePage_Impl<SvxPatternTabPage>(_pSet); + case USE_BACKGROUND_FILL: + { + if ( m_bBtnClicked ) + { + XFillStyleItem aStyleItem( drawing::FillStyle_NONE ); + _pSet->Put( aStyleItem ); + XFillUseSlideBackgroundItem aFillBgItem( true ); + _pSet->Put( aFillBgItem ); + } + break; + } + default: + break; + } + return DeactivateRC::LeavePage; +} + +template< typename TTabPage > +bool SvxAreaTabPage::FillItemSet_Impl( SfxItemSet* rAttrs) +{ + return static_cast<TTabPage&>( *m_xFillTabPage ).FillItemSet( rAttrs ); +} + +bool SvxAreaTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + FillType eFillType = static_cast<FillType>(maBox.GetCurrentButtonPos()); + switch( eFillType ) + { + case TRANSPARENT: + { + rAttrs->Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + rAttrs->Put( XFillUseSlideBackgroundItem( false ) ); + return true; + } + case SOLID: + { + return FillItemSet_Impl<SvxColorTabPage>( rAttrs ); + } + case GRADIENT: + { + return FillItemSet_Impl<SvxGradientTabPage>( rAttrs ); + } + case HATCH: + { + return FillItemSet_Impl<SvxHatchTabPage>( rAttrs ); + } + case BITMAP: + { + return FillItemSet_Impl<SvxBitmapTabPage>( rAttrs ); + } + case PATTERN: + { + return FillItemSet_Impl<SvxPatternTabPage>( rAttrs ); + } + case USE_BACKGROUND_FILL: + { + rAttrs->Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + rAttrs->Put( XFillUseSlideBackgroundItem( true ) ); + return true; + } + default: + return false; + } +} + +template< typename TTabPage > +void SvxAreaTabPage::Reset_Impl( const SfxItemSet* rAttrs ) +{ + static_cast<TTabPage&>( *m_xFillTabPage ).Reset( rAttrs ); +} + +void SvxAreaTabPage::Reset( const SfxItemSet* rAttrs ) +{ + m_bBtnClicked = false; + auto eFillType = maBox.GetCurrentButtonPos(); + switch(eFillType) + { + case SOLID: + { + Reset_Impl<SvxColorTabPage>( rAttrs ); + break; + } + case GRADIENT: + { + Reset_Impl<SvxGradientTabPage>( rAttrs ); + break; + } + case HATCH: + { + Reset_Impl<SvxHatchTabPage>( rAttrs ); + break; + } + case BITMAP: + { + Reset_Impl<SvxBitmapTabPage>( rAttrs ); + break; + } + case PATTERN: + { + Reset_Impl<SvxPatternTabPage>( rAttrs ); + break; + } + default: + break; + } +} + +std::unique_ptr<SfxTabPage> SvxAreaTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + auto xRet = std::make_unique<SvxAreaTabPage>(pPage, pController, *rAttrs); + xRet->SetOptimalSize(pController); + return xRet; +} + +std::unique_ptr<SfxTabPage> SvxAreaTabPage::CreateWithSlideBackground( + weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + auto xRet = std::make_unique<SvxAreaTabPage>(pPage, pController, *rAttrs, true); + xRet->SetOptimalSize(pController); + return xRet; +} + +namespace { + +std::unique_ptr<SfxTabPage> lcl_CreateFillStyleTabPage(sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) +{ + CreateTabPage fnCreate = nullptr; + switch(nId) + { + case TRANSPARENT: fnCreate = nullptr; break; + case SOLID: fnCreate = &SvxColorTabPage::Create; break; + case GRADIENT: fnCreate = &SvxGradientTabPage::Create; break; + case HATCH: fnCreate = &SvxHatchTabPage::Create; break; + case BITMAP: fnCreate = &SvxBitmapTabPage::Create; break; + case PATTERN: fnCreate = &SvxPatternTabPage::Create; break; + case USE_BACKGROUND_FILL: fnCreate = nullptr; break; + } + return fnCreate ? (*fnCreate)( pPage, pController, &rSet ) : nullptr; +} + +} + +IMPL_LINK(SvxAreaTabPage, SelectFillTypeHdl_Impl, weld::Toggleable&, rButton, void) +{ + //tdf#124549 - If the button is already active do not toggle it back. + if(!rButton.get_active()) + rButton.set_active(true); + + SelectFillType(rButton); + m_bBtnClicked = true; +} + +void SvxAreaTabPage::SelectFillType(weld::Toggleable& rButton, const SfxItemSet* _pSet) +{ + if (_pSet) + m_rXFSet.Set(*_pSet); + + sal_Int32 nPos = maBox.GetButtonPos(&rButton); + if (nPos != -1 && (_pSet || nPos != maBox.GetCurrentButtonPos())) + { + maBox.SelectButton(&rButton); + FillType eFillType = static_cast<FillType>(maBox.GetCurrentButtonPos()); + m_xFillTabPage = lcl_CreateFillStyleTabPage(eFillType, m_xFillTab.get(), GetDialogController(), m_rXFSet); + if (m_xFillTabPage) + { + m_xFillTabPage->SetDialogController(GetDialogController()); + CreatePage(eFillType, *m_xFillTabPage); + } + } +} + +void SvxAreaTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxColorListItem* pColorListItem = aSet.GetItem<SvxColorListItem>(SID_COLOR_TABLE, false); + const SvxGradientListItem* pGradientListItem = aSet.GetItem<SvxGradientListItem>(SID_GRADIENT_LIST, false); + const SvxHatchListItem* pHatchingListItem = aSet.GetItem<SvxHatchListItem>(SID_HATCH_LIST, false); + const SvxBitmapListItem* pBitmapListItem = aSet.GetItem<SvxBitmapListItem>(SID_BITMAP_LIST, false); + const SvxPatternListItem* pPatternListItem = aSet.GetItem<SvxPatternListItem>(SID_PATTERN_LIST, false); + + if (pColorListItem) + SetColorList(pColorListItem->GetColorList()); + if (pGradientListItem) + SetGradientList(pGradientListItem->GetGradientList()); + if (pHatchingListItem) + SetHatchingList(pHatchingListItem->GetHatchList()); + if (pBitmapListItem) + SetBitmapList(pBitmapListItem->GetBitmapList()); + if (pPatternListItem) + SetPatternList(pPatternListItem->GetPatternList()); +} + +void SvxAreaTabPage::CreatePage(sal_Int32 nId, SfxTabPage& rTab) +{ + if(nId == SOLID ) + { + auto& rColorTab = static_cast<SvxColorTabPage&>(rTab); + rColorTab.SetColorList(m_pColorList); + rColorTab.SetColorChgd(m_pnColorListState); + rColorTab.Construct(); + rColorTab.ActivatePage(m_rXFSet); + rColorTab.Reset(&m_rXFSet); + rColorTab.set_visible(true); + } + else if(nId == GRADIENT) + { + auto& rGradientTab = static_cast<SvxGradientTabPage&>(rTab); + rGradientTab.SetColorList(m_pColorList); + rGradientTab.SetGradientList(m_pGradientList); + rGradientTab.SetGrdChgd(m_pnGradientListState); + rGradientTab.SetColorChgd(m_pnColorListState); + rGradientTab.Construct(); + rGradientTab.ActivatePage(m_rXFSet); + rGradientTab.Reset(&m_rXFSet); + rGradientTab.set_visible(true); + } + else if(nId == HATCH) + { + auto& rHatchTab = static_cast<SvxHatchTabPage&>(rTab); + rHatchTab.SetColorList(m_pColorList); + rHatchTab.SetHatchingList(m_pHatchingList); + rHatchTab.SetHtchChgd(m_pnHatchingListState); + rHatchTab.SetColorChgd(m_pnColorListState); + rHatchTab.Construct(); + rHatchTab.ActivatePage(m_rXFSet); + rHatchTab.Reset(&m_rXFSet); + rHatchTab.set_visible(true); + } + else if(nId == BITMAP) + { + auto& rBitmapTab = static_cast<SvxBitmapTabPage&>(rTab); + rBitmapTab.SetBitmapList(m_pBitmapList); + rBitmapTab.SetBmpChgd(m_pnBitmapListState); + rBitmapTab.Construct(); + rBitmapTab.ActivatePage(m_rXFSet); + rBitmapTab.Reset(&m_rXFSet); + rBitmapTab.set_visible(true); + } + else if(nId == PATTERN) + { + auto& rPatternTab = static_cast<SvxPatternTabPage&>(rTab); + rPatternTab.SetColorList(m_pColorList); + rPatternTab.SetPatternList(m_pPatternList); + rPatternTab.SetPtrnChgd(m_pnPatternListState); + rPatternTab.SetColorChgd(m_pnColorListState); + rPatternTab.Construct(); + rPatternTab.ActivatePage(m_rXFSet); + rPatternTab.Reset(&m_rXFSet); + rPatternTab.set_visible(true); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpbitmap.cxx b/cui/source/tabpages/tpbitmap.cxx new file mode 100644 index 000000000..bf3b742a1 --- /dev/null +++ b/cui/source/tabpages/tpbitmap.cxx @@ -0,0 +1,824 @@ +/* -*- 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 . + */ + +#include <memory> +#include <stdlib.h> +#include <tools/urlobj.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/svxids.hrc> +#include <strings.hrc> +#include <svx/xfillit0.hxx> +#include <svx/xtable.hxx> +#include <svx/xflbmsxy.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbmsli.hxx> +#include <svx/xflbmpit.hxx> +#include <svx/xflboxy.hxx> +#include <svx/xflbtoxy.hxx> +#include <cuitabarea.hxx> +#include <dialmgr.hxx> +#include <svx/dlgutil.hxx> +#include <svl/intitem.hxx> +#include <sfx2/opengrf.hxx> +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svx/svxdlg.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/dialoghelper.hxx> +#include <sal/log.hxx> +#include <comphelper/lok.hxx> +#include <svtools/unitconv.hxx> + +using namespace com::sun::star; + +namespace { + +enum BitmapStyle +{ + CUSTOM, + TILED, + STRETCHED +}; + +enum TileOffset +{ + ROW, + COLUMN +}; + +} + +SvxBitmapTabPage::SvxBitmapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/imagetabpage.ui", "ImageTabPage", &rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnBitmapListState(nullptr) + , m_fObjectWidth(0.0) + , m_fObjectHeight(0.0) + , m_bLogicalSize(false) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , mpView(nullptr) + , m_xBitmapLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("imagewin", true))) + , m_xBitmapStyleLB(m_xBuilder->weld_combo_box("imagestyle")) + , m_xSizeBox(m_xBuilder->weld_container("sizebox")) + , m_xTsbScale(m_xBuilder->weld_check_button("scaletsb")) + , m_xBitmapWidth(m_xBuilder->weld_metric_spin_button("width", FieldUnit::PERCENT)) + , m_xBitmapHeight(m_xBuilder->weld_metric_spin_button("height", FieldUnit::PERCENT)) + , m_xPositionBox(m_xBuilder->weld_container("posbox")) + , m_xPositionLB(m_xBuilder->weld_combo_box("positionlb")) + , m_xPositionOffBox(m_xBuilder->weld_container("posoffbox")) + , m_xPositionOffX(m_xBuilder->weld_metric_spin_button("posoffx", FieldUnit::PERCENT)) + , m_xPositionOffY(m_xBuilder->weld_metric_spin_button("posoffy", FieldUnit::PERCENT)) + , m_xTileOffBox(m_xBuilder->weld_container("tileoffbox")) + , m_xTileOffLB(m_xBuilder->weld_combo_box("tileofflb")) + , m_xTileOffset(m_xBuilder->weld_metric_spin_button("tileoffmtr", FieldUnit::PERCENT)) + , m_xBtnImport(m_xBuilder->weld_button("BTN_IMPORT")) + , m_xCtlBitmapPreview(new weld::CustomWeld(*m_xBuilder, "CTL_IMAGE_PREVIEW", m_aCtlBitmapPreview)) + , m_xBitmapLBWin(new weld::CustomWeld(*m_xBuilder, "IMAGE", *m_xBitmapLB)) +{ + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_BITMAP) ); + m_rXFSet.Put( XFillBitmapItem(OUString(), Graphic()) ); + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + + m_xBitmapLB->SetSelectHdl( LINK(this, SvxBitmapTabPage, ModifyBitmapHdl) ); + m_xBitmapLB->SetRenameHdl( LINK(this, SvxBitmapTabPage, ClickRenameHdl) ); + m_xBitmapLB->SetDeleteHdl( LINK(this, SvxBitmapTabPage, ClickDeleteHdl) ); + m_xBitmapStyleLB->connect_changed( LINK(this, SvxBitmapTabPage, ModifyBitmapStyleHdl) ); + Link<weld::MetricSpinButton&, void> aLink1( LINK(this, SvxBitmapTabPage, ModifyBitmapSizeHdl) ); + m_xBitmapWidth->connect_value_changed( aLink1 ); + m_xBitmapHeight->connect_value_changed( aLink1 ); + m_xTsbScale->connect_toggled(LINK(this, SvxBitmapTabPage, ClickScaleHdl)); + m_xPositionLB->connect_changed( LINK( this, SvxBitmapTabPage, ModifyBitmapPositionHdl ) ); + Link<weld::MetricSpinButton&, void> aLink( LINK( this, SvxBitmapTabPage, ModifyPositionOffsetHdl ) ); + m_xPositionOffX->connect_value_changed(aLink); + m_xPositionOffY->connect_value_changed(aLink); + m_xTileOffset->connect_value_changed( LINK( this, SvxBitmapTabPage, ModifyTileOffsetHdl ) ); + m_xBtnImport->connect_clicked( LINK(this, SvxBitmapTabPage, ClickImportHdl) ); + if (comphelper::LibreOfficeKit::isActive()) + m_xBtnImport->hide(); + + // Calculate size of display boxes + Size aSize = getDrawPreviewOptimalSize(m_aCtlBitmapPreview.GetDrawingArea()->get_ref_device()); + m_xBitmapLB->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlBitmapPreview->set_size_request(aSize.Width(), aSize.Height()); + + SfxItemPool* pPool = m_rXFSet.GetPool(); + mePoolUnit = pPool->GetMetric( XATTR_FILLBMP_SIZEX ); + meFieldUnit = GetModuleFieldUnit( rInAttrs ); + SetFieldUnit( *m_xBitmapWidth, meFieldUnit, true ); + SetFieldUnit( *m_xBitmapHeight, meFieldUnit, true ); + + m_xBitmapLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if( pViewShell ) + mpView = pViewShell->GetDrawView(); + DBG_ASSERT( mpView, "no valid view (!)" ); +} + +SvxBitmapTabPage::~SvxBitmapTabPage() +{ + m_xBitmapLBWin.reset(); + m_xBitmapLB.reset(); + m_xCtlBitmapPreview.reset(); +} + +void SvxBitmapTabPage::Construct() +{ + m_xBitmapLB->FillPresetListBox( *m_pBitmapList ); +} + +void SvxBitmapTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + XFillBitmapItem aItem( rSet.Get(XATTR_FILLBITMAP) ); + + sal_Int32 nPos( 0 ); + if ( !aItem.isPattern() ) + { + nPos = SearchBitmapList( aItem.GetGraphicObject() ); + if (nPos == -1) + return; + } + else + { + m_xBitmapWidth->set_value( 100, FieldUnit::NONE ); + m_xBitmapHeight->set_value( 100, FieldUnit::NONE ); + const_cast<SfxItemSet&>(rSet).Put( XFillBmpSizeXItem( GetCoreValue( *m_xBitmapWidth, mePoolUnit ) ) ); + const_cast<SfxItemSet&>(rSet).Put( XFillBmpSizeYItem( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) ) ); + } + + sal_uInt16 nId = m_xBitmapLB->GetItemId( static_cast<size_t>( nPos ) ); + m_xBitmapLB->SelectItem( nId ); +} + +DeactivateRC SvxBitmapTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxBitmapTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + rAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + if(VALUESET_ITEM_NOTFOUND != nPos) + { + const XBitmapEntry* pXBitmapEntry = m_pBitmapList->GetBitmap(nPos); + const OUString aString(m_xBitmapLB->GetItemText( m_xBitmapLB->GetSelectedItemId() )); + rAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject())); + } + + BitmapStyle eStylePos = static_cast<BitmapStyle>(m_xBitmapStyleLB->get_active()); + bool bIsStretched( eStylePos == STRETCHED ); + bool bIsTiled( eStylePos == TILED ); + + rAttrs->Put( XFillBmpTileItem(bIsTiled) ); + rAttrs->Put( XFillBmpStretchItem(bIsStretched) ); + + if(!bIsStretched) + { + Size aSetBitmapSize; + switch(eStylePos) + { + case CUSTOM: + case TILED: + { + sal_Int64 nWidthPercent = m_xBitmapWidth->get_value(FieldUnit::NONE); + sal_Int64 nHeightPercent = m_xBitmapHeight->get_value(FieldUnit::NONE); + if (m_xTsbScale->get_sensitive() && m_xTsbScale->get_state() == TRISTATE_TRUE) + { + aSetBitmapSize.setWidth( -nWidthPercent ); + aSetBitmapSize.setHeight( -nHeightPercent ); + } + else if (!m_bLogicalSize) + { + aSetBitmapSize.setWidth( GetCoreValue(*m_xBitmapWidth, mePoolUnit) ); + aSetBitmapSize.setHeight( GetCoreValue(*m_xBitmapHeight, mePoolUnit) ); + } + else + { + rAttrs->Put( XFillBmpSizeLogItem(true) ); + aSetBitmapSize.setWidth( 0 ); + aSetBitmapSize.setHeight( 0 ); + } + + break; + } + default: + break; + } + + rAttrs->Put( XFillBmpSizeXItem( aSetBitmapSize.Width() ) ); + rAttrs->Put( XFillBmpSizeYItem( aSetBitmapSize.Height() ) ); + } + + if (m_xPositionLB->get_sensitive()) + rAttrs->Put( XFillBmpPosItem( static_cast<RectPoint>( m_xPositionLB->get_active() ) ) ); + if (m_xPositionOffX->get_sensitive()) + rAttrs->Put( XFillBmpPosOffsetXItem(m_xPositionOffX->get_value(FieldUnit::PERCENT))); + if (m_xPositionOffY->get_sensitive()) + rAttrs->Put( XFillBmpPosOffsetYItem(m_xPositionOffY->get_value(FieldUnit::PERCENT))); + if (m_xTileOffBox->get_sensitive()) + { + TileOffset eValue = static_cast<TileOffset>(m_xTileOffLB->get_active()); + sal_uInt16 nOffsetValue = static_cast<sal_uInt16>(m_xTileOffset->get_value(FieldUnit::PERCENT)); + sal_uInt16 nRowOff = (eValue == ROW) ? nOffsetValue : 0; + sal_uInt16 nColOff = (eValue == COLUMN) ? nOffsetValue : 0; + rAttrs->Put( XFillBmpTileOffsetXItem(nRowOff) ); + rAttrs->Put( XFillBmpTileOffsetYItem(nColOff) ); + } + return true; +} + + +void SvxBitmapTabPage::Reset( const SfxItemSet* rAttrs ) +{ + double transfWidth = 0.0; + double transfHeight = 0.0; + double fUIScale = 1.0; + if (mpView) + { + fUIScale = ( mpView->GetModel() ? double(mpView->GetModel()->GetUIScale()) : 1.0); + + + if (mpView->AreObjectsMarked()) + { + SfxItemSet rGeoAttr(mpView->GetGeoAttrFromMarked()); + transfWidth = static_cast<double>(GetItem( rGeoAttr, SID_ATTR_TRANSFORM_WIDTH )->GetValue()); + transfHeight= static_cast<double>(GetItem( rGeoAttr, SID_ATTR_TRANSFORM_HEIGHT )->GetValue()); + } + } + m_fObjectWidth = std::max( transfWidth, 1.0 ); + m_fObjectHeight = std::max( transfHeight, 1.0 ); + double fTmpWidth((OutputDevice::LogicToLogic(static_cast<sal_Int32>(m_fObjectWidth), mePoolUnit, MapUnit::Map100thMM )) / fUIScale); + m_fObjectWidth = fTmpWidth; + + double fTmpHeight((OutputDevice::LogicToLogic(static_cast<sal_Int32>(m_fObjectHeight), mePoolUnit, MapUnit::Map100thMM )) / fUIScale); + m_fObjectHeight = fTmpHeight; + + XFillBitmapItem aItem( rAttrs->Get(XATTR_FILLBITMAP) ); + + if(!aItem.isPattern()) + { + m_rXFSet.Put( aItem ); + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); + } + else + m_xCtlBitmapPreview->set_sensitive(false); + + std::unique_ptr<GraphicObject> pGraphicObject; + pGraphicObject.reset( new GraphicObject(aItem.GetGraphicObject()) ); + + BitmapEx aBmpEx(pGraphicObject->GetGraphic().GetBitmapEx()); + Size aTempBitmapSize = aBmpEx.GetSizePixel(); + rBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aTempBitmapSize, MapMode(MapUnit::Map100thMM)); + CalculateBitmapPresetSize(); + + bool bTiled = false; bool bStretched = false; + if(rAttrs->GetItemState( XATTR_FILLBMP_TILE ) != SfxItemState::DONTCARE) + bTiled = rAttrs->Get( XATTR_FILLBMP_TILE ).GetValue(); + if(rAttrs->GetItemState( XATTR_FILLBMP_STRETCH ) != SfxItemState::DONTCARE) + bStretched = rAttrs->Get( XATTR_FILLBMP_STRETCH ).GetValue(); + + if (bTiled) + m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(TILED)); + else if (bStretched) + m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(STRETCHED)); + else + m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(CUSTOM)); + + tools::Long nWidth = 0; + tools::Long nHeight = 0; + + if(rAttrs->GetItemState(XATTR_FILLBMP_SIZELOG) != SfxItemState::DONTCARE) + { + if (rAttrs->Get( XATTR_FILLBMP_SIZELOG ).GetValue()) + { + m_xTsbScale->set_state(TRISTATE_FALSE); + m_bLogicalSize = true; + } + else + { + m_xTsbScale->set_state(TRISTATE_TRUE); + m_bLogicalSize = false; + } + } + else + m_xTsbScale->set_state(TRISTATE_INDET); + + TriState eRelative = TRISTATE_FALSE; + if(rAttrs->GetItemState(XATTR_FILLBMP_SIZEX) != SfxItemState::DONTCARE) + { + nWidth = static_cast<const XFillBmpSizeXItem&>( rAttrs->Get( XATTR_FILLBMP_SIZEX ) ).GetValue(); + if(nWidth == 0) + nWidth = rBitmapSize.Width(); + else if(nWidth < 0) + { + eRelative = TRISTATE_TRUE; + nWidth = std::abs(nWidth); + } + } + + if(rAttrs->GetItemState( XATTR_FILLBMP_SIZEY ) != SfxItemState::DONTCARE) + { + nHeight = rAttrs->Get( XATTR_FILLBMP_SIZEY ).GetValue(); + if(nHeight == 0) + nHeight = rBitmapSize.Height(); + else if(nHeight < 0) + { + eRelative = TRISTATE_TRUE; + nHeight = std::abs(nHeight); + } + } + m_xTsbScale->set_state(eRelative); + ClickScaleHdl(*m_xTsbScale); + + + if(!rBitmapSize.IsEmpty()) + { + if (eRelative == TRISTATE_TRUE) + { + m_xBitmapWidth->set_value(nWidth, FieldUnit::NONE); + m_xBitmapHeight->set_value(nHeight, FieldUnit::NONE); + } + else + { + SetMetricValue(*m_xBitmapWidth, nWidth, mePoolUnit); + SetMetricValue(*m_xBitmapHeight, nHeight, mePoolUnit); + } + } + + if( rAttrs->GetItemState( XATTR_FILLBMP_POS ) != SfxItemState::DONTCARE ) + { + RectPoint eValue = rAttrs->Get( XATTR_FILLBMP_POS ).GetValue(); + m_xPositionLB->set_active( static_cast< sal_Int32 >(eValue) ); + } + + if( rAttrs->GetItemState( XATTR_FILLBMP_POSOFFSETX ) != SfxItemState::DONTCARE ) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_POSOFFSETX ).GetValue(); + m_xPositionOffX->set_value(nValue, FieldUnit::PERCENT); + } + else + m_xPositionOffX->set_text(""); + + if( rAttrs->GetItemState( XATTR_FILLBMP_POSOFFSETY ) != SfxItemState::DONTCARE ) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_POSOFFSETY ).GetValue(); + m_xPositionOffY->set_value(nValue, FieldUnit::PERCENT); + } + else + m_xPositionOffY->set_text(""); + + if( rAttrs->GetItemState( XATTR_FILLBMP_TILEOFFSETX ) != SfxItemState::DONTCARE) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_TILEOFFSETX ).GetValue(); + if(nValue > 0) + { + m_xTileOffLB->set_active(static_cast<sal_Int32>(ROW)); + m_xTileOffset->set_value(nValue, FieldUnit::PERCENT); + } + } + + if( rAttrs->GetItemState( XATTR_FILLBMP_TILEOFFSETY ) != SfxItemState::DONTCARE ) + { + sal_Int32 nValue = rAttrs->Get( XATTR_FILLBMP_TILEOFFSETY ).GetValue(); + if(nValue > 0) + { + m_xTileOffLB->set_active(static_cast<sal_Int32>(COLUMN)); + m_xTileOffset->set_value(nValue, FieldUnit::PERCENT); + } + } + + ClickBitmapHdl_Impl(); +} + +std::unique_ptr<SfxTabPage> SvxBitmapTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxBitmapTabPage>(pPage, pController, *rAttrs); +} + +void SvxBitmapTabPage::ClickBitmapHdl_Impl() +{ + m_xBitmapLBWin->set_sensitive(true); + m_xCtlBitmapPreview->set_sensitive(true); + + ModifyBitmapHdl(m_xBitmapLB.get()); +} + +void SvxBitmapTabPage::CalculateBitmapPresetSize() +{ + if(rBitmapSize.IsEmpty()) + return; + + tools::Long nObjectWidth = static_cast<tools::Long>(m_fObjectWidth); + tools::Long nObjectHeight = static_cast<tools::Long>(m_fObjectHeight); + + if(std::abs(rBitmapSize.Width() - nObjectWidth) < std::abs(rBitmapSize.Height() - nObjectHeight)) + { + rFilledSize.setWidth( nObjectWidth ); + rFilledSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() ); + rZoomedSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() ); + rZoomedSize.setHeight( nObjectHeight ); + } + else + { + rFilledSize.setWidth( rBitmapSize.Width()*nObjectHeight/rBitmapSize.Height() ); + rFilledSize.setHeight( nObjectHeight ); + rZoomedSize.setWidth( nObjectWidth ); + rZoomedSize.setHeight( rBitmapSize.Height()*nObjectWidth/rBitmapSize.Width() ); + } +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapHdl, ValueSet*, void) +{ + std::unique_ptr<GraphicObject> pGraphicObject; + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap( static_cast<sal_uInt16>(nPos) )->GetGraphicObject())); + } + else + { + if(const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLSTYLE))) + { + const drawing::FillStyle eXFS(pFillStyleItem->GetValue()); + + const XFillBitmapItem* pBitmapItem; + if((drawing::FillStyle_BITMAP == eXFS) && (pBitmapItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLBITMAP)))) + { + pGraphicObject.reset(new GraphicObject(pBitmapItem->GetGraphicObject())); + } + } + + if(!pGraphicObject) + { + sal_uInt16 nId = m_xBitmapLB->GetItemId(0); + m_xBitmapLB->SelectItem(nId); + + if(0 != nId) + { + pGraphicObject.reset(new GraphicObject(m_pBitmapList->GetBitmap(0)->GetGraphicObject())); + } + } + } + + if(pGraphicObject) + { + BitmapEx aBmpEx(pGraphicObject->GetGraphic().GetBitmapEx()); + Size aTempBitmapSize = aBmpEx.GetSizePixel(); + const double fUIScale = ( (mpView && mpView->GetModel()) ? double(mpView->GetModel()->GetUIScale()) : 1.0); + Size aBitmapSize100mm = o3tl::convert(aTempBitmapSize, o3tl::Length::pt, o3tl::Length::mm100); + + rBitmapSize.setWidth(aBitmapSize100mm.Width() / fUIScale); + rBitmapSize.setHeight(aBitmapSize100mm.Height() / fUIScale); + CalculateBitmapPresetSize(); + ModifyBitmapStyleHdl( *m_xBitmapStyleLB ); + ModifyBitmapPositionHdl( *m_xPositionLB ); + + m_rXFSet.ClearItem(XATTR_FILLBITMAP); + m_rXFSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + m_rXFSet.Put(XFillBitmapItem(OUString(), *pGraphicObject)); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); + } + else + { + SAL_WARN("cui.tabpages", "SvxBitmapTabPage::ModifyBitmapHdl(): null pGraphicObject"); + } + +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ClickRenameHdl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xBitmapLB->GetSelectedItemId(); + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc( CuiResId( RID_CUISTR_DESC_NEW_BITMAP ) ); + OUString aName( m_pBitmapList->GetBitmap( nPos )->GetName() ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nBitmapPos = SearchBitmapList( aName ); + bool bValidBitmapName = (nBitmapPos == static_cast<sal_Int32>(nPos) ) || (nBitmapPos == -1); + + if(bValidBitmapName) + { + bLoop = false; + m_pBitmapList->GetBitmap(nPos)->SetName(aName); + + m_xBitmapLB->SetItemText(nId, aName); + m_xBitmapLB->SelectItem( nId ); + + *m_pnBitmapListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ClickDeleteHdl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xBitmapLB->GetSelectedItemId(); + size_t nPos = m_xBitmapLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskDelBitmapDialog")); + + if (xQueryBox->run() != RET_YES) + return; + + sal_uInt16 nNextId = m_xBitmapLB->GetItemId(nPos + 1); + if (!nNextId) + nNextId = m_xBitmapLB->GetItemId(nPos - 1); + + m_pBitmapList->Remove( static_cast<sal_uInt16>(nPos) ); + m_xBitmapLB->RemoveItem( nId ); + + m_xBitmapLB->SelectItem(nNextId); + + m_aCtlBitmapPreview.Invalidate(); + ModifyBitmapHdl(m_xBitmapLB.get()); + *m_pnBitmapListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapSizeHdl, weld::MetricSpinButton&, void ) +{ + m_bLogicalSize = false; + if (m_xTsbScale->get_state() != TRISTATE_TRUE && static_cast<BitmapStyle>(m_xBitmapStyleLB->get_active()) != TILED) + { + sal_Int64 nWidthPercent = m_xBitmapWidth->denormalize(m_xBitmapWidth->get_value(FieldUnit::NONE)); + sal_Int64 nHeightPercent = m_xBitmapHeight->denormalize(m_xBitmapHeight->get_value(FieldUnit::NONE)); + if (nWidthPercent == 100 && nHeightPercent == 100) + m_xBitmapStyleLB->set_active(static_cast<sal_Int32>(CUSTOM)); + } + ModifyBitmapStyleHdl(*m_xBitmapStyleLB); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG( SvxBitmapTabPage, ClickScaleHdl, weld::Toggleable&, void ) +{ + if (m_xTsbScale->get_state() == TRISTATE_TRUE) + { + m_xBitmapWidth->set_digits( 0 ); + m_xBitmapWidth->set_unit(FieldUnit::PERCENT); + m_xBitmapWidth->set_value(100, FieldUnit::NONE); + m_xBitmapWidth->set_range(0, 100, FieldUnit::NONE); + + m_xBitmapHeight->set_digits( 0 ); + m_xBitmapHeight->set_unit(FieldUnit::PERCENT); + m_xBitmapHeight->set_value(100, FieldUnit::NONE); + m_xBitmapHeight->set_range(0, 100, FieldUnit::NONE); + } + else + { + m_xBitmapWidth->set_digits( 2 ); + m_xBitmapWidth->set_unit(meFieldUnit); + m_xBitmapWidth->set_value(100, FieldUnit::NONE); + m_xBitmapWidth->set_range(0, 999900, FieldUnit::NONE); + + m_xBitmapHeight->set_digits( 2 ); + m_xBitmapHeight->set_unit(meFieldUnit); + m_xBitmapHeight->set_value(100, FieldUnit::NONE); + m_xBitmapHeight->set_range(0, 999900, FieldUnit::NONE); + } + + ModifyBitmapStyleHdl( *m_xBitmapStyleLB ); +} + +IMPL_LINK_NOARG( SvxBitmapTabPage, ModifyBitmapStyleHdl, weld::ComboBox&, void ) +{ + BitmapStyle eStylePos = static_cast<BitmapStyle>(m_xBitmapStyleLB->get_active()); + bool bIsStretched( eStylePos == STRETCHED ); + bool bIsTiled( eStylePos == TILED ); + + m_xSizeBox->set_sensitive( !bIsStretched ); + m_xPositionBox->set_sensitive( !bIsStretched ); + m_xPositionOffBox->set_sensitive( bIsTiled ); + m_xTileOffBox->set_sensitive( bIsTiled ); + + m_rXFSet.Put( XFillBmpTileItem( bIsTiled ) ); + m_rXFSet.Put( XFillBmpStretchItem( bIsStretched ) ); + + if(!bIsStretched) + { + Size aSetBitmapSize; + switch(eStylePos) + { + case CUSTOM: + case TILED: + { + if (m_xTsbScale->get_sensitive() && m_xTsbScale->get_state() == TRISTATE_TRUE) + { + aSetBitmapSize.setWidth(-m_xBitmapWidth->get_value(FieldUnit::NONE)); + aSetBitmapSize.setHeight(-m_xBitmapHeight->get_value(FieldUnit::NONE)); + } + else + { + aSetBitmapSize.setWidth( GetCoreValue( *m_xBitmapWidth, mePoolUnit ) ); + aSetBitmapSize.setHeight( GetCoreValue( *m_xBitmapHeight, mePoolUnit ) ); + } + } + break; + default: + break; + } + + m_rXFSet.Put( XFillBmpSizeXItem( aSetBitmapSize.Width() ) ); + m_rXFSet.Put( XFillBmpSizeYItem( aSetBitmapSize.Height() ) ); + } + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyBitmapPositionHdl, weld::ComboBox&, void) +{ + if (m_xPositionLB->get_sensitive()) + m_rXFSet.Put( XFillBmpPosItem( static_cast< RectPoint >( m_xPositionLB->get_active() ) ) ); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyPositionOffsetHdl, weld::MetricSpinButton&, void) +{ + if (m_xPositionOffX->get_sensitive()) + m_rXFSet.Put( XFillBmpPosOffsetXItem( m_xPositionOffX->get_value(FieldUnit::PERCENT) ) ); + + if (m_xPositionOffY->get_sensitive()) + m_rXFSet.Put( XFillBmpPosOffsetYItem( m_xPositionOffY->get_value(FieldUnit::PERCENT) ) ); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ModifyTileOffsetHdl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nTileXOff = 0; + sal_uInt16 nTileYOff = 0; + + if(m_xTileOffLB->get_active() == static_cast<sal_Int32>(ROW)) + nTileXOff = m_xTileOffset->get_value(FieldUnit::PERCENT); + + if(m_xTileOffLB->get_active() == static_cast<sal_Int32>(COLUMN)) + nTileYOff = m_xTileOffset->get_value(FieldUnit::PERCENT); + + m_rXFSet.Put( XFillBmpTileOffsetXItem(nTileXOff) ); + m_rXFSet.Put( XFillBmpTileOffsetYItem(nTileYOff) ); + + m_aCtlBitmapPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxBitmapTabPage, ClickImportHdl, weld::Button&, void) +{ + weld::Window* pDialogFrameWeld = GetFrameWeld(); + + SvxOpenGraphicDialog aDlg(CuiResId(RID_CUISTR_ADD_IMAGE), pDialogFrameWeld); + aDlg.EnableLink(false); + tools::Long nCount = m_pBitmapList->Count(); + + if( aDlg.Execute() ) + return; + + Graphic aGraphic; + + std::unique_ptr<weld::WaitObject> xWait(new weld::WaitObject(pDialogFrameWeld)); + ErrCode nError = aDlg.GetGraphic( aGraphic ); + xWait.reset(); + + if( !nError ) + { + OUString aDesc(CuiResId(RID_CUISTR_DESC_EXT_BITMAP)); + + // convert file URL to UI name + OUString aName; + INetURLObject aURL( aDlg.GetPath() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog( + pDialogFrameWeld, aURL.GetLastName().getToken(0, '.'), aDesc)); + nError = ErrCode(1); + + while( pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + + bool bDifferent = true; + + for( tools::Long i = 0; i < nCount && bDifferent; i++ ) + if( aName == m_pBitmapList->GetBitmap( i )->GetName() ) + bDifferent = false; + + if( bDifferent ) { + nError = ERRCODE_NONE; + break; + } + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pDialogFrameWeld, "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xBox->run() != RET_OK) + break; + } + + pDlg.disposeAndClear(); + + if( !nError ) + { + m_pBitmapList->Insert(std::make_unique<XBitmapEntry>(aGraphic, aName), nCount); + + sal_Int32 nId = m_xBitmapLB->GetItemId( nCount - 1 ); + BitmapEx aBitmap = m_pBitmapList->GetBitmapForPreview( nCount, m_xBitmapLB->GetIconSize() ); + + m_xBitmapLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xBitmapLB->SelectItem( nId + 1 ); + *m_pnBitmapListState |= ChangeType::MODIFIED; + + ModifyBitmapHdl(m_xBitmapLB.get()); + } + } + else + { + // graphic couldn't be loaded + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pDialogFrameWeld, "cui/ui/querynoloadedfiledialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("NoLoadedFileDialog")); + xBox->run(); + } +} + +sal_Int32 SvxBitmapTabPage::SearchBitmapList(const GraphicObject& rGraphicObject) +{ + tools::Long nCount = m_pBitmapList->Count(); + sal_Int32 nPos = -1; + + for(tools::Long i = 0;i < nCount;i++) + { + if(rGraphicObject.GetUniqueID() == m_pBitmapList->GetBitmap( i )->GetGraphicObject().GetUniqueID()) + { + nPos = i; + break; + } + } + return nPos; +} + +sal_Int32 SvxBitmapTabPage::SearchBitmapList(std::u16string_view rBitmapName) +{ + tools::Long nCount = m_pBitmapList->Count(); + bool bValidBitmapName = true; + sal_Int32 nPos = -1; + + for(tools::Long i = 0;i < nCount && bValidBitmapName;i++) + { + if(rBitmapName == m_pBitmapList->GetBitmap( i )->GetName()) + { + nPos = i; + bValidBitmapName = false; + } + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpcolor.cxx b/cui/source/tabpages/tpcolor.cxx new file mode 100644 index 000000000..e65c49617 --- /dev/null +++ b/cui/source/tabpages/tpcolor.cxx @@ -0,0 +1,794 @@ +/* -*- 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 . + */ + +#include <memory> +#include <i18nutil/unicode.hxx> +#include <svtools/colrdlg.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +#include <strings.hrc> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xtable.hxx> +#include <cuitabarea.hxx> +#include <svx/svxdlg.hxx> +#include <dialmgr.hxx> +#include <cuitabline.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <officecfg/Office/Common.hxx> +#include <osl/diagnose.h> +#include <comphelper/dispatchcommand.hxx> +#include <comphelper/propertyvalue.hxx> + +using namespace com::sun::star; + +SvxColorTabPage::SvxColorTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/colorpage.ui", "ColorPage", &rInAttrs) + , rOutAttrs ( rInAttrs ) + // All the horrific pointers we store and should not + , pnColorListState( nullptr ) + , aXFillAttr( rInAttrs.GetPool() ) + , rXFSet( aXFillAttr.GetItemSet() ) + , eCM( ColorModel::RGB ) + , m_xValSetColorList(new SvxColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin", true))) + , m_xValSetRecentList(new SvxColorValueSet(nullptr)) + , m_xSelectPalette(m_xBuilder->weld_combo_box("paletteselector")) + , m_xRbRGB(m_xBuilder->weld_radio_button("RGB")) + , m_xRbCMYK(m_xBuilder->weld_radio_button("CMYK")) + , m_xRGBcustom(m_xBuilder->weld_widget("rgbcustom")) + , m_xRGBpreset(m_xBuilder->weld_widget("rgbpreset")) + , m_xRpreset(m_xBuilder->weld_entry("R_preset")) + , m_xGpreset(m_xBuilder->weld_entry("G_preset")) + , m_xBpreset(m_xBuilder->weld_entry("B_preset")) + , m_xRcustom(m_xBuilder->weld_spin_button("R_custom")) + , m_xGcustom(m_xBuilder->weld_spin_button("G_custom")) + , m_xBcustom(m_xBuilder->weld_spin_button("B_custom")) + , m_xHexpreset(new weld::HexColorControl(m_xBuilder->weld_entry("hex_preset"))) + , m_xHexcustom(new weld::HexColorControl(m_xBuilder->weld_entry("hex_custom"))) + , m_xCMYKcustom(m_xBuilder->weld_widget("cmykcustom")) + , m_xCMYKpreset(m_xBuilder->weld_widget("cmykpreset")) + , m_xCpreset(m_xBuilder->weld_entry("C_preset")) + , m_xYpreset(m_xBuilder->weld_entry("Y_preset")) + , m_xMpreset(m_xBuilder->weld_entry("M_preset")) + , m_xKpreset(m_xBuilder->weld_entry("K_preset")) + , m_xCcustom(m_xBuilder->weld_metric_spin_button("C_custom", FieldUnit::PERCENT)) + , m_xYcustom(m_xBuilder->weld_metric_spin_button("Y_custom", FieldUnit::PERCENT)) + , m_xMcustom(m_xBuilder->weld_metric_spin_button("M_custom", FieldUnit::PERCENT)) + , m_xKcustom(m_xBuilder->weld_metric_spin_button("K_custom", FieldUnit::PERCENT)) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnDelete(m_xBuilder->weld_button("delete")) + , m_xBtnWorkOn(m_xBuilder->weld_button("edit")) + , m_xMoreColors(m_xBuilder->weld_button("btnMoreColors")) + , m_xCtlPreviewOld(new weld::CustomWeld(*m_xBuilder, "oldpreview", m_aCtlPreviewOld)) + , m_xCtlPreviewNew(new weld::CustomWeld(*m_xBuilder, "newpreview", m_aCtlPreviewNew)) + , m_xValSetColorListWin(new weld::CustomWeld(*m_xBuilder, "colorset", *m_xValSetColorList)) + , m_xValSetRecentListWin(new weld::CustomWeld(*m_xBuilder, "recentcolorset", *m_xValSetRecentList)) +{ + Size aSize(m_xBtnWorkOn->get_approximate_digit_width() * 25, + m_xBtnWorkOn->get_text_height() * 10); + m_xValSetColorList->set_size_request(aSize.Width(), aSize.Height()); + aSize = Size(m_xBtnWorkOn->get_approximate_digit_width() * 8, + m_xBtnWorkOn->get_text_height() * 3); + m_aCtlPreviewOld.set_size_request(aSize.Width(), aSize.Height()); + m_aCtlPreviewNew.set_size_request(aSize.Width(), aSize.Height()); + // this page needs ExchangeSupport + SetExchangeSupport(); + + // setting the output device + rXFSet.Put( XFillStyleItem(drawing::FillStyle_SOLID) ); + rXFSet.Put( XFillColorItem(OUString(), COL_BLACK) ); + m_aCtlPreviewOld.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + // set handler + m_xSelectPalette->connect_changed(LINK(this, SvxColorTabPage, SelectPaletteLBHdl)); + Link<ValueSet*, void> aValSelectLink = LINK(this, SvxColorTabPage, SelectValSetHdl_Impl); + m_xValSetColorList->SetSelectHdl(aValSelectLink); + m_xValSetRecentList->SetSelectHdl(aValSelectLink); + + Link<weld::SpinButton&,void> aSpinLink = LINK(this, SvxColorTabPage, SpinValueHdl_Impl); + m_xRcustom->connect_value_changed(aSpinLink); + m_xGcustom->connect_value_changed(aSpinLink); + m_xBcustom->connect_value_changed(aSpinLink); + Link<weld::Entry&,void> aEntryLink = LINK(this, SvxColorTabPage, ModifiedHdl_Impl); + m_xHexcustom->connect_changed(aEntryLink); + Link<weld::MetricSpinButton&,void> aMetricSpinLink = LINK(this, SvxColorTabPage, MetricSpinValueHdl_Impl); + m_xCcustom->connect_value_changed(aMetricSpinLink); + m_xYcustom->connect_value_changed(aMetricSpinLink); + m_xMcustom->connect_value_changed(aMetricSpinLink); + m_xKcustom->connect_value_changed(aMetricSpinLink); + + Link<weld::Toggleable&,void> aLink2 = LINK( this, SvxColorTabPage, SelectColorModeHdl_Impl ); + m_xRbRGB->connect_toggled(aLink2); + m_xRbCMYK->connect_toggled(aLink2); + SetColorModel( eCM ); + ChangeColorModel(); + + m_xBtnAdd->connect_clicked( LINK( this, SvxColorTabPage, ClickAddHdl_Impl ) ); + m_xBtnWorkOn->connect_clicked( LINK( this, SvxColorTabPage, ClickWorkOnHdl_Impl ) ); + m_xBtnDelete->connect_clicked( LINK( this, SvxColorTabPage, ClickDeleteHdl_Impl ) ); + // disable modify buttons + // Color palettes can't be modified + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR1) ); + + m_xMoreColors->set_from_icon_name("cmd/sc_additionsdialog.png"); + m_xMoreColors->connect_clicked(LINK(this, SvxColorTabPage, OnMoreColorsClick)); + + // disable preset color values + m_xRGBpreset->set_sensitive(false); + m_xCMYKpreset->set_sensitive(false); + + // ValueSet + m_xValSetColorList->SetStyle(m_xValSetColorList->GetStyle() | + WB_FLATVALUESET | WB_ITEMBORDER | WB_NO_DIRECTSELECT | WB_TABSTOP); + m_xValSetColorList->Show(); + + m_xValSetRecentList->SetStyle(m_xValSetRecentList->GetStyle() | + WB_FLATVALUESET | WB_ITEMBORDER | WB_NO_DIRECTSELECT | WB_TABSTOP); + m_xValSetRecentList->Show(); + + maPaletteManager.ReloadRecentColorSet(*m_xValSetRecentList); + aSize = m_xValSetRecentList->layoutAllVisible(maPaletteManager.GetRecentColorCount()); + m_xValSetRecentList->set_size_request(aSize.Width(), aSize.Height()); +} + +SvxColorTabPage::~SvxColorTabPage() +{ + m_xValSetRecentListWin.reset(); + m_xValSetRecentList.reset(); + m_xValSetColorListWin.reset(); + m_xValSetColorList.reset(); +} + +void SvxColorTabPage::ImpColorCountChanged() +{ + if (!pColorList.is()) + return; + m_xValSetColorList->SetColCount(SvxColorValueSet::getColumnCount()); + m_xValSetRecentList->SetColCount(SvxColorValueSet::getColumnCount()); +} + +void SvxColorTabPage::FillPaletteLB() +{ + m_xSelectPalette->clear(); + std::vector<OUString> aPaletteList = maPaletteManager.GetPaletteList(); + for (auto const& palette : aPaletteList) + { + m_xSelectPalette->append_text(palette); + } + OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); + m_xSelectPalette->set_active_text(aPaletteName); + if (m_xSelectPalette->get_active() != -1) + { + SelectPaletteLBHdl(*m_xSelectPalette); + } +} + +void SvxColorTabPage::Construct() +{ + if (pColorList.is()) + { + FillPaletteLB(); + ImpColorCountChanged(); + } +} + +void SvxColorTabPage::ActivatePage( const SfxItemSet& ) +{ + if( !pColorList.is() ) + return; + + if( const XFillColorItem* pFillColorItem = rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLCOLOR ) ) ) + { + SetColorModel( ColorModel::RGB ); + ChangeColorModel(); + + const Color aColor = pFillColorItem->GetColorValue(); + svx::NamedThemedColor aThemedColor; + aThemedColor.m_aColor = aColor; + ChangeColor( aThemedColor ); + sal_Int32 nPos = FindInPalette( aColor ); + + if ( nPos != -1 ) + m_xValSetColorList->SelectItem(m_xValSetColorList->GetItemId(nPos)); + // else search in other palettes? + + } + + m_aCtlPreviewOld.SetAttributes(aXFillAttr.GetItemSet()); + m_aCtlPreviewOld.Invalidate(); + + SelectValSetHdl_Impl(m_xValSetColorList.get()); +} + +DeactivateRC SvxColorTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +bool SvxColorTabPage::FillItemSet( SfxItemSet* rSet ) +{ + Color aColor = m_xValSetColorList->GetItemColor( m_xValSetColorList->GetSelectedItemId() ); + OUString sColorName; + if ( aCurrentColor.m_aColor == aColor ) + sColorName = m_xValSetColorList->GetItemText( m_xValSetColorList->GetSelectedItemId() ); + else + sColorName = "#" + aCurrentColor.m_aColor.AsRGBHexString().toAsciiUpperCase(); + maPaletteManager.AddRecentColor( aCurrentColor.m_aColor, sColorName ); + XFillColorItem aColorItem( sColorName, aCurrentColor.m_aColor ); + if (aCurrentColor.m_nThemeIndex != -1) + { + aColorItem.GetThemeColor().SetThemeIndex(aCurrentColor.m_nThemeIndex); + } + if (aCurrentColor.m_nLumMod != 10000) + { + aColorItem.GetThemeColor().SetLumMod(aCurrentColor.m_nLumMod); + } + if (aCurrentColor.m_nLumOff != 0) + { + aColorItem.GetThemeColor().SetLumOff(aCurrentColor.m_nLumOff); + } + rSet->Put( aColorItem ); + rSet->Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + return true; +} + +void SvxColorTabPage::UpdateModified() +{ + bool bEnable = pColorList.is() && pColorList->Count(); + m_xBtnWorkOn->set_sensitive(bEnable); +} + +void SvxColorTabPage::Reset( const SfxItemSet* rSet ) +{ + SfxItemState nState = rSet->GetItemState( XATTR_FILLCOLOR ); + + Color aNewColor; + + if ( nState >= SfxItemState::DEFAULT ) + { + XFillColorItem aColorItem( rSet->Get( XATTR_FILLCOLOR ) ); + aPreviousColor = aColorItem.GetColorValue(); + aNewColor = aColorItem.GetColorValue(); + } + + // set color model + OUString aStr = GetUserData(); + eCM = static_cast<ColorModel>(aStr.toInt32()); + SetColorModel( eCM ); + ChangeColorModel(); + + svx::NamedThemedColor aThemedColor; + aThemedColor.m_aColor = aNewColor; + ChangeColor(aThemedColor); + + UpdateModified(); +} + +std::unique_ptr<SfxTabPage> SvxColorTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SvxColorTabPage>(pPage, pController, *rOutAttrs); +} + +// is called when the content of the MtrFields is changed for color values +IMPL_LINK_NOARG(SvxColorTabPage, SpinValueHdl_Impl, weld::SpinButton&, void) +{ + // read current MtrFields, if cmyk, then k-value as transparency + aCurrentColor.m_aColor = Color(static_cast<sal_uInt8>(PercentToColor_Impl(m_xRcustom->get_value())), + static_cast<sal_uInt8>(PercentToColor_Impl(m_xGcustom->get_value())), + static_cast<sal_uInt8>(PercentToColor_Impl(m_xBcustom->get_value()))); + UpdateColorValues(); + + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor.m_aColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, MetricSpinValueHdl_Impl, weld::MetricSpinButton&, void) +{ + // read current MtrFields, if cmyk, then k-value as transparency + aCurrentColor.m_aColor = Color(ColorTransparency, static_cast<sal_uInt8>(PercentToColor_Impl(m_xKcustom->get_value(FieldUnit::NONE))), + static_cast<sal_uInt8>(PercentToColor_Impl(m_xCcustom->get_value(FieldUnit::NONE))), + static_cast<sal_uInt8>(PercentToColor_Impl(m_xYcustom->get_value(FieldUnit::NONE))), + static_cast<sal_uInt8>(PercentToColor_Impl(m_xMcustom->get_value(FieldUnit::NONE)))); + ConvertColorValues (aCurrentColor.m_aColor, ColorModel::RGB); + + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor.m_aColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, ModifiedHdl_Impl, weld::Entry&, void) +{ + aCurrentColor.m_aColor = m_xHexcustom->GetColor(); + UpdateColorValues(); + + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor.m_aColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName( SvxResId( RID_SVXSTR_COLOR ) ); + OUString aDesc( CuiResId( RID_CUISTR_DESC_COLOR ) ); + OUString aName; + + tools::Long j = 1; + bool bValidColorName = false; + // check if name is already existing + while (!bValidColorName) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidColorName = (FindInCustomColors(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError = 1; + + while (pDlg->Execute() == RET_OK) + { + pDlg->GetName( aName ); + + bValidColorName = (FindInCustomColors(aName) == -1); + if (bValidColorName) + { + nError = 0; + break; + } + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + + pDlg.disposeAndClear(); + + if (!nError) + { + m_xSelectPalette->set_active(0); + SelectPaletteLBHdl(*m_xSelectPalette); + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); + css::uno::Sequence< sal_Int32 > aCustomColorList(officecfg::Office::Common::UserColors::CustomColor::get()); + css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); + sal_Int32 nSize = aCustomColorList.getLength(); + aCustomColorList.realloc( nSize + 1 ); + aCustomColorNameList.realloc( nSize + 1 ); + aCustomColorList.getArray()[nSize] = sal_Int32(aCurrentColor.m_aColor); + aCustomColorNameList.getArray()[nSize] = aName; + officecfg::Office::Common::UserColors::CustomColor::set(aCustomColorList, batch); + officecfg::Office::Common::UserColors::CustomColorName::set(aCustomColorNameList, batch); + batch->commit(); + sal_uInt16 nId = m_xValSetColorList->GetItemId(nSize - 1); + m_xValSetColorList->InsertItem( nId + 1 , aCurrentColor.m_aColor, aName ); + m_xValSetColorList->SelectItem( nId + 1 ); + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR2) ); + ImpColorCountChanged(); + } + + UpdateModified(); +} + +IMPL_LINK_NOARG(SvxColorTabPage, ClickWorkOnHdl_Impl, weld::Button&, void) +{ + SvColorDialog aColorDlg; + + aColorDlg.SetColor (aCurrentColor.m_aColor); + aColorDlg.SetMode( svtools::ColorPickerMode::Modify ); + + if (aColorDlg.Execute(GetFrameWeld()) == RET_OK) + { + Color aPreviewColor = aColorDlg.GetColor(); + aCurrentColor.m_aColor = aPreviewColor; + UpdateColorValues( false ); + // fill ItemSet and pass it on to XOut + rXFSet.Put( XFillColorItem( OUString(), aPreviewColor ) ); + //m_aCtlPreviewOld.SetAttributes( aXFillAttr ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + + m_aCtlPreviewNew.Invalidate(); + } +} + +IMPL_LINK_NOARG(SvxColorTabPage, ClickDeleteHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xValSetColorList->GetSelectedItemId(); + size_t nPos = m_xValSetColorList->GetSelectItemPos(); + if (m_xSelectPalette->get_active() != 0 || nPos == VALUESET_ITEM_NOTFOUND) + return; + + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); + css::uno::Sequence< sal_Int32 > aCustomColorList(officecfg::Office::Common::UserColors::CustomColor::get()); + auto aCustomColorListRange = asNonConstRange(aCustomColorList); + css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); + auto aCustomColorNameListRange = asNonConstRange(aCustomColorNameList); + sal_Int32 nSize = aCustomColorList.getLength() - 1; + for(sal_Int32 nIndex = static_cast<sal_Int32>(nPos);nIndex < nSize;nIndex++) + { + aCustomColorListRange[nIndex] = aCustomColorList[nIndex+1]; + aCustomColorNameListRange[nIndex] = aCustomColorNameList[nIndex+1]; + } + aCustomColorList.realloc(nSize); + aCustomColorNameList.realloc(nSize); + officecfg::Office::Common::UserColors::CustomColor::set(aCustomColorList, batch); + officecfg::Office::Common::UserColors::CustomColorName::set(aCustomColorNameList, batch); + batch->commit(); + m_xValSetColorList->RemoveItem(nId); + if (m_xValSetColorList->GetItemCount() != 0) + { + nId = m_xValSetColorList->GetItemId(0); + m_xValSetColorList->SelectItem(nId); + SelectValSetHdl_Impl(m_xValSetColorList.get()); + } + else + { + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR2) ); + } +} + +IMPL_LINK_NOARG(SvxColorTabPage, SelectPaletteLBHdl, weld::ComboBox&, void) +{ + m_xValSetColorList->Clear(); + sal_Int32 nPos = m_xSelectPalette->get_active(); + maPaletteManager.SetPalette( nPos ); + maPaletteManager.ReloadColorSet(*m_xValSetColorList); + + if(nPos != maPaletteManager.GetPaletteCount() - 1 && nPos != 0) + { + XColorListRef pList = XPropertyList::AsColorList( + XPropertyList::CreatePropertyListFromURL( + XPropertyListType::Color, maPaletteManager.GetSelectedPalettePath())); + pList->SetName(maPaletteManager.GetPaletteName()); + if(pList->Load()) + { + SfxOkDialogController* pController = GetDialogController(); + SvxAreaTabDialog* pArea = dynamic_cast<SvxAreaTabDialog*>(pController); + SvxLineTabDialog* pLine = dynamic_cast<SvxLineTabDialog*>(pController); + pColorList = pList; + if( pArea ) + pArea->SetNewColorList(pList); + else if( pLine ) + pLine->SetNewColorList(pList); + else + SetColorList(pList); + *pnColorListState |= ChangeType::CHANGED; + *pnColorListState &= ~ChangeType::MODIFIED; + } + } + if (nPos != 0) + { + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR1) ); + } + + m_xValSetColorList->Resize(); +} + +IMPL_LINK(SvxColorTabPage, SelectValSetHdl_Impl, ValueSet*, pValSet, void) +{ + sal_Int32 nPos = pValSet->GetSelectedItemId(); + if( nPos == 0 ) + return; + + Color aColor = pValSet->GetItemColor( nPos ); + + rXFSet.Put( XFillColorItem( OUString(), aColor ) ); + m_aCtlPreviewNew.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlPreviewNew.Invalidate(); + + bool bThemePaletteSelected = false; + if (pValSet == m_xValSetColorList.get()) + { + bThemePaletteSelected = maPaletteManager.IsThemePaletteSelected(); + } + svx::NamedThemedColor aThemedColor; + aThemedColor.m_aColor = aColor; + if (bThemePaletteSelected) + { + PaletteManager::GetThemeIndexLumModOff(nPos, aThemedColor.m_nThemeIndex, aThemedColor.m_nLumMod, aThemedColor.m_nLumOff); + } + + ChangeColor(aThemedColor, false); + + if (pValSet == m_xValSetColorList.get()) + { + m_xValSetRecentList->SetNoSelection(); + if (m_xSelectPalette->get_active() == 0 && m_xValSetColorList->GetSelectedItemId() != 0) + { + m_xBtnDelete->set_sensitive(true); + m_xBtnDelete->set_tooltip_text(""); + } + else + { + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR1) ); + } + } + if (pValSet == m_xValSetRecentList.get()) + { + m_xValSetColorList->SetNoSelection(); + m_xBtnDelete->set_sensitive(false); + m_xBtnDelete->set_tooltip_text( CuiResId(RID_CUISTR_DELETEUSERCOLOR2) ); + } +} + +void SvxColorTabPage::ConvertColorValues (Color& rColor, ColorModel eModell) +{ + switch (eModell) + { + case ColorModel::RGB: + { + CmykToRgb_Impl (rColor, static_cast<sal_uInt16>(255 - rColor.GetAlpha()) ); + rColor.SetAlpha (255); + } + break; + + case ColorModel::CMYK: + { + sal_uInt16 nK; + RgbToCmyk_Impl (rColor, nK ); + rColor.SetAlpha (255 - static_cast<sal_uInt8>(nK)); + } + break; + } +} + +IMPL_LINK_NOARG(SvxColorTabPage, SelectColorModeHdl_Impl, weld::Toggleable&, void) +{ + if (m_xRbRGB->get_active()) + eCM = ColorModel::RGB; + else if (m_xRbCMYK->get_active()) + eCM = ColorModel::CMYK; + ChangeColorModel(); + UpdateColorValues(); +} + + +IMPL_STATIC_LINK_NOARG(SvxColorTabPage, OnMoreColorsClick, weld::Button&, void) +{ + css::uno::Sequence<css::beans::PropertyValue> aArgs{ comphelper::makePropertyValue( + "AdditionsTag", OUString("Color Palette")) }; + comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs); +} + +void SvxColorTabPage::ChangeColor(const svx::NamedThemedColor &rNewColor, bool bUpdatePreset ) +{ + aPreviousColor = rNewColor.m_aColor; + aCurrentColor = rNewColor; + UpdateColorValues( bUpdatePreset ); + // fill ItemSet and pass it on to XOut + rXFSet.Put( XFillColorItem( OUString(), aCurrentColor.m_aColor ) ); + m_aCtlPreviewNew.SetAttributes(aXFillAttr.GetItemSet()); + m_aCtlPreviewNew.Invalidate(); +} + +void SvxColorTabPage::SetColorModel( ColorModel eModel ) +{ + if (eModel == ColorModel::RGB) + m_xRbRGB->set_active(true); + else if (eModel == ColorModel::CMYK) + m_xRbCMYK->set_active(true); +} + +void SvxColorTabPage::ChangeColorModel() +{ + switch( eCM ) + { + case ColorModel::RGB: + { + m_xRGBcustom->show(); + m_xRGBpreset->show(); + m_xCMYKcustom->hide(); + m_xCMYKpreset->hide(); + } + break; + + case ColorModel::CMYK: + { + m_xCMYKcustom->show(); + m_xCMYKpreset->show(); + m_xRGBcustom->hide(); + m_xRGBpreset->hide(); + } + break; + } +} + +void SvxColorTabPage::UpdateColorValues( bool bUpdatePreset ) +{ + if (eCM != ColorModel::RGB) + { + ConvertColorValues (aPreviousColor, eCM ); + ConvertColorValues (aCurrentColor.m_aColor, eCM); + + m_xCcustom->set_value( ColorToPercent_Impl( aCurrentColor.m_aColor.GetRed() ), FieldUnit::PERCENT ); + m_xMcustom->set_value( ColorToPercent_Impl( aCurrentColor.m_aColor.GetBlue() ), FieldUnit::PERCENT ); + m_xYcustom->set_value( ColorToPercent_Impl( aCurrentColor.m_aColor.GetGreen() ), FieldUnit::PERCENT ); + m_xKcustom->set_value( ColorToPercent_Impl( 255 - aCurrentColor.m_aColor.GetAlpha() ), FieldUnit::PERCENT ); + + if( bUpdatePreset ) + { + m_xCpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetRed()), + Application::GetSettings().GetUILanguageTag())); + m_xMpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetBlue()), + Application::GetSettings().GetUILanguageTag())); + m_xYpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(aPreviousColor.GetGreen()), + Application::GetSettings().GetUILanguageTag())); + m_xKpreset->set_text(unicode::formatPercent(ColorToPercent_Impl(255 - aPreviousColor.GetAlpha()), + Application::GetSettings().GetUILanguageTag())); + } + + ConvertColorValues (aPreviousColor, ColorModel::RGB); + ConvertColorValues (aCurrentColor.m_aColor, ColorModel::RGB); + } + else + { + m_xRcustom->set_value( ColorToPercent_Impl( aCurrentColor.m_aColor.GetRed() ) ); + m_xGcustom->set_value( ColorToPercent_Impl( aCurrentColor.m_aColor.GetGreen() ) ); + m_xBcustom->set_value( ColorToPercent_Impl( aCurrentColor.m_aColor.GetBlue() ) ); + m_xHexcustom->SetColor( aCurrentColor.m_aColor ); + + if( bUpdatePreset ) + { + m_xRpreset->set_text(OUString::number(ColorToPercent_Impl(aPreviousColor.GetRed()))); + m_xGpreset->set_text(OUString::number(ColorToPercent_Impl(aPreviousColor.GetGreen()))); + m_xBpreset->set_text(OUString::number(ColorToPercent_Impl(aPreviousColor.GetBlue()))); + m_xHexpreset->SetColor( aPreviousColor ); + } + } +} + +sal_Int32 SvxColorTabPage::FindInCustomColors(std::u16string_view aColorName) +{ + css::uno::Sequence< OUString > aCustomColorNameList(officecfg::Office::Common::UserColors::CustomColorName::get()); + tools::Long nCount = aCustomColorNameList.getLength(); + bool bValidColorName = true; + sal_Int32 nPos = -1; + + for(tools::Long i = 0;i < nCount && bValidColorName;i++) + { + if(aColorName == aCustomColorNameList[i]) + { + nPos = i; + bValidColorName = false; + } + } + return nPos; +} + +sal_Int32 SvxColorTabPage::FindInPalette( const Color& rColor ) +{ + return pColorList->GetIndexOfColor(rColor); +} + +// A RGB value is converted to a CMYK value - not in an ideal way as +// R is converted into C, G into M and B into Y. The K value is held in an +// extra variable. For further color models one should develop own +// classes which should contain the respective casts. + +void SvxColorTabPage::RgbToCmyk_Impl( Color& rColor, sal_uInt16& rK ) +{ + sal_uInt16 const nColor1 = 255 - rColor.GetRed(); + sal_uInt16 const nColor2 = 255 - rColor.GetGreen(); + sal_uInt16 const nColor3 = 255 - rColor.GetBlue(); + + rK = std::min( std::min( nColor1, nColor2 ), nColor3 ); + + rColor.SetRed( sal::static_int_cast< sal_uInt8 >( nColor1 - rK ) ); + rColor.SetGreen( sal::static_int_cast< sal_uInt8 >( nColor2 - rK ) ); + rColor.SetBlue( sal::static_int_cast< sal_uInt8 >( nColor3 - rK ) ); +} + + +// reverse case to RgbToCmyk_Impl (see above) + +void SvxColorTabPage::CmykToRgb_Impl( Color& rColor, const sal_uInt16 nK ) +{ + tools::Long lTemp; + + lTemp = 255 - ( rColor.GetRed() + nK ); + + if( lTemp < 0 ) + lTemp = 0; + rColor.SetRed( static_cast<sal_uInt8>(lTemp) ); + + lTemp = 255 - ( rColor.GetGreen() + nK ); + + if( lTemp < 0 ) + lTemp = 0; + rColor.SetGreen( static_cast<sal_uInt8>(lTemp) ); + + lTemp = 255 - ( rColor.GetBlue() + nK ); + + if( lTemp < 0 ) + lTemp = 0; + rColor.SetBlue( static_cast<sal_uInt8>(lTemp) ); +} + + +sal_uInt16 SvxColorTabPage::ColorToPercent_Impl( sal_uInt16 nColor ) +{ + sal_uInt16 nValue = 0; + + switch (eCM) + { + case ColorModel::RGB : + nValue = nColor; + break; + + case ColorModel::CMYK: + nValue = static_cast<sal_uInt16>( static_cast<double>(nColor) * 100.0 / 255.0 + 0.5 ); + break; + } + + return nValue; +} + + +sal_uInt16 SvxColorTabPage::PercentToColor_Impl( sal_uInt16 nPercent ) +{ + sal_uInt16 nValue = 0; + + switch (eCM) + { + case ColorModel::RGB : + nValue = nPercent; + break; + + case ColorModel::CMYK: + nValue = static_cast<sal_uInt16>( static_cast<double>(nPercent) * 255.0 / 100.0 + 0.5 ); + break; + } + + return nValue; +} + + +void SvxColorTabPage::FillUserData() +{ + // the color model is saved in the Ini-file + SetUserData( OUString::number( static_cast<int>(eCM) ) ); +} + + +void SvxColorTabPage::SetPropertyList( XPropertyListType t, const XPropertyListRef &xRef ) +{ + OSL_ASSERT( t == XPropertyListType::Color ); + pColorList = XColorListRef( static_cast<XColorList *>(xRef.get() ) ); +} + +void SvxColorTabPage::SetColorList( const XColorListRef& pColList ) +{ + SetPropertyList( XPropertyListType::Color, XPropertyListRef( ( pColList.get() ) ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpgradnt.cxx b/cui/source/tabpages/tpgradnt.cxx new file mode 100644 index 000000000..31a846d9c --- /dev/null +++ b/cui/source/tabpages/tpgradnt.cxx @@ -0,0 +1,633 @@ +/* -*- 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 . + */ + +#include <memory> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sfx2/dialoghelper.hxx> + +#include <strings.hrc> +#include <svx/xfillit0.hxx> +#include <svx/xflgrit.hxx> +#include <svx/colorbox.hxx> +#include <svx/xtable.hxx> +#include <svx/xgrscit.hxx> +#include <cuitabarea.hxx> +#include <svx/svxdlg.hxx> +#include <dialmgr.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <sal/log.hxx> + +#define DEFAULT_GRADIENTSTEP 64 + +using namespace com::sun::star; + +SvxGradientTabPage::SvxGradientTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/gradientpage.ui", "GradientPage", &rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnGradientListState(nullptr) + , m_pnColorListState(nullptr) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xLbGradientType(m_xBuilder->weld_combo_box("gradienttypelb")) + , m_xFtCenter(m_xBuilder->weld_label("centerft")) + , m_xMtrCenterX(m_xBuilder->weld_metric_spin_button("centerxmtr", FieldUnit::PERCENT)) + , m_xMtrCenterY(m_xBuilder->weld_metric_spin_button("centerymtr", FieldUnit::PERCENT)) + , m_xFtAngle(m_xBuilder->weld_label("angleft")) + , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("anglemtr", FieldUnit::DEGREE)) + , m_xSliderAngle(m_xBuilder->weld_scale("angleslider")) + , m_xMtrBorder(m_xBuilder->weld_metric_spin_button("bordermtr", FieldUnit::PERCENT)) + , m_xSliderBorder(m_xBuilder->weld_scale("borderslider")) + , m_xLbColorFrom(new ColorListBox(m_xBuilder->weld_menu_button("colorfromlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xMtrColorFrom(m_xBuilder->weld_metric_spin_button("colorfrommtr", FieldUnit::PERCENT)) + , m_xLbColorTo(new ColorListBox(m_xBuilder->weld_menu_button("colortolb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xMtrColorTo(m_xBuilder->weld_metric_spin_button("colortomtr", FieldUnit::PERCENT)) + , m_xGradientLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("gradientpresetlistwin", true))) + , m_xMtrIncrement(m_xBuilder->weld_spin_button("incrementmtr")) + , m_xCbIncrement(m_xBuilder->weld_check_button("autoincrement")) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnModify(m_xBuilder->weld_button("modify")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "previewctl", m_aCtlPreview)) + , m_xGradientLBWin(new weld::CustomWeld(*m_xBuilder, "gradientpresetlist", *m_xGradientLB)) +{ + Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); + m_xGradientLB->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); + // this page needs ExchangeSupport + SetExchangeSupport(); + + // as long as NOT supported by the item + + m_xMtrColorTo->set_value(100, FieldUnit::PERCENT); + m_xMtrColorFrom->set_value(100, FieldUnit::PERCENT); + + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_GRADIENT) ); + m_rXFSet.Put( XFillGradientItem(OUString(), XGradient( COL_BLACK, COL_WHITE )) ); + m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); + + // set handler + m_xGradientLB->SetSelectHdl( LINK( this, SvxGradientTabPage, ChangeGradientHdl ) ); + m_xGradientLB->SetRenameHdl( LINK( this, SvxGradientTabPage, ClickRenameHdl_Impl ) ); + m_xGradientLB->SetDeleteHdl( LINK( this, SvxGradientTabPage, ClickDeleteHdl_Impl ) ); + m_xBtnAdd->connect_clicked(LINK(this, SvxGradientTabPage, ClickAddHdl_Impl)); + m_xBtnModify->connect_clicked(LINK(this, SvxGradientTabPage, ClickModifyHdl_Impl)); + + Link<weld::MetricSpinButton&,void> aLink = LINK( this, SvxGradientTabPage, ModifiedMetricHdl_Impl ); + Link<weld::ComboBox&,void> aLink2 = LINK( this, SvxGradientTabPage, ModifiedListBoxHdl_Impl ); + m_xLbGradientType->connect_changed( aLink2 ); + m_xCbIncrement->connect_toggled(LINK(this, SvxGradientTabPage, ChangeAutoStepHdl_Impl)); + m_xMtrIncrement->connect_value_changed(LINK(this, SvxGradientTabPage, ModifiedEditHdl_Impl)); + m_xMtrCenterX->connect_value_changed( aLink ); + m_xMtrCenterY->connect_value_changed( aLink ); + m_xMtrAngle->connect_value_changed( aLink ); + m_xSliderAngle->connect_value_changed(LINK(this, SvxGradientTabPage, ModifiedSliderHdl_Impl)); + m_xMtrBorder->connect_value_changed( aLink ); + m_xSliderBorder->connect_value_changed(LINK(this, SvxGradientTabPage, ModifiedSliderHdl_Impl)); + m_xMtrColorFrom->connect_value_changed( aLink ); + Link<ColorListBox&,void> aLink3 = LINK( this, SvxGradientTabPage, ModifiedColorListBoxHdl_Impl ); + m_xLbColorFrom->SetSelectHdl( aLink3 ); + m_xMtrColorTo->connect_value_changed( aLink ); + m_xLbColorTo->SetSelectHdl( aLink3 ); + + m_xGradientLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); + + // #i76307# always paint the preview in LTR, because this is what the document does + m_aCtlPreview.EnableRTL(false); +} + +SvxGradientTabPage::~SvxGradientTabPage() +{ + m_xCtlPreview.reset(); + m_xGradientLBWin.reset(); + m_xGradientLB.reset(); + m_xLbColorTo.reset(); + m_xLbColorFrom.reset(); +} + +void SvxGradientTabPage::Construct() +{ + m_xGradientLB->FillPresetListBox( *m_pGradientList ); +} + +void SvxGradientTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( !m_pColorList.is() ) + return; + + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + SvxAreaTabDialog* pArea = (*m_pnColorListState & ChangeType::CHANGED) ? + dynamic_cast<SvxAreaTabDialog*>(GetDialogController()) : nullptr; + if (pArea) + m_pColorList = pArea->GetNewColorList(); + + ModifiedHdl_Impl( this ); + } + + // determining (and possibly cutting) the name and + // displaying it in the GroupBox + OUString aString = CuiResId( RID_CUISTR_TABLE ) + ": "; + INetURLObject aURL( m_pGradientList->GetPath() ); + + aURL.Append( m_pGradientList->GetName() ); + SAL_WARN_IF( aURL.GetProtocol() == INetProtocol::NotValid, "cui.tabpages", "invalid URL" ); + + if ( aURL.getBase().getLength() > 18 ) + { + aString += OUString::Concat(aURL.getBase().subView( 0, 15 )) + "..."; + } + else + aString += aURL.getBase(); + + sal_Int32 nPos = SearchGradientList( rSet.Get(XATTR_FILLGRADIENT).GetName() ); + if ( nPos != -1) + { + sal_uInt16 nId = m_xGradientLB->GetItemId( static_cast<size_t>( nPos ) ); + m_xGradientLB->SelectItem( nId ); + } + // colors could have been deleted + ChangeGradientHdl_Impl(); +} + + +DeactivateRC SvxGradientTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +bool SvxGradientTabPage::FillItemSet( SfxItemSet* rSet ) +{ + std::unique_ptr<XGradient> pXGradient; + size_t nPos = m_xGradientLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xGradientLB->GetSelectItemPos(); + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + pXGradient.reset(new XGradient( m_pGradientList->GetGradient( static_cast<sal_uInt16>(nPos) )->GetGradient() )); + OUString aString = m_xGradientLB->GetItemText( m_xGradientLB->GetSelectedItemId() ); + rSet->Put( XFillGradientItem( aString, *pXGradient ) ); + } + else + // gradient was passed (unidentified) + { + pXGradient.reset(new XGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + static_cast<css::awt::GradientStyle>(m_xLbGradientType->get_active()), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)), // should be changed in resource + static_cast<sal_uInt16>(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrIncrement->get_value()) )); + rSet->Put( XFillGradientItem( OUString(), *pXGradient ) ); + } + + sal_uInt16 nValue = 0; + if (!m_xCbIncrement->get_active()) + nValue = m_xMtrIncrement->get_value(); + + assert( pXGradient && "XGradient could not be created" ); + rSet->Put( XFillStyleItem( drawing::FillStyle_GRADIENT ) ); + rSet->Put( XGradientStepCountItem( nValue ) ); + return true; +} + +void SvxGradientTabPage::Reset( const SfxItemSet* ) +{ + m_xMtrIncrement->set_value(DEFAULT_GRADIENTSTEP); + ChangeGradientHdl_Impl(); + + // determine state of the buttons + if( m_pGradientList->Count() ) + m_xBtnModify->set_sensitive(true); + else + m_xBtnModify->set_sensitive(false); +} + +std::unique_ptr<SfxTabPage> SvxGradientTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rOutAttrs ) +{ + return std::make_unique<SvxGradientTabPage>(pPage, pController, *rOutAttrs); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedListBoxHdl_Impl, weld::ComboBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + // gradient params changed, it is no longer one of the presets + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedColorListBoxHdl_Impl, ColorListBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedEditHdl_Impl, weld::SpinButton&, rBox, void ) +{ + ModifiedHdl_Impl(&rBox); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedMetricHdl_Impl, weld::MetricSpinButton&, rBox, void ) +{ + ModifiedHdl_Impl(&rBox); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK( SvxGradientTabPage, ModifiedSliderHdl_Impl, weld::Scale&, rSlider, void ) +{ + ModifiedHdl_Impl(&rSlider); + m_xGradientLB->SetNoSelection(); +} + +IMPL_LINK_NOARG( SvxGradientTabPage, ChangeAutoStepHdl_Impl, weld::Toggleable&, void ) +{ + if (m_xCbIncrement->get_active()) + { + m_xMtrIncrement->set_sensitive(false); + } + else + { + m_xMtrIncrement->set_sensitive(true); + } + ModifiedHdl_Impl(m_xMtrIncrement.get()); +} + +void SvxGradientTabPage::ModifiedHdl_Impl( void const * pControl ) +{ + if (pControl == m_xMtrBorder.get()) + m_xSliderBorder->set_value(m_xMtrBorder->get_value(FieldUnit::NONE)); + if (pControl == m_xSliderBorder.get()) + m_xMtrBorder->set_value(m_xSliderBorder->get_value(), FieldUnit::NONE); + if (pControl == m_xMtrAngle.get()) + m_xSliderAngle->set_value(m_xMtrAngle->get_value(FieldUnit::NONE)); + if (pControl == m_xSliderAngle.get()) + m_xMtrAngle->set_value(m_xSliderAngle->get_value(), FieldUnit::NONE); + + css::awt::GradientStyle eXGS = static_cast<css::awt::GradientStyle>(m_xLbGradientType->get_active()); + + XGradient aXGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + eXGS, + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)), // should be changed in resource + static_cast<sal_uInt16>(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrIncrement->get_value()) ); + + // enable/disable controls + if (pControl == m_xLbGradientType.get() || pControl == this) + SetControlState_Impl( eXGS ); + + sal_uInt16 nValue = 0; + if (!m_xCbIncrement->get_active()) + nValue = static_cast<sal_uInt16>(m_xMtrIncrement->get_value()); + m_rXFSet.Put( XGradientStepCountItem( nValue ) ); + + // displaying in XOutDev + m_rXFSet.Put( XFillGradientItem( OUString(), aXGradient ) ); + m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName( SvxResId( RID_SVXSTR_GRADIENT ) ); + OUString aDesc( CuiResId( RID_CUISTR_DESC_GRADIENT ) ); + OUString aName; + + tools::Long nCount = m_pGradientList->Count(); + tools::Long j = 1; + bool bValidGradientName = false; + + while( !bValidGradientName ) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidGradientName = (SearchGradientList(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError = 1; + + while (pDlg->Execute() == RET_OK) + { + pDlg->GetName( aName ); + + bValidGradientName = (SearchGradientList(aName) == -1); + + if (bValidGradientName) + { + nError = 0; + break; + } + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + pDlg.disposeAndClear(); + + if( !nError ) + { + XGradient aXGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + static_cast<css::awt::GradientStyle>(m_xLbGradientType->get_active()), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)), // should be changed in resource + static_cast<sal_uInt16>(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrIncrement->get_value()) ); + + m_pGradientList->Insert(std::make_unique<XGradientEntry>(aXGradient, aName), nCount); + + sal_Int32 nId = m_xGradientLB->GetItemId(nCount - 1); //calculate the last ID + BitmapEx aBitmap = m_pGradientList->GetBitmapForPreview( nCount, m_xGradientLB->GetIconSize() ); + m_xGradientLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xGradientLB->SelectItem( nId + 1 ); + m_xGradientLB->Resize(); + + *m_pnGradientListState |= ChangeType::MODIFIED; + + ChangeGradientHdl_Impl(); + } + + // determine button state + if (m_pGradientList->Count()) + m_xBtnModify->set_sensitive(true); +} + + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aName( m_pGradientList->GetGradient( static_cast<sal_uInt16>(nPos) )->GetName() ); + + XGradient aXGradient( m_xLbColorFrom->GetSelectEntryColor(), + m_xLbColorTo->GetSelectEntryColor(), + static_cast<css::awt::GradientStyle>(m_xLbGradientType->get_active()), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)), // should be changed in resource + static_cast<sal_uInt16>(m_xMtrCenterX->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrCenterY->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrBorder->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorFrom->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrColorTo->get_value(FieldUnit::NONE)), + static_cast<sal_uInt16>(m_xMtrIncrement->get_value()) ); + + m_pGradientList->Replace(std::make_unique<XGradientEntry>(aXGradient, aName), nPos); + + BitmapEx aBitmap = m_pGradientList->GetBitmapForPreview( static_cast<sal_uInt16>(nPos), m_xGradientLB->GetIconSize() ); + m_xGradientLB->RemoveItem( nId ); + m_xGradientLB->InsertItem( nId, Image(aBitmap), aName, static_cast<sal_uInt16>(nPos) ); + m_xGradientLB->SelectItem( nId ); + + *m_pnGradientListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletegradientdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskDelGradientDialog")); + if (xQueryBox->run() == RET_YES) + { + m_pGradientList->Remove(nPos); + m_xGradientLB->RemoveItem( nId ); + nId = m_xGradientLB->GetItemId( 0 ); + m_xGradientLB->SelectItem( nId ); + m_xGradientLB->Resize(); + + m_aCtlPreview.Invalidate(); + + ChangeGradientHdl_Impl(); + + *m_pnGradientListState |= ChangeType::MODIFIED; + } + } + // determine button state + if( !m_pGradientList->Count() ) + m_xBtnModify->set_sensitive(false); +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xGradientLB->GetSelectedItemId(); + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc( CuiResId( RID_CUISTR_DESC_GRADIENT ) ); + OUString aName( m_pGradientList->GetGradient( nPos )->GetName() ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nGradientPos = SearchGradientList(aName); + bool bValidGradientName = (nGradientPos == static_cast<sal_Int32>(nPos) ) || (nGradientPos == -1); + + if( bValidGradientName ) + { + bLoop = false; + m_pGradientList->GetGradient(nPos)->SetName(aName); + + m_xGradientLB->SetItemText( nId, aName ); + m_xGradientLB->SelectItem( nId ); + + *m_pnGradientListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxGradientTabPage, ChangeGradientHdl, ValueSet*, void) +{ + ChangeGradientHdl_Impl(); +} + +void SvxGradientTabPage::ChangeGradientHdl_Impl() +{ + std::unique_ptr<XGradient> pGradient; + size_t nPos = m_xGradientLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + pGradient.reset(new XGradient( m_pGradientList->GetGradient( static_cast<sal_uInt16>( nPos ) )->GetGradient() )); + else + { + if( const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLSTYLE ) ) ) + { + const XFillGradientItem* pGradientItem; + if( ( drawing::FillStyle_GRADIENT == pFillStyleItem->GetValue() ) && + ( pGradientItem = m_rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLGRADIENT ) ) ) ) + { + pGradient.reset(new XGradient( pGradientItem->GetGradientValue() )); + } + } + if( !pGradient ) + { + sal_uInt16 nPosition = m_xGradientLB->GetItemId(0); + m_xGradientLB->SelectItem( nPosition ); + if( nPosition != 0 ) + pGradient.reset(new XGradient( m_pGradientList->GetGradient( 0 )->GetGradient() )); + } + } + + if( !pGradient ) + return; + + css::awt::GradientStyle eXGS = pGradient->GetGradientStyle(); + sal_uInt16 nValue = pGradient->GetSteps(); + if( nValue == 0 ) + { + m_xCbIncrement->set_state(TRISTATE_TRUE); + m_xMtrIncrement->set_sensitive(false); + } + else + { + m_xCbIncrement->set_state(TRISTATE_FALSE); + m_xMtrIncrement->set_sensitive(true); + m_xMtrIncrement->set_value( nValue ); + } + m_xLbGradientType->set_active( + sal::static_int_cast< sal_Int32 >( eXGS ) ); + // if the entry is not in the listbox, + // colors are added temporarily + m_xLbColorFrom->SetNoSelection(); + m_xLbColorFrom->SelectEntry( pGradient->GetStartColor() ); + + m_xLbColorTo->SetNoSelection(); + m_xLbColorTo->SelectEntry( pGradient->GetEndColor() ); + + m_xMtrAngle->set_value(pGradient->GetAngle().get() / 10, FieldUnit::NONE); // should be changed in resource + m_xSliderAngle->set_value(pGradient->GetAngle().get() / 10); + m_xMtrBorder->set_value(pGradient->GetBorder(), FieldUnit::NONE); + m_xSliderBorder->set_value(pGradient->GetBorder()); + m_xMtrCenterX->set_value(pGradient->GetXOffset(), FieldUnit::NONE); + m_xMtrCenterY->set_value(pGradient->GetYOffset(), FieldUnit::NONE); + m_xMtrColorFrom->set_value(pGradient->GetStartIntens(), FieldUnit::NONE); + m_xMtrColorTo->set_value(pGradient->GetEndIntens(), FieldUnit::NONE); + + // disable/enable controls + SetControlState_Impl( eXGS ); + + // fill ItemSet and pass it on to aCtlPreview + m_rXFSet.Put( XFillGradientItem( OUString(), *pGradient ) ); + m_rXFSet.Put( XGradientStepCountItem( nValue ) ); + m_aCtlPreview.SetAttributes(m_aXFillAttr.GetItemSet()); + + m_aCtlPreview.Invalidate(); +} + +void SvxGradientTabPage::SetControlState_Impl( css::awt::GradientStyle eXGS ) +{ + switch( eXGS ) + { + case css::awt::GradientStyle_LINEAR: + case css::awt::GradientStyle_AXIAL: + m_xFtCenter->set_sensitive(false); + m_xMtrCenterX->set_sensitive(false); + m_xMtrCenterY->set_sensitive(false); + m_xFtAngle->set_sensitive(true); + m_xMtrAngle->set_sensitive(true); + m_xSliderAngle->set_sensitive(true); + break; + + case css::awt::GradientStyle_RADIAL: + m_xFtCenter->set_sensitive(true); + m_xMtrCenterX->set_sensitive(true); + m_xMtrCenterY->set_sensitive(true); + m_xFtAngle->set_sensitive(false); + m_xMtrAngle->set_sensitive(false); + m_xSliderAngle->set_sensitive(false); + break; + + case css::awt::GradientStyle_ELLIPTICAL: + m_xFtCenter->set_sensitive(true); + m_xMtrCenterX->set_sensitive(true); + m_xMtrCenterY->set_sensitive(true); + m_xFtAngle->set_sensitive(true); + m_xMtrAngle->set_sensitive(true); + m_xSliderAngle->set_sensitive(true); + break; + + case css::awt::GradientStyle_SQUARE: + case css::awt::GradientStyle_RECT: + m_xFtCenter->set_sensitive(true); + m_xMtrCenterX->set_sensitive(true); + m_xMtrCenterY->set_sensitive(true); + m_xFtAngle->set_sensitive(true); + m_xMtrAngle->set_sensitive(true); + m_xSliderAngle->set_sensitive(true); + break; + default: + break; + } +} + +sal_Int32 SvxGradientTabPage::SearchGradientList(std::u16string_view rGradientName) +{ + tools::Long nCount = m_pGradientList->Count(); + bool bValidGradientName = true; + sal_Int32 nPos = -1; + + for(tools::Long i = 0;i < nCount && bValidGradientName;i++) + { + if(rGradientName == m_pGradientList->GetGradient( i )->GetName()) + { + nPos = i; + bValidGradientName = false; + } + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tphatch.cxx b/cui/source/tabpages/tphatch.cxx new file mode 100644 index 000000000..1a3511473 --- /dev/null +++ b/cui/source/tabpages/tphatch.cxx @@ -0,0 +1,562 @@ +/* -*- 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 . + */ + +#include <memory> +#include <tools/urlobj.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sfx2/dialoghelper.hxx> + +#include <strings.hrc> +#include <svx/xfillit0.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xflclit.hxx> +#include <svx/colorbox.hxx> +#include <svx/xtable.hxx> +#include <svx/xflbckit.hxx> +#include <cuitabarea.hxx> +#include <svx/svxdlg.hxx> +#include <dialmgr.hxx> +#include <svx/dlgutil.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <svx/svxids.hrc> +#include <sal/log.hxx> +#include <svtools/unitconv.hxx> + +using namespace com::sun::star; + +SvxHatchTabPage::SvxHatchTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/hatchpage.ui", "HatchPage", &rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnHatchingListState(nullptr) + , m_pnColorListState(nullptr) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xMtrDistance(m_xBuilder->weld_metric_spin_button("distancemtr", FieldUnit::MM)) + , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("anglemtr", FieldUnit::DEGREE)) + , m_xSliderAngle(m_xBuilder->weld_scale("angleslider")) + , m_xLbLineType(m_xBuilder->weld_combo_box("linetypelb")) + , m_xLbLineColor(new ColorListBox(m_xBuilder->weld_menu_button("linecolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xCbBackgroundColor(m_xBuilder->weld_check_button("backgroundcolor")) + , m_xLbBackgroundColor(new ColorListBox(m_xBuilder->weld_menu_button("backgroundcolorlb"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xHatchLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("hatchpresetlistwin", true))) + , m_xBtnAdd(m_xBuilder->weld_button("add")) + , m_xBtnModify(m_xBuilder->weld_button("modify")) + , m_xHatchLBWin(new weld::CustomWeld(*m_xBuilder, "hatchpresetlist", *m_xHatchLB)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "previewctl", m_aCtlPreview)) +{ + Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); + m_xHatchLBWin->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + SetFieldUnit( *m_xMtrDistance, eFUnit ); + + // determine PoolUnit + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + assert( pPool && "Where is the pool?" ); + m_ePoolUnit = pPool->GetMetric( SID_ATTR_FILL_HATCH ); + + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_HATCH) ); + m_rXFSet.Put( XFillHatchItem(OUString(), XHatch()) ); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_xHatchLB->SetSelectHdl( LINK( this, SvxHatchTabPage, ChangeHatchHdl ) ); + m_xHatchLB->SetRenameHdl( LINK( this, SvxHatchTabPage, ClickRenameHdl_Impl ) ); + m_xHatchLB->SetDeleteHdl( LINK( this, SvxHatchTabPage, ClickDeleteHdl_Impl ) ); + + Link<weld::MetricSpinButton&,void> aLink = LINK( this, SvxHatchTabPage, ModifiedEditHdl_Impl ); + Link<weld::ComboBox&,void> aLink2 = LINK( this, SvxHatchTabPage, ModifiedListBoxHdl_Impl ); + m_xMtrDistance->connect_value_changed( aLink ); + m_xMtrAngle->connect_value_changed( aLink ); + m_xSliderAngle->connect_value_changed(LINK(this, SvxHatchTabPage, ModifiedSliderHdl_Impl)); + m_xLbLineType->connect_changed( aLink2 ); + Link<ColorListBox&,void> aLink3 = LINK( this, SvxHatchTabPage, ModifiedColorListBoxHdl_Impl ); + m_xLbLineColor->SetSelectHdl( aLink3 ); + m_xCbBackgroundColor->connect_toggled( LINK( this, SvxHatchTabPage, ToggleHatchBackgroundColor_Impl ) ); + m_xLbBackgroundColor->SetSelectHdl( LINK( this, SvxHatchTabPage, ModifiedBackgroundHdl_Impl ) ); + + m_xBtnAdd->connect_clicked( LINK( this, SvxHatchTabPage, ClickAddHdl_Impl ) ); + m_xBtnModify->connect_clicked( LINK( this, SvxHatchTabPage, ClickModifyHdl_Impl ) ); + + m_xHatchLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); + + m_aCtlPreview.SetDrawMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode() ? OUTPUT_DRAWMODE_CONTRAST : OUTPUT_DRAWMODE_COLOR); +} + +SvxHatchTabPage::~SvxHatchTabPage() +{ + m_xCtlPreview.reset(); + m_xHatchLBWin.reset(); + m_xHatchLB.reset(); + m_xLbBackgroundColor.reset(); + m_xLbLineColor.reset(); +} + +void SvxHatchTabPage::Construct() +{ + m_xHatchLB->FillPresetListBox(*m_pHatchingList); +} + +void SvxHatchTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( m_pColorList.is() ) + { + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + SvxAreaTabDialog* pArea = (*m_pnColorListState & ChangeType::CHANGED) ? + dynamic_cast<SvxAreaTabDialog*>(GetDialogController()) : nullptr; + if (pArea) + m_pColorList = pArea->GetNewColorList(); + + ModifiedHdl_Impl( this ); + } + + // determining (possibly cutting) the name + // and displaying it in the GroupBox + OUString aString = CuiResId( RID_CUISTR_TABLE ) + ": "; + INetURLObject aURL( m_pHatchingList->GetPath() ); + + aURL.Append( m_pHatchingList->GetName() ); + SAL_WARN_IF( aURL.GetProtocol() == INetProtocol::NotValid, "cui.tabpages", "invalid URL" ); + + if ( aURL.getBase().getLength() > 18 ) + { + aString += OUString::Concat(aURL.getBase().subView( 0, 15 )) + "..."; + } + else + aString += aURL.getBase(); + + sal_Int32 nPos = SearchHatchList( rSet.Get(XATTR_FILLHATCH).GetName() ); + if( nPos != -1) + { + sal_uInt16 nId = m_xHatchLB->GetItemId( static_cast<size_t>( nPos ) ); + m_xHatchLB->SelectItem( nId ); + } + // colors could have been deleted + ChangeHatchHdl_Impl(); + } + + XFillBackgroundItem aBckItem( rSet.Get(XATTR_FILLBACKGROUND)); + m_rXFSet.Put( aBckItem ); + + if (aBckItem.GetValue()) + { + m_xCbBackgroundColor->set_state(TRISTATE_TRUE); + XFillColorItem aColorItem( rSet.Get(XATTR_FILLCOLOR) ); + Color aColor(aColorItem.GetColorValue()); + m_xLbBackgroundColor->SelectEntry(aColor); + m_xLbBackgroundColor->set_sensitive(true); + m_rXFSet.Put( aColorItem ); + } + else + { + m_xCbBackgroundColor->set_state(TRISTATE_FALSE); + m_xLbBackgroundColor->SelectEntry(COL_AUTO); + m_xLbBackgroundColor->set_sensitive(false); + } + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +DeactivateRC SvxHatchTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +sal_Int32 SvxHatchTabPage::SearchHatchList(std::u16string_view rHatchName) +{ + tools::Long nCount = m_pHatchingList->Count(); + bool bValidHatchName = true; + sal_Int32 nPos = -1; + + for(tools::Long i = 0;i < nCount && bValidHatchName;i++) + { + if(rHatchName == m_pHatchingList->GetHatch( i )->GetName()) + { + nPos = i; + bValidHatchName = false; + } + } + return nPos; +} + +bool SvxHatchTabPage::FillItemSet( SfxItemSet* rSet ) +{ + std::unique_ptr<XHatch> pXHatch; + OUString aString; + size_t nPos = m_xHatchLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xHatchLB->GetSelectItemPos(); + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + pXHatch.reset(new XHatch( m_pHatchingList->GetHatch( static_cast<sal_uInt16>(nPos) )->GetHatch() )); + aString = m_xHatchLB->GetItemText( m_xHatchLB->GetSelectedItemId() ); + } + // unidentified hatch has been passed + else + { + pXHatch.reset(new XHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast<css::drawing::HatchStyle>(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)) )); + } + assert( pXHatch && "XHatch couldn't be created" ); + rSet->Put( XFillStyleItem( drawing::FillStyle_HATCH ) ); + rSet->Put( XFillHatchItem( aString, *pXHatch ) ); + rSet->Put( XFillBackgroundItem( m_xCbBackgroundColor->get_active() ) ); + if (m_xCbBackgroundColor->get_active()) + { + NamedColor aColor = m_xLbBackgroundColor->GetSelectedEntry(); + rSet->Put(XFillColorItem(aColor.second, aColor.first)); + } + return true; +} + +void SvxHatchTabPage::Reset( const SfxItemSet* rSet ) +{ + ChangeHatchHdl_Impl(); + + XFillColorItem aColItem( rSet->Get(XATTR_FILLCOLOR) ); + m_xLbBackgroundColor->SelectEntry(aColItem.GetColorValue()); + m_rXFSet.Put( aColItem ); + + XFillBackgroundItem aBckItem( rSet->Get(XATTR_FILLBACKGROUND) ); + if(aBckItem.GetValue()) + m_xCbBackgroundColor->set_state(TRISTATE_TRUE); + else + m_xCbBackgroundColor->set_state(TRISTATE_FALSE); + m_rXFSet.Put( aBckItem ); + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +std::unique_ptr<SfxTabPage> SvxHatchTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet ) +{ + return std::make_unique<SvxHatchTabPage>(pPage, pController, *rSet); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedListBoxHdl_Impl, weld::ComboBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + // hatch params have changed, it is no longer one of the presets + m_xHatchLB->SetNoSelection(); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedColorListBoxHdl_Impl, ColorListBox&, rListBox, void ) +{ + ModifiedHdl_Impl(&rListBox); + m_xHatchLB->SetNoSelection(); +} + +IMPL_LINK_NOARG( SvxHatchTabPage, ToggleHatchBackgroundColor_Impl, weld::Toggleable&, void ) +{ + if (m_xCbBackgroundColor->get_active()) + m_xLbBackgroundColor->set_sensitive(true); + else + m_xLbBackgroundColor->set_sensitive(false); + m_rXFSet.Put( XFillBackgroundItem( m_xCbBackgroundColor->get_active() ) ); + ModifiedBackgroundHdl_Impl(*m_xLbBackgroundColor); +} + +IMPL_LINK_NOARG( SvxHatchTabPage, ModifiedBackgroundHdl_Impl, ColorListBox&, void ) +{ + Color aColor(COL_TRANSPARENT); + if (m_xCbBackgroundColor->get_active()) + { + aColor = m_xLbBackgroundColor->GetSelectEntryColor(); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + m_rXFSet.Put(XFillColorItem( OUString(), aColor )); + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedEditHdl_Impl, weld::MetricSpinButton&, rEdit, void ) +{ + ModifiedHdl_Impl(&rEdit); + m_xHatchLB->SetNoSelection(); +} + +IMPL_LINK( SvxHatchTabPage, ModifiedSliderHdl_Impl, weld::Scale&, rSlider, void ) +{ + ModifiedHdl_Impl(&rSlider); + m_xHatchLB->SetNoSelection(); +} + +void SvxHatchTabPage::ModifiedHdl_Impl( void const * p ) +{ + if (p == m_xMtrAngle.get()) + m_xSliderAngle->set_value(m_xMtrAngle->get_value(FieldUnit::NONE)); + + if (p == m_xSliderAngle.get()) + m_xMtrAngle->set_value(m_xSliderAngle->get_value(), FieldUnit::NONE); + + XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast<css::drawing::HatchStyle>(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)) ); + + m_rXFSet.Put( XFillHatchItem( OUString(), aXHatch ) ); + + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ChangeHatchHdl, ValueSet*, void) +{ + ChangeHatchHdl_Impl(); +} + +void SvxHatchTabPage::ChangeHatchHdl_Impl() +{ + std::unique_ptr<XHatch> pHatch; + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + pHatch.reset(new XHatch( m_pHatchingList->GetHatch( static_cast<sal_uInt16>(nPos) )->GetHatch() )); + else + { + if( const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLSTYLE ) ) ) + { + const XFillHatchItem* pFillHatchItem; + if( ( drawing::FillStyle_HATCH == pFillStyleItem->GetValue() ) && + ( pFillHatchItem = m_rOutAttrs.GetItemIfSet( GetWhich( XATTR_FILLHATCH ) ) ) ) + { + pHatch.reset(new XHatch( pFillHatchItem->GetHatchValue() )); + } + } + if( !pHatch ) + { + sal_uInt16 nPosition = m_xHatchLB->GetItemId( 0 ); + m_xHatchLB->SelectItem( nPosition ); + if( nPosition != 0 ) + pHatch.reset( new XHatch( m_pHatchingList->GetHatch( 0 )->GetHatch() ) ); + } + } + if( pHatch ) + { + m_xLbLineType->set_active( + sal::static_int_cast< sal_Int32 >( pHatch->GetHatchStyle() ) ); + m_xLbLineColor->SetNoSelection(); + m_xLbLineColor->SelectEntry( pHatch->GetColor() ); + SetMetricValue( *m_xMtrDistance, pHatch->GetDistance(), m_ePoolUnit ); + tools::Long nHatchAngle = pHatch->GetAngle().get() / 10; + m_xMtrAngle->set_value(nHatchAngle, FieldUnit::NONE); + m_xSliderAngle->set_value(nHatchAngle); + + // fill ItemSet and pass it on to m_aCtlPreview + m_rXFSet.Put( XFillHatchItem( OUString(), *pHatch ) ); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + + m_aCtlPreview.Invalidate(); + pHatch.reset(); + } + m_xMtrDistance->save_value(); + m_xMtrAngle->save_value(); + m_xLbLineType->save_value(); + m_xLbLineColor->SaveValue(); + m_xLbBackgroundColor->SaveValue(); +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName( SvxResId( RID_SVXSTR_HATCH ) ); + OUString aDesc( CuiResId( RID_CUISTR_DESC_HATCH ) ); + OUString aName; + + tools::Long nCount = m_pHatchingList->Count(); + tools::Long j = 1; + bool bValidHatchName = false; + + while( !bValidHatchName ) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidHatchName = (SearchHatchList(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError = 1; + + while( pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + + bValidHatchName = (SearchHatchList(aName) == -1); + if( bValidHatchName ) + { + nError = 0; + break; + } + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + pDlg.disposeAndClear(); + + if( nError ) + return; + + XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast<css::drawing::HatchStyle>(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)) ); + + m_pHatchingList->Insert(std::make_unique<XHatchEntry>(aXHatch, aName), nCount); + + sal_Int32 nId = m_xHatchLB->GetItemId(nCount - 1); // calculate the last ID + BitmapEx aBitmap = m_pHatchingList->GetBitmapForPreview( nCount, m_xHatchLB->GetIconSize() ); + // Insert the new entry at the next ID + m_xHatchLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xHatchLB->SelectItem( nId + 1 ); + m_xHatchLB->Resize(); + + *m_pnHatchingListState |= ChangeType::MODIFIED; + + ChangeHatchHdl_Impl(); +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aName( m_pHatchingList->GetHatch( static_cast<sal_uInt16>(nPos) )->GetName() ); + + XHatch aXHatch( m_xLbLineColor->GetSelectEntryColor(), + static_cast<css::drawing::HatchStyle>(m_xLbLineType->get_active()), + GetCoreValue( *m_xMtrDistance, m_ePoolUnit ), + Degree10(static_cast<sal_Int16>(m_xMtrAngle->get_value(FieldUnit::NONE) * 10)) ); + + m_pHatchingList->Replace(std::make_unique<XHatchEntry>(aXHatch, aName), nPos); + + BitmapEx aBitmap = m_pHatchingList->GetBitmapForPreview( static_cast<sal_uInt16>(nPos), m_xHatchLB->GetIconSize() ); + m_xHatchLB->RemoveItem( nId ); + m_xHatchLB->InsertItem( nId, Image(aBitmap), aName, static_cast<sal_uInt16>(nPos) ); + m_xHatchLB->SelectItem( nId ); + + // save values for changes recognition (-> method) + m_xMtrDistance->save_value(); + m_xMtrAngle->save_value(); + m_xLbLineType->save_value(); + m_xLbLineColor->SaveValue(); + m_xLbBackgroundColor->SaveValue(); + + *m_pnHatchingListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletehatchdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskDelHatchDialog")); + if (xQueryBox->run() != RET_YES) + return; + + m_pHatchingList->Remove(nPos); + m_xHatchLB->RemoveItem( nId ); + nId = m_xHatchLB->GetItemId(0); + m_xHatchLB->SelectItem( nId ); + m_xHatchLB->Resize(); + + m_aCtlPreview.Invalidate(); + + ChangeHatchHdl_Impl(); + + *m_pnHatchingListState |= ChangeType::MODIFIED; +} + +IMPL_LINK_NOARG(SvxHatchTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void ) +{ + sal_uInt16 nId = m_xHatchLB->GetSelectedItemId(); + size_t nPos = m_xHatchLB->GetSelectItemPos(); + + if( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc( CuiResId( RID_CUISTR_DESC_HATCH ) ); + OUString aName( m_pHatchingList->GetHatch( nPos )->GetName() ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nHatchPos = SearchHatchList( aName ); + bool bValidHatchName = (nHatchPos == static_cast<sal_Int32>(nPos) ) || (nHatchPos == -1); + + if(bValidHatchName) + { + bLoop = false; + m_pHatchingList->GetHatch(nPos)->SetName(aName); + + m_xHatchLB->SetItemText(nId, aName); + m_xHatchLB->SelectItem( nId ); + + *m_pnHatchingListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpline.cxx b/cui/source/tabpages/tpline.cxx new file mode 100644 index 000000000..04eaa41b9 --- /dev/null +++ b/cui/source/tabpages/tpline.cxx @@ -0,0 +1,1695 @@ +/* -*- 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 . + */ + +#include <memory> +#include <editeng/sizeitem.hxx> +#include <osl/file.hxx> +#include <tools/urlobj.hxx> + +#include <strings.hrc> +#include <svx/colorbox.hxx> +#include <svx/dlgctrl.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlinjoit.hxx> +#include <svx/xlncapit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnstcit.hxx> +#include <svx/xlnedcit.hxx> + + +#include <svx/tabline.hxx> +#include <svx/xtable.hxx> +#include <svx/drawitem.hxx> +#include <cuitabline.hxx> +#include <dialmgr.hxx> +#include <svx/dlgutil.hxx> +#include <svx/svxgraphicitem.hxx> +#include <svx/ofaitem.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdview.hxx> +#include <svx/svdmodel.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <editeng/numitem.hxx> +#include <editeng/brushitem.hxx> +#include <svx/gallery.hxx> +#include <sfx2/opengrf.hxx> +#include <svx/dialmgr.hxx> +#include <svx/svxids.hrc> +#include <svx/strings.hrc> +#include <cuitabarea.hxx> +#include <svtools/unitconv.hxx> +#include <comphelper/lok.hxx> + +#define MAX_BMP_WIDTH 16 +#define MAX_BMP_HEIGHT 16 + +using namespace com::sun::star; + +// static ---------------------------------------------------------------- + +const WhichRangesContainer SvxLineTabPage::pLineRanges(svl::Items< + XATTR_LINETRANSPARENCE, XATTR_LINETRANSPARENCE, + SID_ATTR_LINE_STYLE, SID_ATTR_LINE_ENDCENTER +>); + +SvxLineTabPage::SvxLineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/linetabpage.ui", "LineTabPage", &rInAttrs) + , m_pSymbolList(nullptr) + , m_bNewSize(false) + , m_nSymbolType(SVX_SYMBOLTYPE_UNKNOWN) // unknown respectively unchanged + , m_bLastWidthModified(false) + , m_aSymbolLastSize(Size(0,0)) + , m_bSymbols(false) + , m_rOutAttrs(rInAttrs) + , m_bObjSelected(false) + , m_aXLineAttr(rInAttrs.GetPool()) + , m_rXLSet(m_aXLineAttr.GetItemSet()) + , m_pnLineEndListState(nullptr) + , m_pnDashListState(nullptr) + , m_pnColorListState(nullptr) + , m_nPageType(PageType::Area) + , m_nDlgType(0) + , m_pPosDashLb(nullptr) + , m_pPosLineEndLb(nullptr) + , m_xBoxColor(m_xBuilder->weld_widget("boxCOLOR")) + , m_xLbLineStyle(new SvxLineLB(m_xBuilder->weld_combo_box("LB_LINE_STYLE"))) + , m_xLbColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_COLOR"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xBoxWidth(m_xBuilder->weld_widget("boxWIDTH")) + , m_xMtrLineWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_LINE_WIDTH", FieldUnit::CM)) + , m_xBoxTransparency(m_xBuilder->weld_widget("boxTRANSPARENCY")) + , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button("MTR_LINE_TRANSPARENT", FieldUnit::PERCENT)) + , m_xFlLineEnds(m_xBuilder->weld_widget("FL_LINE_ENDS")) + , m_xBoxArrowStyles(m_xBuilder->weld_widget("boxARROW_STYLES")) + , m_xLbStartStyle(new SvxLineEndLB(m_xBuilder->weld_combo_box("LB_START_STYLE"))) + , m_xBoxStart(m_xBuilder->weld_widget("boxSTART")) + , m_xMtrStartWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_START_WIDTH", FieldUnit::CM)) + , m_xTsbCenterStart(m_xBuilder->weld_check_button("TSB_CENTER_START")) + , m_xBoxEnd(m_xBuilder->weld_widget("boxEND")) + , m_xLbEndStyle(new SvxLineEndLB(m_xBuilder->weld_combo_box("LB_END_STYLE"))) + , m_xMtrEndWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_END_WIDTH", FieldUnit::CM)) + , m_xTsbCenterEnd(m_xBuilder->weld_check_button("TSB_CENTER_END")) + , m_xCbxSynchronize(m_xBuilder->weld_check_button("CBX_SYNCHRONIZE")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) + , m_xFLEdgeStyle(m_xBuilder->weld_widget("FL_EDGE_STYLE")) + , m_xGridEdgeCaps(m_xBuilder->weld_widget("gridEDGE_CAPS")) + , m_xLBEdgeStyle(m_xBuilder->weld_combo_box("LB_EDGE_STYLE")) + , m_xLBCapStyle(m_xBuilder->weld_combo_box("LB_CAP_STYLE")) // LineCaps + , m_xFlSymbol(m_xBuilder->weld_widget("FL_SYMBOL_FORMAT")) //#58425# Symbols on a line (e.g. StarChart) + , m_xGridIconSize(m_xBuilder->weld_widget("gridICON_SIZE")) + , m_xSymbolMB(m_xBuilder->weld_menu_button("MB_SYMBOL_BITMAP")) + , m_xSymbolWidthMF(m_xBuilder->weld_metric_spin_button("MF_SYMBOL_WIDTH", FieldUnit::CM)) + , m_xSymbolHeightMF(m_xBuilder->weld_metric_spin_button("MF_SYMBOL_HEIGHT", FieldUnit::CM)) + , m_xSymbolRatioCB(m_xBuilder->weld_check_button("CB_SYMBOL_RATIO")) +{ + // This Page requires ExchangeSupport + SetExchangeSupport(); + + // Metric set + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + [[fallthrough]]; // we now have mm + case FieldUnit::MM: + m_xMtrLineWidth->set_increments(50, 500, FieldUnit::NONE); + m_xMtrStartWidth->set_increments(50, 500, FieldUnit::NONE); + m_xMtrEndWidth->set_increments(50, 500, FieldUnit::NONE); + break; + + case FieldUnit::INCH: + m_xMtrLineWidth->set_increments(2, 20, FieldUnit::NONE); + m_xMtrStartWidth->set_increments(2, 20, FieldUnit::NONE); + m_xMtrEndWidth->set_increments(2, 20, FieldUnit::NONE); + break; + default: ;// prevent warning + } + SetFieldUnit( *m_xMtrLineWidth, eFUnit ); + SetFieldUnit( *m_xMtrStartWidth, eFUnit ); + SetFieldUnit( *m_xMtrEndWidth, eFUnit ); + + // determine PoolUnit + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + m_ePoolUnit = pPool->GetMetric( SID_ATTR_LINE_WIDTH ); + + m_xLbLineStyle->connect_changed(LINK(this, SvxLineTabPage, ClickInvisibleHdl_Impl)); + m_xLbColor->SetSelectHdl( LINK( this, SvxLineTabPage, ChangePreviewListBoxHdl_Impl ) ); + m_xMtrLineWidth->connect_value_changed(LINK(this, SvxLineTabPage, ChangePreviewModifyHdl_Impl)); + m_xMtrTransparent->connect_value_changed(LINK( this, SvxLineTabPage, ChangeTransparentHdl_Impl)); + + m_xLbStartStyle->connect_changed(LINK(this, SvxLineTabPage, ChangeStartListBoxHdl_Impl)); + m_xLbEndStyle->connect_changed(LINK(this, SvxLineTabPage, ChangeEndListBoxHdl_Impl)); + m_xMtrStartWidth->connect_value_changed(LINK(this, SvxLineTabPage, ChangeStartModifyHdl_Impl)); + m_xMtrEndWidth->connect_value_changed(LINK( this, SvxLineTabPage, ChangeEndModifyHdl_Impl)); + m_xTsbCenterStart->connect_toggled(LINK(this, SvxLineTabPage, ChangeStartClickHdl_Impl)); + m_xTsbCenterEnd->connect_toggled(LINK(this, SvxLineTabPage, ChangeEndClickHdl_Impl)); + + Link<weld::ComboBox&,void> aEdgeStyle = LINK(this, SvxLineTabPage, ChangeEdgeStyleHdl_Impl); + m_xLBEdgeStyle->connect_changed(aEdgeStyle); + + // LineCaps + Link<weld::ComboBox&,void> aCapStyle = LINK(this, SvxLineTabPage, ChangeCapStyleHdl_Impl); + m_xLBCapStyle->connect_changed(aCapStyle); + + // Symbols on a line (eg star charts), MB-handler set + m_xSymbolMB->connect_selected(LINK(this, SvxLineTabPage, GraphicHdl_Impl)); + m_xSymbolMB->connect_toggled(LINK(this, SvxLineTabPage, MenuCreateHdl_Impl)); + m_xSymbolWidthMF->connect_value_changed(LINK(this, SvxLineTabPage, SizeHdl_Impl)); + m_xSymbolHeightMF->connect_value_changed(LINK(this, SvxLineTabPage, SizeHdl_Impl)); + m_xSymbolRatioCB->connect_toggled(LINK(this, SvxLineTabPage, RatioHdl_Impl)); + + m_xSymbolRatioCB->set_active(true); + ShowSymbolControls(false); + + m_nActLineWidth = -1; +} + +void SvxLineTabPage::ShowSymbolControls(bool bOn) +{ + // Symbols on a line (e.g. StarCharts), symbol-enable controls + + m_bSymbols=bOn; + m_xFlSymbol->set_visible(bOn); + m_aCtlPreview.ShowSymbol(bOn); +} + +SvxLineTabPage::~SvxLineTabPage() +{ + m_xCtlPreview.reset(); + m_xLbEndStyle.reset(); + m_xLbStartStyle.reset(); + m_xLbColor.reset(); + m_xLbLineStyle.reset(); + m_aGalleryBrushItems.clear(); + m_aSymbolBrushItems.clear(); +} + +void SvxLineTabPage::Construct() +{ + FillListboxes(); +} + +void SvxLineTabPage::FillListboxes() +{ + // Line styles + auto nOldSelect = m_xLbLineStyle->get_active(); + // aLbLineStyle.FillStyles(); + m_xLbLineStyle->Fill( m_pDashList ); + m_xLbLineStyle->set_active( nOldSelect ); + + // Line end style + OUString sNone( comphelper::LibreOfficeKit::isActive() ? SvxResId( RID_SVXSTR_INVISIBLE ) + : SvxResId( RID_SVXSTR_NONE ) ); + nOldSelect = m_xLbStartStyle->get_active(); + m_xLbStartStyle->clear(); + m_xLbStartStyle->append_text(sNone); + m_xLbStartStyle->Fill(m_pLineEndList); + m_xLbStartStyle->set_active(nOldSelect); + nOldSelect = m_xLbEndStyle->get_active(); + m_xLbEndStyle->clear(); + m_xLbEndStyle->append_text(sNone); + m_xLbEndStyle->Fill(m_pLineEndList, false); + m_xLbEndStyle->set_active(nOldSelect); +} + +void SvxLineTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + const CntUInt16Item* pPageTypeItem = rSet.GetItem<CntUInt16Item>(SID_PAGE_TYPE, false); + if (pPageTypeItem) + SetPageType(static_cast<PageType>(pPageTypeItem->GetValue())); + if( m_nDlgType == 0 && m_pDashList.is() ) + { + sal_Int32 nPos; + sal_Int32 nCount; + + // Dash list + if( ( *m_pnDashListState & ChangeType::MODIFIED ) || + ( *m_pnDashListState & ChangeType::CHANGED ) ) + { + if( *m_pnDashListState & ChangeType::CHANGED ) + m_pDashList = static_cast<SvxLineTabDialog*>(GetDialogController() )->GetNewDashList(); + + *m_pnDashListState = ChangeType::NONE; + + // Style list + nPos = m_xLbLineStyle->get_active(); + + m_xLbLineStyle->clear(); + m_xLbLineStyle->append_text(SvxResId(RID_SVXSTR_INVISIBLE)); + m_xLbLineStyle->append_text(SvxResId(RID_SVXSTR_SOLID)); + m_xLbLineStyle->Fill(m_pDashList); + nCount = m_xLbLineStyle->get_count(); + + if ( nCount == 0 ) + ; // This case should never occur + else if( nCount <= nPos ) + m_xLbLineStyle->set_active(0); + else + m_xLbLineStyle->set_active(nPos); + } + + INetURLObject aDashURL( m_pDashList->GetPath() ); + + aDashURL.Append( m_pDashList->GetName() ); + DBG_ASSERT( aDashURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + // LineEnd list + if( ( *m_pnLineEndListState & ChangeType::MODIFIED ) || ( *m_pnLineEndListState & ChangeType::CHANGED ) ) + { + if( *m_pnLineEndListState & ChangeType::CHANGED ) + m_pLineEndList = static_cast<SvxLineTabDialog*>(GetDialogController())->GetNewLineEndList(); + + *m_pnLineEndListState = ChangeType::NONE; + + nPos = m_xLbLineStyle->get_active(); + OUString sNone( comphelper::LibreOfficeKit::isActive() ? SvxResId( RID_SVXSTR_INVISIBLE ) + : SvxResId( RID_SVXSTR_NONE ) ); + + m_xLbStartStyle->clear(); + m_xLbStartStyle->append_text(sNone); + + m_xLbStartStyle->Fill( m_pLineEndList ); + nCount = m_xLbStartStyle->get_count(); + if( nCount == 0 ) + ; // This case should never occur + else if( nCount <= nPos ) + m_xLbStartStyle->set_active(0); + else + m_xLbStartStyle->set_active(nPos); + + m_xLbEndStyle->clear(); + m_xLbEndStyle->append_text(sNone); + + m_xLbEndStyle->Fill( m_pLineEndList, false ); + nCount = m_xLbEndStyle->get_count(); + + if( nCount == 0 ) + ; // This case should never occur + else if( nCount <= nPos ) + m_xLbEndStyle->set_active(0); + else + m_xLbEndStyle->set_active(nPos); + } + INetURLObject aLineURL( m_pLineEndList->GetPath() ); + + aLineURL.Append( m_pLineEndList->GetName() ); + DBG_ASSERT( aLineURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + // Evaluate if another TabPage set another fill type + if( m_xLbLineStyle->get_active() != 0 ) + { + if( m_nPageType == PageType::Hatch ) // 1 + { + m_xLbLineStyle->set_active(*m_pPosDashLb + 2); // +2 due to SOLID and INVISIBLE + ChangePreviewHdl_Impl( nullptr ); + } + if( m_nPageType == PageType::Bitmap ) + { + m_xLbStartStyle->set_active(*m_pPosLineEndLb + 1);// +1 due to SOLID + m_xLbEndStyle->set_active(*m_pPosLineEndLb + 1);// +1 due to SOLID + ChangePreviewHdl_Impl( nullptr ); + } + } + + // ColorList + if( *m_pnColorListState != ChangeType::NONE ) + { + ChangePreviewHdl_Impl( nullptr ); + } + + m_nPageType = PageType::Area; + } + // Page does not yet exist in the ctor, that's why we do it here! + + else if (m_nDlgType == 1101) // nNoArrowNoShadowDlg from chart2/source/controller/dialogs/dlg_ObjectProperties.cxx + { + m_xFlLineEnds->hide(); + m_xFLEdgeStyle->hide(); + } +} + + +DeactivateRC SvxLineTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( m_nDlgType == 0 ) // Line dialog + { + m_nPageType = PageType::Gradient; // possibly for extensions + *m_pPosDashLb = m_xLbLineStyle->get_active() - 2;// First entry SOLID!!! + sal_Int32 nPos = m_xLbStartStyle->get_active(); + if (nPos != -1) + nPos--; + *m_pPosLineEndLb = nPos; + } + + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxLineTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + const SfxPoolItem* pOld = nullptr; + sal_Int32 nPos; + bool bModified = false; + + // To prevent modifications to the list, we do not set other page's items. + if( m_nDlgType != 0 || m_nPageType != PageType::Hatch ) + { + nPos = m_xLbLineStyle->get_active(); + if( nPos != -1 && + m_xLbLineStyle->get_value_changed_from_saved() ) + { + std::unique_ptr<XLineStyleItem> pStyleItem; + + if( nPos == 0 ) + pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_NONE )); + else if( nPos == 1 ) + pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_SOLID )); + else + { + pStyleItem.reset(new XLineStyleItem( drawing::LineStyle_DASH )); + + // For added security + if( m_pDashList->Count() > static_cast<tools::Long>( nPos - 2 ) ) + { + XLineDashItem aDashItem( m_xLbLineStyle->get_active_text(), + m_pDashList->GetDash( nPos - 2 )->GetDash() ); + pOld = GetOldItem( *rAttrs, XATTR_LINEDASH ); + if ( !pOld || !( *static_cast<const XLineDashItem*>(pOld) == aDashItem ) ) + { + rAttrs->Put( aDashItem ); + bModified = true; + } + } + } + pOld = GetOldItem( *rAttrs, XATTR_LINESTYLE ); + if ( !pOld || !( *static_cast<const XLineStyleItem*>(pOld) == *pStyleItem ) ) + { + rAttrs->Put( std::move(pStyleItem) ); + bModified = true; + } + } + } + // Line width + // GetSavedValue() returns OUString! + if( m_xMtrLineWidth->get_value_changed_from_saved() ) + { + XLineWidthItem aItem( GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ) ); + pOld = GetOldItem( *rAttrs, XATTR_LINEWIDTH ); + if ( !pOld || !( *static_cast<const XLineWidthItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + // Width line start + if( m_xMtrStartWidth->get_value_changed_from_saved() ) + { + XLineStartWidthItem aItem( GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ) ); + pOld = GetOldItem( *rAttrs, XATTR_LINESTARTWIDTH ); + if ( !pOld || !( *static_cast<const XLineStartWidthItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + // Width line end + if( m_xMtrEndWidth->get_value_changed_from_saved() ) + { + XLineEndWidthItem aItem( GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ) ); + pOld = GetOldItem( *rAttrs, XATTR_LINEENDWIDTH ); + if ( !pOld || !( *static_cast<const XLineEndWidthItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // Line color + if (m_xLbColor->IsValueChangedFromSaved()) + { + NamedColor aColor = m_xLbColor->GetSelectedEntry(); + XLineColorItem aItem(aColor.second, aColor.first); + pOld = GetOldItem( *rAttrs, XATTR_LINECOLOR ); + if ( !pOld || !( *static_cast<const XLineColorItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + if( m_nDlgType != 0 || m_nPageType != PageType::Bitmap ) + { + // Line start + nPos = m_xLbStartStyle->get_active(); + if( nPos != -1 && m_xLbStartStyle->get_value_changed_from_saved() ) + { + std::unique_ptr<XLineStartItem> pItem; + if( nPos == 0 ) + pItem.reset(new XLineStartItem()); + else if( m_pLineEndList->Count() > static_cast<tools::Long>( nPos - 1 ) ) + pItem.reset(new XLineStartItem( m_xLbStartStyle->get_active_text(), m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() )); + pOld = GetOldItem( *rAttrs, XATTR_LINESTART ); + if( pItem && ( !pOld || *pOld != *pItem ) ) + { + rAttrs->Put( std::move(pItem) ); + bModified = true; + } + } + // Line end + nPos = m_xLbEndStyle->get_active(); + if( nPos != -1 && m_xLbEndStyle->get_value_changed_from_saved() ) + { + std::unique_ptr<XLineEndItem> pItem; + if( nPos == 0 ) + pItem.reset(new XLineEndItem()); + else if( m_pLineEndList->Count() > static_cast<tools::Long>( nPos - 1 ) ) + pItem.reset(new XLineEndItem( m_xLbEndStyle->get_active_text(), m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() )); + pOld = GetOldItem( *rAttrs, XATTR_LINEEND ); + if( pItem && + ( !pOld || !( *static_cast<const XLineEndItem*>(pOld) == *pItem ) ) ) + { + rAttrs->Put( std::move(pItem) ); + bModified = true; + } + } + } + + // Centered line end + TriState eState = m_xTsbCenterStart->get_state(); + if( m_xTsbCenterStart->get_state_changed_from_saved() ) + { + XLineStartCenterItem aItem( eState != TRISTATE_FALSE ); + pOld = GetOldItem( *rAttrs, XATTR_LINESTARTCENTER ); + if ( !pOld || !( *static_cast<const XLineStartCenterItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + eState = m_xTsbCenterEnd->get_state(); + if( m_xTsbCenterEnd->get_state_changed_from_saved() ) + { + XLineEndCenterItem aItem( eState != TRISTATE_FALSE ); + pOld = GetOldItem( *rAttrs, XATTR_LINEENDCENTER ); + if ( !pOld || !( *static_cast<const XLineEndCenterItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // Transparency + sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + if( m_xMtrTransparent->get_value_changed_from_saved() ) + { + XLineTransparenceItem aItem( nVal ); + pOld = GetOldItem( *rAttrs, XATTR_LINETRANSPARENCE ); + if ( !pOld || !( *static_cast<const XLineTransparenceItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + nPos = m_xLBEdgeStyle->get_active(); + if (nPos != -1 && m_xLBEdgeStyle->get_value_changed_from_saved()) + { + std::unique_ptr<XLineJointItem> pNew; + + switch(nPos) + { + case 0: // Rounded, default + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_ROUND)); + break; + } + case 1: // - none - + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_NONE)); + break; + } + case 2: // Miter + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_MITER)); + break; + } + case 3: // Bevel + { + pNew.reset(new XLineJointItem(css::drawing::LineJoint_BEVEL)); + break; + } + } + + if(pNew) + { + pOld = GetOldItem( *rAttrs, XATTR_LINEJOINT ); + + if(!pOld || !(*static_cast<const XLineJointItem*>(pOld) == *pNew)) + { + rAttrs->Put( std::move(pNew) ); + bModified = true; + } + } + } + + // LineCaps + nPos = m_xLBCapStyle->get_active(); + if (nPos != -1 && m_xLBCapStyle->get_value_changed_from_saved()) + { + std::unique_ptr<XLineCapItem> pNew; + + switch(nPos) + { + case 0: // Butt (=Flat), default + { + pNew.reset(new XLineCapItem(css::drawing::LineCap_BUTT)); + break; + } + case 1: // Round + { + pNew.reset(new XLineCapItem(css::drawing::LineCap_ROUND)); + break; + } + case 2: // Square + { + pNew.reset(new XLineCapItem(css::drawing::LineCap_SQUARE)); + break; + } + } + + if(pNew) + { + pOld = GetOldItem( *rAttrs, XATTR_LINECAP ); + + if(!pOld || !(*static_cast<const XLineCapItem*>(pOld) == *pNew)) + { + rAttrs->Put( std::move(pNew) ); + bModified = true; + } + } + } + + if(m_nSymbolType!=SVX_SYMBOLTYPE_UNKNOWN || m_bNewSize) + { + // Was set by selection or the size is different + SvxSizeItem aSItem(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLSIZE),m_aSymbolSize); + const SfxPoolItem* pSOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLSIZE) ); + m_bNewSize = pSOld ? *static_cast<const SvxSizeItem *>(pSOld) != aSItem : m_bNewSize ; + if(m_bNewSize) + { + rAttrs->Put(aSItem); + bModified=true; + } + + SfxInt32Item aTItem(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLTYPE),m_nSymbolType); + const SfxPoolItem* pTOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLTYPE) ); + bool bNewType = pTOld == nullptr || *static_cast<const SfxInt32Item*>(pTOld) != aTItem; + if(bNewType && m_nSymbolType==SVX_SYMBOLTYPE_UNKNOWN) + bNewType=false; // a small fix, type wasn't set -> don't create a type item after all! + if(bNewType) + { + rAttrs->Put(aTItem); + bModified=true; + } + + if(m_nSymbolType!=SVX_SYMBOLTYPE_NONE) + { + SvxBrushItem aBItem(m_aSymbolGraphic,GPOS_MM,rAttrs->GetPool()->GetWhich(SID_ATTR_BRUSH)); + const SfxPoolItem* pBOld = GetOldItem( *rAttrs, rAttrs->GetPool()->GetWhich(SID_ATTR_BRUSH) ); + bool bNewBrush = + pBOld == nullptr || *static_cast<const SvxBrushItem*>(pBOld) != aBItem; + if(bNewBrush) + { + rAttrs->Put(aBItem); + bModified=true; + } + } + } + rAttrs->Put (CntUInt16Item(SID_PAGE_TYPE, static_cast<sal_uInt16>(m_nPageType))); + return bModified; +} + + +void SvxLineTabPage::FillXLSet_Impl() +{ + sal_Int32 nPos; + + if (m_xLbLineStyle->get_active() == -1) + { + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) ); + } + else if (m_xLbLineStyle->get_active() == 0) + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) ); + else if (m_xLbLineStyle->get_active() == 1) + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) ); + else + { + m_rXLSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) ); + + nPos = m_xLbLineStyle->get_active(); + if (nPos != -1) + { + m_rXLSet.Put( XLineDashItem( m_xLbLineStyle->get_active_text(), + m_pDashList->GetDash( nPos - 2 )->GetDash() ) ); + } + } + + nPos = m_xLbStartStyle->get_active(); + if (nPos != -1) + { + if( nPos == 0 ) + m_rXLSet.Put( XLineStartItem() ); + else + m_rXLSet.Put( XLineStartItem( m_xLbStartStyle->get_active_text(), + m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ) ); + } + nPos = m_xLbEndStyle->get_active(); + if (nPos != -1) + { + if( nPos == 0 ) + m_rXLSet.Put( XLineEndItem() ); + else + m_rXLSet.Put( XLineEndItem( m_xLbEndStyle->get_active_text(), + m_pLineEndList->GetLineEnd( nPos - 1 )->GetLineEnd() ) ); + } + + nPos = m_xLBEdgeStyle->get_active(); + if (nPos != -1) + { + switch(nPos) + { + case 0: // Rounded, default + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_ROUND)); + break; + } + case 1: // - none - + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_NONE)); + break; + } + case 2: // Miter + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_MITER)); + break; + } + case 3: // Bevel + { + m_rXLSet.Put(XLineJointItem(css::drawing::LineJoint_BEVEL)); + break; + } + } + } + + // LineCaps + nPos = m_xLBCapStyle->get_active(); + if (nPos != -1) + { + switch(nPos) + { + case 0: // Butt (=Flat), default + { + m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_BUTT)); + break; + } + case 1: // Round + { + m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_ROUND)); + break; + } + case 2: // Square + { + m_rXLSet.Put(XLineCapItem(css::drawing::LineCap_SQUARE)); + break; + } + } + } + + m_rXLSet.Put( XLineStartWidthItem( GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ) ) ); + m_rXLSet.Put( XLineEndWidthItem( GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ) ) ); + + m_rXLSet.Put( XLineWidthItem( GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ) ) ); + NamedColor aColor = m_xLbColor->GetSelectedEntry(); + m_rXLSet.Put(XLineColorItem(aColor.second, aColor.first)); + + // Centered line end + if( m_xTsbCenterStart->get_state() == TRISTATE_TRUE ) + m_rXLSet.Put( XLineStartCenterItem( true ) ); + else if( m_xTsbCenterStart->get_state() == TRISTATE_FALSE ) + m_rXLSet.Put( XLineStartCenterItem( false ) ); + + if( m_xTsbCenterEnd->get_state() == TRISTATE_TRUE ) + m_rXLSet.Put( XLineEndCenterItem( true ) ); + else if( m_xTsbCenterEnd->get_state() == TRISTATE_FALSE ) + m_rXLSet.Put( XLineEndCenterItem( false ) ); + + // Transparency + sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + m_rXLSet.Put( XLineTransparenceItem( nVal ) ); + + m_aCtlPreview.SetLineAttributes(m_aXLineAttr.GetItemSet()); +} + + +void SvxLineTabPage::Reset( const SfxItemSet* rAttrs ) +{ + drawing::LineStyle eXLS; // drawing::LineStyle_NONE, drawing::LineStyle_SOLID, drawing::LineStyle_DASH + + // Line style + tools::Long nSymType=SVX_SYMBOLTYPE_UNKNOWN; + bool bPrevSym=false; + bool bEnable=true; + bool bIgnoreGraphic=false; + bool bIgnoreSize=false; + if(const SfxInt32Item* pSymbolTypeItem = rAttrs->GetItemIfSet(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLTYPE))) + { + nSymType = pSymbolTypeItem->GetValue(); + } + + if(nSymType == SVX_SYMBOLTYPE_AUTO) + { + m_aSymbolGraphic=m_aAutoSymbolGraphic; + m_aSymbolSize=m_aSymbolLastSize=m_aAutoSymbolGraphic.GetPrefSize(); + bPrevSym=true; + } + else if(nSymType == SVX_SYMBOLTYPE_NONE) + { + bEnable=false; + bIgnoreGraphic=true; + bIgnoreSize=true; + } + else if(nSymType >= 0) + { + ScopedVclPtrInstance< VirtualDevice > pVDev; + pVDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + + std::unique_ptr<SdrModel> pModel( + new SdrModel(nullptr, nullptr, true)); + pModel->GetItemPool().FreezeIdRanges(); + rtl::Reference<SdrPage> pPage = new SdrPage( *pModel, false ); + pPage->SetSize(Size(1000,1000)); + pModel->InsertPage( pPage.get(), 0 ); + { + SdrView aView( *pModel, pVDev ); + aView.hideMarkHandles(); + aView.ShowSdrPage(pPage.get()); + size_t nSymTmp = static_cast<size_t>(nSymType); + if(m_pSymbolList) + { + if(m_pSymbolList->GetObjCount()) + { + nSymTmp %= m_pSymbolList->GetObjCount(); // Treat list as cyclic! + SdrObject *pObj=m_pSymbolList->GetObj(nSymTmp); + if(pObj) + { + // directly clone to target SdrModel + pObj = pObj->CloneSdrObject(*pModel); + + if(m_xSymbolAttr) + { + pObj->SetMergedItemSet(*m_xSymbolAttr); + } + else + { + pObj->SetMergedItemSet(m_rOutAttrs); + } + + pPage->NbcInsertObject(pObj); + + // Generate invisible square to give all symbol types a + // bitmap size, which is independent from specific glyph + SdrObject* pInvisibleSquare(m_pSymbolList->GetObj(0)); + + // directly clone to target SdrModel + pInvisibleSquare = pInvisibleSquare->CloneSdrObject(*pModel); + + pPage->NbcInsertObject(pInvisibleSquare); + pInvisibleSquare->SetMergedItem(XFillTransparenceItem(100)); + pInvisibleSquare->SetMergedItem(XLineTransparenceItem(100)); + + aView.MarkAll(); + GDIMetaFile aMeta(aView.GetMarkedObjMetaFile()); + + m_aSymbolGraphic=Graphic(aMeta); + m_aSymbolSize=pObj->GetSnapRect().GetSize(); + m_aSymbolGraphic.SetPrefSize(pInvisibleSquare->GetSnapRect().GetSize()); + m_aSymbolGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM)); + bPrevSym=true; + bEnable=true; + bIgnoreGraphic=true; + + aView.UnmarkAll(); + pInvisibleSquare=pPage->RemoveObject(1); + SdrObject::Free( pInvisibleSquare); + pObj=pPage->RemoveObject(0); + SdrObject::Free( pObj ); + } + } + } + } + } + if(const SvxBrushItem* pBrushItem = rAttrs->GetItemIfSet(rAttrs->GetPool()->GetWhich(SID_ATTR_BRUSH))) + { + const Graphic* pGraphic = pBrushItem->GetGraphic(); + if( pGraphic ) + { + if(!bIgnoreGraphic) + { + m_aSymbolGraphic=*pGraphic; + } + if(!bIgnoreSize) + { + m_aSymbolSize=OutputDevice::LogicToLogic( pGraphic->GetPrefSize(), + pGraphic->GetPrefMapMode(), + MapMode(MapUnit::Map100thMM)); + } + bPrevSym=true; + } + } + + if(const SvxSizeItem* pSymbolSizeItem = rAttrs->GetItemIfSet(rAttrs->GetPool()->GetWhich(SID_ATTR_SYMBOLSIZE))) + { + m_aSymbolSize = pSymbolSizeItem->GetSize(); + } + + m_xGridIconSize->set_sensitive(bEnable); + + if(bPrevSym) + { + SetMetricValue(*m_xSymbolWidthMF, m_aSymbolSize.Width(), m_ePoolUnit); + SetMetricValue(*m_xSymbolHeightMF, m_aSymbolSize.Height(),m_ePoolUnit); + m_aCtlPreview.SetSymbol(&m_aSymbolGraphic,m_aSymbolSize); + m_aSymbolLastSize=m_aSymbolSize; + } + + if( rAttrs->GetItemState( XATTR_LINESTYLE ) != SfxItemState::DONTCARE ) + { + eXLS = rAttrs->Get( XATTR_LINESTYLE ).GetValue(); + + switch( eXLS ) + { + case drawing::LineStyle_NONE: + m_xLbLineStyle->set_active(0); + break; + case drawing::LineStyle_SOLID: + m_xLbLineStyle->set_active(1); + break; + + case drawing::LineStyle_DASH: + m_xLbLineStyle->set_active(-1); + m_xLbLineStyle->set_active_text(rAttrs->Get( XATTR_LINEDASH ).GetName()); + break; + + default: + break; + } + } + else + { + m_xLbLineStyle->set_active(-1); + } + + // Line strength + if( rAttrs->GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE ) + { + SetMetricValue( *m_xMtrLineWidth, rAttrs->Get( XATTR_LINEWIDTH ).GetValue(), m_ePoolUnit ); + } + else + m_xMtrLineWidth->set_text(""); + + // Line color + m_xLbColor->SetNoSelection(); + + if ( rAttrs->GetItemState( XATTR_LINECOLOR ) != SfxItemState::DONTCARE ) + { + Color aCol = rAttrs->Get( XATTR_LINECOLOR ).GetColorValue(); + m_xLbColor->SelectEntry( aCol ); + } + + // Line start + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTART ) == SfxItemState::DEFAULT ) + { + m_xLbStartStyle->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINESTART ) != SfxItemState::DONTCARE ) + { + // #86265# select entry using list and polygon, not string + bool bSelected(false); + const basegfx::B2DPolyPolygon& rItemPolygon = rAttrs->Get(XATTR_LINESTART).GetLineStartValue(); + + for(tools::Long a(0);!bSelected && a < m_pLineEndList->Count(); a++) + { + const XLineEndEntry* pEntry = m_pLineEndList->GetLineEnd(a); + const basegfx::B2DPolyPolygon& rEntryPolygon = pEntry->GetLineEnd(); + + if(rItemPolygon == rEntryPolygon) + { + // select this entry + m_xLbStartStyle->set_active(a + 1); + bSelected = true; + } + } + + if(!bSelected) + m_xLbStartStyle->set_active(0); + } + else + { + m_xLbStartStyle->set_active(-1); + } + + // Line end + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEEND ) == SfxItemState::DEFAULT ) + { + m_xLbEndStyle->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINEEND ) != SfxItemState::DONTCARE ) + { + // #86265# select entry using list and polygon, not string + bool bSelected(false); + const basegfx::B2DPolyPolygon& rItemPolygon = rAttrs->Get(XATTR_LINEEND).GetLineEndValue(); + + for(tools::Long a(0);!bSelected && a < m_pLineEndList->Count(); a++) + { + const XLineEndEntry* pEntry = m_pLineEndList->GetLineEnd(a); + const basegfx::B2DPolyPolygon& rEntryPolygon = pEntry->GetLineEnd(); + + if(rItemPolygon == rEntryPolygon) + { + // select this entry + m_xLbEndStyle->set_active(a + 1); + bSelected = true; + } + } + + if(!bSelected) + m_xLbEndStyle->set_active(0); + } + else + { + m_xLbEndStyle->set_active(-1); + } + + // Line start strength + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTARTWIDTH ) == SfxItemState::DEFAULT ) + { + m_xMtrStartWidth->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINESTARTWIDTH ) != SfxItemState::DONTCARE ) + { + SetMetricValue( *m_xMtrStartWidth, + rAttrs->Get( XATTR_LINESTARTWIDTH ).GetValue(), + m_ePoolUnit ); + } + else + m_xMtrStartWidth->set_text( "" ); + + // Line end strength + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEENDWIDTH ) == SfxItemState::DEFAULT ) + { + m_xMtrEndWidth->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINEENDWIDTH ) != SfxItemState::DONTCARE ) + { + SetMetricValue( *m_xMtrEndWidth, + rAttrs->Get( XATTR_LINEENDWIDTH ).GetValue(), + m_ePoolUnit ); + } + else + m_xMtrEndWidth->set_text(""); + + // Centered line end (start) + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINESTARTCENTER ) == SfxItemState::DEFAULT ) + { + m_xTsbCenterStart->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINESTARTCENTER ) != SfxItemState::DONTCARE ) + { + if( rAttrs->Get( XATTR_LINESTARTCENTER ).GetValue() ) + m_xTsbCenterStart->set_state(TRISTATE_TRUE); + else + m_xTsbCenterStart->set_state(TRISTATE_FALSE); + } + else + { + m_xTsbCenterStart->set_state(TRISTATE_INDET); + } + + // Centered line end (end) + if( m_bObjSelected && rAttrs->GetItemState( XATTR_LINEENDCENTER ) == SfxItemState::DEFAULT ) + { + m_xTsbCenterEnd->set_sensitive(false); + } + else if( rAttrs->GetItemState( XATTR_LINEENDCENTER ) != SfxItemState::DONTCARE ) + { + if( rAttrs->Get( XATTR_LINEENDCENTER ).GetValue() ) + m_xTsbCenterEnd->set_state(TRISTATE_TRUE); + else + m_xTsbCenterEnd->set_state(TRISTATE_FALSE); + } + else + { + m_xTsbCenterEnd->set_state(TRISTATE_INDET); + } + + // Transparency + if( rAttrs->GetItemState( XATTR_LINETRANSPARENCE ) != SfxItemState::DONTCARE ) + { + sal_uInt16 nTransp = rAttrs->Get( XATTR_LINETRANSPARENCE ).GetValue(); + m_xMtrTransparent->set_value(nTransp, FieldUnit::PERCENT); + ChangeTransparentHdl_Impl(*m_xMtrTransparent); + } + else + m_xMtrTransparent->set_text( "" ); + + if( !m_xLbStartStyle->get_sensitive() && + !m_xLbEndStyle->get_sensitive() && + !m_xMtrStartWidth->get_sensitive() && + !m_xMtrEndWidth->get_sensitive() && + !m_xTsbCenterStart->get_sensitive()&& + !m_xTsbCenterEnd->get_sensitive() ) + { + m_xCbxSynchronize->set_sensitive(false); + m_xFlLineEnds->set_sensitive(false); + } + + // Synchronize + // We get the value from the INI file now + OUString aStr = GetUserData(); + m_xCbxSynchronize->set_active(aStr.toInt32() != 0); + + if(m_bObjSelected && SfxItemState::DEFAULT == rAttrs->GetItemState(XATTR_LINEJOINT)) + { +// maFTEdgeStyle.set_sensitive(false); + m_xLBEdgeStyle->set_sensitive(false); + } + else if(SfxItemState::DONTCARE != rAttrs->GetItemState(XATTR_LINEJOINT)) + { + const css::drawing::LineJoint eLineJoint = rAttrs->Get(XATTR_LINEJOINT).GetValue(); + + switch(eLineJoint) + { + case css::drawing::LineJoint::LineJoint_MAKE_FIXED_SIZE: // fallback to round, unused value + case css::drawing::LineJoint_ROUND : m_xLBEdgeStyle->set_active(0); break; + case css::drawing::LineJoint_NONE : m_xLBEdgeStyle->set_active(1); break; + case css::drawing::LineJoint_MIDDLE : // fallback to mitre, unused value + case css::drawing::LineJoint_MITER : m_xLBEdgeStyle->set_active(2); break; + case css::drawing::LineJoint_BEVEL : m_xLBEdgeStyle->set_active(3); break; + } + } + else + { + m_xLBEdgeStyle->set_active(-1); + } + + // fdo#43209 + if(m_bObjSelected && SfxItemState::DEFAULT == rAttrs->GetItemState(XATTR_LINECAP)) + { + m_xLBCapStyle->set_sensitive(false); + } + else if(SfxItemState::DONTCARE != rAttrs->GetItemState(XATTR_LINECAP)) + { + const css::drawing::LineCap eLineCap(rAttrs->Get(XATTR_LINECAP).GetValue()); + + switch(eLineCap) + { + case css::drawing::LineCap_ROUND: m_xLBCapStyle->set_active(1); break; + case css::drawing::LineCap_SQUARE : m_xLBCapStyle->set_active(2); break; + default /*css::drawing::LineCap_BUTT*/: m_xLBCapStyle->set_active(0); break; + } + } + else + { + m_xLBCapStyle->set_active(-1); + } + + // Save values + m_xLbLineStyle->save_value(); + m_xMtrLineWidth->save_value(); + m_xLbColor->SaveValue(); + m_xLbStartStyle->save_value(); + m_xLbEndStyle->save_value(); + m_xMtrStartWidth->save_value(); + m_xMtrEndWidth->save_value(); + m_xTsbCenterStart->save_state(); + m_xTsbCenterEnd->save_state(); + m_xMtrTransparent->save_value(); + + m_xLBEdgeStyle->save_value(); + + // LineCaps + m_xLBCapStyle->save_value(); + + ClickInvisibleHdl_Impl(); + + ChangePreviewHdl_Impl( nullptr ); +} + +std::unique_ptr<SfxTabPage> SvxLineTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxLineTabPage>(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangePreviewListBoxHdl_Impl, ColorListBox&, void) +{ + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK(SvxLineTabPage, ChangePreviewModifyHdl_Impl, weld::MetricSpinButton&, rEdit, void) +{ + ChangePreviewHdl_Impl(&rEdit); +} + +void SvxLineTabPage::ChangePreviewHdl_Impl(const weld::MetricSpinButton* pCntrl) +{ + if (pCntrl == m_xMtrLineWidth.get()) + { + // Line width and start end width + sal_Int32 nNewLineWidth = GetCoreValue( *m_xMtrLineWidth, m_ePoolUnit ); + if(m_nActLineWidth == -1) + { + // Don't initialize yet, get the start value + const SfxPoolItem* pOld = GetOldItem( m_rXLSet, XATTR_LINEWIDTH ); + sal_Int32 nStartLineWidth = 0; + if(pOld) + nStartLineWidth = static_cast<const XLineWidthItem *>(pOld)->GetValue(); + m_nActLineWidth = nStartLineWidth; + } + + if(m_nActLineWidth != nNewLineWidth) + { + // Adapt start/end width + sal_Int32 nValAct = GetCoreValue( *m_xMtrStartWidth, m_ePoolUnit ); + sal_Int32 nValNew = nValAct + (((nNewLineWidth - m_nActLineWidth) * 15) / 10); + if(nValNew < 0) + nValNew = 0; + SetMetricValue( *m_xMtrStartWidth, nValNew, m_ePoolUnit ); + + nValAct = GetCoreValue( *m_xMtrEndWidth, m_ePoolUnit ); + nValNew = nValAct + (((nNewLineWidth - m_nActLineWidth) * 15) / 10); + if(nValNew < 0) + nValNew = 0; + SetMetricValue( *m_xMtrEndWidth, nValNew, m_ePoolUnit ); + } + + // Remember current value + m_nActLineWidth = nNewLineWidth; + } + + FillXLSet_Impl(); + m_aCtlPreview.Invalidate(); + + // Make transparency accessible accordingly + if( m_xLbLineStyle->get_active() == 0 ) // invisible + { + m_xBoxTransparency->set_sensitive(false); + } + else + { + m_xBoxTransparency->set_sensitive(true); + } + + const bool bHasLineStyle = m_xLbLineStyle->get_active() !=0; + const bool bHasLineStart = m_xLbStartStyle->get_active() != 0; + + m_xBoxStart->set_sensitive(bHasLineStart && bHasLineStyle); + + const bool bHasLineEnd = m_xLbEndStyle->get_active() != 0; + + m_xBoxEnd->set_sensitive(bHasLineEnd && bHasLineStyle); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartClickHdl_Impl, weld::Toggleable&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xTsbCenterEnd->set_state(m_xTsbCenterStart->get_state()); + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartListBoxHdl_Impl, weld::ComboBox&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xLbEndStyle->set_active(m_xLbStartStyle->get_active()); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeStartModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xMtrEndWidth->set_value(m_xMtrStartWidth->get_value(FieldUnit::NONE), FieldUnit::NONE); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEdgeStyleHdl_Impl, weld::ComboBox&, void) +{ + ChangePreviewHdl_Impl( nullptr ); +} + +// fdo#43209 +IMPL_LINK_NOARG(SvxLineTabPage, ChangeCapStyleHdl_Impl, weld::ComboBox&, void) +{ + ChangePreviewHdl_Impl( nullptr ); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ClickInvisibleHdl_Impl, weld::ComboBox&, void) +{ + ClickInvisibleHdl_Impl(); +} + +void SvxLineTabPage::ClickInvisibleHdl_Impl() +{ + if( m_xLbLineStyle->get_active() == 0 ) // invisible + { + if(!m_bSymbols) + m_xBoxColor->set_sensitive(false); + + m_xBoxWidth->set_sensitive(false); + + if( m_xFlLineEnds->get_sensitive() ) + { + m_xBoxStart->set_sensitive(false); + m_xBoxArrowStyles->set_sensitive(false); + m_xGridEdgeCaps->set_sensitive(false); + } + } + else + { + // set cap style associated to the line style + sal_Int32 nPos = m_xLbLineStyle->get_active(); + if( nPos > 1 && m_pDashList->Count() > static_cast<tools::Long>( nPos - 2 ) ) + { + css::drawing::DashStyle eStyle = + m_pDashList->GetDash( nPos - 2 )->GetDash().GetDashStyle(); + if ( eStyle == drawing::DashStyle_RECT || eStyle == drawing::DashStyle_RECTRELATIVE) + m_xLBCapStyle->set_active(0); + else + m_xLBCapStyle->set_active(1); + } + + m_xBoxColor->set_sensitive(true); + m_xBoxWidth->set_sensitive(true); + + if (m_xFlLineEnds->get_sensitive()) + { + m_xBoxArrowStyles->set_sensitive(true); + m_xGridEdgeCaps->set_sensitive(true); + } + } + ChangePreviewHdl_Impl( nullptr ); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndClickHdl_Impl, weld::Toggleable&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xTsbCenterStart->set_state(m_xTsbCenterEnd->get_state()); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndListBoxHdl_Impl, weld::ComboBox&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xLbStartStyle->set_active(m_xLbEndStyle->get_active()); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeEndModifyHdl_Impl, weld::MetricSpinButton&, void) +{ + if (m_xCbxSynchronize->get_active()) + m_xMtrStartWidth->set_value(m_xMtrEndWidth->get_value(FieldUnit::NONE), FieldUnit::NONE); + + ChangePreviewHdl_Impl(nullptr); +} + +IMPL_LINK_NOARG(SvxLineTabPage, ChangeTransparentHdl_Impl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nVal = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + + m_rXLSet.Put(XLineTransparenceItem(nVal)); + + FillXLSet_Impl(); + + m_aCtlPreview.Invalidate(); +} + +void SvxLineTabPage::FillUserData() +{ + // Write the synched value to the INI file + OUString aStrUserData = OUString::boolean(m_xCbxSynchronize->get_active()); + SetUserData( aStrUserData ); +} + +// #58425# Symbols on a list (e.g. StarChart) +// Handler for the symbol selection's popup menu (NumMenueButton) +// The following link originates from SvxNumOptionsTabPage +IMPL_LINK_NOARG(SvxLineTabPage, MenuCreateHdl_Impl, weld::Toggleable&, void) +{ + ScopedVclPtrInstance< VirtualDevice > pVD; + + // Initialize popup + if (!m_xGalleryMenu) + { + m_xGalleryMenu = m_xBuilder->weld_menu("gallerysubmenu"); + weld::WaitObject aWait(GetFrameWeld()); + // Get gallery entries + GalleryExplorer::FillObjList(GALLERY_THEME_BULLETS, m_aGrfNames); + + sal_uInt32 i = 0; + for (auto const& grfName : m_aGrfNames) + { + const OUString *pUIName = &grfName; + + // Convert URL encodings to UI characters (e.g. %20 for spaces) + OUString aPhysicalName; + if (osl::FileBase::getSystemPathFromFileURL(grfName, aPhysicalName) + == osl::FileBase::E_None) + { + pUIName = &aPhysicalName; + } + + SvxBmpItemInfo* pInfo = new SvxBmpItemInfo; + pInfo->pBrushItem.reset(new SvxBrushItem(grfName, "", GPOS_AREA, SID_ATTR_BRUSH)); + pInfo->sItemId = "gallery" + OUString::number(i); + m_aGalleryBrushItems.emplace_back(pInfo); + const Graphic* pGraphic = pInfo->pBrushItem->GetGraphic(); + + if(pGraphic) + { + BitmapEx aBitmap(pGraphic->GetBitmapEx()); + Size aSize(aBitmap.GetSizePixel()); + if(aSize.Width() > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT) + { + bool bWidth = aSize.Width() > aSize.Height(); + double nScale = bWidth ? + double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width()): + double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height()); + aBitmap.Scale(nScale, nScale); + + } + pVD->SetOutputSizePixel(aBitmap.GetSizePixel()); + pVD->DrawBitmapEx(Point(), aBitmap); + m_xGalleryMenu->append(pInfo->sItemId, *pUIName, *pVD); + } + else + { + m_xGalleryMenu->append(pInfo->sItemId, *pUIName); + } + ++i; + } + + if (m_aGrfNames.empty()) + m_xSymbolMB->set_item_sensitive("gallery", false); + } + + if (m_xSymbolsMenu || !m_pSymbolList) + return; + + m_xSymbolsMenu = m_xBuilder->weld_menu("symbolssubmenu"); + ScopedVclPtrInstance< VirtualDevice > pVDev; + pVDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + std::unique_ptr<SdrModel> pModel( + new SdrModel(nullptr, nullptr, true)); + pModel->GetItemPool().FreezeIdRanges(); + // Page + rtl::Reference<SdrPage> pPage = new SdrPage( *pModel, false ); + pPage->SetSize(Size(1000,1000)); + pModel->InsertPage( pPage.get(), 0 ); + { + // 3D View + SdrView aView( *pModel, pVDev ); + aView.hideMarkHandles(); + aView.ShowSdrPage(pPage.get()); + + // Generate invisible square to give all symbols a + // bitmap size, which is independent from specific glyph + SdrObject *pInvisibleSquare=m_pSymbolList->GetObj(0); + + // directly clone to target SdrModel + pInvisibleSquare = pInvisibleSquare->CloneSdrObject(*pModel); + + pPage->NbcInsertObject(pInvisibleSquare); + pInvisibleSquare->SetMergedItem(XFillTransparenceItem(100)); + pInvisibleSquare->SetMergedItem(XLineTransparenceItem(100)); + + for(size_t i=0; i < m_pSymbolList->GetObjCount(); ++i) + { + SdrObject *pObj=m_pSymbolList->GetObj(i); + assert(pObj); + + // directly clone to target SdrModel + pObj = pObj->CloneSdrObject(*pModel); + + m_aGrfNames.emplace_back(""); + pPage->NbcInsertObject(pObj); + if(m_xSymbolAttr) + { + pObj->SetMergedItemSet(*m_xSymbolAttr); + } + else + { + pObj->SetMergedItemSet(m_rOutAttrs); + } + aView.MarkAll(); + BitmapEx aBitmapEx(aView.GetMarkedObjBitmapEx()); + GDIMetaFile aMeta(aView.GetMarkedObjMetaFile()); + aView.UnmarkAll(); + pObj=pPage->RemoveObject(1); + SdrObject::Free(pObj); + + SvxBmpItemInfo* pInfo = new SvxBmpItemInfo; + pInfo->pBrushItem.reset(new SvxBrushItem(Graphic(aMeta), GPOS_AREA, SID_ATTR_BRUSH)); + pInfo->sItemId = "symbol" + OUString::number(i); + m_aSymbolBrushItems.emplace_back(pInfo); + + Size aSize(aBitmapEx.GetSizePixel()); + if(aSize.Width() > MAX_BMP_WIDTH || aSize.Height() > MAX_BMP_HEIGHT) + { + bool bWidth = aSize.Width() > aSize.Height(); + double nScale = bWidth ? + double(MAX_BMP_WIDTH) / static_cast<double>(aSize.Width()): + double(MAX_BMP_HEIGHT) / static_cast<double>(aSize.Height()); + aBitmapEx.Scale(nScale, nScale); + } + pVD->SetOutputSizePixel(aBitmapEx.GetSizePixel()); + pVD->DrawBitmapEx(Point(), aBitmapEx); + m_xSymbolsMenu->append(pInfo->sItemId, "", *pVD); + } + pInvisibleSquare=pPage->RemoveObject(0); + SdrObject::Free(pInvisibleSquare); + + if (m_aGrfNames.empty()) + m_xSymbolMB->set_item_sensitive("symbols", false); + } +} + +// #58425# Symbols on a list (e.g. StarChart) +// Handler for menu button +IMPL_LINK(SvxLineTabPage, GraphicHdl_Impl, const OString&, rIdent, void) +{ + const Graphic* pGraphic = nullptr; + Graphic aGraphic; + bool bResetSize = false; + bool bEnable = true; + tools::Long nPreviousSymbolType = m_nSymbolType; + + OString sNumber; + if (rIdent.startsWith("gallery", &sNumber)) + { + SvxBmpItemInfo* pInfo = m_aGalleryBrushItems[sNumber.toUInt32()].get(); + pGraphic = pInfo->pBrushItem->GetGraphic(); + m_nSymbolType = SVX_SYMBOLTYPE_BRUSHITEM; + } + else if (rIdent.startsWith("symbol", &sNumber)) + { + m_nSymbolType = sNumber.toUInt32(); + SvxBmpItemInfo* pInfo = m_aSymbolBrushItems[m_nSymbolType].get(); + pGraphic = pInfo->pBrushItem->GetGraphic(); + } + else if (rIdent == "automatic") + { + pGraphic=&m_aAutoSymbolGraphic; + m_aAutoSymbolGraphic.SetPrefSize( Size(253,253) ); + m_nSymbolType=SVX_SYMBOLTYPE_AUTO; + } + else if (rIdent == "none") + { + m_nSymbolType=SVX_SYMBOLTYPE_NONE; + pGraphic=nullptr; + bEnable = false; + } + else if (rIdent == "file") + { + SvxOpenGraphicDialog aGrfDlg(CuiResId(RID_CUISTR_EDIT_GRAPHIC), GetFrameWeld()); + aGrfDlg.EnableLink(false); + aGrfDlg.AsLink(false); + if( !aGrfDlg.Execute() ) + { + // Remember selected filters + if( !aGrfDlg.GetGraphic(aGraphic) ) + { + m_nSymbolType=SVX_SYMBOLTYPE_BRUSHITEM; + pGraphic = &aGraphic; + bResetSize = true; + } + } + if( !pGraphic ) + return; + } + + if (pGraphic) + { + Size aSize = SvxNumberFormat::GetGraphicSizeMM100(pGraphic); + aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(m_ePoolUnit)); + m_aSymbolGraphic=*pGraphic; + if( bResetSize ) + { + m_aSymbolSize=aSize; + } + else if( nPreviousSymbolType == SVX_SYMBOLTYPE_BRUSHITEM ) + { //#i31097# Data Point Symbol size changes when a different symbol is chosen(maoyg) + if( m_aSymbolSize.Width() != m_aSymbolSize.Height() ) + { + aSize.setWidth( static_cast<tools::Long>( m_aSymbolSize.Width() + m_aSymbolSize.Height() )/2 ); + aSize.setHeight( static_cast<tools::Long>( m_aSymbolSize.Width() + m_aSymbolSize.Height() )/2 ); + m_aSymbolSize = aSize; + } + } + m_aCtlPreview.SetSymbol(&m_aSymbolGraphic,m_aSymbolSize); + } + else + { + m_aSymbolGraphic=Graphic(); + m_aCtlPreview.SetSymbol(nullptr,m_aSymbolSize); + bEnable = false; + } + m_aSymbolLastSize=m_aSymbolSize; + SetMetricValue(*m_xSymbolWidthMF, m_aSymbolSize.Width(), m_ePoolUnit); + SetMetricValue(*m_xSymbolHeightMF, m_aSymbolSize.Height(), m_ePoolUnit); + + m_xGridIconSize->set_sensitive(bEnable); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK( SvxLineTabPage, SizeHdl_Impl, weld::MetricSpinButton&, rField, void) +{ + m_bNewSize = true; + bool bWidth = &rField == m_xSymbolWidthMF.get(); + m_bLastWidthModified = bWidth; + bool bRatio = m_xSymbolRatioCB->get_active(); + tools::Long nWidthVal = static_cast<tools::Long>(m_xSymbolWidthMF->denormalize(m_xSymbolWidthMF->get_value(FieldUnit::MM_100TH))); + tools::Long nHeightVal= static_cast<tools::Long>(m_xSymbolHeightMF->denormalize(m_xSymbolHeightMF->get_value(FieldUnit::MM_100TH))); + nWidthVal = OutputDevice::LogicToLogic(nWidthVal,MapUnit::Map100thMM, m_ePoolUnit ); + nHeightVal = OutputDevice::LogicToLogic(nHeightVal,MapUnit::Map100thMM, m_ePoolUnit); + m_aSymbolSize = Size(nWidthVal,nHeightVal); + double fSizeRatio = double(1); + + if(bRatio) + { + if (m_aSymbolLastSize.Height() && m_aSymbolLastSize.Width()) + fSizeRatio = static_cast<double>(m_aSymbolLastSize.Width()) / m_aSymbolLastSize.Height(); + } + + if (bWidth) + { + tools::Long nDelta = nWidthVal - m_aSymbolLastSize.Width(); + m_aSymbolSize.setWidth( nWidthVal ); + if (bRatio) + { + m_aSymbolSize.setHeight( m_aSymbolLastSize.Height() + static_cast<tools::Long>(static_cast<double>(nDelta) / fSizeRatio) ); + m_aSymbolSize.setHeight( OutputDevice::LogicToLogic( m_aSymbolSize.Height(), m_ePoolUnit, MapUnit::Map100thMM ) ); +//TODO m_xSymbolHeightMF->SetUserValue(m_xSymbolHeightMF->normalize(m_aSymbolSize.Height()), FieldUnit::MM_100TH); + m_xSymbolHeightMF->set_value(m_xSymbolHeightMF->normalize(m_aSymbolSize.Height()), FieldUnit::MM_100TH); + } + } + else + { + tools::Long nDelta = nHeightVal - m_aSymbolLastSize.Height(); + m_aSymbolSize.setHeight( nHeightVal ); + if (bRatio) + { + m_aSymbolSize.setWidth( m_aSymbolLastSize.Width() + static_cast<tools::Long>(static_cast<double>(nDelta) * fSizeRatio) ); + m_aSymbolSize.setWidth( OutputDevice::LogicToLogic( m_aSymbolSize.Width(), m_ePoolUnit, MapUnit::Map100thMM ) ); +//TODO m_xSymbolWidthMF->SetUserValue(m_xSymbolWidthMF->normalize(m_aSymbolSize.Width()), FieldUnit::MM_100TH); + m_xSymbolWidthMF->set_value(m_xSymbolWidthMF->normalize(m_aSymbolSize.Width()), FieldUnit::MM_100TH); + } + } + m_aCtlPreview.ResizeSymbol(m_aSymbolSize); + m_aSymbolLastSize=m_aSymbolSize; +} + +IMPL_LINK(SvxLineTabPage, RatioHdl_Impl, weld::Toggleable&, rBox, void) +{ + if (rBox.get_active()) + { + if (m_bLastWidthModified) + SizeHdl_Impl(*m_xSymbolWidthMF); + else + SizeHdl_Impl(*m_xSymbolHeightMF); + } +} + +void SvxLineTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxDashListItem* pDashListItem = aSet.GetItem<SvxDashListItem>(SID_DASH_LIST, false); + const SvxLineEndListItem* pLineEndListItem = aSet.GetItem<SvxLineEndListItem>(SID_LINEEND_LIST, false); + const SfxUInt16Item* pPageTypeItem = aSet.GetItem<SfxUInt16Item>(SID_PAGE_TYPE, false); + const SfxUInt16Item* pDlgTypeItem = aSet.GetItem<SfxUInt16Item>(SID_DLG_TYPE, false); + const OfaPtrItem* pSdrObjListItem = aSet.GetItem<OfaPtrItem>(SID_OBJECT_LIST, false); + const SfxTabDialogItem* pSymbolAttrItem = aSet.GetItem<SfxTabDialogItem>(SID_ATTR_SET, false); + const SvxGraphicItem* pGraphicItem = aSet.GetItem<SvxGraphicItem>(SID_GRAPHIC, false); + + if (pDashListItem) + SetDashList(pDashListItem->GetDashList()); + if (pLineEndListItem) + SetLineEndList(pLineEndListItem->GetLineEndList()); + if (pPageTypeItem) + SetPageType(static_cast<PageType>(pPageTypeItem->GetValue())); + if (pDlgTypeItem) + SetDlgType(pDlgTypeItem->GetValue()); + Construct(); + + if(pSdrObjListItem) //symbols + { + ShowSymbolControls(true); + m_pSymbolList = static_cast<SdrObjList*>(pSdrObjListItem->GetValue()); + if (pSymbolAttrItem) + m_xSymbolAttr.reset(new SfxItemSet(pSymbolAttrItem->GetItemSet())); + if(pGraphicItem) + m_aAutoSymbolGraphic = pGraphicItem->GetGraphic(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tplnedef.cxx b/cui/source/tabpages/tplnedef.cxx new file mode 100644 index 000000000..66fea1aba --- /dev/null +++ b/cui/source/tabpages/tplnedef.cxx @@ -0,0 +1,840 @@ +/* -*- 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 . + */ + +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <unotools/pathoptions.hxx> +#include <sfx2/filedlghelper.hxx> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> + +#include <strings.hrc> + +#include <svx/xlineit0.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xtable.hxx> + +#include <svx/dlgctrl.hxx> +#include <cuitabline.hxx> +#include <defdlgname.hxx> +#include <svx/svxdlg.hxx> +#include <dialmgr.hxx> +#include <svx/dlgutil.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <svx/svxids.hrc> +#include <cuitabarea.hxx> +#include <svtools/unitconv.hxx> +#include <osl/diagnose.h> + +#define XOUT_WIDTH 150 + +using namespace com::sun::star; + + +SvxLineDefTabPage::SvxLineDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/linestyletabpage.ui", "LineStylePage", &rInAttrs) + , rOutAttrs(rInAttrs) + , aXLineAttr(rInAttrs.GetPool()) + , rXLSet(aXLineAttr.GetItemSet()) + , pnDashListState(nullptr) + , pPageType(nullptr) + , nDlgType(0) + , pPosDashLb(nullptr) + , m_xLbLineStyles(new SvxLineLB(m_xBuilder->weld_combo_box("LB_LINESTYLES"))) + , m_xLbType1(m_xBuilder->weld_combo_box("LB_TYPE_1")) + , m_xLbType2(m_xBuilder->weld_combo_box("LB_TYPE_2")) + , m_xNumFldNumber1(m_xBuilder->weld_spin_button("NUM_FLD_1")) + , m_xNumFldNumber2(m_xBuilder->weld_spin_button("NUM_FLD_2")) + , m_xMtrLength1(m_xBuilder->weld_metric_spin_button("MTR_FLD_LENGTH_1", FieldUnit::CM)) + , m_xMtrLength2(m_xBuilder->weld_metric_spin_button("MTR_FLD_LENGTH_2", FieldUnit::CM)) + , m_xMtrDistance(m_xBuilder->weld_metric_spin_button("MTR_FLD_DISTANCE", FieldUnit::CM)) + , m_xCbxSynchronize(m_xBuilder->weld_check_button("CBX_SYNCHRONIZE")) + , m_xBtnAdd(m_xBuilder->weld_button("BTN_ADD")) + , m_xBtnModify(m_xBuilder->weld_button("BTN_MODIFY")) + , m_xBtnDelete(m_xBuilder->weld_button("BTN_DELETE")) + , m_xBtnLoad(m_xBuilder->weld_button("BTN_LOAD")) + , m_xBtnSave(m_xBuilder->weld_button("BTN_SAVE")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + // adjust metric + eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ; //prevent warning + } + SetFieldUnit(*m_xMtrDistance, eFUnit); + SetFieldUnit(*m_xMtrLength1, eFUnit); + SetFieldUnit(*m_xMtrLength2, eFUnit); + + // determine PoolUnit + SfxItemPool* pPool = rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + ePoolUnit = pPool->GetMetric( SID_ATTR_LINE_WIDTH ); + + rXLSet.Put( XLineStyleItem(drawing::LineStyle_DASH) ); + rXLSet.Put( XLineWidthItem(XOUT_WIDTH) ); + rXLSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 3, 7, 2, 40, 15 ) ) ); + rXLSet.Put( XLineColorItem(OUString(), COL_BLACK) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + + m_xBtnAdd->connect_clicked(LINK(this, SvxLineDefTabPage, ClickAddHdl_Impl)); + m_xBtnModify->connect_clicked(LINK(this, SvxLineDefTabPage, ClickModifyHdl_Impl)); + m_xBtnDelete->connect_clicked(LINK(this, SvxLineDefTabPage, ClickDeleteHdl_Impl)); + m_xBtnLoad->connect_clicked(LINK(this, SvxLineDefTabPage, ClickLoadHdl_Impl)); + m_xBtnSave->connect_clicked(LINK(this, SvxLineDefTabPage, ClickSaveHdl_Impl)); + + m_xNumFldNumber1->connect_value_changed(LINK(this, SvxLineDefTabPage, ChangeNumber1Hdl_Impl)); + m_xNumFldNumber2->connect_value_changed(LINK(this, SvxLineDefTabPage, ChangeNumber2Hdl_Impl)); + m_xLbLineStyles->connect_changed(LINK(this, SvxLineDefTabPage, SelectLinestyleListBoxHdl_Impl)); + + // #i122042# switch off default adding of 'none' and 'solid' entries + // for this ListBox; we want to select only editable/dashed styles + m_xLbLineStyles->setAddStandardFields(false); + + // absolute (in mm) or relative (in %) + m_xCbxSynchronize->connect_toggled(LINK(this, SvxLineDefTabPage, ChangeMetricHdl_Impl)); + + // preview must be updated when there's something changed + Link<weld::ComboBox&, void> aLink = LINK(this, SvxLineDefTabPage, SelectTypeListBoxHdl_Impl); + m_xLbType1->connect_changed(aLink); + m_xLbType2->connect_changed(aLink); + Link<weld::MetricSpinButton&,void> aLink2 = LINK( this, SvxLineDefTabPage, ChangePreviewHdl_Impl ); + m_xMtrLength1->connect_value_changed(aLink2); + m_xMtrLength2->connect_value_changed(aLink2); + m_xMtrDistance->connect_value_changed(aLink2); + + pDashList = nullptr; +} + +SvxLineDefTabPage::~SvxLineDefTabPage() +{ + m_xCtlPreview.reset(); + m_xLbLineStyles.reset(); +} + +void SvxLineDefTabPage::Construct() +{ + // Line style fill; do *not* add default fields here + m_xLbLineStyles->Fill( pDashList ); +} + +void SvxLineDefTabPage::ActivatePage( const SfxItemSet& ) +{ + if( nDlgType != 0 ) // area dialog + return; + + // ActivatePage() is called before the dialog receives PageCreated() !!! + if( !pDashList.is() ) + return; + + if (*pPageType == PageType::Gradient && + *pPosDashLb != -1) + { + m_xLbLineStyles->set_active(*pPosDashLb); + } + // so that a possibly existing line style is discarded + SelectLinestyleHdl_Impl( nullptr ); + + // determining (and possibly cutting) the name + // and displaying it in the GroupBox +// OUString aString( CuiResId( RID_CUISTR_TABLE ) ); +// aString += ": "; + INetURLObject aURL( pDashList->GetPath() ); + + aURL.Append( pDashList->GetName() ); + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + *pPageType = PageType::Area; // 2 + *pPosDashLb = -1; +} + + +DeactivateRC SvxLineDefTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + CheckChanges_Impl(); + + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + +void SvxLineDefTabPage::CheckChanges_Impl() +{ + // is here used to NOT lose changes + //css::drawing::DashStyle eXDS; + + if( m_xNumFldNumber1->get_value_changed_from_saved() || + m_xMtrLength1->get_value_changed_from_saved() || + m_xLbType1->get_value_changed_from_saved() || + m_xNumFldNumber2->get_value_changed_from_saved() || + m_xMtrLength2->get_value_changed_from_saved() || + m_xLbType2->get_value_changed_from_saved() || + m_xMtrDistance->get_value_changed_from_saved() ) + { + std::unique_ptr<weld::MessageDialog> xMessDlg(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Cancel, + CuiResId(RID_CUISTR_ASK_CHANGE_LINESTYLE))); + xMessDlg->set_title(SvxResId(RID_SVXSTR_LINESTYLE)); + xMessDlg->add_button(CuiResId(RID_CUISTR_CHANGE), RET_BTN_1); + xMessDlg->add_button(CuiResId(RID_CUISTR_ADD), RET_BTN_2); + + short nRet = xMessDlg->run(); + + switch( nRet ) + { + case RET_BTN_1: + { + ClickModifyHdl_Impl(*m_xBtnModify); + } + break; + + case RET_BTN_2: + { + ClickAddHdl_Impl(*m_xBtnAdd); + } + break; + + case RET_CANCEL: + break; + } + } + + int nPos = m_xLbLineStyles->get_active(); + if (nPos != -1) + { + *pPosDashLb = nPos; + } +} + + +bool SvxLineDefTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + if( nDlgType == 0 ) // line dialog + { + if( *pPageType == PageType::Hatch ) + { + FillDash_Impl(); + + OUString aString(m_xLbLineStyles->get_active_text()); + rAttrs->Put( XLineStyleItem( drawing::LineStyle_DASH ) ); + rAttrs->Put( XLineDashItem( aString, aDash ) ); + } + } + return true; +} + + +void SvxLineDefTabPage::Reset( const SfxItemSet* rAttrs ) +{ + if( rAttrs->GetItemState( GetWhich( XATTR_LINESTYLE ) ) != SfxItemState::DONTCARE ) + { + drawing::LineStyle eXLS = rAttrs->Get( GetWhich( XATTR_LINESTYLE ) ).GetValue(); + + switch( eXLS ) + { + case drawing::LineStyle_NONE: + case drawing::LineStyle_SOLID: + m_xLbLineStyles->set_active(0); + break; + case drawing::LineStyle_DASH: + { + const XLineDashItem& rDashItem = rAttrs->Get( XATTR_LINEDASH ); + aDash = rDashItem.GetDashValue(); + + m_xLbLineStyles->set_active(-1); + m_xLbLineStyles->set_active_text(rDashItem.GetName()); + break; + } + default: + break; + } + } + SelectLinestyleHdl_Impl( nullptr ); + + // determine button state + if( pDashList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +std::unique_ptr<SfxTabPage> SvxLineDefTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs ) +{ + return std::make_unique<SvxLineDefTabPage>(pPage, pController, *rOutAttrs); +} + +IMPL_LINK(SvxLineDefTabPage, SelectLinestyleListBoxHdl_Impl, weld::ComboBox&, rListBox, void) +{ + SelectLinestyleHdl_Impl(&rListBox); +} + +void SvxLineDefTabPage::SelectLinestyleHdl_Impl(const weld::ComboBox* p) +{ + if(!pDashList->Count()) + return; + + int nTmp = m_xLbLineStyles->get_active(); + if (nTmp == -1) + { + OSL_ENSURE(false, "OOps, non-existent LineDash selected (!)"); + nTmp = 1; + } + + aDash = pDashList->GetDash( nTmp )->GetDash(); + + FillDialog_Impl(); + + rXLSet.Put( XLineDashItem( OUString(), aDash ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); + + // Is not set before, in order to take the new style + // only if there was an entry selected in the ListBox. + // If it was called via Reset(), then p is == NULL + if( p ) + *pPageType = PageType::Hatch; +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ChangePreviewHdl_Impl, weld::MetricSpinButton&, void) +{ + FillDash_Impl(); + m_aCtlPreview.Invalidate(); +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ChangeNumber1Hdl_Impl, weld::SpinButton&, void) +{ + if (m_xNumFldNumber1->get_value() == 0) + { + m_xNumFldNumber2->set_min(1); + } + else + { + m_xNumFldNumber2->set_min(0); + } + + ChangePreviewHdl_Impl(*m_xMtrLength1); +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ChangeNumber2Hdl_Impl, weld::SpinButton&, void) +{ + if (m_xNumFldNumber2->get_value() == 0) + { + m_xNumFldNumber1->set_min(1); + } + else + { + m_xNumFldNumber1->set_min(0); + } + + ChangePreviewHdl_Impl(*m_xMtrLength1); +} + +IMPL_LINK( SvxLineDefTabPage, ChangeMetricHdl_Impl, weld::Toggleable&, r, void) +{ + ChangeMetricHdl_Impl(&r); +} + +void SvxLineDefTabPage::ChangeMetricHdl_Impl(const weld::Toggleable* p) +{ + if( !m_xCbxSynchronize->get_active() && m_xMtrLength1->get_unit() != eFUnit ) + { + tools::Long nTmp1, nTmp2, nTmp3; + + // was changed with Control + if( p ) + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ) * XOUT_WIDTH / 100; + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ) * XOUT_WIDTH / 100; + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ) * XOUT_WIDTH / 100; + } + else + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ); + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ); + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ); + } + m_xMtrLength1->set_digits(2); + m_xMtrLength2->set_digits(2); + m_xMtrDistance->set_digits(2); + + // adjust metric + m_xMtrLength1->set_unit(eFUnit); + m_xMtrLength2->set_unit(eFUnit); + m_xMtrDistance->set_unit(eFUnit); + + // tdf#126736 max 5cm + m_xMtrLength1->set_range(0, 500, FieldUnit::CM); + m_xMtrLength2->set_range(0, 500, FieldUnit::CM); + m_xMtrDistance->set_range(0, 500, FieldUnit::CM); + + SetMetricValue( *m_xMtrLength1, nTmp1, ePoolUnit ); + SetMetricValue( *m_xMtrLength2, nTmp2, ePoolUnit ); + SetMetricValue( *m_xMtrDistance, nTmp3, ePoolUnit ); + } + else if( m_xCbxSynchronize->get_active() && m_xMtrLength1->get_unit() != FieldUnit::PERCENT ) + { + tools::Long nTmp1, nTmp2, nTmp3; + + // was changed with Control + if( p ) + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ) * 100 / XOUT_WIDTH; + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ) * 100 / XOUT_WIDTH; + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ) * 100 / XOUT_WIDTH; + } + else + { + nTmp1 = GetCoreValue( *m_xMtrLength1, ePoolUnit ); + nTmp2 = GetCoreValue( *m_xMtrLength2, ePoolUnit ); + nTmp3 = GetCoreValue( *m_xMtrDistance, ePoolUnit ); + } + + m_xMtrLength1->set_digits(0); + m_xMtrLength2->set_digits(0); + m_xMtrDistance->set_digits(0); + + m_xMtrLength1->set_unit(FieldUnit::PERCENT); + m_xMtrLength2->set_unit(FieldUnit::PERCENT); + m_xMtrDistance->set_unit(FieldUnit::PERCENT); + + // tdf#126736 800% + m_xMtrLength1->set_range(0, 800, FieldUnit::PERCENT); + m_xMtrLength2->set_range(0, 800, FieldUnit::PERCENT); + m_xMtrDistance->set_range(0, 800, FieldUnit::PERCENT); + + m_xMtrLength1->set_value(nTmp1, FieldUnit::PERCENT); + m_xMtrLength2->set_value(nTmp2, FieldUnit::PERCENT); + m_xMtrDistance->set_value(nTmp3, FieldUnit::PERCENT); + } + SelectTypeHdl_Impl( nullptr ); +} + +IMPL_LINK( SvxLineDefTabPage, SelectTypeListBoxHdl_Impl, weld::ComboBox&, rListBox, void ) +{ + SelectTypeHdl_Impl(&rListBox); +} + +void SvxLineDefTabPage::SelectTypeHdl_Impl(const weld::ComboBox* p) +{ + if (p == m_xLbType1.get() || !p) + { + if (m_xLbType1->get_active() == 0) + { + m_xMtrLength1->set_sensitive(false); + m_xMtrLength1->set_text(""); + } + else if (!m_xMtrLength1->get_sensitive()) + { + m_xMtrLength1->set_sensitive(true); + m_xMtrLength1->reformat(); + } + } + + if (p == m_xLbType2.get() || !p) + { + if (m_xLbType2->get_active() == 0) + { + m_xMtrLength2->set_sensitive(false); + m_xMtrLength2->set_text(""); + } + else if (!m_xMtrLength2->get_sensitive()) + { + m_xMtrLength2->set_sensitive(true); + m_xMtrLength2->reformat(); + } + } + ChangePreviewHdl_Impl(*m_xMtrLength1); +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + OUString aNewName(SvxResId(RID_SVXSTR_LINESTYLE)); + OUString aDesc(CuiResId(RID_CUISTR_DESC_LINESTYLE)); + OUString aName; + + tools::Long nCount = pDashList->Count(); + tools::Long j = 1; + bool bDifferent = false; + + while ( !bDifferent ) + { + aName = aNewName + " " + OUString::number( j++ ); + bDifferent = true; + + for ( tools::Long i = 0; i < nCount && bDifferent; i++ ) + if ( aName == pDashList->GetDash( i )->GetName() ) + bDifferent = false; + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + bool bLoop = true; + + while ( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bDifferent = true; + + for( tools::Long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pDashList->GetDash( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + { + bLoop = false; + FillDash_Impl(); + + tools::Long nDashCount = pDashList->Count(); + pDashList->Insert( std::make_unique<XDashEntry>(aDash, aName), nDashCount ); + m_xLbLineStyles->Append( *pDashList->GetDash(nDashCount), pDashList->GetUiBitmap(nDashCount) ); + + m_xLbLineStyles->set_active(m_xLbLineStyles->get_count() - 1); + + *pnDashListState |= ChangeType::MODIFIED; + + *pPageType = PageType::Hatch; + + // save values for changes recognition (-> method) + m_xNumFldNumber1->save_value(); + m_xMtrLength1->save_value(); + m_xLbType1->save_value(); + m_xNumFldNumber2->save_value(); + m_xMtrLength2->save_value(); + m_xLbType2->save_value(); + m_xMtrDistance->save_value(); + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } + pDlg.disposeAndClear(); + + // determine button state + if ( pDashList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineStyles->get_active(); + if (nPos == -1) + return; + + OUString aDesc(CuiResId(RID_CUISTR_DESC_LINESTYLE)); + OUString aName( pDashList->GetDash( nPos )->GetName() ); + OUString aOldName = aName; + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + tools::Long nCount = pDashList->Count(); + bool bLoop = true; + + while ( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bool bDifferent = true; + + for( tools::Long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pDashList->GetDash( i )->GetName() && + aName != aOldName ) + bDifferent = false; + } + + if ( bDifferent ) + { + bLoop = false; + FillDash_Impl(); + + pDashList->Replace(std::make_unique<XDashEntry>(aDash, aName), nPos); + m_xLbLineStyles->Modify(*pDashList->GetDash(nPos), nPos, pDashList->GetUiBitmap(nPos)); + + m_xLbLineStyles->set_active(nPos); + + *pnDashListState |= ChangeType::MODIFIED; + + *pPageType = PageType::Hatch; + + // save values for changes recognition (-> method) + m_xNumFldNumber1->save_value(); + m_xMtrLength1->save_value(); + m_xLbType1->save_value(); + m_xNumFldNumber2->save_value(); + m_xMtrLength2->save_value(); + m_xLbType2->save_value(); + m_xMtrDistance->save_value(); + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickDeleteHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineStyles->get_active(); + if (nPos != -1) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletelinestyledialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskDelLineStyleDialog")); + if (xQueryBox->run() == RET_YES) + { + pDashList->Remove(nPos); + m_xLbLineStyles->remove(nPos); + m_xLbLineStyles->set_active(0); + + SelectLinestyleHdl_Impl( nullptr ); + *pPageType = PageType::Area; // style should not be taken + + *pnDashListState |= ChangeType::MODIFIED; + + ChangePreviewHdl_Impl( *m_xMtrLength1 ); + } + } + + // determine button state + if ( !pDashList->Count() ) + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickLoadHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nReturn = RET_YES; + + if ( *pnDashListState & ChangeType::MODIFIED ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querysavelistdialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("AskSaveList")); + + nReturn = xBox->run(); + + if ( nReturn == RET_YES ) + pDashList->Save(); + } + + if ( nReturn != RET_CANCEL ) + { + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.sod" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( aDlg.Execute() == ERRCODE_NONE ) + { + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + XDashListRef pDshLst = XPropertyList::AsDashList(XPropertyList::CreatePropertyList( XPropertyListType::Dash, aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), "" )); + pDshLst->SetName( aURL.getName() ); + + if( pDshLst->Load() ) + { + pDashList = pDshLst; + static_cast<SvxLineTabDialog*>(GetDialogController())->SetNewDashList( pDashList ); + + m_xLbLineStyles->clear(); + m_xLbLineStyles->Fill( pDashList ); + Reset( &rOutAttrs ); + + pDashList->SetName( aURL.getName() ); + + *pnDashListState |= ChangeType::CHANGED; + *pnDashListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynoloadedfiledialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("NoLoadedFileDialog")); + xBox->run(); + } + } + } + + // determine button state + if ( pDashList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineDefTabPage, ClickSaveHdl_Impl, weld::Button&, void) +{ + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.sod" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + DBG_ASSERT( aFile.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + if( !pDashList->GetName().isEmpty() ) + { + aFile.Append( pDashList->GetName() ); + + if( aFile.getExtension().isEmpty() ) + aFile.SetExtension( u"sod" ); + } + + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if ( aDlg.Execute() != ERRCODE_NONE ) + return; + + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + pDashList->SetName( aURL.getName() ); + pDashList->SetPath( aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( pDashList->Save() ) + { + *pnDashListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynosavefiledialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("NoSaveFileDialog")); + xBox->run(); + } +} + +void SvxLineDefTabPage::FillDash_Impl() +{ + css::drawing::DashStyle eXDS; + + if (m_xCbxSynchronize->get_active()) + eXDS = css::drawing::DashStyle_RECTRELATIVE; + else + eXDS = css::drawing::DashStyle_RECT; + + aDash.SetDashStyle( eXDS ); + aDash.SetDots( static_cast<sal_uInt8>(m_xNumFldNumber1->get_value()) ); + aDash.SetDotLen( m_xLbType1->get_active() == 0 ? 0 : GetCoreValue( *m_xMtrLength1, ePoolUnit ) ); + aDash.SetDashes( static_cast<sal_uInt8>(m_xNumFldNumber2->get_value()) ); + aDash.SetDashLen( m_xLbType2->get_active() == 0 ? 0 : GetCoreValue( *m_xMtrLength2, ePoolUnit ) ); + aDash.SetDistance( GetCoreValue( *m_xMtrDistance, ePoolUnit ) ); + + rXLSet.Put( XLineDashItem( OUString(), aDash ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); +} + +void SvxLineDefTabPage::FillDialog_Impl() +{ + css::drawing::DashStyle eXDS = aDash.GetDashStyle(); // css::drawing::DashStyle_RECT, css::drawing::DashStyle_ROUND + if( eXDS == css::drawing::DashStyle_RECTRELATIVE ) + m_xCbxSynchronize->set_active(true); + else + m_xCbxSynchronize->set_active(false); + + m_xNumFldNumber1->set_value(aDash.GetDots()); + SetMetricValue( *m_xMtrLength1, aDash.GetDotLen(), ePoolUnit ); + m_xLbType1->set_active(aDash.GetDotLen() == 0 ? 0 : 1); + m_xNumFldNumber2->set_value(aDash.GetDashes()); + SetMetricValue( *m_xMtrLength2, aDash.GetDashLen(), ePoolUnit ); + m_xLbType2->set_active(aDash.GetDashLen() == 0 ? 0 : 1); + SetMetricValue( *m_xMtrDistance, aDash.GetDistance(), ePoolUnit ); + + ChangeMetricHdl_Impl(nullptr); + + // save values for changes recognition (-> method) + m_xNumFldNumber1->save_value(); + m_xMtrLength1->save_value(); + m_xLbType1->save_value(); + m_xNumFldNumber2->save_value(); + m_xMtrLength2->save_value(); + m_xLbType2->save_value(); + m_xMtrDistance->save_value(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tplneend.cxx b/cui/source/tabpages/tplneend.cxx new file mode 100644 index 000000000..951b27632 --- /dev/null +++ b/cui/source/tabpages/tplneend.cxx @@ -0,0 +1,610 @@ +/* -*- 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 . + */ + +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <unotools/pathoptions.hxx> +#include <sfx2/filedlghelper.hxx> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> + +#include <strings.hrc> +#include <svx/dialmgr.hxx> +#include <svx/dlgctrl.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdopath.hxx> +#include <svx/xtable.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <cuitabline.hxx> +#include <cuitabarea.hxx> +#include <svx/svxdlg.hxx> +#include <dialmgr.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <svx/strings.hrc> +#include <osl/diagnose.h> + +#define XOUT_WIDTH 150 + +SvxLineEndDefTabPage::SvxLineEndDefTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/lineendstabpage.ui", "LineEndPage", &rInAttrs) + , rOutAttrs(rInAttrs) + , pPolyObj(nullptr) + , aXLineAttr(rInAttrs.GetPool()) + , rXLSet(aXLineAttr.GetItemSet()) + , pnLineEndListState(nullptr) + , pPageType(nullptr) + , nDlgType(0) + , pPosLineEndLb(nullptr) + , m_xEdtName(m_xBuilder->weld_entry("EDT_NAME")) + , m_xLbLineEnds(new SvxLineEndLB(m_xBuilder->weld_combo_box("LB_LINEENDS"))) + , m_xBtnAdd(m_xBuilder->weld_button("BTN_ADD")) + , m_xBtnModify(m_xBuilder->weld_button("BTN_MODIFY")) + , m_xBtnDelete(m_xBuilder->weld_button("BTN_DELETE")) + , m_xBtnLoad(m_xBuilder->weld_button("BTN_LOAD")) + , m_xBtnSave(m_xBuilder->weld_button("BTN_SAVE")) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + rXLSet.Put( XLineStyleItem(css::drawing::LineStyle_SOLID) ); + rXLSet.Put( XLineWidthItem(XOUT_WIDTH) ); + rXLSet.Put( XLineColorItem( OUString(), COL_BLACK ) ); + rXLSet.Put( XLineStartWidthItem( m_aCtlPreview.GetOutputSize().Height() / 2 ) ); + rXLSet.Put( XLineEndWidthItem( m_aCtlPreview.GetOutputSize().Height() / 2 ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + + m_xBtnAdd->connect_clicked(LINK(this, SvxLineEndDefTabPage, ClickAddHdl_Impl)); + m_xBtnModify->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickModifyHdl_Impl)); + m_xBtnDelete->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickDeleteHdl_Impl)); + m_xBtnLoad->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickLoadHdl_Impl)); + m_xBtnSave->connect_clicked(LINK( this, SvxLineEndDefTabPage, ClickSaveHdl_Impl)); + + m_xLbLineEnds->connect_changed(LINK(this, SvxLineEndDefTabPage, SelectLineEndHdl_Impl)); +} + +SvxLineEndDefTabPage::~SvxLineEndDefTabPage() +{ + m_xCtlPreview.reset(); + m_xLbLineEnds.reset(); +} + +void SvxLineEndDefTabPage::Construct() +{ + m_xLbLineEnds->Fill( pLineEndList ); + + bool bCreateArrowPossible = true; + + if( !pPolyObj ) + { + bCreateArrowPossible = false; + } + else if( nullptr == dynamic_cast<const SdrPathObj*>( pPolyObj) ) + { + SdrObjTransformInfoRec aInfoRec; + pPolyObj->TakeObjInfo( aInfoRec ); + SdrObjectUniquePtr pNewObj; + if( aInfoRec.bCanConvToPath ) + pNewObj = pPolyObj->ConvertToPolyObj( true, false ); + + bCreateArrowPossible = nullptr != dynamic_cast<const SdrPathObj*>( pNewObj.get()); + } + + if( !bCreateArrowPossible ) + m_xBtnAdd->set_sensitive(false); +} + +void SvxLineEndDefTabPage::ActivatePage( const SfxItemSet& ) +{ + if( nDlgType != 0 ) // area dialog + return; + + // ActivatePage() is called before the dialog receives PageCreated() !!! + if( !pLineEndList.is() ) + return; + + if( *pPosLineEndLb != -1) + { + m_xLbLineEnds->set_active(*pPosLineEndLb); + SelectLineEndHdl_Impl(); + } + INetURLObject aURL( pLineEndList->GetPath() ); + + aURL.Append( pLineEndList->GetName() ); + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + *pPageType = PageType::Area; // 3 + *pPosLineEndLb = -1; +} + + +DeactivateRC SvxLineEndDefTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + CheckChanges_Impl(); + + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +void SvxLineEndDefTabPage::CheckChanges_Impl() +{ + int nPos = m_xLbLineEnds->get_active(); + + if (nPos != -1) + { + OUString aString = m_xEdtName->get_text(); + + if( aString != m_xLbLineEnds->get_active_text() ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querychangelineenddialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskChangeLineEndDialog")); + if (xQueryBox->run() == RET_YES) + ClickModifyHdl_Impl(*m_xBtnModify); + } + } + nPos = m_xLbLineEnds->get_active(); + + if (nPos != -1) + *pPosLineEndLb = nPos; +} + + +bool SvxLineEndDefTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if( nDlgType == 0 ) // line dialog + { + if( *pPageType == PageType::Bitmap ) + { + CheckChanges_Impl(); + + int nPos = m_xLbLineEnds->get_active(); + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + + rSet->Put( XLineStartItem( pEntry->GetName(), pEntry->GetLineEnd() ) ); + rSet->Put( XLineEndItem( pEntry->GetName(), pEntry->GetLineEnd() ) ); + } + } + return true; +} + +void SvxLineEndDefTabPage::Reset( const SfxItemSet* ) +{ + m_xLbLineEnds->set_active(0); + + // Update lineend + if( pLineEndList->Count() > 0 ) + { + int nPos = m_xLbLineEnds->get_active(); + + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + + m_xEdtName->set_text(m_xLbLineEnds->get_active_text()); + + rXLSet.Put( XLineStartItem( OUString(), pEntry->GetLineEnd() ) ); + rXLSet.Put( XLineEndItem( OUString(), pEntry->GetLineEnd() ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); + } + + // determine button state + if( pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +std::unique_ptr<SfxTabPage> SvxLineEndDefTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxLineEndDefTabPage>(pPage, pController, *rSet ); +} + +void SvxLineEndDefTabPage::SelectLineEndHdl_Impl() +{ + if( pLineEndList->Count() <= 0 ) + return; + + int nPos = m_xLbLineEnds->get_active(); + + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos); + + m_xEdtName->set_text(m_xLbLineEnds->get_active_text()); + + rXLSet.Put( XLineStartItem( OUString(), pEntry->GetLineEnd() ) ); + rXLSet.Put( XLineEndItem( OUString(), pEntry->GetLineEnd() ) ); + + // #i34740# + m_aCtlPreview.SetLineAttributes(aXLineAttr.GetItemSet()); + m_aCtlPreview.Invalidate(); + + // Is not set before, in order to only take the new style, + // if there is an entry selected in the ListBox + *pPageType = PageType::Bitmap; +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, SelectLineEndHdl_Impl, weld::ComboBox&, void) +{ + SelectLineEndHdl_Impl(); +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineEnds->get_active(); + if (nPos == -1) + return; + + OUString aDesc(CuiResId(RID_CUISTR_DESC_LINEEND)); + OUString aName(m_xEdtName->get_text()); + tools::Long nCount = pLineEndList->Count(); + bool bDifferent = true; + + // check whether the name is existing already + for ( tools::Long i = 0; i < nCount && bDifferent; i++ ) + if ( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + + // if yes, repeat and demand a new name + if ( !bDifferent ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarningBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xWarningBox->run(); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + bool bLoop = true; + + while( !bDifferent && bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bDifferent = true; + + for( tools::Long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + bLoop = false; + else + xWarningBox->run(); + } + } + + // if not existing, enter the entry + if( !bDifferent ) + return; + + const XLineEndEntry* pOldEntry = pLineEndList->GetLineEnd(nPos); + + if(pOldEntry) + { + // #123497# Need to replace the existing entry with a new one + pLineEndList->Replace(std::make_unique<XLineEndEntry>(pOldEntry->GetLineEnd(), aName), nPos); + + m_xEdtName->set_text(aName); + + m_xLbLineEnds->Modify(*pLineEndList->GetLineEnd(nPos), nPos, pLineEndList->GetUiBitmap(nPos)); + m_xLbLineEnds->set_active(nPos); + + // set flag for modified + *pnLineEndListState |= ChangeType::MODIFIED; + + *pPageType = PageType::Bitmap; + } + else + { + OSL_ENSURE(false, "LineEnd to be modified not existing (!)"); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + if( pPolyObj ) + { + const SdrObject* pNewObj; + SdrObjectUniquePtr pConvPolyObj; + + if( nullptr != dynamic_cast<const SdrPathObj*>( pPolyObj) ) + { + pNewObj = pPolyObj; + } + else + { + SdrObjTransformInfoRec aInfoRec; + pPolyObj->TakeObjInfo( aInfoRec ); + + if( aInfoRec.bCanConvToPath ) + { + pConvPolyObj = pPolyObj->ConvertToPolyObj( true, false ); + pNewObj = pConvPolyObj.get(); + + if( !pNewObj || nullptr == dynamic_cast<const SdrPathObj*>( pNewObj) ) + return; // cancel, additional safety, which + // has no use for group objects though. + } + else return; // cancel + } + + basegfx::B2DPolyPolygon aNewPolyPolygon(static_cast<const SdrPathObj*>(pNewObj)->GetPathPoly()); + basegfx::B2DRange aNewRange(basegfx::utils::getRange(aNewPolyPolygon)); + + // normalize + aNewPolyPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix( -aNewRange.getMinX(), -aNewRange.getMinY())); + + pConvPolyObj.reset(); + + OUString aNewName(SvxResId(RID_SVXSTR_LINEEND)); + OUString aDesc(CuiResId(RID_CUISTR_DESC_LINEEND)); + OUString aName; + + tools::Long nCount = pLineEndList->Count(); + tools::Long j = 1; + bool bDifferent = false; + + while ( !bDifferent ) + { + aName = aNewName + " " + OUString::number( j++ ); + bDifferent = true; + + for( tools::Long i = 0; i < nCount && bDifferent; i++ ) + if ( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc )); + bool bLoop = true; + + while ( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + bDifferent = true; + + for( tools::Long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + { + bLoop = false; + + auto nLineEndCount = pLineEndList->Count(); + pLineEndList->Insert(std::make_unique<XLineEndEntry>(aNewPolyPolygon, aName), nLineEndCount); + + // add to the ListBox + m_xLbLineEnds->Append(*pLineEndList->GetLineEnd(nLineEndCount), pLineEndList->GetUiBitmap(nLineEndCount)); + m_xLbLineEnds->set_active(m_xLbLineEnds->get_count() - 1); + + *pnLineEndListState |= ChangeType::MODIFIED; + + SelectLineEndHdl_Impl(); + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarningBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xWarningBox->run(); + } + } + } + else + m_xBtnAdd->set_sensitive(false); + + // determine button state + if ( pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickDeleteHdl_Impl, weld::Button&, void) +{ + int nPos = m_xLbLineEnds->get_active(); + + if (nPos != -1) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletelineenddialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskDelLineEndDialog")); + + if (xQueryBox->run() == RET_YES) + { + pLineEndList->Remove(nPos); + m_xLbLineEnds->remove(nPos); + m_xLbLineEnds->set_active(0); + + SelectLineEndHdl_Impl(); + *pPageType = PageType::Area; // LineEnd shall not be taken over + + *pnLineEndListState |= ChangeType::MODIFIED; + + m_aCtlPreview.Invalidate(); + } + } + // determine button state + if( !pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickLoadHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nReturn = RET_YES; + + if ( *pnLineEndListState & ChangeType::MODIFIED ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querysavelistdialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("AskSaveList")); + + nReturn = xBox->run(); + + if ( nReturn == RET_YES ) + pLineEndList->Save(); + } + + if ( nReturn != RET_CANCEL ) + { + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.soe" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( aDlg.Execute() == ERRCODE_NONE ) + { + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + XLineEndListRef pLeList = XPropertyList::AsLineEndList( + XPropertyList::CreatePropertyList( + XPropertyListType::LineEnd, + aPathURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), "")); + pLeList->SetName( aURL.getName() ); + if( pLeList->Load() ) + { + pLineEndList = pLeList; + static_cast<SvxLineTabDialog*>(GetDialogController())->SetNewLineEndList( pLineEndList ); + m_xLbLineEnds->clear(); + m_xLbLineEnds->Fill( pLineEndList ); + Reset( &rOutAttrs ); + + pLineEndList->SetName( aURL.getName() ); + + *pnLineEndListState |= ChangeType::CHANGED; + *pnLineEndListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynoloadedfiledialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("NoLoadedFileDialog")); + xBox->run(); + } + } + } + + // determine button state + if ( pLineEndList->Count() ) + { + m_xBtnModify->set_sensitive(true); + m_xBtnDelete->set_sensitive(true); + m_xBtnSave->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + m_xBtnDelete->set_sensitive(false); + m_xBtnSave->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxLineEndDefTabPage, ClickSaveHdl_Impl, weld::Button&, void) +{ + ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE, FileDialogFlags::NONE, GetFrameWeld()); + OUString aStrFilterType( "*.soe" ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); + + OUString aPalettePath(SvtPathOptions().GetPalettePath()); + OUString aLastDir; + sal_Int32 nIndex = 0; + do + { + aLastDir = aPalettePath.getToken(0, ';', nIndex); + } + while (nIndex >= 0); + + INetURLObject aFile(aLastDir); + DBG_ASSERT( aFile.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + if( !pLineEndList->GetName().isEmpty() ) + { + aFile.Append( pLineEndList->GetName() ); + + if( aFile.getExtension().isEmpty() ) + aFile.SetExtension( u"soe" ); + } + + aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + if ( aDlg.Execute() != ERRCODE_NONE ) + return; + + INetURLObject aURL( aDlg.GetPath() ); + INetURLObject aPathURL( aURL ); + + aPathURL.removeSegment(); + aPathURL.removeFinalSlash(); + + pLineEndList->SetName( aURL.getName() ); + pLineEndList->SetPath( aPathURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); + + if( pLineEndList->Save() ) + { + *pnLineEndListState &= ~ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querynosavefiledialog.ui")); + std::unique_ptr<weld::MessageDialog> xBox(xBuilder->weld_message_dialog("NoSaveFileDialog")); + xBox->run(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tppattern.cxx b/cui/source/tabpages/tppattern.cxx new file mode 100644 index 000000000..4976a0a0e --- /dev/null +++ b/cui/source/tabpages/tppattern.cxx @@ -0,0 +1,553 @@ +/* -*- 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 . + */ + +#include <memory> +#include <tools/urlobj.hxx> +#include <sfx2/dialoghelper.hxx> +#include <svx/colorbox.hxx> +#include <svx/dialmgr.hxx> +#include <vcl/BitmapTools.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svx/strings.hrc> + +#include <strings.hrc> +#include <svx/xfillit0.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xtable.hxx> +#include <svx/xflbmtit.hxx> +#include <cuitabarea.hxx> +#include <svx/svxdlg.hxx> +#include <dialmgr.hxx> +#include <sal/log.hxx> + +using namespace com::sun::star; + +/************************************************************************* +|* Preview control for the display of bitmaps +\************************************************************************/ + +class SvxBitmapCtl +{ +private: + Color aPixelColor, aBackgroundColor; + std::array<sal_uInt8,64> const * pBmpArray; + +public: + // Constructor: BitmapCtl for SvxPixelCtl + SvxBitmapCtl() + : pBmpArray(nullptr) + { + } + + // BitmapCtl: Returns the Bitmap + BitmapEx GetBitmapEx() const + { + if (!pBmpArray) + return BitmapEx(); + return vcl::bitmap::createHistorical8x8FromArray(*pBmpArray, aPixelColor, aBackgroundColor); + } + + void SetBmpArray( std::array<sal_uInt8,64> const & pPixel ) { pBmpArray = &pPixel; } + void SetPixelColor( Color aColor ) { aPixelColor = aColor; } + void SetBackgroundColor( Color aColor ) { aBackgroundColor = aColor; } +}; + +SvxPatternTabPage::SvxPatternTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/patterntabpage.ui", "PatternTabPage", rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnPatternListState(nullptr) + , m_pnColorListState(nullptr) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_xCtlPixel(new SvxPixelCtl(this)) + , m_xLbColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_COLOR"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xLbBackgroundColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_BACKGROUND_COLOR"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xPatternLB(new SvxPresetListBox(m_xBuilder->weld_scrolled_window("patternpresetlistwin", true))) + , m_xBtnAdd(m_xBuilder->weld_button("BTN_ADD")) + , m_xBtnModify(m_xBuilder->weld_button("BTN_MODIFY")) + , m_xCtlPixelWin(new weld::CustomWeld(*m_xBuilder, "CTL_PIXEL", *m_xCtlPixel)) + , m_xCtlPreview(new weld::CustomWeld(*m_xBuilder, "CTL_PREVIEW", m_aCtlPreview)) + , m_xPatternLBWin(new weld::CustomWeld(*m_xBuilder, "patternpresetlist", *m_xPatternLB)) +{ + // size of the bitmap display + Size aSize = getDrawPreviewOptimalSize(m_aCtlPreview.GetDrawingArea()->get_ref_device()); + m_xPatternLB->set_size_request(aSize.Width(), aSize.Height()); + m_xCtlPreview->set_size_request(aSize.Width(), aSize.Height()); + + m_xBitmapCtl.reset(new SvxBitmapCtl); + + // this page needs ExchangeSupport + SetExchangeSupport(); + + // setting the output device + m_rXFSet.Put( XFillStyleItem(drawing::FillStyle_BITMAP) ); + m_rXFSet.Put( XFillBitmapItem(OUString(), Graphic()) ); + + m_xBtnAdd->connect_clicked( LINK( this, SvxPatternTabPage, ClickAddHdl_Impl ) ); + m_xBtnModify->connect_clicked( LINK( this, SvxPatternTabPage, ClickModifyHdl_Impl ) ); + + m_xPatternLB->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangePatternHdl_Impl ) ); + m_xPatternLB->SetRenameHdl( LINK( this, SvxPatternTabPage, ClickRenameHdl_Impl ) ); + m_xPatternLB->SetDeleteHdl( LINK( this, SvxPatternTabPage, ClickDeleteHdl_Impl ) ); + m_xLbColor->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangeColorHdl_Impl ) ); + m_xLbBackgroundColor->SetSelectHdl( LINK( this, SvxPatternTabPage, ChangeColorHdl_Impl ) ); + + m_xPatternLB->SetStyle(WB_FLATVALUESET | WB_NO_DIRECTSELECT | WB_TABSTOP); +} + +SvxPatternTabPage::~SvxPatternTabPage() +{ + m_xPatternLBWin.reset(); + m_xCtlPreview.reset(); + m_xCtlPixelWin.reset(); + m_xPatternLB.reset(); + m_xLbBackgroundColor.reset(); + m_xLbColor.reset(); + m_xCtlPixel.reset(); +} + +void SvxPatternTabPage::Construct() +{ + m_xPatternLB->FillPresetListBox( *m_pPatternList ); +} + +void SvxPatternTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( !m_pColorList.is() ) + return; + + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + SvxAreaTabDialog* pArea = (*m_pnColorListState & ChangeType::CHANGED) ? + dynamic_cast<SvxAreaTabDialog*>(GetDialogController()) : nullptr; + if (pArea) + m_pColorList = pArea->GetNewColorList(); + } + + // determining (possibly cutting) the name and + // displaying it in the GroupBox + OUString aString = CuiResId( RID_CUISTR_TABLE ) + ": "; + INetURLObject aURL( m_pPatternList->GetPath() ); + + aURL.Append( m_pPatternList->GetName() ); + SAL_WARN_IF( aURL.GetProtocol() == INetProtocol::NotValid, "cui.tabpages", "invalid URL" ); + + if( aURL.getBase().getLength() > 18 ) + { + aString += OUString::Concat(aURL.getBase().subView( 0, 15 )) + "..."; + } + else + aString += aURL.getBase(); + + XFillBitmapItem aItem( rSet.Get( XATTR_FILLBITMAP ) ); + + if ( aItem.isPattern() ) + { + sal_Int32 nPos = SearchPatternList( aItem.GetName() ); + if ( nPos != -1) + { + sal_uInt16 nId = m_xPatternLB->GetItemId( static_cast<size_t>( nPos ) ); + m_xPatternLB->SelectItem( nId ); + } + } + else + m_xPatternLB->SelectItem( m_xPatternLB->GetItemId( static_cast<size_t>( 0 ) ) ); +} + + +DeactivateRC SvxPatternTabPage::DeactivatePage( SfxItemSet* _pSet) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxPatternTabPage::FillItemSet( SfxItemSet* _rOutAttrs ) +{ + _rOutAttrs->Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + size_t nPos = m_xPatternLB->IsNoSelection() ? VALUESET_ITEM_NOTFOUND : m_xPatternLB->GetSelectItemPos(); + if(VALUESET_ITEM_NOTFOUND != nPos) + { + const XBitmapEntry* pXBitmapEntry = m_pPatternList->GetBitmap( static_cast<sal_uInt16>(nPos) ); + const OUString aString( m_xPatternLB->GetItemText( m_xPatternLB->GetSelectedItemId() ) ); + + _rOutAttrs->Put(XFillBitmapItem(aString, pXBitmapEntry->GetGraphicObject())); + } + else + { + const BitmapEx aBitmapEx(m_xBitmapCtl->GetBitmapEx()); + + _rOutAttrs->Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx))); + } + _rOutAttrs->Put(XFillBmpTileItem(true)); + return true; +} + + +void SvxPatternTabPage::Reset( const SfxItemSet* ) +{ + m_xBitmapCtl->SetPixelColor( m_xLbColor->GetSelectEntryColor() ); + m_xBitmapCtl->SetBackgroundColor( m_xLbBackgroundColor->GetSelectEntryColor() ); + m_xBitmapCtl->SetBmpArray( m_xCtlPixel->GetBitmapPixelPtr() ); + + // get bitmap and display it + const XFillBitmapItem aBmpItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx())); + if(aBmpItem.isPattern()) + { + m_rXFSet.Put( aBmpItem ); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + + ChangePatternHdl_Impl(m_xPatternLB.get()); + + // determine button state + if( m_pPatternList.is() && m_pPatternList->Count() ) + { + m_xBtnAdd->set_sensitive(true); + m_xBtnModify->set_sensitive(true); + } + else + { + m_xBtnModify->set_sensitive(false); + } +} + +std::unique_ptr<SfxTabPage> SvxPatternTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet ) +{ + return std::make_unique<SvxPatternTabPage>(pPage, pController, *rSet); +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ChangePatternHdl_Impl, ValueSet*, void) +{ + std::unique_ptr<GraphicObject> pGraphicObject; + size_t nPos = m_xPatternLB->GetSelectItemPos(); + + if(VALUESET_ITEM_NOTFOUND != nPos) + { + pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap( static_cast<sal_uInt16>(nPos) )->GetGraphicObject())); + } + else + { + if(const XFillStyleItem* pFillStyleItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLSTYLE))) + { + const drawing::FillStyle eXFS(pFillStyleItem->GetValue()); + + const XFillBitmapItem* pBitmapItem; + if((drawing::FillStyle_BITMAP == eXFS) && (pBitmapItem = m_rOutAttrs.GetItemIfSet(GetWhich(XATTR_FILLBITMAP)))) + { + pGraphicObject.reset(new GraphicObject(pBitmapItem->GetGraphicObject())); + } + } + + if(!pGraphicObject) + { + sal_uInt16 nPosition = m_xPatternLB->GetItemId( 0 ); + m_xPatternLB->SelectItem( nPosition ); + if( nPosition != 0 ) + { + pGraphicObject.reset(new GraphicObject(m_pPatternList->GetBitmap(0)->GetGraphicObject())); + } + } + } + + if(!pGraphicObject) + return; + + Color aBackColor; + Color aPixelColor; + bool bIs8x8(vcl::bitmap::isHistorical8x8(pGraphicObject->GetGraphic().GetBitmapEx(), aBackColor, aPixelColor)); + + m_xLbColor->SetNoSelection(); + m_xLbBackgroundColor->SetNoSelection(); + + if(bIs8x8) + { + m_xCtlPixel->SetPaintable( true ); + m_xBtnModify->set_sensitive(true); + m_xBtnAdd->set_sensitive(true); + + // setting the pixel control + + m_xCtlPixel->SetXBitmap(pGraphicObject->GetGraphic().GetBitmapEx()); + + m_xLbColor->SelectEntry( aPixelColor ); + m_xLbBackgroundColor->SelectEntry( aBackColor ); + + // update m_xBitmapCtl, rXFSet and m_aCtlPreview + m_xBitmapCtl->SetPixelColor( aPixelColor ); + m_xBitmapCtl->SetBackgroundColor( aBackColor ); + m_rXFSet.ClearItem(); + m_rXFSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + m_rXFSet.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx()))); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + else + { + m_xCtlPixel->Reset(); + m_xCtlPixel->SetPaintable( false ); + m_xBtnModify->set_sensitive(false); + m_xBtnAdd->set_sensitive(false); + } + + m_xCtlPixel->Invalidate(); +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickAddHdl_Impl, weld::Button&, void) +{ + + OUString aNewName( SvxResId( RID_SVXSTR_PATTERN_UNTITLED ) ); + OUString aDesc( CuiResId( RID_CUISTR_DESC_NEW_PATTERN ) ); + OUString aName; + + tools::Long nCount = m_pPatternList->Count(); + tools::Long j = 1; + bool bValidPatternName = false; + + while( !bValidPatternName ) + { + aName = aNewName + " " + OUString::number( j++ ); + bValidPatternName = (SearchPatternList(aName) == -1); + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + sal_uInt16 nError(1); + + while( pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + + bValidPatternName = (SearchPatternList(aName) == -1); + + if( bValidPatternName ) { + nError = 0; + break; + } + + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + if (xWarnBox->run() != RET_OK) + break; + } + + pDlg.disposeAndClear(); + + if( !nError ) + { + std::unique_ptr<XBitmapEntry> pEntry; + if( m_xCtlPixel->IsEnabled() ) + { + const BitmapEx aBitmapEx(m_xBitmapCtl->GetBitmapEx()); + + pEntry.reset(new XBitmapEntry(Graphic(aBitmapEx), aName)); + } + else // it must be a not existing imported bitmap + { + if(const XFillBitmapItem* pFillBmpItem = m_rOutAttrs.GetItemIfSet(XATTR_FILLBITMAP)) + { + pEntry.reset(new XBitmapEntry(pFillBmpItem->GetGraphicObject(), aName)); + } + else + assert(!"SvxPatternTabPage::ClickAddHdl_Impl(), XBitmapEntry* pEntry == nullptr ?"); + } + + if( pEntry ) + { + m_pPatternList->Insert(std::move(pEntry), nCount); + sal_Int32 nId = m_xPatternLB->GetItemId( nCount - 1 ); + BitmapEx aBitmap = m_pPatternList->GetBitmapForPreview( nCount, m_xPatternLB->GetIconSize() ); + m_xPatternLB->InsertItem( nId + 1, Image(aBitmap), aName ); + m_xPatternLB->SelectItem( nId + 1 ); + m_xPatternLB->Resize(); + + *m_pnPatternListState |= ChangeType::MODIFIED; + + ChangePatternHdl_Impl(m_xPatternLB.get()); + } + } + + // determine button state + if( m_pPatternList->Count() ) + { + m_xBtnModify->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickModifyHdl_Impl, weld::Button&, void) +{ + sal_uInt16 nId = m_xPatternLB->GetSelectedItemId(); + size_t nPos = m_xPatternLB->GetSelectItemPos(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aName( m_pPatternList->GetBitmap( static_cast<sal_uInt16>(nPos) )->GetName() ); + + const BitmapEx aBitmapEx(m_xBitmapCtl->GetBitmapEx()); + + // #i123497# Need to replace the existing entry with a new one (old returned needs to be deleted) + m_pPatternList->Replace(std::make_unique<XBitmapEntry>(Graphic(aBitmapEx), aName), nPos); + + BitmapEx aBitmap = m_pPatternList->GetBitmapForPreview( static_cast<sal_uInt16>( nPos ), m_xPatternLB->GetIconSize() ); + m_xPatternLB->RemoveItem(nId); + m_xPatternLB->InsertItem( nId, Image(aBitmap), aName, static_cast<sal_uInt16>(nPos) ); + m_xPatternLB->SelectItem( nId ); + + *m_pnPatternListState |= ChangeType::MODIFIED; +} + + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickRenameHdl_Impl, SvxPresetListBox*, void) +{ + size_t nPos = m_xPatternLB->GetSelectItemPos(); + sal_Int32 nId = m_xPatternLB->GetSelectedItemId(); + + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + + OUString aDesc(CuiResId(RID_CUISTR_DESC_NEW_PATTERN)); + OUString aName(m_pPatternList->GetBitmap(nPos)->GetName()); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg(pFact->CreateSvxNameDialog(GetFrameWeld(), aName, aDesc)); + + bool bLoop = true; + + while( bLoop && pDlg->Execute() == RET_OK ) + { + pDlg->GetName( aName ); + sal_Int32 nPatternPos = SearchPatternList(aName); + bool bValidPatternName = (nPatternPos == static_cast<sal_Int32>(nPos) ) || (nPatternPos == -1); + + if( bValidPatternName ) + { + bLoop = false; + + m_pPatternList->GetBitmap(nPos)->SetName(aName); + + m_xPatternLB->SetItemText( nId, aName ); + m_xPatternLB->SelectItem( nId ); + + *m_pnPatternListState |= ChangeType::MODIFIED; + } + else + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/queryduplicatedialog.ui")); + std::unique_ptr<weld::MessageDialog> xWarnBox(xBuilder->weld_message_dialog("DuplicateNameDialog")); + xWarnBox->run(); + } + } +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ClickDeleteHdl_Impl, SvxPresetListBox*, void) +{ + sal_uInt16 nId = m_xPatternLB->GetSelectedItemId(); + size_t nPos = m_xPatternLB->GetSelectItemPos(); + + if( nPos != VALUESET_ITEM_NOTFOUND ) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletebitmapdialog.ui")); + std::unique_ptr<weld::MessageDialog> xQueryBox(xBuilder->weld_message_dialog("AskDelBitmapDialog")); + if (xQueryBox->run() == RET_YES) + { + m_pPatternList->Remove(nPos); + m_xPatternLB->RemoveItem( nId ); + nId = m_xPatternLB->GetItemId(0); + m_xPatternLB->SelectItem( nId ); + m_xPatternLB->Resize(); + + m_aCtlPreview.Invalidate(); + m_xCtlPixel->Invalidate(); + + ChangePatternHdl_Impl(m_xPatternLB.get()); + + *m_pnPatternListState |= ChangeType::MODIFIED; + } + } + // determine button state + if( !m_pPatternList->Count() ) + { + m_xBtnModify->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(SvxPatternTabPage, ChangeColorHdl_Impl, ColorListBox&, void) +{ + ChangeColor_Impl(); + m_xPatternLB->SetNoSelection(); +} + +void SvxPatternTabPage::ChangeColor_Impl() +{ + m_xCtlPixel->SetPixelColor( m_xLbColor->GetSelectEntryColor() ); + m_xCtlPixel->SetBackgroundColor( m_xLbBackgroundColor->GetSelectEntryColor() ); + m_xCtlPixel->Invalidate(); + + m_xBitmapCtl->SetPixelColor( m_xLbColor->GetSelectEntryColor() ); + m_xBitmapCtl->SetBackgroundColor( m_xLbBackgroundColor->GetSelectEntryColor() ); + + // get bitmap and display it + m_rXFSet.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx()))); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); +} + +void SvxPatternTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint) +{ + if (pDrawingArea == m_xCtlPixel->GetDrawingArea()) + { + m_xBitmapCtl->SetBmpArray(m_xCtlPixel->GetBitmapPixelPtr()); + + // get bitmap and display it + m_rXFSet.Put(XFillBitmapItem(OUString(), Graphic(m_xBitmapCtl->GetBitmapEx()))); + m_aCtlPreview.SetAttributes( m_aXFillAttr.GetItemSet() ); + m_aCtlPreview.Invalidate(); + } + + m_xPatternLB->SetNoSelection(); +} + +sal_Int32 SvxPatternTabPage::SearchPatternList(std::u16string_view rPatternName) +{ + tools::Long nCount = m_pPatternList->Count(); + bool bValidPatternName = true; + sal_Int32 nPos = -1; + + for(tools::Long i = 0;i < nCount && bValidPatternName;i++) + { + if(rPatternName == m_pPatternList->GetBitmap( i )->GetName()) + { + nPos = i; + bValidPatternName = false; + } + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tpshadow.cxx b/cui/source/tabpages/tpshadow.cxx new file mode 100644 index 000000000..795a57f13 --- /dev/null +++ b/cui/source/tabpages/tpshadow.cxx @@ -0,0 +1,515 @@ +/* -*- 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 . + */ + +#include <svx/colorbox.hxx> +#include <svx/svxids.hrc> +#include <svtools/unitconv.hxx> + +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/sdmetitm.hxx> +#include <svx/sdooitm.hxx> +#include <svx/sdprcitm.hxx> +#include <svx/sdshcitm.hxx> +#include <svx/sdshitm.hxx> +#include <svx/sdshtitm.hxx> +#include <svx/sdsxyitm.hxx> +#include <svx/drawitem.hxx> +#include <svx/xfltrit.hxx> +#include <cuitabarea.hxx> +#include <svx/dlgutil.hxx> +#include <cuitabline.hxx> + +using namespace com::sun::star; + +const WhichRangesContainer SvxShadowTabPage::pShadowRanges(svl::Items< + SDRATTR_SHADOWCOLOR, SDRATTR_SHADOWTRANSPARENCE, + SDRATTR_SHADOWBLUR, SDRATTR_SHADOWBLUR, + SID_ATTR_FILL_SHADOW, SID_ATTR_FILL_SHADOW, + SID_ATTR_SHADOW_BLUR, SID_ATTR_SHADOW_BLUR, + SID_ATTR_SHADOW_TRANSPARENCE, SID_ATTR_SHADOW_YDISTANCE +>); + +SvxShadowTabPage::SvxShadowTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/shadowtabpage.ui", "ShadowTabPage", rInAttrs) + , m_rOutAttrs(rInAttrs) + , m_pnColorListState(nullptr) + , m_nPageType(PageType::Area) + , m_nDlgType(0) + , m_aXFillAttr(rInAttrs.GetPool()) + , m_rXFSet(m_aXFillAttr.GetItemSet()) + , m_aCtlPosition(this) + , m_xTsbShowShadow(m_xBuilder->weld_check_button("TSB_SHOW_SHADOW")) + , m_xGridShadow(m_xBuilder->weld_widget("gridSHADOW")) + , m_xMtrDistance(m_xBuilder->weld_metric_spin_button("MTR_FLD_DISTANCE", FieldUnit::CM)) + , m_xLbShadowColor(new ColorListBox(m_xBuilder->weld_menu_button("LB_SHADOW_COLOR"), + [this]{ return GetDialogController()->getDialog(); })) + , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button("MTR_SHADOW_TRANSPARENT", FieldUnit::PERCENT)) + , m_xLbShadowBlurMetric(m_xBuilder->weld_metric_spin_button("LB_SHADOW_BLUR", FieldUnit::POINT)) + , m_xCtlPosition(new weld::CustomWeld(*m_xBuilder, "CTL_POSITION", m_aCtlPosition)) + , m_xCtlXRectPreview(new weld::CustomWeld(*m_xBuilder, "CTL_COLOR_PREVIEW", m_aCtlXRectPreview)) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + // adjust metric + FieldUnit eFUnit = GetModuleFieldUnit( rInAttrs ); + + switch ( eFUnit ) + { + case FieldUnit::M: + case FieldUnit::KM: + eFUnit = FieldUnit::MM; + break; + default: ;//prevent warning + } + SetFieldUnit( *m_xMtrDistance, eFUnit ); + + // determine PoolUnit + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + DBG_ASSERT( pPool, "Where is the pool?" ); + m_ePoolUnit = pPool->GetMetric( SDRATTR_SHADOWXDIST ); + + // setting the output device + drawing::FillStyle eXFS = drawing::FillStyle_SOLID; + if( m_rOutAttrs.GetItemState( XATTR_FILLSTYLE ) != SfxItemState::DONTCARE ) + { + eXFS = m_rOutAttrs.Get( GetWhich( XATTR_FILLSTYLE ) ).GetValue(); + switch( eXFS ) + { + case drawing::FillStyle_SOLID: + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLCOLOR ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLCOLOR ) ); + } + break; + + case drawing::FillStyle_GRADIENT: + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLGRADIENT ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLGRADIENT ) ); + } + break; + + case drawing::FillStyle_HATCH: + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLHATCH ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLHATCH ) ); + } + break; + + case drawing::FillStyle_BITMAP: + { + if( SfxItemState::DONTCARE != m_rOutAttrs.GetItemState( XATTR_FILLBITMAP ) ) + { + m_rXFSet.Put( m_rOutAttrs.Get( XATTR_FILLBITMAP ) ); + } + } + break; + case drawing::FillStyle_NONE : break; + default: break; + } + } + else + { + m_rXFSet.Put( XFillColorItem( OUString(), COL_LIGHTRED ) ); + } + + if(drawing::FillStyle_NONE == eXFS) + { + // #i96350# + // fallback to solid fillmode when no fill mode is provided to have + // a reasonable shadow preview. The used color will be a set one or + // the default (currently blue8) + eXFS = drawing::FillStyle_SOLID; + } + + m_rXFSet.Put( XFillStyleItem( eXFS ) ); + m_aCtlXRectPreview.SetRectangleAttributes(m_aXFillAttr.GetItemSet()); + + m_xTsbShowShadow->connect_toggled(LINK( this, SvxShadowTabPage, ClickShadowHdl_Impl)); + m_xLbShadowColor->SetSelectHdl( LINK( this, SvxShadowTabPage, SelectShadowHdl_Impl ) ); + Link<weld::MetricSpinButton&,void> aLink = LINK( this, SvxShadowTabPage, ModifyShadowHdl_Impl ); + m_xLbShadowBlurMetric->connect_value_changed(aLink); + m_xMtrTransparent->connect_value_changed(aLink); + m_xMtrDistance->connect_value_changed(aLink); +} + +SvxShadowTabPage::~SvxShadowTabPage() +{ + m_xCtlXRectPreview.reset(); + m_xLbShadowColor.reset(); + m_xCtlPosition.reset(); + m_xLbShadowBlurMetric.reset(); +} + +void SvxShadowTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + const SfxUInt16Item* pPageTypeItem = rSet.GetItem<SfxUInt16Item>(SID_PAGE_TYPE, false); + if (pPageTypeItem) + SetPageType(static_cast<PageType>(pPageTypeItem->GetValue())); + + if( m_nDlgType != 0 ) + return; + + if( !m_pColorList.is() ) + return; + + // ColorList + if( *m_pnColorListState & ChangeType::CHANGED || + *m_pnColorListState & ChangeType::MODIFIED ) + { + if( *m_pnColorListState & ChangeType::CHANGED ) + { + SvxAreaTabDialog* pArea = dynamic_cast<SvxAreaTabDialog*>(GetDialogController()); + if( pArea ) + { + m_pColorList = pArea->GetNewColorList(); + } + else + { + SvxLineTabDialog* pLine = dynamic_cast<SvxLineTabDialog*>(GetDialogController()); + if( pLine ) + m_pColorList = pLine->GetNewColorList(); + } + } + + SfxItemSet rAttribs( rSet ); + // rSet contains shadow attributes too, but we want + // to use it for updating rectangle attributes only, + // so set the shadow to none here + SdrOnOffItem aItem( makeSdrShadowItem( false )); + rAttribs.Put( aItem ); + + m_aCtlXRectPreview.SetRectangleAttributes( rAttribs ); + ModifyShadowHdl_Impl( *m_xMtrTransparent ); + } + m_nPageType = PageType::Shadow; +} + + +DeactivateRC SvxShadowTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + FillItemSet( _pSet ); + + return DeactivateRC::LeavePage; +} + + +bool SvxShadowTabPage::FillItemSet( SfxItemSet* rAttrs ) +{ + bool bModified = false; + + const SfxPoolItem* pOld = nullptr; + + if (m_xTsbShowShadow->get_state_changed_from_saved()) + { + TriState eState = m_xTsbShowShadow->get_state(); + assert(eState != TRISTATE_INDET); + // given how m_xTsbShowShadow is set up and saved in Reset(), + // eState == TRISTATE_INDET would imply + // !IsValueChangedFromSaved() + SdrOnOffItem aItem( makeSdrShadowItem(eState == TRISTATE_TRUE) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOW ); + if ( !pOld || !( *static_cast<const SdrOnOffItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // shadow removal + // a bit intricate inquiry whether there was something changed, + // as the items can't be displayed directly on controls + sal_Int32 nX = 0, nY = 0; + sal_Int32 nXY = GetCoreValue( *m_xMtrDistance, m_ePoolUnit ); + + switch (m_aCtlPosition.GetActualRP()) + { + case RectPoint::LT: nX = nY = -nXY; break; + case RectPoint::MT: nY = -nXY; break; + case RectPoint::RT: nX = nXY; nY = -nXY; break; + case RectPoint::LM: nX = -nXY; break; + case RectPoint::RM: nX = nXY; break; + case RectPoint::LB: nX = -nXY; nY = nXY; break; + case RectPoint::MB: nY = nXY; break; + case RectPoint::RB: nX = nY = nXY; break; + case RectPoint::MM: break; + } + + // If the values of the shadow distances==SfxItemState::DONTCARE and the displayed + // string in the respective MetricField=="", then the comparison of the old + // and the new distance values would return a wrong result because in such a + // case the new distance values would match the default values of the MetricField !!!! + if ( !m_xMtrDistance->get_text().isEmpty() || + m_rOutAttrs.GetItemState( SDRATTR_SHADOWXDIST ) != SfxItemState::DONTCARE || + m_rOutAttrs.GetItemState( SDRATTR_SHADOWYDIST ) != SfxItemState::DONTCARE ) + { + sal_Int32 nOldX = 9876543; // impossible value, so DontCare + sal_Int32 nOldY = 9876543; + if( m_rOutAttrs.GetItemState( SDRATTR_SHADOWXDIST ) != SfxItemState::DONTCARE && + m_rOutAttrs.GetItemState( SDRATTR_SHADOWYDIST ) != SfxItemState::DONTCARE ) + { + nOldX = m_rOutAttrs.Get( SDRATTR_SHADOWXDIST ).GetValue(); + nOldY = m_rOutAttrs.Get( SDRATTR_SHADOWYDIST ).GetValue(); + } + SdrMetricItem aXItem( makeSdrShadowXDistItem(nX) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWXDIST ); + if ( nX != nOldX && + ( !pOld || !( *static_cast<const SdrMetricItem*>(pOld) == aXItem ) ) ) + { + rAttrs->Put( aXItem ); + bModified = true; + } + SdrMetricItem aYItem( makeSdrShadowYDistItem(nY) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWYDIST ); + if ( nY != nOldY && + ( !pOld || !( *static_cast<const SdrMetricItem*>(pOld) == aYItem ) ) ) + { + rAttrs->Put( aYItem ); + bModified = true; + } + } + + // ShadowColor + { + XColorItem aItem(makeSdrShadowColorItem(m_xLbShadowColor->GetSelectEntryColor())); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWCOLOR ); + if ( !pOld || !( *static_cast<const XColorItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + // transparency + sal_uInt16 nVal = static_cast<sal_uInt16>(m_xMtrTransparent->get_value(FieldUnit::PERCENT)); + if (m_xMtrTransparent->get_value_changed_from_saved()) + { + SdrPercentItem aItem( makeSdrShadowTransparenceItem(nVal) ); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWTRANSPARENCE ); + if ( !pOld || !( *static_cast<const SdrPercentItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + if (m_xLbShadowBlurMetric->get_value_changed_from_saved()) + { + SdrMetricItem aItem(SDRATTR_SHADOWBLUR, m_xLbShadowBlurMetric->get_value(FieldUnit::MM_100TH)); + pOld = GetOldItem( *rAttrs, SDRATTR_SHADOWBLUR ); + if ( !pOld || !( *static_cast<const SdrMetricItem*>(pOld) == aItem ) ) + { + rAttrs->Put( aItem ); + bModified = true; + } + } + + rAttrs->Put (CntUInt16Item(SID_PAGE_TYPE, static_cast<sal_uInt16>(m_nPageType))); + + return bModified; +} + + +void SvxShadowTabPage::Reset( const SfxItemSet* rAttrs ) +{ + // all objects can have a shadow + // at the moment there are only 8 possible positions where a shadow can be set + + // has a shadow been set? + if( rAttrs->GetItemState( SDRATTR_SHADOW ) != SfxItemState::DONTCARE ) + { + if( rAttrs->Get( SDRATTR_SHADOW ).GetValue() ) + m_xTsbShowShadow->set_state(TRISTATE_TRUE); + else + { + m_xTsbShowShadow->set_state(TRISTATE_FALSE); + } + } + else + m_xTsbShowShadow->set_state(TRISTATE_INDET); + + // distance (only 8 possible positions), + // so there is only one item evaluated + + if( rAttrs->GetItemState( SDRATTR_SHADOWXDIST ) != SfxItemState::DONTCARE && + rAttrs->GetItemState( SDRATTR_SHADOWYDIST ) != SfxItemState::DONTCARE ) + { + sal_Int32 nX = rAttrs->Get( SDRATTR_SHADOWXDIST ).GetValue(); + sal_Int32 nY = rAttrs->Get( SDRATTR_SHADOWYDIST ).GetValue(); + + if( nX != 0 ) + SetMetricValue( *m_xMtrDistance, nX < 0 ? -nX : nX, m_ePoolUnit ); + else + SetMetricValue( *m_xMtrDistance, nY < 0 ? -nY : nY, m_ePoolUnit ); + + // setting the shadow control + if ( nX < 0 && nY < 0 ) m_aCtlPosition.SetActualRP( RectPoint::LT ); + else if( nX == 0 && nY < 0 ) m_aCtlPosition.SetActualRP( RectPoint::MT ); + else if( nX > 0 && nY < 0 ) m_aCtlPosition.SetActualRP( RectPoint::RT ); + else if( nX < 0 && nY == 0 ) m_aCtlPosition.SetActualRP( RectPoint::LM ); + // there's no center point anymore + else if( nX == 0 && nY == 0 ) m_aCtlPosition.SetActualRP( RectPoint::RB ); + else if( nX > 0 && nY == 0 ) m_aCtlPosition.SetActualRP( RectPoint::RM ); + else if( nX < 0 && nY > 0 ) m_aCtlPosition.SetActualRP( RectPoint::LB ); + else if( nX == 0 && nY > 0 ) m_aCtlPosition.SetActualRP( RectPoint::MB ); + else if( nX > 0 && nY > 0 ) m_aCtlPosition.SetActualRP( RectPoint::RB ); + } + else + { + // determine default-distance + SfxItemPool* pPool = m_rOutAttrs.GetPool(); + { + sal_Int32 n = pPool->GetDefaultItem(SDRATTR_SHADOWXDIST).GetValue(); + if (n == 0) + n = pPool->GetDefaultItem(SDRATTR_SHADOWYDIST).GetValue(); + SetMetricValue(*m_xMtrDistance, std::abs(n), m_ePoolUnit); + } + + // Tristate, e. g. multiple objects have been marked of which some have a shadow and some don't. + // The text (which shall be displayed) of the MetricFields is set to "" and serves as an + // identification in the method FillItemSet for the fact that the distance value was NOT changed !!!! + m_xMtrDistance->set_text( "" ); + m_aCtlPosition.SetActualRP( RectPoint::MM ); + } + + if( rAttrs->GetItemState( SDRATTR_SHADOWCOLOR ) != SfxItemState::DONTCARE ) + { + m_xLbShadowColor->SelectEntry( rAttrs->Get( SDRATTR_SHADOWCOLOR ).GetColorValue() ); + } + else + m_xLbShadowColor->SetNoSelection(); + + if( rAttrs->GetItemState( SDRATTR_SHADOWTRANSPARENCE ) != SfxItemState::DONTCARE ) + { + sal_uInt16 nTransp = rAttrs->Get( SDRATTR_SHADOWTRANSPARENCE ).GetValue(); + m_xMtrTransparent->set_value(nTransp, FieldUnit::PERCENT); + } + else + m_xMtrTransparent->set_text(""); + + if( rAttrs->GetItemState( SDRATTR_SHADOWBLUR ) != SfxItemState::DONTCARE ) + { + sal_uInt16 nBlur = rAttrs->Get( SDRATTR_SHADOWBLUR ).GetValue(); + m_xLbShadowBlurMetric->set_value(nBlur, FieldUnit::MM_100TH); + } + else + m_xLbShadowBlurMetric->set_text(""); + + //aCtlPosition + m_xMtrDistance->save_value(); + m_xLbShadowColor->SaveValue(); + m_xTsbShowShadow->save_state(); + m_xLbShadowBlurMetric->save_value(); + + // #66832# This field was not saved, but used to determine changes. + // Why? Seems to be the error. + // It IS the error. + m_xMtrTransparent->save_value(); + + ClickShadowHdl_Impl(*m_xTsbShowShadow); + ModifyShadowHdl_Impl(*m_xMtrTransparent); +} + +std::unique_ptr<SfxTabPage> SvxShadowTabPage::Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrs ) +{ + return std::make_unique<SvxShadowTabPage>(pPage, pController, *rAttrs); +} + +IMPL_LINK_NOARG(SvxShadowTabPage, ClickShadowHdl_Impl, weld::Toggleable&, void) +{ + if (m_xTsbShowShadow->get_state() == TRISTATE_FALSE) + { + m_xGridShadow->set_sensitive(false); + m_xCtlPosition->set_sensitive(false); + } + else + { + m_xGridShadow->set_sensitive(true); + m_xCtlPosition->set_sensitive(true); + } + m_aCtlPosition.Invalidate(); + ModifyShadowHdl_Impl(*m_xMtrTransparent); +} + +IMPL_LINK_NOARG(SvxShadowTabPage, SelectShadowHdl_Impl, ColorListBox&, void) +{ + ModifyShadowHdl_Impl(*m_xMtrTransparent); +} + +IMPL_LINK_NOARG(SvxShadowTabPage, ModifyShadowHdl_Impl, weld::MetricSpinButton&, void) +{ + if (m_xTsbShowShadow->get_state() == TRISTATE_TRUE) + m_rXFSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + else + m_rXFSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + + m_rXFSet.Put( XFillColorItem( OUString(), m_xLbShadowColor->GetSelectEntryColor() ) ); + sal_uInt16 nVal = static_cast<sal_uInt16>(m_xMtrTransparent->get_value(FieldUnit::PERCENT)); + m_rXFSet.Put( XFillTransparenceItem( nVal ) ); + + // shadow removal + sal_Int32 nX = 0, nY = 0; + sal_Int32 nXY = GetCoreValue( *m_xMtrDistance, m_ePoolUnit ); + switch( m_aCtlPosition.GetActualRP() ) + { + case RectPoint::LT: nX = nY = -nXY; break; + case RectPoint::MT: nY = -nXY; break; + case RectPoint::RT: nX = nXY; nY = -nXY; break; + case RectPoint::LM: nX = -nXY; break; + case RectPoint::RM: nX = nXY; break; + case RectPoint::LB: nX = -nXY; nY = nXY; break; + case RectPoint::MB: nY = nXY; break; + case RectPoint::RB: nX = nY = nXY; break; + case RectPoint::MM: break; + } + + m_aCtlXRectPreview.SetShadowPosition(Point(nX, nY)); + + m_aCtlXRectPreview.SetShadowAttributes(m_aXFillAttr.GetItemSet()); + m_aCtlXRectPreview.Invalidate(); +} + +void SvxShadowTabPage::PointChanged( weld::DrawingArea*, RectPoint ) +{ + // repaint shadow + ModifyShadowHdl_Impl( *m_xMtrTransparent ); +} + +void SvxShadowTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SvxColorListItem* pColorListItem = aSet.GetItem<SvxColorListItem>(SID_COLOR_TABLE, false); + const SfxUInt16Item* pPageTypeItem = aSet.GetItem<SfxUInt16Item>(SID_PAGE_TYPE, false); + const SfxUInt16Item* pDlgTypeItem = aSet.GetItem<SfxUInt16Item>(SID_DLG_TYPE, false); + + if (pColorListItem) + SetColorList(pColorListItem->GetColorList()); + if (pPageTypeItem) + SetPageType(static_cast<PageType>(pPageTypeItem->GetValue())); + if (pDlgTypeItem) + SetDlgType(pDlgTypeItem->GetValue()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/tptrans.cxx b/cui/source/tabpages/tptrans.cxx new file mode 100644 index 000000000..75180022f --- /dev/null +++ b/cui/source/tabpages/tptrans.cxx @@ -0,0 +1,519 @@ +/* -*- 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 . + */ + +#include <svx/svxids.hrc> + +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflbckit.hxx> +#include <svx/sdshtitm.hxx> +#include <svx/xfltrit.hxx> +#include <cuitabarea.hxx> +#include <svl/intitem.hxx> + +using namespace com::sun::star; + +const WhichRangesContainer SvxTransparenceTabPage::pTransparenceRanges(svl::Items< + XATTR_FILLTRANSPARENCE, XATTR_FILLTRANSPARENCE, + XATTR_FILLFLOATTRANSPARENCE, XATTR_FILLFLOATTRANSPARENCE, + SDRATTR_SHADOWTRANSPARENCE, SDRATTR_SHADOWTRANSPARENCE +>); + +/************************************************************************* +|* +|* Dialog for transparence +|* +\************************************************************************/ + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ClickTransOffHdl_Impl, weld::Toggleable&, void) +{ + // disable all other controls + ActivateLinear(false); + ActivateGradient(false); + + // Preview + rXFSet.ClearItem(XATTR_FILLTRANSPARENCE); + rXFSet.ClearItem(XATTR_FILLFLOATTRANSPARENCE); + m_aCtlXRectPreview.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() ); + + InvalidatePreview(false); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ClickTransLinearHdl_Impl, weld::Toggleable&, void) +{ + // enable linear, disable other + ActivateLinear(true); + ActivateGradient(false); + + // preview + rXFSet.ClearItem (XATTR_FILLFLOATTRANSPARENCE); + ModifyTransparentHdl_Impl(*m_xMtrTransparent); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ClickTransGradientHdl_Impl, weld::Toggleable&, void) +{ + // enable gradient, disable other + ActivateLinear(false); + ActivateGradient(true); + + // preview + rXFSet.ClearItem (XATTR_FILLTRANSPARENCE); + ModifiedTrgrHdl_Impl(nullptr); +} + +SvxTransparenceTabPage::~SvxTransparenceTabPage() +{ +} + +void SvxTransparenceTabPage::ActivateLinear(bool bActivate) +{ + m_xMtrTransparent->set_sensitive(bActivate); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ModifyTransparentHdl_Impl, weld::MetricSpinButton&, void) +{ + sal_uInt16 nPos = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + rXFSet.Put(XFillTransparenceItem(nPos)); + + // preview + InvalidatePreview(); +} + +IMPL_LINK(SvxTransparenceTabPage, ModifiedTrgrListBoxHdl_Impl, weld::ComboBox&, rListBox, void) +{ + ModifiedTrgrHdl_Impl(&rListBox); +} + +IMPL_LINK_NOARG(SvxTransparenceTabPage, ModifiedTrgrEditHdl_Impl, weld::MetricSpinButton&, void) +{ + ModifiedTrgrHdl_Impl(nullptr); +} + +void SvxTransparenceTabPage::ModifiedTrgrHdl_Impl(const weld::ComboBox* pControl) +{ + if (pControl == m_xLbTrgrGradientType.get()) + { + css::awt::GradientStyle eXGS = static_cast<css::awt::GradientStyle>(m_xLbTrgrGradientType->get_active()); + SetControlState_Impl( eXGS ); + } + + // preview + sal_uInt8 nStartCol = static_cast<sal_uInt8>((static_cast<sal_uInt16>(m_xMtrTrgrStartValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + sal_uInt8 nEndCol = static_cast<sal_uInt8>((static_cast<sal_uInt16>(m_xMtrTrgrEndValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + XGradient aTmpGradient( + Color(nStartCol, nStartCol, nStartCol), + Color(nEndCol, nEndCol, nEndCol), + static_cast<css::awt::GradientStyle>(m_xLbTrgrGradientType->get_active()), + Degree10(static_cast<sal_Int16>(m_xMtrTrgrAngle->get_value(FieldUnit::DEGREE)) * 10), + static_cast<sal_uInt16>(m_xMtrTrgrCenterX->get_value(FieldUnit::PERCENT)), + static_cast<sal_uInt16>(m_xMtrTrgrCenterY->get_value(FieldUnit::PERCENT)), + static_cast<sal_uInt16>(m_xMtrTrgrBorder->get_value(FieldUnit::PERCENT)), + 100, 100); + + XFillFloatTransparenceItem aItem( aTmpGradient); + rXFSet.Put ( aItem ); + + InvalidatePreview(); +} + +void SvxTransparenceTabPage::ActivateGradient(bool bActivate) +{ + m_xGridGradient->set_sensitive(bActivate); + + if (bActivate) + { + css::awt::GradientStyle eXGS = static_cast<css::awt::GradientStyle>(m_xLbTrgrGradientType->get_active()); + SetControlState_Impl( eXGS ); + } +} + +void SvxTransparenceTabPage::SetControlState_Impl(css::awt::GradientStyle eXGS) +{ + switch(eXGS) + { + case css::awt::GradientStyle_LINEAR: + case css::awt::GradientStyle_AXIAL: + m_xFtTrgrCenterX->set_sensitive(false); + m_xMtrTrgrCenterX->set_sensitive(false); + m_xFtTrgrCenterY->set_sensitive(false); + m_xMtrTrgrCenterY->set_sensitive(false); + m_xFtTrgrAngle->set_sensitive(true); + m_xMtrTrgrAngle->set_sensitive(true); + break; + + case css::awt::GradientStyle_RADIAL: + m_xFtTrgrCenterX->set_sensitive(true); + m_xMtrTrgrCenterX->set_sensitive(true); + m_xFtTrgrCenterY->set_sensitive(true); + m_xMtrTrgrCenterY->set_sensitive(true); + m_xFtTrgrAngle->set_sensitive(false); + m_xMtrTrgrAngle->set_sensitive(false); + break; + + case css::awt::GradientStyle_ELLIPTICAL: + case css::awt::GradientStyle_SQUARE: + case css::awt::GradientStyle_RECT: + m_xFtTrgrCenterX->set_sensitive(true); + m_xMtrTrgrCenterX->set_sensitive(true); + m_xFtTrgrCenterY->set_sensitive(true); + m_xMtrTrgrCenterY->set_sensitive(true); + m_xFtTrgrAngle->set_sensitive(true); + m_xMtrTrgrAngle->set_sensitive(true); + break; + default: + break; + } +} + +SvxTransparenceTabPage::SvxTransparenceTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/transparencytabpage.ui", "TransparencyTabPage", &rInAttrs) + , rOutAttrs(rInAttrs) + , nPageType(PageType::Area) + , nDlgType(0) + , bBitmap(false) + , aXFillAttr(rInAttrs.GetPool()) + , rXFSet(aXFillAttr.GetItemSet()) + , m_xRbtTransOff(m_xBuilder->weld_radio_button("RBT_TRANS_OFF")) + , m_xRbtTransLinear(m_xBuilder->weld_radio_button("RBT_TRANS_LINEAR")) + , m_xRbtTransGradient(m_xBuilder->weld_radio_button("RBT_TRANS_GRADIENT")) + , m_xMtrTransparent(m_xBuilder->weld_metric_spin_button("MTR_TRANSPARENT", FieldUnit::PERCENT)) + , m_xGridGradient(m_xBuilder->weld_widget("gridGradient")) + , m_xLbTrgrGradientType(m_xBuilder->weld_combo_box("LB_TRGR_GRADIENT_TYPES")) + , m_xFtTrgrCenterX(m_xBuilder->weld_label("FT_TRGR_CENTER_X")) + , m_xMtrTrgrCenterX(m_xBuilder->weld_metric_spin_button("MTR_TRGR_CENTER_X", FieldUnit::PERCENT)) + , m_xFtTrgrCenterY(m_xBuilder->weld_label("FT_TRGR_CENTER_Y")) + , m_xMtrTrgrCenterY(m_xBuilder->weld_metric_spin_button("MTR_TRGR_CENTER_Y", FieldUnit::PERCENT)) + , m_xFtTrgrAngle(m_xBuilder->weld_label("FT_TRGR_ANGLE")) + , m_xMtrTrgrAngle(m_xBuilder->weld_metric_spin_button("MTR_TRGR_ANGLE", FieldUnit::DEGREE)) + , m_xMtrTrgrBorder(m_xBuilder->weld_metric_spin_button("MTR_TRGR_BORDER", FieldUnit::PERCENT)) + , m_xMtrTrgrStartValue(m_xBuilder->weld_metric_spin_button("MTR_TRGR_START_VALUE", FieldUnit::PERCENT)) + , m_xMtrTrgrEndValue(m_xBuilder->weld_metric_spin_button("MTR_TRGR_END_VALUE", FieldUnit::PERCENT)) + , m_xCtlBitmapBorder(m_xBuilder->weld_widget("bitmap_border")) + , m_xCtlXRectBorder(m_xBuilder->weld_widget("trans_border")) + , m_xCtlBitmapPreview(new weld::CustomWeld(*m_xBuilder, "CTL_IMAGE_PREVIEW", m_aCtlBitmapPreview)) + , m_xCtlXRectPreview(new weld::CustomWeld(*m_xBuilder, "CTL_TRANS_PREVIEW", m_aCtlXRectPreview)) +{ + // main selection + m_xRbtTransOff->connect_toggled(LINK(this, SvxTransparenceTabPage, ClickTransOffHdl_Impl)); + m_xRbtTransLinear->connect_toggled(LINK(this, SvxTransparenceTabPage, ClickTransLinearHdl_Impl)); + m_xRbtTransGradient->connect_toggled(LINK(this, SvxTransparenceTabPage, ClickTransGradientHdl_Impl)); + + // linear transparency + m_xMtrTransparent->set_value(50, FieldUnit::PERCENT); + m_xMtrTransparent->connect_value_changed(LINK(this, SvxTransparenceTabPage, ModifyTransparentHdl_Impl)); + + // gradient transparency + m_xMtrTrgrEndValue->set_value(100, FieldUnit::PERCENT); + m_xMtrTrgrStartValue->set_value(0, FieldUnit::PERCENT); + Link<weld::MetricSpinButton&,void> aLink = LINK( this, SvxTransparenceTabPage, ModifiedTrgrEditHdl_Impl); + m_xLbTrgrGradientType->connect_changed(LINK(this, SvxTransparenceTabPage, ModifiedTrgrListBoxHdl_Impl)); + m_xMtrTrgrCenterX->connect_value_changed( aLink ); + m_xMtrTrgrCenterY->connect_value_changed( aLink ); + m_xMtrTrgrAngle->connect_value_changed( aLink ); + m_xMtrTrgrBorder->connect_value_changed( aLink ); + m_xMtrTrgrStartValue->connect_value_changed( aLink ); + m_xMtrTrgrEndValue->connect_value_changed( aLink ); + + // this page needs ExchangeSupport + SetExchangeSupport(); +} + +std::unique_ptr<SfxTabPage> SvxTransparenceTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique<SvxTransparenceTabPage>(pPage, pController, *rAttrs); +} + +bool SvxTransparenceTabPage::FillItemSet(SfxItemSet* rAttrs) +{ + const SfxPoolItem* pGradientItem = nullptr; + const SfxPoolItem* pLinearItem = nullptr; + SfxItemState eStateGradient(rOutAttrs.GetItemState(XATTR_FILLFLOATTRANSPARENCE, true, &pGradientItem)); + SfxItemState eStateLinear(rOutAttrs.GetItemState(XATTR_FILLTRANSPARENCE, true, &pLinearItem)); + bool bGradActive = (eStateGradient == SfxItemState::SET && static_cast<const XFillFloatTransparenceItem*>(pGradientItem)->IsEnabled()); + bool bLinearActive = (eStateLinear == SfxItemState::SET && static_cast<const XFillTransparenceItem*>(pLinearItem)->GetValue() != 0); + + bool bGradUsed = (eStateGradient == SfxItemState::DONTCARE); + bool bLinearUsed = (eStateLinear == SfxItemState::DONTCARE); + + bool bModified(false); + bool bSwitchOffLinear(false); + bool bSwitchOffGradient(false); + + if (m_xMtrTransparent->get_sensitive()) + { + // linear transparence + sal_uInt16 nPos = m_xMtrTransparent->get_value(FieldUnit::PERCENT); + if (m_xMtrTransparent->get_value_changed_from_saved() || !bLinearActive) + { + XFillTransparenceItem aItem(nPos); + SdrPercentItem aShadowItem(makeSdrShadowTransparenceItem(nPos)); + const SfxPoolItem* pOld = GetOldItem(*rAttrs, XATTR_FILLTRANSPARENCE); + if(!pOld || !(*static_cast<const XFillTransparenceItem*>(pOld) == aItem) || !bLinearActive) + { + rAttrs->Put(aItem); + rAttrs->Put(aShadowItem); + bModified = true; + bSwitchOffGradient = true; + } + } + } + else if (m_xGridGradient->get_sensitive()) + { + // transparence gradient, fill ItemSet from values + if (!bGradActive + || m_xLbTrgrGradientType->get_value_changed_from_saved() + || m_xMtrTrgrAngle->get_value_changed_from_saved() + || m_xMtrTrgrCenterX->get_value_changed_from_saved() + || m_xMtrTrgrCenterY->get_value_changed_from_saved() + || m_xMtrTrgrBorder->get_value_changed_from_saved() + || m_xMtrTrgrStartValue->get_value_changed_from_saved() + || m_xMtrTrgrEndValue->get_value_changed_from_saved()) + { + sal_uInt8 nStartCol = static_cast<sal_uInt8>((static_cast<sal_uInt16>(m_xMtrTrgrStartValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + sal_uInt8 nEndCol = static_cast<sal_uInt8>((static_cast<sal_uInt16>(m_xMtrTrgrEndValue->get_value(FieldUnit::PERCENT)) * 255) / 100); + XGradient aTmpGradient( + Color(nStartCol, nStartCol, nStartCol), + Color(nEndCol, nEndCol, nEndCol), + static_cast<css::awt::GradientStyle>(m_xLbTrgrGradientType->get_active()), + Degree10(static_cast<sal_Int16>(m_xMtrTrgrAngle->get_value(FieldUnit::DEGREE)) * 10), + static_cast<sal_uInt16>(m_xMtrTrgrCenterX->get_value(FieldUnit::PERCENT)), + static_cast<sal_uInt16>(m_xMtrTrgrCenterY->get_value(FieldUnit::PERCENT)), + static_cast<sal_uInt16>(m_xMtrTrgrBorder->get_value(FieldUnit::PERCENT)), + 100, 100); + + XFillFloatTransparenceItem aItem(aTmpGradient); + const SfxPoolItem* pOld = GetOldItem(*rAttrs, XATTR_FILLFLOATTRANSPARENCE); + + if(!pOld || !(*static_cast<const XFillFloatTransparenceItem*>(pOld) == aItem) || !bGradActive) + { + rAttrs->Put(aItem); + bModified = true; + bSwitchOffLinear = true; + } + } + } + else + { + // no transparence + bSwitchOffGradient = true; + bSwitchOffLinear = true; + } + + // disable unused XFillFloatTransparenceItem + if(bSwitchOffGradient && (bGradActive || bGradUsed)) + { + XGradient aGrad(COL_BLACK, COL_WHITE); + aGrad.SetStartIntens(100); + aGrad.SetEndIntens(100); + XFillFloatTransparenceItem aItem(aGrad); + aItem.SetEnabled(false); + rAttrs->Put(aItem); + bModified = true; + } + + // disable unused XFillFloatTransparenceItem + if(bSwitchOffLinear && (bLinearActive || bLinearUsed)) + { + XFillTransparenceItem aItem(0); + SdrPercentItem aShadowItem(makeSdrShadowTransparenceItem(0)); + rAttrs->Put(aItem); + rAttrs->Put(aShadowItem); + bModified = true; + } + rAttrs->Put(CntUInt16Item(SID_PAGE_TYPE, static_cast<sal_uInt16>(nPageType))); + return bModified; +} + +void SvxTransparenceTabPage::Reset(const SfxItemSet* rAttrs) +{ + const XFillFloatTransparenceItem* pGradientItem = + rAttrs->GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE); + bool bGradActive = (pGradientItem && pGradientItem->IsEnabled()); + if(!pGradientItem) + pGradientItem = &rAttrs->Get(XATTR_FILLFLOATTRANSPARENCE); + + const XFillTransparenceItem* pLinearItem = + rAttrs->GetItemIfSet(XATTR_FILLTRANSPARENCE); + bool bLinearActive = (pLinearItem && pLinearItem->GetValue() != 0); + if(!pLinearItem) + pLinearItem = &rAttrs->Get(XATTR_FILLTRANSPARENCE); + + // transparence gradient + const XGradient& rGradient = pGradientItem->GetGradientValue(); + css::awt::GradientStyle eXGS(rGradient.GetGradientStyle()); + m_xLbTrgrGradientType->set_active(sal::static_int_cast< sal_Int32 >(eXGS)); + m_xMtrTrgrAngle->set_value(rGradient.GetAngle().get() / 10, FieldUnit::DEGREE); + m_xMtrTrgrBorder->set_value(rGradient.GetBorder(), FieldUnit::PERCENT); + m_xMtrTrgrCenterX->set_value(rGradient.GetXOffset(), FieldUnit::PERCENT); + m_xMtrTrgrCenterY->set_value(rGradient.GetYOffset(), FieldUnit::PERCENT); + m_xMtrTrgrStartValue->set_value(static_cast<sal_uInt16>(((static_cast<sal_uInt16>(rGradient.GetStartColor().GetRed()) + 1) * 100) / 255), FieldUnit::PERCENT); + m_xMtrTrgrEndValue->set_value(static_cast<sal_uInt16>(((static_cast<sal_uInt16>(rGradient.GetEndColor().GetRed()) + 1) * 100) / 255), FieldUnit::PERCENT); + + // linear transparence + sal_uInt16 nTransp = pLinearItem->GetValue(); + m_xMtrTransparent->set_value(bLinearActive ? nTransp : 50, FieldUnit::PERCENT); + ModifyTransparentHdl_Impl(*m_xMtrTransparent); + + // select the correct radio button + if(bGradActive) + { + // transparence gradient, set controls appropriate to item + m_xRbtTransGradient->set_active(true); + ClickTransGradientHdl_Impl(*m_xRbtTransGradient); + } + else if(bLinearActive) + { + // linear transparence + m_xRbtTransLinear->set_active(true); + ClickTransLinearHdl_Impl(*m_xRbtTransLinear); + } + else + { + // no transparence + m_xRbtTransOff->set_active(true); + ClickTransOffHdl_Impl(*m_xRbtTransOff); + ModifiedTrgrHdl_Impl(nullptr); + } + + // save values + ChangesApplied(); + bool bActive = InitPreview ( *rAttrs ); + InvalidatePreview ( bActive ); +} + +void SvxTransparenceTabPage::ChangesApplied() +{ + m_xMtrTransparent->save_value(); + m_xLbTrgrGradientType->save_value(); + m_xMtrTrgrCenterX->save_value(); + m_xMtrTrgrCenterY->save_value(); + m_xMtrTrgrAngle->save_value(); + m_xMtrTrgrBorder->save_value(); + m_xMtrTrgrStartValue->save_value(); + m_xMtrTrgrEndValue->save_value(); +} + +void SvxTransparenceTabPage::ActivatePage(const SfxItemSet& rSet) +{ + const CntUInt16Item* pPageTypeItem = rSet.GetItem<CntUInt16Item>(SID_PAGE_TYPE, false); + if (pPageTypeItem) + SetPageType(static_cast<PageType>(pPageTypeItem->GetValue())); + + if(nDlgType == 0) // area dialog + nPageType = PageType::Transparence; + + InitPreview ( rSet ); +} + +DeactivateRC SvxTransparenceTabPage::DeactivatePage(SfxItemSet* _pSet) +{ + if( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +// Preview-Methods + +bool SvxTransparenceTabPage::InitPreview(const SfxItemSet& rSet) +{ + // set transparencetype for preview + if (m_xRbtTransOff->get_active()) + { + ClickTransOffHdl_Impl(*m_xRbtTransOff); + } + else if (m_xRbtTransLinear->get_active()) + { + ClickTransLinearHdl_Impl(*m_xRbtTransLinear); + } + else if (m_xRbtTransGradient->get_active()) + { + ClickTransGradientHdl_Impl(*m_xRbtTransGradient); + } + + // Get fillstyle for preview + rXFSet.Put ( rSet.Get(XATTR_FILLSTYLE) ); + rXFSet.Put ( rSet.Get(XATTR_FILLCOLOR) ); + rXFSet.Put ( rSet.Get(XATTR_FILLGRADIENT) ); + rXFSet.Put ( rSet.Get(XATTR_FILLHATCH) ); + rXFSet.Put ( rSet.Get(XATTR_FILLBACKGROUND) ); + rXFSet.Put ( rSet.Get(XATTR_FILLBITMAP) ); + + m_aCtlXRectPreview.SetAttributes( aXFillAttr.GetItemSet() ); + m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() ); + + bBitmap = rSet.Get(XATTR_FILLSTYLE).GetValue() == drawing::FillStyle_BITMAP; + + // show the right preview window + if ( bBitmap ) + { + m_xCtlBitmapBorder->show(); + m_xCtlXRectBorder->hide(); + } + else + { + m_xCtlBitmapBorder->hide(); + m_xCtlXRectBorder->show(); + } + + return !m_xRbtTransOff->get_active(); +} + +void SvxTransparenceTabPage::InvalidatePreview (bool bEnable) +{ + if ( bBitmap ) + { + if ( bEnable ) + { + m_xCtlBitmapPreview->set_sensitive(true); + m_aCtlBitmapPreview.SetAttributes( aXFillAttr.GetItemSet() ); + } + else + m_xCtlBitmapPreview->set_sensitive(false); + m_xCtlBitmapPreview->queue_draw(); + } + else + { + if ( bEnable ) + { + m_xCtlXRectPreview->set_sensitive(true); + m_aCtlXRectPreview.SetAttributes( aXFillAttr.GetItemSet() ); + } + else + m_xCtlXRectPreview->set_sensitive(false); + m_xCtlXRectPreview->queue_draw(); + } +} + +void SvxTransparenceTabPage::PageCreated(const SfxAllItemSet& aSet) +{ + const SfxUInt16Item* pPageTypeItem = aSet.GetItem<SfxUInt16Item>(SID_PAGE_TYPE, false); + const SfxUInt16Item* pDlgTypeItem = aSet.GetItem<SfxUInt16Item>(SID_DLG_TYPE, false); + + if (pPageTypeItem) + SetPageType(static_cast<PageType>(pPageTypeItem->GetValue())); + if (pDlgTypeItem) + SetDlgType(pDlgTypeItem->GetValue()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/tabpages/transfrm.cxx b/cui/source/tabpages/transfrm.cxx new file mode 100644 index 000000000..c9fd14095 --- /dev/null +++ b/cui/source/tabpages/transfrm.cxx @@ -0,0 +1,1562 @@ +/* -*- 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 . + */ + +#include <sal/config.h> + +#include <algorithm> + +#include <svx/EnhancedCustomShape2d.hxx> +#include <svx/sdangitm.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdview.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdoashp.hxx> +#include <svx/sderitm.hxx> +#include <svx/svxids.hrc> +#include <svx/transfrmhelper.hxx> +#include <svtools/unitconv.hxx> + +#include <transfrm.hxx> +#include <svx/dlgutil.hxx> +#include <svx/anchorid.hxx> +#include <svl/rectitem.hxx> +#include <swpossizetabpage.hxx> +#include <vcl/canvastools.hxx> +#include <vcl/fieldvalues.hxx> + +// static ---------------------------------------------------------------- + +const WhichRangesContainer SvxPositionSizeTabPage::pPosSizeRanges(svl::Items< + SID_ATTR_TRANSFORM_POS_X, SID_ATTR_TRANSFORM_POS_Y, + SID_ATTR_TRANSFORM_WIDTH, SID_ATTR_TRANSFORM_SIZE_POINT, + SID_ATTR_TRANSFORM_PROTECT_POS, SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_AUTOWIDTH, SID_ATTR_TRANSFORM_AUTOHEIGHT, + SID_ATTR_TRANSFORM_ANCHOR, SID_ATTR_TRANSFORM_VERT_ORIENT +>); + +const WhichRangesContainer SvxAngleTabPage::pAngleRanges(svl::Items< + SID_ATTR_TRANSFORM_ROT_X, SID_ATTR_TRANSFORM_ANGLE, + SID_ATTR_TRANSFORM_INTERN, SID_ATTR_TRANSFORM_INTERN +>); + +const WhichRangesContainer SvxSlantTabPage::pSlantRanges(svl::Items< + SDRATTR_CORNER_RADIUS, SDRATTR_CORNER_RADIUS, + SID_ATTR_TRANSFORM_INTERN, SID_ATTR_TRANSFORM_INTERN, + SID_ATTR_TRANSFORM_SHEAR, SID_ATTR_TRANSFORM_SHEAR_VERTICAL +>); + +/************************************************************************* +|* +|* constructor of the tab dialog: adds the pages to the dialog +|* +\************************************************************************/ + +SvxTransformTabDialog::SvxTransformTabDialog(weld::Window* pParent, const SfxItemSet* pAttr, + const SdrView* pSdrView, SvxAnchorIds nAnchorTypes) + : SfxTabDialogController(pParent, "cui/ui/positionsizedialog.ui", "PositionAndSizeDialog", pAttr) + , pView(pSdrView) + , nAnchorCtrls(nAnchorTypes) +{ + DBG_ASSERT(pView, "no valid view (!)"); + + //different positioning page in Writer + if(nAnchorCtrls & (SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page | SvxAnchorIds::Fly)) + { + AddTabPage("RID_SVXPAGE_SWPOSSIZE", SvxSwPosSizeTabPage::Create, SvxSwPosSizeTabPage::GetRanges); + RemoveTabPage("RID_SVXPAGE_POSITION_SIZE"); + } + else + { + AddTabPage("RID_SVXPAGE_POSITION_SIZE", SvxPositionSizeTabPage::Create, SvxPositionSizeTabPage::GetRanges); + RemoveTabPage("RID_SVXPAGE_SWPOSSIZE"); + } + + AddTabPage("RID_SVXPAGE_ANGLE", SvxAngleTabPage::Create, SvxAngleTabPage::GetRanges); + AddTabPage("RID_SVXPAGE_SLANT", SvxSlantTabPage::Create, SvxSlantTabPage::GetRanges); +} + + +void SvxTransformTabDialog::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + if (rId == "RID_SVXPAGE_POSITION_SIZE") + { + SvxPositionSizeTabPage& rSvxPos = static_cast<SvxPositionSizeTabPage&>(rPage); + rSvxPos.SetView(pView); + rSvxPos.Construct(); + + if(nAnchorCtrls & SvxAnchorIds::NoResize) + { + rSvxPos.DisableResize(); + } + + if(nAnchorCtrls & SvxAnchorIds::NoProtect) + { + rSvxPos.DisableProtect(); + rSvxPos.UpdateControlStates(); + } + } + else if (rId == "RID_SVXPAGE_SWPOSSIZE") + { + SvxSwPosSizeTabPage& rSwPos = static_cast<SvxSwPosSizeTabPage&>(rPage); + + rSwPos.EnableAnchorTypes(nAnchorCtrls); + rSwPos.SetValidateFramePosLink(aValidateLink); + rSwPos.SetView(pView); + } + else if (rId == "RID_SVXPAGE_ANGLE") + { + SvxAngleTabPage& rSvxAng = static_cast<SvxAngleTabPage&>(rPage); + + rSvxAng.SetView( pView ); + rSvxAng.Construct(); + } + else if (rId == "RID_SVXPAGE_SLANT") + { + SvxSlantTabPage& rSvxSlnt = static_cast<SvxSlantTabPage&>(rPage); + + rSvxSlnt.SetView( pView ); + rSvxSlnt.Construct(); + } +} + +void SvxTransformTabDialog::SetValidateFramePosLink(const Link<SvxSwFrameValidation&,void>& rLink) +{ + aValidateLink = rLink; +} + +/************************************************************************* +|* +|* dialog for changing the positions of the rotation +|* angle and the rotation angle of the graphic objects +|* +\************************************************************************/ +SvxAngleTabPage::SvxAngleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/rotationtabpage.ui", "Rotation", rInAttrs) + , pView(nullptr) + , eDlgUnit(FieldUnit::NONE) + , m_aCtlRect(this) + , m_xFlPosition(m_xBuilder->weld_widget("FL_POSITION")) + , m_xMtrPosX(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_X", FieldUnit::CM)) + , m_xMtrPosY(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_Y", FieldUnit::CM)) + , m_xCtlRect(new weld::CustomWeld(*m_xBuilder, "CTL_RECT", m_aCtlRect)) + , m_xFlAngle(m_xBuilder->weld_widget("FL_ANGLE")) + , m_xNfAngle(m_xBuilder->weld_metric_spin_button("NF_ANGLE", FieldUnit::DEGREE)) + , m_xCtlAngle(new svx::DialControl) + , m_xCtlAngleWin(new weld::CustomWeld(*m_xBuilder, "CTL_ANGLE", *m_xCtlAngle)) +{ + // calculate PoolUnit + SfxItemPool* pPool = rInAttrs.GetPool(); + DBG_ASSERT( pPool, "no pool (!)" ); + ePoolUnit = pPool->GetMetric(SID_ATTR_TRANSFORM_POS_X); + + m_xCtlAngle->SetLinkedField(m_xNfAngle.get(), 2); +} + +SvxAngleTabPage::~SvxAngleTabPage() +{ +} + +void SvxAngleTabPage::Construct() +{ + DBG_ASSERT(pView, "No valid view (!)"); + eDlgUnit = GetModuleFieldUnit(GetItemSet()); + SetFieldUnit(*m_xMtrPosX, eDlgUnit, true); + SetFieldUnit(*m_xMtrPosY, eDlgUnit, true); + + if (FieldUnit::MILE == eDlgUnit || FieldUnit::KM == eDlgUnit) + { + m_xMtrPosX->set_digits(3); + m_xMtrPosY->set_digits(3); + } + + { // #i75273# + ::tools::Rectangle aTempRect(pView->GetAllMarkedRect()); + pView->GetSdrPageView()->LogicToPagePos(aTempRect); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + // Take anchor into account (Writer) + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + + if(rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + maAnchor = basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y()); + + if(!maAnchor.equalZero()) // -> Writer + { + maRange = basegfx::B2DRange(maRange.getMinimum() - maAnchor, maRange.getMaximum() - maAnchor); + } + } + + // take scale into account + const Fraction aUIScale(pView->GetModel()->GetUIScale()); + TransfrmHelper::ScaleRect(maRange, aUIScale); + + // take UI units into account + sal_uInt16 nDigits(m_xMtrPosX->get_digits()); + TransfrmHelper::ConvertRect(maRange, nDigits, ePoolUnit, eDlgUnit); + + if(!pView->IsRotateAllowed()) + { + m_xFlPosition->set_sensitive(false); + m_xFlAngle->set_sensitive(false); + } +} + +bool SvxAngleTabPage::FillItemSet(SfxItemSet* rSet) +{ + bool bModified = false; + + if (m_xCtlAngle->IsValueModified() || m_xMtrPosX->get_value_changed_from_saved() || m_xMtrPosY->get_value_changed_from_saved()) + { + const double fUIScale(double(pView->GetModel()->GetUIScale())); + const double fTmpX((GetCoreValue(*m_xMtrPosX, ePoolUnit) + maAnchor.getX()) * fUIScale); + const double fTmpY((GetCoreValue(*m_xMtrPosY, ePoolUnit) + maAnchor.getY()) * fUIScale); + + rSet->Put(SdrAngleItem(SID_ATTR_TRANSFORM_ANGLE, m_xCtlAngle->GetRotation())); + rSet->Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_X, basegfx::fround(fTmpX))); + rSet->Put(SfxInt32Item(SID_ATTR_TRANSFORM_ROT_Y, basegfx::fround(fTmpY))); + + bModified = true; + } + + return bModified; +} + + +void SvxAngleTabPage::Reset(const SfxItemSet* rAttrs) +{ + const double fUIScale(double(pView->GetModel()->GetUIScale())); + + const SfxPoolItem* pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_ROT_X ); + if(pItem) + { + const double fTmp((static_cast<double>(static_cast<const SfxInt32Item*>(pItem)->GetValue()) - maAnchor.getX()) / fUIScale); + SetMetricValue(*m_xMtrPosX, basegfx::fround(fTmp), ePoolUnit); + } + else + { + m_xMtrPosX->set_text(OUString()); + } + + pItem = GetItem(*rAttrs, SID_ATTR_TRANSFORM_ROT_Y); + if(pItem) + { + const double fTmp((static_cast<double>(static_cast<const SfxInt32Item*>(pItem)->GetValue()) - maAnchor.getY()) / fUIScale); + SetMetricValue(*m_xMtrPosY, basegfx::fround(fTmp), ePoolUnit); + } + else + { + m_xMtrPosY->set_text(OUString()); + } + + pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_ANGLE ); + if(pItem) + { + m_xCtlAngle->SetRotation(static_cast<const SdrAngleItem*>(pItem)->GetValue()); + } + else + { + m_xCtlAngle->SetRotation(0_deg100); + } + m_xCtlAngle->SaveValue(); + m_xMtrPosX->save_value(); + m_xMtrPosY->save_value(); +} + +std::unique_ptr<SfxTabPage> SvxAngleTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SvxAngleTabPage>(pPage, pController, *rSet); +} + +void SvxAngleTabPage::ActivatePage(const SfxItemSet& rSet) +{ + if(SfxBoolItem const * bPosProtect = rSet.GetItemIfSet( SID_ATTR_TRANSFORM_PROTECT_POS, false )) + { + m_xFlPosition->set_sensitive(!bPosProtect->GetValue()); + m_xFlAngle->set_sensitive(!bPosProtect->GetValue()); + } +} + +DeactivateRC SvxAngleTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if(_pSet) + { + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; +} + +void SvxAngleTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint eRP) +{ + if (pDrawingArea != m_aCtlRect.GetDrawingArea()) + return; + + switch(eRP) + { + case RectPoint::LT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::MT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::RT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::LM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::MM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::RM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::LB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::MB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::RB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + } +} + +/************************************************************************* +|* +|* dialog for changing slant and corner radius +|* +\************************************************************************/ +SvxSlantTabPage::SvxSlantTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "cui/ui/slantcornertabpage.ui", "SlantAndCornerRadius", &rInAttrs) + , pView(nullptr) + , eDlgUnit(FieldUnit::NONE) + , m_xFlRadius(m_xBuilder->weld_widget("FL_RADIUS")) + , m_xMtrRadius(m_xBuilder->weld_metric_spin_button("MTR_FLD_RADIUS", FieldUnit::CM)) + , m_xFlAngle(m_xBuilder->weld_widget("FL_SLANT")) + , m_xMtrAngle(m_xBuilder->weld_metric_spin_button("MTR_FLD_ANGLE", FieldUnit::DEGREE)) +{ + for (int i = 0; i < 2; ++i) + { + m_aControlGroups[i] = m_xBuilder->weld_widget("controlgroups" + OString::number(i+1)); + m_aControlGroupX[i] = m_xBuilder->weld_widget("controlgroupx" + OString::number(i+1)); + m_aControlX[i] = m_xBuilder->weld_metric_spin_button("controlx" + OString::number(i+1), FieldUnit::CM); + m_aControlGroupY[i] = m_xBuilder->weld_widget("controlgroupy" + OString::number(i+1)); + m_aControlY[i] = m_xBuilder->weld_metric_spin_button("controly" + OString::number(i+1), FieldUnit::CM); + } + + // this page needs ExchangeSupport + SetExchangeSupport(); + + // evaluate PoolUnit + SfxItemPool* pPool = rInAttrs.GetPool(); + assert(pPool && "no pool (!)"); + ePoolUnit = pPool->GetMetric( SID_ATTR_TRANSFORM_POS_X ); +} + +SvxSlantTabPage::~SvxSlantTabPage() +{ +} + +void SvxSlantTabPage::Construct() +{ + // get the range + DBG_ASSERT(pView, "no valid view (!)"); + eDlgUnit = GetModuleFieldUnit(GetItemSet()); + SetFieldUnit(*m_xMtrRadius, eDlgUnit, true); + for (int i = 0; i < 2; ++i) + { + SetFieldUnit(*m_aControlX[i], eDlgUnit, true); + SetFieldUnit(*m_aControlY[i], eDlgUnit, true); + } + + { // #i75273# + ::tools::Rectangle aTempRect(pView->GetAllMarkedRect()); + pView->GetSdrPageView()->LogicToPagePos(aTempRect); + } +} + +bool SvxSlantTabPage::FillItemSet(SfxItemSet* rAttrs) +{ + bool bModified = false; + + if (m_xMtrRadius->get_value_changed_from_saved()) + { + Fraction aUIScale = pView->GetModel()->GetUIScale(); + tools::Long nTmp = tools::Long(GetCoreValue(*m_xMtrRadius, ePoolUnit) * aUIScale); + + rAttrs->Put( makeSdrEckenradiusItem( nTmp ) ); + bModified = true; + } + + if (m_xMtrAngle->get_value_changed_from_saved()) + { + sal_Int32 nValue = static_cast<sal_Int32>(m_xMtrAngle->get_value(FieldUnit::NONE)); + rAttrs->Put( SdrAngleItem( SID_ATTR_TRANSFORM_SHEAR, Degree100(nValue) ) ); + bModified = true; + } + + if( bModified ) + { + // set reference points + ::tools::Rectangle aObjectRect(pView->GetAllMarkedRect()); + pView->GetSdrPageView()->LogicToPagePos(aObjectRect); + Point aPt = aObjectRect.Center(); + + rAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_X, aPt.X())); + rAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_SHEAR_Y, aPt.Y())); + rAttrs->Put( SfxBoolItem( SID_ATTR_TRANSFORM_SHEAR_VERTICAL, false ) ); + } + + bool bControlPointsChanged = false; + for (int i = 0; i < 2; ++i) + { + bControlPointsChanged |= (m_aControlX[i]->get_value_changed_from_saved() || + m_aControlY[i]->get_value_changed_from_saved()); + } + + if (!bControlPointsChanged) + return bModified; + + bool bSelectionIsSdrObjCustomShape(false); + + while(true) + { + if(nullptr == pView) + { + break; + } + + if(0 == pView->GetMarkedObjectList().GetMarkCount()) + { + break; + } + + SdrObject* pCandidate(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()); + + if(nullptr == pCandidate) + { + break; + } + + if(nullptr == dynamic_cast< SdrObjCustomShape* >(pCandidate)) + { + break; + } + + bSelectionIsSdrObjCustomShape = true; + break; + } + + if(bSelectionIsSdrObjCustomShape) + { + SdrObjCustomShape& rSdrObjCustomShape( + static_cast< SdrObjCustomShape& >( + *pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj())); + SdrModel& rModel(rSdrObjCustomShape.getSdrModelFromSdrObject()); + std::unique_ptr<SdrUndoAction> pUndo; + if (rModel.IsUndoEnabled()) + pUndo = rModel.GetSdrUndoFactory().CreateUndoAttrObject(rSdrObjCustomShape); + + if(pUndo) + { + rModel.BegUndo(pUndo->GetComment()); + } + + EnhancedCustomShape2d aShape(rSdrObjCustomShape); + ::tools::Rectangle aLogicRect = aShape.GetLogicRect(); + + for (int i = 0; i < 2; ++i) + { + if (m_aControlX[i]->get_value_changed_from_saved() || m_aControlY[i]->get_value_changed_from_saved()) + { + Point aNewPosition(GetCoreValue(*m_aControlX[i], ePoolUnit), + GetCoreValue(*m_aControlY[i], ePoolUnit)); + aNewPosition.Move(aLogicRect.Left(), aLogicRect.Top()); + + css::awt::Point aPosition; + aPosition.X = aNewPosition.X(); + aPosition.Y = aNewPosition.Y(); + + aShape.SetHandleControllerPosition(i, aPosition); + } + } + + rSdrObjCustomShape.SetChanged(); + rSdrObjCustomShape.BroadcastObjectChange(); + bModified = true; + + if (pUndo) + { + rModel.AddUndo(std::move(pUndo)); + rModel.EndUndo(); + } + } + + return bModified; +} + +void SvxSlantTabPage::Reset(const SfxItemSet* rAttrs) +{ + // if the view has selected objects, items with SfxItemState::DEFAULT need to be disabled + const SfxPoolItem* pItem; + + // corner radius + if(!pView->IsEdgeRadiusAllowed()) + { + m_xMtrRadius->set_text(""); + m_xFlRadius->set_sensitive(false); + } + else + { + pItem = GetItem( *rAttrs, SDRATTR_CORNER_RADIUS ); + + if( pItem ) + { + const double fUIScale(double(pView->GetModel()->GetUIScale())); + const double fTmp(static_cast<double>(static_cast<const SdrMetricItem*>(pItem)->GetValue()) / fUIScale); + SetMetricValue(*m_xMtrRadius, basegfx::fround(fTmp), ePoolUnit); + } + else + { + m_xMtrRadius->set_text(""); + } + } + + m_xMtrRadius->save_value(); + + // slant: angle + if( !pView->IsShearAllowed() ) + { + m_xMtrAngle->set_text( "" ); + m_xFlAngle->set_sensitive(false); + } + else + { + pItem = GetItem( *rAttrs, SID_ATTR_TRANSFORM_SHEAR ); + + if( pItem ) + { + m_xMtrAngle->set_value(static_cast<const SdrAngleItem*>(pItem)->GetValue().get(), FieldUnit::NONE); + } + else + { + m_xMtrAngle->set_text(""); + } + } + + m_xMtrAngle->save_value(); + + bool bSelectionIsSdrObjCustomShape(false); + + while(true) + { + if(1 != pView->GetMarkedObjectList().GetMarkCount()) + { + break; + } + + SdrObject* pCandidate(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj()); + + if(nullptr == pCandidate) + { + break; + } + + if(nullptr == dynamic_cast< SdrObjCustomShape* >(pCandidate)) + { + break; + } + + bSelectionIsSdrObjCustomShape = true; + break; + } + + if(bSelectionIsSdrObjCustomShape) + { + SdrObjCustomShape& rSdrObjCustomShape( + static_cast< SdrObjCustomShape& >( + *pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj())); + + //save geometry + const bool bOrigModelChangeState = pView->GetModel()->IsChanged(); + SdrCustomShapeGeometryItem aInitialGeometry(rSdrObjCustomShape.GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY)); + EnhancedCustomShape2d aShape(rSdrObjCustomShape); + + for (int i = 0; i < 2; ++i) + { + Point aInitialPosition; + if (!aShape.GetHandlePosition(i, aInitialPosition)) + break; + m_aControlGroups[i]->set_sensitive(true); + css::awt::Point aPosition; + + aPosition.X = SAL_MAX_INT32/2; + aPosition.Y = SAL_MAX_INT32/2; + aShape.SetHandleControllerPosition(i, aPosition); + Point aMaxPosition; + aShape.GetHandlePosition(i, aMaxPosition); + + aPosition.X = SAL_MIN_INT32/2; + aPosition.Y = SAL_MIN_INT32/2; + aShape.SetHandleControllerPosition(i, aPosition); + Point aMinPosition; + aShape.GetHandlePosition(i, aMinPosition); + + ::tools::Rectangle aLogicRect = aShape.GetLogicRect(); + aInitialPosition.Move(-aLogicRect.Left(), -aLogicRect.Top()); + aMaxPosition.Move(-aLogicRect.Left(), -aLogicRect.Top()); + aMinPosition.Move(-aLogicRect.Left(), -aLogicRect.Top()); + + SetMetricValue(*m_aControlX[i], aInitialPosition.X(), ePoolUnit); + SetMetricValue(*m_aControlY[i], aInitialPosition.Y(), ePoolUnit); + + if (aMaxPosition.X() == aMinPosition.X()) + m_aControlGroupX[i]->set_sensitive(false); + else + m_aControlX[i]->set_range(aMinPosition.X(), aMaxPosition.X(), FieldUnit::MM); + if (aMaxPosition.Y() == aMinPosition.Y()) + m_aControlGroupY[i]->set_sensitive(false); + else + m_aControlY[i]->set_range(aMinPosition.Y(), aMaxPosition.Y(), FieldUnit::MM); + } + + //restore geometry + rSdrObjCustomShape.SetMergedItem(aInitialGeometry); + pView->GetModel()->SetChanged(bOrigModelChangeState); + } + + for (int i = 0; i < 2; ++i) + { + m_aControlX[i]->save_value(); + m_aControlY[i]->save_value(); + } +} + +std::unique_ptr<SfxTabPage> SvxSlantTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SvxSlantTabPage>(pPage, pController, *rOutAttrs); +} + +void SvxSlantTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if(SfxBoolItem const * bPosProtect = rSet.GetItemIfSet( SID_ATTR_TRANSFORM_PROTECT_POS, false )) + { + m_xFlAngle->set_sensitive(!bPosProtect->GetValue()); + } + if(SfxBoolItem const * bSizeProtect = rSet.GetItemIfSet( SID_ATTR_TRANSFORM_PROTECT_SIZE, false )) + { + m_xFlAngle->set_sensitive(!bSizeProtect->GetValue()); + } + +} + +DeactivateRC SvxSlantTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if(_pSet) + { + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; +} + + +/************************************************************************* +|* +|* Dialog for changing position and size of graphic objects +|* +\************************************************************************/ +SvxPositionSizeTabPage::SvxPositionSizeTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SvxTabPage(pPage, pController, "cui/ui/possizetabpage.ui", "PositionAndSize", rInAttrs) + , mrOutAttrs(rInAttrs) + , mpView(nullptr) + , meDlgUnit(FieldUnit::NONE) + , mnProtectSizeState(TRISTATE_FALSE) + , mbPageDisabled(false) + , mbProtectDisabled(false) + , mbSizeDisabled(false) + , mbAdjustDisabled(true) + , mbIgnoreAutoGrowWidth(true) + , mbIgnoreAutoGrowHeight(true) + , mfOldWidth(0.0) + , mfOldHeight(0.0) + , m_aCtlPos(this) + , m_aCtlSize(this) + , m_xFlPosition(m_xBuilder->weld_widget("FL_POSITION")) + , m_xMtrPosX(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_X", FieldUnit::CM)) + , m_xMtrPosY(m_xBuilder->weld_metric_spin_button("MTR_FLD_POS_Y", FieldUnit::CM)) + , m_xCtlPos(new weld::CustomWeld(*m_xBuilder, "CTL_POSRECT", m_aCtlPos)) + , m_xFlSize(m_xBuilder->weld_widget("FL_SIZE")) + , m_xFtWidth(m_xBuilder->weld_label("FT_WIDTH")) + , m_xMtrWidth(m_xBuilder->weld_metric_spin_button("MTR_FLD_WIDTH", FieldUnit::CM)) + , m_xFtHeight(m_xBuilder->weld_label("FT_HEIGHT")) + , m_xMtrHeight(m_xBuilder->weld_metric_spin_button("MTR_FLD_HEIGHT", FieldUnit::CM)) + , m_xCbxScale(m_xBuilder->weld_check_button("CBX_SCALE")) + , m_xCtlSize(new weld::CustomWeld(*m_xBuilder, "CTL_SIZERECT", m_aCtlSize)) + , m_xFlProtect(m_xBuilder->weld_widget("FL_PROTECT")) + , m_xTsbPosProtect(m_xBuilder->weld_check_button("TSB_POSPROTECT")) + , m_xTsbSizeProtect(m_xBuilder->weld_check_button("TSB_SIZEPROTECT")) + , m_xFlAdjust(m_xBuilder->weld_widget("FL_ADJUST")) + , m_xTsbAutoGrowWidth(m_xBuilder->weld_check_button("TSB_AUTOGROW_WIDTH")) + , m_xTsbAutoGrowHeight(m_xBuilder->weld_check_button("TSB_AUTOGROW_HEIGHT")) +{ + // this page needs ExchangeSupport + SetExchangeSupport(); + + // evaluate PoolUnit + SfxItemPool* pPool = mrOutAttrs.GetPool(); + DBG_ASSERT( pPool, "no pool (!)" ); + mePoolUnit = pPool->GetMetric( SID_ATTR_TRANSFORM_POS_X ); + + m_aCtlPos.SetActualRP(RectPoint::LT); + m_aCtlSize.SetActualRP(RectPoint::LT); + meRP = RectPoint::LT; // see above + + m_xMtrWidth->connect_value_changed( LINK( this, SvxPositionSizeTabPage, ChangeWidthHdl ) ); + m_xMtrHeight->connect_value_changed( LINK( this, SvxPositionSizeTabPage, ChangeHeightHdl ) ); + m_xCbxScale->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickAutoHdl ) ); + + m_xFlAdjust->set_sensitive(false); + + // #i2379# disable controls when protected + m_xTsbPosProtect->connect_toggled( LINK( this, SvxPositionSizeTabPage, ChangePosProtectHdl ) ); + m_xTsbSizeProtect->connect_toggled( LINK( this, SvxPositionSizeTabPage, ChangeSizeProtectHdl ) ); +} + +SvxPositionSizeTabPage::~SvxPositionSizeTabPage() +{ +} + +void SvxPositionSizeTabPage::Construct() +{ + // get range and work area + DBG_ASSERT( mpView, "no valid view (!)" ); + meDlgUnit = GetModuleFieldUnit( GetItemSet() ); + SetFieldUnit( *m_xMtrPosX, meDlgUnit, true ); + SetFieldUnit( *m_xMtrPosY, meDlgUnit, true ); + SetFieldUnit( *m_xMtrWidth, meDlgUnit, true ); + SetFieldUnit( *m_xMtrHeight, meDlgUnit, true ); + + if(FieldUnit::MILE == meDlgUnit || FieldUnit::KM == meDlgUnit) + { + m_xMtrPosX->set_digits( 3 ); + m_xMtrPosY->set_digits( 3 ); + m_xMtrWidth->set_digits( 3 ); + m_xMtrHeight->set_digits( 3 ); + } + + { // #i75273# + ::tools::Rectangle aTempRect(mpView->GetAllMarkedRect()); + mpView->GetSdrPageView()->LogicToPagePos(aTempRect); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + { // #i75273# + ::tools::Rectangle aTempRect(mpView->GetWorkArea()); + mpView->GetSdrPageView()->LogicToPagePos(aTempRect); + maWorkRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + // take anchor into account (Writer) + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if(rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + maAnchor = basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y()); + + if(!maAnchor.equalZero()) // -> Writer + { + for(size_t i = 1; i < rMarkList.GetMarkCount(); ++i) + { + pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + + if(maAnchor != basegfx::B2DPoint(pObj->GetAnchorPos().X(), pObj->GetAnchorPos().Y())) + { + // different anchor positions + m_xMtrPosX->set_text(""); + m_xMtrPosY->set_text(""); + mbPageDisabled = true; + return; + } + } + + // translate ranges about anchor + maRange = basegfx::B2DRange(maRange.getMinimum() - maAnchor, maRange.getMaximum() - maAnchor); + maWorkRange = basegfx::B2DRange(maWorkRange.getMinimum() - maAnchor, maWorkRange.getMaximum() - maAnchor); + } + } + + // this should happen via SID_ATTR_TRANSFORM_AUTOSIZE + if(1 == rMarkList.GetMarkCount()) + { + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + const SdrObjKind eKind(pObj->GetObjIdentifier()); + + if((pObj->GetObjInventor() == SdrInventor::Default) && + (SdrObjKind::Text == eKind || SdrObjKind::TitleText == eKind || SdrObjKind::OutlineText == eKind) && + pObj->HasText()) + { + mbAdjustDisabled = false; + + m_xFlAdjust->set_sensitive(true); + + m_xTsbAutoGrowWidth->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickSizeProtectHdl ) ); + m_xTsbAutoGrowHeight->connect_toggled( LINK( this, SvxPositionSizeTabPage, ClickSizeProtectHdl ) ); + + // is used as flag to evaluate if it's selectable + mbIgnoreAutoGrowWidth = false; + mbIgnoreAutoGrowHeight = false; + } + } + + // take scale into account + const Fraction aUIScale(mpView->GetModel()->GetUIScale()); + TransfrmHelper::ScaleRect( maWorkRange, aUIScale ); + TransfrmHelper::ScaleRect( maRange, aUIScale ); + + // take UI units into account + const sal_uInt16 nDigits(m_xMtrPosX->get_digits()); + TransfrmHelper::ConvertRect( maWorkRange, nDigits, mePoolUnit, meDlgUnit ); + TransfrmHelper::ConvertRect( maRange, nDigits, mePoolUnit, meDlgUnit ); + + SetMinMaxPosition(); +} + + +bool SvxPositionSizeTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + bool bModified(false); + + if ( m_xMtrWidth->has_focus() ) + { + ChangeWidthHdl( *m_xMtrWidth ); + } + + if ( m_xMtrHeight->has_focus() ) + { + ChangeHeightHdl( *m_xMtrHeight ); + } + + if( !mbPageDisabled ) + { + if (m_xMtrPosX->get_value_changed_from_saved() || m_xMtrPosY->get_value_changed_from_saved()) + { + const double fUIScale(double(mpView->GetModel()->GetUIScale())); + double fX((GetCoreValue( *m_xMtrPosX, mePoolUnit ) + maAnchor.getX()) * fUIScale); + double fY((GetCoreValue( *m_xMtrPosY, mePoolUnit ) + maAnchor.getY()) * fUIScale); + + { // #i75273# + ::tools::Rectangle aTempRect(mpView->GetAllMarkedRect()); + mpView->GetSdrPageView()->LogicToPagePos(aTempRect); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + // #101581# GetTopLeftPosition(...) needs coordinates after UI scaling, in real PagePositions + GetTopLeftPosition(fX, fY, maRange); + + rOutAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_X, basegfx::fround(fX))); + rOutAttrs->Put(SfxInt32Item(SID_ATTR_TRANSFORM_POS_Y, basegfx::fround(fY))); + + bModified = true; + } + + if (m_xTsbPosProtect->get_state_changed_from_saved()) + { + if( m_xTsbPosProtect->get_inconsistent() ) + { + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_POS ); + } + else + { + rOutAttrs->Put( + SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_POS, + m_xTsbPosProtect->get_active() ) ); + } + + bModified = true; + } + } + + if (m_xMtrWidth->get_value_changed_from_saved() || m_xMtrHeight->get_value_changed_from_saved()) + { + Fraction aUIScale = mpView->GetModel()->GetUIScale(); + + // get Width + double nWidth = static_cast<double>(m_xMtrWidth->get_value(FieldUnit::MM_100TH)); + tools::Long lWidth = tools::Long(nWidth * static_cast<double>(aUIScale)); + lWidth = OutputDevice::LogicToLogic( lWidth, MapUnit::Map100thMM, mePoolUnit ); + lWidth = static_cast<tools::Long>(m_xMtrWidth->denormalize( lWidth )); + + // get Height + double nHeight = static_cast<double>(m_xMtrHeight->get_value(FieldUnit::MM_100TH)); + tools::Long lHeight = tools::Long(nHeight * static_cast<double>(aUIScale)); + lHeight = OutputDevice::LogicToLogic( lHeight, MapUnit::Map100thMM, mePoolUnit ); + lHeight = static_cast<tools::Long>(m_xMtrHeight->denormalize( lHeight )); + + // put Width & Height to itemset + rOutAttrs->Put( SfxUInt32Item( SID_ATTR_TRANSFORM_WIDTH, static_cast<sal_uInt32>(lWidth) ) ); + rOutAttrs->Put( SfxUInt32Item( SID_ATTR_TRANSFORM_HEIGHT, static_cast<sal_uInt32>(lHeight) ) ); + rOutAttrs->Put( SfxUInt16Item( SID_ATTR_TRANSFORM_SIZE_POINT, sal::static_int_cast< sal_uInt16 >( meRP ) ) ); + bModified = true; + } + + if (m_xTsbSizeProtect->get_state_changed_from_saved()) + { + if ( m_xTsbSizeProtect->get_inconsistent() ) + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_PROTECT_SIZE ); + else + rOutAttrs->Put( + SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_SIZE, + m_xTsbSizeProtect->get_active() ) ); + bModified = true; + } + + if (m_xTsbAutoGrowWidth->get_state_changed_from_saved()) + { + if (!mbIgnoreAutoGrowWidth) + { + if( m_xTsbAutoGrowWidth->get_inconsistent() ) + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_AUTOWIDTH ); + else + rOutAttrs->Put( + SfxBoolItem( SID_ATTR_TRANSFORM_AUTOWIDTH, + m_xTsbAutoGrowWidth->get_active() ) ); + } + bModified = true; + } + + if (m_xTsbAutoGrowHeight->get_state_changed_from_saved()) + { + if (!mbIgnoreAutoGrowHeight) + { + if (m_xTsbAutoGrowHeight->get_inconsistent()) + { + rOutAttrs->InvalidateItem( SID_ATTR_TRANSFORM_AUTOHEIGHT ); + } + else + { + rOutAttrs->Put( + SfxBoolItem( SID_ATTR_TRANSFORM_AUTOHEIGHT, + m_xTsbAutoGrowHeight->get_active() ) ); + } + } + bModified = true; + } + + return bModified; +} + +void SvxPositionSizeTabPage::Reset( const SfxItemSet* ) +{ + const SfxPoolItem* pItem; + const double fUIScale(double(mpView->GetModel()->GetUIScale())); + + if ( !mbPageDisabled ) + { + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_POS_X ); + if ( pItem ) + { + const double fTmp((static_cast<const SfxInt32Item*>(pItem)->GetValue() - maAnchor.getX()) / fUIScale); + SetMetricValue(*m_xMtrPosX, basegfx::fround(fTmp), mePoolUnit); + } + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_POS_Y ); + if ( pItem ) + { + const double fTmp((static_cast<const SfxInt32Item*>(pItem)->GetValue() - maAnchor.getY()) / fUIScale); + SetMetricValue(*m_xMtrPosY, basegfx::fround(fTmp), mePoolUnit); + } + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_PROTECT_POS ); + if ( pItem ) + { + bool bProtected = static_cast<const SfxBoolItem*>( pItem )->GetValue(); + m_xTsbPosProtect->set_active(bProtected); + } + else + { + m_xTsbPosProtect->set_inconsistent(true); + } + + m_xTsbPosProtect->save_state(); + m_aCtlPos.Reset(); + + // #i2379# Disable controls for protected objects + ChangePosProtectHdl(*m_xTsbPosProtect); + } + + { // #i75273# set width + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_WIDTH ); + mfOldWidth = std::max( pItem ? static_cast<double>(static_cast<const SfxUInt32Item*>(pItem)->GetValue()) : 0.0, 1.0 ); + double fTmpWidth((OutputDevice::LogicToLogic(static_cast<sal_Int32>(mfOldWidth), mePoolUnit, MapUnit::Map100thMM)) / fUIScale); + if (m_xMtrWidth->get_digits()) + fTmpWidth *= pow(10.0, m_xMtrWidth->get_digits()); + m_xMtrWidth->set_value(fTmpWidth, FieldUnit::MM_100TH); + } + + { // #i75273# set height + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_HEIGHT ); + mfOldHeight = std::max( pItem ? static_cast<double>(static_cast<const SfxUInt32Item*>(pItem)->GetValue()) : 0.0, 1.0 ); + double fTmpHeight((OutputDevice::LogicToLogic(static_cast<sal_Int32>(mfOldHeight), mePoolUnit, MapUnit::Map100thMM)) / fUIScale); + if (m_xMtrHeight->get_digits()) + fTmpHeight *= pow(10.0, m_xMtrHeight->get_digits()); + m_xMtrHeight->set_value(fTmpHeight, FieldUnit::MM_100TH); + } + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_PROTECT_SIZE ); + if ( pItem ) + { + m_xTsbSizeProtect->set_active(static_cast<const SfxBoolItem*>(pItem)->GetValue()); + } + else + m_xTsbSizeProtect->set_inconsistent(true); + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_AUTOWIDTH ); + if ( pItem ) + { + m_xTsbAutoGrowWidth->set_active(static_cast<const SfxBoolItem*>( pItem )->GetValue()); + } + else + m_xTsbAutoGrowWidth->set_inconsistent(true); + + pItem = GetItem( mrOutAttrs, SID_ATTR_TRANSFORM_AUTOHEIGHT ); + if ( pItem ) + { + m_xTsbAutoGrowHeight->set_active(static_cast<const SfxBoolItem*>( pItem )->GetValue()); + } + else + m_xTsbAutoGrowHeight->set_inconsistent(true); + + // Is matching set? + OUString aStr = GetUserData(); + m_xCbxScale->set_active(aStr.toInt32() != 0); + + m_xMtrPosX->save_value(); + m_xMtrPosY->save_value(); + m_xMtrWidth->save_value(); + m_xMtrHeight->save_value(); + + m_xTsbSizeProtect->save_state(); + m_xTsbAutoGrowWidth->save_state(); + m_xTsbAutoGrowHeight->save_state(); + ClickSizeProtectHdl(*m_xTsbAutoGrowHeight); + + // #i2379# Disable controls for protected objects + ChangeSizeProtectHdl(*m_xTsbSizeProtect); +} + +std::unique_ptr<SfxTabPage> SvxPositionSizeTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SvxPositionSizeTabPage>(pPage, pController, *rOutAttrs); +} + +void SvxPositionSizeTabPage::ActivatePage( const SfxItemSet& rSet ) +{ + if( SfxRectangleItem const * pRectItem = rSet.GetItemIfSet( SID_ATTR_TRANSFORM_INTERN, false ) ) + { + { // #i75273# + const ::tools::Rectangle aTempRect(pRectItem->GetValue()); + maRange = vcl::unotools::b2DRectangleFromRectangle(aTempRect); + } + + SetMinMaxPosition(); + } +} + + +DeactivateRC SvxPositionSizeTabPage::DeactivatePage( SfxItemSet* _pSet ) +{ + if( _pSet ) + { + double fX(static_cast<double>(m_xMtrPosX->get_value(FieldUnit::NONE))); + double fY(static_cast<double>(m_xMtrPosY->get_value(FieldUnit::NONE))); + + GetTopLeftPosition(fX, fY, maRange); + const ::tools::Rectangle aOutRectangle( + basegfx::fround(fX), basegfx::fround(fY), + basegfx::fround(fX + maRange.getWidth()), basegfx::fround(fY + maRange.getHeight())); + _pSet->Put(SfxRectangleItem(SID_ATTR_TRANSFORM_INTERN, aOutRectangle)); + _pSet->Put(SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_POS, + m_xTsbPosProtect->get_state() == TRISTATE_TRUE )); + _pSet->Put(SfxBoolItem( SID_ATTR_TRANSFORM_PROTECT_SIZE, + m_xTsbSizeProtect->get_state() == TRISTATE_TRUE )); + FillItemSet(_pSet); + } + + return DeactivateRC::LeavePage; +} + + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangePosProtectHdl, weld::Toggleable&, void) +{ + // #106572# Remember user's last choice + m_xTsbSizeProtect->set_state(m_xTsbPosProtect->get_state() == TRISTATE_TRUE ? TRISTATE_TRUE : mnProtectSizeState); + UpdateControlStates(); +} + + +void SvxPositionSizeTabPage::UpdateControlStates() +{ + const bool bPosProtect = m_xTsbPosProtect->get_state() == TRISTATE_TRUE; + const bool bSizeProtect = m_xTsbSizeProtect->get_state() == TRISTATE_TRUE; + const bool bHeightChecked = !mbIgnoreAutoGrowHeight && (m_xTsbAutoGrowHeight->get_active()); + const bool bWidthChecked = !mbIgnoreAutoGrowWidth && (m_xTsbAutoGrowWidth->get_active()); + + m_xFlPosition->set_sensitive(!bPosProtect && !mbPageDisabled); + + m_xTsbPosProtect->set_sensitive( !mbProtectDisabled && !mbPageDisabled ); + + m_xFlSize->set_sensitive( !mbSizeDisabled && !bSizeProtect ); + + m_xFtWidth->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bWidthChecked ); + m_xMtrWidth->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bWidthChecked ); + + m_xFtHeight->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked ); + m_xMtrHeight->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked ); + + m_xCbxScale->set_sensitive( !mbSizeDisabled && !bSizeProtect && !bHeightChecked && !bWidthChecked ); + m_xCtlSize->set_sensitive( !mbSizeDisabled && !bSizeProtect && (!bHeightChecked || !bWidthChecked) ); + + m_xFlProtect->set_sensitive( !mbProtectDisabled ); + m_xTsbSizeProtect->set_sensitive( !mbProtectDisabled && !bPosProtect ); + + m_xFlAdjust->set_sensitive( !mbSizeDisabled && !bSizeProtect && !mbAdjustDisabled ); + + m_aCtlSize.Invalidate(); + m_aCtlPos.Invalidate(); +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeSizeProtectHdl, weld::Toggleable&, void) +{ + if (m_xTsbSizeProtect->get_sensitive()) + { + // #106572# Remember user's last choice + + // Note: this works only as long as the dialog is open. When + // the user closes the dialog, there is no way to remember + // whether size was enabled or disabled before pos protect was + // clicked. Thus, if pos protect is selected, the dialog is + // closed and reopened again, unchecking pos protect will + // always uncheck size protect, too. That's life. + mnProtectSizeState = m_xTsbSizeProtect->get_state(); + } + + UpdateControlStates(); +} + +void SvxPositionSizeTabPage::SetMinMaxPosition() +{ + // position + double fLeft(maWorkRange.getMinX()); + double fTop(maWorkRange.getMinY()); + double fRight(maWorkRange.getMaxX()); + double fBottom(maWorkRange.getMaxY()); + + switch (m_aCtlPos.GetActualRP()) + { + case RectPoint::LT: + { + fRight -= maRange.getWidth(); + fBottom -= maRange.getHeight(); + break; + } + case RectPoint::MT: + { + fLeft += maRange.getWidth() / 2.0; + fRight -= maRange.getWidth() / 2.0; + fBottom -= maRange.getHeight(); + break; + } + case RectPoint::RT: + { + fLeft += maRange.getWidth(); + fBottom -= maRange.getHeight(); + break; + } + case RectPoint::LM: + { + fRight -= maRange.getWidth(); + fTop += maRange.getHeight() / 2.0; + fBottom -= maRange.getHeight() / 2.0; + break; + } + case RectPoint::MM: + { + fLeft += maRange.getWidth() / 2.0; + fRight -= maRange.getWidth() / 2.0; + fTop += maRange.getHeight() / 2.0; + fBottom -= maRange.getHeight() / 2.0; + break; + } + case RectPoint::RM: + { + fLeft += maRange.getWidth(); + fTop += maRange.getHeight() / 2.0; + fBottom -= maRange.getHeight() / 2.0; + break; + } + case RectPoint::LB: + { + fRight -= maRange.getWidth(); + fTop += maRange.getHeight(); + break; + } + case RectPoint::MB: + { + fLeft += maRange.getWidth() / 2.0; + fRight -= maRange.getWidth() / 2.0; + fTop += maRange.getHeight(); + break; + } + case RectPoint::RB: + { + fLeft += maRange.getWidth(); + fTop += maRange.getHeight(); + break; + } + } + + const double fMaxLong(vcl::ConvertValue(std::numeric_limits<sal_Int64>::max(), 0, MapUnit::Map100thMM, meDlgUnit) - 1); + fLeft = std::clamp(fLeft, -fMaxLong, fMaxLong); + fRight = std::clamp(fRight, -fMaxLong, fMaxLong); + fTop = std::clamp(fTop, - fMaxLong, fMaxLong); + fBottom = std::clamp(fBottom, -fMaxLong, fMaxLong); + + // #i75273# normalizing when setting the min/max values was wrong, removed + m_xMtrPosX->set_range(basegfx::fround64(fLeft), basegfx::fround64(fRight), FieldUnit::NONE); + m_xMtrPosY->set_range(basegfx::fround64(fTop), basegfx::fround64(fBottom), FieldUnit::NONE); + + // size + fLeft = maWorkRange.getMinX(); + fTop = maWorkRange.getMinY(); + fRight = maWorkRange.getMaxX(); + fBottom = maWorkRange.getMaxY(); + double fNewX(0); + double fNewY(0); + + switch (m_aCtlSize.GetActualRP()) + { + case RectPoint::LT: + { + fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft ); + fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop ); + break; + } + case RectPoint::MT: + { + fNewX = std::min( maRange.getCenter().getX() - fLeft, fRight - maRange.getCenter().getX() ) * 2.0; + fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop ); + break; + } + case RectPoint::RT: + { + fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() ); + fNewY = maWorkRange.getHeight() - ( maRange.getMinY() - fTop ); + break; + } + case RectPoint::LM: + { + fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft ); + fNewY = std::min( maRange.getCenter().getY() - fTop, fBottom - maRange.getCenter().getY() ) * 2.0; + break; + } + case RectPoint::MM: + { + const double f1(maRange.getCenter().getX() - fLeft); + const double f2(fRight - maRange.getCenter().getX()); + const double f3(std::min(f1, f2)); + const double f4(maRange.getCenter().getY() - fTop); + const double f5(fBottom - maRange.getCenter().getY()); + const double f6(std::min(f4, f5)); + + fNewX = f3 * 2.0; + fNewY = f6 * 3.0; + + break; + } + case RectPoint::RM: + { + fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() ); + fNewY = std::min( maRange.getCenter().getY() - fTop, fBottom - maRange.getCenter().getY() ) * 2.0; + break; + } + case RectPoint::LB: + { + fNewX = maWorkRange.getWidth() - ( maRange.getMinX() - fLeft ); + fNewY = maWorkRange.getHeight() - ( fBottom - maRange.getMaxY() ); + break; + } + case RectPoint::MB: + { + fNewX = std::min( maRange.getCenter().getX() - fLeft, fRight - maRange.getCenter().getX() ) * 2.0; + fNewY = maWorkRange.getHeight() - ( maRange.getMaxY() - fBottom ); + break; + } + case RectPoint::RB: + { + fNewX = maWorkRange.getWidth() - ( fRight - maRange.getMaxX() ); + fNewY = maWorkRange.getHeight() - ( fBottom - maRange.getMaxY() ); + break; + } + } + + // #i75273# normalizing when setting the min/max values was wrong, removed + m_xMtrWidth->set_max(basegfx::fround64(fNewX), FieldUnit::NONE); + m_xMtrHeight->set_max(basegfx::fround64(fNewY), FieldUnit::NONE); +} + +void SvxPositionSizeTabPage::GetTopLeftPosition(double& rfX, double& rfY, const basegfx::B2DRange& rRange) +{ + switch (m_aCtlPos.GetActualRP()) + { + case RectPoint::LT: + { + break; + } + case RectPoint::MT: + { + rfX -= rRange.getCenter().getX() - rRange.getMinX(); + break; + } + case RectPoint::RT: + { + rfX -= rRange.getWidth(); + break; + } + case RectPoint::LM: + { + rfY -= rRange.getCenter().getY() - rRange.getMinY(); + break; + } + case RectPoint::MM: + { + rfX -= rRange.getCenter().getX() - rRange.getMinX(); + rfY -= rRange.getCenter().getY() - rRange.getMinY(); + break; + } + case RectPoint::RM: + { + rfX -= rRange.getWidth(); + rfY -= rRange.getCenter().getY() - rRange.getMinY(); + break; + } + case RectPoint::LB: + { + rfY -= rRange.getHeight(); + break; + } + case RectPoint::MB: + { + rfX -= rRange.getCenter().getX() - rRange.getMinX(); + rfY -= rRange.getHeight(); + break; + } + case RectPoint::RB: + { + rfX -= rRange.getWidth(); + rfY -= rRange.getHeight(); + break; + } + } +} + +void SvxPositionSizeTabPage::PointChanged(weld::DrawingArea* pDrawingArea, RectPoint eRP) +{ + if (pDrawingArea == m_aCtlPos.GetDrawingArea()) + { + SetMinMaxPosition(); + switch( eRP ) + { + case RectPoint::LT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::MT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::RT: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMinY()), FieldUnit::NONE ); + break; + } + case RectPoint::LM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::MM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::RM: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getCenter().getY()), FieldUnit::NONE ); + break; + } + case RectPoint::LB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMinX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::MB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getCenter().getX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + case RectPoint::RB: + { + m_xMtrPosX->set_value( basegfx::fround64(maRange.getMaxX()), FieldUnit::NONE ); + m_xMtrPosY->set_value( basegfx::fround64(maRange.getMaxY()), FieldUnit::NONE ); + break; + } + } + } + else + { + meRP = eRP; + SetMinMaxPosition(); + } +} + +void SvxPositionSizeTabPage::DisableResize() +{ + mbSizeDisabled = true; +} + + +void SvxPositionSizeTabPage::DisableProtect() +{ + mbProtectDisabled = true; +} + + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeWidthHdl, weld::MetricSpinButton&, void) +{ + if( !(m_xCbxScale->get_active() && m_xCbxScale->get_sensitive()) ) + return; + + sal_Int64 nHeight(basegfx::fround64((mfOldHeight * static_cast<double>(m_xMtrWidth->get_value(FieldUnit::NONE))) / mfOldWidth)); + sal_Int64 nMin, nMax; + m_xMtrHeight->get_range(nMin, nMax, FieldUnit::NONE); + + if (nHeight <= nMax) + { + m_xMtrHeight->set_value(nHeight, FieldUnit::NONE); + } + else + { + nHeight = nMax; + m_xMtrHeight->set_value(nHeight, FieldUnit::NONE); + + const sal_Int64 nWidth(basegfx::fround64((mfOldWidth * static_cast<double>(nHeight)) / mfOldHeight)); + m_xMtrWidth->set_value(nWidth, FieldUnit::NONE); + } +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ChangeHeightHdl, weld::MetricSpinButton&, void) +{ + if( !(m_xCbxScale->get_active() && m_xCbxScale->get_sensitive()) ) + return; + + sal_Int64 nWidth(basegfx::fround64((mfOldWidth * static_cast<double>(m_xMtrHeight->get_value(FieldUnit::NONE))) / mfOldHeight)); + sal_Int64 nMin, nMax; + m_xMtrWidth->get_range(nMin, nMax, FieldUnit::NONE); + + if (nWidth <= nMax) + { + m_xMtrWidth->set_value(nWidth, FieldUnit::NONE); + } + else + { + nWidth = nMax; + m_xMtrWidth->set_value(nWidth, FieldUnit::NONE); + + const sal_Int64 nHeight(basegfx::fround64((mfOldHeight * static_cast<double>(nWidth)) / mfOldWidth)); + m_xMtrHeight->set_value(nHeight, FieldUnit::NONE); + } +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ClickSizeProtectHdl, weld::Toggleable&, void) +{ + UpdateControlStates(); +} + +IMPL_LINK_NOARG(SvxPositionSizeTabPage, ClickAutoHdl, weld::Toggleable&, void) +{ + if (m_xCbxScale->get_active()) + { + mfOldWidth = std::max( static_cast<double>(GetCoreValue( *m_xMtrWidth, mePoolUnit )), 1.0 ); + mfOldHeight = std::max( static_cast<double>(GetCoreValue( *m_xMtrHeight, mePoolUnit )), 1.0 ); + } +} + +void SvxPositionSizeTabPage::FillUserData() +{ + // matching is saved in the Ini-file + OUString aStr = m_xCbxScale->get_active() ? OUString("1") : OUString("0"); + SetUserData( aStr ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |