LibreOffice Module svx (master) 1
fontworkgallery.cxx
Go to the documentation of this file.
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 <comphelper/lok.hxx>
25
26#include <vcl/toolbox.hxx>
27#include <vcl/virdev.hxx>
28
29#include <sfx2/viewsh.hxx>
30
31#include <svl/itempool.hxx>
32
35
36#include <svx/fmmodel.hxx>
37#include <svx/svdpage.hxx>
38#include <svx/svdobj.hxx>
39#include <svx/svdview.hxx>
40
41#include <svx/gallery.hxx>
43
45
46#include <algorithm>
47#include <memory>
48
49using namespace ::com::sun::star::uno;
50using namespace ::com::sun::star::lang;
51using namespace ::com::sun::star::beans;
52
53namespace svx
54{
55
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"))
64{
65 Size aSize(530, 400);
66 maCtlFavorites->set_size_request(aSize.Width(), aSize.Height());
67
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));
71
74}
75
77{
78}
79
80void FontWorkGalleryDialog::initFavorites(sal_uInt16 nThemeId)
81{
82 // the favorites are read via the gallery
83 sal_uInt32 nFavCount = GalleryExplorer::GetSdrObjCount( nThemeId );
84
85 // lock gallery theme
87
88 sal_uInt32 nModelPos;
89 FmFormModel *pModel = nullptr;
90
91 for( nModelPos = 0; nModelPos < nFavCount; nModelPos++ )
92 {
93 BitmapEx aThumb;
94
95 if (GalleryExplorer::GetSdrObj(nThemeId, nModelPos, pModel, &aThumb) && !aThumb.IsEmpty())
96 {
98 const Point aNull(0, 0);
99
100 if (pVDev->GetDPIScaleFactor() > 1)
101 aThumb.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor());
102
103 const Size aSize(aThumb.GetSizePixel());
104
105 pVDev->SetOutputSizePixel(aSize);
106
107 static const sal_uInt32 nLen(8);
108 static const Color aW(COL_WHITE);
109 static const Color aG(0xef, 0xef, 0xef);
110
111 pVDev->DrawCheckered(aNull, aSize, nLen, aW, aG);
112
113 pVDev->DrawBitmapEx(aNull, aThumb);
114 maFavoritesHorizontal.emplace_back(pVDev);
115 }
116 }
117
118 // release gallery theme
120}
121
123{
124 mnThemeId = nThemeId;
125
126 auto nFavCount = maFavoritesHorizontal.size();
127
128 maCtlFavorites->clear();
129 maIdToTitleMap.clear();
130
131 std::vector<OUString> aTitles;
132 (void)GalleryExplorer::FillObjListTitle(nThemeId, aTitles);
133 assert(aTitles.size() == nFavCount);
134
135 for( size_t nFavorite = 1; nFavorite <= nFavCount; nFavorite++ )
136 {
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);
140 }
141
142 if (maCtlFavorites->n_children())
143 maCtlFavorites->select(0);
144}
145
147{
148 mbInsertIntoPage = false;
149 mpDestModel = pModel;
150}
151
153{
154 OUString sItemId = maCtlFavorites->get_selected_id();
155 if (sItemId.isEmpty())
156 return;
157
158 sal_Int32 nItemId = sItemId.toInt32();
159
160 if (nItemId == 0)
161 return;
162
163 FmFormModel aModel;
164 aModel.GetItemPool().FreezeIdRanges();
165
166 if( !GalleryExplorer::GetSdrObj( mnThemeId, nItemId-1, &aModel ) )
167 return;
168
169 SdrPage* pPage = aModel.GetPage(0);
170 if( !(pPage && pPage->GetObjCount()) )
171 return;
172
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);
180
181 // center shape on current view
183
184 if (!pOutDev)
185 return;
186
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()));
191
192 pNewObject->MakeNameUnique();
193
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);
205
206 tools::Rectangle aObjRect( pNewObject->GetLogicRect() );
207 Point aPagePos;
208 Size aFontworkSize = aObjRect.GetSize();
209
211 {
212 SfxViewShell* pViewShell = SfxViewShell::Current();
213
214 aPagePos = pViewShell->getLOKVisibleArea().Center();
215
216 aPagePos.setX(convertTwipToMm100(aPagePos.X()));
217 aPagePos.setY(convertTwipToMm100(aPagePos.Y()));
218
219 sal_Int32 nLOKViewWidth = 0.8 * convertTwipToMm100(pViewShell->getLOKVisibleArea().getOpenWidth());
220 if (aFontworkSize.getWidth() > nLOKViewWidth)
221 {
222 double fScale = static_cast<double>(aFontworkSize.getWidth()) / nLOKViewWidth;
223 aFontworkSize.setWidth(aFontworkSize.getWidth() / fScale);
224 aFontworkSize.setHeight(aFontworkSize.getHeight() / fScale);
225 }
226 }
227 else
228 {
229 Size aSize = pOutDev->GetOutputSizePixel();
230 tools::Rectangle aPixelVisRect(Point(0,0), aSize);
231 tools::Rectangle aVisArea = pOutDev->PixelToLogic(aPixelVisRect);
232
233 aPagePos = aVisArea.Center();
234 }
235
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) );
240
241 tools::Rectangle aNewObjectRectangle(aPagePos, aFontworkSize);
242 pNewObject->SetLogicRect(aNewObjectRectangle);
243
244 if (bUseSpecialCalcMode)
245 {
246 mxSdrObject = pNewObject;
247 }
248 else
249 {
251
252 if (nullptr != pPV)
253 {
254 mrSdrView.InsertObjectAtView( pNewObject.get(), *pPV );
255 }
256 }
257}
258
260{
261 insertSelectedFontwork();
262 m_xDialog->response(RET_OK);
263}
264
266{
267 insertSelectedFontwork();
268 m_xDialog->response(RET_OK);
269 return true;
270}
271
272IMPL_LINK(FontWorkGalleryDialog, QueryTooltipHandler, const weld::TreeIter&, iter, OUString)
273{
274 const OUString id = maCtlFavorites->get_id(iter);
275 auto it = maIdToTitleMap.find(id);
276 return it != maIdToTitleMap.end() ? it->second : OUString();
277}
278
279namespace {
280
281class FontworkAlignmentWindow final : public WeldToolbarPopup
282{
283public:
284 FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow);
285 virtual void GrabFocus() override
286 {
287 mxLeft->grab_focus();
288 }
289 virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override;
290
291private:
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;
298
299 DECL_LINK( SelectHdl, weld::Toggleable&, void );
300
301 void implSetAlignment( int nAlignmentMode, bool bEnabled );
302};
303
304}
305
306constexpr OUStringLiteral gsFontworkAlignment(u".uno:FontworkAlignment");
307
308FontworkAlignmentWindow::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)
316{
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));
321
322 AddStatusListener( gsFontworkAlignment );
323}
324
325void FontworkAlignmentWindow::implSetAlignment( int nSurface, bool bEnabled )
326{
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;
341}
342
343void FontworkAlignmentWindow::statusChanged( const css::frame::FeatureStateEvent& Event )
344{
345 if( Event.FeatureURL.Main != gsFontworkAlignment )
346 return;
347
348 if( !Event.IsEnabled )
349 {
350 implSetAlignment( 0, false );
351 }
352 else
353 {
354 sal_Int32 nValue = 0;
355 if( Event.State >>= nValue )
356 implSetAlignment( nValue, true );
357 }
358}
359
360IMPL_LINK(FontworkAlignmentWindow, SelectHdl, weld::Toggleable&, rButton, void)
361{
362 if (mbSettingValue || !rButton.get_active())
363 return;
364
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;
377
378 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
379 OUString(gsFontworkAlignment).copy(5), nAlignment) };
380
381 mxControl->dispatchCommand( gsFontworkAlignment, aArgs );
382
383 implSetAlignment( nAlignment, true );
384
385 mxControl->EndPopupMode();
386}
387
388namespace {
389
390class FontworkAlignmentControl : public svt::PopupWindowController
391{
392public:
393 explicit FontworkAlignmentControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
394
395 virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
396 virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override;
397
398 // XInitialization
399 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
400
401 // XServiceInfo
402 virtual OUString SAL_CALL getImplementationName() override;
403 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
404};
405
406}
407
408FontworkAlignmentControl::FontworkAlignmentControl( const Reference< XComponentContext >& rxContext )
409: svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkAlignment" )
410{
411}
412
413std::unique_ptr<WeldToolbarPopup> FontworkAlignmentControl::weldPopupWindow()
414{
415 return std::make_unique<FontworkAlignmentWindow>(this, m_pToolbar);
416}
417
418VclPtr<vcl::Window> FontworkAlignmentControl::createVclPopupWindow( vcl::Window* pParent )
419{
420 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
421 std::make_unique<FontworkAlignmentWindow>(this, pParent->GetFrameWeld()));
422
423 mxInterimPopover->Show();
424
425 return mxInterimPopover;
426}
427
428// XInitialization
429void SAL_CALL FontworkAlignmentControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
430{
431 svt::PopupWindowController::initialize( aArguments );
432
433 if (m_pToolbar)
434 {
435 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
436 m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel());
437 }
438
439 ToolBox* pToolBox = nullptr;
441 if ( getToolboxId( nId, &pToolBox ) )
442 pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
443}
444
445// XServiceInfo
446
447
448OUString FontworkAlignmentControl::getImplementationName()
449{
450 return "com.sun.star.comp.svx.FontworkAlignmentController";
451}
452
453
454Sequence< OUString > FontworkAlignmentControl::getSupportedServiceNames()
455{
456 return { "com.sun.star.frame.ToolbarController" };
457}
458
459
460extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
462 css::uno::XComponentContext* xContext,
463 css::uno::Sequence<css::uno::Any> const &)
464{
465 return cppu::acquire(new FontworkAlignmentControl(xContext));
466}
467
468namespace {
469
470class FontworkCharacterSpacingWindow final : public WeldToolbarPopup
471{
472public:
473 FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow);
474 virtual void GrabFocus() override;
475
476 virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override;
477private:
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;
489
490 DECL_LINK( KernSelectHdl, weld::Toggleable&, void );
491 DECL_LINK( SelectHdl, weld::Toggleable&, void );
492 DECL_LINK( MouseReleaseHdl, const MouseEvent&, bool );
493
494 void implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled );
495 void implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled);
496 void DispatchSpacingDialog();
497};
498
499}
500
501constexpr OUStringLiteral gsFontworkCharacterSpacing(u".uno:FontworkCharacterSpacing");
502constexpr OUStringLiteral gsFontworkKernCharacterPairs(u".uno:FontworkKernCharacterPairs");
503
504FontworkCharacterSpacingWindow::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)
517{
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));
525
526 mxKernPairs->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, KernSelectHdl));
527
528 AddStatusListener( gsFontworkCharacterSpacing );
529 AddStatusListener( gsFontworkKernCharacterPairs );
530
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();
534}
535
536void FontworkCharacterSpacingWindow::GrabFocus()
537{
538 mxVeryTight->grab_focus();
539}
540
541void FontworkCharacterSpacingWindow::implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled )
542{
543 bool bSettingValue = mbSettingValue;
544 mbSettingValue = true;
545
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);
552
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);
559
560 switch(nCharacterSpacing)
561 {
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;
577 }
578
579 mnCharacterSpacing = nCharacterSpacing;
580
581 mbSettingValue = bSettingValue;
582}
583
584void FontworkCharacterSpacingWindow::implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled)
585{
586 mxKernPairs->set_sensitive(bEnabled);
587 mxKernPairs->set_active(bKernOnOff);
588}
589
590void FontworkCharacterSpacingWindow::statusChanged( const css::frame::FeatureStateEvent& Event )
591{
592 if( Event.FeatureURL.Main == gsFontworkCharacterSpacing )
593 {
594 if( !Event.IsEnabled )
595 {
596 implSetCharacterSpacing( 0, false );
597 }
598 else
599 {
600 sal_Int32 nValue = 0;
601 if( Event.State >>= nValue )
602 implSetCharacterSpacing( nValue, true );
603 }
604 }
605 else if( Event.FeatureURL.Main == gsFontworkKernCharacterPairs )
606 {
607 if( !Event.IsEnabled )
608 {
609 implSetKernCharacterPairs(false, false);
610 }
611 else
612 {
613 bool bValue = false;
614 if( Event.State >>= bValue )
615 implSetKernCharacterPairs(bValue, true);
616 }
617 }
618}
619
620IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, KernSelectHdl, weld::Toggleable&, void)
621{
622 if (mbSettingValue)
623 return;
624
625 bool bKernOnOff = mxKernPairs->get_active();
626 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
627 OUString(gsFontworkKernCharacterPairs).copy(5), bKernOnOff) };
628
629 mxControl->dispatchCommand( gsFontworkKernCharacterPairs, aArgs );
630 mbCommandDispatched = true;
631
632 implSetKernCharacterPairs(bKernOnOff, true);
633
634 mxControl->EndPopupMode();
635}
636
637void FontworkCharacterSpacingWindow::DispatchSpacingDialog()
638{
639 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
640 OUString(gsFontworkCharacterSpacing).copy(5), mnCharacterSpacing) };
641
643 xControl->EndPopupMode();
644 xControl->dispatchCommand(".uno:FontworkCharacterSpacingDialog", aArgs);
645 mbCommandDispatched = true;
646}
647
648IMPL_LINK(FontworkCharacterSpacingWindow, SelectHdl, weld::Toggleable&, rButton, void)
649{
650 if (!rButton.get_active())
651 return;
652
653 if (mbSettingValue)
654 return;
655
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;
661
662 if (mxCustom->get_active())
663 DispatchSpacingDialog();
664 else
665 {
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;
677
678 Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(
679 OUString(gsFontworkCharacterSpacing).copy(5), nCharacterSpacing) };
680
681 mxControl->dispatchCommand( gsFontworkCharacterSpacing, aArgs );
682 mbCommandDispatched = true;
683
684 implSetCharacterSpacing( nCharacterSpacing, true );
685 }
686
687 mxControl->EndPopupMode();
688}
689
690IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, MouseReleaseHdl, const MouseEvent&, bool)
691{
692 /*
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.
696
697 So if that happens launch the custom spacing dialog explicitly here on
698 mouse release.
699 */
700 if (mxCustom->get_active() && !mbCommandDispatched)
701 {
702 DispatchSpacingDialog();
703 return true;
704 }
705 return false;
706}
707
708namespace {
709
710class FontworkCharacterSpacingControl : public svt::PopupWindowController
711{
712public:
713 explicit FontworkCharacterSpacingControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
714
715 virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override;
716 virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override;
717
718 // XInitialization
719 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
720
721 // XServiceInfo
722 virtual OUString SAL_CALL getImplementationName() override;
723 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
724};
725
726}
727
728FontworkCharacterSpacingControl::FontworkCharacterSpacingControl( const Reference< XComponentContext >& rxContext )
729: svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkCharacterSpacingFloater" )
730{
731}
732
733std::unique_ptr<WeldToolbarPopup> FontworkCharacterSpacingControl::weldPopupWindow()
734{
735 return std::make_unique<FontworkCharacterSpacingWindow>(this, m_pToolbar);
736}
737
738VclPtr<vcl::Window> FontworkCharacterSpacingControl::createVclPopupWindow( vcl::Window* pParent )
739{
740 mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
741 std::make_unique<FontworkCharacterSpacingWindow>(this, pParent->GetFrameWeld()));
742
743 mxInterimPopover->Show();
744
745 return mxInterimPopover;
746}
747
748// XInitialization
749void SAL_CALL FontworkCharacterSpacingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
750{
751 svt::PopupWindowController::initialize( aArguments );
752
753 if (m_pToolbar)
754 {
755 mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar));
756 m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel());
757 }
758
759 ToolBox* pToolBox = nullptr;
761 if ( getToolboxId( nId, &pToolBox ) )
762 pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
763}
764
765// XServiceInfo
766
767
768OUString FontworkCharacterSpacingControl::getImplementationName()
769{
770 return "com.sun.star.comp.svx.FontworkCharacterSpacingController";
771}
772
773
774Sequence< OUString > FontworkCharacterSpacingControl::getSupportedServiceNames()
775{
776 Sequence<OUString> aSNS { "com.sun.star.frame.ToolbarController" };
777 return aSNS;
778}
779
780
781extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
783 css::uno::XComponentContext* xContext,
784 css::uno::Sequence<css::uno::Any> const &)
785{
786 return cppu::acquire(new FontworkCharacterSpacingControl(xContext));
787}
788
789FontworkCharacterSpacingDialog::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))
792{
793 m_xMtrScale->set_value(nScale, FieldUnit::PERCENT);
794}
795
797{
798}
799
801{
802 return static_cast<sal_Int32>(m_xMtrScale->get_value(FieldUnit::PERCENT));
803}
804
805}
806
807/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr auto convertTwipToMm100(N n)
Reference< XExecutableDialog > m_xDialog
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
bool IsEmpty() const
const Size & GetSizePixel() const
static bool EndLocking(std::u16string_view rThemeName)
Definition: galexpl.cxx:264
static sal_uInt32 GetSdrObjCount(std::u16string_view rThemeName)
Definition: galexpl.cxx:168
static bool FillObjListTitle(const sal_uInt32 nThemeId, std::vector< OUString > &rList)
Definition: galexpl.cxx:85
static bool GetSdrObj(std::u16string_view rThemeName, sal_uInt32 nSdrModelPos, SdrModel *pModel, BitmapEx *pThumb=nullptr)
Definition: galexpl.cxx:197
static bool BeginLocking(std::u16string_view rThemeName)
Definition: galexpl.cxx:239
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Size GetOutputSizePixel() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
constexpr tools::Long getX() const
constexpr tools::Long getY() const
bool InsertObjectAtView(SdrObject *pObj, SdrPageView &rPV, SdrInsertFlags nOptions=SdrInsertFlags::NONE)
Definition: svdedtv.cxx:978
const SfxItemPool & GetItemPool() const
Definition: svdmodel.hxx:318
const SdrPage * GetPage(sal_uInt16 nPgNum) const
Definition: svdmodel.cxx:1860
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:785
size_t GetObjCount() const
Definition: svdpage.cxx:779
virtual rtl::Reference< SdrObject > CloneSdrObject(SdrModel &rTargetModel) const =0
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:379
OutputDevice * GetFirstOutputDevice() const
Definition: svdpntv.cxx:91
SdrModel & getSdrModelFromSdrView() const
Definition: svdpntv.hxx:280
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:323
void FreezeIdRanges()
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
virtual tools::Rectangle getLOKVisibleArea() const
constexpr tools::Long getHeight() const
constexpr tools::Long Height() const
constexpr tools::Long getWidth() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
ToolBoxItemBits GetItemBits(ToolBoxItemId nItemId) const
void SetItemBits(ToolBoxItemId nItemId, ToolBoxItemBits nBits)
static VclPtr< reference_type > Create(Arg &&... arg)
virtual void GrabFocus()=0
virtual void statusChanged(const css::frame::FeatureStateEvent &Event)
virtual std::unique_ptr< WeldToolbarPopup > weldPopupWindow()=0
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override=0
virtual VclPtr< vcl::Window > createVclPopupWindow(vcl::Window *pParent)
virtual OUString SAL_CALL getImplementationName() override=0
std::unique_ptr< weld::IconView > maCtlFavorites
FontWorkGalleryDialog(weld::Window *pParent, SdrView &rView)
void initFavorites(sal_uInt16 nThemeId)
void SetSdrObjectRef(SdrModel *pModel)
std::unique_ptr< weld::Button > mxOKButton
std::map< OUString, OUString > maIdToTitleMap
void fillFavorites(sal_uInt16 nThemeId)
std::vector< VclPtr< VirtualDevice > > maFavoritesHorizontal
rtl::Reference< SdrObject > mxSdrObject
virtual ~FontWorkGalleryDialog() override
virtual ~FontworkCharacterSpacingDialog() override
std::unique_ptr< weld::MetricSpinButton > m_xMtrScale
constexpr Point Center() const
constexpr Size GetSize() const
tools::Long getOpenWidth() const
weld::Window * GetFrameWeld() const
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
FieldUnit
sal_Int16 nValue
Definition: fmsrccfg.cxx:81
#define GALLERY_THEME_FONTWORK
Definition: gallery.hxx:38
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
Reference
void copy(const fs::path &src, const fs::path &dest)
IMPL_LINK(HangulHanjaConversionDialog, ClickByCharacterHdl, weld::Toggleable &, rBox, void)
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 &)
IMPL_LINK(FontworkCharacterSpacingWindow, SelectHdl, weld::Toggleable &, rButton, void)
constexpr OUStringLiteral gsFontworkCharacterSpacing(u".uno:FontworkCharacterSpacing")
constexpr OUStringLiteral gsFontworkKernCharacterPairs(u".uno:FontworkKernCharacterPairs")
IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, MouseReleaseHdl, const MouseEvent &, bool)
IMPL_LINK_NOARG(SuggestionDisplay, SelectSuggestionValueSetHdl, ValueSet *, void)
constexpr OUStringLiteral gsFontworkAlignment(u".uno:FontworkAlignment")
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 &)
sal_Int16 nId
OUString sId
constexpr OUStringLiteral PERCENT(u"Percent")
RET_OK