diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/ui/frmdlg | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/ui/frmdlg')
-rw-r--r-- | sw/source/ui/frmdlg/column.cxx | 1381 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/cption.cxx | 537 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/frmdlg.cxx | 201 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/frmpage.cxx | 3285 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/pattern.cxx | 42 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/uiborder.cxx | 54 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/wrap.cxx | 631 |
7 files changed, 6131 insertions, 0 deletions
diff --git a/sw/source/ui/frmdlg/column.cxx b/sw/source/ui/frmdlg/column.cxx new file mode 100644 index 0000000000..8caa69fade --- /dev/null +++ b/sw/source/ui/frmdlg/column.cxx @@ -0,0 +1,1381 @@ +/* -*- 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 <column.hxx> + +#include <hintids.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <sfx2/htmlmode.hxx> +#include <svx/colorbox.hxx> +#include <editeng/borderline.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/ulspitem.hxx> +#include <svl/ctloptions.hxx> +#include <svl/itemset.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/event.hxx> +#include <vcl/fieldvalues.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +#include <swmodule.hxx> + +#include <swtypes.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <uitool.hxx> +#include <cmdid.h> +#include <viewopt.hxx> +#include <fmtclbl.hxx> +#include <fmtfsize.hxx> +#include <frmatr.hxx> +#include <colmgr.hxx> +#include <prcntfld.hxx> +#include <strings.hrc> +#include <section.hxx> +#include <pagedesc.hxx> + +//to match associated data in ColumnPage.ui +#define LISTBOX_SELECTION 0 +#define LISTBOX_SECTION 1 +#define LISTBOX_SECTIONS 2 +#define LISTBOX_PAGE 3 +#define LISTBOX_FRAME 4 + +using namespace ::com::sun::star; + +#define FRAME_FORMAT_WIDTH 1000 + +// static data +const sal_uInt16 nVisCols = 3; + +static bool IsMarkInSameSection( SwWrtShell& rWrtSh, const SwSection* pSect ) +{ + rWrtSh.SwapPam(); + bool bRet = pSect == rWrtSh.GetCurrSection(); + rWrtSh.SwapPam(); + return bRet; +} + +SwColumnDlg::SwColumnDlg(weld::Window* pParent, SwWrtShell& rSh) + : SfxDialogController(pParent, "modules/swriter/ui/columndialog.ui", "ColumnDialog") + , m_rWrtShell(rSh) + , m_pFrameSet(nullptr) + , m_nOldSelection(0) + , m_nSelectionWidth(0) + , m_bPageChanged(false) + , m_bSectionChanged(false) + , m_bSelSectionChanged(false) + , m_bFrameChanged(false) + , m_xContentArea(m_xBuilder->weld_container("content")) + , m_xOkButton(m_xBuilder->weld_button("ok")) +{ + SwRect aRect; + m_rWrtShell.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR); + + m_nSelectionWidth = aRect.Width(); + + SfxItemSet* pColPgSet = nullptr; + static const auto aSectIds = svl::Items<RES_FRM_SIZE, RES_FRM_SIZE, + RES_COL, RES_COL, + RES_COLUMNBALANCE, RES_FRAMEDIR>; + + const SwSection* pCurrSection = m_rWrtShell.GetCurrSection(); + const sal_uInt16 nFullSectCnt = m_rWrtShell.GetFullSelectedSectionCount(); + if( pCurrSection && ( !m_rWrtShell.HasSelection() || 0 != nFullSectCnt )) + { + m_nSelectionWidth = rSh.GetSectionWidth(*pCurrSection->GetFormat()); + if ( !m_nSelectionWidth ) + m_nSelectionWidth = USHRT_MAX; + m_pSectionSet.reset( new SfxItemSet( m_rWrtShell.GetAttrPool(), aSectIds ) ); + m_pSectionSet->Put( pCurrSection->GetFormat()->GetAttrSet() ); + pColPgSet = m_pSectionSet.get(); + } + + if( m_rWrtShell.HasSelection() && m_rWrtShell.IsInsRegionAvailable() && + ( !pCurrSection || ( 1 != nFullSectCnt && + IsMarkInSameSection( m_rWrtShell, pCurrSection ) ))) + { + m_pSelectionSet.reset( new SfxItemSet( m_rWrtShell.GetAttrPool(), aSectIds ) ); + pColPgSet = m_pSelectionSet.get(); + } + + if( m_rWrtShell.GetFlyFrameFormat() ) + { + const SwFrameFormat* pFormat = rSh.GetFlyFrameFormat() ; + m_pFrameSet = new SfxItemSet(m_rWrtShell.GetAttrPool(), aSectIds ); + m_pFrameSet->Put(pFormat->GetFrameSize()); + m_pFrameSet->Put(pFormat->GetCol()); + pColPgSet = m_pFrameSet; + } + + const SwPageDesc* pPageDesc = m_rWrtShell.GetSelectedPageDescs(); + if( pPageDesc ) + { + m_pPageSet = std::make_unique<SfxItemSetFixed< + RES_FRM_SIZE, RES_FRM_SIZE, + RES_LR_SPACE, RES_LR_SPACE, + RES_COL, RES_COL>>(m_rWrtShell.GetAttrPool()); + + const SwFrameFormat &rFormat = pPageDesc->GetMaster(); + m_nPageWidth = rFormat.GetFrameSize().GetSize().Width(); + + const SvxLRSpaceItem& rLRSpace = rFormat.GetLRSpace(); + const SvxBoxItem& rBox = rFormat.GetBox(); + m_nPageWidth -= rLRSpace.GetLeft() + rLRSpace.GetRight() + rBox.GetSmallestDistance(); + + m_pPageSet->Put(rFormat.GetCol()); + m_pPageSet->Put(rFormat.GetLRSpace()); + pColPgSet = m_pPageSet.get(); + } + + assert(pColPgSet); + + // create TabPage + m_xTabPage = std::make_unique<SwColumnPage>(m_xContentArea.get(), this, *pColPgSet); + m_xTabPage->GetApplyLabel()->show(); + weld::ComboBox* pApplyToLB = m_xTabPage->GetApplyComboBox(); + pApplyToLB->show(); + + if (pCurrSection && (!m_rWrtShell.HasSelection() || 0 != nFullSectCnt)) + { + pApplyToLB->remove_id(1 >= nFullSectCnt ? OUString::number(LISTBOX_SECTIONS) : OUString::number(LISTBOX_SECTION)); + } + else + { + pApplyToLB->remove_id(OUString::number(LISTBOX_SECTION)); + pApplyToLB->remove_id(OUString::number(LISTBOX_SECTIONS)); + } + + if (!( m_rWrtShell.HasSelection() && m_rWrtShell.IsInsRegionAvailable() && + ( !pCurrSection || ( 1 != nFullSectCnt && + IsMarkInSameSection( m_rWrtShell, pCurrSection ) )))) + pApplyToLB->remove_id(OUString::number(LISTBOX_SELECTION)); + + if (!m_rWrtShell.GetFlyFrameFormat()) + pApplyToLB->remove_id(OUString::number(LISTBOX_FRAME)); + + const int nPagePos = pApplyToLB->find_id(OUString::number(LISTBOX_PAGE)); + if (m_pPageSet && pPageDesc) + { + const OUString sPageStr = pApplyToLB->get_text(nPagePos) + pPageDesc->GetName(); + pApplyToLB->remove(nPagePos); + OUString sId(OUString::number(LISTBOX_PAGE)); + pApplyToLB->insert(nPagePos, sPageStr, &sId, nullptr, nullptr); + } + else + pApplyToLB->remove( nPagePos ); + + pApplyToLB->set_active(0); + ObjectHdl(nullptr); + + pApplyToLB->connect_changed(LINK(this, SwColumnDlg, ObjectListBoxHdl)); + m_xOkButton->connect_clicked(LINK(this, SwColumnDlg, OkHdl)); + //#i80458# if no columns can be set then disable OK + if (!pApplyToLB->get_count()) + m_xOkButton->set_sensitive(false); + //#i97810# set focus to the TabPage + m_xTabPage->ActivateColumnControl(); +} + +SwColumnDlg::~SwColumnDlg() +{ + m_xTabPage.reset(); +} + +IMPL_LINK(SwColumnDlg, ObjectListBoxHdl, weld::ComboBox&, rBox, void) +{ + ObjectHdl(&rBox); +} + +void SwColumnDlg::ObjectHdl(const weld::ComboBox* pBox) +{ + SfxItemSet* pSet = EvalCurrentSelection(); + + if (pBox) + { + m_xTabPage->FillItemSet(pSet); + } + weld::ComboBox* pApplyToLB = m_xTabPage->GetApplyComboBox(); + m_nOldSelection = pApplyToLB->get_active_id().toInt32(); + tools::Long nWidth = m_nSelectionWidth; + switch(m_nOldSelection) + { + case LISTBOX_SELECTION : + pSet = m_pSelectionSet.get(); + if( m_pSelectionSet ) + pSet->Put(SwFormatFrameSize(SwFrameSize::Variable, nWidth, nWidth)); + break; + case LISTBOX_SECTION : + case LISTBOX_SECTIONS : + pSet = m_pSectionSet.get(); + pSet->Put(SwFormatFrameSize(SwFrameSize::Variable, nWidth, nWidth)); + break; + case LISTBOX_PAGE : + nWidth = m_nPageWidth; + pSet = m_pPageSet.get(); + pSet->Put(SwFormatFrameSize(SwFrameSize::Variable, nWidth, nWidth)); + break; + case LISTBOX_FRAME: + pSet = m_pFrameSet; + break; + } + + bool bIsSection = pSet == m_pSectionSet.get() || pSet == m_pSelectionSet.get(); + m_xTabPage->ShowBalance(bIsSection); + m_xTabPage->SetInSection(bIsSection); + m_xTabPage->SetFrameMode(true); + m_xTabPage->SetPageWidth(nWidth); + if( pSet ) + m_xTabPage->Reset(pSet); +} + +IMPL_LINK_NOARG(SwColumnDlg, OkHdl, weld::Button&, void) +{ + // evaluate current selection + SfxItemSet* pSet = EvalCurrentSelection(); + m_xTabPage->FillItemSet(pSet); + + if(m_pSelectionSet && SfxItemState::SET == m_pSelectionSet->GetItemState(RES_COL)) + { + //insert region with columns + const SwFormatCol& rColItem = m_pSelectionSet->Get(RES_COL); + //only if there actually are columns! + if(rColItem.GetNumCols() > 1) + m_rWrtShell.GetView().GetViewFrame().GetDispatcher()->Execute( + FN_INSERT_REGION, SfxCallMode::ASYNCHRON, *m_pSelectionSet ); + } + + if(m_pSectionSet && m_pSectionSet->Count() && m_bSectionChanged ) + { + const SwSection* pCurrSection = m_rWrtShell.GetCurrSection(); + const SwSectionFormat* pFormat = pCurrSection->GetFormat(); + const size_t nNewPos = m_rWrtShell.GetSectionFormatPos( *pFormat ); + SwSectionData aData(*pCurrSection); + m_rWrtShell.UpdateSection( nNewPos, aData, m_pSectionSet.get() ); + } + + if(m_pSectionSet && m_pSectionSet->Count() && m_bSelSectionChanged ) + { + m_rWrtShell.SetSectionAttr( *m_pSectionSet ); + } + + if(m_pPageSet && SfxItemState::SET == m_pPageSet->GetItemState(RES_COL) && m_bPageChanged) + { + // determine current PageDescriptor and fill the Set with it + const size_t nCurIdx = m_rWrtShell.GetCurPageDesc(); + SwPageDesc aPageDesc(m_rWrtShell.GetPageDesc(nCurIdx)); + SwFrameFormat &rFormat = aPageDesc.GetMaster(); + rFormat.SetFormatAttr(m_pPageSet->Get(RES_COL)); + m_rWrtShell.ChgPageDesc(nCurIdx, aPageDesc); + } + if(m_pFrameSet && SfxItemState::SET == m_pFrameSet->GetItemState(RES_COL) && m_bFrameChanged) + { + SfxItemSetFixed<RES_COL, RES_COL> aTmp(*m_pFrameSet->GetPool()); + aTmp.Put(*m_pFrameSet); + m_rWrtShell.StartAction(); + m_rWrtShell.Push(); + m_rWrtShell.SetFlyFrameAttr( aTmp ); + // undo the frame selection again + if(m_rWrtShell.IsFrameSelected()) + { + m_rWrtShell.UnSelectFrame(); + m_rWrtShell.LeaveSelFrameMode(); + } + m_rWrtShell.Pop(); + m_rWrtShell.EndAction(); + } + m_xDialog->response(RET_OK); +} + +SfxItemSet* SwColumnDlg::EvalCurrentSelection() +{ + SfxItemSet* pSet = nullptr; + + switch(m_nOldSelection) + { + case LISTBOX_SELECTION : + pSet = m_pSelectionSet.get(); + break; + case LISTBOX_SECTION : + pSet = m_pSectionSet.get(); + m_bSectionChanged = true; + break; + case LISTBOX_SECTIONS : + pSet = m_pSectionSet.get(); + m_bSelSectionChanged = true; + break; + case LISTBOX_PAGE : + pSet = m_pPageSet.get(); + m_bPageChanged = true; + break; + case LISTBOX_FRAME: + pSet = m_pFrameSet; + m_bFrameChanged = true; + break; + } + + return pSet; +} + +static +sal_uInt16 GetMaxWidth( SwColMgr const * pColMgr, sal_uInt16 nCols ) +{ + sal_uInt16 nMax = pColMgr->GetActualSize(); + if( --nCols ) + nMax -= pColMgr->GetGutterWidth() * nCols; + return nMax; +} + +const WhichRangesContainer SwColumnPage::s_aPageRg(svl::Items<RES_COL, RES_COL>); + +void SwColumnPage::ResetColWidth() +{ + if( m_nCols ) + { + const sal_uInt16 nWidth = GetMaxWidth( m_xColMgr.get(), m_nCols ) / m_nCols; + + for(sal_uInt16 i = 0; i < m_nCols; ++i) + m_nColWidth[i] = static_cast<tools::Long>(nWidth); + } + +} + +constexpr sal_uInt16 g_nMinWidth(MINLAY); + +// Now as TabPage +SwColumnPage::SwColumnPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/columnpage.ui", "ColumnPage", &rSet) + , m_nFirstVis(0) + , m_pModifiedField(nullptr) + , m_bFormat(false) + , m_bFrame(false) + , m_bHtmlMode(false) + , m_bLockUpdate(false) + , m_xCLNrEdt(m_xBuilder->weld_spin_button("colsnf")) + , m_xBalanceColsCB(m_xBuilder->weld_check_button("balance")) + , m_xBtnBack(m_xBuilder->weld_button("back")) + , m_xLbl1(m_xBuilder->weld_label("1")) + , m_xLbl2(m_xBuilder->weld_label("2")) + , m_xLbl3(m_xBuilder->weld_label("3")) + , m_xBtnNext(m_xBuilder->weld_button("next")) + , m_xAutoWidthBox(m_xBuilder->weld_check_button("autowidth")) + , m_xLineTypeLbl(m_xBuilder->weld_label("linestyleft")) + , m_xLineWidthLbl(m_xBuilder->weld_label("linewidthft")) + , m_xLineWidthEdit(m_xBuilder->weld_metric_spin_button("linewidthmf", FieldUnit::POINT)) + , m_xLineColorLbl(m_xBuilder->weld_label("linecolorft")) + , m_xLineHeightLbl(m_xBuilder->weld_label("lineheightft")) + , m_xLineHeightEdit(m_xBuilder->weld_metric_spin_button("lineheightmf", FieldUnit::PERCENT)) + , m_xLinePosLbl(m_xBuilder->weld_label("lineposft")) + , m_xLinePosDLB(m_xBuilder->weld_combo_box("lineposlb")) + , m_xTextDirectionFT(m_xBuilder->weld_label("textdirectionft")) + , m_xTextDirectionLB(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("textdirectionlb"))) + , m_xLineColorDLB(new ColorListBox(m_xBuilder->weld_menu_button("colorlb"), + [this]{ return GetFrameWeld(); })) + , m_xLineTypeDLB(new SvtLineListBox(m_xBuilder->weld_menu_button("linestylelb"))) + , m_xEd1(new SwPercentField(m_xBuilder->weld_metric_spin_button("width1mf", FieldUnit::CM))) + , m_xEd2(new SwPercentField(m_xBuilder->weld_metric_spin_button("width2mf", FieldUnit::CM))) + , m_xEd3(new SwPercentField(m_xBuilder->weld_metric_spin_button("width3mf", FieldUnit::CM))) + , m_xDistEd1(new SwPercentField(m_xBuilder->weld_metric_spin_button("spacing1mf", FieldUnit::CM))) + , m_xDistEd2(new SwPercentField(m_xBuilder->weld_metric_spin_button("spacing2mf", FieldUnit::CM))) + , m_xDefaultVS(new weld::CustomWeld(*m_xBuilder, "valueset", m_aDefaultVS)) + , m_xPgeExampleWN(new weld::CustomWeld(*m_xBuilder, "pageexample", m_aPgeExampleWN)) + , m_xFrameExampleWN(new weld::CustomWeld(*m_xBuilder, "frameexample", m_aFrameExampleWN)) + , m_xApplyToFT(m_xBuilder->weld_label("applytoft")) + , m_xApplyToLB(m_xBuilder->weld_combo_box("applytolb")) +{ + connectPercentField(*m_xEd1); + connectPercentField(*m_xEd2); + connectPercentField(*m_xEd3); + connectPercentField(*m_xDistEd1); + connectPercentField(*m_xDistEd2); + + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xTextDirectionLB->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); + m_xTextDirectionLB->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + + SetExchangeSupport(); + + m_aDefaultVS.SetColCount(5); + + for (int i = 0; i < 5; ++i) + //Set accessible name one by one + { + OUString aItemText; + switch( i ) + { + case 0: + aItemText = SwResId( STR_COLUMN_VALUESET_ITEM0 ) ; + break; + case 1: + aItemText = SwResId( STR_COLUMN_VALUESET_ITEM1 ) ; + break; + case 2: + aItemText = SwResId( STR_COLUMN_VALUESET_ITEM2 ) ; + break; + case 3: + aItemText = SwResId( STR_COLUMN_VALUESET_ITEM3 ); + break; + default: + aItemText = SwResId( STR_COLUMN_VALUESET_ITEM4 ); + break; + } + m_aDefaultVS.InsertItem( i + 1, aItemText, i ); + } + + m_aDefaultVS.SetSelectHdl(LINK(this, SwColumnPage, SetDefaultsHdl)); + + Link<weld::SpinButton&,void> aCLNrLk = LINK(this, SwColumnPage, ColModify); + m_xCLNrEdt->connect_value_changed(aCLNrLk); + Link<weld::MetricSpinButton&,void> aLk = LINK(this, SwColumnPage, GapModify); + m_xDistEd1->connect_value_changed(aLk); + m_xDistEd2->connect_value_changed(aLk); + + aLk = LINK(this, SwColumnPage, EdModify); + + m_xEd1->connect_value_changed(aLk); + m_xEd2->connect_value_changed(aLk); + m_xEd3->connect_value_changed(aLk); + + m_xBtnBack->connect_clicked(LINK(this, SwColumnPage, Up)); + m_xBtnNext->connect_clicked(LINK(this, SwColumnPage, Down)); + m_xAutoWidthBox->connect_toggled(LINK(this, SwColumnPage, AutoWidthHdl)); + + Link<weld::MetricSpinButton&,void> aLk2 = LINK( this, SwColumnPage, UpdateColMgr ); + m_xLineTypeDLB->SetSelectHdl(LINK(this, SwColumnPage, UpdateColMgrLineBox)); + m_xLineWidthEdit->connect_value_changed(aLk2); + m_xLineColorDLB->SetSelectHdl(LINK( this, SwColumnPage, UpdateColMgrColorBox)); + m_xLineHeightEdit->connect_value_changed(aLk2); + m_xLinePosDLB->connect_changed(LINK(this, SwColumnPage, UpdateColMgrListBox)); + + // Separator line + m_xLineTypeDLB->SetSourceUnit( FieldUnit::TWIP ); + + // Fill the line styles listbox + m_xLineTypeDLB->InsertEntry( + ::editeng::SvxBorderLine::getWidthImpl(SvxBorderLineStyle::SOLID), + SvxBorderLineStyle::SOLID ); + m_xLineTypeDLB->InsertEntry( + ::editeng::SvxBorderLine::getWidthImpl(SvxBorderLineStyle::DOTTED), + SvxBorderLineStyle::DOTTED ); + m_xLineTypeDLB->InsertEntry( + ::editeng::SvxBorderLine::getWidthImpl(SvxBorderLineStyle::DASHED), + SvxBorderLineStyle::DASHED ); + + sal_Int64 nLineWidth = m_xLineWidthEdit->get_value(FieldUnit::POINT); + nLineWidth = static_cast<tools::Long>(vcl::ConvertDoubleValue( + nLineWidth, + m_xLineWidthEdit->get_digits(), + FieldUnit::POINT, MapUnit::MapTwip )); + m_xLineTypeDLB->SetWidth(nLineWidth); + m_xLineColorDLB->SelectEntry(COL_BLACK); +} + +SwColumnPage::~SwColumnPage() +{ + m_xFrameExampleWN.reset(); + m_xPgeExampleWN.reset(); + m_xDefaultVS.reset(); + m_xDistEd2.reset(); + m_xDistEd1.reset(); + m_xEd3.reset(); + m_xEd2.reset(); + m_xEd1.reset(); + m_xLineTypeDLB.reset(); + m_xLineColorDLB.reset(); + m_xTextDirectionLB.reset(); +} + +void SwColumnPage::SetPageWidth(tools::Long nPageWidth) +{ + tools::Long nNewMaxWidth = static_cast< tools::Long >(m_xEd1->NormalizePercent(nPageWidth)); + + m_xDistEd1->set_max(nNewMaxWidth, FieldUnit::TWIP); + m_xDistEd2->set_max(nNewMaxWidth, FieldUnit::TWIP); + m_xEd1->set_max(nNewMaxWidth, FieldUnit::TWIP); + m_xEd2->set_max(nNewMaxWidth, FieldUnit::TWIP); + m_xEd3->set_max(nNewMaxWidth, FieldUnit::TWIP); +} + +void SwColumnPage::connectPercentField(SwPercentField &rWrap) +{ + weld::MetricSpinButton *pField = rWrap.get(); + assert(pField); + m_aPercentFieldsMap[pField] = &rWrap; +} + +void SwColumnPage::Reset(const SfxItemSet *rSet) +{ + const sal_uInt16 nHtmlMode = + ::GetHtmlMode(static_cast<const SwDocShell*>(SfxObjectShell::Current())); + if(nHtmlMode & HTMLMODE_ON) + { + m_bHtmlMode = true; + m_xAutoWidthBox->set_sensitive(false); + } + FieldUnit aMetric = ::GetDfltMetric(m_bHtmlMode); + m_xEd1->SetMetric(aMetric); + m_xEd2->SetMetric(aMetric); + m_xEd3->SetMetric(aMetric); + m_xDistEd1->SetMetric(aMetric); + m_xDistEd2->SetMetric(aMetric); + //default spacing between cols = 0.5cm + m_xDistEd1->set_value(50, FieldUnit::CM); + m_xDistEd2->set_value(50, FieldUnit::CM); + + m_xColMgr.reset(new SwColMgr(*rSet)); + m_nCols = m_xColMgr->GetCount() ; + m_xCLNrEdt->set_max(std::max(o3tl::narrowing<sal_uInt16>(m_xCLNrEdt->get_max()), m_nCols)); + + if(m_bFrame) + { + if(m_bFormat) // there is no size here + m_xColMgr->SetActualWidth(FRAME_FORMAT_WIDTH); + else + { + const SwFormatFrameSize& rSize = rSet->Get(RES_FRM_SIZE); + const SvxBoxItem& rBox = rSet->Get(RES_BOX); + m_xColMgr->SetActualWidth(o3tl::narrowing<sal_uInt16>(rSize.GetSize().Width()) - rBox.GetSmallestDistance()); + } + } + if (m_xBalanceColsCB->get_visible()) + { + if( const SwFormatNoBalancedColumns* pItem = rSet->GetItemIfSet( RES_COLUMNBALANCE, false ) ) + m_xBalanceColsCB->set_active(!pItem->GetValue()); + else + m_xBalanceColsCB->set_active(true); + } + + //text direction + if( SfxItemState::DEFAULT <= rSet->GetItemState( RES_FRAMEDIR ) ) + { + const SvxFrameDirectionItem& rItem = rSet->Get(RES_FRAMEDIR); + SvxFrameDirection nVal = rItem.GetValue(); + m_xTextDirectionLB->set_active_id(nVal); + m_xTextDirectionLB->save_value(); + } + + Init(); + ActivatePage( *rSet ); +} + +// create TabPage +std::unique_ptr<SfxTabPage> SwColumnPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwColumnPage>(pPage, pController, *rSet); +} + +// stuff attributes into the Set when OK +bool SwColumnPage::FillItemSet(SfxItemSet *rSet) +{ + // set in ItemSet; + // the current settings are already present + + const SfxPoolItem* pOldItem; + const SwFormatCol& rCol = m_xColMgr->GetColumns(); + if(nullptr == (pOldItem = GetOldItem( *rSet, RES_COL )) || + rCol != *pOldItem ) + rSet->Put(rCol); + + if (m_xBalanceColsCB->get_visible()) + { + rSet->Put(SwFormatNoBalancedColumns(!m_xBalanceColsCB->get_active())); + } + if (m_xTextDirectionLB->get_visible()) + { + if (m_xTextDirectionLB->get_value_changed_from_saved()) + { + rSet->Put(SvxFrameDirectionItem(m_xTextDirectionLB->get_active_id(), RES_FRAMEDIR) ); + } + } + return true; +} + +// update ColumnManager +IMPL_LINK_NOARG( SwColumnPage, UpdateColMgrListBox, weld::ComboBox&, void ) +{ + UpdateColMgr(*m_xLineWidthEdit); +} + +IMPL_LINK_NOARG( SwColumnPage, UpdateColMgrLineBox, SvtLineListBox&, void ) +{ + UpdateColMgr(*m_xLineWidthEdit); +} + +IMPL_LINK_NOARG( SwColumnPage, UpdateColMgrColorBox, ColorListBox&, void ) +{ + UpdateColMgr(*m_xLineWidthEdit); +} + +IMPL_LINK_NOARG( SwColumnPage, UpdateColMgr, weld::MetricSpinButton&, void ) +{ + if (!m_xColMgr) + return; + tools::Long nGutterWidth = m_xColMgr->GetGutterWidth(); + if (m_nCols > 1) + { + // Determine whether the most narrow column is too narrow + // for the adjusted column gap + tools::Long nMin = m_nColWidth[0]; + + for( sal_uInt16 i = 1; i < m_nCols; ++i ) + nMin = std::min(nMin, m_nColWidth[i]); + + bool bAutoWidth = m_xAutoWidthBox->get_active(); + if(!bAutoWidth) + { + m_xColMgr->SetAutoWidth(false); + // when the user didn't allocate the whole width, + // add the missing amount to the last column. + tools::Long nSum = 0; + for(sal_uInt16 i = 0; i < m_nCols; ++i) + nSum += m_nColWidth[i]; + nGutterWidth = 0; + for(sal_uInt16 i = 0; i < m_nCols - 1; ++i) + nGutterWidth += m_nColDist[i]; + nSum += nGutterWidth; + + tools::Long nMaxW = m_xColMgr->GetActualSize(); + + if( nSum < nMaxW ) + m_nColWidth[m_nCols - 1] += nMaxW - nSum; + + m_xColMgr->SetColWidth( 0, static_cast< sal_uInt16 >(m_nColWidth[0] + m_nColDist[0]/2) ); + for( sal_uInt16 i = 1; i < m_nCols-1; ++i ) + { + tools::Long nActDist = (m_nColDist[i] + m_nColDist[i - 1]) / 2; + m_xColMgr->SetColWidth( i, static_cast< sal_uInt16 >(m_nColWidth[i] + nActDist )); + } + m_xColMgr->SetColWidth( m_nCols-1, static_cast< sal_uInt16 >(m_nColWidth[m_nCols-1] + m_nColDist[m_nCols -2]/2) ); + + } + + bool bEnable = isLineNotNone(); + m_xLineHeightEdit->set_sensitive(bEnable); + m_xLineHeightLbl->set_sensitive(bEnable); + m_xLineWidthLbl->set_sensitive(bEnable); + m_xLineWidthEdit->set_sensitive(bEnable); + m_xLineColorDLB->set_sensitive(bEnable); + m_xLineColorLbl->set_sensitive(bEnable); + + sal_Int64 nLineWidth = m_xLineWidthEdit->get_value(FieldUnit::PERCENT); + nLineWidth = static_cast<tools::Long>(vcl::ConvertDoubleValue( + nLineWidth, + m_xLineWidthEdit->get_digits(), + m_xLineWidthEdit->get_unit(), MapUnit::MapTwip )); + if( !bEnable ) + m_xColMgr->SetNoLine(); + else + { + m_xColMgr->SetLineWidthAndColor( + m_xLineTypeDLB->GetSelectEntryStyle(), + nLineWidth, + m_xLineColorDLB->GetSelectEntryColor() ); + m_xColMgr->SetAdjust(SwColLineAdj(m_xLinePosDLB->get_active() + 1)); + m_xColMgr->SetLineHeightPercent(static_cast<short>(m_xLineHeightEdit->get_value(FieldUnit::PERCENT))); + bEnable = m_xColMgr->GetLineHeightPercent() != 100; + } + m_xLinePosLbl->set_sensitive(bEnable); + m_xLinePosDLB->set_sensitive(bEnable); + + //fdo#66815 if the values are going to be the same, don't update + //them to avoid the listbox selection resetting + if (nLineWidth != m_xLineTypeDLB->GetWidth()) + m_xLineTypeDLB->SetWidth(nLineWidth); + Color aColor(m_xLineColorDLB->GetSelectEntryColor()); + if (aColor != m_xLineTypeDLB->GetColor()) + m_xLineTypeDLB->SetColor(aColor); + } + else + { + m_xColMgr->NoCols(); + m_nCols = 0; + } + + //set maximum values + m_xCLNrEdt->set_max(std::max(tools::Long(1), + std::min(tools::Long(nMaxCols), tools::Long(m_xColMgr->GetActualSize() / (nGutterWidth + MINLAY)) ))); + + //prompt example window + if(!m_bLockUpdate) + { + if(m_bFrame) + { + m_aFrameExampleWN.SetColumns(m_xColMgr->GetColumns()); + m_aFrameExampleWN.Invalidate(); + } + else + m_aPgeExampleWN.Invalidate(); + } +} + +void SwColumnPage::Init() +{ + m_xCLNrEdt->set_value(m_nCols); + + bool bAutoWidth = m_xColMgr->IsAutoWidth() || m_bHtmlMode; + m_xAutoWidthBox->set_active(bAutoWidth); + + sal_Int32 nColumnWidthSum = 0; + // set the widths + for(sal_uInt16 i = 0; i < m_nCols; ++i) + { + m_nColWidth[i] = m_xColMgr->GetColWidth(i); + nColumnWidthSum += m_nColWidth[i]; + if(i < m_nCols - 1) + m_nColDist[i] = m_xColMgr->GetGutterWidth(i); + } + + if( 1 < m_nCols ) + { + // #97495# make sure that the automatic column width's are always equal + if(bAutoWidth) + { + nColumnWidthSum /= m_nCols; + for(sal_uInt16 i = 0; i < m_nCols; ++i) + m_nColWidth[i] = nColumnWidthSum; + } + SwColLineAdj eAdj = m_xColMgr->GetAdjust(); + if( COLADJ_NONE == eAdj ) // the dialog doesn't know a NONE! + { + eAdj = COLADJ_TOP; + //without Adjust no line type + m_xLineTypeDLB->SelectEntry(SvxBorderLineStyle::NONE); + m_xLineHeightEdit->set_value(100, FieldUnit::PERCENT); + } + else + { + // Need to multiply by 100 because of the 2 decimals + m_xLineWidthEdit->set_value( m_xColMgr->GetLineWidth() * 100, FieldUnit::TWIP); + m_xLineColorDLB->SelectEntry( m_xColMgr->GetLineColor() ); + m_xLineTypeDLB->SelectEntry( m_xColMgr->GetLineStyle() ); + m_xLineTypeDLB->SetWidth( m_xColMgr->GetLineWidth( ) ); + m_xLineHeightEdit->set_value(m_xColMgr->GetLineHeightPercent(), FieldUnit::PERCENT); + + } + m_xLinePosDLB->set_active( static_cast< sal_Int32 >(eAdj - 1) ); + } + else + { + m_xLinePosDLB->set_active(0); + m_xLineTypeDLB->SelectEntry(SvxBorderLineStyle::NONE); + m_xLineHeightEdit->set_value(100, FieldUnit::PERCENT); + } + + UpdateCols(); + Update(nullptr); + + // set maximum number of columns + // values below 1 are not allowed + m_xCLNrEdt->set_max(std::max(tools::Long(1), + std::min(tools::Long(nMaxCols), tools::Long(m_xColMgr->GetActualSize() / g_nMinWidth) ))); +} + +bool SwColumnPage::isLineNotNone() const +{ + // nothing is turned off + return m_xLineTypeDLB->GetSelectEntryStyle() != SvxBorderLineStyle::NONE; +} + +/* + * The number of columns has changed -- here the controls for editing of the + * columns are en- or disabled according to the column number. In case there are + * more than nVisCols (=3) all Edit are being enabled and the buttons for + * scrolling too. Otherwise Edits are being enabled according to the column + * numbers; one column can not be edited. + */ +void SwColumnPage::UpdateCols() +{ + bool bEnableBtns= false; + bool bEnable12 = false; + bool bEnable3 = false; + const bool bEdit = !m_xAutoWidthBox->get_active(); + if ( m_nCols > nVisCols ) + { + bEnableBtns = !m_bHtmlMode; + bEnable12 = bEnable3 = bEdit; + } + else if( bEdit ) + { + // here are purposely hardly any breaks + switch(m_nCols) + { + case 3: bEnable3 = true; + [[fallthrough]]; + case 2: bEnable12= true; break; + default: /* do nothing */; + } + } + m_xEd1->set_sensitive(bEnable12); + bool bEnable = m_nCols > 1; + m_xDistEd1->set_sensitive(bEnable); + m_xAutoWidthBox->set_sensitive(bEnable && !m_bHtmlMode); + m_xEd2->set_sensitive(bEnable12); + m_xDistEd2->set_sensitive(bEnable3); + m_xEd3->set_sensitive(bEnable3); + m_xLbl1->set_sensitive(bEnable12); + m_xLbl2->set_sensitive(bEnable12); + m_xLbl3->set_sensitive(bEnable3); + m_xBtnBack->set_sensitive(bEnableBtns); + m_xBtnNext->set_sensitive(bEnableBtns); + + m_xLineTypeDLB->set_sensitive( bEnable ); + m_xLineTypeLbl->set_sensitive( bEnable ); + + if (bEnable) + { + bEnable = isLineNotNone(); + } + + //all these depend on > 1 column and line style != none + m_xLineHeightEdit->set_sensitive(bEnable); + m_xLineHeightLbl->set_sensitive(bEnable); + m_xLineWidthLbl->set_sensitive(bEnable); + m_xLineWidthEdit->set_sensitive(bEnable); + m_xLineColorDLB->set_sensitive(bEnable); + m_xLineColorLbl->set_sensitive(bEnable); + + if (bEnable) + bEnable = m_xColMgr->GetLineHeightPercent() != 100; + + //and these additionally depend on line height != 100% + m_xLinePosDLB->set_sensitive(bEnable); + m_xLinePosLbl->set_sensitive(bEnable); +} + +void SwColumnPage::SetLabels( sal_uInt16 nVis ) +{ + //insert ~ before the last character, e.g. 1 -> ~1, 10 -> 1~0 + const OUString sLbl( '~' ); + + const OUString sLbl1(OUString::number( nVis + 1 )); + m_xLbl1->set_label(sLbl1.replaceAt(sLbl1.getLength()-1, 0, sLbl)); + + const OUString sLbl2(OUString::number( nVis + 2 )); + m_xLbl2->set_label(sLbl2.replaceAt(sLbl2.getLength()-1, 0, sLbl)); + + const OUString sLbl3(OUString::number( nVis + 3 )); + m_xLbl3->set_label(sLbl3.replaceAt(sLbl3.getLength()-1, 0, sLbl)); + + const OUString sColumnWidth = SwResId( STR_ACCESS_COLUMN_WIDTH ) ; + m_xEd1->set_accessible_name(sColumnWidth.replaceFirst("%1", sLbl1)); + m_xEd2->set_accessible_name(sColumnWidth.replaceFirst("%1", sLbl2)); + m_xEd3->set_accessible_name(sColumnWidth.replaceFirst("%1", sLbl3)); + + const OUString sDist = SwResId( STR_ACCESS_PAGESETUP_SPACING ) ; + m_xDistEd1->set_accessible_name( + sDist.replaceFirst("%1", sLbl1).replaceFirst("%2", sLbl2)); + + m_xDistEd2->set_accessible_name( + sDist.replaceFirst("%1", sLbl2).replaceFirst("%2", sLbl3)); +} + +/* + * Handler that is called at alteration of the column number. An alteration of + * the column number overwrites potential user's width settings; all columns + * are equally wide. + */ +IMPL_LINK_NOARG(SwColumnPage, ColModify, weld::SpinButton&, void) +{ + ColModify(/*bForceColReset=*/false); +} + +void SwColumnPage::ColModify(bool bForceColReset) +{ + m_nCols = o3tl::narrowing<sal_uInt16>(m_xCLNrEdt->get_value()); + //#107890# the handler is also called from LoseFocus() + //then no change has been made and thus no action should be taken + // #i17816# changing the displayed types within the ValueSet + //from two columns to two columns with different settings doesn't invalidate the + // example windows in ::ColModify() + if (!bForceColReset && m_xColMgr->GetCount() == m_nCols) + return; + + if (!bForceColReset) + m_aDefaultVS.SetNoSelection(); + tools::Long nDist = static_cast< tools::Long >(m_xDistEd1->DenormalizePercent(m_xDistEd1->get_value(FieldUnit::TWIP))); + m_xColMgr->SetCount(m_nCols, o3tl::narrowing<sal_uInt16>(nDist)); + for(sal_uInt16 i = 0; i < m_nCols; i++) + m_nColDist[i] = nDist; + m_nFirstVis = 0; + SetLabels( m_nFirstVis ); + UpdateCols(); + ResetColWidth(); + Update(nullptr); +} + +/* + * Modify handler for an alteration of the column width or the column gap. + * These changes take effect time-displaced. With an alteration of the column + * width the automatic calculation of the column width is overruled; only an + * alteration of the column number leads back to that default. + */ +IMPL_LINK(SwColumnPage, GapModify, weld::MetricSpinButton&, rMetricField, void) +{ + if (m_nCols < 2) + return; + SwPercentField *pField = m_aPercentFieldsMap[&rMetricField]; + assert(pField); + tools::Long nActValue = static_cast< tools::Long >(pField->DenormalizePercent(pField->get_value(FieldUnit::TWIP))); + if (m_xAutoWidthBox->get_active()) + { + const tools::Long nMaxGap = static_cast< tools::Long > + ((m_xColMgr->GetActualSize() - m_nCols * MINLAY)/(m_nCols - 1)); + if(nActValue > nMaxGap) + { + nActValue = nMaxGap; + m_xDistEd1->set_value(m_xDistEd1->NormalizePercent(nMaxGap), FieldUnit::TWIP); + } + m_xColMgr->SetGutterWidth(o3tl::narrowing<sal_uInt16>(nActValue)); + for(sal_uInt16 i = 0; i < m_nCols; i++) + m_nColDist[i] = nActValue; + + ResetColWidth(); + UpdateCols(); + } + else + { + const sal_uInt16 nVis = m_nFirstVis + ((pField == m_xDistEd2.get()) ? 1 : 0); + tools::Long nDiff = nActValue - m_nColDist[nVis]; + if(nDiff) + { + tools::Long nLeft = m_nColWidth[nVis]; + tools::Long nRight = m_nColWidth[nVis + 1]; + if(nLeft + nRight + 2 * MINLAY < nDiff) + nDiff = nLeft + nRight - 2 * MINLAY; + if(nDiff < nRight - MINLAY) + { + nRight -= nDiff; + } + else + { + tools::Long nTemp = nDiff - nRight + MINLAY; + nRight = MINLAY; + if(nLeft > nTemp - MINLAY) + { + nLeft -= nTemp; + nTemp = 0; + } + else + { + nTemp -= nLeft + MINLAY; + nLeft = MINLAY; + } + nDiff = nTemp; + } + m_nColWidth[nVis] = nLeft; + m_nColWidth[nVis + 1] = nRight; + m_nColDist[nVis] += nDiff; + + m_xColMgr->SetColWidth( nVis, sal_uInt16(nLeft) ); + m_xColMgr->SetColWidth( nVis + 1, sal_uInt16(nRight) ); + m_xColMgr->SetGutterWidth( sal_uInt16(m_nColDist[nVis]), nVis ); + } + + } + Update(&rMetricField); +} + +IMPL_LINK(SwColumnPage, EdModify, weld::MetricSpinButton&, rEdit, void) +{ + SwPercentField *pField = m_aPercentFieldsMap[&rEdit]; + assert(pField); + m_pModifiedField = pField; + Timeout(); +} + +// Handler behind the Checkbox for automatic width. When the box is checked +// no explicit values for the column width can be entered. +IMPL_LINK(SwColumnPage, AutoWidthHdl, weld::Toggleable&, rBox, void) +{ + tools::Long nDist = static_cast< tools::Long >(m_xDistEd1->DenormalizePercent(m_xDistEd1->get_value(FieldUnit::TWIP))); + m_xColMgr->SetCount(m_nCols, o3tl::narrowing<sal_uInt16>(nDist)); + for(sal_uInt16 i = 0; i < m_nCols; i++) + m_nColDist[i] = nDist; + if (rBox.get_active()) + { + m_xColMgr->SetGutterWidth(sal_uInt16(nDist)); + ResetColWidth(); + } + m_xColMgr->SetAutoWidth(rBox.get_active(), sal_uInt16(nDist)); + UpdateCols(); + Update(nullptr); +} + +// scroll up the contents of the edits +IMPL_LINK_NOARG(SwColumnPage, Up, weld::Button&, void) +{ + if( m_nFirstVis ) + { + --m_nFirstVis; + SetLabels( m_nFirstVis ); + Update(nullptr); + } +} + +// scroll down the contents of the edits. +IMPL_LINK_NOARG(SwColumnPage, Down, weld::Button&, void) +{ + if( m_nFirstVis + nVisCols < m_nCols ) + { + ++m_nFirstVis; + SetLabels( m_nFirstVis ); + Update(nullptr); + } +} + +// relict from ancient times - now directly without time handler; triggered by +// an alteration of the column width or the column gap. +void SwColumnPage::Timeout() +{ + SwPercentField *pField = m_pModifiedField; + if (m_pModifiedField) + { + // find the changed column + sal_uInt16 nChanged = m_nFirstVis; + if (m_pModifiedField == m_xEd2.get()) + ++nChanged; + else if (m_pModifiedField == m_xEd3.get()) + nChanged += 2; + + tools::Long nNewWidth = static_cast< tools::Long > + (m_pModifiedField->DenormalizePercent(m_pModifiedField->get_value(FieldUnit::TWIP))); + tools::Long nDiff = nNewWidth - m_nColWidth[nChanged]; + + // when it's the last column + if(nChanged == m_nCols - 1) + { + m_nColWidth[0] -= nDiff; + if(m_nColWidth[0] < static_cast<tools::Long>(g_nMinWidth)) + { + nNewWidth -= g_nMinWidth - m_nColWidth[0]; + m_nColWidth[0] = g_nMinWidth; + } + + } + else if(nDiff) + { + m_nColWidth[nChanged + 1] -= nDiff; + if(m_nColWidth[nChanged + 1] < static_cast<tools::Long>(g_nMinWidth)) + { + nNewWidth -= g_nMinWidth - m_nColWidth[nChanged + 1]; + m_nColWidth[nChanged + 1] = g_nMinWidth; + } + } + m_nColWidth[nChanged] = nNewWidth; + m_pModifiedField = nullptr; + } + + Update(pField ? pField->get() : nullptr); +} + +// Update the view +void SwColumnPage::Update(const weld::MetricSpinButton* pInteractiveField) +{ + m_xBalanceColsCB->set_sensitive(m_nCols > 1); + if(m_nCols >= 2) + { + sal_Int64 nCurrentValue, nNewValue; + + nCurrentValue = m_xEd1->NormalizePercent(m_xEd1->DenormalizePercent(m_xEd1->get_value(FieldUnit::TWIP))); + nNewValue = m_xEd1->NormalizePercent(m_nColWidth[m_nFirstVis]); + + //fdo#87612 if we're interacting with this widget and the value will be the same + //then leave it alone (i.e. don't change equivalent values of e.g. .8 -> 0.8) + if (nNewValue != nCurrentValue || pInteractiveField != m_xEd1->get()) + m_xEd1->set_value(nNewValue, FieldUnit::TWIP); + + nCurrentValue = m_xDistEd1->NormalizePercent(m_xDistEd1->DenormalizePercent(m_xDistEd1->get_value(FieldUnit::TWIP))); + nNewValue = m_xDistEd1->NormalizePercent(m_nColDist[m_nFirstVis]); + if (nNewValue != nCurrentValue || pInteractiveField != m_xDistEd1->get()) + m_xDistEd1->set_value(nNewValue, FieldUnit::TWIP); + + nCurrentValue = m_xEd2->NormalizePercent(m_xEd2->DenormalizePercent(m_xEd2->get_value(FieldUnit::TWIP))); + nNewValue = m_xEd2->NormalizePercent(m_nColWidth[m_nFirstVis+1]); + if (nNewValue != nCurrentValue || pInteractiveField != m_xEd2->get()) + m_xEd2->set_value(nNewValue, FieldUnit::TWIP); + + if(m_nCols >= 3) + { + nCurrentValue = m_xDistEd2->NormalizePercent(m_xDistEd2->DenormalizePercent(m_xDistEd2->get_value(FieldUnit::TWIP))); + nNewValue = m_xDistEd2->NormalizePercent(m_nColDist[m_nFirstVis+1]); + if (nNewValue != nCurrentValue || pInteractiveField != m_xDistEd2->get()) + m_xDistEd2->set_value(nNewValue, FieldUnit::TWIP); + + nCurrentValue = m_xEd3->NormalizePercent(m_xEd3->DenormalizePercent(m_xEd3->get_value(FieldUnit::TWIP))); + nNewValue = m_xEd3->NormalizePercent(m_nColWidth[m_nFirstVis+2]); + if (nNewValue != nCurrentValue || pInteractiveField != m_xEd3->get()) + m_xEd3->set_value(nNewValue, FieldUnit::TWIP); + } + else + { + m_xEd3->set_text(OUString()); + m_xDistEd2->set_text(OUString()); + } + } + else + { + m_xEd1->set_text(OUString()); + m_xEd2->set_text(OUString()); + m_xEd3->set_text(OUString()); + m_xDistEd1->set_text(OUString()); + m_xDistEd2->set_text(OUString()); + } + UpdateColMgr(*m_xLineWidthEdit); +} + +// Update Bsp +void SwColumnPage::ActivatePage(const SfxItemSet& rSet) +{ + bool bVertical = false; + if (SfxItemState::DEFAULT <= rSet.GetItemState(RES_FRAMEDIR)) + { + const SvxFrameDirectionItem& rDirItem = + rSet.Get(RES_FRAMEDIR); + bVertical = rDirItem.GetValue() == SvxFrameDirection::Vertical_RL_TB|| + rDirItem.GetValue() == SvxFrameDirection::Vertical_LR_TB; + } + + if (!m_bFrame) + { + if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_PAGE_SIZE )) + { + const SvxSizeItem& rSize = rSet.Get(SID_ATTR_PAGE_SIZE); + + sal_uInt16 nActWidth; + + if (!bVertical) + { + const SvxLRSpaceItem& rLRSpace = rSet.Get(RES_LR_SPACE); + const SvxBoxItem& rBox = rSet.Get(RES_BOX); + nActWidth = rSize.GetSize().Width() + - rLRSpace.GetLeft() - rLRSpace.GetRight() - rBox.GetSmallestDistance(); + } + else + { + const SvxULSpaceItem& rULSpace = rSet.Get( RES_UL_SPACE ); + const SvxBoxItem& rBox = rSet.Get(RES_BOX); + nActWidth = rSize.GetSize().Height() + - rULSpace.GetUpper() - rULSpace.GetLower() - rBox.GetSmallestDistance(); + + } + + if( m_xColMgr->GetActualSize() != nActWidth) + { + m_xColMgr->SetActualWidth(nActWidth); + ColModify(/*bForceColReset=*/false); + UpdateColMgr( *m_xLineWidthEdit ); + } + } + m_xFrameExampleWN->hide(); + m_aPgeExampleWN.UpdateExample(rSet, m_xColMgr.get()); + m_xPgeExampleWN->show(); + + } + else + { + m_xPgeExampleWN->hide(); + m_xFrameExampleWN->show(); + + // Size + const SwFormatFrameSize& rSize = rSet.Get(RES_FRM_SIZE); + const SvxBoxItem& rBox = rSet.Get(RES_BOX); + + sal_uInt16 nTotalWish; + if (m_bFormat) + nTotalWish = FRAME_FORMAT_WIDTH; + else + { + tools::Long const nDistance = rBox.GetSmallestDistance(); + nTotalWish = (!bVertical ? rSize.GetWidth() : rSize.GetHeight()) - 2 * nDistance; + } + + // set maximum values of column width + SetPageWidth(nTotalWish); + + if(m_xColMgr->GetActualSize() != nTotalWish) + { + m_xColMgr->SetActualWidth(nTotalWish); + Init(); + } + bool bPercent; + // only relative data in frame format + if ( m_bFormat || (rSize.GetWidthPercent() && rSize.GetWidthPercent() != SwFormatFrameSize::SYNCED) ) + { + // set value for 100% + m_xEd1->SetRefValue(nTotalWish); + m_xEd2->SetRefValue(nTotalWish); + m_xEd3->SetRefValue(nTotalWish); + m_xDistEd1->SetRefValue(nTotalWish); + m_xDistEd2->SetRefValue(nTotalWish); + + // switch to %-view + bPercent = true; + } + else + bPercent = false; + + m_xEd1->ShowPercent(bPercent); + m_xEd2->ShowPercent(bPercent); + m_xEd3->ShowPercent(bPercent); + m_xDistEd1->ShowPercent(bPercent); + m_xDistEd2->ShowPercent(bPercent); + m_xDistEd1->SetMetricFieldMin(0); + m_xDistEd2->SetMetricFieldMin(0); + } + Update(nullptr); +} + +DeactivateRC SwColumnPage::DeactivatePage(SfxItemSet *_pSet) +{ + if(_pSet) + FillItemSet(_pSet); + + return DeactivateRC::LeavePage; +} + +IMPL_LINK(SwColumnPage, SetDefaultsHdl, ValueSet *, pVS, void) +{ + const sal_uInt16 nItem = pVS->GetSelectedItemId(); + if( nItem < 4 ) + { + m_xCLNrEdt->set_value(nItem); + m_xAutoWidthBox->set_active(true); + m_xDistEd1->set_value(50, FieldUnit::CM); + ColModify(/*bForceColReset=*/true); + } + else + { + m_bLockUpdate = true; + m_xCLNrEdt->set_value(2); + m_xAutoWidthBox->set_active(false); + m_xDistEd1->set_value(50, FieldUnit::CM); + ColModify(/*bForceColReset=*/true); + // now set the width ratio to 2 : 1 or 1 : 2 respectively + const tools::Long nSmall = static_cast< tools::Long >(m_xColMgr->GetActualSize() / 3); + if(nItem == 4) + { + m_xEd2->set_value(m_xEd2->NormalizePercent(nSmall), FieldUnit::TWIP); + m_pModifiedField = m_xEd2.get(); + } + else + { + m_xEd1->set_value(m_xEd1->NormalizePercent(nSmall), FieldUnit::TWIP); + m_pModifiedField = m_xEd1.get(); + } + m_bLockUpdate = false; + Timeout(); + + } +} + +void SwColumnPage::SetFrameMode(bool bMod) +{ + m_bFrame = bMod; +} + +void SwColumnPage::SetInSection(bool bSet) +{ + if(!SvtCTLOptions::IsCTLFontEnabled()) + return; + + m_xTextDirectionFT->set_visible(bSet); + m_xTextDirectionLB->set_visible(bSet); +} + +void ColumnValueSet::UserDraw(const UserDrawEvent& rUDEvt) +{ + vcl::RenderContext* pDev = rUDEvt.GetRenderContext(); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + + tools::Rectangle aRect = rUDEvt.GetRect(); + const sal_uInt16 nItemId = rUDEvt.GetItemId(); + tools::Long nRectWidth = aRect.GetWidth(); + tools::Long nRectHeight = aRect.GetHeight(); + + Point aBLPos = aRect.TopLeft(); + Color aFillColor(pDev->GetFillColor()); + Color aLineColor(pDev->GetLineColor()); + pDev->SetFillColor(rStyleSettings.GetFieldColor()); + pDev->SetLineColor(rStyleSettings.GetFieldTextColor()); + + tools::Long nStep = std::abs(std::abs(nRectHeight * 95 /100) / 11); + tools::Long nTop = (nRectHeight - 11 * nStep ) / 2; + sal_uInt16 nCols = 0; + tools::Long nStarts[3]; + tools::Long nEnds[3]; + nStarts[0] = nRectWidth * 10 / 100; + switch( nItemId ) + { + case 1: + nEnds[0] = nRectWidth * 9 / 10; + nCols = 1; + break; + case 2: nCols = 2; + nEnds[0] = nRectWidth * 45 / 100; + nStarts[1] = nEnds[0] + nStep; + nEnds[1] = nRectWidth * 9 / 10; + break; + case 3: nCols = 3; + nEnds[0] = nRectWidth * 30 / 100; + nStarts[1] = nEnds[0] + nStep; + nEnds[1] = nRectWidth * 63 / 100; + nStarts[2] = nEnds[1] + nStep; + nEnds[2] = nRectWidth * 9 / 10; + break; + case 4: nCols = 2; + nEnds[0] = nRectWidth * 63 / 100; + nStarts[1] = nEnds[0] + nStep; + nEnds[1] = nRectWidth * 9 / 10; + break; + case 5: nCols = 2; + nEnds[0] = nRectWidth * 30 / 100; + nStarts[1] = nEnds[0] + nStep; + nEnds[1] = nRectWidth * 9 / 10; + break; + } + for(sal_uInt16 j = 0; j < nCols; j++ ) + { + Point aStart(aBLPos.X() + nStarts[j], 0); + Point aEnd(aBLPos.X() + nEnds[j], 0); + for( sal_uInt16 i = 0; i < 12; i ++) + { + aStart.setY( aBLPos.Y() + nTop + i * nStep); + aEnd.setY( aStart.Y() ); + pDev->DrawLine(aStart, aEnd); + } + } + pDev->SetFillColor(aFillColor); + pDev->SetLineColor(aLineColor); +} + +void ColumnValueSet::StyleUpdated() +{ + SetFormat(); + Invalidate(); + ValueSet::StyleUpdated(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/frmdlg/cption.cxx b/sw/source/ui/frmdlg/cption.cxx new file mode 100644 index 0000000000..e6b387a429 --- /dev/null +++ b/sw/source/ui/frmdlg/cption.cxx @@ -0,0 +1,537 @@ +/* -*- 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 <utility> +#include <view.hxx> +#include <wrtsh.hxx> +#include <cption.hxx> +#include <fldmgr.hxx> +#include <expfld.hxx> +#include <numrule.hxx> +#include <poolfmt.hxx> +#include <docsh.hxx> +#include <calc.hxx> +#include <uitool.hxx> +#include <doc.hxx> +#include <modcfg.hxx> +#include <swmodule.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp> +#include <com/sun/star/text/XTextTablesSupplier.hpp> +#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp> +#include <com/sun/star/text/XTextFramesSupplier.hpp> +#include <comphelper/string.hxx> +#include <vcl/weld.hxx> +#include <strings.hrc> +#include <SwStyleNameMapper.hxx> + +using namespace ::com::sun::star; + +namespace { + +class SwSequenceOptionDialog : public weld::GenericDialogController +{ + SwView& m_rView; + OUString m_aFieldTypeName; + + std::unique_ptr<weld::ComboBox> m_xLbLevel; + std::unique_ptr<weld::Entry> m_xEdDelim; + + std::unique_ptr<weld::ComboBox> m_xLbCharStyle; + std::unique_ptr<weld::CheckButton> m_xApplyBorderAndShadowCB; + + //#i61007# order of captions + std::unique_ptr<weld::ComboBox> m_xLbCaptionOrder; + +public: + SwSequenceOptionDialog(weld::Window *pParent, SwView &rV, OUString aSeqFieldType); + void Apply(); + + bool IsApplyBorderAndShadow() const { return m_xApplyBorderAndShadowCB->get_active(); } + void SetApplyBorderAndShadow( bool bSet ) { m_xApplyBorderAndShadowCB->set_active(bSet); } + + //#i61007# order of captions + bool IsOrderNumberingFirst() const { return m_xLbCaptionOrder->get_active() == 1; } + void SetOrderNumberingFirst(bool bSet) { m_xLbCaptionOrder->set_active(bSet ? 1 : 0); } + + void SetCharacterStyle(const OUString& rStyle); + OUString GetCharacterStyle() const; +}; + +} + +OUString SwCaptionDialog::s_aSepTextSave(": "); // Caption separator text + +//Resolves: tdf#47427 disallow typing *or* pasting invalid content into the category box +OUString TextFilterAutoConvert::filter(const OUString &rText) +{ + if (!rText.isEmpty() && rText != m_sNone && !SwCalc::IsValidVarName(rText)) + return m_sLastGoodText; + m_sLastGoodText = rText; + return rText; +} + +SwCaptionDialog::SwCaptionDialog(weld::Window *pParent, SwView &rV) + : SfxDialogController(pParent, "modules/swriter/ui/insertcaption.ui", "InsertCaptionDialog") + , m_sNone(SwResId(SW_STR_NONE)) + , m_aTextFilter(m_sNone) + , m_rView(rV) + , m_pMgr(new SwFieldMgr(m_rView.GetWrtShellPtr())) + , m_bCopyAttributes(false) + , m_bOrderNumberingFirst(SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst()) + , m_xTextEdit(m_xBuilder->weld_entry("caption_edit")) + , m_xCategoryBox(m_xBuilder->weld_combo_box("category")) + , m_xFormatText(m_xBuilder->weld_label("numbering_label")) + , m_xFormatBox(m_xBuilder->weld_combo_box("numbering")) + , m_xNumberingSeparatorFT(m_xBuilder->weld_label("num_separator")) + , m_xNumberingSeparatorED(m_xBuilder->weld_entry("num_separator_edit")) + , m_xSepText(m_xBuilder->weld_label("separator_label")) + , m_xSepEdit(m_xBuilder->weld_entry("separator_edit")) + , m_xPosBox(m_xBuilder->weld_combo_box("position")) + , m_xOKButton(m_xBuilder->weld_button("ok")) + , m_xAutoCaptionButton(m_xBuilder->weld_button("auto")) + , m_xOptionButton(m_xBuilder->weld_button("options")) + , m_xPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreview)) +{ + //#i61007# order of captions + ApplyCaptionOrder(); + SwWrtShell &rSh = m_rView.GetWrtShell(); + uno::Reference< frame::XModel > xModel = m_rView.GetDocShell()->GetBaseModel(); + + SelectionType eType = rSh.GetSelectionType(); + if ( eType & SelectionType::Ole ) + { + eType = SelectionType::Graphic; + uno::Reference< text::XTextEmbeddedObjectsSupplier > xObjs(xModel, uno::UNO_QUERY); + m_xNameAccess = xObjs->getEmbeddedObjects(); + } + + m_xCategoryBox->connect_changed(LINK(this, SwCaptionDialog, ModifyComboHdl)); + Link<weld::Entry&,void> aLk = LINK(this, SwCaptionDialog, ModifyEntryHdl); + m_xTextEdit->connect_changed(aLk); + m_xNumberingSeparatorED->connect_changed(aLk); + m_xSepEdit->connect_changed(aLk); + + m_xFormatBox->connect_changed(LINK(this, SwCaptionDialog, SelectListBoxHdl)); + m_xOKButton->connect_clicked(LINK(this, SwCaptionDialog, OKHdl)); + m_xOptionButton->connect_clicked(LINK(this, SwCaptionDialog, OptionHdl)); + m_xAutoCaptionButton->connect_clicked(LINK(this, SwCaptionDialog, CaptionHdl)); + m_xAutoCaptionButton->set_accessible_description(SwResId(STR_A11Y_DESC_AUTO)); + + m_xCategoryBox->append_text(m_sNone); + size_t nCount = m_pMgr->GetFieldTypeCount(); + for (size_t i = 0; i < nCount; ++i) + { + SwFieldType *pType = m_pMgr->GetFieldType( SwFieldIds::Unknown, i ); + if( pType->Which() == SwFieldIds::SetExp && + static_cast<SwSetExpFieldType *>( pType)->GetType() & nsSwGetSetExpType::GSE_SEQ ) + m_xCategoryBox->append_text(pType->GetName()); + } + + OUString sString; + sal_uInt16 nPoolId = 0; + if (eType & SelectionType::Graphic) + { + nPoolId = RES_POOLCOLL_LABEL_FIGURE; + + SwSetExpFieldType* pTypeIll= static_cast<SwSetExpFieldType*>(rSh.GetFieldType(SwFieldIds::SetExp, SwResId(STR_POOLCOLL_LABEL_ABB))); + if(rSh.IsUsed(*pTypeIll)) //default to illustration for legacy docs + { + nPoolId = RES_POOLCOLL_LABEL_ABB; + + } + + sString = m_rView.GetOldGrfCat(); + m_bCopyAttributes = true; + //if not OLE + if(!m_xNameAccess.is()) + { + uno::Reference< text::XTextGraphicObjectsSupplier > xGraphics(xModel, uno::UNO_QUERY); + m_xNameAccess = xGraphics->getGraphicObjects(); + } + + } + else if( eType & SelectionType::Table ) + { + nPoolId = RES_POOLCOLL_LABEL_TABLE; + sString = m_rView.GetOldTabCat(); + uno::Reference< text::XTextTablesSupplier > xTables(xModel, uno::UNO_QUERY); + m_xNameAccess = xTables->getTextTables(); + } + else if( eType & SelectionType::Frame ) + { + nPoolId = RES_POOLCOLL_LABEL_FRAME; + sString = m_rView.GetOldFrameCat(); + uno::Reference< text::XTextFramesSupplier > xFrames(xModel, uno::UNO_QUERY); + m_xNameAccess = xFrames->getTextFrames(); + } + else if( eType == SelectionType::Text ) + { + nPoolId = RES_POOLCOLL_LABEL_FRAME; + sString = m_rView.GetOldFrameCat(); + } + else if( eType & SelectionType::DrawObject ) + { + nPoolId = RES_POOLCOLL_LABEL_DRAWING; + sString = m_rView.GetOldDrwCat(); + } + if( nPoolId ) + { + if (sString.isEmpty()) + sString = SwStyleNameMapper::GetUIName(nPoolId, OUString()); + auto nIndex = m_xCategoryBox->find_text(sString); + if (nIndex != -1) + m_xCategoryBox->set_active(nIndex); + else + m_xCategoryBox->set_entry_text(sString); + } + + // aFormatBox + sal_uInt16 nSelFormat = SVX_NUM_ARABIC; + nCount = m_pMgr->GetFieldTypeCount(); + for ( size_t i = nCount; i; ) + { + SwFieldType* pFieldType = m_pMgr->GetFieldType(SwFieldIds::Unknown, --i); + if (pFieldType->GetName() == m_xCategoryBox->get_active_text()) + { + nSelFormat = o3tl::narrowing<sal_uInt16>(static_cast<SwSetExpFieldType*>(pFieldType)->GetSeqFormat()); + break; + } + } + + sal_uInt16 nFormatCount = m_pMgr->GetFormatCount(SwFieldTypesEnum::Sequence, false); + for ( sal_uInt16 i = 0; i < nFormatCount; ++i ) + { + const sal_uInt16 nFormatId = m_pMgr->GetFormatId(SwFieldTypesEnum::Sequence, i); + m_xFormatBox->append(OUString::number(nFormatId), m_pMgr->GetFormatStr(SwFieldTypesEnum::Sequence, i)); + if (nFormatId == nSelFormat) + m_xFormatBox->set_active(i); + } + + // aPosBox + if (eType == SelectionType::Graphic + || eType == SelectionType::Table + || eType == (SelectionType::Table | SelectionType::NumberList) + || eType == (SelectionType::Table | SelectionType::Text) + || eType == (SelectionType::Table | SelectionType::NumberList | SelectionType::Text) + || eType == SelectionType::DrawObject + || eType == (SelectionType::DrawObject | SelectionType::Ornament)) + { + m_xPosBox->append_text(SwResId(STR_CAPTION_ABOVE)); + m_xPosBox->append_text(SwResId(STR_CAPTION_BELOW)); + } + else if(eType == SelectionType::Frame + || eType == SelectionType::Text) + { + m_xPosBox->append_text(SwResId(STR_CAPTION_BEGINNING)); + m_xPosBox->append_text(SwResId(STR_CAPTION_END)); + } + + if (eType & SelectionType::Table) + { + m_xPosBox->set_active(0); + } + else + { + m_xPosBox->set_active(1); + } + + ModifyHdl(); + + m_xSepEdit->set_text(s_aSepTextSave); + m_xTextEdit->grab_focus(); + DrawSample(); +} + +IMPL_LINK_NOARG(SwCaptionDialog, OKHdl, weld::Button&, void) +{ + Apply(); + m_xDialog->response(RET_OK); +} + +void SwCaptionDialog::Apply() +{ + InsCaptionOpt aOpt; + aOpt.UseCaption() = true; + OUString aName(m_xCategoryBox->get_active_text()); + if ( aName == m_sNone ) + { + aOpt.SetCategory( OUString() ); + aOpt.SetNumSeparator( OUString() ); + } + else + { + aOpt.SetCategory(comphelper::string::strip(aName, ' ')); + aOpt.SetNumSeparator(m_xNumberingSeparatorED->get_text()); + } + aOpt.SetNumType(m_xFormatBox->get_active_id().toUInt32()); + aOpt.SetSeparator(m_xSepEdit->get_sensitive() ? m_xSepEdit->get_text() : OUString()); + aOpt.SetCaption(m_xTextEdit->get_text()); + aOpt.SetPos(m_xPosBox->get_active()); + aOpt.IgnoreSeqOpts() = true; + aOpt.CopyAttributes() = m_bCopyAttributes; + aOpt.SetCharacterStyle( m_sCharacterStyle ); + m_rView.InsertCaption( &aOpt ); + s_aSepTextSave = m_xSepEdit->get_text(); +} + +short SwCaptionDialog::run() +{ + short nRet = SfxDialogController::run(); + if (nRet == RET_OK) + Apply(); + return nRet; +} + +IMPL_LINK_NOARG(SwCaptionDialog, OptionHdl, weld::Button&, void) +{ + OUString sFieldTypeName = m_xCategoryBox->get_active_text(); + if(sFieldTypeName == m_sNone) + sFieldTypeName.clear(); + auto pDlg = std::make_shared<SwSequenceOptionDialog>(m_xDialog.get(), m_rView, sFieldTypeName); + pDlg->SetApplyBorderAndShadow(m_bCopyAttributes); + pDlg->SetCharacterStyle( m_sCharacterStyle ); + pDlg->SetOrderNumberingFirst( m_bOrderNumberingFirst ); + + GenericDialogController::runAsync(pDlg, [pDlg, this](sal_Int32 nResult){ + if (nResult == RET_OK) { + pDlg->Apply(); + m_bCopyAttributes = pDlg->IsApplyBorderAndShadow(); + m_sCharacterStyle = pDlg->GetCharacterStyle(); + //#i61007# order of captions + if( m_bOrderNumberingFirst != pDlg->IsOrderNumberingFirst() ) + { + m_bOrderNumberingFirst = pDlg->IsOrderNumberingFirst(); + SW_MOD()->GetModuleConfig()->SetCaptionOrderNumberingFirst(m_bOrderNumberingFirst); + ApplyCaptionOrder(); + } + DrawSample(); + } + }); +} + +IMPL_LINK_NOARG(SwCaptionDialog, SelectListBoxHdl, weld::ComboBox&, void) +{ + DrawSample(); +} + +void SwCaptionDialog::ModifyHdl() +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + OUString sFieldTypeName = m_xCategoryBox->get_active_text(); + bool bCorrectFieldName = !sFieldTypeName.isEmpty(); + bool bNone = sFieldTypeName == m_sNone; + SwFieldType* pType = (bCorrectFieldName && !bNone) + ? rSh.GetFieldType( SwFieldIds::SetExp, sFieldTypeName ) + : nullptr; + m_xOKButton->set_sensitive( bCorrectFieldName && + (!pType || + static_cast<SwSetExpFieldType*>(pType)->GetType() == nsSwGetSetExpType::GSE_SEQ) ); + m_xOptionButton->set_sensitive(m_xOKButton->get_sensitive() && !bNone); + m_xNumberingSeparatorFT->set_sensitive(m_bOrderNumberingFirst && !bNone); + m_xNumberingSeparatorED->set_sensitive(m_bOrderNumberingFirst && !bNone); + m_xFormatText->set_sensitive(!bNone); + m_xFormatBox->set_sensitive(!bNone); + m_xSepText->set_sensitive(!bNone); + m_xSepEdit->set_sensitive(!bNone); + DrawSample(); +} + +IMPL_LINK_NOARG(SwCaptionDialog, ModifyEntryHdl, weld::Entry&, void) +{ + ModifyHdl(); +} + +IMPL_LINK_NOARG(SwCaptionDialog, ModifyComboHdl, weld::ComboBox&, void) +{ + OUString sText = m_xCategoryBox->get_active_text(); + OUString sAllowedText = m_aTextFilter.filter(sText); + if (sText != sAllowedText) + { + m_xCategoryBox->set_entry_text(sAllowedText); + m_xCategoryBox->select_entry_region(sAllowedText.getLength(), sAllowedText.getLength()); + } + ModifyHdl(); +} + +IMPL_LINK_NOARG(SwCaptionDialog, CaptionHdl, weld::Button&, void) +{ + SfxItemSet aSet(m_rView.GetDocShell()->GetDoc()->GetAttrPool()); + SwCaptionOptDlg aDlg(m_xDialog.get(), aSet); + aDlg.run(); +} + +void SwCaptionDialog::DrawSample() +{ + OUString aStr; + OUString sCaption = m_xTextEdit->get_text(); + + // number + OUString sFieldTypeName = m_xCategoryBox->get_active_text(); + bool bNone = sFieldTypeName == m_sNone; + if( !bNone ) + { + const sal_uInt16 nNumFormat = m_xFormatBox->get_active_id().toUInt32(); + if (SVX_NUM_NUMBER_NONE != nNumFormat) + { + // category + //#i61007# order of captions + if( !m_bOrderNumberingFirst ) + { + aStr = sFieldTypeName; + if ( !aStr.isEmpty() ) + aStr += " "; + } + + SwWrtShell &rSh = m_rView.GetWrtShell(); + SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>(rSh.GetFieldType( + SwFieldIds::SetExp, sFieldTypeName )); + if( pFieldType && pFieldType->GetOutlineLvl() < MAXLEVEL ) + { + SwNumberTree::tNumberVector aNumVector; + aNumVector.insert(aNumVector.end(), pFieldType->GetOutlineLvl() + 1, 1); + + OUString sNumber( rSh.GetOutlineNumRule()-> + MakeNumString(aNumVector, false )); + if( !sNumber.isEmpty() ) + aStr += sNumber + pFieldType->GetDelimiter(); + } + + switch( nNumFormat ) + { + case SVX_NUM_CHARS_UPPER_LETTER: aStr += "A"; break; + case SVX_NUM_CHARS_UPPER_LETTER_N: aStr += "A"; break; + case SVX_NUM_CHARS_LOWER_LETTER: aStr += "a"; break; + case SVX_NUM_CHARS_LOWER_LETTER_N: aStr += "a"; break; + case SVX_NUM_ROMAN_UPPER: aStr += "I"; break; + case SVX_NUM_ROMAN_LOWER: aStr += "i"; break; + default: aStr += "1"; break; + } + //#i61007# order of captions + if( m_bOrderNumberingFirst ) + { + aStr += m_xNumberingSeparatorED->get_text() + sFieldTypeName; + } + + } + if( !sCaption.isEmpty() ) + { + aStr += m_xSepEdit->get_text(); + } + } + aStr += sCaption; + // do preview! + m_aPreview.SetPreviewText(aStr); +} + +SwCaptionDialog::~SwCaptionDialog() +{ +} + +SwSequenceOptionDialog::SwSequenceOptionDialog(weld::Window *pParent, SwView &rV, OUString aSeqFieldType ) + : GenericDialogController(pParent, "modules/swriter/ui/captionoptions.ui", "CaptionOptionsDialog") + , m_rView(rV) + , m_aFieldTypeName(std::move(aSeqFieldType)) + , m_xLbLevel(m_xBuilder->weld_combo_box("level")) + , m_xEdDelim(m_xBuilder->weld_entry("separator")) + , m_xLbCharStyle(m_xBuilder->weld_combo_box("style")) + , m_xApplyBorderAndShadowCB(m_xBuilder->weld_check_button("border_and_shadow")) + , m_xLbCaptionOrder(m_xBuilder->weld_combo_box("caption_order")) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + + const OUString sNone(SwResId(SW_STR_NONE)); + + m_xLbLevel->append_text(sNone); + for (sal_uInt16 n = 0; n < MAXLEVEL; ++n) + m_xLbLevel->append_text(OUString::number(n + 1)); + + SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>(rSh.GetFieldType( + SwFieldIds::SetExp, m_aFieldTypeName )); + + sal_Unicode nLvl = MAXLEVEL; + OUString sDelim(": "); + if( pFieldType ) + { + sDelim = pFieldType->GetDelimiter(); + nLvl = pFieldType->GetOutlineLvl(); + } + + m_xLbLevel->set_active(nLvl < MAXLEVEL ? nLvl + 1 : 0); + m_xEdDelim->set_text(sDelim); + + m_xLbCharStyle->append_text(sNone); + ::FillCharStyleListBox(*m_xLbCharStyle, m_rView.GetDocShell(), true, true); + m_xLbCharStyle->set_active(0); +} + +void SwSequenceOptionDialog::Apply() +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>(rSh.GetFieldType( + SwFieldIds::SetExp, m_aFieldTypeName )); + + sal_Int8 nLvl = static_cast<sal_Int8>(m_xLbLevel->get_active() - 1); + sal_Unicode cDelim = m_xEdDelim->get_text()[0]; + + bool bUpdate = true; + if( pFieldType ) + { + pFieldType->SetDelimiter( OUString(cDelim) ); + pFieldType->SetOutlineLvl( nLvl ); + } + else if( !m_aFieldTypeName.isEmpty() && nLvl < MAXLEVEL ) + { + // then we have to insert that + SwSetExpFieldType aFieldType( rSh.GetDoc(), m_aFieldTypeName, nsSwGetSetExpType::GSE_SEQ ); + aFieldType.SetDelimiter( OUString(cDelim) ); + aFieldType.SetOutlineLvl( nLvl ); + rSh.InsertFieldType( aFieldType ); + } + else + bUpdate = false; + + if( bUpdate ) + rSh.UpdateExpFields(); +} + +OUString SwSequenceOptionDialog::GetCharacterStyle() const +{ + if (m_xLbCharStyle->get_active() != -1) + return m_xLbCharStyle->get_active_text(); + return OUString(); +} + +void SwSequenceOptionDialog::SetCharacterStyle(const OUString& rStyle) +{ + const int nPos = m_xLbCharStyle->find_text(rStyle); + if (nPos == -1) + m_xLbCharStyle->set_active(0); + else + m_xLbCharStyle->set_active(nPos); +} + +// #i61007# order of captions +void SwCaptionDialog::ApplyCaptionOrder() +{ + m_xNumberingSeparatorFT->set_sensitive(m_bOrderNumberingFirst); + m_xNumberingSeparatorED->set_sensitive(m_bOrderNumberingFirst); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/frmdlg/frmdlg.cxx b/sw/source/ui/frmdlg/frmdlg.cxx new file mode 100644 index 0000000000..0eaf29dfe6 --- /dev/null +++ b/sw/source/ui/frmdlg/frmdlg.cxx @@ -0,0 +1,201 @@ +/* -*- 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/dialogs.hrc> +#include <hintids.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/htmlmode.hxx> +#include <fmtfsize.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <frmdlg.hxx> +#include <frmpage.hxx> +#include <wrap.hxx> +#include <column.hxx> +#include <macassgn.hxx> +#include <IDocumentSettingAccess.hxx> + +#include <strings.hrc> +#include <svl/eitem.hxx> +#include <svx/svxids.hrc> +#include <svx/flagsdef.hxx> +#include <svx/drawitem.hxx> +#include <comphelper/lok.hxx> + +// the dialog's carrier +SwFrameDlg::SwFrameDlg(const SfxViewFrame& rViewFrame, + weld::Window* pParent, + const SfxItemSet& rCoreSet, + bool bNewFrame, + const OUString& sResType, + bool bFormat, + const OUString& sDefPage, + const OUString* pStr) + + : SfxTabDialogController(pParent, "modules/swriter/ui/" + sResType.toAsciiLowerCase() + ".ui", + sResType, &rCoreSet, pStr != nullptr) + , m_bFormat(bFormat) + , m_bNew(bNewFrame) + , m_rSet(rCoreSet) + , m_sDlgType(sResType) + , m_pWrtShell(static_cast<SwView*>(rViewFrame.GetViewShell())->GetWrtShellPtr()) +{ + sal_uInt16 nHtmlMode = ::GetHtmlMode(m_pWrtShell->GetView().GetDocShell()); + bool bHTMLMode = (nHtmlMode & HTMLMODE_ON) != 0; + + // example font for both example TabPages + + if (pStr) + { + m_xDialog->set_title(m_xDialog->get_title() + SwResId(STR_FRMUI_COLL_HEADER) + *pStr + ")"); + } + + AddTabPage("type", SwFramePage::Create, nullptr); + AddTabPage("options", SwFrameAddPage::Create, nullptr); + AddTabPage("wrap", SwWrapTabPage::Create, nullptr); + AddTabPage("hyperlink", SwFrameURLPage::Create, nullptr); + if (m_sDlgType == "PictureDialog") + { + AddTabPage("picture", SwGrfExtPage::Create, nullptr); + AddTabPage("crop", RID_SVXPAGE_GRFCROP); + } + if (m_sDlgType == "FrameDialog") + { + AddTabPage("columns", SwColumnPage::Create, nullptr); + } + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + + // add Area and Transparence TabPages + AddTabPage("area", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_AREA ), pFact->GetTabPageRangesFunc( RID_SVXPAGE_AREA )); + AddTabPage("transparence", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_TRANSPARENCE ), pFact->GetTabPageRangesFunc( RID_SVXPAGE_TRANSPARENCE ) ); + + AddTabPage("macro", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_MACROASSIGN), nullptr); + AddTabPage("borders", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BORDER ), nullptr); + + if(bHTMLMode) + { + if (m_sDlgType == "FrameDialog" || m_sDlgType == "ObjectDialog") + { + if (m_sDlgType == "FrameDialog") + RemoveTabPage("columns"); + RemoveTabPage("hyperlink"); + RemoveTabPage("macro"); + } + else if (m_sDlgType == "PictureDialog") + RemoveTabPage("crop"); + if( m_sDlgType != "FrameDialog" ) + { + // RemoveTabPage("background"); + RemoveTabPage("area"); + RemoveTabPage("transparence"); + } + } + + if(comphelper::LibreOfficeKit::isActive()) + RemoveTabPage("macro"); + + if (m_bNew) + SetCurPageId("type"); + + if (!sDefPage.isEmpty()) + SetCurPageId(sDefPage); +} + +SwFrameDlg::~SwFrameDlg() +{ +} + +void SwFrameDlg::PageCreated(const OUString& rId, SfxTabPage &rPage) +{ + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + if (rId == "type") + { + static_cast<SwFramePage&>(rPage).SetNewFrame(m_bNew); + static_cast<SwFramePage&>(rPage).SetFormatUsed(m_bFormat); + static_cast<SwFramePage&>(rPage).SetFrameType(m_sDlgType); + } + else if (rId == "options") + { + static_cast<SwFrameAddPage&>(rPage).SetFormatUsed(m_bFormat); + static_cast<SwFrameAddPage&>(rPage).SetFrameType(m_sDlgType); + static_cast<SwFrameAddPage&>(rPage).SetNewFrame(m_bNew); + static_cast<SwFrameAddPage&>(rPage).SetShell(m_pWrtShell); + } + else if (rId == "wrap") + { + static_cast<SwWrapTabPage&>(rPage).SetNewFrame(m_bNew); + static_cast<SwWrapTabPage&>(rPage).SetFormatUsed(m_bFormat, false); + static_cast<SwWrapTabPage&>(rPage).SetShell(m_pWrtShell); + } + else if (rId == "columns") + { + static_cast<SwColumnPage&>(rPage).SetFrameMode(true); + static_cast<SwColumnPage&>(rPage).SetFormatUsed(m_bFormat); + + const SwFormatFrameSize& rSize = m_rSet.Get( RES_FRM_SIZE ); + static_cast<SwColumnPage&>(rPage).SetPageWidth( rSize.GetWidth() ); + } + else if (rId == "macro") + { + SfxAllItemSet aNewSet(*aSet.GetPool()); + aNewSet.Put( SwMacroAssignDlg::AddEvents( + m_sDlgType == "PictureDialog" ? MACASSGN_GRAPHIC : m_sDlgType == "ObjectDialog" ? MACASSGN_OLE : MACASSGN_FRMURL ) ); + if (m_pWrtShell) + rPage.SetFrame( m_pWrtShell->GetView().GetViewFrame().GetFrame().GetFrameInterface() ); + rPage.PageCreated(aNewSet); + } + else if (rId == "borders") + { + aSet.Put (SfxUInt16Item(SID_SWMODE_TYPE,static_cast<sal_uInt16>(SwBorderModes::FRAME))); + rPage.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. SvxColorListItem) to make + // these pages find the needed attributes for fill style suggestions. + // These are set in preparation to trigger this dialog (FN_FORMAT_FRAME_DLG and + // FN_DRAW_WRAP_DLG), but could also be directly added from the DrawModel. + else if (rId == "area") + { + SfxItemSetFixed<SID_COLOR_TABLE, SID_PATTERN_LIST, + SID_OFFER_IMPORT, SID_OFFER_IMPORT> + aNew(*GetInputSetImpl()->GetPool()); + + aNew.Put(m_rSet); + + // add flag for direct graphic content selection + aNew.Put(SfxBoolItem(SID_OFFER_IMPORT, true)); + + rPage.PageCreated(aNew); + } + else if (rId == "transparence") + { + rPage.PageCreated(m_rSet); + } + else if (rId == "crop") + { + sal_Int32 nPreferredDPI = m_pWrtShell->GetDoc()->getIDocumentSettingAccess().getImagePreferredDPI(); + if (nPreferredDPI) + rPage.getAdditionalProperties().emplace("PreferredDPI", css::uno::Any(nPreferredDPI)); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/frmdlg/frmpage.cxx b/sw/source/ui/frmdlg/frmpage.cxx new file mode 100644 index 0000000000..b3e2a873ad --- /dev/null +++ b/sw/source/ui/frmdlg/frmpage.cxx @@ -0,0 +1,3285 @@ +/* -*- 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/embed/Aspects.hpp> +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> + +#include <cmdid.h> +#include <hintids.hxx> +#include <bitmaps.hlst> +#include <o3tl/safeint.hxx> +#include <vcl/mnemonic.hxx> +#include <svl/stritem.hxx> +#include <sfx2/htmlmode.hxx> +#include <editeng/opaqitem.hxx> +#include <editeng/protitem.hxx> +#include <editeng/prntitem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/swframeposstrings.hxx> +#include <svx/swframevalidation.hxx> +#include <svx/sdangitm.hxx> +#include <comphelper/classids.hxx> +#include <tools/globname.hxx> +#include <tools/urlobj.hxx> +#include <fmturl.hxx> +#include <fmteiro.hxx> +#include <fmtcnct.hxx> +#include <fmtsrnd.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <swmodule.hxx> +#include <uitool.hxx> +#include <docsh.hxx> +#include <viewopt.hxx> +#include <frmdlg.hxx> +#include <frmmgr.hxx> +#include <frmpage.hxx> +#include <colmgr.hxx> +#include <grfatr.hxx> +#include <fmtfollowtextflow.hxx> +#include <svx/sdtaitm.hxx> +#include <sal/macros.h> +#include <osl/diagnose.h> + +#include <strings.hrc> +#include <formatflysplit.hxx> +#include <fmtcntnt.hxx> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <svx/graphichelper.hxx> +#include <sfx2/filedlghelper.hxx> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker3.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <vcl/graphicfilter.hxx> +#include <svtools/embedhlp.hxx> +#include <comphelper/lok.hxx> +#include <memory> + +using namespace ::com::sun::star; +using namespace ::sfx2; + +#define SwFPos SvxSwFramePosString + +namespace { + +struct StringIdPair_Impl +{ + SvxSwFramePosString::StringId eHori; + SvxSwFramePosString::StringId eVert; +}; + +} + +#define MAX_PERCENT_WIDTH SAL_CONST_INT64(254) +#define MAX_PERCENT_HEIGHT SAL_CONST_INT64(254) + +namespace { + +enum class LB { + NONE = 0x00000000L, + Frame = 0x00000001L, // text region of the paragraph + PrintArea = 0x00000002L, // text region of the paragraph + indentions + VertFrame = 0x00000004L, // vertical text region of the paragraph + VertPrintArea = 0x00000008L, // vertical text region of the paragraph + indentions + RelFrameLeft = 0x00000010L, // left paragraph edge + RelFrameRight = 0x00000020L, // right paragraph edge + + RelPageLeft = 0x00000040L, // left page edge + RelPageRight = 0x00000080L, // right page edge + RelPageFrame = 0x00000100L, // whole page + RelPagePrintArea = 0x00000200L, // text region of the page + + FlyRelPageLeft = 0x00000400L, // left frame edge + FlyRelPageRight = 0x00000800L, // right frame edge + FlyRelPageFrame = 0x00001000L, // whole frame + FlyRelPagePrintArea = 0x00002000L, // inside of the frame + + RelBase = 0x00010000L, // character alignment Base + RelChar = 0x00020000L, // character alignment Character + RelRow = 0x00040000L, // character alignment Row + + FlyVertFrame = 0x00100000L, // vertical entire frame + FlyVertPrintArea = 0x00200000L, // vertical frame text area + + VertLine = 0x00400000L, // vertical text line +}; + +} + +namespace o3tl { + template<> struct typed_flags<LB> : is_typed_flags<LB, 0x00773fffL> {}; +} + +namespace { + +struct RelationMap +{ + SvxSwFramePosString::StringId eStrId; + SvxSwFramePosString::StringId eMirrorStrId; + LB nLBRelation; + sal_Int16 nRelation; +}; + +} + +struct FrameMap +{ + SvxSwFramePosString::StringId eStrId; + SvxSwFramePosString::StringId eMirrorStrId; + sal_Int16 nAlign; + LB nLBRelations; +}; + + +RelationMap const aRelationMap[] = +{ + {SwFPos::FRAME, SwFPos::FRAME, LB::Frame, text::RelOrientation::FRAME}, + {SwFPos::PRTAREA, SwFPos::PRTAREA, LB::PrintArea, text::RelOrientation::PRINT_AREA}, + {SwFPos::REL_PG_LEFT, SwFPos::MIR_REL_PG_LEFT, LB::RelPageLeft, text::RelOrientation::PAGE_LEFT}, + {SwFPos::REL_PG_RIGHT, SwFPos::MIR_REL_PG_RIGHT, LB::RelPageRight, text::RelOrientation::PAGE_RIGHT}, + {SwFPos::REL_FRM_LEFT, SwFPos::MIR_REL_FRM_LEFT, LB::RelFrameLeft, text::RelOrientation::FRAME_LEFT}, + {SwFPos::REL_FRM_RIGHT, SwFPos::MIR_REL_FRM_RIGHT, LB::RelFrameRight, text::RelOrientation::FRAME_RIGHT}, + {SwFPos::REL_PG_FRAME, SwFPos::REL_PG_FRAME, LB::RelPageFrame, text::RelOrientation::PAGE_FRAME}, + {SwFPos::REL_PG_PRTAREA, SwFPos::REL_PG_PRTAREA, LB::RelPagePrintArea, text::RelOrientation::PAGE_PRINT_AREA}, + {SwFPos::REL_CHAR, SwFPos::REL_CHAR, LB::RelChar, text::RelOrientation::CHAR}, + + {SwFPos::FLY_REL_PG_LEFT, SwFPos::FLY_MIR_REL_PG_LEFT, LB::FlyRelPageLeft, text::RelOrientation::PAGE_LEFT}, + {SwFPos::FLY_REL_PG_RIGHT, SwFPos::FLY_MIR_REL_PG_RIGHT, LB::FlyRelPageRight, text::RelOrientation::PAGE_RIGHT}, + {SwFPos::FLY_REL_PG_FRAME, SwFPos::FLY_REL_PG_FRAME, LB::FlyRelPageFrame, text::RelOrientation::PAGE_FRAME}, + {SwFPos::FLY_REL_PG_PRTAREA, SwFPos::FLY_REL_PG_PRTAREA, LB::FlyRelPagePrintArea, text::RelOrientation::PAGE_PRINT_AREA}, + + {SwFPos::REL_BORDER, SwFPos::REL_BORDER, LB::VertFrame, text::RelOrientation::FRAME}, + {SwFPos::REL_PRTAREA, SwFPos::REL_PRTAREA, LB::VertPrintArea, text::RelOrientation::PRINT_AREA}, + + {SwFPos::FLY_REL_PG_FRAME, SwFPos::FLY_REL_PG_FRAME, LB::FlyVertFrame, text::RelOrientation::FRAME}, + {SwFPos::FLY_REL_PG_PRTAREA, SwFPos::FLY_REL_PG_PRTAREA, LB::FlyVertPrintArea, text::RelOrientation::PRINT_AREA}, + + {SwFPos::REL_LINE, SwFPos::REL_LINE, LB::VertLine, text::RelOrientation::TEXT_LINE} +}; + +RelationMap const aAsCharRelationMap[] = +{ + {SwFPos::REL_BASE, SwFPos::REL_BASE, LB::RelBase, text::RelOrientation::FRAME}, + {SwFPos::REL_CHAR, SwFPos::REL_CHAR, LB::RelChar, text::RelOrientation::FRAME}, + {SwFPos::REL_ROW, SwFPos::REL_ROW, LB::RelRow, text::RelOrientation::FRAME} +}; + +// site anchored +constexpr auto HORI_PAGE_REL = LB::RelPageFrame | LB::RelPagePrintArea | LB::RelPageLeft | + LB::RelPageRight; + +FrameMap const aHPageMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, HORI_PAGE_REL}, + {SwFPos::RIGHT, SwFPos::MIR_RIGHT, text::HoriOrientation::RIGHT, HORI_PAGE_REL}, + {SwFPos::CENTER_HORI, SwFPos::CENTER_HORI, text::HoriOrientation::CENTER, HORI_PAGE_REL}, + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, HORI_PAGE_REL} +}; + +FrameMap const aHPageHtmlMap[] = +{ + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, LB::RelPageFrame} +}; + +#define VERT_PAGE_REL (LB::RelPageFrame|LB::RelPagePrintArea) + +FrameMap const aVPageMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, VERT_PAGE_REL}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::BOTTOM, VERT_PAGE_REL}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CENTER, VERT_PAGE_REL}, + {SwFPos::FROMTOP, SwFPos::FROMTOP, text::VertOrientation::NONE, VERT_PAGE_REL} +}; + +FrameMap const aVPageHtmlMap[] = +{ + {SwFPos::FROMTOP, SwFPos::FROMTOP, text::VertOrientation::NONE, LB::RelPageFrame} +}; + +// frame anchored +constexpr auto HORI_FRAME_REL = LB::FlyRelPageFrame | LB::FlyRelPagePrintArea | + LB::FlyRelPageLeft | LB::FlyRelPageRight; + +FrameMap const aHFrameMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, HORI_FRAME_REL}, + {SwFPos::RIGHT, SwFPos::MIR_RIGHT, text::HoriOrientation::RIGHT, HORI_FRAME_REL}, + {SwFPos::CENTER_HORI, SwFPos::CENTER_HORI, text::HoriOrientation::CENTER, HORI_FRAME_REL}, + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, HORI_FRAME_REL} +}; + +FrameMap const aHFlyHtmlMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, LB::FlyRelPageFrame}, + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, LB::FlyRelPageFrame} +}; + +// own vertical alignment map for objects anchored to frame +#define VERT_FRAME_REL (LB::FlyVertFrame|LB::FlyVertPrintArea) + +FrameMap const aVFrameMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, VERT_FRAME_REL}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::BOTTOM, VERT_FRAME_REL}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CENTER, VERT_FRAME_REL}, + {SwFPos::FROMTOP, SwFPos::FROMTOP, text::VertOrientation::NONE, VERT_FRAME_REL} +}; + +FrameMap const aVFlyHtmlMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, LB::FlyVertFrame}, + {SwFPos::FROMTOP, SwFPos::FROMTOP, text::VertOrientation::NONE, LB::FlyVertFrame} +}; + +// paragraph anchored +constexpr auto HORI_PARA_REL = LB::Frame | LB::PrintArea | LB::RelPageLeft | LB::RelPageRight | + LB::RelPageFrame | LB::RelPagePrintArea | LB::RelFrameLeft | + LB::RelFrameRight; + +FrameMap const aHParaMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, HORI_PARA_REL}, + {SwFPos::RIGHT, SwFPos::MIR_RIGHT, text::HoriOrientation::RIGHT, HORI_PARA_REL}, + {SwFPos::CENTER_HORI, SwFPos::CENTER_HORI, text::HoriOrientation::CENTER, HORI_PARA_REL}, + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, HORI_PARA_REL} +}; + +#define HTML_HORI_PARA_REL (LB::Frame|LB::PrintArea) + +FrameMap const aHParaHtmlMap[] = +{ + {SwFPos::LEFT, SwFPos::LEFT, text::HoriOrientation::LEFT, HTML_HORI_PARA_REL}, + {SwFPos::RIGHT, SwFPos::RIGHT, text::HoriOrientation::RIGHT, HTML_HORI_PARA_REL} +}; + +FrameMap const aHParaHtmlAbsMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, HTML_HORI_PARA_REL}, + {SwFPos::RIGHT, SwFPos::MIR_RIGHT, text::HoriOrientation::RIGHT, HTML_HORI_PARA_REL} +}; + +// allow vertical alignment at page areas +constexpr auto VERT_PARA_REL = LB::VertFrame | LB::VertPrintArea | + LB::RelPageFrame | LB::RelPagePrintArea; + +FrameMap const aVParaMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, VERT_PARA_REL}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::BOTTOM, VERT_PARA_REL}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CENTER, VERT_PARA_REL}, + {SwFPos::FROMTOP, SwFPos::FROMTOP, text::VertOrientation::NONE, VERT_PARA_REL} +}; + +FrameMap const aVParaHtmlMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, LB::VertPrintArea} +}; + +// anchored relative to the character +constexpr auto HORI_CHAR_REL = LB::Frame|LB::PrintArea | LB::RelPageLeft | LB::RelPageRight | + LB::RelPageFrame | LB::RelPagePrintArea | LB::RelFrameLeft | + LB::RelFrameRight | LB::RelChar; + +FrameMap const aHCharMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, HORI_CHAR_REL}, + {SwFPos::RIGHT, SwFPos::MIR_RIGHT, text::HoriOrientation::RIGHT, HORI_CHAR_REL}, + {SwFPos::CENTER_HORI, SwFPos::CENTER_HORI, text::HoriOrientation::CENTER, HORI_CHAR_REL}, + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, HORI_CHAR_REL} +}; + +#define HTML_HORI_CHAR_REL (LB::Frame|LB::PrintArea|LB::RelChar) + +FrameMap const aHCharHtmlMap[] = +{ + {SwFPos::LEFT, SwFPos::LEFT, text::HoriOrientation::LEFT, HTML_HORI_CHAR_REL}, + {SwFPos::RIGHT, SwFPos::RIGHT, text::HoriOrientation::RIGHT, HTML_HORI_CHAR_REL} +}; + +FrameMap const aHCharHtmlAbsMap[] = +{ + {SwFPos::LEFT, SwFPos::MIR_LEFT, text::HoriOrientation::LEFT, LB::PrintArea|LB::RelChar}, + {SwFPos::RIGHT, SwFPos::MIR_RIGHT, text::HoriOrientation::RIGHT, LB::PrintArea}, + {SwFPos::FROMLEFT, SwFPos::MIR_FROMLEFT, text::HoriOrientation::NONE, LB::RelPageFrame} +}; + +// allow vertical alignment at page areas +constexpr auto VERT_CHAR_REL = LB::VertFrame | LB::VertPrintArea | + LB::RelPageFrame | LB::RelPagePrintArea; + +FrameMap const aVCharMap[] = +{ + // 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 <SwFramePage::FillRelLB(..)>, <SwFramePage::GetAlignment(..)> + // and <SwFramePage::FillPosLB(..)> + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, VERT_CHAR_REL|LB::RelChar}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::BOTTOM, VERT_CHAR_REL|LB::RelChar}, + {SwFPos::BELOW, SwFPos::BELOW, text::VertOrientation::CHAR_BOTTOM, LB::RelChar}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CENTER, VERT_CHAR_REL|LB::RelChar}, + {SwFPos::FROMTOP, SwFPos::FROMTOP, text::VertOrientation::NONE, VERT_CHAR_REL}, + {SwFPos::FROMBOTTOM, SwFPos::FROMBOTTOM, text::VertOrientation::NONE, LB::RelChar|LB::VertLine}, + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::LINE_TOP, LB::VertLine}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::LINE_BOTTOM, LB::VertLine}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::LINE_CENTER, LB::VertLine} +}; + +FrameMap const aVCharHtmlMap[] = +{ + {SwFPos::BELOW, SwFPos::BELOW, text::VertOrientation::CHAR_BOTTOM, LB::RelChar} +}; + +FrameMap const aVCharHtmlAbsMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, LB::RelChar}, + {SwFPos::BELOW, SwFPos::BELOW, text::VertOrientation::CHAR_BOTTOM, LB::RelChar} +}; + +// anchored as character +FrameMap const aVAsCharMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, LB::RelBase}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::BOTTOM, LB::RelBase}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CENTER, LB::RelBase}, + + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::CHAR_TOP, LB::RelChar}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::CHAR_BOTTOM, LB::RelChar}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CHAR_CENTER, LB::RelChar}, + + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::LINE_TOP, LB::RelRow}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::LINE_BOTTOM, LB::RelRow}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::LINE_CENTER, LB::RelRow}, + + {SwFPos::FROMBOTTOM, SwFPos::FROMBOTTOM, text::VertOrientation::NONE, LB::RelBase} +}; + +FrameMap const aVAsCharHtmlMap[] = +{ + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::TOP, LB::RelBase}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::CENTER, LB::RelBase}, + + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::CHAR_TOP, LB::RelChar}, + + {SwFPos::TOP, SwFPos::TOP, text::VertOrientation::LINE_TOP, LB::RelRow}, + {SwFPos::BOTTOM, SwFPos::BOTTOM, text::VertOrientation::LINE_BOTTOM, LB::RelRow}, + {SwFPos::CENTER_VERT, SwFPos::CENTER_VERT, text::VertOrientation::LINE_CENTER, LB::RelRow} +}; + +const WhichRangesContainer SwFramePage::s_aPageRg(svl::Items< + RES_FRM_SIZE, RES_FRM_SIZE, + RES_VERT_ORIENT, RES_ANCHOR, + RES_COL, RES_COL, + RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW +>); +const WhichRangesContainer SwFrameAddPage::s_aAddPgRg(svl::Items< + RES_PRINT, RES_PRINT, + RES_PROTECT, RES_PROTECT, + FN_SET_FRM_NAME, FN_SET_FRM_NAME, + FN_SET_FRM_ALT_NAME, FN_SET_FRM_ALT_NAME, + FN_UNO_DESCRIPTION, FN_UNO_DESCRIPTION +>); + +static size_t lcl_GetFrameMapCount( const FrameMap* pMap) +{ + if ( pMap ) + { + 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); + return std::size(aHPageMap); + } + return 0; +} + +static void lcl_InsertVectors(weld::ComboBox& rBox, + const std::vector< OUString >& rPrev, const std::vector< OUString >& rThis, + const std::vector< OUString >& rNext, const std::vector< OUString >& rRemain) +{ + for(const auto& rItem : rPrev) + rBox.append_text(rItem); + for(const auto& rItem : rThis) + rBox.append_text(rItem); + for(const auto& rItem : rNext) + rBox.append_text(rItem); + rBox.append_separator(""); + //now insert all strings sorted + const auto nStartPos = rBox.get_count(); + + for(const auto& rItem : rPrev) + ::InsertStringSorted("", rItem, rBox, nStartPos ); + for(const auto& rItem : rThis) + ::InsertStringSorted("", rItem, rBox, nStartPos ); + for(const auto& rItem : rNext) + ::InsertStringSorted("", rItem, rBox, nStartPos ); + for(const auto& rItem : rRemain) + ::InsertStringSorted("", rItem, rBox, nStartPos ); +} + +// --> OD 2009-08-31 #mongolianlayout# +// add input parameter +static SvxSwFramePosString::StringId lcl_ChangeResIdToVerticalOrRTL(SvxSwFramePosString::StringId eStringId, bool bVertical, bool bVerticalL2R, bool bRTL) +{ + //special handling of STR_FROMLEFT + if ( SwFPos::FROMLEFT == eStringId ) + { + eStringId = bVertical + ? ( bRTL + ? SwFPos::FROMBOTTOM + : SwFPos::FROMTOP ) + : ( bRTL + ? SwFPos::FROMRIGHT + : SwFPos::FROMLEFT ); + return eStringId; + } + // --> OD 2009-08-31 #mongolianlayout# + // special handling of STR_FROMTOP in case of mongolianlayout (vertical left-to-right) + if ( SwFPos::FROMTOP == eStringId && + bVertical && bVerticalL2R ) + { + eStringId = SwFPos::FROMLEFT; + return eStringId; + } + if ( bVertical ) + { + //exchange horizontal strings with vertical strings and vice versa + static const StringIdPair_Impl aHoriIds[] = + { + {SwFPos::LEFT, SwFPos::TOP}, + {SwFPos::RIGHT, SwFPos::BOTTOM}, + {SwFPos::CENTER_HORI, SwFPos::CENTER_VERT}, + {SwFPos::FROMTOP, SwFPos::FROMRIGHT}, + {SwFPos::REL_PG_LEFT, SwFPos::REL_PG_TOP}, + {SwFPos::REL_PG_RIGHT, SwFPos::REL_PG_BOTTOM} , + {SwFPos::REL_FRM_LEFT, SwFPos::REL_FRM_TOP}, + {SwFPos::REL_FRM_RIGHT, SwFPos::REL_FRM_BOTTOM} + }; + static const StringIdPair_Impl aVertIds[] = + { + {SwFPos::TOP, SwFPos::RIGHT}, + {SwFPos::BOTTOM, SwFPos::LEFT }, + {SwFPos::CENTER_VERT, SwFPos::CENTER_HORI}, + {SwFPos::FROMTOP, SwFPos::FROMRIGHT }, + {SwFPos::REL_PG_TOP, SwFPos::REL_PG_LEFT }, + {SwFPos::REL_PG_BOTTOM, SwFPos::REL_PG_RIGHT } , + {SwFPos::REL_FRM_TOP, SwFPos::REL_FRM_LEFT }, + {SwFPos::REL_FRM_BOTTOM, SwFPos::REL_FRM_RIGHT } + }; + // --> OD 2009-08-31 #monglianlayout# + static const StringIdPair_Impl aVertL2RIds[] = + { + {SwFPos::TOP, SwFPos::LEFT }, + {SwFPos::BOTTOM, SwFPos::RIGHT }, + {SwFPos::CENTER_VERT, SwFPos::CENTER_HORI }, + {SwFPos::FROMTOP, SwFPos::FROMLEFT }, + {SwFPos::REL_PG_TOP, SwFPos::REL_PG_LEFT }, + {SwFPos::REL_PG_BOTTOM, SwFPos::REL_PG_RIGHT } , + {SwFPos::REL_FRM_TOP, SwFPos::REL_FRM_LEFT }, + {SwFPos::REL_FRM_BOTTOM, SwFPos::REL_FRM_RIGHT } + }; + for(const StringIdPair_Impl & rHoriId : aHoriIds) + { + if(rHoriId.eHori == eStringId) + { + eStringId = rHoriId.eVert; + return eStringId; + } + } + for(size_t nIndex = 0; nIndex < SAL_N_ELEMENTS(aVertIds); ++nIndex) + { + // --> OD 2009-08-31 #mongolianlayout# + if ( !bVerticalL2R ) + { + if(aVertIds[nIndex].eHori == eStringId) + { + eStringId = aVertIds[nIndex].eVert; + break; + } + } + else + { + if(aVertL2RIds[nIndex].eHori == eStringId) + { + eStringId = aVertL2RIds[nIndex].eVert; + break; + } + } + } + } + return eStringId; +} + +// helper method in order to determine all possible +// listbox relations in a relation map for a given relation +static LB lcl_GetLBRelationsForRelations( const sal_Int16 _nRel ) +{ + LB nLBRelations = LB::NONE; + + for (RelationMap const & i : aRelationMap) + { + if ( i.nRelation == _nRel ) + { + nLBRelations |= i.nLBRelation; + } + } + + return nLBRelations; +} + +// helper method on order to determine all possible +// listbox relations in a relation map for a given string ID +static LB lcl_GetLBRelationsForStrID( const FrameMap* _pMap, + const SvxSwFramePosString::StringId _eStrId, + const bool _bUseMirrorStr ) +{ + LB nLBRelations = LB::NONE; + + size_t nRelMapSize = lcl_GetFrameMapCount( _pMap ); + for ( size_t nRelMapPos = 0; nRelMapPos < nRelMapSize; ++nRelMapPos ) + { + if ( ( !_bUseMirrorStr && _pMap[nRelMapPos].eStrId == _eStrId ) || + ( _bUseMirrorStr && _pMap[nRelMapPos].eMirrorStrId == _eStrId ) ) + { + nLBRelations |= _pMap[nRelMapPos].nLBRelations; + } + } + + return nLBRelations; +} + +// standard frame TabPage +namespace +{ + void HandleAutoCB(bool _bChecked, weld::Label& _rFT_man, weld::Label& _rFT_auto, weld::MetricSpinButton& _rPF_Edit) + { + _rFT_man.set_visible( !_bChecked ); + _rFT_auto.set_visible( _bChecked ); + OUString accName = _bChecked ? _rFT_auto.get_label() : _rFT_man.get_label(); + _rPF_Edit.set_accessible_name(accName); + } +} + +SwFramePage::SwFramePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/frmtypepage.ui", "FrameTypePage", &rSet) + , m_bAtHorzPosModified(false) + , m_bAtVertPosModified(false) + , m_bFormat(false) + , m_bNew(true) + , m_bNoModifyHdl(true) + , m_bIsVerticalFrame(false) + , m_bIsVerticalL2R(false) + , m_bIsInRightToLeft(false) + , m_bHtmlMode(false) + , m_nHtmlMode(0) + , m_nUpperBorder(0) + , m_nLowerBorder(0) + , m_fWidthHeightRatio(1.0) + , mpToCharContentPos(nullptr) + , m_nOldH(text::HoriOrientation::CENTER) + , m_nOldHRel(text::RelOrientation::FRAME) + , m_nOldV(text::VertOrientation::TOP) + , m_nOldVRel(text::RelOrientation::PRINT_AREA) + , m_pVMap(nullptr) + , m_pHMap(nullptr) + , m_bAllowVertPositioning( true ) + , m_bIsMathOLE(false) + , m_bIsMathBaselineAlignment(true) + , m_xWidthFT(m_xBuilder->weld_label("widthft")) + , m_xWidthAutoFT(m_xBuilder->weld_label("autowidthft")) + , m_xRelWidthCB(m_xBuilder->weld_check_button("relwidth")) + , m_xRelWidthRelationLB(m_xBuilder->weld_combo_box("relwidthrelation")) + , m_xAutoWidthCB(m_xBuilder->weld_check_button("autowidth")) + , m_xHeightFT(m_xBuilder->weld_label("heightft")) + , m_xHeightAutoFT(m_xBuilder->weld_label("autoheightft")) + , m_xRelHeightCB(m_xBuilder->weld_check_button("relheight")) + , m_xRelHeightRelationLB(m_xBuilder->weld_combo_box("relheightrelation")) + , m_xAutoHeightCB(m_xBuilder->weld_check_button("autoheight")) + , m_xFixedRatioCB(m_xBuilder->weld_check_button("ratio")) + , m_xRealSizeBT(m_xBuilder->weld_button("origsize")) + , m_xAnchorFrame(m_xBuilder->weld_widget("anchorframe")) + , m_xAnchorAtPageRB(m_xBuilder->weld_radio_button("topage")) + , m_xAnchorAtParaRB(m_xBuilder->weld_radio_button("topara")) + , m_xAnchorAtCharRB(m_xBuilder->weld_radio_button("tochar")) + , m_xAnchorAsCharRB(m_xBuilder->weld_radio_button("aschar")) + , m_xAnchorAtFrameRB(m_xBuilder->weld_radio_button("toframe")) + , m_xHorizontalFT(m_xBuilder->weld_label("horiposft")) + , m_xHorizontalDLB(m_xBuilder->weld_combo_box("horipos")) + , m_xAtHorzPosFT(m_xBuilder->weld_label("horibyft")) + , m_xAtHorzPosED(m_xBuilder->weld_metric_spin_button("byhori", FieldUnit::CM)) + , m_xHoriRelationFT(m_xBuilder->weld_label("horitoft")) + , m_xHoriRelationLB(m_xBuilder->weld_combo_box("horianchor")) + , m_xMirrorPagesCB(m_xBuilder->weld_check_button("mirror")) + , m_xVerticalFT(m_xBuilder->weld_label("vertposft")) + , m_xVerticalDLB(m_xBuilder->weld_combo_box("vertpos")) + , m_xAtVertPosFT(m_xBuilder->weld_label("vertbyft")) + , m_xAtVertPosED(m_xBuilder->weld_metric_spin_button("byvert", FieldUnit::CM)) + , m_xVertRelationFT(m_xBuilder->weld_label("verttoft")) + , m_xVertRelationLB(m_xBuilder->weld_combo_box("vertanchor")) + , m_xFollowTextFlowCB(m_xBuilder->weld_check_button("followtextflow")) + , m_xFlySplitCB(m_xBuilder->weld_check_button("flysplit")) + , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "preview", m_aExampleWN)) + , m_xWidthED(new SwPercentField(m_xBuilder->weld_metric_spin_button("width", FieldUnit::CM))) + , m_xHeightED(new SwPercentField(m_xBuilder->weld_metric_spin_button("height", FieldUnit::CM))) +{ + const auto nWidthRequest = m_xAtHorzPosED->get_preferred_size().Width(); + m_xAtHorzPosED->set_size_request(nWidthRequest, -1); + m_xAtVertPosED->set_size_request(nWidthRequest, -1); + + setOptimalFrameWidth(); + setOptimalRelWidth(); + + SetExchangeSupport(); + + Link<weld::MetricSpinButton&,void> aLk3 = LINK(this, SwFramePage, ModifyHdl); + m_xWidthED->connect_value_changed( aLk3 ); + m_xHeightED->connect_value_changed( aLk3 ); + m_xAtHorzPosED->connect_value_changed( aLk3 ); + m_xAtVertPosED->connect_value_changed( aLk3 ); + m_xFollowTextFlowCB->connect_toggled(LINK(this, SwFramePage, RangeModifyClickHdl)); + + Link<weld::Toggleable&,void> aLk2 = LINK(this, SwFramePage, AnchorTypeHdl); + m_xAnchorAtPageRB->connect_toggled( aLk2 ); + m_xAnchorAtParaRB->connect_toggled( aLk2 ); + m_xAnchorAtCharRB->connect_toggled( aLk2 ); + m_xAnchorAsCharRB->connect_toggled( aLk2 ); + m_xAnchorAtFrameRB->connect_toggled( aLk2 ); + + m_xHorizontalDLB->connect_changed(LINK(this, SwFramePage, PosHdl)); + m_xVerticalDLB->connect_changed(LINK(this, SwFramePage, PosHdl)); + + m_xHoriRelationLB->connect_changed(LINK(this, SwFramePage, RelHdl)); + m_xVertRelationLB->connect_changed(LINK(this, SwFramePage, RelHdl)); + + m_xMirrorPagesCB->connect_toggled(LINK(this, SwFramePage, MirrorHdl)); + + aLk2 = LINK(this, SwFramePage, RelSizeClickHdl); + m_xRelWidthCB->connect_toggled(aLk2); + m_xRelHeightCB->connect_toggled(aLk2); + + m_xAutoWidthCB->connect_toggled(LINK(this, SwFramePage, AutoWidthClickHdl)); + m_xAutoHeightCB->connect_toggled(LINK(this, SwFramePage, AutoHeightClickHdl)); + + if (comphelper::LibreOfficeKit::isActive()) + { + m_xAnchorAtPageRB->hide(); + m_xAnchorAtFrameRB->hide(); + } +} + +SwFramePage::~SwFramePage() +{ +} + +namespace +{ + struct FrameMaps + { + FrameMap const * pMap; + size_t nCount; + }; +} + +void SwFramePage::setOptimalFrameWidth() +{ + static FrameMaps const 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 FrameMaps & rMap : aMaps) + { + for (size_t j = 0; j < rMap.nCount; ++j) + { + aFrames.push_back(rMap.pMap[j].eStrId); + aFrames.push_back(rMap.pMap[j].eMirrorStrId); + } + } + + std::sort(aFrames.begin(), aFrames.end()); + aFrames.erase(std::unique(aFrames.begin(), aFrames.end()), aFrames.end()); + + for (const auto& rFrame : aFrames) + { + m_xHorizontalDLB->append_text(SvxSwFramePosString::GetString(rFrame)); + } + + Size aBiggest(m_xHorizontalDLB->get_preferred_size()); + m_xHorizontalDLB->set_size_request(aBiggest.Width(), -1); + m_xVerticalDLB->set_size_request(aBiggest.Width(), -1); + m_xHorizontalDLB->clear(); +} + +namespace +{ + struct RelationMaps + { + RelationMap const * pMap; + size_t nCount; + }; + +/// Checks if the current fly frame contains exactly one table. +bool ContainsSingleTable(const SwFrameFormat& rFlyFormat) +{ + const SwNodeIndex* pStartNode = rFlyFormat.GetContent().GetContentIdx(); + if (!pStartNode) + { + return false; + } + + // Check if the frame content starts with a table. + SwNodeIndex aNodeIndex(*pStartNode); + ++aNodeIndex; + if (!aNodeIndex.GetNode().IsTableNode()) + { + return false; + } + + // Check if the frame content ends with the same table. + SwNodeIndex aEndIndex(*aNodeIndex.GetNode().EndOfSectionNode()); + ++aEndIndex; + if (&aEndIndex.GetNode() != pStartNode->GetNode().EndOfSectionNode()) + { + return false; + } + + return true; +} + +bool ContainsChain(const SwFrameFormat& rFlyFormat) +{ + const SwFormatChain& rChain = rFlyFormat.GetChain(); + return rChain.GetPrev() || rChain.GetNext(); +} + +/// Determines if rFlyFormat is anchored in a fly frame that is part of a draw-format + fly-format +/// ("textbox") pair. +bool InTextBox(const SwFrameFormat& rFlyFormat) +{ + const SwFormatAnchor& rAnchor = rFlyFormat.GetAnchor(); + SwNode* pAnchorNode = rAnchor.GetAnchorNode(); + if (!pAnchorNode) + { + return false; + } + + const SwStartNode* pFlyNode = pAnchorNode->FindFlyStartNode(); + if (!pFlyNode) + { + return false; + } + + if (!pFlyNode->GetFlyFormat()->GetOtherTextBoxFormats()) + { + return false; + } + + return true; +} +} + +void SwFramePage::setOptimalRelWidth() +{ + static const RelationMaps aMaps[] = { + { aRelationMap, SAL_N_ELEMENTS(aRelationMap) }, + { aAsCharRelationMap, SAL_N_ELEMENTS(aAsCharRelationMap) } + }; + + std::vector<SvxSwFramePosString::StringId> aRels; + for (const RelationMaps & rMap : aMaps) + { + for (size_t j = 0; j < rMap.nCount; ++j) + { + aRels.push_back(rMap.pMap[j].eStrId); + aRels.push_back(rMap.pMap[j].eMirrorStrId); + } + } + + std::sort(aRels.begin(), aRels.end()); + aRels.erase(std::unique(aRels.begin(), aRels.end()), aRels.end()); + + for (const auto& rRel : aRels) + { + m_xHoriRelationLB->append_text(SvxSwFramePosString::GetString(rRel)); + } + + Size aBiggest(m_xHoriRelationLB->get_preferred_size()); + m_xHoriRelationLB->set_size_request(aBiggest.Width(), -1); + m_xVertRelationLB->set_size_request(aBiggest.Width(), -1); + m_xRelWidthRelationLB->set_size_request(aBiggest.Width(), -1); + m_xRelHeightRelationLB->set_size_request(aBiggest.Width(), -1); + m_xHoriRelationLB->clear(); +} + +std::unique_ptr<SfxTabPage> SwFramePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwFramePage>(pPage, pController, *rSet); +} + +void SwFramePage::EnableGraficMode() +{ + // i#39692 - mustn't be called more than once + if (!m_xRealSizeBT->get_visible()) + { + m_xWidthFT->show(); + m_xWidthAutoFT->hide(); + m_xAutoHeightCB->hide(); + + m_xHeightFT->show(); + m_xHeightAutoFT->hide(); + m_xAutoWidthCB->hide(); + + m_xRealSizeBT->show(); + } +} + +SwWrtShell *SwFramePage::getFrameDlgParentShell() +{ + return static_cast<SwFrameDlg*>(GetDialogController())->GetWrtShell(); +} + +void SwFramePage::Reset( const SfxItemSet *rSet ) +{ + SwWrtShell* pSh = m_bFormat ? ::GetActiveWrtShell() : + getFrameDlgParentShell(); + OSL_ENSURE(pSh , "shell not found"); + if (!pSh) + return; + + m_nHtmlMode = ::GetHtmlMode(pSh->GetView().GetDocShell()); + m_bHtmlMode = (m_nHtmlMode & HTMLMODE_ON) != 0; + + FieldUnit aMetric = ::GetDfltMetric(m_bHtmlMode); + m_xWidthED->SetMetric(aMetric); + m_xHeightED->SetMetric(aMetric); + ::SetFieldUnit(*m_xAtHorzPosED, aMetric); + ::SetFieldUnit(*m_xAtVertPosED, aMetric); + + const SwFormatAnchor& rAnchor = rSet->Get(RES_ANCHOR); + + if (const SfxBoolItem* pMathItem = rSet->GetItemIfSet(FN_OLE_IS_MATH, false)) + m_bIsMathOLE = pMathItem->GetValue(); + if (const SfxBoolItem* pAlignItem = rSet->GetItemIfSet(FN_MATH_BASELINE_ALIGNMENT, false)) + m_bIsMathBaselineAlignment = pAlignItem->GetValue(); + EnableVerticalPositioning( !(m_bIsMathOLE && m_bIsMathBaselineAlignment + && RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) ); + + if (m_bFormat) + { + // at formats no to-fly anchor + m_xAnchorAtFrameRB->set_sensitive(false); + if (rSet->GetItemState(FN_KEEP_ASPECT_RATIO) != SfxItemState::SET) + { + m_xFixedRatioCB->set_sensitive(false); + } + } + else + { + if (rAnchor.GetAnchorId() != RndStdIds::FLY_AT_FLY && !pSh->IsFlyInFly()) + m_xAnchorAtFrameRB->hide(); + if ( pSh->IsFrameVertical( true, m_bIsInRightToLeft, m_bIsVerticalL2R ) ) + { + OUString sHLabel = m_xHorizontalFT->get_label(); + m_xHorizontalFT->set_label(m_xVerticalFT->get_label()); + m_xVerticalFT->set_label(sHLabel); + m_bIsVerticalFrame = true; + } + } + + if ( m_sDlgType == "PictureDialog" || m_sDlgType == "ObjectDialog" ) + { + pSh->GetGrfSize( m_aGrfSize ); + + if ( !m_bNew ) + { + m_xRealSizeBT->connect_clicked(LINK(this, SwFramePage, RealSizeHdl)); + EnableGraficMode(); + } + + if (m_sDlgType == "PictureDialog") + m_xFixedRatioCB->set_active(false); + else + { + if ( m_bNew ) + SetPageTitle(SwResId(STR_FRMUI_OLE_INSERT)); + else + SetPageTitle(SwResId(STR_FRMUI_OLE_EDIT)); + } + } + else + { + m_aGrfSize = rSet->Get(RES_FRM_SIZE).GetSize(); + } + + // entering percent value made possible + + // the available space is not yet known so the RefValue has to be calculated from size and relative size values + // this is needed only if relative values are already set + const SwFormatFrameSize& rFrameSize = rSet->Get(RES_FRM_SIZE); + + m_xRelWidthRelationLB->append_text(SvxSwFramePosString::GetString(SwFPos::FRAME)); + m_xRelWidthRelationLB->append_text(SvxSwFramePosString::GetString(SwFPos::REL_PG_FRAME)); + if (rFrameSize.GetWidthPercent() != SwFormatFrameSize::SYNCED && rFrameSize.GetWidthPercent() != 0) + { + //calculate the reference value from the width and relative width values + sal_Int32 nSpace = rFrameSize.GetWidth() * 100 / rFrameSize.GetWidthPercent(); + m_xWidthED->SetRefValue( nSpace ); + + m_xRelWidthRelationLB->set_sensitive(true); + } + else + m_xRelWidthRelationLB->set_sensitive(false); + + m_xRelHeightRelationLB->append_text(SvxSwFramePosString::GetString(SwFPos::FRAME)); + m_xRelHeightRelationLB->append_text(SvxSwFramePosString::GetString(SwFPos::REL_PG_FRAME)); + if (rFrameSize.GetHeightPercent() != SwFormatFrameSize::SYNCED && rFrameSize.GetHeightPercent() != 0) + { + //calculate the reference value from the with and relative width values + sal_Int32 nSpace = rFrameSize.GetHeight() * 100 / rFrameSize.GetHeightPercent(); + m_xHeightED->SetRefValue( nSpace ); + + m_xRelHeightRelationLB->set_sensitive(true); + } + else + m_xRelHeightRelationLB->set_sensitive(false); + + // general initialisation part + switch(rAnchor.GetAnchorId()) + { + case RndStdIds::FLY_AT_PAGE: m_xAnchorAtPageRB->set_active(true); break; + case RndStdIds::FLY_AT_PARA: m_xAnchorAtParaRB->set_active(true); break; + case RndStdIds::FLY_AT_CHAR: m_xAnchorAtCharRB->set_active(true); break; + case RndStdIds::FLY_AS_CHAR: m_xAnchorAsCharRB->set_active(true); break; + case RndStdIds::FLY_AT_FLY: m_xAnchorAtFrameRB->set_active(true);break; + default:; //prevent warning + } + + // i#22341 - determine content position of character + // Note: content position can be NULL + mpToCharContentPos = rAnchor.GetAnchorNode() ? &rAnchor : nullptr; + + // i#18732 - init checkbox value + { + const bool bFollowTextFlow = + rSet->Get(RES_FOLLOW_TEXT_FLOW).GetValue(); + m_xFollowTextFlowCB->set_active(bFollowTextFlow); + } + { + const bool bFlySplit = rSet->Get(RES_FLY_SPLIT).GetValue(); + m_xFlySplitCB->set_active(bFlySplit); + } + + if(m_bHtmlMode) + { + m_xAutoHeightCB->set_sensitive(false); + m_xAutoWidthCB->set_sensitive(false); + m_xMirrorPagesCB->hide(); + if (m_sDlgType == "FrameDialog") + m_xFixedRatioCB->set_sensitive(false); + // i#18732 hide checkbox in HTML mode + m_xFollowTextFlowCB->hide(); + } + else + { + // enable/disable of check box 'Mirror on..' + m_xMirrorPagesCB->set_sensitive(!m_xAnchorAsCharRB->get_active()); + + // enable/disable check box 'Follow text flow'. + // enable check box 'Follow text + // flow' also for anchor type to-frame. + m_xFollowTextFlowCB->set_sensitive(m_xAnchorAtParaRB->get_active() || + m_xAnchorAtCharRB->get_active() || + m_xAnchorAtFrameRB->get_active()); + m_xFlySplitCB->set_sensitive(m_xAnchorAtParaRB->get_active()); + } + + const SwFrameFormat* pFlyFormat = pSh->GetFlyFrameFormat(); + if (!pFlyFormat || !ContainsSingleTable(*pFlyFormat) || ContainsChain(*pFlyFormat)) + { + bool bSingleTable = false; + if (!pFlyFormat && m_bNew) + { + // No fly is selected: check if a whole table is selected. If so, allow moving that into + // a split fly. + if (SwFlyFrameAttrMgr::SingleTableSelected(*pSh)) + { + bSingleTable = true; + } + } + + // Only allow fly split if the frame contains a single table, otherwise it would be hard to + // save the resulting model to Word formats. + if (!bSingleTable) + { + m_xFlySplitCB->hide(); + } + } + else if (pFlyFormat && !m_bNew && InTextBox(*pFlyFormat)) + { + // Disallow split flys in fly frames which form a textbox, i.e. non-editeng shape text. + m_xFlySplitCB->hide(); + } + + Init(*rSet); + m_xAtVertPosED->save_value(); + m_xAtHorzPosED->save_value(); + m_xFollowTextFlowCB->save_state(); + m_xFlySplitCB->save_state(); + + m_xWidthED->save_value(); + m_xHeightED->save_value(); + + m_bNoModifyHdl = false; + //lock PercentFields + m_xWidthED->LockAutoCalculation(true); + m_xHeightED->LockAutoCalculation(true); + RangeModifyHdl(); // set all maximum values initially + m_xHeightED->LockAutoCalculation(false); + m_xWidthED->LockAutoCalculation(false); + + m_xAutoHeightCB->save_state(); + m_xAutoWidthCB->save_state(); + + SwTwips nWidth = static_cast< SwTwips >(m_xWidthED->DenormalizePercent(m_xWidthED->get_value(FieldUnit::TWIP))); + SwTwips nHeight = static_cast< SwTwips >(m_xHeightED->DenormalizePercent(m_xHeightED->get_value(FieldUnit::TWIP))); + m_fWidthHeightRatio = nHeight ? double(nWidth) / double(nHeight) : 1.0; +} + +// stuff attributes into the set when OK +bool SwFramePage::FillItemSet(SfxItemSet *rSet) +{ + bool bRet = false; + + const SfxItemSet& rOldSet = GetItemSet(); + const SfxPoolItem* pOldItem = nullptr; + + RndStdIds eAnchorId = GetAnchor(); + + if ( !m_bFormat || eAnchorId != RndStdIds::FLY_AT_FLY ) + { + pOldItem = GetOldItem(*rSet, RES_ANCHOR); + if (m_bNew || !pOldItem || eAnchorId != static_cast<const SwFormatAnchor*>(pOldItem)->GetAnchorId()) + { + SwWrtShell* pSh = m_bFormat ? ::GetActiveWrtShell() + : getFrameDlgParentShell(); + OSL_ENSURE( pSh , "shell not found"); + if (pSh) + { + SwFormatAnchor aAnc( eAnchorId, eAnchorId == RndStdIds::FLY_AT_PAGE ? pSh->GetPhyPageNum() : 0 ); + bRet = nullptr != rSet->Put( aAnc ); + } + } + } + + if ( m_pHMap ) + { + SwFormatHoriOrient aHoriOrient( rOldSet.Get(RES_HORI_ORIENT) ); + + const sal_Int32 nMapPos = GetMapPos(m_pHMap, *m_xHorizontalDLB); + const sal_Int16 eHOri = GetAlignment(m_pHMap, nMapPos, *m_xHoriRelationLB); + const sal_Int16 eRel = GetRelation(*m_xHoriRelationLB); + + aHoriOrient.SetHoriOrient( eHOri ); + aHoriOrient.SetRelationOrient( eRel ); + aHoriOrient.SetPosToggle(m_xMirrorPagesCB->get_active()); + + bool bMod = m_xAtHorzPosED->get_value_changed_from_saved(); + bMod |= m_xMirrorPagesCB->get_state_changed_from_saved(); + + if ( eHOri == text::HoriOrientation::NONE && + (m_bNew || (m_bAtHorzPosModified || bMod) || m_nOldH != eHOri ) ) + { + SwTwips nX = static_cast< SwTwips >(m_xAtHorzPosED->denormalize(m_xAtHorzPosED->get_value(FieldUnit::TWIP))); + aHoriOrient.SetPos( nX ); + } + + pOldItem = GetOldItem(*rSet, FN_HORI_ORIENT); + bool bSame = false; + if ((m_bNew == m_bFormat) && pOldItem) + { + bSame = aHoriOrient == static_cast<const SwFormatHoriOrient&>(*pOldItem); + } + if ((m_bNew && !m_bFormat) || ((m_bAtHorzPosModified || bMod) && !bSame)) + { + bRet |= nullptr != rSet->Put( aHoriOrient ); + } + } + + if ( m_pVMap ) + { + // alignment vertical + SwFormatVertOrient aVertOrient( rOldSet.Get(RES_VERT_ORIENT) ); + + const sal_Int32 nMapPos = GetMapPos(m_pVMap, *m_xVerticalDLB); + const sal_Int16 eVOri = GetAlignment(m_pVMap, nMapPos, *m_xVertRelationLB); + const sal_Int16 eRel = GetRelation(*m_xVertRelationLB); + + aVertOrient.SetVertOrient ( eVOri); + aVertOrient.SetRelationOrient( eRel ); + + bool bMod = m_xAtVertPosED->get_value_changed_from_saved(); + + if ( eVOri == text::VertOrientation::NONE && + ( m_bNew || (m_bAtVertPosModified || bMod) || m_nOldV != eVOri) ) + { + // vertical position + // recalculate offset for character bound frames + SwTwips nY = static_cast< SwTwips >(m_xAtVertPosED->denormalize(m_xAtVertPosED->get_value(FieldUnit::TWIP))); + if (eAnchorId == RndStdIds::FLY_AS_CHAR) + { + nY *= -1; + } + aVertOrient.SetPos( nY ); + } + pOldItem = GetOldItem(*rSet, FN_VERT_ORIENT); + bool bSame = false; + if((m_bNew == m_bFormat) && pOldItem) + { + bSame = m_bFormat ? + aVertOrient.GetVertOrient() == static_cast<const SwFormatVertOrient*>(pOldItem)->GetVertOrient() && + aVertOrient.GetRelationOrient() == static_cast<const SwFormatVertOrient*>(pOldItem)->GetRelationOrient() && + aVertOrient.GetPos() == static_cast<const SwFormatVertOrient*>(pOldItem)->GetPos() + : aVertOrient == static_cast<const SwFormatVertOrient&>(*pOldItem); + } + if( ( m_bNew && !m_bFormat ) || ((m_bAtVertPosModified || bMod) && !bSame )) + { + bRet |= nullptr != rSet->Put( aVertOrient ); + } + } + + // set size + // new exception: when the size of pMgr(, 0), then the properties + // for a graphic that isn't even loaded, are set. Then no SetSize + // is done here when the size settings were not changed by the + // user. + const SwFormatFrameSize& rOldSize = rOldSet.Get(RES_FRM_SIZE); + SwFormatFrameSize aSz( rOldSize ); + + auto nRelWidthRelation = m_xRelWidthRelationLB->get_active(); + if (nRelWidthRelation != -1) + { + if (nRelWidthRelation == 0) + aSz.SetWidthPercentRelation(text::RelOrientation::FRAME); + else if (nRelWidthRelation == 1) + aSz.SetWidthPercentRelation(text::RelOrientation::PAGE_FRAME); + } + auto nRelHeightRelation = m_xRelHeightRelationLB->get_active(); + if (nRelHeightRelation != -1) + { + if (nRelHeightRelation == 0) + aSz.SetHeightPercentRelation(text::RelOrientation::FRAME); + else if (nRelHeightRelation == 1) + aSz.SetHeightPercentRelation(text::RelOrientation::PAGE_FRAME); + } + + bool bValueModified = m_xWidthED->get_value_changed_from_saved() || + m_xHeightED->get_value_changed_from_saved(); + bool bCheckChanged = m_xRelWidthCB->get_state_changed_from_saved() || + m_xRelHeightCB->get_state_changed_from_saved() || + m_xFixedRatioCB->get_state_changed_from_saved(); + + bool bLegalValue = !(!rOldSize.GetWidth () && !rOldSize.GetHeight() && + m_xWidthED->get_value() == m_xWidthED->get_min() && + m_xHeightED->get_value() == m_xHeightED->get_min()); + + if ((m_bNew && !m_bFormat) || ((bValueModified || bCheckChanged) && bLegalValue)) + { + sal_Int64 nNewWidth = m_xWidthED->DenormalizePercent(m_xWidthED->GetRealValue(FieldUnit::TWIP)); + sal_Int64 nNewHeight = m_xHeightED->DenormalizePercent(m_xHeightED->GetRealValue(FieldUnit::TWIP)); + aSz.SetWidth (static_cast< SwTwips >(nNewWidth)); + aSz.SetHeight(static_cast< SwTwips >(nNewHeight)); + + if (m_xRelWidthCB->get_active()) + { + aSz.SetWidthPercent(static_cast<sal_uInt8>(std::min(MAX_PERCENT_WIDTH, m_xWidthED->Convert(m_xWidthED->NormalizePercent(nNewWidth), FieldUnit::TWIP, FieldUnit::PERCENT)))); + } + else + aSz.SetWidthPercent(0); + if (m_xRelHeightCB->get_active()) + aSz.SetHeightPercent(static_cast<sal_uInt8>(std::min(MAX_PERCENT_HEIGHT, m_xHeightED->Convert(m_xHeightED->NormalizePercent(nNewHeight), FieldUnit::TWIP, FieldUnit::PERCENT)))); + else + aSz.SetHeightPercent(0); + + if (m_xFixedRatioCB->get_active() && (m_xRelWidthCB->get_active() != m_xRelHeightCB->get_active())) + { + if (m_xRelWidthCB->get_active()) + aSz.SetHeightPercent(SwFormatFrameSize::SYNCED); + else + aSz.SetWidthPercent(SwFormatFrameSize::SYNCED); + } + } + + if( !IsInGraficMode() ) + { + if (m_xAutoHeightCB->get_state_changed_from_saved()) + { + SwFrameSize eFrameSize = m_xAutoHeightCB->get_active()? SwFrameSize::Minimum : SwFrameSize::Fixed; + if( eFrameSize != aSz.GetHeightSizeType() ) + aSz.SetHeightSizeType(eFrameSize); + } + if (m_xAutoWidthCB->get_state_changed_from_saved()) + { + SwFrameSize eFrameSize = m_xAutoWidthCB->get_active()? SwFrameSize::Minimum : SwFrameSize::Fixed; + if( eFrameSize != aSz.GetWidthSizeType() ) + aSz.SetWidthSizeType( eFrameSize ); + } + } + if (m_xFixedRatioCB->get_state_changed_from_saved()) + bRet |= nullptr != rSet->Put(SfxBoolItem(FN_KEEP_ASPECT_RATIO, m_xFixedRatioCB->get_active())); + + pOldItem = GetOldItem(*rSet, RES_FRM_SIZE); + + bool bSizeChanged = pOldItem && aSz != *pOldItem; + if (!bSizeChanged && m_bNew) + { + // If no custom size is provided, always set a size for a new frame, to avoid ~zero width. + bSizeChanged = true; + } + if (bSizeChanged || (!pOldItem && !m_bFormat) || + (m_bFormat && + (aSz.GetWidth() > 0 || aSz.GetWidthPercent() > 0) && + (aSz.GetHeight() > 0 || aSz.GetHeightPercent() > 0))) + { + if (aSz.GetHeightSizeType() == SwFrameSize::Variable) // there is no VAR_SIZE in frames + aSz.SetHeightSizeType(SwFrameSize::Minimum); + + bRet |= nullptr != rSet->Put( aSz ); + } + if (m_xFollowTextFlowCB->get_state_changed_from_saved()) + { + bRet |= nullptr != rSet->Put(SwFormatFollowTextFlow(m_xFollowTextFlowCB->get_active())); + } + if (m_xFlySplitCB->get_state_changed_from_saved()) + { + bRet |= rSet->Put(SwFormatFlySplit(m_xFlySplitCB->get_active())) != nullptr; + } + return bRet; +} + +// initialise horizontal and vertical Pos +void SwFramePage::InitPos(RndStdIds eId, + sal_Int16 nH, + sal_Int16 nHRel, + sal_Int16 nV, + sal_Int16 nVRel, + tools::Long nX, + tools::Long nY) +{ + auto nPos = m_xVerticalDLB->get_active(); + if (nPos != -1 && m_pVMap) + { + m_nOldV = m_pVMap[nPos].nAlign; + + nPos = m_xVertRelationLB->get_active(); + if (nPos != -1) + m_nOldVRel = weld::fromId<RelationMap*>(m_xVertRelationLB->get_id(nPos))->nRelation; + } + + nPos = m_xHorizontalDLB->get_active(); + if (nPos != -1 && m_pHMap) + { + m_nOldH = m_pHMap[nPos].nAlign; + + nPos = m_xHoriRelationLB->get_active(); + if (nPos != -1) + m_nOldHRel = weld::fromId<RelationMap*>(m_xHoriRelationLB->get_id(nPos))->nRelation; + } + + bool bEnable = true; + if ( eId == RndStdIds::FLY_AT_PAGE ) + { + m_pVMap = m_bHtmlMode ? aVPageHtmlMap : aVPageMap; + m_pHMap = m_bHtmlMode ? aHPageHtmlMap : aHPageMap; + } + else if ( eId == RndStdIds::FLY_AT_FLY ) + { + // own vertical alignment map for to frame + // anchored objects. + m_pVMap = m_bHtmlMode ? aVFlyHtmlMap : aVFrameMap; + m_pHMap = m_bHtmlMode ? aHFlyHtmlMap : aHFrameMap; + } + else if ( eId == RndStdIds::FLY_AT_PARA ) + { + if(m_bHtmlMode) + { + m_pVMap = aVParaHtmlMap; + m_pHMap = aHParaHtmlAbsMap; + } + else + { + m_pVMap = aVParaMap; + m_pHMap = aHParaMap; + } + } + else if ( eId == RndStdIds::FLY_AT_CHAR ) + { + if(m_bHtmlMode) + { + m_pVMap = aVCharHtmlAbsMap; + m_pHMap = aHCharHtmlAbsMap; + } + else + { + m_pVMap = aVCharMap; + m_pHMap = aHCharMap; + } + } + else if ( eId == RndStdIds::FLY_AS_CHAR ) + { + m_pVMap = m_bHtmlMode ? aVAsCharHtmlMap : aVAsCharMap; + m_pHMap = nullptr; + bEnable = false; + } + m_xHorizontalDLB->set_sensitive( bEnable ); + m_xHorizontalFT->set_sensitive( bEnable ); + + // select current Pos + // horizontal + if ( nH < 0 ) + { + nH = m_nOldH; + nHRel = m_nOldHRel; + } + sal_Int32 nMapPos = FillPosLB(m_pHMap, nH, nHRel, *m_xHorizontalDLB); + FillRelLB(m_pHMap, nMapPos, nH, nHRel, *m_xHoriRelationLB, *m_xHoriRelationFT); + + // vertical + if ( nV < 0 ) + { + nV = m_nOldV; + nVRel = m_nOldVRel; + } + nMapPos = FillPosLB(m_pVMap, nV, nVRel, *m_xVerticalDLB); + FillRelLB(m_pVMap, nMapPos, nV, nVRel, *m_xVertRelationLB, *m_xVertRelationFT); + + bEnable = nH == text::HoriOrientation::NONE && eId != RndStdIds::FLY_AS_CHAR; + if (!bEnable) + m_xAtHorzPosED->set_value(0, FieldUnit::TWIP); + else + { + if (nX != LONG_MAX) + m_xAtHorzPosED->set_value(m_xAtHorzPosED->normalize(nX), FieldUnit::TWIP); + } + m_xAtHorzPosFT->set_sensitive( bEnable ); + m_xAtHorzPosED->set_sensitive( bEnable ); + + bEnable = nV == text::VertOrientation::NONE; + if ( !bEnable ) + m_xAtVertPosED->set_value(0, FieldUnit::TWIP); + else + { + if (eId == RndStdIds::FLY_AS_CHAR) + { + if ( nY == LONG_MAX ) + nY = 0; + else + nY *= -1; + } + if ( nY != LONG_MAX ) + m_xAtVertPosED->set_value(m_xAtVertPosED->normalize(nY), FieldUnit::TWIP); + } + m_xAtVertPosFT->set_sensitive( bEnable && m_bAllowVertPositioning ); + m_xAtVertPosED->set_sensitive( bEnable && m_bAllowVertPositioning ); + UpdateExample(); +} + +sal_Int32 SwFramePage::FillPosLB(const FrameMap* _pMap, + const sal_Int16 _nAlign, + const sal_Int16 _nRel, + weld::ComboBox& _rLB ) +{ + OUString sSelEntry; + const OUString sOldEntry = _rLB.get_active_text(); + + _rLB.clear(); + + // i#22341 determine all possible listbox relations for + // given relation for map <aVCharMap> + const LB nLBRelations = (_pMap != aVCharMap) + ? LB::NONE + : ::lcl_GetLBRelationsForRelations( _nRel ); + + // fill Listbox + size_t nCount = ::lcl_GetFrameMapCount(_pMap); + for (size_t i = 0; _pMap && i < nCount; ++i) + { +// Why not from the left/from inside or from above? + SvxSwFramePosString::StringId eStrId = m_xMirrorPagesCB->get_active() ? _pMap[i].eMirrorStrId : _pMap[i].eStrId; + // --> OD 2009-08-31 #mongolianlayout# + eStrId = lcl_ChangeResIdToVerticalOrRTL( eStrId, + m_bIsVerticalFrame, + m_bIsVerticalL2R, + m_bIsInRightToLeft); + OUString sEntry(SvxSwFramePosString::GetString(eStrId)); + if (_rLB.find_text(sEntry) == -1) + { + // don't insert entries when frames are character bound + _rLB.append_text(sEntry); + } + // i#22341 - 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.get_count()) + _rLB.set_active(0); + + PosHdl(_rLB); + + return GetMapPos(_pMap, _rLB); +} + +void SwFramePage::FillRelLB(const FrameMap* _pMap, + const sal_uInt16 _nLBSelPos, + const sal_Int16 _nAlign, + const sal_Int16 _nRel, + weld::ComboBox& _rLB, + weld::Label& _rFT) +{ + OUString sSelEntry; + LB nLBRelations = LB::NONE; + size_t nMapCount = ::lcl_GetFrameMapCount(_pMap); + + _rLB.clear(); + + if (_nLBSelPos < nMapCount) + { + if (_pMap == aVAsCharHtmlMap || _pMap == aVAsCharMap) + { + const OUString sOldEntry(_rLB.get_active_text()); + SvxSwFramePosString::StringId eStrId = _pMap[_nLBSelPos].eStrId; + + for (size_t nMapPos = 0; nMapPos < nMapCount; nMapPos++) + { + if (_pMap[nMapPos].eStrId == eStrId) + { + nLBRelations = _pMap[nMapPos].nLBRelations; + for (RelationMap const & rCharMap : aAsCharRelationMap) + { + if (nLBRelations & rCharMap.nLBRelation) + { + // --> OD 2009-08-31 #mongolianlayout# + SvxSwFramePosString::StringId sStrId1 = + lcl_ChangeResIdToVerticalOrRTL( rCharMap.eStrId, + m_bIsVerticalFrame, + m_bIsVerticalL2R, + m_bIsInRightToLeft); + const OUString sEntry = SvxSwFramePosString::GetString(sStrId1); + _rLB.append(weld::toId(&rCharMap), 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 + { + // special handling for map <aVCharMap>, + // because its ambiguous in its <eStrId>/<eMirrorStrId>. + if ( _pMap == aVCharMap ) + { + nLBRelations = ::lcl_GetLBRelationsForStrID( _pMap, + ( m_xMirrorPagesCB->get_active() + ? _pMap[_nLBSelPos].eMirrorStrId + : _pMap[_nLBSelPos].eStrId), + m_xMirrorPagesCB->get_active() ); + } + else + { + nLBRelations = _pMap[_nLBSelPos].nLBRelations; + } + + for (sal_uLong nBit = 1; nBit < 0x80000000; nBit <<= 1) + { + if (nLBRelations & static_cast<LB>(nBit)) + { + for (RelationMap const & rMap : aRelationMap) + { + if (rMap.nLBRelation == static_cast<LB>(nBit)) + { + SvxSwFramePosString::StringId eStrId1 = m_xMirrorPagesCB->get_active() ? + rMap.eMirrorStrId : rMap.eStrId; + // --> OD 2009-08-31 #mongolianlayout# + eStrId1 = + lcl_ChangeResIdToVerticalOrRTL( eStrId1, + m_bIsVerticalFrame, + m_bIsVerticalL2R, + m_bIsInRightToLeft); + const OUString sEntry = SvxSwFramePosString::GetString(eStrId1); + _rLB.append(weld::toId(&rMap), sEntry); + if (sSelEntry.isEmpty() && rMap.nRelation == _nRel) + sSelEntry = sEntry; + } + } + } + } + if (!sSelEntry.isEmpty()) + _rLB.set_active_text(sSelEntry); + else + { + // Probably anchor switch. So look for similar relation + sal_Int16 nSimRel = -1; + switch (_nRel) + { + case text::RelOrientation::FRAME: + nSimRel = text::RelOrientation::PAGE_FRAME; + break; + case text::RelOrientation::PRINT_AREA: + nSimRel = text::RelOrientation::PAGE_PRINT_AREA; + break; + case text::RelOrientation::PAGE_LEFT: + nSimRel = text::RelOrientation::FRAME_LEFT; + break; + case text::RelOrientation::PAGE_RIGHT: + nSimRel = text::RelOrientation::FRAME_RIGHT; + break; + case text::RelOrientation::FRAME_LEFT: + nSimRel = text::RelOrientation::PAGE_LEFT; + break; + case text::RelOrientation::FRAME_RIGHT: + nSimRel = text::RelOrientation::PAGE_RIGHT; + break; + case text::RelOrientation::PAGE_FRAME: + nSimRel = text::RelOrientation::FRAME; + break; + case text::RelOrientation::PAGE_PRINT_AREA: + nSimRel = text::RelOrientation::PRINT_AREA; + break; + + default: + if (_rLB.get_active() != -1) + { + RelationMap *pEntry = weld::fromId<RelationMap*>(_rLB.get_id(_rLB.get_count() - 1)); + nSimRel = pEntry->nRelation; + } + break; + } + + for (int i = 0; i < _rLB.get_count(); i++) + { + RelationMap *pEntry = weld::fromId<RelationMap*>(_rLB.get_id(i)); + if (pEntry->nRelation == nSimRel) + { + _rLB.set_active(i); + break; + } + } + + if (_rLB.get_active() == -1) + _rLB.set_active(0); + } + } + } + + const bool bEnable = _rLB.get_count() != 0 + && (&_rLB != m_xVertRelationLB.get() || m_bAllowVertPositioning); + _rLB.set_sensitive( bEnable ); + _rFT.set_sensitive( bEnable ); + + RelHdl(_rLB); +} + +sal_Int16 SwFramePage::GetRelation(const weld::ComboBox& rRelationLB) +{ + const auto nPos = rRelationLB.get_active(); + if (nPos != -1) + { + RelationMap *pEntry = weld::fromId<RelationMap *>(rRelationLB.get_id(nPos)); + return pEntry->nRelation; + } + + return 0; +} + +sal_Int16 SwFramePage::GetAlignment(FrameMap const *pMap, sal_Int32 nMapPos, + const weld::ComboBox& rRelationLB) +{ + if (!pMap || nMapPos < 0) + return 0; + + const size_t nMapCount = ::lcl_GetFrameMapCount(pMap); + + if (o3tl::make_unsigned(nMapPos) >= nMapCount) + return 0; + + // i#22341 special handling also for map <aVCharMap>, + // because it contains ambiguous items for alignment + if ( pMap != aVAsCharHtmlMap && pMap != aVAsCharMap && pMap != aVCharMap ) + return pMap[nMapPos].nAlign; + + if (rRelationLB.get_active() == -1) + return 0; + + const RelationMap *const pRelationMap = weld::fromId<const RelationMap*>( + rRelationLB.get_active_id()); + const LB nRel = pRelationMap->nLBRelation; + const SvxSwFramePosString::StringId eStrId = pMap[nMapPos].eStrId; + + for (size_t i = 0; i < nMapCount; ++i) + { + if (pMap[i].eStrId == eStrId && (pMap[i].nLBRelations & nRel)) + return pMap[i].nAlign; + } + + return 0; +} + +sal_Int32 SwFramePage::GetMapPos(const FrameMap *pMap, const weld::ComboBox& rAlignLB) +{ + sal_Int32 nMapPos = 0; + auto nLBSelPos = rAlignLB.get_active(); + + if (nLBSelPos != -1) + { + if (pMap == aVAsCharHtmlMap || pMap == aVAsCharMap) + { + const size_t nMapCount = ::lcl_GetFrameMapCount(pMap); + const OUString sSelEntry(rAlignLB.get_active_text()); + + for (size_t i = 0; i < nMapCount; i++) + { + SvxSwFramePosString::StringId eResId = pMap[i].eStrId; + + OUString sEntry = SvxSwFramePosString::GetString(eResId); + sEntry = MnemonicGenerator::EraseAllMnemonicChars( sEntry ); + + if (sEntry == sSelEntry) + { + nMapPos = static_cast< sal_Int32 >(i); + break; + } + } + } + else + nMapPos = nLBSelPos; + } + + return nMapPos; +} + +RndStdIds SwFramePage::GetAnchor() const +{ + RndStdIds nRet = RndStdIds::FLY_AT_PAGE; + if (m_xAnchorAtParaRB->get_active()) + { + nRet = RndStdIds::FLY_AT_PARA; + } + else if (m_xAnchorAtCharRB->get_active()) + { + nRet = RndStdIds::FLY_AT_CHAR; + } + else if (m_xAnchorAsCharRB->get_active()) + { + nRet = RndStdIds::FLY_AS_CHAR; + } + else if (m_xAnchorAtFrameRB->get_active()) + { + nRet = RndStdIds::FLY_AT_FLY; + } + return nRet; +} + +// Bsp - Update +void SwFramePage::ActivatePage(const SfxItemSet& rSet) +{ + m_bNoModifyHdl = true; + Init(rSet); + m_bNoModifyHdl = false; + //lock PercentFields + m_xWidthED->LockAutoCalculation(true); + m_xHeightED->LockAutoCalculation(true); + RangeModifyHdl(); // set all maximum values initially + m_xHeightED->LockAutoCalculation(false); + m_xWidthED->LockAutoCalculation(false); + m_xFollowTextFlowCB->save_state(); + m_xFlySplitCB->save_state(); +} + +DeactivateRC SwFramePage::DeactivatePage(SfxItemSet * _pSet) +{ + if ( _pSet ) + { + FillItemSet( _pSet ); + + if (!m_bFormat) // tdf#112574 no anchor in styles + { + //FillItemSet doesn't set the anchor into the set when it matches + //the original. But for the other pages we need the current anchor. + SwWrtShell* pSh = m_bFormat ? ::GetActiveWrtShell() + : getFrameDlgParentShell(); + if (pSh) + { + RndStdIds eAnchorId = GetAnchor(); + SwFormatAnchor aAnc( eAnchorId, eAnchorId == RndStdIds::FLY_AT_PAGE ? pSh->GetPhyPageNum() : 0 ); + _pSet->Put( aAnc ); + } + } + } + + return DeactivateRC::LeavePage; +} + +// swap left/right with inside/outside +IMPL_LINK_NOARG(SwFramePage, MirrorHdl, weld::Toggleable&, void) +{ + RndStdIds eId = GetAnchor(); + InitPos(eId, -1, 0, -1, 0, LONG_MAX, LONG_MAX); +} + +IMPL_LINK( SwFramePage, RelSizeClickHdl, weld::Toggleable&, rBtn, void ) +{ + if (&rBtn == m_xRelWidthCB.get()) + { + m_xWidthED->ShowPercent(rBtn.get_active()); + m_xRelWidthRelationLB->set_sensitive(rBtn.get_active()); + if (rBtn.get_active()) + m_xWidthED->get()->set_max(MAX_PERCENT_WIDTH, FieldUnit::NONE); + } + else // rBtn == m_xRelHeightCB.get() + { + m_xHeightED->ShowPercent(rBtn.get_active()); + m_xRelHeightRelationLB->set_sensitive(rBtn.get_active()); + if (rBtn.get_active()) + m_xHeightED->get()->set_max(MAX_PERCENT_HEIGHT, FieldUnit::NONE); + } + + RangeModifyHdl(); // correct the values again + + if (&rBtn == m_xRelWidthCB.get()) + ModifyHdl(*m_xWidthED->get()); + else // rBtn == m_xRelHeightCB.get() + ModifyHdl(*m_xHeightED->get()); +} + +// range check +IMPL_LINK_NOARG(SwFramePage, RangeModifyClickHdl, weld::Toggleable&, void) +{ + RangeModifyHdl(); +} + +void SwFramePage::RangeModifyHdl() +{ + if (m_bNoModifyHdl) + return; + + SwWrtShell* pSh = m_bFormat ? ::GetActiveWrtShell() + : getFrameDlgParentShell(); + OSL_ENSURE(pSh , "shell not found"); + if (!pSh) + return; + + SwFlyFrameAttrMgr aMgr( m_bNew, pSh, GetItemSet() ); + SvxSwFrameValidation aVal; + + aVal.nAnchorType = GetAnchor(); + aVal.bAutoHeight = m_xAutoHeightCB->get_active(); + aVal.bMirror = m_xMirrorPagesCB->get_active(); + aVal.bFollowTextFlow = m_xFollowTextFlowCB->get_active(); + + if ( m_pHMap ) + { + // alignment horizontal + const sal_Int32 nMapPos = GetMapPos(m_pHMap, *m_xHorizontalDLB); + aVal.nHoriOrient = GetAlignment(m_pHMap, nMapPos, *m_xHoriRelationLB); + aVal.nHRelOrient = GetRelation(*m_xHoriRelationLB); + } + else + aVal.nHoriOrient = text::HoriOrientation::NONE; + + if ( m_pVMap ) + { + // alignment vertical + const sal_Int32 nMapPos = GetMapPos(m_pVMap, *m_xVerticalDLB); + aVal.nVertOrient = GetAlignment(m_pVMap, nMapPos, *m_xVertRelationLB); + aVal.nVRelOrient = GetRelation(*m_xVertRelationLB); + } + else + aVal.nVertOrient = text::VertOrientation::NONE; + + const tools::Long nAtHorzPosVal = static_cast< tools::Long >( + m_xAtHorzPosED->denormalize(m_xAtHorzPosED->get_value(FieldUnit::TWIP)) ); + const tools::Long nAtVertPosVal = static_cast< tools::Long >( + m_xAtVertPosED->denormalize(m_xAtVertPosED->get_value(FieldUnit::TWIP)) ); + + aVal.nHPos = nAtHorzPosVal; + aVal.nVPos = nAtVertPosVal; + + aMgr.ValidateMetrics(aVal, mpToCharContentPos, true); // one time, to get reference values for percental values + + // set reference values for percental values (100%) ... + m_xWidthED->SetRefValue(aVal.aPercentSize.Width()); + m_xHeightED->SetRefValue(aVal.aPercentSize.Height()); + + // ... and correctly convert width and height with it + SwTwips nWidth = static_cast< SwTwips >(m_xWidthED->DenormalizePercent(m_xWidthED->get_value(FieldUnit::TWIP))); + SwTwips nHeight = static_cast< SwTwips >(m_xHeightED->DenormalizePercent(m_xHeightED->get_value(FieldUnit::TWIP))); + aVal.nWidth = nWidth; + aVal.nHeight = nHeight; + + aMgr.ValidateMetrics(aVal, mpToCharContentPos); // one more time, to determine all remaining values with correct width and height. + + // all columns have to be correct + const SfxItemSet* pExampleSet = GetDialogExampleSet(); + if (pExampleSet && SfxItemState::DEFAULT <= pExampleSet->GetItemState(RES_COL)) + { + const SwFormatCol& rCol = pExampleSet->Get(RES_COL); + if ( rCol.GetColumns().size() > 1 ) + { + for (const SwColumn & i : rCol.GetColumns()) + { + aVal.nMinWidth += i.GetLeft() + + i.GetRight() + + MINFLY; + } + aVal.nMinWidth -= MINFLY;//one was already in there! + } + } + + nWidth = aVal.nWidth; + nHeight = aVal.nHeight; + + // minimum range also for template + m_xHeightED->set_min(m_xHeightED->NormalizePercent(aVal.nMinHeight), FieldUnit::TWIP); + m_xWidthED->set_min(m_xWidthED->NormalizePercent(aVal.nMinWidth), FieldUnit::TWIP); + + SwTwips nMaxWidth(aVal.nMaxWidth); + SwTwips nMaxHeight(aVal.nMaxHeight); + + if (aVal.bAutoHeight && (m_sDlgType == "PictureDialog" || m_sDlgType == "ObjectDialog")) + { + SwTwips nTmp = std::min(nWidth * nMaxHeight / std::max(nHeight, SwTwips(1)), nMaxHeight); + m_xWidthED->set_max(m_xWidthED->NormalizePercent(nTmp), FieldUnit::TWIP); + + nTmp = std::min(nHeight * nMaxWidth / std::max(nWidth, SwTwips(1)), nMaxWidth); + m_xHeightED->set_max(m_xWidthED->NormalizePercent(nTmp), FieldUnit::TWIP); + } + else + { + SwTwips nTmp = static_cast< SwTwips >(m_xHeightED->NormalizePercent(nMaxHeight)); + m_xHeightED->set_max(nTmp, FieldUnit::TWIP); + + nTmp = static_cast< SwTwips >(m_xWidthED->NormalizePercent(nMaxWidth)); + m_xWidthED->set_max(nTmp, FieldUnit::TWIP); + } + + m_xAtHorzPosED->set_range(m_xAtHorzPosED->normalize(aVal.nMinHPos), + m_xAtHorzPosED->normalize(aVal.nMaxHPos), + FieldUnit::TWIP); + if (aVal.nHPos != nAtHorzPosVal) + m_xAtHorzPosED->set_value(m_xAtHorzPosED->normalize(aVal.nHPos), FieldUnit::TWIP); + + const SwTwips nUpperOffset = (aVal.nAnchorType == RndStdIds::FLY_AS_CHAR) + ? m_nUpperBorder : 0; + const SwTwips nLowerOffset = (aVal.nAnchorType == RndStdIds::FLY_AS_CHAR) + ? m_nLowerBorder : 0; + + m_xAtVertPosED->set_range(m_xAtVertPosED->normalize(aVal.nMinVPos + nLowerOffset + nUpperOffset), + m_xAtVertPosED->normalize(aVal.nMaxVPos), + FieldUnit::TWIP); + if (aVal.nVPos != nAtVertPosVal) + m_xAtVertPosED->set_value(m_xAtVertPosED->normalize(aVal.nVPos), FieldUnit::TWIP); +} + +IMPL_LINK_NOARG(SwFramePage, AnchorTypeHdl, weld::Toggleable&, void) +{ + m_xMirrorPagesCB->set_sensitive(!m_xAnchorAsCharRB->get_active()); + + // i#18732 - enable check box 'Follow text flow' for anchor + // type to-paragraph' and to-character + // i#22305 - enable check box 'Follow text + // flow' also for anchor type to-frame. + m_xFollowTextFlowCB->set_sensitive(m_xAnchorAtParaRB->get_active() || + m_xAnchorAtCharRB->get_active() || + m_xAnchorAtFrameRB->get_active()); + m_xFlySplitCB->set_sensitive(m_xAnchorAtParaRB->get_active()); + + RndStdIds eId = GetAnchor(); + + InitPos( eId, -1, 0, -1, 0, LONG_MAX, LONG_MAX); + RangeModifyHdl(); + + if(m_bHtmlMode) + { + PosHdl(*m_xHorizontalDLB); + PosHdl(*m_xVerticalDLB); + } + + EnableVerticalPositioning( !(m_bIsMathOLE && m_bIsMathBaselineAlignment + && RndStdIds::FLY_AS_CHAR == eId) ); +} + +IMPL_LINK( SwFramePage, PosHdl, weld::ComboBox&, rLB, void ) +{ + bool bHori = &rLB == m_xHorizontalDLB.get(); + weld::ComboBox *pRelLB = bHori ? m_xHoriRelationLB.get() : m_xVertRelationLB.get(); + weld::Label *pRelFT = bHori ? m_xHoriRelationFT.get() : m_xVertRelationFT.get(); + FrameMap const *pMap = bHori ? m_pHMap : m_pVMap; + + const sal_Int32 nMapPos = GetMapPos(pMap, rLB); + const sal_Int16 nAlign = GetAlignment(pMap, nMapPos, *pRelLB); + + if (bHori) + { + bool bEnable = text::HoriOrientation::NONE == nAlign; + m_xAtHorzPosED->set_sensitive( bEnable ); + m_xAtHorzPosFT->set_sensitive( bEnable ); + } + else + { + bool bEnable = text::VertOrientation::NONE == nAlign && m_bAllowVertPositioning; + m_xAtVertPosED->set_sensitive( bEnable ); + m_xAtVertPosFT->set_sensitive( bEnable ); + } + + RangeModifyHdl(); + + sal_Int16 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(); + + if (bHori) + m_bAtHorzPosModified = true; + else + m_bAtVertPosModified = true; + + // special treatment for HTML-Mode with horizontal-vertical-dependencies + if(!(m_bHtmlMode && (RndStdIds::FLY_AT_CHAR == GetAnchor()))) + return; + + bool bSet = false; + if(bHori) + { + // right is allowed only above - from the left only above + // from the left at character -> below + if((text::HoriOrientation::LEFT == nAlign || text::HoriOrientation::RIGHT == nAlign) && + 0 == m_xVerticalDLB->get_active()) + { + if(text::RelOrientation::FRAME == nRel) + m_xVerticalDLB->set_active(1); + else + m_xVerticalDLB->set_active(0); + bSet = true; + } + else if(text::HoriOrientation::LEFT == nAlign && 1 == m_xVerticalDLB->get_active()) + { + m_xVerticalDLB->set_active(0); + bSet = true; + } + else if(text::HoriOrientation::NONE == nAlign && 1 == m_xVerticalDLB->get_active()) + { + m_xVerticalDLB->set_active(0); + bSet = true; + } + if(bSet) + PosHdl(*m_xVerticalDLB); + } + else + { + if(text::VertOrientation::TOP == nAlign) + { + if (1 == m_xHorizontalDLB->get_active()) + { + m_xHorizontalDLB->set_active(0); + bSet = true; + } + m_xHoriRelationLB->set_active(1); + } + else if(text::VertOrientation::CHAR_BOTTOM == nAlign) + { + if (2 == m_xHorizontalDLB->get_active()) + { + m_xHorizontalDLB->set_active(0); + bSet = true; + } + m_xHoriRelationLB->set_active(0) ; + } + if(bSet) + PosHdl(*m_xHorizontalDLB); + } +} + +// horizontal Pos +IMPL_LINK( SwFramePage, RelHdl, weld::ComboBox&, rLB, void ) +{ + bool bHori = &rLB == m_xHoriRelationLB.get(); + + UpdateExample(); + + if (bHori) + m_bAtHorzPosModified = true; + else + m_bAtVertPosModified = true; + + if (m_bHtmlMode && (RndStdIds::FLY_AT_CHAR == GetAnchor())) + { + if(bHori) + { + const sal_Int16 nRel = GetRelation(*m_xHoriRelationLB); + if(text::RelOrientation::PRINT_AREA == nRel && 0 == m_xVerticalDLB->get_active()) + { + m_xVerticalDLB->set_active(1); + } + else if(text::RelOrientation::CHAR == nRel && 1 == m_xVerticalDLB->get_active()) + { + m_xVerticalDLB->set_active(0); + } + } + } + RangeModifyHdl(); +} + +IMPL_LINK_NOARG(SwFramePage, RealSizeHdl, weld::Button&, void) +{ + m_xWidthED->set_value(m_xWidthED->NormalizePercent(m_aGrfSize.Width()), FieldUnit::TWIP); + m_xHeightED->set_value(m_xHeightED->NormalizePercent(m_aGrfSize.Height()), FieldUnit::TWIP); + m_fWidthHeightRatio = m_aGrfSize.Height() ? double(m_aGrfSize.Width()) / double(m_aGrfSize.Height()) : 1.0; + UpdateExample(); +} + +IMPL_LINK_NOARG(SwFramePage, AutoWidthClickHdl, weld::Toggleable&, void) +{ + if( !IsInGraficMode() ) + HandleAutoCB( m_xAutoWidthCB->get_active(), *m_xWidthFT, *m_xWidthAutoFT, *m_xWidthED->get() ); +} + +IMPL_LINK_NOARG(SwFramePage, AutoHeightClickHdl, weld::Toggleable&, void) +{ + if (!IsInGraficMode()) + HandleAutoCB(m_xAutoHeightCB->get_active(), *m_xHeightFT, *m_xHeightAutoFT, *m_xWidthED->get()); +} + +IMPL_LINK( SwFramePage, ModifyHdl, weld::MetricSpinButton&, rEdit, void ) +{ + SwTwips nWidth = static_cast< SwTwips >(m_xWidthED->DenormalizePercent(m_xWidthED->get_value(FieldUnit::TWIP))); + SwTwips nHeight = static_cast< SwTwips >(m_xHeightED->DenormalizePercent(m_xHeightED->get_value(FieldUnit::TWIP))); + if (m_xFixedRatioCB->get_active()) + { + if (&rEdit == m_xWidthED->get()) + { + nHeight = SwTwips(static_cast<double>(nWidth) / m_fWidthHeightRatio); + m_xHeightED->set_value(m_xHeightED->NormalizePercent(nHeight), FieldUnit::TWIP); + } + else if (&rEdit == m_xHeightED->get()) + { + nWidth = SwTwips(static_cast<double>(nHeight) * m_fWidthHeightRatio); + m_xWidthED->set_value(m_xWidthED->NormalizePercent(nWidth), FieldUnit::TWIP); + } + } + m_fWidthHeightRatio = nHeight ? double(nWidth) / double(nHeight) : 1.0; + UpdateExample(); +} + +void SwFramePage::UpdateExample() +{ + auto nPos = m_xHorizontalDLB->get_active(); + if (m_pHMap && nPos != -1) + { + const sal_Int32 nMapPos = GetMapPos(m_pHMap, *m_xHorizontalDLB); + m_aExampleWN.SetHAlign(GetAlignment(m_pHMap, nMapPos, *m_xHoriRelationLB)); + m_aExampleWN.SetHoriRel(GetRelation(*m_xHoriRelationLB)); + } + + nPos = m_xVerticalDLB->get_active(); + if (m_pVMap && nPos != -1) + { + const sal_Int32 nMapPos = GetMapPos(m_pVMap, *m_xVerticalDLB); + m_aExampleWN.SetVAlign(GetAlignment(m_pVMap, nMapPos, *m_xVertRelationLB)); + m_aExampleWN.SetVertRel(GetRelation(*m_xVertRelationLB)); + } + + // size + auto nXPos = m_xAtHorzPosED->denormalize(m_xAtHorzPosED->get_value(FieldUnit::TWIP)); + auto nYPos = m_xAtVertPosED->denormalize(m_xAtVertPosED->get_value(FieldUnit::TWIP)); + m_aExampleWN.SetRelPos(Point(nXPos, nYPos)); + + m_aExampleWN.SetAnchor(GetAnchor()); + m_aExampleWN.Invalidate(); +} + +void SwFramePage::Init(const SfxItemSet& rSet) +{ + if(!m_bFormat) + { + SwWrtShell* pSh = getFrameDlgParentShell(); + + // size + const bool bSizeFixed = pSh->IsSelObjProtected( FlyProtectFlags::Fixed ) != FlyProtectFlags::NONE; + + m_xWidthED->set_sensitive( !bSizeFixed ); + m_xHeightED->set_sensitive( !bSizeFixed ); + + // size controls for math OLE objects + if ( m_sDlgType == "ObjectDialog" && ! m_bNew ) + { + // disable width and height for math objects + const SvGlobalName& rFactNm( pSh->GetOLEObject()->getClassID() ); + + static struct GlobalNameId { + sal_uInt32 n1; + sal_uInt16 n2, n3; + sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15; + } const aGlbNmIds[] = { { SO3_SM_CLASSID_60 }, { SO3_SM_CLASSID_50 }, + { SO3_SM_CLASSID_40 }, { SO3_SM_CLASSID_30 } }; + + for (const GlobalNameId & rId : aGlbNmIds) { + SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3, + rId.b8, rId.b9, rId.b10, rId.b11, + rId.b12, rId.b13, rId.b14, rId.b15 ); + + if( rFactNm == aGlbNm ) + { + // disable size controls for math OLE objects + m_xWidthFT->set_sensitive(false); + m_xWidthED->set_sensitive(false); + m_xRelWidthCB->set_sensitive(false); + m_xHeightFT->set_sensitive(false); + m_xHeightED->set_sensitive(false); + m_xRelHeightCB->set_sensitive(false); + m_xFixedRatioCB->set_sensitive(false); + m_xRealSizeBT->set_sensitive(false); + break; + } + } + + // TODO/LATER: get correct aspect + if(0 != (pSh->GetOLEObject()->getStatus( embed::Aspects::MSOLE_CONTENT ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) ) + m_xRealSizeBT->set_sensitive(false); + } + } + + const SwFormatFrameSize& rSize = rSet.Get(RES_FRM_SIZE); + sal_Int64 nWidth = m_xWidthED->NormalizePercent(rSize.GetWidth()); + sal_Int64 nHeight = m_xHeightED->NormalizePercent(rSize.GetHeight()); + + if (nWidth != m_xWidthED->get_value(FieldUnit::TWIP)) + m_xWidthED->set_value(nWidth, FieldUnit::TWIP); + + if (nHeight != m_xHeightED->get_value(FieldUnit::TWIP)) + m_xHeightED->set_value(nHeight, FieldUnit::TWIP); + + if (!IsInGraficMode()) + { + SwFrameSize eSize = rSize.GetHeightSizeType(); + bool bCheck = eSize != SwFrameSize::Fixed; + m_xAutoHeightCB->set_active(bCheck); + HandleAutoCB( bCheck, *m_xHeightFT, *m_xHeightAutoFT, *m_xWidthED->get() ); + if( eSize == SwFrameSize::Variable ) + m_xHeightED->set_value(m_xHeightED->get_min()); + + eSize = rSize.GetWidthSizeType(); + bCheck = eSize != SwFrameSize::Fixed; + m_xAutoWidthCB->set_active(bCheck); + HandleAutoCB( bCheck, *m_xWidthFT, *m_xWidthAutoFT, *m_xWidthED->get() ); + if( eSize == SwFrameSize::Variable ) + m_xWidthED->set_value(m_xWidthED->get_min()); + + if ( !m_bFormat ) + { + SwWrtShell* pSh = getFrameDlgParentShell(); + const SwFrameFormat* pFormat = pSh->GetFlyFrameFormat(); + if( pFormat && pFormat->GetChain().GetNext() ) + m_xAutoHeightCB->set_sensitive( false ); + } + } + else + m_xAutoHeightCB->hide(); + + // organise circulation-gap for character bound frames + const SvxULSpaceItem &rUL = rSet.Get(RES_UL_SPACE); + m_nUpperBorder = rUL.GetUpper(); + m_nLowerBorder = rUL.GetLower(); + + if (SfxItemState::SET == rSet.GetItemState(FN_KEEP_ASPECT_RATIO)) + m_xFixedRatioCB->set_active(rSet.Get(FN_KEEP_ASPECT_RATIO).GetValue()); + + // columns + SwFormatCol aCol( rSet.Get(RES_COL) ); + ::FitToActualSize( aCol, o3tl::narrowing<sal_uInt16>(rSize.GetWidth()) ); + + RndStdIds eAnchorId = GetAnchor(); + + if ( m_bNew && !m_bFormat ) + InitPos(eAnchorId, -1, 0, -1, 0, LONG_MAX, LONG_MAX); + else + { + const SwFormatHoriOrient& rHori = rSet.Get(RES_HORI_ORIENT); + const SwFormatVertOrient& rVert = rSet.Get(RES_VERT_ORIENT); + m_nOldH = rHori.GetHoriOrient(); + m_nOldHRel = rHori.GetRelationOrient(); + m_nOldV = rVert.GetVertOrient(); + m_nOldVRel = rVert.GetRelationOrient(); + + if (eAnchorId == RndStdIds::FLY_AT_PAGE) + { + if (m_nOldHRel == text::RelOrientation::FRAME) + m_nOldHRel = text::RelOrientation::PAGE_FRAME; + else if (m_nOldHRel == text::RelOrientation::PRINT_AREA) + m_nOldHRel = text::RelOrientation::PAGE_PRINT_AREA; + if (m_nOldVRel == text::RelOrientation::FRAME) + m_nOldVRel = text::RelOrientation::PAGE_FRAME; + else if (m_nOldVRel == text::RelOrientation::PRINT_AREA) + m_nOldVRel = text::RelOrientation::PAGE_PRINT_AREA; + } + + m_xMirrorPagesCB->set_active(rHori.IsPosToggle()); + m_xMirrorPagesCB->save_state(); + + InitPos(eAnchorId, + m_nOldH, + m_nOldHRel, + m_nOldV, + m_nOldVRel, + rHori.GetPos(), + rVert.GetPos()); + } + + // transparent for example + // circulation for example + const SwFormatSurround& rSurround = rSet.Get(RES_SURROUND); + m_aExampleWN.SetWrap( rSurround.GetSurround() ); + + if ( rSurround.GetSurround() == css::text::WrapTextMode_THROUGH ) + { + const SvxOpaqueItem& rOpaque = rSet.Get(RES_OPAQUE); + m_aExampleWN.SetTransparent(!rOpaque.GetValue()); + } + + // switch to percent if applicable + RangeModifyHdl(); // set reference values (for 100%) + + if (rSize.GetWidthPercent() == SwFormatFrameSize::SYNCED || rSize.GetHeightPercent() == SwFormatFrameSize::SYNCED) + m_xFixedRatioCB->set_active(true); + m_xFixedRatioCB->save_state(); + if (rSize.GetWidthPercent() && rSize.GetWidthPercent() != SwFormatFrameSize::SYNCED && + !m_xRelWidthCB->get_active()) + { + m_xRelWidthCB->set_active(true); + RelSizeClickHdl(*m_xRelWidthCB); + m_xWidthED->set_value(rSize.GetWidthPercent(), FieldUnit::PERCENT); + } + if (rSize.GetHeightPercent() && rSize.GetHeightPercent() != SwFormatFrameSize::SYNCED && + !m_xRelHeightCB->get_active()) + { + m_xRelHeightCB->set_active(true); + RelSizeClickHdl(*m_xRelHeightCB); + m_xHeightED->set_value(rSize.GetHeightPercent(), FieldUnit::PERCENT); + } + m_xRelWidthCB->save_state(); + m_xRelHeightCB->save_state(); + + if (rSize.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME) + m_xRelWidthRelationLB->set_active(1); + else + m_xRelWidthRelationLB->set_active(0); + + if (rSize.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME) + m_xRelHeightRelationLB->set_active(1); + else + m_xRelHeightRelationLB->set_active(0); +} + +void SwFramePage::SetFormatUsed(bool bFormatUsed) +{ + m_bFormat = bFormatUsed; + if (m_bFormat) + m_xAnchorAtFrameRB->hide(); +} + +void SwFramePage::EnableVerticalPositioning( bool bEnable ) +{ + m_bAllowVertPositioning = bEnable; + m_xVerticalFT->set_sensitive( bEnable ); + m_xVerticalDLB->set_sensitive( bEnable ); + m_xAtVertPosFT->set_sensitive( bEnable ); + m_xAtVertPosED->set_sensitive( bEnable ); + m_xVertRelationFT->set_sensitive( bEnable ); + m_xVertRelationLB->set_sensitive( bEnable ); +} + +SwGrfExtPage::SwGrfExtPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/picturepage.ui", "PicturePage", &rSet) + , m_bHtmlMode(false) + , m_xMirror(m_xBuilder->weld_widget("flipframe")) + , m_xMirrorVertBox(m_xBuilder->weld_check_button("vert")) + , m_xMirrorHorzBox(m_xBuilder->weld_check_button("hori")) + , m_xAllPagesRB(m_xBuilder->weld_radio_button("allpages")) + , m_xLeftPagesRB(m_xBuilder->weld_radio_button("leftpages")) + , m_xRightPagesRB(m_xBuilder->weld_radio_button("rightpages")) + , m_xConnectED(m_xBuilder->weld_entry("entry")) + , m_xBrowseBT(m_xBuilder->weld_button("browse")) + , m_xLinkFrame(m_xBuilder->weld_frame("linkframe")) + // RotGrfFlyFrame: Need Angle and RotateControls now + , m_xFlAngle(m_xBuilder->weld_frame("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)) + , m_xBmpWin(new weld::CustomWeld(*m_xBuilder, "preview", m_aBmpWin)) + // tdf#138843 place holder for the graphic type + , m_xLabelGraphicType(m_xBuilder->weld_label("label-graphic-type")) +{ + m_aBmpWin.SetBitmapEx(BitmapEx(RID_BMP_PREVIEW_FALLBACK)); + + m_xCtlAngle->SetLinkedField(m_xNfAngle.get(), 2); + + SetExchangeSupport(); + m_xMirrorHorzBox->connect_toggled(LINK(this, SwGrfExtPage, MirrorHdl)); + m_xMirrorVertBox->connect_toggled(LINK(this, SwGrfExtPage, MirrorHdl)); + m_xBrowseBT->connect_clicked(LINK(this, SwGrfExtPage, BrowseHdl)); +} + +SwGrfExtPage::~SwGrfExtPage() +{ + m_xBmpWin.reset(); + m_xCtlAngleWin.reset(); + m_xCtlAngle.reset(); + m_xGrfDlg.reset(); +} + +std::unique_ptr<SfxTabPage> SwGrfExtPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwGrfExtPage>(pPage, pController, *rSet); +} + +void SwGrfExtPage::Reset(const SfxItemSet *rSet) +{ + const sal_uInt16 nHtmlMode = ::GetHtmlMode(static_cast<const SwDocShell*>(SfxObjectShell::Current())); + m_bHtmlMode = (nHtmlMode & HTMLMODE_ON) != 0; + + const SfxBoolItem* pConnectItem = rSet->GetItemIfSet( FN_PARAM_GRF_CONNECT ); + if( pConnectItem && pConnectItem->GetValue() ) + { + m_xBrowseBT->set_sensitive(true); + m_xConnectED->set_editable(true); + } + + // RotGrfFlyFrame: Get RotationAngle and set at control + if(const SdrAngleItem* pAngleItem = rSet->GetItemIfSet( SID_ATTR_TRANSFORM_ANGLE, false)) + { + m_xCtlAngle->SetRotation(pAngleItem->GetValue()); + } + else + { + m_xCtlAngle->SetRotation(0_deg100); + } + m_xCtlAngle->SaveValue(); + + ActivatePage(*rSet); +} + +void SwGrfExtPage::ActivatePage(const SfxItemSet& rSet) +{ + const SvxProtectItem& rProt = rSet.Get(RES_PROTECT); + bool bProtContent = rProt.IsContentProtected(); + + const SfxPoolItem* pItem = nullptr; + bool bEnable = false; + bool bEnableMirrorRB = false; + + SfxItemState eState = rSet.GetItemState(RES_GRFATR_MIRRORGRF, true, &pItem); + if (SfxItemState::UNKNOWN != eState && !bProtContent && !m_bHtmlMode) + { + if( SfxItemState::SET != eState ) + pItem = &rSet.Get( RES_GRFATR_MIRRORGRF ); + + bEnable = true; + + MirrorGraph eMirror = static_cast<const SwMirrorGrf* >(pItem)->GetValue(); + switch( eMirror ) + { + case MirrorGraph::Dont: break; + case MirrorGraph::Vertical: m_xMirrorHorzBox->set_active(true); break; + case MirrorGraph::Horizontal: m_xMirrorVertBox->set_active(true); break; + case MirrorGraph::Both: m_xMirrorHorzBox->set_active(true); + m_xMirrorVertBox->set_active(true); + break; + default: + ; + } + + const int nPos = (static_cast<const SwMirrorGrf* >(pItem)->IsGrfToggle() ? 1 : 0) + + ((eMirror == MirrorGraph::Vertical || eMirror == MirrorGraph::Both) ? 2 : 0); + + bEnableMirrorRB = nPos != 0; + + switch (nPos) + { + case 1: // mirror at left / even pages + m_xLeftPagesRB->set_active(true); + m_xMirrorHorzBox->set_active(true); + break; + case 2: // mirror on all pages + m_xAllPagesRB->set_active(true); + break; + case 3: // mirror on right / odd pages + m_xRightPagesRB->set_active(true); + break; + default: + m_xAllPagesRB->set_active(true); + break; + } + } + + if( const SvxBrushItem* pGraphicBrushItem = rSet.GetItemIfSet( SID_ATTR_GRAF_GRAPHIC, false ) ) + { + if( !pGraphicBrushItem->GetGraphicLink().isEmpty() ) + { + m_aGrfName = m_aNewGrfName = pGraphicBrushItem->GetGraphicLink(); + m_xConnectED->set_text(m_aNewGrfName); + } + OUString referer; + SfxStringItem const * it = rSet.GetItem(SID_REFERER); + if (it != nullptr) { + referer = it->GetValue(); + } + const Graphic* pGrf = pGraphicBrushItem->GetGraphic(referer); + if( pGrf ) + { + m_aBmpWin.SetGraphic( *pGrf ); + m_xLabelGraphicType->set_label(GraphicHelper::GetImageType(*pGrf)); + } + } + + m_xConnectED->save_value(); + + m_xMirror->set_sensitive(bEnable); + m_xAllPagesRB->set_sensitive(bEnableMirrorRB); + m_xLeftPagesRB->set_sensitive(bEnableMirrorRB); + m_xRightPagesRB->set_sensitive(bEnableMirrorRB); + + m_xAllPagesRB->save_state(); + m_xLeftPagesRB->save_state(); + m_xRightPagesRB->save_state(); + m_xMirrorHorzBox->save_state(); + m_xMirrorVertBox->save_state(); + + m_aBmpWin.MirrorHorz( m_xMirrorVertBox->get_active() ); + m_aBmpWin.MirrorVert( m_xMirrorHorzBox->get_active() ); + m_aBmpWin.Invalidate(); +} + +bool SwGrfExtPage::FillItemSet( SfxItemSet *rSet ) +{ + bool bModified = false; + if ( m_xMirrorHorzBox->get_state_changed_from_saved() || + m_xMirrorVertBox->get_state_changed_from_saved() || + m_xAllPagesRB->get_state_changed_from_saved() || + m_xLeftPagesRB->get_state_changed_from_saved() || + m_xRightPagesRB->get_state_changed_from_saved() ) + { + bModified = true; + + bool bHori = false; + + if (m_xMirrorHorzBox->get_active() && + !m_xLeftPagesRB->get_active()) + bHori = true; + + MirrorGraph eMirror; + eMirror = m_xMirrorVertBox->get_active() && bHori ? + MirrorGraph::Both : bHori ? + MirrorGraph::Vertical : m_xMirrorVertBox->get_active() ? + MirrorGraph::Horizontal : MirrorGraph::Dont; + + bool bMirror = !m_xAllPagesRB->get_active(); + SwMirrorGrf aMirror( eMirror ); + aMirror.SetGrfToggle(bMirror ); + rSet->Put( aMirror ); + } + + if (m_aGrfName != m_aNewGrfName || m_xConnectED->get_value_changed_from_saved()) + { + bModified = true; + m_aGrfName = m_xConnectED->get_text(); + rSet->Put( SvxBrushItem( m_aGrfName, m_aFilterName, GPOS_LT, + SID_ATTR_GRAF_GRAPHIC )); + } + + // RotGrfFlyFrame: Safe rotation if modified + if(m_xCtlAngle->IsValueModified()) + { + rSet->Put(SdrAngleItem(SID_ATTR_TRANSFORM_ANGLE, m_xCtlAngle->GetRotation())); + bModified = true; + } + + return bModified; +} + +DeactivateRC SwGrfExtPage::DeactivatePage(SfxItemSet *_pSet) +{ + if( _pSet ) + FillItemSet( _pSet ); + return DeactivateRC::LeavePage; +} + +IMPL_LINK_NOARG(SwGrfExtPage, BrowseHdl, weld::Button&, void) +{ + if(!m_xGrfDlg) + { + m_xGrfDlg.reset(new FileDialogHelper( + ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW, + FileDialogFlags::Graphic, GetFrameWeld())); + m_xGrfDlg->SetTitle(m_xLinkFrame->get_label()); + } + m_xGrfDlg->SetDisplayDirectory(m_xConnectED->get_text()); + uno::Reference < ui::dialogs::XFilePicker3 > xFP = m_xGrfDlg->GetFilePicker(); + uno::Reference < ui::dialogs::XFilePickerControlAccess > xCtrlAcc(xFP, uno::UNO_QUERY); + xCtrlAcc->setValue( ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, uno::Any(true) ); + + if ( m_xGrfDlg->Execute() != ERRCODE_NONE ) + return; + +// remember selected filter + m_aFilterName = m_xGrfDlg->GetCurrentFilter(); + m_aNewGrfName = INetURLObject::decode( m_xGrfDlg->GetPath(), + INetURLObject::DecodeMechanism::Unambiguous ); + m_xConnectED->set_text(m_aNewGrfName); + //reset mirrors because maybe a Bitmap was swapped with + //another type of graphic that cannot be mirrored. + m_xMirrorVertBox->set_active(false); + m_xMirrorHorzBox->set_active(false); + m_xAllPagesRB->set_sensitive(false); + m_xLeftPagesRB->set_sensitive(false); + m_xRightPagesRB->set_sensitive(false); + m_aBmpWin.MirrorHorz(false); + m_aBmpWin.MirrorVert(false); + + Graphic aGraphic; + (void)GraphicFilter::LoadGraphic(m_xGrfDlg->GetPath(), OUString(), aGraphic); + m_aBmpWin.SetGraphic(aGraphic); + m_xLabelGraphicType->set_label(GraphicHelper::GetImageType(aGraphic)); + + bool bEnable = GraphicType::Bitmap == aGraphic.GetType() || + GraphicType::GdiMetafile == aGraphic.GetType(); + m_xMirrorVertBox->set_sensitive(bEnable); + m_xMirrorHorzBox->set_sensitive(bEnable); + m_xAllPagesRB->set_sensitive(bEnable); + m_xLeftPagesRB->set_sensitive(bEnable); + m_xRightPagesRB->set_sensitive(bEnable); + +} + +IMPL_LINK_NOARG(SwGrfExtPage, MirrorHdl, weld::Toggleable&, void) +{ + bool bEnable = m_xMirrorHorzBox->get_active(); + + m_aBmpWin.MirrorHorz( m_xMirrorVertBox->get_active() ); + m_aBmpWin.MirrorVert( bEnable ); + + m_xAllPagesRB->set_sensitive(bEnable); + m_xLeftPagesRB->set_sensitive(bEnable); + m_xRightPagesRB->set_sensitive(bEnable); + + if (!m_xAllPagesRB->get_active() && !m_xLeftPagesRB->get_active() && !m_xRightPagesRB->get_active()) + m_xAllPagesRB->set_active(true); +} + +// example window +BmpWindow::BmpWindow() + : m_bHorz(false) + , m_bVert(false) + , m_bGraphic(false) +{ +} + +void BmpWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + Size aSize = pDrawingArea->get_ref_device().LogicToPixel(Size(127 , 66), MapMode(MapUnit::MapAppFont)); + set_size_request(aSize.Width(), aSize.Height()); + SetOutputSizePixel(aSize); +} + +void BmpWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + // Setup + rRenderContext.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetDialogColor())); + rRenderContext.Erase(); + // #i119307# the graphic might have transparency, set up white as the color + // to use when drawing a rectangle under the image + rRenderContext.SetLineColor(COL_WHITE); + rRenderContext.SetFillColor(COL_WHITE); + + // Paint + Point aPntPos; + Size aPntSz(GetOutputSizePixel()); + Size aGrfSize; + if (m_bGraphic) + aGrfSize = ::GetGraphicSizeTwip(m_aGraphic, &rRenderContext); + //it should show the default bitmap also if no graphic can be found + if (!aGrfSize.Width() && !aGrfSize.Height()) + aGrfSize = rRenderContext.PixelToLogic(m_aBmp.GetSizePixel()); + + tools::Long nRelGrf = aGrfSize.Width() * 100 / aGrfSize.Height(); + tools::Long nRelWin = aPntSz.Width() * 100 / aPntSz.Height(); + if (nRelGrf < nRelWin) + { + const tools::Long nWidth = aPntSz.Width(); + // if we use a replacement preview, try to draw at original size + if (!m_bGraphic && (aGrfSize.Width() <= aPntSz.Width()) + && (aGrfSize.Height() <= aPntSz.Height())) + { + const tools::Long nHeight = aPntSz.Height(); + aPntSz.setWidth( aGrfSize.Width() ); + aPntSz.setHeight( aGrfSize.Height() ); + aPntPos.AdjustY((nHeight - aPntSz.Height()) / 2 ); + } + else + aPntSz.setWidth( aPntSz.Height() * nRelGrf /100 ); + + aPntPos.AdjustX(nWidth - aPntSz.Width() ) ; + } + + // #i119307# clear window background, the graphic might have transparency + rRenderContext.DrawRect(tools::Rectangle(aPntPos, aPntSz)); + + if (m_bHorz || m_bVert) + { + BitmapEx aTmpBmp(m_bGraphic ? m_aGraphic.GetBitmapEx() : m_aBmp); + BmpMirrorFlags nMirrorFlags(BmpMirrorFlags::NONE); + if (m_bHorz) + nMirrorFlags |= BmpMirrorFlags::Vertical; + if (m_bVert) + nMirrorFlags |= BmpMirrorFlags::Horizontal; + aTmpBmp.Mirror(nMirrorFlags); + rRenderContext.DrawBitmapEx(aPntPos, aPntSz, aTmpBmp); + } + else if (m_bGraphic) //draw unmirrored preview graphic + { + m_aGraphic.Draw(rRenderContext, aPntPos, aPntSz); + } + else //draw unmirrored stock sample image + { + rRenderContext.DrawBitmapEx(aPntPos, aPntSz, m_aBmp); + } +} + +BmpWindow::~BmpWindow() +{ +} + +void BmpWindow::SetGraphic(const Graphic& rGraphic) +{ + m_aGraphic = rGraphic; + Size aSize = m_aGraphic.GetPrefSize(); + m_bGraphic = aSize.Width() && aSize.Height(); + Invalidate(); +} + +void BmpWindow::SetBitmapEx(const BitmapEx& rBmp) +{ + m_aBmp = rBmp; + Invalidate(); +} + +// set URL and ImageMap at frames +SwFrameURLPage::SwFrameURLPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/frmurlpage.ui", "FrameURLPage", &rSet) + , m_xURLED(m_xBuilder->weld_entry("url")) + , m_xSearchPB(m_xBuilder->weld_button("search")) + , m_xNameED(m_xBuilder->weld_entry("name")) + , m_xFrameCB(m_xBuilder->weld_combo_box("frame")) + , m_xServerCB(m_xBuilder->weld_check_button("server")) + , m_xClientCB(m_xBuilder->weld_check_button("client")) +{ + m_xSearchPB->connect_clicked(LINK(this, SwFrameURLPage, InsertFileHdl)); +} + +SwFrameURLPage::~SwFrameURLPage() +{ +} + +void SwFrameURLPage::Reset( const SfxItemSet *rSet ) +{ + if ( SfxItemState::SET == rSet->GetItemState( SID_DOCFRAME )) + { + TargetList aList; + SfxFrame::GetDefaultTargetList(aList); + size_t nCount = aList.size(); + for (size_t i = 0; i < nCount; ++i) + { + m_xFrameCB->append_text(aList.at(i)); + } + } + + if ( const SwFormatURL* pFormatURL = rSet->GetItemIfSet( RES_URL ) ) + { + m_xURLED->set_text(INetURLObject::decode(pFormatURL->GetURL(), + INetURLObject::DecodeMechanism::Unambiguous)); + m_xNameED->set_text(pFormatURL->GetName()); + + m_xClientCB->set_sensitive(pFormatURL->GetMap() != nullptr); + m_xClientCB->set_active(pFormatURL->GetMap() != nullptr); + m_xServerCB->set_active(pFormatURL->IsServerMap()); + + m_xFrameCB->set_entry_text(pFormatURL->GetTargetFrameName()); + m_xFrameCB->save_value(); + } + else + m_xClientCB->set_sensitive(false); + + m_xServerCB->save_state(); + m_xClientCB->save_state(); +} + +bool SwFrameURLPage::FillItemSet(SfxItemSet *rSet) +{ + bool bModified = false; + const SwFormatURL* pOldURL = GetOldItem(*rSet, RES_URL); + std::unique_ptr<SwFormatURL> pFormatURL; + if(pOldURL) + pFormatURL.reset(pOldURL->Clone()); + else + pFormatURL.reset(new SwFormatURL()); + + { + const OUString sText = m_xURLED->get_text(); + + if( pFormatURL->GetURL() != sText || + pFormatURL->GetName() != m_xNameED->get_text() || + m_xServerCB->get_active() != pFormatURL->IsServerMap() ) + { + pFormatURL->SetURL(sText, m_xServerCB->get_active()); + pFormatURL->SetName(m_xNameED->get_text()); + bModified = true; + } + } + + if (!m_xClientCB->get_active() && pFormatURL->GetMap() != nullptr) + { + pFormatURL->SetMap(nullptr); + bModified = true; + } + + if(pFormatURL->GetTargetFrameName() != m_xFrameCB->get_active_text()) + { + pFormatURL->SetTargetFrameName(m_xFrameCB->get_active_text()); + bModified = true; + } + rSet->Put(std::move(pFormatURL)); + return bModified; +} + +std::unique_ptr<SfxTabPage> SwFrameURLPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwFrameURLPage>(pPage, pController, *rSet); +} + +IMPL_LINK_NOARG(SwFrameURLPage, InsertFileHdl, weld::Button&, void) +{ + FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + uno::Reference < ui::dialogs::XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); + + try + { + const OUString sTemp(m_xURLED->get_text()); + if(!sTemp.isEmpty()) + xFP->setDisplayDirectory(sTemp); + } + catch( const uno::Exception& ) {} + if( aDlgHelper.Execute() == ERRCODE_NONE ) + { + m_xURLED->set_text(xFP->getSelectedFiles().getConstArray()[0]); + } +} + +SwFrameAddPage::SwFrameAddPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/frmaddpage.ui", "FrameAddPage", &rSet) + , m_pWrtSh(nullptr) + , m_bHtmlMode(false) + , m_bFormat(false) + , m_bNew(false) + , m_xNameFrame(m_xBuilder->weld_widget("nameframe")) + , m_xNameFT(m_xBuilder->weld_label("name_label")) + , m_xNameED(m_xBuilder->weld_entry("name")) + , m_xAltNameFT(m_xBuilder->weld_label("altname_label")) + , m_xAltNameED(m_xBuilder->weld_entry("altname")) + , m_xDescriptionFT(m_xBuilder->weld_label("description_label")) + , m_xDescriptionED(m_xBuilder->weld_text_view("description")) + , m_xDecorativeCB(m_xBuilder->weld_check_button("decorative")) + , m_xSequenceFrame(m_xBuilder->weld_widget("frmSequence")) + , m_xPrevLB(m_xBuilder->weld_combo_box("prev")) + , m_xNextLB(m_xBuilder->weld_combo_box("next")) + , m_xProtectFrame(m_xBuilder->weld_widget("protect")) + , m_xProtectContentCB(m_xBuilder->weld_check_button("protectcontent")) + , m_xProtectFrameCB(m_xBuilder->weld_check_button("protectframe")) + , m_xProtectSizeCB(m_xBuilder->weld_check_button("protectsize")) + , m_xContentAlignFrame(m_xBuilder->weld_widget("contentalign")) + , m_xVertAlignLB(m_xBuilder->weld_combo_box("vertalign")) + , m_xPropertiesFrame(m_xBuilder->weld_widget("properties")) + , m_xEditInReadonlyCB(m_xBuilder->weld_check_button("editinreadonly")) + , m_xPrintFrameCB(m_xBuilder->weld_check_button("printframe")) + , m_xTextFlowFT(m_xBuilder->weld_label("textflow_label")) + , m_xTextFlowLB(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box("textflow"))) +{ + m_xTextFlowLB->append(SvxFrameDirection::Horizontal_LR_TB, SvxResId(RID_SVXSTR_FRAMEDIR_LTR)); + m_xTextFlowLB->append(SvxFrameDirection::Horizontal_RL_TB, SvxResId(RID_SVXSTR_FRAMEDIR_RTL)); + m_xTextFlowLB->append(SvxFrameDirection::Vertical_RL_TB, SvxResId(RID_SVXSTR_PAGEDIR_RTL_VERT)); + m_xTextFlowLB->append(SvxFrameDirection::Vertical_LR_TB, SvxResId(RID_SVXSTR_PAGEDIR_LTR_VERT)); + m_xTextFlowLB->append(SvxFrameDirection::Vertical_LR_BT, SvxResId(RID_SVXSTR_PAGEDIR_LTR_BTT_VERT)); + m_xTextFlowLB->append(SvxFrameDirection::Environment, SvxResId(RID_SVXSTR_FRAMEDIR_SUPER)); + m_xDescriptionED->set_size_request(-1, m_xDescriptionED->get_preferred_size().Height()); + + m_xDecorativeCB->connect_toggled(LINK(this, SwFrameAddPage, DecorativeHdl)); +} + +SwFrameAddPage::~SwFrameAddPage() +{ + m_xTextFlowLB.reset(); +} + +std::unique_ptr<SfxTabPage> SwFrameAddPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwFrameAddPage>(pPage, pController, *rSet); +} + +void SwFrameAddPage::Reset(const SfxItemSet *rSet ) +{ + sal_uInt16 nHtmlMode = ::GetHtmlMode(static_cast<const SwDocShell*>(SfxObjectShell::Current())); + m_bHtmlMode = (nHtmlMode & HTMLMODE_ON) != 0; + if (m_bHtmlMode) + { + m_xProtectFrame->hide(); + m_xEditInReadonlyCB->hide(); + m_xPrintFrameCB->hide(); + } + if (m_sDlgType == "PictureDialog" || m_sDlgType == "ObjectDialog") + { + m_xSequenceFrame->hide(); + m_xEditInReadonlyCB->hide(); + if (m_bHtmlMode) + { + m_xPropertiesFrame->hide(); + } + m_xContentAlignFrame->hide(); + } + + if(const SfxStringItem* pNameItem = rSet->GetItemIfSet(FN_SET_FRM_ALT_NAME, false)) + { + m_xAltNameED->set_text(pNameItem->GetValue()); + m_xAltNameED->save_value(); + } + + if(const SfxStringItem* pDescriptionItem = rSet->GetItemIfSet(FN_UNO_DESCRIPTION, false)) + { + m_xDescriptionED->set_text(pDescriptionItem->GetValue()); + m_xDescriptionED->save_value(); + } + + if(!m_bFormat) + { + // insert graphic - properties + // bNew is not set, so recognise by selection + OUString aTmpName1; + if(const SfxStringItem* pNameItem = rSet->GetItemIfSet(FN_SET_FRM_NAME, false)) + { + aTmpName1 = pNameItem->GetValue(); + } + + OSL_ENSURE(m_pWrtSh, "no Shell?"); + if( m_bNew || aTmpName1.isEmpty() ) + { + if (m_sDlgType == "PictureDialog") + aTmpName1 = m_pWrtSh->GetUniqueGrfName(); + else if (m_sDlgType == "ObjectDialog") + aTmpName1 = m_pWrtSh->GetUniqueOLEName(); + else + aTmpName1 = m_pWrtSh->GetUniqueFrameName(); + + m_pWrtSh->SetFlyName(aTmpName1); + } + + m_xNameED->set_text( aTmpName1 ); + m_xNameED->save_value(); + } + else + { + m_xNameED->set_sensitive( false ); + m_xAltNameED->set_sensitive(false); + m_xNameFT->set_sensitive( false ); + m_xAltNameFT->set_sensitive(false); + } + if (m_sDlgType == "FrameDialog" && m_xAltNameFT->get_visible()) + { + m_xAltNameFT->hide(); + m_xAltNameED->hide(); + } + else + { + m_xNameED->connect_changed(LINK(this, SwFrameAddPage, EditModifyHdl)); + } + + if (!m_bNew) + { + SwFrameFormat* pFormat = m_pWrtSh->GetFlyFrameFormat(); + + if (pFormat) + { + const SwFormatChain &rChain = pFormat->GetChain(); + const SwFlyFrameFormat* pFlyFormat; + OUString sNextChain, sPrevChain; + pFlyFormat = rChain.GetPrev(); + if (pFlyFormat != nullptr) + { + sPrevChain = pFlyFormat->GetName(); + } + + pFlyFormat = rChain.GetNext(); + if (pFlyFormat != nullptr) + { + sNextChain = pFlyFormat->GetName(); + } + //determine chainable frames + std::vector< OUString > aPrevPageFrames; + std::vector< OUString > aThisPageFrames; + std::vector< OUString > aNextPageFrames; + std::vector< OUString > aRemainFrames; + m_pWrtSh->GetConnectableFrameFormats(*pFormat, sNextChain, false, + aPrevPageFrames, aThisPageFrames, aNextPageFrames, aRemainFrames ); + for (sal_Int32 nEntry = m_xPrevLB->get_count(); nEntry > 1; nEntry--) + m_xPrevLB->remove(nEntry - 1); + lcl_InsertVectors(*m_xPrevLB, aPrevPageFrames, aThisPageFrames, aNextPageFrames, aRemainFrames); + if(!sPrevChain.isEmpty()) + { + if (m_xPrevLB->find_text(sPrevChain) == -1) + m_xPrevLB->insert_text(1, sPrevChain); + m_xPrevLB->set_active_text(sPrevChain); + } + else + m_xPrevLB->set_active(0); + aPrevPageFrames.clear(); + aNextPageFrames.clear(); + aThisPageFrames.clear(); + aRemainFrames.clear(); + + m_pWrtSh->GetConnectableFrameFormats(*pFormat, sPrevChain, true, + aPrevPageFrames, aThisPageFrames, aNextPageFrames, aRemainFrames ); + for (sal_Int32 nEntry = m_xNextLB->get_count(); nEntry > 1; nEntry--) + m_xNextLB->remove(nEntry - 1); + lcl_InsertVectors(*m_xNextLB, aPrevPageFrames, aThisPageFrames, aNextPageFrames, aRemainFrames); + if(!sNextChain.isEmpty()) + { + if (m_xNextLB->find_text(sNextChain) == -1) + m_xNextLB->insert_text(1, sNextChain); + m_xNextLB->set_active_text(sNextChain); + } + else + m_xNextLB->set_active(0); + Link<weld::ComboBox&,void> aLink(LINK(this, SwFrameAddPage, ChainModifyHdl)); + m_xPrevLB->connect_changed(aLink); + m_xNextLB->connect_changed(aLink); + } + } + // Pos Protected + const SvxProtectItem& rProt = rSet->Get(RES_PROTECT); + m_xProtectFrameCB->set_active(rProt.IsPosProtected()); + m_xProtectContentCB->set_active(rProt.IsContentProtected()); + m_xProtectSizeCB->set_active(rProt.IsSizeProtected()); + + const SwFormatEditInReadonly& rEdit = rSet->Get(RES_EDIT_IN_READONLY); + m_xEditInReadonlyCB->set_active(rEdit.GetValue()); + m_xEditInReadonlyCB->save_state(); + + // print + const SvxPrintItem& rPrt = rSet->Get(RES_PRINT); + m_xPrintFrameCB->set_active(rPrt.GetValue()); + m_xPrintFrameCB->save_state(); + + SfxBoolItem const& rDecorative = rSet->Get(RES_DECORATIVE); + m_xDecorativeCB->set_active(rDecorative.GetValue()); + m_xDecorativeCB->save_state(); + + // textflow + if( (!m_bHtmlMode || (0 != (nHtmlMode&HTMLMODE_SOME_STYLES))) + && m_sDlgType != "PictureDialog" && m_sDlgType != "ObjectDialog" + && SfxItemState::UNKNOWN != rSet->GetItemState( RES_FRAMEDIR ) ) + { + m_xTextFlowFT->show(); + m_xTextFlowLB->show(); + + //vertical text flow is not possible in HTML + if(m_bHtmlMode) + { + m_xTextFlowLB->remove_id(SvxFrameDirection::Vertical_RL_TB); + } + SvxFrameDirection nVal = rSet->Get(RES_FRAMEDIR).GetValue(); + m_xTextFlowLB->set_active_id(nVal); + m_xTextFlowLB->save_value(); + } + else + { + m_xTextFlowFT->hide(); + m_xTextFlowLB->hide(); + } + + // Content alignment + if ( rSet->GetItemState(RES_TEXT_VERT_ADJUST) > SfxItemState::DEFAULT ) + { + SdrTextVertAdjust nAdjust = rSet->Get(RES_TEXT_VERT_ADJUST).GetValue(); + sal_Int32 nPos = 0; + switch(nAdjust) + { + case SDRTEXTVERTADJUST_TOP: nPos = 0; break; + case SDRTEXTVERTADJUST_CENTER: + case SDRTEXTVERTADJUST_BLOCK: nPos = 1; break; + case SDRTEXTVERTADJUST_BOTTOM: nPos = 2; break; + } + m_xVertAlignLB->set_active(nPos); + } + m_xVertAlignLB->save_value(); + + DecorativeHdl(*m_xDecorativeCB); +} + +bool SwFrameAddPage::FillItemSet(SfxItemSet *rSet) +{ + bool bRet = false; + if (m_xNameED->get_value_changed_from_saved()) + bRet |= nullptr != rSet->Put(SfxStringItem(FN_SET_FRM_NAME, m_xNameED->get_text())); + if (m_xAltNameED->get_value_changed_from_saved()) + bRet |= nullptr != rSet->Put(SfxStringItem(FN_SET_FRM_ALT_NAME, m_xAltNameED->get_text())); + if (m_xDescriptionED->get_value_changed_from_saved()) + bRet |= nullptr != rSet->Put(SfxStringItem(FN_UNO_DESCRIPTION, m_xDescriptionED->get_text())); + + const SfxPoolItem* pOldItem; + SvxProtectItem aProt ( GetItemSet().Get(RES_PROTECT) ); + aProt.SetContentProtect( m_xProtectContentCB->get_active() ); + aProt.SetSizeProtect ( m_xProtectSizeCB->get_active() ); + aProt.SetPosProtect ( m_xProtectFrameCB->get_active() ); + if ( nullptr == (pOldItem = GetOldItem(*rSet, FN_SET_PROTECT)) || + aProt != *pOldItem ) + bRet |= nullptr != rSet->Put( aProt); + + if ( m_xEditInReadonlyCB->get_state_changed_from_saved() ) + bRet |= nullptr != rSet->Put( SwFormatEditInReadonly( RES_EDIT_IN_READONLY, m_xEditInReadonlyCB->get_active())); + + if ( m_xPrintFrameCB->get_state_changed_from_saved() ) + bRet |= nullptr != rSet->Put( SvxPrintItem( RES_PRINT, m_xPrintFrameCB->get_active())); + + if (m_xDecorativeCB->get_state_changed_from_saved()) + { + bRet |= nullptr != rSet->Put(SfxBoolItem(RES_DECORATIVE, m_xDecorativeCB->get_active())); + } + + // textflow + if (m_xTextFlowLB->get_visible() && m_xTextFlowLB->get_value_changed_from_saved()) + { + SvxFrameDirection eDirection = m_xTextFlowLB->get_active_id(); + bRet |= nullptr != rSet->Put( SvxFrameDirectionItem(eDirection, RES_FRAMEDIR )); + } + if(m_pWrtSh) + { + const SwFrameFormat* pFormat = m_pWrtSh->GetFlyFrameFormat(); + if (pFormat) + { + OUString sCurrentPrevChain, sCurrentNextChain; + if (m_xPrevLB->get_active()) + sCurrentPrevChain = m_xPrevLB->get_active_text(); + if (m_xNextLB->get_active()) + sCurrentNextChain = m_xNextLB->get_active_text(); + const SwFormatChain &rChain = pFormat->GetChain(); + const SwFlyFrameFormat* pFlyFormat; + OUString sNextChain, sPrevChain; + pFlyFormat = rChain.GetPrev(); + if (pFlyFormat != nullptr) + sPrevChain = pFlyFormat->GetName(); + + pFlyFormat = rChain.GetNext(); + if (pFlyFormat != nullptr) + sNextChain = pFlyFormat->GetName(); + if(sPrevChain != sCurrentPrevChain) + bRet |= nullptr != rSet->Put(SfxStringItem(FN_PARAM_CHAIN_PREVIOUS, sCurrentPrevChain)); + if(sNextChain != sCurrentNextChain) + bRet |= nullptr != rSet->Put(SfxStringItem(FN_PARAM_CHAIN_NEXT, sCurrentNextChain)); + } + } + + if (m_xVertAlignLB->get_value_changed_from_saved()) + { + SdrTextVertAdjust nAdjust; + switch (m_xVertAlignLB->get_active()) + { + default: + case 0 : nAdjust = SDRTEXTVERTADJUST_TOP; break; + case 1 : nAdjust = SDRTEXTVERTADJUST_CENTER; break; + case 2 : nAdjust = SDRTEXTVERTADJUST_BOTTOM; break; + } + bRet |= nullptr != rSet->Put(SdrTextVertAdjustItem(nAdjust, RES_TEXT_VERT_ADJUST)); + } + + return bRet; +} + +IMPL_LINK_NOARG(SwFrameAddPage, EditModifyHdl, weld::Entry&, void) +{ + bool bEnable = !m_xNameED->get_text().isEmpty(); + m_xAltNameED->set_sensitive(bEnable); + m_xAltNameFT->set_sensitive(bEnable); +} + +IMPL_LINK_NOARG(SwFrameAddPage, DecorativeHdl, weld::Toggleable&, void) +{ + bool const bEnable(!m_xDecorativeCB->get_active()); + m_xAltNameED->set_sensitive(bEnable); + m_xAltNameFT->set_sensitive(bEnable); + m_xDescriptionED->set_sensitive(bEnable); + m_xDescriptionFT->set_sensitive(bEnable); +} + +void SwFrameAddPage::SetFormatUsed(bool bFormatUsed) +{ + m_bFormat = bFormatUsed; + if (m_bFormat) + { + m_xNameFrame->hide(); + } +} + +IMPL_LINK(SwFrameAddPage, ChainModifyHdl, weld::ComboBox&, rBox, void) +{ + OUString sCurrentPrevChain, sCurrentNextChain; + if (m_xPrevLB->get_active()) + sCurrentPrevChain = m_xPrevLB->get_active_text(); + if (m_xNextLB->get_active()) + sCurrentNextChain = m_xNextLB->get_active_text(); + SwFrameFormat* pFormat = m_pWrtSh->GetFlyFrameFormat(); + if (!pFormat) + return; + + bool bNextBox = m_xNextLB.get() == &rBox; + weld::ComboBox& rChangeLB = bNextBox ? *m_xPrevLB : *m_xNextLB; + for (sal_Int32 nEntry = rChangeLB.get_count(); nEntry > 1; nEntry--) + rChangeLB.remove(nEntry - 1); + //determine chainable frames + std::vector< OUString > aPrevPageFrames; + std::vector< OUString > aThisPageFrames; + std::vector< OUString > aNextPageFrames; + std::vector< OUString > aRemainFrames; + m_pWrtSh->GetConnectableFrameFormats(*pFormat, bNextBox ? sCurrentNextChain : sCurrentPrevChain, !bNextBox, + aPrevPageFrames, aThisPageFrames, aNextPageFrames, aRemainFrames ); + lcl_InsertVectors(rChangeLB, + aPrevPageFrames, aThisPageFrames, aNextPageFrames, aRemainFrames); + const OUString sToSelect = bNextBox ? sCurrentPrevChain : sCurrentNextChain; + if (rChangeLB.find_text(sToSelect) != -1) + rChangeLB.set_active_text(sToSelect); + else + rChangeLB.set_active(0); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/frmdlg/pattern.cxx b/sw/source/ui/frmdlg/pattern.cxx new file mode 100644 index 0000000000..097ed18230 --- /dev/null +++ b/sw/source/ui/frmdlg/pattern.cxx @@ -0,0 +1,42 @@ +/* -*- 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/sfxdlg.hxx> +#include <svx/dialogs.hrc> +#include <swtypes.hxx> +#include <pattern.hxx> +#include <strings.hrc> + +SwBackgroundDlg::SwBackgroundDlg(weld::Window* pParent, const SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet) + +{ + m_xDialog->set_title(SwResId(STR_FRMUI_PATTERN)); + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BKG); + if (fnCreatePage) + { + std::unique_ptr<SfxTabPage> xRet = (*fnCreatePage)(get_content_area(), this, &rSet); + xRet->PageCreated(rSet); + xRet->ActivatePage(rSet); + SetTabPage(std::move(xRet)); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/frmdlg/uiborder.cxx b/sw/source/ui/frmdlg/uiborder.cxx new file mode 100644 index 0000000000..73c55b0e3c --- /dev/null +++ b/sw/source/ui/frmdlg/uiborder.cxx @@ -0,0 +1,54 @@ +/* -*- 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/dialogs.hrc> +#include <svl/itemset.hxx> +#include <svx/flagsdef.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/tabdlg.hxx> +#include <svl/intitem.hxx> + +#include <swtypes.hxx> +#include <uiborder.hxx> +#include <strings.hrc> + +SwBorderDlg::SwBorderDlg(weld::Window* pParent, const SfxItemSet& rSet, SwBorderModes nType) + : SfxSingleTabDialogController(pParent, &rSet) +{ + m_xDialog->set_title(SwResId(STR_FRMUI_BORDER)); + + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc(RID_SVXPAGE_BORDER); + + if (fnCreatePage) + { + std::unique_ptr<SfxTabPage> xNewPage = (*fnCreatePage)(get_content_area(), this, &rSet); + SfxAllItemSet aSet(*(rSet.GetPool())); + aSet.Put(SfxUInt16Item(SID_SWMODE_TYPE, static_cast<sal_uInt16>(nType))); + if (SwBorderModes::TABLE == nType) + aSet.Put(SfxUInt32Item(SID_FLAG_TYPE, SVX_HIDESHADOWCTL)); + xNewPage->PageCreated(aSet); + SetTabPage(std::move(xNewPage)); + } +} + +SwBorderDlg::~SwBorderDlg() {} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/frmdlg/wrap.cxx b/sw/source/ui/frmdlg/wrap.cxx new file mode 100644 index 0000000000..684fe38b22 --- /dev/null +++ b/sw/source/ui/frmdlg/wrap.cxx @@ -0,0 +1,631 @@ +/* -*- 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 <hintids.hxx> +#include <vcl/graph.hxx> + +#include <sfx2/htmlmode.hxx> +#include <sfx2/objsh.hxx> +#include <svl/intitem.hxx> +#include <editeng/opaqitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lrspitem.hxx> +#include <fmtfollowtextflow.hxx> +#include <svtools/unitconv.hxx> +#include <svx/swframevalidation.hxx> + +#include <cmdid.h> +#include <docsh.hxx> +#include <uitool.hxx> +#include <wrtsh.hxx> +#include <swmodule.hxx> +#include <viewopt.hxx> +#include <fmtsrnd.hxx> +#include <frmmgr.hxx> +#include <wrap.hxx> +#include <bitmaps.hlst> +#include <fmtwrapinfluenceonobjpos.hxx> + +using namespace ::com::sun::star; + +const WhichRangesContainer SwWrapTabPage::s_aWrapPageRg(svl::Items< + RES_LR_SPACE, RES_UL_SPACE, + RES_PRINT, RES_PRINT, + RES_PROTECT, RES_SURROUND +>); + +SwWrapDlg::SwWrapDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtShell, bool bDrawMode) + : SfxSingleTabDialogController(pParent, &rSet, "modules/swriter/ui/wrapdialog.ui", "WrapDialog") +{ + // create TabPage + auto xNewPage = SwWrapTabPage::Create(get_content_area(), this, &rSet); + SwWrapTabPage* pWrapPage = static_cast<SwWrapTabPage*>(xNewPage.get()); + pWrapPage->SetFormatUsed(false, bDrawMode); + pWrapPage->SetShell(pWrtShell); + SetTabPage(std::move(xNewPage)); +} + +SwWrapTabPage::SwWrapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/wrappage.ui", "WrapPage", &rSet) + , m_nAnchorId(RndStdIds::FLY_AT_PARA) + , m_nHtmlMode(0) + , m_pWrtSh(nullptr) + , m_bFormat(false) + , m_bNew(true) + , m_bHtmlMode(false) + , m_bDrawMode(false) + , m_bContourImage(false) + , m_xNoWrapImg(m_xBuilder->weld_image("noneimg")) + , m_xNoWrapRB(m_xBuilder->weld_radio_button("none")) + , m_xWrapLeftImg(m_xBuilder->weld_image("beforeimg")) + , m_xWrapLeftRB(m_xBuilder->weld_radio_button("before")) + , m_xWrapRightImg(m_xBuilder->weld_image("afterimg")) + , m_xWrapRightRB(m_xBuilder->weld_radio_button("after")) + , m_xWrapParallelImg(m_xBuilder->weld_image("parallelimg")) + , m_xWrapParallelRB(m_xBuilder->weld_radio_button("parallel")) + , m_xWrapThroughImg(m_xBuilder->weld_image("throughimg")) + , m_xWrapThroughRB(m_xBuilder->weld_radio_button("through")) + , m_xIdealWrapImg(m_xBuilder->weld_image("optimalimg")) + , m_xIdealWrapRB(m_xBuilder->weld_radio_button("optimal")) + , m_xLeftMarginED(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM)) + , m_xRightMarginED(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM)) + , m_xTopMarginED(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM)) + , m_xBottomMarginED(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM)) + , m_xWrapAnchorOnlyCB(m_xBuilder->weld_check_button("anchoronly")) + , m_xWrapTransparentCB(m_xBuilder->weld_check_button("transparent")) + , m_xWrapOutlineCB(m_xBuilder->weld_check_button("outline")) + , m_xWrapOutsideCB(m_xBuilder->weld_check_button("outside")) + , m_xAllowOverlapCB(m_xBuilder->weld_check_button("allowoverlap")) +{ + SetExchangeSupport(); + + Link<weld::MetricSpinButton&,void> aLk = LINK(this, SwWrapTabPage, RangeModifyHdl); + m_xLeftMarginED->connect_value_changed(aLk); + m_xRightMarginED->connect_value_changed(aLk); + m_xTopMarginED->connect_value_changed(aLk); + m_xBottomMarginED->connect_value_changed(aLk); + + Link<weld::Toggleable&,void> aLk2 = LINK(this, SwWrapTabPage, WrapTypeHdl); + m_xNoWrapRB->connect_toggled(aLk2); + m_xWrapLeftRB->connect_toggled(aLk2); + m_xWrapRightRB->connect_toggled(aLk2); + m_xWrapParallelRB->connect_toggled(aLk2); + m_xWrapThroughRB->connect_toggled(aLk2); + m_xIdealWrapRB->connect_toggled(aLk2); + SetImages(); + m_xWrapOutlineCB->connect_toggled(LINK(this, SwWrapTabPage, ContourHdl)); +} + +SwWrapTabPage::~SwWrapTabPage() +{ +} + +std::unique_ptr<SfxTabPage> SwWrapTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwWrapTabPage>(pPage, pController, *rSet); +} + +void SwWrapTabPage::Reset(const SfxItemSet *rSet) +{ + // contour for Draw, Graphic and OLE (Insert/Graphic/Properties still missing!) + if( m_bDrawMode ) + { + m_xWrapOutlineCB->show(); + m_xWrapOutsideCB->show(); + + m_xWrapTransparentCB->set_active( 0 == rSet->Get(FN_DRAW_WRAP_DLG).GetValue() ); + m_xWrapTransparentCB->save_state(); + } + else + { + bool bShowCB = m_bFormat; + if( !m_bFormat ) + { + SelectionType nSelType = m_pWrtSh->GetSelectionType(); + if( ( nSelType & SelectionType::Graphic ) || + ( nSelType & SelectionType::Ole && GraphicType::NONE != + m_pWrtSh->GetIMapGraphic().GetType() )) + bShowCB = true; + } + if( bShowCB ) + { + m_xWrapOutlineCB->show(); + m_xWrapOutsideCB->show(); + } + } + + m_nHtmlMode = ::GetHtmlMode(static_cast<const SwDocShell*>(SfxObjectShell::Current())); + m_bHtmlMode = (m_nHtmlMode & HTMLMODE_ON) != 0; + + FieldUnit aMetric = ::GetDfltMetric(m_bHtmlMode); + SetFieldUnit(*m_xLeftMarginED, aMetric); + SetFieldUnit(*m_xRightMarginED, aMetric); + SetFieldUnit(*m_xTopMarginED, aMetric); + SetFieldUnit(*m_xBottomMarginED, aMetric); + + const SwFormatSurround& rSurround = rSet->Get(RES_SURROUND); + + css::text::WrapTextMode nSur = rSurround.GetSurround(); + const SwFormatAnchor &rAnch = rSet->Get(RES_ANCHOR); + m_nAnchorId = rAnch.GetAnchorId(); + + if (((m_nAnchorId == RndStdIds::FLY_AT_PARA) || (m_nAnchorId == RndStdIds::FLY_AT_CHAR)) + && (nSur != css::text::WrapTextMode_NONE)) + { + m_xWrapAnchorOnlyCB->set_active(rSurround.IsAnchorOnly()); + } + else + { + m_xWrapAnchorOnlyCB->set_sensitive(false); + } + + const bool bContour = rSurround.IsContour(); + m_xWrapOutlineCB->set_active(bContour); + m_xWrapOutsideCB->set_active(rSurround.IsOutside()); + m_xWrapThroughRB->set_sensitive(!m_xWrapOutlineCB->get_active()); + m_bContourImage = !bContour; + + weld::RadioButton* pBtn = nullptr; + + switch (nSur) + { + case css::text::WrapTextMode_NONE: + { + pBtn = m_xNoWrapRB.get(); + break; + } + + case css::text::WrapTextMode_THROUGH: + { + // transparent ? + pBtn = m_xWrapThroughRB.get(); + + if (!m_bDrawMode) + { + const SvxOpaqueItem& rOpaque = rSet->Get(RES_OPAQUE); + m_xWrapTransparentCB->set_active(!rOpaque.GetValue()); + } + break; + } + + case css::text::WrapTextMode_PARALLEL: + { + pBtn = m_xWrapParallelRB.get(); + break; + } + + case css::text::WrapTextMode_DYNAMIC: + { + pBtn = m_xIdealWrapRB.get(); + break; + } + + default: + { + if (nSur == css::text::WrapTextMode_LEFT) + pBtn = m_xWrapLeftRB.get(); + else if (nSur == css::text::WrapTextMode_RIGHT) + pBtn = m_xWrapRightRB.get(); + } + } + if (pBtn) + { + pBtn->set_active(true); + WrapTypeHdl(*pBtn); + // For character objects that currently are in passage, the default + // "contour on" is prepared here, in case we switch to any other + // passage later. + if (m_bDrawMode && !m_xWrapOutlineCB->get_sensitive()) + m_xWrapOutlineCB->set_active(true); + } + m_xWrapTransparentCB->set_sensitive(pBtn == m_xWrapThroughRB.get() && !m_bHtmlMode); + + const SvxULSpaceItem& rUL = rSet->Get(RES_UL_SPACE); + const SvxLRSpaceItem& rLR = rSet->Get(RES_LR_SPACE); + + // gap to text + m_xLeftMarginED->set_value(m_xLeftMarginED->normalize(rLR.GetLeft()), FieldUnit::TWIP); + m_xRightMarginED->set_value(m_xRightMarginED->normalize(rLR.GetRight()), FieldUnit::TWIP); + m_xTopMarginED->set_value(m_xTopMarginED->normalize(rUL.GetUpper()), FieldUnit::TWIP); + m_xBottomMarginED->set_value(m_xBottomMarginED->normalize(rUL.GetLower()), FieldUnit::TWIP); + + m_xLeftMarginED->save_value(); + m_xRightMarginED->save_value(); + m_xTopMarginED->save_value(); + m_xBottomMarginED->save_value(); + + ContourHdl(*m_xWrapOutlineCB); + + const SwFormatWrapInfluenceOnObjPos& rInfluence = rSet->Get(RES_WRAP_INFLUENCE_ON_OBJPOS); + m_xAllowOverlapCB->set_active(rInfluence.GetAllowOverlap()); + + ActivatePage( *rSet ); +} + +// stuff attributes into the set when OK +bool SwWrapTabPage::FillItemSet(SfxItemSet *rSet) +{ + bool bModified = false; + const SfxPoolItem* pOldItem; + const SwFormatSurround& rOldSur = GetItemSet().Get(RES_SURROUND); + SwFormatSurround aSur( rOldSur ); + + std::shared_ptr<SvxOpaqueItem> aOp(std::make_shared<SvxOpaqueItem>(RES_OPAQUE)); + + if (!m_bDrawMode) + { + aOp.reset(GetItemSet().Get(RES_OPAQUE).Clone()); + aOp->SetValue(true); + } + + if (m_xNoWrapRB->get_active()) + aSur.SetSurround(css::text::WrapTextMode_NONE); + else if (m_xWrapLeftRB->get_active()) + aSur.SetSurround(css::text::WrapTextMode_LEFT); + else if (m_xWrapRightRB->get_active()) + aSur.SetSurround(css::text::WrapTextMode_RIGHT); + else if (m_xWrapParallelRB->get_active()) + aSur.SetSurround(css::text::WrapTextMode_PARALLEL); + else if (m_xWrapThroughRB->get_active()) + { + aSur.SetSurround(css::text::WrapTextMode_THROUGH); + if (m_xWrapTransparentCB->get_active() && !m_bDrawMode) + aOp->SetValue(false); + } + else if (m_xIdealWrapRB->get_active()) + aSur.SetSurround(css::text::WrapTextMode_DYNAMIC); + + aSur.SetAnchorOnly( m_xWrapAnchorOnlyCB->get_active() ); + bool bContour = m_xWrapOutlineCB->get_active() && m_xWrapOutlineCB->get_sensitive(); + aSur.SetContour( bContour ); + + if ( bContour ) + aSur.SetOutside(m_xWrapOutsideCB->get_active()); + + if(nullptr == (pOldItem = GetOldItem( *rSet, RES_SURROUND )) || + aSur != *pOldItem ) + { + rSet->Put(aSur); + bModified = true; + } + + if (!m_bDrawMode) + { + if(nullptr == (pOldItem = GetOldItem( *rSet, FN_OPAQUE )) || + *aOp != *pOldItem ) + { + rSet->Put(*aOp); + bModified = true; + } + } + + bool bTopMod = m_xTopMarginED->get_value_changed_from_saved(); + bool bBottomMod = m_xBottomMarginED->get_value_changed_from_saved(); + + SvxULSpaceItem aUL( RES_UL_SPACE ); + aUL.SetUpper(o3tl::narrowing<sal_uInt16>(m_xTopMarginED->denormalize(m_xTopMarginED->get_value(FieldUnit::TWIP)))); + aUL.SetLower(o3tl::narrowing<sal_uInt16>(m_xBottomMarginED->denormalize(m_xBottomMarginED->get_value(FieldUnit::TWIP)))); + + if ( bTopMod || bBottomMod ) + { + if(nullptr == (pOldItem = GetOldItem(*rSet, RES_UL_SPACE)) || + aUL != *pOldItem ) + { + rSet->Put( aUL ); + bModified = true; + } + } + + bool bLeftMod = m_xLeftMarginED->get_value_changed_from_saved(); + bool bRightMod = m_xRightMarginED->get_value_changed_from_saved(); + + SvxLRSpaceItem aLR( RES_LR_SPACE ); + aLR.SetLeft(o3tl::narrowing<sal_uInt16>(m_xLeftMarginED->denormalize(m_xLeftMarginED->get_value(FieldUnit::TWIP)))); + aLR.SetRight(o3tl::narrowing<sal_uInt16>(m_xRightMarginED->denormalize(m_xRightMarginED->get_value(FieldUnit::TWIP)))); + + if ( bLeftMod || bRightMod ) + { + if( nullptr == (pOldItem = GetOldItem(*rSet, RES_LR_SPACE)) || + aLR != *pOldItem ) + { + rSet->Put(aLR); + bModified = true; + } + } + + if ( m_bDrawMode ) + { + bool bChecked = m_xWrapTransparentCB->get_active() && m_xWrapTransparentCB->get_sensitive(); + if ((m_xWrapTransparentCB->get_saved_state() == TRISTATE_TRUE) != bChecked) + bModified |= nullptr != rSet->Put(SfxInt16Item(FN_DRAW_WRAP_DLG, bChecked ? 0 : 1)); + } + + const SwFormatWrapInfluenceOnObjPos& rOldInfluence + = GetItemSet().Get(RES_WRAP_INFLUENCE_ON_OBJPOS); + SwFormatWrapInfluenceOnObjPos aInfluence(rOldInfluence); + aInfluence.SetAllowOverlap(m_xAllowOverlapCB->get_active()); + + pOldItem = GetOldItem(*rSet, RES_WRAP_INFLUENCE_ON_OBJPOS); + if (!pOldItem || aInfluence != *pOldItem) + { + rSet->Put(aInfluence); + bModified = true; + } + + return bModified; +} + +// example update +void SwWrapTabPage::ActivatePage(const SfxItemSet& rSet) +{ + // anchor + const SwFormatAnchor &rAnch = rSet.Get(RES_ANCHOR); + m_nAnchorId = rAnch.GetAnchorId(); + bool bEnable = (m_nAnchorId != RndStdIds::FLY_AS_CHAR); + + SwWrtShell* pSh = m_bFormat ? ::GetActiveWrtShell() : m_pWrtSh; + if (pSh && !m_bDrawMode) + { + SwFlyFrameAttrMgr aMgr( m_bNew, pSh, GetItemSet() ); + SvxSwFrameValidation aVal; + + // size + const SwFormatFrameSize& rFrameSize = rSet.Get(RES_FRM_SIZE); + Size aSize = rFrameSize.GetSize(); + + // position + const SwFormatHoriOrient& rHori = rSet.Get(RES_HORI_ORIENT); + const SwFormatVertOrient& rVert = rSet.Get(RES_VERT_ORIENT); + + aVal.nAnchorType = m_nAnchorId; + aVal.bAutoHeight = rFrameSize.GetHeightSizeType() == SwFrameSize::Minimum; + aVal.bMirror = rHori.IsPosToggle(); + // #i18732# + aVal.bFollowTextFlow = rSet.Get(RES_FOLLOW_TEXT_FLOW).GetValue(); + + aVal.nHoriOrient = static_cast<short>(rHori.GetHoriOrient()); + aVal.nVertOrient = static_cast<short>(rVert.GetVertOrient()); + + aVal.nHPos = rHori.GetPos(); + aVal.nHRelOrient = rHori.GetRelationOrient(); + aVal.nVPos = rVert.GetPos(); + aVal.nVRelOrient = rVert.GetRelationOrient(); + + if (rFrameSize.GetWidthPercent() && rFrameSize.GetWidthPercent() != SwFormatFrameSize::SYNCED) + aSize.setWidth( aSize.Width() * rFrameSize.GetWidthPercent() / 100 ); + + if (rFrameSize.GetHeightPercent() && rFrameSize.GetHeightPercent() != SwFormatFrameSize::SYNCED) + aSize.setHeight( aSize.Height() * rFrameSize.GetHeightPercent() / 100 ); + + aVal.nWidth = aSize.Width(); + aVal.nHeight = aSize.Height(); + + aMgr.ValidateMetrics(aVal, nullptr); + + SwTwips nLeft; + SwTwips nRight; + SwTwips nTop; + SwTwips nBottom; + + nLeft = aVal.nHPos - aVal.nMinHPos; + nRight = aVal.nMaxWidth - aVal.nWidth; + nTop = aVal.nVPos - aVal.nMinVPos; + nBottom = aVal.nMaxHeight - aVal.nHeight; + + { + if (aVal.nAnchorType == RndStdIds::FLY_AS_CHAR) + { + nLeft = nRight; + + if (aVal.nVPos < 0) + { + if (aVal.nVPos <= aVal.nMaxHeight) + nTop = aVal.nMaxVPos - aVal.nHeight; + else + nTop = 0; // no passage + } + else + nTop = aVal.nMaxVPos - aVal.nHeight - aVal.nVPos; + } + else + { + nLeft += nRight; + nTop += nBottom; + } + + nBottom = nTop; + nRight = nLeft; + } + + m_xLeftMarginED->set_max(m_xLeftMarginED->normalize(nLeft), FieldUnit::TWIP); + m_xRightMarginED->set_max(m_xRightMarginED->normalize(nRight), FieldUnit::TWIP); + + m_xTopMarginED->set_max(m_xTopMarginED->normalize(nTop), FieldUnit::TWIP); + m_xBottomMarginED->set_max(m_xBottomMarginED->normalize(nBottom), FieldUnit::TWIP); + + RangeModifyHdl(*m_xLeftMarginED); + RangeModifyHdl(*m_xTopMarginED); + } + + const SwFormatSurround& rSurround = rSet.Get(RES_SURROUND); + css::text::WrapTextMode nSur = rSurround.GetSurround(); + + m_xWrapTransparentCB->set_sensitive(bEnable && !m_bHtmlMode && nSur == css::text::WrapTextMode_THROUGH); + if(m_bHtmlMode) + { + const SwFormatHoriOrient& rHori = rSet.Get(RES_HORI_ORIENT); + sal_Int16 eHOrient = rHori.GetHoriOrient(); + sal_Int16 eHRelOrient = rHori.GetRelationOrient(); + m_xWrapOutlineCB->hide(); + const bool bAllHtmlModes = + ((m_nAnchorId == RndStdIds::FLY_AT_PARA) || (m_nAnchorId == RndStdIds::FLY_AT_CHAR)) && + (eHOrient == text::HoriOrientation::RIGHT || eHOrient == text::HoriOrientation::LEFT); + m_xWrapAnchorOnlyCB->set_sensitive(bAllHtmlModes && nSur != css::text::WrapTextMode_NONE); + m_xWrapOutsideCB->hide(); + m_xIdealWrapRB->set_sensitive(false); + + m_xWrapTransparentCB->set_sensitive(false); + m_xNoWrapRB->set_sensitive(RndStdIds::FLY_AT_PARA == m_nAnchorId); + m_xWrapParallelRB->set_sensitive(false); + m_xWrapLeftRB->set_sensitive + ( (RndStdIds::FLY_AT_PARA == m_nAnchorId) + || ( (RndStdIds::FLY_AT_CHAR == m_nAnchorId) + && (eHOrient == text::HoriOrientation::RIGHT) + && (eHRelOrient == text::RelOrientation::PRINT_AREA))); + m_xWrapRightRB->set_sensitive + ( (RndStdIds::FLY_AT_PARA == m_nAnchorId) + || ( (RndStdIds::FLY_AT_CHAR == m_nAnchorId) + && (eHOrient == text::HoriOrientation::LEFT) + && (eHRelOrient == text::RelOrientation::PRINT_AREA))); + + m_xWrapThroughRB->set_sensitive + ( ( (RndStdIds::FLY_AT_PAGE == m_nAnchorId) + || ( (RndStdIds::FLY_AT_CHAR == m_nAnchorId) + && (eHRelOrient != text::RelOrientation::PRINT_AREA)) + || (RndStdIds::FLY_AT_PARA == m_nAnchorId)) + && (eHOrient != text::HoriOrientation::RIGHT)); + if (m_xNoWrapRB->get_active() && !m_xNoWrapRB->get_sensitive()) + { + if(m_xWrapThroughRB->get_sensitive()) + m_xWrapThroughRB->set_active(true); + else if(m_xWrapLeftRB->get_sensitive()) + m_xWrapLeftRB->set_active(true); + else if(m_xWrapRightRB->get_sensitive()) + m_xWrapRightRB->set_active(true); + + } + if (m_xWrapLeftRB->get_active() && !m_xWrapLeftRB->get_sensitive()) + { + if(m_xWrapRightRB->get_sensitive()) + m_xWrapRightRB->set_active(true); + else if(m_xWrapThroughRB->get_sensitive()) + m_xWrapThroughRB->set_active(true); + } + if (m_xWrapRightRB->get_active() && !m_xWrapRightRB->get_sensitive()) + { + if(m_xWrapLeftRB->get_sensitive()) + m_xWrapLeftRB->set_active(true); + else if(m_xWrapThroughRB->get_sensitive()) + m_xWrapThroughRB->set_active(true); + } + if (m_xWrapThroughRB->get_active() && !m_xWrapThroughRB->get_sensitive()) + if(m_xNoWrapRB->get_sensitive()) + m_xNoWrapRB->set_active(true); + + if (m_xWrapParallelRB->get_active() && !m_xWrapParallelRB->get_sensitive()) + m_xWrapThroughRB->set_active(true); + } + else + { + m_xNoWrapRB->set_sensitive(bEnable); + m_xWrapLeftRB->set_sensitive(bEnable); + m_xWrapRightRB->set_sensitive(bEnable); + m_xIdealWrapRB->set_sensitive(bEnable); + m_xWrapThroughRB->set_sensitive(bEnable); + m_xWrapParallelRB->set_sensitive(bEnable); + m_xWrapAnchorOnlyCB->set_sensitive( + ((m_nAnchorId == RndStdIds::FLY_AT_PARA) || (m_nAnchorId == RndStdIds::FLY_AT_CHAR)) + && nSur != css::text::WrapTextMode_NONE ); + } + ContourHdl(*m_xWrapOutlineCB); +} + +DeactivateRC SwWrapTabPage::DeactivatePage(SfxItemSet* _pSet) +{ + if(_pSet) + FillItemSet(_pSet); + + return DeactivateRC::LeavePage; +} + +IMPL_LINK(SwWrapTabPage, RangeModifyHdl, weld::MetricSpinButton&, rEdit, void) +{ + auto nValue = rEdit.get_value(FieldUnit::NONE); + weld::MetricSpinButton* pOpposite = nullptr; + if (&rEdit == m_xLeftMarginED.get()) + pOpposite = m_xRightMarginED.get(); + else if (&rEdit == m_xRightMarginED.get()) + pOpposite = m_xLeftMarginED.get(); + else if (&rEdit == m_xTopMarginED.get()) + pOpposite = m_xBottomMarginED.get(); + else if (&rEdit == m_xBottomMarginED.get()) + pOpposite = m_xTopMarginED.get(); + + assert(pOpposite); + + if (pOpposite) + { + auto nOpposite = pOpposite->get_value(FieldUnit::NONE); + + if (nValue + nOpposite > std::max(rEdit.get_max(FieldUnit::NONE), pOpposite->get_max(FieldUnit::NONE))) + pOpposite->set_value(pOpposite->get_max(FieldUnit::NONE) - nValue, FieldUnit::NONE); + } +} + +IMPL_LINK_NOARG(SwWrapTabPage, WrapTypeHdl, weld::Toggleable&, void) +{ + bool bWrapThrough = m_xWrapThroughRB->get_active(); + m_xWrapTransparentCB->set_sensitive(bWrapThrough && !m_bHtmlMode); + bWrapThrough |= ( m_nAnchorId == RndStdIds::FLY_AS_CHAR ); + m_xWrapOutlineCB->set_sensitive(!bWrapThrough && !m_xNoWrapRB->get_active()); + m_xWrapOutsideCB->set_sensitive(!bWrapThrough && m_xWrapOutlineCB->get_active()); + m_xWrapAnchorOnlyCB->set_sensitive( + ((m_nAnchorId == RndStdIds::FLY_AT_PARA) || (m_nAnchorId == RndStdIds::FLY_AT_CHAR)) && + (!m_xNoWrapRB->get_active()) ); + + ContourHdl(*m_xWrapOutlineCB); +} + +IMPL_LINK_NOARG(SwWrapTabPage, ContourHdl, weld::Toggleable&, void) +{ + bool bEnable = !(m_xWrapOutlineCB->get_active() && m_xWrapOutlineCB->get_sensitive()); + + m_xWrapOutsideCB->set_sensitive(!bEnable); + + bEnable = !m_xWrapOutlineCB->get_active(); + if (bEnable == m_bContourImage) // so that it doesn't always flicker + { + m_bContourImage = !bEnable; + SetImages(); + } +} + +void SwWrapTabPage::SetImages() +{ + m_xWrapThroughImg->set_from_icon_name(RID_BMP_WRAP_THROUGH); + bool bWrapOutline = !m_xWrapOutlineCB->get_active(); + if (bWrapOutline) + { + m_xNoWrapImg->set_from_icon_name(RID_BMP_WRAP_NONE); + m_xWrapLeftImg->set_from_icon_name(RID_BMP_WRAP_LEFT); + m_xWrapRightImg->set_from_icon_name(RID_BMP_WRAP_RIGHT); + m_xWrapParallelImg->set_from_icon_name(RID_BMP_WRAP_PARALLEL); + m_xIdealWrapImg->set_from_icon_name(RID_BMP_WRAP_IDEAL); + } + else + { + m_xNoWrapImg->set_from_icon_name(RID_BMP_WRAP_CONTOUR_NONE); + m_xWrapLeftImg->set_from_icon_name(RID_BMP_WRAP_CONTOUR_LEFT); + m_xWrapRightImg->set_from_icon_name(RID_BMP_WRAP_CONTOUR_RIGHT); + m_xWrapParallelImg->set_from_icon_name(RID_BMP_WRAP_CONTOUR_PARALLEL); + m_xIdealWrapImg->set_from_icon_name(RID_BMP_WRAP_CONTOUR_IDEAL); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |