xref: /trunk/main/vcl/source/window/toolbox2.cxx (revision e1d5bd03a6ea7ac2b26b792c9e2a94e9f347a43b)
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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <tools/list.hxx>
28 #include <tools/debug.hxx>
29 #include <tools/rc.h>
30 
31 #include <vcl/svapp.hxx>
32 #include <vcl/help.hxx>
33 #include <vcl/bitmap.hxx>
34 #include <vcl/toolbox.hxx>
35 #include <vcl/mnemonic.hxx>
36 #include <vcl/menu.hxx>
37 #include <vcl/unohelp.hxx>
38 #include <vcl/ImageListProvider.hxx>
39 
40 #include <svdata.hxx>
41 #include <brdwin.hxx>
42 #include <toolbox.h>
43 
44 #include <unotools/confignode.hxx>
45 
46 #include <com/sun/star/lang/IllegalArgumentException.hpp>
47 
48 using namespace vcl;
49 using namespace rtl;
50 
51 // =======================================================================
52 
53 #define TB_SEP_SIZE             8
54 
55 // -----------------------------------------------------------------------
56 
57 ImplToolBoxPrivateData::ImplToolBoxPrivateData() :
58         m_pLayoutData( NULL ),
59         mpImageListProvider( NULL ),
60         meImageListType( vcl::IMAGELISTTYPE_UNKNOWN )
61 {
62     meButtonSize = TOOLBOX_BUTTONSIZE_DONTCARE;
63     mpMenu = new PopupMenu();
64     mnEventId = 0;
65 
66     maMenuType = TOOLBOX_MENUTYPE_NONE;
67     maMenubuttonItem.maItemSize = Size( TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET, TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET );
68     maMenubuttonItem.meState = STATE_NOCHECK;
69     mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
70 
71 
72     mbIsLocked = sal_False;
73     mbNativeButtons = sal_False;
74     mbIsPaintLocked = sal_False;
75     mbAssumeDocked = sal_False;
76     mbAssumePopupMode = sal_False;
77     mbAssumeFloating = sal_False;
78     mbKeyInputDisabled = sal_False;
79     mbMenubuttonSelected = sal_False;
80     mbPageScroll = sal_False;
81     mbWillUsePopupMode = sal_False;
82     mbDropDownByKeyboard = sal_False;
83 }
84 
85 ImplToolBoxPrivateData::~ImplToolBoxPrivateData()
86 {
87     if( m_pLayoutData )
88         delete m_pLayoutData;
89     delete mpMenu;
90 }
91 
92 // -----------------------------------------------------------------------
93 ImplToolItem::ImplToolItem()
94 {
95     mnId            = 0;
96     mpWindow        = NULL;
97     mpUserData      = NULL;
98     meType          = TOOLBOXITEM_BUTTON;
99     mnBits          = 0;
100     meState         = STATE_NOCHECK;
101     mbEnabled       = sal_True;
102     mbVisible       = sal_True;
103     mbEmptyBtn      = sal_True;
104     mbShowWindow    = sal_False;
105     mbBreak         = sal_False;
106     mnSepSize       = TB_SEP_SIZE;
107     mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
108     mnImageAngle    = 0;
109     mbMirrorMode    = sal_False;
110     mbVisibleText   = sal_False;
111 }
112 
113 // -----------------------------------------------------------------------
114 
115 ImplToolItem::ImplToolItem( sal_uInt16 nItemId, const Image& rImage,
116                             ToolBoxItemBits nItemBits ) :
117     maImage( rImage )
118 {
119     mnId            = nItemId;
120     mpWindow        = NULL;
121     mpUserData      = NULL;
122     meType          = TOOLBOXITEM_BUTTON;
123     mnBits          = nItemBits;
124     meState         = STATE_NOCHECK;
125     mbEnabled       = sal_True;
126     mbVisible       = sal_True;
127     mbEmptyBtn      = sal_False;
128     mbShowWindow    = sal_False;
129     mbBreak         = sal_False;
130     mnSepSize       = TB_SEP_SIZE;
131     mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
132     mnImageAngle    = 0;
133     mbMirrorMode    = false;
134     mbVisibleText   = false;
135 }
136 
137 // -----------------------------------------------------------------------
138 
139 ImplToolItem::ImplToolItem( sal_uInt16 nItemId, const XubString& rText,
140                             ToolBoxItemBits nItemBits ) :
141     maText( rText )
142 {
143     mnId            = nItemId;
144     mpWindow        = NULL;
145     mpUserData      = NULL;
146     meType          = TOOLBOXITEM_BUTTON;
147     mnBits          = nItemBits;
148     meState         = STATE_NOCHECK;
149     mbEnabled       = sal_True;
150     mbVisible       = sal_True;
151     mbEmptyBtn      = sal_False;
152     mbShowWindow    = sal_False;
153     mbBreak         = sal_False;
154     mnSepSize       = TB_SEP_SIZE;
155     mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
156     mnImageAngle    = 0;
157     mbMirrorMode    = false;
158     mbVisibleText   = false;
159 }
160 
161 // -----------------------------------------------------------------------
162 
163 ImplToolItem::ImplToolItem( sal_uInt16 nItemId, const Image& rImage,
164                             const XubString& rText, ToolBoxItemBits nItemBits ) :
165     maImage( rImage ),
166     maText( rText )
167 {
168     mnId            = nItemId;
169     mpWindow        = NULL;
170     mpUserData      = NULL;
171     meType          = TOOLBOXITEM_BUTTON;
172     mnBits          = nItemBits;
173     meState         = STATE_NOCHECK;
174     mbEnabled       = sal_True;
175     mbVisible       = sal_True;
176     mbEmptyBtn      = sal_False;
177     mbShowWindow    = sal_False;
178     mbBreak         = sal_False;
179     mnSepSize       = TB_SEP_SIZE;
180     mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
181     mnImageAngle    = 0;
182     mbMirrorMode    = false;
183     mbVisibleText   = false;
184 }
185 
186 // -----------------------------------------------------------------------
187 
188 ImplToolItem::ImplToolItem( const ImplToolItem& rItem ) :
189         mpWindow                ( rItem.mpWindow ),
190         mpUserData              ( rItem.mpUserData ),
191         maImage                 ( rItem.maImage ),
192         maHighImage             ( rItem.maHighImage ),
193         mnImageAngle            ( rItem.mnImageAngle ),
194         mbMirrorMode            ( rItem.mbMirrorMode ),
195         maText                  ( rItem.maText ),
196         maQuickHelpText         ( rItem.maQuickHelpText ),
197         maHelpText              ( rItem.maHelpText ),
198         maCommandStr            ( rItem.maCommandStr ),
199         maHelpId                ( rItem.maHelpId ),
200         maRect                  ( rItem.maRect ),
201         maCalcRect              ( rItem.maCalcRect ),
202         maItemSize              ( rItem.maItemSize ),
203         mnSepSize               ( rItem.mnSepSize ),
204         mnDropDownArrowWidth    ( rItem.mnDropDownArrowWidth ),
205         meType                  ( rItem.meType ),
206         mnBits                  ( rItem.mnBits ),
207         meState                 ( rItem.meState ),
208         mnId                    ( rItem.mnId ),
209         mbEnabled               ( rItem.mbEnabled ),
210         mbVisible               ( rItem.mbVisible ),
211         mbEmptyBtn              ( rItem.mbEmptyBtn ),
212         mbShowWindow            ( rItem.mbShowWindow ),
213         mbBreak                 ( rItem.mbBreak ),
214         mbVisibleText           ( rItem.mbVisibleText )
215 {
216 }
217 
218 // -----------------------------------------------------------------------
219 
220 ImplToolItem::~ImplToolItem()
221 {
222 }
223 
224 // -----------------------------------------------------------------------
225 
226 ImplToolItem& ImplToolItem::operator=( const ImplToolItem& rItem )
227 {
228     mpWindow                = rItem.mpWindow;
229     mpUserData              = rItem.mpUserData;
230     maImage                 = rItem.maImage;
231     maHighImage             = rItem.maHighImage;
232     mnImageAngle            = rItem.mnImageAngle;
233     mbMirrorMode            = rItem.mbMirrorMode;
234     maText                  = rItem.maText;
235     maQuickHelpText         = rItem.maQuickHelpText;
236     maHelpText              = rItem.maHelpText;
237     maCommandStr            = rItem.maCommandStr;
238     maHelpId                = rItem.maHelpId;
239     maRect                  = rItem.maRect;
240     maCalcRect              = rItem.maCalcRect;
241     mnSepSize               = rItem.mnSepSize;
242     mnDropDownArrowWidth    = rItem.mnDropDownArrowWidth;
243     maItemSize              = rItem.maItemSize;
244     mbVisibleText           = rItem.mbVisibleText;
245     meType                  = rItem.meType;
246     mnBits                  = rItem.mnBits;
247     meState                 = rItem.meState;
248     mnId                    = rItem.mnId;
249     mbEnabled               = rItem.mbEnabled;
250     mbVisible               = rItem.mbVisible;
251     mbEmptyBtn              = rItem.mbEmptyBtn;
252     mbShowWindow            = rItem.mbShowWindow;
253     mbBreak                 = rItem.mbBreak;
254     return *this;
255 }
256 
257 // -----------------------------------------------------------------------
258 
259 Size ImplToolItem::GetSize( sal_Bool bHorz, sal_Bool bCheckMaxWidth, long maxWidth, const Size& rDefaultSize )
260 {
261     Size aSize( rDefaultSize ); // the size of 'standard' toolbox items
262                                 // non-standard items are eg windows or buttons with text
263 
264     if ( (meType == TOOLBOXITEM_BUTTON) || (meType == TOOLBOXITEM_SPACE) )
265     {
266         aSize = maItemSize;
267 
268         if ( mpWindow && bHorz )
269         {
270             // get size of item window and check if it fits
271             // no windows in vertical toolbars (the default is mbShowWindow=sal_False)
272             Size aWinSize = mpWindow->GetSizePixel();
273             if ( !bCheckMaxWidth || (aWinSize.Width() <= maxWidth) )
274             {
275                 aSize.Width()   = aWinSize.Width();
276                 aSize.Height()  = aWinSize.Height();
277                 mbShowWindow = sal_True;
278             }
279             else
280             {
281                 if ( mbEmptyBtn )
282                 {
283                     aSize.Width()   = 0;
284                     aSize.Height()  = 0;
285                 }
286             }
287         }
288     }
289     else if ( meType == TOOLBOXITEM_SEPARATOR )
290     {
291         if ( bHorz )
292         {
293             aSize.Width()   = mnSepSize;
294             aSize.Height()  = rDefaultSize.Height();
295         }
296         else
297         {
298             aSize.Width()   = rDefaultSize.Width();
299             aSize.Height()  = mnSepSize;
300         }
301     }
302     else if ( meType == TOOLBOXITEM_BREAK )
303     {
304         aSize.Width()   = 0;
305         aSize.Height()  = 0;
306     }
307 
308     return aSize;
309 }
310 
311 // -----------------------------------------------------------------------
312 
313 void ImplToolItem::DetermineButtonDrawStyle( ButtonType eButtonType, sal_Bool& rbImage, sal_Bool& rbText ) const
314 {
315     if ( meType != TOOLBOXITEM_BUTTON )
316     {
317         // no button -> draw nothing
318         rbImage = rbText = sal_False;
319         return;
320     }
321 
322     sal_Bool bHasImage;
323     sal_Bool bHasText;
324 
325     // check for image and/or text
326     if ( !(maImage) )
327         bHasImage = sal_False;
328     else
329         bHasImage = sal_True;
330     if ( !maText.Len() )
331         bHasText = sal_False;
332     else
333         bHasText = sal_True;
334 
335     // prefer images if symbolonly buttons are drawn
336     // prefer texts if textonly buttons are dreawn
337 
338     if ( eButtonType == BUTTON_SYMBOL )         // drawing icons only
339     {
340         if( bHasImage || !bHasText )
341         {
342             rbImage = sal_True;
343             rbText  = sal_False;
344         }
345         else
346         {
347             rbImage = sal_False;
348             rbText  = sal_True;
349         }
350     }
351     else if ( eButtonType == BUTTON_TEXT )      // drawing text only
352     {
353         if( bHasText || !bHasImage )
354         {
355             rbImage = sal_False;
356             rbText  = sal_True;
357         }
358         else
359         {
360             rbImage = sal_True;
361             rbText  = sal_False;
362         }
363     }
364     else                                        // drawing icons and text both
365     {
366         rbImage = sal_True;
367         rbText  = sal_True;
368     }
369 }
370 
371 // -----------------------------------------------------------------------
372 
373 Rectangle ImplToolItem::GetDropDownRect( sal_Bool bHorz ) const
374 {
375     Rectangle aRect;
376     if( (mnBits & TIB_DROPDOWN) && !maRect.IsEmpty() )
377     {
378         aRect = maRect;
379         if( mbVisibleText && !bHorz )
380             // item will be rotated -> place dropdown to the bottom
381             aRect.Top() = aRect.Bottom() - mnDropDownArrowWidth;
382         else
383             // place dropdown to the right
384             aRect.Left() = aRect.Right() - mnDropDownArrowWidth;
385     }
386     return aRect;
387 }
388 
389 // -----------------------------------------------------------------------
390 
391 sal_Bool ImplToolItem::IsClipped() const
392 {
393     return ( meType == TOOLBOXITEM_BUTTON && mbVisible && maRect.IsEmpty() );
394 }
395 
396 // -----------------------------------------------------------------------
397 // -----------------------------------------------------------------------
398 
399 const XubString& ToolBox::ImplConvertMenuString( const XubString& rStr )
400 {
401     maCvtStr = rStr;
402     if ( mbMenuStrings )
403         maCvtStr.EraseTrailingChars( '.' );
404     maCvtStr = MnemonicGenerator::EraseAllMnemonicChars( maCvtStr );
405     return maCvtStr;
406 }
407 
408 // -----------------------------------------------------------------------
409 
410 void ToolBox::ImplInvalidate( sal_Bool bNewCalc, sal_Bool bFullPaint )
411 {
412     ImplUpdateInputEnable();
413 
414     if ( bNewCalc )
415         mbCalc = sal_True;
416 
417     if ( bFullPaint )
418     {
419         mbFormat = sal_True;
420 
421         // Muss ueberhaupt eine neue Ausgabe erfolgen
422         if ( IsReallyVisible() && IsUpdateMode() )
423         {
424             Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
425                                    mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
426             maTimer.Stop();
427         }
428     }
429     else
430     {
431         if ( !mbFormat )
432         {
433             mbFormat = sal_True;
434 
435             // Muss ueberhaupt eine neue Ausgabe erfolgen
436             if ( IsReallyVisible() && IsUpdateMode() )
437                 maTimer.Start();
438         }
439     }
440 
441     // request new layout by layoutmanager
442     ImplCallEventListeners( VCLEVENT_TOOLBOX_FORMATCHANGED );
443 }
444 
445 // -----------------------------------------------------------------------
446 
447 void ToolBox::ImplUpdateItem( sal_uInt16 nIndex )
448 {
449     // Muss ueberhaupt eine neue Ausgabe erfolgen
450     if ( IsReallyVisible() && IsUpdateMode() )
451     {
452         if ( nIndex == 0xFFFF )
453         {
454             // #i52217# no immediate draw as this might lead to paint problems
455             Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
456                                     mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
457         }
458         else
459         {
460             if ( !mbFormat )
461             {
462                 // #i52217# no immediate draw as this might lead to paint problems
463                 Invalidate( mpData->m_aItems[nIndex].maRect );
464             }
465             else
466                 maPaintRect.Union( mpData->m_aItems[nIndex].maRect );
467         }
468     }
469 }
470 
471 // -----------------------------------------------------------------------
472 
473 void ToolBox::Click()
474 {
475     ImplCallEventListeners( VCLEVENT_TOOLBOX_CLICK );
476     maClickHdl.Call( this );
477 }
478 
479 // -----------------------------------------------------------------------
480 
481 void ToolBox::DoubleClick()
482 {
483     ImplCallEventListeners( VCLEVENT_TOOLBOX_DOUBLECLICK );
484     maDoubleClickHdl.Call( this );
485 }
486 
487 // -----------------------------------------------------------------------
488 
489 void ToolBox::Activate()
490 {
491     mnActivateCount++;
492     ImplCallEventListeners( VCLEVENT_TOOLBOX_ACTIVATE );
493     maActivateHdl.Call( this );
494 }
495 
496 // -----------------------------------------------------------------------
497 
498 void ToolBox::Deactivate()
499 {
500     mnActivateCount--;
501     ImplCallEventListeners( VCLEVENT_TOOLBOX_DEACTIVATE );
502     maDeactivateHdl.Call( this );
503 
504     if ( mbHideStatusText )
505     {
506         GetpApp()->HideHelpStatusText();
507         mbHideStatusText = sal_False;
508     }
509 }
510 
511 // -----------------------------------------------------------------------
512 
513 void ToolBox::Highlight()
514 {
515     ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
516     maHighlightHdl.Call( this );
517 
518     XubString aStr = GetHelpText( mnCurItemId );
519     if ( aStr.Len() || mbHideStatusText )
520     {
521         GetpApp()->ShowHelpStatusText( aStr );
522         mbHideStatusText = sal_True;
523     }
524 }
525 
526 // -----------------------------------------------------------------------
527 
528 void ToolBox::Select()
529 {
530     ImplDelData aDelData;
531     ImplAddDel( &aDelData );
532 
533     ImplCallEventListeners( VCLEVENT_TOOLBOX_SELECT );
534     maSelectHdl.Call( this );
535 
536     if ( aDelData.IsDelete() )
537         return;
538     ImplRemoveDel( &aDelData );
539 
540     // TODO: GetFloatingWindow in DockingWindow is currently inline, change it to check dockingwrapper
541     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
542     if( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() )
543         pWrapper->GetFloatingWindow()->EndPopupMode();
544 }
545 
546 // -----------------------------------------------------------------------
547 
548 void ToolBox::NextToolBox()
549 {
550     maNextToolBoxHdl.Call( this );
551 }
552 
553 // -----------------------------------------------------------------------
554 
555 void ToolBox::Customize( const ToolBoxCustomizeEvent& )
556 {
557 }
558 
559 // -----------------------------------------------------------------------
560 
561 void ToolBox::UserDraw( const UserDrawEvent& )
562 {
563 }
564 
565 // -----------------------------------------------------------------------
566 
567 void ToolBox::InsertItem( const ResId& rResId, sal_uInt16 nPos )
568 {
569     sal_uLong                   nObjMask;
570     sal_Bool                    bImage = sal_False;     // Wurde Image gesetzt
571 
572     // Item anlegen
573     ImplToolItem aItem;
574 
575     GetRes( rResId.SetRT( RSC_TOOLBOXITEM ) );
576     nObjMask            = ReadLongRes();
577 
578     if ( nObjMask & RSC_TOOLBOXITEM_ID )
579         aItem.mnId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
580     else
581         aItem.mnId = 1;
582 
583     if ( nObjMask & RSC_TOOLBOXITEM_TYPE )
584         aItem.meType = (ToolBoxItemType)ReadLongRes();
585 
586     if ( nObjMask & RSC_TOOLBOXITEM_STATUS )
587         aItem.mnBits = (ToolBoxItemBits)ReadLongRes();
588 
589     if( nObjMask & RSC_TOOLBOXITEM_HELPID )
590         aItem.maHelpId = ReadByteStringRes();
591 
592     if ( nObjMask & RSC_TOOLBOXITEM_TEXT )
593     {
594         aItem.maText = ReadStringRes();
595         aItem.maText = ImplConvertMenuString( aItem.maText );
596     }
597     if ( nObjMask & RSC_TOOLBOXITEM_HELPTEXT )
598         aItem.maHelpText = ReadStringRes();
599 
600     if ( nObjMask & RSC_TOOLBOXITEM_BITMAP )
601     {
602         Bitmap aBmp = Bitmap( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) );
603         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
604         aItem.maImage = Image( aBmp, IMAGE_STDBTN_COLOR );
605         bImage = sal_True;
606     }
607     if ( nObjMask & RSC_TOOLBOXITEM_IMAGE )
608     {
609         aItem.maImage = Image( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) );
610         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
611         bImage = sal_True;
612     }
613     if ( nObjMask & RSC_TOOLBOXITEM_DISABLE )
614         aItem.mbEnabled = !(sal_Bool)ReadShortRes();
615 
616     if ( nObjMask & RSC_TOOLBOXITEM_STATE )
617         aItem.meState   = (TriState)ReadLongRes();
618 
619     if ( nObjMask & RSC_TOOLBOXITEM_HIDE )
620         aItem.mbVisible = !((sal_Bool)ReadShortRes());
621 
622     if ( nObjMask & RSC_TOOLBOXITEM_COMMAND )
623         aItem.maCommandStr = ReadStringRes();
624 
625     // Wenn kein Image geladen wurde, versuchen wir das Image aus der
626     // Image-Liste zu holen
627     if ( !bImage && aItem.mnId )
628         aItem.maImage = maImageList.GetImage( aItem.mnId );
629 
630     // Wenn es sich um ein ButtonItem handelt, die ID ueberpruefen
631     sal_Bool bNewCalc;
632     if ( aItem.meType != TOOLBOXITEM_BUTTON )
633     {
634         bNewCalc = sal_False;
635         aItem.mnId = 0;
636     }
637     else
638     {
639         bNewCalc = sal_True;
640 
641         DBG_ASSERT( aItem.mnId, "ToolBox::InsertItem(): ItemId == 0" );
642         DBG_ASSERT( GetItemPos( aItem.mnId ) == TOOLBOX_ITEM_NOTFOUND,
643                     "ToolBox::InsertItem(): ItemId already exists" );
644     }
645 
646     // Item anlegen und in die Liste einfuegen
647     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
648     mpData->ImplClearLayoutData();
649 
650     // ToolBox neu brechnen und neu ausgeben
651     ImplInvalidate( bNewCalc );
652 
653     // Notify
654     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
655     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
656 }
657 
658 // -----------------------------------------------------------------------
659 
660 void ToolBox::InsertItem( sal_uInt16 nItemId, const Image& rImage,
661                           ToolBoxItemBits nBits, sal_uInt16 nPos )
662 {
663     DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
664     DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
665                 "ToolBox::InsertItem(): ItemId already exists" );
666 
667     // Item anlegen und in die Liste einfuegen
668     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, rImage, nBits ) );
669     mpData->ImplClearLayoutData();
670 
671     ImplInvalidate( sal_True );
672 
673     // Notify
674     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
675     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >(nNewPos ) );
676 }
677 
678 // -----------------------------------------------------------------------
679 
680 void ToolBox::InsertItem( sal_uInt16 nItemId, const Image& rImage,
681                           const XubString& rText,
682                           ToolBoxItemBits nBits, sal_uInt16 nPos )
683 {
684     DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
685     DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
686                 "ToolBox::InsertItem(): ItemId already exists" );
687 
688     // Item anlegen und in die Liste einfuegen
689     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, rImage, ImplConvertMenuString( rText ), nBits ) );
690     mpData->ImplClearLayoutData();
691 
692     ImplInvalidate( sal_True );
693 
694     // Notify
695     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
696     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
697 }
698 
699 // -----------------------------------------------------------------------
700 
701 void ToolBox::InsertItem( sal_uInt16 nItemId, const XubString& rText,
702                           ToolBoxItemBits nBits, sal_uInt16 nPos )
703 {
704     DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
705     DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
706                 "ToolBox::InsertItem(): ItemId already exists" );
707 
708     // Item anlegen und in die Liste einfuegen
709     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, ImplConvertMenuString( rText ), nBits ) );
710     mpData->ImplClearLayoutData();
711 
712     ImplInvalidate( sal_True );
713 
714     // Notify
715     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
716     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
717 }
718 
719 // -----------------------------------------------------------------------
720 
721 void ToolBox::InsertWindow( sal_uInt16 nItemId, Window* pWindow,
722                             ToolBoxItemBits nBits, sal_uInt16 nPos )
723 {
724     DBG_ASSERT( nItemId, "ToolBox::InsertWindow(): ItemId == 0" );
725     DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
726                 "ToolBox::InsertWindow(): ItemId already exists" );
727 
728     // Item anlegen und in die Liste einfuegen
729     ImplToolItem aItem;
730     aItem.mnId       = nItemId;
731     aItem.meType     = TOOLBOXITEM_BUTTON;
732     aItem.mnBits     = nBits;
733     aItem.mpWindow   = pWindow;
734     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
735     mpData->ImplClearLayoutData();
736 
737     if ( pWindow )
738         pWindow->Hide();
739 
740     ImplInvalidate( sal_True );
741 
742     // Notify
743     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
744     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
745 }
746 
747 // -----------------------------------------------------------------------
748 
749 void ToolBox::InsertSpace( sal_uInt16 nPos )
750 {
751     // Item anlegen und in die Liste einfuegen
752     ImplToolItem aItem;
753     aItem.meType     = TOOLBOXITEM_SPACE;
754     aItem.mbEnabled  = sal_False;
755     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
756     mpData->ImplClearLayoutData();
757 
758     ImplInvalidate( sal_False );
759 
760     // Notify
761     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
762     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
763 }
764 
765 // -----------------------------------------------------------------------
766 
767 void ToolBox::InsertSeparator( sal_uInt16 nPos, sal_uInt16 nPixSize )
768 {
769     // Item anlegen und in die Liste einfuegen
770     ImplToolItem aItem;
771     aItem.meType     = TOOLBOXITEM_SEPARATOR;
772     aItem.mbEnabled  = sal_False;
773     if ( nPixSize )
774         aItem.mnSepSize = nPixSize;
775     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
776     mpData->ImplClearLayoutData();
777 
778     ImplInvalidate( sal_False );
779 
780     // Notify
781     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
782     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
783 }
784 
785 // -----------------------------------------------------------------------
786 
787 void ToolBox::InsertBreak( sal_uInt16 nPos )
788 {
789     // Item anlegen und in die Liste einfuegen
790     ImplToolItem aItem;
791     aItem.meType     = TOOLBOXITEM_BREAK;
792     aItem.mbEnabled  = sal_False;
793     mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
794     mpData->ImplClearLayoutData();
795 
796     ImplInvalidate( sal_False );
797 
798     // Notify
799     sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
800     ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
801 }
802 
803 // -----------------------------------------------------------------------
804 
805 void ToolBox::RemoveItem( sal_uInt16 nPos )
806 {
807     if( nPos < mpData->m_aItems.size() )
808     {
809         sal_Bool bMustCalc;
810         if ( mpData->m_aItems[nPos].meType == TOOLBOXITEM_BUTTON )
811             bMustCalc = sal_True;
812         else
813             bMustCalc = sal_False;
814 
815         if ( mpData->m_aItems[nPos].mpWindow )
816             mpData->m_aItems[nPos].mpWindow->Hide();
817 
818         // PaintRect um das removete Item erweitern
819         maPaintRect.Union( mpData->m_aItems[nPos].maRect );
820 
821         // Absichern gegen das Loeschen im Select-Handler
822         if ( mpData->m_aItems[nPos].mnId == mnCurItemId )
823             mnCurItemId = 0;
824         if ( mpData->m_aItems[nPos].mnId == mnHighItemId )
825             mnHighItemId = 0;
826 
827         ImplInvalidate( bMustCalc );
828 
829         mpData->m_aItems.erase( mpData->m_aItems.begin()+nPos );
830         mpData->ImplClearLayoutData();
831 
832         // Notify
833         ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMREMOVED, reinterpret_cast< void* >( nPos ) );
834     }
835 }
836 
837 // -----------------------------------------------------------------------
838 
839 void ToolBox::MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos )
840 {
841     sal_uInt16 nPos = GetItemPos( nItemId );
842 
843     if ( nPos == nNewPos )
844         return;
845 
846     if ( nPos < nNewPos )
847         nNewPos--;
848 
849     // Existiert Item
850     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
851     {
852         // ToolBox-Item in der Liste verschieben
853         ImplToolItem aItem = mpData->m_aItems[nPos];
854         mpData->m_aItems.erase( mpData->m_aItems.begin()+nPos );
855         mpData->m_aItems.insert( (nNewPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nNewPos : mpData->m_aItems.end(), aItem );
856         mpData->ImplClearLayoutData();
857 
858         // ToolBox neu ausgeben
859         ImplInvalidate( sal_False );
860 
861         // Notify
862         if( nPos < nNewPos )    // only send one event, all indices above this item are invalid anyway
863             ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMREMOVED, reinterpret_cast< void* >( nPos ) );
864         else
865         {
866             sal_uInt16 nNewPos2 = sal::static_int_cast<sal_uInt16>(( nNewPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nNewPos);
867             ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos2 ) );
868         }
869     }
870 }
871 
872 // -----------------------------------------------------------------------
873 
874 void ToolBox::CopyItem( const ToolBox& rToolBox, sal_uInt16 nItemId,
875                         sal_uInt16 nNewPos )
876 {
877     DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
878                 "ToolBox::CopyItem(): ItemId already exists" );
879 
880     sal_uInt16 nPos = rToolBox.GetItemPos( nItemId );
881 
882     // Existiert Item
883     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
884     {
885         // ToolBox-Item in der Liste verschieben
886         ImplToolItem aNewItem = rToolBox.mpData->m_aItems[nPos];
887         // Bestimme Daten zuruecksetzen
888         aNewItem.mpWindow      = NULL;
889         aNewItem.mbShowWindow = sal_False;
890 
891         mpData->m_aItems.insert( (nNewPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nNewPos : mpData->m_aItems.end(), aNewItem );
892         mpData->ImplClearLayoutData();
893         // ToolBox neu ausgeben
894         ImplInvalidate( sal_False );
895 
896         // Notify
897         sal_uInt16 nNewPos2 = sal::static_int_cast<sal_uInt16>(( nNewPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nNewPos);
898         ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos2 ) );
899     }
900 }
901 
902 // -----------------------------------------------------------------------
903 
904 void ToolBox::CopyItems( const ToolBox& rToolBox )
905 {
906     mpData->ImplClearLayoutData();
907     mpData->m_aItems = rToolBox.mpData->m_aItems;
908     // Absichern gegen das Loeschen im Select-Handler
909     mnCurItemId = 0;
910     mnHighItemId = 0;
911 
912     for( std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
913          it != mpData->m_aItems.end(); ++it )
914     {
915         it->mpWindow        = NULL;
916         it->mbShowWindow    = sal_False;
917     }
918 
919     ImplInvalidate( sal_True, sal_True );
920 
921     // Notify
922     ImplCallEventListeners( VCLEVENT_TOOLBOX_ALLITEMSCHANGED );
923 }
924 
925 // -----------------------------------------------------------------------
926 
927 void ToolBox::Clear()
928 {
929     mpData->m_aItems.clear();
930     mpData->ImplClearLayoutData();
931 
932     // Absichern gegen das Loeschen im Select-Handler
933     mnCurItemId = 0;
934     mnHighItemId = 0;
935 
936     ImplInvalidate( sal_True, sal_True );
937 
938     // Notify
939     ImplCallEventListeners( VCLEVENT_TOOLBOX_ALLITEMSCHANGED );
940 }
941 
942 // -----------------------------------------------------------------------
943 
944 void ToolBox::SetButtonType( ButtonType eNewType )
945 {
946     if ( meButtonType != eNewType )
947     {
948         meButtonType = eNewType;
949 
950         // Hier besser alles neu ausgeben, da es ansonsten zu Problemen
951         // mit den per CopyBits kopierten Bereichen geben kann
952         ImplInvalidate( sal_True );
953     }
954 }
955 
956 // -----------------------------------------------------------------------
957 
958 void ToolBox::SetToolboxButtonSize( ToolBoxButtonSize eSize )
959 {
960     if( mpData->meButtonSize != eSize )
961     {
962         mpData->meButtonSize = eSize;
963         mbCalc = sal_True;
964         mbFormat = sal_True;
965     }
966 }
967 
968 ToolBoxButtonSize ToolBox::GetToolboxButtonSize() const
969 {
970     return mpData->meButtonSize;
971 }
972 
973 // -----------------------------------------------------------------------
974 
975 const Size& ToolBox::GetDefaultImageSize() const
976 {
977     static Size aSmallButtonSize( TB_SMALLIMAGESIZE, TB_SMALLIMAGESIZE );
978 
979     static sal_uLong s_nSymbolsStyle = STYLE_SYMBOLS_DEFAULT;
980     static Size aLargeButtonSize( TB_LARGEIMAGESIZE, TB_LARGEIMAGESIZE );
981 
982     sal_uLong nSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyle();
983     if ( s_nSymbolsStyle != nSymbolsStyle )
984     {
985         s_nSymbolsStyle = nSymbolsStyle;
986         switch ( nSymbolsStyle )
987         {
988             case STYLE_SYMBOLS_INDUSTRIAL:
989                 aLargeButtonSize = Size( TB_LARGEIMAGESIZE_INDUSTRIAL, TB_LARGEIMAGESIZE_INDUSTRIAL );
990                 break;
991             case STYLE_SYMBOLS_CRYSTAL:
992                 aLargeButtonSize = Size( TB_LARGEIMAGESIZE_CRYSTAL, TB_LARGEIMAGESIZE_CRYSTAL );
993                 break;
994             case STYLE_SYMBOLS_OXYGEN:
995                 aLargeButtonSize = Size( TB_LARGEIMAGESIZE_OXYGEN, TB_LARGEIMAGESIZE_OXYGEN );
996                 break;
997             default:
998                 aLargeButtonSize = Size( TB_LARGEIMAGESIZE, TB_LARGEIMAGESIZE );
999         }
1000     }
1001 
1002     return GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE ? aLargeButtonSize : aSmallButtonSize;
1003 }
1004 
1005 // -----------------------------------------------------------------------
1006 
1007 void ToolBox::SetAlign( WindowAlign eNewAlign )
1008 {
1009     if ( meAlign != eNewAlign )
1010     {
1011         meAlign = eNewAlign;
1012 
1013         if ( !ImplIsFloatingMode() )
1014         {
1015             // Setzen, ob Items horizontal oder vertikal angeordnet werden sollen
1016             if ( (eNewAlign == WINDOWALIGN_LEFT) || (eNewAlign == WINDOWALIGN_RIGHT) )
1017                 mbHorz = sal_False;
1018             else
1019                 mbHorz = sal_True;
1020 
1021             // Hier alles neu ausgeben, da sich Border auch aendert
1022             mbCalc = sal_True;
1023             mbFormat = sal_True;
1024             if ( IsReallyVisible() && IsUpdateMode() )
1025                 Invalidate();
1026         }
1027     }
1028 }
1029 
1030 // -----------------------------------------------------------------------
1031 
1032 void ToolBox::SetLineCount( sal_uInt16 nNewLines )
1033 {
1034     if ( !nNewLines )
1035         nNewLines = 1;
1036 
1037     if ( mnLines != nNewLines )
1038     {
1039         mnLines = nNewLines;
1040 
1041         // Hier besser alles neu ausgeben, da es ansonsten zu Problemen
1042         // mit den per CopyBits kopierten Bereichen geben kann
1043         ImplInvalidate( sal_False );
1044     }
1045 }
1046 
1047 // -----------------------------------------------------------------------
1048 
1049 void ToolBox::SetPageScroll( sal_Bool b )
1050 {
1051     mpData->mbPageScroll = b;
1052 }
1053 
1054 sal_Bool ToolBox::GetPageScroll()
1055 {
1056     return mpData->mbPageScroll;
1057 }
1058 
1059 // -----------------------------------------------------------------------
1060 
1061 void ToolBox::SetNextToolBox( const XubString& rStr )
1062 {
1063     sal_Bool bCalcNew = (!maNextToolBoxStr.Len() != !rStr.Len());
1064     maNextToolBoxStr = rStr;
1065     if ( bCalcNew )
1066         ImplInvalidate( sal_True, sal_False );
1067 }
1068 
1069 // -----------------------------------------------------------------------
1070 
1071 sal_uInt16 ToolBox::GetItemCount() const
1072 {
1073     return (sal_uInt16)mpData->m_aItems.size();
1074 }
1075 
1076 // -----------------------------------------------------------------------
1077 
1078 ToolBoxItemType ToolBox::GetItemType( sal_uInt16 nPos ) const
1079 {
1080     return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].meType : TOOLBOXITEM_DONTKNOW;
1081 }
1082 
1083 // -----------------------------------------------------------------------
1084 
1085 sal_uInt16 ToolBox::GetItemPos( sal_uInt16 nItemId ) const
1086 {
1087     int nCount = mpData->m_aItems.size();
1088     for( int nPos = 0; nPos < nCount; nPos++ )
1089         if( mpData->m_aItems[nPos].mnId == nItemId )
1090             return (sal_uInt16)nPos;
1091 
1092     return TOOLBOX_ITEM_NOTFOUND;
1093 }
1094 
1095 // -----------------------------------------------------------------------
1096 
1097 sal_uInt16 ToolBox::GetItemPos( const Point& rPos ) const
1098 {
1099     // search the item position on the given point
1100     sal_uInt16 nRet = TOOLBOX_ITEM_NOTFOUND;
1101     sal_uInt16 nPos = 0;
1102     std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
1103     while( it != mpData->m_aItems.end() )
1104     {
1105         if ( it->maRect.IsInside( rPos ) )
1106         {
1107             // item found -> save position and break
1108             nRet = nPos;
1109             break;
1110         }
1111 
1112         ++it;
1113         ++nPos;
1114     }
1115 
1116     return nRet;
1117 }
1118 
1119 // -----------------------------------------------------------------------
1120 
1121 sal_uInt16 ToolBox::GetItemId( sal_uInt16 nPos ) const
1122 {
1123     return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].mnId : 0;
1124 }
1125 
1126 // -----------------------------------------------------------------------
1127 
1128 sal_uInt16 ToolBox::GetItemId( const Point& rPos ) const
1129 {
1130     // Item suchen, das geklickt wurde
1131     std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
1132     while( it != mpData->m_aItems.end() )
1133     {
1134         // Ist es dieses Item
1135         if ( it->maRect.IsInside( rPos ) )
1136         {
1137             if ( it->meType == TOOLBOXITEM_BUTTON )
1138                 return it->mnId;
1139             else
1140                 return 0;
1141         }
1142 
1143         ++it;
1144     }
1145 
1146     return 0;
1147 }
1148 
1149 // -----------------------------------------------------------------------
1150 
1151 Point ToolBox::ImplGetPopupPosition( const Rectangle& rRect, const Size& rSize ) const
1152 {
1153     Point aPos;
1154     if( !rRect.IsEmpty() )
1155     {
1156         Rectangle aScreen = GetDesktopRectPixel();
1157 
1158         // the popup should be positioned so that it will not cover
1159         // the item rect and that it fits the desktop
1160         // the preferred direction is always towards the center of
1161         // the application window
1162 
1163         Point devPos;           // the position in device coordinates for screen comparison
1164         switch( meAlign )
1165         {
1166             case WINDOWALIGN_TOP:
1167                 aPos = rRect.BottomLeft();
1168                 aPos.Y()++;
1169                 devPos = OutputToAbsoluteScreenPixel( aPos );
1170                 if( devPos.Y() + rSize.Height() >= aScreen.Bottom() )
1171                     aPos.Y() = rRect.Top() - rSize.Height();
1172                 break;
1173             case WINDOWALIGN_BOTTOM:
1174                 aPos = rRect.TopLeft();
1175                 aPos.Y()--;
1176                 devPos = OutputToAbsoluteScreenPixel( aPos );
1177                 if( devPos.Y() - rSize.Height() > aScreen.Top() )
1178                     aPos.Y() -= rSize.Height();
1179                 else
1180                     aPos.Y() = rRect.Bottom();
1181                 break;
1182             case WINDOWALIGN_LEFT:
1183                 aPos = rRect.TopRight();
1184                 aPos.X()++;
1185                 devPos = OutputToAbsoluteScreenPixel( aPos );
1186                 if( devPos.X() + rSize.Width() >= aScreen.Right() )
1187                     aPos.X() = rRect.Left() - rSize.Width();
1188                 break;
1189             case WINDOWALIGN_RIGHT:
1190                 aPos = rRect.TopLeft();
1191                 aPos.X()--;
1192                 devPos = OutputToAbsoluteScreenPixel( aPos );
1193                 if( devPos.X() - rSize.Width() > aScreen.Left() )
1194                     aPos.X() -= rSize.Width();
1195                 else
1196                     aPos.X() = rRect.Right();
1197                 break;
1198             default:
1199                 break;
1200         };
1201     }
1202     return aPos;
1203 }
1204 
1205 
1206 Point ToolBox::GetItemPopupPosition( sal_uInt16 nItemId, const Size& rSize ) const
1207 {
1208     return ImplGetPopupPosition( GetItemRect( nItemId ), rSize );
1209 }
1210 
1211 // -----------------------------------------------------------------------
1212 
1213 Rectangle ToolBox::GetItemRect( sal_uInt16 nItemId ) const
1214 {
1215     if ( mbCalc || mbFormat )
1216         ((ToolBox*)this)->ImplFormat();
1217 
1218     sal_uInt16 nPos = GetItemPos( nItemId );
1219     return GetItemPosRect( nPos );
1220 }
1221 
1222 // -----------------------------------------------------------------------
1223 
1224 Rectangle ToolBox::GetItemPosRect( sal_uInt16 nPos ) const
1225 {
1226     if ( mbCalc || mbFormat )
1227         ((ToolBox*)this)->ImplFormat();
1228 
1229     if ( nPos < mpData->m_aItems.size() )
1230         return mpData->m_aItems[nPos].maRect;
1231     else
1232         return Rectangle();
1233 }
1234 
1235 // -----------------------------------------------------------------------
1236 Rectangle ToolBox::GetItemDropDownRect( sal_uInt16 nItemId ) const
1237 {
1238     if ( mbCalc || mbFormat )
1239         ((ToolBox*)this)->ImplFormat();
1240 
1241     sal_uInt16 nPos = GetItemPos( nItemId );
1242     return GetItemPosDropDownRect( nPos );
1243 }
1244 
1245 // -----------------------------------------------------------------------
1246 
1247 Rectangle ToolBox::GetItemPosDropDownRect( sal_uInt16 nPos ) const
1248 {
1249     if ( mbCalc || mbFormat )
1250         ((ToolBox*)this)->ImplFormat();
1251 
1252     if ( nPos < mpData->m_aItems.size() )
1253         return mpData->m_aItems[nPos].GetDropDownRect( mbHorz );
1254     else
1255         return Rectangle();
1256 }
1257 
1258 // -----------------------------------------------------------------------
1259 
1260 Rectangle ToolBox::GetMenubuttonRect() const
1261 {
1262     return mpData->maMenubuttonItem.maRect;
1263 }
1264 
1265 sal_Bool ToolBox::ImplHasExternalMenubutton()
1266 {
1267     // check if the borderwindow (i.e. the decoration) provides the menu button
1268     sal_Bool bRet = sal_False;
1269     if( ImplIsFloatingMode() )
1270     {
1271         // custom menu is placed in the decoration
1272         ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( WINDOW_BORDER ) );
1273         if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
1274             bRet = sal_True;
1275     }
1276     return bRet;
1277 }
1278 // -----------------------------------------------------------------------
1279 
1280 void ToolBox::SetItemBits( sal_uInt16 nItemId, ToolBoxItemBits nBits )
1281 {
1282     sal_uInt16 nPos = GetItemPos( nItemId );
1283 
1284     if ( nPos < mpData->m_aItems.size() )
1285     {
1286         ToolBoxItemBits nOldBits = mpData->m_aItems[nPos].mnBits;
1287         mpData->m_aItems[nPos].mnBits = nBits;
1288         nBits &= TIB_LEFT | TIB_AUTOSIZE | TIB_DROPDOWN;
1289         nOldBits &= TIB_LEFT | TIB_AUTOSIZE | TIB_DROPDOWN;
1290         // trigger reformat when the item width has changed (dropdown arrow)
1291         sal_Bool bFormat = (nBits & TIB_DROPDOWN) != (nOldBits & TIB_DROPDOWN);
1292         if ( nBits != nOldBits )
1293             ImplInvalidate( sal_True, bFormat );
1294     }
1295 }
1296 
1297 // -----------------------------------------------------------------------
1298 
1299 ToolBoxItemBits ToolBox::GetItemBits( sal_uInt16 nItemId ) const
1300 {
1301     ImplToolItem* pItem = ImplGetItem( nItemId );
1302 
1303     if ( pItem )
1304         return pItem->mnBits;
1305     else
1306         return 0;
1307 }
1308 
1309 // -----------------------------------------------------------------------
1310 
1311 void ToolBox::SetItemData( sal_uInt16 nItemId, void* pNewData )
1312 {
1313     sal_uInt16 nPos = GetItemPos( nItemId );
1314 
1315     if ( nPos < mpData->m_aItems.size() )
1316     {
1317         mpData->m_aItems[nPos].mpUserData = pNewData;
1318         ImplUpdateItem( nPos );
1319     }
1320 }
1321 
1322 // -----------------------------------------------------------------------
1323 
1324 void* ToolBox::GetItemData( sal_uInt16 nItemId ) const
1325 {
1326     ImplToolItem* pItem = ImplGetItem( nItemId );
1327 
1328     if ( pItem )
1329         return pItem->mpUserData;
1330     else
1331         return NULL;
1332 }
1333 
1334 // -----------------------------------------------------------------------
1335 
1336 void ToolBox::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
1337 {
1338     sal_uInt16 nPos = GetItemPos( nItemId );
1339 
1340     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1341     {
1342         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1343         // Nur wenn alles berechnet ist, mehr Aufwand treiben
1344         if ( !mbCalc )
1345         {
1346             Size aOldSize = pItem->maImage.GetSizePixel();
1347             pItem->maImage = rImage;
1348             if ( aOldSize != pItem->maImage.GetSizePixel() )
1349                 ImplInvalidate( sal_True );
1350             else
1351                 ImplUpdateItem( nPos );
1352         }
1353         else
1354             pItem->maImage = rImage;
1355     }
1356 }
1357 
1358 // -----------------------------------------------------------------------
1359 
1360 void ToolBox::SetImageList( const ImageList& rImageList )
1361 {
1362     maImageList = rImageList;
1363 
1364     sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
1365     for( sal_uInt16 i = 0; i < nCount; i++ )
1366     {
1367         Image aImage;
1368         if ( mpData->m_aItems[i].mnId )
1369             aImage = maImageList.GetImage( mpData->m_aItems[i].mnId );
1370         if( !!aImage )
1371             SetItemImage( mpData->m_aItems[i].mnId, aImage );
1372     }
1373 }
1374 
1375 // -----------------------------------------------------------------------
1376 
1377 static Image ImplRotImage( const Image& rImage, long nAngle10 )
1378 {
1379     Image       aRet;
1380     BitmapEx    aRotBitmapEx( rImage.GetBitmapEx() );
1381 
1382     aRotBitmapEx.Rotate( nAngle10, Color( COL_WHITE ) );
1383 
1384     return Image( aRotBitmapEx );
1385 }
1386 
1387 void ToolBox::SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 )
1388 {
1389     sal_uInt16 nPos = GetItemPos( nItemId );
1390 
1391     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1392     {
1393         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1394         Size aOldSize = pItem->maImage.GetSizePixel();
1395 
1396         long nDeltaAngle = (nAngle10 - pItem->mnImageAngle) % 3600;
1397         while( nDeltaAngle < 0 )
1398             nDeltaAngle += 3600;
1399 
1400         pItem->mnImageAngle = nAngle10;
1401         if( nDeltaAngle && !!pItem->maImage )
1402         {
1403             pItem->maImage = ImplRotImage( pItem->maImage, nDeltaAngle );
1404             if( !!pItem->maHighImage )
1405                 pItem->maHighImage = ImplRotImage( pItem->maHighImage, nDeltaAngle );
1406         }
1407 
1408         if ( !mbCalc )
1409         {
1410             if ( aOldSize != pItem->maImage.GetSizePixel() )
1411                 ImplInvalidate( sal_True );
1412             else
1413                 ImplUpdateItem( nPos );
1414         }
1415     }
1416 }
1417 
1418 // -----------------------------------------------------------------------
1419 
1420 static Image ImplMirrorImage( const Image& rImage )
1421 {
1422     Image       aRet;
1423     BitmapEx    aMirrBitmapEx( rImage.GetBitmapEx() );
1424 
1425     aMirrBitmapEx.Mirror( BMP_MIRROR_HORZ );
1426 
1427     return Image( aMirrBitmapEx );
1428 }
1429 
1430 void ToolBox::SetItemImageMirrorMode( sal_uInt16 nItemId, sal_Bool bMirror )
1431 {
1432     sal_uInt16 nPos = GetItemPos( nItemId );
1433 
1434     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1435     {
1436         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1437 
1438         if( ( pItem->mbMirrorMode && ! bMirror ) ||
1439             ( ! pItem->mbMirrorMode && bMirror )
1440             )
1441         {
1442             pItem->mbMirrorMode = bMirror ? true : false;
1443             if( !!pItem->maImage )
1444             {
1445                 pItem->maImage = ImplMirrorImage( pItem->maImage );
1446                 if( !!pItem->maHighImage )
1447                     pItem->maHighImage = ImplMirrorImage( pItem->maHighImage );
1448             }
1449 
1450             if ( !mbCalc )
1451                 ImplUpdateItem( nPos );
1452         }
1453     }
1454 }
1455 
1456 // -----------------------------------------------------------------------
1457 
1458 Image ToolBox::GetItemImage( sal_uInt16 nItemId ) const
1459 {
1460     ImplToolItem* pItem = ImplGetItem( nItemId );
1461 
1462     if ( pItem )
1463         return pItem->maImage;
1464     else
1465         return Image();
1466 }
1467 
1468 // -----------------------------------------------------------------------
1469 
1470 long ToolBox::GetItemImageAngle( sal_uInt16 nItemId ) const
1471 {
1472     ImplToolItem* pItem = ImplGetItem( nItemId );
1473 
1474     if ( pItem )
1475         return pItem->mnImageAngle;
1476     else
1477         return 0;
1478 }
1479 
1480 // -----------------------------------------------------------------------
1481 
1482 sal_Bool ToolBox::GetItemImageMirrorMode( sal_uInt16 nItemId ) const
1483 {
1484     ImplToolItem* pItem = ImplGetItem( nItemId );
1485 
1486     if ( pItem )
1487         return pItem->mbMirrorMode;
1488     else
1489         return sal_False;
1490 }
1491 
1492 // -----------------------------------------------------------------------
1493 
1494 void ToolBox::SetItemHighImage( sal_uInt16 nItemId, const Image& rImage )
1495 {
1496     ImplToolItem* pItem = ImplGetItem( nItemId );
1497     if ( pItem )
1498     {
1499         DBG_ASSERT( (pItem->maImage.GetSizePixel() == rImage.GetSizePixel()) ||
1500                     ((!rImage) == sal_True), "ToolBox::SetItemHighImage() - ImageSize != HighImageSize" );
1501         pItem->maHighImage = rImage;
1502     }
1503 }
1504 
1505 // -----------------------------------------------------------------------
1506 
1507 Image ToolBox::GetItemHighImage( sal_uInt16 nItemId ) const
1508 {
1509     ImplToolItem* pItem = ImplGetItem( nItemId );
1510 
1511     if ( pItem )
1512         return pItem->maHighImage;
1513     else
1514         return Image();
1515 }
1516 
1517 // -----------------------------------------------------------------------
1518 
1519 void ToolBox::SetItemText( sal_uInt16 nItemId, const XubString& rText )
1520 {
1521     sal_uInt16 nPos = GetItemPos( nItemId );
1522 
1523     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1524     {
1525         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1526         // Nur wenn alles berechnet ist, mehr Aufwand treiben
1527         if ( !mbCalc &&
1528              ((meButtonType != BUTTON_SYMBOL) || !pItem->maImage) )
1529         {
1530             long nOldWidth = GetCtrlTextWidth( pItem->maText );
1531             pItem->maText = ImplConvertMenuString( rText );
1532             mpData->ImplClearLayoutData();
1533             if ( nOldWidth != GetCtrlTextWidth( pItem->maText ) )
1534                 ImplInvalidate( sal_True );
1535             else
1536                 ImplUpdateItem( nPos );
1537         }
1538         else
1539             pItem->maText = ImplConvertMenuString( rText );
1540 
1541         // Notify button changed event to prepare accessibility bridge
1542         ImplCallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
1543 
1544         // Notify
1545         ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMTEXTCHANGED, reinterpret_cast< void* >( nPos ) );
1546     }
1547 }
1548 
1549 // -----------------------------------------------------------------------
1550 
1551 const XubString& ToolBox::GetItemText( sal_uInt16 nItemId ) const
1552 {
1553     ImplToolItem* pItem = ImplGetItem( nItemId );
1554 
1555     if ( pItem )
1556         return pItem->maText;
1557     else
1558         return ImplGetSVEmptyStr();
1559 }
1560 
1561 // -----------------------------------------------------------------------
1562 
1563 void ToolBox::SetItemWindow( sal_uInt16 nItemId, Window* pNewWindow )
1564 {
1565     sal_uInt16 nPos = GetItemPos( nItemId );
1566 
1567     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1568     {
1569         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1570         pItem->mpWindow = pNewWindow;
1571         if ( pNewWindow )
1572             pNewWindow->Hide();
1573         ImplInvalidate( sal_True );
1574         ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED, reinterpret_cast< void* >( nPos ) );
1575     }
1576 }
1577 
1578 // -----------------------------------------------------------------------
1579 
1580 Window* ToolBox::GetItemWindow( sal_uInt16 nItemId ) const
1581 {
1582     ImplToolItem* pItem = ImplGetItem( nItemId );
1583 
1584     if ( pItem )
1585         return pItem->mpWindow;
1586     else
1587         return NULL;
1588 }
1589 
1590 // -----------------------------------------------------------------------
1591 
1592 void ToolBox::StartSelection()
1593 {
1594     if ( mbDrag )
1595         EndSelection();
1596 
1597     if ( !mbSelection )
1598     {
1599         mbSelection  = sal_True;
1600         mnCurPos     = TOOLBOX_ITEM_NOTFOUND;
1601         mnCurItemId  = 0;
1602         Activate();
1603     }
1604 }
1605 
1606 // -----------------------------------------------------------------------
1607 
1608 void ToolBox::EndSelection()
1609 {
1610     mbCommandDrag = sal_False;
1611 
1612     if ( mbDrag || mbSelection )
1613     {
1614         // Daten zuruecksetzen
1615         mbDrag = sal_False;
1616         mbSelection = sal_False;
1617         if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
1618             ImplDrawItem( mnCurPos );
1619         EndTracking();
1620         ReleaseMouse();
1621         Deactivate();
1622     }
1623 
1624     mnCurPos        = TOOLBOX_ITEM_NOTFOUND;
1625     mnCurItemId     = 0;
1626     mnDownItemId    = 0;
1627     mnMouseClicks   = 0;
1628     mnMouseModifier = 0;
1629 }
1630 
1631 // -----------------------------------------------------------------------
1632 
1633 void ToolBox::SetItemDown( sal_uInt16 nItemId, sal_Bool bDown, sal_Bool bRelease )
1634 {
1635     sal_uInt16 nPos = GetItemPos( nItemId );
1636 
1637     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1638     {
1639         if ( bDown )
1640         {
1641             if ( nPos != mnCurPos )
1642             {
1643                 mnCurPos = nPos;
1644                 ImplDrawItem( mnCurPos, sal_True );
1645                 Flush();
1646             }
1647         }
1648         else
1649         {
1650             if ( nPos == mnCurPos )
1651             {
1652                 ImplDrawItem( mnCurPos, sal_False );
1653                 Flush();
1654                 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1655             }
1656         }
1657 
1658         if ( bRelease )
1659         {
1660             if ( mbDrag || mbSelection )
1661             {
1662                 mbDrag = sal_False;
1663                 mbSelection = sal_False;
1664                 EndTracking();
1665                 ReleaseMouse();
1666                 Deactivate();
1667             }
1668 
1669             mnCurItemId     = 0;
1670             mnDownItemId    = 0;
1671             mnMouseClicks   = 0;
1672             mnMouseModifier = 0;
1673         }
1674     }
1675 }
1676 
1677 // -----------------------------------------------------------------------
1678 
1679 sal_Bool ToolBox::IsItemDown( sal_uInt16 nItemId ) const
1680 {
1681     sal_uInt16 nPos = GetItemPos( nItemId );
1682 
1683     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1684         return (nPos == mnCurPos);
1685     else
1686         return sal_False;
1687 }
1688 
1689 // -----------------------------------------------------------------------
1690 
1691 void ToolBox::SetItemState( sal_uInt16 nItemId, TriState eState )
1692 {
1693     sal_uInt16 nPos = GetItemPos( nItemId );
1694 
1695     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1696     {
1697         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1698 
1699         // Hat sich der Status geaendert
1700         if ( pItem->meState != eState )
1701         {
1702             // Wenn RadioCheck, dann vorherigen unchecken
1703             if ( (eState == STATE_CHECK) && (pItem->mnBits & TIB_AUTOCHECK) &&
1704                  (pItem->mnBits & TIB_RADIOCHECK) )
1705             {
1706                 ImplToolItem*    pGroupItem;
1707                 sal_uInt16          nGroupPos;
1708                 sal_uInt16          nItemCount = GetItemCount();
1709 
1710                 nGroupPos = nPos;
1711                 while ( nGroupPos )
1712                 {
1713                     pGroupItem = &mpData->m_aItems[nGroupPos-1];
1714                     if ( pGroupItem->mnBits & TIB_RADIOCHECK )
1715                     {
1716                         if ( pGroupItem->meState != STATE_NOCHECK )
1717                             SetItemState( pGroupItem->mnId, STATE_NOCHECK );
1718                     }
1719                     else
1720                         break;
1721                     nGroupPos--;
1722                 }
1723 
1724                 nGroupPos = nPos+1;
1725                 while ( nGroupPos < nItemCount )
1726                 {
1727                     pGroupItem = &mpData->m_aItems[nGroupPos];
1728                     if ( pGroupItem->mnBits & TIB_RADIOCHECK )
1729                     {
1730                         if ( pGroupItem->meState != STATE_NOCHECK )
1731                             SetItemState( pGroupItem->mnId, STATE_NOCHECK );
1732                     }
1733                     else
1734                         break;
1735                     nGroupPos++;
1736                 }
1737             }
1738 
1739             pItem->meState = eState;
1740             ImplUpdateItem( nPos );
1741 
1742             // Notify button changed event to prepare accessibility bridge
1743             ImplCallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
1744 
1745             // Notify
1746             ImplCallEventListeners( VCLEVENT_TOOLBOX_CLICK, reinterpret_cast< void* >( nPos ) );
1747         }
1748     }
1749 }
1750 
1751 // -----------------------------------------------------------------------
1752 
1753 TriState ToolBox::GetItemState( sal_uInt16 nItemId ) const
1754 {
1755     ImplToolItem* pItem = ImplGetItem( nItemId );
1756 
1757     if ( pItem )
1758         return pItem->meState;
1759     else
1760         return STATE_NOCHECK;
1761 }
1762 
1763 // -----------------------------------------------------------------------
1764 
1765 void ToolBox::EnableItem( sal_uInt16 nItemId, sal_Bool bEnable )
1766 {
1767     sal_uInt16 nPos = GetItemPos( nItemId );
1768 
1769     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1770     {
1771         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1772         if ( bEnable )
1773             bEnable = sal_True;
1774         if ( pItem->mbEnabled != bEnable )
1775         {
1776             pItem->mbEnabled = bEnable;
1777 
1778             // Gegebenenfalls das Fenster mit updaten
1779             if ( pItem->mpWindow )
1780                 pItem->mpWindow->Enable( pItem->mbEnabled );
1781 
1782             // Item updaten
1783             ImplUpdateItem( nPos );
1784 
1785             ImplUpdateInputEnable();
1786 
1787             // Notify button changed event to prepare accessibility bridge
1788             ImplCallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
1789 
1790             ImplCallEventListeners( bEnable ? VCLEVENT_TOOLBOX_ITEMENABLED : VCLEVENT_TOOLBOX_ITEMDISABLED, reinterpret_cast< void* >( nPos ) );
1791         }
1792     }
1793 }
1794 
1795 // -----------------------------------------------------------------------
1796 
1797 sal_Bool ToolBox::IsItemEnabled( sal_uInt16 nItemId ) const
1798 {
1799     ImplToolItem* pItem = ImplGetItem( nItemId );
1800 
1801     if ( pItem )
1802         return pItem->mbEnabled;
1803     else
1804         return sal_False;
1805 }
1806 
1807 // -----------------------------------------------------------------------
1808 
1809 void ToolBox::ShowItem( sal_uInt16 nItemId, sal_Bool bVisible )
1810 {
1811     sal_uInt16 nPos = GetItemPos( nItemId );
1812     mpData->ImplClearLayoutData();
1813 
1814     if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1815     {
1816         ImplToolItem* pItem = &mpData->m_aItems[nPos];
1817         if ( pItem->mbVisible != bVisible )
1818         {
1819             pItem->mbVisible = bVisible;
1820             ImplInvalidate( sal_False );
1821         }
1822     }
1823 }
1824 
1825 // -----------------------------------------------------------------------
1826 
1827 sal_Bool ToolBox::IsItemVisible( sal_uInt16 nItemId ) const
1828 {
1829     ImplToolItem* pItem = ImplGetItem( nItemId );
1830 
1831     if ( pItem )
1832         return pItem->mbVisible;
1833     else
1834         return sal_False;
1835 }
1836 
1837 // -----------------------------------------------------------------------
1838 
1839 sal_Bool ToolBox::IsItemReallyVisible( sal_uInt16 nItemId ) const
1840 {
1841     // is the item on the visible area of the toolbox?
1842     sal_Bool bRet = sal_False;
1843     Rectangle aRect( mnLeftBorder, mnTopBorder, mnDX-mnRightBorder, mnDY-mnBottomBorder );
1844     ImplToolItem* pItem = ImplGetItem( nItemId );
1845 
1846     if ( pItem && pItem->mbVisible &&
1847          !pItem->maRect.IsEmpty() && aRect.IsOver( pItem->maRect ) )
1848     {
1849         bRet = sal_True;
1850     }
1851 
1852     return bRet;
1853 }
1854 
1855 // -----------------------------------------------------------------------
1856 
1857 void ToolBox::SetItemCommand( sal_uInt16 nItemId, const XubString& rCommand )
1858 {
1859     ImplToolItem* pItem = ImplGetItem( nItemId );
1860 
1861     if ( pItem )
1862         pItem->maCommandStr = rCommand;
1863 }
1864 
1865 // -----------------------------------------------------------------------
1866 
1867 const XubString& ToolBox::GetItemCommand( sal_uInt16 nItemId ) const
1868 {
1869     ImplToolItem* pItem = ImplGetItem( nItemId );
1870 
1871     if ( pItem )
1872         return pItem->maCommandStr;
1873     else
1874         return ImplGetSVEmptyStr();
1875 }
1876 
1877 // -----------------------------------------------------------------------
1878 
1879 void ToolBox::SetQuickHelpText( sal_uInt16 nItemId, const XubString& rText )
1880 {
1881     ImplToolItem* pItem = ImplGetItem( nItemId );
1882 
1883     if ( pItem )
1884         pItem->maQuickHelpText = rText;
1885 }
1886 
1887 // -----------------------------------------------------------------------
1888 
1889 const XubString& ToolBox::GetQuickHelpText( sal_uInt16 nItemId ) const
1890 {
1891     ImplToolItem* pItem = ImplGetItem( nItemId );
1892 
1893     if ( pItem )
1894         return pItem->maQuickHelpText;
1895     else
1896         return ImplGetSVEmptyStr();
1897 }
1898 
1899 // -----------------------------------------------------------------------
1900 
1901 void ToolBox::SetHelpText( sal_uInt16 nItemId, const XubString& rText )
1902 {
1903     ImplToolItem* pItem = ImplGetItem( nItemId );
1904 
1905     if ( pItem )
1906         pItem->maHelpText = rText;
1907 }
1908 
1909 // -----------------------------------------------------------------------
1910 
1911 const XubString& ToolBox::GetHelpText( sal_uInt16 nItemId ) const
1912 {
1913     return ImplGetHelpText( nItemId );
1914 }
1915 
1916 // -----------------------------------------------------------------------
1917 
1918 void ToolBox::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
1919 {
1920     ImplToolItem* pItem = ImplGetItem( nItemId );
1921 
1922     if ( pItem )
1923         pItem->maHelpId = rHelpId;
1924 }
1925 
1926 // -----------------------------------------------------------------------
1927 
1928 rtl::OString ToolBox::GetHelpId( sal_uInt16 nItemId ) const
1929 {
1930     rtl::OString aRet;
1931 
1932     ImplToolItem* pItem = ImplGetItem( nItemId );
1933 
1934     if ( pItem )
1935     {
1936         if ( pItem->maHelpId.getLength() )
1937             aRet = pItem->maHelpId;
1938         else
1939             aRet = ::rtl::OUStringToOString( pItem->maCommandStr, RTL_TEXTENCODING_UTF8 );
1940     }
1941 
1942     return aRet;
1943 }
1944 
1945 // -----------------------------------------------------------------------
1946 
1947 void ToolBox::SetBorder( long nX, long nY )
1948 {
1949     mnBorderX = nX;
1950     mnBorderY = nY;
1951 
1952     ImplInvalidate( sal_True, sal_True );
1953 }
1954 
1955 // -----------------------------------------------------------------------
1956 
1957 void ToolBox::SetOutStyle( sal_uInt16 nNewStyle )
1958 {
1959     // always force flat looking toolbars since NWF
1960     nNewStyle |= TOOLBOX_STYLE_FLAT;
1961 
1962     if ( mnOutStyle != nNewStyle )
1963     {
1964         mnOutStyle = nNewStyle;
1965         ImplDisableFlatButtons();
1966 
1967         // Damit das ButtonDevice neu angelegt wird
1968         if ( !(mnOutStyle & TOOLBOX_STYLE_FLAT) )
1969         {
1970             mnMaxItemWidth  = 1;
1971             mnMaxItemHeight = 1;
1972         }
1973 
1974         ImplInvalidate( sal_True, sal_True );
1975     }
1976 }
1977 
1978 // -----------------------------------------------------------------------
1979 
1980 void ToolBox::RecalcItems()
1981 {
1982     ImplInvalidate( sal_True );
1983 }
1984 
1985 // -----------------------------------------------------------------------
1986 
1987 // disable key input if all items are disabled
1988 
1989 void ToolBox::ImplUpdateInputEnable()
1990 {
1991     for( std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
1992          it != mpData->m_aItems.end(); ++it )
1993     {
1994         if( it->mbEnabled )
1995         {
1996             // at least one useful entry
1997             mpData->mbKeyInputDisabled = sal_False;
1998             return;
1999         }
2000     }
2001     mpData->mbKeyInputDisabled = sal_True;
2002 }
2003 
2004 // -----------------------------------------------------------------------
2005 
2006 void ToolBox::ImplFillLayoutData() const
2007 {
2008     mpData->m_pLayoutData = new ToolBoxLayoutData();
2009 
2010     sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
2011     for( sal_uInt16 i = 0; i < nCount; i++ )
2012     {
2013         ImplToolItem* pItem = &mpData->m_aItems[i];
2014 
2015         // Nur malen, wenn Rechteck im PaintRectangle liegt
2016         if ( !pItem->maRect.IsEmpty() )
2017             const_cast<ToolBox*>(this)->ImplDrawItem( i, sal_False, sal_False, sal_True );
2018     }
2019 }
2020 
2021 // -----------------------------------------------------------------------
2022 
2023 String ToolBox::GetDisplayText() const
2024 {
2025     if( ! mpData->m_pLayoutData )
2026         ImplFillLayoutData();
2027     return mpData->m_pLayoutData ? mpData->m_pLayoutData->m_aDisplayText : String();
2028 }
2029 
2030 // -----------------------------------------------------------------------
2031 
2032 Rectangle ToolBox::GetCharacterBounds( sal_uInt16 nItemID, long nIndex ) const
2033 {
2034     long nItemIndex = -1;
2035     if( ! mpData->m_pLayoutData )
2036         ImplFillLayoutData();
2037     if( mpData->m_pLayoutData )
2038     {
2039         for( sal_uLong i = 0; i < mpData->m_pLayoutData->m_aLineItemIds.size(); i++ )
2040         {
2041             if( mpData->m_pLayoutData->m_aLineItemIds[i] == nItemID )
2042             {
2043                 nItemIndex = mpData->m_pLayoutData->m_aLineIndices[i];
2044                 break;
2045             }
2046         }
2047     }
2048     return (mpData->m_pLayoutData && nItemIndex != -1) ? mpData->m_pLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
2049 }
2050 
2051 // -----------------------------------------------------------------------
2052 
2053 long ToolBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const
2054 {
2055     long nIndex = -1;
2056     rItemID = 0;
2057     if( ! mpData->m_pLayoutData )
2058         ImplFillLayoutData();
2059     if( mpData->m_pLayoutData )
2060     {
2061         nIndex = mpData->m_pLayoutData->GetIndexForPoint( rPoint );
2062         for( sal_uLong i = 0; i < mpData->m_pLayoutData->m_aLineIndices.size(); i++ )
2063         {
2064             if( mpData->m_pLayoutData->m_aLineIndices[i] <= nIndex &&
2065                 (i == mpData->m_pLayoutData->m_aLineIndices.size()-1 || mpData->m_pLayoutData->m_aLineIndices[i+1] > nIndex) )
2066             {
2067                 rItemID = mpData->m_pLayoutData->m_aLineItemIds[i];
2068                 break;
2069             }
2070         }
2071     }
2072     return nIndex;
2073 }
2074 
2075 // -----------------------------------------------------------------------
2076 
2077 long ToolBox::GetTextCount() const
2078 {
2079     if( ! mpData->m_pLayoutData )
2080         ImplFillLayoutData();
2081     return mpData->m_pLayoutData ? mpData->m_pLayoutData->GetLineCount() : 0;
2082 }
2083 
2084 // -----------------------------------------------------------------------
2085 
2086 Pair ToolBox::GetTextStartEnd( long nText ) const
2087 {
2088     if( ! mpData->m_pLayoutData )
2089         ImplFillLayoutData();
2090     return mpData->m_pLayoutData ? mpData->m_pLayoutData->GetLineStartEnd( nText ) : Pair( -1, -1 );
2091 }
2092 
2093 // -----------------------------------------------------------------------
2094 
2095 sal_uInt16 ToolBox::GetDisplayItemId( long nText ) const
2096 {
2097     sal_uInt16 nItemId = 0;
2098     if( ! mpData->m_pLayoutData )
2099         ImplFillLayoutData();
2100     if( mpData->m_pLayoutData && nText >= 0 && (sal_uLong)nText < mpData->m_pLayoutData->m_aLineItemIds.size() )
2101         nItemId = mpData->m_pLayoutData->m_aLineItemIds[nText];
2102     return nItemId;
2103 }
2104 
2105 
2106 // -----------------------------------------------------------------------
2107 
2108 void ToolBox::SetDropdownClickHdl( const Link& rLink )
2109 {
2110     mpData->maDropdownClickHdl = rLink;
2111 }
2112 
2113 const Link& ToolBox::GetDropdownClickHdl() const
2114 {
2115     return mpData->maDropdownClickHdl;
2116 }
2117 
2118 // -----------------------------------------------------------------------
2119 
2120 void ToolBox::SetMenuType( sal_uInt16 aType )
2121 {
2122     if( aType != mpData->maMenuType )
2123     {
2124         mpData->maMenuType = aType;
2125         if( IsFloatingMode() )
2126         {
2127             // the menu button may have to be moved into the decoration which changes the layout
2128             ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2129             if( pWrapper )
2130                 pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( aType & TOOLBOX_MENUTYPE_CUSTOMIZE) ? sal_True : sal_False );
2131 
2132             mbFormat = sal_True;
2133             ImplFormat();
2134             ImplSetMinMaxFloatSize( this );
2135         }
2136         else
2137         {
2138             // trigger redraw of menu button
2139             if( !mpData->maMenubuttonItem.maRect.IsEmpty() )
2140                 Invalidate(mpData->maMenubuttonItem.maRect);
2141         }
2142     }
2143 }
2144 
2145 sal_uInt16 ToolBox::GetMenuType() const
2146 {
2147     return mpData->maMenuType;
2148 }
2149 
2150 sal_Bool ToolBox::IsMenuEnabled() const
2151 {
2152     return mpData->maMenuType != TOOLBOX_MENUTYPE_NONE;
2153 }
2154 
2155 PopupMenu* ToolBox::GetMenu() const
2156 {
2157     return mpData->mpMenu;
2158 }
2159 
2160 void ToolBox::SetMenuButtonHdl( const Link& rLink )
2161 {
2162     mpData->maMenuButtonHdl = rLink;
2163 }
2164 
2165 const Link& ToolBox::GetMenuButtonHdl() const
2166 {
2167     return mpData->maMenuButtonHdl;
2168 }
2169 
2170 // -----------------------------------------------------------------------
2171 
2172 sal_Bool ToolBox::ImplHasClippedItems()
2173 {
2174     // are any items currently clipped ?
2175     ImplFormat();
2176     std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
2177     while ( it != mpData->m_aItems.end() )
2178     {
2179         if( it->IsClipped() )
2180             return sal_True;
2181         it++;
2182     }
2183     return sal_False;
2184 }
2185 
2186 void ToolBox::ImplUpdateCustomMenu()
2187 {
2188     // fill clipped items into menu
2189     if( !IsMenuEnabled() )
2190         return;
2191 
2192     PopupMenu *pMenu = GetMenu();
2193 
2194     sal_uInt16 i = 0;
2195     // remove old entries
2196     while( i < pMenu->GetItemCount() )
2197     {
2198         if( pMenu->GetItemId( i ) >= TOOLBOX_MENUITEM_START )
2199         {
2200             pMenu->RemoveItem( i );
2201             i = 0;
2202         }
2203         else
2204             i++;
2205     }
2206 
2207     // add menu items, starting from the end and inserting at pos 0
2208     if ( !mpData->m_aItems.empty() )
2209     {
2210         for ( std::vector< ImplToolItem >::reverse_iterator it(mpData->m_aItems.rbegin());
2211                 it != mpData->m_aItems.rend(); ++it)
2212         {
2213             if( it->IsClipped() )
2214             {
2215                 sal_uInt16 id = it->mnId + TOOLBOX_MENUITEM_START;
2216                 pMenu->InsertItem( id, it->maText, it->maImage, 0, 0 );
2217                 pMenu->EnableItem( id, it->mbEnabled );
2218                 pMenu->CheckItem( id, it->meState == STATE_CHECK );
2219             }
2220         }
2221     }
2222 }
2223 
2224 IMPL_LINK( ToolBox, ImplCustomMenuListener, VclMenuEvent*, pEvent )
2225 {
2226     if( pEvent->GetMenu() == GetMenu() && pEvent->GetId() == VCLEVENT_MENU_SELECT )
2227     {
2228         sal_uInt16 id = GetMenu()->GetItemId( pEvent->GetItemPos() );
2229         if( id >= TOOLBOX_MENUITEM_START )
2230             TriggerItem( id - TOOLBOX_MENUITEM_START, sal_False, sal_False );
2231     }
2232     return 0;
2233 }
2234 
2235 IMPL_LINK( ToolBox, ImplCallExecuteCustomMenu, void*, EMPTYARG )
2236 {
2237     mpData->mnEventId = 0;
2238     ImplExecuteCustomMenu();
2239     return 0;
2240 }
2241 
2242 void ToolBox::ImplExecuteCustomMenu()
2243 {
2244     if( IsMenuEnabled() )
2245     {
2246         if( GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE )
2247             // call button handler to allow for menu customization
2248             mpData->maMenuButtonHdl.Call( this );
2249 
2250         // register handler
2251         GetMenu()->AddEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
2252 
2253         // make sure all disabled entries will be shown
2254         GetMenu()->SetMenuFlags(
2255             GetMenu()->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES );
2256 
2257         // toolbox might be destroyed during execute
2258         ImplDelData aDelData;
2259         ImplAddDel( &aDelData );
2260         ImplDelData aBorderDel;
2261         bool bBorderDel = false;
2262 
2263         Window *pWin = this;
2264         Rectangle aMenuRect = mpData->maMenubuttonItem.maRect;
2265         if( IsFloatingMode() )
2266         {
2267             // custom menu is placed in the decoration
2268             ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( WINDOW_BORDER ) );
2269             if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
2270             {
2271                 pWin = pBorderWin;
2272                 aMenuRect = pBorderWin->GetMenuRect();
2273                 pWin->ImplAddDel( &aBorderDel );
2274                 bBorderDel = true;
2275             }
2276         }
2277 
2278         sal_uInt16 uId = GetMenu()->Execute( pWin, Rectangle( ImplGetPopupPosition( aMenuRect, Size() ), Size() ),
2279                                 POPUPMENU_EXECUTE_DOWN | POPUPMENU_NOMOUSEUPCLOSE );
2280 
2281         if ( aDelData.IsDelete() )
2282             return;
2283         ImplRemoveDel( &aDelData );
2284 
2285         if( GetMenu() )
2286             GetMenu()->RemoveEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
2287         if( bBorderDel )
2288         {
2289             if( aBorderDel.IsDelete() )
2290                 return;
2291             pWin->ImplRemoveDel( &aBorderDel );
2292         }
2293 
2294         pWin->Invalidate( aMenuRect );
2295 
2296         if( uId )
2297             GrabFocusToDocument();
2298     }
2299 }
2300 
2301 void ToolBox::ExecuteCustomMenu()
2302 {
2303     if( IsMenuEnabled() )
2304     {
2305         // handle custom menu asynchronously
2306         // to avoid problems if the toolbox is closed during menu execute
2307         ImplUpdateCustomMenu();
2308         Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
2309     }
2310 }
2311 
2312 // -----------------------------------------------------------------------
2313 
2314 // checks override first, useful during calculation of sizes
2315 sal_Bool ToolBox::ImplIsFloatingMode() const
2316 {
2317     DBG_ASSERT( !(mpData->mbAssumeDocked && mpData->mbAssumeFloating),
2318         "ToolBox::ImplIsFloatingMode(): cannot assume docked and floating" );
2319 
2320     if( mpData->mbAssumeDocked )
2321         return sal_False;
2322     else if( mpData->mbAssumeFloating )
2323         return sal_True;
2324     else
2325         return IsFloatingMode();
2326 }
2327 
2328 // checks override first, useful during calculation of sizes
2329 sal_Bool ToolBox::ImplIsInPopupMode() const
2330 {
2331     if( mpData->mbAssumePopupMode )
2332         return sal_True;
2333     else
2334     {
2335         ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2336         return ( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() );
2337     }
2338 }
2339 
2340 // -----------------------------------------------------------------------
2341 
2342 void ToolBox::Lock( sal_Bool bLock )
2343 {
2344     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2345     if( !pWrapper )
2346         return;
2347     if( mpData->mbIsLocked != bLock )
2348     {
2349         mpData->mbIsLocked = bLock;
2350         if( !ImplIsFloatingMode() )
2351         {
2352             mbCalc = sal_True;
2353             mbFormat = sal_True;
2354             SetSizePixel( CalcWindowSizePixel(1) );
2355             Invalidate();
2356         }
2357     }
2358 }
2359 
2360 // -----------------------------------------------------------------------
2361 
2362 sal_Bool ToolBox::AlwaysLocked()
2363 {
2364     // read config item to determine toolbox behaviour, used for subtoolbars
2365 
2366     static int nAlwaysLocked = -1;
2367 
2368     if( nAlwaysLocked == -1 )
2369     {
2370         nAlwaysLocked = 0; // ask configuration only once
2371 
2372         utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithServiceFactory(
2373             vcl::unohelper::GetMultiServiceFactory(),
2374             OUString::createFromAscii( "/org.openoffice.Office.UI.GlobalSettings/Toolbars" ) );    // note: case sensisitive !
2375         if ( aNode.isValid() )
2376         {
2377             // feature enabled ?
2378             sal_Bool bStatesEnabled = sal_Bool();
2379             ::com::sun::star::uno::Any aValue = aNode.getNodeValue( OUString::createFromAscii( "StatesEnabled" ) );
2380             if( aValue >>= bStatesEnabled )
2381             {
2382                 if( bStatesEnabled == sal_True )
2383                 {
2384                     // now read the locking state
2385                     utl::OConfigurationNode aNode2 = utl::OConfigurationTreeRoot::tryCreateWithServiceFactory(
2386                         vcl::unohelper::GetMultiServiceFactory(),
2387                         OUString::createFromAscii( "/org.openoffice.Office.UI.GlobalSettings/Toolbars/States" ) );    // note: case sensisitive !
2388 
2389                     sal_Bool bLocked = sal_Bool();
2390                     ::com::sun::star::uno::Any aValue2 = aNode2.getNodeValue( OUString::createFromAscii( "Locked" ) );
2391                     if( aValue2 >>= bLocked )
2392                         nAlwaysLocked = (bLocked == sal_True) ? 1 : 0;
2393                 }
2394             }
2395         }
2396     }
2397 
2398     return nAlwaysLocked == 1 ? sal_True : sal_False;
2399 }
2400 
2401 sal_Bool ToolBox::WillUsePopupMode() const
2402 {
2403     return mpData->mbWillUsePopupMode;
2404 }
2405 
2406 void ToolBox::WillUsePopupMode( sal_Bool b )
2407 {
2408     mpData->mbWillUsePopupMode = b;
2409 }
2410 
2411 void ToolBox::ImplUpdateImageList()
2412 {
2413     if (mpData->mpImageListProvider != NULL)
2414     {
2415         sal_Bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
2416         try
2417         {
2418             ImageListType eType = bHC ? vcl::HIGHCONTRAST_YES : vcl::HIGHCONTRAST_NO;
2419 
2420             if (eType != mpData->meImageListType)
2421             {
2422                 vcl::IImageListProvider* pImageListProvider = mpData->mpImageListProvider;
2423                 SetImageList( pImageListProvider->getImageList(eType) );
2424                 mpData->meImageListType = eType;
2425             }
2426         }
2427         catch (com::sun::star::lang::IllegalArgumentException &) {}
2428     }
2429 }
2430 
2431 void ToolBox::SetImageListProvider(vcl::IImageListProvider* _pProvider)
2432 {
2433     mpData->mpImageListProvider = _pProvider;
2434     ImplUpdateImageList();
2435 }
2436 // -----------------------------------------------------------------------
2437