diff options
Diffstat (limited to 'svx/source/tbxctrls/fontworkgallery.cxx')
-rw-r--r-- | svx/source/tbxctrls/fontworkgallery.cxx | 799 |
1 files changed, 799 insertions, 0 deletions
diff --git a/svx/source/tbxctrls/fontworkgallery.cxx b/svx/source/tbxctrls/fontworkgallery.cxx new file mode 100644 index 000000000..802cc1f4f --- /dev/null +++ b/svx/source/tbxctrls/fontworkgallery.cxx @@ -0,0 +1,799 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <com/sun/star/text/WritingMode.hpp> + +#include <comphelper/lok.hxx> +#include <comphelper/propertyvalue.hxx> + +#include <vcl/toolbox.hxx> +#include <vcl/virdev.hxx> + +#include <sfx2/viewsh.hxx> + +#include <svl/itempool.hxx> + +#include <svtools/toolbarmenu.hxx> +#include <svtools/popupwindowcontroller.hxx> + +#include <svx/fmmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdview.hxx> + +#include <svx/gallery.hxx> +#include <svx/fontworkgallery.hxx> + +#include <tools/UnitConversion.hxx> + +#include <algorithm> +#include <memory> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +namespace svx +{ + +FontWorkGalleryDialog::FontWorkGalleryDialog(weld::Window* pParent, SdrView& rSdrView) + : GenericDialogController(pParent, "svx/ui/fontworkgallerydialog.ui", "FontworkGalleryDialog") + , mnThemeId(0xffff) + , mrSdrView(rSdrView) + , mbInsertIntoPage(true) + , mpSdrObject(nullptr) + , mpDestModel(nullptr) + , maCtlFavorites(m_xBuilder->weld_icon_view("ctlFavoriteswin")) + , mxOKButton(m_xBuilder->weld_button("ok")) +{ + Size aSize(530, 400); + maCtlFavorites->set_size_request(aSize.Width(), aSize.Height()); + + maCtlFavorites->connect_item_activated( LINK( this, FontWorkGalleryDialog, DoubleClickFavoriteHdl ) ); + mxOKButton->connect_clicked(LINK(this, FontWorkGalleryDialog, ClickOKHdl)); + + initFavorites( GALLERY_THEME_FONTWORK ); + fillFavorites( GALLERY_THEME_FONTWORK ); +} + +FontWorkGalleryDialog::~FontWorkGalleryDialog() +{ +} + +void FontWorkGalleryDialog::initFavorites(sal_uInt16 nThemeId) +{ + // the favorites are read via the gallery + sal_uInt32 nFavCount = GalleryExplorer::GetSdrObjCount( nThemeId ); + + // lock gallery theme + GalleryExplorer::BeginLocking(nThemeId); + + sal_uInt32 nModelPos; + FmFormModel *pModel = nullptr; + + for( nModelPos = 0; nModelPos < nFavCount; nModelPos++ ) + { + BitmapEx aThumb; + + if (GalleryExplorer::GetSdrObj(nThemeId, nModelPos, pModel, &aThumb) && !aThumb.IsEmpty()) + { + VclPtr< VirtualDevice > pVDev = VclPtr<VirtualDevice>::Create(); + const Point aNull(0, 0); + + if (pVDev->GetDPIScaleFactor() > 1) + aThumb.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor()); + + const Size aSize(aThumb.GetSizePixel()); + + pVDev->SetOutputSizePixel(aSize); + + static const sal_uInt32 nLen(8); + static const Color aW(COL_WHITE); + static const Color aG(0xef, 0xef, 0xef); + + pVDev->DrawCheckered(aNull, aSize, nLen, aW, aG); + + pVDev->DrawBitmapEx(aNull, aThumb); + maFavoritesHorizontal.emplace_back(pVDev); + } + } + + // release gallery theme + GalleryExplorer::EndLocking(nThemeId); +} + +void FontWorkGalleryDialog::fillFavorites(sal_uInt16 nThemeId) +{ + mnThemeId = nThemeId; + + auto nFavCount = maFavoritesHorizontal.size(); + + maCtlFavorites->clear(); + + for( size_t nFavorite = 1; nFavorite <= nFavCount; nFavorite++ ) + { + OUString sId = OUString::number(static_cast<sal_uInt16>(nFavorite)); + maCtlFavorites->insert(-1, nullptr, &sId, maFavoritesHorizontal[nFavorite - 1], nullptr); + } + + if (maCtlFavorites->n_children()) + maCtlFavorites->select(0); +} + +void FontWorkGalleryDialog::SetSdrObjectRef( SdrModel* pModel) +{ + mbInsertIntoPage = false; + mpDestModel = pModel; +} + +void FontWorkGalleryDialog::insertSelectedFontwork() +{ + OUString sItemId = maCtlFavorites->get_selected_id(); + if (sItemId.isEmpty()) + return; + + sal_Int32 nItemId = sItemId.toInt32(); + + if (nItemId == 0) + return; + + FmFormModel aModel; + aModel.GetItemPool().FreezeIdRanges(); + + if( !GalleryExplorer::GetSdrObj( mnThemeId, nItemId-1, &aModel ) ) + return; + + SdrPage* pPage = aModel.GetPage(0); + if( !(pPage && pPage->GetObjCount()) ) + return; + + // tdf#116993 Calc uses a 'special' mode for this dialog in being the + // only caller of ::SetSdrObjectRef. Only in that case mpDestModel seems + // to be the correct target SdrModel. + // If this is not used, the correct SdrModel seems to be the one from + // the mrSdrView that is used to insert (InsertObjectAtView below) the + // cloned SdrObject. + const bool bUseSpecialCalcMode(!mbInsertIntoPage && nullptr != mpDestModel); + + // center shape on current view + OutputDevice* pOutDev(mrSdrView.GetFirstOutputDevice()); + + if (!pOutDev) + return; + + // Clone directly to target SdrModel (may be different due to user/caller (!)) + SdrObject* pNewObject( + pPage->GetObj(0)->CloneSdrObject( + bUseSpecialCalcMode ? *mpDestModel : mrSdrView.getSdrModelFromSdrView())); + + pNewObject->MakeNameUnique(); + + // tdf#117629 + // Since the 'old' ::CloneSdrObject also copies the SdrPage* the + // SdrObject::getUnoShape() *will* create the wrong UNO API object + // early. This IS one of the reasons I do change these things - this + // error does not happen with my next change I am working on already + // ARGH! For now, reset the SdrPage* to nullptr. + // What sense does it have to copy the SdrPage* of the original SdrObject ?!? + // TTTT: This also *might* be the hidden reason for the strange code at the + // end of SdrObject::SetPage that tries to delete the SvxShape under some + // circumstances... + // pNewObject->SetPage(nullptr); + + tools::Rectangle aObjRect( pNewObject->GetLogicRect() ); + Point aPagePos; + Size aFontworkSize = aObjRect.GetSize(); + + if (comphelper::LibreOfficeKit::isActive()) + { + SfxViewShell* pViewShell = SfxViewShell::Current(); + + aPagePos = pViewShell->getLOKVisibleArea().Center(); + + aPagePos.setX(convertTwipToMm100(aPagePos.X())); + aPagePos.setY(convertTwipToMm100(aPagePos.Y())); + + sal_Int32 nLOKViewWidth = 0.8 * convertTwipToMm100(pViewShell->getLOKVisibleArea().getWidth()); + if (aFontworkSize.getWidth() > nLOKViewWidth) + { + double fScale = static_cast<double>(aFontworkSize.getWidth()) / nLOKViewWidth; + aFontworkSize.setWidth(aFontworkSize.getWidth() / fScale); + aFontworkSize.setHeight(aFontworkSize.getHeight() / fScale); + } + } + else + { + Size aSize = pOutDev->GetOutputSizePixel(); + tools::Rectangle aPixelVisRect(Point(0,0), aSize); + tools::Rectangle aVisArea = pOutDev->PixelToLogic(aPixelVisRect); + + aPagePos = aVisArea.Center(); + } + + if (aPagePos.getX() > aFontworkSize.getWidth() / 2) + aPagePos.AdjustX( -(aFontworkSize.getWidth() / 2) ); + if (aPagePos.getY() > aFontworkSize.getHeight() / 2) + aPagePos.AdjustY( -(aFontworkSize.getHeight() / 2) ); + + tools::Rectangle aNewObjectRectangle(aPagePos, aFontworkSize); + pNewObject->SetLogicRect(aNewObjectRectangle); + + if (bUseSpecialCalcMode) + { + mpSdrObject = pNewObject; + } + else + { + SdrPageView* pPV(mrSdrView.GetSdrPageView()); + + if (nullptr != pPV) + { + mrSdrView.InsertObjectAtView( pNewObject, *pPV ); + } + else + { + // tdf#116993 no target -> delete clone + SdrObject::Free(pNewObject); + } + } +} + +IMPL_LINK_NOARG(FontWorkGalleryDialog, ClickOKHdl, weld::Button&, void) +{ + insertSelectedFontwork(); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(FontWorkGalleryDialog, DoubleClickFavoriteHdl, weld::IconView&, bool) +{ + insertSelectedFontwork(); + m_xDialog->response(RET_OK); + return true; +} + +namespace { + +class FontworkAlignmentWindow final : public WeldToolbarPopup +{ +public: + FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override + { + mxLeft->grab_focus(); + } + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; + +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<weld::RadioButton> mxLeft; + std::unique_ptr<weld::RadioButton> mxCenter; + std::unique_ptr<weld::RadioButton> mxRight; + std::unique_ptr<weld::RadioButton> mxStretch; + bool mbSettingValue; + + DECL_LINK( SelectHdl, weld::Toggleable&, void ); + + void implSetAlignment( int nAlignmentMode, bool bEnabled ); +}; + +} + +constexpr OUStringLiteral gsFontworkAlignment(u".uno:FontworkAlignment"); + +FontworkAlignmentWindow::FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/fontworkalignmentcontrol.ui", "FontworkAlignmentControl") + , mxControl(pControl) + , mxLeft(m_xBuilder->weld_radio_button("left")) + , mxCenter(m_xBuilder->weld_radio_button("center")) + , mxRight(m_xBuilder->weld_radio_button("right")) + , mxStretch(m_xBuilder->weld_radio_button("stretch")) + , mbSettingValue(false) +{ + mxLeft->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxCenter->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxRight->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxStretch->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + + AddStatusListener( gsFontworkAlignment ); +} + +void FontworkAlignmentWindow::implSetAlignment( int nSurface, bool bEnabled ) +{ + bool bSettingValue = mbSettingValue; + mbSettingValue = true; + mxLeft->set_active(nSurface == 0 && bEnabled); + mxLeft->set_sensitive(bEnabled); + mxCenter->set_active(nSurface == 1 && bEnabled); + mxCenter->set_sensitive(bEnabled); + mxRight->set_active(nSurface == 2 && bEnabled); + mxRight->set_sensitive(bEnabled); + //Refer https://bugs.documentfoundation.org/show_bug.cgi?id=145092 for why following lines are commented + //mxWord->set_active(nSurface == 3 && bEnabled); + //mxWord->set_sensitive(bEnabled); + mxStretch->set_active(nSurface == 4 && bEnabled); + mxStretch->set_sensitive(bEnabled); + mbSettingValue = bSettingValue; +} + +void FontworkAlignmentWindow::statusChanged( const css::frame::FeatureStateEvent& Event ) +{ + if( Event.FeatureURL.Main != gsFontworkAlignment ) + return; + + if( !Event.IsEnabled ) + { + implSetAlignment( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetAlignment( nValue, true ); + } +} + +IMPL_LINK(FontworkAlignmentWindow, SelectHdl, weld::Toggleable&, rButton, void) +{ + if (mbSettingValue || !rButton.get_active()) + return; + + sal_Int32 nAlignment; + if (mxLeft->get_active()) + nAlignment = 0; + else if (mxCenter->get_active()) + nAlignment = 1; + else if (mxRight->get_active()) + nAlignment = 2; + //Refer https://bugs.documentfoundation.org/show_bug.cgi?id=145092 for why following lines are commented + //else if (mxWord->get_active()) + // nAlignment = 3; + else + nAlignment = 4; + + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue( + OUString(gsFontworkAlignment).copy(5), nAlignment) }; + + mxControl->dispatchCommand( gsFontworkAlignment, aArgs ); + + implSetAlignment( nAlignment, true ); + + mxControl->EndPopupMode(); +} + +namespace { + +class FontworkAlignmentControl : public svt::PopupWindowController +{ +public: + explicit FontworkAlignmentControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +FontworkAlignmentControl::FontworkAlignmentControl( const Reference< XComponentContext >& rxContext ) +: svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkAlignment" ) +{ +} + +std::unique_ptr<WeldToolbarPopup> FontworkAlignmentControl::weldPopupWindow() +{ + return std::make_unique<FontworkAlignmentWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> FontworkAlignmentControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<FontworkAlignmentWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL FontworkAlignmentControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString FontworkAlignmentControl::getImplementationName() +{ + return "com.sun.star.comp.svx.FontworkAlignmentController"; +} + + +Sequence< OUString > FontworkAlignmentControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_FontworkAlignmentControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FontworkAlignmentControl(xContext)); +} + +namespace { + +class FontworkCharacterSpacingWindow final : public WeldToolbarPopup +{ +public: + FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override; + + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<weld::RadioButton> mxVeryTight; + std::unique_ptr<weld::RadioButton> mxTight; + std::unique_ptr<weld::RadioButton> mxNormal; + std::unique_ptr<weld::RadioButton> mxLoose; + std::unique_ptr<weld::RadioButton> mxVeryLoose; + std::unique_ptr<weld::RadioButton> mxCustom; + std::unique_ptr<weld::CheckButton> mxKernPairs; + sal_Int32 mnCharacterSpacing; + bool mbSettingValue; + bool mbCommandDispatched; + + DECL_LINK( KernSelectHdl, weld::Toggleable&, void ); + DECL_LINK( SelectHdl, weld::Toggleable&, void ); + DECL_LINK( MouseReleaseHdl, const MouseEvent&, bool ); + + void implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled ); + void implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled); + void DispatchSpacingDialog(); +}; + +} + +constexpr OUStringLiteral gsFontworkCharacterSpacing(u".uno:FontworkCharacterSpacing"); +constexpr OUStringLiteral gsFontworkKernCharacterPairs(u".uno:FontworkKernCharacterPairs"); + +FontworkCharacterSpacingWindow::FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/fontworkcharacterspacingcontrol.ui", "FontworkCharacterSpacingControl") + , mxControl(pControl) + , mxVeryTight(m_xBuilder->weld_radio_button("verytight")) + , mxTight(m_xBuilder->weld_radio_button("tight")) + , mxNormal(m_xBuilder->weld_radio_button("normal")) + , mxLoose(m_xBuilder->weld_radio_button("loose")) + , mxVeryLoose(m_xBuilder->weld_radio_button("veryloose")) + , mxCustom(m_xBuilder->weld_radio_button("custom")) + , mxKernPairs(m_xBuilder->weld_check_button("kernpairs")) + , mnCharacterSpacing(0) + , mbSettingValue(false) + , mbCommandDispatched(false) +{ + mxVeryTight->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxTight->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxNormal->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxLoose->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxVeryLoose->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxCustom->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxCustom->connect_mouse_release(LINK(this, FontworkCharacterSpacingWindow, MouseReleaseHdl)); + + mxKernPairs->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, KernSelectHdl)); + + AddStatusListener( gsFontworkCharacterSpacing ); + AddStatusListener( gsFontworkKernCharacterPairs ); + + // See TODO in svx/source/toolbars/fontworkbar.cxx for SID_FONTWORK_KERN_CHARACTER_PAIRS, + // the kernpairs setting is ignored, so hide the widget entirely + mxKernPairs->hide(); +} + +void FontworkCharacterSpacingWindow::GrabFocus() +{ + mxVeryTight->grab_focus(); +} + +void FontworkCharacterSpacingWindow::implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled ) +{ + bool bSettingValue = mbSettingValue; + mbSettingValue = true; + + mxVeryTight->set_sensitive(bEnabled); + mxTight->set_sensitive(bEnabled); + mxNormal->set_sensitive(bEnabled); + mxLoose->set_sensitive(bEnabled); + mxVeryLoose->set_sensitive(bEnabled); + mxCustom->set_sensitive(bEnabled); + + mxVeryTight->set_active(false); + mxTight->set_active(false); + mxNormal->set_active(false); + mxLoose->set_active(false); + mxVeryLoose->set_active(false); + mxCustom->set_active(true); + + switch(nCharacterSpacing) + { + case 80: + mxVeryTight->set_active(true); + break; + case 90: + mxTight->set_active(true); + break; + case 100: + mxNormal->set_active(true); + break; + case 120: + mxLoose->set_active(true); + break; + case 150: + mxVeryLoose->set_active(true); + break; + } + + mnCharacterSpacing = nCharacterSpacing; + + mbSettingValue = bSettingValue; +} + +void FontworkCharacterSpacingWindow::implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled) +{ + mxKernPairs->set_sensitive(bEnabled); + mxKernPairs->set_active(bKernOnOff); +} + +void FontworkCharacterSpacingWindow::statusChanged( const css::frame::FeatureStateEvent& Event ) +{ + if( Event.FeatureURL.Main == gsFontworkCharacterSpacing ) + { + if( !Event.IsEnabled ) + { + implSetCharacterSpacing( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetCharacterSpacing( nValue, true ); + } + } + else if( Event.FeatureURL.Main == gsFontworkKernCharacterPairs ) + { + if( !Event.IsEnabled ) + { + implSetKernCharacterPairs(false, false); + } + else + { + bool bValue = false; + if( Event.State >>= bValue ) + implSetKernCharacterPairs(bValue, true); + } + } +} + +IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, KernSelectHdl, weld::Toggleable&, void) +{ + if (mbSettingValue) + return; + + bool bKernOnOff = mxKernPairs->get_active(); + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue( + OUString(gsFontworkKernCharacterPairs).copy(5), bKernOnOff) }; + + mxControl->dispatchCommand( gsFontworkKernCharacterPairs, aArgs ); + mbCommandDispatched = true; + + implSetKernCharacterPairs(bKernOnOff, true); + + mxControl->EndPopupMode(); +} + +void FontworkCharacterSpacingWindow::DispatchSpacingDialog() +{ + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue( + OUString(gsFontworkCharacterSpacing).copy(5), mnCharacterSpacing) }; + + rtl::Reference<svt::PopupWindowController> xControl(mxControl); + xControl->EndPopupMode(); + xControl->dispatchCommand(".uno:FontworkCharacterSpacingDialog", aArgs); + mbCommandDispatched = true; +} + +IMPL_LINK(FontworkCharacterSpacingWindow, SelectHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + + if (mbSettingValue) + return; + + // see MouseReleaseHdl for mbCommandDispatched check, there's no guarantee + // this toggle will happen before that mouse release though it does in + // practice for vcl and gtk + if (mbCommandDispatched) + return; + + if (mxCustom->get_active()) + DispatchSpacingDialog(); + else + { + sal_Int32 nCharacterSpacing; + if (mxVeryTight->get_active()) + nCharacterSpacing = 80; + else if (mxTight->get_active()) + nCharacterSpacing = 90; + else if (mxLoose->get_active()) + nCharacterSpacing = 120; + else if (mxVeryLoose->get_active()) + nCharacterSpacing = 150; + else + nCharacterSpacing = 100; + + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue( + OUString(gsFontworkCharacterSpacing).copy(5), nCharacterSpacing) }; + + mxControl->dispatchCommand( gsFontworkCharacterSpacing, aArgs ); + mbCommandDispatched = true; + + implSetCharacterSpacing( nCharacterSpacing, true ); + } + + mxControl->EndPopupMode(); +} + +IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, MouseReleaseHdl, const MouseEvent&, bool) +{ + /* + tdf#145296 if the "custom" radiobutton was presented preselected as + toggled on and the user clicked on it then there's no toggled signal sent + because the item was already toggled on and didn't change state. + + So if that happens launch the custom spacing dialog explicitly here on + mouse release. + */ + if (mxCustom->get_active() && !mbCommandDispatched) + { + DispatchSpacingDialog(); + return true; + } + return false; +} + +namespace { + +class FontworkCharacterSpacingControl : public svt::PopupWindowController +{ +public: + explicit FontworkCharacterSpacingControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +FontworkCharacterSpacingControl::FontworkCharacterSpacingControl( const Reference< XComponentContext >& rxContext ) +: svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkCharacterSpacingFloater" ) +{ +} + +std::unique_ptr<WeldToolbarPopup> FontworkCharacterSpacingControl::weldPopupWindow() +{ + return std::make_unique<FontworkCharacterSpacingWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> FontworkCharacterSpacingControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<FontworkCharacterSpacingWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL FontworkCharacterSpacingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString FontworkCharacterSpacingControl::getImplementationName() +{ + return "com.sun.star.comp.svx.FontworkCharacterSpacingController"; +} + + +Sequence< OUString > FontworkCharacterSpacingControl::getSupportedServiceNames() +{ + Sequence<OUString> aSNS { "com.sun.star.frame.ToolbarController" }; + return aSNS; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_FontworkCharacterSpacingControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FontworkCharacterSpacingControl(xContext)); +} + +FontworkCharacterSpacingDialog::FontworkCharacterSpacingDialog(weld::Window* pParent, sal_Int32 nScale) + : GenericDialogController(pParent, "svx/ui/fontworkspacingdialog.ui", "FontworkSpacingDialog") + , m_xMtrScale(m_xBuilder->weld_metric_spin_button("entry", FieldUnit::PERCENT)) +{ + m_xMtrScale->set_value(nScale, FieldUnit::PERCENT); +} + +FontworkCharacterSpacingDialog::~FontworkCharacterSpacingDialog() +{ +} + +sal_Int32 FontworkCharacterSpacingDialog::getScale() const +{ + return static_cast<sal_Int32>(m_xMtrScale->get_value(FieldUnit::PERCENT)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |