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