xref: /trunk/main/svx/source/tbxctrls/fillctrl.cxx (revision 00467759)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svx.hxx"
24 
25 #include <string> // HACK: prevent conflict between STLPORT and Workshop headers
26 #include <sfx2/app.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/viewsh.hxx>
30 #include <rtl/ustring.hxx>
31 #include <svx/dialogs.hrc>
32 
33 #define TMP_STR_BEGIN	'['
34 #define TMP_STR_END		']'
35 
36 #include "svx/drawitem.hxx"
37 #include "svx/xattr.hxx"
38 #include <svx/xtable.hxx>
39 #include <svx/fillctrl.hxx>
40 #include <svx/itemwin.hxx>
41 #include <svx/dialmgr.hxx>
42 #include "helpid.hrc"
43 
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::util;
46 using namespace ::com::sun::star::beans;
47 using namespace ::com::sun::star::frame;
48 using namespace ::com::sun::star::lang;
49 
50 SFX_IMPL_TOOLBOX_CONTROL( SvxFillToolBoxControl, XFillStyleItem );
51 
52 /*************************************************************************
53 |*
54 |* SvxFillToolBoxControl
55 |*
56 \************************************************************************/
57 
SvxFillToolBoxControl(sal_uInt16 nSlotId,sal_uInt16 nId,ToolBox & rTbx)58 SvxFillToolBoxControl::SvxFillToolBoxControl(
59     sal_uInt16 nSlotId,
60     sal_uInt16 nId,
61     ToolBox& rTbx )
62 :   SfxToolBoxControl( nSlotId, nId, rTbx ),
63     mpStyleItem(0),
64     mpColorItem(0),
65     mpGradientItem(0),
66     mpHatchItem(0),
67     mpBitmapItem(0),
68     mpFillControl(0),
69     mpFillTypeLB(0),
70     mpFillAttrLB(0),
71     meLastXFS(XFILL_NONE),
72     mbUpdate(false)
73 {
74     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillColor" )));
75     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillGradient" )));
76     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillHatch" )));
77     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillBitmap" )));
78     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ColorTableState" )));
79     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GradientListState" )));
80     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:HatchListState" )));
81     addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:BitmapListState" )));
82 }
83 
84 //========================================================================
85 
~SvxFillToolBoxControl()86 SvxFillToolBoxControl::~SvxFillToolBoxControl()
87 {
88     delete mpStyleItem;
89     delete mpColorItem;
90     delete mpGradientItem;
91     delete mpHatchItem;
92     delete mpBitmapItem;
93 }
94 
95 //========================================================================
96 
StateChanged(sal_uInt16 nSID,SfxItemState eState,const SfxPoolItem * pState)97 void SvxFillToolBoxControl::StateChanged(
98     sal_uInt16 nSID,
99     SfxItemState eState,
100     const SfxPoolItem* pState)
101 {
102     bool bEnableControls(false);
103 
104     if(eState == SFX_ITEM_DISABLED)
105     {
106         // slot disable state
107         if(nSID == SID_ATTR_FILL_STYLE)
108         {
109             mpFillTypeLB->Disable();
110             mpFillTypeLB->SetNoSelection();
111         }
112 
113         mpFillAttrLB->Disable();
114         mpFillAttrLB->SetNoSelection();
115     }
116     else if(SFX_ITEM_AVAILABLE == eState)
117     {
118         // slot available state
119         if(nSID == SID_ATTR_FILL_STYLE)
120         {
121             delete mpStyleItem;
122             mpStyleItem = static_cast< XFillStyleItem* >(pState->Clone());
123             mpFillTypeLB->Enable();
124         }
125         else if(mpStyleItem)
126         {
127             const XFillStyle eXFS(static_cast< XFillStyle >(mpStyleItem->GetValue()));
128 
129             if(nSID == SID_ATTR_FILL_COLOR)
130             {
131                 delete mpColorItem;
132                 mpColorItem = static_cast< XFillColorItem* >(pState->Clone());
133 
134                 if(eXFS == XFILL_SOLID)
135                 {
136                     bEnableControls = true;
137                 }
138             }
139             else if(nSID == SID_ATTR_FILL_GRADIENT)
140             {
141                 delete mpGradientItem;
142                 mpGradientItem = static_cast< XFillGradientItem* >(pState->Clone());
143 
144                 if(eXFS == XFILL_GRADIENT)
145                 {
146                     bEnableControls = true;
147                 }
148             }
149             else if(nSID == SID_ATTR_FILL_HATCH)
150             {
151                 delete mpHatchItem;
152                 mpHatchItem = static_cast< XFillHatchItem* >(pState->Clone());
153 
154                 if(eXFS == XFILL_HATCH)
155                 {
156                     bEnableControls = true;
157                 }
158             }
159             else if(nSID == SID_ATTR_FILL_BITMAP)
160             {
161                 delete mpBitmapItem;
162                 mpBitmapItem = static_cast< XFillBitmapItem* >(pState->Clone());
163 
164                 if(eXFS == XFILL_BITMAP)
165                 {
166                     bEnableControls = true;
167                 }
168             }
169         }
170 
171         if(mpStyleItem)
172         {
173             // ensure that the correct entry is selected in mpFillTypeLB
174             XFillStyle eXFS(static_cast< XFillStyle >(mpStyleItem->GetValue()));
175             const bool bFillTypeChangedByUser(mpFillControl->mbFillTypeChanged);
176 
177             if(bFillTypeChangedByUser)
178             {
179                 meLastXFS = static_cast< XFillStyle >(mpFillControl->mnLastFillTypeControlSelectEntryPos);
180                 mpFillControl->mbFillTypeChanged = false;
181             }
182 
183             if(meLastXFS != eXFS)
184             {
185                 mbUpdate = true;
186                 mpFillTypeLB->SelectEntryPos(sal::static_int_cast<sal_uInt16>(eXFS));
187             }
188 
189             mpFillAttrLB->Enable();
190         }
191 
192         if(bEnableControls)
193         {
194             mpFillAttrLB->Enable();
195             mbUpdate = true;
196         }
197 
198         Update(pState);
199     }
200     else
201     {
202         // slot empty or ambigous
203         if(nSID == SID_ATTR_FILL_STYLE)
204         {
205             mpFillTypeLB->SetNoSelection();
206             mpFillAttrLB->Disable();
207             mpFillAttrLB->SetNoSelection();
208             delete mpStyleItem;
209             mpStyleItem = 0;
210             mbUpdate = false;
211         }
212         else
213         {
214             XFillStyle eXFS(XFILL_NONE);
215 
216             if(mpStyleItem)
217             {
218                 eXFS = static_cast< XFillStyle >(mpStyleItem->GetValue());
219             }
220 
221             if(!mpStyleItem ||
222                 (nSID == SID_ATTR_FILL_COLOR && eXFS == XFILL_SOLID) ||
223                 (nSID == SID_ATTR_FILL_GRADIENT && eXFS == XFILL_GRADIENT) ||
224                 (nSID == SID_ATTR_FILL_HATCH && eXFS == XFILL_HATCH) ||
225                 (nSID == SID_ATTR_FILL_BITMAP && eXFS == XFILL_BITMAP))
226             {
227                 mpFillAttrLB->SetNoSelection();
228             }
229         }
230     }
231 }
232 
233 //========================================================================
234 
Update(const SfxPoolItem * pState)235 void SvxFillToolBoxControl::Update(const SfxPoolItem* pState)
236 {
237     if(mpStyleItem && pState && mbUpdate)
238     {
239         mbUpdate = false;
240         const XFillStyle eXFS(static_cast< XFillStyle >(mpStyleItem->GetValue()));
241 
242         // Pruefen, ob Fuellstil schon vorher aktiv war
243         if(meLastXFS != eXFS)
244         {
245             // update mnLastFillTypeControlSelectEntryPos and fill style list
246             mpFillControl->updateLastFillTypeControlSelectEntryPos();
247             mpFillControl->InitializeFillStyleAccordingToGivenFillType(eXFS);
248             meLastXFS = eXFS;
249         }
250 
251         switch(eXFS)
252         {
253             case XFILL_NONE:
254             {
255                 break;
256             }
257 
258             case XFILL_SOLID:
259             {
260                 if(mpColorItem)
261                 {
262                     String aString(mpColorItem->GetName());
263                     ::Color aColor = mpColorItem->GetColorValue();
264 
265                     mpFillAttrLB->SelectEntry(aString);
266 
267                     if(mpFillAttrLB->GetSelectEntryPos() == LISTBOX_ENTRY_NOTFOUND || mpFillAttrLB->GetSelectEntryColor() != aColor)
268                     {
269                         mpFillAttrLB->SelectEntry(aColor);
270                     }
271 
272                     // Pruefen, ob Eintrag nicht in der Liste ist
273                     if(mpFillAttrLB->GetSelectEntryPos() == LISTBOX_ENTRY_NOTFOUND || mpFillAttrLB->GetSelectEntryColor() != aColor)
274                     {
275                         sal_uInt16 nCount = mpFillAttrLB->GetEntryCount();
276                         String aTmpStr;
277                         if(nCount > 0)
278                         {
279                             //Letzter Eintrag wird auf temporaere Farbe geprueft
280                             aTmpStr = mpFillAttrLB->GetEntry(nCount - 1);
281 
282                             if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END)
283                             {
284                                 mpFillAttrLB->RemoveEntry(nCount - 1);
285                             }
286                         }
287 
288                         aTmpStr = TMP_STR_BEGIN;
289                         aTmpStr += aString;
290                         aTmpStr += TMP_STR_END;
291 
292                         sal_uInt16 nPos = mpFillAttrLB->InsertEntry(aColor,aTmpStr);
293                         mpFillAttrLB->SelectEntryPos(nPos);
294                     }
295                 }
296                 else
297                 {
298                     mpFillAttrLB->SetNoSelection();
299                 }
300                 break;
301             }
302 
303             case XFILL_GRADIENT:
304             {
305                 if(mpGradientItem)
306                 {
307                     String aString(mpGradientItem->GetName());
308                     mpFillAttrLB->SelectEntry(aString);
309 
310                     // Pruefen, ob Eintrag nicht in der Liste ist
311                     if(mpFillAttrLB->GetSelectEntry() != aString)
312                     {
313                         sal_uInt16 nCount = mpFillAttrLB->GetEntryCount();
314                         String aTmpStr;
315 
316                         if(nCount > 0)
317                         {
318                             //Letzter Eintrag wird auf temporaeren Eintrag geprueft
319                             aTmpStr = mpFillAttrLB->GetEntry(nCount - 1);
320 
321                             if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END)
322                             {
323                                 mpFillAttrLB->RemoveEntry(nCount - 1);
324                             }
325                         }
326 
327                         aTmpStr = TMP_STR_BEGIN;
328                         aTmpStr += aString;
329                         aTmpStr += TMP_STR_END;
330 
331                         XGradientEntry* pEntry = new XGradientEntry(mpGradientItem->GetGradientValue(),aTmpStr);
332                         XGradientListSharedPtr aGradientList(XPropertyListFactory::CreateSharedXGradientList(String::CreateFromAscii("TmpList")));
333 
334                         aGradientList->Insert(pEntry);
335                         aGradientList->SetDirty(false);
336                         const Bitmap aBmp = aGradientList->GetUiBitmap(0);
337 
338                         if(!aBmp.IsEmpty())
339                         {
340                             ((ListBox*)mpFillAttrLB)->InsertEntry(pEntry->GetName(),aBmp);
341                             mpFillAttrLB->SelectEntryPos(mpFillAttrLB->GetEntryCount() - 1);
342                         }
343                     }
344                 }
345                 else
346                 {
347                     mpFillAttrLB->SetNoSelection();
348                 }
349                 break;
350             }
351 
352             case XFILL_HATCH:
353             {
354                 if(mpHatchItem)
355                 {
356                     String aString(mpHatchItem->GetName());
357                     mpFillAttrLB->SelectEntry(aString);
358 
359                     // Pruefen, ob Eintrag nicht in der Liste ist
360                     if(mpFillAttrLB->GetSelectEntry() != aString)
361                     {
362                         sal_uInt16 nCount = mpFillAttrLB->GetEntryCount();
363                         String aTmpStr;
364                         if(nCount > 0)
365                         {
366                             //Letzter Eintrag wird auf temporaeren Eintrag geprueft
367                             aTmpStr = mpFillAttrLB->GetEntry(nCount - 1);
368                             if(aTmpStr.GetChar(0) == TMP_STR_BEGIN &&
369                                 aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END)
370                             {
371                                 mpFillAttrLB->RemoveEntry(nCount - 1);
372                             }
373                         }
374 
375                         aTmpStr = TMP_STR_BEGIN;
376                         aTmpStr += aString;
377                         aTmpStr += TMP_STR_END;
378 
379                         XHatchEntry* pEntry = new XHatchEntry(mpHatchItem->GetHatchValue(),aTmpStr);
380                         XHatchListSharedPtr aHatchList(XPropertyListFactory::CreateSharedXHatchList(String::CreateFromAscii("TmpList")));
381 
382                         aHatchList->Insert(pEntry);
383                         aHatchList->SetDirty(sal_False);
384                         const Bitmap aBmp = aHatchList->GetUiBitmap(0);
385 
386                         if(!aBmp.IsEmpty())
387                         {
388                             ((ListBox*)mpFillAttrLB)->InsertEntry(pEntry->GetName(),aBmp);
389                             mpFillAttrLB->SelectEntryPos(mpFillAttrLB->GetEntryCount() - 1);
390                         }
391                     }
392                 }
393                 else
394                 {
395                     mpFillAttrLB->SetNoSelection();
396                 }
397                 break;
398             }
399 
400             case XFILL_BITMAP:
401             {
402                 if(mpBitmapItem)
403                 {
404                     String aString(mpBitmapItem->GetName());
405                     mpFillAttrLB->SelectEntry(aString);
406 
407                     // Pruefen, ob Eintrag nicht in der Liste ist
408                     if(mpFillAttrLB->GetSelectEntry() != aString)
409                     {
410                         sal_uInt16 nCount = mpFillAttrLB->GetEntryCount();
411                         String aTmpStr;
412 
413                         if(nCount > 0)
414                         {
415                             //Letzter Eintrag wird auf temporaeren Eintrag geprueft
416                             aTmpStr = mpFillAttrLB->GetEntry(nCount - 1);
417 
418                             if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END)
419                             {
420                                 mpFillAttrLB->RemoveEntry(nCount - 1);
421                             }
422                         }
423 
424                         aTmpStr = TMP_STR_BEGIN;
425                         aTmpStr += aString;
426                         aTmpStr += TMP_STR_END;
427 
428                         XBitmapListSharedPtr aNew(XPropertyListFactory::CreateSharedXBitmapList(String::CreateFromAscii("TmpList")));
429                         aNew->Insert(new XBitmapEntry(mpBitmapItem->GetGraphicObject(),aTmpStr));
430                         aNew->SetDirty(false);
431 
432                         mpFillAttrLB->Fill(aNew);
433                         mpFillAttrLB->SelectEntryPos(mpFillAttrLB->GetEntryCount() - 1);
434                     }
435                 }
436                 else
437                 {
438                     mpFillAttrLB->SetNoSelection();
439                 }
440                 break;
441             }
442 
443             default:
444             {
445                 DBG_ERROR("Nicht unterstuetzter Flaechentyp");
446                 break;
447             }
448         }
449 
450         // update mnLastFillAttrControlSelectEntryPos
451         mpFillControl->updateLastFillAttrControlSelectEntryPos();
452     }
453 
454     if(pState && mpStyleItem)
455     {
456         XFillStyle eXFS = static_cast< XFillStyle >(mpStyleItem->GetValue());
457 
458         // Die Listen haben sich geaendert ?
459         switch(eXFS)
460         {
461             case XFILL_SOLID:
462             {
463                 const SvxColorTableItem* pItem = dynamic_cast< const SvxColorTableItem* >(pState);
464 
465                 if(pItem)
466                 {
467                     ::Color aTmpColor(mpFillAttrLB->GetSelectEntryColor());
468                     mpFillAttrLB->Clear();
469                     mpFillAttrLB->Fill(pItem->GetColorTable());
470                     mpFillAttrLB->SelectEntry(aTmpColor);
471                 }
472                 break;
473             }
474             case XFILL_GRADIENT:
475             {
476                 const SvxGradientListItem* pItem = dynamic_cast< const SvxGradientListItem* >(pState);
477 
478                 if(pItem)
479                 {
480                     String aString(mpFillAttrLB->GetSelectEntry());
481                     mpFillAttrLB->Clear();
482                     mpFillAttrLB->Fill(pItem->GetGradientList());
483                     mpFillAttrLB->SelectEntry(aString);
484                 }
485                 break;
486             }
487             case XFILL_HATCH:
488             {
489                 const SvxHatchListItem* pItem = dynamic_cast< const SvxHatchListItem* >(pState);
490 
491                 if(pItem)
492                 {
493                     String aString(mpFillAttrLB->GetSelectEntry());
494                     mpFillAttrLB->Clear();
495                     mpFillAttrLB->Fill(pItem->GetHatchList());
496                     mpFillAttrLB->SelectEntry(aString);
497                 }
498                 break;
499             }
500             case XFILL_BITMAP:
501             {
502                 const SvxBitmapListItem* pItem = dynamic_cast< const SvxBitmapListItem* >(pState);
503 
504                 if(pItem)
505                 {
506                     String aString(mpFillAttrLB->GetSelectEntry());
507                     mpFillAttrLB->Clear();
508                     mpFillAttrLB->Fill(pItem->GetBitmapList());
509                     mpFillAttrLB->SelectEntry(aString);
510                 }
511                 break;
512             }
513             default: // XFILL_NONE
514             {
515                 break;
516             }
517         }
518     }
519 }
520 
521 //========================================================================
522 
CreateItemWindow(Window * pParent)523 Window* SvxFillToolBoxControl::CreateItemWindow(Window *pParent)
524 {
525     if(GetSlotId() == SID_ATTR_FILL_STYLE)
526     {
527         mpFillControl = new FillControl(pParent);
528         // Damit dem FillControl das SvxFillToolBoxControl bekannt ist
529         // (und um kompatibel zu bleiben)
530         mpFillControl->SetData(this);
531 
532         mpFillAttrLB = (SvxFillAttrBox*)mpFillControl->mpLbFillAttr;
533         mpFillTypeLB = (SvxFillTypeBox*)mpFillControl->mpLbFillType;
534 
535         mpFillAttrLB->SetUniqueId(HID_FILL_ATTR_LISTBOX);
536         mpFillTypeLB->SetUniqueId(HID_FILL_TYPE_LISTBOX);
537 
538         if(!mpStyleItem)
539         {
540             // for Writer and Calc it's not the same instance of
541             // SvxFillToolBoxControl which gets used after deselecting
542             // and selecting a DrawObject, thhus a useful initialization is
543             // needed to get the FillType and the FillStyle List inited
544             // correctly. This in combination with meLastXFS inited to
545             // XFILL_NONE do the trick
546             mpStyleItem = new XFillStyleItem(XFILL_SOLID);
547         }
548 
549         return mpFillControl;
550     }
551     return NULL;
552 }
553 
554 /*************************************************************************
555 |*
556 |* FillControl
557 |*
558 \************************************************************************/
559 
FillControl(Window * pParent,WinBits nStyle)560 FillControl::FillControl(Window* pParent,WinBits nStyle)
561 :   Window(pParent,nStyle | WB_DIALOGCONTROL),
562     mpLbFillType(new SvxFillTypeBox(this)),
563     mpLbFillAttr(new SvxFillAttrBox(this)),
564     maLogicalFillSize(40,80),
565     maLogicalAttrSize(50,80),
566     mnLastFillTypeControlSelectEntryPos(mpLbFillType->GetSelectEntryPos()),
567     mnLastFillAttrControlSelectEntryPos(mpLbFillAttr->GetSelectEntryPos()),
568     mbFillTypeChanged(false)
569 {
570     Size aTypeSize(LogicToPixel(maLogicalFillSize,MAP_APPFONT));
571     Size aAttrSize(LogicToPixel(maLogicalAttrSize,MAP_APPFONT));
572     mpLbFillType->SetSizePixel(aTypeSize);
573     mpLbFillAttr->SetSizePixel(aAttrSize);
574 
575     //to get the base height
576     aTypeSize = mpLbFillType->GetSizePixel();
577     aAttrSize = mpLbFillAttr->GetSizePixel();
578     Point aAttrPnt = mpLbFillAttr->GetPosPixel();
579     SetSizePixel(
580         Size(aAttrPnt.X() + aAttrSize.Width(),
581         Max(aAttrSize.Height(),aTypeSize.Height())));
582 
583     mpLbFillType->SetSelectHdl(LINK(this,FillControl,SelectFillTypeHdl));
584     mpLbFillAttr->SetSelectHdl(LINK(this,FillControl,SelectFillAttrHdl));
585 }
586 
587 //------------------------------------------------------------------------
588 
~FillControl()589 FillControl::~FillControl()
590 {
591     delete mpLbFillType;
592     delete mpLbFillAttr;
593 }
594 
595 //------------------------------------------------------------------------
596 
InitializeFillStyleAccordingToGivenFillType(XFillStyle aFillStyle)597 void FillControl::InitializeFillStyleAccordingToGivenFillType(XFillStyle aFillStyle)
598 {
599     SfxObjectShell* pSh = SfxObjectShell::Current();
600     bool bDone(false);
601 
602     if(pSh)
603     {
604         // clear in all cases, else we would risk a mix of FillStyles in the Style list
605         mpLbFillAttr->Clear();
606 
607         switch(aFillStyle)
608         {
609             case XFILL_SOLID:
610             {
611                 if(pSh->GetItem(SID_COLOR_TABLE))
612                 {
613                     const SvxColorTableItem* pItem = static_cast< const SvxColorTableItem* >(pSh->GetItem(SID_COLOR_TABLE));
614                     mpLbFillAttr->Enable();
615                     mpLbFillAttr->Fill(pItem->GetColorTable());
616                     bDone = true;
617                 }
618                 break;
619             }
620 
621             case XFILL_GRADIENT:
622             {
623                 if(pSh->GetItem(SID_GRADIENT_LIST))
624                 {
625                     const SvxGradientListItem* pItem = static_cast< const SvxGradientListItem* >(pSh->GetItem(SID_GRADIENT_LIST));
626                     mpLbFillAttr->Enable();
627                     mpLbFillAttr->Fill(pItem->GetGradientList());
628                     bDone = true;
629                 }
630                 break;
631             }
632 
633             case XFILL_HATCH:
634             {
635                 if(pSh->GetItem(SID_HATCH_LIST))
636                 {
637                     const SvxHatchListItem* pItem = static_cast< const SvxHatchListItem* >(pSh->GetItem(SID_HATCH_LIST));
638                     mpLbFillAttr->Enable();
639                     mpLbFillAttr->Fill(pItem->GetHatchList());
640                     bDone = true;
641                 }
642                 break;
643             }
644 
645             case XFILL_BITMAP:
646             {
647                 if(pSh->GetItem(SID_BITMAP_LIST))
648                 {
649                     const SvxBitmapListItem* pItem = static_cast< const SvxBitmapListItem* >(pSh->GetItem(SID_BITMAP_LIST));
650                     mpLbFillAttr->Enable();
651                     mpLbFillAttr->Fill(pItem->GetBitmapList());
652                     bDone = true;
653                 }
654                 break;
655             }
656             default: // XFILL_NONE
657             {
658                 // accept disable (no styles for XFILL_NONE)
659                 break;
660             }
661         }
662     }
663 
664     if(!bDone)
665     {
666         mpLbFillAttr->Disable();
667     }
668 }
669 
updateLastFillTypeControlSelectEntryPos()670 void FillControl::updateLastFillTypeControlSelectEntryPos()
671 {
672     mnLastFillTypeControlSelectEntryPos = mpLbFillType->GetSelectEntryPos();
673 }
674 
IMPL_LINK(FillControl,SelectFillTypeHdl,ListBox *,pBox)675 IMPL_LINK(FillControl,SelectFillTypeHdl,ListBox *,pBox)
676 {
677     if(!pBox) // only work with real calls from ListBox, do not accept direct calls with zeros here
678     {
679         return 0;
680     }
681 
682     const bool bAction(
683            !mpLbFillType->IsTravelSelect() // keep TravelSelect, this means keyboard up/down in the list
684         && mpLbFillType->GetSelectEntryCount()
685         && mpLbFillType->GetSelectEntryPos() != mnLastFillTypeControlSelectEntryPos);
686 
687     updateLastFillTypeControlSelectEntryPos();
688     XFillStyle eXFS = static_cast< XFillStyle >(mpLbFillType->GetSelectEntryPos());
689 
690     if(bAction && XFILL_NONE != eXFS)
691     {
692         mbFillTypeChanged = true;
693     }
694 
695     // update list of FillStyles in any case
696     InitializeFillStyleAccordingToGivenFillType(eXFS);
697 
698     // for XFILL_NONE do no longer call SelectFillAttrHdl (as done before),
699     // trigger needed actions directly. This is the only action this handler
700     // can trigger directly as the user action is finished in this case
701     if(XFILL_NONE == eXFS && bAction)
702     {
703         // for XFILL_NONE do no longer call SelectFillAttrHdl,
704         // trigger needed actions directly
705         Any a;
706         Sequence< PropertyValue > aArgsFillStyle(1);
707         XFillStyleItem aXFillStyleItem(eXFS);
708 
709         aArgsFillStyle[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"));
710         aXFillStyleItem.QueryValue(a);
711         aArgsFillStyle[0].Value = a;
712         ((SvxFillToolBoxControl*)GetData())->Dispatch(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillStyle")), aArgsFillStyle);
713     }
714 
715     mpLbFillType->Selected();
716 
717     // release focus. Needed to get focus automatically back to EditView
718     if(mpLbFillType->IsRelease())
719     {
720         SfxViewShell* pViewShell = SfxViewShell::Current();
721 
722         if(pViewShell && pViewShell->GetWindow())
723         {
724             pViewShell->GetWindow()->GrabFocus();
725         }
726     }
727 
728     return 0;
729 }
730 
731 //------------------------------------------------------------------------
732 
updateLastFillAttrControlSelectEntryPos()733 void FillControl::updateLastFillAttrControlSelectEntryPos()
734 {
735     mnLastFillAttrControlSelectEntryPos = mpLbFillAttr->GetSelectEntryPos();
736 }
737 
IMPL_LINK(FillControl,SelectFillAttrHdl,ListBox *,pBox)738 IMPL_LINK(FillControl, SelectFillAttrHdl, ListBox *, pBox)
739 {
740     if(!pBox) // only work with real calls from ListBox, do not accept direct calls with zeros here
741     {
742         return 0;
743     }
744 
745     const bool bAction(
746            !mpLbFillAttr->IsTravelSelect() // keep TravelSelect, this means keyboard up/down in the list
747         && mpLbFillAttr->GetSelectEntryCount()
748         && mpLbFillAttr->GetSelectEntryPos() != mnLastFillAttrControlSelectEntryPos);
749 
750     updateLastFillAttrControlSelectEntryPos();
751 
752     if(bAction)
753     {
754         SfxObjectShell* pSh = SfxObjectShell::Current();
755 
756         // Need to prepare the PropertyValue for the FillStyle dispatch action early,
757         // else the call for FillType to Dispatch(".uno:FillStyle") will already destroy the current state
758         // of selection in mpLbFillAttr again by calls to StateChanged which *will* set to no
759         // selection again (e.g. when two objects, same fill style, but different fill attributes)
760         Any a;
761         Sequence< PropertyValue > aArgsFillAttr(1);
762         ::rtl::OUString aFillAttrCommand;
763         XFillStyle eXFS(static_cast< XFillStyle >(mpLbFillType->GetSelectEntryPos()));
764 
765         switch(eXFS)
766         {
767             case XFILL_NONE:
768             {
769                 // handled in SelectFillTypeHdl, nothing to do here
770                 break;
771             }
772 
773             case XFILL_SOLID:
774             {
775                 //Eintrag wird auf temporaere Farbe geprueft
776                 String aTmpStr = mpLbFillAttr->GetSelectEntry();
777 
778                 if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END)
779                 {
780                     aTmpStr.Erase(aTmpStr.Len() - 1,1);
781                     aTmpStr.Erase(0,1);
782                 }
783 
784                 XFillColorItem aXFillColorItem(aTmpStr,mpLbFillAttr->GetSelectEntryColor());
785                 aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor"));
786                 aXFillColorItem.QueryValue(a);
787                 aArgsFillAttr[0].Value = a;
788                 aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillColor"));
789                 break;
790             }
791             case XFILL_GRADIENT:
792             {
793                 sal_uInt16 nPos = mpLbFillAttr->GetSelectEntryPos();
794 
795                 if(nPos != LISTBOX_ENTRY_NOTFOUND && pSh && pSh->GetItem(SID_GRADIENT_LIST))
796                 {
797                     const SvxGradientListItem* pItem = static_cast< const SvxGradientListItem* >(pSh->GetItem(SID_GRADIENT_LIST));
798 
799                     if(nPos < pItem->GetGradientList()->Count())  // kein temp. Eintrag ?
800                     {
801                         XGradient aGradient = pItem->GetGradientList()->GetGradient(nPos)->GetGradient();
802                         XFillGradientItem aXFillGradientItem(mpLbFillAttr->GetSelectEntry(),aGradient);
803                         aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillGradient"));
804                         aXFillGradientItem.QueryValue(a);
805                         aArgsFillAttr[0].Value = a;
806                         aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillGradient"));
807                     }
808                 }
809                 break;
810             }
811 
812             case XFILL_HATCH:
813             {
814                 sal_uInt16 nPos = mpLbFillAttr->GetSelectEntryPos();
815 
816                 if(nPos != LISTBOX_ENTRY_NOTFOUND && pSh && pSh->GetItem(SID_HATCH_LIST))
817                 {
818                     const SvxHatchListItem* pItem = static_cast< const SvxHatchListItem* >(pSh->GetItem(SID_HATCH_LIST));
819 
820                     if(nPos < pItem->GetHatchList()->Count())  // kein temp. Eintrag ?
821                     {
822                         XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch();
823                         XFillHatchItem aXFillHatchItem(mpLbFillAttr->GetSelectEntry(),aHatch);
824 
825                         aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillHatch"));
826                         aXFillHatchItem.QueryValue(a);
827                         aArgsFillAttr[0].Value = a;
828                         aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillHatch"));
829                     }
830                 }
831                 break;
832             }
833 
834             case XFILL_BITMAP:
835             {
836                 sal_uInt16 nPos = mpLbFillAttr->GetSelectEntryPos();
837 
838                 if(nPos != LISTBOX_ENTRY_NOTFOUND && pSh && pSh->GetItem(SID_BITMAP_LIST))
839                 {
840                     const SvxBitmapListItem* pItem = static_cast< const SvxBitmapListItem* >(pSh->GetItem(SID_BITMAP_LIST));
841 
842                     if(nPos < pItem->GetBitmapList()->Count())  // kein temp. Eintrag ?
843                     {
844                         const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos);
845                         const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->GetSelectEntry(),pXBitmapEntry->GetGraphicObject());
846 
847                         aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillBitmap"));
848                         aXFillBitmapItem.QueryValue(a);
849                         aArgsFillAttr[0].Value = a;
850                         aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillBitmap"));
851                     }
852                 }
853                 break;
854             }
855         }
856 
857         // this is the place where evtl. a new slot action may be introduced to avoid the
858         // two undo entries. Reason for this is that indeed two actions are executed, the fill style
859         // and the fill attribute change. The sidebar already handles both separately, so
860         // changing the fill style already changes the object and adds a default fill attribute for
861         // the newly choosen fill style.
862         // This control uses the older user's two-step action to select a fill style and a fill attribute. In
863         // this case a lot of things may go wrong (e.g. the user stops that action and does something
864         // different), thus the solution of the sidebar should be preferred from my POV in the future
865 
866         // first set the fill style if changed
867         if(mbFillTypeChanged)
868         {
869             Sequence< PropertyValue > aArgsFillStyle(1);
870             XFillStyleItem aXFillStyleItem(eXFS);
871 
872             aArgsFillStyle[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"));
873             aXFillStyleItem.QueryValue(a);
874             aArgsFillStyle[0].Value = a;
875             ((SvxFillToolBoxControl*)GetData())->Dispatch(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillStyle")), aArgsFillStyle);
876             mbFillTypeChanged = false;
877         }
878 
879         // second set fill attribute when a change was detected and prepared
880         if(aFillAttrCommand.getLength())
881         {
882             ((SvxFillToolBoxControl*)GetData())->Dispatch(aFillAttrCommand, aArgsFillAttr);
883         }
884 
885         // release focus. Needed to get focus automatically back to EditView
886         if(mpLbFillAttr->IsRelease() && pBox)
887         {
888             SfxViewShell* pViewShell = SfxViewShell::Current();
889 
890             if(pViewShell && pViewShell->GetWindow())
891             {
892                 pViewShell->GetWindow()->GrabFocus();
893             }
894         }
895     }
896 
897     return 0;
898 }
899 
900 //------------------------------------------------------------------------
901 
Resize()902 void FillControl::Resize()
903 {
904     // Breite der beiden ListBoxen nicht 1/2 : 1/2, sondern 2/5 : 3/5
905     long nW = GetOutputSizePixel().Width() / 5;
906     long nH = 180;
907     long nSep = 0; // war vorher 4
908 
909     mpLbFillType->SetSizePixel(Size(nW * 2 - nSep,nH));
910     mpLbFillAttr->SetPosSizePixel(Point(nW * 2 + nSep,0),Size(nW * 3 - nSep,nH));
911 }
912 
913 //------------------------------------------------------------------------
914 
DataChanged(const DataChangedEvent & rDCEvt)915 void FillControl::DataChanged(const DataChangedEvent& rDCEvt)
916 {
917     if((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
918         (rDCEvt.GetFlags() & SETTINGS_STYLE))
919     {
920         Size aTypeSize(LogicToPixel(maLogicalFillSize,MAP_APPFONT));
921         Size aAttrSize(LogicToPixel(maLogicalAttrSize,MAP_APPFONT));
922         mpLbFillType->SetSizePixel(aTypeSize);
923         mpLbFillAttr->SetSizePixel(aAttrSize);
924 
925         //to get the base height
926         aTypeSize = mpLbFillType->GetSizePixel();
927         aAttrSize = mpLbFillAttr->GetSizePixel();
928         Point aAttrPnt = mpLbFillAttr->GetPosPixel();
929 
930         SetSizePixel(
931             Size(aAttrPnt.X() + aAttrSize.Width(),
932             Max(aAttrSize.Height(),aTypeSize.Height())));
933     }
934     Window::DataChanged(rDCEvt);
935 }
936 
937 //------------------------------------------------------------------------
938 //eof
939