diff options
Diffstat (limited to 'sw/source/uibase/sidebar')
34 files changed, 6507 insertions, 0 deletions
diff --git a/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx new file mode 100644 index 0000000000..a1907c9b63 --- /dev/null +++ b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.cxx @@ -0,0 +1,377 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <AccessibilityCheck.hxx> +#include <AccessibilityIssue.hxx> +#include <cmdid.h> +#include <doc.hxx> +#include <docsh.hxx> +#include <ndtxt.hxx> +#include <wrtsh.hxx> + +#include <officecfg/Office/Common.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/AccessibilityIssue.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/svapp.hxx> + +#include "A11yCheckIssuesPanel.hxx" + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar +{ +AccessibilityCheckEntry::AccessibilityCheckEntry( + weld::Container* pParent, std::shared_ptr<sfx::AccessibilityIssue> const& rAccessibilityIssue) + : m_xBuilder(Application::CreateBuilder(pParent, "svx/ui/accessibilitycheckentry.ui")) + , m_xContainer(m_xBuilder->weld_container("accessibilityCheckEntryBox")) + , m_xLabel(m_xBuilder->weld_label("accessibilityCheckEntryLabel")) + , m_xGotoButton(m_xBuilder->weld_link_button("accessibilityCheckEntryLinkButton")) + , m_xFixButton(m_xBuilder->weld_button("accessibilityCheckEntryFixButton")) + , m_pAccessibilityIssue(rAccessibilityIssue) +{ + // lock in the height as including the button so all rows are the same height + m_xContainer->set_size_request(-1, m_xContainer->get_preferred_size().Height()); + + if (m_pAccessibilityIssue->canGotoIssue()) + { + m_xGotoButton->set_label(m_pAccessibilityIssue->m_aIssueText); + + // tdf#156137 allow LinkButton label to wrap + int nMaxWidth = m_xGotoButton->get_approximate_digit_width() * 10; + m_xGotoButton->set_label_wrap(true); + m_xGotoButton->set_size_request(nMaxWidth, -1); + + m_xGotoButton->connect_activate_link( + LINK(this, AccessibilityCheckEntry, GotoButtonClicked)); + + // add full path of linked graphic as tooltip, + if (m_pAccessibilityIssue->m_eIssueID == sfx::AccessibilityIssueID::LINKED_GRAPHIC) + { + auto pSwIssue = std::static_pointer_cast<sw::AccessibilityIssue>(m_pAccessibilityIssue); + auto aInfo = pSwIssue->getAdditionalInfo(); + if (aInfo.size() > 0) + { + m_xGotoButton->set_tooltip_text(aInfo[0]); + } + } + + m_xLabel->set_visible(false); + } + else + { + m_xLabel->set_label(m_pAccessibilityIssue->m_aIssueText); + m_xGotoButton->set_visible(false); + } + + m_xFixButton->set_visible(m_pAccessibilityIssue->canQuickFixIssue()); + m_xFixButton->connect_clicked(LINK(this, AccessibilityCheckEntry, FixButtonClicked)); + + m_pAccessibilityIssue->setParent(dynamic_cast<weld::Window*>(get_widget())); +} + +IMPL_LINK_NOARG(AccessibilityCheckEntry, GotoButtonClicked, weld::LinkButton&, bool) +{ + m_pAccessibilityIssue->gotoIssue(); + return true; +} + +IMPL_LINK_NOARG(AccessibilityCheckEntry, FixButtonClicked, weld::Button&, void) +{ + m_pAccessibilityIssue->quickFixIssue(); +} + +std::unique_ptr<PanelLayout> A11yCheckIssuesPanel::Create(weld::Widget* pParent, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw ::com::sun::star::lang::IllegalArgumentException( + "no parent window given to A11yCheckIssuesPanel::Create", nullptr, 0); + return std::make_unique<A11yCheckIssuesPanel>(pParent, pBindings); +} + +A11yCheckIssuesPanel::A11yCheckIssuesPanel(weld::Widget* pParent, SfxBindings* pBindings) + : PanelLayout(pParent, "A11yCheckIssuesPanel", "modules/swriter/ui/a11ycheckissuespanel.ui") + , m_xExpanderDocument(m_xBuilder->weld_expander("expand_document")) + , m_xExpanderStyles(m_xBuilder->weld_expander("expand_styles")) + , m_xExpanderLinked(m_xBuilder->weld_expander("expand_linked")) + , m_xExpanderNoAlt(m_xBuilder->weld_expander("expand_no_alt")) + , m_xExpanderTable(m_xBuilder->weld_expander("expand_table")) + , m_xExpanderFormatting(m_xBuilder->weld_expander("expand_formatting")) + , m_xExpanderHyperlink(m_xBuilder->weld_expander("expand_hyperlink")) + , m_xExpanderFakes(m_xBuilder->weld_expander("expand_fakes")) + , m_xExpanderNumbering(m_xBuilder->weld_expander("expand_numbering")) + , m_xExpanderOther(m_xBuilder->weld_expander("expand_other")) + , m_xBoxDocument(m_xBuilder->weld_box("box_document")) + , m_xBoxStyles(m_xBuilder->weld_box("box_styles")) + , m_xBoxLinked(m_xBuilder->weld_box("box_linked")) + , m_xBoxNoAlt(m_xBuilder->weld_box("box_no_alt")) + , m_xBoxTable(m_xBuilder->weld_box("box_table")) + , m_xBoxFormatting(m_xBuilder->weld_box("box_formatting")) + , m_xBoxHyperlink(m_xBuilder->weld_box("box_hyperlink")) + , m_xBoxFakes(m_xBuilder->weld_box("box_fakes")) + , m_xBoxNumbering(m_xBuilder->weld_box("box_numbering")) + , m_xBoxOther(m_xBuilder->weld_box("box_other")) + , mpBindings(pBindings) + , mpDoc(nullptr) + , maA11yCheckController(FN_STAT_ACCESSIBILITY_CHECK, *pBindings, *this) + , mnIssueCount(0) + , mbAutomaticCheckEnabled(false) +{ + SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(SfxObjectShell::Current()); + if (!pDocSh) + return; + + // Automatic a11y checking must be enabled for this panel to work properly + mbAutomaticCheckEnabled + = officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::get(); + if (!mbAutomaticCheckEnabled) + { + std::shared_ptr<comphelper::ConfigurationChanges> batch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(true, batch); + batch->commit(); + pBindings->Invalidate(SID_ACCESSIBILITY_CHECK_ONLINE); + } + + mpDoc = pDocSh->GetDoc(); + + populateIssues(); +} + +void A11yCheckIssuesPanel::ImplDestroy() +{ + // Restore state when this panel is no longer used + if (!mbAutomaticCheckEnabled) + { + std::shared_ptr<comphelper::ConfigurationChanges> batch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(false, batch); + batch->commit(); + mpBindings->Invalidate(SID_ACCESSIBILITY_CHECK_ONLINE); + } + m_xExpanderDocument.reset(); + m_xExpanderStyles.reset(); + m_xExpanderLinked.reset(); + m_xExpanderNoAlt.reset(); + m_xExpanderTable.reset(); + m_xExpanderFormatting.reset(); + m_xExpanderHyperlink.reset(); + m_xExpanderFakes.reset(); + m_xExpanderNumbering.reset(); + m_xExpanderOther.reset(); + m_xBoxDocument.reset(); + m_xBoxStyles.reset(); + m_xBoxLinked.reset(); + m_xBoxNoAlt.reset(); + m_xBoxTable.reset(); + m_xBoxFormatting.reset(); + m_xBoxHyperlink.reset(); + m_xBoxFakes.reset(); + m_xBoxNumbering.reset(); + m_xBoxOther.reset(); +} + +A11yCheckIssuesPanel::~A11yCheckIssuesPanel() { suppress_fun_call_w_exception(ImplDestroy()); } + +void A11yCheckIssuesPanel::removeOldWidgets() +{ + for (auto const& xEntry : m_aDocumentEntries) + m_xBoxDocument->move(xEntry->get_widget(), nullptr); + m_xExpanderDocument->set_visible(false); + + for (auto const& xEntry : m_aStylesEntries) + m_xBoxStyles->move(xEntry->get_widget(), nullptr); + m_xExpanderStyles->set_visible(false); + + for (auto const& xEntry : m_aLinkedEntries) + m_xBoxLinked->move(xEntry->get_widget(), nullptr); + m_xExpanderLinked->set_visible(false); + + for (auto const& xEntry : m_aNoAltEntries) + m_xBoxNoAlt->move(xEntry->get_widget(), nullptr); + m_xExpanderNoAlt->set_visible(false); + + for (auto const& xEntry : m_aTableEntries) + m_xBoxTable->move(xEntry->get_widget(), nullptr); + m_xExpanderTable->set_visible(false); + + for (auto const& xEntry : m_aFormattingEntries) + m_xBoxFormatting->move(xEntry->get_widget(), nullptr); + m_xExpanderFormatting->set_visible(false); + + for (auto const& xEntry : m_aHyperlinkEntries) + m_xBoxHyperlink->move(xEntry->get_widget(), nullptr); + m_xExpanderHyperlink->set_visible(false); + + for (auto const& xEntry : m_aFakesEntries) + m_xBoxFakes->move(xEntry->get_widget(), nullptr); + m_xExpanderFakes->set_visible(false); + + for (auto const& xEntry : m_aNumberingEntries) + m_xBoxNumbering->move(xEntry->get_widget(), nullptr); + m_xExpanderNumbering->set_visible(false); + + for (auto const& xEntry : m_aOtherEntries) + m_xBoxOther->move(xEntry->get_widget(), nullptr); + m_xExpanderOther->set_visible(false); +} + +void A11yCheckIssuesPanel::populateIssues() +{ + if (!mpDoc) + return; + sw::AccessibilityCheck aCheck(mpDoc); + aCheck.check(); + m_aIssueCollection = aCheck.getIssueCollection(); + + removeOldWidgets(); + + sal_Int32 iDocument = 0; + sal_Int32 iStyles = 0; + sal_Int32 iLinked = 0; + sal_Int32 iNoAlt = 0; + sal_Int32 iTable = 0; + sal_Int32 iFormatting = 0; + sal_Int32 iHyperlink = 0; + sal_Int32 iFakes = 0; + sal_Int32 iNumbering = 0; + sal_Int32 iOther = 0; + for (std::shared_ptr<sfx::AccessibilityIssue> const& pIssue : m_aIssueCollection.getIssues()) + { + switch (pIssue->m_eIssueID) + { + case sfx::AccessibilityIssueID::DOCUMENT_TITLE: + case sfx::AccessibilityIssueID::DOCUMENT_LANGUAGE: + case sfx::AccessibilityIssueID::DOCUMENT_BACKGROUND: + { + auto xEntry + = std::make_unique<AccessibilityCheckEntry>(m_xBoxDocument.get(), pIssue); + m_xBoxDocument->reorder_child(xEntry->get_widget(), iDocument++); + m_xExpanderDocument->set_visible(true); + m_aDocumentEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::STYLE_LANGUAGE: + { + auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxStyles.get(), pIssue); + m_xBoxStyles->reorder_child(xEntry->get_widget(), iStyles++); + m_xExpanderStyles->set_visible(true); + m_aStylesEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::LINKED_GRAPHIC: + { + auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxLinked.get(), pIssue); + m_xBoxLinked->reorder_child(xEntry->get_widget(), iLinked++); + m_xExpanderLinked->set_visible(true); + m_aLinkedEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::NO_ALT_OLE: + case sfx::AccessibilityIssueID::NO_ALT_GRAPHIC: + case sfx::AccessibilityIssueID::NO_ALT_SHAPE: + { + auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxNoAlt.get(), pIssue); + m_xBoxNoAlt->reorder_child(xEntry->get_widget(), iNoAlt++); + m_xExpanderNoAlt->set_visible(true); + m_aNoAltEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::TABLE_MERGE_SPLIT: + { + auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxTable.get(), pIssue); + m_xBoxTable->reorder_child(xEntry->get_widget(), iTable++); + m_xExpanderTable->set_visible(true); + m_aTableEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::TEXT_FORMATTING: + case sfx::AccessibilityIssueID::TABLE_FORMATTING: + { + auto xEntry + = std::make_unique<AccessibilityCheckEntry>(m_xBoxFormatting.get(), pIssue); + m_xBoxFormatting->reorder_child(xEntry->get_widget(), iFormatting++); + m_xExpanderFormatting->set_visible(true); + m_aFormattingEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::HYPERLINK_IS_TEXT: + case sfx::AccessibilityIssueID::HYPERLINK_SHORT: + { + auto xEntry + = std::make_unique<AccessibilityCheckEntry>(m_xBoxHyperlink.get(), pIssue); + m_xBoxHyperlink->reorder_child(xEntry->get_widget(), iHyperlink++); + m_xExpanderHyperlink->set_visible(true); + m_aHyperlinkEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::FAKE_FOOTNOTE: + case sfx::AccessibilityIssueID::FAKE_CAPTION: + { + auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxFakes.get(), pIssue); + m_xBoxFakes->reorder_child(xEntry->get_widget(), iFakes++); + m_xExpanderFakes->set_visible(true); + m_aFakesEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::MANUAL_NUMBERING: + { + auto xEntry + = std::make_unique<AccessibilityCheckEntry>(m_xBoxNumbering.get(), pIssue); + m_xBoxNumbering->reorder_child(xEntry->get_widget(), iNumbering++); + m_xExpanderNumbering->set_visible(true); + m_aNumberingEntries.push_back(std::move(xEntry)); + } + break; + case sfx::AccessibilityIssueID::UNSPECIFIED: + { + auto xEntry = std::make_unique<AccessibilityCheckEntry>(m_xBoxOther.get(), pIssue); + m_xBoxOther->reorder_child(xEntry->get_widget(), iOther++); + m_xExpanderOther->set_visible(true); + m_aOtherEntries.push_back(std::move(xEntry)); + } + break; + default: + { + SAL_WARN("sw.a11y", "Invalid issue ID."); + continue; + } + break; + }; + } +} + +void A11yCheckIssuesPanel::NotifyItemUpdate(const sal_uInt16 nSid, const SfxItemState /* eState */, + const SfxPoolItem* pState) +{ + if (!pState) //disposed + return; + + switch (nSid) + { + case FN_STAT_ACCESSIBILITY_CHECK: + { + sal_Int32 nIssueCount = static_cast<const SfxInt32Item*>(pState)->GetValue(); + if (nIssueCount != mnIssueCount) + { + mnIssueCount = nIssueCount; + populateIssues(); + } + } + break; + default: + break; + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx new file mode 100644 index 0000000000..7f569e16ef --- /dev/null +++ b/sw/source/uibase/sidebar/A11yCheckIssuesPanel.hxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <memory> + +#include <sfx2/AccessibilityIssue.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <svl/poolitem.hxx> +#include <tools/link.hxx> +#include <vcl/weld.hxx> + +#include <doc.hxx> + +namespace sw::sidebar +{ +class AccessibilityCheckEntry final +{ +private: + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + std::unique_ptr<weld::Label> m_xLabel; + std::unique_ptr<weld::LinkButton> m_xGotoButton; + std::unique_ptr<weld::Button> m_xFixButton; + + std::shared_ptr<sfx::AccessibilityIssue> const& m_pAccessibilityIssue; + +public: + AccessibilityCheckEntry(weld::Container* pParent, + std::shared_ptr<sfx::AccessibilityIssue> const& pAccessibilityIssue); + + weld::Widget* get_widget() const { return m_xContainer.get(); } + + DECL_LINK(GotoButtonClicked, weld::LinkButton&, bool); + DECL_LINK(FixButtonClicked, weld::Button&, void); +}; + +class A11yCheckIssuesPanel : public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent, SfxBindings* pBindings); + + virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState(const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override{}; + + A11yCheckIssuesPanel(weld::Widget* pParent, SfxBindings* pBindings); + void ImplDestroy(); + virtual ~A11yCheckIssuesPanel() override; + +private: + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aDocumentEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aStylesEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aLinkedEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aNoAltEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aTableEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aFormattingEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aHyperlinkEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aFakesEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aNumberingEntries; + std::vector<std::unique_ptr<AccessibilityCheckEntry>> m_aOtherEntries; + std::unique_ptr<weld::Expander> m_xExpanderDocument; + std::unique_ptr<weld::Expander> m_xExpanderStyles; + std::unique_ptr<weld::Expander> m_xExpanderLinked; + std::unique_ptr<weld::Expander> m_xExpanderNoAlt; + std::unique_ptr<weld::Expander> m_xExpanderTable; + std::unique_ptr<weld::Expander> m_xExpanderFormatting; + std::unique_ptr<weld::Expander> m_xExpanderHyperlink; + std::unique_ptr<weld::Expander> m_xExpanderFakes; + std::unique_ptr<weld::Expander> m_xExpanderNumbering; + std::unique_ptr<weld::Expander> m_xExpanderOther; + std::unique_ptr<weld::Box> m_xBoxDocument; + std::unique_ptr<weld::Box> m_xBoxStyles; + std::unique_ptr<weld::Box> m_xBoxLinked; + std::unique_ptr<weld::Box> m_xBoxNoAlt; + std::unique_ptr<weld::Box> m_xBoxTable; + std::unique_ptr<weld::Box> m_xBoxFormatting; + std::unique_ptr<weld::Box> m_xBoxHyperlink; + std::unique_ptr<weld::Box> m_xBoxFakes; + std::unique_ptr<weld::Box> m_xBoxNumbering; + std::unique_ptr<weld::Box> m_xBoxOther; + sfx::AccessibilityIssueCollection m_aIssueCollection; + void removeOldWidgets(); + void populateIssues(); + + SfxBindings* mpBindings; + SwDoc* mpDoc; + ::sfx2::sidebar::ControllerItem maA11yCheckController; + sal_Int32 mnIssueCount; + bool mbAutomaticCheckEnabled; +}; + +} //end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/uibase/sidebar/PageColumnControl.cxx b/sw/source/uibase/sidebar/PageColumnControl.cxx new file mode 100644 index 0000000000..6afb22a819 --- /dev/null +++ b/sw/source/uibase/sidebar/PageColumnControl.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include "PageColumnControl.hxx" +#include <PageColumnPopup.hxx> + +#include <cmdid.h> + +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/intitem.hxx> +#include <svx/pageitem.hxx> + +namespace sw::sidebar { + +PageColumnControl::PageColumnControl(PageColumnPopup* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pagecolumncontrol.ui", "PageColumnControl") + , m_xMoreButton(m_xBuilder->weld_button("moreoptions")) + , m_xControl(pControl) +{ + bool bLandscape = false; + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SfxPoolItemHolder aResult; + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult); + const SvxPageItem* pPageItem(static_cast<const SvxPageItem*>(aResult.getItem())); + bLandscape = pPageItem->IsLandscape(); + } + + if ( bLandscape ) + { + m_xOneColumn = m_xBuilder->weld_button("column1L"); + m_xTwoColumns = m_xBuilder->weld_button("column2L"); + m_xThreeColumns = m_xBuilder->weld_button("column3L"); + m_xLeft = m_xBuilder->weld_button("columnleftL"); + m_xRight = m_xBuilder->weld_button("columnrightL"); + } + else + { + m_xOneColumn = m_xBuilder->weld_button("column1"); + m_xTwoColumns = m_xBuilder->weld_button( "column2"); + m_xThreeColumns = m_xBuilder->weld_button("column3"); + m_xLeft = m_xBuilder->weld_button("columnleft"); + m_xRight = m_xBuilder->weld_button("columnright"); + } + + m_xOneColumn->show(); + m_xTwoColumns->show(); + m_xThreeColumns->show(); + m_xLeft->show(); + m_xRight->show(); + + m_xOneColumn->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) ); + m_xTwoColumns->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) ); + m_xThreeColumns->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) ); + m_xLeft->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) ); + m_xRight->connect_clicked( LINK( this, PageColumnControl, ColumnButtonClickHdl_Impl ) ); + + m_xMoreButton->connect_clicked( LINK( this, PageColumnControl, MoreButtonClickHdl_Impl ) ); +} + +void PageColumnControl::GrabFocus() +{ + m_xMoreButton->grab_focus(); +} + +PageColumnControl::~PageColumnControl() +{ +} + +void PageColumnControl::ExecuteColumnChange( const sal_uInt16 nColumnType ) +{ + SfxInt16Item aPageColumnTypeItem(SID_ATTR_PAGE_COLUMN); + aPageColumnTypeItem.SetValue( nColumnType ); + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetBindings().GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLUMN, + SfxCallMode::RECORD, { &aPageColumnTypeItem }); +} + +IMPL_LINK( PageColumnControl, ColumnButtonClickHdl_Impl, weld::Button&, rButton, void ) +{ + if ( &rButton == m_xOneColumn.get() ) + ExecuteColumnChange( 1 ); + else if ( &rButton == m_xTwoColumns.get() ) + ExecuteColumnChange( 2 ); + else if ( &rButton == m_xThreeColumns.get() ) + ExecuteColumnChange( 3 ); + else if ( &rButton == m_xLeft.get() ) + ExecuteColumnChange( 4 ); + else if ( &rButton == m_xRight.get() ) + ExecuteColumnChange( 5 ); + + m_xControl->EndPopupMode(); +} + +IMPL_LINK_NOARG( PageColumnControl, MoreButtonClickHdl_Impl, weld::Button&, void ) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetBindings().GetDispatcher()->Execute( FN_FORMAT_PAGE_COLUMN_DLG, SfxCallMode::ASYNCHRON ); + m_xControl->EndPopupMode(); +} + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageColumnControl.hxx b/sw/source/uibase/sidebar/PageColumnControl.hxx new file mode 100644 index 0000000000..f4e35291b7 --- /dev/null +++ b/sw/source/uibase/sidebar/PageColumnControl.hxx @@ -0,0 +1,56 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGECOLUMNCONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGECOLUMNCONTROL_HXX + +#include <svtools/toolbarmenu.hxx> +#include <vcl/weld.hxx> + +class PageColumnPopup; + +namespace sw::sidebar +{ +class PageColumnControl final : public WeldToolbarPopup +{ +public: + explicit PageColumnControl(PageColumnPopup* pControl, weld::Widget* pParent); + virtual void GrabFocus() override; + virtual ~PageColumnControl() override; + +private: + std::unique_ptr<weld::Button> m_xOneColumn; + std::unique_ptr<weld::Button> m_xTwoColumns; + std::unique_ptr<weld::Button> m_xThreeColumns; + std::unique_ptr<weld::Button> m_xLeft; + std::unique_ptr<weld::Button> m_xRight; + std::unique_ptr<weld::Button> m_xMoreButton; + + rtl::Reference<PageColumnPopup> m_xControl; + + static void ExecuteColumnChange(const sal_uInt16 nColumnType); + + DECL_LINK(ColumnButtonClickHdl_Impl, weld::Button&, void); + DECL_LINK(MoreButtonClickHdl_Impl, weld::Button&, void); +}; + +} // end of namespace sw::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageColumnPopup.cxx b/sw/source/uibase/sidebar/PageColumnPopup.cxx new file mode 100644 index 0000000000..da64a484d3 --- /dev/null +++ b/sw/source/uibase/sidebar/PageColumnPopup.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <PageColumnPopup.hxx> +#include "PageColumnControl.hxx" +#include <vcl/toolbox.hxx> + +PageColumnPopup::PageColumnPopup(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageColumnPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageColumnPopup::~PageColumnPopup() +{ +} + +std::unique_ptr<WeldToolbarPopup> PageColumnPopup::weldPopupWindow() +{ + return std::make_unique<sw::sidebar::PageColumnControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> PageColumnPopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<sw::sidebar::PageColumnControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageColumnPopup::getImplementationName() +{ + return "lo.writer.PageColumnToolBoxControl"; +} + +css::uno::Sequence<OUString> PageColumnPopup::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_PageColumnToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new PageColumnPopup(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageFooterPanel.cxx b/sw/source/uibase/sidebar/PageFooterPanel.cxx new file mode 100644 index 0000000000..1a2f049dce --- /dev/null +++ b/sw/source/uibase/sidebar/PageFooterPanel.cxx @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <sal/config.h> +#include <svl/intitem.hxx> +#include <svl/eitem.hxx> +#include <svl/itemset.hxx> +#include <svx/dlgutil.hxx> +#include <svx/rulritem.hxx> +#include <svx/svdtrans.hxx> +#include <svx/spacinglistbox.hxx> +#include <svx/samecontentlistbox.hxx> +#include "PageFooterPanel.hxx" +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <cmdid.h> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar{ + +std::unique_ptr<PanelLayout> PageFooterPanel::Create( + weld::Widget* pParent, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageFooterPanel::Create", nullptr, 0); + return std::make_unique<PageFooterPanel>(pParent, pBindings); +} + +void PageFooterPanel::SetMarginsAndSpacingFieldUnit() +{ + SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::SPACING_INCH : SpacingType::SPACING_CM, *mxFooterSpacingLB); + SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::MARGINS_INCH : SpacingType::MARGINS_CM, *mxFooterMarginPresetLB); +} + +PageFooterPanel::PageFooterPanel( + weld::Widget* pParent, + SfxBindings* pBindings) : + PanelLayout(pParent, "PageFooterPanel", "modules/swriter/ui/pagefooterpanel.ui"), + mpBindings( pBindings ), + maHFToggleController(SID_ATTR_PAGE_FOOTER, *pBindings, *this), + maMetricController(SID_ATTR_METRIC, *pBindings,*this), + maFooterLRMarginController(SID_ATTR_PAGE_FOOTER_LRMARGIN, *pBindings, *this), + maFooterSpacingController(SID_ATTR_PAGE_FOOTER_SPACING, *pBindings, *this), + maFooterLayoutController(SID_ATTR_PAGE_FOOTER_LAYOUT, *pBindings, *this), + meFUnit(GetModuleFieldUnit()), + mpFooterItem( new SfxBoolItem(SID_ATTR_PAGE_FOOTER) ), + mpFooterLRMarginItem( new SvxLongLRSpaceItem(0, 0, SID_ATTR_PAGE_FOOTER_LRMARGIN)), + mpFooterSpacingItem( new SvxLongULSpaceItem(0, 0, SID_ATTR_PAGE_FOOTER_SPACING)), + mpFooterLayoutItem( new SfxInt16Item(SID_ATTR_PAGE_FOOTER_LAYOUT)), + mxFooterToggle(m_xBuilder->weld_check_button("footertoggle")), + mxFooterSpacingLB(m_xBuilder->weld_combo_box("spacingpreset")), + mxFooterMarginPresetLB(m_xBuilder->weld_combo_box("footermarginpreset")), + mxFooterLayoutLB(m_xBuilder->weld_combo_box("samecontentLB")), + mxCustomEntry(m_xBuilder->weld_label("customlabel")) +{ + Initialize(); +} + +PageFooterPanel::~PageFooterPanel() +{ + mxFooterToggle.reset(); + maMetricController.dispose(); + mxFooterSpacingLB.reset(); + mxFooterLayoutLB.reset(); + mxFooterMarginPresetLB.reset(); + mxCustomEntry.reset(); +} + +FieldUnit PageFooterPanel::GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState) +{ + FieldUnit eUnit; + + if (pState && eState >= SfxItemState::DEFAULT) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue()); + else + eUnit = GetModuleFieldUnit(); + + return eUnit; +} + +void PageFooterPanel::Initialize() +{ + SameContentListBox::Fill(*mxFooterLayoutLB); + + SetMarginsAndSpacingFieldUnit(); + + m_aCustomEntry = mxCustomEntry->get_label(); + mxFooterToggle->connect_toggled( LINK(this, PageFooterPanel, FooterToggleHdl) ); + mxFooterMarginPresetLB->connect_changed( LINK(this, PageFooterPanel, FooterLRMarginHdl)); + mxFooterSpacingLB->connect_changed( LINK(this, PageFooterPanel, FooterSpacingHdl)); + mxFooterLayoutLB->connect_changed( LINK(this, PageFooterPanel, FooterLayoutHdl)); + + mpBindings->Invalidate(SID_ATTR_METRIC); + mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER); + mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER_LRMARGIN); + mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER_SPACING); + mpBindings->Invalidate(SID_ATTR_PAGE_FOOTER_LAYOUT); +} + +void PageFooterPanel::UpdateFooterCheck() +{ + if (mxFooterToggle->get_active()) + { + mxFooterSpacingLB->set_sensitive(true); + mxFooterLayoutLB->set_sensitive(true); + mxFooterMarginPresetLB->set_sensitive(true); + } + else + { + mxFooterSpacingLB->set_sensitive(false); + mxFooterLayoutLB->set_sensitive(false); + mxFooterMarginPresetLB->set_sensitive(false); + } +} + +void PageFooterPanel::UpdateMarginControl() +{ + sal_uInt16 nLeft = mpFooterLRMarginItem->GetLeft(); + sal_uInt16 nRight = mpFooterLRMarginItem->GetRight(); + sal_uInt16 nCount = mxFooterMarginPresetLB->get_count(); + if(nLeft == nRight) + { + for (sal_uInt16 i = 0; i < nCount; ++i) + { + if (mxFooterMarginPresetLB->get_id(i).toUInt32() == nLeft) + { + mxFooterMarginPresetLB->set_active(i); + int nCustomEntry = mxFooterMarginPresetLB->find_text(m_aCustomEntry); + if (nCustomEntry != -1) + mxFooterMarginPresetLB->remove(nCustomEntry); + return; + } + } + } + mxFooterMarginPresetLB->append_text(m_aCustomEntry); + mxFooterMarginPresetLB->set_active_text(m_aCustomEntry); +} + +void PageFooterPanel::UpdateSpacingControl() +{ + sal_uInt16 nBottom = mpFooterSpacingItem->GetUpper(); + sal_uInt16 nCount = mxFooterSpacingLB->get_count(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + if (mxFooterSpacingLB->get_id(i).toUInt32() == nBottom) + { + mxFooterSpacingLB->set_active(i); + int nCustomEntry = mxFooterSpacingLB->find_text(m_aCustomEntry); + if (nCustomEntry != -1) + mxFooterSpacingLB->remove(nCustomEntry); + return; + } + } + mxFooterSpacingLB->append_text(m_aCustomEntry); + mxFooterSpacingLB->set_active_text(m_aCustomEntry); +} + +void PageFooterPanel::UpdateLayoutControl() +{ + sal_uInt16 nLayout = mpFooterLayoutItem->GetValue(); + mxFooterLayoutLB->set_active(nLayout); +} + +void PageFooterPanel::NotifyItemUpdate( + const sal_uInt16 nSid, + const SfxItemState eState, + const SfxPoolItem* pState) +{ + if (!mxFooterToggle) //disposed + return; + + switch(nSid) + { + case SID_ATTR_PAGE_FOOTER: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SfxBoolItem*>( pState) ) + { + mpFooterItem.reset( static_cast<SfxBoolItem*>(pState->Clone()) ); + mxFooterToggle->set_active(mpFooterItem->GetValue()); + UpdateFooterCheck(); + } + } + break; + case SID_ATTR_PAGE_FOOTER_LRMARGIN: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SvxLongLRSpaceItem*>( pState) ) + { + mpFooterLRMarginItem.reset( static_cast<SvxLongLRSpaceItem*>(pState->Clone()) ); + UpdateMarginControl(); + } + } + break; + case SID_ATTR_PAGE_FOOTER_SPACING: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SvxLongULSpaceItem*>( pState) ) + { + mpFooterSpacingItem.reset(static_cast<SvxLongULSpaceItem*>(pState->Clone()) ); + UpdateSpacingControl(); + } + } + break; + case SID_ATTR_PAGE_FOOTER_LAYOUT: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SfxInt16Item*>( pState) ) + { + mpFooterLayoutItem.reset(static_cast<SfxInt16Item*>(pState->Clone()) ); + UpdateLayoutControl(); + } + } + break; + case SID_ATTR_METRIC: + { + FieldUnit eFUnit = GetCurrentUnit(eState, pState); + if (meFUnit != eFUnit) + { + meFUnit = eFUnit; + SetMarginsAndSpacingFieldUnit(); + UpdateSpacingControl(); + UpdateMarginControl(); + } + } + break; + default: + break; + } +} + +IMPL_LINK_NOARG( PageFooterPanel, FooterToggleHdl, weld::Toggleable&, void ) +{ + bool IsChecked = mxFooterToggle->get_active(); + mpFooterItem->SetValue(IsChecked); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER, SfxCallMode::RECORD, { mpFooterItem.get() } ); + UpdateFooterCheck(); +} + +IMPL_LINK_NOARG( PageFooterPanel, FooterLRMarginHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nVal = mxFooterMarginPresetLB->get_active_id().toUInt32(); + mpFooterLRMarginItem->SetLeft(nVal); + mpFooterLRMarginItem->SetRight(nVal); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER_LRMARGIN, + SfxCallMode::RECORD, { mpFooterLRMarginItem.get() } ); +} + +IMPL_LINK_NOARG( PageFooterPanel, FooterSpacingHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nVal = mxFooterSpacingLB->get_active_id().toUInt32(); + mpFooterSpacingItem->SetUpper(nVal); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER_SPACING, + SfxCallMode::RECORD, { mpFooterSpacingItem.get() } ); + +} +IMPL_LINK_NOARG( PageFooterPanel, FooterLayoutHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nVal = mxFooterLayoutLB->get_active(); + mpFooterLayoutItem->SetValue(nVal); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_FOOTER_LAYOUT, + SfxCallMode::RECORD, { mpFooterLayoutItem.get() } ); +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageFooterPanel.hxx b/sw/source/uibase/sidebar/PageFooterPanel.hxx new file mode 100644 index 0000000000..6f5397a16c --- /dev/null +++ b/sw/source/uibase/sidebar/PageFooterPanel.hxx @@ -0,0 +1,101 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEFOOTERPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEFOOTERPANEL_HXX + +#include <memory> + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <svl/intitem.hxx> +#include <svl/poolitem.hxx> +#include <svl/eitem.hxx> +#include <svx/rulritem.hxx> + +namespace sw::sidebar { + +class PageFooterPanel : + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + SfxBindings* GetBindings() const { return mpBindings; } + PageFooterPanel( + weld::Widget* pParent, + SfxBindings* pBindings); + virtual ~PageFooterPanel() override; + +private: + + SfxBindings* mpBindings; + + ::sfx2::sidebar::ControllerItem maHFToggleController; + ::sfx2::sidebar::ControllerItem maMetricController; + ::sfx2::sidebar::ControllerItem maFooterLRMarginController; + ::sfx2::sidebar::ControllerItem maFooterSpacingController; + ::sfx2::sidebar::ControllerItem maFooterLayoutController; + + FieldUnit meFUnit; + + OUString m_aCustomEntry; + + void Initialize(); + void SetMarginsAndSpacingFieldUnit(); + void UpdateFooterCheck(); + void UpdateMarginControl(); + void UpdateSpacingControl(); + void UpdateLayoutControl(); + + ::std::unique_ptr<SfxBoolItem> mpFooterItem; + ::std::unique_ptr<SvxLongLRSpaceItem> mpFooterLRMarginItem; + ::std::unique_ptr<SvxLongULSpaceItem> mpFooterSpacingItem; + ::std::unique_ptr<SfxInt16Item> mpFooterLayoutItem; + + std::unique_ptr<weld::CheckButton> mxFooterToggle; + std::unique_ptr<weld::ComboBox> mxFooterSpacingLB; + std::unique_ptr<weld::ComboBox> mxFooterMarginPresetLB; + std::unique_ptr<weld::ComboBox> mxFooterLayoutLB; + std::unique_ptr<weld::Label> mxCustomEntry; + + static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState); + + DECL_LINK( FooterToggleHdl, weld::Toggleable&, void ); + DECL_LINK( FooterLRMarginHdl, weld::ComboBox&, void); + DECL_LINK( FooterSpacingHdl, weld::ComboBox&, void); + DECL_LINK( FooterLayoutHdl, weld::ComboBox&, void); +}; + +} //end of namespace sw::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageFormatPanel.cxx b/sw/source/uibase/sidebar/PageFormatPanel.cxx new file mode 100644 index 0000000000..fdfa9ce661 --- /dev/null +++ b/sw/source/uibase/sidebar/PageFormatPanel.cxx @@ -0,0 +1,418 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <sal/config.h> +#include <sal/log.hxx> +#include <swtypes.hxx> +#include <svl/intitem.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/paperinf.hxx> +#include <svx/dlgutil.hxx> +#include <svx/rulritem.hxx> +#include <svx/svdtrans.hxx> +#include "PageFormatPanel.hxx" +#include "PageMarginUtils.hxx" +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/module.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <pageformatpanel.hrc> +#include <cmdid.h> +#include <svtools/optionsdrawinglayer.hxx> +#include <unotools/localedatawrapper.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar{ + +std::unique_ptr<PanelLayout> PageFormatPanel::Create( + weld::Widget* pParent, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageFormatPanel::Create", nullptr, 0); + + return std::make_unique<PageFormatPanel>(pParent, pBindings); +} + +void PageFormatPanel::SetMarginFieldUnit() +{ + auto nSelected = mxMarginSelectBox->get_active(); + mxMarginSelectBox->clear(); + + const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetLocaleDataWrapper(); + if (IsInch(meFUnit)) + { + OUString sSuffix = weld::MetricSpinButton::MetricToString(FieldUnit::INCH); + for (auto const& [aName, nSize] : RID_PAGEFORMATPANEL_MARGINS_INCH) + { + OUString sStr = rLocaleData.getNum(nSize, 2, true, false) + sSuffix; + mxMarginSelectBox->append_text(SwResId(aName).replaceFirst("%1", sStr)); + } + } + else + { + OUString sSuffix = weld::MetricSpinButton::MetricToString(FieldUnit::CM); + for (auto const& [aName, nSize] : RID_PAGEFORMATPANEL_MARGINS_CM) + { + OUString sStr = rLocaleData.getNum(nSize, 2, true, false) + " " + sSuffix; + mxMarginSelectBox->append_text(SwResId(aName).replaceFirst("%1", sStr)); + } + } + mxMarginSelectBox->set_active(nSelected); +} + +PageFormatPanel::PageFormatPanel(weld::Widget* pParent, SfxBindings* pBindings) : + PanelLayout(pParent, "PageFormatPanel", "modules/swriter/ui/pageformatpanel.ui"), + mpBindings( pBindings ), + mxPaperSizeBox(new SvxPaperSizeListBox(m_xBuilder->weld_combo_box("papersize"))), + mxPaperWidth(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("paperwidth", FieldUnit::CM))), + mxPaperHeight(new SvxRelativeField(m_xBuilder->weld_metric_spin_button("paperheight", FieldUnit::CM))), + mxPaperOrientation(m_xBuilder->weld_combo_box("paperorientation")), + mxMarginSelectBox(m_xBuilder->weld_combo_box("marginLB")), + mxCustomEntry(m_xBuilder->weld_label("customlabel")), + maPaperSizeController(SID_ATTR_PAGE_SIZE, *pBindings, *this), + maPaperOrientationController(SID_ATTR_PAGE, *pBindings, *this), + maMetricController(SID_ATTR_METRIC, *pBindings,*this), + maSwPageLRControl(SID_ATTR_PAGE_LRSPACE, *pBindings, *this), + maSwPageULControl(SID_ATTR_PAGE_ULSPACE, *pBindings, *this), + mpPageItem( new SvxPageItem(SID_ATTR_PAGE) ), + mpPageLRMarginItem( new SvxLongLRSpaceItem( 0, 0, SID_ATTR_PAGE_LRSPACE ) ), + mpPageULMarginItem( new SvxLongULSpaceItem( 0, 0, SID_ATTR_PAGE_ULSPACE ) ), + meFUnit(GetModuleFieldUnit()), + meUnit() +{ + Initialize(); +} + +PageFormatPanel::~PageFormatPanel() +{ + mxPaperSizeBox.reset(); + mxPaperWidth.reset(); + mxPaperHeight.reset(); + mxPaperOrientation.reset(); + mxMarginSelectBox.reset(); + mxCustomEntry.reset(); + + maMetricController.dispose(); + maPaperOrientationController.dispose(); + maPaperSizeController.dispose(); + maSwPageLRControl.dispose(); + maSwPageULControl.dispose(); + mpPageULMarginItem.reset(); + mpPageLRMarginItem.reset(); + mpPageItem.reset(); +} + +void PageFormatPanel::Initialize() +{ + mxPaperSizeBox->FillPaperSizeEntries( PaperSizeApp::Std ); + maPaperSizeController.SetFallbackCoreMetric(MapUnit::MapTwip); + meUnit = maPaperSizeController.GetCoreMetric(); + mxPaperWidth->SetFieldUnit(meFUnit); + mxPaperHeight->SetFieldUnit(meFUnit); + SetMarginFieldUnit(); + m_aCustomEntry = mxCustomEntry->get_label(); + + mxPaperWidth->set_max(mxPaperWidth->normalize(SvtOptionsDrawinglayer::GetMaximumPaperWidth()), FieldUnit::CM); + mxPaperHeight->set_max(mxPaperHeight->normalize(SvtOptionsDrawinglayer::GetMaximumPaperHeight()), FieldUnit::CM); + + mxPaperSizeBox->connect_changed( LINK(this, PageFormatPanel, PaperFormatModifyHdl )); + mxPaperOrientation->connect_changed( LINK(this, PageFormatPanel, PaperFormatModifyHdl )); + mxPaperHeight->connect_value_changed( LINK(this, PageFormatPanel, PaperSizeModifyHdl )); + mxPaperWidth->connect_value_changed( LINK(this, PageFormatPanel, PaperSizeModifyHdl )); + mxMarginSelectBox->connect_changed( LINK(this, PageFormatPanel, PaperModifyMarginHdl)); + + mpBindings->Update(SID_ATTR_METRIC); + mpBindings->Update(SID_ATTR_PAGE); + mpBindings->Update(SID_ATTR_PAGE_SIZE); + mpBindings->Update(SID_ATTR_PAGE_LRSPACE); + mpBindings->Update(SID_ATTR_PAGE_ULSPACE); + + UpdateMarginBox(); +} + +void PageFormatPanel::NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) +{ + switch(nSId) + { + case SID_ATTR_PAGE_SIZE: + { + const SvxSizeItem* pSizeItem = nullptr; + if (eState >= SfxItemState::DEFAULT) + pSizeItem = dynamic_cast< const SvxSizeItem* >(pState); + if (pSizeItem) + { + Size aPaperSize = pSizeItem->GetSize(); + + mxPaperWidth->set_value(mxPaperWidth->normalize(aPaperSize.Width()), FieldUnit::TWIP); + mxPaperHeight->set_value(mxPaperHeight->normalize(aPaperSize.Height()), FieldUnit::TWIP); + + if(mxPaperOrientation->get_active() == 1) + Swap(aPaperSize); + + Paper ePaper = SvxPaperInfo::GetSvxPaper(aPaperSize, meUnit); + mxPaperSizeBox->set_active_id( ePaper ); + } + } + break; + case SID_ATTR_METRIC: + { + meUnit = maPaperSizeController.GetCoreMetric(); + FieldUnit eFUnit = GetCurrentUnit(eState, pState); + if (eFUnit != meFUnit) + { + meFUnit = eFUnit; + mxPaperHeight->SetFieldUnit(meFUnit); + mxPaperWidth->SetFieldUnit(meFUnit); + SetMarginFieldUnit(); + UpdateMarginBox(); + } + } + break; + case SID_ATTR_PAGE: + { + if ( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SvxPageItem *>( pState ) ) + { + mpPageItem.reset( static_cast<SvxPageItem*>(pState->Clone()) ); + if ( mpPageItem->IsLandscape() ) + mxPaperOrientation->set_active(1); + else + mxPaperOrientation->set_active(0); + } + } + break; + case SID_ATTR_PAGE_LRSPACE: + { + if ( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SvxLongLRSpaceItem *>( pState ) ) + { + mpPageLRMarginItem.reset( static_cast<SvxLongLRSpaceItem*>(pState->Clone()) ); + UpdateMarginBox(); + } + } + break; + case SID_ATTR_PAGE_ULSPACE: + { + if ( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SvxLongULSpaceItem *>( pState ) ) + { + mpPageULMarginItem.reset( static_cast<SvxLongULSpaceItem*>(pState->Clone()) ); + UpdateMarginBox(); + } + } + break; + default: + break; + } +} + +IMPL_LINK_NOARG(PageFormatPanel, PaperFormatModifyHdl, weld::ComboBox&, void) +{ + Paper ePaper = mxPaperSizeBox->get_active_id(); + Size aSize; + + if(ePaper!=PAPER_USER) + aSize = SvxPaperInfo::GetPaperSize(ePaper, meUnit); + else + aSize = Size(mxPaperWidth->GetCoreValue(meUnit), mxPaperHeight->GetCoreValue(meUnit)); + + if (mxPaperOrientation->get_active() == 1 || ePaper==PAPER_USER) + Swap(aSize); + + mpPageItem->SetLandscape(mxPaperOrientation->get_active() == 1); + SvxSizeItem aSizeItem(SID_ATTR_PAGE_SIZE, aSize); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, SfxCallMode::RECORD, { &aSizeItem, mpPageItem.get() }); +} + +IMPL_LINK_NOARG(PageFormatPanel, PaperSizeModifyHdl, weld::MetricSpinButton&, void) +{ + Size aSize(mxPaperWidth->GetCoreValue(meUnit), mxPaperHeight->GetCoreValue(meUnit)); + SvxSizeItem aSizeItem(SID_ATTR_PAGE_SIZE, aSize); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, SfxCallMode::RECORD, { &aSizeItem }); +} + +IMPL_LINK_NOARG(PageFormatPanel, PaperModifyMarginHdl, weld::ComboBox&, void) +{ + bool bMirrored = false; + bool bApplyNewPageMargins = true; + switch (mxMarginSelectBox->get_active()) + { + case 0: + SetNone(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 1: + SetNarrow(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 2: + SetModerate(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 3: + SetNormal075(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 4: + SetNormal100(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 5: + SetNormal125(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 6: + SetWide(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + case 7: + SetMirrored(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored); + break; + default: + bApplyNewPageMargins = false; + break; + } + + if(bApplyNewPageMargins) + { + ExecuteMarginLRChange( mnPageLeftMargin, mnPageRightMargin ); + ExecuteMarginULChange( mnPageTopMargin, mnPageBottomMargin ); + if(bMirrored != (mpPageItem->GetPageUsage() == SvxPageUsage::Mirror)) + { + mpPageItem->SetPageUsage( bMirrored ? SvxPageUsage::Mirror : SvxPageUsage::All ); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE, + SfxCallMode::RECORD, { mpPageItem.get() }); + } + } +} + +FieldUnit PageFormatPanel::GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ) +{ + FieldUnit eUnit = FieldUnit::NONE; + + if ( pState && eState >= SfxItemState::DEFAULT ) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue()); + else + { + SfxViewFrame* pFrame = SfxViewFrame::Current(); + SfxObjectShell* pSh = nullptr; + if ( pFrame ) + pSh = pFrame->GetObjectShell(); + if ( pSh ) + { + SfxModule* pModule = pSh->GetModule(); + if ( pModule ) + { + const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC ); + if ( pItem ) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + } + else + { + SAL_WARN("sw.ui", "GetModuleFieldUnit(): no module found"); + } + } + } + + return eUnit; +} + +void PageFormatPanel::ExecuteMarginLRChange( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin ) +{ + mpPageLRMarginItem->SetLeft( nPageLeftMargin ); + mpPageLRMarginItem->SetRight( nPageRightMargin ); + mpBindings->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_LRSPACE, SfxCallMode::RECORD, { mpPageLRMarginItem.get() }); +} + +void PageFormatPanel::ExecuteMarginULChange(const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin) +{ + mpPageULMarginItem->SetUpper( nPageTopMargin ); + mpPageULMarginItem->SetLower( nPageBottomMargin ); + mpBindings->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_ULSPACE, SfxCallMode::RECORD, { mpPageULMarginItem.get() }); +} + +void PageFormatPanel::UpdateMarginBox() +{ + mnPageLeftMargin = mpPageLRMarginItem->GetLeft(); + mnPageRightMargin = mpPageLRMarginItem->GetRight(); + mnPageTopMargin = mpPageULMarginItem->GetUpper(); + mnPageBottomMargin = mpPageULMarginItem->GetLower(); + + int nCustomEntry = mxMarginSelectBox->find_text(m_aCustomEntry); + + bool bMirrored = (mpPageItem->GetPageUsage() == SvxPageUsage::Mirror); + if( IsNone(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(0); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsNarrow(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(1); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsModerate(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(2); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsNormal075(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(3); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsNormal100(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(4); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsNormal125(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(5); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsWide(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(6); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else if( IsMirrored(mnPageLeftMargin, mnPageRightMargin, mnPageTopMargin, mnPageBottomMargin, bMirrored) ) + { + mxMarginSelectBox->set_active(7); + if (nCustomEntry != -1) + mxMarginSelectBox->remove(nCustomEntry); + } + else + { + if (nCustomEntry == -1) + mxMarginSelectBox->append_text(m_aCustomEntry); + mxMarginSelectBox->set_active_text(m_aCustomEntry); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageFormatPanel.hxx b/sw/source/uibase/sidebar/PageFormatPanel.hxx new file mode 100644 index 0000000000..a1eb2f109b --- /dev/null +++ b/sw/source/uibase/sidebar/PageFormatPanel.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> + +#include <svx/pageitem.hxx> +#include <svx/rulritem.hxx> +#include <svx/papersizelistbox.hxx> + +#include <tools/fldunit.hxx> +#include <svl/poolitem.hxx> +#include <svx/relfld.hxx> + +#include <memory> + +namespace sw::sidebar { + +class PageFormatPanel : + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + PageFormatPanel( + weld::Widget* pParent, + SfxBindings* pBindings); + virtual ~PageFormatPanel() override; + + static FieldUnit GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ); + +private: + + SfxBindings* mpBindings; + + std::unique_ptr<SvxPaperSizeListBox> mxPaperSizeBox; + std::unique_ptr<SvxRelativeField> mxPaperWidth; + std::unique_ptr<SvxRelativeField> mxPaperHeight; + std::unique_ptr<weld::ComboBox> mxPaperOrientation; + std::unique_ptr<weld::ComboBox> mxMarginSelectBox; + std::unique_ptr<weld::Label> mxCustomEntry; + + ::sfx2::sidebar::ControllerItem maPaperSizeController; + ::sfx2::sidebar::ControllerItem maPaperOrientationController; + ::sfx2::sidebar::ControllerItem maMetricController; + ::sfx2::sidebar::ControllerItem maSwPageLRControl; + ::sfx2::sidebar::ControllerItem maSwPageULControl; + + std::unique_ptr<SvxPageItem> mpPageItem; + std::unique_ptr<SvxLongLRSpaceItem> mpPageLRMarginItem; + std::unique_ptr<SvxLongULSpaceItem> mpPageULMarginItem; + + FieldUnit meFUnit; + MapUnit meUnit; + + tools::Long mnPageLeftMargin; + tools::Long mnPageRightMargin; + tools::Long mnPageTopMargin; + tools::Long mnPageBottomMargin; + OUString m_aCustomEntry; + + void Initialize(); + void SetMarginFieldUnit(); + void UpdateMarginBox(); + void ExecuteMarginLRChange( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin ); + void ExecuteMarginULChange( const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin); + DECL_LINK(PaperFormatModifyHdl, weld::ComboBox&, void); + DECL_LINK(PaperSizeModifyHdl, weld::MetricSpinButton&, void); + DECL_LINK(PaperModifyMarginHdl, weld::ComboBox&, void ); +}; + +} //end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageHeaderPanel.cxx b/sw/source/uibase/sidebar/PageHeaderPanel.cxx new file mode 100644 index 0000000000..e0706f9c76 --- /dev/null +++ b/sw/source/uibase/sidebar/PageHeaderPanel.cxx @@ -0,0 +1,287 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <sal/config.h> +#include <svl/intitem.hxx> +#include <svl/eitem.hxx> +#include <svl/itemset.hxx> +#include <svx/dlgutil.hxx> +#include <svx/rulritem.hxx> +#include <svx/svdtrans.hxx> +#include <svx/spacinglistbox.hxx> +#include <svx/samecontentlistbox.hxx> +#include "PageHeaderPanel.hxx" +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <cmdid.h> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar{ + +std::unique_ptr<PanelLayout> PageHeaderPanel::Create( + weld::Widget* pParent, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageHeaderPanel::Create", nullptr, 0); + if( pBindings == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no SfxBindings given to PageHeaderPanel::Create", nullptr, 0); + + return std::make_unique<PageHeaderPanel>(pParent, pBindings); +} + +void PageHeaderPanel::SetMarginsAndSpacingFieldUnit() +{ + SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::SPACING_INCH : SpacingType::SPACING_CM, *mxHeaderSpacingLB); + SpacingListBox::Fill(IsInch(meFUnit) ? SpacingType::MARGINS_INCH : SpacingType::MARGINS_CM, *mxHeaderMarginPresetLB); +} + +PageHeaderPanel::PageHeaderPanel( + weld::Widget* pParent, + SfxBindings* pBindings + ) : + PanelLayout(pParent, "PageHeaderPanel", "modules/swriter/ui/pageheaderpanel.ui"), + mpBindings( pBindings ), + maHFToggleController(SID_ATTR_PAGE_HEADER, *pBindings, *this), + maMetricController(SID_ATTR_METRIC, *pBindings,*this), + maHeaderLRMarginController(SID_ATTR_PAGE_HEADER_LRMARGIN, *pBindings, *this), + maHeaderSpacingController(SID_ATTR_PAGE_HEADER_SPACING, *pBindings, *this), + maHeaderLayoutController(SID_ATTR_PAGE_HEADER_LAYOUT, *pBindings, *this), + meFUnit(GetModuleFieldUnit()), + mpHeaderItem( new SfxBoolItem(SID_ATTR_PAGE_HEADER) ), + mpHeaderLRMarginItem( new SvxLongLRSpaceItem(0, 0, SID_ATTR_PAGE_HEADER_LRMARGIN)), + mpHeaderSpacingItem( new SvxLongULSpaceItem(0, 0, SID_ATTR_PAGE_HEADER_SPACING)), + mpHeaderLayoutItem( new SfxInt16Item(SID_ATTR_PAGE_HEADER_LAYOUT)), + mxHeaderToggle(m_xBuilder->weld_check_button("headertoggle")), + mxHeaderSpacingLB(m_xBuilder->weld_combo_box("spacingpreset")), + mxHeaderMarginPresetLB(m_xBuilder->weld_combo_box("headermarginpreset")), + mxHeaderLayoutLB(m_xBuilder->weld_combo_box("samecontentLB")), + mxCustomEntry(m_xBuilder->weld_label("customlabel")) +{ + Initialize(); +} + +PageHeaderPanel::~PageHeaderPanel() +{ + mxHeaderToggle.reset(); + mxHeaderSpacingLB.reset(); + mxHeaderLayoutLB.reset(); + mxHeaderMarginPresetLB.reset(); + mxCustomEntry.reset(); +} + +FieldUnit PageHeaderPanel::GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState) +{ + FieldUnit eUnit; + + if (pState && eState >= SfxItemState::DEFAULT) + eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pState)->GetValue()); + else + eUnit = GetModuleFieldUnit(); + + return eUnit; +} + +void PageHeaderPanel::Initialize() +{ + SameContentListBox::Fill(*mxHeaderLayoutLB); + + SetMarginsAndSpacingFieldUnit(); + + m_aCustomEntry = mxCustomEntry->get_label(); + mxHeaderToggle->connect_toggled( LINK(this, PageHeaderPanel, HeaderToggleHdl) ); + mxHeaderMarginPresetLB->connect_changed( LINK(this, PageHeaderPanel, HeaderLRMarginHdl)); + mxHeaderSpacingLB->connect_changed( LINK(this, PageHeaderPanel, HeaderSpacingHdl)); + mxHeaderLayoutLB->connect_changed( LINK(this, PageHeaderPanel, HeaderLayoutHdl)); + + mpBindings->Invalidate(SID_ATTR_METRIC); + mpBindings->Invalidate(SID_ATTR_PAGE_HEADER); + mpBindings->Invalidate(SID_ATTR_PAGE_HEADER_LRMARGIN); + mpBindings->Invalidate(SID_ATTR_PAGE_HEADER_SPACING); + mpBindings->Invalidate(SID_ATTR_PAGE_HEADER_LAYOUT); +} + +void PageHeaderPanel::UpdateHeaderCheck() +{ + if (mxHeaderToggle->get_active()) + { + mxHeaderSpacingLB->set_sensitive(true); + mxHeaderLayoutLB->set_sensitive(true); + mxHeaderMarginPresetLB->set_sensitive(true); + } + else + { + mxHeaderSpacingLB->set_sensitive(false); + mxHeaderLayoutLB->set_sensitive(false); + mxHeaderMarginPresetLB->set_sensitive(false); + } +} + +void PageHeaderPanel::UpdateMarginControl() +{ + sal_uInt16 nLeft = mpHeaderLRMarginItem->GetLeft(); + sal_uInt16 nRight = mpHeaderLRMarginItem->GetRight(); + sal_uInt16 nCount = mxHeaderMarginPresetLB->get_count(); + if(nLeft == nRight) + { + for (sal_uInt16 i = 0; i < nCount; ++i) + { + if (mxHeaderMarginPresetLB->get_id(i).toUInt32() == nLeft) + { + mxHeaderMarginPresetLB->set_active(i); + int nCustomEntry = mxHeaderMarginPresetLB->find_text(m_aCustomEntry); + if (nCustomEntry != -1) + mxHeaderMarginPresetLB->remove(nCustomEntry); + return; + } + } + } + mxHeaderMarginPresetLB->append_text(m_aCustomEntry); + mxHeaderMarginPresetLB->set_active_text(m_aCustomEntry); +} + +void PageHeaderPanel::UpdateSpacingControl() +{ + sal_uInt16 nBottom = mpHeaderSpacingItem->GetLower(); + sal_uInt16 nCount = mxHeaderSpacingLB->get_count(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + if (mxHeaderSpacingLB->get_id(i).toUInt32() == nBottom) + { + mxHeaderSpacingLB->set_active(i); + int nCustomEntry = mxHeaderSpacingLB->find_text(m_aCustomEntry); + if (nCustomEntry != -1) + mxHeaderSpacingLB->remove(nCustomEntry); + return; + } + } + mxHeaderSpacingLB->append_text(m_aCustomEntry); + mxHeaderSpacingLB->set_active_text(m_aCustomEntry); +} + +void PageHeaderPanel::UpdateLayoutControl() +{ + sal_uInt16 nLayout = mpHeaderLayoutItem->GetValue(); + mxHeaderLayoutLB->set_active(nLayout); +} + +void PageHeaderPanel::NotifyItemUpdate( + const sal_uInt16 nSid, + const SfxItemState eState, + const SfxPoolItem* pState) +{ + if (!mxHeaderToggle) //disposed + return; + + switch(nSid) + { + case SID_ATTR_PAGE_HEADER: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SfxBoolItem*>( pState) ) + { + mpHeaderItem.reset( static_cast<SfxBoolItem*>(pState->Clone()) ); + mxHeaderToggle->set_active(mpHeaderItem->GetValue()); + UpdateHeaderCheck(); + } + } + break; + case SID_ATTR_PAGE_HEADER_LRMARGIN: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SvxLongLRSpaceItem*>( pState) ) + { + mpHeaderLRMarginItem.reset( static_cast<SvxLongLRSpaceItem*>(pState->Clone()) ); + UpdateMarginControl(); + } + } + break; + case SID_ATTR_PAGE_HEADER_SPACING: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SvxLongULSpaceItem*>( pState) ) + { + mpHeaderSpacingItem.reset(static_cast<SvxLongULSpaceItem*>(pState->Clone()) ); + UpdateSpacingControl(); + } + } + break; + case SID_ATTR_PAGE_HEADER_LAYOUT: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast<const SfxInt16Item*>( pState) ) + { + mpHeaderLayoutItem.reset(static_cast<SfxInt16Item*>(pState->Clone()) ); + UpdateLayoutControl(); + } + } + break; + case SID_ATTR_METRIC: + { + FieldUnit eFUnit = GetCurrentUnit(eState, pState); + if (meFUnit != eFUnit) + { + meFUnit = eFUnit; + SetMarginsAndSpacingFieldUnit(); + UpdateSpacingControl(); + UpdateMarginControl(); + } + } + break; + default: + break; + } +} + +IMPL_LINK_NOARG( PageHeaderPanel, HeaderToggleHdl, weld::Toggleable&, void ) +{ + bool IsChecked = mxHeaderToggle->get_active(); + mpHeaderItem->SetValue(IsChecked); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER, SfxCallMode::RECORD, { mpHeaderItem.get() } ); + UpdateHeaderCheck(); +} + +IMPL_LINK_NOARG( PageHeaderPanel, HeaderLRMarginHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nVal = mxHeaderMarginPresetLB->get_active_id().toUInt32(); + mpHeaderLRMarginItem->SetLeft(nVal); + mpHeaderLRMarginItem->SetRight(nVal); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER_LRMARGIN, + SfxCallMode::RECORD, { mpHeaderLRMarginItem.get() } ); +} + +IMPL_LINK_NOARG( PageHeaderPanel, HeaderSpacingHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nVal = mxHeaderSpacingLB->get_active_id().toUInt32(); + mpHeaderSpacingItem->SetLower(nVal); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER_SPACING, + SfxCallMode::RECORD, { mpHeaderSpacingItem.get() } ); +} +IMPL_LINK_NOARG( PageHeaderPanel, HeaderLayoutHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nVal = mxHeaderLayoutLB->get_active(); + mpHeaderLayoutItem->SetValue(nVal); + GetBindings()->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_HEADER_LAYOUT, + SfxCallMode::RECORD, { mpHeaderLayoutItem.get() } ); +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageHeaderPanel.hxx b/sw/source/uibase/sidebar/PageHeaderPanel.hxx new file mode 100644 index 0000000000..7ccd7268c8 --- /dev/null +++ b/sw/source/uibase/sidebar/PageHeaderPanel.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <memory> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <svl/intitem.hxx> +#include <svl/poolitem.hxx> +#include <svl/eitem.hxx> +#include <svx/rulritem.hxx> + +namespace sw::sidebar { + +class PageHeaderPanel : + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + SfxBindings* GetBindings() const { return mpBindings; } + PageHeaderPanel( + weld::Widget* pParent, + SfxBindings* pBindings); + virtual ~PageHeaderPanel() override; + +private: + + SfxBindings* mpBindings; + + ::sfx2::sidebar::ControllerItem maHFToggleController; + ::sfx2::sidebar::ControllerItem maMetricController; + ::sfx2::sidebar::ControllerItem maHeaderLRMarginController; + ::sfx2::sidebar::ControllerItem maHeaderSpacingController; + ::sfx2::sidebar::ControllerItem maHeaderLayoutController; + + FieldUnit meFUnit; + + OUString m_aCustomEntry; + + void Initialize(); + void SetMarginsAndSpacingFieldUnit(); + void UpdateHeaderCheck(); + void UpdateMarginControl(); + void UpdateSpacingControl(); + void UpdateLayoutControl(); + + ::std::unique_ptr<SfxBoolItem> mpHeaderItem; + ::std::unique_ptr<SvxLongLRSpaceItem> mpHeaderLRMarginItem; + ::std::unique_ptr<SvxLongULSpaceItem> mpHeaderSpacingItem; + ::std::unique_ptr<SfxInt16Item> mpHeaderLayoutItem; + + std::unique_ptr<weld::CheckButton> mxHeaderToggle; + std::unique_ptr<weld::ComboBox> mxHeaderSpacingLB; + std::unique_ptr<weld::ComboBox> mxHeaderMarginPresetLB; + std::unique_ptr<weld::ComboBox> mxHeaderLayoutLB; + std::unique_ptr<weld::Label> mxCustomEntry; + + static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState); + + DECL_LINK( HeaderToggleHdl, weld::Toggleable&, void ); + DECL_LINK( HeaderLRMarginHdl, weld::ComboBox&, void); + DECL_LINK( HeaderSpacingHdl, weld::ComboBox&, void); + DECL_LINK( HeaderLayoutHdl, weld::ComboBox&, void); +}; + +} //end of namespace sw::sidebar + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageMarginControl.cxx b/sw/source/uibase/sidebar/PageMarginControl.cxx new file mode 100644 index 0000000000..2b9bb36cd7 --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginControl.cxx @@ -0,0 +1,597 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <sal/config.h> + +#include "PageMarginControl.hxx" +#include <strings.hrc> + +#include <editeng/sizeitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/module.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/pageitem.hxx> +#include <svx/rulritem.hxx> +#include <svl/itempool.hxx> +#include <svl/intitem.hxx> +#include <svtools/unitconv.hxx> +#include <unotools/viewoptions.hxx> + +#include <swtypes.hxx> +#include <cmdid.h> +#include <PageMarginPopup.hxx> + +#include <com/sun/star/document/XUndoManagerSupplier.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/frame/XFrame.hpp> + +constexpr OUString SWPAGE_LEFT_GVALUE = u"Sw_Page_Left"_ustr; +constexpr OUString SWPAGE_RIGHT_GVALUE = u"Sw_Page_Right"_ustr; +constexpr OUString SWPAGE_TOP_GVALUE = u"Sw_Page_Top"_ustr; +constexpr OUString SWPAGE_DOWN_GVALUE = u"Sw_Page_Down"_ustr; +constexpr OUString SWPAGE_MIRROR_GVALUE = u"Sw_Page_Mirrored"_ustr; + +namespace +{ + FieldUnit lcl_GetFieldUnit() + { + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SfxPoolItemHolder aResult; + const SfxItemState eState(pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_METRIC, aResult)); + const SfxUInt16Item* pItem(static_cast<const SfxUInt16Item*>(aResult.getItem())); + if (pItem && eState >= SfxItemState::DEFAULT) + return static_cast<FieldUnit>(pItem->GetValue()); + } + return SfxModule::GetCurrentFieldUnit(); + } + + MapUnit lcl_GetUnit() + { + SfxItemPool &rPool = SfxGetpApp()->GetPool(); + sal_uInt16 nWhich = rPool.GetWhich( SID_ATTR_PAGE_SIZE ); + return rPool.GetMetric( nWhich ); + } + + css::uno::Reference< css::document::XUndoManager > getUndoManager( const css::uno::Reference< css::frame::XFrame >& rxFrame ) + { + const css::uno::Reference< css::frame::XController >& xController = rxFrame->getController(); + if ( xController.is() ) + { + const css::uno::Reference< css::frame::XModel >& xModel = xController->getModel(); + if ( xModel.is() ) + { + const css::uno::Reference< css::document::XUndoManagerSupplier > xSuppUndo( xModel, css::uno::UNO_QUERY_THROW ); + return css::uno::Reference< css::document::XUndoManager >( xSuppUndo->getUndoManager(), css::uno::UNO_SET_THROW ); + } + } + + return css::uno::Reference< css::document::XUndoManager > (); + } +} + +namespace sw::sidebar { + +PageMarginControl::PageMarginControl(PageMarginPopup* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pagemargincontrol.ui", "PageMarginControl") + , m_xMoreButton(m_xBuilder->weld_button("moreoptions")) + , m_xLeft(m_xBuilder->weld_label("leftLabel")) + , m_xRight(m_xBuilder->weld_label("rightLabel")) + , m_xInner(m_xBuilder->weld_label("innerLabel")) + , m_xOuter(m_xBuilder->weld_label("outerLabel")) + , m_xLeftMarginEdit(m_xBuilder->weld_metric_spin_button("left", FieldUnit::CM)) + , m_xRightMarginEdit(m_xBuilder->weld_metric_spin_button("right", FieldUnit::CM)) + , m_xTopMarginEdit(m_xBuilder->weld_metric_spin_button("top", FieldUnit::CM)) + , m_xBottomMarginEdit(m_xBuilder->weld_metric_spin_button("bottom", FieldUnit::CM)) + , m_xWidthHeightField(m_xBuilder->weld_metric_spin_button("hidden", FieldUnit::CM)) + , m_xControl(pControl) + , m_nPageLeftMargin(0) + , m_nPageRightMargin(0) + , m_nPageTopMargin(0) + , m_nPageBottomMargin(0) + , m_bMirrored(false) + , m_eUnit( lcl_GetUnit() ) + , m_bUserCustomValuesAvailable( false ) + , m_nUserCustomPageLeftMargin( 0 ) + , m_nUserCustomPageRightMargin( 0 ) + , m_nUserCustomPageTopMargin( 0 ) + , m_nUserCustomPageBottomMargin( 0 ) + , m_bUserCustomMirrored( false ) + , m_bCustomValuesUsed( false ) +{ + m_xWidthHeightField->set_unit(FieldUnit::CM); + m_xWidthHeightField->set_range(0, 9999, FieldUnit::NONE); + m_xWidthHeightField->set_digits(2); + m_xWidthHeightField->set_increments(10, 100, FieldUnit::NONE); + SetFieldUnit( *m_xWidthHeightField, lcl_GetFieldUnit() ); + + bool bLandscape = false; + const SvxSizeItem* pSize = nullptr; + const SvxLongLRSpaceItem* pLRItem = nullptr; + const SvxLongULSpaceItem* pULItem = nullptr; + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SfxPoolItemHolder aResult; + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult); + const SvxPageItem* pPageItem(static_cast<const SvxPageItem*>(aResult.getItem())); + bLandscape = pPageItem->IsLandscape(); + m_bMirrored = pPageItem->GetPageUsage() == SvxPageUsage::Mirror; + + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult); + pSize = static_cast<const SvxSizeItem*>(aResult.getItem()); + + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_LRSPACE, aResult); + pLRItem = static_cast<const SvxLongLRSpaceItem*>(aResult.getItem()); + + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_ULSPACE, aResult); + pULItem = static_cast<const SvxLongULSpaceItem*>(aResult.getItem()); + } + + if ( pLRItem ) + { + m_nPageLeftMargin = pLRItem->GetLeft(); + m_nPageRightMargin = pLRItem->GetRight(); + } + + if ( pULItem ) + { + m_nPageTopMargin = pULItem->GetUpper(); + m_nPageBottomMargin = pULItem->GetLower(); + } + + if ( bLandscape ) + { + m_xNarrow = m_xBuilder->weld_button("narrowL"); + m_xNormal = m_xBuilder->weld_button("normalL"); + m_xWide = m_xBuilder->weld_button("wideL"); + m_xMirrored = m_xBuilder->weld_button("mirroredL"); + m_xLast = m_xBuilder->weld_button("lastL"); + } + else + { + m_xNarrow = m_xBuilder->weld_button("narrow"); + m_xNormal = m_xBuilder->weld_button("normal"); + m_xWide = m_xBuilder->weld_button("wide"); + m_xMirrored = m_xBuilder->weld_button("mirrored"); + m_xLast = m_xBuilder->weld_button("last"); + } + + m_xNarrow->show(); + m_xNormal->show(); + m_xWide->show(); + m_xMirrored->show(); + m_xLast->show(); + m_xMoreButton->show(); + + m_xNarrow->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) ); + m_xNormal->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) ); + m_xWide->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) ); + m_xMirrored->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) ); + m_xLast->connect_clicked( LINK( this, PageMarginControl, SelectMarginHdl ) ); + m_xMoreButton->connect_clicked( LINK(this, PageMarginControl, MoreButtonClickHdl_Impl)); + + m_bUserCustomValuesAvailable = GetUserCustomValues(); + + FillHelpText( m_bUserCustomValuesAvailable ); + + Link<weld::MetricSpinButton&,void> aLinkLR = LINK( this, PageMarginControl, ModifyLRMarginHdl ); + m_xLeftMarginEdit->connect_value_changed( aLinkLR ); + SetMetricValue( *m_xLeftMarginEdit, m_nPageLeftMargin, m_eUnit ); + SetFieldUnit( *m_xLeftMarginEdit, lcl_GetFieldUnit() ); + + m_xRightMarginEdit->connect_value_changed( aLinkLR ); + SetMetricValue( *m_xRightMarginEdit, m_nPageRightMargin, m_eUnit ); + SetFieldUnit( *m_xRightMarginEdit, lcl_GetFieldUnit() ); + + Link<weld::MetricSpinButton&,void> aLinkUL = LINK( this, PageMarginControl, ModifyULMarginHdl ); + m_xTopMarginEdit->connect_value_changed( aLinkUL ); + SetMetricValue( *m_xTopMarginEdit, m_nPageTopMargin, m_eUnit ); + SetFieldUnit( *m_xTopMarginEdit, lcl_GetFieldUnit() ); + + m_xBottomMarginEdit->connect_value_changed( aLinkUL ); + SetMetricValue( *m_xBottomMarginEdit, m_nPageBottomMargin, m_eUnit ); + SetFieldUnit( *m_xBottomMarginEdit, lcl_GetFieldUnit() ); + + if (pSize) + { + m_aPageSize = pSize->GetSize(); + SetMetricFieldMaxValues( m_aPageSize ); + } + + if ( m_bMirrored ) + { + m_xLeft->hide(); + m_xRight->hide(); + m_xInner->show(); + m_xOuter->show(); + } + else + { + m_xLeft->show(); + m_xRight->show(); + m_xInner->hide(); + m_xOuter->hide(); + } +} + +void PageMarginControl::GrabFocus() +{ + m_xMoreButton->grab_focus(); +} + +PageMarginControl::~PageMarginControl() +{ + StoreUserCustomValues(); +} + +void PageMarginControl::SetMetricFieldMaxValues( const Size& rPageSize ) +{ + const tools::Long nML = m_xLeftMarginEdit->denormalize( m_xLeftMarginEdit->get_value( FieldUnit::TWIP ) ); + const tools::Long nMR = m_xRightMarginEdit->denormalize( m_xRightMarginEdit->get_value( FieldUnit::TWIP ) ); + const tools::Long nMT = m_xTopMarginEdit->denormalize( m_xTopMarginEdit->get_value( FieldUnit::TWIP ) ); + const tools::Long nMB = m_xBottomMarginEdit->denormalize( m_xBottomMarginEdit->get_value( FieldUnit::TWIP ) ); + + const tools::Long nPH = OutputDevice::LogicToLogic( rPageSize.Height(), m_eUnit, MapUnit::MapTwip ); + const tools::Long nPW = OutputDevice::LogicToLogic( rPageSize.Width(), m_eUnit, MapUnit::MapTwip ); + + // Left + tools::Long nMax = nPW - nMR - MINBODY; + m_xLeftMarginEdit->set_max( m_xLeftMarginEdit->normalize( nMax ), FieldUnit::TWIP ); + + // Right + nMax = nPW - nML - MINBODY; + m_xRightMarginEdit->set_max( m_xRightMarginEdit->normalize( nMax ), FieldUnit::TWIP ); + + //Top + nMax = nPH - nMB - MINBODY; + m_xTopMarginEdit->set_max( m_xTopMarginEdit->normalize( nMax ), FieldUnit::TWIP ); + + //Bottom + nMax = nPH - nMT - MINBODY; + m_xBottomMarginEdit->set_max( m_xTopMarginEdit->normalize( nMax ), FieldUnit::TWIP ); +} + +void PageMarginControl::FillHelpText( const bool bUserCustomValuesAvailable ) +{ + const OUString aLeft = SwResId( STR_MARGIN_TOOLTIP_LEFT ); + const OUString aRight = SwResId( STR_MARGIN_TOOLTIP_RIGHT ); + const OUString aTop = SwResId( STR_MARGIN_TOOLTIP_TOP ); + const OUString aBottom = SwResId( STR_MARGIN_TOOLTIP_BOT ); + + SetMetricValue( *m_xWidthHeightField, SWPAGE_NARROW_VALUE, m_eUnit ); + const OUString aNarrowValText = m_xWidthHeightField->get_text(); + OUString aHelpText = aLeft + + aNarrowValText + + aRight + + aNarrowValText + + aTop + + aNarrowValText + + aBottom + + aNarrowValText; + m_xNarrow->set_tooltip_text( aHelpText ); + + SetMetricValue( *m_xWidthHeightField, SWPAGE_NORMAL_VALUE, m_eUnit ); + const OUString aNormalValText = m_xWidthHeightField->get_text(); + aHelpText = aLeft + + aNormalValText + + aRight + + aNormalValText + + aTop + + aNormalValText + + aBottom + + aNormalValText; + m_xNormal->set_tooltip_text( aHelpText ); + + SetMetricValue( *m_xWidthHeightField, SWPAGE_WIDE_VALUE1, m_eUnit ); + const OUString aWide1ValText = m_xWidthHeightField->get_text(); + SetMetricValue( *m_xWidthHeightField, SWPAGE_WIDE_VALUE2, m_eUnit ); + const OUString aWide2ValText = m_xWidthHeightField->get_text(); + aHelpText = aLeft + + aWide2ValText + + aRight + + aWide2ValText + + aTop + + aWide1ValText + + aBottom + + aWide1ValText; + m_xWide->set_tooltip_text( aHelpText ); + + const OUString aInner = SwResId( STR_MARGIN_TOOLTIP_INNER ); + const OUString aOuter = SwResId( STR_MARGIN_TOOLTIP_OUTER ); + + SetMetricValue( *m_xWidthHeightField, SWPAGE_WIDE_VALUE3, m_eUnit ); + const OUString aWide3ValText = m_xWidthHeightField->get_text(); + aHelpText = aInner + + aWide3ValText + + aOuter + + aWide1ValText + + aTop + + aWide1ValText + + aBottom + + aWide1ValText; + m_xMirrored->set_tooltip_text( aHelpText ); + + if ( bUserCustomValuesAvailable ) + { + aHelpText = m_bUserCustomMirrored ? aInner : aLeft; + SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageLeftMargin, m_eUnit ); + aHelpText += m_xWidthHeightField->get_text(); + aHelpText += m_bUserCustomMirrored ? aOuter : aRight; + SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageRightMargin, m_eUnit ); + aHelpText += m_xWidthHeightField->get_text() + aTop; + SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageTopMargin, m_eUnit ); + aHelpText += m_xWidthHeightField->get_text() + aBottom; + SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageBottomMargin, m_eUnit ); + aHelpText += m_xWidthHeightField->get_text(); + } + else + { + aHelpText.clear(); + } + m_xLast->set_tooltip_text( aHelpText ); +} + +IMPL_LINK( PageMarginControl, SelectMarginHdl, weld::Button&, rControl, void ) +{ + bool bMirrored = false; + bool bApplyNewPageMargins = true; + if( &rControl == m_xNarrow.get() ) + { + m_nPageLeftMargin = SWPAGE_NARROW_VALUE; + m_nPageRightMargin = SWPAGE_NARROW_VALUE; + m_nPageTopMargin = SWPAGE_NARROW_VALUE; + m_nPageBottomMargin = SWPAGE_NARROW_VALUE; + bMirrored = false; + } + if( &rControl == m_xNormal.get() ) + { + m_nPageLeftMargin = SWPAGE_NORMAL_VALUE; + m_nPageRightMargin = SWPAGE_NORMAL_VALUE; + m_nPageTopMargin = SWPAGE_NORMAL_VALUE; + m_nPageBottomMargin = SWPAGE_NORMAL_VALUE; + bMirrored = false; + } + if( &rControl == m_xWide.get() ) + { + m_nPageLeftMargin = SWPAGE_WIDE_VALUE2; + m_nPageRightMargin = SWPAGE_WIDE_VALUE2; + m_nPageTopMargin = SWPAGE_WIDE_VALUE1; + m_nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = false; + } + if( &rControl == m_xMirrored.get() ) + { + m_nPageLeftMargin = SWPAGE_WIDE_VALUE3; + m_nPageRightMargin = SWPAGE_WIDE_VALUE1; + m_nPageTopMargin = SWPAGE_WIDE_VALUE1; + m_nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = true; + } + if( &rControl == m_xLast.get() ) + { + if ( m_bUserCustomValuesAvailable ) + { + m_nPageLeftMargin = m_nUserCustomPageLeftMargin; + m_nPageRightMargin = m_nUserCustomPageRightMargin; + m_nPageTopMargin = m_nUserCustomPageTopMargin; + m_nPageBottomMargin = m_nUserCustomPageBottomMargin; + bMirrored = m_bUserCustomMirrored; + } + else + { + bApplyNewPageMargins = false; + } + } + + if ( !bApplyNewPageMargins ) + return; + + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + const css::uno::Reference<css::document::XUndoManager> xUndoManager(pViewFrm ? getUndoManager(pViewFrm->GetFrame().GetFrameInterface()) : nullptr); + if ( xUndoManager.is() ) + xUndoManager->enterUndoContext( "" ); + + ExecuteMarginLRChange( m_nPageLeftMargin, m_nPageRightMargin ); + ExecuteMarginULChange( m_nPageTopMargin, m_nPageBottomMargin ); + if ( m_bMirrored != bMirrored ) + { + m_bMirrored = bMirrored; + ExecutePageLayoutChange( m_bMirrored ); + } + + if ( xUndoManager.is() ) + xUndoManager->leaveUndoContext(); + + m_bCustomValuesUsed = false; + m_xControl->EndPopupMode(); +} + +void PageMarginControl::ExecuteMarginLRChange( + const tools::Long nPageLeftMargin, + const tools::Long nPageRightMargin ) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SvxLongLRSpaceItem aPageLRMarginItem( 0, 0, SID_ATTR_PAGE_LRSPACE ); + aPageLRMarginItem.SetLeft( nPageLeftMargin ); + aPageLRMarginItem.SetRight( nPageRightMargin ); + pViewFrm->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE_LRSPACE, + SfxCallMode::RECORD, { &aPageLRMarginItem } ); + } +} + +void PageMarginControl::ExecuteMarginULChange( + const tools::Long nPageTopMargin, + const tools::Long nPageBottomMargin ) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SvxLongULSpaceItem aPageULMarginItem( 0, 0, SID_ATTR_PAGE_ULSPACE ); + aPageULMarginItem.SetUpper( nPageTopMargin ); + aPageULMarginItem.SetLower( nPageBottomMargin ); + pViewFrm->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE_ULSPACE, + SfxCallMode::RECORD, { &aPageULMarginItem } ); + } +} + +void PageMarginControl::ExecutePageLayoutChange( const bool bMirrored ) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SvxPageItem aPageItem( SID_ATTR_PAGE ); + aPageItem.SetPageUsage( bMirrored ? SvxPageUsage::Mirror : SvxPageUsage::All ); + pViewFrm->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE, + SfxCallMode::RECORD, { &aPageItem } ); + } +} + +IMPL_LINK_NOARG( PageMarginControl, ModifyLRMarginHdl, weld::MetricSpinButton&, void ) +{ + m_nPageLeftMargin = GetCoreValue( *m_xLeftMarginEdit, m_eUnit ); + m_nPageRightMargin = GetCoreValue( *m_xRightMarginEdit, m_eUnit ); + ExecuteMarginLRChange( m_nPageLeftMargin, m_nPageRightMargin ); + SetMetricFieldMaxValues( m_aPageSize ); + m_bCustomValuesUsed = true; +} + +IMPL_LINK_NOARG( PageMarginControl, ModifyULMarginHdl, weld::MetricSpinButton&, void ) +{ + m_nPageTopMargin = GetCoreValue( *m_xTopMarginEdit, m_eUnit ); + m_nPageBottomMargin = GetCoreValue( *m_xBottomMarginEdit, m_eUnit ); + ExecuteMarginULChange( m_nPageTopMargin, m_nPageBottomMargin ); + SetMetricFieldMaxValues( m_aPageSize ); + m_bCustomValuesUsed = true; +} + +IMPL_LINK_NOARG(PageMarginControl, MoreButtonClickHdl_Impl, weld::Button&, void) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetBindings().GetDispatcher()->Execute(FN_FORMAT_PAGE_SETTING_DLG, + SfxCallMode::ASYNCHRON); + m_xControl->EndPopupMode(); +} + +bool PageMarginControl::GetUserCustomValues() +{ + bool bUserCustomValuesAvailable = false; + + SvtViewOptions aWinOpt( EViewType::Window, SWPAGE_LEFT_GVALUE ); + if ( aWinOpt.Exists() ) + { + css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt.GetUserData(); + OUString aTmp; + if ( aSeq.hasElements()) + aSeq[0].Value >>= aTmp; + OUString aWinData( aTmp ); + m_nUserCustomPageLeftMargin = aWinData.toInt32(); + bUserCustomValuesAvailable = true; + } + + SvtViewOptions aWinOpt2( EViewType::Window, SWPAGE_RIGHT_GVALUE ); + if ( aWinOpt2.Exists() ) + { + css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt2.GetUserData(); + OUString aTmp; + if ( aSeq.hasElements()) + aSeq[0].Value >>= aTmp; + OUString aWinData( aTmp ); + m_nUserCustomPageRightMargin = aWinData.toInt32(); + bUserCustomValuesAvailable = true; + } + + SvtViewOptions aWinOpt3( EViewType::Window, SWPAGE_TOP_GVALUE ); + if ( aWinOpt3.Exists() ) + { + css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt3.GetUserData(); + OUString aTmp; + if ( aSeq.hasElements() ) + aSeq[0].Value >>= aTmp; + OUString aWinData( aTmp ); + m_nUserCustomPageTopMargin = aWinData.toInt32(); + bUserCustomValuesAvailable = true; + } + + SvtViewOptions aWinOpt4( EViewType::Window, SWPAGE_DOWN_GVALUE ); + if ( aWinOpt4.Exists() ) + { + css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt4.GetUserData(); + OUString aTmp; + if ( aSeq.hasElements()) + aSeq[0].Value >>= aTmp; + OUString aWinData( aTmp ); + m_nUserCustomPageBottomMargin = aWinData.toInt32(); + bUserCustomValuesAvailable = true; + } + + SvtViewOptions aWinOpt5( EViewType::Window, SWPAGE_MIRROR_GVALUE ); + if ( aWinOpt5.Exists() ) + { + css::uno::Sequence < css::beans::NamedValue > aSeq = aWinOpt5.GetUserData(); + OUString aTmp; + if ( aSeq.hasElements()) + aSeq[0].Value >>= aTmp; + OUString aWinData( aTmp ); + m_bUserCustomMirrored = aWinData.toInt32() != 0; + bUserCustomValuesAvailable = true; + } + + return bUserCustomValuesAvailable; +} + +void PageMarginControl::StoreUserCustomValues() +{ + if ( !m_bCustomValuesUsed ) + { + return; + } + + css::uno::Sequence < css::beans::NamedValue > aSeq( 1 ); + auto pSeq = aSeq.getArray(); + SvtViewOptions aWinOpt( EViewType::Window, SWPAGE_LEFT_GVALUE ); + + pSeq[0].Name = "mnPageLeftMargin"; + pSeq[0].Value <<= OUString::number( m_nPageLeftMargin ); + aWinOpt.SetUserData( aSeq ); + + SvtViewOptions aWinOpt2( EViewType::Window, SWPAGE_RIGHT_GVALUE ); + pSeq[0].Name = "mnPageRightMargin"; + pSeq[0].Value <<= OUString::number( m_nPageRightMargin ); + aWinOpt2.SetUserData( aSeq ); + + SvtViewOptions aWinOpt3( EViewType::Window, SWPAGE_TOP_GVALUE ); + pSeq[0].Name = "mnPageTopMargin"; + pSeq[0].Value <<= OUString::number( m_nPageTopMargin ); + aWinOpt3.SetUserData( aSeq ); + + SvtViewOptions aWinOpt4( EViewType::Window, SWPAGE_DOWN_GVALUE ); + pSeq[0].Name = "mnPageBottomMargin"; + pSeq[0].Value <<= OUString::number( m_nPageBottomMargin ); + aWinOpt4.SetUserData( aSeq ); + + SvtViewOptions aWinOpt5( EViewType::Window, SWPAGE_MIRROR_GVALUE ); + pSeq[0].Name = "mbMirrored"; + pSeq[0].Value <<= OUString::number( m_bMirrored ? 1 : 0 ); + aWinOpt5.SetUserData( aSeq ); +} + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageMarginControl.hxx b/sw/source/uibase/sidebar/PageMarginControl.hxx new file mode 100644 index 0000000000..6cfb7b05bf --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginControl.hxx @@ -0,0 +1,114 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEMARGINCONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEMARGINCONTROL_HXX + +#include <sal/config.h> + +#include <o3tl/unit_conversion.hxx> +#include <svtools/toolbarmenu.hxx> + +#define SWPAGE_NARROW_VALUE 720 +#define SWPAGE_NORMAL_VALUE 1136 +#define SWPAGE_WIDE_VALUE1 1440 +#define SWPAGE_WIDE_VALUE2 2880 +#define SWPAGE_WIDE_VALUE3 1800 + +// #i19922# - tdf#126051 see cui/source/tabpages/page.cxx and svx/source/dialog/hdft.cxx +constexpr tools::Long MINBODY = o3tl::toTwips(1, o3tl::Length::mm); // 1mm in twips rounded + +class PageMarginPopup; + +namespace sw::sidebar { + +class PageMarginControl final : public WeldToolbarPopup +{ +public: + explicit PageMarginControl(PageMarginPopup* pControl, weld::Widget* pParent); + virtual void GrabFocus() override; + virtual ~PageMarginControl() override; + +private: + std::unique_ptr<weld::Button> m_xNarrow; + std::unique_ptr<weld::Button> m_xNormal; + std::unique_ptr<weld::Button> m_xWide; + std::unique_ptr<weld::Button> m_xMirrored; + std::unique_ptr<weld::Button> m_xLast; + std::unique_ptr<weld::Button> m_xMoreButton; + + std::unique_ptr<weld::Label> m_xLeft; + std::unique_ptr<weld::Label> m_xRight; + std::unique_ptr<weld::Label> m_xInner; + std::unique_ptr<weld::Label> m_xOuter; + + std::unique_ptr<weld::MetricSpinButton> m_xLeftMarginEdit; + std::unique_ptr<weld::MetricSpinButton> m_xRightMarginEdit; + std::unique_ptr<weld::MetricSpinButton> m_xTopMarginEdit; + std::unique_ptr<weld::MetricSpinButton> m_xBottomMarginEdit; + + // hidden metric field + std::unique_ptr<weld::MetricSpinButton> m_xWidthHeightField; + + rtl::Reference<PageMarginPopup> m_xControl; + + tools::Long m_nPageLeftMargin; + tools::Long m_nPageRightMargin; + tools::Long m_nPageTopMargin; + tools::Long m_nPageBottomMargin; + bool m_bMirrored; + + const MapUnit m_eUnit; + + Size m_aPageSize; + + bool m_bUserCustomValuesAvailable; + tools::Long m_nUserCustomPageLeftMargin; + tools::Long m_nUserCustomPageRightMargin; + tools::Long m_nUserCustomPageTopMargin; + tools::Long m_nUserCustomPageBottomMargin; + bool m_bUserCustomMirrored; + + bool m_bCustomValuesUsed; + + DECL_LINK( SelectMarginHdl, weld::Button&, void ); + DECL_LINK( ModifyLRMarginHdl, weld::MetricSpinButton&, void ); + DECL_LINK( ModifyULMarginHdl, weld::MetricSpinButton&, void ); + DECL_LINK(MoreButtonClickHdl_Impl, weld::Button&, void); + + static void ExecuteMarginLRChange( + const tools::Long nPageLeftMargin, + const tools::Long nPageRightMargin ); + static void ExecuteMarginULChange( + const tools::Long nPageTopMargin, + const tools::Long nPageBottomMargin ); + static void ExecutePageLayoutChange( const bool bMirrored ); + + void SetMetricFieldMaxValues(const Size& rPageSize); + + bool GetUserCustomValues(); + void StoreUserCustomValues(); + + void FillHelpText( const bool bUserCustomValuesAvailable ); +}; + +} // end of namespace sw::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageMarginPopup.cxx b/sw/source/uibase/sidebar/PageMarginPopup.cxx new file mode 100644 index 0000000000..67f13acc01 --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginPopup.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <PageMarginPopup.hxx> +#include "PageMarginControl.hxx" +#include <vcl/toolbox.hxx> + +PageMarginPopup::PageMarginPopup(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageMarginPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageMarginPopup::~PageMarginPopup() +{ +} + +std::unique_ptr<WeldToolbarPopup> PageMarginPopup::weldPopupWindow() +{ + return std::make_unique<sw::sidebar::PageMarginControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> PageMarginPopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<sw::sidebar::PageMarginControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageMarginPopup::getImplementationName() +{ + return "lo.writer.PageMarginToolBoxControl"; +} + +css::uno::Sequence<OUString> PageMarginPopup::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_PageMarginToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new PageMarginPopup(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageMarginUtils.hxx b/sw/source/uibase/sidebar/PageMarginUtils.hxx new file mode 100644 index 0000000000..ce7d5f65ee --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginUtils.hxx @@ -0,0 +1,194 @@ +/* -*- 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 <cmath> +#include <tools/long.hxx> + +#define SWPAGE_NO_MARGIN 0 +#define SWPAGE_NARROW_VALUE 720 +#define SWPAGE_MODERATE_LR 1080 +#define SWPAGE_NORMAL_VALUE 1136 +#define SWPAGE_WIDE_VALUE1 1440 +#define SWPAGE_WIDE_VALUE2 2880 +#define SWPAGE_WIDE_VALUE3 1800 +#define SWPAGE_UNIT_THRESHOLD 5 + +namespace sw::sidebar{ + +bool IsNone( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_NO_MARGIN) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_NO_MARGIN ) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_NO_MARGIN) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_NO_MARGIN) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetNone( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_NO_MARGIN; + nPageRightMargin = SWPAGE_NO_MARGIN; + nPageTopMargin = SWPAGE_NO_MARGIN; + nPageBottomMargin = SWPAGE_NO_MARGIN; + bMirrored = false; +} + +bool IsNarrow( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_NARROW_VALUE) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetNarrow( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_NARROW_VALUE; + nPageRightMargin = SWPAGE_NARROW_VALUE; + nPageTopMargin = SWPAGE_NARROW_VALUE; + nPageBottomMargin = SWPAGE_NARROW_VALUE; + bMirrored = false; +} + +bool IsModerate( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_MODERATE_LR) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_MODERATE_LR) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetModerate( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_MODERATE_LR; + nPageRightMargin = SWPAGE_MODERATE_LR; + nPageTopMargin = SWPAGE_WIDE_VALUE1; + nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = false; +} + +bool IsNormal075( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_NORMAL_VALUE) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetNormal075( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_NORMAL_VALUE; + nPageRightMargin = SWPAGE_NORMAL_VALUE; + nPageTopMargin = SWPAGE_NORMAL_VALUE; + nPageBottomMargin = SWPAGE_NORMAL_VALUE; + bMirrored = false; +} + +bool IsNormal100( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetNormal100( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_WIDE_VALUE1; + nPageRightMargin = SWPAGE_WIDE_VALUE1; + nPageTopMargin = SWPAGE_WIDE_VALUE1; + nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = false; +} + +bool IsNormal125( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE3) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE3) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetNormal125( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_WIDE_VALUE3; + nPageRightMargin = SWPAGE_WIDE_VALUE3; + nPageTopMargin = SWPAGE_WIDE_VALUE1; + nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = false; +} + +bool IsWide( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE2) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE2) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + !bMirrored ); +} + +void SetWide( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_WIDE_VALUE2; + nPageRightMargin = SWPAGE_WIDE_VALUE2; + nPageTopMargin = SWPAGE_WIDE_VALUE1; + nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = false; +} + +bool IsMirrored( const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin, + const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin, bool bMirrored) +{ + return( std::abs(nPageLeftMargin - SWPAGE_WIDE_VALUE3) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageRightMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageTopMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + std::abs(nPageBottomMargin - SWPAGE_WIDE_VALUE1) <= SWPAGE_UNIT_THRESHOLD && + bMirrored ); +} + +void SetMirrored( tools::Long& nPageLeftMargin, tools::Long& nPageRightMargin, + tools::Long& nPageTopMargin, tools::Long& nPageBottomMargin, bool& bMirrored) +{ + nPageLeftMargin = SWPAGE_WIDE_VALUE3; + nPageRightMargin = SWPAGE_WIDE_VALUE1; + nPageTopMargin = SWPAGE_WIDE_VALUE1; + nPageBottomMargin = SWPAGE_WIDE_VALUE1; + bMirrored = true; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageOrientationControl.cxx b/sw/source/uibase/sidebar/PageOrientationControl.cxx new file mode 100644 index 0000000000..6f0a45d268 --- /dev/null +++ b/sw/source/uibase/sidebar/PageOrientationControl.cxx @@ -0,0 +1,197 @@ +/* -*- 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 "PageOrientationControl.hxx" +#include "PageMarginControl.hxx" +#include <PageOrientationPopup.hxx> +#include <com/sun/star/document/XUndoManager.hpp> +#include <com/sun/star/document/XUndoManagerSupplier.hpp> +#include <com/sun/star/frame/XFrame.hpp> + +#include <sfx2/viewsh.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <cmdid.h> + +namespace { + css::uno::Reference< css::document::XUndoManager > getUndoManager( const css::uno::Reference< css::frame::XFrame >& rxFrame ) + { + const css::uno::Reference< css::frame::XController >& xController = rxFrame->getController(); + if ( xController.is() ) + { + const css::uno::Reference< css::frame::XModel >& xModel = xController->getModel(); + if ( xModel.is() ) + { + const css::uno::Reference< css::document::XUndoManagerSupplier > xSuppUndo( xModel, css::uno::UNO_QUERY_THROW ); + return css::uno::Reference< css::document::XUndoManager >( xSuppUndo->getUndoManager(), css::uno::UNO_SET_THROW ); + } + } + + return css::uno::Reference< css::document::XUndoManager > (); + } +} + +namespace sw::sidebar { + +PageOrientationControl::PageOrientationControl(PageOrientationPopup* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pageorientationcontrol.ui", "PageOrientationControl") + , m_xPortrait(m_xBuilder->weld_button("portrait")) + , m_xLandscape(m_xBuilder->weld_button("landscape")) + , m_xControl(pControl) + , mpPageItem( new SvxPageItem(SID_ATTR_PAGE) ) + , mpPageSizeItem( new SvxSizeItem(SID_ATTR_PAGE_SIZE) ) + , mpPageLRMarginItem( new SvxLongLRSpaceItem( 0, 0, SID_ATTR_PAGE_LRSPACE ) ) + , mpPageULMarginItem( new SvxLongULSpaceItem( 0, 0, SID_ATTR_PAGE_ULSPACE ) ) +{ + m_xPortrait->connect_clicked( LINK( this, PageOrientationControl,ImplOrientationHdl ) ); + m_xLandscape->connect_clicked( LINK( this, PageOrientationControl,ImplOrientationHdl ) ); +} + +void PageOrientationControl::GrabFocus() +{ + m_xPortrait->grab_focus(); +} + +PageOrientationControl::~PageOrientationControl() +{ +} + +void PageOrientationControl::ExecuteMarginLRChange( + const tools::Long nPageLeftMargin, + const tools::Long nPageRightMargin ) +{ + mpPageLRMarginItem->SetLeft( nPageLeftMargin ); + mpPageLRMarginItem->SetRight( nPageRightMargin ); + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_LRSPACE, + SfxCallMode::RECORD, { mpPageLRMarginItem.get() }); +} + +void PageOrientationControl::ExecuteMarginULChange( + const tools::Long nPageTopMargin, + const tools::Long nPageBottomMargin ) +{ + mpPageULMarginItem->SetUpper( nPageTopMargin ); + mpPageULMarginItem->SetLower( nPageBottomMargin ); + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_ULSPACE, + SfxCallMode::RECORD, { mpPageULMarginItem.get() }); +} + +void PageOrientationControl::ExecuteOrientationChange( const bool bLandscape ) +{ + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + if (!pViewFrm) + return; + + css::uno::Reference< css::document::XUndoManager > mxUndoManager( + getUndoManager( pViewFrm->GetFrame().GetFrameInterface() ) ); + + if ( mxUndoManager.is() ) + mxUndoManager->enterUndoContext( "" ); + + SfxPoolItemHolder aResult; + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult); + mpPageSizeItem.reset(static_cast<const SvxSizeItem*>(aResult.getItem())->Clone()); + + // Prevent accidental toggling of page orientation + if ((mpPageSizeItem->GetWidth() > mpPageSizeItem->GetHeight()) == bLandscape) + { + if ( mxUndoManager.is() ) + mxUndoManager->leaveUndoContext(); + return; + } + + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_LRSPACE, aResult); + mpPageLRMarginItem.reset(static_cast<const SvxLongLRSpaceItem*>(aResult.getItem())->Clone()); + + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_ULSPACE, aResult); + mpPageULMarginItem.reset(static_cast<const SvxLongULSpaceItem*>(aResult.getItem())->Clone()); + + { + // set new page orientation + mpPageItem->SetLandscape( bLandscape ); + + // swap the width and height of the page size + const tools::Long nRotatedWidth = mpPageSizeItem->GetSize().Height(); + const tools::Long nRotatedHeight = mpPageSizeItem->GetSize().Width(); + mpPageSizeItem->SetSize(Size(nRotatedWidth, nRotatedHeight)); + + // apply changed attributes + pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, + SfxCallMode::RECORD, { mpPageSizeItem.get(), mpPageItem.get() }); + } + + // check, if margin values still fit to the changed page size. + // if not, adjust margin values + { + const tools::Long nML = mpPageLRMarginItem->GetLeft(); + const tools::Long nMR = mpPageLRMarginItem->GetRight(); + const tools::Long nTmpPW = nML + nMR + MINBODY; + + const tools::Long nPW = mpPageSizeItem->GetSize().Width(); + + if ( nTmpPW > nPW ) + { + if ( nML <= nMR ) + { + ExecuteMarginLRChange( mpPageLRMarginItem->GetLeft(), nMR - (nTmpPW - nPW ) ); + } + else + { + ExecuteMarginLRChange( nML - (nTmpPW - nPW ), mpPageLRMarginItem->GetRight() ); + } + } + + const tools::Long nMT = mpPageULMarginItem->GetUpper(); + const tools::Long nMB = mpPageULMarginItem->GetLower(); + const tools::Long nTmpPH = nMT + nMB + MINBODY; + + const tools::Long nPH = mpPageSizeItem->GetSize().Height(); + + if ( nTmpPH > nPH ) + { + if ( nMT <= nMB ) + { + ExecuteMarginULChange( mpPageULMarginItem->GetUpper(), nMB - ( nTmpPH - nPH ) ); + } + else + { + ExecuteMarginULChange( nMT - ( nTmpPH - nPH ), mpPageULMarginItem->GetLower() ); + } + } + } + + if ( mxUndoManager.is() ) + mxUndoManager->leaveUndoContext(); +} + +IMPL_LINK(PageOrientationControl, ImplOrientationHdl, weld::Button&, rControl, void) +{ + if (&rControl == m_xPortrait.get()) + ExecuteOrientationChange( false ); + else + ExecuteOrientationChange( true ); + + m_xControl->EndPopupMode(); +} + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageOrientationControl.hxx b/sw/source/uibase/sidebar/PageOrientationControl.hxx new file mode 100644 index 0000000000..da82474b08 --- /dev/null +++ b/sw/source/uibase/sidebar/PageOrientationControl.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <memory> +#include <svtools/toolbarmenu.hxx> +#include <svx/pageitem.hxx> +#include <svx/rulritem.hxx> +#include <editeng/sizeitem.hxx> + +class PageOrientationPopup; + +namespace sw::sidebar { + +class PageOrientationControl final : public WeldToolbarPopup +{ +public: + explicit PageOrientationControl(PageOrientationPopup* pControl, weld::Widget* pParent); + virtual void GrabFocus() override; + virtual ~PageOrientationControl() override; + +private: + std::unique_ptr<weld::Button> m_xPortrait; + std::unique_ptr<weld::Button> m_xLandscape; + rtl::Reference<PageOrientationPopup> m_xControl; + + std::unique_ptr<SvxPageItem> mpPageItem; + std::unique_ptr<SvxSizeItem> mpPageSizeItem; + std::unique_ptr<SvxLongLRSpaceItem> mpPageLRMarginItem; + std::unique_ptr<SvxLongULSpaceItem> mpPageULMarginItem; + + void ExecuteMarginULChange(const tools::Long nPageTopMargin, const tools::Long nPageBottomMargin); + void ExecuteMarginLRChange(const tools::Long nPageLeftMargin, const tools::Long nPageRightMargin); + void ExecuteOrientationChange(const bool bLandscape); + + DECL_LINK(ImplOrientationHdl, weld::Button&, void); +}; + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageOrientationPopup.cxx b/sw/source/uibase/sidebar/PageOrientationPopup.cxx new file mode 100644 index 0000000000..ca506c83a6 --- /dev/null +++ b/sw/source/uibase/sidebar/PageOrientationPopup.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <PageOrientationPopup.hxx> +#include "PageOrientationControl.hxx" +#include <vcl/toolbox.hxx> + +PageOrientationPopup::PageOrientationPopup(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageOrientationPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageOrientationPopup::~PageOrientationPopup() +{ +} + +std::unique_ptr<WeldToolbarPopup> PageOrientationPopup::weldPopupWindow() +{ + return std::make_unique<sw::sidebar::PageOrientationControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> PageOrientationPopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<sw::sidebar::PageOrientationControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageOrientationPopup::getImplementationName() +{ + return "lo.writer.PageOrientationToolBoxControl"; +} + +css::uno::Sequence<OUString> PageOrientationPopup::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_PageOrientationToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new PageOrientationPopup(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageSizeControl.cxx b/sw/source/uibase/sidebar/PageSizeControl.cxx new file mode 100644 index 0000000000..4ea5995c09 --- /dev/null +++ b/sw/source/uibase/sidebar/PageSizeControl.cxx @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include "PageSizeControl.hxx" + +#include <cmdid.h> +#include <svx/pageitem.hxx> +#include <svx/sidebar/ValueSetWithTextControl.hxx> + +#include <unotools/localedatawrapper.hxx> +#include <rtl/character.hxx> +#include <editeng/paperinf.hxx> +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/module.hxx> +#include <sfx2/viewfrm.hxx> + +#include <vcl/settings.hxx> +#include <svl/itempool.hxx> +#include <svl/intitem.hxx> +#include <svtools/unitconv.hxx> +#include <editeng/sizeitem.hxx> + +#include <PageSizePopup.hxx> + +namespace +{ + FieldUnit lcl_GetFieldUnit() + { + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SfxPoolItemHolder aResult; + const SfxItemState eState(pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_METRIC, aResult)); + const SfxUInt16Item* pItem(static_cast<const SfxUInt16Item*>(aResult.getItem())); + + if (pItem && eState >= SfxItemState::DEFAULT) + return static_cast<FieldUnit>(pItem->GetValue()); + } + return SfxModule::GetCurrentFieldUnit(); + } + + MapUnit lcl_GetUnit() + { + SfxItemPool &rPool = SfxGetpApp()->GetPool(); + sal_uInt16 nWhich = rPool.GetWhich( SID_ATTR_PAGE_SIZE ); + return rPool.GetMetric( nWhich ); + } +} + +namespace sw::sidebar { + +PageSizeControl::PageSizeControl(PageSizePopup* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "modules/swriter/ui/pagesizecontrol.ui", "PageSizeControl") + , mxMoreButton(m_xBuilder->weld_button("moreoptions")) + , mxWidthHeightField(m_xBuilder->weld_metric_spin_button("metric", FieldUnit::CM)) + , mxSizeValueSet(new svx::sidebar::ValueSetWithTextControl) + , mxSizeValueSetWin(new weld::CustomWeld(*m_xBuilder, "pagesizevalueset", *mxSizeValueSet)) + , mxControl(pControl) +{ + mxWidthHeightField->set_unit(FieldUnit::CM); + mxWidthHeightField->set_range(0, 9999, FieldUnit::NONE); + mxWidthHeightField->set_digits(2); + mxWidthHeightField->set_increments(10, 100, FieldUnit::NONE); + SetFieldUnit( *mxWidthHeightField, lcl_GetFieldUnit() ); + + maPaperList.push_back( PAPER_A3 ); + maPaperList.push_back( PAPER_A4 ); + maPaperList.push_back( PAPER_A5 ); + maPaperList.push_back( PAPER_B4_ISO ); + maPaperList.push_back( PAPER_B5_ISO ); + maPaperList.push_back( PAPER_ENV_C5 ); + maPaperList.push_back( PAPER_LETTER ); + maPaperList.push_back( PAPER_LEGAL ); + + mxSizeValueSet->SetStyle( mxSizeValueSet->GetStyle() | WB_3DLOOK | WB_NO_DIRECTSELECT ); + mxSizeValueSet->SetColor( Application::GetSettings().GetStyleSettings().GetMenuColor() ); + + sal_uInt16 nSelectedItem = 0; + { + OUString aMetricStr; + { + const OUString aText = mxWidthHeightField->get_text(); + for (short i = aText.getLength() - 1; i >= 0; i--) + { + sal_Unicode c = aText[i]; + if ( rtl::isAsciiAlpha(c) || (c == '\'') || (c == '\"') || (c == '%') ) + { + aMetricStr = OUStringChar(c) + aMetricStr; + } + else + { + if (!aMetricStr.isEmpty()) + { + break; + } + } + } + } + + bool bLandscape = false; + const SvxSizeItem* pSize(nullptr); + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + { + SfxPoolItemHolder aResult; + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult ); + bLandscape = static_cast<const SvxPageItem*>(aResult.getItem())->IsLandscape(); + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult); + pSize = static_cast<const SvxSizeItem*>(aResult.getItem()); + } + + const LocaleDataWrapper& localeDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); + OUString aWidthStr; + OUString aHeightStr; + OUString aItemText2; + for ( std::vector< Paper >::size_type nPaperIdx = 0; + nPaperIdx < maPaperList.size(); + ++nPaperIdx ) + { + Size aPaperSize = SvxPaperInfo::GetPaperSize( maPaperList[ nPaperIdx ] ); + if ( bLandscape ) + { + Swap( aPaperSize ); + } + + mxWidthHeightField->set_value( mxWidthHeightField->normalize( aPaperSize.Width() ), FieldUnit::TWIP ); + aWidthStr = localeDataWrapper.getNum( + mxWidthHeightField->get_value(FieldUnit::NONE), + mxWidthHeightField->get_digits(), + true, + true ); + + mxWidthHeightField->set_value( mxWidthHeightField->normalize( aPaperSize.Height() ), FieldUnit::TWIP); + aHeightStr = localeDataWrapper.getNum( + mxWidthHeightField->get_value(FieldUnit::NONE), + mxWidthHeightField->get_digits(), + true, + true ); + + aItemText2 = aWidthStr + " x " + aHeightStr + " " + aMetricStr; + + mxSizeValueSet->AddItem( + SvxPaperInfo::GetName( maPaperList[ nPaperIdx ] ), + aItemText2 ); + + if ( pSize && aPaperSize == pSize->GetSize() ) + { + nSelectedItem = nPaperIdx + 1; + } + } + } + mxSizeValueSet->SetNoSelection(); + mxSizeValueSet->SetSelectHdl( LINK(this, PageSizeControl, ImplSizeHdl ) ); + mxSizeValueSet->SetOptimalDrawingAreaHeight(); + mxSizeValueSet->Show(); + mxSizeValueSet->Resize(); + + mxSizeValueSet->SelectItem( nSelectedItem ); + mxSizeValueSet->SetFormat(); + mxSizeValueSet->Invalidate(); + + mxMoreButton->connect_clicked( LINK( this, PageSizeControl, MoreButtonClickHdl_Impl ) ); + mxMoreButton->grab_focus(); +} + +void PageSizeControl::GrabFocus() +{ + mxSizeValueSet->GrabFocus(); +} + +PageSizeControl::~PageSizeControl() +{ +} + +void PageSizeControl::ExecuteSizeChange( const Paper ePaper ) +{ + bool bLandscape = false; + MapUnit eUnit = lcl_GetUnit(); + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + if (!pViewFrm) + return; + + SfxPoolItemHolder aResult; + pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE, aResult); + const SvxPageItem* pItem(static_cast<const SvxPageItem*>(aResult.getItem())); + bLandscape = pItem->IsLandscape(); + + SvxSizeItem aPageSizeItem(SID_ATTR_PAGE_SIZE); + Size aPageSize = SvxPaperInfo::GetPaperSize( ePaper, eUnit ); + if ( bLandscape ) + { + Swap( aPageSize ); + } + aPageSizeItem.SetSize( aPageSize ); + + pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, + SfxCallMode::RECORD, { &aPageSizeItem }); +} + + +IMPL_LINK_NOARG(PageSizeControl, ImplSizeHdl, ValueSet*, void) +{ + mxSizeValueSet->SetNoSelection(); + const sal_uInt16 nSelectedPaper = mxSizeValueSet->GetSelectedItemId(); + const Paper ePaper = maPaperList[nSelectedPaper - 1]; + ExecuteSizeChange( ePaper ); + + mxControl->EndPopupMode(); +} + +IMPL_LINK_NOARG(PageSizeControl, MoreButtonClickHdl_Impl, weld::Button&, void) +{ + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetDispatcher()->Execute( FN_FORMAT_PAGE_SETTING_DLG, SfxCallMode::ASYNCHRON ); + mxControl->EndPopupMode(); +} + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageSizeControl.hxx b/sw/source/uibase/sidebar/PageSizeControl.hxx new file mode 100644 index 0000000000..bbeaa1b198 --- /dev/null +++ b/sw/source/uibase/sidebar/PageSizeControl.hxx @@ -0,0 +1,65 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESIZECONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESIZECONTROL_HXX + +#include <i18nutil/paper.hxx> + +#include <svtools/toolbarmenu.hxx> +#include <svtools/valueset.hxx> + +#include <vector> + +namespace svx::sidebar +{ +class ValueSetWithTextControl; +} +class PageSizePopup; +class ValueSet; + +namespace sw::sidebar +{ +class PageSizeControl final : public WeldToolbarPopup +{ +public: + explicit PageSizeControl(PageSizePopup* pControl, weld::Widget* pParent); + virtual void GrabFocus() override; + virtual ~PageSizeControl() override; + +private: + std::unique_ptr<weld::Button> mxMoreButton; + // hidden metric field + std::unique_ptr<weld::MetricSpinButton> mxWidthHeightField; + std::unique_ptr<svx::sidebar::ValueSetWithTextControl> mxSizeValueSet; + std::unique_ptr<weld::CustomWeld> mxSizeValueSetWin; + rtl::Reference<PageSizePopup> mxControl; + + std::vector<Paper> maPaperList; + + static void ExecuteSizeChange(const Paper ePaper); + + DECL_LINK(ImplSizeHdl, ValueSet*, void); + DECL_LINK(MoreButtonClickHdl_Impl, weld::Button&, void); +}; + +} // end of namespace sw::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageSizePopup.cxx b/sw/source/uibase/sidebar/PageSizePopup.cxx new file mode 100644 index 0000000000..7e2f7e7a4f --- /dev/null +++ b/sw/source/uibase/sidebar/PageSizePopup.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <PageSizePopup.hxx> +#include "PageSizeControl.hxx" +#include <vcl/toolbox.hxx> + +PageSizePopup::PageSizePopup(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageSizePopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageSizePopup::~PageSizePopup() +{ +} + +std::unique_ptr<WeldToolbarPopup> PageSizePopup::weldPopupWindow() +{ + return std::make_unique<sw::sidebar::PageSizeControl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> PageSizePopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<sw::sidebar::PageSizeControl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageSizePopup::getImplementationName() +{ + return "lo.writer.PageSizeToolBoxControl"; +} + +css::uno::Sequence<OUString> PageSizePopup::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_PageSizeToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new PageSizePopup(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageStylesPanel.cxx b/sw/source/uibase/sidebar/PageStylesPanel.cxx new file mode 100644 index 0000000000..53cf43fb74 --- /dev/null +++ b/sw/source/uibase/sidebar/PageStylesPanel.cxx @@ -0,0 +1,619 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <sal/config.h> +#include <svl/intitem.hxx> +#include <svx/colorbox.hxx> +#include <svx/drawitem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/itemwin.hxx> +#include <svx/SvxNumOptionsTabPageHelper.hxx> +#include "PageStylesPanel.hxx" +#include <sfx2/sidebar/Panel.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/objsh.hxx> +#include <cmdid.h> + +using namespace ::com::sun::star; + +namespace sw::sidebar{ + +namespace { + +enum eFillStyle +{ + NONE, + SOLID, + GRADIENT, + HATCH, + BITMAP, + PATTERN +}; + +} + +const SvxPageUsage aArr[] = +{ + SvxPageUsage::All, + SvxPageUsage::Mirror, + SvxPageUsage::Right, + SvxPageUsage::Left +}; + + +static sal_uInt16 PageUsageToPos_Impl( SvxPageUsage nUsage ) +{ + for ( size_t i = 0; i < SAL_N_ELEMENTS(aArr); ++i ) + if ( aArr[i] == nUsage ) + return i; + return 3; +} + +static SvxPageUsage PosToPageUsage_Impl( sal_uInt16 nPos ) +{ + if ( nPos >= SAL_N_ELEMENTS(aArr) ) + return SvxPageUsage::NONE; + return aArr[nPos]; +} + +std::unique_ptr<PanelLayout> PageStylesPanel::Create(weld::Widget* pParent, SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageStylesPanel::Create", nullptr, 0); + if( pBindings == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no SfxBindings given to PageStylesPanel::Create", nullptr, 0); + + return std::make_unique<PageStylesPanel>(pParent, pBindings); +} + +PageStylesPanel::PageStylesPanel( + weld::Widget* pParent, + SfxBindings* pBindings + ) : + PanelLayout(pParent, "PageStylesPanel", "modules/swriter/ui/pagestylespanel.ui"), + mpBindings( pBindings ), + mpPageColumnItem( new SfxInt16Item(SID_ATTR_PAGE_COLUMN) ), + mpPageItem( new SvxPageItem(SID_ATTR_PAGE) ), + maPageColumnControl(SID_ATTR_PAGE_COLUMN, *pBindings, *this), + maPageNumFormatControl( SID_ATTR_PAGE, *pBindings, *this ), + maBgColorControl( SID_ATTR_PAGE_COLOR, *pBindings, *this ), + maBgHatchingControl( SID_ATTR_PAGE_HATCH, *pBindings, *this ), + maBgGradientControl( SID_ATTR_PAGE_GRADIENT, *pBindings, *this ), + maBgBitmapControl( SID_ATTR_PAGE_BITMAP, *pBindings, *this ), + maBgFillStyleControl(SID_ATTR_PAGE_FILLSTYLE, *pBindings, *this), + mxBgColorLB(new ColorListBox(m_xBuilder->weld_menu_button("lbcolor"), [this]{ return GetFrameWeld(); })), + mxBgHatchingLB(m_xBuilder->weld_combo_box("lbhatching")), + mxBgGradientLB(new ColorListBox(m_xBuilder->weld_menu_button("lbgradient"), [this]{ return GetFrameWeld(); })), + mxBgBitmapLB(m_xBuilder->weld_combo_box("lbbitmap")), + mxLayoutSelectLB(m_xBuilder->weld_combo_box("layoutbox")), + mxColumnCount(m_xBuilder->weld_combo_box("columnbox")), + mxNumberSelectLB(new SvxPageNumberListBox(m_xBuilder->weld_combo_box("numberbox"))), + mxBgFillType(m_xBuilder->weld_combo_box("bgselect")), + mxCustomEntry(m_xBuilder->weld_label("customlabel")) +{ + Initialize(); +} + +PageStylesPanel::~PageStylesPanel() +{ + mxColumnCount.reset(); + mxNumberSelectLB.reset(); + mxBgFillType.reset(); + mxBgColorLB.reset(); + mxBgHatchingLB.reset(); + mxBgGradientLB.reset(); + mxBgBitmapLB.reset(); + mxLayoutSelectLB.reset(); + mxCustomEntry.reset(); + + maBgBitmapControl.dispose(); + maBgColorControl.dispose(); + maBgFillStyleControl.dispose(); + maBgGradientControl.dispose(); + maBgHatchingControl.dispose(); + maPageColumnControl.dispose(); + maPageNumFormatControl.dispose(); +} + +void PageStylesPanel::Initialize() +{ + SvxFillTypeBox::Fill(*mxBgFillType); + + m_aCustomEntry = mxCustomEntry->get_label(); + mpBindings->Invalidate(SID_ATTR_PAGE_COLUMN); + mpBindings->Invalidate(SID_ATTR_PAGE); + mpBindings->Invalidate(SID_ATTR_PAGE_FILLSTYLE); + Update(); + + mxColumnCount->connect_changed( LINK(this, PageStylesPanel, ModifyColumnCountHdl) ); + SvxNumOptionsTabPageHelper::GetI18nNumbering(mxNumberSelectLB->get_widget(), ::std::numeric_limits<sal_uInt16>::max()); + mxNumberSelectLB->connect_changed( LINK(this, PageStylesPanel, ModifyNumberingHdl) ); + mxLayoutSelectLB->connect_changed( LINK(this, PageStylesPanel, ModifyLayoutHdl) ); + mxBgFillType->connect_changed( LINK(this, PageStylesPanel, ModifyFillStyleHdl)); + mxBgColorLB->SetSelectHdl( LINK(this, PageStylesPanel, ModifyFillColorListHdl)); + mxBgGradientLB->SetSelectHdl( LINK(this, PageStylesPanel, ModifyFillColorListHdl)); + mxBgHatchingLB->connect_changed( LINK(this, PageStylesPanel, ModifyFillColorHdl)); + mxBgBitmapLB->connect_changed( LINK(this, PageStylesPanel, ModifyFillColorHdl)); +} + +void PageStylesPanel::Update() +{ + const eFillStyle eXFS = static_cast<eFillStyle>(mxBgFillType->get_active()); + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (!pSh) + { + SAL_WARN("sw.ui", "PageStylesPanel::Update(): no SfxObjectShell found"); + return; + } + switch(eXFS) + { + case NONE: + { + mxBgColorLB->hide(); + mxBgHatchingLB->hide(); + mxBgGradientLB->hide(); + mxBgBitmapLB->hide(); + } + break; + case SOLID: + { + mxBgBitmapLB->hide(); + mxBgGradientLB->hide(); + mxBgHatchingLB->hide(); + mxBgColorLB->show(); + const Color aColor = GetColorSetOrDefault(); + mxBgColorLB->SelectEntry(aColor); + } + break; + case GRADIENT: + { + mxBgBitmapLB->hide(); + mxBgHatchingLB->hide(); + mxBgColorLB->show(); + mxBgGradientLB->show(); + + const basegfx::BGradient aBGradient = GetGradientSetOrDefault(); + const Color aStartColor(aBGradient.GetColorStops().front().getStopColor()); + mxBgColorLB->SelectEntry(aStartColor); + const Color aEndColor(aBGradient.GetColorStops().back().getStopColor()); + mxBgGradientLB->SelectEntry(aEndColor); + } + break; + + case HATCH: + { + mxBgColorLB->hide(); + mxBgGradientLB->hide(); + mxBgBitmapLB->hide(); + mxBgHatchingLB->show(); + mxBgHatchingLB->clear(); + SvxFillAttrBox::Fill(*mxBgHatchingLB, pSh->GetItem(SID_HATCH_LIST)->GetHatchList()); + + const OUString aHatchName = GetHatchingSetOrDefault(); + mxBgHatchingLB->set_active_text( aHatchName ); + } + break; + + case BITMAP: + case PATTERN: + { + mxBgColorLB->hide(); + mxBgGradientLB->hide(); + mxBgHatchingLB->hide(); + mxBgBitmapLB->show(); + mxBgBitmapLB->clear(); + OUString aBitmapName; + + if( eXFS == BITMAP ) + { + SvxFillAttrBox::Fill(*mxBgBitmapLB, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList()); + aBitmapName = GetBitmapSetOrDefault(); + } + else + { + SvxFillAttrBox::Fill(*mxBgBitmapLB, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList()); + aBitmapName = GetPatternSetOrDefault(); + } + + mxBgBitmapLB->set_active_text( aBitmapName ); + } + break; + + default: + break; + } + + // Need to do a relayouting, otherwise the panel size is not updated after show / hide controls + if (m_pPanel) + m_pPanel->TriggerDeckLayouting(); +} + +Color const & PageStylesPanel::GetColorSetOrDefault() +{ + if ( !mpBgColorItem ) + mpBgColorItem.reset( new XFillColorItem( OUString(), Color(0x72, 0x9f, 0xcf) ) ); + + return mpBgColorItem->GetColorValue(); +} + +basegfx::BGradient const & PageStylesPanel::GetGradientSetOrDefault() +{ + if( !mpBgGradientItem ) + { + basegfx::BGradient aGradient; + OUString aGradientName; + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + { + const SvxGradientListItem* pGradListItem = pSh->GetItem(SID_GRADIENT_LIST); + aGradient = pGradListItem->GetGradientList()->GetGradient(0)->GetGradient(); + aGradientName = pGradListItem->GetGradientList()->GetGradient(0)->GetName(); + } + mpBgGradientItem.reset( new XFillGradientItem( aGradientName, aGradient ) ); + } + + return mpBgGradientItem->GetGradientValue(); +} + +OUString const & PageStylesPanel::GetHatchingSetOrDefault() +{ + if( !mpBgHatchItem ) + { + XHatch aHatch; + OUString aHatchName; + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + { + const SvxHatchListItem * pHatchListItem = pSh->GetItem(SID_HATCH_LIST); + aHatch = pHatchListItem->GetHatchList()->GetHatch(0)->GetHatch(); + aHatchName = pHatchListItem->GetHatchList()->GetHatch(0)->GetName(); + } + mpBgHatchItem.reset( new XFillHatchItem( aHatchName, aHatch ) ); + } + + return mpBgHatchItem->GetName(); +} + +OUString const & PageStylesPanel::GetBitmapSetOrDefault() +{ + if( !mpBgBitmapItem || mpBgBitmapItem->isPattern() ) + { + GraphicObject aGraphObj; + OUString aBmpName; + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + { + const SvxBitmapListItem * pBmpListItem = pSh->GetItem(SID_BITMAP_LIST); + aGraphObj = pBmpListItem->GetBitmapList()->GetBitmap(0)->GetGraphicObject(); + aBmpName = pBmpListItem->GetBitmapList()->GetBitmap(0)->GetName(); + } + mpBgBitmapItem.reset( new XFillBitmapItem( aBmpName, aGraphObj ) ); + } + + return mpBgBitmapItem->GetName(); +} + +OUString const & PageStylesPanel::GetPatternSetOrDefault() +{ + if( !mpBgBitmapItem || !mpBgBitmapItem->isPattern() ) + { + GraphicObject aGraphObj; + OUString aPatternName; + if (SfxObjectShell* pSh = SfxObjectShell::Current()) + { + const SvxPatternListItem * pPatternListItem = pSh->GetItem(SID_PATTERN_LIST); + aGraphObj = pPatternListItem->GetPatternList()->GetBitmap(0)->GetGraphicObject(); + aPatternName = pPatternListItem->GetPatternList()->GetBitmap(0)->GetName(); + } + mpBgBitmapItem.reset( new XFillBitmapItem( aPatternName, aGraphObj ) ); + } + + return mpBgBitmapItem->GetName(); +} + +void PageStylesPanel::NotifyItemUpdate( + const sal_uInt16 nSid, + const SfxItemState eState, + const SfxPoolItem* pState) +{ + if (!mxColumnCount) //disposed + return; + + switch(nSid) + { + case SID_ATTR_PAGE_COLUMN: + { + if ( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SfxInt16Item *>( pState ) ) + { + mpPageColumnItem.reset( static_cast<SfxInt16Item*>(pState->Clone()) ); + if(mpPageColumnItem->GetValue() <= 5) + { + mxColumnCount->set_active(mpPageColumnItem->GetValue() - 1); + int nIndex = mxColumnCount->find_text(m_aCustomEntry); + if (nIndex != -1) + mxColumnCount->remove(nIndex); + } + else + { + if (mxColumnCount->find_text(m_aCustomEntry) == -1) + mxColumnCount->append_text(m_aCustomEntry); + mxColumnCount->set_active_text(m_aCustomEntry); + } + } + } + break; + + case SID_ATTR_PAGE: + { + if( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SvxPageItem*>( pState ) ) + { + mpPageItem.reset( static_cast<SvxPageItem*>(pState->Clone()) ); + SvxNumType eNumType = mpPageItem->GetNumType(); + mxNumberSelectLB->set_active_id(eNumType); + + SvxPageUsage nUse = mpPageItem->GetPageUsage(); + mxLayoutSelectLB->set_active( PageUsageToPos_Impl( nUse ) ); + } + } + break; + + case SID_ATTR_PAGE_COLOR: + { + if(eState >= SfxItemState::DEFAULT) + { + mxBgFillType->set_active( static_cast<sal_Int32>(SOLID) ); + mpBgColorItem.reset(pState ? static_cast< XFillColorItem* >(pState->Clone()) : nullptr); + Update(); + } + } + break; + + case SID_ATTR_PAGE_HATCH: + { + if(eState >= SfxItemState::DEFAULT) + { + mxBgFillType->set_active( static_cast<sal_Int32>(HATCH) ); + mpBgHatchItem.reset(pState ? static_cast < XFillHatchItem* >(pState->Clone()) : nullptr); + Update(); + } + } + break; + + case SID_ATTR_PAGE_GRADIENT: + { + if(eState >= SfxItemState::DEFAULT) + { + mxBgFillType->set_active( static_cast<sal_Int32>(GRADIENT) ); + mpBgGradientItem.reset(pState ? static_cast< XFillGradientItem* >(pState->Clone()) : nullptr); + Update(); + } + } + break; + case SID_ATTR_PAGE_BITMAP: + { + if(eState >= SfxItemState::DEFAULT) + { + mpBgBitmapItem.reset(pState ? static_cast< XFillBitmapItem* >(pState->Clone()) : nullptr); + if (mpBgBitmapItem) + { + if (mpBgBitmapItem->isPattern()) + mxBgFillType->set_active( static_cast<sal_Int32>(PATTERN) ); + else + mxBgFillType->set_active( static_cast<sal_Int32>(BITMAP) ); + } + Update(); + } + } + break; + + case SID_ATTR_PAGE_FILLSTYLE: + { + const XFillStyleItem* pFillStyleItem = nullptr; + if (eState >= SfxItemState::DEFAULT) + pFillStyleItem = dynamic_cast< const XFillStyleItem* >(pState); + if (pFillStyleItem) + { + css::drawing::FillStyle eXFS = pFillStyleItem->GetValue(); + switch(eXFS) + { + case drawing::FillStyle_NONE: + mxBgFillType->set_active( static_cast<sal_Int32>(NONE) ); + break; + case drawing::FillStyle_SOLID: + mxBgFillType->set_active( static_cast<sal_Int32>(SOLID) ); + break; + case drawing::FillStyle_GRADIENT: + mxBgFillType->set_active( static_cast<sal_Int32>(GRADIENT) ); + break; + case drawing::FillStyle_HATCH: + mxBgFillType->set_active( static_cast<sal_Int32>(HATCH) ); + break; + case drawing::FillStyle_BITMAP: + if (mpBgBitmapItem->isPattern()) + mxBgFillType->set_active( static_cast<sal_Int32>(PATTERN) ); + else + mxBgFillType->set_active( static_cast<sal_Int32>(BITMAP) ); + break; + default: + break; + } + Update(); + } + } + break; + + default: + break; + } +} + +IMPL_LINK_NOARG( PageStylesPanel, ModifyColumnCountHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nColumnType = mxColumnCount->get_active() + 1; + mpPageColumnItem->SetValue( nColumnType ); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLUMN, + SfxCallMode::RECORD, { mpPageColumnItem.get() }); +} + +IMPL_LINK_NOARG( PageStylesPanel, ModifyNumberingHdl, weld::ComboBox&, void ) +{ + SvxNumType nEntryData = mxNumberSelectLB->get_active_id(); + mpPageItem->SetNumType(nEntryData); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE, SfxCallMode::RECORD, { mpPageItem.get() }); +} + +IMPL_LINK_NOARG( PageStylesPanel, ModifyLayoutHdl, weld::ComboBox&, void ) +{ + sal_uInt16 nUse = mxLayoutSelectLB->get_active(); + mpPageItem->SetPageUsage(PosToPageUsage_Impl(nUse)); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_PAGE, SfxCallMode::RECORD, { mpPageItem.get() }); +} + +IMPL_LINK_NOARG(PageStylesPanel, ModifyFillStyleHdl, weld::ComboBox&, void) +{ + const eFillStyle eXFS = static_cast<eFillStyle>(mxBgFillType->get_active()); + Update(); + + switch (eXFS) + { + case NONE: + { + const XFillStyleItem aXFillStyleItem(drawing::FillStyle_NONE); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_FILLSTYLE, SfxCallMode::RECORD, { &aXFillStyleItem }); + } + break; + + case SOLID: + { + XFillColorItem aItem( OUString(), mpBgColorItem->GetColorValue() ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLOR, SfxCallMode::RECORD, { &aItem }); + } + break; + + case GRADIENT: + { + XFillGradientItem aItem( mpBgGradientItem->GetName(), mpBgGradientItem->GetGradientValue() ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_GRADIENT, SfxCallMode::RECORD, { &aItem }); + } + break; + + case HATCH: + { + XFillHatchItem aItem( mpBgHatchItem->GetName(), mpBgHatchItem->GetHatchValue() ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_HATCH, SfxCallMode::RECORD, { &aItem }); + } + break; + + case BITMAP: + case PATTERN: + { + XFillBitmapItem aItem( mpBgBitmapItem->GetName(), mpBgBitmapItem->GetGraphicObject() ); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_BITMAP, SfxCallMode::RECORD, { &aItem }); + } + break; + + default: + break; + } +} + +void PageStylesPanel::ModifyFillColor() +{ + const eFillStyle eXFS = static_cast<eFillStyle>(mxBgFillType->get_active()); + SfxObjectShell* pSh = SfxObjectShell::Current(); + switch(eXFS) + { + case SOLID: + { + auto aNamedColor = mxBgColorLB->GetSelectedEntry(); + XFillColorItem aItem(OUString(), aNamedColor.m_aColor); + aItem.setComplexColor(aNamedColor.getComplexColor()); + aItem.setComplexColor(mxBgColorLB->GetSelectedEntry().getComplexColor()); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLOR, SfxCallMode::RECORD, { &aItem }); + } + break; + case GRADIENT: + { + basegfx::BGradient aGradient( + basegfx::BColorStops( + mxBgColorLB->GetSelectEntryColor().getBColor(), + mxBgGradientLB->GetSelectEntryColor().getBColor())); + + XFillGradientItem aItem(aGradient); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_GRADIENT, SfxCallMode::RECORD, { &aItem }); + } + break; + case HATCH: + if (pSh) + { + const SvxHatchListItem * pHatchListItem = pSh->GetItem(SID_HATCH_LIST); + sal_uInt16 nPos = mxBgHatchingLB->get_active(); + XHatch aHatch = pHatchListItem->GetHatchList()->GetHatch(nPos)->GetHatch(); + const OUString aHatchName = pHatchListItem->GetHatchList()->GetHatch(nPos)->GetName(); + + XFillHatchItem aItem(aHatchName, aHatch); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_HATCH, SfxCallMode::RECORD, { &aItem }); + } + break; + case BITMAP: + case PATTERN: + if (pSh) + { + sal_Int16 nPos = mxBgBitmapLB->get_active(); + GraphicObject aBitmap; + OUString aBitmapName; + + if ( eXFS == BITMAP ) + { + SvxBitmapListItem const * pBitmapListItem = pSh->GetItem(SID_BITMAP_LIST); + aBitmap = pBitmapListItem->GetBitmapList()->GetBitmap(nPos)->GetGraphicObject(); + aBitmapName = pBitmapListItem->GetBitmapList()->GetBitmap(nPos)->GetName(); + } + else + { + SvxPatternListItem const * pPatternListItem = pSh->GetItem(SID_PATTERN_LIST); + aBitmap = pPatternListItem->GetPatternList()->GetBitmap(nPos)->GetGraphicObject(); + aBitmapName = pPatternListItem->GetPatternList()->GetBitmap(nPos)->GetName(); + } + + XFillBitmapItem aItem(aBitmapName, aBitmap); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_BITMAP, SfxCallMode::RECORD, { &aItem }); + } + break; + default: + break; + } +} + +IMPL_LINK_NOARG(PageStylesPanel, ModifyFillColorHdl, weld::ComboBox&, void) +{ + ModifyFillColor(); +} + +IMPL_LINK_NOARG(PageStylesPanel, ModifyFillColorListHdl, ColorListBox&, void) +{ + ModifyFillColor(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageStylesPanel.hxx b/sw/source/uibase/sidebar/PageStylesPanel.hxx new file mode 100644 index 0000000000..5395b2784e --- /dev/null +++ b/sw/source/uibase/sidebar/PageStylesPanel.hxx @@ -0,0 +1,115 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESTYLESPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESTYLESPANEL_HXX + +#include <memory> + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <svl/intitem.hxx> +#include <svl/poolitem.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/pageitem.hxx> +#include <svx/pagenumberlistbox.hxx> + +class List; +class ColorListBox; +namespace sw::sidebar { + +class PageStylesPanel: + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + SfxBindings* pBindings); + + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + SfxBindings* GetBindings() const { return mpBindings; } + PageStylesPanel( + weld::Widget* pParent, + SfxBindings* pBindings); + virtual ~PageStylesPanel() override; + +private: + + SfxBindings* mpBindings; + + ::std::unique_ptr<SfxInt16Item> mpPageColumnItem; + ::std::unique_ptr<SvxPageItem> mpPageItem; + ::std::unique_ptr<XFillColorItem> mpBgColorItem; + ::std::unique_ptr<XFillGradientItem> mpBgGradientItem; + ::std::unique_ptr<XFillHatchItem> mpBgHatchItem; + ::std::unique_ptr<XFillBitmapItem> mpBgBitmapItem; + + ::sfx2::sidebar::ControllerItem maPageColumnControl; + ::sfx2::sidebar::ControllerItem maPageNumFormatControl; + ::sfx2::sidebar::ControllerItem maBgColorControl; + ::sfx2::sidebar::ControllerItem maBgHatchingControl; + ::sfx2::sidebar::ControllerItem maBgGradientControl; + ::sfx2::sidebar::ControllerItem maBgBitmapControl; + ::sfx2::sidebar::ControllerItem maBgFillStyleControl; + + std::unique_ptr<ColorListBox> mxBgColorLB; + std::unique_ptr<weld::ComboBox> mxBgHatchingLB; + std::unique_ptr<ColorListBox> mxBgGradientLB; + std::unique_ptr<weld::ComboBox> mxBgBitmapLB; + std::unique_ptr<weld::ComboBox> mxLayoutSelectLB; + std::unique_ptr<weld::ComboBox> mxColumnCount; + std::unique_ptr<SvxPageNumberListBox> mxNumberSelectLB; + std::unique_ptr<weld::ComboBox> mxBgFillType; + std::unique_ptr<weld::Label> mxCustomEntry; + OUString m_aCustomEntry; + + void Initialize(); + void Update(); + Color const & GetColorSetOrDefault(); + basegfx::BGradient const & GetGradientSetOrDefault(); + OUString const & GetHatchingSetOrDefault(); + OUString const & GetBitmapSetOrDefault(); + OUString const & GetPatternSetOrDefault(); + + void ModifyFillColor(); + + DECL_LINK( ModifyColumnCountHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyNumberingHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyLayoutHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyFillStyleHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyFillColorHdl, weld::ComboBox&, void ); + DECL_LINK( ModifyFillColorListHdl, ColorListBox&, void ); +}; + +} //end of namespace sw::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/StylePresetsPanel.cxx b/sw/source/uibase/sidebar/StylePresetsPanel.cxx new file mode 100644 index 0000000000..ff05d11cfe --- /dev/null +++ b/sw/source/uibase/sidebar/StylePresetsPanel.cxx @@ -0,0 +1,205 @@ +/* -*- 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/. + * + */ + +#include <sal/config.h> + +#include "StylePresetsPanel.hxx" + +#include <vcl/image.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> + +#include <sfx2/objsh.hxx> +#include <sfx2/StylePreviewRenderer.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <sfx2/doctempl.hxx> + +#include <shellio.hxx> +#include <docsh.hxx> + +#include <sfx2/docfile.hxx> + +namespace sw::sidebar { + +namespace { + +void renderPreview(sfx2::StyleManager* pStyleManager, OutputDevice& aOutputDevice, + std::u16string_view sName, sal_Int32 nHeight, tools::Rectangle const & aRect) +{ + SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(sName, SfxStyleFamily::Para); + + if (pStyleSheet) + { + std::unique_ptr<sfx2::StylePreviewRenderer> pStylePreviewRenderer + = pStyleManager->CreateStylePreviewRenderer(aOutputDevice, pStyleSheet, nHeight); + pStylePreviewRenderer->recalculate(); + pStylePreviewRenderer->render(aRect, sfx2::StylePreviewRenderer::RenderAlign::TOP); + } +} + +BitmapEx GenerateStylePreview(SfxObjectShell& rSource, OUString const & aName) +{ + sfx2::StyleManager* pStyleManager = rSource.GetStyleManager(); + + ScopedVclPtrInstance<VirtualDevice> pVirtualDev(*Application::GetDefaultDevice()); + + float fScalingFactor = pVirtualDev->GetDPIScaleFactor(); + + sal_Int32 nMargin = 6 * fScalingFactor; + + sal_Int32 nPreviewWidth = 144 * fScalingFactor; + + sal_Int32 nNameHeight = 16 * fScalingFactor; + sal_Int32 nTitleHeight = 32 * fScalingFactor; + sal_Int32 nHeadingHeight = 24 * fScalingFactor; + sal_Int32 nTextBodyHeight = 16 * fScalingFactor; + sal_Int32 nBottomMargin = 2 * fScalingFactor; + + sal_Int32 nNameFontSize = 12 * fScalingFactor; + + sal_Int32 nPreviewHeight = nNameHeight + nTitleHeight + nHeadingHeight + nTextBodyHeight + nBottomMargin; + + Size aSize(nPreviewWidth, nPreviewHeight); + + pVirtualDev->SetOutputSizePixel(aSize); + + pVirtualDev->SetLineColor(COL_LIGHTGRAY); + pVirtualDev->SetFillColor(); + + tools::Long y = 0; + { + pVirtualDev->SetFillColor(COL_LIGHTGRAY); + tools::Rectangle aNameRect(0, y, nPreviewWidth, nNameHeight); + pVirtualDev->DrawRect(aNameRect); + + vcl::Font aFont; + aFont.SetFontSize(Size(0, nNameFontSize)); + + pVirtualDev->SetFont(aFont); + + Size aTextSize(pVirtualDev->GetTextWidth(aName), pVirtualDev->GetTextHeight()); + + Point aPoint((aNameRect.GetWidth() / 2.0) - (aTextSize.Width() / 2.0), + y + (aNameRect.GetHeight() / 2.0) - (aTextSize.Height() / 2.0)); + + pVirtualDev->DrawText(aPoint, aName); + + y += nNameHeight; + } + + { + tools::Rectangle aRenderRect(Point(nMargin, y), aSize); + renderPreview(pStyleManager, *pVirtualDev, u"Title", nTitleHeight, aRenderRect); + y += nTitleHeight; + } + + { + tools::Rectangle aRenderRect(Point(nMargin, y), aSize); + renderPreview(pStyleManager, *pVirtualDev, u"Heading 1", nHeadingHeight, aRenderRect); + y += nHeadingHeight; + } + { + tools::Rectangle aRenderRect(Point(nMargin, y), aSize); + renderPreview(pStyleManager, *pVirtualDev, u"Body Text", nTextBodyHeight, aRenderRect); + } + + return pVirtualDev->GetBitmapEx(Point(), aSize); +} + +BitmapEx CreatePreview(OUString const & aUrl, OUString const & aName) +{ + if (SfxObjectShell* pObjectShell = SfxObjectShell::Current()) + { + SfxMedium aMedium(aUrl, StreamMode::STD_READWRITE); + SfxObjectShellLock xTemplDoc = SfxObjectShell::CreateObjectByFactoryName(pObjectShell->GetFactory().GetFactoryName(), SfxObjectCreateMode::ORGANIZER); + xTemplDoc->DoInitNew(); + if (xTemplDoc->LoadFrom(aMedium)) + return GenerateStylePreview(*xTemplDoc, aName); + } + return BitmapEx(); +} + +} + +std::unique_ptr<PanelLayout> StylePresetsPanel::Create(weld::Widget* pParent) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException("no parent Window given to StylePresetsPanel::Create", nullptr, 0); + + return std::make_unique<StylePresetsPanel>(pParent); +} + +StylePresetsPanel::StylePresetsPanel(weld::Widget* pParent) + : PanelLayout(pParent, "StylePresetsPanel", "modules/swriter/ui/sidebarstylepresets.ui") + , mxValueSet(new ValueSet(nullptr)) + , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxValueSet)) +{ + mxValueSet->SetColCount(2); + + mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor()); + mxValueSet->SetDoubleClickHdl(LINK(this, StylePresetsPanel, DoubleClickHdl)); + + RefreshList(); +} + +void StylePresetsPanel::RefreshList() +{ + SfxDocumentTemplates aTemplates; + sal_uInt16 nCount = aTemplates.GetRegionCount(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + OUString aRegionName(aTemplates.GetFullRegionName(i)); + if (aRegionName == "Styles") + { + for (sal_uInt16 j = 0; j < aTemplates.GetCount(i); ++j) + { + OUString aName = aTemplates.GetName(i,j); + OUString aURL = aTemplates.GetPath(i,j); + BitmapEx aPreview = CreatePreview(aURL, aName); + sal_uInt16 nId = j + 1; + mxValueSet->InsertItem(nId, Image(aPreview), aName); + maTemplateEntries.push_back(std::make_unique<TemplateEntry>(aURL)); + mxValueSet->SetItemData(nId, maTemplateEntries.back().get()); + } + mxValueSet->SetOptimalSize(); + } + } +} + +StylePresetsPanel::~StylePresetsPanel() +{ +} + +IMPL_LINK_NOARG(StylePresetsPanel, DoubleClickHdl, ValueSet*, void) +{ + sal_Int32 nItemId = mxValueSet->GetSelectedItemId(); + TemplateEntry* pEntry = static_cast<TemplateEntry*>(mxValueSet->GetItemData(nItemId)); + + if (SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current())) + { + SwgReaderOption aOption; + aOption.SetTextFormats(true); + aOption.SetNumRules(true); + pDocSh->LoadStylesFromFile(pEntry->maURL, aOption, false); + } +} + +void StylePresetsPanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/, + const SfxItemState /*eState*/, + const SfxPoolItem* /*pState*/) +{ +} + +} // end of namespace ::sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/StylePresetsPanel.hxx b/sw/source/uibase/sidebar/StylePresetsPanel.hxx new file mode 100644 index 0000000000..f912688863 --- /dev/null +++ b/sw/source/uibase/sidebar/StylePresetsPanel.hxx @@ -0,0 +1,63 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <memory> + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <svtools/valueset.hxx> +#include <utility> + +namespace sw::sidebar { + +class StylePresetsPanel : public PanelLayout, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent); + + StylePresetsPanel(weld::Widget* pParent); + + virtual ~StylePresetsPanel() override; + + virtual void NotifyItemUpdate(const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + +private: + struct TemplateEntry + { + explicit TemplateEntry(OUString aURL) + : maURL(std::move(aURL)) + {} + + OUString maURL; + }; + + void RefreshList(); + + std::unique_ptr<ValueSet> mxValueSet; + std::unique_ptr<weld::CustomWeld> mxValueSetWin; + + std::vector<std::unique_ptr<TemplateEntry>> maTemplateEntries; + + DECL_LINK(DoubleClickHdl, ValueSet*, void); +}; + +} // end of namespace sw::sidebar + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/SwPanelFactory.cxx b/sw/source/uibase/sidebar/SwPanelFactory.cxx new file mode 100644 index 0000000000..5ae3a781bc --- /dev/null +++ b/sw/source/uibase/sidebar/SwPanelFactory.cxx @@ -0,0 +1,220 @@ +/* -*- 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/ui/XUIElementFactory.hpp> + +#include "A11yCheckIssuesPanel.hxx" +#include "ThemePanel.hxx" +#include "StylePresetsPanel.hxx" +#include "PageStylesPanel.hxx" +#include "PageFormatPanel.hxx" +#include "PageHeaderPanel.hxx" +#include "PageFooterPanel.hxx" +#include "WrapPropertyPanel.hxx" +#include "WriterInspectorTextPanel.hxx" +#include "TableEditPanel.hxx" +#include <navipi.hxx> +#include <redlndlg.hxx> + +#include <sfx2/sidebar/SidebarPanelBase.hxx> +#include <vcl/weldutils.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/compbase.hxx> +#include <cppuhelper/supportsservice.hxx> + + +using namespace css; +using namespace css::uno; + +namespace { + +typedef comphelper::WeakComponentImplHelper < + css::ui::XUIElementFactory, css::lang::XServiceInfo + > PanelFactoryInterfaceBase; + +class SwPanelFactory final : public PanelFactoryInterfaceBase +{ +private: + SwPanelFactory(SwPanelFactory const&) = delete; + SwPanelFactory& operator=(SwPanelFactory const&) = delete; + +public: + SwPanelFactory(); + + // XUIElementFactory + css::uno::Reference<css::ui::XUIElement> SAL_CALL createUIElement( + const OUString& rsResourceURL, + const css::uno::Sequence<css::beans::PropertyValue>& rArguments) override; + + OUString SAL_CALL getImplementationName() override + { return "org.apache.openoffice.comp.sw.sidebar.SwPanelFactory"; } + + sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { return cppu::supportsService(this, ServiceName); } + + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { return {"com.sun.star.ui.UIElementFactory"}; } +}; + +SwPanelFactory::SwPanelFactory() +{ +} + +Reference<ui::XUIElement> SAL_CALL SwPanelFactory::createUIElement ( + const OUString& rsResourceURL, + const css::uno::Sequence<css::beans::PropertyValue>& rArguments) +{ + Reference<ui::XUIElement> xElement; + + const ::comphelper::NamedValueCollection aArguments (rArguments); + Reference<frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<frame::XFrame>())); + Reference<awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<awt::XWindow>())); + const sal_uInt64 nBindingsValue (aArguments.getOrDefault("SfxBindings", sal_uInt64(0))); + SfxBindings* pBindings = reinterpret_cast<SfxBindings*>(nBindingsValue); + + weld::Widget* pParent(nullptr); + if (weld::TransportAsXWindow* pTunnel = dynamic_cast<weld::TransportAsXWindow*>(xParentWindow.get())) + pParent = pTunnel->getWidget(); + + if (!pParent) + throw RuntimeException( + "PanelFactory::createUIElement called without ParentWindow", + nullptr); + if ( ! xFrame.is()) + throw RuntimeException( + "PanelFactory::createUIElement called without Frame", + nullptr); + if (pBindings == nullptr) + throw RuntimeException( + "PanelFactory::createUIElement called without SfxBindings", + nullptr); + + if(rsResourceURL.endsWith("/PageStylesPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageStylesPanel::Create( pParent, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(-1,-1,-1)); + } + else if(rsResourceURL.endsWith("/PageFormatPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageFormatPanel::Create( pParent, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(-1,-1,-1)); + } + else if(rsResourceURL.endsWith("/PageHeaderPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageHeaderPanel::Create( pParent, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(-1,-1,-1)); + } + else if(rsResourceURL.endsWith("/PageFooterPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::PageFooterPanel::Create( pParent, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/WrapPropertyPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::WrapPropertyPanel::Create( pParent, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/NavigatorPanel")) + { + std::unique_ptr<PanelLayout> xPanel = SwNavigationPI::Create( pParent, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(0,-1,-1)); + } + else if (rsResourceURL.endsWith("/ManageChangesPanel")) + { + auto xPanel = std::make_unique<SwRedlineAcceptPanel>(pParent); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(0,-1,-1)); + } + else if (rsResourceURL.endsWith("/WriterInspectorTextPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::WriterInspectorTextPanel::Create(pParent); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + std::move(xPanel), + ui::LayoutSize(0,-1,-1)); + } + else if (rsResourceURL.endsWith("/StylePresetsPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::StylePresetsPanel::Create(pParent); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/ThemePanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::ThemePanel::Create(pParent); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/TableEditPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::TableEditPanel::Create(pParent, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/A11yCheckIssuesPanel")) + { + std::unique_ptr<PanelLayout> xPanel = sw::sidebar::A11yCheckIssuesPanel::Create(pParent, pBindings); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1)); + } + + return xElement; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +org_apache_openoffice_comp_sw_sidebar_SwPanelFactory_get_implementation( + css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SwPanelFactory()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/TableEditPanel.cxx b/sw/source/uibase/sidebar/TableEditPanel.cxx new file mode 100644 index 0000000000..61dcd2d4e5 --- /dev/null +++ b/sw/source/uibase/sidebar/TableEditPanel.cxx @@ -0,0 +1,233 @@ +/* -*- 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/. + * + */ + +#include "TableEditPanel.hxx" +#include <sal/config.h> +#include <swtypes.hxx> +#include <cmdid.h> +#include <svl/intitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/dlgctrl.hxx> +#include <swmodule.hxx> +#include <usrpref.hxx> +#include <comphelper/lok.hxx> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar +{ +std::unique_ptr<PanelLayout> +TableEditPanel::Create(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException( + "no parent Window given to TableEditPanel::Create", nullptr, 0); + if (!rxFrame.is()) + throw css::lang::IllegalArgumentException("no XFrame given to TableEditPanel::Create", + nullptr, 1); + + return std::make_unique<TableEditPanel>(pParent, rxFrame, pBindings); +} + +void TableEditPanel::NotifyItemUpdate(const sal_uInt16 nSID, const SfxItemState eState, + const SfxPoolItem* pState) +{ + switch (nSID) + { + case SID_ATTR_TABLE_ROW_HEIGHT: + { + bool bDisabled = eState == SfxItemState::DISABLED; + m_aRowHeightEdit.set_sensitive(!bDisabled); + + if (pState && eState >= SfxItemState::DEFAULT) + { + const SfxUInt32Item* pItem = static_cast<const SfxUInt32Item*>(pState); + if (pItem) + { + tools::Long nNewHeight = pItem->GetValue(); + nNewHeight = m_aRowHeightEdit.normalize(nNewHeight); + m_aRowHeightEdit.set_value(nNewHeight, FieldUnit::TWIP); + } + } + else if (eState != SfxItemState::DISABLED) + m_aRowHeightEdit.set_text(""); + + break; + } + case SID_ATTR_TABLE_COLUMN_WIDTH: + { + bool bDisabled = eState == SfxItemState::DISABLED; + m_aColumnWidthEdit.set_sensitive(!bDisabled); + + if (pState && eState >= SfxItemState::DEFAULT) + { + const SfxUInt32Item* pItem = static_cast<const SfxUInt32Item*>(pState); + if (pItem) + { + tools::Long nNewWidth = pItem->GetValue(); + nNewWidth = m_aColumnWidthEdit.normalize(nNewWidth); + m_aColumnWidthEdit.set_value(nNewWidth, FieldUnit::TWIP); + } + } + else if (eState != SfxItemState::DISABLED) + m_aColumnWidthEdit.set_text(""); + + break; + } + } +} + +TableEditPanel::TableEditPanel(weld::Widget* pParent, + const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings) + : PanelLayout(pParent, "TableEditPanel", "modules/swriter/ui/sidebartableedit.ui") + , m_pBindings(pBindings) + , m_aRowHeightEdit(m_xBuilder->weld_metric_spin_button("rowheight", FieldUnit::CM)) + , m_aColumnWidthEdit(m_xBuilder->weld_metric_spin_button("columnwidth", FieldUnit::CM)) + , m_xInsert(m_xBuilder->weld_toolbar("insert")) + , m_xInsertDispatch(new ToolbarUnoDispatcher(*m_xInsert, *m_xBuilder, rxFrame)) + , m_xSelect(m_xBuilder->weld_toolbar("select")) + , m_xSelectDispatch(new ToolbarUnoDispatcher(*m_xSelect, *m_xBuilder, rxFrame)) + , m_xRowSizing(m_xBuilder->weld_toolbar("rowsizing")) + , m_xRowSizingDispatch(new ToolbarUnoDispatcher(*m_xRowSizing, *m_xBuilder, rxFrame)) + , m_xColumnSizing(m_xBuilder->weld_toolbar("columnsizing")) + , m_xColumnSizingDispatch(new ToolbarUnoDispatcher(*m_xColumnSizing, *m_xBuilder, rxFrame)) + , m_xDelete(m_xBuilder->weld_toolbar("delete")) + , m_xDeleteDispatch(new ToolbarUnoDispatcher(*m_xDelete, *m_xBuilder, rxFrame)) + , m_xSplitMerge(m_xBuilder->weld_toolbar("split_merge")) + , m_xSplitMergeDispatch(new ToolbarUnoDispatcher(*m_xSplitMerge, *m_xBuilder, rxFrame)) + , m_xMisc(m_xBuilder->weld_toolbar("misc")) + , m_xMiscDispatch(new ToolbarUnoDispatcher(*m_xMisc, *m_xBuilder, rxFrame)) + , m_aRowHeightController(SID_ATTR_TABLE_ROW_HEIGHT, *pBindings, *this) + , m_aColumnWidthController(SID_ATTR_TABLE_COLUMN_WIDTH, *pBindings, *this) + , m_aInsertRowsBeforeController(FN_TABLE_INSERT_ROW_BEFORE, *pBindings, *this) + , m_aInsertRowsAfterController(FN_TABLE_INSERT_ROW_AFTER, *pBindings, *this) + , m_aInsertColumnsBeforeController(FN_TABLE_INSERT_COL_BEFORE, *pBindings, *this) + , m_aInsertColumnsAfterController(FN_TABLE_INSERT_COL_AFTER, *pBindings, *this) + , m_aDeleteRowsController(FN_TABLE_DELETE_ROW, *pBindings, *this) + , m_aDeleteColumnsController(FN_TABLE_DELETE_COL, *pBindings, *this) + , m_aDeleteTableController(FN_TABLE_DELETE_TABLE, *pBindings, *this) + , m_aSetMinimalRowHeightController(SID_TABLE_MINIMAL_ROW_HEIGHT, *pBindings, *this) + , m_aSetOptimalRowHeightController(FN_TABLE_OPTIMAL_HEIGHT, *pBindings, *this) + , m_aDistributeRowsController(FN_TABLE_BALANCE_ROWS, *pBindings, *this) + , m_aSetMinimalColumnWidthController(SID_TABLE_MINIMAL_COLUMN_WIDTH, *pBindings, *this) + , m_aSetOptimalColumnWidthController(FN_TABLE_ADJUST_CELLS, *pBindings, *this) + , m_aDistributeColumnsController(FN_TABLE_BALANCE_CELLS, *pBindings, *this) + , m_aMergeCellsController(FN_TABLE_MERGE_CELLS, *pBindings, *this) +{ + // tdf#130197 Give this toolbar a width as if it had 5 entries (the parent + // grid has homogeneous width set so both columns will have the same + // width). This will align this TableEditPanel's columns with + // ParaPropertyPanel's columns + padWidthForSidebar(*m_xSplitMerge, rxFrame); + + InitRowHeightToolitem(); + InitColumnWidthToolitem(); + + if (comphelper::LibreOfficeKit::isActive()) + m_xMisc->set_item_visible(".uno:InsertFormula", false); +} + +void TableEditPanel::InitRowHeightToolitem() +{ + Link<weld::MetricSpinButton&, void> aLink = LINK(this, TableEditPanel, RowHeightMofiyHdl); + m_aRowHeightEdit.connect_value_changed(aLink); + + FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(false)->GetMetric(); + m_aRowHeightEdit.SetFieldUnit(eFieldUnit); + + m_aRowHeightEdit.set_min(MINLAY, FieldUnit::TWIP); + m_aRowHeightEdit.set_max(SAL_MAX_INT32, FieldUnit::TWIP); + + limitWidthForSidebar(m_aRowHeightEdit); +} + +void TableEditPanel::InitColumnWidthToolitem() +{ + Link<weld::MetricSpinButton&, void> aLink = LINK(this, TableEditPanel, ColumnWidthMofiyHdl); + m_aColumnWidthEdit.connect_value_changed(aLink); + + FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(false)->GetMetric(); + m_aColumnWidthEdit.SetFieldUnit(eFieldUnit); + + m_aColumnWidthEdit.set_min(MINLAY, FieldUnit::TWIP); + m_aColumnWidthEdit.set_max(SAL_MAX_INT32, FieldUnit::TWIP); + + limitWidthForSidebar(m_aColumnWidthEdit); +} + +TableEditPanel::~TableEditPanel() +{ + m_xMiscDispatch.reset(); + m_xMisc.reset(); + + m_xSplitMergeDispatch.reset(); + m_xSplitMerge.reset(); + + m_xDeleteDispatch.reset(); + m_xDelete.reset(); + + m_xColumnSizingDispatch.reset(); + m_xColumnSizing.reset(); + + m_xRowSizingDispatch.reset(); + m_xRowSizing.reset(); + + m_xSelectDispatch.reset(); + m_xSelect.reset(); + + m_xInsertDispatch.reset(); + m_xInsert.reset(); + + m_aRowHeightController.dispose(); + m_aColumnWidthController.dispose(); + m_aInsertRowsBeforeController.dispose(); + m_aInsertRowsAfterController.dispose(); + m_aInsertColumnsBeforeController.dispose(); + m_aInsertColumnsAfterController.dispose(); + m_aDeleteRowsController.dispose(); + m_aDeleteColumnsController.dispose(); + m_aDeleteTableController.dispose(); + m_aSetMinimalRowHeightController.dispose(); + m_aSetOptimalRowHeightController.dispose(); + m_aDistributeRowsController.dispose(); + m_aSetMinimalColumnWidthController.dispose(); + m_aSetOptimalColumnWidthController.dispose(); + m_aDistributeColumnsController.dispose(); + m_aMergeCellsController.dispose(); +} + +IMPL_LINK_NOARG(TableEditPanel, RowHeightMofiyHdl, weld::MetricSpinButton&, void) +{ + SwTwips nNewHeight = static_cast<SwTwips>( + m_aRowHeightEdit.denormalize(m_aRowHeightEdit.get_value(FieldUnit::TWIP))); + SfxUInt32Item aRowHeight(SID_ATTR_TABLE_ROW_HEIGHT); + aRowHeight.SetValue(nNewHeight); + + m_pBindings->GetDispatcher()->ExecuteList(SID_ATTR_TABLE_ROW_HEIGHT, SfxCallMode::RECORD, + { &aRowHeight }); +} + +IMPL_LINK_NOARG(TableEditPanel, ColumnWidthMofiyHdl, weld::MetricSpinButton&, void) +{ + SwTwips nNewWidth = static_cast<SwTwips>( + m_aColumnWidthEdit.denormalize(m_aColumnWidthEdit.get_value(FieldUnit::TWIP))); + SfxUInt32Item aColumnWidth(SID_ATTR_TABLE_COLUMN_WIDTH); + aColumnWidth.SetValue(nNewWidth); + + m_pBindings->GetDispatcher()->ExecuteList(SID_ATTR_TABLE_COLUMN_WIDTH, SfxCallMode::RECORD, + { &aColumnWidth }); +} +} // end of namespace ::sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/TableEditPanel.hxx b/sw/source/uibase/sidebar/TableEditPanel.hxx new file mode 100644 index 0000000000..140de86538 --- /dev/null +++ b/sw/source/uibase/sidebar/TableEditPanel.hxx @@ -0,0 +1,85 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <com/sun/star/frame/XFrame.hpp> +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/weldutils.hxx> +#include <svx/relfld.hxx> + +namespace sw::sidebar +{ +class TableEditPanel : public PanelLayout, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> + Create(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings); + + TableEditPanel(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame, + SfxBindings* pBindings); + virtual ~TableEditPanel() override; + + virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState(const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override{}; + +private: + void InitRowHeightToolitem(); + void InitColumnWidthToolitem(); + + SfxBindings* m_pBindings; + + SvxRelativeField m_aRowHeightEdit; + SvxRelativeField m_aColumnWidthEdit; + std::unique_ptr<weld::Toolbar> m_xInsert; + std::unique_ptr<ToolbarUnoDispatcher> m_xInsertDispatch; + std::unique_ptr<weld::Toolbar> m_xSelect; + std::unique_ptr<ToolbarUnoDispatcher> m_xSelectDispatch; + std::unique_ptr<weld::Toolbar> m_xRowSizing; + std::unique_ptr<ToolbarUnoDispatcher> m_xRowSizingDispatch; + std::unique_ptr<weld::Toolbar> m_xColumnSizing; + std::unique_ptr<ToolbarUnoDispatcher> m_xColumnSizingDispatch; + std::unique_ptr<weld::Toolbar> m_xDelete; + std::unique_ptr<ToolbarUnoDispatcher> m_xDeleteDispatch; + std::unique_ptr<weld::Toolbar> m_xSplitMerge; + std::unique_ptr<ToolbarUnoDispatcher> m_xSplitMergeDispatch; + std::unique_ptr<weld::Toolbar> m_xMisc; + std::unique_ptr<ToolbarUnoDispatcher> m_xMiscDispatch; + + ::sfx2::sidebar::ControllerItem m_aRowHeightController; + ::sfx2::sidebar::ControllerItem m_aColumnWidthController; + ::sfx2::sidebar::ControllerItem m_aInsertRowsBeforeController; + ::sfx2::sidebar::ControllerItem m_aInsertRowsAfterController; + ::sfx2::sidebar::ControllerItem m_aInsertColumnsBeforeController; + ::sfx2::sidebar::ControllerItem m_aInsertColumnsAfterController; + ::sfx2::sidebar::ControllerItem m_aDeleteRowsController; + ::sfx2::sidebar::ControllerItem m_aDeleteColumnsController; + ::sfx2::sidebar::ControllerItem m_aDeleteTableController; + ::sfx2::sidebar::ControllerItem m_aSetMinimalRowHeightController; + ::sfx2::sidebar::ControllerItem m_aSetOptimalRowHeightController; + ::sfx2::sidebar::ControllerItem m_aDistributeRowsController; + ::sfx2::sidebar::ControllerItem m_aSetMinimalColumnWidthController; + ::sfx2::sidebar::ControllerItem m_aSetOptimalColumnWidthController; + ::sfx2::sidebar::ControllerItem m_aDistributeColumnsController; + ::sfx2::sidebar::ControllerItem m_aMergeCellsController; + + DECL_LINK(RowHeightMofiyHdl, weld::MetricSpinButton&, void); + DECL_LINK(ColumnWidthMofiyHdl, weld::MetricSpinButton&, void); +}; + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/ThemePanel.cxx b/sw/source/uibase/sidebar/ThemePanel.cxx new file mode 100644 index 0000000000..55853a544f --- /dev/null +++ b/sw/source/uibase/sidebar/ThemePanel.cxx @@ -0,0 +1,111 @@ +/* -*- 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/. + * + */ + +#include "ThemePanel.hxx" +#include <sal/config.h> + +#include <doc.hxx> +#include <docsh.hxx> +#include <drawdoc.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <ThemeColorChanger.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <docmodel/theme/Theme.hxx> +#include <svx/svdpage.hxx> +#include <svx/dialog/ThemeColorValueSet.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar +{ + +std::unique_ptr<PanelLayout> ThemePanel::Create(weld::Widget* pParent) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException("no parent Window given to PagePropertyPanel::Create", nullptr, 0); + + return std::make_unique<ThemePanel>(pParent); +} + +ThemePanel::ThemePanel(weld::Widget* pParent) + : PanelLayout(pParent, "ThemePanel", "modules/swriter/ui/sidebartheme.ui") + , mxValueSetColors(new svx::ThemeColorValueSet) + , mxValueSetColorsWin(new weld::CustomWeld(*m_xBuilder, "valueset_colors", *mxValueSetColors)) + , mxApplyButton(m_xBuilder->weld_button("apply")) +{ + mxValueSetColors->SetColCount(2); + mxValueSetColors->SetLineCount(3); + mxValueSetColors->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor()); + + mxApplyButton->connect_clicked(LINK(this, ThemePanel, ClickHdl)); + mxValueSetColors->SetDoubleClickHdl(LINK(this, ThemePanel, DoubleClickValueSetHdl)); + + auto const& rColorSets = svx::ColorSets::get(); + for (model::ColorSet const& rColorSet : rColorSets.getColorSetVector()) + { + mxValueSetColors->insert(rColorSet); + } + + mxValueSetColors->SetOptimalSize(); + + if (!rColorSets.getColorSetVector().empty()) + mxValueSetColors->SelectItem(1); // ItemId 1, position 0 +} + +ThemePanel::~ThemePanel() +{ + mxValueSetColorsWin.reset(); + mxValueSetColors.reset(); + mxApplyButton.reset(); +} + +IMPL_LINK_NOARG(ThemePanel, ClickHdl, weld::Button&, void) +{ + DoubleClickHdl(); +} + +IMPL_LINK_NOARG(ThemePanel, DoubleClickValueSetHdl, ValueSet*, void) +{ + DoubleClickHdl(); +} + +IMPL_LINK_NOARG(ThemePanel, DoubleClickHdl, weld::TreeView&, bool) +{ + DoubleClickHdl(); + return true; +} + +void ThemePanel::DoubleClickHdl() +{ + SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current()); + if (!pDocSh) + return; + + sal_uInt32 nItemId = mxValueSetColors->GetSelectedItemId(); + if (!nItemId) + return; + sal_uInt32 nIndex = nItemId - 1; + + auto const& rColorSets = svx::ColorSets::get(); + model::ColorSet const& rColorSet = rColorSets.getColorSet(nIndex); + + ThemeColorChanger aChanger(pDocSh); + aChanger.apply(std::make_shared<model::ColorSet>(rColorSet)); +} + +void ThemePanel::NotifyItemUpdate(const sal_uInt16 /*nSId*/, + const SfxItemState /*eState*/, + const SfxPoolItem* /*pState*/) +{ +} + +} // end of namespace ::sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/ThemePanel.hxx b/sw/source/uibase/sidebar/ThemePanel.hxx new file mode 100644 index 0000000000..12285286f5 --- /dev/null +++ b/sw/source/uibase/sidebar/ThemePanel.hxx @@ -0,0 +1,55 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <svtools/valueset.hxx> +#include <svx/ColorSets.hxx> + +namespace svx { class ThemeColorValueSet; } + +namespace sw::sidebar +{ + +class ThemePanel : public PanelLayout, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent); + + ThemePanel(weld::Widget* pParent); + virtual ~ThemePanel() override; + + virtual void NotifyItemUpdate(const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + +private: + std::unique_ptr<weld::TreeView> mxListBoxFonts; + std::unique_ptr<svx::ThemeColorValueSet> mxValueSetColors; + std::unique_ptr<weld::CustomWeld> mxValueSetColorsWin; + std::unique_ptr<weld::Button> mxApplyButton; + + DECL_LINK(ClickHdl, weld::Button&, void); + DECL_LINK(DoubleClickHdl, weld::TreeView&, bool); + DECL_LINK(DoubleClickValueSetHdl, ValueSet*, void); + void DoubleClickHdl(); + +}; + +} // end of namespace sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/WrapPropertyPanel.cxx b/sw/source/uibase/sidebar/WrapPropertyPanel.cxx new file mode 100644 index 0000000000..8f38a161ff --- /dev/null +++ b/sw/source/uibase/sidebar/WrapPropertyPanel.cxx @@ -0,0 +1,175 @@ +/* -*- 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 "WrapPropertyPanel.hxx" + +#include <editeng/editids.hrc> +#include <svx/spacinglistbox.hxx> +#include <svx/svdtrans.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <svl/itemset.hxx> +#include <hintids.hxx> +#include <strings.hrc> +#include <uitool.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +namespace sw::sidebar { + +std::unique_ptr<PanelLayout> WrapPropertyPanel::Create ( + weld::Widget* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame, + SfxBindings* pBindings) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException("no parent Window given to WrapPropertyPanel::Create", nullptr, 0); + if ( ! rxFrame.is()) + throw css::lang::IllegalArgumentException("no XFrame given to WrapPropertyPanel::Create", nullptr, 1); + if (pBindings == nullptr) + throw css::lang::IllegalArgumentException("no SfxBindings given to WrapPropertyPanel::Create", nullptr, 2); + + return std::make_unique<WrapPropertyPanel>(pParent, rxFrame, pBindings); +} + +WrapPropertyPanel::WrapPropertyPanel( + weld::Widget* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame, + SfxBindings* pBindings ) + : PanelLayout(pParent, "WrapPropertyPanel", "modules/swriter/ui/sidebarwrap.ui") + , mpBindings(pBindings) + // spacing + , m_nTop(0) + , m_nBottom(0) + , m_nLeft(0) + , m_nRight(0) + // resources + , m_aCustomEntry(SwResId(STR_WRAP_PANEL_CUSTOM_STR)) + // controller items + , maSwLRSpacingControl(SID_ATTR_LRSPACE, *pBindings, *this) + , maSwULSpacingControl(SID_ATTR_ULSPACE, *pBindings, *this) + , mxWrapOptions(m_xBuilder->weld_toolbar("wrapoptions")) + , mxWrapOptionsDispatch(new ToolbarUnoDispatcher(*mxWrapOptions, *m_xBuilder, rxFrame)) + , mxSpacingLB(m_xBuilder->weld_combo_box("spacingLB")) +{ + FieldUnit eMetric = ::GetDfltMetric(false); + SpacingListBox::Fill(IsInch(eMetric) ? SpacingType::SPACING_INCH : SpacingType::SPACING_CM, *mxSpacingLB); + + Initialize(); +} + +WrapPropertyPanel::~WrapPropertyPanel() +{ + + mxWrapOptionsDispatch.reset(); + mxWrapOptions.reset(); + + maSwLRSpacingControl.dispose(); + maSwULSpacingControl.dispose(); +} + +void WrapPropertyPanel::Initialize() +{ + mxSpacingLB->connect_changed(LINK(this, WrapPropertyPanel, SpacingLBHdl)); + + mpBindings->Update( SID_ATTR_LRSPACE ); + mpBindings->Update( SID_ATTR_ULSPACE ); +} + +void WrapPropertyPanel::UpdateSpacingLB() +{ + if( (m_nLeft == m_nRight) && (m_nTop == m_nBottom) && (m_nLeft == m_nTop) ) + { + sal_Int32 nCount = mxSpacingLB->get_count(); + for (sal_Int32 i = 0; i < nCount; i++) + { + if (mxSpacingLB->get_id(i).toUInt32() == m_nLeft) + { + mxSpacingLB->set_active(i); + int nCustomEntry = mxSpacingLB->find_text(m_aCustomEntry); + if (nCustomEntry != -1) + mxSpacingLB->remove(nCustomEntry); + return; + } + } + } + + if (mxSpacingLB->find_text(m_aCustomEntry) == -1) + mxSpacingLB->append_text(m_aCustomEntry); + mxSpacingLB->set_active_text(m_aCustomEntry); +} + +IMPL_LINK(WrapPropertyPanel, SpacingLBHdl, weld::ComboBox&, rBox, void) +{ + sal_uInt16 nVal = rBox.get_active_id().toUInt32(); + + SvxLRSpaceItem aLRItem(nVal, nVal, 0, RES_LR_SPACE); + SvxULSpaceItem aULItem(nVal, nVal, RES_UL_SPACE); + + m_nTop = m_nBottom = m_nLeft = m_nRight = nVal; + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_LRSPACE, + SfxCallMode::RECORD, { &aLRItem }); + mpBindings->GetDispatcher()->ExecuteList(SID_ATTR_ULSPACE, + SfxCallMode::RECORD, { &aULItem }); +} + +void WrapPropertyPanel::NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) +{ + switch(nSId) + { + case SID_ATTR_LRSPACE: + { + if(eState >= SfxItemState::DEFAULT) + { + const SvxLRSpaceItem* pItem = dynamic_cast< const SvxLRSpaceItem* >(pState); + if(pItem) + { + m_nLeft = pItem->GetLeft(); + m_nRight = pItem->GetRight(); + + UpdateSpacingLB(); + } + } + } + break; + case SID_ATTR_ULSPACE: + { + if(eState >= SfxItemState::DEFAULT) + { + const SvxULSpaceItem* pItem = dynamic_cast< const SvxULSpaceItem* >(pState); + if(pItem) + { + m_nTop = pItem->GetUpper(); + m_nBottom = pItem->GetLower(); + + UpdateSpacingLB(); + } + } + } + break; + } +} + +} // end of namespace ::sw::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/WrapPropertyPanel.hxx b/sw/source/uibase/sidebar/WrapPropertyPanel.hxx new file mode 100644 index 0000000000..d81cf71c97 --- /dev/null +++ b/sw/source/uibase/sidebar/WrapPropertyPanel.hxx @@ -0,0 +1,87 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_WRAPPROPERTYPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_WRAPPROPERTYPANEL_HXX + +#include <sfx2/sidebar/PanelLayout.hxx> +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/weldutils.hxx> +#include <com/sun/star/frame/XFrame.hpp> +#include <vcl/weld.hxx> + +namespace sw::sidebar { + + class WrapPropertyPanel + : public PanelLayout + , public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface + { + public: + static std::unique_ptr<PanelLayout> Create( + weld::Widget* pParent, + const css::uno::Reference< css::frame::XFrame>& rxFrame, + SfxBindings* pBindings ); + + // interface of ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface + virtual void NotifyItemUpdate( + const sal_uInt16 nSId, + const SfxItemState eState, + const SfxPoolItem* pState) override; + + virtual void GetControlState( + const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override {}; + + virtual ~WrapPropertyPanel() override; + + WrapPropertyPanel( + weld::Widget* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame, + SfxBindings* pBindings ); + private: + SfxBindings* mpBindings; + + //Spacing + sal_uInt16 m_nTop; + sal_uInt16 m_nBottom; + sal_uInt16 m_nLeft; + sal_uInt16 m_nRight; + + //custom entry + OUString m_aCustomEntry; + + // Controller Items + ::sfx2::sidebar::ControllerItem maSwLRSpacingControl; + ::sfx2::sidebar::ControllerItem maSwULSpacingControl; + + std::unique_ptr<weld::Toolbar> mxWrapOptions; + std::unique_ptr<ToolbarUnoDispatcher> mxWrapOptionsDispatch; + + std::unique_ptr<weld::ComboBox> mxSpacingLB; + + void Initialize(); + void UpdateSpacingLB(); + + DECL_LINK(SpacingLBHdl, weld::ComboBox&, void); + }; + +} // end of namespace ::sw::sidebar + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx new file mode 100644 index 0000000000..49086fa9a0 --- /dev/null +++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.cxx @@ -0,0 +1,773 @@ +/* -*- 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 "WriterInspectorTextPanel.hxx" + +#include <doc.hxx> +#include <ndtxt.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> +#include <unoprnms.hxx> +#include <editeng/unoprnms.hxx> +#include <com/sun/star/text/XBookmarksSupplier.hpp> +#include <com/sun/star/text/XTextSectionsSupplier.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/text/XTextRangeCompare.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/table/BorderLine2.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/rdf/XMetadatable.hpp> +#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include <unotextrange.hxx> +#include <comphelper/string.hxx> +#include <comphelper/processfactory.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <vcl/settings.hxx> +#include <inspectorproperties.hrc> +#include <strings.hrc> +#include <rdfhelper.hxx> + +namespace sw::sidebar +{ +static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh, + std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx); + +std::unique_ptr<PanelLayout> WriterInspectorTextPanel::Create(weld::Widget* pParent) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException( + "no parent Window given to WriterInspectorTextPanel::Create", nullptr, 0); + return std::make_unique<WriterInspectorTextPanel>(pParent); +} + +WriterInspectorTextPanel::WriterInspectorTextPanel(weld::Widget* pParent) + : InspectorTextPanel(pParent) + , m_nParIdx(0) +{ + SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(SfxObjectShell::Current()); + m_pShell = pDocSh ? pDocSh->GetWrtShell() : nullptr; + if (m_pShell) + { + m_oldLink = m_pShell->GetChgLnk(); + m_pShell->SetChgLnk(LINK(this, WriterInspectorTextPanel, AttrChangedNotify)); + + // tdf#154629 listen to know if the shell destructs before this panel does, + // which can happen on entering print preview + m_pShell->Add(this); + } + + // Update panel on start + std::vector<svx::sidebar::TreeNode> aStore; + SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr; + if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode()) + UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx); + updateEntries(aStore, m_nParIdx); +} + +void WriterInspectorTextPanel::SwClientNotify(const SwModify& rModify, const SfxHint& rHint) +{ + if (rHint.GetId() == SfxHintId::SwLegacyModify) + { + const sw::LegacyModifyHint& rLegacy = static_cast<const sw::LegacyModifyHint&>(rHint); + if (rLegacy.GetWhich() == RES_OBJECTDYING) + m_pShell = nullptr; + } + SwClient::SwClientNotify(rModify, rHint); +} + +WriterInspectorTextPanel::~WriterInspectorTextPanel() +{ + if (m_pShell) + { + m_pShell->SetChgLnk(m_oldLink); + m_pShell->Remove(this); + } +} + +static OUString PropertyNametoRID(const OUString& rName) +{ + static const std::map<OUString, TranslateId> aNameToRID = { + { "BorderDistance", RID_BORDER_DISTANCE }, + { "BottomBorder", RID_BOTTOM_BORDER }, + { "BottomBorderDistance", RID_BOTTOM_BORDER_DISTANCE }, + { "BreakType", RID_BREAK_TYPE }, + { "Category", RID_CATEGORY }, + { "Cell", RID_CELL }, + { "CharAutoEscapement", RID_CHAR_AUTO_ESCAPEMENT }, + { "CharAutoKerning", RID_CHAR_AUTO_KERNING }, + { "CharAutoStyleName", RID_CHAR_AUTO_STYLE_NAME }, + { "CharBackColor", RID_CHAR_BACK_COLOR }, + { "CharBackTransparent", RID_CHAR_BACK_TRANSPARENT }, + { "CharBorderDistance", RID_CHAR_BORDER_DISTANCE }, + { "CharBottomBorder", RID_CHAR_BOTTOM_BORDER }, + { "CharBottomBorderDistance", RID_CHAR_BOTTOM_BORDER_DISTANCE }, + { "CharCaseMap", RID_CHAR_CASE_MAP }, + { "CharColor", RID_CHAR_COLOR }, + { "CharCombineIsOn", RID_CHAR_COMBINE_IS_ON }, + { "CharCombinePrefix", RID_CHAR_COMBINE_PREFIX }, + { "CharCombineSuffix", RID_CHAR_COMBINE_SUFFIX }, + { "CharContoured", RID_CHAR_CONTOURED }, + { "CharCrossedOut", RID_CHAR_CROSSED_OUT }, + { "CharDiffHeight", RID_CHAR_DIFF_HEIGHT }, + { "CharDiffHeightAsian", RID_CHAR_DIFF_HEIGHT_ASIAN }, + { "CharDiffHeightComplex", RID_CHAR_DIFF_HEIGHT_COMPLEX }, + { "CharEmphasis", RID_CHAR_EMPHASIS }, + { "CharEscapement", RID_CHAR_ESCAPEMENT }, + { "CharEscapementHeight", RID_CHAR_ESCAPEMENT_HEIGHT }, + { "CharFlash", RID_CHAR_FLASH }, + { "CharFontCharSet", RID_CHAR_FONT_CHAR_SET }, + { "CharFontCharSetAsian", RID_CHAR_FONT_CHAR_SET_ASIAN }, + { "CharFontCharSetComplex", RID_CHAR_FONT_CHAR_SET_COMPLEX }, + { "CharFontFamily", RID_CHAR_FONT_FAMILY }, + { "CharFontFamilyAsian", RID_CHAR_FONT_FAMILY_ASIAN }, + { "CharFontFamilyComplex", RID_CHAR_FONT_FAMILY_COMPLEX }, + { "CharFontName", RID_CHAR_FONT_NAME }, + { "CharFontNameAsian", RID_CHAR_FONT_NAME_ASIAN }, + { "CharFontNameComplex", RID_CHAR_FONT_NAME_COMPLEX }, + { "CharFontPitch", RID_CHAR_FONT_PITCH }, + { "CharFontPitchAsian", RID_CHAR_FONT_PITCH_ASIAN }, + { "CharFontPitchComplex", RID_CHAR_FONT_PITCH_COMPLEX }, + { "CharFontStyleName", RID_CHAR_FONT_STYLE_NAME }, + { "CharFontStyleNameAsian", RID_CHAR_FONT_STYLE_NAME_ASIAN }, + { "CharFontStyleNameComplex", RID_CHAR_FONT_STYLE_NAME_COMPLEX }, + { "CharHeight", RID_CHAR_HEIGHT }, + { "CharHeightAsian", RID_CHAR_HEIGHT_ASIAN }, + { "CharHeightComplex", RID_CHAR_HEIGHT_COMPLEX }, + { "CharHidden", RID_CHAR_HIDDEN }, + { "CharHighlight", RID_CHAR_HIGHLIGHT }, + { "CharInteropGrabBag", RID_CHAR_INTEROP_GRAB_BAG }, + { "CharKerning", RID_CHAR_KERNING }, + { "CharLeftBorder", RID_CHAR_LEFT_BORDER }, + { "CharLeftBorderDistance", RID_CHAR_LEFT_BORDER_DISTANCE }, + { "CharLocale", RID_CHAR_LOCALE }, + { "CharLocaleAsian", RID_CHAR_LOCALE_ASIAN }, + { "CharLocaleComplex", RID_CHAR_LOCALE_COMPLEX }, + { "CharNoHyphenation", RID_CHAR_NO_HYPHENATION }, + { "CharOverline", RID_CHAR_OVERLINE }, + { "CharOverlineColor", RID_CHAR_OVERLINE_COLOR }, + { "CharOverlineHasColor", RID_CHAR_OVERLINE_HAS_COLOR }, + { "CharPosture", RID_CHAR_POSTURE }, + { "CharPostureAsian", RID_CHAR_POSTURE_ASIAN }, + { "CharPostureComplex", RID_CHAR_POSTURE_COMPLEX }, + { "CharPropHeight", RID_CHAR_PROP_HEIGHT }, + { "CharPropHeightAsian", RID_CHAR_PROP_HEIGHT_ASIAN }, + { "CharPropHeightComplex", RID_CHAR_PROP_HEIGHT_COMPLEX }, + { "CharRelief", RID_CHAR_RELIEF }, + { "CharRightBorder", RID_CHAR_RIGHT_BORDER }, + { "CharRightBorderDistance", RID_CHAR_RIGHT_BORDER_DISTANCE }, + { "CharRotation", RID_CHAR_ROTATION }, + { "CharRotationIsFitToLine", RID_CHAR_ROTATION_IS_FIT_TO_LINE }, + { "CharScaleWidth", RID_CHAR_SCALE_WIDTH }, + { "CharShadingValue", RID_CHAR_SHADING_VALUE }, + { "CharShadowFormat", RID_CHAR_SHADOW_FORMAT }, + { "CharShadowed", RID_CHAR_SHADOWED }, + { "CharStrikeout", RID_CHAR_STRIKEOUT }, + { "CharStyleName", RID_CHAR_STYLE_NAME }, + { "CharStyleNames", RID_CHAR_STYLE_NAMES }, + { "CharTopBorder", RID_CHAR_TOP_BORDER }, + { "CharTopBorderDistance", RID_CHAR_TOP_BORDER_DISTANCE }, + { "CharTransparence", RID_CHAR_TRANSPARENCE }, + { "CharUnderline", RID_CHAR_UNDERLINE }, + { "CharUnderlineColor", RID_CHAR_UNDERLINE_COLOR }, + { "CharUnderlineHasColor", RID_CHAR_UNDERLINE_HAS_COLOR }, + { "CharWeight", RID_CHAR_WEIGHT }, + { "CharWeightAsian", RID_CHAR_WEIGHT_ASIAN }, + { "CharWeightComplex", RID_CHAR_WEIGHT_COMPLEX }, + { "CharWordMode", RID_CHAR_WORD_MODE }, + { "ContinueingPreviousSubTree", RID_CONTINUING_PREVIOUS_SUB_TREE }, + { "DisplayName", RID_DISPLAY_NAME }, + { "DocumentIndex", RID_DOCUMENT_INDEX }, + { "DocumentIndexMark", RID_DOCUMENT_INDEX_MARK }, + { "DropCapCharStyleName", RID_DROP_CAP_CHAR_STYLE_NAME }, + { "DropCapFormat", RID_DROP_CAP_FORMAT }, + { "DropCapWholeWord", RID_DROP_CAP_WHOLE_WORD }, + { "Endnote", RID_ENDNOTE }, + { "FillBackground", RID_FILL_BACKGROUND }, + { "FillBitmap", RID_FILL_BITMAP }, + { "FillBitmapLogicalSize", RID_FILL_BITMAP_LOGICAL_SIZE }, + { "FillBitmapMode", RID_FILL_BITMAP_MODE }, + { "FillBitmapName", RID_FILL_BITMAP_NAME }, + { "FillBitmapOffsetX", RID_FILL_BITMAP_OFFSET_X }, + { "FillBitmapOffsetY", RID_FILL_BITMAP_OFFSET_Y }, + { "FillBitmapPositionOffsetX", RID_FILL_BITMAP_POSITION_OFFSET_X }, + { "FillBitmapPositionOffsetY", RID_FILL_BITMAP_POSITION_OFFSET_Y }, + { "FillBitmapRectanglePoint", RID_FILL_BITMAP_RECTANGLE_POINT }, + { "FillBitmapSizeX", RID_FILL_BITMAP_SIZE_X }, + { "FillBitmapSizeY", RID_FILL_BITMAP_SIZE_Y }, + { "FillBitmapStretch", RID_FILL_BITMAP_STRETCH }, + { "FillBitmapTile", RID_FILL_BITMAP_TILE }, + { "FillBitmapURL", RID_FILL_BITMAP_URL }, + { "FillColor", RID_FILL_COLOR }, + { "FillColor2", RID_FILL_COLOR2 }, + { "FillGradient", RID_FILL_GRADIENT }, + { "FillGradientName", RID_FILL_GRADIENT_NAME }, + { "FillGradientStepCount", RID_FILL_GRADIENT_STEP_COUNT }, + { "FillHatch", RID_FILL_HATCH }, + { "FillHatchName", RID_FILL_HATCH_NAME }, + { "FillStyle", RID_FILL_STYLE }, + { "FillTransparence", RID_FILL_TRANSPARENCE }, + { "FillTransparenceGradient", RID_FILL_TRANSPARENCE_GRADIENT }, + { "FillTransparenceGradientName", RID_FILL_TRANSPARENCE_GRADIENT_NAME }, + { "FollowStyle", RID_FOLLOW_STYLE }, + { "Footnote", RID_FOOTNOTE }, + { "Hidden", RID_HIDDEN }, + { "HyperLinkEvents", RID_HYPERLINK_EVENTS }, + { "HyperLinkName", RID_HYPERLINK_NAME }, + { "HyperLinkTarget", RID_HYPERLINK_TARGET }, + { "HyperLinkURL", RID_HYPERLINK_URL }, + { "IsAutoUpdate", RID_IS_AUTO_UPDATE }, + { "IsPhysical", RID_IS_PHYSICAL }, + { "LeftBorder", RID_LEFT_BORDER }, + { "LeftBorderDistance", RID_LEFT_BORDER_DISTANCE }, + { "ListAutoFormat", RID_LIST_AUTO_FORMAT }, + { "ListId", RID_LIST_ID }, + { "ListLabelString", RID_LIST_LABEL_STRING }, + { "MetadataReference", RID_METADATA_REFERENCE }, + { "NestedTextContent", RID_NESTED_TEXT_CONTENT }, + { "NumberingIsNumber", RID_NUMBERING_IS_NUMBER }, + { "NumberingLevel", RID_NUMBERING_LEVEL }, + { "NumberingRules", RID_NUMBERING_RULES }, + { "NumberingStartValue", RID_NUMBERING_START_VALUE }, + { "NumberingStyleName", RID_NUMBERING_STYLE_NAME }, + { "OutlineContentVisible", RID_OUTLINE_CONTENT_VISIBLE }, + { "OutlineLevel", RID_OUTLINE_LEVEL }, + { "PageDescName", RID_PAGE_DESC_NAME }, + { "PageNumberOffset", RID_PAGE_NUMBER_OFFSET }, + { "PageStyleName", RID_PAGE_STYLE_NAME }, + { "ParRsid", RID_PAR_RSID }, + { "ParaAdjust", RID_PARA_ADJUST }, + { "ParaAutoStyleName", RID_PARA_AUTO_STYLE_NAME }, + { "ParaBackColor", RID_PARA_BACK_COLOR }, + { "ParaBackGraphic", RID_PARA_BACK_GRAPHIC }, + { "ParaBackGraphicFilter", RID_PARA_BACK_GRAPHIC_FILTER }, + { "ParaBackGraphicLocation", RID_PARA_BACK_GRAPHIC_LOCATION }, + { "ParaBackGraphicURL", RID_PARA_BACK_GRAPHIC_URL }, + { "ParaBackTransparent", RID_PARA_BACK_TRANSPARENT }, + { "ParaBottomMargin", RID_PARA_BOTTOM_MARGIN }, + { "ParaBottomMarginRelative", RID_PARA_BOTTOM_MARGIN_RELATIVE }, + { "ParaChapterNumberingLevel", RID_PARA_CHAPTER_NUMBERING_LEVEL }, + { "ParaConditionalStyleName", RID_PARA_CONDITIONAL_STYLE_NAME }, + { "ParaContextMargin", RID_PARA_CONTEXT_MARGIN }, + { "ParaExpandSingleWord", RID_PARA_EXPAND_SINGLE_WORD }, + { "ParaFirstLineIndent", RID_PARA_FIRST_LINE_INDENT }, + { "ParaFirstLineIndentRelative", RID_PARA_FIRST_LINE_INDENT_RELATIVE }, + { "ParaHyphenationMaxHyphens", RID_PARA_HYPHENATION_MAX_HYPHENS }, + { "ParaHyphenationMaxLeadingChars", RID_PARA_HYPHENATION_MAX_LEADING_CHARS }, + { "ParaHyphenationMaxTrailingChars", RID_PARA_HYPHENATION_MAX_TRAILING_CHARS }, + { "ParaHyphenationNoCaps", RID_PARA_HYPHENATION_NO_CAPS }, + { "ParaHyphenationNoLastWord", RID_PARA_HYPHENATION_NO_LAST_WORD }, + { "ParaHyphenationMinWordLength", RID_PARA_HYPHENATION_MIN_WORD_LENGTH }, + { "ParaHyphenationZone", RID_PARA_HYPHENATION_ZONE }, + { "ParaInteropGrabBag", RID_PARA_INTEROP_GRAB_BAG }, + { "ParaIsAutoFirstLineIndent", RID_PARA_IS_AUTO_FIRST_LINE_INDENT }, + { "ParaIsCharacterDistance", RID_PARA_IS_CHARACTER_DISTANCE }, + { "ParaIsConnectBorder", RID_PARA_IS_CONNECT_BORDER }, + { "ParaIsForbiddenRules", RID_PARA_IS_FORBIDDEN_RULES }, + { "ParaIsHangingPunctuation", RID_PARA_IS_HANGING_PUNCTUATION }, + { "ParaIsHyphenation", RID_PARA_IS_HYPHENATION }, + { "ParaIsNumberingRestart", RID_PARA_IS_NUMBERING_RESTART }, + { "ParaKeepTogether", RID_PARA_KEEP_TOGETHER }, + { "ParaLastLineAdjust", RID_PARA_LAST_LINE_ADJUST }, + { "ParaLeftMargin", RID_PARA_LEFT_MARGIN }, + { "ParaLeftMarginRelative", RID_PARA_LEFT_MARGIN_RELATIVE }, + { "ParaLineNumberCount", RID_PARA_LINE_NUMBER_COUNT }, + { "ParaLineNumberStartValue", RID_PARA_LINE_NUMBER_START_VALUE }, + { "ParaLineSpacing", RID_PARA_LINE_SPACING }, + { "ParaOrphans", RID_PARA_ORPHANS }, + { "ParaRegisterModeActive", RID_PARA_REGISTER_MODE_ACTIVE }, + { "ParaRightMargin", RID_PARA_RIGHT_MARGIN }, + { "ParaRightMarginRelative", RID_PARA_RIGHT_MARGIN_RELATIVE }, + { "ParaShadowFormat", RID_PARA_SHADOW_FORMAT }, + { "ParaSplit", RID_PARA_SPLIT }, + { "ParaStyleName", RID_PARA_STYLE_NAME }, + { "ParaTabStops", RID_PARA_TAB_STOPS }, + { "ParaTopMargin", RID_PARA_TOP_MARGIN }, + { "ParaTopMarginRelative", RID_PARA_TOP_MARGIN_RELATIVE }, + { "ParaUserDefinedAttributes", RID_PARA_USER_DEFINED_ATTRIBUTES }, + { "ParaVertAlignment", RID_PARA_VERT_ALIGNMENT }, + { "ParaWidows", RID_PARA_WIDOWS }, + { "ReferenceMark", RID_REFERENCE_MARK }, + { "RightBorder", RID_RIGHT_BORDER }, + { "RightBorderDistance", RID_RIGHT_BORDER_DISTANCE }, + { "Rsid", RID_RSID }, + { "RubyAdjust", RID_RUBY_ADJUST }, + { "RubyCharStyleName", RID_RUBY_CHAR_STYLE_NAME }, + { "RubyIsAbove", RID_RUBY_IS_ABOVE }, + { "RubyPosition", RID_RUBY_POSITION }, + { "RubyText", RID_RUBY_TEXT }, + { "SnapToGrid", RID_SNAP_TO_GRID }, + { "StyleInteropGrabBag", RID_STYLE_INTEROP_GRAB_BAG }, + { "TextField", RID_TEXT_FIELD }, + { "TextFrame", RID_TEXT_FRAME }, + { "TextParagraph", RID_TEXT_PARAGRAPH }, + { "TextSection", RID_TEXT_SECTION }, + { "TextTable", RID_TEXT_TABLE }, + { "TextUserDefinedAttributes", RID_TEXT_USER_DEFINED_ATTRIBUTES }, + { "TopBorder", RID_TOP_BORDER }, + { "TopBorderDistance", RID_TOP_BORDER_DISTANCE }, + { "UnvisitedCharStyleName", RID_UNVISITED_CHAR_STYLE_NAME }, + { "VisitedCharStyleName", RID_VISITED_CHAR_STYLE_NAME }, + { "WritingMode", RID_WRITING_MODE }, + { "BorderColor", RID_BORDER_COLOR }, + { "BorderInnerLineWidth", RID_BORDER_INNER_LINE_WIDTH }, + { "BorderLineDistance", RID_BORDER_LINE_DISTANCE }, + { "BorderLineStyle", RID_BORDER_LINE_STYLE }, + { "BorderLineWidth", RID_BORDER_LINE_WIDTH }, + { "BorderOuterLineWidth", RID_BORDER_OUTER_LINE_WIDTH }, + }; + + auto itr = aNameToRID.find(rName); + if (itr != aNameToRID.end()) + return SwResId(itr->second); + return rName; +} + +static svx::sidebar::TreeNode SimplePropToTreeNode(const OUString& rName, const css::uno::Any& rVal) +{ + svx::sidebar::TreeNode aCurNode; + aCurNode.sNodeName = PropertyNametoRID(rName); + aCurNode.aValue = rVal; + + return aCurNode; +} + +static svx::sidebar::TreeNode BorderToTreeNode(const OUString& rName, const css::uno::Any& rVal) +{ + table::BorderLine2 aBorder; + rVal >>= aBorder; + svx::sidebar::TreeNode aCurNode; + aCurNode.sNodeName = PropertyNametoRID(rName); + aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty; + + aCurNode.children + = { SimplePropToTreeNode("BorderColor", css::uno::Any(aBorder.Color)), + SimplePropToTreeNode("BorderLineWidth", css::uno::Any(aBorder.LineWidth)), + SimplePropToTreeNode("BorderLineStyle", css::uno::Any(aBorder.LineStyle)), + SimplePropToTreeNode("BorderLineDistance", css::uno::Any(aBorder.LineDistance)), + SimplePropToTreeNode("BorderInnerLineWidth", css::uno::Any(aBorder.InnerLineWidth)), + SimplePropToTreeNode("BorderOuterLineWidth", css::uno::Any(aBorder.OuterLineWidth)) }; + return aCurNode; +} + +static svx::sidebar::TreeNode LocaleToTreeNode(const OUString& rName, const css::uno::Any& rVal) +{ + svx::sidebar::TreeNode aCurNode; + aCurNode.sNodeName = PropertyNametoRID(rName); + lang::Locale aLocale; + rVal >>= aLocale; + OUString aLocaleText(aLocale.Language + "-" + aLocale.Country); + if (!aLocale.Variant.isEmpty()) + aLocaleText += " (" + aLocale.Variant + ")"; + aCurNode.aValue <<= aLocaleText; + + return aCurNode; +} + +// Collect text of the current level of the annotated text +// ranges (InContentMetadata) and metadata fields (MetadataField) +static OUString NestedTextContentToText(const css::uno::Any& rVal) +{ + uno::Reference<container::XEnumerationAccess> xMeta; + if (rVal >>= xMeta) + { + uno::Reference<container::XEnumeration> xMetaPortions = xMeta->createEnumeration(); + + OUStringBuffer aBuf; + while (xMetaPortions->hasMoreElements()) + { + uno::Reference<css::text::XTextRange> xRng(xMetaPortions->nextElement(), + uno::UNO_QUERY); + aBuf.append(xRng->getString()); + } + return aBuf.makeStringAndClear(); + } + + return OUString(); +} + +// List metadata associated to the paragraph or character range +static void MetadataToTreeNode(const css::uno::Reference<css::uno::XInterface>& rSource, + svx::sidebar::TreeNode& rNode) +{ + uno::Reference<rdf::XMetadatable> xMeta(rSource, uno::UNO_QUERY_THROW); + // don't add tree node "Metadata Reference", if there is no xml:id + if (!xMeta.is() || xMeta->getMetadataReference().Second.isEmpty()) + return; + + // add metadata of parents for nested annotated text ranges + uno::Reference<container::XChild> xChild(rSource, uno::UNO_QUERY); + if (xChild.is()) + { + uno::Reference<container::XEnumerationAccess> xParentMeta(xChild->getParent(), + uno::UNO_QUERY); + if (xParentMeta.is()) + MetadataToTreeNode(xParentMeta, rNode); + } + + svx::sidebar::TreeNode aCurNode; + aCurNode.sNodeName = PropertyNametoRID("MetadataReference"); + aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty; + + aCurNode.children.push_back( + SimplePropToTreeNode("xml:id", uno::Any(xMeta->getMetadataReference().Second))); + + // list associated (predicate, object) pairs of the actual subject + // under the tree node "Metadata Reference" + if (SwDocShell* pDocSh = static_cast<SwDocShell*>(SfxObjectShell::Current())) + { + uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(pDocSh->GetBaseModel(), + uno::UNO_QUERY); + const uno::Reference<rdf::XRepository>& xRepo = xDocumentMetadataAccess->getRDFRepository(); + const css::uno::Reference<css::rdf::XResource> xSubject(rSource, uno::UNO_QUERY); + std::map<OUString, OUString> xStatements + = SwRDFHelper::getStatements(pDocSh->GetBaseModel(), xRepo->getGraphNames(), xSubject); + for (const auto& pair : xStatements) + aCurNode.children.push_back(SimplePropToTreeNode(pair.first, uno::Any(pair.second))); + } + + rNode.children.push_back(aCurNode); +} + +static svx::sidebar::TreeNode +PropertyToTreeNode(const css::beans::Property& rProperty, + const uno::Reference<beans::XPropertySet>& xPropertiesSet, const bool rIsGrey) +{ + const OUString& rPropName = rProperty.Name; + svx::sidebar::TreeNode aCurNode; + const uno::Any aAny = xPropertiesSet->getPropertyValue(rPropName); + aCurNode.sNodeName = PropertyNametoRID(rPropName); + + // These properties are handled separately as they are stored in STRUCT and not in single data members + if (rPropName == "CharTopBorder" || rPropName == "CharBottomBorder" + || rPropName == "CharLeftBorder" || rPropName == "CharRightBorder" + || rPropName == "TopBorder" || rPropName == "BottomBorder" || rPropName == "LeftBorder" + || rPropName == "RightBorder") + { + aCurNode = BorderToTreeNode(rPropName, aAny); + } + else if (rPropName == "CharLocale") + { + aCurNode = LocaleToTreeNode(rPropName, aAny); + } + else + aCurNode = SimplePropToTreeNode(rPropName, aAny); + + if (rIsGrey) + { + aCurNode.isGrey = true; + for (svx::sidebar::TreeNode& rChildNode : aCurNode.children) + rChildNode.isGrey = true; // grey out all the children nodes + } + + return aCurNode; +} + +static void InsertValues(const css::uno::Reference<css::uno::XInterface>& rSource, + std::unordered_map<OUString, bool>& rIsDefined, + svx::sidebar::TreeNode& rNode, const bool isRoot, + const std::vector<OUString>& rHiddenProperty, + svx::sidebar::TreeNode& rFieldsNode) +{ + uno::Reference<beans::XPropertySet> xPropertiesSet(rSource, uno::UNO_QUERY_THROW); + uno::Reference<beans::XPropertyState> xPropertiesState(rSource, uno::UNO_QUERY_THROW); + const uno::Sequence<beans::Property> aProperties + = xPropertiesSet->getPropertySetInfo()->getProperties(); + + for (const beans::Property& rProperty : aProperties) + { + const OUString& rPropName = rProperty.Name; + if (std::find(rHiddenProperty.begin(), rHiddenProperty.end(), rPropName) + != rHiddenProperty.end()) + continue; + + if (isRoot + || xPropertiesState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE) + { + svx::sidebar::TreeNode aCurNode + = PropertyToTreeNode(rProperty, xPropertiesSet, rIsDefined[rPropName]); + rIsDefined[rPropName] = true; + + // process NestedTextContent and show associated metadata + // under the tree node "Metadata Reference", if they exist + if (rPropName == "NestedTextContent") + { + uno::Reference<container::XEnumerationAccess> xMeta; + if (aCurNode.aValue >>= xMeta) + MetadataToTreeNode(xMeta, rFieldsNode); + aCurNode.aValue <<= NestedTextContentToText(aCurNode.aValue); + } + + rNode.children.push_back(aCurNode); + } + } + + const comphelper::string::NaturalStringSorter aSorter( + comphelper::getProcessComponentContext(), + Application::GetSettings().GetUILanguageTag().getLocale()); + + std::sort( + rNode.children.begin(), rNode.children.end(), + [&aSorter](svx::sidebar::TreeNode const& rEntry1, svx::sidebar::TreeNode const& rEntry2) { + return aSorter.compare(rEntry1.sNodeName, rEntry2.sNodeName) < 0; + }); +} + +static void UpdateTree(SwDocShell& rDocSh, SwEditShell& rEditSh, + std::vector<svx::sidebar::TreeNode>& aStore, sal_Int32& rParIdx) +{ + SwDoc* pDoc = rDocSh.GetDoc(); + SwPaM* pCursor = rEditSh.GetCursor(); + svx::sidebar::TreeNode aCharDFNode; + svx::sidebar::TreeNode aCharNode; + svx::sidebar::TreeNode aParaNode; + svx::sidebar::TreeNode aParaDFNode; + svx::sidebar::TreeNode aBookmarksNode; + svx::sidebar::TreeNode aFieldsNode; + svx::sidebar::TreeNode aTextSectionsNode; + + aCharNode.sNodeName = SwResId(STR_CHARACTERSTYLEFAMILY); + aParaNode.sNodeName = SwResId(STR_PARAGRAPHSTYLEFAMILY); + aCharDFNode.sNodeName = SwResId(RID_CHAR_DIRECTFORMAT); + aParaDFNode.sNodeName = SwResId(RID_PARA_DIRECTFORMAT); + aBookmarksNode.sNodeName = SwResId(STR_CONTENT_TYPE_BOOKMARK); + aFieldsNode.sNodeName = SwResId(STR_CONTENT_TYPE_TEXTFIELD); + aTextSectionsNode.sNodeName = SwResId(STR_CONTENT_TYPE_REGION); + aCharDFNode.NodeType = svx::sidebar::TreeNode::Category; + aCharNode.NodeType = svx::sidebar::TreeNode::Category; + aParaNode.NodeType = svx::sidebar::TreeNode::Category; + aParaDFNode.NodeType = svx::sidebar::TreeNode::Category; + aBookmarksNode.NodeType = svx::sidebar::TreeNode::Category; + aFieldsNode.NodeType = svx::sidebar::TreeNode::Category; + aTextSectionsNode.NodeType = svx::sidebar::TreeNode::Category; + + rtl::Reference<SwXTextRange> xRange( + SwXTextRange::CreateXTextRange(*pDoc, *pCursor->GetPoint(), nullptr)); + if (!xRange) + throw uno::RuntimeException(); + std::unordered_map<OUString, bool> aIsDefined; + + const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID, + UNO_NAME_PARA_IS_NUMBERING_RESTART, + UNO_NAME_PARA_STYLE_NAME, + UNO_NAME_PARA_CONDITIONAL_STYLE_NAME, + UNO_NAME_PAGE_STYLE_NAME, + UNO_NAME_NUMBERING_START_VALUE, + UNO_NAME_NUMBERING_IS_NUMBER, + UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE, + UNO_NAME_CHAR_STYLE_NAME, + UNO_NAME_NUMBERING_LEVEL, + UNO_NAME_SORTED_TEXT_ID, + UNO_NAME_PARRSID, + UNO_NAME_CHAR_COLOR_THEME, + UNO_NAME_CHAR_COLOR_TINT_OR_SHADE }; + + const std::vector<OUString> aHiddenCharacterProperties{ UNO_NAME_CHAR_COLOR_THEME, + UNO_NAME_CHAR_COLOR_TINT_OR_SHADE }; + + InsertValues(static_cast<cppu::OWeakObject*>(xRange.get()), aIsDefined, aCharDFNode, false, + aHiddenProperties, aFieldsNode); + + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(rDocSh.GetBaseModel(), + uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + OUString sCurrentCharStyle, sCurrentParaStyle, sDisplayName; + + uno::Reference<container::XNameAccess> xStyleFamily( + xStyleFamilies->getByName("CharacterStyles"), uno::UNO_QUERY_THROW); + xRange->getPropertyValue("CharStyleName") >>= sCurrentCharStyle; + xRange->getPropertyValue("ParaStyleName") >>= sCurrentParaStyle; + + if (!sCurrentCharStyle.isEmpty()) + { + uno::Reference<beans::XPropertySet> xPropertiesSet( + xStyleFamily->getByName(sCurrentCharStyle), css::uno::UNO_QUERY_THROW); + xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName; + svx::sidebar::TreeNode aCurrentChild; + aCurrentChild.sNodeName = sDisplayName; + aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty; + + InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, false, aHiddenCharacterProperties, + aFieldsNode); + + aCharNode.children.push_back(aCurrentChild); + } + + // Collect paragraph direct formatting + uno::Reference<container::XEnumeration> xParaEnum = xRange->createEnumeration(); + uno::Reference<text::XTextRange> xThisParagraphRange(xParaEnum->nextElement(), uno::UNO_QUERY); + if (xThisParagraphRange.is()) + { + // Collect metadata of the current paragraph + MetadataToTreeNode(xThisParagraphRange, aParaDFNode); + InsertValues(xThisParagraphRange, aIsDefined, aParaDFNode, false, aHiddenProperties, + aFieldsNode); + } + + xStyleFamily.set(xStyleFamilies->getByName("ParagraphStyles"), uno::UNO_QUERY_THROW); + + while (!sCurrentParaStyle.isEmpty()) + { + uno::Reference<style::XStyle> xPropertiesStyle(xStyleFamily->getByName(sCurrentParaStyle), + uno::UNO_QUERY_THROW); + uno::Reference<beans::XPropertySet> xPropertiesSet(xPropertiesStyle, + css::uno::UNO_QUERY_THROW); + xPropertiesSet->getPropertyValue("DisplayName") >>= sDisplayName; + OUString aParentParaStyle = xPropertiesStyle->getParentStyle(); + svx::sidebar::TreeNode aCurrentChild; + aCurrentChild.sNodeName = sDisplayName; + aCurrentChild.NodeType = svx::sidebar::TreeNode::ComplexProperty; + + InsertValues(xPropertiesSet, aIsDefined, aCurrentChild, aParentParaStyle.isEmpty(), + aHiddenCharacterProperties, aFieldsNode); + + aParaNode.children.push_back(aCurrentChild); + sCurrentParaStyle = aParentParaStyle; + } + + std::reverse(aParaNode.children.begin(), + aParaNode.children.end()); // Parent style should be first then children + + // Collect bookmarks at character position + uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(rDocSh.GetBaseModel(), + uno::UNO_QUERY); + + uno::Reference<container::XIndexAccess> xBookmarks(xBookmarksSupplier->getBookmarks(), + uno::UNO_QUERY); + for (sal_Int32 i = 0; i < xBookmarks->getCount(); ++i) + { + svx::sidebar::TreeNode aCurNode; + uno::Reference<text::XTextContent> bookmark; + xBookmarks->getByIndex(i) >>= bookmark; + uno::Reference<container::XNamed> xBookmark(bookmark, uno::UNO_QUERY); + + try + { + uno::Reference<text::XTextRange> bookmarkRange = bookmark->getAnchor(); + uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(), + uno::UNO_QUERY); + if (xTextRangeCompare.is() + && xTextRangeCompare->compareRegionStarts(bookmarkRange, xRange) != -1 + && xTextRangeCompare->compareRegionEnds(xRange, bookmarkRange) != -1) + { + aCurNode.sNodeName = xBookmark->getName(); + aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty; + + MetadataToTreeNode(xBookmark, aCurNode); + // show bookmark only if it has RDF metadata + if (aCurNode.children.size() > 0) + aBookmarksNode.children.push_back(aCurNode); + } + } + catch (const lang::IllegalArgumentException&) + { + } + } + + // Collect sections at character position + uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(rDocSh.GetBaseModel(), + uno::UNO_QUERY); + + uno::Reference<container::XIndexAccess> xTextSections(xTextSectionsSupplier->getTextSections(), + uno::UNO_QUERY); + for (sal_Int32 i = 0; i < xTextSections->getCount(); ++i) + { + svx::sidebar::TreeNode aCurNode; + uno::Reference<text::XTextContent> section; + xTextSections->getByIndex(i) >>= section; + uno::Reference<container::XNamed> xTextSection(section, uno::UNO_QUERY); + + try + { + uno::Reference<text::XTextRange> sectionRange = section->getAnchor(); + uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xRange->getText(), + uno::UNO_QUERY); + if (xTextRangeCompare.is() + && xTextRangeCompare->compareRegionStarts(sectionRange, xRange) != -1 + && xTextRangeCompare->compareRegionEnds(xRange, sectionRange) != -1) + { + aCurNode.sNodeName = xTextSection->getName(); + aCurNode.NodeType = svx::sidebar::TreeNode::ComplexProperty; + + MetadataToTreeNode(xTextSection, aCurNode); + // show section only if it has RDF metadata + if (aCurNode.children.size() > 0) + aTextSectionsNode.children.push_back(aCurNode); + } + } + catch (const lang::IllegalArgumentException&) + { + } + } + + /* + Display Order :- + SECTIONS with RDF metadata (optional) + BOOKMARKS with RDF metadata (optional) + FIELDS with RDF metadata (optional) + PARAGRAPH STYLE + PARAGRAPH DIRECT FORMATTING + CHARACTER STYLE + DIRECT FORMATTING + */ + rParIdx = 0; + // show sections, bookmarks and fields only if they have RDF metadata + if (aTextSectionsNode.children.size() > 0) + { + aStore.push_back(aTextSectionsNode); + rParIdx++; + } + if (aBookmarksNode.children.size() > 0) + { + aStore.push_back(aBookmarksNode); + rParIdx++; + } + if (aFieldsNode.children.size() > 0) + { + aStore.push_back(aFieldsNode); + rParIdx++; + } + aStore.push_back(aParaNode); + aStore.push_back(aParaDFNode); + aStore.push_back(aCharNode); + aStore.push_back(aCharDFNode); +} + +IMPL_LINK(WriterInspectorTextPanel, AttrChangedNotify, LinkParamNone*, pLink, void) +{ + if (m_oldLink.IsSet()) + m_oldLink.Call(pLink); + + SwDocShell* pDocSh = m_pShell->GetDoc()->GetDocShell(); + std::vector<svx::sidebar::TreeNode> aStore; + + SwEditShell* pEditSh = pDocSh ? pDocSh->GetDoc()->GetEditShell() : nullptr; + if (pEditSh && pEditSh->GetCursor()->GetPointNode().GetTextNode()) + UpdateTree(*pDocSh, *pEditSh, aStore, m_nParIdx); + + updateEntries(aStore, m_nParIdx); +} + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx b/sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx new file mode 100644 index 0000000000..2c2df34a94 --- /dev/null +++ b/sw/source/uibase/sidebar/WriterInspectorTextPanel.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <svx/sidebar/InspectorTextPanel.hxx> +#include <calbck.hxx> + +class SwWrtShell; + +namespace sw::sidebar +{ +class WriterInspectorTextPanel final : public svx::sidebar::InspectorTextPanel, public SwClient +{ +public: + static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent); + + WriterInspectorTextPanel(weld::Widget* pParent); + + virtual ~WriterInspectorTextPanel() override; + +private: + SwWrtShell* m_pShell; + Link<LinkParamNone*, void> m_oldLink; + sal_Int32 m_nParIdx; // count optional metadata tree items to collapse default paragraph styles + + // attributes have changed + DECL_LINK(AttrChangedNotify, LinkParamNone*, void); + + virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override; +}; + +} // end of namespace svx::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |