bump product version to 4.1.6.2
[LibreOffice.git] / vcl / source / window / toolbox.cxx
blob7582fcedd78ef94669eba345426694ffde29b89d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <rtl/logfile.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/rc.h>
25 #include <tools/poly.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/decoview.hxx>
29 #include <vcl/accel.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/help.hxx>
32 #include <vcl/spin.h>
33 #include <vcl/toolbox.hxx>
34 #include <vcl/bitmap.hxx>
35 #include <vcl/mnemonic.hxx>
36 #include <vcl/gradient.hxx>
37 #include <vcl/menu.hxx>
39 #include <svdata.hxx>
40 #include <window.h>
41 #include <toolbox.h>
42 #include <salframe.hxx>
43 #if defined WNT
44 #include <svsys.h>
45 #endif
47 #include <string.h>
48 #include <vector>
49 #include <math.h>
51 // =======================================================================
53 DBG_NAMEEX( Window )
55 // =======================================================================
57 #define SMALLBUTTON_HSIZE 7
58 #define SMALLBUTTON_VSIZE 7
60 #define SMALLBUTTON_OFF_NORMAL_X 3
61 #define SMALLBUTTON_OFF_NORMAL_Y 3
63 // -----------------------------------------------------------------------
65 #define TB_TEXTOFFSET 2
66 #define TB_IMAGETEXTOFFSET 3
67 #define TB_LINESPACING 3
68 #define TB_SPIN_SIZE 14
69 #define TB_SPIN_OFFSET 2
70 #define TB_BORDER_OFFSET1 4
71 #define TB_BORDER_OFFSET2 2
72 #define TB_CUSTOMIZE_OFFSET 2
73 #define TB_RESIZE_OFFSET 3
74 #define TB_MAXLINES 5
75 #define TB_MAXNOSCROLL 32765
77 #define TB_MIN_WIN_WIDTH 20
79 #define TB_CALCMODE_HORZ 1
80 #define TB_CALCMODE_VERT 2
81 #define TB_CALCMODE_FLOAT 3
83 #define TB_WBLINESIZING (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)
85 #define DOCK_LINEHSIZE ((sal_uInt16)0x0001)
86 #define DOCK_LINEVSIZE ((sal_uInt16)0x0002)
87 #define DOCK_LINERIGHT ((sal_uInt16)0x1000)
88 #define DOCK_LINEBOTTOM ((sal_uInt16)0x2000)
89 #define DOCK_LINELEFT ((sal_uInt16)0x4000)
90 #define DOCK_LINETOP ((sal_uInt16)0x8000)
91 #define DOCK_LINEOFFSET 3
94 // -----------------------------------------------------------------------
95 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bEnabled, sal_Bool bIsWindow );
96 // -----------------------------------------------------------------------
98 typedef ::std::vector< ToolBox* > ImplTBList;
100 class ImplTBDragMgr
102 private:
103 ImplTBList* mpBoxList;
104 ToolBox* mpDragBox;
105 Point maMouseOff;
106 Rectangle maRect;
107 Rectangle maStartRect;
108 Accelerator maAccel;
109 long mnMinWidth;
110 long mnMaxWidth;
111 sal_uInt16 mnLineMode;
112 sal_uInt16 mnStartLines;
113 void* mpCustomizeData;
114 sal_Bool mbCustomizeMode;
115 sal_Bool mbResizeMode;
116 sal_Bool mbShowDragRect;
118 public:
119 ImplTBDragMgr();
120 ~ImplTBDragMgr();
122 void push_back( ToolBox* pBox )
123 { mpBoxList->push_back( pBox ); }
124 void erase( ToolBox* pBox )
126 for ( ImplTBList::iterator it = mpBoxList->begin(); it != mpBoxList->end(); ++it ) {
127 if ( *it == pBox ) {
128 mpBoxList->erase( it );
129 break;
133 size_t size() const
134 { return mpBoxList->size(); }
136 ToolBox* FindToolBox( const Rectangle& rRect );
138 void StartDragging( ToolBox* pDragBox,
139 const Point& rPos, const Rectangle& rRect,
140 sal_uInt16 nLineMode, sal_Bool bResizeItem,
141 void* pData = NULL );
142 void Dragging( const Point& rPos );
143 void EndDragging( sal_Bool bOK = sal_True );
144 void HideDragRect() { if ( mbShowDragRect ) mpDragBox->HideTracking(); }
145 void UpdateDragRect();
146 DECL_LINK( SelectHdl, Accelerator* );
148 sal_Bool IsCustomizeMode() { return mbCustomizeMode; }
149 sal_Bool IsResizeMode() { return mbResizeMode; }
152 // -----------------------------------------------------------------------
154 static ImplTBDragMgr* ImplGetTBDragMgr()
156 ImplSVData* pSVData = ImplGetSVData();
157 if ( !pSVData->maCtrlData.mpTBDragMgr )
158 pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr;
159 return pSVData->maCtrlData.mpTBDragMgr;
162 // -----------------------------------------------------------------------
164 int ToolBox::ImplGetDragWidth( ToolBox* pThis )
166 #define TB_DRAGWIDTH 8 // the default width of the grip
168 int width = TB_DRAGWIDTH;
169 if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
172 ImplControlValue aControlValue;
173 Point aPoint;
174 Rectangle aContent, aBound;
175 Rectangle aArea( aPoint, pThis->GetOutputSizePixel() );
177 if ( pThis->GetNativeControlRegion(CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
178 aArea, 0, aControlValue, OUString(), aBound, aContent) )
180 width = pThis->mbHorz ? aContent.GetWidth() : aContent.GetHeight();
183 return width;
186 ButtonType determineButtonType( ImplToolItem* pItem, ButtonType defaultType )
188 ButtonType tmpButtonType = defaultType;
189 ToolBoxItemBits nBits( pItem->mnBits & 0x300 );
190 if ( nBits & TIB_TEXTICON ) // item has custom setting
192 tmpButtonType = BUTTON_SYMBOLTEXT;
193 if ( nBits == TIB_TEXT_ONLY )
194 tmpButtonType = BUTTON_TEXT;
195 else if ( nBits == TIB_ICON_ONLY )
196 tmpButtonType = BUTTON_SYMBOL;
198 return tmpButtonType;
201 // -----------------------------------------------------------------------
203 void ToolBox::ImplUpdateDragArea( ToolBox *pThis )
205 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
206 if( pWrapper )
208 if ( pThis->ImplIsFloatingMode() || pWrapper->IsLocked() )
209 pWrapper->SetDragArea( Rectangle() );
210 else
212 if( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
213 pWrapper->SetDragArea( Rectangle( 0, 0, ImplGetDragWidth( pThis ), pThis->GetOutputSizePixel().Height() ) );
214 else
215 pWrapper->SetDragArea( Rectangle( 0, 0, pThis->GetOutputSizePixel().Width(), ImplGetDragWidth( pThis ) ) );
220 // -----------------------------------------------------------------------
222 void ToolBox::ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop,
223 long& rRight, long& rBottom, const ToolBox *pThis )
225 if( pThis->ImplIsFloatingMode() || !(pThis->mnWinStyle & WB_BORDER) )
227 // no border in floating mode
228 rLeft = rTop = rRight = rBottom = 0;
229 return;
232 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
234 // reserve dragarea only for dockable toolbars
235 int dragwidth = ( pWrapper && !pWrapper->IsLocked() ) ? ImplGetDragWidth( (ToolBox*)pThis ) : 0;
237 // no shadow border for dockable toolbars
238 int borderwidth = pWrapper ? 0: 2;
240 if ( eAlign == WINDOWALIGN_TOP )
242 rLeft = borderwidth+dragwidth;
243 rTop = borderwidth;
244 rRight = borderwidth;
245 rBottom = 0;
247 else if ( eAlign == WINDOWALIGN_LEFT )
249 rLeft = borderwidth;
250 rTop = borderwidth+dragwidth;
251 rRight = 0;
252 rBottom = borderwidth;
254 else if ( eAlign == WINDOWALIGN_BOTTOM )
256 rLeft = borderwidth+dragwidth;
257 rTop = 0;
258 rRight = borderwidth;
259 rBottom = borderwidth;
261 else
263 rLeft = 0;
264 rTop = borderwidth+dragwidth;
265 rRight = borderwidth;
266 rBottom = borderwidth;
270 // -----------------------------------------------------------------------
272 static void ImplCheckUpdate( ToolBox *pThis )
274 // remove any pending invalidates to avoid
275 // have them triggered when paint is locked (see mpData->mbIsPaintLocked)
276 // which would result in erasing the background only and not painting any items
277 // this must not be done when we're already in Paint()
279 // this is only required for transparent toolbars (see ImplDrawTransparentBackground() )
280 if( !pThis->IsBackground() && pThis->HasPaintEvent() && !pThis->IsInPaint() )
281 pThis->Update();
284 // -----------------------------------------------------------------------
286 void ToolBox::ImplDrawGrip( ToolBox* pThis )
288 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
289 if( pWrapper && !pWrapper->GetDragArea().IsEmpty() )
291 // execute pending paint requests
292 ImplCheckUpdate( pThis );
294 sal_Bool bNativeOk = sal_False;
295 if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_HORZ : PART_THUMB_VERT ) )
297 ToolbarValue aToolbarValue;
298 aToolbarValue.maGripRect = pWrapper->GetDragArea();
299 Point aPt;
300 Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
301 ControlState nState = CTRL_STATE_ENABLED;
303 bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
304 aCtrlRegion, nState, aToolbarValue, OUString() );
307 if( bNativeOk )
308 return;
310 const StyleSettings& rStyleSettings = pThis->GetSettings().GetStyleSettings();
311 pThis->SetLineColor( rStyleSettings.GetShadowColor() );
313 Size aSz ( pThis->GetOutputSizePixel() );
315 if ( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
317 int height = (int) (0.6 * aSz.Height() + 0.5);
318 int i = (aSz.Height() - height) / 2;
319 height += i;
320 while( i <= height )
322 int x = ImplGetDragWidth( pThis ) / 2;
324 pThis->DrawPixel( Point(x, i), rStyleSettings.GetDarkShadowColor() );
325 pThis->DrawPixel( Point(x+1, i), rStyleSettings.GetShadowColor() );
327 pThis->DrawPixel( Point(x, i+1), rStyleSettings.GetShadowColor() );
328 pThis->DrawPixel( Point(x+1, i+1), rStyleSettings.GetFaceColor() );
329 pThis->DrawPixel( Point(x+2, i+1), Color(COL_WHITE) );
331 pThis->DrawPixel( Point(x+1, i+2), Color(COL_WHITE) );
332 pThis->DrawPixel( Point(x+2, i+2), Color(COL_WHITE) );
333 i+=4;
336 else
338 int width = (int) (0.6 * aSz.Width() + 0.5);
339 int i = (aSz.Width() - width) / 2;
340 width += i;
341 while( i <= width )
343 int y = ImplGetDragWidth(pThis) / 2;
345 pThis->DrawPixel( Point(i, y), rStyleSettings.GetDarkShadowColor() );
346 pThis->DrawPixel( Point(i+1, y), rStyleSettings.GetShadowColor() );
348 pThis->DrawPixel( Point(i, y+1), rStyleSettings.GetShadowColor() );
349 pThis->DrawPixel( Point(i+1, y+1), rStyleSettings.GetFaceColor() );
350 pThis->DrawPixel( Point(i+2, y+1), Color(COL_WHITE) );
352 pThis->DrawPixel( Point(i+1, y+2), Color(COL_WHITE) );
353 pThis->DrawPixel( Point(i+2, y+2), Color(COL_WHITE) );
354 i+=4;
360 void ToolBox::ImplDrawGradientBackground( ToolBox* pThis, ImplDockingWindowWrapper * )
362 // draw a nice gradient
364 Color startCol, endCol;
365 startCol = pThis->GetSettings().GetStyleSettings().GetFaceGradientColor();
366 endCol = pThis->GetSettings().GetStyleSettings().GetFaceColor();
367 if( pThis->GetSettings().GetStyleSettings().GetHighContrastMode() )
368 // no 'extreme' gradient when high contrast
369 startCol = endCol;
371 Gradient g;
372 g.SetAngle( pThis->mbHorz ? 0 : 900 );
373 g.SetStyle( GradientStyle_LINEAR );
375 g.SetStartColor( startCol );
376 g.SetEndColor( endCol );
378 sal_Bool bLineColor = pThis->IsLineColor();
379 Color aOldCol = pThis->GetLineColor();
380 pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
382 Size aFullSz( pThis->GetOutputSizePixel() );
383 Size aLineSz( aFullSz );
385 // use the linesize only when floating
386 // full window height is used when docked (single line)
387 if( pThis->ImplIsFloatingMode() )
389 long nLineSize;
390 if( pThis->mbHorz )
392 nLineSize = pThis->mnMaxItemHeight;
393 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
394 nLineSize = pThis->mnWinHeight;
396 aLineSz.Height() = nLineSize;
398 else
400 nLineSize = pThis->mnMaxItemWidth;
401 aLineSz.Width() = nLineSize;
405 long nLeft, nTop, nRight, nBottom;
406 ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
408 Size aTopLineSz( aLineSz );
409 Size aBottomLineSz( aLineSz );
411 if ( pThis->mnWinStyle & WB_BORDER )
413 if( pThis->mbHorz )
415 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nTop;
416 aBottomLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
418 if( pThis->mnCurLines == 1 )
419 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
421 else
423 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
424 aBottomLineSz.Width() += TB_BORDER_OFFSET1 + nRight;
426 if( pThis->mnCurLines == 1 )
427 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
431 if ( pThis->mnWinStyle & WB_LINESPACING )
433 if( pThis->mbHorz )
435 aLineSz.Height() += TB_LINESPACING;
436 if( pThis->mnCurLines > 1 )
437 aTopLineSz.Height() += TB_LINESPACING;
439 else
441 aLineSz.Width() += TB_LINESPACING;
442 if( pThis->mnCurLines > 1 )
443 aTopLineSz.Width() += TB_LINESPACING;
447 if( pThis->mbHorz )
449 long y = 0;
450 sal_Bool bDrawSep = sal_False; // pThis->ImplIsFloatingMode() && ( pThis->mnWinStyle & WB_LINESPACING );
452 pThis->DrawGradient( Rectangle( 0, y, aTopLineSz.Width(), y+aTopLineSz.Height()), g );
453 y += aTopLineSz.Height();
455 if ( bDrawSep )
456 pThis->DrawLine( Point(0, y-2), Point(aTopLineSz.Width(), y-2) );
458 while( y < (pThis->mnDY - aBottomLineSz.Height()) )
460 pThis->DrawGradient( Rectangle( 0, y, aLineSz.Width(), y+aLineSz.Height()), g);
461 y += aLineSz.Height();
463 if ( bDrawSep )
464 pThis->DrawLine( Point(0, y-2), Point(aLineSz.Width(), y-2) );
467 pThis->DrawGradient( Rectangle( 0, y, aBottomLineSz.Width(), y+aBottomLineSz.Height()), g );
468 if ( bDrawSep )
469 pThis->DrawLine( Point(0, y-2), Point(aBottomLineSz.Width(), y-2) );
471 else
473 long x = 0;
475 pThis->DrawGradient( Rectangle( x, 0, x+aTopLineSz.Width(), aTopLineSz.Height()), g );
476 x += aTopLineSz.Width();
478 while( x < (pThis->mnDX - aBottomLineSz.Width()) )
480 pThis->DrawGradient( Rectangle( x, 0, x+aLineSz.Width(), aLineSz.Height()), g);
481 x += aLineSz.Width();
484 pThis->DrawGradient( Rectangle( x, 0, x+aBottomLineSz.Width(), aBottomLineSz.Height()), g );
487 if( bLineColor )
488 pThis->SetLineColor( aOldCol );
492 sal_Bool ToolBox::ImplDrawNativeBackground( ToolBox* pThis, const Region & )
494 // use NWF
495 Point aPt;
496 Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
497 ControlState nState = CTRL_STATE_ENABLED;
499 return pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
500 aCtrlRegion, nState, ImplControlValue(), OUString() );
503 void ToolBox::ImplDrawTransparentBackground( ToolBox* pThis, const Region &rRegion )
505 // just invalidate to trigger paint of the parent
507 const bool bOldPaintLock = pThis->mpData->mbIsPaintLocked;
508 pThis->mpData->mbIsPaintLocked = true;
510 // send an invalidate to the first opaque parent and invalidate the whole hierarchy from there (noclipchildren)
511 pThis->Invalidate( rRegion, INVALIDATE_UPDATE|INVALIDATE_NOCLIPCHILDREN );
513 pThis->mpData->mbIsPaintLocked = bOldPaintLock;
516 void ToolBox::ImplDrawConstantBackground( ToolBox* pThis, const Region &rRegion, sal_Bool bIsInPopupMode )
518 // draw a constant color
519 if( !bIsInPopupMode )
520 // default background
521 pThis->Erase( rRegion.GetBoundRect() );
522 else
524 // use different color in popupmode
525 pThis->DrawWallpaper( rRegion.GetBoundRect(),
526 Wallpaper( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() ) );
531 void ToolBox::ImplDrawBackground( ToolBox* pThis, const Rectangle &rRect )
533 // execute pending paint requests
534 ImplCheckUpdate( pThis );
536 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
537 sal_Bool bIsInPopupMode = pThis->ImplIsInPopupMode();
539 Region aPaintRegion( rRect );
541 // make sure we do not invalidate/erase too much
542 if( pThis->IsInPaint() )
543 aPaintRegion.Intersect( pThis->GetActiveClipRegion() );
545 pThis->Push( PUSH_CLIPREGION );
546 pThis->IntersectClipRegion( aPaintRegion );
549 if( !pWrapper /*|| bIsInPopupMode*/ )
551 // no gradient for ordinary toolbars (not dockable)
552 if( !pThis->IsBackground() && !pThis->IsInPaint() )
553 ImplDrawTransparentBackground( pThis, aPaintRegion );
554 else
555 ImplDrawConstantBackground( pThis, aPaintRegion, bIsInPopupMode );
557 else
559 // toolbars known to the dockingmanager will be drawn using NWF or a gradient
560 // docked toolbars are transparent and NWF is already used in the docking area which is their common background
561 // so NWF is used here for floating toolbars only
562 sal_Bool bNativeOk = sal_False;
563 if( pThis->ImplIsFloatingMode() && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL) )
564 bNativeOk = ImplDrawNativeBackground( pThis, aPaintRegion );
566 if( !bNativeOk )
568 if( !pThis->IsBackground() ||
569 ( pThis->GetAlign() == WINDOWALIGN_TOP && !Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty() ) )
571 if( !pThis->IsInPaint() )
572 ImplDrawTransparentBackground( pThis, aPaintRegion );
574 else
575 ImplDrawGradientBackground( pThis, pWrapper );
579 // restore clip region
580 pThis->Pop();
583 void ToolBox::ImplErase( ToolBox* pThis, const Rectangle &rRect, sal_Bool bHighlight, sal_Bool bHasOpenPopup )
585 // the background of non NWF buttons is painted in a constant color
586 // to have the same highlight color (transparency in DrawSelectionBackground())
587 // items with open popups will also painted using a constant color
588 if( !pThis->mpData->mbNativeButtons &&
589 (bHighlight || ! (((Window*) pThis)->GetStyle() & WB_3DLOOK ) ) )
591 if( (((Window*) pThis)->GetStyle() & WB_3DLOOK ) )
593 pThis->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
594 pThis->SetLineColor();
595 if( bHasOpenPopup )
596 // choose the same color as the popup will use
597 pThis->SetFillColor( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() );
598 else
599 pThis->SetFillColor( Color( COL_WHITE ) );
601 pThis->DrawRect( rRect );
602 pThis->Pop();
604 else
605 ImplDrawBackground( pThis, rRect );
607 else
608 ImplDrawBackground( pThis, rRect );
611 void ToolBox::ImplDrawBorder( ToolBox* pWin )
613 const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
614 long nDX = pWin->mnDX;
615 long nDY = pWin->mnDY;
617 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pWin );
619 // draw borders for ordinary toolbars only (not dockable)
620 if( pWrapper )
621 return;
623 if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
625 // draw bottom border
626 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
627 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
628 pWin->SetLineColor( rStyleSettings.GetLightColor() );
629 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
631 else
633 // draw top border
634 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
635 pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
636 pWin->SetLineColor( rStyleSettings.GetLightColor() );
637 pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
639 if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
641 if ( pWin->meAlign == WINDOWALIGN_LEFT )
643 // draw left-bottom border
644 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
645 pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
646 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
647 pWin->SetLineColor( rStyleSettings.GetLightColor() );
648 pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
649 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
651 else
653 // draw right-bottom border
654 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
655 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
656 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
657 pWin->SetLineColor( rStyleSettings.GetLightColor() );
658 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
659 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
665 if ( pWin->meAlign == WINDOWALIGN_BOTTOM || pWin->meAlign == WINDOWALIGN_TOP )
667 // draw right border
668 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
669 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) );
670 pWin->SetLineColor( rStyleSettings.GetLightColor() );
671 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
675 // -----------------------------------------------------------------------
677 static bool ImplIsFixedControl( const ImplToolItem *pItem )
679 return ( pItem->mpWindow &&
680 (pItem->mpWindow->GetType() == WINDOW_FIXEDTEXT ||
681 pItem->mpWindow->GetType() == WINDOW_FIXEDLINE ||
682 pItem->mpWindow->GetType() == WINDOW_GROUPBOX) );
685 // -----------------------------------------------------------------------
687 const ImplToolItem *ToolBox::ImplGetFirstClippedItem( const ToolBox* pThis )
689 std::vector< ImplToolItem >::const_iterator it;
690 it = pThis->mpData->m_aItems.begin();
691 while ( it != pThis->mpData->m_aItems.end() )
693 if( it->IsClipped() )
694 return &(*it);
695 ++it;
697 return NULL;
700 // -----------------------------------------------------------------------
702 Size ToolBox::ImplCalcSize( const ToolBox* pThis, sal_uInt16 nCalcLines, sal_uInt16 nCalcMode )
704 long nMax;
705 long nLeft = 0;
706 long nTop = 0;
707 long nRight = 0;
708 long nBottom = 0;
709 Size aSize;
710 WindowAlign eOldAlign = pThis->meAlign;
711 sal_Bool bOldHorz = pThis->mbHorz;
712 sal_Bool bOldAssumeDocked = pThis->mpData->mbAssumeDocked;
713 sal_Bool bOldAssumeFloating = pThis->mpData->mbAssumeFloating;
715 if ( nCalcMode )
717 sal_Bool bOldFloatingMode = pThis->ImplIsFloatingMode();
719 pThis->mpData->mbAssumeDocked = sal_False;
720 pThis->mpData->mbAssumeFloating = sal_False;
722 if ( nCalcMode == TB_CALCMODE_HORZ )
724 pThis->mpData->mbAssumeDocked = sal_True; // force non-floating mode during calculation
725 ImplCalcBorder( WINDOWALIGN_TOP, nLeft, nTop, nRight, nBottom, pThis );
726 ((ToolBox*)pThis)->mbHorz = sal_True;
727 if ( pThis->mbHorz != bOldHorz )
728 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
730 else if ( nCalcMode == TB_CALCMODE_VERT )
732 pThis->mpData->mbAssumeDocked = sal_True; // force non-floating mode during calculation
733 ImplCalcBorder( WINDOWALIGN_LEFT, nLeft, nTop, nRight, nBottom, pThis );
734 ((ToolBox*)pThis)->mbHorz = sal_False;
735 if ( pThis->mbHorz != bOldHorz )
736 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_LEFT;
738 else if ( nCalcMode == TB_CALCMODE_FLOAT )
740 pThis->mpData->mbAssumeFloating = sal_True; // force non-floating mode during calculation
741 nLeft = nTop = nRight = nBottom = 0;
742 ((ToolBox*)pThis)->mbHorz = sal_True;
743 if ( pThis->mbHorz != bOldHorz )
744 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
747 if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) ||
748 (pThis->ImplIsFloatingMode() != bOldFloatingMode ) )
749 ((ToolBox*)pThis)->mbCalc = sal_True;
751 else
752 ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
754 ((ToolBox*)pThis)->ImplCalcItem();
756 if( !nCalcMode && pThis->ImplIsFloatingMode() )
758 aSize = ImplCalcFloatSize( ((ToolBox*)pThis), nCalcLines );
760 else
762 if ( pThis->mbHorz )
764 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
765 aSize.Height() = nCalcLines * pThis->mnWinHeight;
766 else
767 aSize.Height() = nCalcLines * pThis->mnMaxItemHeight;
769 if ( pThis->mnWinStyle & WB_LINESPACING )
770 aSize.Height() += (nCalcLines-1)*TB_LINESPACING;
772 if ( pThis->mnWinStyle & WB_BORDER )
773 aSize.Height() += (TB_BORDER_OFFSET2*2) + nTop + nBottom;
775 nMax = 0;
776 ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
777 if ( nMax )
778 aSize.Width() += nMax;
780 if ( pThis->mnWinStyle & WB_BORDER )
781 aSize.Width() += (TB_BORDER_OFFSET1*2) + nLeft + nRight;
783 else
785 aSize.Width() = nCalcLines * pThis->mnMaxItemWidth;
787 if ( pThis->mnWinStyle & WB_LINESPACING )
788 aSize.Width() += (nCalcLines-1)*TB_LINESPACING;
790 if ( pThis->mnWinStyle & WB_BORDER )
791 aSize.Width() += (TB_BORDER_OFFSET2*2) + nLeft + nRight;
793 nMax = 0;
794 ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
795 if ( nMax )
796 aSize.Height() += nMax;
798 if ( pThis->mnWinStyle & WB_BORDER )
799 aSize.Height() += (TB_BORDER_OFFSET1*2) + nTop + nBottom;
802 // restore previous values
803 if ( nCalcMode )
805 pThis->mpData->mbAssumeDocked = bOldAssumeDocked;
806 pThis->mpData->mbAssumeFloating = bOldAssumeFloating;
807 if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
809 ((ToolBox*)pThis)->meAlign = eOldAlign;
810 ((ToolBox*)pThis)->mbHorz = bOldHorz;
811 ((ToolBox*)pThis)->mbCalc = sal_True;
815 return aSize;
818 // -----------------------------------------------------------------------
820 void ToolBox::ImplCalcFloatSizes( ToolBox* pThis )
822 if ( !pThis->maFloatSizes.empty() )
823 return;
825 // calculate the minimal size, i.e. where the biggest item just fits
826 long nCalcSize = 0;
828 std::vector< ImplToolItem >::const_iterator it;
829 it = pThis->mpData->m_aItems.begin();
830 while ( it != pThis->mpData->m_aItems.end() )
832 if ( it->mbVisible )
834 if ( it->mpWindow )
836 long nTempSize = it->mpWindow->GetSizePixel().Width();
837 if ( nTempSize > nCalcSize )
838 nCalcSize = nTempSize;
840 else
842 if( it->maItemSize.Width() > nCalcSize )
843 nCalcSize = it->maItemSize.Width();
846 ++it;
849 // calc an upper bound for ImplCalcBreaks below
850 long upperBoundWidth = nCalcSize * pThis->mpData->m_aItems.size();
852 sal_uInt16 nLines;
853 sal_uInt16 nCalcLines;
854 sal_uInt16 nTempLines;
855 long nMaxLineWidth;
856 nCalcLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, sal_True );
858 pThis->maFloatSizes.reserve( nCalcLines );
860 nTempLines = nLines = nCalcLines;
861 while ( nLines )
863 long nHeight = ImplCalcSize( pThis, nTempLines, TB_CALCMODE_FLOAT ).Height();
865 ImplToolSize aSize;
866 aSize.mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET1*2);
867 aSize.mnHeight = nHeight;
868 aSize.mnLines = nTempLines;
869 pThis->maFloatSizes.push_back( aSize );
870 nLines--;
871 if ( nLines )
875 nCalcSize += pThis->mnMaxItemWidth;
876 nTempLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, sal_True );
878 while ( (nCalcSize < upperBoundWidth) && (nLines < nTempLines) && (nTempLines != 1) );
879 if ( nTempLines < nLines )
880 nLines = nTempLines;
885 // -----------------------------------------------------------------------
887 Size ToolBox::ImplCalcFloatSize( ToolBox* pThis, sal_uInt16& rLines )
889 ImplCalcFloatSizes( pThis );
891 if ( !rLines )
893 rLines = pThis->mnFloatLines;
894 if ( !rLines )
895 rLines = pThis->mnLines;
898 sal_uInt16 i = 0;
899 while ( i + 1u < pThis->maFloatSizes.size() &&
900 rLines < pThis->maFloatSizes[i].mnLines )
902 i++;
905 Size aSize( pThis->maFloatSizes[i].mnWidth,
906 pThis->maFloatSizes[i].mnHeight );
907 rLines = pThis->maFloatSizes[i].mnLines;
909 return aSize;
912 // -----------------------------------------------------------------------
914 void ToolBox::ImplCalcMinMaxFloatSize( ToolBox* pThis, Size& rMinSize, Size& rMaxSize )
916 ImplCalcFloatSizes( pThis );
918 sal_uInt16 i = 0;
919 rMinSize = Size( pThis->maFloatSizes[i].mnWidth, pThis->maFloatSizes[i].mnHeight );
920 rMaxSize = Size( pThis->maFloatSizes[i].mnWidth, pThis->maFloatSizes[i].mnHeight );
921 while ( ++i < pThis->maFloatSizes.size() )
923 if( pThis->maFloatSizes[i].mnWidth < rMinSize.Width() )
924 rMinSize.Width() = pThis->maFloatSizes[i].mnWidth;
925 if( pThis->maFloatSizes[i].mnHeight < rMinSize.Height() )
926 rMinSize.Height() = pThis->maFloatSizes[i].mnHeight;
928 if( pThis->maFloatSizes[i].mnWidth > rMaxSize.Width() )
929 rMaxSize.Width() = pThis->maFloatSizes[i].mnWidth;
930 if( pThis->maFloatSizes[i].mnHeight > rMaxSize.Height() )
931 rMaxSize.Height() = pThis->maFloatSizes[i].mnHeight;
935 void ToolBox::ImplSetMinMaxFloatSize( ToolBox *pThis )
937 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
938 Size aMinSize, aMaxSize;
939 ImplCalcMinMaxFloatSize( pThis, aMinSize, aMaxSize );
940 if( pWrapper )
942 pWrapper->SetMinOutputSizePixel( aMinSize );
943 pWrapper->SetMaxOutputSizePixel( aMaxSize );
944 pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) ? sal_True : sal_False );
946 else
948 // TODO: change SetMinOutputSizePixel to be not inline
949 pThis->SetMinOutputSizePixel( aMinSize );
950 pThis->SetMaxOutputSizePixel( aMaxSize );
954 // -----------------------------------------------------------------------
957 sal_uInt16 ToolBox::ImplCalcLines( ToolBox* pThis, long nToolSize )
959 long nLineHeight;
961 if ( pThis->mbHorz )
963 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
964 nLineHeight = pThis->mnWinHeight;
965 else
966 nLineHeight = pThis->mnMaxItemHeight;
968 else
969 nLineHeight = pThis->mnMaxItemWidth;
971 if ( pThis->mnWinStyle & WB_BORDER )
972 nToolSize -= TB_BORDER_OFFSET2*2;
974 if ( pThis->mnWinStyle & WB_LINESPACING )
976 nLineHeight += TB_LINESPACING;
977 nToolSize += TB_LINESPACING;
980 // #i91917# always report at least one line
981 long nLines = nToolSize/nLineHeight;
982 if( nLines < 1 )
983 nLines = 1;
985 return static_cast<sal_uInt16>(nLines);
988 // -----------------------------------------------------------------------
990 sal_uInt16 ToolBox::ImplTestLineSize( ToolBox* pThis, const Point& rPos )
992 if ( !pThis->ImplIsFloatingMode() &&
993 (!pThis->mbScroll || (pThis->mnLines > 1) || (pThis->mnCurLines > pThis->mnVisLines)) )
995 WindowAlign eAlign = pThis->GetAlign();
997 if ( eAlign == WINDOWALIGN_LEFT )
999 if ( rPos.X() > pThis->mnDX-DOCK_LINEOFFSET )
1000 return DOCK_LINEHSIZE | DOCK_LINERIGHT;
1002 else if ( eAlign == WINDOWALIGN_TOP )
1004 if ( rPos.Y() > pThis->mnDY-DOCK_LINEOFFSET )
1005 return DOCK_LINEVSIZE | DOCK_LINEBOTTOM;
1007 else if ( eAlign == WINDOWALIGN_RIGHT )
1009 if ( rPos.X() < DOCK_LINEOFFSET )
1010 return DOCK_LINEHSIZE | DOCK_LINELEFT;
1012 else if ( eAlign == WINDOWALIGN_BOTTOM )
1014 if ( rPos.Y() < DOCK_LINEOFFSET )
1015 return DOCK_LINEVSIZE | DOCK_LINETOP;
1019 return 0;
1022 // -----------------------------------------------------------------------
1024 void ToolBox::ImplLineSizing( ToolBox* pThis, const Point& rPos, Rectangle& rRect,
1025 sal_uInt16 nLineMode )
1027 sal_Bool mbHorz;
1028 long nOneLineSize;
1029 long nCurSize;
1030 long nMaxSize;
1031 long nSize;
1032 Size aSize;
1034 if ( nLineMode & DOCK_LINERIGHT )
1036 nCurSize = rPos.X() - rRect.Left();
1037 mbHorz = sal_False;
1039 else if ( nLineMode & DOCK_LINEBOTTOM )
1041 nCurSize = rPos.Y() - rRect.Top();
1042 mbHorz = sal_True;
1044 else if ( nLineMode & DOCK_LINELEFT )
1046 nCurSize = rRect.Right() - rPos.X();
1047 mbHorz = sal_False;
1049 else if ( nLineMode & DOCK_LINETOP )
1051 nCurSize = rRect.Bottom() - rPos.Y();
1052 mbHorz = sal_True;
1054 else {
1055 OSL_FAIL( "ImplLineSizing: Trailing else" );
1056 nCurSize = 0;
1057 mbHorz = sal_False;
1060 Size aWinSize = pThis->GetSizePixel();
1061 sal_uInt16 nMaxLines = (pThis->mnLines > pThis->mnCurLines) ? pThis->mnLines : pThis->mnCurLines;
1062 if ( nMaxLines > TB_MAXLINES )
1063 nMaxLines = TB_MAXLINES;
1064 if ( mbHorz )
1066 nOneLineSize = ImplCalcSize( pThis, 1 ).Height();
1067 nMaxSize = pThis->maOutDockRect.GetHeight() - 20;
1068 if ( nMaxSize < aWinSize.Height() )
1069 nMaxSize = aWinSize.Height();
1071 else
1073 nOneLineSize = ImplCalcSize( pThis, 1 ).Width();
1074 nMaxSize = pThis->maOutDockRect.GetWidth() - 20;
1075 if ( nMaxSize < aWinSize.Width() )
1076 nMaxSize = aWinSize.Width();
1079 sal_uInt16 i = 1;
1080 if ( nCurSize <= nOneLineSize )
1081 nSize = nOneLineSize;
1082 else
1084 nSize = 0;
1085 while ( (nSize < nCurSize) && (i < nMaxLines) )
1087 i++;
1088 aSize = ImplCalcSize( pThis, i );
1089 if ( mbHorz )
1090 nSize = aSize.Height();
1091 else
1092 nSize = aSize.Width();
1093 if ( nSize > nMaxSize )
1095 i--;
1096 aSize = ImplCalcSize( pThis, i );
1097 if ( mbHorz )
1098 nSize = aSize.Height();
1099 else
1100 nSize = aSize.Width();
1101 break;
1106 if ( nLineMode & DOCK_LINERIGHT )
1107 rRect.Right() = rRect.Left()+nSize-1;
1108 else if ( nLineMode & DOCK_LINEBOTTOM )
1109 rRect.Bottom() = rRect.Top()+nSize-1;
1110 else if ( nLineMode & DOCK_LINELEFT )
1111 rRect.Left() = rRect.Right()-nSize;
1112 else
1113 rRect.Top() = rRect.Bottom()-nSize;
1115 pThis->mnDockLines = i;
1118 // -----------------------------------------------------------------------
1120 sal_uInt16 ToolBox::ImplFindItemPos( ToolBox* pBox, const Point& rPos )
1122 sal_uInt16 nPos = 0;
1123 long nLast = 0;
1124 Point aPos = rPos;
1125 Size aSize( pBox->mnDX, pBox->mnDY );
1127 if ( aPos.X() > aSize.Width()-TB_BORDER_OFFSET1 )
1128 aPos.X() = aSize.Width()-TB_BORDER_OFFSET1;
1129 if ( aPos.Y() > aSize.Height()-TB_BORDER_OFFSET1 )
1130 aPos.Y() = aSize.Height()-TB_BORDER_OFFSET1;
1132 // Item suchen, das geklickt wurde
1133 std::vector< ImplToolItem >::const_iterator it = pBox->mpData->m_aItems.begin();
1134 while ( it != pBox->mpData->m_aItems.end() )
1136 if ( it->mbVisible )
1138 if ( nLast || !it->maRect.IsEmpty() )
1140 if ( pBox->mbHorz )
1142 if ( nLast &&
1143 ((nLast < it->maRect.Top()) || it->maRect.IsEmpty()) )
1144 return nPos;
1146 if ( aPos.Y() <= it->maRect.Bottom() )
1148 if ( aPos.X() < it->maRect.Left() )
1149 return nPos;
1150 else if ( aPos.X() < it->maRect.Right() )
1151 return nPos+1;
1152 else if ( !nLast )
1153 nLast = it->maRect.Bottom();
1156 else
1158 if ( nLast &&
1159 ((nLast < it->maRect.Left()) || it->maRect.IsEmpty()) )
1160 return nPos;
1162 if ( aPos.X() <= it->maRect.Right() )
1164 if ( aPos.Y() < it->maRect.Top() )
1165 return nPos;
1166 else if ( aPos.Y() < it->maRect.Bottom() )
1167 return nPos+1;
1168 else if ( !nLast )
1169 nLast = it->maRect.Right();
1175 nPos++;
1176 ++it;
1179 return nPos;
1182 // -----------------------------------------------------------------------
1184 ImplTBDragMgr::ImplTBDragMgr()
1186 mpBoxList = new ImplTBList();
1187 mnLineMode = 0;
1188 mnStartLines = 0;
1189 mbCustomizeMode = sal_False;
1190 mbResizeMode = sal_False;
1191 mbShowDragRect = sal_False;
1192 mpDragBox = NULL;
1194 maAccel.InsertItem( KEY_RETURN, KeyCode( KEY_RETURN ) );
1195 maAccel.InsertItem( KEY_ESCAPE, KeyCode( KEY_ESCAPE ) );
1196 maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl ) );
1199 // -----------------------------------------------------------------------
1201 ImplTBDragMgr::~ImplTBDragMgr()
1203 delete mpBoxList;
1206 // -----------------------------------------------------------------------
1208 ToolBox* ImplTBDragMgr::FindToolBox( const Rectangle& rRect )
1210 for ( size_t i = 0, n = mpBoxList->size(); i < n; ++i )
1212 ToolBox* pBox = (*mpBoxList)[ i ];
1214 * FIXME: since we can have multiple frames now we cannot
1215 * find the drag target by its position alone.
1216 * As long as the toolbar config dialogue is not a system window
1217 * this works in one frame only anyway. If the dialogue
1218 * changes to a system window, we need a new implementation here
1220 if ( pBox->IsReallyVisible()
1221 && pBox->ImplGetWindowImpl()->mpFrame == mpDragBox->ImplGetWindowImpl()->mpFrame
1223 if ( !pBox->ImplIsFloatingMode() )
1225 Point aPos = pBox->GetPosPixel();
1226 aPos = pBox->GetParent()->OutputToScreenPixel( aPos );
1227 Rectangle aTempRect( aPos, pBox->GetSizePixel() );
1228 if ( aTempRect.IsOver( rRect ) )
1229 return pBox;
1234 return NULL;
1237 // -----------------------------------------------------------------------
1239 void ImplTBDragMgr::StartDragging( ToolBox* pToolBox,
1240 const Point& rPos, const Rectangle& rRect,
1241 sal_uInt16 nDragLineMode, sal_Bool bResizeItem,
1242 void* pData )
1244 mpDragBox = pToolBox;
1245 pToolBox->CaptureMouse();
1246 pToolBox->mbDragging = sal_True;
1247 Application::InsertAccel( &maAccel );
1249 if ( nDragLineMode )
1251 mnLineMode = nDragLineMode;
1252 mnStartLines = pToolBox->mnDockLines;
1254 else
1256 mpCustomizeData = pData;
1257 mbResizeMode = bResizeItem;
1258 pToolBox->Activate();
1259 pToolBox->mnCurItemId = pToolBox->mnConfigItem;
1260 pToolBox->Highlight();
1261 pToolBox->mnCurItemId = 0;
1262 if ( mbResizeMode )
1264 if ( rRect.GetWidth() < TB_MIN_WIN_WIDTH )
1265 mnMinWidth = rRect.GetWidth();
1266 else
1267 mnMinWidth = TB_MIN_WIN_WIDTH;
1268 mnMaxWidth = pToolBox->GetSizePixel().Width()-rRect.Left()-
1269 TB_SPIN_SIZE-TB_BORDER_OFFSET1-(TB_SPIN_OFFSET*2);
1273 // MouseOffset berechnen
1274 maMouseOff.X() = rRect.Left() - rPos.X();
1275 maMouseOff.Y() = rRect.Top() - rPos.Y();
1276 maRect = rRect;
1277 maStartRect = rRect;
1278 mbShowDragRect = sal_True;
1279 pToolBox->ShowTracking( maRect );
1282 // -----------------------------------------------------------------------
1284 void ImplTBDragMgr::Dragging( const Point& rPos )
1286 if ( mnLineMode )
1288 ToolBox::ImplLineSizing( mpDragBox, rPos, maRect, mnLineMode );
1289 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1290 maRect.Move( aOff.X(), aOff.Y() );
1291 mpDragBox->Docking( rPos, maRect );
1292 maRect.Move( -aOff.X(), -aOff.Y() );
1293 mpDragBox->ShowTracking( maRect );
1295 else
1297 if ( mbResizeMode )
1299 long nXOff = rPos.X()-maStartRect.Left();
1300 nXOff += maMouseOff.X()+(maStartRect.Right()-maStartRect.Left());
1301 if ( nXOff < mnMinWidth )
1302 nXOff = mnMinWidth;
1303 if ( nXOff > mnMaxWidth )
1304 nXOff = mnMaxWidth;
1305 maRect.Right() = maStartRect.Left()+nXOff;
1307 else
1309 maRect.SetPos( rPos );
1310 maRect.Move( maMouseOff.X(), maMouseOff.Y() );
1312 mpDragBox->ShowTracking( maRect );
1316 // -----------------------------------------------------------------------
1318 void ImplTBDragMgr::EndDragging( sal_Bool bOK )
1320 mpDragBox->HideTracking();
1321 mpDragBox->ReleaseMouse();
1322 mpDragBox->mbDragging = sal_False;
1323 mbShowDragRect = sal_False;
1324 Application::RemoveAccel( &maAccel );
1326 if ( mnLineMode )
1328 if ( !bOK )
1330 mpDragBox->mnDockLines = mnStartLines;
1331 mpDragBox->EndDocking( maStartRect, sal_False );
1333 else
1334 mpDragBox->EndDocking( maRect, sal_False );
1335 mnLineMode = 0;
1336 mnStartLines = 0;
1338 else
1340 sal_uInt16 nTempItem = mpDragBox->mnConfigItem;
1341 if ( nTempItem )
1343 mpDragBox->mnConfigItem = 0;
1344 if ( !mbResizeMode )
1345 mpDragBox->Invalidate( mpDragBox->GetItemRect( nTempItem ) );
1348 if ( bOK && (maRect != maStartRect) )
1350 if ( mbResizeMode )
1352 ImplToolItem* pItem = mpDragBox->ImplGetItem( nTempItem );
1353 Size aSize = pItem->mpWindow->GetSizePixel();
1354 aSize.Width() = maRect.GetWidth();
1355 pItem->mpWindow->SetSizePixel( aSize );
1357 // re-calculate and show ToolBox
1358 mpDragBox->ImplInvalidate( sal_True );
1359 mpDragBox->Customize( ToolBoxCustomizeEvent( mpDragBox, nTempItem,
1360 TOOLBOX_CUSTOMIZE_RESIZE,
1361 mpCustomizeData ) );
1363 else
1365 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1366 Rectangle aScreenRect( maRect );
1367 aScreenRect.Move( aOff.X(), aOff.Y() );
1368 ToolBox* pDropBox = FindToolBox( aScreenRect );
1369 if ( pDropBox )
1371 // Determine search position
1372 Point aPos;
1373 if ( pDropBox->mbHorz )
1375 aPos.X() = aScreenRect.Left()-TB_CUSTOMIZE_OFFSET;
1376 aPos.Y() = aScreenRect.Center().Y();
1378 else
1380 aPos.X() = aScreenRect.Center().X();
1381 aPos.Y() = aScreenRect.Top()-TB_CUSTOMIZE_OFFSET;
1384 aPos = pDropBox->ScreenToOutputPixel( aPos );
1385 sal_uInt16 nPos = ToolBox::ImplFindItemPos( pDropBox, aPos );
1386 mpDragBox->Customize( ToolBoxCustomizeEvent( pDropBox, nTempItem,
1387 nPos, mpCustomizeData ) );
1389 else
1391 mpDragBox->Customize( ToolBoxCustomizeEvent( NULL, nTempItem,
1392 0, mpCustomizeData ) );
1396 mpCustomizeData = NULL;
1397 mbResizeMode = sal_False;
1398 mpDragBox->Deactivate();
1401 mpDragBox = NULL;
1404 // -----------------------------------------------------------------------
1406 void ImplTBDragMgr::UpdateDragRect()
1408 // Only update if we're already dragging
1409 if ( !mbShowDragRect )
1410 return;
1412 mpDragBox->ShowTracking( maRect );
1415 // -----------------------------------------------------------------------
1417 IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator*, pAccel )
1419 if ( pAccel->GetCurItemId() == KEY_ESCAPE )
1420 EndDragging( sal_False );
1421 else
1422 EndDragging( sal_True );
1424 return sal_True;
1427 // -----------------------------------------------------------------------
1429 void ToolBox::ImplInit( Window* pParent, WinBits nStyle )
1432 // initialize variables
1433 ImplGetWindowImpl()->mbToolBox = sal_True;
1434 mpData = new ImplToolBoxPrivateData;
1435 mpFloatWin = NULL;
1436 mnDX = 0;
1437 mnDY = 0;
1438 mnMaxItemWidth = 0;
1439 mnMaxItemHeight = 0;
1440 mnWinHeight = 0;
1441 mnLeftBorder = 0;
1442 mnTopBorder = 0;
1443 mnRightBorder = 0;
1444 mnBottomBorder = 0;
1445 mnLastResizeDY = 0;
1446 mnOutStyle = TOOLBOX_STYLE_FLAT; // force flat buttons since NWF
1447 mnHighItemId = 0;
1448 mnCurItemId = 0;
1449 mnDownItemId = 0;
1450 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1451 mnFocusPos = TOOLBOX_ITEM_NOTFOUND; // current position during keyboard access
1452 mnLines = 1;
1453 mnCurLine = 1;
1454 mnCurLines = 1;
1455 mnVisLines = 1;
1456 mnFloatLines = 0;
1457 mnConfigItem = 0;
1458 mnMouseClicks = 0;
1459 mnMouseModifier = 0;
1460 mbDrag = sal_False;
1461 mbSelection = sal_False;
1462 mbCommandDrag = sal_False;
1463 mbUpper = sal_False;
1464 mbLower = sal_False;
1465 mbIn = sal_False;
1466 mbCalc = sal_True;
1467 mbFormat = sal_False;
1468 mbFullPaint = sal_False;
1469 mbHorz = sal_True;
1470 mbScroll = (nStyle & WB_SCROLL) != 0;
1471 mbCustomize = sal_False;
1472 mbCustomizeMode = sal_False;
1473 mbDragging = sal_False;
1474 mbMenuStrings = sal_False;
1475 mbIsShift = sal_False;
1476 mbIsKeyEvent = sal_False;
1477 mbChangingHighlight = sal_False;
1478 meButtonType = BUTTON_SYMBOL;
1479 meAlign = WINDOWALIGN_TOP;
1480 meLastStyle = POINTER_ARROW;
1481 mnWinStyle = nStyle;
1482 meLayoutMode = TBX_LAYOUT_NORMAL;
1483 mnLastFocusItemId = 0;
1484 mnKeyModifier = 0;
1485 mnActivateCount = 0;
1487 maTimer.SetTimeout( 50 );
1488 maTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplUpdateHdl ) );
1490 // set timeout and handler for dropdown items
1491 mpData->maDropdownTimer.SetTimeout( 250 );
1492 mpData->maDropdownTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplDropdownLongClickHdl ) );
1494 DockingWindow::ImplInit( pParent, nStyle & ~(WB_BORDER) );
1497 // always set WB_TABSTOP for ToolBars !!! if( mnWinStyle & WB_TABSTOP )
1499 // dockingwindow's ImplInit removes some bits, so restore them here
1500 // to allow keyboard handling for toolbars
1501 ImplGetWindowImpl()->mnStyle |= WB_TABSTOP|WB_NODIALOGCONTROL;
1502 ImplGetWindowImpl()->mnStyle &= ~WB_DIALOGCONTROL;
1505 ImplInitSettings( sal_True, sal_True, sal_True );
1508 // -----------------------------------------------------------------------
1510 void ToolBox::ImplInitSettings( sal_Bool bFont,
1511 sal_Bool bForeground, sal_Bool bBackground )
1513 mpData->mbNativeButtons = IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
1515 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1517 if ( bFont )
1519 Font aFont = rStyleSettings.GetToolFont();
1520 if ( IsControlFont() )
1521 aFont.Merge( GetControlFont() );
1522 SetZoomedPointFont( aFont );
1525 if ( bForeground || bFont )
1527 Color aColor;
1528 if ( IsControlForeground() )
1529 aColor = GetControlForeground();
1530 else if ( Window::GetStyle() & WB_3DLOOK )
1531 aColor = rStyleSettings.GetButtonTextColor();
1532 else
1533 aColor = rStyleSettings.GetWindowTextColor();
1534 SetTextColor( aColor );
1535 SetTextFillColor();
1538 if ( bBackground )
1540 Color aColor;
1541 if ( IsControlBackground() )
1543 aColor = GetControlBackground();
1544 SetBackground( aColor );
1545 SetPaintTransparent( sal_False );
1546 SetParentClipMode( 0 );
1548 else
1550 if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) ||
1551 ( GetAlign() == WINDOWALIGN_TOP && !Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty() ) )
1553 SetBackground();
1554 SetPaintTransparent( sal_True );
1555 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
1556 mpData->maDisplayBackground = Wallpaper( rStyleSettings.GetFaceColor() );
1558 else
1560 if ( Window::GetStyle() & WB_3DLOOK )
1561 aColor = rStyleSettings.GetFaceColor();
1562 else
1563 aColor = rStyleSettings.GetWindowColor();
1565 SetBackground( aColor );
1566 SetPaintTransparent( sal_False );
1567 SetParentClipMode( 0 );
1569 ImplUpdateImageList();
1575 // -----------------------------------------------------------------------
1577 void ToolBox::ImplLoadRes( const ResId& rResId )
1579 ResMgr* pMgr = rResId.GetResMgr();
1580 if( ! pMgr )
1581 return;
1583 DockingWindow::ImplLoadRes( rResId );
1585 sal_uLong nObjMask;
1587 nObjMask = ReadLongRes();
1589 if ( nObjMask & RSC_TOOLBOX_BUTTONTYPE )
1590 SetButtonType( (ButtonType)ReadLongRes() );
1592 if ( nObjMask & RSC_TOOLBOX_ALIGN )
1593 SetAlign( (WindowAlign)ReadLongRes() );
1595 if ( nObjMask & RSC_TOOLBOX_LINECOUNT )
1596 SetLineCount( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
1598 if ( nObjMask & RSC_TOOLBOX_CUSTOMIZE )
1600 sal_Bool bCust = (sal_Bool)ReadShortRes();
1601 EnableCustomize( bCust );
1604 if ( nObjMask & RSC_TOOLBOX_MENUSTRINGS )
1606 sal_Bool bCust = (sal_Bool)ReadShortRes();
1607 EnableMenuStrings( bCust );
1610 if ( nObjMask & RSC_TOOLBOX_FLOATLINES )
1611 SetFloatingLines( ReadShortRes() );
1613 if ( nObjMask & RSC_TOOLBOX_ITEMIMAGELIST )
1615 maImageList = ImageList( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1616 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1619 if ( nObjMask & RSC_TOOLBOX_ITEMLIST )
1621 sal_uLong nEle = ReadLongRes();
1623 // insert item
1624 for ( sal_uLong i = 0; i < nEle; i++ )
1626 InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1627 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
1632 // -----------------------------------------------------------------------
1634 ToolBox::ToolBox( Window* pParent, WinBits nStyle ) :
1635 DockingWindow( WINDOW_TOOLBOX )
1637 ImplInit( pParent, nStyle );
1640 // -----------------------------------------------------------------------
1642 ToolBox::ToolBox( Window* pParent, const ResId& rResId ) :
1643 DockingWindow( WINDOW_TOOLBOX )
1645 RTL_LOGFILE_CONTEXT( aLog, "vcl: ToolBox::ToolBox( Window* pParent, const ResId& rResId )" );
1647 rResId.SetRT( RSC_TOOLBOX );
1648 WinBits nStyle = ImplInitRes( rResId );
1649 ImplInit( pParent, nStyle );
1650 ImplLoadRes( rResId );
1652 // calculate size of floating windows and switch if the
1653 // toolbox is initially in floating mode
1654 if ( ImplIsFloatingMode() )
1655 mbHorz = sal_True;
1656 else
1657 Resize();
1659 if ( !(nStyle & WB_HIDE) )
1660 Show();
1663 // -----------------------------------------------------------------------
1665 ToolBox::~ToolBox()
1667 // custom menu event still running?
1668 if( mpData->mnEventId )
1669 Application::RemoveUserEvent( mpData->mnEventId );
1671 // #103005# make sure our activate/deactivate balance is right
1672 while( mnActivateCount > 0 )
1673 Deactivate();
1675 // terminate popupmode if the floating window is
1676 // still connected
1677 if ( mpFloatWin )
1678 mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
1680 // delete private data
1681 delete mpData;
1683 // remove the lists when there are no more toolbox references to
1684 // the lists
1685 ImplSVData* pSVData = ImplGetSVData();
1686 if ( pSVData->maCtrlData.mpTBDragMgr )
1688 // remove if in TBDrag-Manager
1689 if ( mbCustomize )
1690 pSVData->maCtrlData.mpTBDragMgr->erase( this );
1692 if ( !pSVData->maCtrlData.mpTBDragMgr->size() )
1694 delete pSVData->maCtrlData.mpTBDragMgr;
1695 pSVData->maCtrlData.mpTBDragMgr = NULL;
1700 // -----------------------------------------------------------------------
1702 ImplToolItem* ToolBox::ImplGetItem( sal_uInt16 nItemId ) const
1704 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1705 while ( it != mpData->m_aItems.end() )
1707 if ( it->mnId == nItemId )
1708 return &(*it);
1709 ++it;
1712 return NULL;
1714 // -----------------------------------------------------------------------
1716 static void ImplAddButtonBorder( long &rWidth, long& rHeight, sal_Bool bNativeButtons )
1718 rWidth += SMALLBUTTON_HSIZE;
1719 rHeight += SMALLBUTTON_VSIZE;
1721 if( bNativeButtons )
1723 // give more border space for rounded buttons
1724 rWidth += 2;
1725 rHeight += 4;
1729 // -----------------------------------------------------------------------
1731 sal_Bool ToolBox::ImplCalcItem()
1733 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
1735 // recalc required ?
1736 if ( !mbCalc )
1737 return sal_False;
1739 ImplDisableFlatButtons();
1741 long nDefWidth;
1742 long nDefHeight;
1743 long nMaxWidth = 0;
1744 long nMaxHeight = 0;
1745 long nMinWidth = 6;
1746 long nMinHeight = 6;
1747 long nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
1749 // set defaults if image or text is needed but empty
1750 nDefWidth = GetDefaultImageSize().Width();
1751 nDefHeight = GetDefaultImageSize().Height();
1753 mnWinHeight = 0;
1754 // determine minimum size necessary in NWF
1756 Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1757 Rectangle aReg( aRect );
1758 ImplControlValue aVal;
1759 Rectangle aNativeBounds, aNativeContent;
1760 if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
1762 if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
1763 aReg,
1764 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1765 aVal, OUString(),
1766 aNativeBounds, aNativeContent ) )
1768 aRect = aNativeBounds;
1769 if( aRect.GetWidth() > nMinWidth )
1770 nMinWidth = aRect.GetWidth();
1771 if( aRect.GetHeight() > nMinHeight )
1772 nMinHeight = aRect.GetHeight();
1773 if( nDropDownArrowWidth < nMinWidth )
1774 nDropDownArrowWidth = nMinWidth;
1775 if( nMinWidth > mpData->mnMenuButtonWidth )
1776 mpData->mnMenuButtonWidth = nMinWidth;
1777 else if( nMinWidth < TB_MENUBUTTON_SIZE )
1778 mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
1782 // also calculate the area for comboboxes, drop down list boxes and spinfields
1783 // as these are often inserted into toolboxes; set mnWinHeight to the
1784 // greater of those values to prevent toolbar flickering (#i103385#)
1785 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1786 aReg = aRect;
1787 if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
1788 aReg,
1789 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1790 aVal, OUString(),
1791 aNativeBounds, aNativeContent ) )
1793 aRect = aNativeBounds;
1794 if( aRect.GetHeight() > mnWinHeight )
1795 mnWinHeight = aRect.GetHeight();
1797 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1798 aReg = aRect;
1799 if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
1800 aReg,
1801 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1802 aVal, OUString(),
1803 aNativeBounds, aNativeContent ) )
1805 aRect = aNativeBounds;
1806 if( aRect.GetHeight() > mnWinHeight )
1807 mnWinHeight = aRect.GetHeight();
1809 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1810 aReg = aRect;
1811 if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
1812 aReg,
1813 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1814 aVal, OUString(),
1815 aNativeBounds, aNativeContent ) )
1817 aRect = aNativeBounds;
1818 if( aRect.GetHeight() > mnWinHeight )
1819 mnWinHeight = aRect.GetHeight();
1823 if ( ! mpData->m_aItems.empty() )
1825 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1826 while ( it != mpData->m_aItems.end() )
1828 sal_Bool bImage;
1829 sal_Bool bText;
1831 it->mbVisibleText = sal_False; // indicates if text will definitely be drawn, influences dropdown pos
1833 if ( it->meType == TOOLBOXITEM_BUTTON )
1835 // check if image and/or text exists
1836 if ( !(it->maImage) )
1837 bImage = sal_False;
1838 else
1839 bImage = sal_True;
1840 if ( !it->maText.Len() )
1841 bText = sal_False;
1842 else
1843 bText = sal_True;
1844 ButtonType tmpButtonType = determineButtonType( &(*it), meButtonType ); // default to toolbox setting
1845 if ( bImage || bText )
1848 it->mbEmptyBtn = sal_False;
1850 if ( tmpButtonType == BUTTON_SYMBOL )
1852 // we're drawing images only
1853 if ( bImage || !bText )
1855 it->maItemSize = it->maImage.GetSizePixel();
1857 else
1859 it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
1860 GetTextHeight() );
1861 it->mbVisibleText = sal_True;
1864 else if ( tmpButtonType == BUTTON_TEXT )
1866 // we're drawing text only
1867 if ( bText || !bImage )
1869 it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
1870 GetTextHeight() );
1871 it->mbVisibleText = sal_True;
1873 else
1875 it->maItemSize = it->maImage.GetSizePixel();
1878 else
1880 // we're drawing images and text
1881 it->maItemSize.Width() = bText ? GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET : 0;
1882 it->maItemSize.Height() = bText ? GetTextHeight() : 0;
1884 // leave space between image and text
1885 if( bText )
1886 it->maItemSize.Width() += TB_IMAGETEXTOFFSET;
1888 // image and text side by side
1889 it->maItemSize.Width() += it->maImage.GetSizePixel().Width();
1890 if ( it->maImage.GetSizePixel().Height() > it->maItemSize.Height() )
1891 it->maItemSize.Height() = it->maImage.GetSizePixel().Height();
1893 it->mbVisibleText = bText;
1896 else
1897 { // no image and no text
1898 it->maItemSize = Size( nDefWidth, nDefHeight );
1899 it->mbEmptyBtn = sal_True;
1902 // if required, take window height into consideration
1903 if ( it->mpWindow )
1905 long nHeight = it->mpWindow->GetSizePixel().Height();
1906 if ( nHeight > mnWinHeight )
1907 mnWinHeight = nHeight;
1910 // add in drop down arrow
1911 if( it->mnBits & TIB_DROPDOWN )
1913 it->maItemSize.Width() += nDropDownArrowWidth;
1914 it->mnDropDownArrowWidth = nDropDownArrowWidth;
1917 // text items will be rotated in vertical mode
1918 // -> swap width and height
1919 if( it->mbVisibleText && !mbHorz )
1921 long tmp = it->maItemSize.Width();
1922 it->maItemSize.Width() = it->maItemSize.Height();
1923 it->maItemSize.Height() = tmp;
1926 else if ( it->meType == TOOLBOXITEM_SPACE )
1928 it->maItemSize = Size( nDefWidth, nDefHeight );
1931 if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
1933 // add borders
1934 ImplAddButtonBorder( it->maItemSize.Width(), it->maItemSize.Height(), mpData->mbNativeButtons );
1936 if( it->meType == TOOLBOXITEM_BUTTON )
1938 if( it->maItemSize.Width() < nMinWidth )
1939 it->maItemSize.Width() = nMinWidth;
1940 if( it->maItemSize.Height() < nMinHeight )
1941 it->maItemSize.Height() = nMinHeight;
1944 // keep track of max item size
1945 if ( it->maItemSize.Width() > nMaxWidth )
1946 nMaxWidth = it->maItemSize.Width();
1947 if ( it->maItemSize.Height() > nMaxHeight )
1948 nMaxHeight = it->maItemSize.Height();
1951 ++it;
1954 else
1956 nMaxWidth = nDefWidth;
1957 nMaxHeight = nDefHeight;
1959 ImplAddButtonBorder( nMaxWidth, nMaxHeight, mpData->mbNativeButtons );
1962 if( !ImplIsFloatingMode() && GetToolboxButtonSize() != TOOLBOX_BUTTONSIZE_DONTCARE )
1964 // make sure all vertical toolbars have the same width and horizontal have the same height
1965 // this depends on the used button sizes
1966 // as this is used for alignement of multiple toolbars
1967 // it is only required for docked toolbars
1969 long nFixedWidth = nDefWidth+nDropDownArrowWidth;
1970 long nFixedHeight = nDefHeight;
1971 ImplAddButtonBorder( nFixedWidth, nFixedHeight, mpData->mbNativeButtons );
1973 if( mbHorz )
1974 nMaxHeight = nFixedHeight;
1975 else
1976 nMaxWidth = nFixedWidth;
1979 mbCalc = sal_False;
1980 mbFormat = sal_True;
1982 // do we have to recalc the sizes ?
1983 if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) )
1985 mnMaxItemWidth = nMaxWidth;
1986 mnMaxItemHeight = nMaxHeight;
1988 return sal_True;
1990 else
1991 return sal_False;
1994 // -----------------------------------------------------------------------
1996 sal_uInt16 ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, sal_Bool bCalcHorz )
1998 sal_uLong nLineStart = 0;
1999 sal_uLong nGroupStart = 0;
2000 long nLineWidth = 0;
2001 long nCurWidth;
2002 long nLastGroupLineWidth = 0;
2003 long nMaxLineWidth = 0;
2004 sal_uInt16 nLines = 1;
2005 sal_Bool bWindow;
2006 sal_Bool bBreak = sal_False;
2007 long nWidthTotal = nWidth;
2008 long nMenuWidth = 0;
2010 // when docked the menubutton will be in the first line
2011 if( IsMenuEnabled() && !ImplIsFloatingMode() )
2012 nMenuWidth = mpData->maMenubuttonItem.maItemSize.Width();
2014 // we need to know which item is the last visible one to be able to add
2015 // the menu width in case we are unable to show all the items
2016 std::vector< ImplToolItem >::iterator it, lastVisible;
2017 for ( it = mpData->m_aItems.begin(); it != mpData->m_aItems.end(); ++it )
2019 if ( it->mbVisible )
2020 lastVisible = it;
2023 it = mpData->m_aItems.begin();
2024 while ( it != mpData->m_aItems.end() )
2026 it->mbBreak = bBreak;
2027 bBreak = sal_False;
2029 if ( it->mbVisible )
2031 bWindow = sal_False;
2032 bBreak = sal_False;
2033 nCurWidth = 0;
2035 if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2037 if ( bCalcHorz )
2038 nCurWidth = it->maItemSize.Width();
2039 else
2040 nCurWidth = it->maItemSize.Height();
2042 if ( it->mpWindow && bCalcHorz )
2044 long nWinItemWidth = it->mpWindow->GetSizePixel().Width();
2045 if ( !mbScroll || (nWinItemWidth <= nWidthTotal) )
2047 nCurWidth = nWinItemWidth;
2048 bWindow = sal_True;
2050 else
2052 if ( it->mbEmptyBtn )
2054 nCurWidth = 0;
2059 // in case we are able to show all the items, we do not want
2060 // to show the toolbar's menu; otherwise yes
2061 if ( ( ( it == lastVisible ) && (nLineWidth+nCurWidth > nWidthTotal) && mbScroll ) ||
2062 ( ( it != lastVisible ) && (nLineWidth+nCurWidth+nMenuWidth > nWidthTotal) && mbScroll ) )
2063 bBreak = sal_True;
2065 else if ( it->meType == TOOLBOXITEM_SEPARATOR )
2067 nCurWidth = it->mnSepSize;
2068 if ( !ImplIsFloatingMode() && ( it != lastVisible ) && (nLineWidth+nCurWidth+nMenuWidth > nWidthTotal) )
2069 bBreak = sal_True;
2071 // treat breaks as separators, except when using old style toolbars (ie. no menu button)
2072 else if ( (it->meType == TOOLBOXITEM_BREAK) && !IsMenuEnabled() )
2073 bBreak = sal_True;
2075 if ( bBreak )
2077 nLines++;
2079 // Add break before the entire group or take group apart?
2080 if ( (it->meType == TOOLBOXITEM_BREAK) ||
2081 (nLineStart == nGroupStart) )
2083 if ( nLineWidth > nMaxLineWidth )
2084 nMaxLineWidth = nLineWidth;
2086 nLineWidth = 0;
2087 nLineStart = it - mpData->m_aItems.begin();
2088 nGroupStart = nLineStart;
2089 it->mbBreak = sal_True;
2090 bBreak = sal_False;
2092 else
2094 if ( nLastGroupLineWidth > nMaxLineWidth )
2095 nMaxLineWidth = nLastGroupLineWidth;
2097 // if the break is added before the group, set it to
2098 // beginning of line and re-calculate
2099 nLineWidth = 0;
2100 nLineStart = nGroupStart;
2101 it = mpData->m_aItems.begin() + nGroupStart;
2102 continue;
2105 else
2107 if( ImplIsFloatingMode() || !IsMenuEnabled() ) // no group breaking when being docked single-line
2109 if ( (it->meType != TOOLBOXITEM_BUTTON) || bWindow )
2111 // found separator or break
2112 nLastGroupLineWidth = nLineWidth;
2113 nGroupStart = it - mpData->m_aItems.begin();
2114 if ( !bWindow )
2115 nGroupStart++;
2120 nLineWidth += nCurWidth;
2123 ++it;
2127 if ( pMaxLineWidth )
2129 if ( nLineWidth > nMaxLineWidth )
2130 nMaxLineWidth = nLineWidth;
2132 if( ImplIsFloatingMode() && !ImplIsInPopupMode() )
2134 // leave enough space to display buttons in the decoration
2135 long aMinWidth = 2 * GetSettings().GetStyleSettings().GetFloatTitleHeight();
2136 if( nMaxLineWidth < aMinWidth )
2137 nMaxLineWidth = aMinWidth;
2139 *pMaxLineWidth = nMaxLineWidth;
2142 return nLines;
2145 // -----------------------------------------------------------------------
2147 Size ToolBox::ImplGetOptimalFloatingSize()
2149 if( !ImplIsFloatingMode() )
2150 return Size();
2152 Size aCurrentSize( mnDX, mnDY );
2153 Size aSize1( aCurrentSize );
2154 Size aSize2( aCurrentSize );
2156 // try to preserve current height
2158 // calc number of floating lines for current window height
2159 sal_uInt16 nFloatLinesHeight = ImplCalcLines( this, mnDY );
2160 // calc window size according to this number
2161 aSize1 = ImplCalcFloatSize( this, nFloatLinesHeight );
2163 if( aCurrentSize == aSize1 )
2164 return aSize1;
2166 // try to preserve current width
2168 long nLineHeight = ( mnWinHeight > mnMaxItemHeight ) ? mnWinHeight : mnMaxItemHeight;
2169 int nBorderX = 2*TB_BORDER_OFFSET1 + mnLeftBorder + mnRightBorder;
2170 int nBorderY = 2*TB_BORDER_OFFSET2 + mnTopBorder + mnBottomBorder;
2171 Size aSz( aCurrentSize );
2172 long maxX;
2173 sal_uInt16 nLines = ImplCalcBreaks( aSz.Width()-nBorderX, &maxX, mbHorz );
2175 sal_uInt16 manyLines = 1000;
2176 Size aMinimalFloatSize = ImplCalcFloatSize( this, manyLines );
2178 aSz.Height() = nBorderY + nLineHeight * nLines;
2179 // line space when more than one line
2180 if ( mnWinStyle & WB_LINESPACING )
2181 aSz.Height() += (nLines-1)*TB_LINESPACING;
2183 aSz.Width() = nBorderX + maxX;
2185 // avoid clipping of any items
2186 if( aSz.Width() < aMinimalFloatSize.Width() )
2187 aSize2 = ImplCalcFloatSize( this, nLines );
2188 else
2189 aSize2 = aSz;
2191 if( aCurrentSize == aSize2 )
2192 return aSize2;
2194 // set the size with the smallest delta as the current size
2195 long dx1 = abs( mnDX - aSize1.Width() );
2196 long dy1 = abs( mnDY - aSize1.Height() );
2198 long dx2 = abs( mnDX - aSize2.Width() );
2199 long dy2 = abs( mnDY - aSize2.Height() );
2201 if( dx1*dy1 < dx2*dy2 )
2202 aCurrentSize = aSize1;
2203 else
2204 aCurrentSize = aSize2;
2206 return aCurrentSize;
2209 namespace
2211 static void lcl_hideDoubleSeparators( std::vector< ImplToolItem >& rItems )
2213 bool bLastSep( true );
2214 std::vector< ImplToolItem >::iterator it;
2215 for ( it = rItems.begin(); it != rItems.end(); ++it )
2217 if ( it->meType == TOOLBOXITEM_SEPARATOR )
2219 it->mbVisible = sal_False;
2220 if ( !bLastSep )
2222 // check if any visible items have to appear behind it
2223 std::vector< ImplToolItem >::iterator temp_it;
2224 for ( temp_it = it+1; temp_it != rItems.end(); ++temp_it )
2226 if ( ((temp_it->meType == TOOLBOXITEM_BUTTON) &&
2227 temp_it->mbVisible) )
2229 it->mbVisible = sal_True;
2230 break;
2234 bLastSep = true;
2236 else if ( it->mbVisible )
2237 bLastSep = false;
2242 void ToolBox::ImplFormat( sal_Bool bResize )
2244 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2246 // Has to re-formatted
2247 if ( !mbFormat )
2248 return;
2250 mpData->ImplClearLayoutData();
2252 // recalulate positions and sizes
2253 Rectangle aEmptyRect;
2254 long nLineSize;
2255 long nLeft;
2256 long nTop;
2257 long nMax; // width of layoutarea in pixels
2258 sal_uInt16 nFormatLine;
2259 sal_Bool bMustFullPaint;
2261 std::vector< ImplToolItem >::iterator it;
2263 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2264 sal_Bool bIsInPopupMode = ImplIsInPopupMode();
2266 maFloatSizes.clear();
2268 // compute border sizes
2269 ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder, this );
2271 // update drag area (where the 'grip' will be placed)
2272 Rectangle aOldDragRect;
2273 if( pWrapper )
2274 aOldDragRect = pWrapper->GetDragArea();
2275 ImplUpdateDragArea( this );
2277 if ( ImplCalcItem() )
2278 bMustFullPaint = sal_True;
2279 else
2280 bMustFullPaint = sal_False;
2283 // calculate new size during interactive resize or
2284 // set computed size when formatting only
2285 if ( ImplIsFloatingMode() )
2287 if ( bResize )
2288 mnFloatLines = ImplCalcLines( this, mnDY );
2289 else
2290 SetOutputSizePixel( ImplGetOptimalFloatingSize() );
2293 // Horizontal
2294 if ( mbHorz )
2296 long nBottom;
2297 // nLineSize: height of a single line, will fit highest item
2298 nLineSize = mnMaxItemHeight;
2300 if ( mnWinHeight > mnMaxItemHeight )
2301 nLineSize = mnWinHeight;
2303 if ( mbScroll )
2305 nMax = mnDX;
2306 mnVisLines = ImplCalcLines( this, mnDY );
2308 else
2310 // layout over all lines
2311 mnVisLines = mnLines;
2312 nMax = TB_MAXNOSCROLL;
2315 // add in all border offsets
2316 if ( mnWinStyle & WB_BORDER )
2318 nLeft = TB_BORDER_OFFSET1 + mnLeftBorder;
2319 nTop = TB_BORDER_OFFSET2 + mnTopBorder;
2320 nBottom = TB_BORDER_OFFSET1 + mnBottomBorder;
2321 nMax -= nLeft + TB_BORDER_OFFSET1 + mnRightBorder;
2323 else
2325 nLeft = 0;
2326 nTop = 0;
2327 nBottom = 0;
2330 // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2331 // we have to center all items in the window height
2332 if( IsMenuEnabled() && !ImplIsFloatingMode() )
2334 long nWinHeight = mnDY - nTop - nBottom;
2335 if( nWinHeight > nLineSize )
2336 nLineSize = nWinHeight;
2339 else
2341 long nRight;
2342 nLineSize = mnMaxItemWidth;
2344 if ( mbScroll )
2346 mnVisLines = ImplCalcLines( this, mnDX );
2347 nMax = mnDY;
2349 else
2351 mnVisLines = mnLines;
2352 nMax = TB_MAXNOSCROLL;
2355 if ( mnWinStyle & WB_BORDER )
2357 nTop = TB_BORDER_OFFSET1 + mnTopBorder;
2358 nLeft = TB_BORDER_OFFSET2 + mnLeftBorder;
2359 nRight = TB_BORDER_OFFSET2 + mnRightBorder;
2360 nMax -= nTop + TB_BORDER_OFFSET1 + mnBottomBorder;
2362 else
2364 nLeft = 0;
2365 nTop = 0;
2366 nRight = 0;
2369 // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2370 // we have to center all items in the window height
2371 if( !ImplIsFloatingMode() && IsMenuEnabled() )
2373 long nWinWidth = mnDX - nLeft - nRight;
2374 if( nWinWidth > nLineSize )
2375 nLineSize = nWinWidth;
2379 // no calculation if the window has no size (nMax=0)
2380 // non scrolling toolboxes must be computed though
2381 if ( (nMax <= 0) && mbScroll )
2383 mnVisLines = 1;
2384 mnCurLine = 1;
2385 mnCurLines = 1;
2387 it = mpData->m_aItems.begin();
2388 while ( it != mpData->m_aItems.end() )
2390 it->maRect = aEmptyRect;
2391 ++it;
2394 maLowerRect = aEmptyRect;
2395 maUpperRect = aEmptyRect;
2397 else
2399 // init start values
2400 long nX = nLeft; // top-left offset
2401 long nY = nTop;
2402 nFormatLine = 1;
2404 // save old scroll rectangles and reset them
2405 Rectangle aOldLowerRect = maLowerRect;
2406 Rectangle aOldUpperRect = maUpperRect;
2407 Rectangle aOldMenubuttonRect = mpData->maMenubuttonItem.maRect;
2408 maUpperRect = aEmptyRect;
2409 maLowerRect = aEmptyRect;
2410 mpData->maMenubuttonItem.maRect = aEmptyRect;
2412 // do we have any toolbox items at all ?
2413 if ( !mpData->m_aItems.empty() || IsMenuEnabled() )
2415 lcl_hideDoubleSeparators( mpData->m_aItems );
2417 // compute line breaks and visible lines give the current window width (nMax)
2418 // the break indicators will be stored within each item (it->mbBreak)
2419 mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2421 // check for scrollbar buttons or dropdown menu
2422 // (if a menu is enabled, this will be used to store clipped
2423 // items and no scroll buttons will appear)
2424 if ( (!ImplIsFloatingMode() && (mnCurLines > mnVisLines) && mbScroll ) ||
2425 IsMenuEnabled() )
2427 // compute linebreaks again, incorporating scrollbar buttons
2428 if( !IsMenuEnabled() )
2430 nMax -= TB_SPIN_SIZE+TB_SPIN_OFFSET;
2431 mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2434 // compute scroll rectangles or menu button
2435 if ( mbHorz )
2437 if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2439 if( !ImplIsFloatingMode() )
2441 mpData->maMenubuttonItem.maRect.Right() = mnDX - 2;
2442 mpData->maMenubuttonItem.maRect.Top() = nTop;
2443 mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-TB_BORDER_OFFSET2-1;
2445 else
2447 mpData->maMenubuttonItem.maRect.Right() = mnDX - mnRightBorder-TB_BORDER_OFFSET1-1;
2448 mpData->maMenubuttonItem.maRect.Top() = nTop;
2449 mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-TB_BORDER_OFFSET2-1;
2451 mpData->maMenubuttonItem.maRect.Left() = mpData->maMenubuttonItem.maRect.Right() - mpData->mnMenuButtonWidth;
2453 else
2455 maUpperRect.Left() = nLeft+nMax+TB_SPIN_OFFSET;
2456 maUpperRect.Right() = maUpperRect.Left()+TB_SPIN_SIZE-1;
2457 maUpperRect.Top() = nTop;
2458 maLowerRect.Bottom() = mnDY-mnBottomBorder-TB_BORDER_OFFSET2-1;
2459 maLowerRect.Left() = maUpperRect.Left();
2460 maLowerRect.Right() = maUpperRect.Right();
2461 maUpperRect.Bottom() = maUpperRect.Top() +
2462 (maLowerRect.Bottom()-maUpperRect.Top())/2;
2463 maLowerRect.Top() = maUpperRect.Bottom();
2466 else
2468 if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2470 if( !ImplIsFloatingMode() )
2472 mpData->maMenubuttonItem.maRect.Bottom() = mnDY - 2;
2473 mpData->maMenubuttonItem.maRect.Left() = nLeft;
2474 mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-TB_BORDER_OFFSET2-1;
2476 else
2478 mpData->maMenubuttonItem.maRect.Bottom() = mnDY - mnBottomBorder-TB_BORDER_OFFSET1-1;
2479 mpData->maMenubuttonItem.maRect.Left() = nLeft;
2480 mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-TB_BORDER_OFFSET2-1;
2482 mpData->maMenubuttonItem.maRect.Top() = mpData->maMenubuttonItem.maRect.Bottom() - mpData->mnMenuButtonWidth;
2484 else
2486 maUpperRect.Top() = nTop+nMax+TB_SPIN_OFFSET;
2487 maUpperRect.Bottom() = maUpperRect.Top()+TB_SPIN_SIZE-1;
2488 maUpperRect.Left() = nLeft;
2489 maLowerRect.Right() = mnDX-mnRightBorder-TB_BORDER_OFFSET2-1;
2490 maLowerRect.Top() = maUpperRect.Top();
2491 maLowerRect.Bottom() = maUpperRect.Bottom();
2492 maUpperRect.Right() = maUpperRect.Left() +
2493 (maLowerRect.Right()-maUpperRect.Left())/2;
2494 maLowerRect.Left() = maUpperRect.Right();
2499 // no scrolling when there is a "more"-menu
2500 // anything will "fit" in a single line then
2501 if( IsMenuEnabled() )
2502 mnCurLines = 1;
2504 // determine the currently visible line
2505 if ( mnVisLines >= mnCurLines )
2506 mnCurLine = 1;
2507 else if ( mnCurLine+mnVisLines-1 > mnCurLines )
2508 mnCurLine = mnCurLines - (mnVisLines-1);
2510 it = mpData->m_aItems.begin();
2511 while ( it != mpData->m_aItems.end() )
2513 it->mbShowWindow = sal_False;
2515 // check for line break and advance nX/nY accordingly
2516 if ( it->mbBreak )
2518 nFormatLine++;
2520 // increment starting with the second line
2521 if ( nFormatLine > mnCurLine )
2523 if ( mbHorz )
2525 nX = nLeft;
2526 if ( mnWinStyle & WB_LINESPACING )
2527 nY += nLineSize+TB_LINESPACING;
2528 else
2529 nY += nLineSize;
2531 else
2533 nY = nTop;
2534 if ( mnWinStyle & WB_LINESPACING )
2535 nX += nLineSize+TB_LINESPACING;
2536 else
2537 nX += nLineSize;
2542 if ( !it->mbVisible || (nFormatLine < mnCurLine) ||
2543 (nFormatLine > mnCurLine+mnVisLines-1) )
2544 // item is not visible
2545 it->maCalcRect = aEmptyRect;
2546 else
2548 // 1. determine current item width/height
2549 // take window size and orientation into account, because this affects the size of item windows
2551 Size aCurrentItemSize( it->GetSize( mbHorz, mbScroll, nMax, Size(mnMaxItemWidth, mnMaxItemHeight) ) );
2553 // 2. position item rect and use size from step 1
2554 // items will be centered horizontally (if mbHorz) or vertically
2555 // advance nX and nY accordingly
2556 if ( mbHorz )
2558 it->maCalcRect.Left() = nX;
2559 // if special TBX_LAYOUT_LOCKVERT lock vertical position
2560 // don't recalulate the vertical position of the item
2561 if ( meLayoutMode == TBX_LAYOUT_LOCKVERT && mnLines == 1 )
2563 // Somewhat of a hack here, calc deletes and re-adds
2564 // the sum/assign & ok/cancel items dynamically.
2565 // Because TBX_LAYOUT_LOCKVERT effectively prevents
2566 // recalculation of the vertical pos of an item the
2567 // it->maRect.Top() for those newly added items is
2568 // 0. The hack here is that we want to effectively
2569 // recalculate the vertical pos for those added
2570 // items here. ( Note: assume mnMaxItemHeight is
2571 // equal to the LineSize when multibar has a single
2572 // line size )
2573 it->maCalcRect.Top() = it->maRect.Top() ? it->maRect.Top() : ( nY + ( mnMaxItemHeight-aCurrentItemSize.Height())/2 );
2575 else
2576 it->maCalcRect.Top() = nY+(nLineSize-aCurrentItemSize.Height())/2;
2577 it->maCalcRect.Right() = nX+aCurrentItemSize.Width()-1;
2578 it->maCalcRect.Bottom() = it->maCalcRect.Top()+aCurrentItemSize.Height()-1;
2579 nX += aCurrentItemSize.Width();
2581 else
2583 it->maCalcRect.Left() = nX+(nLineSize-aCurrentItemSize.Width())/2;
2584 it->maCalcRect.Top() = nY;
2585 it->maCalcRect.Right() = it->maCalcRect.Left()+aCurrentItemSize.Width()-1;
2586 it->maCalcRect.Bottom() = nY+aCurrentItemSize.Height()-1;
2587 nY += aCurrentItemSize.Height();
2591 // position window items into calculated item rect
2592 if ( it->mpWindow )
2594 if ( it->mbShowWindow )
2596 Point aPos( it->maCalcRect.Left(), it->maCalcRect.Top() );
2597 it->mpWindow->SetPosPixel( aPos );
2598 if ( !mbCustomizeMode )
2599 it->mpWindow->Show();
2601 else
2602 it->mpWindow->Hide();
2605 ++it;
2606 } // end of loop over all items
2608 else
2609 // we have no toolbox items
2610 mnCurLines = 1;
2613 if( IsMenuEnabled() && ImplIsFloatingMode() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2615 // custom menu will be the last button in floating mode
2616 ImplToolItem &rIt = mpData->maMenubuttonItem;
2618 if ( mbHorz )
2620 rIt.maRect.Left() = nX+TB_MENUBUTTON_OFFSET;
2621 rIt.maRect.Top() = nY;
2622 rIt.maRect.Right() = rIt.maRect.Left() + mpData->mnMenuButtonWidth;
2623 rIt.maRect.Bottom() = nY+nLineSize-1;
2624 nX += rIt.maItemSize.Width();
2626 else
2628 rIt.maRect.Left() = nX;
2629 rIt.maRect.Top() = nY+TB_MENUBUTTON_OFFSET;
2630 rIt.maRect.Right() = nX+nLineSize-1;
2631 rIt.maRect.Bottom() = rIt.maRect.Top() + mpData->mnMenuButtonWidth;
2632 nY += rIt.maItemSize.Height();
2637 // if toolbox visible trigger paint for changed regions
2638 if ( IsVisible() && !mbFullPaint )
2640 if ( bMustFullPaint )
2642 maPaintRect = Rectangle( mnLeftBorder, mnTopBorder,
2643 mnDX-mnRightBorder, mnDY-mnBottomBorder );
2645 else
2647 if ( aOldLowerRect != maLowerRect )
2649 maPaintRect.Union( maLowerRect );
2650 maPaintRect.Union( aOldLowerRect );
2652 if ( aOldUpperRect != maUpperRect )
2654 maPaintRect.Union( maUpperRect );
2655 maPaintRect.Union( aOldUpperRect );
2657 if ( aOldMenubuttonRect != mpData->maMenubuttonItem.maRect )
2659 maPaintRect.Union( mpData->maMenubuttonItem.maRect );
2660 maPaintRect.Union( aOldMenubuttonRect );
2662 if ( pWrapper && aOldDragRect != pWrapper->GetDragArea() )
2664 maPaintRect.Union( pWrapper->GetDragArea() );
2665 maPaintRect.Union( aOldDragRect );
2668 it = mpData->m_aItems.begin();
2669 while ( it != mpData->m_aItems.end() )
2671 if ( it->maRect != it->maCalcRect )
2673 maPaintRect.Union( it->maRect );
2674 maPaintRect.Union( it->maCalcRect );
2676 ++it;
2680 Invalidate( maPaintRect );
2683 // store the new calculated item rects
2684 maPaintRect = aEmptyRect;
2685 Rectangle aVisibleRect(Point(0, 0), GetOutputSizePixel());
2686 it = mpData->m_aItems.begin();
2687 while ( it != mpData->m_aItems.end() )
2689 it->maRect = it->maCalcRect;
2690 it->maRect.IsOver(aVisibleRect);
2691 ++it;
2695 // indicate formatting is done
2696 mbFormat = sal_False;
2699 // -----------------------------------------------------------------------
2701 IMPL_LINK_NOARG(ToolBox, ImplDropdownLongClickHdl)
2703 if( mnCurPos != TOOLBOX_ITEM_NOTFOUND &&
2704 (mpData->m_aItems[ mnCurPos ].mnBits & TIB_DROPDOWN)
2707 mpData->mbDropDownByKeyboard = sal_False;
2708 GetDropdownClickHdl().Call( this );
2710 // do not reset data if the dropdown handler opened a floating window
2711 // see ImplFloatControl()
2712 if( mpFloatWin == NULL )
2714 // no floater was opened
2715 Deactivate();
2716 ImplDrawItem( mnCurPos, 0 );
2718 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
2719 mnCurItemId = 0;
2720 mnDownItemId = 0;
2721 mnMouseClicks = 0;
2722 mnMouseModifier = 0;
2723 mnHighItemId = 0;
2727 return 0;
2730 // -----------------------------------------------------------------------
2732 IMPL_LINK_NOARG(ToolBox, ImplUpdateHdl)
2734 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2736 if( mbFormat )
2737 ImplFormat();
2739 return 0;
2742 // -----------------------------------------------------------------------
2744 static void ImplDrawMoreIndicator( ToolBox *pBox, const Rectangle& rRect, sal_Bool bSetColor, sal_Bool bRotate )
2746 Color aOldFillColor = pBox->GetFillColor();
2747 Color aOldLineColor = pBox->GetLineColor();
2748 pBox->SetLineColor();
2750 if ( bSetColor )
2752 if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
2753 pBox->SetFillColor( Color( COL_WHITE ) );
2754 else
2755 pBox->SetFillColor( Color( COL_BLACK ) );
2758 if( !bRotate )
2760 long width = 8;
2761 long height = 5;
2762 long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
2763 long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
2764 while( height >= 1)
2766 pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2767 x+=4;
2768 pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2769 x-=4;
2770 y++;
2771 if( height <= 3) x--;
2772 else x++;
2773 height--;
2776 else
2778 long width = 5;
2779 long height = 8;
2780 long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
2781 long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
2782 while( width >= 1)
2784 pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
2785 y+=4;
2786 pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
2787 y-=4;
2788 x++;
2789 if( width <= 3) y--;
2790 else y++;
2791 width--;
2795 pBox->SetFillColor( aOldFillColor );
2796 pBox->SetLineColor( aOldLineColor );
2799 static void ImplDrawDropdownArrow( ToolBox *pBox, const Rectangle& rDropDownRect, sal_Bool bSetColor, sal_Bool bRotate )
2801 sal_Bool bLineColor = pBox->IsLineColor();
2802 sal_Bool bFillColor = pBox->IsFillColor();
2803 Color aOldFillColor = pBox->GetFillColor();
2804 Color aOldLineColor = pBox->GetLineColor();
2805 pBox->SetLineColor();
2807 if ( bSetColor )
2809 if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
2810 pBox->SetFillColor( Color( COL_WHITE ) );
2811 else
2812 pBox->SetFillColor( Color( COL_BLACK ) );
2815 if( !bRotate )
2817 long width = 5;
2818 long height = 3;
2819 long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
2820 long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
2821 while( width >= 1)
2823 pBox->DrawRect( Rectangle( x, y, x+width-1, y ) );
2824 y++; x++;
2825 width -= 2;
2828 else
2830 long width = 3;
2831 long height = 5;
2832 long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
2833 long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
2834 while( height >= 1)
2836 pBox->DrawRect( Rectangle( x, y, x, y+height-1 ) );
2837 y++; x++;
2838 height -= 2;
2842 if( bFillColor )
2843 pBox->SetFillColor( aOldFillColor );
2844 else
2845 pBox->SetFillColor();
2846 if( bLineColor )
2847 pBox->SetLineColor( aOldLineColor );
2848 else
2849 pBox->SetLineColor( );
2852 // -----------------------------------------------------------------------
2854 void ToolBox::ImplDrawMenubutton( ToolBox *pThis, sal_Bool bHighlight )
2856 if( !pThis->mpData->maMenubuttonItem.maRect.IsEmpty() )
2858 // #i53937# paint menu button only if necessary
2859 if( !pThis->ImplHasClippedItems() )
2860 return;
2862 // execute pending paint requests
2863 ImplCheckUpdate( pThis );
2865 sal_Bool bFillColor = pThis->IsFillColor();
2866 sal_Bool bLineColor = pThis->IsLineColor();
2867 Color aOldFillCol = pThis->GetFillColor();
2868 Color aOldLineCol = pThis->GetLineColor();
2870 // draw the 'more' indicator / button (>>)
2871 ImplErase( pThis, pThis->mpData->maMenubuttonItem.maRect, bHighlight );
2873 if( bHighlight )
2874 ImplDrawButton( pThis, pThis->mpData->maMenubuttonItem.maRect, 2, sal_False, sal_True, sal_False );
2876 if( pThis->ImplHasClippedItems() )
2877 ImplDrawMoreIndicator( pThis, pThis->mpData->maMenubuttonItem.maRect, sal_True, !pThis->mbHorz );
2879 // store highlight state
2880 pThis->mpData->mbMenubuttonSelected = bHighlight;
2882 // restore colors
2883 if( bFillColor )
2884 pThis->SetFillColor( aOldFillCol );
2885 else
2886 pThis->SetFillColor();
2887 if( bLineColor )
2888 pThis->SetLineColor( aOldLineCol );
2889 else
2890 pThis->SetLineColor();
2894 // -----------------------------------------------------------------------
2896 void ToolBox::ImplDrawSpin( sal_Bool bUpperIn, sal_Bool bLowerIn )
2898 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2900 sal_Bool bTmpUpper;
2901 sal_Bool bTmpLower;
2903 if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() )
2904 return;
2906 if ( mnCurLine > 1 )
2907 bTmpUpper = sal_True;
2908 else
2909 bTmpUpper = sal_False;
2911 if ( mnCurLine+mnVisLines-1 < mnCurLines )
2912 bTmpLower = sal_True;
2913 else
2914 bTmpLower = sal_False;
2916 if ( !IsEnabled() )
2918 bTmpUpper = sal_False;
2919 bTmpLower = sal_False;
2922 ImplDrawSpinButton( this, maUpperRect, maLowerRect,
2923 bUpperIn, bLowerIn, bTmpUpper, bTmpLower, !mbHorz );
2926 // -----------------------------------------------------------------------
2928 void ToolBox::ImplDrawSeparator( sal_uInt16 nPos, Rectangle rRect )
2930 bool bNativeOk = false;
2931 ImplToolItem* pItem = &mpData->m_aItems[nPos];
2933 ControlPart nPart = IsHorizontal() ? PART_SEPARATOR_VERT : PART_SEPARATOR_HORZ;
2934 if( IsNativeControlSupported( CTRL_TOOLBAR, nPart ) )
2936 ImplControlValue aControlValue;
2937 ControlState nState = 0;
2938 bNativeOk = DrawNativeControl( CTRL_TOOLBAR, nPart,
2939 rRect, nState, aControlValue, OUString() );
2942 /* Draw the widget only if it can't be drawn natively. */
2943 if( !bNativeOk )
2945 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2946 ImplToolItem* pTempItem = &mpData->m_aItems[nPos-1];
2948 // no separator before or after windows or at breaks
2949 if ( pTempItem && !pTempItem->mbShowWindow && nPos < mpData->m_aItems.size()-1 )
2951 pTempItem = &mpData->m_aItems[nPos+1];
2952 if ( !pTempItem->mbShowWindow && !pTempItem->mbBreak )
2954 long nCenterPos, nSlim;
2955 SetLineColor( rStyleSettings.GetSeparatorColor() );
2956 if ( IsHorizontal() )
2958 nSlim = (pItem->maRect.Bottom() - pItem->maRect.Top ()) / 4;
2959 nCenterPos = pItem->maRect.Center().X();
2960 DrawLine( Point( nCenterPos, pItem->maRect.Top() + nSlim ),
2961 Point( nCenterPos, pItem->maRect.Bottom() - nSlim ) );
2963 else
2965 nSlim = (pItem->maRect.Right() - pItem->maRect.Left ()) / 4;
2966 nCenterPos = pItem->maRect.Center().Y();
2967 DrawLine( Point( pItem->maRect.Left() + nSlim, nCenterPos ),
2968 Point( pItem->maRect.Right() - nSlim, nCenterPos ) );
2975 // -----------------------------------------------------------------------
2977 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bEnabled, sal_Bool bIsWindow )
2979 // draws toolbar button background either native or using a coloured selection
2980 // if bIsWindow is sal_True, the corresponding item is a control and only a selection border will be drawn
2982 sal_Bool bNativeOk = sal_False;
2983 if( !bIsWindow && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
2985 ImplControlValue aControlValue;
2986 ControlState nState = 0;
2988 if ( highlight == 1 ) nState |= CTRL_STATE_PRESSED;
2989 if ( highlight == 2 ) nState |= CTRL_STATE_ROLLOVER;
2990 if ( bEnabled ) nState |= CTRL_STATE_ENABLED;
2992 aControlValue.setTristateVal( bChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
2995 bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
2996 rRect, nState, aControlValue, OUString() );
2999 if( !bNativeOk )
3000 pThis->DrawSelectionBackground( rRect, bIsWindow ? 3 : highlight, bChecked, sal_True, bIsWindow, 2, NULL, NULL );
3003 void ToolBox::ImplDrawItem( sal_uInt16 nPos, sal_uInt16 nHighlight, sal_Bool bPaint, sal_Bool bLayout )
3005 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3007 if( nPos >= mpData->m_aItems.size() )
3008 return;
3010 // execute pending paint requests
3011 ImplCheckUpdate( this );
3013 ImplDisableFlatButtons();
3015 SetFillColor();
3017 ImplToolItem* pItem = &mpData->m_aItems[nPos];
3018 MetricVector* pVector = bLayout ? &mpData->m_pLayoutData->m_aUnicodeBoundRects : NULL;
3019 OUString* pDisplayText = bLayout ? &mpData->m_pLayoutData->m_aDisplayText : NULL;
3021 if(!pItem->mbEnabled)
3022 nHighlight = 0;
3024 // if the rectangle is outside visible area
3025 if ( pItem->maRect.IsEmpty() )
3026 return;
3028 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3030 // no gradient background for items that have a popup open
3031 sal_Bool bHasOpenPopup = (mpFloatWin != NULL) && (mnDownItemId==pItem->mnId);
3033 sal_Bool bHighContrastWhite = sal_False;
3034 // check the face color as highcontrast indicator
3035 // because the toolbox itself might have a gradient
3036 if( rStyleSettings.GetFaceColor() == Color( COL_WHITE ) )
3037 bHighContrastWhite = sal_True;
3039 // Compute buttons area.
3040 Size aBtnSize = pItem->maRect.GetSize();
3041 if( ImplGetSVData()->maNWFData.mbToolboxDropDownSeparate )
3043 // separate button not for dropdown only where the whole button is painted
3044 if ( pItem->mnBits & TIB_DROPDOWN &&
3045 ((pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY) )
3047 Rectangle aArrowRect = pItem->GetDropDownRect( mbHorz );
3048 if( aArrowRect.Top() == pItem->maRect.Top() ) // dropdown arrow on right side
3049 aBtnSize.Width() -= aArrowRect.GetWidth();
3050 else // dropdown arrow on bottom side
3051 aBtnSize.Height() -= aArrowRect.GetHeight();
3055 /* Compute the button/separator rectangle here, we'll need it for
3056 * both the buttons and the separators. */
3057 Rectangle aButtonRect( pItem->maRect.TopLeft(), aBtnSize );
3058 long nOffX = SMALLBUTTON_OFF_NORMAL_X;
3059 long nOffY = SMALLBUTTON_OFF_NORMAL_Y;
3060 long nImageOffX = 0;
3061 long nImageOffY = 0;
3062 sal_uInt16 nStyle = 0;
3064 // draw separators in flat style only
3065 if ( !bLayout &&
3066 (mnOutStyle & TOOLBOX_STYLE_FLAT) &&
3067 (pItem->meType == TOOLBOXITEM_SEPARATOR) &&
3068 nPos > 0
3071 ImplDrawSeparator( nPos, aButtonRect );
3074 // do nothing if item is no button or will be displayed as window
3075 if ( (pItem->meType != TOOLBOXITEM_BUTTON) ||
3076 (pItem->mbShowWindow && !mbCustomizeMode) )
3077 return;
3079 // we need a TBDragMananger to draw the configuration item
3080 ImplTBDragMgr* pMgr;
3081 if ( pItem->mnId == mnConfigItem )
3083 pMgr = ImplGetTBDragMgr();
3084 pMgr->HideDragRect();
3086 else
3087 pMgr = NULL;
3089 // during configuration mode visible windows will be drawn in a special way
3090 if ( mbCustomizeMode && pItem->mbShowWindow )
3092 Font aOldFont = GetFont();
3093 Color aOldTextColor = GetTextColor();
3095 SetZoomedPointFont( rStyleSettings.GetAppFont() );
3096 SetLineColor( Color( COL_BLACK ) );
3097 SetFillColor( rStyleSettings.GetFieldColor() );
3098 SetTextColor( rStyleSettings.GetFieldTextColor() );
3099 if( !bLayout )
3100 DrawRect( pItem->maRect );
3102 Size aSize( GetCtrlTextWidth( pItem->maText ), GetTextHeight() );
3103 Point aPos( pItem->maRect.Left()+2, pItem->maRect.Top() );
3104 aPos.Y() += (pItem->maRect.GetHeight()-aSize.Height())/2;
3105 sal_Bool bClip;
3106 if ( (aSize.Width() > pItem->maRect.GetWidth()-2) ||
3107 (aSize.Height() > pItem->maRect.GetHeight()-2) )
3109 bClip = sal_True;
3110 Rectangle aTempRect( pItem->maRect.Left()+1, pItem->maRect.Top()+1,
3111 pItem->maRect.Right()-1, pItem->maRect.Bottom()-1 );
3112 Region aTempRegion( aTempRect );
3113 SetClipRegion( aTempRegion );
3115 else
3116 bClip = sal_False;
3117 if( bLayout )
3119 mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.getLength() );
3120 mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3121 mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3123 DrawCtrlText( aPos, pItem->maText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
3124 if ( bClip )
3125 SetClipRegion();
3126 SetFont( aOldFont );
3127 SetTextColor( aOldTextColor );
3129 // draw Config-Frame if required
3130 if ( pMgr && !bLayout)
3131 pMgr->UpdateDragRect();
3132 return;
3135 if ( pItem->meState == STATE_CHECK )
3137 nStyle |= BUTTON_DRAW_CHECKED;
3139 else if ( pItem->meState == STATE_DONTKNOW )
3141 nStyle |= BUTTON_DRAW_DONTKNOW;
3143 if ( nHighlight == 1 )
3145 nStyle |= BUTTON_DRAW_PRESSED;
3148 if( ! bLayout )
3150 if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
3152 if ( (pItem->meState != STATE_NOCHECK) || !bPaint )
3154 ImplErase( this, pItem->maRect, nHighlight != 0, bHasOpenPopup );
3157 else
3159 DecorationView aDecoView( this );
3160 aDecoView.DrawButton( aButtonRect, nStyle );
3164 nOffX += pItem->maRect.Left();
3165 nOffY += pItem->maRect.Top();
3167 // determine what has to be drawn on the button: image, text or both
3168 sal_Bool bImage;
3169 sal_Bool bText;
3170 ButtonType tmpButtonType = determineButtonType( pItem, meButtonType ); // default to toolbox setting
3171 pItem->DetermineButtonDrawStyle( tmpButtonType, bImage, bText );
3173 // compute output values
3174 long nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE;
3175 long nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE;
3176 Size aImageSize;
3177 Size aTxtSize;
3179 if ( bText )
3181 aTxtSize.Width() = GetCtrlTextWidth( pItem->maText );
3182 aTxtSize.Height() = GetTextHeight();
3185 if ( bImage && ! bLayout )
3187 const Image* pImage;
3188 if ( (nHighlight != 0) && (!(pItem->maHighImage)) == sal_False )
3189 pImage = &(pItem->maHighImage);
3190 else
3191 pImage = &(pItem->maImage);
3193 aImageSize = pImage->GetSizePixel();
3195 // determine drawing flags
3196 sal_uInt16 nImageStyle = 0;
3198 if ( !pItem->mbEnabled || !IsEnabled() )
3199 nImageStyle |= IMAGE_DRAW_DISABLE;
3201 // #i35563# the dontknow state indicates different states at the same time
3202 // which should not be rendered disabled but normal
3204 // draw the image
3205 nImageOffX = nOffX;
3206 nImageOffY = nOffY;
3207 if ( (pItem->mnBits & (TIB_LEFT|TIB_DROPDOWN)) || bText )
3209 // left align also to leave space for drop down arrow
3210 // and when drawing text+image
3211 // just center in y, except for vertical (ie rotated text)
3212 if( mbHorz || !bText )
3213 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3215 else
3217 nImageOffX += (nBtnWidth-aImageSize.Width())/2;
3218 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3220 if ( nHighlight != 0 || (pItem->meState == STATE_CHECK) )
3222 if( bHasOpenPopup )
3223 ImplDrawFloatwinBorder( pItem );
3224 else
3225 ImplDrawButton( this, aButtonRect, nHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? sal_True : sal_False );
3227 if( nHighlight != 0 )
3229 if( bHighContrastWhite )
3230 nImageStyle |= IMAGE_DRAW_COLORTRANSFORM;
3233 DrawImage( Point( nImageOffX, nImageOffY ), *pImage, nImageStyle );
3236 // draw the text
3237 sal_Bool bRotate = sal_False;
3238 if ( bText )
3240 long nTextOffX = nOffX;
3241 long nTextOffY = nOffY;
3243 // rotate text when vertically docked
3244 Font aOldFont = GetFont();
3245 if( pItem->mbVisibleText && !ImplIsFloatingMode() &&
3246 ((meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT)) )
3248 bRotate = sal_True;
3250 Font aRotateFont = aOldFont;
3251 aRotateFont.SetOrientation( 2700 );
3253 // center horizontally
3254 nTextOffX += aTxtSize.Height();
3255 nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
3257 // add in image offset
3258 if( bImage )
3259 nTextOffY = nImageOffY + aImageSize.Height() + TB_IMAGETEXTOFFSET;
3261 SetFont( aRotateFont );
3263 else
3265 // center vertically
3266 nTextOffY += (nBtnHeight-aTxtSize.Height())/2;
3268 // add in image offset
3269 if( bImage )
3270 nTextOffX = nImageOffX + aImageSize.Width() + TB_IMAGETEXTOFFSET;
3273 // draw selection only if not already drawn during image output (see above)
3274 if ( !bLayout && !bImage && (nHighlight != 0 || (pItem->meState == STATE_CHECK) ) )
3276 if( bHasOpenPopup )
3277 ImplDrawFloatwinBorder( pItem );
3278 else
3279 ImplDrawButton( this, pItem->maRect, nHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? sal_True : sal_False );
3282 sal_uInt16 nTextStyle = 0;
3283 if ( !pItem->mbEnabled )
3284 nTextStyle |= TEXT_DRAW_DISABLE;
3285 if( bLayout )
3287 mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.getLength() );
3288 mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3289 mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3291 DrawCtrlText( Point( nTextOffX, nTextOffY ), pItem->maText,
3292 0, STRING_LEN, nTextStyle, pVector, pDisplayText );
3293 if ( bRotate )
3294 SetFont( aOldFont );
3297 if( bLayout )
3298 return;
3300 // paint optional drop down arrow
3301 if ( pItem->mnBits & TIB_DROPDOWN )
3303 Rectangle aDropDownRect( pItem->GetDropDownRect( mbHorz ) );
3304 sal_Bool bSetColor = sal_True;
3305 if ( !pItem->mbEnabled || !IsEnabled() )
3307 bSetColor = sal_False;
3308 SetFillColor( rStyleSettings.GetShadowColor() );
3311 // dropdown only will be painted without inner border
3312 if( (pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY )
3314 ImplErase( this, aDropDownRect, nHighlight != 0, bHasOpenPopup );
3316 if( nHighlight != 0 || (pItem->meState == STATE_CHECK) )
3318 if( bHasOpenPopup )
3319 ImplDrawFloatwinBorder( pItem );
3320 else
3321 ImplDrawButton( this, aDropDownRect, nHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), sal_False );
3324 ImplDrawDropdownArrow( this, aDropDownRect, bSetColor, bRotate );
3327 // draw config-frame if required
3328 if ( pMgr )
3329 pMgr->UpdateDragRect();
3332 // -----------------------------------------------------------------------
3334 void ToolBox::ImplDrawFloatwinBorder( ImplToolItem* pItem )
3336 if ( !pItem->maRect.IsEmpty() )
3338 Rectangle aRect( mpFloatWin->ImplGetItemEdgeClipRect() );
3339 aRect.SetPos( AbsoluteScreenToOutputPixel( aRect.TopLeft() ) );
3340 SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
3341 Point p1, p2;
3343 p1 = pItem->maRect.TopLeft();
3344 p1.X()++;
3345 p2 = pItem->maRect.TopRight();
3346 p2.X()--;
3347 DrawLine( p1, p2);
3348 p1 = pItem->maRect.BottomLeft();
3349 p1.X()++;
3350 p2 = pItem->maRect.BottomRight();
3351 p2.X()--;
3352 DrawLine( p1, p2);
3354 p1 = pItem->maRect.TopLeft();
3355 p1.Y()++;
3356 p2 = pItem->maRect.BottomLeft();
3357 p2.Y()--;
3358 DrawLine( p1, p2);
3359 p1 = pItem->maRect.TopRight();
3360 p1.Y()++;
3361 p2 = pItem->maRect.BottomRight();
3362 p2.Y()--;
3363 DrawLine( p1, p2);
3365 //DrawRect( pItem->maRect );
3369 void ToolBox::ImplFloatControl( sal_Bool bStart, FloatingWindow* pFloatWindow )
3371 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3373 if ( bStart )
3375 mpFloatWin = pFloatWindow;
3377 // redraw item, to trigger drawing of a special border
3378 ImplDrawItem( mnCurPos, 1 );
3380 mbDrag = sal_False;
3381 EndTracking();
3382 ReleaseMouse();
3384 else
3386 mpFloatWin = NULL;
3388 // if focus is still in this toolbox, then the floater was opened by keyboard
3389 // draw current item with highlight and keep old state
3390 sal_Bool bWasKeyboardActivate = mpData->mbDropDownByKeyboard;
3393 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3394 ImplDrawItem( mnCurPos, bWasKeyboardActivate ? 2 : 0 );
3395 Deactivate();
3397 if( !bWasKeyboardActivate )
3399 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3400 mnCurItemId = 0;
3401 mnHighItemId = 0;
3403 mnDownItemId = 0;
3408 // -----------------------------------------------------------------------
3410 void ToolBox::ShowLine( sal_Bool bNext )
3412 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3414 mbFormat = sal_True;
3416 if ( mpData->mbPageScroll )
3418 sal_uInt16 delta = mnVisLines;
3419 if ( bNext )
3421 mnCurLine = mnCurLine + delta;
3422 if ( mnCurLine+mnVisLines-1 > mnCurLines )
3423 mnCurLine = mnCurLines - mnVisLines+1;
3425 else
3427 if( mnCurLine >= delta+1 )
3428 mnCurLine = mnCurLine - delta;
3429 else
3430 mnCurLine = 1;
3433 else
3435 if ( bNext )
3436 mnCurLine++;
3437 else
3438 mnCurLine--;
3441 ImplFormat();
3444 // -----------------------------------------------------------------------
3446 sal_Bool ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, sal_Bool bRepeat )
3448 Point aMousePos = rMEvt.GetPosPixel();
3450 // ToolBox active?
3451 if ( mbDrag && mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3453 // is the cursor over the item?
3454 ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
3455 if ( pItem->maRect.IsInside( aMousePos ) )
3457 if ( !mnCurItemId )
3459 ImplDrawItem( mnCurPos, 1 );
3460 mnCurItemId = pItem->mnId;
3461 Highlight();
3464 if ( (pItem->mnBits & TIB_REPEAT) && bRepeat )
3465 Select();
3467 else
3469 if ( mnCurItemId )
3471 ImplDrawItem( mnCurPos );
3472 mnCurItemId = 0;
3473 ImplDrawItem( mnCurPos );
3474 Highlight();
3478 return sal_True;
3481 if ( mbUpper )
3483 sal_Bool bNewIn = maUpperRect.IsInside( aMousePos );
3484 if ( bNewIn != mbIn )
3486 mbIn = bNewIn;
3487 ImplDrawSpin( mbIn, sal_False );
3489 return sal_True;
3492 if ( mbLower )
3494 sal_Bool bNewIn = maLowerRect.IsInside( aMousePos );
3495 if ( bNewIn != mbIn )
3497 mbIn = bNewIn;
3498 ImplDrawSpin( sal_False, mbIn );
3500 return sal_True;
3503 return sal_False;
3506 // -----------------------------------------------------------------------
3508 sal_Bool ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, sal_Bool bCancel )
3510 ImplDisableFlatButtons();
3512 // stop eventual running dropdown timer
3513 if( mnCurPos < mpData->m_aItems.size() &&
3514 (mpData->m_aItems[mnCurPos].mnBits & TIB_DROPDOWN ) )
3516 mpData->maDropdownTimer.Stop();
3519 if ( mbDrag || mbSelection )
3521 // set mouse data if in selection mode, as then
3522 // the MouseButtonDown handler cannot be called
3523 if ( mbSelection )
3525 mnMouseClicks = rMEvt.GetClicks();
3526 mnMouseModifier = rMEvt.GetModifier();
3529 Deactivate();
3531 if ( mbDrag )
3532 mbDrag = sal_False;
3533 else
3535 mbSelection = sal_False;
3536 if ( mnCurPos == TOOLBOX_ITEM_NOTFOUND )
3537 return sal_True;
3540 // has mouse been released on top of item?
3541 if( mnCurPos < mpData->m_aItems.size() )
3543 ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
3544 if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) )
3546 mnCurItemId = pItem->mnId;
3547 if ( !bCancel )
3549 // execute AutoCheck if required
3550 if ( pItem->mnBits & TIB_AUTOCHECK )
3552 if ( pItem->mnBits & TIB_RADIOCHECK )
3554 if ( pItem->meState != STATE_CHECK )
3555 SetItemState( pItem->mnId, STATE_CHECK );
3557 else
3559 if ( pItem->meState != STATE_CHECK )
3560 pItem->meState = STATE_CHECK;
3561 else
3562 pItem->meState = STATE_NOCHECK;
3566 // do not call Select when Repeat is active, as in this
3567 // case that was triggered already in MouseButtonDown
3568 if ( !(pItem->mnBits & TIB_REPEAT) )
3570 // prevent from being destroyed in the select handler
3571 ImplDelData aDelData;
3572 ImplAddDel( &aDelData );
3573 Select();
3574 if ( aDelData.IsDead() )
3575 return sal_True;
3576 ImplRemoveDel( &aDelData );
3581 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3584 // Items not destroyed, in Select handler
3585 if ( mnCurItemId )
3587 sal_uInt16 nHighlight;
3588 if ( (mnCurItemId == mnHighItemId) && (mnOutStyle & TOOLBOX_STYLE_FLAT) )
3589 nHighlight = 2;
3590 else
3591 nHighlight = 0;
3592 // Get current pos for the case that items are inserted/removed
3593 // in the toolBox
3594 mnCurPos = GetItemPos( mnCurItemId );
3595 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3597 ImplDrawItem( mnCurPos, nHighlight );
3598 Flush();
3604 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3605 mnCurItemId = 0;
3606 mnDownItemId = 0;
3607 mnMouseClicks = 0;
3608 mnMouseModifier = 0;
3609 return sal_True;
3611 else if ( mbUpper || mbLower )
3613 if ( mbIn )
3614 ShowLine( !mbUpper );
3615 mbUpper = sal_False;
3616 mbLower = sal_False;
3617 mbIn = sal_False;
3618 ImplDrawSpin( sal_False, sal_False );
3619 return sal_True;
3622 return sal_False;
3625 // -----------------------------------------------------------------------
3627 void ToolBox::MouseMove( const MouseEvent& rMEvt )
3629 // pressing a modifier generates synthetic mouse moves
3630 // ignore it if keyboard selection is acive
3631 if( HasFocus() && ( rMEvt.GetMode() & MOUSE_MODIFIERCHANGED ) )
3632 return;
3634 if ( ImplHandleMouseMove( rMEvt ) )
3635 return;
3637 ImplDisableFlatButtons();
3639 Point aMousePos = rMEvt.GetPosPixel();
3641 // only highlight when the focus is not inside a child window of a toolbox
3642 // eg, in a edit control
3643 // and do not hilight when focus is in a different toolbox
3644 sal_Bool bDrawHotSpot = sal_True;
3645 Window *pWin = Application::GetFocusWindow();
3646 if( pWin && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this )
3647 bDrawHotSpot = sal_False;
3649 if ( mbSelection && bDrawHotSpot )
3651 sal_uInt16 i = 0;
3652 sal_uInt16 nNewPos = TOOLBOX_ITEM_NOTFOUND;
3654 // search the item that has been clicked
3655 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3656 while ( it != mpData->m_aItems.end() )
3658 // if the mouse position is in this item,
3659 // we can stop the search
3660 if ( it->maRect.IsInside( aMousePos ) )
3662 // select it if it is a button
3663 if ( it->meType == TOOLBOXITEM_BUTTON )
3665 // if button is disabled, do not
3666 // change it
3667 if ( !it->mbEnabled || it->mbShowWindow )
3668 nNewPos = mnCurPos;
3669 else
3670 nNewPos = i;
3673 break;
3676 i++;
3677 ++it;
3680 // was a new entery selected ?
3681 // don't change selection if keyboard selection is active and
3682 // mouse leaves the toolbox
3683 if ( nNewPos != mnCurPos && !( HasFocus() && nNewPos == TOOLBOX_ITEM_NOTFOUND ) )
3685 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3687 ImplDrawItem( mnCurPos );
3688 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( mnCurPos ) );
3691 mnCurPos = nNewPos;
3692 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3694 mnCurItemId = mnHighItemId = it->mnId;
3695 ImplDrawItem( mnCurPos, 2 ); // always use shadow effect (2)
3697 else
3698 mnCurItemId = mnHighItemId = 0;
3700 Highlight();
3702 return;
3705 if ( mbDragging )
3707 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
3708 pMgr->Dragging( aMousePos );
3709 return;
3712 PointerStyle eStyle = POINTER_ARROW;
3714 // change mouse cursor over drag area
3715 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
3716 if( pWrapper && pWrapper->GetDragArea().IsInside( rMEvt.GetPosPixel() ) )
3717 eStyle = POINTER_MOVE;
3719 if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
3721 if ( rMEvt.GetMode() & MOUSE_SIMPLEMOVE )
3723 sal_uInt16 nLinePtr = ImplTestLineSize( this, rMEvt.GetPosPixel() );
3724 if ( nLinePtr & DOCK_LINEHSIZE )
3726 if ( meAlign == WINDOWALIGN_LEFT )
3727 eStyle = POINTER_WINDOW_ESIZE;
3728 else
3729 eStyle = POINTER_WINDOW_WSIZE;
3731 else if ( nLinePtr & DOCK_LINEVSIZE )
3733 if ( meAlign == WINDOWALIGN_TOP )
3734 eStyle = POINTER_WINDOW_SSIZE;
3735 else
3736 eStyle = POINTER_WINDOW_NSIZE;
3741 if ( (eStyle == POINTER_ARROW) && mbCustomizeMode )
3743 // search the item which was clicked
3744 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3745 while ( it != mpData->m_aItems.end() )
3747 // show resize pointer if it is a customize window
3748 if ( it->mbShowWindow )
3750 if ( it->maRect.IsInside( aMousePos ) )
3752 if ( it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X() )
3753 eStyle = POINTER_HSIZEBAR;
3754 break;
3758 ++it;
3762 if ( bDrawHotSpot && ( (mnOutStyle & TOOLBOX_STYLE_FLAT) || !mnOutStyle ) )
3764 sal_Bool bClearHigh = sal_True;
3765 if ( !rMEvt.IsLeaveWindow() && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
3767 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3768 while ( it != mpData->m_aItems.end() )
3770 if ( it->maRect.IsInside( aMousePos ) )
3772 if ( (it->meType == TOOLBOXITEM_BUTTON) && it->mbEnabled )
3774 if ( !mnOutStyle || (mnOutStyle & TOOLBOX_STYLE_FLAT) )
3776 bClearHigh = sal_False;
3777 if ( mnHighItemId != it->mnId )
3779 sal_uInt16 nTempPos = sal::static_int_cast<sal_uInt16>(it - mpData->m_aItems.begin());
3780 if ( mnHighItemId )
3782 ImplHideFocus();
3783 sal_uInt16 nPos = GetItemPos( mnHighItemId );
3784 ImplDrawItem( nPos );
3785 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
3787 if ( mpData->mbMenubuttonSelected )
3789 // remove highlight from menubutton
3790 ImplDrawMenubutton( this, sal_False );
3792 mnHighItemId = it->mnId;
3793 ImplDrawItem( nTempPos, 2 );
3794 ImplShowFocus();
3795 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
3799 break;
3802 ++it;
3806 // only clear highlight when focus is not in toolbar
3807 sal_Bool bMenuButtonHit = mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) && ImplHasClippedItems();
3808 if ( bClearHigh || bMenuButtonHit )
3810 if ( !bMenuButtonHit && mpData->mbMenubuttonSelected )
3812 // remove highlight from menubutton
3813 ImplDrawMenubutton( this, sal_False );
3816 if( mnHighItemId )
3818 sal_uInt16 nClearPos = GetItemPos( mnHighItemId );
3819 if ( nClearPos != TOOLBOX_ITEM_NOTFOUND )
3821 ImplDrawItem( nClearPos, (nClearPos == mnCurPos) ? 1 : 0 );
3822 if( nClearPos != mnCurPos )
3823 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nClearPos ) );
3825 ImplHideFocus();
3826 mnHighItemId = 0;
3829 if( bMenuButtonHit )
3831 ImplDrawMenubutton( this, sal_True );
3836 if ( meLastStyle != eStyle )
3838 meLastStyle = eStyle;
3839 Pointer aPtr( eStyle );
3840 SetPointer( aPtr );
3843 DockingWindow::MouseMove( rMEvt );
3846 // -----------------------------------------------------------------------
3848 void ToolBox::MouseButtonDown( const MouseEvent& rMEvt )
3850 // only trigger toolbox for left mouse button and when
3851 // we're not in normal operation
3852 if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
3854 // call activate already here, as items could
3855 // be exchanged
3856 Activate();
3858 // update ToolBox here, such that user knows it
3859 if ( mbFormat )
3861 ImplFormat();
3862 Update();
3865 Point aMousePos = rMEvt.GetPosPixel();
3866 sal_uInt16 i = 0;
3867 sal_uInt16 nNewPos = TOOLBOX_ITEM_NOTFOUND;
3869 // search for item that was clicked
3870 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3871 while ( it != mpData->m_aItems.end() )
3873 // is this the item?
3874 if ( it->maRect.IsInside( aMousePos ) )
3876 // do nothing if it is a separator or
3877 // if the item has been disabled
3878 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
3879 (!it->mbShowWindow || mbCustomizeMode) )
3880 nNewPos = i;
3882 break;
3885 i++;
3886 ++it;
3889 // item found
3890 if ( nNewPos != TOOLBOX_ITEM_NOTFOUND )
3892 if ( mbCustomize )
3894 if ( rMEvt.IsMod2() || mbCustomizeMode )
3896 Deactivate();
3898 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
3899 Rectangle aItemRect = GetItemRect( it->mnId );
3900 mnConfigItem = it->mnId;
3902 sal_Bool bResizeItem;
3903 if ( mbCustomizeMode && it->mbShowWindow &&
3904 (it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X()) )
3905 bResizeItem = sal_True;
3906 else
3907 bResizeItem = sal_False;
3908 pMgr->StartDragging( this, aMousePos, aItemRect, 0, bResizeItem );
3909 return;
3913 if ( !it->mbEnabled )
3915 Deactivate();
3916 return;
3920 // update actual data
3921 sal_uInt16 nTrackFlags = 0;
3922 mnCurPos = i;
3923 mnCurItemId = it->mnId;
3924 mnDownItemId = mnCurItemId;
3925 mnMouseClicks = rMEvt.GetClicks();
3926 mnMouseModifier = rMEvt.GetModifier();
3927 if ( it->mnBits & TIB_REPEAT )
3928 nTrackFlags |= STARTTRACK_BUTTONREPEAT;
3931 if ( mbSelection )
3933 ImplDrawItem( mnCurPos, 1 );
3934 Highlight();
3936 else
3938 // update bDrag here, as it is evaluated in the EndSelection
3939 mbDrag = sal_True;
3941 // on double-click: only call the handler, but do so before the button
3942 // is hit, as in the handler dragging
3943 // can be terminated
3944 if ( rMEvt.GetClicks() == 2 )
3945 DoubleClick();
3948 if ( mbDrag )
3950 ImplDrawItem( mnCurPos, 1 );
3951 Highlight();
3954 // was dropdown arrow pressed
3955 if( (it->mnBits & TIB_DROPDOWN) )
3957 if( ( (it->mnBits & TIB_DROPDOWNONLY) == TIB_DROPDOWNONLY) || it->GetDropDownRect( mbHorz ).IsInside( aMousePos ))
3959 // dropdownonly always triggers the dropdown handler, over the whole button area
3961 // the drop down arrow should not trigger the item action
3962 mpData->mbDropDownByKeyboard = sal_False;
3963 GetDropdownClickHdl().Call( this );
3965 // do not reset data if the dropdown handler opened a floating window
3966 // see ImplFloatControl()
3967 if( mpFloatWin == NULL )
3969 // no floater was opened
3970 Deactivate();
3971 ImplDrawItem( mnCurPos, 0 );
3973 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3974 mnCurItemId = 0;
3975 mnDownItemId = 0;
3976 mnMouseClicks = 0;
3977 mnMouseModifier = 0;
3978 mnHighItemId = 0;
3980 return;
3982 else // activate long click timer
3983 mpData->maDropdownTimer.Start();
3987 // call Click handler
3988 if ( rMEvt.GetClicks() != 2 )
3989 Click();
3991 // also call Select handler at repeat
3992 if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
3993 Select();
3995 // if the actions was not aborted in Click handler
3996 if ( mbDrag )
3997 StartTracking( nTrackFlags );
4000 // if mouse was clicked over an item we
4001 // can abort here
4002 return;
4005 Deactivate();
4007 // menu button hit ?
4008 if( mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) && ImplHasClippedItems() )
4010 ExecuteCustomMenu();
4011 return;
4014 // check scroll- and next-buttons here
4015 if ( maUpperRect.IsInside( aMousePos ) )
4017 if ( mnCurLine > 1 )
4019 StartTracking();
4020 mbUpper = sal_True;
4021 mbIn = sal_True;
4022 ImplDrawSpin( sal_True, sal_False );
4024 return;
4026 if ( maLowerRect.IsInside( aMousePos ) )
4028 if ( mnCurLine+mnVisLines-1 < mnCurLines )
4030 StartTracking();
4031 mbLower = sal_True;
4032 mbIn = sal_True;
4033 ImplDrawSpin( sal_False, sal_True );
4035 return;
4038 // Linesizing testen
4039 if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4041 sal_uInt16 nLineMode = ImplTestLineSize( this, aMousePos );
4042 if ( nLineMode )
4044 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4046 // call handler, such that we can set the
4047 // dock rectangles
4048 StartDocking();
4050 Point aPos = GetParent()->OutputToScreenPixel( GetPosPixel() );
4051 Size aSize = GetSizePixel();
4052 aPos = ScreenToOutputPixel( aPos );
4054 // start dragging
4055 pMgr->StartDragging( this, aMousePos, Rectangle( aPos, aSize ),
4056 nLineMode, sal_False );
4057 return;
4061 // no item, then only click or double click
4062 if ( rMEvt.GetClicks() == 2 )
4063 DoubleClick();
4064 else
4065 Click();
4068 if ( !mbDrag && !mbSelection && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4069 DockingWindow::MouseButtonDown( rMEvt );
4072 // -----------------------------------------------------------------------
4074 void ToolBox::MouseButtonUp( const MouseEvent& rMEvt )
4076 if ( ImplHandleMouseButtonUp( rMEvt ) )
4077 return;
4079 if ( mbDragging && (rMEvt.IsLeft() || mbCommandDrag) )
4081 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4082 pMgr->EndDragging();
4083 return;
4085 mbCommandDrag = sal_False;
4087 DockingWindow::MouseButtonUp( rMEvt );
4090 // -----------------------------------------------------------------------
4092 void ToolBox::Tracking( const TrackingEvent& rTEvt )
4094 ImplDelData aDelData;
4095 ImplAddDel( &aDelData );
4097 if ( rTEvt.IsTrackingEnded() )
4098 ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() );
4099 else
4100 ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() );
4102 if ( aDelData.IsDead() )
4103 // toolbox was deleted
4104 return;
4105 ImplRemoveDel( &aDelData );
4106 DockingWindow::Tracking( rTEvt );
4109 // -----------------------------------------------------------------------
4111 void ToolBox::Paint( const Rectangle& rPaintRect )
4113 if( mpData->mbIsPaintLocked )
4114 return;
4115 if ( rPaintRect == Rectangle( 0, 0, mnDX-1, mnDY-1 ) )
4116 mbFullPaint = sal_True;
4117 ImplFormat();
4118 mbFullPaint = sal_False;
4121 ImplDrawBackground( this, rPaintRect );
4123 if ( (mnWinStyle & WB_BORDER) && !ImplIsFloatingMode() )
4124 ImplDrawBorder( this );
4126 if( !ImplIsFloatingMode() )
4127 ImplDrawGrip( this );
4129 ImplDrawMenubutton( this, mpData->mbMenubuttonSelected );
4131 // draw SpinButtons
4132 if ( mnWinStyle & WB_SCROLL )
4134 if ( mnCurLines > mnLines )
4135 ImplDrawSpin( sal_False, sal_False );
4138 // draw buttons
4139 sal_uInt16 nHighPos;
4140 if ( mnHighItemId )
4141 nHighPos = GetItemPos( mnHighItemId );
4142 else
4143 nHighPos = TOOLBOX_ITEM_NOTFOUND;
4145 sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
4146 for( sal_uInt16 i = 0; i < nCount; i++ )
4148 ImplToolItem* pItem = &mpData->m_aItems[i];
4150 // only draw when the rectangle is in the draw rectangle
4151 if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) )
4153 sal_uInt16 nHighlight = 0;
4154 if ( i == mnCurPos )
4155 nHighlight = 1;
4156 else if ( i == nHighPos )
4157 nHighlight = 2;
4158 ImplDrawItem( i, nHighlight );
4161 ImplShowFocus();
4164 // -----------------------------------------------------------------------
4166 void ToolBox::Move()
4168 DockingWindow::Move();
4171 // -----------------------------------------------------------------------
4173 void ToolBox::Resize()
4175 Size aSize = GetOutputSizePixel();
4176 // #i31422# some WindowManagers send (0,0) sizes when
4177 // switching virtual desktops - ignore this and avoid reformatting
4178 if( !aSize.Width() && !aSize.Height() )
4179 return;
4181 long nOldDX = mnDX;
4182 long nOldDY = mnDY;
4183 mnDX = aSize.Width();
4184 mnDY = aSize.Height();
4186 mnLastResizeDY = 0;
4188 // invalidate everything to have gradient backgrounds properly drawn
4189 Invalidate();
4191 // re-format or re-draw
4192 if ( mbScroll )
4194 if ( !mbFormat )
4196 mbFormat = sal_True;
4197 if( IsReallyVisible() )
4198 ImplFormat( sal_True );
4202 // redraw border
4203 if ( mnWinStyle & WB_BORDER )
4205 // as otherwise, when painting we might think we have to re-draw everything
4206 if ( mbFormat && IsReallyVisible() )
4207 Invalidate();
4208 else
4210 if ( mnRightBorder )
4212 if ( nOldDX > mnDX )
4213 Invalidate( Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) );
4214 else
4215 Invalidate( Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) );
4218 if ( mnBottomBorder )
4220 if ( nOldDY > mnDY )
4221 Invalidate( Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) );
4222 else
4223 Invalidate( Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) );
4229 // -----------------------------------------------------------------------
4230 const XubString& ToolBox::ImplGetHelpText( sal_uInt16 nItemId ) const
4232 ImplToolItem* pItem = ImplGetItem( nItemId );
4234 if ( pItem )
4236 if ( !pItem->maHelpText.Len() && ( !pItem->maHelpId.isEmpty() || pItem->maCommandStr.Len() ))
4238 Help* pHelp = Application::GetHelp();
4239 if ( pHelp )
4241 if ( pItem->maCommandStr.Len() )
4242 pItem->maHelpText = pHelp->GetHelpText( pItem->maCommandStr, this );
4243 if ( !pItem->maHelpText.Len() && !pItem->maHelpId.isEmpty() )
4244 pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
4248 return pItem->maHelpText;
4250 else
4251 return ImplGetSVEmptyStr();
4254 // -----------------------------------------------------------------------
4256 void ToolBox::RequestHelp( const HelpEvent& rHEvt )
4258 sal_uInt16 nItemId;
4259 Point aHelpPos;
4261 if( !rHEvt.KeyboardActivated() )
4263 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
4264 aHelpPos = rHEvt.GetMousePosPixel();
4266 else
4268 if( !mnHighItemId )
4269 return;
4270 else
4271 nItemId = mnHighItemId;
4272 Rectangle aRect( GetItemRect( nItemId ) );
4273 if( aRect.IsEmpty() )
4274 return;
4275 else
4276 aHelpPos = OutputToScreenPixel( aRect.Center() );
4279 if ( nItemId )
4281 if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4283 // get rectangle
4284 Rectangle aTempRect = GetItemRect( nItemId );
4285 Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4286 aTempRect.Left() = aPt.X();
4287 aTempRect.Top() = aPt.Y();
4288 aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4289 aTempRect.Right() = aPt.X();
4290 aTempRect.Bottom() = aPt.Y();
4292 // get text and display it
4293 XubString aStr = GetQuickHelpText( nItemId );
4294 const XubString& rHelpStr = GetHelpText( nItemId );
4295 if ( !aStr.Len() )
4296 aStr = MnemonicGenerator::EraseAllMnemonicChars( GetItemText( nItemId ) );
4297 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4299 if ( rHelpStr.Len() )
4300 aStr = rHelpStr;
4301 Help::ShowBalloon( this, aHelpPos, aTempRect, aStr );
4303 else
4304 Help::ShowQuickHelp( this, aTempRect, aStr, rHelpStr, QUICKHELP_CTRLTEXT );
4305 return;
4307 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
4309 String aCommand = GetItemCommand( nItemId );
4310 OString aHelpId( GetHelpId( nItemId ) );
4312 if ( aCommand.Len() || !aHelpId.isEmpty() )
4314 // If help is available then trigger it
4315 Help* pHelp = Application::GetHelp();
4316 if ( pHelp )
4318 if ( aCommand.Len() )
4319 pHelp->Start( aCommand, this );
4320 else if ( !aHelpId.isEmpty() )
4321 pHelp->Start( OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), this );
4323 return;
4328 DockingWindow::RequestHelp( rHEvt );
4331 // -----------------------------------------------------------------------
4333 long ToolBox::Notify( NotifyEvent& rNEvt )
4335 if ( rNEvt.GetType() == EVENT_KEYINPUT )
4337 KeyEvent aKEvt = *rNEvt.GetKeyEvent();
4338 KeyCode aKeyCode = aKEvt.GetKeyCode();
4339 sal_uInt16 nKeyCode = aKeyCode.GetCode();
4340 switch( nKeyCode )
4342 case KEY_TAB:
4344 // internal TAB cycling only if parent is not a dialog or if we are the ony child
4345 // otherwise the dialog control will take over
4346 sal_Bool bNoTabCycling = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL &&
4347 ImplGetParent()->GetChildCount() != 1 );
4349 if( bNoTabCycling && ! (GetStyle() & WB_FORCETABCYCLE) )
4350 return DockingWindow::Notify( rNEvt );
4351 else if( ImplChangeHighlightUpDn( aKeyCode.IsShift() ? sal_True : sal_False , bNoTabCycling ) )
4352 return sal_False;
4353 else
4354 return DockingWindow::Notify( rNEvt );
4356 default:
4357 break;
4360 else if( rNEvt.GetType() == EVENT_GETFOCUS )
4362 if( rNEvt.GetWindow() == this )
4364 // the toolbar itself got the focus
4365 if( mnLastFocusItemId != 0 )
4367 // restore last item
4368 ImplChangeHighlight( ImplGetItem( mnLastFocusItemId ) );
4369 mnLastFocusItemId = 0;
4371 else if( (GetGetFocusFlags() & (GETFOCUS_BACKWARD|GETFOCUS_TAB) ) == (GETFOCUS_BACKWARD|GETFOCUS_TAB))
4372 // Shift-TAB was pressed in the parent
4373 ImplChangeHighlightUpDn( sal_False );
4374 else
4375 ImplChangeHighlightUpDn( sal_True );
4377 mnLastFocusItemId = 0;
4379 return true;
4381 else
4383 // a child window got the focus so update current item to
4384 // allow for proper lose focus handling in keyboard navigation
4385 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4386 while( it != mpData->m_aItems.end() )
4388 if ( it->mbVisible )
4390 if ( it->mpWindow && it->mpWindow->ImplIsWindowOrChild( rNEvt.GetWindow() ) )
4392 mnHighItemId = it->mnId;
4393 break;
4397 ++it;
4399 return DockingWindow::Notify( rNEvt );
4402 else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
4404 // deselect
4405 ImplHideFocus();
4406 mnHighItemId = 0;
4407 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
4410 return DockingWindow::Notify( rNEvt );
4413 // -----------------------------------------------------------------------
4415 void ToolBox::Command( const CommandEvent& rCEvt )
4417 if ( maCommandHandler.IsSet() )
4418 maCommandHandler.Call( (void *)( &rCEvt ));
4420 // depict StartDrag on MouseButton/Left/Alt
4421 if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) && rCEvt.IsMouseEvent() &&
4422 mbCustomize && !mbDragging && !mbDrag && !mbSelection &&
4423 (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4425 // We only allow dragging of items. Therefore, we have to check
4426 // if an item was clicked, otherwise we could move the window, and
4427 // this is unwanted.
4428 // We only do this in customize mode, as otherwise
4429 // items could be moved accidentally
4430 if ( mbCustomizeMode )
4432 Point aMousePos = rCEvt.GetMousePosPixel();
4433 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4434 while ( it != mpData->m_aItems.end() )
4436 // is this the item?
4437 if ( it->maRect.IsInside( aMousePos ) )
4439 // do nothing if it is a separator or
4440 // the item has been disabled
4441 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
4442 !it->mbShowWindow )
4443 mbCommandDrag = sal_True;
4444 break;
4447 ++it;
4450 if ( mbCommandDrag )
4452 MouseEvent aMEvt( aMousePos, 1, MOUSE_SIMPLECLICK,
4453 MOUSE_LEFT, KEY_MOD2 );
4454 ToolBox::MouseButtonDown( aMEvt );
4455 return;
4459 else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
4461 if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) )
4463 const CommandWheelData* pData = rCEvt.GetWheelData();
4464 if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
4466 if ( (mnCurLine > 1) && (pData->GetDelta() > 0) )
4467 ShowLine( sal_False );
4468 else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) )
4469 ShowLine( sal_True );
4470 ImplDrawSpin( sal_False, sal_False );
4471 return;
4476 DockingWindow::Command( rCEvt );
4479 // -----------------------------------------------------------------------
4481 void ToolBox::StateChanged( StateChangedType nType )
4483 DockingWindow::StateChanged( nType );
4485 if ( nType == STATE_CHANGE_INITSHOW )
4486 ImplFormat();
4487 else if ( nType == STATE_CHANGE_ENABLE )
4488 ImplUpdateItem();
4489 else if ( nType == STATE_CHANGE_UPDATEMODE )
4491 if ( IsUpdateMode() )
4492 Invalidate();
4494 else if ( (nType == STATE_CHANGE_ZOOM) ||
4495 (nType == STATE_CHANGE_CONTROLFONT) )
4497 mbCalc = sal_True;
4498 mbFormat = sal_True;
4499 ImplInitSettings( sal_True, sal_False, sal_False );
4500 Invalidate();
4502 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
4504 ImplInitSettings( sal_False, sal_True, sal_False );
4505 Invalidate();
4507 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
4509 ImplInitSettings( sal_False, sal_False, sal_True ); // font, foreground, background
4510 Invalidate();
4513 if ( maStateChangedHandler.IsSet() )
4514 maStateChangedHandler.Call( &nType );
4517 // -----------------------------------------------------------------------
4519 void ToolBox::DataChanged( const DataChangedEvent& rDCEvt )
4521 DockingWindow::DataChanged( rDCEvt );
4523 if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
4524 (rDCEvt.GetType() == DATACHANGED_FONTS) ||
4525 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
4526 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
4527 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
4529 mbCalc = sal_True;
4530 mbFormat = sal_True;
4531 ImplInitSettings( sal_True, sal_True, sal_True );
4532 Invalidate();
4535 if ( maDataChangedHandler.IsSet() )
4536 maDataChangedHandler.Call( (void*)&rDCEvt );
4539 // -----------------------------------------------------------------------
4541 sal_Bool ToolBox::PrepareToggleFloatingMode()
4543 return DockingWindow::PrepareToggleFloatingMode();
4546 // -----------------------------------------------------------------------
4548 void ToolBox::ToggleFloatingMode()
4550 DockingWindow::ToggleFloatingMode();
4552 sal_Bool mbOldHorz = mbHorz;
4554 if ( ImplIsFloatingMode() )
4556 mbHorz = sal_True;
4557 meAlign = WINDOWALIGN_TOP;
4558 mbScroll = sal_True;
4560 if( mbOldHorz != mbHorz )
4561 mbCalc = sal_True; // orientation was changed !
4563 ImplSetMinMaxFloatSize( this );
4564 SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
4566 else
4568 mbScroll = (mnWinStyle & WB_SCROLL) ? sal_True : sal_False;
4569 if ( (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM) )
4570 mbHorz = sal_True;
4571 else
4572 mbHorz = sal_False;
4574 // set focus back to document
4575 ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
4578 if( mbOldHorz != mbHorz )
4580 // if orientation changes, the toolbox has to be initialized again
4581 // to update the direction of the gradient
4582 mbCalc = sal_True;
4583 ImplInitSettings( sal_True, sal_True, sal_True );
4586 mbFormat = sal_True;
4587 ImplFormat();
4590 // -----------------------------------------------------------------------
4592 void ToolBox::StartDocking()
4594 meDockAlign = meAlign;
4595 mnDockLines = mnLines;
4596 mbLastFloatMode = ImplIsFloatingMode();
4597 DockingWindow::StartDocking();
4600 // -----------------------------------------------------------------------
4602 sal_Bool ToolBox::Docking( const Point& rPos, Rectangle& rRect )
4604 // do nothing during dragging, it was calculated before
4605 if ( mbDragging )
4606 return sal_False;
4608 sal_Bool bFloatMode = sal_False;
4610 DockingWindow::Docking( rPos, rRect );
4612 // if the mouse is outside the area, it can only become a floating window
4613 Rectangle aDockingRect( rRect );
4614 if ( !ImplIsFloatingMode() )
4616 // don't use tracking rectangle for alignment check, because it will be too large
4617 // to get a floating mode as result - switch to floating size
4618 // so the calculation only depends on the position of the rectangle, not the current
4619 // docking state of the window
4620 sal_uInt16 nTemp = 0;
4621 aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
4623 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
4624 aDockingRect.SetPos( ImplGetFrameWindow()->GetPointerPosPixel() );
4627 Rectangle aIntersection = maOutDockRect.GetIntersection( aDockingRect );
4628 if ( !aIntersection.IsEmpty() && !IsDockingPrevented() )
4630 Rectangle aInRect = maInDockRect;
4631 Size aDockSize;
4632 aDockSize.Width() = ImplCalcSize( this, mnLines, TB_CALCMODE_VERT ).Width();
4633 aDockSize.Height() = ImplCalcSize( this, mnLines, TB_CALCMODE_HORZ ).Height();
4634 aInRect.Left() += aDockSize.Width()/2;
4635 aInRect.Top() += aDockSize.Height()/2;
4636 aInRect.Right() -= aDockSize.Width()/2;
4637 aInRect.Bottom() -= aDockSize.Height()/2;
4639 // if the window is too small, use the complete InDock-Rect
4640 if ( aInRect.Left() >= aInRect.Right() )
4642 aInRect.Left() = maInDockRect.Left();
4643 aInRect.Right() = maInDockRect.Right();
4645 if ( aInRect.Top() >= aInRect.Bottom() )
4647 aInRect.Top() = maInDockRect.Top();
4648 aInRect.Bottom() = maInDockRect.Bottom();
4651 // if the mouse is outside the Dock area, it can only
4652 // become a floating window
4653 Rectangle aIntersect = aInRect.GetIntersection( aDockingRect );
4654 if ( aIntersect == aDockingRect )
4655 bFloatMode = sal_True;
4656 else
4658 // docking rectangle is in the "sensible area"
4659 Point aPos = aDockingRect.TopLeft();
4660 Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
4661 Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
4662 Size aInSize = aInRect.GetSize();
4664 if ( aInPosTL.X() <= 0 )
4665 meDockAlign = WINDOWALIGN_LEFT;
4666 else if ( aInPosTL.Y() <= 0)
4667 meDockAlign = WINDOWALIGN_TOP;
4668 else if ( aInPosBR.X() >= aInSize.Width() )
4669 meDockAlign = WINDOWALIGN_RIGHT;
4670 else if ( aInPosBR.Y() >= aInSize.Height() )
4671 meDockAlign = WINDOWALIGN_BOTTOM;
4673 // update the Dock size if Dock-Align was changed
4674 if ( (meDockAlign == WINDOWALIGN_TOP) || (meDockAlign == WINDOWALIGN_BOTTOM) )
4675 aDockSize.Width() = maInDockRect.GetWidth();
4676 else
4677 aDockSize.Height() = maInDockRect.GetHeight();
4679 aDockingRect.SetSize( aDockSize );
4681 Point aPosTL( maInDockRect.TopLeft() );
4682 switch ( meDockAlign )
4684 case WINDOWALIGN_TOP :
4685 aDockingRect.SetPos( aPosTL );
4686 break;
4687 case WINDOWALIGN_LEFT :
4688 aDockingRect.SetPos( aPosTL );
4689 break;
4690 case WINDOWALIGN_BOTTOM :
4692 Point aPosBL( maInDockRect.BottomLeft() );
4693 aPosBL.Y() -= aDockingRect.GetHeight();
4694 aDockingRect.SetPos( aPosBL );
4695 break;
4697 case WINDOWALIGN_RIGHT :
4699 Point aPosTR( maInDockRect.TopRight() );
4700 aPosTR.X() -= aDockingRect.GetWidth();
4701 aDockingRect.SetPos( aPosTR );
4702 break;
4707 else
4708 bFloatMode = sal_True;
4710 if ( bFloatMode )
4712 meDockAlign = meAlign;
4713 if ( !mbLastFloatMode )
4715 sal_uInt16 nTemp = 0;
4716 aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
4720 rRect = aDockingRect;
4721 mbLastFloatMode = bFloatMode;
4723 return bFloatMode;
4726 // -----------------------------------------------------------------------
4728 void ToolBox::EndDocking( const Rectangle& rRect, sal_Bool bFloatMode )
4730 if ( !IsDockingCanceled() )
4732 if ( mnLines != mnDockLines )
4733 SetLineCount( mnDockLines );
4734 if ( meAlign != meDockAlign )
4735 SetAlign( meDockAlign );
4737 if ( bFloatMode || (bFloatMode != ImplIsFloatingMode()) )
4738 DockingWindow::EndDocking( rRect, bFloatMode );
4741 // -----------------------------------------------------------------------
4743 void ToolBox::Resizing( Size& rSize )
4745 sal_uInt16 nCalcLines;
4746 sal_uInt16 nTemp;
4748 // Alle Floatinggroessen berechnen
4749 ImplCalcFloatSizes( this );
4751 if ( !mnLastResizeDY )
4752 mnLastResizeDY = mnDY;
4754 // Ist vertikales Resizing angesagt
4755 if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) )
4757 nCalcLines = ImplCalcLines( this, rSize.Height() );
4758 if ( nCalcLines < 1 )
4759 nCalcLines = 1;
4760 rSize = ImplCalcFloatSize( this, nCalcLines );
4762 else
4764 nCalcLines = 1;
4765 nTemp = nCalcLines;
4766 Size aTempSize = ImplCalcFloatSize( this, nTemp );
4767 while ( (aTempSize.Width() > rSize.Width()) &&
4768 (nCalcLines <= maFloatSizes[0].mnLines) )
4770 nCalcLines++;
4771 nTemp = nCalcLines;
4772 aTempSize = ImplCalcFloatSize( this, nTemp );
4774 rSize = aTempSize;
4777 mnLastResizeDY = rSize.Height();
4780 Size ToolBox::GetOptimalSize() const
4782 return ImplCalcSize( this, mnLines );
4785 Size ToolBox::CalcWindowSizePixel( sal_uInt16 nCalcLines ) const
4787 return ImplCalcSize( this, nCalcLines );
4790 Size ToolBox::CalcWindowSizePixel( sal_uInt16 nCalcLines, WindowAlign eAlign ) const
4792 return ImplCalcSize( this, nCalcLines,
4793 (eAlign == WINDOWALIGN_TOP || eAlign == WINDOWALIGN_BOTTOM) ? TB_CALCMODE_HORZ : TB_CALCMODE_VERT );
4796 sal_uInt16 ToolBox::ImplCountLineBreaks( const ToolBox *pThis )
4798 sal_uInt16 nLines = 0;
4800 std::vector< ImplToolItem >::const_iterator it = ((ToolBox*)pThis)->mpData->m_aItems.begin();
4801 while ( it != ((ToolBox*)pThis)->mpData->m_aItems.end() )
4803 if( it->meType == TOOLBOXITEM_BREAK )
4804 ++nLines;
4805 ++it;
4807 return nLines;
4810 Size ToolBox::CalcPopupWindowSizePixel() const
4812 // count number of breaks and calc corresponding floating window size
4813 sal_uInt16 nLines = ImplCountLineBreaks( this );
4815 if( nLines )
4816 ++nLines; // add the first line
4817 else
4819 // no breaks found: use quadratic layout
4820 nLines = (sal_uInt16) ceil( sqrt( (double) GetItemCount() ) );
4823 sal_Bool bPopup = mpData->mbAssumePopupMode;
4824 ToolBox *pThis = (ToolBox*) this;
4825 pThis->mpData->mbAssumePopupMode = sal_True;
4827 Size aSize = CalcFloatingWindowSizePixel( nLines );
4829 pThis->mpData->mbAssumePopupMode = bPopup;
4830 return aSize;
4833 Size ToolBox::CalcFloatingWindowSizePixel() const
4835 sal_uInt16 nLines = ImplCountLineBreaks( this );
4836 ++nLines; // add the first line
4837 return CalcFloatingWindowSizePixel( nLines );
4840 Size ToolBox::CalcFloatingWindowSizePixel( sal_uInt16 nCalcLines ) const
4842 sal_Bool bFloat = mpData->mbAssumeFloating;
4843 sal_Bool bDocking = mpData->mbAssumeDocked;
4845 // simulate floating mode and force reformat before calculating
4846 ToolBox *pThis = (ToolBox*) this;
4847 pThis->mpData->mbAssumeFloating = sal_True;
4848 pThis->mpData->mbAssumeDocked = sal_False;
4850 Size aSize = ImplCalcFloatSize( (ToolBox*) this, nCalcLines );
4852 pThis->mbFormat = sal_True;
4853 pThis->mpData->mbAssumeFloating = bFloat;
4854 pThis->mpData->mbAssumeDocked = bDocking;
4856 return aSize;
4859 // -----------------------------------------------------------------------
4861 Size ToolBox::CalcMinimumWindowSizePixel() const
4863 if( ImplIsFloatingMode() )
4864 return ImplCalcSize( this, mnFloatLines );
4865 else
4867 // create dummy toolbox for measurements
4868 ToolBox *pToolBox = new ToolBox( GetParent(), GetStyle() );
4870 // copy until first useful item
4871 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
4872 while( it != mpData->m_aItems.end() )
4874 pToolBox->CopyItem( *this, it->mnId );
4875 if( (it->meType != TOOLBOXITEM_BUTTON) ||
4876 !it->mbVisible || ImplIsFixedControl( &(*it) ) )
4877 ++it;
4878 else
4879 break;
4882 // add to docking manager if required to obtain a drag area
4883 // (which is accounted for in calcwindowsizepixel)
4884 if( ImplGetDockingManager()->GetDockingWindowWrapper( this ) )
4885 ImplGetDockingManager()->AddWindow( pToolBox );
4887 // account for menu
4888 if( IsMenuEnabled() )
4889 pToolBox->SetMenuType( GetMenuType() );
4891 pToolBox->SetAlign( GetAlign() );
4892 Size aSize = pToolBox->CalcWindowSizePixel( 1 );
4894 ImplGetDockingManager()->RemoveWindow( pToolBox );
4895 pToolBox->Clear();
4896 delete pToolBox;
4898 return aSize;
4902 // -----------------------------------------------------------------------
4904 void ToolBox::EnableCustomize( sal_Bool bEnable )
4906 if ( bEnable != mbCustomize )
4908 mbCustomize = bEnable;
4910 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4911 if ( bEnable )
4912 pMgr->push_back( this );
4913 else
4914 pMgr->erase( this );
4918 // -----------------------------------------------------------------------
4920 void ToolBox::GetFocus()
4922 DockingWindow::GetFocus();
4925 // -----------------------------------------------------------------------
4927 void ToolBox::LoseFocus()
4929 ImplChangeHighlight( NULL, sal_True );
4931 DockingWindow::LoseFocus();
4934 // -----------------------------------------------------------------------
4936 // performs the action associated with an item, ie simulates clicking the item
4937 void ToolBox::TriggerItem( sal_uInt16 nItemId, sal_Bool bShift, sal_Bool bCtrl )
4939 mnHighItemId = nItemId;
4940 sal_uInt16 nModifier = 0;
4941 if( bShift )
4942 nModifier |= KEY_SHIFT;
4943 if( bCtrl )
4944 nModifier |= KEY_MOD1;
4945 KeyCode aKeyCode( 0, nModifier );
4946 ImplActivateItem( aKeyCode );
4949 // -----------------------------------------------------------------------
4951 // calls the button's action handler
4952 // returns sal_True if action was called
4953 sal_Bool ToolBox::ImplActivateItem( KeyCode aKeyCode )
4955 sal_Bool bRet = sal_True;
4956 if( mnHighItemId )
4958 ImplToolItem *pToolItem = ImplGetItem( mnHighItemId );
4960 // #107712#, activate can also be called for disabled entries
4961 if( pToolItem && !pToolItem->mbEnabled )
4962 return sal_True;
4964 if( pToolItem && pToolItem->mpWindow && HasFocus() )
4966 ImplHideFocus();
4967 mbChangingHighlight = sal_True; // avoid focus change due to loose focus
4968 pToolItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
4969 mbChangingHighlight = sal_False;
4971 else
4973 mnDownItemId = mnCurItemId = mnHighItemId;
4974 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
4975 if ( pItem->mnBits & TIB_AUTOCHECK )
4977 if ( pItem->mnBits & TIB_RADIOCHECK )
4979 if ( pItem->meState != STATE_CHECK )
4980 SetItemState( pItem->mnId, STATE_CHECK );
4982 else
4984 if ( pItem->meState != STATE_CHECK )
4985 pItem->meState = STATE_CHECK;
4986 else
4987 pItem->meState = STATE_NOCHECK;
4990 mnMouseModifier = aKeyCode.GetModifier();
4991 mbIsKeyEvent = sal_True;
4992 Activate();
4993 Click();
4995 // #107776# we might be destroyed in the selecthandler
4996 ImplDelData aDelData;
4997 ImplAddDel( &aDelData );
4998 Select();
4999 if ( aDelData.IsDead() )
5000 return bRet;
5001 ImplRemoveDel( &aDelData );
5003 Deactivate();
5004 mbIsKeyEvent = sal_False;
5005 mnMouseModifier = 0;
5008 else
5009 bRet = sal_False;
5010 return bRet;
5013 // -----------------------------------------------------------------------
5015 sal_Bool ImplCloseLastPopup( Window *pParent )
5017 // close last popup toolbox (see also:
5018 // ImplHandleMouseFloatMode(...) in winproc.cxx )
5020 if( ImplGetSVData()->maWinData.mpFirstFloat )
5022 FloatingWindow* pLastLevelFloat = ImplGetSVData()->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
5023 // only close the floater if it is not our direct parent, which would kill ourself
5024 if( pLastLevelFloat && pLastLevelFloat != pParent )
5026 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
5027 return sal_True;
5030 return sal_False;
5033 // opens a drop down toolbox item
5034 // returns sal_True if item was opened
5035 sal_Bool ToolBox::ImplOpenItem( KeyCode aKeyCode )
5037 sal_uInt16 nCode = aKeyCode.GetCode();
5038 sal_Bool bRet = sal_True;
5040 // arrow keys should work only in the opposite direction of alignment (to not break cursor travelling)
5041 if ( ((nCode == KEY_LEFT || nCode == KEY_RIGHT) && IsHorizontal())
5042 || ((nCode == KEY_UP || nCode == KEY_DOWN) && !IsHorizontal()) )
5043 return sal_False;
5045 if( IsMenuEnabled() && mpData->mbMenubuttonSelected )
5047 if( ImplCloseLastPopup( GetParent() ) )
5048 return bRet;
5050 UpdateCustomMenu();
5051 Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
5053 else if( mnHighItemId && ImplGetItem( mnHighItemId ) &&
5054 (ImplGetItem( mnHighItemId )->mnBits & TIB_DROPDOWN) )
5056 if( ImplCloseLastPopup( GetParent() ) )
5057 return bRet;
5059 mnDownItemId = mnCurItemId = mnHighItemId;
5060 mnCurPos = GetItemPos( mnCurItemId );
5061 mnLastFocusItemId = mnCurItemId; // save item id for possible later focus restore
5062 mnMouseModifier = aKeyCode.GetModifier();
5063 mbIsShift = sal_True;
5064 mbIsKeyEvent = sal_True;
5065 Activate();
5067 mpData->mbDropDownByKeyboard = sal_True;
5068 GetDropdownClickHdl().Call( this );
5070 mbIsKeyEvent = sal_False;
5071 mbIsShift = sal_False;
5072 mnMouseModifier = 0;
5074 else
5075 bRet = sal_False;
5077 return bRet;
5080 // -----------------------------------------------------------------------
5082 void ToolBox::KeyInput( const KeyEvent& rKEvt )
5084 KeyCode aKeyCode = rKEvt.GetKeyCode();
5085 mnKeyModifier = aKeyCode.GetModifier();
5086 sal_uInt16 nCode = aKeyCode.GetCode();
5087 sal_Bool bParentIsDialog = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL );
5088 sal_Bool bForwardKey = sal_False;
5089 sal_Bool bGrabFocusToDocument = sal_False;
5091 // #107776# we might be destroyed in the keyhandler
5092 ImplDelData aDelData;
5093 ImplAddDel( &aDelData );
5095 switch ( nCode )
5097 case KEY_UP:
5099 // Ctrl-Cursor activates next toolbox, indicated by a blue arrow pointing to the left/up
5100 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5101 break;
5102 if( !IsHorizontal() )
5103 ImplChangeHighlightUpDn( sal_True );
5104 else
5105 ImplOpenItem( aKeyCode );
5107 break;
5108 case KEY_LEFT:
5110 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5111 break;
5112 if( IsHorizontal() )
5113 ImplChangeHighlightUpDn( sal_True );
5114 else
5115 ImplOpenItem( aKeyCode );
5117 break;
5118 case KEY_DOWN:
5120 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5121 break;
5122 if( !IsHorizontal() )
5123 ImplChangeHighlightUpDn( sal_False );
5124 else
5125 ImplOpenItem( aKeyCode );
5127 break;
5128 case KEY_RIGHT:
5130 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5131 break;
5132 if( IsHorizontal() )
5133 ImplChangeHighlightUpDn( sal_False );
5134 else
5135 ImplOpenItem( aKeyCode );
5137 break;
5138 case KEY_PAGEUP:
5139 if ( mnCurLine > 1 )
5141 if( mnCurLine > mnVisLines )
5142 mnCurLine = mnCurLine - mnVisLines;
5143 else
5144 mnCurLine = 1;
5145 mbFormat = sal_True;
5146 ImplFormat();
5147 ImplDrawSpin( sal_False, sal_False );
5148 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5150 break;
5151 case KEY_PAGEDOWN:
5152 if ( mnCurLine+mnVisLines-1 < mnCurLines )
5154 if( mnCurLine + 2*mnVisLines-1 < mnCurLines )
5155 mnCurLine = mnCurLine + mnVisLines;
5156 else
5157 mnCurLine = mnCurLines;
5158 mbFormat = sal_True;
5159 ImplFormat();
5160 ImplDrawSpin( sal_False, sal_False );
5161 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5163 break;
5164 case KEY_END:
5166 ImplChangeHighlight( NULL );
5167 ImplChangeHighlightUpDn( sal_False );
5169 break;
5170 case KEY_HOME:
5172 ImplChangeHighlight( NULL );
5173 ImplChangeHighlightUpDn( sal_True );
5175 break;
5176 case KEY_ESCAPE:
5178 if( !ImplIsFloatingMode() && bParentIsDialog )
5179 DockingWindow::KeyInput( rKEvt );
5180 else
5182 // send focus to document pane
5183 Window *pWin = this;
5184 while( pWin )
5186 if( !pWin->GetParent() )
5188 pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
5189 break;
5191 pWin = pWin->GetParent();
5195 break;
5196 case KEY_RETURN:
5198 // #107712#, disabled entries are selectable now
5199 // leave toolbox and move focus to document
5200 if( mnHighItemId )
5202 ImplToolItem *pItem = ImplGetItem( mnHighItemId );
5203 if( !pItem->mbEnabled )
5205 bGrabFocusToDocument = sal_True;
5208 if( !bGrabFocusToDocument )
5209 bForwardKey = !ImplActivateItem( aKeyCode );
5211 break;
5212 default:
5214 sal_uInt16 aKeyGroup = aKeyCode.GetGroup();
5215 ImplToolItem *pItem = NULL;
5216 if( mnHighItemId )
5217 pItem = ImplGetItem( mnHighItemId );
5218 // #i13931# forward alphanum keyinput into embedded control
5219 if( (aKeyGroup == KEYGROUP_NUM || aKeyGroup == KEYGROUP_ALPHA ) && pItem && pItem->mpWindow && pItem->mbEnabled )
5221 Window *pFocusWindow = Application::GetFocusWindow();
5222 ImplHideFocus();
5223 mbChangingHighlight = sal_True; // avoid focus change due to loose focus
5224 pItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5225 mbChangingHighlight = sal_False;
5226 if( pFocusWindow != Application::GetFocusWindow() )
5227 Application::GetFocusWindow()->KeyInput( rKEvt );
5229 else
5231 // do nothing to avoid key presses going into the document
5232 // while the toolbox has the focus
5233 // just forward function and special keys and combinations with Alt-key
5234 if( aKeyGroup == KEYGROUP_FKEYS || aKeyGroup == KEYGROUP_MISC || aKeyCode.IsMod2() )
5235 bForwardKey = sal_True;
5240 if ( aDelData.IsDead() )
5241 return;
5242 ImplRemoveDel( &aDelData );
5244 // #107251# move focus away if this toolbox was disabled during keyinput
5245 if( HasFocus() && mpData->mbKeyInputDisabled && (ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL)
5247 sal_uInt16 n = 0;
5248 Window *pFocusControl = ImplGetParent()->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
5249 if ( pFocusControl && pFocusControl != this )
5250 pFocusControl->ImplControlFocus( GETFOCUS_INIT );
5253 mnKeyModifier = 0;
5255 // #107712#, leave toolbox
5256 if( bGrabFocusToDocument )
5258 GrabFocusToDocument();
5259 return;
5262 if( bForwardKey )
5263 DockingWindow::KeyInput( rKEvt );
5266 // -----------------------------------------------------------------------
5268 // returns the current toolbox line of the item
5269 sal_uInt16 ToolBox::ImplGetItemLine( ImplToolItem* pCurrentItem )
5271 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
5272 sal_uInt16 nLine = 1;
5273 while( it != mpData->m_aItems.end() )
5275 if ( it->mbBreak )
5276 ++nLine;
5277 if( &(*it) == pCurrentItem)
5278 break;
5279 ++it;
5281 return nLine;
5284 // returns the first displayable item in the given line
5285 ImplToolItem* ToolBox::ImplGetFirstValidItem( sal_uInt16 nLine )
5287 if( !nLine || nLine > mnCurLines )
5288 return NULL;
5290 nLine--;
5292 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5293 while( it != mpData->m_aItems.end() )
5295 // find correct line
5296 if ( it->mbBreak )
5297 nLine--;
5298 if( !nLine )
5300 // find first useful item
5301 while( it != mpData->m_aItems.end() && ((it->meType != TOOLBOXITEM_BUTTON) ||
5302 /*!it->mbEnabled ||*/ !it->mbVisible || ImplIsFixedControl( &(*it) )) )
5304 ++it;
5305 if( it == mpData->m_aItems.end() || it->mbBreak )
5306 return NULL; // no valid items in this line
5308 return &(*it);
5310 ++it;
5313 return (it == mpData->m_aItems.end()) ? NULL : &(*it);
5316 // -----------------------------------------------------------------------
5318 sal_uInt16 ToolBox::ImplFindItemPos( const ImplToolItem* pItem, const std::vector< ImplToolItem >& rList )
5320 if( pItem )
5322 sal_uInt16 nPos;
5323 for( nPos = 0; nPos < rList.size(); ++nPos )
5324 if( &rList[ nPos ] == pItem )
5325 return nPos;
5327 return TOOLBOX_ITEM_NOTFOUND;
5330 void ToolBox::ChangeHighlight( sal_uInt16 nPos )
5332 if ( nPos < GetItemCount() ) {
5333 ImplGrabFocus( 0 );
5334 ImplChangeHighlight ( ImplGetItem ( GetItemId ( (sal_uInt16) nPos ) ), sal_False );
5338 void ToolBox::ImplChangeHighlight( ImplToolItem* pItem, sal_Bool bNoGrabFocus )
5340 // avoid recursion due to focus change
5341 if( mbChangingHighlight )
5342 return;
5344 mbChangingHighlight = sal_True;
5346 ImplToolItem* pOldItem = NULL;
5348 if ( mnHighItemId )
5350 ImplHideFocus();
5351 sal_uInt16 nPos = GetItemPos( mnHighItemId );
5352 pOldItem = ImplGetItem( mnHighItemId );
5353 // #i89962# ImplDrawItem can cause Invalidate/Update
5354 // which will in turn ImplShowFocus again
5355 // set mnHighItemId to 0 already to prevent this hen/egg problem
5356 mnHighItemId = 0;
5357 ImplDrawItem( nPos, 0 );
5358 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
5361 if( !bNoGrabFocus && pItem != pOldItem && pOldItem && pOldItem->mpWindow )
5363 // move focus into toolbox
5364 GrabFocus();
5367 if( pItem )
5369 sal_uInt16 aPos = ToolBox::ImplFindItemPos( pItem, mpData->m_aItems );
5370 if( aPos != TOOLBOX_ITEM_NOTFOUND)
5372 // check for line breaks
5373 sal_uInt16 nLine = ImplGetItemLine( pItem );
5375 if( nLine >= mnCurLine + mnVisLines )
5377 mnCurLine = nLine - mnVisLines + 1;
5378 mbFormat = sal_True;
5380 else if ( nLine < mnCurLine )
5382 mnCurLine = nLine;
5383 mbFormat = sal_True;
5386 if( mbFormat )
5388 ImplFormat();
5391 mnHighItemId = pItem->mnId;
5392 ImplDrawItem( aPos, 2 ); // always use shadow effect (2)
5394 if( mbSelection )
5395 mnCurPos = aPos;
5396 ImplShowFocus();
5398 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
5401 else
5403 ImplHideFocus();
5404 mnHighItemId = 0;
5405 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
5408 mbChangingHighlight = sal_False;
5411 // -----------------------------------------------------------------------
5413 // check for keyboard accessible items
5414 static sal_Bool ImplIsValidItem( const ImplToolItem* pItem, sal_Bool bNotClipped )
5416 sal_Bool bValid = (pItem && pItem->meType == TOOLBOXITEM_BUTTON && pItem->mbVisible && !ImplIsFixedControl( pItem ));
5417 if( bValid && bNotClipped && pItem->IsClipped() )
5418 bValid = sal_False;
5419 return bValid;
5422 // -----------------------------------------------------------------------
5424 sal_Bool ToolBox::ImplChangeHighlightUpDn( sal_Bool bUp, sal_Bool bNoCycle )
5426 ImplToolItem* pToolItem = ImplGetItem( mnHighItemId );
5428 if( !pToolItem || !mnHighItemId )
5430 // menubutton highlighted ?
5431 if( mpData->mbMenubuttonSelected )
5433 if( bUp )
5435 // select last valid non-clipped item
5436 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
5437 ImplToolItem* pItem = NULL;
5438 while( it != mpData->m_aItems.begin() )
5440 --it;
5441 if ( ImplIsValidItem( &(*it), sal_True ) )
5443 pItem = &(*it);
5444 break;
5447 ImplDrawMenubutton( this, sal_False );
5448 ImplChangeHighlight( pItem );
5450 else
5452 // select first valid non-clipped item
5453 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5454 while( it != mpData->m_aItems.end() )
5456 if ( ImplIsValidItem( &(*it), sal_True ) )
5457 break;
5458 ++it;
5460 if( it != mpData->m_aItems.end() )
5462 ImplDrawMenubutton( this, sal_False );
5463 ImplChangeHighlight( &(*it) );
5466 return sal_True;
5469 if( bUp )
5471 // Select first valid item
5472 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5473 while( it != mpData->m_aItems.end() )
5475 if ( ImplIsValidItem( &(*it), sal_False ) )
5476 break;
5477 ++it;
5480 // select the menu button if a clipped item would be selected
5481 if( (it != mpData->m_aItems.end() && &(*it) == ImplGetFirstClippedItem( this )) && IsMenuEnabled() )
5483 ImplChangeHighlight( NULL );
5484 ImplDrawMenubutton( this, sal_True );
5486 else
5487 ImplChangeHighlight( (it != mpData->m_aItems.end()) ? &(*it) : NULL );
5488 return sal_True;
5490 else
5492 // Select last valid item
5494 // docked toolbars have the menubutton as last item - if this button is enabled
5495 if( IsMenuEnabled() && !ImplIsFloatingMode() )
5497 ImplChangeHighlight( NULL );
5498 ImplDrawMenubutton( this, sal_True );
5500 else
5502 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
5503 ImplToolItem* pItem = NULL;
5504 while( it != mpData->m_aItems.begin() )
5506 --it;
5507 if ( ImplIsValidItem( &(*it), sal_False ) )
5509 pItem = &(*it);
5510 break;
5513 ImplChangeHighlight( pItem );
5515 return sal_True;
5519 if( pToolItem )
5521 sal_uLong pos = ToolBox::ImplFindItemPos( pToolItem, mpData->m_aItems );
5522 sal_uLong nCount = mpData->m_aItems.size();
5524 sal_uLong i=0;
5527 if( bUp )
5529 if( !pos-- )
5531 if( bNoCycle )
5532 return sal_False;
5534 // highlight the menu button if it is the last item
5535 if( IsMenuEnabled() && !ImplIsFloatingMode() )
5537 ImplChangeHighlight( NULL );
5538 ImplDrawMenubutton( this, sal_True );
5539 return sal_True;
5541 else
5542 pos = nCount-1;
5545 else
5547 if( ++pos >= nCount )
5549 if( bNoCycle )
5550 return sal_False;
5552 // highlight the menu button if it is the last item
5553 if( IsMenuEnabled() && !ImplIsFloatingMode() )
5555 ImplChangeHighlight( NULL );
5556 ImplDrawMenubutton( this, sal_True );
5557 return sal_True;
5559 else
5560 pos = 0;
5564 pToolItem = &mpData->m_aItems[pos];
5566 if ( ImplIsValidItem( pToolItem, sal_False ) )
5567 break;
5569 } while( ++i < nCount);
5571 if( pToolItem->IsClipped() && IsMenuEnabled() )
5573 // select the menu button if a clipped item would be selected
5574 ImplChangeHighlight( NULL );
5575 ImplDrawMenubutton( this, sal_True );
5577 else if( i != nCount )
5578 ImplChangeHighlight( pToolItem );
5579 else
5580 return sal_False;
5582 return sal_True;
5585 // -----------------------------------------------------------------------
5587 void ToolBox::ImplShowFocus()
5589 if( mnHighItemId && HasFocus() )
5591 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5592 if( pItem->mpWindow )
5594 Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
5595 pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = sal_True;
5596 pWin->Invalidate( 0 );
5601 // -----------------------------------------------------------------------
5603 void ToolBox::ImplHideFocus()
5605 if( mnHighItemId )
5607 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5608 if( pItem->mpWindow )
5610 Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
5611 pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = sal_False;
5612 pWin->Invalidate( 0 );
5616 if ( mpData->mbMenubuttonSelected )
5618 // remove highlight from menubutton
5619 ImplDrawMenubutton( this, sal_False );
5623 // -----------------------------------------------------------------------
5625 void ToolBox::ImplDisableFlatButtons()
5627 #ifdef WNT // Check in the Windows registry if an AT tool wants no flat toolboxes
5628 static bool bInit = false, bValue = false;
5629 if( ! bInit )
5631 bInit = true;
5632 HKEY hkey;
5634 if( ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER,
5635 "Software\\LibreOffice\\Accessibility\\AtToolSupport",
5636 &hkey) )
5638 DWORD dwType = 0;
5639 sal_uInt8 Data[6]; // possible values: "true", "false", "1", "0", DWORD
5640 DWORD cbData = sizeof(Data);
5642 if( ERROR_SUCCESS == RegQueryValueEx(hkey, "DisableFlatToolboxButtons",
5643 NULL, &dwType, Data, &cbData) )
5645 switch (dwType)
5647 case REG_SZ:
5648 bValue = ((0 == stricmp((const char *) Data, "1")) || (0 == stricmp((const char *) Data, "true")));
5649 break;
5650 case REG_DWORD:
5651 bValue = (bool)(((DWORD *) Data)[0]);
5652 break;
5655 RegCloseKey(hkey);
5658 if( bValue )
5659 mnOutStyle &= ~TOOLBOX_STYLE_FLAT;
5660 #endif
5663 void ToolBox::SetToolbarLayoutMode( ToolBoxLayoutMode eLayout )
5665 if ( meLayoutMode != eLayout )
5666 meLayoutMode = eLayout;
5669 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */