1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
21 #include <com/sun/star/text/WritingMode.hpp>
22 
23 #include <vcl/toolbox.hxx>
24 #include <vcl/settings.hxx>
25 #include <vcl/virdev.hxx>
26 
27 #include <svl/itempool.hxx>
28 
29 #include <svtools/toolbarmenu.hxx>
30 #include <svtools/popupwindowcontroller.hxx>
31 #include <svtools/popupmenucontrollerbase.hxx>
32 
33 #include <sfx2/app.hxx>
34 #include <sfx2/dispatch.hxx>
35 
36 #include <editeng/eeitem.hxx>
37 #include <editeng/frmdiritem.hxx>
38 
39 #include <svx/fmmodel.hxx>
40 #include <svx/svxids.hrc>
41 #include <svx/dialmgr.hxx>
42 #include <svx/strings.hrc>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdobj.hxx>
45 #include <svx/svdview.hxx>
46 #include <svx/svdoutl.hxx>
47 
48 #include <svx/gallery.hxx>
49 #include <svx/dlgutil.hxx>
50 #include <svx/fontworkgallery.hxx>
51 
52 #include <algorithm>
53 #include <memory>
54 
55 #include <bitmaps.hlst>
56 
57 using ::svtools::ToolbarMenu;
58 
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::beans;
62 
63 namespace svx
64 {
65 
66 const int nColCount = 4;
67 const int nLineCount = 4;
68 
FontWorkGalleryDialog(weld::Window * pParent,SdrView & rSdrView)69 FontWorkGalleryDialog::FontWorkGalleryDialog(weld::Window* pParent, SdrView& rSdrView)
70     : GenericDialogController(pParent, "svx/ui/fontworkgallerydialog.ui", "FontworkGalleryDialog")
71     , mnThemeId(0xffff)
72     , mrSdrView(rSdrView)
73     , mppSdrObject(nullptr)
74     , mpDestModel(nullptr)
75     , maCtlFavorites(m_xBuilder->weld_scrolled_window("ctlFavoriteswin"))
76     , mxCtlFavorites(new weld::CustomWeld(*m_xBuilder, "ctlFavorites", maCtlFavorites))
77     , mxOKButton(m_xBuilder->weld_button("ok"))
78 {
79     Size aSize(maCtlFavorites.GetDrawingArea()->get_ref_device().LogicToPixel(Size(200, 200), MapMode(MapUnit::MapAppFont)));
80     mxCtlFavorites->set_size_request(aSize.Width(), aSize.Height());
81 
82     maCtlFavorites.SetDoubleClickHdl( LINK( this, FontWorkGalleryDialog, DoubleClickFavoriteHdl ) );
83     mxOKButton->connect_clicked(LINK(this, FontWorkGalleryDialog, ClickOKHdl));
84 
85     maCtlFavorites.SetColCount( nColCount );
86     maCtlFavorites.SetLineCount( nLineCount );
87     maCtlFavorites.SetExtraSpacing( 3 );
88 
89     initFavorites( GALLERY_THEME_FONTWORK );
90     fillFavorites( GALLERY_THEME_FONTWORK );
91 }
92 
~FontWorkGalleryDialog()93 FontWorkGalleryDialog::~FontWorkGalleryDialog()
94 {
95 }
96 
initFavorites(sal_uInt16 nThemeId)97 void FontWorkGalleryDialog::initFavorites(sal_uInt16 nThemeId)
98 {
99     // the favorites are read via the gallery
100     sal_uInt32 nFavCount = GalleryExplorer::GetSdrObjCount( nThemeId );
101 
102     // lock gallery theme
103     GalleryExplorer::BeginLocking(nThemeId);
104 
105     sal_uInt32 nModelPos;
106     FmFormModel *pModel = nullptr;
107 
108     for( nModelPos = 0; nModelPos < nFavCount; nModelPos++ )
109     {
110         BitmapEx aThumb;
111 
112         if (GalleryExplorer::GetSdrObj(nThemeId, nModelPos, pModel, &aThumb) && !!aThumb)
113         {
114             ScopedVclPtrInstance< VirtualDevice > pVDev;
115             const Point aNull(0, 0);
116 
117             if (pVDev->GetDPIScaleFactor() > 1)
118                 aThumb.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor());
119 
120             const Size aSize(aThumb.GetSizePixel());
121 
122             pVDev->SetOutputSizePixel(aSize);
123 
124             static const sal_uInt32 nLen(8);
125             static const Color aW(COL_WHITE);
126             static const Color aG(0xef, 0xef, 0xef);
127 
128             pVDev->DrawCheckered(aNull, aSize, nLen, aW, aG);
129 
130             pVDev->DrawBitmapEx(aNull, aThumb);
131             maFavoritesHorizontal.emplace_back(pVDev->GetBitmapEx(aNull, aSize));
132         }
133     }
134 
135     // release gallery theme
136     GalleryExplorer::EndLocking(nThemeId);
137 }
138 
fillFavorites(sal_uInt16 nThemeId)139 void FontWorkGalleryDialog::fillFavorites(sal_uInt16 nThemeId)
140 {
141     mnThemeId = nThemeId;
142 
143     Size aThumbSize(maCtlFavorites.GetOutputSizePixel());
144     aThumbSize.setWidth( aThumbSize.Width() / nColCount );
145     aThumbSize.setHeight( aThumbSize.Height() / nLineCount );
146     aThumbSize.AdjustWidth( -12 );
147     aThumbSize.AdjustHeight( -12 );
148 
149     auto nFavCount = maFavoritesHorizontal.size();
150 
151     // ValueSet favorites
152     if( nFavCount > (nColCount * nLineCount) )
153     {
154         WinBits nWinBits = maCtlFavorites.GetStyle();
155         nWinBits |= WB_VSCROLL;
156         maCtlFavorites.SetStyle( nWinBits );
157     }
158 
159     maCtlFavorites.Clear();
160 
161     for( size_t nFavorite = 1; nFavorite <= nFavCount; nFavorite++ )
162     {
163         OUString aStr = SvxResId(RID_SVXFLOAT3D_FAVORITE) + " " + OUString::number(nFavorite);
164         Image aThumbImage( maFavoritesHorizontal[nFavorite-1] );
165         maCtlFavorites.InsertItem( static_cast<sal_uInt16>(nFavorite), aThumbImage, aStr );
166     }
167 
168     if (maCtlFavorites.GetItemCount())
169         maCtlFavorites.SelectItem(1);
170 }
171 
SetSdrObjectRef(SdrObject ** ppSdrObject,SdrModel * pModel)172 void FontWorkGalleryDialog::SetSdrObjectRef( SdrObject** ppSdrObject, SdrModel* pModel )
173 {
174     mppSdrObject = ppSdrObject;
175     mpDestModel = pModel;
176 }
177 
insertSelectedFontwork()178 void FontWorkGalleryDialog::insertSelectedFontwork()
179 {
180     sal_uInt16 nItemId = maCtlFavorites.GetSelectedItemId();
181 
182     if( nItemId > 0 )
183     {
184         std::unique_ptr<FmFormModel> pModel(new FmFormModel());
185         pModel->GetItemPool().FreezeIdRanges();
186 
187         if( GalleryExplorer::GetSdrObj( mnThemeId, nItemId-1, pModel.get() ) )
188         {
189             SdrPage* pPage = pModel->GetPage(0);
190             if( pPage && pPage->GetObjCount() )
191             {
192                 // tdf#116993 Calc uses a 'special' mode for this dialog in being the
193                 // only caller of ::SetSdrObjectRef. Only in that case mpDestModel seems
194                 // to be the correct target SdrModel.
195                 // If this is not used, the correct SdrModel seems to be the one from
196                 // the mrSdrView that is used to insert (InsertObjectAtView below) the
197                 // cloned SdrObject.
198                 const bool bUseSpecialCalcMode(nullptr != mppSdrObject && nullptr != mpDestModel);
199 
200                 // center shape on current view
201                 OutputDevice* pOutDev(mrSdrView.GetFirstOutputDevice());
202 
203                 if (pOutDev)
204                 {
205                     // Clone directly to target SdrModel (may be different due to user/caller (!))
206                     SdrObject* pNewObject(
207                         pPage->GetObj(0)->CloneSdrObject(
208                             bUseSpecialCalcMode ? *mpDestModel : mrSdrView.getSdrModelFromSdrView()));
209 
210                     // tdf#117629
211                     // Since the 'old' ::CloneSdrObject also copies the SdrPage* the
212                     // SdrObject::getUnoShape() *will* create the wrong UNO API object
213                     // early. This IS one of the reasons I do change these things - this
214                     // error does not happen with my next change I am working on already
215                     // ARGH! For now, reset the SdrPage* to nullptr.
216                     // What sense does it have to copy the SdrPage* of the original SdrObject ?!?
217                     // TTTT: This also *might* be the hidden reason for the strange code at the
218                     // end of SdrObject::SetPage that tries to delete the SvxShape under some
219                     // circumstances...
220                     // pNewObject->SetPage(nullptr);
221 
222                     tools::Rectangle aObjRect( pNewObject->GetLogicRect() );
223                     tools::Rectangle aVisArea = pOutDev->PixelToLogic(tools::Rectangle(Point(0,0), pOutDev->GetOutputSizePixel()));
224                     Point aPagePos = aVisArea.Center();
225                     aPagePos.AdjustX( -(aObjRect.GetWidth() / 2) );
226                     aPagePos.AdjustY( -(aObjRect.GetHeight() / 2) );
227                     tools::Rectangle aNewObjectRectangle(aPagePos, aObjRect.GetSize());
228                     pNewObject->SetLogicRect(aNewObjectRectangle);
229 
230                     if (bUseSpecialCalcMode)
231                     {
232                         *mppSdrObject = pNewObject;
233                     }
234                     else
235                     {
236                         SdrPageView* pPV(mrSdrView.GetSdrPageView());
237 
238                         if (nullptr != pPV)
239                         {
240                             mrSdrView.InsertObjectAtView( pNewObject, *pPV );
241                         }
242                         else
243                         {
244                             // tdf#116993 no target -> delete clone
245                             SdrObject::Free(pNewObject);
246                         }
247                     }
248                 }
249             }
250         }
251     }
252 }
253 
IMPL_LINK_NOARG(FontWorkGalleryDialog,ClickOKHdl,weld::Button &,void)254 IMPL_LINK_NOARG(FontWorkGalleryDialog, ClickOKHdl, weld::Button&, void)
255 {
256     insertSelectedFontwork();
257     m_xDialog->response(RET_OK);
258 }
259 
IMPL_LINK_NOARG(FontWorkGalleryDialog,DoubleClickFavoriteHdl,SvtValueSet *,void)260 IMPL_LINK_NOARG(FontWorkGalleryDialog, DoubleClickFavoriteHdl, SvtValueSet*, void)
261 {
262     insertSelectedFontwork();
263     m_xDialog->response(RET_OK);
264 }
265 
266 class FontworkAlignmentWindow : public ToolbarMenu
267 {
268 public:
269     FontworkAlignmentWindow( svt::ToolboxController& rController, vcl::Window* pParentWindow );
270 
271     virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override;
272 
273 private:
274     svt::ToolboxController& mrController;
275 
276     DECL_LINK( SelectHdl, ToolbarMenu*, void );
277 
278     void    implSetAlignment( int nAlignmentMode, bool bEnabled );
279 };
280 
281 static const OUStringLiteral gsFontworkAlignment(".uno:FontworkAlignment");
282 
FontworkAlignmentWindow(svt::ToolboxController & rController,vcl::Window * pParentWindow)283 FontworkAlignmentWindow::FontworkAlignmentWindow(svt::ToolboxController& rController, vcl::Window* pParentWindow)
284     : ToolbarMenu(rController.getFrameInterface(), pParentWindow, WB_STDPOPUP)
285     , mrController(rController)
286 {
287     SetSelectHdl( LINK( this, FontworkAlignmentWindow, SelectHdl ) );
288 
289     Image aImgAlgin1(StockImage::Yes, RID_SVXBMP_FONTWORK_ALIGN_LEFT);
290     Image aImgAlgin2(StockImage::Yes, RID_SVXBMP_FONTWORK_ALIGN_CENTER);
291     Image aImgAlgin3(StockImage::Yes, RID_SVXBMP_FONTWORK_ALIGN_RIGHT);
292     Image aImgAlgin4(StockImage::Yes, RID_SVXBMP_FONTWORK_ALIGN_WORD);
293     Image aImgAlgin5(StockImage::Yes, RID_SVXBMP_FONTWORK_ALIGN_STRETCH);
294 
295     appendEntry(0, SvxResId(RID_SVXSTR_ALIGN_LEFT), aImgAlgin1);
296     appendEntry(1, SvxResId(RID_SVXSTR_ALIGN_CENTER), aImgAlgin2);
297     appendEntry(2, SvxResId(RID_SVXSTR_ALIGN_RIGHT), aImgAlgin3);
298     appendEntry(3, SvxResId(RID_SVXSTR_ALIGN_WORD), aImgAlgin4);
299     appendEntry(4, SvxResId(RID_SVXSTR_ALIGN_STRETCH), aImgAlgin5);
300 
301     SetOutputSizePixel( getMenuSize() );
302 
303     AddStatusListener( gsFontworkAlignment );
304 }
305 
implSetAlignment(int nSurface,bool bEnabled)306 void FontworkAlignmentWindow::implSetAlignment( int nSurface, bool bEnabled )
307 {
308     int i;
309     for( i = 0; i < 5; i++ )
310     {
311         checkEntry( i, (i == nSurface) && bEnabled );
312         enableEntry( i, bEnabled );
313     }
314 }
315 
statusChanged(const css::frame::FeatureStateEvent & Event)316 void FontworkAlignmentWindow::statusChanged( const css::frame::FeatureStateEvent& Event )
317 {
318     if( Event.FeatureURL.Main == gsFontworkAlignment )
319     {
320         if( !Event.IsEnabled )
321         {
322             implSetAlignment( 0, false );
323         }
324         else
325         {
326             sal_Int32 nValue = 0;
327             if( Event.State >>= nValue )
328                 implSetAlignment( nValue, true );
329         }
330     }
331 }
332 
IMPL_LINK_NOARG(FontworkAlignmentWindow,SelectHdl,ToolbarMenu *,void)333 IMPL_LINK_NOARG(FontworkAlignmentWindow, SelectHdl, ToolbarMenu*, void)
334 {
335     if ( IsInPopupMode() )
336         EndPopupMode();
337 
338     sal_Int32 nAlignment = getSelectedEntryId();
339     if( nAlignment >= 0 )
340     {
341         Sequence< PropertyValue > aArgs( 1 );
342         aArgs[0].Name = OUString(gsFontworkAlignment).copy(5);
343         aArgs[0].Value <<= nAlignment;
344 
345         mrController.dispatchCommand( gsFontworkAlignment, aArgs );
346 
347         implSetAlignment( nAlignment, true );
348     }
349 }
350 
351 class FontworkAlignmentControl : public svt::PopupWindowController
352 {
353 public:
354     explicit FontworkAlignmentControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
355 
356     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
357 
358     // XInitialization
359     virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
360 
361     // XServiceInfo
362     virtual OUString SAL_CALL getImplementationName() override;
363     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
364 
365     using  svt::PopupWindowController::createPopupWindow;
366 };
367 
368 
FontworkAlignmentControl(const Reference<XComponentContext> & rxContext)369 FontworkAlignmentControl::FontworkAlignmentControl( const Reference< XComponentContext >& rxContext )
370 : svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkAlignment" )
371 {
372 }
373 
374 
createPopupWindow(vcl::Window * pParent)375 VclPtr<vcl::Window> FontworkAlignmentControl::createPopupWindow( vcl::Window* pParent )
376 {
377     return VclPtr<FontworkAlignmentWindow>::Create( *this, pParent );
378 }
379 
380 // XInitialization
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)381 void SAL_CALL FontworkAlignmentControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
382 {
383     svt::PopupWindowController::initialize( aArguments );
384 
385     ToolBox* pToolBox = nullptr;
386     sal_uInt16 nId = 0;
387     if ( getToolboxId( nId, &pToolBox ) )
388         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
389 }
390 
391 // XServiceInfo
392 
393 
getImplementationName()394 OUString FontworkAlignmentControl::getImplementationName()
395 {
396     return "com.sun.star.comp.svx.FontworkAlignmentController";
397 }
398 
399 
getSupportedServiceNames()400 Sequence< OUString > FontworkAlignmentControl::getSupportedServiceNames()
401 {
402     Sequence<OUString> aSNS { "com.sun.star.frame.ToolbarController" };
403     return aSNS;
404 }
405 
406 
407 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 &)408 com_sun_star_comp_svx_FontworkAlignmentControl_get_implementation(
409     css::uno::XComponentContext* xContext,
410     css::uno::Sequence<css::uno::Any> const &)
411 {
412     return cppu::acquire(new FontworkAlignmentControl(xContext));
413 }
414 
415 
416 class FontworkCharacterSpacingWindow : public ToolbarMenu
417 {
418 public:
419     FontworkCharacterSpacingWindow( svt::ToolboxController& rController, vcl::Window* pParentWindow );
420 
421     virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override;
422 private:
423     svt::ToolboxController& mrController;
424 
425     DECL_LINK( SelectHdl, ToolbarMenu*, void );
426 
427     void    implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled );
428     void    implSetKernCharacterPairs( bool bEnabled );
429 
430 };
431 static const OUStringLiteral gsFontworkCharacterSpacing(".uno:FontworkCharacterSpacing");
432 static const OUStringLiteral gsFontworkKernCharacterPairs(".uno:FontworkKernCharacterPairs");
433 
FontworkCharacterSpacingWindow(svt::ToolboxController & rController,vcl::Window * pParentWindow)434 FontworkCharacterSpacingWindow::FontworkCharacterSpacingWindow(svt::ToolboxController& rController, vcl::Window* pParentWindow)
435     : ToolbarMenu(rController.getFrameInterface(), pParentWindow, WB_STDPOPUP)
436     , mrController(rController)
437 {
438     SetSelectHdl( LINK( this, FontworkCharacterSpacingWindow, SelectHdl ) );
439 
440     appendEntry(0, SvxResId(RID_SVXSTR_CHARS_SPACING_VERY_TIGHT), MenuItemBits::RADIOCHECK);
441     appendEntry(1, SvxResId(RID_SVXSTR_CHARS_SPACING_TIGHT), MenuItemBits::RADIOCHECK);
442     appendEntry(2, SvxResId(RID_SVXSTR_CHARS_SPACING_NORMAL), MenuItemBits::RADIOCHECK);
443     appendEntry(3, SvxResId(RID_SVXSTR_CHARS_SPACING_LOOSE), MenuItemBits::RADIOCHECK);
444     appendEntry(4, SvxResId(RID_SVXSTR_CHARS_SPACING_VERY_LOOSE), MenuItemBits::RADIOCHECK);
445     appendEntry(5, SvxResId(RID_SVXSTR_CHARS_SPACING_CUSTOM), MenuItemBits::RADIOCHECK);
446     appendSeparator();
447     appendEntry(6, SvxResId(RID_SVXSTR_CHARS_SPACING_KERN_PAIRS), MenuItemBits::CHECKABLE);
448 
449     SetOutputSizePixel( getMenuSize() );
450 
451     AddStatusListener( gsFontworkCharacterSpacing );
452     AddStatusListener( gsFontworkKernCharacterPairs );
453 }
454 
implSetCharacterSpacing(sal_Int32 nCharacterSpacing,bool bEnabled)455 void FontworkCharacterSpacingWindow::implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled )
456 {
457     sal_Int32 i;
458     for ( i = 0; i < 6; i++ )
459     {
460         checkEntry( i, false );
461         enableEntry( i, bEnabled );
462     }
463     if ( nCharacterSpacing != -1 )
464     {
465         sal_Int32 nEntry;
466         switch( nCharacterSpacing )
467         {
468             case 80 : nEntry = 0; break;
469             case 90 : nEntry = 1; break;
470             case 100 : nEntry = 2; break;
471             case 120 : nEntry = 3; break;
472             case 150 : nEntry = 4; break;
473             default : nEntry = 5; break;
474         }
475         checkEntry( nEntry, bEnabled );
476     }
477 }
478 
479 
implSetKernCharacterPairs(bool bEnabled)480 void FontworkCharacterSpacingWindow::implSetKernCharacterPairs( bool bEnabled )
481 {
482     enableEntry( 6, bEnabled );
483     checkEntry( 6, bEnabled );
484 }
485 
486 
statusChanged(const css::frame::FeatureStateEvent & Event)487 void FontworkCharacterSpacingWindow::statusChanged( const css::frame::FeatureStateEvent& Event )
488 {
489     if( Event.FeatureURL.Main == gsFontworkCharacterSpacing )
490     {
491         if( !Event.IsEnabled )
492         {
493             implSetCharacterSpacing( 0, false );
494         }
495         else
496         {
497             sal_Int32 nValue = 0;
498             if( Event.State >>= nValue )
499                 implSetCharacterSpacing( nValue, true );
500         }
501     }
502     else if( Event.FeatureURL.Main == gsFontworkKernCharacterPairs )
503     {
504         if( !Event.IsEnabled )
505         {
506             implSetKernCharacterPairs( false );
507         }
508         else
509         {
510             bool bValue = false;
511             if( Event.State >>= bValue )
512                 implSetKernCharacterPairs( true );
513         }
514     }
515 }
516 
517 
IMPL_LINK_NOARG(FontworkCharacterSpacingWindow,SelectHdl,ToolbarMenu *,void)518 IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, SelectHdl,ToolbarMenu*, void)
519 {
520     if ( IsInPopupMode() )
521         EndPopupMode();
522 
523     sal_Int32 nSelection = getSelectedEntryId();
524     sal_Int32 nCharacterSpacing;
525     switch( nSelection )
526     {
527         case 0 : nCharacterSpacing = 80; break;
528         case 1 : nCharacterSpacing = 90; break;
529         case 2 : nCharacterSpacing = 100; break;
530         case 3 : nCharacterSpacing = 120; break;
531         case 4 : nCharacterSpacing = 150; break;
532         default : nCharacterSpacing = 100; break;
533     }
534     if ( nSelection == 5 )  // custom spacing
535     {
536         Sequence< PropertyValue > aArgs( 1 );
537         aArgs[0].Name = OUString(gsFontworkCharacterSpacing).copy(5);
538         aArgs[0].Value <<= nCharacterSpacing;
539 
540         mrController.dispatchCommand( ".uno:FontworkCharacterSpacingDialog", aArgs );
541     }
542     else if ( nSelection == 6 ) // KernCharacterPairs
543     {
544         Sequence< PropertyValue > aArgs( 1 );
545         aArgs[0].Name = OUString(gsFontworkKernCharacterPairs).copy(5);
546         aArgs[0].Value <<= true;
547 
548         mrController.dispatchCommand( gsFontworkKernCharacterPairs, aArgs );
549 
550         implSetKernCharacterPairs( true );
551     }
552     else if( nSelection >= 0 )
553     {
554         Sequence< PropertyValue > aArgs( 1 );
555         aArgs[0].Name = OUString(gsFontworkCharacterSpacing).copy(5);
556         aArgs[0].Value <<= nCharacterSpacing;
557 
558         mrController.dispatchCommand( gsFontworkCharacterSpacing,  aArgs );
559 
560         implSetCharacterSpacing( nCharacterSpacing, true );
561     }
562 }
563 
564 class FontworkCharacterSpacingControl : public svt::PopupWindowController
565 {
566 public:
567     explicit FontworkCharacterSpacingControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
568 
569     virtual VclPtr<vcl::Window> createPopupWindow( vcl::Window* pParent ) override;
570 
571     // XInitialization
572     virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
573 
574     // XServiceInfo
575     virtual OUString SAL_CALL getImplementationName() override;
576     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
577 
578     using svt::PopupWindowController::createPopupWindow;
579 };
580 
581 
FontworkCharacterSpacingControl(const Reference<XComponentContext> & rxContext)582 FontworkCharacterSpacingControl::FontworkCharacterSpacingControl( const Reference< XComponentContext >& rxContext )
583 : svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkCharacterSpacingFloater" )
584 {
585 }
586 
587 
createPopupWindow(vcl::Window * pParent)588 VclPtr<vcl::Window> FontworkCharacterSpacingControl::createPopupWindow( vcl::Window* pParent )
589 {
590     return VclPtr<FontworkCharacterSpacingWindow>::Create( *this, pParent );
591 }
592 
593 // XInitialization
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)594 void SAL_CALL FontworkCharacterSpacingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
595 {
596     svt::PopupWindowController::initialize( aArguments );
597 
598     ToolBox* pToolBox = nullptr;
599     sal_uInt16 nId = 0;
600     if ( getToolboxId( nId, &pToolBox ) )
601         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
602 }
603 
604 // XServiceInfo
605 
606 
getImplementationName()607 OUString FontworkCharacterSpacingControl::getImplementationName()
608 {
609     return "com.sun.star.comp.svx.FontworkCharacterSpacingController";
610 }
611 
612 
getSupportedServiceNames()613 Sequence< OUString > FontworkCharacterSpacingControl::getSupportedServiceNames()
614 {
615     Sequence<OUString> aSNS { "com.sun.star.frame.ToolbarController" };
616     return aSNS;
617 }
618 
619 
620 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 &)621 com_sun_star_comp_svx_FontworkCharacterSpacingControl_get_implementation(
622     css::uno::XComponentContext* xContext,
623     css::uno::Sequence<css::uno::Any> const &)
624 {
625     return cppu::acquire(new FontworkCharacterSpacingControl(xContext));
626 }
627 
FontworkCharacterSpacingDialog(weld::Window * pParent,sal_Int32 nScale)628 FontworkCharacterSpacingDialog::FontworkCharacterSpacingDialog(weld::Window* pParent, sal_Int32 nScale)
629     : GenericDialogController(pParent, "svx/ui/fontworkspacingdialog.ui", "FontworkSpacingDialog")
630     , m_xMtrScale(m_xBuilder->weld_metric_spin_button("entry", FieldUnit::PERCENT))
631 {
632     m_xMtrScale->set_value(nScale, FieldUnit::PERCENT);
633 }
634 
~FontworkCharacterSpacingDialog()635 FontworkCharacterSpacingDialog::~FontworkCharacterSpacingDialog()
636 {
637 }
638 
getScale() const639 sal_Int32 FontworkCharacterSpacingDialog::getScale() const
640 {
641     return static_cast<sal_Int32>(m_xMtrScale->get_value(FieldUnit::PERCENT));
642 }
643 
644 }
645 
646 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
647