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