Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / tbxctrls / fontworkgallery.cxx
blob8011aa0c07bfce90da970d0dfb72452527d48a19
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/text/WritingMode.hpp>
23 #include <comphelper/lok.hxx>
24 #include <comphelper/propertyvalue.hxx>
26 #include <vcl/toolbox.hxx>
27 #include <vcl/virdev.hxx>
29 #include <sfx2/viewsh.hxx>
31 #include <svl/itempool.hxx>
33 #include <svtools/toolbarmenu.hxx>
34 #include <svtools/popupwindowcontroller.hxx>
36 #include <svx/fmmodel.hxx>
37 #include <svx/svdpage.hxx>
38 #include <svx/svdobj.hxx>
39 #include <svx/svdview.hxx>
41 #include <svx/gallery.hxx>
42 #include <svx/fontworkgallery.hxx>
44 #include <tools/UnitConversion.hxx>
46 #include <algorithm>
47 #include <memory>
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::beans;
53 namespace svx
56 FontWorkGalleryDialog::FontWorkGalleryDialog(weld::Window* pParent, SdrView& rSdrView)
57 : GenericDialogController(pParent, "svx/ui/fontworkgallerydialog.ui", "FontworkGalleryDialog")
58 , mnThemeId(0xffff)
59 , mrSdrView(rSdrView)
60 , mbInsertIntoPage(true)
61 , mpDestModel(nullptr)
62 , maCtlFavorites(m_xBuilder->weld_icon_view("ctlFavoriteswin"))
63 , mxOKButton(m_xBuilder->weld_button("ok"))
65 Size aSize(530, 400);
66 maCtlFavorites->set_size_request(aSize.Width(), aSize.Height());
68 maCtlFavorites->connect_item_activated( LINK( this, FontWorkGalleryDialog, DoubleClickFavoriteHdl ) );
69 maCtlFavorites->connect_query_tooltip(LINK(this, FontWorkGalleryDialog, QueryTooltipHandler));
70 mxOKButton->connect_clicked(LINK(this, FontWorkGalleryDialog, ClickOKHdl));
72 initFavorites( GALLERY_THEME_FONTWORK );
73 fillFavorites( GALLERY_THEME_FONTWORK );
76 FontWorkGalleryDialog::~FontWorkGalleryDialog()
80 void FontWorkGalleryDialog::initFavorites(sal_uInt16 nThemeId)
82 // the favorites are read via the gallery
83 sal_uInt32 nFavCount = GalleryExplorer::GetSdrObjCount( nThemeId );
85 // lock gallery theme
86 GalleryExplorer::BeginLocking(nThemeId);
88 sal_uInt32 nModelPos;
89 FmFormModel *pModel = nullptr;
91 for( nModelPos = 0; nModelPos < nFavCount; nModelPos++ )
93 BitmapEx aThumb;
95 if (GalleryExplorer::GetSdrObj(nThemeId, nModelPos, pModel, &aThumb) && !aThumb.IsEmpty())
97 VclPtr< VirtualDevice > pVDev = VclPtr<VirtualDevice>::Create();
98 const Point aNull(0, 0);
100 if (pVDev->GetDPIScaleFactor() > 1)
101 aThumb.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor());
103 const Size aSize(aThumb.GetSizePixel());
105 pVDev->SetOutputSizePixel(aSize);
107 static const sal_uInt32 nLen(8);
108 static const Color aW(COL_WHITE);
109 static const Color aG(0xef, 0xef, 0xef);
111 pVDev->DrawCheckered(aNull, aSize, nLen, aW, aG);
113 pVDev->DrawBitmapEx(aNull, aThumb);
114 maFavoritesHorizontal.emplace_back(pVDev);
118 // release gallery theme
119 GalleryExplorer::EndLocking(nThemeId);
122 void FontWorkGalleryDialog::fillFavorites(sal_uInt16 nThemeId)
124 mnThemeId = nThemeId;
126 auto nFavCount = maFavoritesHorizontal.size();
128 maCtlFavorites->clear();
129 maIdToTitleMap.clear();
131 std::vector<OUString> aTitles;
132 (void)GalleryExplorer::FillObjListTitle(nThemeId, aTitles);
133 assert(aTitles.size() == nFavCount);
135 for( size_t nFavorite = 1; nFavorite <= nFavCount; nFavorite++ )
137 OUString sId = OUString::number(static_cast<sal_uInt16>(nFavorite));
138 maIdToTitleMap.emplace(sId, aTitles.at(nFavorite - 1));
139 maCtlFavorites->insert(-1, nullptr, &sId, maFavoritesHorizontal[nFavorite - 1], nullptr);
142 if (maCtlFavorites->n_children())
143 maCtlFavorites->select(0);
146 void FontWorkGalleryDialog::SetSdrObjectRef( SdrModel* pModel)
148 mbInsertIntoPage = false;
149 mpDestModel = pModel;
152 void FontWorkGalleryDialog::insertSelectedFontwork()
154 OUString sItemId = maCtlFavorites->get_selected_id();
155 if (sItemId.isEmpty())
156 return;
158 sal_Int32 nItemId = sItemId.toInt32();
160 if (nItemId == 0)
161 return;
163 FmFormModel aModel;
164 aModel.GetItemPool().FreezeIdRanges();
166 if( !GalleryExplorer::GetSdrObj( mnThemeId, nItemId-1, &aModel ) )
167 return;
169 SdrPage* pPage = aModel.GetPage(0);
170 if( !(pPage && pPage->GetObjCount()) )
171 return;
173 // tdf#116993 Calc uses a 'special' mode for this dialog in being the
174 // only caller of ::SetSdrObjectRef. Only in that case mpDestModel seems
175 // to be the correct target SdrModel.
176 // If this is not used, the correct SdrModel seems to be the one from
177 // the mrSdrView that is used to insert (InsertObjectAtView below) the
178 // cloned SdrObject.
179 const bool bUseSpecialCalcMode(!mbInsertIntoPage && nullptr != mpDestModel);
181 // center shape on current view
182 OutputDevice* pOutDev(mrSdrView.GetFirstOutputDevice());
184 if (!pOutDev)
185 return;
187 // Clone directly to target SdrModel (may be different due to user/caller (!))
188 rtl::Reference<SdrObject> pNewObject(
189 pPage->GetObj(0)->CloneSdrObject(
190 bUseSpecialCalcMode ? *mpDestModel : mrSdrView.getSdrModelFromSdrView()));
192 pNewObject->MakeNameUnique();
194 // tdf#117629
195 // Since the 'old' ::CloneSdrObject also copies the SdrPage* the
196 // SdrObject::getUnoShape() *will* create the wrong UNO API object
197 // early. This IS one of the reasons I do change these things - this
198 // error does not happen with my next change I am working on already
199 // ARGH! For now, reset the SdrPage* to nullptr.
200 // What sense does it have to copy the SdrPage* of the original SdrObject ?!?
201 // TTTT: This also *might* be the hidden reason for the strange code at the
202 // end of SdrObject::SetPage that tries to delete the SvxShape under some
203 // circumstances...
204 // pNewObject->SetPage(nullptr);
206 tools::Rectangle aObjRect( pNewObject->GetLogicRect() );
207 Point aPagePos;
208 Size aFontworkSize = aObjRect.GetSize();
210 if (comphelper::LibreOfficeKit::isActive())
212 SfxViewShell* pViewShell = SfxViewShell::Current();
214 aPagePos = pViewShell->getLOKVisibleArea().Center();
216 aPagePos.setX(convertTwipToMm100(aPagePos.X()));
217 aPagePos.setY(convertTwipToMm100(aPagePos.Y()));
219 sal_Int32 nLOKViewWidth = 0.8 * convertTwipToMm100(pViewShell->getLOKVisibleArea().getOpenWidth());
220 if (aFontworkSize.getWidth() > nLOKViewWidth)
222 double fScale = static_cast<double>(aFontworkSize.getWidth()) / nLOKViewWidth;
223 aFontworkSize.setWidth(aFontworkSize.getWidth() / fScale);
224 aFontworkSize.setHeight(aFontworkSize.getHeight() / fScale);
227 else
229 Size aSize = pOutDev->GetOutputSizePixel();
230 tools::Rectangle aPixelVisRect(Point(0,0), aSize);
231 tools::Rectangle aVisArea = pOutDev->PixelToLogic(aPixelVisRect);
233 aPagePos = aVisArea.Center();
236 if (aPagePos.getX() > aFontworkSize.getWidth() / 2)
237 aPagePos.AdjustX( -(aFontworkSize.getWidth() / 2) );
238 if (aPagePos.getY() > aFontworkSize.getHeight() / 2)
239 aPagePos.AdjustY( -(aFontworkSize.getHeight() / 2) );
241 tools::Rectangle aNewObjectRectangle(aPagePos, aFontworkSize);
242 pNewObject->SetLogicRect(aNewObjectRectangle);
244 if (bUseSpecialCalcMode)
246 mxSdrObject = pNewObject;
248 else
250 SdrPageView* pPV(mrSdrView.GetSdrPageView());
252 if (nullptr != pPV)
254 mrSdrView.InsertObjectAtView( pNewObject.get(), *pPV );
259 IMPL_LINK_NOARG(FontWorkGalleryDialog, ClickOKHdl, weld::Button&, void)
261 insertSelectedFontwork();
262 m_xDialog->response(RET_OK);
265 IMPL_LINK_NOARG(FontWorkGalleryDialog, DoubleClickFavoriteHdl, weld::IconView&, bool)
267 insertSelectedFontwork();
268 m_xDialog->response(RET_OK);
269 return true;
272 IMPL_LINK(FontWorkGalleryDialog, QueryTooltipHandler, const weld::TreeIter&, iter, OUString)
274 const OUString id = maCtlFavorites->get_id(iter);
275 auto it = maIdToTitleMap.find(id);
276 return it != maIdToTitleMap.end() ? it->second : OUString();
279 namespace {
281 class FontworkAlignmentWindow final : public WeldToolbarPopup
283 public:
284 FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow);
285 virtual void GrabFocus() override
287 mxLeft->grab_focus();
289 virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override;
291 private:
292 rtl::Reference<svt::PopupWindowController> mxControl;
293 std::unique_ptr<weld::RadioButton> mxLeft;
294 std::unique_ptr<weld::RadioButton> mxCenter;
295 std::unique_ptr<weld::RadioButton> mxRight;
296 std::unique_ptr<weld::RadioButton> mxStretch;
297 bool mbSettingValue;
299 DECL_LINK( SelectHdl, weld::Toggleable&, void );
301 void implSetAlignment( int nAlignmentMode, bool bEnabled );
306 constexpr OUStringLiteral gsFontworkAlignment(u".uno:FontworkAlignment");
308 FontworkAlignmentWindow::FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParent)
309 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/fontworkalignmentcontrol.ui", "FontworkAlignmentControl")
310 , mxControl(pControl)
311 , mxLeft(m_xBuilder->weld_radio_button("left"))
312 , mxCenter(m_xBuilder->weld_radio_button("center"))
313 , mxRight(m_xBuilder->weld_radio_button("right"))
314 , mxStretch(m_xBuilder->weld_radio_button("stretch"))
315 , mbSettingValue(false)
317 mxLeft->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl));
318 mxCenter->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl));
319 mxRight->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl));
320 mxStretch->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl));
322 AddStatusListener( gsFontworkAlignment );
325 void FontworkAlignmentWindow::implSetAlignment( int nSurface, bool bEnabled )
327 bool bSettingValue = mbSettingValue;
328 mbSettingValue = true;
329 mxLeft->set_active(nSurface == 0 && bEnabled);
330 mxLeft->set_sensitive(bEnabled);
331 mxCenter->set_active(nSurface == 1 && bEnabled);
332 mxCenter->set_sensitive(bEnabled);
333 mxRight->set_active(nSurface == 2 && bEnabled);
334 mxRight->set_sensitive(bEnabled);
335 //Refer https://bugs.documentfoundation.org/show_bug.cgi?id=145092 for why following lines are commented
336 //mxWord->set_active(nSurface == 3 && bEnabled);
337 //mxWord->set_sensitive(bEnabled);
338 mxStretch->set_active(nSurface == 4 && bEnabled);
339 mxStretch->set_sensitive(bEnabled);
340 mbSettingValue = bSettingValue;
343 void FontworkAlignmentWindow::statusChanged( const css::frame::FeatureStateEvent& Event )
345 if( Event.FeatureURL.Main != gsFontworkAlignment )
346 return;
348 if( !Event.IsEnabled )
350 implSetAlignment( 0, false );
352 else
354 sal_Int32 nValue = 0;
355 if( Event.State >>= nValue )
356 implSetAlignment( nValue, true );
360 IMPL_LINK(FontworkAlignmentWindow, SelectHdl, weld::Toggleable&, rButton, void)
362 if (mbSettingValue || !rButton.get_active())
363 return;
365 sal_Int32 nAlignment;
366 if (mxLeft->get_active())
367 nAlignment = 0;
368 else if (mxCenter->get_active())
369 nAlignment = 1;
370 else if (mxRight->get_active())
371 nAlignment = 2;
372 //Refer https://bugs.documentfoundation.org/show_bug.cgi?id=145092 for why following lines are commented
373 //else if (mxWord->get_active())
374 // nAlignment = 3;
375 else
376 nAlignment = 4;
378 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
379 OUString(gsFontworkAlignment).copy(5), nAlignment) };
381 mxControl->dispatchCommand( gsFontworkAlignment, aArgs );
383 implSetAlignment( nAlignment, true );
385 mxControl->EndPopupMode();
388 namespace {
390 class FontworkAlignmentControl : public svt::PopupWindowController
392 public:
393 explicit FontworkAlignmentControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
395 virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
396 virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override;
398 // XInitialization
399 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
401 // XServiceInfo
402 virtual OUString SAL_CALL getImplementationName() override;
403 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
408 FontworkAlignmentControl::FontworkAlignmentControl( const Reference< XComponentContext >& rxContext )
409 : svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkAlignment" )
413 std::unique_ptr<WeldToolbarPopup> FontworkAlignmentControl::weldPopupWindow()
415 return std::make_unique<FontworkAlignmentWindow>(this, m_pToolbar);
418 VclPtr<vcl::Window> FontworkAlignmentControl::createVclPopupWindow( vcl::Window* pParent )
420 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
421 std::make_unique<FontworkAlignmentWindow>(this, pParent->GetFrameWeld()));
423 mxInterimPopover->Show();
425 return mxInterimPopover;
428 // XInitialization
429 void SAL_CALL FontworkAlignmentControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
431 svt::PopupWindowController::initialize( aArguments );
433 if (m_pToolbar)
435 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
436 m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel());
439 ToolBox* pToolBox = nullptr;
440 ToolBoxItemId nId;
441 if ( getToolboxId( nId, &pToolBox ) )
442 pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
445 // XServiceInfo
448 OUString FontworkAlignmentControl::getImplementationName()
450 return "com.sun.star.comp.svx.FontworkAlignmentController";
454 Sequence< OUString > FontworkAlignmentControl::getSupportedServiceNames()
456 return { "com.sun.star.frame.ToolbarController" };
460 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
461 com_sun_star_comp_svx_FontworkAlignmentControl_get_implementation(
462 css::uno::XComponentContext* xContext,
463 css::uno::Sequence<css::uno::Any> const &)
465 return cppu::acquire(new FontworkAlignmentControl(xContext));
468 namespace {
470 class FontworkCharacterSpacingWindow final : public WeldToolbarPopup
472 public:
473 FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow);
474 virtual void GrabFocus() override;
476 virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override;
477 private:
478 rtl::Reference<svt::PopupWindowController> mxControl;
479 std::unique_ptr<weld::RadioButton> mxVeryTight;
480 std::unique_ptr<weld::RadioButton> mxTight;
481 std::unique_ptr<weld::RadioButton> mxNormal;
482 std::unique_ptr<weld::RadioButton> mxLoose;
483 std::unique_ptr<weld::RadioButton> mxVeryLoose;
484 std::unique_ptr<weld::RadioButton> mxCustom;
485 std::unique_ptr<weld::CheckButton> mxKernPairs;
486 sal_Int32 mnCharacterSpacing;
487 bool mbSettingValue;
488 bool mbCommandDispatched;
490 DECL_LINK( KernSelectHdl, weld::Toggleable&, void );
491 DECL_LINK( SelectHdl, weld::Toggleable&, void );
492 DECL_LINK( MouseReleaseHdl, const MouseEvent&, bool );
494 void implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled );
495 void implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled);
496 void DispatchSpacingDialog();
501 constexpr OUStringLiteral gsFontworkCharacterSpacing(u".uno:FontworkCharacterSpacing");
502 constexpr OUStringLiteral gsFontworkKernCharacterPairs(u".uno:FontworkKernCharacterPairs");
504 FontworkCharacterSpacingWindow::FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParent)
505 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/fontworkcharacterspacingcontrol.ui", "FontworkCharacterSpacingControl")
506 , mxControl(pControl)
507 , mxVeryTight(m_xBuilder->weld_radio_button("verytight"))
508 , mxTight(m_xBuilder->weld_radio_button("tight"))
509 , mxNormal(m_xBuilder->weld_radio_button("normal"))
510 , mxLoose(m_xBuilder->weld_radio_button("loose"))
511 , mxVeryLoose(m_xBuilder->weld_radio_button("veryloose"))
512 , mxCustom(m_xBuilder->weld_radio_button("custom"))
513 , mxKernPairs(m_xBuilder->weld_check_button("kernpairs"))
514 , mnCharacterSpacing(0)
515 , mbSettingValue(false)
516 , mbCommandDispatched(false)
518 mxVeryTight->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl));
519 mxTight->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl));
520 mxNormal->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl));
521 mxLoose->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl));
522 mxVeryLoose->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl));
523 mxCustom->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl));
524 mxCustom->connect_mouse_release(LINK(this, FontworkCharacterSpacingWindow, MouseReleaseHdl));
526 mxKernPairs->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, KernSelectHdl));
528 AddStatusListener( gsFontworkCharacterSpacing );
529 AddStatusListener( gsFontworkKernCharacterPairs );
531 // See TODO in svx/source/toolbars/fontworkbar.cxx for SID_FONTWORK_KERN_CHARACTER_PAIRS,
532 // the kernpairs setting is ignored, so hide the widget entirely
533 mxKernPairs->hide();
536 void FontworkCharacterSpacingWindow::GrabFocus()
538 mxVeryTight->grab_focus();
541 void FontworkCharacterSpacingWindow::implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled )
543 bool bSettingValue = mbSettingValue;
544 mbSettingValue = true;
546 mxVeryTight->set_sensitive(bEnabled);
547 mxTight->set_sensitive(bEnabled);
548 mxNormal->set_sensitive(bEnabled);
549 mxLoose->set_sensitive(bEnabled);
550 mxVeryLoose->set_sensitive(bEnabled);
551 mxCustom->set_sensitive(bEnabled);
553 mxVeryTight->set_active(false);
554 mxTight->set_active(false);
555 mxNormal->set_active(false);
556 mxLoose->set_active(false);
557 mxVeryLoose->set_active(false);
558 mxCustom->set_active(true);
560 switch(nCharacterSpacing)
562 case 80:
563 mxVeryTight->set_active(true);
564 break;
565 case 90:
566 mxTight->set_active(true);
567 break;
568 case 100:
569 mxNormal->set_active(true);
570 break;
571 case 120:
572 mxLoose->set_active(true);
573 break;
574 case 150:
575 mxVeryLoose->set_active(true);
576 break;
579 mnCharacterSpacing = nCharacterSpacing;
581 mbSettingValue = bSettingValue;
584 void FontworkCharacterSpacingWindow::implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled)
586 mxKernPairs->set_sensitive(bEnabled);
587 mxKernPairs->set_active(bKernOnOff);
590 void FontworkCharacterSpacingWindow::statusChanged( const css::frame::FeatureStateEvent& Event )
592 if( Event.FeatureURL.Main == gsFontworkCharacterSpacing )
594 if( !Event.IsEnabled )
596 implSetCharacterSpacing( 0, false );
598 else
600 sal_Int32 nValue = 0;
601 if( Event.State >>= nValue )
602 implSetCharacterSpacing( nValue, true );
605 else if( Event.FeatureURL.Main == gsFontworkKernCharacterPairs )
607 if( !Event.IsEnabled )
609 implSetKernCharacterPairs(false, false);
611 else
613 bool bValue = false;
614 if( Event.State >>= bValue )
615 implSetKernCharacterPairs(bValue, true);
620 IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, KernSelectHdl, weld::Toggleable&, void)
622 if (mbSettingValue)
623 return;
625 bool bKernOnOff = mxKernPairs->get_active();
626 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
627 OUString(gsFontworkKernCharacterPairs).copy(5), bKernOnOff) };
629 mxControl->dispatchCommand( gsFontworkKernCharacterPairs, aArgs );
630 mbCommandDispatched = true;
632 implSetKernCharacterPairs(bKernOnOff, true);
634 mxControl->EndPopupMode();
637 void FontworkCharacterSpacingWindow::DispatchSpacingDialog()
639 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
640 OUString(gsFontworkCharacterSpacing).copy(5), mnCharacterSpacing) };
642 rtl::Reference<svt::PopupWindowController> xControl(mxControl);
643 xControl->EndPopupMode();
644 xControl->dispatchCommand(".uno:FontworkCharacterSpacingDialog", aArgs);
645 mbCommandDispatched = true;
648 IMPL_LINK(FontworkCharacterSpacingWindow, SelectHdl, weld::Toggleable&, rButton, void)
650 if (!rButton.get_active())
651 return;
653 if (mbSettingValue)
654 return;
656 // see MouseReleaseHdl for mbCommandDispatched check, there's no guarantee
657 // this toggle will happen before that mouse release though it does in
658 // practice for vcl and gtk
659 if (mbCommandDispatched)
660 return;
662 if (mxCustom->get_active())
663 DispatchSpacingDialog();
664 else
666 sal_Int32 nCharacterSpacing;
667 if (mxVeryTight->get_active())
668 nCharacterSpacing = 80;
669 else if (mxTight->get_active())
670 nCharacterSpacing = 90;
671 else if (mxLoose->get_active())
672 nCharacterSpacing = 120;
673 else if (mxVeryLoose->get_active())
674 nCharacterSpacing = 150;
675 else
676 nCharacterSpacing = 100;
678 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
679 OUString(gsFontworkCharacterSpacing).copy(5), nCharacterSpacing) };
681 mxControl->dispatchCommand( gsFontworkCharacterSpacing, aArgs );
682 mbCommandDispatched = true;
684 implSetCharacterSpacing( nCharacterSpacing, true );
687 mxControl->EndPopupMode();
690 IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, MouseReleaseHdl, const MouseEvent&, bool)
693 tdf#145296 if the "custom" radiobutton was presented preselected as
694 toggled on and the user clicked on it then there's no toggled signal sent
695 because the item was already toggled on and didn't change state.
697 So if that happens launch the custom spacing dialog explicitly here on
698 mouse release.
700 if (mxCustom->get_active() && !mbCommandDispatched)
702 DispatchSpacingDialog();
703 return true;
705 return false;
708 namespace {
710 class FontworkCharacterSpacingControl : public svt::PopupWindowController
712 public:
713 explicit FontworkCharacterSpacingControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
715 virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
716 virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override;
718 // XInitialization
719 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
721 // XServiceInfo
722 virtual OUString SAL_CALL getImplementationName() override;
723 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
728 FontworkCharacterSpacingControl::FontworkCharacterSpacingControl( const Reference< XComponentContext >& rxContext )
729 : svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkCharacterSpacingFloater" )
733 std::unique_ptr<WeldToolbarPopup> FontworkCharacterSpacingControl::weldPopupWindow()
735 return std::make_unique<FontworkCharacterSpacingWindow>(this, m_pToolbar);
738 VclPtr<vcl::Window> FontworkCharacterSpacingControl::createVclPopupWindow( vcl::Window* pParent )
740 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
741 std::make_unique<FontworkCharacterSpacingWindow>(this, pParent->GetFrameWeld()));
743 mxInterimPopover->Show();
745 return mxInterimPopover;
748 // XInitialization
749 void SAL_CALL FontworkCharacterSpacingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
751 svt::PopupWindowController::initialize( aArguments );
753 if (m_pToolbar)
755 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
756 m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel());
759 ToolBox* pToolBox = nullptr;
760 ToolBoxItemId nId;
761 if ( getToolboxId( nId, &pToolBox ) )
762 pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
765 // XServiceInfo
768 OUString FontworkCharacterSpacingControl::getImplementationName()
770 return "com.sun.star.comp.svx.FontworkCharacterSpacingController";
774 Sequence< OUString > FontworkCharacterSpacingControl::getSupportedServiceNames()
776 Sequence<OUString> aSNS { "com.sun.star.frame.ToolbarController" };
777 return aSNS;
781 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
782 com_sun_star_comp_svx_FontworkCharacterSpacingControl_get_implementation(
783 css::uno::XComponentContext* xContext,
784 css::uno::Sequence<css::uno::Any> const &)
786 return cppu::acquire(new FontworkCharacterSpacingControl(xContext));
789 FontworkCharacterSpacingDialog::FontworkCharacterSpacingDialog(weld::Window* pParent, sal_Int32 nScale)
790 : GenericDialogController(pParent, "svx/ui/fontworkspacingdialog.ui", "FontworkSpacingDialog")
791 , m_xMtrScale(m_xBuilder->weld_metric_spin_button("entry", FieldUnit::PERCENT))
793 m_xMtrScale->set_value(nScale, FieldUnit::PERCENT);
796 FontworkCharacterSpacingDialog::~FontworkCharacterSpacingDialog()
800 sal_Int32 FontworkCharacterSpacingDialog::getScale() const
802 return static_cast<sal_Int32>(m_xMtrScale->get_value(FieldUnit::PERCENT));
807 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */