LibreOffice Module svx (master)  1
fillctrl.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 #include <sfx2/dispatch.hxx>
21 #include <sfx2/objsh.hxx>
22 #include <sfx2/viewsh.hxx>
23 #include <rtl/ustring.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/toolbox.hxx>
27 #include <vcl/virdev.hxx>
28 #include <svx/svxids.hrc>
29 #include <tools/json_writer.hxx>
30 
31 constexpr OUStringLiteral TMP_STR_BEGIN = u"[";
32 constexpr OUStringLiteral TMP_STR_END = u"]";
33 
34 #include <svx/drawitem.hxx>
35 #include <svx/xfillit0.hxx>
36 #include <svx/xtable.hxx>
37 #include <svx/fillctrl.hxx>
38 #include <svx/itemwin.hxx>
39 #include <svx/xflclit.hxx>
40 #include <svx/xflgrit.hxx>
41 #include <svx/xflhtit.hxx>
42 #include <svx/xbtmpit.hxx>
43 #include <memory>
44 
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::util;
48 using namespace ::com::sun::star::beans;
49 using namespace ::com::sun::star::lang;
50 
51 namespace {
52 
54 {
55  NONE,
56  SOLID,
57  GRADIENT,
58  HATCH,
59  BITMAP,
60  PATTERN
61 };
62 
63 drawing::FillStyle toCssFillStyle( eFillStyle eXFS )
64 {
65  if (eXFS == PATTERN)
66  {
67  return drawing::FillStyle_BITMAP;
68  }
69 
70  return static_cast<drawing::FillStyle>(eXFS);
71 }
72 
73 }
74 
76 
78  sal_uInt16 nSlotId,
79  ToolBoxItemId nId,
80  ToolBox& rTbx )
81  : SfxToolBoxControl( nSlotId, nId, rTbx )
82  , mxFillControl(nullptr)
83  , mpLbFillType(nullptr)
84  , mpToolBoxColor(nullptr)
85  , mpLbFillAttr(nullptr)
86  , mnLastXFS(-1)
87  , mnLastPosGradient(0)
88  , mnLastPosHatch(0)
89  , mnLastPosBitmap(0)
90  , mnLastPosPattern(0)
91 {
92  addStatusListener( ".uno:FillColor");
93  addStatusListener( ".uno:FillGradient");
94  addStatusListener( ".uno:FillHatch");
95  addStatusListener( ".uno:FillBitmap");
96  addStatusListener( ".uno:ColorTableState");
97  addStatusListener( ".uno:GradientListState");
98  addStatusListener( ".uno:HatchListState");
99  addStatusListener( ".uno:BitmapListState");
100 }
101 
103 {
104 }
105 
107  sal_uInt16 nSID,
108  SfxItemState eState,
109  const SfxPoolItem* pState)
110 {
111  const bool bDisabled(SfxItemState::DISABLED == eState);
112 
113  switch(nSID)
114  {
115  case SID_ATTR_FILL_STYLE:
116  {
117  if(bDisabled)
118  {
119  mpLbFillType->set_sensitive(false);
121  mpLbFillAttr->show();
122  mpLbFillAttr->set_sensitive(false);
124  mpToolBoxColor->hide();
125  mnLastXFS = -1;
126  mpStyleItem.reset();
127  }
128 
129  if(eState >= SfxItemState::DEFAULT)
130  {
131  const XFillStyleItem* pItem = dynamic_cast< const XFillStyleItem* >(pState);
132 
133  if(pItem)
134  {
135  mpStyleItem.reset(pItem->Clone());
137  drawing::FillStyle eXFS = mpStyleItem->GetValue();
138  mnLastXFS = sal::static_int_cast< sal_Int32 >(eXFS);
140 
141  if(drawing::FillStyle_NONE == eXFS)
142  {
144  mpLbFillAttr->set_sensitive(false);
145  }
146 
147  Update();
148  break;
149  }
150  }
151 
153  mpLbFillAttr->show();
154  mpLbFillAttr->set_sensitive(false);
156  mpToolBoxColor->hide();
157  mnLastXFS = -1;
158  mpStyleItem.reset();
160  break;
161  }
162  case SID_ATTR_FILL_COLOR:
163  {
164  if(SfxItemState::DEFAULT == eState)
165  {
166  mpColorItem.reset(pState ? static_cast<XFillColorItem*>(pState->Clone()) : nullptr);
167  }
168 
169  if(mpStyleItem && drawing::FillStyle_SOLID == mpStyleItem->GetValue())
170  {
171  mpLbFillAttr->hide();
172  mpToolBoxColor->show();
174 
175  Update();
176  }
177  break;
178  }
179  case SID_ATTR_FILL_GRADIENT:
180  {
181  if(SfxItemState::DEFAULT == eState)
182  {
183  mpFillGradientItem.reset(pState ? static_cast<XFillGradientItem*>(pState->Clone()) : nullptr);
184  }
185 
186  if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue())
187  {
188  mpLbFillAttr->show();
189  mpToolBoxColor->hide();
191 
192  if(SfxItemState::DEFAULT == eState)
193  {
195  Update();
196  }
197  else if(SfxItemState::DISABLED == eState )
198  {
199  mpLbFillAttr->set_sensitive(false);
201  }
202  else
203  {
205  }
206  }
207  break;
208  }
209  case SID_ATTR_FILL_HATCH:
210  {
211  if(SfxItemState::DEFAULT == eState)
212  {
213  mpHatchItem.reset(pState ? static_cast<XFillHatchItem*>(pState->Clone()) : nullptr);
214  }
215 
216  if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue())
217  {
218  mpLbFillAttr->show();
219  mpToolBoxColor->hide();
221 
222  if(SfxItemState::DEFAULT == eState)
223  {
225  Update();
226  }
227  else if(SfxItemState::DISABLED == eState )
228  {
229  mpLbFillAttr->set_sensitive(false);
231  }
232  else
233  {
235  }
236  }
237  break;
238  }
239  case SID_ATTR_FILL_BITMAP:
240  {
241  if(SfxItemState::DEFAULT == eState)
242  {
243  mpBitmapItem.reset(pState ? static_cast<XFillBitmapItem*>(pState->Clone()) : nullptr);
244  }
245 
246  if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue())
247  {
248  mpLbFillAttr->show();
249  mpToolBoxColor->hide();
251 
252  if(SfxItemState::DEFAULT == eState)
253  {
255  Update();
256  }
257  else if(SfxItemState::DISABLED == eState )
258  {
259  mpLbFillAttr->set_sensitive(false);
261  }
262  else
263  {
265  }
266  }
267  break;
268  }
269  case SID_GRADIENT_LIST:
270  {
271  if(SfxItemState::DEFAULT == eState)
272  {
273  if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue())
274  {
276  {
277  const OUString aString( mpFillGradientItem->GetName() );
279 
280  mpLbFillAttr->clear();
282  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
283  mpLbFillAttr->set_active_text(aString);
284  }
285  else
286  {
288  }
289  }
290  }
291  break;
292  }
293  case SID_HATCH_LIST:
294  {
295  if(SfxItemState::DEFAULT == eState)
296  {
297  if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue())
298  {
299  if(mpHatchItem)
300  {
301  const OUString aString( mpHatchItem->GetName() );
303 
304  mpLbFillAttr->clear();
306  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
307  mpLbFillAttr->set_active_text(aString);
308  }
309  else
310  {
312  }
313  }
314  }
315  break;
316  }
317  case SID_BITMAP_LIST:
318  {
319  if(SfxItemState::DEFAULT == eState)
320  {
321  if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue())
322  {
323  if(mpBitmapItem)
324  {
325  const OUString aString( mpBitmapItem->GetName() );
327 
328  mpLbFillAttr->clear();
330  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
331  mpLbFillAttr->set_active_text(aString);
332  }
333  else
334  {
336  }
337  }
338  }
339  break;
340  }
341  }
342 }
343 
345 {
346  if(!mpStyleItem)
347  return;
348 
349  const drawing::FillStyle eXFS = mpStyleItem->GetValue();
351 
352  switch( eXFS )
353  {
354  case drawing::FillStyle_NONE:
355  {
356  mpLbFillAttr->show();
357  mpToolBoxColor->hide();
359  break;
360  }
361  case drawing::FillStyle_SOLID:
362  {
363  if(mpColorItem)
364  {
365  mpLbFillAttr->hide();
366  mpToolBoxColor->show();
368  }
369  break;
370  }
371  case drawing::FillStyle_GRADIENT:
372  {
373  mpLbFillAttr->show();
374  mpToolBoxColor->hide();
376 
377  if(pSh && pSh->GetItem(SID_GRADIENT_LIST))
378  {
380  mpLbFillAttr->clear();
381  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
382 
384  {
385  const OUString aString(mpFillGradientItem->GetName());
386 
387  mpLbFillAttr->set_active_text(aString);
388 
389  // Check if the entry is not in the list
390  if (mpLbFillAttr->get_active_text() != aString)
391  {
392  sal_Int32 nCount = mpLbFillAttr->get_count();
393  OUString aTmpStr;
394  if( nCount > 0 )
395  {
396  // Last entry gets tested against temporary entry
397  aTmpStr = mpLbFillAttr->get_text( nCount - 1 );
398  if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
399  aTmpStr.endsWith(TMP_STR_END) )
400  {
401  mpLbFillAttr->remove(nCount - 1);
402  }
403  }
404  aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
405 
406  rtl::Reference<XGradientList> xGradientList = new XGradientList( "", ""/*TODO?*/ );
407  xGradientList->Insert(std::make_unique<XGradientEntry>(mpFillGradientItem->GetGradientValue(), aTmpStr));
408  xGradientList->SetDirty( false );
409  const BitmapEx aBmp = xGradientList->GetUiBitmap( 0 );
410 
411  if (!aBmp.IsEmpty())
412  {
414  const Size aBmpSize(aBmp.GetSizePixel());
415  pVD->SetOutputSizePixel(aBmpSize, false);
416  pVD->DrawBitmapEx(Point(), aBmp);
417  mpLbFillAttr->append("", xGradientList->Get(0)->GetName(), *pVD);
419  }
420  }
421 
422  }
423  else
424  {
426  }
427  }
428  else
429  {
431  }
432  break;
433  }
434  case drawing::FillStyle_HATCH:
435  {
436  mpLbFillAttr->show();
437  mpToolBoxColor->hide();
439 
440  if(pSh && pSh->GetItem(SID_HATCH_LIST))
441  {
443  mpLbFillAttr->clear();
444  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
445 
446  if(mpHatchItem)
447  {
448  const OUString aString(mpHatchItem->GetName());
449 
450  mpLbFillAttr->set_active_text( aString );
451 
452  // Check if the entry is not in the list
453  if( mpLbFillAttr->get_active_text() != aString )
454  {
455  const sal_Int32 nCount = mpLbFillAttr->get_count();
456  OUString aTmpStr;
457  if( nCount > 0 )
458  {
459  // Last entry gets tested against temporary entry
460  aTmpStr = mpLbFillAttr->get_text( nCount - 1 );
461  if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
462  aTmpStr.endsWith(TMP_STR_END) )
463  {
464  mpLbFillAttr->remove( nCount - 1 );
465  }
466  }
467  aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
468 
469  rtl::Reference<XHatchList> xHatchList = new XHatchList( "", ""/*TODO?*/ );
470  xHatchList->Insert(std::make_unique<XHatchEntry>(mpHatchItem->GetHatchValue(), aTmpStr));
471  xHatchList->SetDirty( false );
472  const BitmapEx & aBmp = xHatchList->GetUiBitmap( 0 );
473 
474  if( !aBmp.IsEmpty() )
475  {
477  const Size aBmpSize(aBmp.GetSizePixel());
478  pVD->SetOutputSizePixel(aBmpSize, false);
479  pVD->DrawBitmapEx(Point(), aBmp);
480  mpLbFillAttr->append("", xHatchList->GetHatch(0)->GetName(), *pVD);
482  }
483  }
484  }
485  else
486  {
488  }
489  }
490  else
491  {
493  }
494  break;
495  }
496  case drawing::FillStyle_BITMAP:
497  {
498  mpLbFillAttr->show();
499  mpToolBoxColor->hide();
501 
502  if(pSh)
503  {
505  mpLbFillAttr->clear();
506 
507  if(mpBitmapItem && !mpBitmapItem->isPattern() && pSh->GetItem(SID_BITMAP_LIST))
508  {
509  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
510 
511  const OUString aString(mpBitmapItem->GetName());
512 
513  mpLbFillAttr->set_active_text(aString);
514 
515  // Check if the entry is not in the list
516  if (mpLbFillAttr->get_active_text() != aString)
517  {
518  sal_Int32 nCount = mpLbFillAttr->get_count();
519  OUString aTmpStr;
520  if( nCount > 0 )
521  {
522  // Last entry gets tested against temporary entry
523  aTmpStr = mpLbFillAttr->get_text(nCount - 1);
524  if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
525  aTmpStr.endsWith(TMP_STR_END) )
526  {
527  mpLbFillAttr->remove(nCount - 1);
528  }
529  }
530  aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
531 
532  XBitmapListRef xBitmapList =
535  XPropertyListType::Bitmap, "TmpList", ""/*TODO?*/));
536  xBitmapList->Insert(std::make_unique<XBitmapEntry>(mpBitmapItem->GetGraphicObject(), aTmpStr));
537  xBitmapList->SetDirty( false );
538  SvxFillAttrBox::Fill(*mpLbFillAttr, xBitmapList);
540  }
541 
542  }
543  else if (mpBitmapItem && mpBitmapItem->isPattern() && pSh->GetItem(SID_PATTERN_LIST))
544  {
545  mnLastXFS = sal::static_int_cast<sal_Int32>(PATTERN);
547 
548  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
549  const OUString aString(mpBitmapItem->GetName());
550 
551  mpLbFillAttr->set_active_text(aString);
552  }
553  else
554  {
556  }
557  }
558  else
559  {
561  }
562  break;
563  }
564  default:
565  OSL_ENSURE(false, "Non supported FillType (!)");
566  break;
567  }
568 
569 }
570 
572 {
573  if(GetSlotId() == SID_ATTR_FILL_STYLE)
574  {
576 
580 
581  mpLbFillType->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillTypeHdl));
582  mpLbFillAttr->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillAttrHdl));
583 
584 
585  return mxFillControl;
586  }
587  return VclPtr<InterimItemWindow>();
588 }
589 
590 FillControl::FillControl(vcl::Window* pParent, const css::uno::Reference<css::frame::XFrame>& rFrame)
591  : InterimItemWindow(pParent, "svx/ui/fillctrlbox.ui", "FillCtrlBox")
592  , mxLbFillType(m_xBuilder->weld_combo_box("type"))
593  , mxToolBoxColor(m_xBuilder->weld_toolbar("color"))
594  , mxColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxColor, *m_xBuilder, rFrame))
595  , mxLbFillAttr(m_xBuilder->weld_combo_box("attr"))
596  , mnTypeCurPos(0)
597  , mnAttrCurPos(0)
598 {
600 
601  mxLbFillAttr->connect_key_press(LINK(this, FillControl, AttrKeyInputHdl));
602  mxLbFillType->connect_key_press(LINK(this, FillControl, TypeKeyInputHdl));
603  mxToolBoxColor->connect_key_press(LINK(this, FillControl, ColorKeyInputHdl));
604 
605  mxLbFillType->connect_get_property_tree(LINK(this, FillControl, DumpAsPropertyTreeHdl));
606 
607  mxLbFillType->connect_focus_in(LINK(this, FillControl, TypeFocusHdl));
608  mxLbFillAttr->connect_focus_in(LINK(this, FillControl, AttrFocusHdl));
609 
611 
612  SetOptimalSize();
613 }
614 
615 IMPL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
616 {
617  rJsonWriter.put("command", ".uno:FillStyle");
618 }
619 
621 {
623  if (pCurSh)
624  {
625  vcl::Window* pShellWnd = pCurSh->GetWindow();
626  if (pShellWnd)
627  pShellWnd->GrabFocus();
628  }
629 }
630 
631 IMPL_LINK(FillControl, TypeKeyInputHdl, const KeyEvent&, rKEvt, bool)
632 {
633  const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
634  sal_uInt16 nCode = rKeyCode.GetCode();
635 
636  if (nCode == KEY_ESCAPE)
637  {
638  mxLbFillType->set_active(mnTypeCurPos);
639  ReleaseFocus_Impl();
640  return true;
641  }
642 
643  if (nCode != KEY_TAB)
644  return false;
645  if (rKeyCode.IsShift())
646  return ChildKeyInput(rKEvt);
647  if (mxLbFillAttr->get_visible() && !mxLbFillAttr->get_sensitive())
648  return ChildKeyInput(rKEvt);
649  return false;
650 }
651 
653 {
654  mnTypeCurPos = mxLbFillType->get_active();
655 }
656 
658 {
659  mnAttrCurPos = mxLbFillAttr->get_active();
660 }
661 
662 IMPL_LINK(FillControl, AttrKeyInputHdl, const KeyEvent&, rKEvt, bool)
663 {
664  const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
665  sal_uInt16 nCode = rKeyCode.GetCode();
666 
667  if (nCode == KEY_ESCAPE)
668  {
669  mxLbFillAttr->set_active(mnAttrCurPos);
670  ReleaseFocus_Impl();
671  return true;
672  }
673 
674  return ChildKeyInput(rKEvt);
675 }
676 
677 IMPL_LINK(FillControl, ColorKeyInputHdl, const KeyEvent&, rKEvt, bool)
678 {
679  return ChildKeyInput(rKEvt);
680 }
681 
683 {
684  disposeOnce();
685 }
686 
688 {
689  mxLbFillAttr.reset();
690  mxColorDispatch.reset();
691  mxToolBoxColor.reset();
692  mxLbFillType.reset();
694 }
695 
697 {
698  sal_Int32 nXFS = mpLbFillType->get_active();
699 
700  if(mnLastXFS == nXFS)
701  return;
702 
703  eFillStyle eXFS = static_cast<eFillStyle>(nXFS);
704  mpLbFillAttr->clear();
706  const XFillStyleItem aXFillStyleItem(toCssFillStyle(eXFS));
707 
708  // #i122676# Do no longer trigger two Execute calls, one for SID_ATTR_FILL_STYLE
709  // and one for setting the fill attribute itself, but add two SfxPoolItems to the
710  // call to get just one action at the SdrObject and to create only one Undo action, too.
711  // Checked that this works in all apps.
712  switch( eXFS )
713  {
714  default:
715  case NONE:
716  {
717  mpLbFillAttr->show();
718  mpToolBoxColor->hide();
719  mpLbFillAttr->set_sensitive(false);
720  if (pSh)
721  {
722  // #i122676# need to call a single SID_ATTR_FILL_STYLE change
723  pSh->GetDispatcher()->ExecuteList(
724  SID_ATTR_FILL_STYLE, SfxCallMode::RECORD,
725  { &aXFillStyleItem });
726  }
727  break;
728  }
729  case SOLID:
730  {
731  mpLbFillAttr->hide();
732  mpToolBoxColor->show();
733  if (pSh)
734  {
735  const ::Color aColor = mpColorItem ? mpColorItem->GetColorValue() : COL_AUTO;
736  const XFillColorItem aXFillColorItem( "", aColor );
737 
738  // #i122676# change FillStyle and Color in one call
739  pSh->GetDispatcher()->ExecuteList(
740  SID_ATTR_FILL_COLOR, SfxCallMode::RECORD,
741  { &aXFillColorItem, &aXFillStyleItem });
742  }
743  break;
744  }
745  case GRADIENT:
746  {
747  mpLbFillAttr->show();
748  mpToolBoxColor->hide();
749 
750  if(pSh && pSh->GetItem(SID_GRADIENT_LIST))
751  {
752  if(!mpLbFillAttr->get_count())
753  {
754  mpLbFillAttr->set_sensitive(true);
755  mpLbFillAttr->clear();
756  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
757  }
758 
759  if (mnLastPosGradient != -1)
760  {
761  const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST);
762 
763  if(mnLastPosGradient < pItem->GetGradientList()->Count())
764  {
765  const XGradient aGradient = pItem->GetGradientList()->GetGradient(mnLastPosGradient)->GetGradient();
766  const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_text(mnLastPosGradient), aGradient);
767 
768  // #i122676# change FillStyle and Gradient in one call
769  pSh->GetDispatcher()->ExecuteList(
770  SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD,
771  { &aXFillGradientItem, &aXFillStyleItem });
772  mpLbFillAttr->set_active(mnLastPosGradient);
773  }
774  }
775  }
776  else
777  {
778  mpLbFillAttr->set_sensitive(false);
779  }
780  break;
781  }
782  case HATCH:
783  {
784  mpLbFillAttr->show();
785  mpToolBoxColor->hide();
786 
787  if(pSh && pSh->GetItem(SID_HATCH_LIST))
788  {
789  if(!mpLbFillAttr->get_count())
790  {
791  mpLbFillAttr->set_sensitive(true);
792  mpLbFillAttr->clear();
793  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
794  }
795 
796  if (mnLastPosHatch != -1)
797  {
798  const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST);
799 
800  if(mnLastPosHatch < pItem->GetHatchList()->Count())
801  {
802  const XHatch aHatch = pItem->GetHatchList()->GetHatch(mnLastPosHatch)->GetHatch();
803  const XFillHatchItem aXFillHatchItem(mpLbFillAttr->get_active_text(), aHatch);
804 
805  // #i122676# change FillStyle and Hatch in one call
806  pSh->GetDispatcher()->ExecuteList(
807  SID_ATTR_FILL_HATCH, SfxCallMode::RECORD,
808  { &aXFillHatchItem, &aXFillStyleItem });
809  mpLbFillAttr->set_active(mnLastPosHatch);
810  }
811  }
812  }
813  else
814  {
815  mpLbFillAttr->set_sensitive(false);
816  }
817  break;
818  }
819  case BITMAP:
820  {
821  mpLbFillAttr->show();
822  mpToolBoxColor->hide();
823 
824  if(pSh && pSh->GetItem(SID_BITMAP_LIST))
825  {
826  if(!mpLbFillAttr->get_count())
827  {
828  mpLbFillAttr->set_sensitive(true);
829  mpLbFillAttr->clear();
830  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
831  }
832 
833  if (mnLastPosBitmap != -1)
834  {
835  const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST);
836 
837  if(mnLastPosBitmap < pItem->GetBitmapList()->Count())
838  {
839  const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(mnLastPosBitmap);
840  const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
841 
842  // #i122676# change FillStyle and Bitmap in one call
843  pSh->GetDispatcher()->ExecuteList(
844  SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
845  { &aXFillBitmapItem, &aXFillStyleItem });
846  mpLbFillAttr->set_active(mnLastPosBitmap);
847  }
848  }
849  }
850  else
851  {
852  mpLbFillAttr->set_sensitive(false);
853  }
854  break;
855  }
856  case PATTERN:
857  {
858  mpLbFillAttr->show();
859  mpToolBoxColor->hide();
860 
861  if(pSh && pSh->GetItem(SID_PATTERN_LIST))
862  {
863  if(!mpLbFillAttr->get_count())
864  {
865  mpLbFillAttr->set_sensitive(true);
866  mpLbFillAttr->clear();
867  SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
868  }
869 
870  if (mnLastPosPattern != -1)
871  {
872  const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST);
873 
874  if(mnLastPosPattern < pItem->GetPatternList()->Count())
875  {
876  const XBitmapEntry* pXBitmapEntry = pItem->GetPatternList()->GetBitmap(mnLastPosPattern);
877  const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
878 
879  // #i122676# change FillStyle and Bitmap in one call
880  pSh->GetDispatcher()->ExecuteList(
881  SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
882  { &aXFillBitmapItem, &aXFillStyleItem });
883  mpLbFillAttr->set_active(mnLastPosPattern);
884  }
885  }
886  }
887  else
888  {
889  mpLbFillAttr->set_sensitive(false);
890  }
891  break;
892  }
893 
894  }
895 
896  mnLastXFS = nXFS;
897 
898  mxFillControl->Resize();
899 }
900 
902 {
903  sal_Int32 nXFS = mpLbFillType->get_active();
904  eFillStyle eXFS = static_cast<eFillStyle>(nXFS);
905 
906  const XFillStyleItem aXFillStyleItem(toCssFillStyle(eXFS));
908 
909  // #i122676# dependent from bFillStyleChange, do execute a single or two
910  // changes in one Execute call
911  const bool bFillStyleChange(mnLastXFS != nXFS);
912 
913  switch (eXFS)
914  {
915  case SOLID:
916  {
917  if (bFillStyleChange && pSh)
918  {
919  // #i122676# Single FillStyle change call needed here
920  pSh->GetDispatcher()->ExecuteList(
921  SID_ATTR_FILL_STYLE, SfxCallMode::RECORD,
922  { &aXFillStyleItem });
923  }
924  break;
925  }
926  case GRADIENT:
927  {
928  sal_Int32 nPos = mpLbFillAttr->get_active();
929 
930  if (nPos == -1)
931  {
932  nPos = mnLastPosGradient;
933  }
934 
935  if (nPos != -1 && pSh && pSh->GetItem(SID_GRADIENT_LIST))
936  {
937  const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST);
938 
939  if(nPos < pItem->GetGradientList()->Count())
940  {
941  const XGradient aGradient = pItem->GetGradientList()->GetGradient(nPos)->GetGradient();
942  const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_active_text(), aGradient);
943 
944  // #i122676# Change FillStyle and Gradient in one call
945  pSh->GetDispatcher()->ExecuteList(
946  SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD,
947  bFillStyleChange
948  ? std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem, &aXFillStyleItem }
949  : std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem });
950  }
951  }
952 
953  if (nPos != -1)
954  {
955  mnLastPosGradient = nPos;
956  }
957  break;
958  }
959  case HATCH:
960  {
961  sal_Int32 nPos = mpLbFillAttr->get_active();
962 
963  if (nPos == -1)
964  {
965  nPos = mnLastPosHatch;
966  }
967 
968  if (nPos != -1 && pSh && pSh->GetItem(SID_HATCH_LIST))
969  {
970  const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST);
971 
972  if(nPos < pItem->GetHatchList()->Count())
973  {
974  const XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch();
975  const XFillHatchItem aXFillHatchItem( mpLbFillAttr->get_active_text(), aHatch);
976 
977  // #i122676# Change FillStyle and Hatch in one call
978  pSh->GetDispatcher()->ExecuteList(
979  SID_ATTR_FILL_HATCH, SfxCallMode::RECORD,
980  bFillStyleChange
981  ? std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem, &aXFillStyleItem }
982  : std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem });
983  }
984  }
985 
986  if (nPos != -1)
987  {
988  mnLastPosHatch = nPos;
989  }
990  break;
991  }
992  case BITMAP:
993  {
994  sal_Int32 nPos = mpLbFillAttr->get_active();
995 
996  if (nPos == -1)
997  {
998  nPos = mnLastPosBitmap;
999  }
1000 
1001  if (nPos != -1 && pSh && pSh->GetItem(SID_BITMAP_LIST))
1002  {
1003  const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST);
1004 
1005  if(nPos < pItem->GetBitmapList()->Count())
1006  {
1007  const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos);
1008  const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
1009 
1010  // #i122676# Change FillStyle and Bitmap in one call
1011  pSh->GetDispatcher()->ExecuteList(
1012  SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
1013  bFillStyleChange
1014  ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem }
1015  : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem });
1016  }
1017  }
1018 
1019  if (nPos != -1)
1020  {
1021  mnLastPosBitmap = nPos;
1022  }
1023  break;
1024  }
1025  case PATTERN:
1026  {
1027  sal_Int32 nPos = mpLbFillAttr->get_active();
1028 
1029  if (nPos == -1)
1030  {
1031  nPos = mnLastPosPattern;
1032  }
1033 
1034  if (nPos != -1 && pSh && pSh->GetItem(SID_PATTERN_LIST))
1035  {
1036  const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST);
1037 
1038  if(nPos < pItem->GetPatternList()->Count())
1039  {
1040  const XBitmapEntry* pXBitmapEntry = pItem->GetPatternList()->GetBitmap(nPos);
1041  const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
1042 
1043  // #i122676# Change FillStyle and Bitmap in one call
1044  pSh->GetDispatcher()->ExecuteList(
1045  SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
1046  bFillStyleChange
1047  ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem }
1048  : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem });
1049  }
1050  }
1051 
1052  if (nPos != -1)
1053  {
1054  mnLastPosPattern = nPos;
1055  }
1056  break;
1057  }
1058 
1059  default: break;
1060  }
1061 }
1062 
1064 {
1065  Size aSize(mxLbFillType->get_preferred_size());
1066  Size aFirstSize(mxToolBoxColor->get_preferred_size());
1067  auto nWidth = std::max(aFirstSize.Width(), LogicToPixel(Size(55, 0), MapMode(MapUnit::MapAppFont)).Width());
1068  auto nHeight = std::max(aSize.Height(), aFirstSize.Height());
1069  mxToolBoxColor->set_size_request(nWidth, -1);
1070  mxLbFillAttr->set_size_request(42, -1); //something narrow so the toolbar sets the overall size of this column
1071  SetSizePixel(Size(m_xContainer->get_preferred_size().Width(), nHeight));
1072 }
1073 
1075 {
1076  if((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1077  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1078  {
1079  SetOptimalSize();
1080  }
1082 }
1083 
1084 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual ~FillControl() override
Definition: fillctrl.cxx:682
virtual void dispose() override
Definition: fillctrl.cxx:687
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
const XPatternListRef & GetPatternList() const
Definition: drawitem.hxx:146
std::unique_ptr< XFillBitmapItem > mpBitmapItem
Definition: fillctrl.hxx:49
enum SAL_DLLPUBLIC_RTTI FillStyle
virtual void hide()=0
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const =0
SVX_DLLPUBLIC void Fill(weld::ComboBox &, const XHatchListRef &pList)
Definition: itemwin.cxx:243
virtual OUString get_text(int pos) const =0
static XBitmapListRef AsBitmapList(rtl::Reference< XPropertyList > const &plist)
Definition: xtable.hxx:379
constexpr::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
std::unique_ptr< XFillColorItem > mpColorItem
Definition: fillctrl.hxx:46
css::uno::Reference< css::lang::XComponent > m_xFrame
virtual void SetSizePixel(const Size &rNewSize)
std::unique_ptr< XFillGradientItem > mpFillGradientItem
Definition: fillctrl.hxx:47
const XGradientListRef & GetGradientList() const
Definition: drawitem.hxx:73
sal_uInt16 GetCode() const
DataChangedEventType GetType() const
IMPL_LINK_NOARG(FillControl, TypeFocusHdl, weld::Widget &, void)
Definition: fillctrl.cxx:652
static SfxObjectShell * Current()
void append(const OUString &rId, const OUString &rStr)
virtual int get_count() const =0
constexpr OUStringLiteral TMP_STR_BEGIN
Definition: fillctrl.cxx:31
NONE
virtual void show()=0
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: fillctrl.cxx:1074
FillControl(vcl::Window *pParent, const css::uno::Reference< css::frame::XFrame > &rFrame)
Definition: fillctrl.cxx:590
int nCount
constexpr OUStringLiteral TMP_STR_END
Definition: fillctrl.cxx:32
AllSettingsFlags GetFlags() const
static SfxViewShell * Current()
IMPL_LINK(FillControl, TypeKeyInputHdl, const KeyEvent &, rKEvt, bool)
Definition: fillctrl.cxx:631
virtual void Resize() override
virtual void StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem *pState) override
Definition: fillctrl.cxx:106
sal_uInt16 nCode
const GraphicObject & GetGraphicObject() const
Definition: xtable.hxx:125
const XHatchListRef & GetHatchList() const
Definition: drawitem.hxx:97
const SfxPoolItem * GetItem(sal_uInt16 nSlotId) const
bool IsEmpty() const
std::unique_ptr< weld::ComboBox > mxLbFillAttr
Definition: fillctrl.hxx:84
virtual ~SvxFillToolBoxControl() override
Definition: fillctrl.cxx:102
void set_active_text(const OUString &rStr)
SVX_DLLPUBLIC void Fill(weld::ComboBox &rListBox)
Definition: itemwin.cxx:173
Point LogicToPixel(const Point &rLogicPt) const
SfxDispatcher * GetDispatcher() const
static void ReleaseFocus_Impl()
Definition: fillctrl.cxx:620
constexpr OUStringLiteral PATTERN
void SetOptimalSize()
Definition: fillctrl.cxx:1063
void connect_changed(const Link< ComboBox &, void > &rLink)
Count
SvxFillToolBoxControl(sal_uInt16 nSlotId, ToolBoxItemId nId, ToolBox &rTbx)
Definition: fillctrl.cxx:77
float u
static XPropertyListRef CreatePropertyList(XPropertyListType t, const OUString &rPath, const OUString &rReferer)
Definition: xtable.cxx:315
std::unique_ptr< XFillHatchItem > mpHatchItem
Definition: fillctrl.hxx:48
virtual void set_active(int pos)=0
VclPtr< FillControl > mxFillControl
Definition: fillctrl.hxx:51
virtual void clear()=0
weld::ComboBox * mpLbFillType
Definition: fillctrl.hxx:52
void GrabFocus()
const XBitmapListRef & GetBitmapList() const
Definition: drawitem.hxx:122
SFX_IMPL_TOOLBOX_CONTROL(SvxFillToolBoxControl, XFillStyleItem)
void reset(reference_type *pBody)
bool IsShift() const
virtual VclPtr< InterimItemWindow > CreateItemWindow(vcl::Window *pParent) override
Definition: fillctrl.cxx:571
SfxItemState
std::unique_ptr< weld::Container > m_xContainer
weld::ComboBox * mpLbFillAttr
Definition: fillctrl.hxx:54
constexpr sal_uInt16 KEY_ESCAPE
virtual void dispose() override
eFillStyle
Definition: fillctrl.cxx:53
unsigned short GetSlotId() const
vcl::Window * GetWindow() const
std::unique_ptr< XFillStyleItem > mpStyleItem
Definition: fillctrl.hxx:45
std::unique_ptr< ToolbarUnoDispatcher > mxColorDispatch
Definition: fillctrl.hxx:83
weld::Toolbar * mpToolBoxColor
Definition: fillctrl.hxx:53
virtual void remove(int pos)=0
IMPL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, tools::JsonWriter &, rJsonWriter, void)
Definition: fillctrl.cxx:615
std::unique_ptr< weld::Toolbar > mxToolBoxColor
Definition: fillctrl.hxx:82
const Size & GetSizePixel() const
std::unique_ptr< weld::ComboBox > mxLbFillType
Definition: fillctrl.hxx:81
void InitControlBase(weld::Widget *pWidget)
virtual XFillStyleItem * Clone(SfxItemPool *pPool=nullptr) const override
Definition: xattr.cxx:1753
sal_uInt16 nPos
virtual void set_sensitive(bool sensitive)=0
constexpr sal_uInt16 KEY_TAB
virtual void DataChanged(const DataChangedEvent &rDCEvt)
virtual OUString get_active_text() const =0