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