Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / tbxctrls / fillctrl.cxx
blob9ca978e073312bfcb120b1559096b91ed2191695
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
31 constexpr OUStringLiteral TMP_STR_BEGIN = u"[";
32 constexpr OUStringLiteral TMP_STR_END = u"]";
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>
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;
51 namespace {
53 enum eFillStyle
55 NONE,
56 SOLID,
57 GRADIENT,
58 HATCH,
59 BITMAP,
60 PATTERN
63 drawing::FillStyle toCssFillStyle( eFillStyle eXFS )
65 if (eXFS == PATTERN)
67 return drawing::FillStyle_BITMAP;
70 return static_cast<drawing::FillStyle>(eXFS);
75 SFX_IMPL_TOOLBOX_CONTROL( SvxFillToolBoxControl, XFillStyleItem );
77 SvxFillToolBoxControl::SvxFillToolBoxControl(
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)
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");
102 SvxFillToolBoxControl::~SvxFillToolBoxControl()
106 void SvxFillToolBoxControl::StateChangedAtToolBoxControl(
107 sal_uInt16 nSID,
108 SfxItemState eState,
109 const SfxPoolItem* pState)
111 const bool bDisabled(SfxItemState::DISABLED == eState);
113 switch(nSID)
115 case SID_ATTR_FILL_STYLE:
117 if(bDisabled)
119 mpLbFillType->set_sensitive(false);
120 mpLbFillType->set_active(-1);
121 mpLbFillAttr->show();
122 mpLbFillAttr->set_sensitive(false);
123 mpLbFillAttr->set_active(-1);
124 mpToolBoxColor->hide();
125 mnLastXFS = -1;
126 mpStyleItem.reset();
129 if(eState >= SfxItemState::DEFAULT)
131 const XFillStyleItem* pItem = dynamic_cast< const XFillStyleItem* >(pState);
133 if(pItem)
135 mpStyleItem.reset(pItem->Clone());
136 mpLbFillType->set_sensitive(true);
137 drawing::FillStyle eXFS = mpStyleItem->GetValue();
138 mnLastXFS = sal::static_int_cast< sal_Int32 >(eXFS);
139 mpLbFillType->set_active(mnLastXFS);
141 if(drawing::FillStyle_NONE == eXFS)
143 mpLbFillAttr->set_active(-1);
144 mpLbFillAttr->set_sensitive(false);
147 Update();
148 break;
152 mpLbFillType->set_active(-1);
153 mpLbFillAttr->show();
154 mpLbFillAttr->set_sensitive(false);
155 mpLbFillAttr->set_active(-1);
156 mpToolBoxColor->hide();
157 mnLastXFS = -1;
158 mpStyleItem.reset();
159 mxFillControl->Resize();
160 break;
162 case SID_ATTR_FILL_COLOR:
164 if(SfxItemState::DEFAULT == eState)
166 mpColorItem.reset(pState ? static_cast<XFillColorItem*>(pState->Clone()) : nullptr);
169 if(mpStyleItem && drawing::FillStyle_SOLID == mpStyleItem->GetValue())
171 mpLbFillAttr->hide();
172 mpToolBoxColor->show();
173 mxFillControl->Resize();
175 Update();
177 break;
179 case SID_ATTR_FILL_GRADIENT:
181 if(SfxItemState::DEFAULT == eState)
183 mpFillGradientItem.reset(pState ? static_cast<XFillGradientItem*>(pState->Clone()) : nullptr);
186 if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue())
188 mpLbFillAttr->show();
189 mpToolBoxColor->hide();
190 mxFillControl->Resize();
192 if(SfxItemState::DEFAULT == eState)
194 mpLbFillAttr->set_sensitive(true);
195 Update();
197 else if(SfxItemState::DISABLED == eState )
199 mpLbFillAttr->set_sensitive(false);
200 mpLbFillAttr->set_active(-1);
202 else
204 mpLbFillAttr->set_active(-1);
207 break;
209 case SID_ATTR_FILL_HATCH:
211 if(SfxItemState::DEFAULT == eState)
213 mpHatchItem.reset(pState ? static_cast<XFillHatchItem*>(pState->Clone()) : nullptr);
216 if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue())
218 mpLbFillAttr->show();
219 mpToolBoxColor->hide();
220 mxFillControl->Resize();
222 if(SfxItemState::DEFAULT == eState)
224 mpLbFillAttr->set_sensitive(true);
225 Update();
227 else if(SfxItemState::DISABLED == eState )
229 mpLbFillAttr->set_sensitive(false);
230 mpLbFillAttr->set_active(-1);
232 else
234 mpLbFillAttr->set_active(-1);
237 break;
239 case SID_ATTR_FILL_BITMAP:
241 if(SfxItemState::DEFAULT == eState)
243 mpBitmapItem.reset(pState ? static_cast<XFillBitmapItem*>(pState->Clone()) : nullptr);
246 if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue())
248 mpLbFillAttr->show();
249 mpToolBoxColor->hide();
250 mxFillControl->Resize();
252 if(SfxItemState::DEFAULT == eState)
254 mpLbFillAttr->set_sensitive(true);
255 Update();
257 else if(SfxItemState::DISABLED == eState )
259 mpLbFillAttr->set_sensitive(false);
260 mpLbFillAttr->set_active(-1);
262 else
264 mpLbFillAttr->set_active(-1);
267 break;
269 case SID_GRADIENT_LIST:
271 if(SfxItemState::DEFAULT == eState)
273 if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue())
275 if(mpFillGradientItem)
277 const OUString aString( mpFillGradientItem->GetName() );
278 mpLbFillAttr->clear();
279 if (const SfxObjectShell* pSh = SfxObjectShell::Current())
281 mpLbFillAttr->set_sensitive(true);
282 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
284 mpLbFillAttr->set_active_text(aString);
286 else
288 mpLbFillAttr->set_active(-1);
292 break;
294 case SID_HATCH_LIST:
296 if(SfxItemState::DEFAULT == eState)
298 if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue())
300 if(mpHatchItem)
302 const OUString aString( mpHatchItem->GetName() );
303 mpLbFillAttr->clear();
304 if (const SfxObjectShell* pSh = SfxObjectShell::Current())
306 mpLbFillAttr->set_sensitive(true);
307 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
309 mpLbFillAttr->set_active_text(aString);
311 else
313 mpLbFillAttr->set_active(-1);
317 break;
319 case SID_BITMAP_LIST:
321 if(SfxItemState::DEFAULT == eState)
323 if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue())
325 if(mpBitmapItem)
327 const OUString aString( mpBitmapItem->GetName() );
328 mpLbFillAttr->clear();
329 if (const SfxObjectShell* pSh = SfxObjectShell::Current())
331 mpLbFillAttr->set_sensitive(true);
332 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
334 mpLbFillAttr->set_active_text(aString);
336 else
338 mpLbFillAttr->set_active(-1);
342 break;
347 void SvxFillToolBoxControl::Update()
349 if(!mpStyleItem)
350 return;
352 const drawing::FillStyle eXFS = mpStyleItem->GetValue();
353 SfxObjectShell* pSh = SfxObjectShell::Current();
355 switch( eXFS )
357 case drawing::FillStyle_NONE:
359 mpLbFillAttr->show();
360 mpToolBoxColor->hide();
361 mxFillControl->Resize();
362 break;
364 case drawing::FillStyle_SOLID:
366 if(mpColorItem)
368 mpLbFillAttr->hide();
369 mpToolBoxColor->show();
370 mxFillControl->Resize();
372 break;
374 case drawing::FillStyle_GRADIENT:
376 mpLbFillAttr->show();
377 mpToolBoxColor->hide();
378 mxFillControl->Resize();
380 if(pSh && pSh->GetItem(SID_GRADIENT_LIST))
382 mpLbFillAttr->set_sensitive(true);
383 mpLbFillAttr->clear();
384 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
386 if(mpFillGradientItem)
388 const OUString aString(mpFillGradientItem->GetName());
390 mpLbFillAttr->set_active_text(aString);
392 // Check if the entry is not in the list
393 if (mpLbFillAttr->get_active_text() != aString)
395 sal_Int32 nCount = mpLbFillAttr->get_count();
396 OUString aTmpStr;
397 if( nCount > 0 )
399 // Last entry gets tested against temporary entry
400 aTmpStr = mpLbFillAttr->get_text( nCount - 1 );
401 if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
402 aTmpStr.endsWith(TMP_STR_END) )
404 mpLbFillAttr->remove(nCount - 1);
407 aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
409 rtl::Reference<XGradientList> xGradientList = new XGradientList( "", ""/*TODO?*/ );
410 xGradientList->Insert(std::make_unique<XGradientEntry>(mpFillGradientItem->GetGradientValue(), aTmpStr));
411 xGradientList->SetDirty( false );
412 const BitmapEx aBmp = xGradientList->GetUiBitmap( 0 );
414 if (!aBmp.IsEmpty())
416 ScopedVclPtrInstance< VirtualDevice > pVD;
417 const Size aBmpSize(aBmp.GetSizePixel());
418 pVD->SetOutputSizePixel(aBmpSize, false);
419 pVD->DrawBitmapEx(Point(), aBmp);
420 mpLbFillAttr->append("", xGradientList->Get(0)->GetName(), *pVD);
421 mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1);
426 else
428 mpLbFillAttr->set_active(-1);
431 else
433 mpLbFillAttr->set_active(-1);
435 break;
437 case drawing::FillStyle_HATCH:
439 mpLbFillAttr->show();
440 mpToolBoxColor->hide();
441 mxFillControl->Resize();
443 if(pSh && pSh->GetItem(SID_HATCH_LIST))
445 mpLbFillAttr->set_sensitive(true);
446 mpLbFillAttr->clear();
447 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
449 if(mpHatchItem)
451 const OUString aString(mpHatchItem->GetName());
453 mpLbFillAttr->set_active_text( aString );
455 // Check if the entry is not in the list
456 if( mpLbFillAttr->get_active_text() != aString )
458 const sal_Int32 nCount = mpLbFillAttr->get_count();
459 OUString aTmpStr;
460 if( nCount > 0 )
462 // Last entry gets tested against temporary entry
463 aTmpStr = mpLbFillAttr->get_text( nCount - 1 );
464 if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
465 aTmpStr.endsWith(TMP_STR_END) )
467 mpLbFillAttr->remove( nCount - 1 );
470 aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
472 rtl::Reference<XHatchList> xHatchList = new XHatchList( "", ""/*TODO?*/ );
473 xHatchList->Insert(std::make_unique<XHatchEntry>(mpHatchItem->GetHatchValue(), aTmpStr));
474 xHatchList->SetDirty( false );
475 const BitmapEx & aBmp = xHatchList->GetUiBitmap( 0 );
477 if( !aBmp.IsEmpty() )
479 ScopedVclPtrInstance< VirtualDevice > pVD;
480 const Size aBmpSize(aBmp.GetSizePixel());
481 pVD->SetOutputSizePixel(aBmpSize, false);
482 pVD->DrawBitmapEx(Point(), aBmp);
483 mpLbFillAttr->append("", xHatchList->GetHatch(0)->GetName(), *pVD);
484 mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1);
488 else
490 mpLbFillAttr->set_active(-1);
493 else
495 mpLbFillAttr->set_active(-1);
497 break;
499 case drawing::FillStyle_BITMAP:
501 mpLbFillAttr->show();
502 mpToolBoxColor->hide();
503 mxFillControl->Resize();
505 if(pSh)
507 mpLbFillAttr->set_sensitive(true);
508 mpLbFillAttr->clear();
510 if(mpBitmapItem && !mpBitmapItem->isPattern() && pSh->GetItem(SID_BITMAP_LIST))
512 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
514 const OUString aString(mpBitmapItem->GetName());
516 mpLbFillAttr->set_active_text(aString);
518 // Check if the entry is not in the list
519 if (mpLbFillAttr->get_active_text() != aString)
521 sal_Int32 nCount = mpLbFillAttr->get_count();
522 OUString aTmpStr;
523 if( nCount > 0 )
525 // Last entry gets tested against temporary entry
526 aTmpStr = mpLbFillAttr->get_text(nCount - 1);
527 if( aTmpStr.startsWith(TMP_STR_BEGIN) &&
528 aTmpStr.endsWith(TMP_STR_END) )
530 mpLbFillAttr->remove(nCount - 1);
533 aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END;
535 XBitmapListRef xBitmapList =
536 XPropertyList::AsBitmapList(
537 XPropertyList::CreatePropertyList(
538 XPropertyListType::Bitmap, "TmpList", ""/*TODO?*/));
539 xBitmapList->Insert(std::make_unique<XBitmapEntry>(mpBitmapItem->GetGraphicObject(), aTmpStr));
540 xBitmapList->SetDirty( false );
541 SvxFillAttrBox::Fill(*mpLbFillAttr, xBitmapList);
542 mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1);
546 else if (mpBitmapItem && mpBitmapItem->isPattern() && pSh->GetItem(SID_PATTERN_LIST))
548 mnLastXFS = sal::static_int_cast<sal_Int32>(PATTERN);
549 mpLbFillType->set_active(mnLastXFS);
551 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
552 const OUString aString(mpBitmapItem->GetName());
554 mpLbFillAttr->set_active_text(aString);
556 else
558 mpLbFillAttr->set_active(-1);
561 else
563 mpLbFillAttr->set_active(-1);
565 break;
567 default:
568 OSL_ENSURE(false, "Non supported FillType (!)");
569 break;
574 VclPtr<InterimItemWindow> SvxFillToolBoxControl::CreateItemWindow(vcl::Window *pParent)
576 if(GetSlotId() == SID_ATTR_FILL_STYLE)
578 mxFillControl.reset(VclPtr<FillControl>::Create(pParent, m_xFrame));
580 mpLbFillType = mxFillControl->mxLbFillType.get();
581 mpLbFillAttr = mxFillControl->mxLbFillAttr.get();
582 mpToolBoxColor = mxFillControl->mxToolBoxColor.get();
584 mpLbFillType->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillTypeHdl));
585 mpLbFillAttr->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillAttrHdl));
588 return mxFillControl;
590 return VclPtr<InterimItemWindow>();
593 FillControl::FillControl(vcl::Window* pParent, const css::uno::Reference<css::frame::XFrame>& rFrame)
594 : InterimItemWindow(pParent, "svx/ui/fillctrlbox.ui", "FillCtrlBox")
595 , mxLbFillType(m_xBuilder->weld_combo_box("type"))
596 , mxToolBoxColor(m_xBuilder->weld_toolbar("color"))
597 , mxColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxColor, *m_xBuilder, rFrame))
598 , mxLbFillAttr(m_xBuilder->weld_combo_box("attr"))
599 , mnTypeCurPos(0)
600 , mnAttrCurPos(0)
602 InitControlBase(mxLbFillType.get());
604 mxLbFillAttr->connect_key_press(LINK(this, FillControl, AttrKeyInputHdl));
605 mxLbFillType->connect_key_press(LINK(this, FillControl, TypeKeyInputHdl));
606 mxToolBoxColor->connect_key_press(LINK(this, FillControl, ColorKeyInputHdl));
608 mxLbFillType->connect_get_property_tree(LINK(this, FillControl, DumpAsPropertyTreeHdl));
610 mxLbFillType->connect_focus_in(LINK(this, FillControl, TypeFocusHdl));
611 mxLbFillAttr->connect_focus_in(LINK(this, FillControl, AttrFocusHdl));
613 SvxFillTypeBox::Fill(*mxLbFillType);
615 SetOptimalSize();
618 IMPL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
620 rJsonWriter.put("command", ".uno:FillStyle");
623 void FillControl::ReleaseFocus_Impl()
625 SfxViewShell* pCurSh = SfxViewShell::Current();
626 if (pCurSh)
628 vcl::Window* pShellWnd = pCurSh->GetWindow();
629 if (pShellWnd)
630 pShellWnd->GrabFocus();
634 IMPL_LINK(FillControl, TypeKeyInputHdl, const KeyEvent&, rKEvt, bool)
636 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
637 sal_uInt16 nCode = rKeyCode.GetCode();
639 if (nCode == KEY_ESCAPE)
641 mxLbFillType->set_active(mnTypeCurPos);
642 ReleaseFocus_Impl();
643 return true;
646 if (nCode != KEY_TAB)
647 return false;
648 if (rKeyCode.IsShift())
649 return ChildKeyInput(rKEvt);
650 if (mxLbFillAttr->get_visible() && !mxLbFillAttr->get_sensitive())
651 return ChildKeyInput(rKEvt);
652 return false;
655 IMPL_LINK_NOARG(FillControl, TypeFocusHdl, weld::Widget&, void)
657 mnTypeCurPos = mxLbFillType->get_active();
660 IMPL_LINK_NOARG(FillControl, AttrFocusHdl, weld::Widget&, void)
662 mnAttrCurPos = mxLbFillAttr->get_active();
665 IMPL_LINK(FillControl, AttrKeyInputHdl, const KeyEvent&, rKEvt, bool)
667 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
668 sal_uInt16 nCode = rKeyCode.GetCode();
670 if (nCode == KEY_ESCAPE)
672 mxLbFillAttr->set_active(mnAttrCurPos);
673 ReleaseFocus_Impl();
674 return true;
677 return ChildKeyInput(rKEvt);
680 IMPL_LINK(FillControl, ColorKeyInputHdl, const KeyEvent&, rKEvt, bool)
682 return ChildKeyInput(rKEvt);
685 FillControl::~FillControl()
687 disposeOnce();
690 void FillControl::dispose()
692 mxLbFillAttr.reset();
693 mxColorDispatch.reset();
694 mxToolBoxColor.reset();
695 mxLbFillType.reset();
696 InterimItemWindow::dispose();
699 IMPL_LINK_NOARG(SvxFillToolBoxControl, SelectFillTypeHdl, weld::ComboBox&, void)
701 sal_Int32 nXFS = mpLbFillType->get_active();
703 if(mnLastXFS == nXFS)
704 return;
706 eFillStyle eXFS = static_cast<eFillStyle>(nXFS);
707 mpLbFillAttr->clear();
708 SfxObjectShell* pSh = SfxObjectShell::Current();
709 const XFillStyleItem aXFillStyleItem(toCssFillStyle(eXFS));
711 // #i122676# Do no longer trigger two Execute calls, one for SID_ATTR_FILL_STYLE
712 // and one for setting the fill attribute itself, but add two SfxPoolItems to the
713 // call to get just one action at the SdrObject and to create only one Undo action, too.
714 // Checked that this works in all apps.
715 switch( eXFS )
717 default:
718 case NONE:
720 mpLbFillAttr->show();
721 mpToolBoxColor->hide();
722 mpLbFillAttr->set_sensitive(false);
723 if (pSh)
725 // #i122676# need to call a single SID_ATTR_FILL_STYLE change
726 pSh->GetDispatcher()->ExecuteList(
727 SID_ATTR_FILL_STYLE, SfxCallMode::RECORD,
728 { &aXFillStyleItem });
730 break;
732 case SOLID:
734 mpLbFillAttr->hide();
735 mpToolBoxColor->show();
736 if (pSh)
738 const ::Color aColor = mpColorItem ? mpColorItem->GetColorValue() : COL_AUTO;
739 const XFillColorItem aXFillColorItem( "", aColor );
741 // #i122676# change FillStyle and Color in one call
742 pSh->GetDispatcher()->ExecuteList(
743 SID_ATTR_FILL_COLOR, SfxCallMode::RECORD,
744 { &aXFillColorItem, &aXFillStyleItem });
746 break;
748 case GRADIENT:
750 mpLbFillAttr->show();
751 mpToolBoxColor->hide();
753 if(pSh && pSh->GetItem(SID_GRADIENT_LIST))
755 if(!mpLbFillAttr->get_count())
757 mpLbFillAttr->set_sensitive(true);
758 mpLbFillAttr->clear();
759 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList());
762 if (mnLastPosGradient != -1)
764 const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST);
766 if(mnLastPosGradient < pItem->GetGradientList()->Count())
768 const basegfx::BGradient aGradient = pItem->GetGradientList()->GetGradient(mnLastPosGradient)->GetGradient();
769 const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_text(mnLastPosGradient), aGradient);
771 // #i122676# change FillStyle and Gradient in one call
772 pSh->GetDispatcher()->ExecuteList(
773 SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD,
774 { &aXFillGradientItem, &aXFillStyleItem });
775 mpLbFillAttr->set_active(mnLastPosGradient);
779 else
781 mpLbFillAttr->set_sensitive(false);
783 break;
785 case HATCH:
787 mpLbFillAttr->show();
788 mpToolBoxColor->hide();
790 if(pSh && pSh->GetItem(SID_HATCH_LIST))
792 if(!mpLbFillAttr->get_count())
794 mpLbFillAttr->set_sensitive(true);
795 mpLbFillAttr->clear();
796 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList());
799 if (mnLastPosHatch != -1)
801 const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST);
803 if(mnLastPosHatch < pItem->GetHatchList()->Count())
805 const XHatch aHatch = pItem->GetHatchList()->GetHatch(mnLastPosHatch)->GetHatch();
806 const XFillHatchItem aXFillHatchItem(mpLbFillAttr->get_active_text(), aHatch);
808 // #i122676# change FillStyle and Hatch in one call
809 pSh->GetDispatcher()->ExecuteList(
810 SID_ATTR_FILL_HATCH, SfxCallMode::RECORD,
811 { &aXFillHatchItem, &aXFillStyleItem });
812 mpLbFillAttr->set_active(mnLastPosHatch);
816 else
818 mpLbFillAttr->set_sensitive(false);
820 break;
822 case BITMAP:
824 mpLbFillAttr->show();
825 mpToolBoxColor->hide();
827 if(pSh && pSh->GetItem(SID_BITMAP_LIST))
829 if(!mpLbFillAttr->get_count())
831 mpLbFillAttr->set_sensitive(true);
832 mpLbFillAttr->clear();
833 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList());
836 if (mnLastPosBitmap != -1)
838 const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST);
840 if(mnLastPosBitmap < pItem->GetBitmapList()->Count())
842 const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(mnLastPosBitmap);
843 const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
845 // #i122676# change FillStyle and Bitmap in one call
846 pSh->GetDispatcher()->ExecuteList(
847 SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
848 { &aXFillBitmapItem, &aXFillStyleItem });
849 mpLbFillAttr->set_active(mnLastPosBitmap);
853 else
855 mpLbFillAttr->set_sensitive(false);
857 break;
859 case PATTERN:
861 mpLbFillAttr->show();
862 mpToolBoxColor->hide();
864 if(pSh && pSh->GetItem(SID_PATTERN_LIST))
866 if(!mpLbFillAttr->get_count())
868 mpLbFillAttr->set_sensitive(true);
869 mpLbFillAttr->clear();
870 SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_PATTERN_LIST)->GetPatternList());
873 if (mnLastPosPattern != -1)
875 const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST);
877 if(mnLastPosPattern < pItem->GetPatternList()->Count())
879 const XBitmapEntry* pXBitmapEntry = pItem->GetPatternList()->GetBitmap(mnLastPosPattern);
880 const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
882 // #i122676# change FillStyle and Bitmap in one call
883 pSh->GetDispatcher()->ExecuteList(
884 SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
885 { &aXFillBitmapItem, &aXFillStyleItem });
886 mpLbFillAttr->set_active(mnLastPosPattern);
890 else
892 mpLbFillAttr->set_sensitive(false);
894 break;
899 mnLastXFS = nXFS;
901 mxFillControl->Resize();
904 IMPL_LINK_NOARG(SvxFillToolBoxControl, SelectFillAttrHdl, weld::ComboBox&, void)
906 sal_Int32 nXFS = mpLbFillType->get_active();
907 eFillStyle eXFS = static_cast<eFillStyle>(nXFS);
909 const XFillStyleItem aXFillStyleItem(toCssFillStyle(eXFS));
910 SfxObjectShell* pSh = SfxObjectShell::Current();
912 // #i122676# dependent from bFillStyleChange, do execute a single or two
913 // changes in one Execute call
914 const bool bFillStyleChange(mnLastXFS != nXFS);
916 switch (eXFS)
918 case SOLID:
920 if (bFillStyleChange && pSh)
922 // #i122676# Single FillStyle change call needed here
923 pSh->GetDispatcher()->ExecuteList(
924 SID_ATTR_FILL_STYLE, SfxCallMode::RECORD,
925 { &aXFillStyleItem });
927 break;
929 case GRADIENT:
931 sal_Int32 nPos = mpLbFillAttr->get_active();
933 if (nPos == -1)
935 nPos = mnLastPosGradient;
938 if (nPos != -1 && pSh && pSh->GetItem(SID_GRADIENT_LIST))
940 const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST);
942 if(nPos < pItem->GetGradientList()->Count())
944 const basegfx::BGradient aGradient = pItem->GetGradientList()->GetGradient(nPos)->GetGradient();
945 const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_active_text(), aGradient);
947 // #i122676# Change FillStyle and Gradient in one call
948 pSh->GetDispatcher()->ExecuteList(
949 SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD,
950 bFillStyleChange
951 ? std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem, &aXFillStyleItem }
952 : std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem });
956 if (nPos != -1)
958 mnLastPosGradient = nPos;
960 break;
962 case HATCH:
964 sal_Int32 nPos = mpLbFillAttr->get_active();
966 if (nPos == -1)
968 nPos = mnLastPosHatch;
971 if (nPos != -1 && pSh && pSh->GetItem(SID_HATCH_LIST))
973 const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST);
975 if(nPos < pItem->GetHatchList()->Count())
977 const XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch();
978 const XFillHatchItem aXFillHatchItem( mpLbFillAttr->get_active_text(), aHatch);
980 // #i122676# Change FillStyle and Hatch in one call
981 pSh->GetDispatcher()->ExecuteList(
982 SID_ATTR_FILL_HATCH, SfxCallMode::RECORD,
983 bFillStyleChange
984 ? std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem, &aXFillStyleItem }
985 : std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem });
989 if (nPos != -1)
991 mnLastPosHatch = nPos;
993 break;
995 case BITMAP:
997 sal_Int32 nPos = mpLbFillAttr->get_active();
999 if (nPos == -1)
1001 nPos = mnLastPosBitmap;
1004 if (nPos != -1 && pSh && pSh->GetItem(SID_BITMAP_LIST))
1006 const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST);
1008 if(nPos < pItem->GetBitmapList()->Count())
1010 const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos);
1011 const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
1013 // #i122676# Change FillStyle and Bitmap in one call
1014 pSh->GetDispatcher()->ExecuteList(
1015 SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
1016 bFillStyleChange
1017 ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem }
1018 : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem });
1022 if (nPos != -1)
1024 mnLastPosBitmap = nPos;
1026 break;
1028 case PATTERN:
1030 sal_Int32 nPos = mpLbFillAttr->get_active();
1032 if (nPos == -1)
1034 nPos = mnLastPosPattern;
1037 if (nPos != -1 && pSh && pSh->GetItem(SID_PATTERN_LIST))
1039 const SvxPatternListItem * pItem = pSh->GetItem(SID_PATTERN_LIST);
1041 if(nPos < pItem->GetPatternList()->Count())
1043 const XBitmapEntry* pXBitmapEntry = pItem->GetPatternList()->GetBitmap(nPos);
1044 const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject());
1046 // #i122676# Change FillStyle and Bitmap in one call
1047 pSh->GetDispatcher()->ExecuteList(
1048 SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD,
1049 bFillStyleChange
1050 ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem }
1051 : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem });
1055 if (nPos != -1)
1057 mnLastPosPattern = nPos;
1059 break;
1062 default: break;
1066 void FillControl::SetOptimalSize()
1068 Size aSize(mxLbFillType->get_preferred_size());
1069 Size aFirstSize(mxToolBoxColor->get_preferred_size());
1070 auto nWidth = std::max(aFirstSize.Width(), LogicToPixel(Size(55, 0), MapMode(MapUnit::MapAppFont)).Width());
1071 auto nHeight = std::max(aSize.Height(), aFirstSize.Height());
1072 mxToolBoxColor->set_size_request(nWidth, -1);
1073 mxLbFillAttr->set_size_request(42, -1); //something narrow so the toolbar sets the overall size of this column
1074 SetSizePixel(Size(m_xContainer->get_preferred_size().Width(), nHeight));
1077 void FillControl::DataChanged(const DataChangedEvent& rDCEvt)
1079 if((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1080 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1082 SetOptimalSize();
1084 InterimItemWindow::DataChanged(rDCEvt);
1087 void FillControl::GetFocus()
1089 // tdf#148047 if the dropdown is active then leave the focus
1090 // there and don't grab back to a different widget
1091 if (mxToolBoxColor->get_menu_item_active(".uno:FillColor"))
1092 return;
1093 InterimItemWindow::GetFocus();
1096 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */