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