xref: /aoo41x/main/vcl/source/window/toolbox.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <rtl/logfile.hxx>
32 
33 #include <tools/list.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/rc.h>
36 #include <tools/poly.hxx>
37 
38 #include <vcl/event.hxx>
39 #include <vcl/decoview.hxx>
40 #include <vcl/accel.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/help.hxx>
43 #include <vcl/sound.hxx>
44 #include <vcl/virdev.hxx>
45 #include <vcl/spin.h>
46 #include <vcl/toolbox.hxx>
47 #include <vcl/bitmap.hxx>
48 #include <vcl/mnemonic.hxx>
49 #include <vcl/gradient.hxx>
50 #include <vcl/menu.hxx>
51 
52 #include <svdata.hxx>
53 #include <window.h>
54 #include <toolbox.h>
55 #include <salframe.hxx>
56 #if defined WNT
57 #include <svsys.h>
58 #endif
59 
60 #include <string.h>
61 #include <vector>
62 #include <math.h>
63 
64 // =======================================================================
65 
66 DBG_NAMEEX( Window )
67 
68 // =======================================================================
69 
70 #define SMALLBUTTON_HSIZE           7
71 #define SMALLBUTTON_VSIZE           7
72 
73 #define SMALLBUTTON_OFF_NORMAL_X    3
74 #define SMALLBUTTON_OFF_NORMAL_Y    3
75 #define SMALLBUTTON_OFF_CHECKED_X   4
76 #define SMALLBUTTON_OFF_CHECKED_Y   4
77 #define SMALLBUTTON_OFF_PRESSED_X   5
78 #define SMALLBUTTON_OFF_PRESSED_Y   5
79 
80 #define OUTBUTTON_SIZE              6
81 #define OUTBUTTON_BORDER            4
82 #define OUTBUTTON_OFF_NORMAL_X      1
83 #define OUTBUTTON_OFF_NORMAL_Y      1
84 
85 // -----------------------------------------------------------------------
86 
87 #define DEF_MIN_WIDTH           8
88 #define DEF_MIN_HEIGHT          8
89 #define DEF_TEXT_WIDTH          40
90 
91 #define TB_TEXTOFFSET           2
92 #define TB_IMAGETEXTOFFSET      3
93 #define TB_LINESPACING          3
94 #define TB_SPIN_SIZE            14
95 #define TB_SPIN_OFFSET          2
96 #define TB_NEXT_SIZE            22
97 #define TB_NEXT_OFFSET          2
98 #define TB_BORDER_OFFSET1       4
99 #define TB_BORDER_OFFSET2       2
100 #define TB_CUSTOMIZE_OFFSET     2
101 #define TB_RESIZE_OFFSET        3
102 #define TB_MAXLINES             5
103 #define TB_MAXNOSCROLL          32765
104 
105 #define TB_MIN_WIN_WIDTH        20
106 
107 #define TB_CALCMODE_HORZ        1
108 #define TB_CALCMODE_VERT        2
109 #define TB_CALCMODE_FLOAT       3
110 
111 #define TB_WBLINESIZING         (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)
112 
113 #define TB_MAX_GROUPS           100
114 
115 #define DOCK_LINEHSIZE          ((sal_uInt16)0x0001)
116 #define DOCK_LINEVSIZE          ((sal_uInt16)0x0002)
117 #define DOCK_LINERIGHT          ((sal_uInt16)0x1000)
118 #define DOCK_LINEBOTTOM         ((sal_uInt16)0x2000)
119 #define DOCK_LINELEFT           ((sal_uInt16)0x4000)
120 #define DOCK_LINETOP            ((sal_uInt16)0x8000)
121 #define DOCK_LINEOFFSET         3
122 
123 
124 // -----------------------------------------------------------------------
125 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bEnabled, sal_Bool bIsWindow );
126 // -----------------------------------------------------------------------
127 
128 struct ImplToolSize
129 {
130     long            mnWidth;
131     long            mnHeight;
132     sal_uInt16          mnLines;
133 };
134 
135 struct ImplToolSizeArray
136 {
137     long          mnLength;
138     long          mnLastEntry;
139     ImplToolSize* mpSize;
140 
141     ImplToolSizeArray() { mpSize = NULL; mnLength = 0; mnLastEntry = 0; }
142     ~ImplToolSizeArray() { if( mpSize ) delete [] mpSize; mnLength = 0; }
143 };
144 
145 // -----------------------------------------------------------------------
146 
147 DECLARE_LIST( ImplTBList, ToolBox* )
148 
149 class ImplTBDragMgr
150 {
151 private:
152     ImplTBList*     mpBoxList;
153     ToolBox*        mpDragBox;
154     Point           maMouseOff;
155     Rectangle       maRect;
156     Rectangle       maStartRect;
157     Accelerator     maAccel;
158     long            mnMinWidth;
159     long            mnMaxWidth;
160     sal_uInt16          mnLineMode;
161     sal_uInt16          mnStartLines;
162     void*           mpCustomizeData;
163     sal_Bool            mbCustomizeMode;
164     sal_Bool            mbResizeMode;
165     sal_Bool            mbShowDragRect;
166 
167 public:
168                     ImplTBDragMgr();
169                     ~ImplTBDragMgr();
170 
171     void            Insert( ToolBox* pBox )
172                         { mpBoxList->Insert( pBox ); }
173     void            Remove( ToolBox* pBox )
174                         { mpBoxList->Remove( pBox ); }
175     sal_uLong           Count() const
176                         { return mpBoxList->Count(); }
177 
178     ToolBox*        FindToolBox( const Rectangle& rRect );
179 
180     void            StartDragging( ToolBox* pDragBox,
181                                    const Point& rPos, const Rectangle& rRect,
182                                    sal_uInt16 nLineMode, sal_Bool bResizeItem,
183                                    void* pData = NULL );
184     void            Dragging( const Point& rPos );
185     void            EndDragging( sal_Bool bOK = sal_True );
186     void            HideDragRect() { if ( mbShowDragRect ) mpDragBox->HideTracking(); }
187     void            UpdateDragRect();
188                     DECL_LINK( SelectHdl, Accelerator* );
189 
190     void            StartCustomizeMode();
191     void            EndCustomizeMode();
192     sal_Bool            IsCustomizeMode() { return mbCustomizeMode; }
193     sal_Bool            IsResizeMode() { return mbResizeMode; }
194 };
195 
196 // -----------------------------------------------------------------------
197 
198 static ImplTBDragMgr* ImplGetTBDragMgr()
199 {
200     ImplSVData* pSVData = ImplGetSVData();
201     if ( !pSVData->maCtrlData.mpTBDragMgr )
202         pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr;
203     return pSVData->maCtrlData.mpTBDragMgr;
204 }
205 
206 // -----------------------------------------------------------------------
207 
208 int ToolBox::ImplGetDragWidth( ToolBox* pThis )
209 {
210     #define TB_DRAGWIDTH 8  // the default width of the grip
211 
212     int width = TB_DRAGWIDTH;
213     if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
214     {
215 
216 		ImplControlValue aControlValue;
217 		Point aPoint;
218 		Rectangle aContent, aBound;
219 		Rectangle aArea( aPoint, pThis->GetOutputSizePixel() );
220 
221         if ( pThis->GetNativeControlRegion(CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
222 				aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
223         {
224             width = pThis->mbHorz ? aContent.GetWidth() : aContent.GetHeight();
225         }
226     }
227     return width;
228 }
229 
230 ButtonType determineButtonType( ImplToolItem* pItem, ButtonType defaultType )
231 {
232     ButtonType tmpButtonType = defaultType;
233     ToolBoxItemBits nBits( pItem->mnBits & 0x300 );
234     if ( nBits & TIB_TEXTICON ) // item has custom setting
235     {
236         tmpButtonType = BUTTON_SYMBOLTEXT;
237         if ( nBits == TIB_TEXT_ONLY )
238             tmpButtonType = BUTTON_TEXT;
239         else if ( nBits == TIB_ICON_ONLY )
240             tmpButtonType = BUTTON_SYMBOL;
241     }
242     return tmpButtonType;
243 }
244 
245 // -----------------------------------------------------------------------
246 
247 void ToolBox::ImplUpdateDragArea( ToolBox *pThis )
248 {
249     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
250     if( pWrapper )
251     {
252         if ( pThis->ImplIsFloatingMode() || pWrapper->IsLocked() )
253             pWrapper->SetDragArea( Rectangle() );
254         else
255         {
256             if( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
257                 pWrapper->SetDragArea( Rectangle( 0, 0, ImplGetDragWidth( pThis ), pThis->GetOutputSizePixel().Height() ) );
258             else
259                 pWrapper->SetDragArea( Rectangle( 0, 0, pThis->GetOutputSizePixel().Width(), ImplGetDragWidth( pThis ) ) );
260         }
261     }
262 }
263 
264 // -----------------------------------------------------------------------
265 
266 void ToolBox::ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop,
267                               long& rRight, long& rBottom, const ToolBox *pThis )
268 {
269     if( pThis->ImplIsFloatingMode() || !(pThis->mnWinStyle & WB_BORDER) )
270     {
271         // no border in floating mode
272         rLeft = rTop = rRight = rBottom = 0;
273         return;
274     }
275 
276     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
277 
278     // reserve dragarea only for dockable toolbars
279     int    dragwidth = ( pWrapper && !pWrapper->IsLocked() ) ? ImplGetDragWidth( (ToolBox*)pThis ) : 0;
280 
281     // no shadow border for dockable toolbars
282     int    borderwidth = pWrapper ? 0: 2;
283 
284     if ( eAlign == WINDOWALIGN_TOP )
285     {
286         rLeft   = borderwidth+dragwidth;
287         rTop    = borderwidth;
288         rRight  = borderwidth;
289         rBottom = 0;
290     }
291     else if ( eAlign == WINDOWALIGN_LEFT )
292     {
293         rLeft   = borderwidth;
294         rTop    = borderwidth+dragwidth;
295         rRight  = 0;
296         rBottom = borderwidth;
297     }
298     else if ( eAlign == WINDOWALIGN_BOTTOM )
299     {
300         rLeft   = borderwidth+dragwidth;
301         rTop    = 0;
302         rRight  = borderwidth;
303         rBottom = borderwidth;
304     }
305     else
306     {
307         rLeft   = 0;
308         rTop    = borderwidth+dragwidth;
309         rRight  = borderwidth;
310         rBottom = borderwidth;
311     }
312 }
313 
314 // -----------------------------------------------------------------------
315 
316 static void ImplCheckUpdate( ToolBox *pThis )
317 {
318     // remove any pending invalidates to avoid
319     // have them triggered when paint is locked (see mpData->mbIsPaintLocked)
320     // which would result in erasing the background only and not painting any items
321     // this must not be done when we're already in Paint()
322 
323     // this is only required for transparent toolbars (see ImplDrawTransparentBackground() )
324     if( !pThis->IsBackground() && pThis->HasPaintEvent() && !pThis->IsInPaint() )
325         pThis->Update();
326 }
327 
328 // -----------------------------------------------------------------------
329 
330 void ToolBox::ImplDrawGrip( ToolBox* pThis )
331 {
332     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
333     if( pWrapper && !pWrapper->GetDragArea().IsEmpty() )
334     {
335         // execute pending paint requests
336         ImplCheckUpdate( pThis );
337 
338         sal_Bool bNativeOk = sal_False;
339         if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_HORZ : PART_THUMB_VERT ) )
340         {
341             ToolbarValue        aToolbarValue;
342             aToolbarValue.maGripRect = pWrapper->GetDragArea();
343             Point aPt;
344             Rectangle           aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
345             ControlState        nState = CTRL_STATE_ENABLED;
346 
347             bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
348                                             aCtrlRegion, nState, aToolbarValue, rtl::OUString() );
349         }
350 
351         if( bNativeOk )
352             return;
353 
354         const StyleSettings&    rStyleSettings = pThis->GetSettings().GetStyleSettings();
355         pThis->SetLineColor( rStyleSettings.GetShadowColor() );
356 
357         Size aSz ( pThis->GetOutputSizePixel() );
358 
359         if ( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
360         {
361             int height = (int) (0.6 * aSz.Height() + 0.5);
362             int i = (aSz.Height() - height) / 2;
363             height += i;
364             while( i <= height )
365             {
366                 int x = ImplGetDragWidth( pThis ) / 2;
367 
368                 pThis->DrawPixel( Point(x, i), rStyleSettings.GetDarkShadowColor() );
369                 pThis->DrawPixel( Point(x+1, i), rStyleSettings.GetShadowColor() );
370 
371                 pThis->DrawPixel( Point(x, i+1), rStyleSettings.GetShadowColor() );
372                 pThis->DrawPixel( Point(x+1, i+1), rStyleSettings.GetFaceColor() );
373                 pThis->DrawPixel( Point(x+2, i+1), Color(COL_WHITE) );
374 
375                 pThis->DrawPixel( Point(x+1, i+2), Color(COL_WHITE) );
376                 pThis->DrawPixel( Point(x+2, i+2), Color(COL_WHITE) );
377                 i+=4;
378             }
379         }
380         else
381         {
382             int width = (int) (0.6 * aSz.Width() + 0.5);
383             int i = (aSz.Width() - width) / 2;
384             width += i;
385             while( i <= width )
386             {
387                 int y = ImplGetDragWidth(pThis) / 2;
388 
389                 pThis->DrawPixel( Point(i, y), rStyleSettings.GetDarkShadowColor() );
390                 pThis->DrawPixel( Point(i+1, y), rStyleSettings.GetShadowColor() );
391 
392                 pThis->DrawPixel( Point(i, y+1), rStyleSettings.GetShadowColor() );
393                 pThis->DrawPixel( Point(i+1, y+1), rStyleSettings.GetFaceColor() );
394                 pThis->DrawPixel( Point(i+2, y+1), Color(COL_WHITE) );
395 
396                 pThis->DrawPixel( Point(i+1, y+2), Color(COL_WHITE) );
397                 pThis->DrawPixel( Point(i+2, y+2), Color(COL_WHITE) );
398                 i+=4;
399             }
400         }
401     }
402 }
403 
404 void ToolBox::ImplDrawGradientBackground( ToolBox* pThis, ImplDockingWindowWrapper * )
405 {
406     // draw a nice gradient
407 
408     Color startCol, endCol;
409     startCol = pThis->GetSettings().GetStyleSettings().GetFaceGradientColor();
410     endCol = pThis->GetSettings().GetStyleSettings().GetFaceColor();
411     if( pThis->GetSettings().GetStyleSettings().GetHighContrastMode() )
412         // no 'extreme' gradient when high contrast
413         startCol = endCol;
414 
415     Gradient g;
416     g.SetAngle( pThis->mbHorz ? 0 : 900 );
417     g.SetStyle( GRADIENT_LINEAR );
418 
419     g.SetStartColor( startCol );
420     g.SetEndColor( endCol );
421 
422     sal_Bool bLineColor = pThis->IsLineColor();
423     Color aOldCol = pThis->GetLineColor();
424     pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
425 
426     Size aFullSz( pThis->GetOutputSizePixel() );
427     Size aLineSz( aFullSz );
428 
429     // use the linesize only when floating
430     // full window height is used when docked (single line)
431     if( pThis->ImplIsFloatingMode() )
432     {
433         long nLineSize;
434         if( pThis->mbHorz )
435         {
436             nLineSize = pThis->mnMaxItemHeight;
437             if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
438                 nLineSize = pThis->mnWinHeight;
439 
440             aLineSz.Height() = nLineSize;
441         }
442         else
443         {
444             nLineSize = pThis->mnMaxItemWidth;
445             aLineSz.Width() = nLineSize;
446         }
447     }
448 
449     long nLeft, nTop, nRight, nBottom;
450     ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
451 
452     Size aTopLineSz( aLineSz );
453     Size aBottomLineSz( aLineSz );
454 
455     if ( pThis->mnWinStyle & WB_BORDER )
456     {
457         if( pThis->mbHorz )
458         {
459             aTopLineSz.Height() += TB_BORDER_OFFSET2 + nTop;
460             aBottomLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
461 
462             if( pThis->mnCurLines == 1 )
463                 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
464         }
465         else
466         {
467             aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
468             aBottomLineSz.Width() += TB_BORDER_OFFSET1 + nRight;
469 
470             if( pThis->mnCurLines == 1 )
471                 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
472         }
473     }
474 
475     if( pThis->mbHorz )
476     {
477         aTopLineSz.Height() += pThis->mnBorderY;
478         if( pThis->mnCurLines == 1 )
479             aTopLineSz.Height() += pThis->mnBorderY;
480 
481         aBottomLineSz.Height() += pThis->mnBorderY;
482     }
483     else
484     {
485         aTopLineSz.Width() += pThis->mnBorderX;
486         if( pThis->mnCurLines == 1 )
487             aTopLineSz.Width() += pThis->mnBorderX;
488 
489         aBottomLineSz.Width() += pThis->mnBorderX;
490     }
491 
492 
493     if ( pThis->mnWinStyle & WB_LINESPACING )
494     {
495         if( pThis->mbHorz )
496         {
497             aLineSz.Height() += TB_LINESPACING;
498             if( pThis->mnCurLines > 1 )
499                 aTopLineSz.Height() += TB_LINESPACING;
500         }
501         else
502         {
503             aLineSz.Width() += TB_LINESPACING;
504             if( pThis->mnCurLines > 1 )
505                 aTopLineSz.Width() += TB_LINESPACING;
506         }
507     }
508 
509     if( pThis->mbHorz )
510     {
511         long y = 0;
512         sal_Bool bDrawSep = sal_False; // pThis->ImplIsFloatingMode() && ( pThis->mnWinStyle & WB_LINESPACING );
513 
514         pThis->DrawGradient( Rectangle( 0, y, aTopLineSz.Width(), y+aTopLineSz.Height()), g );
515         y += aTopLineSz.Height();
516 
517         if ( bDrawSep )
518             pThis->DrawLine( Point(0, y-2), Point(aTopLineSz.Width(), y-2) );
519 
520         while( y < (pThis->mnDY - aBottomLineSz.Height()) )
521         {
522             pThis->DrawGradient( Rectangle( 0, y, aLineSz.Width(), y+aLineSz.Height()), g);
523             y += aLineSz.Height();
524 
525             if ( bDrawSep )
526                 pThis->DrawLine( Point(0, y-2), Point(aLineSz.Width(), y-2) );
527         }
528 
529         pThis->DrawGradient( Rectangle( 0, y, aBottomLineSz.Width(), y+aBottomLineSz.Height()), g );
530         if ( bDrawSep )
531             pThis->DrawLine( Point(0, y-2), Point(aBottomLineSz.Width(), y-2) );
532     }
533     else
534     {
535         long x = 0;
536 
537         pThis->DrawGradient( Rectangle( x, 0, x+aTopLineSz.Width(), aTopLineSz.Height()), g );
538         x += aTopLineSz.Width();
539 
540         while( x < (pThis->mnDX - aBottomLineSz.Width()) )
541         {
542             pThis->DrawGradient( Rectangle( x, 0, x+aLineSz.Width(), aLineSz.Height()), g);
543             x += aLineSz.Width();
544         }
545 
546         pThis->DrawGradient( Rectangle( x, 0, x+aBottomLineSz.Width(), aBottomLineSz.Height()), g );
547     }
548 
549     if( bLineColor )
550         pThis->SetLineColor( aOldCol );
551 
552 }
553 
554 sal_Bool ToolBox::ImplDrawNativeBackground( ToolBox* pThis, const Region & )
555 {
556     // use NWF
557     Point aPt;
558     Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
559     ControlState  nState = CTRL_STATE_ENABLED;
560 
561     return pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
562                                     aCtrlRegion, nState, ImplControlValue(), rtl::OUString() );
563 }
564 
565 void ToolBox::ImplDrawTransparentBackground( ToolBox* pThis, const Region &rRegion )
566 {
567     // just invalidate to trigger paint of the parent
568 
569 	const bool		bOldPaintLock = pThis->mpData->mbIsPaintLocked;
570 	pThis->mpData->mbIsPaintLocked = true;
571 
572     // send an invalidate to the first opaque parent and invalidate the whole hierarchy from there (noclipchildren)
573 	pThis->Invalidate( rRegion, INVALIDATE_UPDATE|INVALIDATE_NOCLIPCHILDREN );
574 
575 	pThis->mpData->mbIsPaintLocked = bOldPaintLock;
576 }
577 
578 void ToolBox::ImplDrawConstantBackground( ToolBox* pThis, const Region &rRegion, sal_Bool bIsInPopupMode )
579 {
580     // draw a constant color
581     if( !bIsInPopupMode )
582         // default background
583         pThis->Erase( rRegion.GetBoundRect() );
584     else
585     {
586         // use different color in popupmode
587 	    pThis->DrawWallpaper( rRegion.GetBoundRect(),
588             Wallpaper( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() ) );
589     }
590 }
591 
592 
593 void ToolBox::ImplDrawBackground( ToolBox* pThis, const Rectangle &rRect )
594 {
595     // execute pending paint requests
596     ImplCheckUpdate( pThis );
597 
598     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
599     sal_Bool bIsInPopupMode = pThis->ImplIsInPopupMode();
600 
601     Region aPaintRegion( rRect );
602 
603     // make sure we do not invalidate/erase too much
604     if( pThis->IsInPaint() )
605         aPaintRegion.Intersect( pThis->GetActiveClipRegion() );
606 
607     pThis->Push( PUSH_CLIPREGION );
608     pThis->IntersectClipRegion( aPaintRegion );
609 
610 
611     if( !pWrapper /*|| bIsInPopupMode*/ )
612     {
613         // no gradient for ordinary toolbars (not dockable)
614 		if( !pThis->IsBackground() && !pThis->IsInPaint() )
615             ImplDrawTransparentBackground( pThis, aPaintRegion );
616 		else
617             ImplDrawConstantBackground( pThis, aPaintRegion, bIsInPopupMode );
618     }
619     else
620     {
621         // toolbars known to the dockingmanager will be drawn using NWF or a gradient
622         // docked toolbars are transparent and NWF is already used in the docking area which is their common background
623         // so NWF is used here for floating toolbars only
624         sal_Bool bNativeOk = sal_False;
625         if( pThis->ImplIsFloatingMode() && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL) )
626             bNativeOk = ImplDrawNativeBackground( pThis, aPaintRegion );
627 
628         if( !bNativeOk )
629         {
630             if( !pThis->IsBackground() )
631             {
632                 if( !pThis->IsInPaint() )
633                     ImplDrawTransparentBackground( pThis, aPaintRegion );
634             }
635             else
636                 ImplDrawGradientBackground( pThis, pWrapper );
637         }
638     }
639 
640     // restore clip region
641     pThis->Pop();
642 }
643 
644 void ToolBox::ImplErase( ToolBox* pThis, const Rectangle &rRect, sal_Bool bHighlight, sal_Bool bHasOpenPopup )
645 {
646     // the background of non NWF buttons is painted in a constant color
647     // to have the same highlight color (transparency in DrawSelectionBackground())
648     // items with open popups will also painted using a constant color
649     if( !pThis->mpData->mbNativeButtons &&
650         (bHighlight || ! (((Window*) pThis)->GetStyle() & WB_3DLOOK ) ) )
651     {
652         if( (((Window*) pThis)->GetStyle() & WB_3DLOOK ) )
653         {
654             pThis->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
655             pThis->SetLineColor();
656             if( bHasOpenPopup )
657                 // choose the same color as the popup will use
658                 pThis->SetFillColor( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() );
659             else
660                 pThis->SetFillColor( Color( COL_WHITE ) );
661 
662             pThis->DrawRect( rRect );
663             pThis->Pop();
664         }
665         else
666             ImplDrawBackground( pThis, rRect );
667     }
668     else
669         ImplDrawBackground( pThis, rRect );
670 }
671 
672 void ToolBox::ImplDrawBorder( ToolBox* pWin )
673 {
674     const StyleSettings&    rStyleSettings = pWin->GetSettings().GetStyleSettings();
675     long                    nDX = pWin->mnDX;
676     long                    nDY = pWin->mnDY;
677 
678     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pWin );
679 
680     // draw borders for ordinary toolbars only (not dockable)
681     if( pWrapper )
682         return;
683 
684     if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
685     {
686         // draw bottom border
687         pWin->SetLineColor( rStyleSettings.GetShadowColor() );
688         pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
689         pWin->SetLineColor( rStyleSettings.GetLightColor() );
690         pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
691     }
692     else
693     {
694         // draw top border
695         pWin->SetLineColor( rStyleSettings.GetShadowColor() );
696         pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
697         pWin->SetLineColor( rStyleSettings.GetLightColor() );
698         pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
699 
700         if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
701         {
702             if ( pWin->meAlign == WINDOWALIGN_LEFT )
703             {
704                 // draw left-bottom border
705                 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
706                 pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
707                 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
708                 pWin->SetLineColor( rStyleSettings.GetLightColor() );
709                 pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
710                 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
711             }
712             else
713             {
714                 // draw right-bottom border
715                 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
716                 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
717                 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
718                 pWin->SetLineColor( rStyleSettings.GetLightColor() );
719                 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
720                 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
721             }
722         }
723     }
724 
725 
726     if ( pWin->meAlign == WINDOWALIGN_BOTTOM || pWin->meAlign == WINDOWALIGN_TOP )
727     {
728         // draw right border
729         pWin->SetLineColor( rStyleSettings.GetShadowColor() );
730         pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) );
731         pWin->SetLineColor( rStyleSettings.GetLightColor() );
732         pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
733     }
734 }
735 
736 // -----------------------------------------------------------------------
737 
738 static bool ImplIsFixedControl( const ImplToolItem *pItem )
739 {
740     return ( pItem->mpWindow &&
741             (pItem->mpWindow->GetType() == WINDOW_FIXEDTEXT ||
742              pItem->mpWindow->GetType() == WINDOW_FIXEDLINE ||
743              pItem->mpWindow->GetType() == WINDOW_GROUPBOX) );
744 }
745 
746 // -----------------------------------------------------------------------
747 
748 const ImplToolItem *ToolBox::ImplGetFirstClippedItem( const ToolBox* pThis )
749 {
750     std::vector< ImplToolItem >::const_iterator it;
751     it = pThis->mpData->m_aItems.begin();
752     while ( it != pThis->mpData->m_aItems.end() )
753     {
754         if( it->IsClipped() )
755             return &(*it);
756         ++it;
757     }
758     return NULL;
759 }
760 
761 // -----------------------------------------------------------------------
762 
763 Size ToolBox::ImplCalcSize( const ToolBox* pThis, sal_uInt16 nCalcLines, sal_uInt16 nCalcMode )
764 {
765     long            nMax;
766     long            nLeft = 0;
767     long            nTop = 0;
768     long            nRight = 0;
769     long            nBottom = 0;
770     Size            aSize;
771     WindowAlign     eOldAlign = pThis->meAlign;
772     sal_Bool            bOldHorz = pThis->mbHorz;
773     sal_Bool            bOldAssumeDocked = pThis->mpData->mbAssumeDocked;
774     sal_Bool            bOldAssumeFloating = pThis->mpData->mbAssumeFloating;
775 
776     if ( nCalcMode )
777     {
778         sal_Bool bOldFloatingMode = pThis->ImplIsFloatingMode();
779 
780         pThis->mpData->mbAssumeDocked = sal_False;
781         pThis->mpData->mbAssumeFloating = sal_False;
782 
783         if ( nCalcMode == TB_CALCMODE_HORZ )
784         {
785             pThis->mpData->mbAssumeDocked = sal_True;   // force non-floating mode during calculation
786             ImplCalcBorder( WINDOWALIGN_TOP, nLeft, nTop, nRight, nBottom, pThis );
787             ((ToolBox*)pThis)->mbHorz = sal_True;
788             if ( pThis->mbHorz != bOldHorz )
789                 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
790         }
791         else if ( nCalcMode == TB_CALCMODE_VERT )
792         {
793             pThis->mpData->mbAssumeDocked = sal_True;   // force non-floating mode during calculation
794             ImplCalcBorder( WINDOWALIGN_LEFT, nLeft, nTop, nRight, nBottom, pThis );
795             ((ToolBox*)pThis)->mbHorz = sal_False;
796             if ( pThis->mbHorz != bOldHorz )
797                 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_LEFT;
798         }
799         else if ( nCalcMode == TB_CALCMODE_FLOAT )
800         {
801             pThis->mpData->mbAssumeFloating = sal_True;   // force non-floating mode during calculation
802             nLeft = nTop = nRight = nBottom = 0;
803             ((ToolBox*)pThis)->mbHorz = sal_True;
804             if ( pThis->mbHorz != bOldHorz )
805                 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
806         }
807 
808         if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) ||
809              (pThis->ImplIsFloatingMode() != bOldFloatingMode ) )
810             ((ToolBox*)pThis)->mbCalc = sal_True;
811     }
812     else
813         ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
814 
815     ((ToolBox*)pThis)->ImplCalcItem();
816 
817     if( !nCalcMode && pThis->ImplIsFloatingMode() )
818     {
819         aSize = ImplCalcFloatSize( ((ToolBox*)pThis), nCalcLines );
820     }
821     else
822     {
823         if ( pThis->mbHorz )
824         {
825             if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
826                 aSize.Height() = nCalcLines * pThis->mnWinHeight;
827             else
828                 aSize.Height() = nCalcLines * pThis->mnMaxItemHeight;
829 
830             if ( pThis->mnWinStyle & WB_LINESPACING )
831                 aSize.Height() += (nCalcLines-1)*TB_LINESPACING;
832 
833             if ( pThis->mnWinStyle & WB_BORDER )
834                 aSize.Height() += (TB_BORDER_OFFSET2*2) + nTop + nBottom;
835 
836             nMax = 0;
837             ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
838             if ( nMax )
839                 aSize.Width() += nMax;
840 
841             if ( pThis->mnWinStyle & WB_BORDER )
842                 aSize.Width() += (TB_BORDER_OFFSET1*2) + nLeft + nRight;
843         }
844         else
845         {
846             aSize.Width() = nCalcLines * pThis->mnMaxItemWidth;
847 
848             if ( pThis->mnWinStyle & WB_LINESPACING )
849                 aSize.Width() += (nCalcLines-1)*TB_LINESPACING;
850 
851             if ( pThis->mnWinStyle & WB_BORDER )
852                 aSize.Width() += (TB_BORDER_OFFSET2*2) + nLeft + nRight;
853 
854             nMax = 0;
855             ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
856             if ( nMax )
857                 aSize.Height() += nMax;
858 
859             if ( pThis->mnWinStyle & WB_BORDER )
860                 aSize.Height() += (TB_BORDER_OFFSET1*2) + nTop + nBottom;
861         }
862     }
863     // restore previous values
864     if ( nCalcMode )
865     {
866         pThis->mpData->mbAssumeDocked = bOldAssumeDocked;
867         pThis->mpData->mbAssumeFloating = bOldAssumeFloating;
868         if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
869         {
870             ((ToolBox*)pThis)->meAlign  = eOldAlign;
871             ((ToolBox*)pThis)->mbHorz   = bOldHorz;
872             ((ToolBox*)pThis)->mbCalc   = sal_True;
873         }
874     }
875 
876     if ( aSize.Width() )
877         aSize.Width() += pThis->mnBorderX*2;
878     if ( aSize.Height() )
879         aSize.Height() += pThis->mnBorderY*2;
880 
881     return aSize;
882 }
883 
884 // -----------------------------------------------------------------------
885 
886 void ToolBox::ImplCalcFloatSizes( ToolBox* pThis )
887 {
888     if ( pThis->mpFloatSizeAry )
889         return;
890 
891     // calculate the minimal size, i.e. where the biggest item just fits
892     long            nCalcSize = 0;
893 
894     std::vector< ImplToolItem >::const_iterator it;
895     it = pThis->mpData->m_aItems.begin();
896     while ( it != pThis->mpData->m_aItems.end() )
897     {
898         if ( it->mbVisible )
899         {
900             if ( it->mpWindow )
901             {
902                 long nTempSize = it->mpWindow->GetSizePixel().Width();
903                 if ( nTempSize > nCalcSize )
904                     nCalcSize = nTempSize;
905             }
906             else
907             {
908                 if( it->maItemSize.Width() > nCalcSize )
909                     nCalcSize = it->maItemSize.Width();
910             }
911         }
912         ++it;
913     }
914 
915     // calc an upper bound for ImplCalcBreaks below
916     long upperBoundWidth = nCalcSize * pThis->mpData->m_aItems.size();
917 
918     sal_uInt16  i;
919     sal_uInt16  nLines;
920     sal_uInt16  nCalcLines;
921     sal_uInt16  nTempLines;
922     long    nHeight;
923     long    nMaxLineWidth;
924     nCalcLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, sal_True );
925 
926     pThis->mpFloatSizeAry = new ImplToolSizeArray;
927     pThis->mpFloatSizeAry->mpSize = new ImplToolSize[nCalcLines];
928     pThis->mpFloatSizeAry->mnLength = nCalcLines;
929 
930     memset( pThis->mpFloatSizeAry->mpSize, 0, sizeof( ImplToolSize )*nCalcLines );
931     i = 0;
932     nTempLines = nLines = nCalcLines;
933     while ( nLines )
934     {
935         nHeight = ImplCalcSize( pThis, nTempLines, TB_CALCMODE_FLOAT ).Height();
936         pThis->mpFloatSizeAry->mnLastEntry = i;
937         pThis->mpFloatSizeAry->mpSize[i].mnHeight = nHeight;
938         pThis->mpFloatSizeAry->mpSize[i].mnLines  = nTempLines;
939         pThis->mpFloatSizeAry->mpSize[i].mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET1*2);
940         nLines--;
941         if ( nLines )
942         {
943             do
944             {
945                 nCalcSize += pThis->mnMaxItemWidth;
946                 nTempLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, sal_True );
947             }
948             while ( (nCalcSize < upperBoundWidth) && (nLines < nTempLines) && (nTempLines != 1) );
949             if ( nTempLines < nLines )
950                 nLines = nTempLines;
951         }
952         i++;
953     }
954 }
955 
956 // -----------------------------------------------------------------------
957 
958 Size ToolBox::ImplCalcFloatSize( ToolBox* pThis, sal_uInt16& rLines )
959 {
960     ImplCalcFloatSizes( pThis );
961 
962     if ( !rLines )
963     {
964         rLines = pThis->mnFloatLines;
965         if ( !rLines )
966             rLines = pThis->mnLines;
967     }
968 
969     sal_uInt16 i = 0;
970     while ( i < pThis->mpFloatSizeAry->mnLastEntry &&
971         rLines < pThis->mpFloatSizeAry->mpSize[i].mnLines )
972         i++;
973 
974     Size aSize( pThis->mpFloatSizeAry->mpSize[i].mnWidth,
975                 pThis->mpFloatSizeAry->mpSize[i].mnHeight );
976     rLines = pThis->mpFloatSizeAry->mpSize[i].mnLines;
977     if ( pThis->maNextToolBoxStr.Len() && pThis->mbScroll )
978         aSize.Width() += TB_NEXT_SIZE-TB_NEXT_OFFSET;
979     return aSize;
980 }
981 
982 // -----------------------------------------------------------------------
983 
984 void ToolBox::ImplCalcMinMaxFloatSize( ToolBox* pThis, Size& rMinSize, Size& rMaxSize )
985 {
986     ImplCalcFloatSizes( pThis );
987 
988     sal_uInt16 i = 0;
989     rMinSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
990     rMaxSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
991     while ( ++i <= pThis->mpFloatSizeAry->mnLastEntry )
992     {
993         if( pThis->mpFloatSizeAry->mpSize[i].mnWidth < rMinSize.Width() )
994             rMinSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
995         if( pThis->mpFloatSizeAry->mpSize[i].mnHeight < rMinSize.Height() )
996             rMinSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
997 
998         if( pThis->mpFloatSizeAry->mpSize[i].mnWidth > rMaxSize.Width() )
999             rMaxSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
1000         if( pThis->mpFloatSizeAry->mpSize[i].mnHeight > rMaxSize.Height() )
1001             rMaxSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
1002     }
1003 }
1004 
1005 void ToolBox::ImplSetMinMaxFloatSize( ToolBox *pThis )
1006 {
1007     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
1008     Size aMinSize, aMaxSize;
1009     ImplCalcMinMaxFloatSize( pThis, aMinSize, aMaxSize );
1010     if( pWrapper )
1011     {
1012         pWrapper->SetMinOutputSizePixel( aMinSize );
1013         pWrapper->SetMaxOutputSizePixel( aMaxSize );
1014         pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) ? sal_True : sal_False );
1015     }
1016     else
1017     {
1018         // TODO: change SetMinOutputSizePixel to be not inline
1019         pThis->SetMinOutputSizePixel( aMinSize );
1020         pThis->SetMaxOutputSizePixel( aMaxSize );
1021     }
1022 }
1023 
1024 // -----------------------------------------------------------------------
1025 
1026 
1027 sal_uInt16 ToolBox::ImplCalcLines( ToolBox* pThis, long nToolSize )
1028 {
1029     long nLineHeight;
1030 
1031     if ( pThis->mbHorz )
1032     {
1033         if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
1034             nLineHeight = pThis->mnWinHeight;
1035         else
1036             nLineHeight = pThis->mnMaxItemHeight;
1037     }
1038     else
1039         nLineHeight = pThis->mnMaxItemWidth;
1040 
1041     if ( pThis->mnWinStyle & WB_BORDER )
1042         nToolSize -= TB_BORDER_OFFSET2*2;
1043 
1044     if ( pThis->mnWinStyle & WB_LINESPACING )
1045     {
1046         nLineHeight += TB_LINESPACING;
1047         nToolSize += TB_LINESPACING;
1048     }
1049 
1050     // #i91917# always report at least one line
1051     long nLines = nToolSize/nLineHeight;
1052     if( nLines < 1 )
1053         nLines = 1;
1054 
1055     return static_cast<sal_uInt16>(nLines);
1056 }
1057 
1058 // -----------------------------------------------------------------------
1059 
1060 sal_uInt16 ToolBox::ImplTestLineSize( ToolBox* pThis, const Point& rPos )
1061 {
1062     if ( !pThis->ImplIsFloatingMode() &&
1063          (!pThis->mbScroll || (pThis->mnLines > 1) || (pThis->mnCurLines > pThis->mnVisLines)) )
1064     {
1065         WindowAlign eAlign = pThis->GetAlign();
1066 
1067         if ( eAlign == WINDOWALIGN_LEFT )
1068         {
1069             if ( rPos.X() > pThis->mnDX-DOCK_LINEOFFSET )
1070                 return DOCK_LINEHSIZE | DOCK_LINERIGHT;
1071         }
1072         else if ( eAlign == WINDOWALIGN_TOP )
1073         {
1074             if ( rPos.Y() > pThis->mnDY-DOCK_LINEOFFSET )
1075                 return DOCK_LINEVSIZE | DOCK_LINEBOTTOM;
1076         }
1077         else if ( eAlign == WINDOWALIGN_RIGHT )
1078         {
1079             if ( rPos.X() < DOCK_LINEOFFSET )
1080                 return DOCK_LINEHSIZE | DOCK_LINELEFT;
1081         }
1082         else if ( eAlign == WINDOWALIGN_BOTTOM )
1083         {
1084             if ( rPos.Y() < DOCK_LINEOFFSET )
1085                 return DOCK_LINEVSIZE | DOCK_LINETOP;
1086         }
1087     }
1088 
1089     return 0;
1090 }
1091 
1092 // -----------------------------------------------------------------------
1093 
1094 void ToolBox::ImplLineSizing( ToolBox* pThis, const Point& rPos, Rectangle& rRect,
1095                      sal_uInt16 nLineMode )
1096 {
1097     sal_Bool    mbHorz;
1098     long    nOneLineSize;
1099     long    nCurSize;
1100     long    nMaxSize;
1101     long    nSize;
1102     Size    aSize;
1103 
1104     if ( nLineMode & DOCK_LINERIGHT )
1105     {
1106         nCurSize = rPos.X() - rRect.Left();
1107         mbHorz = sal_False;
1108     }
1109     else if ( nLineMode & DOCK_LINEBOTTOM )
1110     {
1111         nCurSize = rPos.Y() - rRect.Top();
1112         mbHorz = sal_True;
1113     }
1114     else if ( nLineMode & DOCK_LINELEFT )
1115     {
1116         nCurSize = rRect.Right() - rPos.X();
1117         mbHorz = sal_False;
1118     }
1119     else if ( nLineMode & DOCK_LINETOP )
1120     {
1121         nCurSize = rRect.Bottom() - rPos.Y();
1122         mbHorz = sal_True;
1123     }
1124     else {
1125         DBG_ERROR( "ImplLineSizing: Trailing else" );
1126         nCurSize = 0;
1127         mbHorz = sal_False;
1128     }
1129 
1130     Size    aWinSize = pThis->GetSizePixel();
1131     sal_uInt16  nMaxLines = (pThis->mnLines > pThis->mnCurLines) ? pThis->mnLines : pThis->mnCurLines;
1132     if ( nMaxLines > TB_MAXLINES )
1133         nMaxLines = TB_MAXLINES;
1134     if ( mbHorz )
1135     {
1136         nOneLineSize = ImplCalcSize( pThis, 1 ).Height();
1137         nMaxSize = pThis->maOutDockRect.GetHeight() - 20;
1138         if ( nMaxSize < aWinSize.Height() )
1139             nMaxSize = aWinSize.Height();
1140     }
1141     else
1142     {
1143         nOneLineSize = ImplCalcSize( pThis, 1 ).Width();
1144         nMaxSize = pThis->maOutDockRect.GetWidth() - 20;
1145         if ( nMaxSize < aWinSize.Width() )
1146             nMaxSize = aWinSize.Width();
1147     }
1148 
1149     sal_uInt16 i = 1;
1150     if ( nCurSize <= nOneLineSize )
1151         nSize = nOneLineSize;
1152     else
1153     {
1154         nSize = 0;
1155         while ( (nSize < nCurSize) && (i < nMaxLines) )
1156         {
1157             i++;
1158             aSize = ImplCalcSize( pThis, i );
1159             if ( mbHorz )
1160                 nSize = aSize.Height();
1161             else
1162                 nSize = aSize.Width();
1163             if ( nSize > nMaxSize )
1164             {
1165                 i--;
1166                 aSize = ImplCalcSize( pThis, i );
1167                 if ( mbHorz )
1168                     nSize = aSize.Height();
1169                 else
1170                     nSize = aSize.Width();
1171                 break;
1172             }
1173         }
1174     }
1175 
1176     if ( nLineMode & DOCK_LINERIGHT )
1177         rRect.Right() = rRect.Left()+nSize-1;
1178     else if ( nLineMode & DOCK_LINEBOTTOM )
1179         rRect.Bottom() = rRect.Top()+nSize-1;
1180     else if ( nLineMode & DOCK_LINELEFT )
1181         rRect.Left() = rRect.Right()-nSize;
1182     else //if ( nLineMode & DOCK_LINETOP )
1183         rRect.Top() = rRect.Bottom()-nSize;
1184 
1185     pThis->mnDockLines = i;
1186 }
1187 
1188 // -----------------------------------------------------------------------
1189 
1190 sal_uInt16 ToolBox::ImplFindItemPos( ToolBox* pBox, const Point& rPos )
1191 {
1192     sal_uInt16  nPos = 0;
1193     long    nLast = 0;
1194     Point   aPos = rPos;
1195     Size    aSize( pBox->mnDX, pBox->mnDY );
1196 
1197     if ( aPos.X() > aSize.Width()-TB_BORDER_OFFSET1 )
1198         aPos.X() = aSize.Width()-TB_BORDER_OFFSET1;
1199     if ( aPos.Y() > aSize.Height()-TB_BORDER_OFFSET1 )
1200         aPos.Y() = aSize.Height()-TB_BORDER_OFFSET1;
1201 
1202     // Item suchen, das geklickt wurde
1203     std::vector< ImplToolItem >::const_iterator it = pBox->mpData->m_aItems.begin();
1204     while ( it != pBox->mpData->m_aItems.end() )
1205     {
1206         if ( it->mbVisible )
1207         {
1208             if ( nLast || !it->maRect.IsEmpty() )
1209             {
1210                 if ( pBox->mbHorz )
1211                 {
1212                     if ( nLast &&
1213                          ((nLast < it->maRect.Top()) || it->maRect.IsEmpty()) )
1214                         return nPos;
1215 
1216                     if ( aPos.Y() <= it->maRect.Bottom() )
1217                     {
1218                         if ( aPos.X() < it->maRect.Left() )
1219                             return nPos;
1220                         else if ( aPos.X() < it->maRect.Right() )
1221                             return nPos+1;
1222                         else if ( !nLast )
1223                             nLast = it->maRect.Bottom();
1224                     }
1225                 }
1226                 else
1227                 {
1228                     if ( nLast &&
1229                          ((nLast < it->maRect.Left()) || it->maRect.IsEmpty()) )
1230                         return nPos;
1231 
1232                     if ( aPos.X() <= it->maRect.Right() )
1233                     {
1234                         if ( aPos.Y() < it->maRect.Top() )
1235                             return nPos;
1236                         else if ( aPos.Y() < it->maRect.Bottom() )
1237                             return nPos+1;
1238                         else if ( !nLast )
1239                             nLast = it->maRect.Right();
1240                     }
1241                 }
1242             }
1243         }
1244 
1245         nPos++;
1246         ++it;
1247     }
1248 
1249     return nPos;
1250 }
1251 
1252 // -----------------------------------------------------------------------
1253 
1254 ImplTBDragMgr::ImplTBDragMgr()
1255 {
1256     mpBoxList       = new ImplTBList( 4, 4 );
1257     mnLineMode      = 0;
1258     mnStartLines    = 0;
1259     mbCustomizeMode = sal_False;
1260     mbResizeMode    = sal_False;
1261     mbShowDragRect  = sal_False;
1262     mpDragBox       = NULL;
1263 
1264     maAccel.InsertItem( KEY_RETURN, KeyCode( KEY_RETURN ) );
1265     maAccel.InsertItem( KEY_ESCAPE, KeyCode( KEY_ESCAPE ) );
1266     maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl ) );
1267 }
1268 
1269 // -----------------------------------------------------------------------
1270 
1271 ImplTBDragMgr::~ImplTBDragMgr()
1272 {
1273     delete mpBoxList;
1274 }
1275 
1276 // -----------------------------------------------------------------------
1277 
1278 ToolBox* ImplTBDragMgr::FindToolBox( const Rectangle& rRect )
1279 {
1280     ToolBox* pBox = mpBoxList->First();
1281     while ( pBox )
1282     {
1283         /*
1284          *  FIXME: since we can have multiple frames now we cannot
1285          *  find the drag target by its position alone.
1286          *  As long as the toolbar config dialogue is not a system window
1287          *  this works in one frame only anyway. If the dialogue
1288          *  changes to a system window, we need a new implementation here
1289          */
1290         if ( pBox->IsReallyVisible() && pBox->ImplGetWindowImpl()->mpFrame == mpDragBox->ImplGetWindowImpl()->mpFrame )
1291         {
1292             if ( !pBox->ImplIsFloatingMode() )
1293             {
1294                 Point aPos = pBox->GetPosPixel();
1295                 aPos = pBox->GetParent()->OutputToScreenPixel( aPos );
1296                 Rectangle aTempRect( aPos, pBox->GetSizePixel() );
1297                 if ( aTempRect.IsOver( rRect ) )
1298                     return pBox;
1299             }
1300         }
1301 
1302         pBox = mpBoxList->Next();
1303     }
1304 
1305     return pBox;
1306 }
1307 
1308 // -----------------------------------------------------------------------
1309 
1310 void ImplTBDragMgr::StartDragging( ToolBox* pToolBox,
1311                                    const Point& rPos, const Rectangle& rRect,
1312                                    sal_uInt16 nDragLineMode, sal_Bool bResizeItem,
1313                                    void* pData )
1314 {
1315     mpDragBox = pToolBox;
1316     pToolBox->CaptureMouse();
1317     pToolBox->mbDragging = sal_True;
1318     Application::InsertAccel( &maAccel );
1319 
1320     if ( nDragLineMode )
1321     {
1322         mnLineMode = nDragLineMode;
1323         mnStartLines = pToolBox->mnDockLines;
1324     }
1325     else
1326     {
1327         mpCustomizeData = pData;
1328         mbResizeMode = bResizeItem;
1329         pToolBox->Activate();
1330         pToolBox->mnCurItemId = pToolBox->mnConfigItem;
1331         pToolBox->Highlight();
1332         pToolBox->mnCurItemId = 0;
1333         if ( mbResizeMode )
1334         {
1335             if ( rRect.GetWidth() < TB_MIN_WIN_WIDTH )
1336                 mnMinWidth = rRect.GetWidth();
1337             else
1338                 mnMinWidth = TB_MIN_WIN_WIDTH;
1339             mnMaxWidth = pToolBox->GetSizePixel().Width()-rRect.Left()-
1340                          TB_SPIN_SIZE-TB_BORDER_OFFSET1-(TB_SPIN_OFFSET*2);
1341         }
1342     }
1343 
1344     // MouseOffset berechnen
1345     maMouseOff.X() = rRect.Left() - rPos.X();
1346     maMouseOff.Y() = rRect.Top() - rPos.Y();
1347     maRect = rRect;
1348     maStartRect = rRect;
1349     mbShowDragRect = sal_True;
1350     pToolBox->ShowTracking( maRect );
1351 }
1352 
1353 // -----------------------------------------------------------------------
1354 
1355 void ImplTBDragMgr::Dragging( const Point& rPos )
1356 {
1357     if ( mnLineMode )
1358     {
1359         ToolBox::ImplLineSizing( mpDragBox, rPos, maRect, mnLineMode );
1360         Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1361         maRect.Move( aOff.X(), aOff.Y() );
1362         mpDragBox->Docking( rPos, maRect );
1363         maRect.Move( -aOff.X(), -aOff.Y() );
1364         mpDragBox->ShowTracking( maRect );
1365     }
1366     else
1367     {
1368         if ( mbResizeMode )
1369         {
1370             long nXOff = rPos.X()-maStartRect.Left();
1371             nXOff += maMouseOff.X()+(maStartRect.Right()-maStartRect.Left());
1372             if ( nXOff < mnMinWidth )
1373                 nXOff = mnMinWidth;
1374             if ( nXOff > mnMaxWidth )
1375                 nXOff = mnMaxWidth;
1376             maRect.Right() = maStartRect.Left()+nXOff;
1377         }
1378         else
1379         {
1380             maRect.SetPos( rPos );
1381             maRect.Move( maMouseOff.X(), maMouseOff.Y() );
1382         }
1383         mpDragBox->ShowTracking( maRect );
1384     }
1385 }
1386 
1387 // -----------------------------------------------------------------------
1388 
1389 void ImplTBDragMgr::EndDragging( sal_Bool bOK )
1390 {
1391     mpDragBox->HideTracking();
1392     mpDragBox->ReleaseMouse();
1393     mpDragBox->mbDragging = sal_False;
1394     mbShowDragRect = sal_False;
1395     Application::RemoveAccel( &maAccel );
1396 
1397     if ( mnLineMode )
1398     {
1399         if ( !bOK )
1400         {
1401             mpDragBox->mnDockLines = mnStartLines;
1402             mpDragBox->EndDocking( maStartRect, sal_False );
1403         }
1404         else
1405             mpDragBox->EndDocking( maRect, sal_False );
1406         mnLineMode = 0;
1407         mnStartLines = 0;
1408     }
1409     else
1410     {
1411         sal_uInt16 nTempItem = mpDragBox->mnConfigItem;
1412         if ( nTempItem )
1413         {
1414             mpDragBox->mnConfigItem = 0;
1415             if ( !mbResizeMode )
1416                 mpDragBox->Invalidate( mpDragBox->GetItemRect( nTempItem ) );
1417         }
1418 
1419         if ( bOK && (maRect != maStartRect) )
1420         {
1421             if ( mbResizeMode )
1422             {
1423                 ImplToolItem* pItem = mpDragBox->ImplGetItem( nTempItem );
1424                 Size aSize = pItem->mpWindow->GetSizePixel();
1425                 aSize.Width() = maRect.GetWidth();
1426                 pItem->mpWindow->SetSizePixel( aSize );
1427 
1428                 // ToolBox neu brechnen und neu ausgeben
1429                 mpDragBox->ImplInvalidate( sal_True );
1430                 mpDragBox->Customize( ToolBoxCustomizeEvent( mpDragBox, nTempItem,
1431                                                              TOOLBOX_CUSTOMIZE_RESIZE,
1432                                                              mpCustomizeData ) );
1433             }
1434             else
1435             {
1436                 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1437                 Rectangle aScreenRect( maRect );
1438                 aScreenRect.Move( aOff.X(), aOff.Y() );
1439                 ToolBox* pDropBox = FindToolBox( aScreenRect );
1440                 if ( pDropBox )
1441                 {
1442                     // Such-Position bestimmen
1443                     Point aPos;
1444                     if ( pDropBox->mbHorz )
1445                     {
1446                         aPos.X() = aScreenRect.Left()-TB_CUSTOMIZE_OFFSET;
1447                         aPos.Y() = aScreenRect.Center().Y();
1448                     }
1449                     else
1450                     {
1451                         aPos.X() = aScreenRect.Center().X();
1452                         aPos.Y() = aScreenRect.Top()-TB_CUSTOMIZE_OFFSET;
1453                     }
1454 
1455                     aPos = pDropBox->ScreenToOutputPixel( aPos );
1456                     sal_uInt16 nPos = ToolBox::ImplFindItemPos( pDropBox, aPos );
1457                     mpDragBox->Customize( ToolBoxCustomizeEvent( pDropBox, nTempItem,
1458                                                                  nPos, mpCustomizeData ) );
1459                 }
1460                 else
1461                 {
1462                     mpDragBox->Customize( ToolBoxCustomizeEvent( NULL, nTempItem,
1463                                                                  0, mpCustomizeData ) );
1464                 }
1465             }
1466         }
1467         mpCustomizeData = NULL;
1468         mbResizeMode = sal_False;
1469         mpDragBox->Deactivate();
1470     }
1471 
1472     mpDragBox = NULL;
1473 }
1474 
1475 // -----------------------------------------------------------------------
1476 
1477 void ImplTBDragMgr::UpdateDragRect()
1478 {
1479     // Nur Updaten, wenn wir schon im Dragging sind
1480     if ( !mbShowDragRect )
1481         return;
1482 
1483     mpDragBox->ShowTracking( maRect );
1484 }
1485 
1486 // -----------------------------------------------------------------------
1487 
1488 IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator*, pAccel )
1489 {
1490     if ( pAccel->GetCurItemId() == KEY_ESCAPE )
1491         EndDragging( sal_False );
1492     else
1493         EndDragging( sal_True );
1494 
1495     return sal_True;
1496 }
1497 
1498 // -----------------------------------------------------------------------
1499 
1500 void ImplTBDragMgr::StartCustomizeMode()
1501 {
1502     mbCustomizeMode = sal_True;
1503 
1504     ToolBox* pBox = mpBoxList->First();
1505     while ( pBox )
1506     {
1507         pBox->ImplStartCustomizeMode();
1508         pBox = mpBoxList->Next();
1509     }
1510 }
1511 
1512 // -----------------------------------------------------------------------
1513 
1514 void ImplTBDragMgr::EndCustomizeMode()
1515 {
1516     mbCustomizeMode = sal_False;
1517 
1518     ToolBox* pBox = mpBoxList->First();
1519     while ( pBox )
1520     {
1521         pBox->ImplEndCustomizeMode();
1522         pBox = mpBoxList->Next();
1523     }
1524 }
1525 
1526 // -----------------------------------------------------------------------
1527 
1528 
1529 static void ImplDrawOutButton( OutputDevice* pOutDev, const Rectangle& rRect,
1530                                sal_uInt16 nStyle )
1531 {
1532     const StyleSettings&    rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
1533     Color                   aShadowColor = rStyleSettings.GetShadowColor();
1534     Point                   aPos( rRect.TopLeft() );
1535     Size                    aSize( rRect.GetSize() );
1536     long                    nOffset = 0;
1537 
1538     if ( pOutDev->GetBackground().GetColor() == aShadowColor )
1539         aShadowColor = rStyleSettings.GetDarkShadowColor();
1540 
1541     if ( nStyle & BUTTON_DRAW_PRESSED )
1542     {
1543         aPos.X()++;
1544         aPos.Y()++;
1545         nOffset++;
1546     }
1547 
1548     // Hintergrund loeschen
1549     pOutDev->Erase( rRect );
1550 
1551     // Button zeichnen
1552     pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
1553     pOutDev->DrawLine( aPos,
1554                        Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ) );
1555     pOutDev->DrawLine( aPos,
1556                        Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1557     pOutDev->SetLineColor( aShadowColor );
1558     pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ),
1559                        Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1560     pOutDev->DrawLine( Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ),
1561                        Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1562     for ( long i = 0; i < OUTBUTTON_BORDER-1-nOffset; i++ )
1563     {
1564         pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+OUTBUTTON_BORDER ),
1565                            Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+aSize.Height()-1 ) );
1566         pOutDev->DrawLine( Point( aPos.X()+OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ),
1567                            Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) )  );
1568     }
1569 }
1570 
1571 
1572 // -----------------------------------------------------------------------
1573 
1574 void ToolBox::ImplInit( Window* pParent, WinBits nStyle )
1575 {
1576 
1577     // Variablen initialisieren
1578     ImplGetWindowImpl()->mbToolBox         = sal_True;
1579     mpBtnDev          = NULL;
1580     mpFloatSizeAry    = NULL;
1581     mpData				= new ImplToolBoxPrivateData;
1582     mpFloatWin        = NULL;
1583     mnDX              = 0;
1584     mnDY              = 0;
1585     mnMaxItemWidth       = 0;
1586     mnMaxItemHeight      = 0;
1587     mnWinHeight       = 0;
1588     mnBorderX         = 0;
1589     mnBorderY         = 0;
1590     mnLeftBorder      = 0;
1591     mnTopBorder       = 0;
1592     mnRightBorder     = 0;
1593     mnBottomBorder    = 0;
1594     mnLastResizeDY    = 0;
1595     mnOutStyle        = TOOLBOX_STYLE_FLAT; // force flat buttons since NWF
1596     mnHighItemId      = 0;
1597     mnCurItemId       = 0;
1598     mnDownItemId      = 0;
1599     mnCurPos          = TOOLBOX_ITEM_NOTFOUND;
1600     mnFocusPos        = TOOLBOX_ITEM_NOTFOUND;	// current position during keyboard access
1601     mnLines           = 1;
1602     mnCurLine         = 1;
1603     mnCurLines        = 1;
1604     mnVisLines        = 1;
1605     mnFloatLines      = 0;
1606     mnConfigItem      = 0;
1607     mnMouseClicks     = 0;
1608     mnMouseModifier   = 0;
1609     mbDrag            = sal_False;
1610     mbSelection       = sal_False;
1611     mbCommandDrag     = sal_False;
1612     mbUpper           = sal_False;
1613     mbLower           = sal_False;
1614     mbNextTool        = sal_False;
1615     mbIn              = sal_False;
1616     mbCalc            = sal_True;
1617     mbFormat          = sal_False;
1618     mbFullPaint       = sal_False;
1619     mbHorz            = sal_True;
1620     mbScroll          = (nStyle & WB_SCROLL) != 0;
1621     mbCustomize       = sal_False;
1622     mbCustomizeMode   = sal_False;
1623     mbDragging        = sal_False;
1624     mbHideStatusText  = sal_False;
1625     mbMenuStrings     = sal_False;
1626     mbIsShift		  = sal_False;
1627     mbIsKeyEvent = sal_False;
1628     mbChangingHighlight = sal_False;
1629     meButtonType      = BUTTON_SYMBOL;
1630     meAlign           = WINDOWALIGN_TOP;
1631     meLastStyle       = POINTER_ARROW;
1632     mnWinStyle        = nStyle;
1633     mnLastFocusItemId          = 0;
1634 	mnKeyModifier	  = 0;
1635     mnActivateCount   = 0;
1636 
1637     maTimer.SetTimeout( 50 );
1638     maTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplUpdateHdl ) );
1639 
1640     // set timeout and handler for dropdown items
1641     mpData->maDropdownTimer.SetTimeout( 250 );
1642     mpData->maDropdownTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplDropdownLongClickHdl ) );
1643 
1644     DockingWindow::ImplInit( pParent, nStyle & ~(WB_BORDER) );
1645 
1646 
1647     // always set WB_TABSTOP for ToolBars !!!  if( mnWinStyle & WB_TABSTOP )
1648     {
1649         // dockingwindow's ImplInit removes some bits, so restore them here
1650         // to allow keyboard handling for toolbars
1651         ImplGetWindowImpl()->mnStyle |= WB_TABSTOP|WB_NODIALOGCONTROL;
1652         ImplGetWindowImpl()->mnStyle &= ~WB_DIALOGCONTROL;
1653     }
1654 
1655     ImplInitSettings( sal_True, sal_True, sal_True );
1656 }
1657 
1658 // -----------------------------------------------------------------------
1659 
1660 void ToolBox::ImplInitSettings( sal_Bool bFont,
1661                                 sal_Bool bForeground, sal_Bool bBackground )
1662 {
1663     mpData->mbNativeButtons = IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
1664 
1665     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1666 
1667     if ( bFont )
1668     {
1669         Font aFont = rStyleSettings.GetToolFont();
1670         if ( IsControlFont() )
1671             aFont.Merge( GetControlFont() );
1672         SetZoomedPointFont( aFont );
1673     }
1674 
1675     if ( bForeground || bFont )
1676     {
1677         Color aColor;
1678         if ( IsControlForeground() )
1679             aColor = GetControlForeground();
1680         else if ( Window::GetStyle() & WB_3DLOOK )
1681             aColor = rStyleSettings.GetButtonTextColor();
1682         else
1683             aColor = rStyleSettings.GetWindowTextColor();
1684         SetTextColor( aColor );
1685         SetTextFillColor();
1686     }
1687 
1688     if ( bBackground )
1689     {
1690         Color aColor;
1691         if ( IsControlBackground() )
1692         {
1693             aColor = GetControlBackground();
1694             SetBackground( aColor );
1695             SetPaintTransparent( sal_False );
1696             SetParentClipMode( 0 );
1697         }
1698         else
1699         {
1700             if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
1701             {
1702                 SetBackground();
1703                 SetPaintTransparent( sal_True );
1704                 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
1705                 mpData->maDisplayBackground = Wallpaper( rStyleSettings.GetFaceColor() );
1706             }
1707             else
1708             {
1709                 if ( Window::GetStyle() & WB_3DLOOK )
1710                     aColor = rStyleSettings.GetFaceColor();
1711                 else
1712                     aColor = rStyleSettings.GetWindowColor();
1713 
1714                 SetBackground( aColor );
1715                 SetPaintTransparent( sal_False );
1716                 SetParentClipMode( 0 );
1717 
1718                 ImplUpdateImageList();
1719             }
1720         }
1721     }
1722 }
1723 
1724 // -----------------------------------------------------------------------
1725 
1726 void ToolBox::ImplLoadRes( const ResId& rResId )
1727 {
1728     ResMgr* pMgr = rResId.GetResMgr();
1729     if( ! pMgr )
1730         return;
1731 
1732     DockingWindow::ImplLoadRes( rResId );
1733 
1734     sal_uLong              nObjMask;
1735 
1736     nObjMask = ReadLongRes();
1737 
1738     if ( nObjMask & RSC_TOOLBOX_BUTTONTYPE )
1739         SetButtonType( (ButtonType)ReadLongRes() );
1740 
1741     if ( nObjMask & RSC_TOOLBOX_ALIGN )
1742         SetAlign( (WindowAlign)ReadLongRes() );
1743 
1744     if ( nObjMask & RSC_TOOLBOX_LINECOUNT )
1745         SetLineCount( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
1746 
1747     if ( nObjMask & RSC_TOOLBOX_CUSTOMIZE )
1748     {
1749         sal_Bool bCust = (sal_Bool)ReadShortRes();
1750         EnableCustomize( bCust );
1751     }
1752 
1753     if ( nObjMask & RSC_TOOLBOX_MENUSTRINGS )
1754     {
1755         sal_Bool bCust = (sal_Bool)ReadShortRes();
1756         EnableMenuStrings( bCust );
1757     }
1758 
1759     if ( nObjMask & RSC_TOOLBOX_FLOATLINES )
1760         SetFloatingLines( ReadShortRes() );
1761 
1762     if ( nObjMask & RSC_TOOLBOX_ITEMIMAGELIST )
1763     {
1764         maImageList = ImageList( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1765         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1766     }
1767 
1768     if ( nObjMask & RSC_TOOLBOX_ITEMLIST )
1769     {
1770         sal_uLong nEle = ReadLongRes();
1771 
1772         // Item hinzufuegen
1773         for ( sal_uLong i = 0; i < nEle; i++ )
1774         {
1775             InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1776             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
1777         }
1778     }
1779 }
1780 
1781 // -----------------------------------------------------------------------
1782 
1783 ToolBox::ToolBox( Window* pParent, WinBits nStyle ) :
1784     DockingWindow( WINDOW_TOOLBOX )
1785 {
1786     ImplInit( pParent, nStyle );
1787 }
1788 
1789 // -----------------------------------------------------------------------
1790 
1791 ToolBox::ToolBox( Window* pParent, const ResId& rResId ) :
1792     DockingWindow( WINDOW_TOOLBOX )
1793 {
1794     RTL_LOGFILE_CONTEXT( aLog, "vcl: ToolBox::ToolBox( Window* pParent, const ResId& rResId )" );
1795 
1796     rResId.SetRT( RSC_TOOLBOX );
1797     WinBits nStyle = ImplInitRes( rResId );
1798     ImplInit( pParent, nStyle );
1799     ImplLoadRes( rResId );
1800 
1801     // Groesse des FloatingWindows berechnen und umschalten, wenn die
1802     // ToolBox initial im FloatingModus ist
1803     if ( ImplIsFloatingMode() )
1804         mbHorz = sal_True;
1805     else
1806         Resize();
1807 
1808     if ( !(nStyle & WB_HIDE) )
1809         Show();
1810 }
1811 
1812 // -----------------------------------------------------------------------
1813 
1814 ToolBox::~ToolBox()
1815 {
1816     // custom menu event still running?
1817     if( mpData->mnEventId )
1818         Application::RemoveUserEvent( mpData->mnEventId );
1819 
1820     // #103005# make sure our activate/deactivate balance is right
1821     while( mnActivateCount > 0 )
1822         Deactivate();
1823 
1824     // Falls noch ein Floating-Window connected ist, dann den
1825     // PopupModus beenden
1826     if ( mpFloatWin )
1827         mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
1828 
1829     // delete private data
1830     delete mpData;
1831 
1832     // FloatSizeAry gegebenenfalls loeschen
1833     if ( mpFloatSizeAry )
1834         delete mpFloatSizeAry;
1835 
1836     // Wenn keine ToolBox-Referenzen mehr auf die Listen bestehen, dann
1837     // Listen mit wegloeschen
1838     ImplSVData* pSVData = ImplGetSVData();
1839     if ( pSVData->maCtrlData.mpTBDragMgr )
1840     {
1841         // Wenn im TBDrag-Manager, dann wieder rausnehmen
1842         if ( mbCustomize )
1843             pSVData->maCtrlData.mpTBDragMgr->Remove( this );
1844 
1845         if ( !pSVData->maCtrlData.mpTBDragMgr->Count() )
1846         {
1847             delete pSVData->maCtrlData.mpTBDragMgr;
1848             pSVData->maCtrlData.mpTBDragMgr = NULL;
1849         }
1850     }
1851 }
1852 
1853 // -----------------------------------------------------------------------
1854 
1855 ImplToolItem* ToolBox::ImplGetItem( sal_uInt16 nItemId ) const
1856 {
1857     std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1858     while ( it != mpData->m_aItems.end() )
1859     {
1860         if ( it->mnId == nItemId )
1861             return &(*it);
1862         ++it;
1863     }
1864 
1865     return NULL;
1866 }
1867 // -----------------------------------------------------------------------
1868 
1869 static void ImplAddButtonBorder( long &rWidth, long& rHeight, sal_uInt16 aOutStyle, sal_Bool bNativeButtons )
1870 {
1871     if ( aOutStyle & TOOLBOX_STYLE_OUTBUTTON )
1872     {
1873         rWidth += OUTBUTTON_SIZE;
1874         rHeight += OUTBUTTON_SIZE;
1875     }
1876     else
1877     {
1878         rWidth += SMALLBUTTON_HSIZE;
1879         rHeight += SMALLBUTTON_VSIZE;
1880     }
1881 
1882     if( bNativeButtons )
1883     {
1884         // give more border space for rounded buttons
1885         rWidth += 2;
1886         rHeight += 4;
1887     }
1888 }
1889 
1890 // -----------------------------------------------------------------------
1891 
1892 sal_Bool ToolBox::ImplCalcItem()
1893 {
1894     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
1895 
1896     // recalc required ?
1897     if ( !mbCalc )
1898         return sal_False;
1899 
1900 	ImplDisableFlatButtons();
1901 
1902     long            nDefWidth;
1903     long            nDefHeight;
1904     long            nMaxWidth = 0;
1905     long            nMaxHeight = 0;
1906     long            nHeight;
1907     long            nMinWidth   = 6;
1908     long            nMinHeight  = 6;
1909     long            nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
1910 
1911     // set defaults if image or text is needed but empty
1912     nDefWidth       = GetDefaultImageSize().Width();
1913     nDefHeight      = GetDefaultImageSize().Height();
1914 
1915     mnWinHeight = 0;
1916     // determine minimum size necessary in NWF
1917     {
1918         Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1919         Rectangle aReg( aRect );
1920         ImplControlValue aVal;
1921         Rectangle aNativeBounds, aNativeContent;
1922         if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
1923         {
1924             if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
1925                                         aReg,
1926                                         CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1927                                         aVal, OUString(),
1928                                         aNativeBounds, aNativeContent ) )
1929             {
1930                 aRect = aNativeBounds;
1931                 if( aRect.GetWidth() > nMinWidth )
1932                     nMinWidth = aRect.GetWidth();
1933                 if( aRect.GetHeight() > nMinHeight )
1934                     nMinHeight = aRect.GetHeight();
1935                 if( nDropDownArrowWidth < nMinWidth )
1936                     nDropDownArrowWidth = nMinWidth;
1937                 if( nMinWidth > mpData->mnMenuButtonWidth )
1938                     mpData->mnMenuButtonWidth = nMinWidth;
1939                 else if( nMinWidth < TB_MENUBUTTON_SIZE )
1940                     mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
1941             }
1942         }
1943 
1944         // also calculate the area for comboboxes, drop down list boxes and spinfields
1945         // as these are often inserted into toolboxes; set mnWinHeight to the
1946         // greater of those values to prevent toolbar flickering (#i103385#)
1947         aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1948         aReg = aRect;
1949         if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
1950                                     aReg,
1951                                     CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1952                                     aVal, OUString(),
1953                                     aNativeBounds, aNativeContent ) )
1954         {
1955             aRect = aNativeBounds;
1956             if( aRect.GetHeight() > mnWinHeight )
1957                 mnWinHeight = aRect.GetHeight();
1958         }
1959         aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1960         aReg = aRect;
1961         if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
1962                                     aReg,
1963                                     CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1964                                     aVal, OUString(),
1965                                     aNativeBounds, aNativeContent ) )
1966         {
1967             aRect = aNativeBounds;
1968             if( aRect.GetHeight() > mnWinHeight )
1969                 mnWinHeight = aRect.GetHeight();
1970         }
1971         aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1972         aReg = aRect;
1973         if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
1974                                     aReg,
1975                                     CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1976                                     aVal, OUString(),
1977                                     aNativeBounds, aNativeContent ) )
1978         {
1979             aRect = aNativeBounds;
1980             if( aRect.GetHeight() > mnWinHeight )
1981                 mnWinHeight = aRect.GetHeight();
1982         }
1983     }
1984 
1985     if ( ! mpData->m_aItems.empty() )
1986     {
1987         std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1988         while ( it != mpData->m_aItems.end() )
1989         {
1990             sal_Bool bImage;
1991             sal_Bool bText;
1992 
1993             it->mbVisibleText = sal_False;  // indicates if text will definitely be drawn, influences dropdown pos
1994 
1995             if ( it->meType == TOOLBOXITEM_BUTTON )
1996             {
1997                 // check if image and/or text exists
1998                 if ( !(it->maImage) )
1999                     bImage = sal_False;
2000                 else
2001                     bImage = sal_True;
2002                 if ( !it->maText.Len() )
2003                     bText = sal_False;
2004                 else
2005                     bText = sal_True;
2006                 ButtonType tmpButtonType = determineButtonType( &(*it), meButtonType ); // default to toolbox setting
2007                 if ( bImage || bText )
2008                 {
2009 
2010                     it->mbEmptyBtn = sal_False;
2011 
2012                     if ( tmpButtonType == BUTTON_SYMBOL )
2013                     {
2014                         // we're drawing images only
2015                         if ( bImage || !bText )
2016                         {
2017                             it->maItemSize = it->maImage.GetSizePixel();
2018                         }
2019                         else
2020                         {
2021                             it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
2022                                                    GetTextHeight() );
2023                             it->mbVisibleText = sal_True;
2024                         }
2025                     }
2026                     else if ( tmpButtonType == BUTTON_TEXT )
2027                     {
2028                         // we're drawing text only
2029                         if ( bText || !bImage )
2030                         {
2031                             it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
2032                                                    GetTextHeight() );
2033                             it->mbVisibleText = sal_True;
2034                         }
2035                         else
2036                         {
2037                             it->maItemSize = it->maImage.GetSizePixel();
2038                         }
2039                     }
2040                     else
2041                     {
2042                         // we're drawing images and text
2043                         it->maItemSize.Width() = bText ? GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET : 0;
2044                         it->maItemSize.Height() = bText ? GetTextHeight() : 0;
2045 
2046                         // leave space between image and text
2047                         if( bText )
2048                             it->maItemSize.Width() += TB_IMAGETEXTOFFSET;
2049 
2050                         // image and text side by side
2051                         it->maItemSize.Width() += it->maImage.GetSizePixel().Width();
2052                         if ( it->maImage.GetSizePixel().Height() > it->maItemSize.Height() )
2053                             it->maItemSize.Height() = it->maImage.GetSizePixel().Height();
2054 
2055                         it->mbVisibleText = bText;
2056                     }
2057                 }
2058                 else
2059                 {   // no image and no text
2060                     it->maItemSize = Size( nDefWidth, nDefHeight );
2061                     it->mbEmptyBtn = sal_True;
2062                 }
2063 
2064                 // Gegebenenfalls die Fensterhoehe mit beruecksichtigen
2065                 if ( it->mpWindow )
2066                 {
2067                     nHeight = it->mpWindow->GetSizePixel().Height();
2068                     if ( nHeight > mnWinHeight )
2069                         mnWinHeight = nHeight;
2070                 }
2071 
2072                 // add in drop down arrow
2073                 if( it->mnBits & TIB_DROPDOWN )
2074                 {
2075                     it->maItemSize.Width() += nDropDownArrowWidth;
2076                     it->mnDropDownArrowWidth = nDropDownArrowWidth;
2077                 }
2078 
2079                 // text items will be rotated in vertical mode
2080                 // -> swap width and height
2081                 if( it->mbVisibleText && !mbHorz )
2082                 {
2083                     long tmp = it->maItemSize.Width();
2084                     it->maItemSize.Width() = it->maItemSize.Height();
2085                     it->maItemSize.Height() = tmp;
2086                 }
2087             }
2088             else if ( it->meType == TOOLBOXITEM_SPACE )
2089             {
2090                 it->maItemSize = Size( nDefWidth, nDefHeight );
2091             }
2092 
2093             if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2094             {
2095                 // add borders
2096                 ImplAddButtonBorder( it->maItemSize.Width(), it->maItemSize.Height(), mnOutStyle, mpData->mbNativeButtons );
2097 
2098                 if( it->meType == TOOLBOXITEM_BUTTON )
2099                 {
2100                     if( it->maItemSize.Width() < nMinWidth )
2101                         it->maItemSize.Width() = nMinWidth;
2102                     if( it->maItemSize.Height() < nMinHeight )
2103                         it->maItemSize.Height() = nMinHeight;
2104                 }
2105 
2106                 // keep track of max item size
2107                 if ( it->maItemSize.Width() > nMaxWidth )
2108                     nMaxWidth = it->maItemSize.Width();
2109                 if ( it->maItemSize.Height() > nMaxHeight )
2110                     nMaxHeight = it->maItemSize.Height();
2111             }
2112 
2113             ++it;
2114         }
2115     }
2116     else
2117     {
2118         nMaxWidth  = nDefWidth;
2119         nMaxHeight = nDefHeight;
2120 
2121         ImplAddButtonBorder( nMaxWidth, nMaxHeight, mnOutStyle, mpData->mbNativeButtons );
2122     }
2123 
2124     if( !ImplIsFloatingMode() && GetToolboxButtonSize() != TOOLBOX_BUTTONSIZE_DONTCARE )
2125     {
2126         // make sure all vertical toolbars have the same width and horizontal have the same height
2127         // this depends on the used button sizes
2128         // as this is used for alignement of multiple toolbars
2129         // it is only required for docked toolbars
2130 
2131         long nFixedWidth = nDefWidth+nDropDownArrowWidth;
2132         long nFixedHeight = nDefHeight;
2133         ImplAddButtonBorder( nFixedWidth, nFixedHeight, mnOutStyle, mpData->mbNativeButtons );
2134 
2135         if( mbHorz )
2136             nMaxHeight = nFixedHeight;
2137         else
2138             nMaxWidth = nFixedWidth;
2139     }
2140 
2141     mbCalc = sal_False;
2142     mbFormat = sal_True;
2143 
2144     // do we have to recalc the sizes ?
2145     if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) )
2146     {
2147         mnMaxItemWidth  = nMaxWidth;
2148         mnMaxItemHeight = nMaxHeight;
2149 
2150         return sal_True;
2151     }
2152     else
2153         return sal_False;
2154 }
2155 
2156 // -----------------------------------------------------------------------
2157 
2158 sal_uInt16 ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, sal_Bool bCalcHorz )
2159 {
2160     sal_uLong           nLineStart = 0;
2161     sal_uLong           nGroupStart = 0;
2162     long            nLineWidth = 0;
2163     long            nCurWidth;
2164     long            nLastGroupLineWidth = 0;
2165     long            nMaxLineWidth = 0;
2166     sal_uInt16          nLines = 1;
2167     sal_Bool            bWindow;
2168     sal_Bool            bBreak = sal_False;
2169     long            nWidthTotal = nWidth;
2170 
2171     // when docked the menubutton will be in the first line
2172     // ->initialize first linewidth with button
2173     if( IsMenuEnabled() && !ImplIsFloatingMode() )
2174         nLineWidth = mpData->maMenubuttonItem.maItemSize.Width();
2175 
2176     std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
2177     while ( it != mpData->m_aItems.end() )
2178     {
2179         it->mbBreak = bBreak;
2180         bBreak = sal_False;
2181 
2182         if ( it->mbVisible )
2183         {
2184             bWindow     = sal_False;
2185             bBreak      = sal_False;
2186             nCurWidth   = 0;
2187 
2188             if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2189             {
2190                 if ( bCalcHorz )
2191                     nCurWidth = it->maItemSize.Width();
2192                 else
2193                     nCurWidth = it->maItemSize.Height();
2194 
2195                 if ( it->mpWindow && bCalcHorz )
2196                 {
2197                     long nWinItemWidth = it->mpWindow->GetSizePixel().Width();
2198                     if ( !mbScroll || (nWinItemWidth <= nWidthTotal) )
2199                     {
2200                         nCurWidth = nWinItemWidth;
2201                         bWindow   = sal_True;
2202                     }
2203                     else
2204                     {
2205                         if ( it->mbEmptyBtn )
2206                         {
2207                             nCurWidth = 0;
2208                         }
2209                     }
2210                 }
2211 
2212                 // check for line break
2213                 if ( (nLineWidth+nCurWidth > nWidthTotal) && mbScroll )
2214                     bBreak = sal_True;
2215             }
2216             else if ( it->meType == TOOLBOXITEM_SEPARATOR )
2217                 nCurWidth = it->mnSepSize;
2218             // treat breaks as separators, except when using old style toolbars (ie. no menu button)
2219             else if ( (it->meType == TOOLBOXITEM_BREAK) && !IsMenuEnabled() )
2220                 bBreak = sal_True;
2221 
2222             if ( bBreak )
2223             {
2224                 nLines++;
2225 
2226                 // Gruppe auseinanderbrechen oder ganze Gruppe umbrechen?
2227                 if ( (it->meType == TOOLBOXITEM_BREAK) ||
2228                      (nLineStart == nGroupStart) )
2229                 {
2230                     if ( nLineWidth > nMaxLineWidth )
2231                         nMaxLineWidth = nLineWidth;
2232 
2233                     nLineWidth = 0;
2234                     nLineStart = it - mpData->m_aItems.begin();
2235                     nGroupStart = nLineStart;
2236                     it->mbBreak = sal_True;
2237                     bBreak = sal_False;
2238                 }
2239                 else
2240                 {
2241                     if ( nLastGroupLineWidth > nMaxLineWidth )
2242                         nMaxLineWidth = nLastGroupLineWidth;
2243 
2244                     // Wenn ganze Gruppe umgebrochen wird, diese auf
2245                     // Zeilenanfang setzen und wieder neu berechnen
2246                     nLineWidth = 0;
2247                     nLineStart = nGroupStart;
2248                     it = mpData->m_aItems.begin() + nGroupStart;
2249                     continue;
2250                 }
2251             }
2252             else
2253             {
2254                 if( ImplIsFloatingMode() || !IsMenuEnabled() ) // no group breaking when being docked single-line
2255                 {
2256                     if ( (it->meType != TOOLBOXITEM_BUTTON) || bWindow )
2257                     {
2258                         // found separator or break
2259                         nLastGroupLineWidth = nLineWidth;
2260                         nGroupStart = it - mpData->m_aItems.begin();
2261                         if ( !bWindow )
2262                             nGroupStart++;
2263                     }
2264                 }
2265             }
2266 
2267             nLineWidth += nCurWidth;
2268         }
2269 
2270         ++it;
2271     }
2272 
2273 
2274     if ( pMaxLineWidth )
2275     {
2276         if ( nLineWidth > nMaxLineWidth )
2277             nMaxLineWidth = nLineWidth;
2278 
2279         if( ImplIsFloatingMode() && !ImplIsInPopupMode() )
2280         {
2281             // leave enough space to display buttons in the decoration
2282             long aMinWidth = 2 * GetSettings().GetStyleSettings().GetFloatTitleHeight();
2283             if( nMaxLineWidth < aMinWidth )
2284                 nMaxLineWidth = aMinWidth;
2285         }
2286 
2287         // Wegen Separatoren kann MaxLineWidth > Width werden, hat aber
2288         // auf die Umbrueche keine Auswirkung
2289         //if ( nMaxLineWidth > nWidth )
2290         //    nMaxLineWidth = nWidth;
2291 
2292         *pMaxLineWidth = nMaxLineWidth;
2293     }
2294 
2295     return nLines;
2296 }
2297 
2298 // -----------------------------------------------------------------------
2299 namespace
2300 {
2301     sal_Bool ImplFollowedByVisibleButton( std::vector< ImplToolItem >::iterator _aSeparator, std::vector< ImplToolItem >::iterator _aEnd )
2302     {
2303         std::vector< ImplToolItem >::iterator aLookup = _aSeparator;
2304         while ( ++aLookup != _aEnd )
2305         {
2306             if ( aLookup->meType == TOOLBOXITEM_SEPARATOR )
2307                 return ImplFollowedByVisibleButton( aLookup, _aEnd );
2308 
2309             if ( ( aLookup->meType == TOOLBOXITEM_BUTTON ) && aLookup->mbVisible )
2310                 return sal_True;
2311         }
2312         return sal_False;
2313     }
2314 }
2315 
2316 
2317 // -----------------------------------------------------------------------
2318 
2319 Size ToolBox::ImplGetOptimalFloatingSize( FloatingSizeMode eMode )
2320 {
2321     if( !ImplIsFloatingMode() )
2322         return Size();
2323 
2324     Size aCurrentSize( mnDX, mnDY );
2325     Size aSize1( aCurrentSize );
2326     Size aSize2( aCurrentSize );
2327 
2328     // try to preserve current height
2329     if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURHEIGHT )
2330     {
2331         // calc number of floating lines for current window height
2332         sal_uInt16 nFloatLinesHeight = ImplCalcLines( this, mnDY );
2333         // calc window size according to this number
2334         aSize1 = ImplCalcFloatSize( this, nFloatLinesHeight );
2335 
2336         if( eMode == FSMODE_FAVOURHEIGHT || aCurrentSize == aSize1 )
2337             return aSize1;
2338     }
2339 
2340     if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURWIDTH )
2341     {
2342         // try to preserve current width
2343         long nLineHeight = ( mnWinHeight > mnMaxItemHeight ) ? mnWinHeight : mnMaxItemHeight;
2344         int nBorderX = 2*TB_BORDER_OFFSET1 + mnLeftBorder + mnRightBorder + 2*mnBorderX;
2345         int nBorderY = 2*TB_BORDER_OFFSET2 + mnTopBorder + mnBottomBorder + 2*mnBorderY;
2346         Size aSz( aCurrentSize );
2347         long maxX;
2348         sal_uInt16 nLines = ImplCalcBreaks( aSz.Width()-nBorderX, &maxX, mbHorz );
2349 
2350         sal_uInt16 manyLines = 1000;
2351         Size aMinimalFloatSize = ImplCalcFloatSize( this, manyLines );
2352 
2353         aSz.Height() = nBorderY + nLineHeight * nLines;
2354         // line space when more than one line
2355         if ( mnWinStyle & WB_LINESPACING )
2356             aSz.Height() += (nLines-1)*TB_LINESPACING;
2357 
2358         aSz.Width() = nBorderX + maxX;
2359 
2360         // avoid clipping of any items
2361         if( aSz.Width() < aMinimalFloatSize.Width() )
2362             aSize2 = ImplCalcFloatSize( this, nLines );
2363         else
2364             aSize2 = aSz;
2365 
2366         if( eMode == FSMODE_FAVOURWIDTH || aCurrentSize == aSize2 )
2367             return aSize2;
2368         else
2369         {
2370             // set the size with the smallest delta as the current size
2371             long dx1 = abs( mnDX - aSize1.Width() );
2372             long dy1 = abs( mnDY - aSize1.Height() );
2373 
2374             long dx2 = abs( mnDX - aSize2.Width() );
2375             long dy2 = abs( mnDY - aSize2.Height() );
2376 
2377             if( dx1*dy1 < dx2*dy2 )
2378                 aCurrentSize = aSize1;
2379             else
2380                 aCurrentSize = aSize2;
2381         }
2382     }
2383     return aCurrentSize;
2384 }
2385 
2386 
2387 void ToolBox::ImplFormat( sal_Bool bResize )
2388 {
2389     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2390 
2391     // Muss ueberhaupt neu formatiert werden
2392     if ( !mbFormat )
2393         return;
2394 
2395     mpData->ImplClearLayoutData();
2396 
2397     // Positionen/Groessen berechnen
2398     Rectangle       aEmptyRect;
2399     long            nLineSize;
2400     long            nLeft;
2401     long            nRight;
2402     long            nTop;
2403     long            nBottom;
2404     long            nMax;   // width of layoutarea in pixels
2405     long            nX;
2406     long            nY;
2407     sal_uInt16          nFormatLine;
2408     sal_Bool            bMustFullPaint;
2409     sal_Bool            bLastSep;
2410 
2411     std::vector< ImplToolItem >::iterator   it;
2412     std::vector< ImplToolItem >::iterator   temp_it;
2413 
2414     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2415     sal_Bool bIsInPopupMode = ImplIsInPopupMode();
2416 
2417     // FloatSizeAry gegebenenfalls loeschen
2418     if ( mpFloatSizeAry )
2419     {
2420         delete mpFloatSizeAry;
2421         mpFloatSizeAry = NULL;
2422     }
2423 
2424     // compute border sizes
2425     ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder, this );
2426 
2427     // update drag area (where the 'grip' will be placed)
2428     Rectangle aOldDragRect;
2429     if( pWrapper )
2430         aOldDragRect = pWrapper->GetDragArea();
2431     ImplUpdateDragArea( this );
2432 
2433     if ( ImplCalcItem() )
2434         bMustFullPaint = sal_True;
2435     else
2436         bMustFullPaint = sal_False;
2437 
2438 
2439     // calculate new size during interactive resize or
2440     // set computed size when formatting only
2441     if ( ImplIsFloatingMode() )
2442     {
2443         if ( bResize )
2444             mnFloatLines = ImplCalcLines( this, mnDY );
2445         else
2446             SetOutputSizePixel( ImplGetOptimalFloatingSize( FSMODE_AUTO ) );
2447     }
2448 
2449     // Horizontal
2450     if ( mbHorz )
2451     {
2452         // nLineSize: height of a single line, will fit highest item
2453         nLineSize = mnMaxItemHeight;
2454 
2455         if ( mnWinHeight > mnMaxItemHeight )
2456             nLineSize = mnWinHeight;
2457 
2458         if ( mbScroll )
2459         {
2460             nMax        = mnDX;
2461             mnVisLines  = ImplCalcLines( this, mnDY );
2462         }
2463         else
2464         {
2465             // layout over all lines
2466             mnVisLines  = mnLines;
2467             nMax        = TB_MAXNOSCROLL;
2468         }
2469 
2470         // add in all border offsets
2471         // inner border as well as custom border (mnBorderX, mnBorderY)
2472         if ( mnWinStyle & WB_BORDER )
2473         {
2474             nLeft       = TB_BORDER_OFFSET1 + mnLeftBorder;
2475             nTop        = TB_BORDER_OFFSET2 + mnTopBorder;
2476             nBottom     = TB_BORDER_OFFSET1 + mnBottomBorder;
2477             nMax       -= nLeft + TB_BORDER_OFFSET1 + mnRightBorder;
2478         }
2479         else
2480         {
2481             nLeft       = 0;
2482             nTop        = 0;
2483             nBottom     = 0;
2484         }
2485 
2486         nLeft += mnBorderX;
2487         nTop  += mnBorderY;
2488         nBottom += mnBorderY;
2489         nMax  -= mnBorderX*2;
2490 
2491         // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2492         // we have to center all items in the window height
2493         if( IsMenuEnabled() && !ImplIsFloatingMode() )
2494         {
2495             long  nWinHeight = mnDY - nTop - nBottom;
2496             if( nWinHeight > nLineSize )
2497                 nLineSize = nWinHeight;
2498         }
2499     }
2500     else
2501     {
2502         nLineSize = mnMaxItemWidth;
2503 
2504         if ( mbScroll )
2505         {
2506             mnVisLines  = ImplCalcLines( this, mnDX );
2507             nMax        = mnDY;
2508         }
2509         else
2510         {
2511             mnVisLines  = mnLines;
2512             nMax        = TB_MAXNOSCROLL;
2513         }
2514 
2515         if ( mnWinStyle & WB_BORDER )
2516         {
2517             nTop        = TB_BORDER_OFFSET1 + mnTopBorder;
2518             nLeft       = TB_BORDER_OFFSET2 + mnLeftBorder;
2519             nRight      = TB_BORDER_OFFSET2 + mnRightBorder;
2520             nMax       -= nTop + TB_BORDER_OFFSET1 + mnBottomBorder;
2521         }
2522         else
2523         {
2524             nLeft       = 0;
2525             nTop        = 0;
2526             nRight      = 0;
2527         }
2528 
2529         nLeft += mnBorderX;
2530         nRight+= mnBorderX;
2531         nTop  += mnBorderY;
2532         nMax  -= mnBorderY*2;
2533 
2534         // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2535         // we have to center all items in the window height
2536         if( !ImplIsFloatingMode() && IsMenuEnabled() )
2537         {
2538             long  nWinWidth = mnDX - nLeft - nRight;
2539             if( nWinWidth > nLineSize )
2540                 nLineSize = nWinWidth;
2541         }
2542     }
2543 
2544     // no calculation if the window has no size (nMax=0)
2545     // non scrolling toolboxes must be computed though
2546     if ( (nMax <= 0) && mbScroll )
2547     {
2548         mnVisLines   = 1;
2549         mnCurLine    = 1;
2550         mnCurLines   = 1;
2551 
2552         it = mpData->m_aItems.begin();
2553         while ( it != mpData->m_aItems.end() )
2554         {
2555             it->maRect = aEmptyRect;
2556 
2557             // For items not visible, release resources only needed during
2558             // painting the items (on Win98, for example, these are system-wide
2559             // resources that are easily exhausted, so be nice):
2560 
2561 			/* !!!
2562 				it->maImage.ClearCaches();
2563             	it->maHighImage.ClearCaches();
2564 			*/
2565 
2566             ++it;
2567         }
2568 
2569         maLowerRect = aEmptyRect;
2570         maUpperRect = aEmptyRect;
2571         maNextToolRect = aEmptyRect;
2572     }
2573     else
2574     {
2575         // init start values
2576         nX          = nLeft;    // top-left offset
2577         nY          = nTop;
2578         nFormatLine = 1;
2579         bLastSep    = sal_True;
2580 
2581         // save old scroll rectangles and reset them
2582         Rectangle aOldLowerRect = maLowerRect;
2583         Rectangle aOldUpperRect = maUpperRect;
2584         Rectangle aOldNextToolRect = maNextToolRect;
2585         Rectangle aOldMenubuttonRect = mpData->maMenubuttonItem.maRect;
2586         maUpperRect = aEmptyRect;
2587         maLowerRect = aEmptyRect;
2588         maNextToolRect = aEmptyRect;
2589         mpData->maMenubuttonItem.maRect = aEmptyRect;
2590 
2591         // additional toolboxes require a toggle button (maNextToolRect)
2592         if ( maNextToolBoxStr.Len() && mbScroll )
2593         {
2594             nMax -= TB_NEXT_SIZE-TB_NEXT_OFFSET;
2595             if ( mbHorz )
2596             {
2597                 maNextToolRect.Left()    = nLeft+nMax;
2598                 maNextToolRect.Right()   = maNextToolRect.Left()+TB_NEXT_SIZE-1;
2599                 maNextToolRect.Top()     = nTop;
2600                 maNextToolRect.Bottom()  = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2601             }
2602             else
2603             {
2604                 maNextToolRect.Top()     = nTop+nMax;
2605                 maNextToolRect.Bottom()  = maNextToolRect.Top()+TB_NEXT_SIZE-1;
2606                 maNextToolRect.Left()    = nLeft;
2607                 maNextToolRect.Right()   = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2608             }
2609         }
2610 
2611         // do we have any toolbox items at all ?
2612         if ( !mpData->m_aItems.empty() || IsMenuEnabled() )
2613         {
2614             // compute line breaks and visible lines give the current window width (nMax)
2615             // the break indicators will be stored within each item (it->mbBreak)
2616             mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2617 
2618             // check for scrollbar buttons or dropdown menu
2619             // (if a menu is enabled, this will be used to store clipped
2620             //  items and no scroll buttons will appear)
2621             if ( (!ImplIsFloatingMode() && (mnCurLines > mnVisLines) && mbScroll ) ||
2622                 IsMenuEnabled() )
2623             {
2624                 // compute linebreaks again, incorporating scrollbar buttons
2625                 if( !IsMenuEnabled() )
2626                 {
2627                     nMax -= TB_SPIN_SIZE+TB_SPIN_OFFSET;
2628                     mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2629                 }
2630 
2631                 // compute scroll rectangles or menu button
2632                 if ( mbHorz )
2633                 {
2634                     if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2635                     {
2636                         if( !ImplIsFloatingMode() )
2637                         {
2638                             mpData->maMenubuttonItem.maRect.Right() = mnDX - 2;
2639                             mpData->maMenubuttonItem.maRect.Top() = nTop;
2640                             mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2641                         }
2642                         else
2643                         {
2644                             mpData->maMenubuttonItem.maRect.Right() = mnDX - mnRightBorder-mnBorderX-TB_BORDER_OFFSET1-1;
2645                             mpData->maMenubuttonItem.maRect.Top() = nTop;
2646                             mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2647                         }
2648                         mpData->maMenubuttonItem.maRect.Left() = mpData->maMenubuttonItem.maRect.Right() - mpData->mnMenuButtonWidth;
2649                     }
2650                     else
2651                     {
2652                         maUpperRect.Left()   = nLeft+nMax+TB_SPIN_OFFSET;
2653                         maUpperRect.Right()  = maUpperRect.Left()+TB_SPIN_SIZE-1;
2654                         maUpperRect.Top()    = nTop;
2655                         maLowerRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2656                         maLowerRect.Left()   = maUpperRect.Left();
2657                         maLowerRect.Right()  = maUpperRect.Right();
2658                         maUpperRect.Bottom() = maUpperRect.Top() +
2659                                             (maLowerRect.Bottom()-maUpperRect.Top())/2;
2660                         maLowerRect.Top()    = maUpperRect.Bottom();
2661                     }
2662                 }
2663                 else
2664                 {
2665                     if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2666                     {
2667                         if( !ImplIsFloatingMode() )
2668                         {
2669                             mpData->maMenubuttonItem.maRect.Bottom() = mnDY - 2;
2670                             mpData->maMenubuttonItem.maRect.Left() = nLeft;
2671                             mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2672                         }
2673                         else
2674                         {
2675                             mpData->maMenubuttonItem.maRect.Bottom() = mnDY - mnBottomBorder-mnBorderY-TB_BORDER_OFFSET1-1;
2676                             mpData->maMenubuttonItem.maRect.Left() = nLeft;
2677                             mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2678                         }
2679                         mpData->maMenubuttonItem.maRect.Top() = mpData->maMenubuttonItem.maRect.Bottom() - mpData->mnMenuButtonWidth;
2680                     }
2681                     else
2682                     {
2683                         maUpperRect.Top()    = nTop+nMax+TB_SPIN_OFFSET;;
2684                         maUpperRect.Bottom() = maUpperRect.Top()+TB_SPIN_SIZE-1;
2685                         maUpperRect.Left()   = nLeft;
2686                         maLowerRect.Right()  = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2687                         maLowerRect.Top()    = maUpperRect.Top();
2688                         maLowerRect.Bottom() = maUpperRect.Bottom();
2689                         maUpperRect.Right()  = maUpperRect.Left() +
2690                                             (maLowerRect.Right()-maUpperRect.Left())/2;
2691                         maLowerRect.Left()   = maUpperRect.Right();
2692                     }
2693                 }
2694             }
2695 
2696             // no scrolling when there is a "more"-menu
2697             // anything will "fit" in a single line then
2698             if( IsMenuEnabled() )
2699                 mnCurLines = 1;
2700 
2701             // determine the currently visible line
2702             if ( mnVisLines >= mnCurLines )
2703                 mnCurLine = 1;
2704             else if ( mnCurLine+mnVisLines-1 > mnCurLines )
2705                 mnCurLine = mnCurLines - (mnVisLines-1);
2706 
2707             it = mpData->m_aItems.begin();
2708             while ( it != mpData->m_aItems.end() )
2709             {
2710                 // hide double separators
2711                 if ( it->meType == TOOLBOXITEM_SEPARATOR )
2712                 {
2713                     it->mbVisible = sal_False;
2714                     if ( !bLastSep )
2715                     {
2716                         // check if any visible items have to appear behind it
2717                         temp_it = it+1;
2718                         while ( temp_it != mpData->m_aItems.end() )
2719                         {
2720                             if ( (temp_it->meType == TOOLBOXITEM_SEPARATOR) ||
2721                                  ((temp_it->meType == TOOLBOXITEM_BUTTON) &&
2722                                   temp_it->mbVisible) )
2723                             {
2724                                 it->mbVisible = sal_True;
2725                                 break;
2726                             }
2727                             ++temp_it;
2728                         }
2729                     }
2730                     bLastSep = sal_True;
2731                 }
2732                 else if ( it->mbVisible )
2733                     bLastSep = sal_False;
2734 
2735                 it->mbShowWindow = sal_False;
2736 
2737                 // check for line break and advance nX/nY accordingly
2738                 if ( it->mbBreak )
2739                 {
2740                     nFormatLine++;
2741 
2742                     // increment starting with the second line
2743                     if ( nFormatLine > mnCurLine )
2744                     {
2745                         if ( mbHorz )
2746                         {
2747                             nX = nLeft;
2748                             if ( mnWinStyle & WB_LINESPACING )
2749                                 nY += nLineSize+TB_LINESPACING;
2750                             else
2751                                 nY += nLineSize;
2752                         }
2753                         else
2754                         {
2755                             nY = nTop;
2756                             if ( mnWinStyle & WB_LINESPACING )
2757                                 nX += nLineSize+TB_LINESPACING;
2758                             else
2759                                 nX += nLineSize;
2760                         }
2761                     }
2762                 }
2763 
2764                 if ( !it->mbVisible || (nFormatLine < mnCurLine) ||
2765                      (nFormatLine > mnCurLine+mnVisLines-1) )
2766                      // item is not visible
2767                     it->maCalcRect = aEmptyRect;
2768                 else
2769                 {
2770                     // 1. determine current item width/height
2771                     // take window size and orientation into account, because this affects the size of item windows
2772 
2773                     Size aCurrentItemSize( it->GetSize( mbHorz, mbScroll, nMax, Size(mnMaxItemWidth, mnMaxItemHeight) ) );
2774 
2775                     // 2. position item rect and use size from step 1
2776                     //  items will be centered horizontally (if mbHorz) or vertically
2777                     //  advance nX and nY accordingly
2778                     if ( mbHorz )
2779                     {
2780                         it->maCalcRect.Left()     = nX;
2781                         it->maCalcRect.Top()      = nY+(nLineSize-aCurrentItemSize.Height())/2;
2782                         it->maCalcRect.Right()    = nX+aCurrentItemSize.Width()-1;
2783                         it->maCalcRect.Bottom()   = it->maCalcRect.Top()+aCurrentItemSize.Height()-1;
2784                         nX += aCurrentItemSize.Width();
2785                     }
2786                     else
2787                     {
2788                         it->maCalcRect.Left()     = nX+(nLineSize-aCurrentItemSize.Width())/2;
2789                         it->maCalcRect.Top()      = nY;
2790                         it->maCalcRect.Right()    = it->maCalcRect.Left()+aCurrentItemSize.Width()-1;
2791                         it->maCalcRect.Bottom()   = nY+aCurrentItemSize.Height()-1;
2792                         nY += aCurrentItemSize.Height();
2793                     }
2794                 }
2795 
2796                 // position window items into calculated item rect
2797                 if ( it->mpWindow )
2798                 {
2799                     if ( it->mbShowWindow )
2800                     {
2801                         Point aPos( it->maCalcRect.Left(), it->maCalcRect.Top() );
2802                         it->mpWindow->SetPosPixel( aPos );
2803                         if ( !mbCustomizeMode )
2804                             it->mpWindow->Show();
2805                     }
2806                     else
2807                         it->mpWindow->Hide();
2808                 }
2809 
2810                 ++it;
2811             } // end of loop over all items
2812         }
2813         else
2814             // we have no toolbox items
2815             mnCurLines = 1;
2816 
2817 
2818         if( IsMenuEnabled() && ImplIsFloatingMode() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2819         {
2820             // custom menu will be the last button in floating mode
2821             ImplToolItem &rIt = mpData->maMenubuttonItem;
2822 
2823             if ( mbHorz )
2824             {
2825                 rIt.maRect.Left()     = nX+TB_MENUBUTTON_OFFSET;
2826                 rIt.maRect.Top()      = nY;
2827                 rIt.maRect.Right()    = rIt.maRect.Left() + mpData->mnMenuButtonWidth;
2828                 rIt.maRect.Bottom()   = nY+nLineSize-1;
2829                 nX += rIt.maItemSize.Width();
2830             }
2831             else
2832             {
2833                 rIt.maRect.Left()     = nX;
2834                 rIt.maRect.Top()      = nY+TB_MENUBUTTON_OFFSET;
2835                 rIt.maRect.Right()    = nX+nLineSize-1;
2836                 rIt.maRect.Bottom()   = rIt.maRect.Top() + mpData->mnMenuButtonWidth;
2837                 nY += rIt.maItemSize.Height();
2838             }
2839         }
2840 
2841 
2842         // if toolbox visible trigger paint for changed regions
2843         if ( IsVisible() && !mbFullPaint )
2844         {
2845             if ( bMustFullPaint )
2846             {
2847                 maPaintRect = Rectangle( mnLeftBorder, mnTopBorder,
2848                                          mnDX-mnRightBorder, mnDY-mnBottomBorder );
2849             }
2850             else
2851             {
2852                 if ( aOldLowerRect != maLowerRect )
2853                 {
2854                     maPaintRect.Union( maLowerRect );
2855                     maPaintRect.Union( aOldLowerRect );
2856                 }
2857                 if ( aOldUpperRect != maUpperRect )
2858                 {
2859                     maPaintRect.Union( maUpperRect );
2860                     maPaintRect.Union( aOldUpperRect );
2861                 }
2862                 if ( aOldNextToolRect != maNextToolRect )
2863                 {
2864                     maPaintRect.Union( maNextToolRect );
2865                     maPaintRect.Union( aOldNextToolRect );
2866                 }
2867                 if ( aOldMenubuttonRect != mpData->maMenubuttonItem.maRect )
2868                 {
2869                     maPaintRect.Union( mpData->maMenubuttonItem.maRect );
2870                     maPaintRect.Union( aOldMenubuttonRect );
2871                 }
2872                 if ( pWrapper && aOldDragRect != pWrapper->GetDragArea() )
2873                 {
2874                     maPaintRect.Union( pWrapper->GetDragArea() );
2875                     maPaintRect.Union( aOldDragRect );
2876                 }
2877 
2878                 it = mpData->m_aItems.begin();
2879                 while ( it != mpData->m_aItems.end() )
2880                 {
2881                     if ( it->maRect != it->maCalcRect )
2882                     {
2883                         maPaintRect.Union( it->maRect );
2884                         maPaintRect.Union( it->maCalcRect );
2885                     }
2886                     ++it;
2887                 }
2888             }
2889 
2890             Invalidate( maPaintRect );
2891         }
2892 
2893         // store the new calculated item rects
2894         maPaintRect = aEmptyRect;
2895         Rectangle aVisibleRect(Point(0, 0), GetOutputSizePixel());
2896         it = mpData->m_aItems.begin();
2897         while ( it != mpData->m_aItems.end() )
2898         {
2899             it->maRect = it->maCalcRect;
2900             if (!it->maRect.IsOver(aVisibleRect))
2901             {
2902                 // For items not visible, release resources only needed during
2903                 // painting the items (on Win98, for example, these are system-
2904                 // wide resources that are easily exhausted, so be nice):
2905 
2906 				/* !!!
2907 				it->maImage.ClearCaches();
2908                 it->maHighImage.ClearCaches();
2909 				*/
2910             }
2911             ++it;
2912         }
2913     }
2914 
2915     // indicate formatting is done
2916     mbFormat = sal_False;
2917 }
2918 
2919 // -----------------------------------------------------------------------
2920 
2921 IMPL_LINK( ToolBox, ImplDropdownLongClickHdl, ToolBox*, EMPTYARG )
2922 {
2923     if( mnCurPos != TOOLBOX_ITEM_NOTFOUND &&
2924         (mpData->m_aItems[ mnCurPos ].mnBits & TIB_DROPDOWN)
2925         )
2926     {
2927         mpData->mbDropDownByKeyboard = sal_False;
2928         GetDropdownClickHdl().Call( this );
2929 
2930         // do not reset data if the dropdown handler opened a floating window
2931         // see ImplFloatControl()
2932         if( mpFloatWin == NULL )
2933         {
2934             // no floater was opened
2935             Deactivate();
2936             ImplDrawItem( mnCurPos, sal_False );
2937 
2938             mnCurPos         = TOOLBOX_ITEM_NOTFOUND;
2939             mnCurItemId      = 0;
2940             mnDownItemId     = 0;
2941             mnMouseClicks    = 0;
2942             mnMouseModifier  = 0;
2943             mnHighItemId     = 0;
2944         }
2945     }
2946 
2947     return 0;
2948 }
2949 
2950 // -----------------------------------------------------------------------
2951 
2952 IMPL_LINK( ToolBox, ImplUpdateHdl, void*, EMPTYARG )
2953 {
2954     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2955 
2956     if( mbFormat )
2957         ImplFormat();
2958 
2959     return 0;
2960 }
2961 
2962 // -----------------------------------------------------------------------
2963 
2964 static void ImplDrawMoreIndicator( ToolBox *pBox, const Rectangle& rRect, sal_Bool bSetColor, sal_Bool bRotate )
2965 {
2966     Color aOldFillColor = pBox->GetFillColor();
2967     Color aOldLineColor = pBox->GetLineColor();
2968     pBox->SetLineColor();
2969 
2970     if ( bSetColor )
2971     {
2972         if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
2973             pBox->SetFillColor( Color( COL_WHITE ) );
2974         else
2975             pBox->SetFillColor( Color( COL_BLACK ) );
2976     }
2977 
2978     if( !bRotate )
2979     {
2980         long width = 8;
2981         long height = 5;
2982         long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
2983         long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
2984         while( height >= 1)
2985         {
2986             pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2987             x+=4;
2988             pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2989             x-=4;
2990             y++;
2991             if( height <= 3) x--;
2992             else            x++;
2993             height--;
2994         }
2995     }
2996     else
2997     {
2998         long width = 5;
2999         long height = 8;
3000         long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
3001         long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
3002         while( width >= 1)
3003         {
3004             pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
3005             y+=4;
3006             pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
3007             y-=4;
3008             x++;
3009             if( width <= 3) y--;
3010             else           y++;
3011             width--;
3012         }
3013     }
3014 
3015     pBox->SetFillColor( aOldFillColor );
3016     pBox->SetLineColor( aOldLineColor );
3017 }
3018 
3019 static void ImplDrawDropdownArrow( ToolBox *pBox, const Rectangle& rDropDownRect, sal_Bool bSetColor, sal_Bool bRotate )
3020 {
3021     sal_Bool bLineColor = pBox->IsLineColor();
3022     sal_Bool bFillColor = pBox->IsFillColor();
3023     Color aOldFillColor = pBox->GetFillColor();
3024     Color aOldLineColor = pBox->GetLineColor();
3025     pBox->SetLineColor();
3026 
3027     if ( bSetColor )
3028     {
3029         if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
3030             pBox->SetFillColor( Color( COL_WHITE ) );
3031         else
3032             pBox->SetFillColor( Color( COL_BLACK ) );
3033     }
3034 
3035     if( !bRotate )
3036     {
3037         long width = 5;
3038         long height = 3;
3039         long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
3040         long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
3041         while( width >= 1)
3042         {
3043             pBox->DrawRect( Rectangle( x, y, x+width-1, y ) );
3044             y++; x++;
3045             width -= 2;
3046         }
3047     }
3048     else
3049     {
3050         long width = 3;
3051         long height = 5;
3052         long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
3053         long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
3054         while( height >= 1)
3055         {
3056             pBox->DrawRect( Rectangle( x, y, x, y+height-1 ) );
3057             y++; x++;
3058             height -= 2;
3059         }
3060     }
3061 
3062     if( bFillColor )
3063         pBox->SetFillColor( aOldFillColor );
3064     else
3065         pBox->SetFillColor();
3066     if( bLineColor )
3067         pBox->SetLineColor( aOldLineColor );
3068     else
3069         pBox->SetLineColor( );
3070 }
3071 
3072 void ToolBox::ImplDrawToolArrow( ToolBox* pBox, long nX, long nY, sal_Bool bBlack, sal_Bool bColTransform,
3073                                  sal_Bool bLeft, sal_Bool bTop, long nSize )
3074 {
3075     Color           aOldFillColor = pBox->GetFillColor();
3076     WindowAlign     eAlign = pBox->meAlign;
3077     long            n = 0;
3078     long            nHalfSize;
3079     if ( bLeft )
3080         eAlign = WINDOWALIGN_RIGHT;
3081     else if ( bTop )
3082         eAlign = WINDOWALIGN_BOTTOM;
3083 
3084     nHalfSize = nSize/2;
3085 
3086     switch ( eAlign )
3087     {
3088         case WINDOWALIGN_LEFT:
3089             if ( bBlack )
3090                 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3091             while ( n <= nHalfSize )
3092             {
3093                 pBox->DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
3094                 n++;
3095             }
3096             if ( bBlack )
3097             {
3098                 pBox->SetFillColor( aOldFillColor );
3099                 n = 1;
3100                 while ( n < nHalfSize )
3101                 {
3102                     pBox->DrawRect( Rectangle( nX+n, nY+1+n, nX+n, nY+nSize-1-n ) );
3103                     n++;
3104                 }
3105             }
3106             break;
3107         case WINDOWALIGN_TOP:
3108             if ( bBlack )
3109                 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3110             while ( n <= nHalfSize )
3111             {
3112                 pBox->DrawRect( Rectangle( nX+n, nY+n, nX+nSize-n, nY+n ) );
3113                 n++;
3114             }
3115             if ( bBlack )
3116             {
3117                 pBox->SetFillColor( aOldFillColor );
3118                 n = 1;
3119                 while ( n < nHalfSize )
3120                 {
3121                     pBox->DrawRect( Rectangle( nX+1+n, nY+n, nX+nSize-1-n, nY+n ) );
3122                     n++;
3123                 }
3124             }
3125             break;
3126         case WINDOWALIGN_RIGHT:
3127             if ( bBlack )
3128                 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3129             while ( n <= nHalfSize )
3130             {
3131                 pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+n, nX+nHalfSize-n, nY+nSize-n ) );
3132                 n++;
3133             }
3134             if ( bBlack )
3135             {
3136                 pBox->SetFillColor( aOldFillColor );
3137                 n = 1;
3138                 while ( n < nHalfSize )
3139                 {
3140                     pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+1+n, nX+nHalfSize-n, nY+nSize-1-n ) );
3141                     n++;
3142                 }
3143             }
3144             break;
3145         case WINDOWALIGN_BOTTOM:
3146             if ( bBlack )
3147                 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3148             while ( n <= nHalfSize )
3149             {
3150                 pBox->DrawRect( Rectangle( nX+n, nY+nHalfSize-n, nX+nSize-n, nY+nHalfSize-n ) );
3151                 n++;
3152             }
3153             if ( bBlack )
3154             {
3155                 pBox->SetFillColor( aOldFillColor );
3156                 n = 1;
3157                 while ( n < nHalfSize )
3158                 {
3159                     pBox->DrawRect( Rectangle( nX+1+n, nY+nHalfSize-n, nX+nSize-1-n, nY+nHalfSize-n ) );
3160                     n++;
3161                 }
3162             }
3163             break;
3164     }
3165 }
3166 
3167 void ToolBox::SetToolArrowClipregion( ToolBox* pBox, long nX, long nY,
3168                                       sal_Bool bLeft, sal_Bool bTop, long nSize )
3169 {
3170     WindowAlign     eAlign = pBox->meAlign;
3171     long            nHalfSize;
3172     if ( bLeft )
3173         eAlign = WINDOWALIGN_RIGHT;
3174     else if ( bTop )
3175         eAlign = WINDOWALIGN_BOTTOM;
3176 
3177     nHalfSize = nSize/2;
3178 
3179     Point p[6];
3180 
3181     switch ( eAlign )
3182     {
3183         case WINDOWALIGN_LEFT:
3184             p[0].X() = nX-1; p[0].Y() = nY-1;
3185             p[1].X() = nX-1; p[1].Y() = nY+nSize+1;
3186             p[2].X() = nX+1; p[2].Y() = nY+nSize+1;
3187             p[3].X() = nX+nHalfSize+1; p[3].Y() = nY+nHalfSize+1;
3188             p[4].X() = nX+nHalfSize+1; p[4].Y() = nY+nHalfSize-1;
3189             p[5].X() = nX+1; p[5].Y() = nY-1;
3190             break;
3191         case WINDOWALIGN_TOP:
3192             p[0].X() = nX-1; p[0].Y() = nY-1;
3193             p[1].X() = nX-1; p[1].Y() = nY+1;
3194             p[2].X() = nX+nHalfSize-1; p[2].Y() = nY+nHalfSize+1;
3195             p[3].X() = nX+nHalfSize+1; p[3].Y() = nY+nHalfSize+1;
3196             p[4].X() = nX+nSize+1; p[4].Y() = nY+1;
3197             p[5].X() = nX+nSize+1; p[5].Y() = nY-1;
3198             break;
3199         case WINDOWALIGN_RIGHT:
3200             p[0].X() = nX+nHalfSize-1; p[0].Y() = nY-1;
3201             p[1].X() = nX-1; p[1].Y() = nY+nHalfSize-1;
3202             p[2].X() = nX-1; p[2].Y() = nY+nHalfSize+1;
3203             p[3].X() = nX+nHalfSize-1; p[3].Y() = nY+nSize+1;
3204             p[4].X() = nX+nHalfSize+1; p[4].Y() = nY+nSize+1;
3205             p[5].X() = nX+nHalfSize+1; p[5].Y() = nY-1;
3206             break;
3207         case WINDOWALIGN_BOTTOM:
3208             p[0].X() = nX-1; p[0].Y() = nY+nHalfSize-1;
3209             p[1].X() = nX-1; p[1].Y() = nY+nHalfSize+1;
3210             p[2].X() = nX+nSize+1; p[2].Y() = nY+nHalfSize+1;
3211             p[3].X() = nX+nSize+1; p[3].Y() = nY+nHalfSize-1;
3212             p[4].X() = nX+nHalfSize+1; p[4].Y() = nY-1;
3213             p[5].X() = nX+nHalfSize-1; p[5].Y() = nY-1;
3214             break;
3215     }
3216     Polygon aPoly(6,p);
3217     Region aRgn( aPoly );
3218     pBox->SetClipRegion( aRgn );
3219 }
3220 
3221 // -----------------------------------------------------------------------
3222 
3223 void ToolBox::ImplDrawMenubutton( ToolBox *pThis, sal_Bool bHighlight )
3224 {
3225     if( !pThis->mpData->maMenubuttonItem.maRect.IsEmpty() )
3226     {
3227         // #i53937# paint menu button only if necessary
3228         if( !(pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) && !pThis->ImplHasClippedItems() )
3229             return;
3230 
3231         // execute pending paint requests
3232         ImplCheckUpdate( pThis );
3233 
3234         sal_Bool bFillColor = pThis->IsFillColor();
3235         sal_Bool bLineColor = pThis->IsLineColor();
3236         Color aOldFillCol = pThis->GetFillColor();
3237         Color aOldLineCol = pThis->GetLineColor();
3238         sal_Bool bNativeButtons = pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
3239 
3240         Rectangle aInnerRect( pThis->mpData->maMenubuttonItem.maRect );
3241         if( pThis->mpData->mnMenuButtonWidth > TB_MENUBUTTON_SIZE )
3242         {
3243             long nDiff = pThis->mpData->mnMenuButtonWidth - TB_MENUBUTTON_SIZE;
3244             long nDiff1 = nDiff/2;
3245             long nDiff2 = nDiff - nDiff1;
3246             if( pThis->IsHorizontal() )
3247             {
3248                 aInnerRect.Left() += nDiff1;
3249                 aInnerRect.Right() -= nDiff2;
3250             }
3251             else
3252             {
3253                 aInnerRect.Top() += nDiff1;
3254                 aInnerRect.Bottom() -= nDiff2;
3255             }
3256         }
3257 
3258         if( pThis->IsHorizontal() )
3259         {
3260             aInnerRect.nLeft+=2;
3261             aInnerRect.nRight-=1;
3262             aInnerRect.nTop+=1;
3263             aInnerRect.nBottom-=1;
3264         }
3265         else
3266         {
3267             aInnerRect.nLeft+=1;
3268             aInnerRect.nRight-=1;
3269             aInnerRect.nTop+=2;
3270             aInnerRect.nBottom-=1;
3271         }
3272 
3273         ImplErase( pThis, bNativeButtons ? pThis->mpData->maMenubuttonItem.maRect : aInnerRect, bHighlight );
3274 
3275         if( bHighlight )
3276         {
3277             if( bNativeButtons )
3278                 ImplDrawButton( pThis, pThis->mpData->maMenubuttonItem.maRect, 2, sal_False, sal_True, sal_False );
3279             else
3280                 pThis->DrawSelectionBackground( aInnerRect, 2, sal_False, sal_False, sal_False );
3281         }
3282         else
3283         {
3284             // improve visibility by using a dark gradient
3285             Gradient g;
3286             g.SetAngle( pThis->mbHorz ? 0 : 900 );
3287             g.SetStyle( GRADIENT_LINEAR );
3288 
3289             g.SetStartColor( pThis->GetSettings().GetStyleSettings().GetFaceColor() );
3290             g.SetEndColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
3291 
3292             pThis->DrawGradient( aInnerRect, g );
3293         }
3294 
3295         Rectangle aRect( aInnerRect );
3296         if( pThis->mbHorz )
3297             aRect.Top() = aRect.Bottom() - aRect.getHeight()/3;
3298         else
3299             aRect.Left() = aRect.Right() - aRect.getWidth()/3;
3300 
3301         if( pThis->mpData->maMenuType & TOOLBOX_MENUTYPE_CUSTOMIZE )
3302             ImplDrawDropdownArrow( pThis, aRect, sal_True, !pThis->mbHorz );
3303 
3304         if( pThis->ImplHasClippedItems() )
3305         {
3306             aRect = aInnerRect;
3307             if( pThis->mbHorz )
3308                 aRect.Bottom() = aRect.Top() + aRect.getHeight()/3;
3309             else
3310                 aRect.Right() = aRect.Left() + aRect.getWidth()/3;
3311 
3312             ImplDrawMoreIndicator( pThis, aRect, sal_True, !pThis->mbHorz );
3313         }
3314 
3315         // store highlight state
3316         pThis->mpData->mbMenubuttonSelected = bHighlight;
3317 
3318         // restore colors
3319         if( bFillColor )
3320             pThis->SetFillColor( aOldFillCol );
3321         else
3322             pThis->SetFillColor();
3323         if( bLineColor )
3324             pThis->SetLineColor( aOldLineCol );
3325         else
3326             pThis->SetLineColor();
3327     }
3328 }
3329 
3330 // -----------------------------------------------------------------------
3331 
3332 void ToolBox::ImplDrawSpin( sal_Bool bUpperIn, sal_Bool bLowerIn )
3333 {
3334     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3335 
3336     sal_Bool    bTmpUpper;
3337     sal_Bool    bTmpLower;
3338 
3339     if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() )
3340         return;
3341 
3342     if ( mnCurLine > 1 )
3343         bTmpUpper = sal_True;
3344     else
3345         bTmpUpper = sal_False;
3346 
3347     if ( mnCurLine+mnVisLines-1 < mnCurLines )
3348         bTmpLower = sal_True;
3349     else
3350         bTmpLower = sal_False;
3351 
3352     if ( !IsEnabled() )
3353     {
3354         bTmpUpper = sal_False;
3355         bTmpLower = sal_False;
3356     }
3357 
3358     ImplDrawSpinButton( this, maUpperRect, maLowerRect,
3359                         bUpperIn, bLowerIn, bTmpUpper, bTmpLower, !mbHorz );
3360 }
3361 
3362 // -----------------------------------------------------------------------
3363 
3364 void ToolBox::ImplDrawNext( sal_Bool bIn )
3365 {
3366     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3367 
3368     if ( maNextToolRect.IsEmpty() )
3369         return;
3370 
3371     DecorationView aDecoView( this );
3372 
3373     // Button malen
3374     long    nX      = SMALLBUTTON_OFF_NORMAL_X;
3375     long    nY      = SMALLBUTTON_OFF_NORMAL_Y;
3376     sal_uInt16  nStyle  = 0;
3377     if ( bIn == 1 )
3378     {
3379         nStyle |= BUTTON_DRAW_PRESSED;
3380         nX = SMALLBUTTON_OFF_PRESSED_X;
3381         nY = SMALLBUTTON_OFF_PRESSED_Y;
3382     }
3383     aDecoView.DrawButton( maNextToolRect, nStyle );
3384 
3385     // Inhalt ausgeben
3386     sal_Bool    bLeft   = sal_False;
3387     sal_Bool    bTop    = sal_False;
3388     if ( mbHorz )
3389     {
3390         bLeft = sal_True;
3391         nX += (maNextToolRect.GetWidth()-6)/2-4;
3392         nY += (maNextToolRect.GetHeight()-6)/2-6;
3393     }
3394     else
3395     {
3396         bTop = sal_True;
3397         nY += (maNextToolRect.GetHeight()-6)/2-4;
3398         nX += (maNextToolRect.GetWidth()-6)/2-6;
3399     }
3400 
3401     nX += maNextToolRect.Left();
3402     nY += maNextToolRect.Top();
3403     SetLineColor();
3404     SetFillColor( COL_LIGHTBLUE );
3405     ImplDrawToolArrow( this, nX, nY, sal_True, sal_False, bLeft, bTop, 10 );
3406 }
3407 
3408 // -----------------------------------------------------------------------
3409 
3410 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bEnabled, sal_Bool bIsWindow )
3411 {
3412     // draws toolbar button background either native or using a coloured selection
3413     // if bIsWindow is sal_True, the corresponding item is a control and only a selection border will be drawn
3414 
3415     sal_Bool bNativeOk = sal_False;
3416     if( !bIsWindow && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
3417     {
3418         ImplControlValue    aControlValue;
3419         ControlState        nState = 0;
3420 
3421         if ( highlight == 1 )   nState |= CTRL_STATE_PRESSED;
3422         if ( highlight == 2 ) 	nState |= CTRL_STATE_ROLLOVER;
3423         if ( bEnabled )         nState |= CTRL_STATE_ENABLED;
3424 
3425         aControlValue.setTristateVal( bChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
3426 
3427 
3428         bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
3429                                               rRect, nState, aControlValue, rtl::OUString() );
3430     }
3431 
3432     if( !bNativeOk )
3433         pThis->DrawSelectionBackground( rRect, bIsWindow ? 3 : highlight, bChecked, sal_True, bIsWindow, 2, NULL, NULL );
3434 }
3435 
3436 void ToolBox::ImplDrawItem( sal_uInt16 nPos, sal_Bool bHighlight, sal_Bool bPaint, sal_Bool bLayout )
3437 {
3438     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3439 
3440     if( nPos >= mpData->m_aItems.size() )
3441         return;
3442 
3443     // execute pending paint requests
3444     ImplCheckUpdate( this );
3445 
3446 	ImplDisableFlatButtons();
3447 
3448     SetFillColor();
3449 
3450     ImplToolItem* pItem = &mpData->m_aItems[nPos];
3451     MetricVector* pVector = bLayout ? &mpData->m_pLayoutData->m_aUnicodeBoundRects : NULL;
3452     String* pDisplayText = bLayout ? &mpData->m_pLayoutData->m_aDisplayText : NULL;
3453 
3454     bHighlight = bHighlight && pItem->mbEnabled;
3455 
3456     // Falls Rechteck ausserhalb des sichbaren Bereichs liegt
3457     if ( pItem->maRect.IsEmpty() )
3458         return;
3459 
3460     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3461 
3462     // no gradient background for items that have a popup open
3463     sal_Bool bHasOpenPopup = (mpFloatWin != NULL) && (mnDownItemId==pItem->mnId);
3464 
3465     sal_Bool bHighContrastWhite = sal_False;
3466     // check the face color as highcontrast indicator
3467     // because the toolbox itself might have a gradient
3468     if( rStyleSettings.GetFaceColor() == Color( COL_WHITE ) )
3469         bHighContrastWhite = sal_True;
3470 
3471     // draw separators in flat style only
3472     if ( !bLayout &&
3473          (mnOutStyle & TOOLBOX_STYLE_FLAT) &&
3474          (pItem->meType == TOOLBOXITEM_SEPARATOR) &&
3475          nPos > 0
3476          )
3477     {
3478         // no separator before or after windows or at breaks
3479         ImplToolItem* pTempItem = &mpData->m_aItems[nPos-1];
3480         if ( pTempItem && !pTempItem->mbShowWindow && nPos < mpData->m_aItems.size()-1 )
3481         {
3482             pTempItem = &mpData->m_aItems[nPos+1];
3483             if ( !pTempItem->mbShowWindow && !pTempItem->mbBreak )
3484             {
3485                 long nCenterPos, nSlim;
3486                 SetLineColor( rStyleSettings.GetSeparatorColor() );
3487                 if ( IsHorizontal() )
3488                 {
3489                     nSlim = (pItem->maRect.Bottom() - pItem->maRect.Top ()) / 4;
3490                     nCenterPos = pItem->maRect.Center().X();
3491                     DrawLine( Point( nCenterPos, pItem->maRect.Top() + nSlim ),
3492                               Point( nCenterPos, pItem->maRect.Bottom() - nSlim ) );
3493                 }
3494                 else
3495                 {
3496                     nSlim = (pItem->maRect.Right() - pItem->maRect.Left ()) / 4;
3497                     nCenterPos = pItem->maRect.Center().Y();
3498                     DrawLine( Point( pItem->maRect.Left() + nSlim, nCenterPos ),
3499                               Point( pItem->maRect.Right() - nSlim, nCenterPos ) );
3500                 }
3501             }
3502         }
3503     }
3504 
3505     // do nothing if item is no button or will be displayed as window
3506     if ( (pItem->meType != TOOLBOXITEM_BUTTON) ||
3507          (pItem->mbShowWindow && !mbCustomizeMode) )
3508         return;
3509 
3510     // we need a TBDragMananger to draw the configuration item
3511     ImplTBDragMgr* pMgr;
3512     if ( pItem->mnId == mnConfigItem )
3513     {
3514         pMgr = ImplGetTBDragMgr();
3515         pMgr->HideDragRect();
3516     }
3517     else
3518         pMgr = NULL;
3519 
3520     // during configuration mode visible windows will be drawn in a special way
3521     if ( mbCustomizeMode && pItem->mbShowWindow )
3522     {
3523         Font    aOldFont = GetFont();
3524         Color   aOldTextColor = GetTextColor();
3525 
3526         SetZoomedPointFont( rStyleSettings.GetAppFont() );
3527         SetLineColor( Color( COL_BLACK ) );
3528         SetFillColor( rStyleSettings.GetFieldColor() );
3529         SetTextColor( rStyleSettings.GetFieldTextColor() );
3530         if( !bLayout )
3531             DrawRect( pItem->maRect );
3532 
3533         Size aSize( GetCtrlTextWidth( pItem->maText ), GetTextHeight() );
3534         Point aPos( pItem->maRect.Left()+2, pItem->maRect.Top() );
3535         aPos.Y() += (pItem->maRect.GetHeight()-aSize.Height())/2;
3536         sal_Bool bClip;
3537         if ( (aSize.Width() > pItem->maRect.GetWidth()-2) ||
3538              (aSize.Height() > pItem->maRect.GetHeight()-2) )
3539         {
3540             bClip = sal_True;
3541             Rectangle aTempRect( pItem->maRect.Left()+1, pItem->maRect.Top()+1,
3542                                  pItem->maRect.Right()-1, pItem->maRect.Bottom()-1 );
3543             Region aTempRegion( aTempRect );
3544             SetClipRegion( aTempRegion );
3545         }
3546         else
3547             bClip = sal_False;
3548         if( bLayout )
3549         {
3550             mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
3551             mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3552             mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3553         }
3554         DrawCtrlText( aPos, pItem->maText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
3555         if ( bClip )
3556             SetClipRegion();
3557         SetFont( aOldFont );
3558         SetTextColor( aOldTextColor );
3559 
3560         // Gegebenenfalls noch Config-Frame zeichnen
3561         if ( pMgr && !bLayout)
3562             pMgr->UpdateDragRect();
3563         return;
3564     }
3565 
3566     // draw button
3567     Size    aBtnSize    = pItem->maRect.GetSize();
3568     if( ImplGetSVData()->maNWFData.mbToolboxDropDownSeparate )
3569     {
3570         // separate button not for dropdown only where the whole button is painted
3571         if ( pItem->mnBits & TIB_DROPDOWN &&
3572             ((pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY) )
3573         {
3574             Rectangle aArrowRect = pItem->GetDropDownRect( mbHorz );
3575             if( aArrowRect.Top() == pItem->maRect.Top() ) // dropdown arrow on right side
3576                 aBtnSize.Width() -= aArrowRect.GetWidth();
3577             else // dropdown arrow on bottom side
3578                 aBtnSize.Height() -= aArrowRect.GetHeight();
3579         }
3580     }
3581     Rectangle aButtonRect( pItem->maRect.TopLeft(), aBtnSize );
3582     long    nOffX       = SMALLBUTTON_OFF_NORMAL_X;
3583     long    nOffY       = SMALLBUTTON_OFF_NORMAL_Y;
3584     long    nImageOffX=0;
3585     long    nImageOffY=0;
3586     long    nTextOffX=0;
3587     long    nTextOffY=0;
3588     sal_uInt16  nStyle      = 0;
3589 
3590     if ( pItem->meState == STATE_CHECK )
3591     {
3592         nStyle |= BUTTON_DRAW_CHECKED;
3593     }
3594     else if ( pItem->meState == STATE_DONTKNOW )
3595     {
3596         nStyle |= BUTTON_DRAW_DONTKNOW;
3597     }
3598     if ( bHighlight == 1 )
3599     {
3600         nStyle |= BUTTON_DRAW_PRESSED;
3601     }
3602 
3603     if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
3604     {
3605         nOffX = OUTBUTTON_OFF_NORMAL_X;
3606         nOffY = OUTBUTTON_OFF_NORMAL_Y;
3607         if ( bHighlight )
3608         {
3609             nOffX++;
3610             nOffY++;
3611         }
3612     }
3613 
3614     if( ! bLayout )
3615     {
3616         if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
3617         {
3618             if ( (pItem->meState != STATE_NOCHECK) || !bPaint )
3619             {
3620                 ImplErase( this, pItem->maRect, bHighlight, bHasOpenPopup );
3621             }
3622         }
3623         else
3624         {
3625             if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
3626                 ImplDrawOutButton( this, aButtonRect, nStyle );
3627             else
3628             {
3629                 DecorationView aDecoView( this );
3630                 aDecoView.DrawButton( aButtonRect, nStyle );
3631             }
3632         }
3633     }
3634 
3635     nOffX += pItem->maRect.Left();
3636     nOffY += pItem->maRect.Top();
3637 
3638     // determine what has to be drawn on the button: image, text or both
3639     sal_Bool bImage;
3640     sal_Bool bText;
3641     ButtonType tmpButtonType = determineButtonType( pItem, meButtonType ); // default to toolbox setting
3642     pItem->DetermineButtonDrawStyle( tmpButtonType, bImage, bText );
3643 
3644     // compute output values
3645     long    nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE;
3646     long    nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE;
3647     Size    aImageSize;
3648     Size    aTxtSize;
3649 
3650     if ( bText )
3651     {
3652         aTxtSize.Width() = GetCtrlTextWidth( pItem->maText );
3653         aTxtSize.Height() = GetTextHeight();
3654     }
3655 
3656     if ( bImage && ! bLayout )
3657     {
3658         const Image* pImage;
3659         if ( bHighlight && (!(pItem->maHighImage)) == sal_False )
3660             pImage = &(pItem->maHighImage);
3661         else
3662             pImage = &(pItem->maImage);
3663 
3664         aImageSize = pImage->GetSizePixel();
3665 
3666         // determine drawing flags
3667         sal_uInt16 nImageStyle = 0;
3668 
3669         if ( !pItem->mbEnabled || !IsEnabled() )
3670             nImageStyle |= IMAGE_DRAW_DISABLE;
3671 
3672         // #i35563# the dontknow state indicates different states at the same time
3673         // which should not be rendered disabled but normal
3674         //if ( pItem->meState == STATE_DONTKNOW )
3675         //    nImageStyle |= IMAGE_DRAW_DISABLE;
3676 
3677         // draw the image
3678         nImageOffX = nOffX;
3679         nImageOffY = nOffY;
3680         if ( (pItem->mnBits & (TIB_LEFT|TIB_DROPDOWN)) || bText )
3681         {
3682             // left align also to leave space for drop down arrow
3683             // and when drawing text+image
3684             // just center in y, except for vertical (ie rotated text)
3685             if( mbHorz || !bText )
3686                 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3687         }
3688         else
3689         {
3690             nImageOffX += (nBtnWidth-aImageSize.Width())/2;
3691             nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3692         }
3693         if ( bHighlight || (pItem->meState == STATE_CHECK) )
3694         {
3695             if( bHasOpenPopup )
3696                 ImplDrawFloatwinBorder( pItem );
3697             else
3698                 ImplDrawButton( this, aButtonRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? sal_True : sal_False );
3699 
3700             if( bHighlight )
3701             {
3702                 if( bHighContrastWhite )
3703                     nImageStyle |= IMAGE_DRAW_COLORTRANSFORM;
3704             }
3705         }
3706         DrawImage( Point( nImageOffX, nImageOffY ), *pImage, nImageStyle );
3707     }
3708 
3709     // draw the text
3710     sal_Bool bRotate = sal_False;
3711     if ( bText )
3712     {
3713         nTextOffX = nOffX;
3714         nTextOffY = nOffY;
3715 
3716         // rotate text when vertically docked
3717         Font aOldFont = GetFont();
3718         if( pItem->mbVisibleText && !ImplIsFloatingMode() &&
3719             ((meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT)) )
3720         {
3721             bRotate = sal_True;
3722 
3723             Font aRotateFont = aOldFont;
3724             /*
3725             if ( meAlign == WINDOWALIGN_LEFT )
3726             {
3727                 aRotateFont.SetOrientation( 900 );
3728                 nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
3729                 nTextOffY += aTxtSize.Width();
3730                 nTextOffY += (nBtnHeight-aTxtSize.Width())/2;
3731             }
3732             else*/
3733             {
3734                 aRotateFont.SetOrientation( 2700 );
3735 
3736                 // center horizontally
3737                 nTextOffX += aTxtSize.Height();
3738                 nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
3739 
3740                 // add in image offset
3741                 if( bImage )
3742                     nTextOffY = nImageOffY + aImageSize.Height() + TB_IMAGETEXTOFFSET;
3743             }
3744 
3745             SetFont( aRotateFont );
3746         }
3747         else
3748         {
3749             // center vertically
3750             nTextOffY += (nBtnHeight-aTxtSize.Height())/2;
3751 
3752             // add in image offset
3753             if( bImage )
3754                 nTextOffX = nImageOffX + aImageSize.Width() + TB_IMAGETEXTOFFSET;
3755             //nTextOffX += TB_TEXTOFFSET/2;
3756         }
3757 
3758         // draw selection only if not already drawn during image output (see above)
3759         if ( !bLayout && !bImage && (bHighlight || (pItem->meState == STATE_CHECK) ) )
3760         {
3761             if( bHasOpenPopup )
3762                 ImplDrawFloatwinBorder( pItem );
3763             else
3764                 ImplDrawButton( this, pItem->maRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? sal_True : sal_False );
3765         }
3766 
3767         sal_uInt16 nTextStyle = 0;
3768         if ( !pItem->mbEnabled )
3769             nTextStyle |= TEXT_DRAW_DISABLE;
3770         if( bLayout )
3771         {
3772             mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
3773             mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3774             mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3775         }
3776         DrawCtrlText( Point( nTextOffX, nTextOffY ), pItem->maText,
3777                       0, STRING_LEN, nTextStyle, pVector, pDisplayText );
3778         if ( bRotate )
3779             SetFont( aOldFont );
3780     }
3781 
3782     if( bLayout )
3783         return;
3784 
3785     // paint optional drop down arrow
3786     if ( pItem->mnBits & TIB_DROPDOWN )
3787     {
3788         Rectangle aDropDownRect( pItem->GetDropDownRect( mbHorz ) );
3789         sal_Bool bSetColor = sal_True;
3790         if ( !pItem->mbEnabled || !IsEnabled() )
3791         {
3792             bSetColor = sal_False;
3793             SetFillColor( rStyleSettings.GetShadowColor() );
3794         }
3795 
3796         // dropdown only will be painted without inner border
3797         if( (pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY )
3798         {
3799             ImplErase( this, aDropDownRect, bHighlight, bHasOpenPopup );
3800 
3801             if( bHighlight || (pItem->meState == STATE_CHECK) )
3802             {
3803                 if( bHasOpenPopup )
3804                     ImplDrawFloatwinBorder( pItem );
3805                 else
3806                     ImplDrawButton( this, aDropDownRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), sal_False );
3807             }
3808         }
3809         ImplDrawDropdownArrow( this, aDropDownRect, bSetColor, bRotate );
3810     }
3811 
3812     // Gegebenenfalls noch Config-Frame zeichnen
3813     if ( pMgr )
3814         pMgr->UpdateDragRect();
3815 }
3816 
3817 // -----------------------------------------------------------------------
3818 
3819 void ToolBox::ImplStartCustomizeMode()
3820 {
3821     mbCustomizeMode = sal_True;
3822 
3823     mpData->ImplClearLayoutData();
3824 
3825     std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3826     while ( it != mpData->m_aItems.end() )
3827     {
3828         if ( it->mbShowWindow )
3829         {
3830             it->mpWindow->Hide();
3831 
3832             if ( !(it->maRect.IsEmpty()) )
3833                 Invalidate( it->maRect );
3834         }
3835 
3836         ++it;
3837     }
3838 }
3839 
3840 void ToolBox::SetCustomizeMode( sal_Bool bSet )
3841 {
3842     if ( bSet )
3843         ImplStartCustomizeMode();
3844     else
3845         ImplEndCustomizeMode();
3846 }
3847 
3848 // -----------------------------------------------------------------------
3849 
3850 void ToolBox::ImplEndCustomizeMode()
3851 {
3852     mbCustomizeMode = sal_False;
3853 
3854     mpData->ImplClearLayoutData();
3855 
3856     std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3857     while ( it != mpData->m_aItems.end() )
3858     {
3859         if ( it->mbShowWindow )
3860         {
3861             if ( !(it->maRect.IsEmpty()) )
3862                 Invalidate( it->maRect );
3863 
3864             it->mpWindow->Show();
3865         }
3866 
3867         ++it;
3868     }
3869 }
3870 
3871 // -----------------------------------------------------------------------
3872 
3873 void ToolBox::ImplDrawFloatwinBorder( ImplToolItem* pItem )
3874 {
3875     if ( !pItem->maRect.IsEmpty() )
3876     {
3877         Rectangle aRect( mpFloatWin->ImplGetItemEdgeClipRect() );
3878         aRect.SetPos( AbsoluteScreenToOutputPixel( aRect.TopLeft() ) );
3879         SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
3880         Point p1, p2;
3881 
3882         p1 = pItem->maRect.TopLeft();
3883         p1.X()++;
3884         p2 = pItem->maRect.TopRight();
3885         p2.X()--;
3886         DrawLine( p1, p2);
3887         p1 = pItem->maRect.BottomLeft();
3888         p1.X()++;
3889         p2 = pItem->maRect.BottomRight();
3890         p2.X()--;
3891         DrawLine( p1, p2);
3892 
3893         p1 = pItem->maRect.TopLeft();
3894         p1.Y()++;
3895         p2 = pItem->maRect.BottomLeft();
3896         p2.Y()--;
3897         DrawLine( p1, p2);
3898         p1 = pItem->maRect.TopRight();
3899         p1.Y()++;
3900         p2 = pItem->maRect.BottomRight();
3901         p2.Y()--;
3902         DrawLine( p1, p2);
3903 
3904         //DrawRect( pItem->maRect );
3905     }
3906 }
3907 
3908 void ToolBox::ImplFloatControl( sal_Bool bStart, FloatingWindow* pFloatWindow )
3909 {
3910     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3911 
3912     if ( bStart )
3913     {
3914         mpFloatWin = pFloatWindow;
3915 
3916         // redraw item, to trigger drawing of a special border
3917         ImplDrawItem( mnCurPos, sal_True );
3918 
3919         mbDrag = sal_False;
3920         EndTracking();
3921         ReleaseMouse();
3922     }
3923     else
3924     {
3925         mpFloatWin = NULL;
3926 
3927         // if focus is still in this toolbox, then the floater was opened by keyboard
3928         // draw current item with highlight and keep old state
3929         sal_Bool bWasKeyboardActivate = mpData->mbDropDownByKeyboard;
3930 
3931 
3932         if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3933             ImplDrawItem( mnCurPos, bWasKeyboardActivate ? 2 : 0 );
3934         Deactivate();
3935 
3936         if( !bWasKeyboardActivate )
3937         {
3938             mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3939             mnCurItemId = 0;
3940             mnHighItemId = 0;
3941         }
3942         mnDownItemId = 0;
3943 
3944     }
3945 }
3946 
3947 // -----------------------------------------------------------------------
3948 
3949 void ToolBox::ShowLine( sal_Bool bNext )
3950 {
3951     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3952 
3953     mbFormat = sal_True;
3954 
3955     if ( mpData->mbPageScroll )
3956     {
3957         sal_uInt16 delta = mnVisLines;
3958         if ( bNext )
3959         {
3960             mnCurLine = mnCurLine + delta;
3961             if ( mnCurLine+mnVisLines-1 > mnCurLines )
3962                 mnCurLine = mnCurLines - mnVisLines+1;
3963         }
3964         else
3965         {
3966             if( mnCurLine >= delta+1 )
3967                 mnCurLine = mnCurLine - delta;
3968             else
3969                 mnCurLine = 1;
3970         }
3971     }
3972     else
3973     {
3974         if ( bNext )
3975             mnCurLine++;
3976         else
3977             mnCurLine--;
3978     }
3979 
3980     ImplFormat();
3981 }
3982 
3983 // -----------------------------------------------------------------------
3984 
3985 sal_Bool ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, sal_Bool bRepeat )
3986 {
3987     Point aMousePos = rMEvt.GetPosPixel();
3988 
3989     // Ist ToolBox aktiv
3990     if ( mbDrag && mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3991     {
3992         // Befindet sich Maus ueber dem Item
3993         ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
3994         if ( pItem->maRect.IsInside( aMousePos ) )
3995         {
3996             if ( !mnCurItemId )
3997             {
3998                 ImplDrawItem( mnCurPos, sal_True );
3999                 mnCurItemId = pItem->mnId;
4000                 Highlight();
4001             }
4002 
4003             if ( (pItem->mnBits & TIB_REPEAT) && bRepeat )
4004                 Select();
4005         }
4006         else
4007         {
4008             if ( mnCurItemId )
4009             {
4010                 ImplDrawItem( mnCurPos );
4011                 mnCurItemId = 0;
4012                 ImplDrawItem( mnCurPos );
4013                 Highlight();
4014             }
4015         }
4016 
4017         return sal_True;
4018     }
4019 
4020     if ( mbUpper )
4021     {
4022         sal_Bool bNewIn = maUpperRect.IsInside( aMousePos );
4023         if ( bNewIn != mbIn )
4024         {
4025             mbIn = bNewIn;
4026             ImplDrawSpin( mbIn, sal_False );
4027         }
4028         return sal_True;
4029     }
4030 
4031     if ( mbLower )
4032     {
4033         sal_Bool bNewIn = maLowerRect.IsInside( aMousePos );
4034         if ( bNewIn != mbIn )
4035         {
4036             mbIn = bNewIn;
4037             ImplDrawSpin( sal_False, mbIn );
4038         }
4039         return sal_True;
4040     }
4041 
4042     if ( mbNextTool )
4043     {
4044         sal_Bool bNewIn = maNextToolRect.IsInside( aMousePos );
4045         if ( bNewIn != mbIn )
4046         {
4047             mbIn = bNewIn;
4048             ImplDrawNext( mbIn );
4049         }
4050         return sal_True;
4051     }
4052 
4053     return sal_False;
4054 }
4055 
4056 // -----------------------------------------------------------------------
4057 
4058 sal_Bool ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, sal_Bool bCancel )
4059 {
4060 	ImplDisableFlatButtons();
4061 
4062     // stop eventual running dropdown timer
4063     if( mnCurPos < mpData->m_aItems.size() &&
4064         (mpData->m_aItems[mnCurPos].mnBits & TIB_DROPDOWN ) )
4065     {
4066         mpData->maDropdownTimer.Stop();
4067     }
4068 
4069     if ( mbDrag || mbSelection )
4070     {
4071         // Hier die MouseDaten setzen, wenn Selection-Modus, da dann kein
4072         // MouseButtonDown-Handler gerufen wird
4073         if ( mbSelection )
4074         {
4075             mnMouseClicks    = rMEvt.GetClicks();
4076             mnMouseModifier  = rMEvt.GetModifier();
4077         }
4078 
4079         Deactivate();
4080 
4081         if ( mbDrag )
4082             mbDrag = sal_False;
4083         else
4084         {
4085             mbSelection = sal_False;
4086             if ( mnCurPos == TOOLBOX_ITEM_NOTFOUND )
4087                 return sal_True;
4088         }
4089 
4090         // Wurde Maus ueber dem Item losgelassen
4091         if( mnCurPos < mpData->m_aItems.size() )
4092         {
4093             ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
4094             if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) )
4095             {
4096                 mnCurItemId = pItem->mnId;
4097                 if ( !bCancel )
4098                 {
4099                     // Gegebenenfalls ein AutoCheck durchfuehren
4100                     if ( pItem->mnBits & TIB_AUTOCHECK )
4101                     {
4102                         if ( pItem->mnBits & TIB_RADIOCHECK )
4103                         {
4104                             if ( pItem->meState != STATE_CHECK )
4105                                 SetItemState( pItem->mnId, STATE_CHECK );
4106                         }
4107                         else
4108                         {
4109                             if ( pItem->meState != STATE_CHECK )
4110                                 pItem->meState = STATE_CHECK;
4111                             else
4112                                 pItem->meState = STATE_NOCHECK;
4113                         }
4114                     }
4115 
4116                     // Select nicht bei Repeat ausloesen, da dies schon im
4117                     // MouseButtonDown ausgeloest wurde
4118                     if ( !(pItem->mnBits & TIB_REPEAT) )
4119                     {
4120                         // Gegen zerstoeren im Select-Handler sichern
4121                         ImplDelData aDelData;
4122                         ImplAddDel( &aDelData );
4123                         Select();
4124                         if ( aDelData.IsDelete() )
4125                             return sal_True;
4126                         ImplRemoveDel( &aDelData );
4127                     }
4128                 }
4129 
4130                 {
4131                     DBG_CHKTHIS( Window, ImplDbgCheckWindow );
4132                 }
4133 
4134                 // Items nicht geloescht, im Select-Handler
4135                 if ( mnCurItemId )
4136                 {
4137                     sal_Bool bHighlight;
4138                     if ( (mnCurItemId == mnHighItemId) && (mnOutStyle & TOOLBOX_STYLE_FLAT) )
4139                         bHighlight = 2;
4140                     else
4141                         bHighlight = sal_False;
4142                     // Get current pos for the case that items are inserted/removed
4143                     // in the toolBox
4144                     mnCurPos = GetItemPos( mnCurItemId );
4145                     if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4146                     {
4147                         ImplDrawItem( mnCurPos, bHighlight );
4148                         Flush();
4149                     }
4150                 }
4151             }
4152         }
4153 
4154         mnCurPos         = TOOLBOX_ITEM_NOTFOUND;
4155         mnCurItemId      = 0;
4156         mnDownItemId     = 0;
4157         mnMouseClicks    = 0;
4158         mnMouseModifier  = 0;
4159         return sal_True;
4160     }
4161     else if ( mbUpper || mbLower )
4162     {
4163         if ( mbIn )
4164             ShowLine( !mbUpper );
4165         mbUpper = sal_False;
4166         mbLower = sal_False;
4167         mbIn    = sal_False;
4168         ImplDrawSpin( sal_False, sal_False );
4169         return sal_True;
4170     }
4171     else if ( mbNextTool )
4172     {
4173         mbNextTool  = sal_False;
4174         mbIn        = sal_False;
4175         ImplDrawNext( sal_False );
4176         NextToolBox();
4177         return sal_True;
4178     }
4179 
4180     return sal_False;
4181 }
4182 
4183 // -----------------------------------------------------------------------
4184 
4185 void ToolBox::MouseMove( const MouseEvent& rMEvt )
4186 {
4187 	// pressing a modifier generates synthetic mouse moves
4188 	// ignore it if keyboard selection is acive
4189 	if( HasFocus() && ( rMEvt.GetMode() & MOUSE_MODIFIERCHANGED ) )
4190 		return;
4191 
4192     if ( ImplHandleMouseMove( rMEvt ) )
4193         return;
4194 
4195 	ImplDisableFlatButtons();
4196 
4197     Point aMousePos = rMEvt.GetPosPixel();
4198 
4199     // only highlight when the focus is not inside a child window of a toolbox
4200     // eg, in a edit control
4201     // and do not hilight when focus is in a different toolbox
4202     sal_Bool bDrawHotSpot = sal_True;
4203     Window *pWin = Application::GetFocusWindow();
4204     if( pWin && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this )
4205         bDrawHotSpot = sal_False;
4206     /*
4207     else
4208         if( pWin && !pWin->ImplGetWindowImpl()->mbToolBox )
4209             while( pWin )
4210             {
4211                 pWin = pWin->GetParent();
4212                 if( pWin && pWin->ImplGetWindowImpl()->mbToolBox )
4213                 {
4214                     bDrawHotSpot = sal_False;
4215                     break;
4216                 }
4217             }
4218             */
4219 
4220     if ( mbSelection && bDrawHotSpot )
4221     {
4222         sal_uInt16  i = 0;
4223         sal_uInt16  nNewPos = TOOLBOX_ITEM_NOTFOUND;
4224 
4225         // Item suchen, das geklickt wurde
4226         std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4227         while ( it != mpData->m_aItems.end() )
4228         {
4229             // Wenn Mausposition in diesem Item vorhanden, kann die
4230             // Suche abgebrochen werden
4231             if ( it->maRect.IsInside( aMousePos ) )
4232             {
4233                 // Wenn es ein Button ist, dann wird er selektiert
4234                 if ( it->meType == TOOLBOXITEM_BUTTON )
4235                 {
4236                     // Wenn er disablet ist, findet keine Aenderung
4237                     // statt
4238                     if ( !it->mbEnabled || it->mbShowWindow )
4239                         nNewPos = mnCurPos;
4240                     else
4241                         nNewPos = i;
4242                 }
4243 
4244                 break;
4245             }
4246 
4247             i++;
4248             ++it;
4249         }
4250 
4251         // was a new entery selected ?
4252 		// don't  change selection if keyboard selection is active and
4253         // mouse leaves the toolbox
4254         if ( nNewPos != mnCurPos && !( HasFocus() && nNewPos == TOOLBOX_ITEM_NOTFOUND ) )
4255         {
4256             if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4257             {
4258                 ImplDrawItem( mnCurPos );
4259                 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( mnCurPos ) );
4260             }
4261 
4262             mnCurPos = nNewPos;
4263             if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4264             {
4265                 mnCurItemId = mnHighItemId = it->mnId;
4266                 ImplDrawItem( mnCurPos, 2 /*sal_True*/ ); // always use shadow effect (2)
4267             }
4268             else
4269                 mnCurItemId = mnHighItemId = 0;
4270 
4271             Highlight();
4272         }
4273         return;
4274     }
4275 
4276     if ( mbDragging )
4277     {
4278         ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4279         pMgr->Dragging( aMousePos );
4280         return;
4281     }
4282 
4283     PointerStyle eStyle = POINTER_ARROW;
4284 
4285     // change mouse cursor over drag area
4286     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
4287     if( pWrapper && pWrapper->GetDragArea().IsInside( rMEvt.GetPosPixel() ) )
4288         eStyle = POINTER_MOVE;
4289 
4290     if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4291     {
4292         if ( rMEvt.GetMode() & MOUSE_SIMPLEMOVE )
4293         {
4294             sal_uInt16 nLinePtr = ImplTestLineSize( this, rMEvt.GetPosPixel() );
4295             if ( nLinePtr & DOCK_LINEHSIZE )
4296             {
4297                 if ( meAlign == WINDOWALIGN_LEFT )
4298                     eStyle = POINTER_WINDOW_ESIZE;
4299                 else
4300                     eStyle = POINTER_WINDOW_WSIZE;
4301             }
4302             else if ( nLinePtr & DOCK_LINEVSIZE )
4303             {
4304                 if ( meAlign == WINDOWALIGN_TOP )
4305                     eStyle = POINTER_WINDOW_SSIZE;
4306                 else
4307                     eStyle = POINTER_WINDOW_NSIZE;
4308             }
4309         }
4310     }
4311 
4312     if ( (eStyle == POINTER_ARROW) && mbCustomizeMode )
4313     {
4314         // Item suchen, das geklickt wurde
4315         std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4316         while ( it != mpData->m_aItems.end() )
4317         {
4318             // Wenn es ein Customize-Window ist, gegebenenfalls den
4319             // Resize-Pointer anzeigen
4320             if ( it->mbShowWindow )
4321             {
4322                 if ( it->maRect.IsInside( aMousePos ) )
4323                 {
4324                     if ( it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X() )
4325                         eStyle = POINTER_HSIZEBAR;
4326                     break;
4327                 }
4328             }
4329 
4330             ++it;
4331         }
4332     }
4333 
4334     if ( bDrawHotSpot && ( ((eStyle == POINTER_ARROW) && (mnOutStyle & TOOLBOX_STYLE_HANDPOINTER)) ||
4335          (mnOutStyle & TOOLBOX_STYLE_FLAT) || !mnOutStyle ) )
4336     {
4337         sal_Bool bClearHigh = sal_True;
4338         if ( !rMEvt.IsLeaveWindow() && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4339         {
4340             std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4341             while ( it != mpData->m_aItems.end() )
4342             {
4343                 if ( it->maRect.IsInside( aMousePos ) )
4344                 {
4345                     if ( (it->meType == TOOLBOXITEM_BUTTON) && it->mbEnabled )
4346                     {
4347                         if ( !mnOutStyle || (mnOutStyle & TOOLBOX_STYLE_FLAT) )
4348                         {
4349                             bClearHigh = sal_False;
4350                             if ( mnHighItemId != it->mnId )
4351                             {
4352                                 sal_uInt16 nTempPos = sal::static_int_cast<sal_uInt16>(it - mpData->m_aItems.begin());
4353                                 if ( mnHighItemId )
4354                                 {
4355                                     ImplHideFocus();
4356                                     sal_uInt16 nPos = GetItemPos( mnHighItemId );
4357                                     ImplDrawItem( nPos );
4358                                     ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
4359                                 }
4360                                 if ( mpData->mbMenubuttonSelected )
4361                                 {
4362                                     // remove highlight from menubutton
4363                                     ImplDrawMenubutton( this, sal_False );
4364                                 }
4365                                 mnHighItemId = it->mnId;
4366                                 ImplDrawItem( nTempPos, 2 );
4367                                 ImplShowFocus();
4368                                 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
4369                             }
4370                         }
4371                         if ( mnOutStyle & TOOLBOX_STYLE_HANDPOINTER )
4372                             eStyle = POINTER_REFHAND;
4373                     }
4374                     break;
4375                 }
4376 
4377                 ++it;
4378             }
4379         }
4380 
4381         // only clear highlight when focus is not in toolbar
4382         sal_Bool bMenuButtonHit = mpData->maMenubuttonItem.maRect.IsInside( aMousePos );
4383         if ( bClearHigh || bMenuButtonHit )
4384         {
4385             if ( !bMenuButtonHit && mpData->mbMenubuttonSelected )
4386             {
4387                 // remove highlight from menubutton
4388                 ImplDrawMenubutton( this, sal_False );
4389             }
4390 
4391             if( mnHighItemId )
4392             {
4393                 sal_uInt16 nClearPos = GetItemPos( mnHighItemId );
4394                 if ( nClearPos != TOOLBOX_ITEM_NOTFOUND )
4395                 {
4396                     ImplDrawItem( nClearPos, (nClearPos == mnCurPos) ? sal_True : sal_False );
4397                     if( nClearPos != mnCurPos )
4398                         ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nClearPos ) );
4399                 }
4400                 ImplHideFocus();
4401                 mnHighItemId = 0;
4402             }
4403 
4404             if( bMenuButtonHit )
4405             {
4406                 ImplDrawMenubutton( this, sal_True );
4407             }
4408         }
4409     }
4410 
4411     if ( meLastStyle != eStyle )
4412     {
4413         meLastStyle = eStyle;
4414         Pointer aPtr( eStyle );
4415         SetPointer( aPtr );
4416     }
4417 
4418     DockingWindow::MouseMove( rMEvt );
4419 }
4420 
4421 // -----------------------------------------------------------------------
4422 
4423 void ToolBox::MouseButtonDown( const MouseEvent& rMEvt )
4424 {
4425     // Nur bei linker Maustaste ToolBox ausloesen und wenn wir uns nicht
4426     // noch in der normalen Bearbeitung befinden
4427     if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4428     {
4429         // Activate schon hier rufen, da gegebenenfalls noch Items
4430         // ausgetauscht werden
4431         Activate();
4432 
4433         // ToolBox hier updaten, damit der Anwender weiss, was Sache ist
4434         if ( mbFormat )
4435         {
4436             ImplFormat();
4437             Update();
4438         }
4439 
4440         Point  aMousePos = rMEvt.GetPosPixel();
4441         sal_uInt16 i = 0;
4442         sal_uInt16 nNewPos = TOOLBOX_ITEM_NOTFOUND;
4443 
4444         // Item suchen, das geklickt wurde
4445         std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4446         while ( it != mpData->m_aItems.end() )
4447         {
4448             // Ist es dieses Item
4449             if ( it->maRect.IsInside( aMousePos ) )
4450             {
4451                 // Ist es ein Separator oder ist das Item disabled,
4452                 // dann mache nichts
4453                 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
4454                      (!it->mbShowWindow || mbCustomizeMode) )
4455                     nNewPos = i;
4456 
4457                 break;
4458             }
4459 
4460             i++;
4461             ++it;
4462         }
4463 
4464         // Item gefunden
4465         if ( nNewPos != TOOLBOX_ITEM_NOTFOUND )
4466         {
4467             if ( mbCustomize )
4468             {
4469                 if ( rMEvt.IsMod2() || mbCustomizeMode )
4470                 {
4471                     Deactivate();
4472 
4473                     ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4474                     Rectangle aItemRect = GetItemRect( it->mnId );
4475                     mnConfigItem = it->mnId;
4476 
4477                     sal_Bool bResizeItem;
4478                     if ( mbCustomizeMode && it->mbShowWindow &&
4479                          (it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X()) )
4480                         bResizeItem = sal_True;
4481                     else
4482                         bResizeItem = sal_False;
4483                     pMgr->StartDragging( this, aMousePos, aItemRect, 0, bResizeItem );
4484                     return;
4485                 }
4486             }
4487 
4488             if ( !it->mbEnabled )
4489             {
4490                 Deactivate();
4491                 return;
4492             }
4493 
4494 
4495             // Aktuelle Daten setzen
4496             sal_uInt16 nTrackFlags = 0;
4497             mnCurPos         = i;
4498             mnCurItemId      = it->mnId;
4499             mnDownItemId     = mnCurItemId;
4500             mnMouseClicks    = rMEvt.GetClicks();
4501             mnMouseModifier  = rMEvt.GetModifier();
4502             if ( it->mnBits & TIB_REPEAT )
4503                 nTrackFlags |= STARTTRACK_BUTTONREPEAT;
4504 
4505 
4506             if ( mbSelection )
4507             {
4508                 ImplDrawItem( mnCurPos, sal_True );
4509                 Highlight();
4510             }
4511             else
4512             {
4513                 // Hier schon bDrag setzen, da in EndSelection ausgewertet wird
4514                 mbDrag = sal_True;
4515 
4516                 // Bei Doppelklick nur den Handler rufen, aber bevor der
4517                 // Button gehiltet wird, da evt. in diesem Handler der
4518                 // Drag-Vorgang abgebrochen wird
4519                 if ( rMEvt.GetClicks() == 2 )
4520                     DoubleClick();
4521 
4522 
4523                 if ( mbDrag )
4524                 {
4525                     ImplDrawItem( mnCurPos, sal_True );
4526                     Highlight();
4527                 }
4528 
4529                 // was dropdown arrow pressed
4530                 if( (it->mnBits & TIB_DROPDOWN) )
4531                 {
4532                     if( ( (it->mnBits & TIB_DROPDOWNONLY) == TIB_DROPDOWNONLY) || it->GetDropDownRect( mbHorz ).IsInside( aMousePos ))
4533                     {
4534                         // dropdownonly always triggers the dropdown handler, over the whole button area
4535 
4536                         // the drop down arrow should not trigger the item action
4537                         mpData->mbDropDownByKeyboard = sal_False;
4538                         GetDropdownClickHdl().Call( this );
4539 
4540                         // do not reset data if the dropdown handler opened a floating window
4541                         // see ImplFloatControl()
4542                         if( mpFloatWin == NULL )
4543                         {
4544                             // no floater was opened
4545                             Deactivate();
4546                             ImplDrawItem( mnCurPos, sal_False );
4547 
4548                             mnCurPos         = TOOLBOX_ITEM_NOTFOUND;
4549                             mnCurItemId      = 0;
4550                             mnDownItemId     = 0;
4551                             mnMouseClicks    = 0;
4552                             mnMouseModifier  = 0;
4553                             mnHighItemId     = 0;
4554                         }
4555                         return;
4556                     }
4557                     else // activate long click timer
4558                         mpData->maDropdownTimer.Start();
4559                 }
4560 
4561 
4562                 // Click-Handler aufrufen
4563                 if ( rMEvt.GetClicks() != 2 )
4564                     Click();
4565 
4566                 // Bei Repeat auch den Select-Handler rufen
4567                 if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
4568                     Select();
4569 
4570                 // Wenn die Aktion nicht im Click-Handler abgebrochen wurde
4571                 if ( mbDrag )
4572                     StartTracking( nTrackFlags );
4573             }
4574 
4575             // Wenn Maus ueber einem Item gedrueckt wurde, koennen wir
4576             // die Bearbeitung abbrechen
4577             return;
4578         }
4579 
4580         Deactivate();
4581 
4582         // menu button hit ?
4583         if( mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) )
4584         {
4585             ExecuteCustomMenu();
4586             return;
4587         }
4588 
4589 
4590         // Gegebenenfalls noch Scroll- und Next-Buttons ueberpruefen
4591         if ( maUpperRect.IsInside( aMousePos ) )
4592         {
4593             if ( mnCurLine > 1 )
4594             {
4595                 StartTracking();
4596                 mbUpper = sal_True;
4597                 mbIn    = sal_True;
4598                 ImplDrawSpin( sal_True, sal_False );
4599             }
4600             return;
4601         }
4602         if ( maLowerRect.IsInside( aMousePos ) )
4603         {
4604             if ( mnCurLine+mnVisLines-1 < mnCurLines )
4605             {
4606                 StartTracking();
4607                 mbLower = sal_True;
4608                 mbIn    = sal_True;
4609                 ImplDrawSpin( sal_False, sal_True );
4610             }
4611             return;
4612         }
4613         if ( maNextToolRect.IsInside( aMousePos ) )
4614         {
4615             StartTracking();
4616             mbNextTool   = sal_True;
4617             mbIn         = sal_True;
4618             ImplDrawNext( sal_True );
4619             return;
4620         }
4621 
4622         // Linesizing testen
4623         if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4624         {
4625             sal_uInt16 nLineMode = ImplTestLineSize( this, aMousePos );
4626             if ( nLineMode )
4627             {
4628                 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4629 
4630                 // Handler rufen, damit die Dock-Rectangles gesetzt werden
4631                 // koenen
4632                 StartDocking();
4633 
4634                 Point aPos  = GetParent()->OutputToScreenPixel( GetPosPixel() );
4635                 Size  aSize = GetSizePixel();
4636                 aPos = ScreenToOutputPixel( aPos );
4637 
4638                 // Dragging starten
4639                 pMgr->StartDragging( this, aMousePos, Rectangle( aPos, aSize ),
4640                                      nLineMode, sal_False );
4641                 return;
4642             }
4643         }
4644 
4645         // Kein Item, dann nur Click oder DoubleClick
4646         if ( rMEvt.GetClicks() == 2 )
4647             DoubleClick();
4648         else
4649             Click();
4650     }
4651 
4652     if ( !mbDrag && !mbSelection && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4653         DockingWindow::MouseButtonDown( rMEvt );
4654 }
4655 
4656 // -----------------------------------------------------------------------
4657 
4658 void ToolBox::MouseButtonUp( const MouseEvent& rMEvt )
4659 {
4660     if ( ImplHandleMouseButtonUp( rMEvt ) )
4661         return;
4662 
4663     if ( mbDragging && (rMEvt.IsLeft() || mbCommandDrag) )
4664     {
4665         ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4666         pMgr->EndDragging();
4667         return;
4668     }
4669     mbCommandDrag = sal_False;
4670 
4671     DockingWindow::MouseButtonUp( rMEvt );
4672 }
4673 
4674 // -----------------------------------------------------------------------
4675 
4676 void ToolBox::Tracking( const TrackingEvent& rTEvt )
4677 {
4678     ImplDelData aDelData;
4679     ImplAddDel( &aDelData );
4680 
4681     if ( rTEvt.IsTrackingEnded() )
4682         ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() );
4683     else
4684         ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() );
4685 
4686     if ( aDelData.IsDelete() )
4687         // toolbox was deleted
4688         return;
4689     ImplRemoveDel( &aDelData );
4690     DockingWindow::Tracking( rTEvt );
4691 }
4692 
4693 // -----------------------------------------------------------------------
4694 
4695 void ToolBox::Paint( const Rectangle& rPaintRect )
4696 {
4697     if( mpData->mbIsPaintLocked )
4698         return;
4699     if ( rPaintRect == Rectangle( 0, 0, mnDX-1, mnDY-1 ) )
4700         mbFullPaint = sal_True;
4701     ImplFormat();
4702     mbFullPaint = sal_False;
4703 
4704 
4705     ImplDrawBackground( this, rPaintRect );
4706 
4707     if ( (mnWinStyle & WB_BORDER) && !ImplIsFloatingMode() )
4708         ImplDrawBorder( this );
4709 
4710     if( !ImplIsFloatingMode() )
4711         ImplDrawGrip( this );
4712 
4713     ImplDrawMenubutton( this, mpData->mbMenubuttonSelected );
4714 
4715     // SpinButtons zeichnen
4716     if ( mnWinStyle & WB_SCROLL )
4717     {
4718         if ( mnCurLines > mnLines )
4719             ImplDrawSpin( sal_False, sal_False );
4720     }
4721 
4722     // NextButton zeichnen
4723     ImplDrawNext( sal_False );
4724 
4725     // Buttons zeichnen
4726     sal_uInt16 nHighPos;
4727     if ( mnHighItemId )
4728         nHighPos = GetItemPos( mnHighItemId );
4729     else
4730         nHighPos = TOOLBOX_ITEM_NOTFOUND;
4731 
4732     sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
4733     for( sal_uInt16 i = 0; i < nCount; i++ )
4734     {
4735         ImplToolItem* pItem = &mpData->m_aItems[i];
4736 
4737         // Nur malen, wenn Rechteck im PaintRectangle liegt
4738         if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) )
4739         {
4740             sal_Bool bHighlight = sal_False;
4741             if ( i == mnCurPos )
4742                 bHighlight = 1;
4743             else if ( i == nHighPos )
4744                 bHighlight = 2;
4745             ImplDrawItem( i, bHighlight );
4746         }
4747     }
4748     ImplShowFocus();
4749 }
4750 
4751 // -----------------------------------------------------------------------
4752 
4753 void ToolBox::Move()
4754 {
4755     DockingWindow::Move();
4756 }
4757 
4758 // -----------------------------------------------------------------------
4759 
4760 void ToolBox::Resize()
4761 {
4762     Size aSize = GetOutputSizePixel();
4763     // #i31422# some WindowManagers send (0,0) sizes when
4764     // switching virtual desktops - ignore this and avoid reformatting
4765     if( !aSize.Width() && !aSize.Height() )
4766         return;
4767 
4768     long nOldDX = mnDX;
4769     long nOldDY = mnDY;
4770     mnDX = aSize.Width();
4771     mnDY = aSize.Height();
4772 
4773     mnLastResizeDY = 0;
4774 
4775     // invalidate everything to have gradient backgrounds properly drawn
4776     Invalidate();
4777 
4778     // Evt. neu formatieren oder neu painten
4779     if ( mbScroll )
4780     {
4781         if ( !mbFormat )
4782         {
4783             mbFormat = sal_True;
4784             if( IsReallyVisible() )
4785                 ImplFormat( sal_True );
4786         }
4787     }
4788 
4789     // Border muss neu ausgegeben werden
4790     if ( mnWinStyle & WB_BORDER )
4791     {
4792         // Da wir sonst beim Paint denken, das alles neu gepaintet wird
4793         if ( mbFormat && IsReallyVisible() )
4794             Invalidate();
4795         else
4796         {
4797             if ( mnRightBorder )
4798             {
4799                 if ( nOldDX > mnDX )
4800                     Invalidate( Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) );
4801                 else
4802                     Invalidate( Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) );
4803             }
4804 
4805             if ( mnBottomBorder )
4806             {
4807                 if ( nOldDY > mnDY )
4808                     Invalidate( Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) );
4809                 else
4810                     Invalidate( Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) );
4811             }
4812         }
4813     }
4814 }
4815 
4816 // -----------------------------------------------------------------------
4817 const XubString& ToolBox::ImplGetHelpText( sal_uInt16 nItemId ) const
4818 {
4819     ImplToolItem* pItem = ImplGetItem( nItemId );
4820 
4821 	if ( pItem )
4822 	{
4823 		if ( !pItem->maHelpText.Len() && ( pItem->maHelpId.getLength() || pItem->maCommandStr.Len() ))
4824 		{
4825 			Help* pHelp = Application::GetHelp();
4826 			if ( pHelp )
4827             {
4828 				if ( pItem->maCommandStr.Len() )
4829                     pItem->maHelpText = pHelp->GetHelpText( pItem->maCommandStr, this );
4830                 if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() )
4831                     pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
4832             }
4833 		}
4834 
4835 		return pItem->maHelpText;
4836 	}
4837 	else
4838 		return ImplGetSVEmptyStr();
4839 }
4840 
4841 // -----------------------------------------------------------------------
4842 
4843 void ToolBox::RequestHelp( const HelpEvent& rHEvt )
4844 {
4845     sal_uInt16 nItemId;
4846 	Point aHelpPos;
4847 
4848 	if( !rHEvt.KeyboardActivated() )
4849 	{
4850 		nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
4851 		aHelpPos = rHEvt.GetMousePosPixel();
4852 	}
4853 	else
4854 	{
4855 		if( !mnHighItemId )
4856 			return;
4857 		else
4858 			nItemId = mnHighItemId;
4859 		Rectangle aRect( GetItemRect( nItemId ) );
4860 		if( aRect.IsEmpty() )
4861 			return;
4862 		else
4863 			aHelpPos = OutputToScreenPixel( aRect.Center() );
4864 	}
4865 
4866     if ( nItemId )
4867     {
4868         if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4869         {
4870             // Rechteck ermitteln
4871             Rectangle aTempRect = GetItemRect( nItemId );
4872             Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4873             aTempRect.Left()   = aPt.X();
4874             aTempRect.Top()    = aPt.Y();
4875             aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4876             aTempRect.Right()  = aPt.X();
4877             aTempRect.Bottom() = aPt.Y();
4878 
4879             // Text ermitteln und anzeigen
4880             XubString aStr = GetQuickHelpText( nItemId );
4881             const XubString& rHelpStr = GetHelpText( nItemId );
4882             if ( !aStr.Len() )
4883                 aStr = MnemonicGenerator::EraseAllMnemonicChars( GetItemText( nItemId ) );
4884             if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4885             {
4886                 if ( rHelpStr.Len() )
4887                     aStr = rHelpStr;
4888                 Help::ShowBalloon( this, aHelpPos, aTempRect, aStr );
4889             }
4890             else
4891                 Help::ShowQuickHelp( this, aTempRect, aStr, rHelpStr, QUICKHELP_CTRLTEXT );
4892             return;
4893         }
4894         else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
4895         {
4896             String aCommand = GetItemCommand( nItemId );
4897             rtl::OString  aHelpId( GetHelpId( nItemId ) );
4898 
4899             if ( aCommand.Len() || aHelpId.getLength() )
4900             {
4901                 // Wenn eine Hilfe existiert, dann ausloesen
4902                 Help* pHelp = Application::GetHelp();
4903                 if ( pHelp )
4904                 {
4905                     if ( aCommand.Len() )
4906                         pHelp->Start( aCommand, this );
4907                     else if ( aHelpId.getLength() )
4908                         pHelp->Start( rtl::OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), this );
4909                 }
4910                 return;
4911             }
4912         }
4913     }
4914     else if ( maNextToolRect.IsInside( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ) )
4915     {
4916         if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4917         {
4918             // Rechteck ermitteln
4919             Rectangle aTempRect = maNextToolRect;
4920             Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4921             aTempRect.Left()   = aPt.X();
4922             aTempRect.Top()    = aPt.Y();
4923             aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4924             aTempRect.Right()  = aPt.X();
4925             aTempRect.Bottom() = aPt.Y();
4926 
4927             if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4928                 Help::ShowBalloon( this, aTempRect.Center(), aTempRect, maNextToolBoxStr );
4929             else
4930                 Help::ShowQuickHelp( this, aTempRect, maNextToolBoxStr );
4931             return;
4932         }
4933     }
4934 
4935     DockingWindow::RequestHelp( rHEvt );
4936 }
4937 
4938 // -----------------------------------------------------------------------
4939 
4940 long ToolBox::Notify( NotifyEvent& rNEvt )
4941 {
4942     if ( rNEvt.GetType() == EVENT_KEYINPUT )
4943     {
4944         KeyEvent aKEvt = *rNEvt.GetKeyEvent();
4945         KeyCode aKeyCode = aKEvt.GetKeyCode();
4946         sal_uInt16  nKeyCode = aKeyCode.GetCode();
4947         switch( nKeyCode )
4948         {
4949             case KEY_TAB:
4950                 {
4951                 // internal TAB cycling only if parent is not a dialog or if we are the ony child
4952                 // otherwise the dialog control will take over
4953                 sal_Bool bNoTabCycling = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL &&
4954                     ImplGetParent()->GetChildCount() != 1 );
4955 
4956                 if( bNoTabCycling &&  ! (GetStyle() & WB_FORCETABCYCLE) )
4957                     return DockingWindow::Notify( rNEvt );
4958                 else if( ImplChangeHighlightUpDn( aKeyCode.IsShift() ? sal_True : sal_False , bNoTabCycling ) )
4959                     return sal_False;
4960                 else
4961                     return DockingWindow::Notify( rNEvt );
4962                 }
4963             default:
4964                 break;
4965         };
4966     }
4967     else if( rNEvt.GetType() == EVENT_GETFOCUS )
4968     {
4969         if( rNEvt.GetWindow() == this )
4970         {
4971             // the toolbar itself got the focus
4972             if( mnLastFocusItemId != 0 )
4973             {
4974                 // restore last item
4975                 ImplChangeHighlight( ImplGetItem( mnLastFocusItemId ) );
4976                 mnLastFocusItemId = 0;
4977             }
4978             else if( (GetGetFocusFlags() & (GETFOCUS_BACKWARD|GETFOCUS_TAB) ) == (GETFOCUS_BACKWARD|GETFOCUS_TAB))
4979                 // Shift-TAB was pressed in the parent
4980                 ImplChangeHighlightUpDn( sal_False );
4981             else
4982                 ImplChangeHighlightUpDn( sal_True );
4983 
4984             mnLastFocusItemId = 0;
4985 
4986             return true;
4987         }
4988         else
4989         {
4990             // a child window got the focus so update current item to
4991             // allow for proper lose focus handling in keyboard navigation
4992             std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4993             while( it != mpData->m_aItems.end() )
4994             {
4995                 if ( it->mbVisible )
4996                 {
4997                     if ( it->mpWindow && it->mpWindow->ImplIsWindowOrChild( rNEvt.GetWindow() ) )
4998                     {
4999                         mnHighItemId = it->mnId;
5000                         break;
5001                     }
5002                 }
5003 
5004                 ++it;
5005             }
5006             return DockingWindow::Notify( rNEvt );
5007         }
5008     }
5009     else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
5010     {
5011         // deselect
5012         ImplHideFocus();
5013         mnHighItemId = 0;
5014         mnCurPos = TOOLBOX_ITEM_NOTFOUND;
5015     }
5016 
5017     return DockingWindow::Notify( rNEvt );
5018 }
5019 
5020 // -----------------------------------------------------------------------
5021 
5022 void ToolBox::Command( const CommandEvent& rCEvt )
5023 {
5024     // StartDrag auf MouseButton/Left/Alt abbilden
5025     if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) && rCEvt.IsMouseEvent() &&
5026          mbCustomize && !mbDragging && !mbDrag && !mbSelection &&
5027          (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
5028     {
5029         // Wir erlauben nur das Draggen von Items. Deshalb muessen wir
5030         // testen, ob auch ein Item angeklickt wurde, ansonsten wuerden
5031         // wir evt. das Fenster verschieben, was nicht gewollt waere.
5032         // Wir machen dieses jedoch nur im Customize-Mode, da ansonsten
5033         // Items zuhaeufig ausversehen verschoben werden.
5034         if ( mbCustomizeMode )
5035         {
5036             Point           aMousePos = rCEvt.GetMousePosPixel();
5037             std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
5038             while ( it != mpData->m_aItems.end() )
5039             {
5040                 // Ist es dieses Item
5041                 if ( it->maRect.IsInside( aMousePos ) )
5042                 {
5043                     // Ist es ein Separator oder ist das Item disabled,
5044                     // dann mache nichts
5045                     if ( (it->meType == TOOLBOXITEM_BUTTON) &&
5046                          !it->mbShowWindow )
5047                         mbCommandDrag = sal_True;
5048                     break;
5049                 }
5050 
5051                 ++it;
5052             }
5053 
5054             if ( mbCommandDrag )
5055             {
5056                 MouseEvent aMEvt( aMousePos, 1, MOUSE_SIMPLECLICK,
5057                                   MOUSE_LEFT, KEY_MOD2 );
5058                 ToolBox::MouseButtonDown( aMEvt );
5059                 return;
5060             }
5061         }
5062     }
5063     else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
5064     {
5065         if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) )
5066         {
5067             const CommandWheelData* pData = rCEvt.GetWheelData();
5068             if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
5069             {
5070                 if ( (mnCurLine > 1) && (pData->GetDelta() > 0) )
5071                     ShowLine( sal_False );
5072                 else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) )
5073                     ShowLine( sal_True );
5074                 ImplDrawSpin( sal_False, sal_False );
5075                 return;
5076             }
5077         }
5078     }
5079 
5080     DockingWindow::Command( rCEvt );
5081 }
5082 
5083 // -----------------------------------------------------------------------
5084 
5085 void ToolBox::StateChanged( StateChangedType nType )
5086 {
5087     DockingWindow::StateChanged( nType );
5088 
5089     if ( nType == STATE_CHANGE_INITSHOW )
5090         ImplFormat();
5091     else if ( nType == STATE_CHANGE_ENABLE )
5092         ImplUpdateItem();
5093     else if ( nType == STATE_CHANGE_UPDATEMODE )
5094     {
5095         if ( IsUpdateMode() )
5096             Invalidate();
5097     }
5098     else if ( (nType == STATE_CHANGE_ZOOM) ||
5099               (nType == STATE_CHANGE_CONTROLFONT) )
5100     {
5101         mbCalc = sal_True;
5102         mbFormat = sal_True;
5103         ImplInitSettings( sal_True, sal_False, sal_False );
5104         Invalidate();
5105     }
5106     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
5107     {
5108         ImplInitSettings( sal_False, sal_True, sal_False );
5109         Invalidate();
5110     }
5111     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
5112     {
5113         ImplInitSettings( sal_False, sal_False, sal_True ); // font, foreground, background
5114         Invalidate();
5115     }
5116 }
5117 
5118 // -----------------------------------------------------------------------
5119 
5120 void ToolBox::DataChanged( const DataChangedEvent& rDCEvt )
5121 {
5122     DockingWindow::DataChanged( rDCEvt );
5123 
5124     if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
5125          (rDCEvt.GetType() == DATACHANGED_FONTS) ||
5126          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
5127          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
5128           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
5129     {
5130         mbCalc = sal_True;
5131         mbFormat = sal_True;
5132         ImplInitSettings( sal_True, sal_True, sal_True );
5133         Invalidate();
5134     }
5135 }
5136 
5137 // -----------------------------------------------------------------------
5138 
5139 sal_Bool ToolBox::PrepareToggleFloatingMode()
5140 {
5141     return DockingWindow::PrepareToggleFloatingMode();
5142 }
5143 
5144 // -----------------------------------------------------------------------
5145 
5146 void ToolBox::ToggleFloatingMode()
5147 {
5148     DockingWindow::ToggleFloatingMode();
5149 
5150     sal_Bool mbOldHorz = mbHorz;
5151 
5152     if ( ImplIsFloatingMode() )
5153     {
5154         mbHorz   = sal_True;
5155         meAlign  = WINDOWALIGN_TOP;
5156         mbScroll = sal_True;
5157 
5158         if( mbOldHorz != mbHorz )
5159             mbCalc = sal_True;  // orientation was changed !
5160 
5161         ImplSetMinMaxFloatSize( this );
5162         SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
5163     }
5164     else
5165     {
5166         mbScroll = (mnWinStyle & WB_SCROLL) ? sal_True : sal_False;
5167         if ( (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM) )
5168             mbHorz = sal_True;
5169         else
5170             mbHorz = sal_False;
5171 
5172         // set focus back to document
5173         ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
5174     }
5175 
5176     if( mbOldHorz != mbHorz )
5177     {
5178         // if orientation changes, the toolbox has to be initialized again
5179         // to update the direction of the gradient
5180         mbCalc = sal_True;
5181         ImplInitSettings( sal_True, sal_True, sal_True );
5182     }
5183 
5184     mbFormat = sal_True;
5185     ImplFormat();
5186 }
5187 
5188 // -----------------------------------------------------------------------
5189 
5190 void ToolBox::StartDocking()
5191 {
5192     meDockAlign = meAlign;
5193     mnDockLines = mnLines;
5194     mbLastFloatMode = ImplIsFloatingMode();
5195     DockingWindow::StartDocking();
5196 }
5197 
5198 // -----------------------------------------------------------------------
5199 
5200 sal_Bool ToolBox::Docking( const Point& rPos, Rectangle& rRect )
5201 {
5202     // Wenn Dragging, dann nicht machen, da vorher schon berechnet
5203     if ( mbDragging )
5204         return sal_False;
5205 
5206     sal_Bool bFloatMode = sal_False;
5207 
5208     DockingWindow::Docking( rPos, rRect );
5209 
5210     // Befindet sich die Maus ausserhalb des Bereichs befindet, kann es nur ein
5211     // FloatWindow werden
5212 	Rectangle aDockingRect( rRect );
5213 	if ( !ImplIsFloatingMode() )
5214 	{
5215 		// don't use tracking rectangle for alignment check, because it will be too large
5216 		// to get a floating mode as result - switch to floating size
5217 		// so the calculation only depends on the position of the rectangle, not the current
5218 		// docking state of the window
5219         sal_uInt16 nTemp = 0;
5220 		aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
5221 
5222 		// in this mode docking is never done by keyboard, so it's OK to use the mouse position
5223 		aDockingRect.SetPos( ImplGetFrameWindow()->GetPointerPosPixel() );
5224 	}
5225 
5226 	Rectangle aIntersection = maOutDockRect.GetIntersection( aDockingRect );
5227     if ( !aIntersection.IsEmpty() && !IsDockingPrevented() )
5228     {
5229         Rectangle   aInRect = maInDockRect;
5230         Size aDockSize;
5231         aDockSize.Width()  = ImplCalcSize( this, mnLines, TB_CALCMODE_VERT ).Width();
5232         aDockSize.Height() = ImplCalcSize( this, mnLines, TB_CALCMODE_HORZ ).Height();
5233         aInRect.Left()   += aDockSize.Width()/2;
5234         aInRect.Top()    += aDockSize.Height()/2;
5235         aInRect.Right()  -= aDockSize.Width()/2;
5236         aInRect.Bottom() -= aDockSize.Height()/2;
5237 
5238         // Wenn Fenster zu klein, wird das gesammte InDock-Rect genommen
5239         if ( aInRect.Left() >= aInRect.Right() )
5240         {
5241             aInRect.Left()  = maInDockRect.Left();
5242             aInRect.Right() = maInDockRect.Right();
5243         }
5244         if ( aInRect.Top() >= aInRect.Bottom() )
5245         {
5246             aInRect.Top()    = maInDockRect.Top();
5247             aInRect.Bottom() = maInDockRect.Bottom();
5248         }
5249 
5250         // Wenn Maus nicht im Dock-Bereich, dann kann es nur zum
5251         // FloatWindow werden
5252         Rectangle aIntersect = aInRect.GetIntersection( aDockingRect );
5253         if ( aIntersect == aDockingRect )
5254             bFloatMode = sal_True;
5255         else
5256         {
5257             // docking rectangle is in the "sensible area"
5258             Point aPos = aDockingRect.TopLeft();
5259             Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
5260             Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
5261             Size  aInSize = aInRect.GetSize();
5262 
5263             if ( aInPosTL.X() <= 0 )
5264                 meDockAlign = WINDOWALIGN_LEFT;
5265             else if ( aInPosTL.Y() <= 0)
5266                 meDockAlign = WINDOWALIGN_TOP;
5267             else if ( aInPosBR.X() >= aInSize.Width() )
5268                 meDockAlign = WINDOWALIGN_RIGHT;
5269             else if ( aInPosBR.Y() >= aInSize.Height() )
5270                 meDockAlign = WINDOWALIGN_BOTTOM;
5271 
5272             // Wenn sich Dock-Align geaendert hat, muessen wir die
5273             // neue Dock-Groesse setzen
5274             if ( (meDockAlign == WINDOWALIGN_TOP) || (meDockAlign == WINDOWALIGN_BOTTOM) )
5275                 aDockSize.Width() = maInDockRect.GetWidth();
5276             else
5277                 aDockSize.Height() = maInDockRect.GetHeight();
5278 
5279             aDockingRect.SetSize( aDockSize );
5280 
5281             Point aPosTL( maInDockRect.TopLeft() );
5282             switch ( meDockAlign )
5283             {
5284                 case WINDOWALIGN_TOP :
5285                     aDockingRect.SetPos( aPosTL );
5286                     break;
5287                 case WINDOWALIGN_LEFT :
5288                     aDockingRect.SetPos( aPosTL );
5289                     break;
5290                 case WINDOWALIGN_BOTTOM :
5291                 {
5292                     Point aPosBL( maInDockRect.BottomLeft() );
5293                     aPosBL.Y() -= aDockingRect.GetHeight();
5294                     aDockingRect.SetPos( aPosBL );
5295                     break;
5296                 }
5297                 case WINDOWALIGN_RIGHT :
5298                 {
5299                     Point aPosTR( maInDockRect.TopRight() );
5300                     aPosTR.X() -= aDockingRect.GetWidth();
5301                     aDockingRect.SetPos( aPosTR );
5302                     break;
5303                 }
5304             }
5305         }
5306     }
5307     else
5308         bFloatMode = sal_True;
5309 
5310     if ( bFloatMode )
5311     {
5312         meDockAlign = meAlign;
5313         if ( !mbLastFloatMode )
5314         {
5315             sal_uInt16 nTemp = 0;
5316             aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
5317         }
5318     }
5319 
5320 	rRect = aDockingRect;
5321     mbLastFloatMode = bFloatMode;
5322 
5323     return bFloatMode;
5324 }
5325 
5326 // -----------------------------------------------------------------------
5327 
5328 void ToolBox::EndDocking( const Rectangle& rRect, sal_Bool bFloatMode )
5329 {
5330     if ( !IsDockingCanceled() )
5331     {
5332         if ( mnLines != mnDockLines )
5333             SetLineCount( mnDockLines );
5334         if ( meAlign != meDockAlign )
5335             SetAlign( meDockAlign );
5336     }
5337     if ( bFloatMode || (bFloatMode != ImplIsFloatingMode()) )
5338         DockingWindow::EndDocking( rRect, bFloatMode );
5339 }
5340 
5341 // -----------------------------------------------------------------------
5342 
5343 void ToolBox::Resizing( Size& rSize )
5344 {
5345     sal_uInt16  nCalcLines;
5346     sal_uInt16  nTemp;
5347 
5348     // Alle Floatinggroessen berechnen
5349     ImplCalcFloatSizes( this );
5350 
5351     if ( !mnLastResizeDY )
5352         mnLastResizeDY = mnDY;
5353 
5354     // Ist vertikales Resizing angesagt
5355     if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) )
5356     {
5357         nCalcLines = ImplCalcLines( this, rSize.Height() );
5358         if ( nCalcLines < 1 )
5359             nCalcLines = 1;
5360         rSize = ImplCalcFloatSize( this, nCalcLines );
5361     }
5362     else
5363     {
5364         nCalcLines = 1;
5365         nTemp = nCalcLines;
5366         Size aTempSize = ImplCalcFloatSize( this, nTemp );
5367         while ( (aTempSize.Width() > rSize.Width()) &&
5368                 (nCalcLines <= mpFloatSizeAry->mpSize[0].mnLines) )
5369         {
5370             nCalcLines++;
5371             nTemp = nCalcLines;
5372             aTempSize = ImplCalcFloatSize( this, nTemp );
5373         }
5374         rSize = aTempSize;
5375     }
5376 
5377     mnLastResizeDY = rSize.Height();
5378 }
5379 
5380 // -----------------------------------------------------------------------
5381 
5382 Size ToolBox::CalcWindowSizePixel( sal_uInt16 nCalcLines ) const
5383 {
5384     return ImplCalcSize( this, nCalcLines );
5385 }
5386 
5387 Size ToolBox::CalcWindowSizePixel( sal_uInt16 nCalcLines, WindowAlign eAlign ) const
5388 {
5389     return ImplCalcSize( this, nCalcLines,
5390         (eAlign == WINDOWALIGN_TOP || eAlign == WINDOWALIGN_BOTTOM) ? TB_CALCMODE_HORZ : TB_CALCMODE_VERT );
5391 }
5392 
5393 sal_uInt16 ToolBox::ImplCountLineBreaks( const ToolBox *pThis )
5394 {
5395     sal_uInt16 nLines = 0;
5396 
5397     std::vector< ImplToolItem >::const_iterator it = ((ToolBox*)pThis)->mpData->m_aItems.begin();
5398     while ( it != ((ToolBox*)pThis)->mpData->m_aItems.end() )
5399     {
5400         if( it->meType == TOOLBOXITEM_BREAK )
5401             nLines++;
5402         it++;
5403     }
5404     return nLines;
5405 }
5406 
5407 Size ToolBox::CalcPopupWindowSizePixel() const
5408 {
5409     // count number of breaks and calc corresponding floating window size
5410     sal_uInt16 nLines = ImplCountLineBreaks( this );
5411 
5412     if( nLines )
5413         nLines++;   // add the first line
5414     else
5415     {
5416         // no breaks found: use quadratic layout
5417         nLines = (sal_uInt16) ceil( sqrt( (double) GetItemCount() ) );
5418     }
5419 
5420     sal_Bool bPopup = mpData->mbAssumePopupMode;
5421     ToolBox *pThis = (ToolBox*) this;
5422     pThis->mpData->mbAssumePopupMode = sal_True;
5423 
5424     Size aSize = CalcFloatingWindowSizePixel( nLines );
5425 
5426     pThis->mpData->mbAssumePopupMode = bPopup;
5427     return aSize;
5428 }
5429 
5430 Size ToolBox::CalcFloatingWindowSizePixel() const
5431 {
5432     sal_uInt16 nLines = ImplCountLineBreaks( this );
5433     nLines++; // add the first line
5434     return CalcFloatingWindowSizePixel( nLines );
5435 }
5436 
5437 Size ToolBox::CalcFloatingWindowSizePixel( sal_uInt16 nCalcLines ) const
5438 {
5439     sal_Bool bFloat = mpData->mbAssumeFloating;
5440     sal_Bool bDocking = mpData->mbAssumeDocked;
5441 
5442     // simulate floating mode and force reformat before calculating
5443     ToolBox *pThis = (ToolBox*) this;
5444     pThis->mpData->mbAssumeFloating = sal_True;
5445     pThis->mpData->mbAssumeDocked = sal_False;
5446 
5447     Size aSize = ImplCalcFloatSize( (ToolBox*) this, nCalcLines );
5448 
5449     pThis->mbFormat = sal_True;
5450     pThis->mpData->mbAssumeFloating = bFloat;
5451     pThis->mpData->mbAssumeDocked = bDocking;
5452 
5453     return aSize;
5454 }
5455 
5456 // -----------------------------------------------------------------------
5457 
5458 Size ToolBox::CalcMinimumWindowSizePixel() const
5459 {
5460     if( ImplIsFloatingMode() )
5461         return ImplCalcSize( this, mnFloatLines );
5462     else
5463     {
5464         // create dummy toolbox for measurements
5465         ToolBox *pToolBox = new ToolBox( GetParent(), GetStyle() );
5466 
5467         // copy until first useful item
5468         std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5469         while( it != mpData->m_aItems.end() )
5470         {
5471             pToolBox->CopyItem( *this, it->mnId );
5472             if( (it->meType != TOOLBOXITEM_BUTTON) ||
5473                 !it->mbVisible || ImplIsFixedControl( &(*it) ) )
5474                 it++;
5475             else
5476                 break;
5477         }
5478 
5479         // add to docking manager if required to obtain a drag area
5480         // (which is accounted for in calcwindowsizepixel)
5481         if( ImplGetDockingManager()->GetDockingWindowWrapper( this ) )
5482             ImplGetDockingManager()->AddWindow( pToolBox );
5483 
5484         // account for menu
5485         if( IsMenuEnabled() )
5486             pToolBox->SetMenuType( GetMenuType() );
5487 
5488         pToolBox->SetAlign( GetAlign() );
5489         Size aSize = pToolBox->CalcWindowSizePixel( 1 );
5490 
5491         ImplGetDockingManager()->RemoveWindow( pToolBox );
5492         pToolBox->Clear();
5493         delete pToolBox;
5494 
5495         return aSize;
5496     }
5497 }
5498 
5499 // -----------------------------------------------------------------------
5500 
5501 void ToolBox::EnableCustomize( sal_Bool bEnable )
5502 {
5503     if ( bEnable != mbCustomize )
5504     {
5505         mbCustomize = bEnable;
5506 
5507         ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5508         if ( bEnable )
5509             pMgr->Insert( this );
5510         else
5511             pMgr->Remove( this );
5512     }
5513 }
5514 
5515 // -----------------------------------------------------------------------
5516 
5517 void ToolBox::StartCustomize( const Rectangle& rRect, void* pData )
5518 {
5519     DBG_ASSERT( mbCustomize,
5520                 "ToolBox::StartCustomize(): ToolBox must be customized" );
5521 
5522     ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5523     Point aMousePos = GetPointerPosPixel();
5524     Point aPos = ScreenToOutputPixel( rRect.TopLeft() );
5525     Rectangle aRect( aPos.X(), aPos.Y(),
5526                      aPos.X()+rRect.GetWidth()+SMALLBUTTON_HSIZE,
5527                      aPos.Y()+rRect.GetHeight()+SMALLBUTTON_VSIZE );
5528     aMousePos = ScreenToOutputPixel( aPos );
5529     Pointer aPtr;
5530     SetPointer( aPtr );
5531     pMgr->StartDragging( this, aMousePos, aRect, 0, sal_False, pData );
5532 }
5533 
5534 // -----------------------------------------------------------------------
5535 
5536 void ToolBox::StartCustomizeMode()
5537 {
5538     ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5539     pMgr->StartCustomizeMode();
5540 }
5541 
5542 // -----------------------------------------------------------------------
5543 
5544 void ToolBox::EndCustomizeMode()
5545 {
5546     ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5547     pMgr->EndCustomizeMode();
5548 }
5549 
5550 // -----------------------------------------------------------------------
5551 
5552 sal_Bool ToolBox::IsCustomizeMode()
5553 {
5554     ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5555     return pMgr->IsCustomizeMode();
5556 }
5557 
5558 // -----------------------------------------------------------------------
5559 
5560 void ToolBox::GetFocus()
5561 {
5562 	DockingWindow::GetFocus();
5563 }
5564 
5565 // -----------------------------------------------------------------------
5566 
5567 void ToolBox::LoseFocus()
5568 {
5569     ImplChangeHighlight( NULL, sal_True );
5570 
5571 	DockingWindow::LoseFocus();
5572 }
5573 
5574 // -----------------------------------------------------------------------
5575 
5576 // performs the action associated with an item, ie simulates clicking the item
5577 void ToolBox::TriggerItem( sal_uInt16 nItemId, sal_Bool bShift, sal_Bool bCtrl )
5578 {
5579     mnHighItemId = nItemId;
5580     sal_uInt16 nModifier = 0;
5581     if( bShift )
5582         nModifier |= KEY_SHIFT;
5583     if( bCtrl )
5584         nModifier |= KEY_MOD1;
5585     KeyCode aKeyCode( 0, nModifier );
5586     ImplActivateItem( aKeyCode );
5587 }
5588 
5589 // -----------------------------------------------------------------------
5590 
5591 // calls the button's action handler
5592 // returns sal_True if action was called
5593 sal_Bool ToolBox::ImplActivateItem( KeyCode aKeyCode )
5594 {
5595 	sal_Bool bRet = sal_True;
5596 	if( mnHighItemId )
5597 	{
5598         ImplToolItem *pToolItem = ImplGetItem( mnHighItemId );
5599 
5600         // #107712#, activate can also be called for disabled entries
5601         if( pToolItem && !pToolItem->mbEnabled )
5602             return sal_True;
5603 
5604         if( pToolItem && pToolItem->mpWindow && HasFocus() )
5605         {
5606             ImplHideFocus();
5607             mbChangingHighlight = sal_True;  // avoid focus change due to loose focus
5608             pToolItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5609             mbChangingHighlight = sal_False;
5610         }
5611         else
5612         {
5613 			mnDownItemId = mnCurItemId = mnHighItemId;
5614 	        ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5615             if ( pItem->mnBits & TIB_AUTOCHECK )
5616             {
5617 				if ( pItem->mnBits & TIB_RADIOCHECK )
5618 				{
5619 					if ( pItem->meState != STATE_CHECK )
5620 						SetItemState( pItem->mnId, STATE_CHECK );
5621 				}
5622 				else
5623 				{
5624 					if ( pItem->meState != STATE_CHECK )
5625 						pItem->meState = STATE_CHECK;
5626 					else
5627 						pItem->meState = STATE_NOCHECK;
5628 				}
5629             }
5630             mnMouseModifier = aKeyCode.GetModifier();
5631             mbIsKeyEvent = sal_True;
5632             Activate();
5633             Click();
5634 
5635             // #107776# we might be destroyed in the selecthandler
5636             ImplDelData aDelData;
5637             ImplAddDel( &aDelData );
5638             Select();
5639             if ( aDelData.IsDelete() )
5640                 return bRet;
5641             ImplRemoveDel( &aDelData );
5642 
5643             Deactivate();
5644             mbIsKeyEvent = sal_False;
5645             mnMouseModifier = 0;
5646         }
5647 	}
5648 	else
5649 		bRet = sal_False;
5650 	return bRet;
5651 }
5652 
5653 // -----------------------------------------------------------------------
5654 
5655 sal_Bool ImplCloseLastPopup( Window *pParent )
5656 {
5657     // close last popup toolbox (see also:
5658     // ImplHandleMouseFloatMode(...) in winproc.cxx )
5659 
5660     if( ImplGetSVData()->maWinData.mpFirstFloat )
5661     {
5662 	    FloatingWindow* pLastLevelFloat = ImplGetSVData()->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
5663 	    // only close the floater if it is not our direct parent, which would kill ourself
5664 	    if( pLastLevelFloat && pLastLevelFloat != pParent )
5665 	    {
5666 		    pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
5667 		    return sal_True;
5668 	    }
5669     }
5670     return sal_False;
5671 }
5672 
5673 // opens a drop down toolbox item
5674 // returns sal_True if item was opened
5675 sal_Bool ToolBox::ImplOpenItem( KeyCode aKeyCode )
5676 {
5677     sal_uInt16 nCode = aKeyCode.GetCode();
5678     sal_Bool bRet = sal_True;
5679 
5680     // arrow keys should work only in the opposite direction of alignment (to not break cursor travelling)
5681     if ( ((nCode == KEY_LEFT || nCode == KEY_RIGHT) && IsHorizontal())
5682       || ((nCode == KEY_UP   || nCode == KEY_DOWN)  && !IsHorizontal()) )
5683         return sal_False;
5684 
5685     if( IsMenuEnabled() && mpData->mbMenubuttonSelected )
5686     {
5687         if( ImplCloseLastPopup( GetParent() ) )
5688             return bRet;
5689 
5690         ImplUpdateCustomMenu();
5691         Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
5692     }
5693     else if( mnHighItemId &&  ImplGetItem( mnHighItemId ) &&
5694         (ImplGetItem( mnHighItemId )->mnBits & TIB_DROPDOWN) )
5695 	{
5696         if( ImplCloseLastPopup( GetParent() ) )
5697             return bRet;
5698 
5699 		mnDownItemId = mnCurItemId = mnHighItemId;
5700         mnCurPos = GetItemPos( mnCurItemId );
5701 		mnLastFocusItemId = mnCurItemId; // save item id for possible later focus restore
5702 		mnMouseModifier = aKeyCode.GetModifier();
5703 		mbIsShift = sal_True;
5704 		mbIsKeyEvent = sal_True;
5705 		Activate();
5706 
5707         mpData->mbDropDownByKeyboard = sal_True;
5708         GetDropdownClickHdl().Call( this );
5709 
5710 		mbIsKeyEvent = sal_False;
5711 		mbIsShift = sal_False;
5712 		mnMouseModifier = 0;
5713 	}
5714     else
5715         bRet = sal_False;
5716 
5717     return bRet;
5718 }
5719 
5720 // -----------------------------------------------------------------------
5721 
5722 void ToolBox::KeyInput( const KeyEvent& rKEvt )
5723 {
5724     KeyCode aKeyCode = rKEvt.GetKeyCode();
5725 	mnKeyModifier = aKeyCode.GetModifier();
5726     sal_uInt16 nCode = aKeyCode.GetCode();
5727     sal_Bool bParentIsDialog = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL );
5728 	sal_Bool bForwardKey = sal_False;
5729 	sal_Bool bGrabFocusToDocument = sal_False;
5730 
5731     // #107776# we might be destroyed in the keyhandler
5732     ImplDelData aDelData;
5733     ImplAddDel( &aDelData );
5734 
5735     switch ( nCode )
5736     {
5737         case KEY_UP:
5738         {
5739             // Ctrl-Cursor activates next toolbox, indicated by a blue arrow pointing to the left/up
5740 			if( aKeyCode.GetModifier() )	// allow only pure cursor keys
5741 				break;
5742 			if( !IsHorizontal() )
5743 				ImplChangeHighlightUpDn( sal_True );
5744 			else
5745 				ImplOpenItem( aKeyCode );
5746         }
5747         break;
5748         case KEY_LEFT:
5749         {
5750 			if( aKeyCode.GetModifier() )	// allow only pure cursor keys
5751 				break;
5752 			if( IsHorizontal() )
5753 				ImplChangeHighlightUpDn( sal_True );
5754 			else
5755 				ImplOpenItem( aKeyCode );
5756         }
5757         break;
5758         case KEY_DOWN:
5759         {
5760 			if( aKeyCode.GetModifier() )	// allow only pure cursor keys
5761 				break;
5762 			if( !IsHorizontal() )
5763 				ImplChangeHighlightUpDn( sal_False );
5764 			else
5765 				ImplOpenItem( aKeyCode );
5766         }
5767         break;
5768         case KEY_RIGHT:
5769         {
5770 			if( aKeyCode.GetModifier() )	// allow only pure cursor keys
5771 				break;
5772 			if( IsHorizontal() )
5773 				ImplChangeHighlightUpDn( sal_False );
5774 			else
5775 				ImplOpenItem( aKeyCode );
5776         }
5777         break;
5778         case KEY_PAGEUP:
5779             if ( mnCurLine > 1 )
5780             {
5781                 if( mnCurLine > mnVisLines )
5782                     mnCurLine = mnCurLine - mnVisLines;
5783                 else
5784                     mnCurLine = 1;
5785                 mbFormat = sal_True;
5786                 ImplFormat();
5787                 ImplDrawSpin( sal_False, sal_False );
5788                 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5789             }
5790         break;
5791         case KEY_PAGEDOWN:
5792             if ( mnCurLine+mnVisLines-1 < mnCurLines )
5793             {
5794                 if( mnCurLine + 2*mnVisLines-1 < mnCurLines )
5795                     mnCurLine = mnCurLine + mnVisLines;
5796                 else
5797                     mnCurLine = mnCurLines;
5798                 mbFormat = sal_True;
5799                 ImplFormat();
5800                 ImplDrawSpin( sal_False, sal_False );
5801                 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5802             }
5803         break;
5804         case KEY_END:
5805 			{
5806                 ImplChangeHighlight( NULL );
5807                 ImplChangeHighlightUpDn( sal_False );
5808 			}
5809 			break;
5810         case KEY_HOME:
5811 			{
5812                 ImplChangeHighlight( NULL );
5813                 ImplChangeHighlightUpDn( sal_True );
5814 			}
5815 			break;
5816         case KEY_ESCAPE:
5817 		{
5818             if( !ImplIsFloatingMode() && bParentIsDialog )
5819 			    DockingWindow::KeyInput( rKEvt );
5820             else
5821             {
5822                 // send focus to document pane
5823                 Window *pWin = this;
5824                 while( pWin )
5825                 {
5826                     if( !pWin->GetParent() )
5827                     {
5828                         pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
5829                         break;
5830                     }
5831                     pWin = pWin->GetParent();
5832                 }
5833             }
5834 		}
5835 		break;
5836         case KEY_RETURN:
5837         {
5838             // #107712#, disabled entries are selectable now
5839             //  leave toolbox and move focus to document
5840 	        if( mnHighItemId )
5841 	        {
5842                 ImplToolItem *pItem = ImplGetItem( mnHighItemId );
5843                 if( !pItem->mbEnabled )
5844                 {
5845                     Sound::Beep( SOUND_DISABLE, this );
5846                     bGrabFocusToDocument = sal_True;
5847                 }
5848             }
5849             if( !bGrabFocusToDocument )
5850                 bForwardKey = !ImplActivateItem( aKeyCode );
5851         }
5852         break;
5853         default:
5854             {
5855             sal_uInt16 aKeyGroup = aKeyCode.GetGroup();
5856             ImplToolItem *pItem = NULL;
5857 	        if( mnHighItemId )
5858                 pItem = ImplGetItem( mnHighItemId );
5859             // #i13931# forward alphanum keyinput into embedded control
5860             if( (aKeyGroup == KEYGROUP_NUM || aKeyGroup == KEYGROUP_ALPHA ) && pItem && pItem->mpWindow && pItem->mbEnabled )
5861             {
5862                 Window *pFocusWindow = Application::GetFocusWindow();
5863                 ImplHideFocus();
5864                 mbChangingHighlight = sal_True;  // avoid focus change due to loose focus
5865                 pItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5866                 mbChangingHighlight = sal_False;
5867                 if( pFocusWindow != Application::GetFocusWindow() )
5868                     Application::GetFocusWindow()->KeyInput( rKEvt );
5869             }
5870             else
5871             {
5872 			    // do nothing to avoid key presses going into the document
5873 			    // while the toolbox has the focus
5874                 // just forward function and special keys and combinations with Alt-key
5875                 if( aKeyGroup == KEYGROUP_FKEYS || aKeyGroup == KEYGROUP_MISC || aKeyCode.IsMod2() )
5876                     bForwardKey = sal_True;
5877             }
5878         }
5879     }
5880 
5881     if ( aDelData.IsDelete() )
5882         return;
5883     ImplRemoveDel( &aDelData );
5884 
5885     // #107251# move focus away if this toolbox was disabled during keyinput
5886     if( HasFocus() && mpData->mbKeyInputDisabled && (ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL)
5887     {
5888         sal_uInt16 n = 0;
5889         Window *pFocusControl = ImplGetParent()->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
5890         if ( pFocusControl && pFocusControl != this )
5891             pFocusControl->ImplControlFocus( GETFOCUS_INIT );
5892     }
5893 
5894 	mnKeyModifier = 0;
5895 
5896     // #107712#, leave toolbox
5897     if( bGrabFocusToDocument )
5898     {
5899         GrabFocusToDocument();
5900         return;
5901     }
5902 
5903 	if( bForwardKey )
5904 		DockingWindow::KeyInput( rKEvt );
5905 }
5906 
5907 // -----------------------------------------------------------------------
5908 
5909 // returns the current toolbox line of the item
5910 sal_uInt16 ToolBox::ImplGetItemLine( ImplToolItem* pCurrentItem )
5911 {
5912     std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
5913     sal_uInt16 nLine = 1;
5914     while( it != mpData->m_aItems.end() )
5915     {
5916         if ( it->mbBreak )
5917             nLine++;
5918         if( &(*it) == pCurrentItem)
5919             break;
5920         ++it;
5921     }
5922     return nLine;
5923 }
5924 
5925 // returns the first displayable item in the given line
5926 ImplToolItem* ToolBox::ImplGetFirstValidItem( sal_uInt16 nLine )
5927 {
5928     if( !nLine || nLine > mnCurLines )
5929         return NULL;
5930 
5931     nLine--;
5932 
5933     std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5934     while( it != mpData->m_aItems.end() )
5935     {
5936         // find correct line
5937         if ( it->mbBreak )
5938             nLine--;
5939         if( !nLine )
5940         {
5941             // find first useful item
5942             while( it != mpData->m_aItems.end() && ((it->meType != TOOLBOXITEM_BUTTON) ||
5943                 /*!it->mbEnabled ||*/ !it->mbVisible || ImplIsFixedControl( &(*it) )) )
5944             {
5945                 ++it;
5946                 if( it == mpData->m_aItems.end() || it->mbBreak )
5947                     return NULL;    // no valid items in this line
5948             }
5949             return &(*it);
5950         }
5951         ++it;
5952     }
5953 
5954     return (it == mpData->m_aItems.end()) ? NULL : &(*it);
5955 }
5956 
5957 // returns the last displayable item in the given line
5958 ImplToolItem* ToolBox::ImplGetLastValidItem( sal_uInt16 nLine )
5959 {
5960     if( !nLine || nLine > mnCurLines )
5961         return NULL;
5962 
5963     nLine--;
5964     ImplToolItem *pFound = NULL;
5965     std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5966     while( it != mpData->m_aItems.end() )
5967     {
5968         // find correct line
5969         if ( it->mbBreak )
5970             nLine--;
5971         if( !nLine )
5972         {
5973             // find last useful item
5974             while( it != mpData->m_aItems.end() && ((it->meType == TOOLBOXITEM_BUTTON) &&
5975                 /*it->mbEnabled &&*/ it->mbVisible && !ImplIsFixedControl( &(*it) )) )
5976             {
5977                 pFound = &(*it);
5978                 ++it;
5979                 if( it == mpData->m_aItems.end() || it->mbBreak )
5980                     return pFound;    // end of line: return last useful item
5981             }
5982             return pFound;
5983         }
5984         ++it;
5985     }
5986 
5987     return pFound;
5988 }
5989 
5990 // -----------------------------------------------------------------------
5991 
5992 sal_uInt16 ToolBox::ImplFindItemPos( const ImplToolItem* pItem, const std::vector< ImplToolItem >& rList )
5993 {
5994     if( pItem )
5995     {
5996         sal_uInt16 nPos;
5997         for( nPos = 0; nPos < rList.size(); nPos++ )
5998             if( &rList[ nPos ] == pItem )
5999                 return nPos;
6000     }
6001     return TOOLBOX_ITEM_NOTFOUND;
6002 }
6003 
6004 void ToolBox::ChangeHighlight( sal_uInt16 nPos )
6005 {
6006     if ( nPos < GetItemCount() ) {
6007         ImplGrabFocus( 0 );
6008         ImplChangeHighlight ( ImplGetItem ( GetItemId ( (sal_uInt16) nPos ) ), sal_False );
6009     }
6010 }
6011 
6012 void ToolBox::ImplChangeHighlight( ImplToolItem* pItem, sal_Bool bNoGrabFocus )
6013 {
6014     // avoid recursion due to focus change
6015     if( mbChangingHighlight )
6016         return;
6017 
6018     mbChangingHighlight = sal_True;
6019 
6020 	ImplToolItem* pOldItem = NULL;
6021 
6022     if ( mnHighItemId )
6023     {
6024         ImplHideFocus();
6025         sal_uInt16 nPos = GetItemPos( mnHighItemId );
6026 	    pOldItem = ImplGetItem( mnHighItemId );
6027         // #i89962# ImplDrawItem can cause Invalidate/Update
6028         // which will in turn ImplShowFocus again
6029         // set mnHighItemId to 0 already to prevent this hen/egg problem
6030         mnHighItemId = 0;
6031         ImplDrawItem( nPos, sal_False );
6032         ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
6033     }
6034 
6035     if( !bNoGrabFocus && pItem != pOldItem && pOldItem && pOldItem->mpWindow )
6036     {
6037         // move focus into toolbox
6038         GrabFocus();
6039     }
6040 
6041     if( pItem )
6042 	{
6043 		sal_uInt16 aPos = ToolBox::ImplFindItemPos( pItem, mpData->m_aItems );
6044 		if( aPos != TOOLBOX_ITEM_NOTFOUND)
6045 		{
6046             // check for line breaks
6047             sal_uInt16 nLine = ImplGetItemLine( pItem );
6048 
6049             if( nLine >= mnCurLine + mnVisLines )
6050             {
6051                 mnCurLine = nLine - mnVisLines + 1;
6052                 mbFormat = sal_True;
6053             }
6054             else if ( nLine < mnCurLine )
6055             {
6056                 mnCurLine = nLine;
6057                 mbFormat = sal_True;
6058             }
6059 
6060             if( mbFormat )
6061             {
6062                 ImplFormat();
6063             }
6064 
6065             mnHighItemId = pItem->mnId;
6066 			ImplDrawItem( aPos, 2 );    // always use shadow effect (2)
6067 
6068             if( mbSelection )
6069                 mnCurPos = aPos;
6070             ImplShowFocus();
6071 
6072             ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
6073 		}
6074 	}
6075     else
6076     {
6077         ImplHideFocus();
6078         mnHighItemId = 0;
6079         mnCurPos = TOOLBOX_ITEM_NOTFOUND;
6080     }
6081 
6082     mbChangingHighlight = sal_False;
6083 }
6084 
6085 // -----------------------------------------------------------------------
6086 
6087 // check for keyboard accessible items
6088 static sal_Bool ImplIsValidItem( const ImplToolItem* pItem, sal_Bool bNotClipped )
6089 {
6090     sal_Bool bValid = (pItem && pItem->meType == TOOLBOXITEM_BUTTON && pItem->mbVisible && !ImplIsFixedControl( pItem ));
6091     if( bValid && bNotClipped && pItem->IsClipped() )
6092         bValid = sal_False;
6093     return bValid;
6094 }
6095 
6096 // -----------------------------------------------------------------------
6097 
6098 sal_Bool ToolBox::ImplChangeHighlightUpDn( sal_Bool bUp, sal_Bool bNoCycle )
6099 {
6100 	ImplToolItem* pToolItem = ImplGetItem( mnHighItemId );
6101 
6102     if( !pToolItem || !mnHighItemId )
6103     {
6104         // menubutton highlighted ?
6105         if( mpData->mbMenubuttonSelected )
6106         {
6107             if( bUp )
6108             {
6109                 // select last valid non-clipped item
6110                 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
6111                 ImplToolItem* pItem = NULL;
6112                 while( it != mpData->m_aItems.begin() )
6113                 {
6114                     --it;
6115 	                if ( ImplIsValidItem( &(*it), sal_True ) )
6116                     {
6117 	                    pItem = &(*it);
6118                         break;
6119                     }
6120                 }
6121                 ImplDrawMenubutton( this, sal_False );
6122                 ImplChangeHighlight( pItem );
6123             }
6124             else
6125             {
6126                 // select first valid non-clipped item
6127                 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
6128                 while( it != mpData->m_aItems.end() )
6129                 {
6130 	                if ( ImplIsValidItem( &(*it), sal_True ) )
6131                         break;
6132                     ++it;
6133                 }
6134                 if( it != mpData->m_aItems.end() )
6135                 {
6136                     ImplDrawMenubutton( this, sal_False );
6137                     ImplChangeHighlight( &(*it) );
6138                 }
6139             }
6140             return sal_True;
6141         }
6142 
6143         if( bUp )
6144         {
6145             // Select first valid item
6146             std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
6147             while( it != mpData->m_aItems.end() )
6148             {
6149                 if ( ImplIsValidItem( &(*it), sal_False ) )
6150                     break;
6151                 ++it;
6152             }
6153 
6154             // select the menu button if a clipped item would be selected
6155             if( (it != mpData->m_aItems.end() && &(*it) == ImplGetFirstClippedItem( this )) && IsMenuEnabled() )
6156             {
6157                 ImplChangeHighlight( NULL );
6158                 ImplDrawMenubutton( this, sal_True );
6159             }
6160             else
6161                 ImplChangeHighlight( (it != mpData->m_aItems.end()) ? &(*it) : NULL );
6162             return sal_True;
6163         }
6164         else
6165         {
6166             // Select last valid item
6167 
6168             // docked toolbars have the menubutton as last item - if this button is enabled
6169             if( IsMenuEnabled() && !ImplIsFloatingMode() )
6170             {
6171                 ImplChangeHighlight( NULL );
6172                 ImplDrawMenubutton( this, sal_True );
6173             }
6174             else
6175             {
6176                 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
6177                 ImplToolItem* pItem = NULL;
6178                 while( it != mpData->m_aItems.begin() )
6179                 {
6180                     --it;
6181 	                if ( ImplIsValidItem( &(*it), sal_False ) )
6182                     {
6183 	                    pItem = &(*it);
6184                         break;
6185                     }
6186                 }
6187                 ImplChangeHighlight( pItem );
6188             }
6189             return sal_True;
6190         }
6191     }
6192 
6193 	if( pToolItem )
6194 	{
6195         sal_uLong pos = ToolBox::ImplFindItemPos( pToolItem, mpData->m_aItems );
6196         sal_uLong nCount = mpData->m_aItems.size();
6197 
6198         sal_uLong i=0;
6199         do
6200         {
6201             if( bUp )
6202             {
6203                 if( !pos-- )
6204                 {
6205                     if( bNoCycle )
6206                         return sal_False;
6207 
6208                     // highlight the menu button if it is the last item
6209                     if( IsMenuEnabled() && !ImplIsFloatingMode() )
6210                     {
6211                         ImplChangeHighlight( NULL );
6212                         ImplDrawMenubutton( this, sal_True );
6213                         return sal_True;
6214                     }
6215                     else
6216                         pos = nCount-1;
6217                 }
6218             }
6219             else
6220             {
6221                 if( ++pos >= nCount )
6222                 {
6223                     if( bNoCycle )
6224                         return sal_False;
6225 
6226                     // highlight the menu button if it is the last item
6227                     if( IsMenuEnabled() && !ImplIsFloatingMode() )
6228                     {
6229                         ImplChangeHighlight( NULL );
6230                         ImplDrawMenubutton( this, sal_True );
6231                         return sal_True;
6232                     }
6233                     else
6234                         pos = 0;
6235                 }
6236             }
6237 
6238             pToolItem = &mpData->m_aItems[pos];
6239 
6240             if ( ImplIsValidItem( pToolItem, sal_False ) )
6241 			    break;
6242 
6243         } while( ++i < nCount);
6244 
6245         if( pToolItem->IsClipped() && IsMenuEnabled() )
6246         {
6247             // select the menu button if a clipped item would be selected
6248             ImplChangeHighlight( NULL );
6249             ImplDrawMenubutton( this, sal_True );
6250         }
6251         else if( i != nCount )
6252             ImplChangeHighlight( pToolItem );
6253         else
6254             return sal_False;
6255     }
6256     return sal_True;
6257 }
6258 
6259 // -----------------------------------------------------------------------
6260 
6261 void ToolBox::ImplShowFocus()
6262 {
6263     if( mnHighItemId && HasFocus() )
6264     {
6265     	ImplToolItem* pItem = ImplGetItem( mnHighItemId );
6266         if( pItem->mpWindow )
6267         {
6268             Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
6269             pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = sal_True;
6270             pWin->Invalidate( 0 );
6271         }
6272     }
6273 }
6274 
6275 // -----------------------------------------------------------------------
6276 
6277 void ToolBox::ImplHideFocus()
6278 {
6279     if( mnHighItemId )
6280     {
6281     	ImplToolItem* pItem = ImplGetItem( mnHighItemId );
6282         if( pItem->mpWindow )
6283         {
6284             Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
6285             pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = sal_False;
6286             pWin->Invalidate( 0 );
6287         }
6288     }
6289 
6290     if ( mpData->mbMenubuttonSelected )
6291     {
6292         // remove highlight from menubutton
6293         ImplDrawMenubutton( this, sal_False );
6294     }
6295 }
6296 
6297 // -----------------------------------------------------------------------
6298 
6299 void ToolBox::ImplDisableFlatButtons()
6300 {
6301 #ifdef WNT        // Check in the Windows registry if an AT tool wants no flat toolboxes
6302 	static bool bInit = false, bValue = false;
6303 	if( ! bInit )
6304 	{
6305 		bInit = true;
6306         HKEY hkey;
6307 
6308 		if( ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER,
6309 			"Software\\OpenOffice.org\\Accessibility\\AtToolSupport",
6310 			&hkey) )
6311 		{
6312 			DWORD dwType = 0;
6313 			sal_uInt8 Data[6]; // possible values: "true", "false", "1", "0", DWORD
6314 			DWORD cbData = sizeof(Data);
6315 
6316 	        if( ERROR_SUCCESS == RegQueryValueEx(hkey, "DisableFlatToolboxButtons",
6317 				NULL, &dwType, Data, &cbData) )
6318 			{
6319 				switch (dwType)
6320 				{
6321 					case REG_SZ:
6322 						bValue = ((0 == stricmp((const char *) Data, "1")) || (0 == stricmp((const char *) Data, "true")));
6323 						break;
6324 					case REG_DWORD:
6325 						bValue = (bool)(((DWORD *) Data)[0]);
6326 						break;
6327 				}
6328 			}
6329 			RegCloseKey(hkey);
6330         }
6331 	}
6332 	if( bValue )
6333 		mnOutStyle &= ~TOOLBOX_STYLE_FLAT;
6334 #endif
6335 }
6336