Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / vcl / source / window / toolbox.cxx
blobdda343ad8c54a72e153c9481557dadfed7a46230
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <rtl/logfile.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/rc.h>
34 #include <tools/poly.hxx>
36 #include <vcl/event.hxx>
37 #include <vcl/decoview.hxx>
38 #include <vcl/accel.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/help.hxx>
41 #include <vcl/sound.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/spin.h>
44 #include <vcl/toolbox.hxx>
45 #include <vcl/bitmap.hxx>
46 #include <vcl/mnemonic.hxx>
47 #include <vcl/gradient.hxx>
48 #include <vcl/menu.hxx>
50 #include <svdata.hxx>
51 #include <window.h>
52 #include <toolbox.h>
53 #include <salframe.hxx>
54 #if defined WNT
55 #include <svsys.h>
56 #endif
58 #include <string.h>
59 #include <vector>
60 #include <math.h>
62 // =======================================================================
64 DBG_NAMEEX( Window )
66 // =======================================================================
68 #define SMALLBUTTON_HSIZE 7
69 #define SMALLBUTTON_VSIZE 7
71 #define SMALLBUTTON_OFF_NORMAL_X 3
72 #define SMALLBUTTON_OFF_NORMAL_Y 3
73 #define SMALLBUTTON_OFF_PRESSED_X 5
74 #define SMALLBUTTON_OFF_PRESSED_Y 5
76 #define OUTBUTTON_SIZE 6
77 #define OUTBUTTON_BORDER 4
78 #define OUTBUTTON_OFF_NORMAL_X 1
79 #define OUTBUTTON_OFF_NORMAL_Y 1
81 // -----------------------------------------------------------------------
83 #define TB_TEXTOFFSET 2
84 #define TB_IMAGETEXTOFFSET 3
85 #define TB_LINESPACING 3
86 #define TB_SPIN_SIZE 14
87 #define TB_SPIN_OFFSET 2
88 #define TB_NEXT_SIZE 22
89 #define TB_NEXT_OFFSET 2
90 #define TB_BORDER_OFFSET1 4
91 #define TB_BORDER_OFFSET2 2
92 #define TB_CUSTOMIZE_OFFSET 2
93 #define TB_RESIZE_OFFSET 3
94 #define TB_MAXLINES 5
95 #define TB_MAXNOSCROLL 32765
97 #define TB_MIN_WIN_WIDTH 20
99 #define TB_CALCMODE_HORZ 1
100 #define TB_CALCMODE_VERT 2
101 #define TB_CALCMODE_FLOAT 3
103 #define TB_WBLINESIZING (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)
105 #define DOCK_LINEHSIZE ((sal_uInt16)0x0001)
106 #define DOCK_LINEVSIZE ((sal_uInt16)0x0002)
107 #define DOCK_LINERIGHT ((sal_uInt16)0x1000)
108 #define DOCK_LINEBOTTOM ((sal_uInt16)0x2000)
109 #define DOCK_LINELEFT ((sal_uInt16)0x4000)
110 #define DOCK_LINETOP ((sal_uInt16)0x8000)
111 #define DOCK_LINEOFFSET 3
114 // -----------------------------------------------------------------------
115 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bEnabled, sal_Bool bIsWindow );
116 // -----------------------------------------------------------------------
118 struct ImplToolSize
120 long mnWidth;
121 long mnHeight;
122 sal_uInt16 mnLines;
125 struct ImplToolSizeArray
127 long mnLength;
128 long mnLastEntry;
129 ImplToolSize* mpSize;
131 ImplToolSizeArray() { mpSize = NULL; mnLength = 0; mnLastEntry = 0; }
132 ~ImplToolSizeArray() { if( mpSize ) delete [] mpSize; mnLength = 0; }
135 // -----------------------------------------------------------------------
137 typedef ::std::vector< ToolBox* > ImplTBList;
139 class ImplTBDragMgr
141 private:
142 ImplTBList* mpBoxList;
143 ToolBox* mpDragBox;
144 Point maMouseOff;
145 Rectangle maRect;
146 Rectangle maStartRect;
147 Accelerator maAccel;
148 long mnMinWidth;
149 long mnMaxWidth;
150 sal_uInt16 mnLineMode;
151 sal_uInt16 mnStartLines;
152 void* mpCustomizeData;
153 sal_Bool mbCustomizeMode;
154 sal_Bool mbResizeMode;
155 sal_Bool mbShowDragRect;
157 public:
158 ImplTBDragMgr();
159 ~ImplTBDragMgr();
161 void push_back( ToolBox* pBox )
162 { mpBoxList->push_back( pBox ); }
163 void erase( ToolBox* pBox )
165 for ( ImplTBList::iterator it = mpBoxList->begin(); it != mpBoxList->end(); ++it ) {
166 if ( *it == pBox ) {
167 mpBoxList->erase( it );
168 break;
172 size_t size() const
173 { return mpBoxList->size(); }
175 ToolBox* FindToolBox( const Rectangle& rRect );
177 void StartDragging( ToolBox* pDragBox,
178 const Point& rPos, const Rectangle& rRect,
179 sal_uInt16 nLineMode, sal_Bool bResizeItem,
180 void* pData = NULL );
181 void Dragging( const Point& rPos );
182 void EndDragging( sal_Bool bOK = sal_True );
183 void HideDragRect() { if ( mbShowDragRect ) mpDragBox->HideTracking(); }
184 void UpdateDragRect();
185 DECL_LINK( SelectHdl, Accelerator* );
187 sal_Bool IsCustomizeMode() { return mbCustomizeMode; }
188 sal_Bool IsResizeMode() { return mbResizeMode; }
191 // -----------------------------------------------------------------------
193 static ImplTBDragMgr* ImplGetTBDragMgr()
195 ImplSVData* pSVData = ImplGetSVData();
196 if ( !pSVData->maCtrlData.mpTBDragMgr )
197 pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr;
198 return pSVData->maCtrlData.mpTBDragMgr;
201 // -----------------------------------------------------------------------
203 int ToolBox::ImplGetDragWidth( ToolBox* pThis )
205 #define TB_DRAGWIDTH 8 // the default width of the grip
207 int width = TB_DRAGWIDTH;
208 if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
211 ImplControlValue aControlValue;
212 Point aPoint;
213 Rectangle aContent, aBound;
214 Rectangle aArea( aPoint, pThis->GetOutputSizePixel() );
216 if ( pThis->GetNativeControlRegion(CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
217 aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
219 width = pThis->mbHorz ? aContent.GetWidth() : aContent.GetHeight();
222 return width;
225 ButtonType determineButtonType( ImplToolItem* pItem, ButtonType defaultType )
227 ButtonType tmpButtonType = defaultType;
228 ToolBoxItemBits nBits( pItem->mnBits & 0x300 );
229 if ( nBits & TIB_TEXTICON ) // item has custom setting
231 tmpButtonType = BUTTON_SYMBOLTEXT;
232 if ( nBits == TIB_TEXT_ONLY )
233 tmpButtonType = BUTTON_TEXT;
234 else if ( nBits == TIB_ICON_ONLY )
235 tmpButtonType = BUTTON_SYMBOL;
237 return tmpButtonType;
240 // -----------------------------------------------------------------------
242 void ToolBox::ImplUpdateDragArea( ToolBox *pThis )
244 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
245 if( pWrapper )
247 if ( pThis->ImplIsFloatingMode() || pWrapper->IsLocked() )
248 pWrapper->SetDragArea( Rectangle() );
249 else
251 if( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
252 pWrapper->SetDragArea( Rectangle( 0, 0, ImplGetDragWidth( pThis ), pThis->GetOutputSizePixel().Height() ) );
253 else
254 pWrapper->SetDragArea( Rectangle( 0, 0, pThis->GetOutputSizePixel().Width(), ImplGetDragWidth( pThis ) ) );
259 // -----------------------------------------------------------------------
261 void ToolBox::ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop,
262 long& rRight, long& rBottom, const ToolBox *pThis )
264 if( pThis->ImplIsFloatingMode() || !(pThis->mnWinStyle & WB_BORDER) )
266 // no border in floating mode
267 rLeft = rTop = rRight = rBottom = 0;
268 return;
271 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
273 // reserve dragarea only for dockable toolbars
274 int dragwidth = ( pWrapper && !pWrapper->IsLocked() ) ? ImplGetDragWidth( (ToolBox*)pThis ) : 0;
276 // no shadow border for dockable toolbars
277 int borderwidth = pWrapper ? 0: 2;
279 if ( eAlign == WINDOWALIGN_TOP )
281 rLeft = borderwidth+dragwidth;
282 rTop = borderwidth;
283 rRight = borderwidth;
284 rBottom = 0;
286 else if ( eAlign == WINDOWALIGN_LEFT )
288 rLeft = borderwidth;
289 rTop = borderwidth+dragwidth;
290 rRight = 0;
291 rBottom = borderwidth;
293 else if ( eAlign == WINDOWALIGN_BOTTOM )
295 rLeft = borderwidth+dragwidth;
296 rTop = 0;
297 rRight = borderwidth;
298 rBottom = borderwidth;
300 else
302 rLeft = 0;
303 rTop = borderwidth+dragwidth;
304 rRight = borderwidth;
305 rBottom = borderwidth;
309 // -----------------------------------------------------------------------
311 static void ImplCheckUpdate( ToolBox *pThis )
313 // remove any pending invalidates to avoid
314 // have them triggered when paint is locked (see mpData->mbIsPaintLocked)
315 // which would result in erasing the background only and not painting any items
316 // this must not be done when we're already in Paint()
318 // this is only required for transparent toolbars (see ImplDrawTransparentBackground() )
319 if( !pThis->IsBackground() && pThis->HasPaintEvent() && !pThis->IsInPaint() )
320 pThis->Update();
323 // -----------------------------------------------------------------------
325 void ToolBox::ImplDrawGrip( ToolBox* pThis )
327 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
328 if( pWrapper && !pWrapper->GetDragArea().IsEmpty() )
330 // execute pending paint requests
331 ImplCheckUpdate( pThis );
333 sal_Bool bNativeOk = sal_False;
334 if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_HORZ : PART_THUMB_VERT ) )
336 ToolbarValue aToolbarValue;
337 aToolbarValue.maGripRect = pWrapper->GetDragArea();
338 Point aPt;
339 Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
340 ControlState nState = CTRL_STATE_ENABLED;
342 bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
343 aCtrlRegion, nState, aToolbarValue, rtl::OUString() );
346 if( bNativeOk )
347 return;
349 const StyleSettings& rStyleSettings = pThis->GetSettings().GetStyleSettings();
350 pThis->SetLineColor( rStyleSettings.GetShadowColor() );
352 Size aSz ( pThis->GetOutputSizePixel() );
354 if ( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
356 int height = (int) (0.6 * aSz.Height() + 0.5);
357 int i = (aSz.Height() - height) / 2;
358 height += i;
359 while( i <= height )
361 int x = ImplGetDragWidth( pThis ) / 2;
363 pThis->DrawPixel( Point(x, i), rStyleSettings.GetDarkShadowColor() );
364 pThis->DrawPixel( Point(x+1, i), rStyleSettings.GetShadowColor() );
366 pThis->DrawPixel( Point(x, i+1), rStyleSettings.GetShadowColor() );
367 pThis->DrawPixel( Point(x+1, i+1), rStyleSettings.GetFaceColor() );
368 pThis->DrawPixel( Point(x+2, i+1), Color(COL_WHITE) );
370 pThis->DrawPixel( Point(x+1, i+2), Color(COL_WHITE) );
371 pThis->DrawPixel( Point(x+2, i+2), Color(COL_WHITE) );
372 i+=4;
375 else
377 int width = (int) (0.6 * aSz.Width() + 0.5);
378 int i = (aSz.Width() - width) / 2;
379 width += i;
380 while( i <= width )
382 int y = ImplGetDragWidth(pThis) / 2;
384 pThis->DrawPixel( Point(i, y), rStyleSettings.GetDarkShadowColor() );
385 pThis->DrawPixel( Point(i+1, y), rStyleSettings.GetShadowColor() );
387 pThis->DrawPixel( Point(i, y+1), rStyleSettings.GetShadowColor() );
388 pThis->DrawPixel( Point(i+1, y+1), rStyleSettings.GetFaceColor() );
389 pThis->DrawPixel( Point(i+2, y+1), Color(COL_WHITE) );
391 pThis->DrawPixel( Point(i+1, y+2), Color(COL_WHITE) );
392 pThis->DrawPixel( Point(i+2, y+2), Color(COL_WHITE) );
393 i+=4;
399 void ToolBox::ImplDrawGradientBackground( ToolBox* pThis, ImplDockingWindowWrapper * )
401 // draw a nice gradient
403 Color startCol, endCol;
404 startCol = pThis->GetSettings().GetStyleSettings().GetFaceGradientColor();
405 endCol = pThis->GetSettings().GetStyleSettings().GetFaceColor();
406 if( pThis->GetSettings().GetStyleSettings().GetHighContrastMode() )
407 // no 'extreme' gradient when high contrast
408 startCol = endCol;
410 Gradient g;
411 g.SetAngle( pThis->mbHorz ? 0 : 900 );
412 g.SetStyle( GradientStyle_LINEAR );
414 g.SetStartColor( startCol );
415 g.SetEndColor( endCol );
417 sal_Bool bLineColor = pThis->IsLineColor();
418 Color aOldCol = pThis->GetLineColor();
419 pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
421 Size aFullSz( pThis->GetOutputSizePixel() );
422 Size aLineSz( aFullSz );
424 // use the linesize only when floating
425 // full window height is used when docked (single line)
426 if( pThis->ImplIsFloatingMode() )
428 long nLineSize;
429 if( pThis->mbHorz )
431 nLineSize = pThis->mnMaxItemHeight;
432 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
433 nLineSize = pThis->mnWinHeight;
435 aLineSz.Height() = nLineSize;
437 else
439 nLineSize = pThis->mnMaxItemWidth;
440 aLineSz.Width() = nLineSize;
444 long nLeft, nTop, nRight, nBottom;
445 ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
447 Size aTopLineSz( aLineSz );
448 Size aBottomLineSz( aLineSz );
450 if ( pThis->mnWinStyle & WB_BORDER )
452 if( pThis->mbHorz )
454 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nTop;
455 aBottomLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
457 if( pThis->mnCurLines == 1 )
458 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
460 else
462 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
463 aBottomLineSz.Width() += TB_BORDER_OFFSET1 + nRight;
465 if( pThis->mnCurLines == 1 )
466 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
470 if( pThis->mbHorz )
472 aTopLineSz.Height() += pThis->mnBorderY;
473 if( pThis->mnCurLines == 1 )
474 aTopLineSz.Height() += pThis->mnBorderY;
476 aBottomLineSz.Height() += pThis->mnBorderY;
478 else
480 aTopLineSz.Width() += pThis->mnBorderX;
481 if( pThis->mnCurLines == 1 )
482 aTopLineSz.Width() += pThis->mnBorderX;
484 aBottomLineSz.Width() += pThis->mnBorderX;
488 if ( pThis->mnWinStyle & WB_LINESPACING )
490 if( pThis->mbHorz )
492 aLineSz.Height() += TB_LINESPACING;
493 if( pThis->mnCurLines > 1 )
494 aTopLineSz.Height() += TB_LINESPACING;
496 else
498 aLineSz.Width() += TB_LINESPACING;
499 if( pThis->mnCurLines > 1 )
500 aTopLineSz.Width() += TB_LINESPACING;
504 if( pThis->mbHorz )
506 long y = 0;
507 sal_Bool bDrawSep = sal_False; // pThis->ImplIsFloatingMode() && ( pThis->mnWinStyle & WB_LINESPACING );
509 pThis->DrawGradient( Rectangle( 0, y, aTopLineSz.Width(), y+aTopLineSz.Height()), g );
510 y += aTopLineSz.Height();
512 if ( bDrawSep )
513 pThis->DrawLine( Point(0, y-2), Point(aTopLineSz.Width(), y-2) );
515 while( y < (pThis->mnDY - aBottomLineSz.Height()) )
517 pThis->DrawGradient( Rectangle( 0, y, aLineSz.Width(), y+aLineSz.Height()), g);
518 y += aLineSz.Height();
520 if ( bDrawSep )
521 pThis->DrawLine( Point(0, y-2), Point(aLineSz.Width(), y-2) );
524 pThis->DrawGradient( Rectangle( 0, y, aBottomLineSz.Width(), y+aBottomLineSz.Height()), g );
525 if ( bDrawSep )
526 pThis->DrawLine( Point(0, y-2), Point(aBottomLineSz.Width(), y-2) );
528 else
530 long x = 0;
532 pThis->DrawGradient( Rectangle( x, 0, x+aTopLineSz.Width(), aTopLineSz.Height()), g );
533 x += aTopLineSz.Width();
535 while( x < (pThis->mnDX - aBottomLineSz.Width()) )
537 pThis->DrawGradient( Rectangle( x, 0, x+aLineSz.Width(), aLineSz.Height()), g);
538 x += aLineSz.Width();
541 pThis->DrawGradient( Rectangle( x, 0, x+aBottomLineSz.Width(), aBottomLineSz.Height()), g );
544 if( bLineColor )
545 pThis->SetLineColor( aOldCol );
549 sal_Bool ToolBox::ImplDrawNativeBackground( ToolBox* pThis, const Region & )
551 // use NWF
552 Point aPt;
553 Rectangle aCtrlRegion( aPt, pThis->GetOutputSizePixel() );
554 ControlState nState = CTRL_STATE_ENABLED;
556 return pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
557 aCtrlRegion, nState, ImplControlValue(), rtl::OUString() );
560 void ToolBox::ImplDrawTransparentBackground( ToolBox* pThis, const Region &rRegion )
562 // just invalidate to trigger paint of the parent
564 const bool bOldPaintLock = pThis->mpData->mbIsPaintLocked;
565 pThis->mpData->mbIsPaintLocked = true;
567 // send an invalidate to the first opaque parent and invalidate the whole hierarchy from there (noclipchildren)
568 pThis->Invalidate( rRegion, INVALIDATE_UPDATE|INVALIDATE_NOCLIPCHILDREN );
570 pThis->mpData->mbIsPaintLocked = bOldPaintLock;
573 void ToolBox::ImplDrawConstantBackground( ToolBox* pThis, const Region &rRegion, sal_Bool bIsInPopupMode )
575 // draw a constant color
576 if( !bIsInPopupMode )
577 // default background
578 pThis->Erase( rRegion.GetBoundRect() );
579 else
581 // use different color in popupmode
582 pThis->DrawWallpaper( rRegion.GetBoundRect(),
583 Wallpaper( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() ) );
588 void ToolBox::ImplDrawBackground( ToolBox* pThis, const Rectangle &rRect )
590 // execute pending paint requests
591 ImplCheckUpdate( pThis );
593 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
594 sal_Bool bIsInPopupMode = pThis->ImplIsInPopupMode();
596 Region aPaintRegion( rRect );
598 // make sure we do not invalidate/erase too much
599 if( pThis->IsInPaint() )
600 aPaintRegion.Intersect( pThis->GetActiveClipRegion() );
602 pThis->Push( PUSH_CLIPREGION );
603 pThis->IntersectClipRegion( aPaintRegion );
606 if( !pWrapper /*|| bIsInPopupMode*/ )
608 // no gradient for ordinary toolbars (not dockable)
609 if( !pThis->IsBackground() && !pThis->IsInPaint() )
610 ImplDrawTransparentBackground( pThis, aPaintRegion );
611 else
612 ImplDrawConstantBackground( pThis, aPaintRegion, bIsInPopupMode );
614 else
616 // toolbars known to the dockingmanager will be drawn using NWF or a gradient
617 // docked toolbars are transparent and NWF is already used in the docking area which is their common background
618 // so NWF is used here for floating toolbars only
619 sal_Bool bNativeOk = sal_False;
620 if( pThis->ImplIsFloatingMode() && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL) )
621 bNativeOk = ImplDrawNativeBackground( pThis, aPaintRegion );
623 if( !bNativeOk )
625 if( !pThis->IsBackground() )
627 if( !pThis->IsInPaint() )
628 ImplDrawTransparentBackground( pThis, aPaintRegion );
630 else
631 ImplDrawGradientBackground( pThis, pWrapper );
635 // restore clip region
636 pThis->Pop();
639 void ToolBox::ImplErase( ToolBox* pThis, const Rectangle &rRect, sal_Bool bHighlight, sal_Bool bHasOpenPopup )
641 // the background of non NWF buttons is painted in a constant color
642 // to have the same highlight color (transparency in DrawSelectionBackground())
643 // items with open popups will also painted using a constant color
644 if( !pThis->mpData->mbNativeButtons &&
645 (bHighlight || ! (((Window*) pThis)->GetStyle() & WB_3DLOOK ) ) )
647 if( (((Window*) pThis)->GetStyle() & WB_3DLOOK ) )
649 pThis->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
650 pThis->SetLineColor();
651 if( bHasOpenPopup )
652 // choose the same color as the popup will use
653 pThis->SetFillColor( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() );
654 else
655 pThis->SetFillColor( Color( COL_WHITE ) );
657 pThis->DrawRect( rRect );
658 pThis->Pop();
660 else
661 ImplDrawBackground( pThis, rRect );
663 else
664 ImplDrawBackground( pThis, rRect );
667 void ToolBox::ImplDrawBorder( ToolBox* pWin )
669 const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
670 long nDX = pWin->mnDX;
671 long nDY = pWin->mnDY;
673 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pWin );
675 // draw borders for ordinary toolbars only (not dockable)
676 if( pWrapper )
677 return;
679 if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
681 // draw bottom border
682 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
683 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
684 pWin->SetLineColor( rStyleSettings.GetLightColor() );
685 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
687 else
689 // draw top border
690 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
691 pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
692 pWin->SetLineColor( rStyleSettings.GetLightColor() );
693 pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
695 if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
697 if ( pWin->meAlign == WINDOWALIGN_LEFT )
699 // draw left-bottom border
700 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
701 pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
702 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
703 pWin->SetLineColor( rStyleSettings.GetLightColor() );
704 pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
705 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
707 else
709 // draw right-bottom border
710 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
711 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
712 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
713 pWin->SetLineColor( rStyleSettings.GetLightColor() );
714 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
715 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
721 if ( pWin->meAlign == WINDOWALIGN_BOTTOM || pWin->meAlign == WINDOWALIGN_TOP )
723 // draw right border
724 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
725 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) );
726 pWin->SetLineColor( rStyleSettings.GetLightColor() );
727 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
731 // -----------------------------------------------------------------------
733 static bool ImplIsFixedControl( const ImplToolItem *pItem )
735 return ( pItem->mpWindow &&
736 (pItem->mpWindow->GetType() == WINDOW_FIXEDTEXT ||
737 pItem->mpWindow->GetType() == WINDOW_FIXEDLINE ||
738 pItem->mpWindow->GetType() == WINDOW_GROUPBOX) );
741 // -----------------------------------------------------------------------
743 const ImplToolItem *ToolBox::ImplGetFirstClippedItem( const ToolBox* pThis )
745 std::vector< ImplToolItem >::const_iterator it;
746 it = pThis->mpData->m_aItems.begin();
747 while ( it != pThis->mpData->m_aItems.end() )
749 if( it->IsClipped() )
750 return &(*it);
751 ++it;
753 return NULL;
756 // -----------------------------------------------------------------------
758 Size ToolBox::ImplCalcSize( const ToolBox* pThis, sal_uInt16 nCalcLines, sal_uInt16 nCalcMode )
760 long nMax;
761 long nLeft = 0;
762 long nTop = 0;
763 long nRight = 0;
764 long nBottom = 0;
765 Size aSize;
766 WindowAlign eOldAlign = pThis->meAlign;
767 sal_Bool bOldHorz = pThis->mbHorz;
768 sal_Bool bOldAssumeDocked = pThis->mpData->mbAssumeDocked;
769 sal_Bool bOldAssumeFloating = pThis->mpData->mbAssumeFloating;
771 if ( nCalcMode )
773 sal_Bool bOldFloatingMode = pThis->ImplIsFloatingMode();
775 pThis->mpData->mbAssumeDocked = sal_False;
776 pThis->mpData->mbAssumeFloating = sal_False;
778 if ( nCalcMode == TB_CALCMODE_HORZ )
780 pThis->mpData->mbAssumeDocked = sal_True; // force non-floating mode during calculation
781 ImplCalcBorder( WINDOWALIGN_TOP, nLeft, nTop, nRight, nBottom, pThis );
782 ((ToolBox*)pThis)->mbHorz = sal_True;
783 if ( pThis->mbHorz != bOldHorz )
784 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
786 else if ( nCalcMode == TB_CALCMODE_VERT )
788 pThis->mpData->mbAssumeDocked = sal_True; // force non-floating mode during calculation
789 ImplCalcBorder( WINDOWALIGN_LEFT, nLeft, nTop, nRight, nBottom, pThis );
790 ((ToolBox*)pThis)->mbHorz = sal_False;
791 if ( pThis->mbHorz != bOldHorz )
792 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_LEFT;
794 else if ( nCalcMode == TB_CALCMODE_FLOAT )
796 pThis->mpData->mbAssumeFloating = sal_True; // force non-floating mode during calculation
797 nLeft = nTop = nRight = nBottom = 0;
798 ((ToolBox*)pThis)->mbHorz = sal_True;
799 if ( pThis->mbHorz != bOldHorz )
800 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
803 if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) ||
804 (pThis->ImplIsFloatingMode() != bOldFloatingMode ) )
805 ((ToolBox*)pThis)->mbCalc = sal_True;
807 else
808 ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
810 ((ToolBox*)pThis)->ImplCalcItem();
812 if( !nCalcMode && pThis->ImplIsFloatingMode() )
814 aSize = ImplCalcFloatSize( ((ToolBox*)pThis), nCalcLines );
816 else
818 if ( pThis->mbHorz )
820 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
821 aSize.Height() = nCalcLines * pThis->mnWinHeight;
822 else
823 aSize.Height() = nCalcLines * pThis->mnMaxItemHeight;
825 if ( pThis->mnWinStyle & WB_LINESPACING )
826 aSize.Height() += (nCalcLines-1)*TB_LINESPACING;
828 if ( pThis->mnWinStyle & WB_BORDER )
829 aSize.Height() += (TB_BORDER_OFFSET2*2) + nTop + nBottom;
831 nMax = 0;
832 ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
833 if ( nMax )
834 aSize.Width() += nMax;
836 if ( pThis->mnWinStyle & WB_BORDER )
837 aSize.Width() += (TB_BORDER_OFFSET1*2) + nLeft + nRight;
839 else
841 aSize.Width() = nCalcLines * pThis->mnMaxItemWidth;
843 if ( pThis->mnWinStyle & WB_LINESPACING )
844 aSize.Width() += (nCalcLines-1)*TB_LINESPACING;
846 if ( pThis->mnWinStyle & WB_BORDER )
847 aSize.Width() += (TB_BORDER_OFFSET2*2) + nLeft + nRight;
849 nMax = 0;
850 ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
851 if ( nMax )
852 aSize.Height() += nMax;
854 if ( pThis->mnWinStyle & WB_BORDER )
855 aSize.Height() += (TB_BORDER_OFFSET1*2) + nTop + nBottom;
858 // restore previous values
859 if ( nCalcMode )
861 pThis->mpData->mbAssumeDocked = bOldAssumeDocked;
862 pThis->mpData->mbAssumeFloating = bOldAssumeFloating;
863 if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
865 ((ToolBox*)pThis)->meAlign = eOldAlign;
866 ((ToolBox*)pThis)->mbHorz = bOldHorz;
867 ((ToolBox*)pThis)->mbCalc = sal_True;
871 if ( aSize.Width() )
872 aSize.Width() += pThis->mnBorderX*2;
873 if ( aSize.Height() )
874 aSize.Height() += pThis->mnBorderY*2;
876 return aSize;
879 // -----------------------------------------------------------------------
881 void ToolBox::ImplCalcFloatSizes( ToolBox* pThis )
883 if ( pThis->mpFloatSizeAry )
884 return;
886 // calculate the minimal size, i.e. where the biggest item just fits
887 long nCalcSize = 0;
889 std::vector< ImplToolItem >::const_iterator it;
890 it = pThis->mpData->m_aItems.begin();
891 while ( it != pThis->mpData->m_aItems.end() )
893 if ( it->mbVisible )
895 if ( it->mpWindow )
897 long nTempSize = it->mpWindow->GetSizePixel().Width();
898 if ( nTempSize > nCalcSize )
899 nCalcSize = nTempSize;
901 else
903 if( it->maItemSize.Width() > nCalcSize )
904 nCalcSize = it->maItemSize.Width();
907 ++it;
910 // calc an upper bound for ImplCalcBreaks below
911 long upperBoundWidth = nCalcSize * pThis->mpData->m_aItems.size();
913 sal_uInt16 i;
914 sal_uInt16 nLines;
915 sal_uInt16 nCalcLines;
916 sal_uInt16 nTempLines;
917 long nHeight;
918 long nMaxLineWidth;
919 nCalcLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, sal_True );
921 pThis->mpFloatSizeAry = new ImplToolSizeArray;
922 pThis->mpFloatSizeAry->mpSize = new ImplToolSize[nCalcLines];
923 pThis->mpFloatSizeAry->mnLength = nCalcLines;
925 memset( pThis->mpFloatSizeAry->mpSize, 0, sizeof( ImplToolSize )*nCalcLines );
926 i = 0;
927 nTempLines = nLines = nCalcLines;
928 while ( nLines )
930 nHeight = ImplCalcSize( pThis, nTempLines, TB_CALCMODE_FLOAT ).Height();
931 pThis->mpFloatSizeAry->mnLastEntry = i;
932 pThis->mpFloatSizeAry->mpSize[i].mnHeight = nHeight;
933 pThis->mpFloatSizeAry->mpSize[i].mnLines = nTempLines;
934 pThis->mpFloatSizeAry->mpSize[i].mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET1*2);
935 nLines--;
936 if ( nLines )
940 nCalcSize += pThis->mnMaxItemWidth;
941 nTempLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, sal_True );
943 while ( (nCalcSize < upperBoundWidth) && (nLines < nTempLines) && (nTempLines != 1) );
944 if ( nTempLines < nLines )
945 nLines = nTempLines;
947 i++;
951 // -----------------------------------------------------------------------
953 Size ToolBox::ImplCalcFloatSize( ToolBox* pThis, sal_uInt16& rLines )
955 ImplCalcFloatSizes( pThis );
957 if ( !rLines )
959 rLines = pThis->mnFloatLines;
960 if ( !rLines )
961 rLines = pThis->mnLines;
964 sal_uInt16 i = 0;
965 while ( i < pThis->mpFloatSizeAry->mnLastEntry &&
966 rLines < pThis->mpFloatSizeAry->mpSize[i].mnLines )
967 i++;
969 Size aSize( pThis->mpFloatSizeAry->mpSize[i].mnWidth,
970 pThis->mpFloatSizeAry->mpSize[i].mnHeight );
971 rLines = pThis->mpFloatSizeAry->mpSize[i].mnLines;
972 if ( pThis->maNextToolBoxStr.Len() && pThis->mbScroll )
973 aSize.Width() += TB_NEXT_SIZE-TB_NEXT_OFFSET;
974 return aSize;
977 // -----------------------------------------------------------------------
979 void ToolBox::ImplCalcMinMaxFloatSize( ToolBox* pThis, Size& rMinSize, Size& rMaxSize )
981 ImplCalcFloatSizes( pThis );
983 sal_uInt16 i = 0;
984 rMinSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
985 rMaxSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
986 while ( ++i <= pThis->mpFloatSizeAry->mnLastEntry )
988 if( pThis->mpFloatSizeAry->mpSize[i].mnWidth < rMinSize.Width() )
989 rMinSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
990 if( pThis->mpFloatSizeAry->mpSize[i].mnHeight < rMinSize.Height() )
991 rMinSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
993 if( pThis->mpFloatSizeAry->mpSize[i].mnWidth > rMaxSize.Width() )
994 rMaxSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
995 if( pThis->mpFloatSizeAry->mpSize[i].mnHeight > rMaxSize.Height() )
996 rMaxSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
1000 void ToolBox::ImplSetMinMaxFloatSize( ToolBox *pThis )
1002 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
1003 Size aMinSize, aMaxSize;
1004 ImplCalcMinMaxFloatSize( pThis, aMinSize, aMaxSize );
1005 if( pWrapper )
1007 pWrapper->SetMinOutputSizePixel( aMinSize );
1008 pWrapper->SetMaxOutputSizePixel( aMaxSize );
1009 pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) ? sal_True : sal_False );
1011 else
1013 // TODO: change SetMinOutputSizePixel to be not inline
1014 pThis->SetMinOutputSizePixel( aMinSize );
1015 pThis->SetMaxOutputSizePixel( aMaxSize );
1019 // -----------------------------------------------------------------------
1022 sal_uInt16 ToolBox::ImplCalcLines( ToolBox* pThis, long nToolSize )
1024 long nLineHeight;
1026 if ( pThis->mbHorz )
1028 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
1029 nLineHeight = pThis->mnWinHeight;
1030 else
1031 nLineHeight = pThis->mnMaxItemHeight;
1033 else
1034 nLineHeight = pThis->mnMaxItemWidth;
1036 if ( pThis->mnWinStyle & WB_BORDER )
1037 nToolSize -= TB_BORDER_OFFSET2*2;
1039 if ( pThis->mnWinStyle & WB_LINESPACING )
1041 nLineHeight += TB_LINESPACING;
1042 nToolSize += TB_LINESPACING;
1045 // #i91917# always report at least one line
1046 long nLines = nToolSize/nLineHeight;
1047 if( nLines < 1 )
1048 nLines = 1;
1050 return static_cast<sal_uInt16>(nLines);
1053 // -----------------------------------------------------------------------
1055 sal_uInt16 ToolBox::ImplTestLineSize( ToolBox* pThis, const Point& rPos )
1057 if ( !pThis->ImplIsFloatingMode() &&
1058 (!pThis->mbScroll || (pThis->mnLines > 1) || (pThis->mnCurLines > pThis->mnVisLines)) )
1060 WindowAlign eAlign = pThis->GetAlign();
1062 if ( eAlign == WINDOWALIGN_LEFT )
1064 if ( rPos.X() > pThis->mnDX-DOCK_LINEOFFSET )
1065 return DOCK_LINEHSIZE | DOCK_LINERIGHT;
1067 else if ( eAlign == WINDOWALIGN_TOP )
1069 if ( rPos.Y() > pThis->mnDY-DOCK_LINEOFFSET )
1070 return DOCK_LINEVSIZE | DOCK_LINEBOTTOM;
1072 else if ( eAlign == WINDOWALIGN_RIGHT )
1074 if ( rPos.X() < DOCK_LINEOFFSET )
1075 return DOCK_LINEHSIZE | DOCK_LINELEFT;
1077 else if ( eAlign == WINDOWALIGN_BOTTOM )
1079 if ( rPos.Y() < DOCK_LINEOFFSET )
1080 return DOCK_LINEVSIZE | DOCK_LINETOP;
1084 return 0;
1087 // -----------------------------------------------------------------------
1089 void ToolBox::ImplLineSizing( ToolBox* pThis, const Point& rPos, Rectangle& rRect,
1090 sal_uInt16 nLineMode )
1092 sal_Bool mbHorz;
1093 long nOneLineSize;
1094 long nCurSize;
1095 long nMaxSize;
1096 long nSize;
1097 Size aSize;
1099 if ( nLineMode & DOCK_LINERIGHT )
1101 nCurSize = rPos.X() - rRect.Left();
1102 mbHorz = sal_False;
1104 else if ( nLineMode & DOCK_LINEBOTTOM )
1106 nCurSize = rPos.Y() - rRect.Top();
1107 mbHorz = sal_True;
1109 else if ( nLineMode & DOCK_LINELEFT )
1111 nCurSize = rRect.Right() - rPos.X();
1112 mbHorz = sal_False;
1114 else if ( nLineMode & DOCK_LINETOP )
1116 nCurSize = rRect.Bottom() - rPos.Y();
1117 mbHorz = sal_True;
1119 else {
1120 OSL_FAIL( "ImplLineSizing: Trailing else" );
1121 nCurSize = 0;
1122 mbHorz = sal_False;
1125 Size aWinSize = pThis->GetSizePixel();
1126 sal_uInt16 nMaxLines = (pThis->mnLines > pThis->mnCurLines) ? pThis->mnLines : pThis->mnCurLines;
1127 if ( nMaxLines > TB_MAXLINES )
1128 nMaxLines = TB_MAXLINES;
1129 if ( mbHorz )
1131 nOneLineSize = ImplCalcSize( pThis, 1 ).Height();
1132 nMaxSize = pThis->maOutDockRect.GetHeight() - 20;
1133 if ( nMaxSize < aWinSize.Height() )
1134 nMaxSize = aWinSize.Height();
1136 else
1138 nOneLineSize = ImplCalcSize( pThis, 1 ).Width();
1139 nMaxSize = pThis->maOutDockRect.GetWidth() - 20;
1140 if ( nMaxSize < aWinSize.Width() )
1141 nMaxSize = aWinSize.Width();
1144 sal_uInt16 i = 1;
1145 if ( nCurSize <= nOneLineSize )
1146 nSize = nOneLineSize;
1147 else
1149 nSize = 0;
1150 while ( (nSize < nCurSize) && (i < nMaxLines) )
1152 i++;
1153 aSize = ImplCalcSize( pThis, i );
1154 if ( mbHorz )
1155 nSize = aSize.Height();
1156 else
1157 nSize = aSize.Width();
1158 if ( nSize > nMaxSize )
1160 i--;
1161 aSize = ImplCalcSize( pThis, i );
1162 if ( mbHorz )
1163 nSize = aSize.Height();
1164 else
1165 nSize = aSize.Width();
1166 break;
1171 if ( nLineMode & DOCK_LINERIGHT )
1172 rRect.Right() = rRect.Left()+nSize-1;
1173 else if ( nLineMode & DOCK_LINEBOTTOM )
1174 rRect.Bottom() = rRect.Top()+nSize-1;
1175 else if ( nLineMode & DOCK_LINELEFT )
1176 rRect.Left() = rRect.Right()-nSize;
1177 else
1178 rRect.Top() = rRect.Bottom()-nSize;
1180 pThis->mnDockLines = i;
1183 // -----------------------------------------------------------------------
1185 sal_uInt16 ToolBox::ImplFindItemPos( ToolBox* pBox, const Point& rPos )
1187 sal_uInt16 nPos = 0;
1188 long nLast = 0;
1189 Point aPos = rPos;
1190 Size aSize( pBox->mnDX, pBox->mnDY );
1192 if ( aPos.X() > aSize.Width()-TB_BORDER_OFFSET1 )
1193 aPos.X() = aSize.Width()-TB_BORDER_OFFSET1;
1194 if ( aPos.Y() > aSize.Height()-TB_BORDER_OFFSET1 )
1195 aPos.Y() = aSize.Height()-TB_BORDER_OFFSET1;
1197 // Item suchen, das geklickt wurde
1198 std::vector< ImplToolItem >::const_iterator it = pBox->mpData->m_aItems.begin();
1199 while ( it != pBox->mpData->m_aItems.end() )
1201 if ( it->mbVisible )
1203 if ( nLast || !it->maRect.IsEmpty() )
1205 if ( pBox->mbHorz )
1207 if ( nLast &&
1208 ((nLast < it->maRect.Top()) || it->maRect.IsEmpty()) )
1209 return nPos;
1211 if ( aPos.Y() <= it->maRect.Bottom() )
1213 if ( aPos.X() < it->maRect.Left() )
1214 return nPos;
1215 else if ( aPos.X() < it->maRect.Right() )
1216 return nPos+1;
1217 else if ( !nLast )
1218 nLast = it->maRect.Bottom();
1221 else
1223 if ( nLast &&
1224 ((nLast < it->maRect.Left()) || it->maRect.IsEmpty()) )
1225 return nPos;
1227 if ( aPos.X() <= it->maRect.Right() )
1229 if ( aPos.Y() < it->maRect.Top() )
1230 return nPos;
1231 else if ( aPos.Y() < it->maRect.Bottom() )
1232 return nPos+1;
1233 else if ( !nLast )
1234 nLast = it->maRect.Right();
1240 nPos++;
1241 ++it;
1244 return nPos;
1247 // -----------------------------------------------------------------------
1249 ImplTBDragMgr::ImplTBDragMgr()
1251 mpBoxList = new ImplTBList();
1252 mnLineMode = 0;
1253 mnStartLines = 0;
1254 mbCustomizeMode = sal_False;
1255 mbResizeMode = sal_False;
1256 mbShowDragRect = sal_False;
1257 mpDragBox = NULL;
1259 maAccel.InsertItem( KEY_RETURN, KeyCode( KEY_RETURN ) );
1260 maAccel.InsertItem( KEY_ESCAPE, KeyCode( KEY_ESCAPE ) );
1261 maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl ) );
1264 // -----------------------------------------------------------------------
1266 ImplTBDragMgr::~ImplTBDragMgr()
1268 delete mpBoxList;
1271 // -----------------------------------------------------------------------
1273 ToolBox* ImplTBDragMgr::FindToolBox( const Rectangle& rRect )
1275 for ( size_t i = 0, n = mpBoxList->size(); i < n; ++i )
1277 ToolBox* pBox = (*mpBoxList)[ i ];
1279 * FIXME: since we can have multiple frames now we cannot
1280 * find the drag target by its position alone.
1281 * As long as the toolbar config dialogue is not a system window
1282 * this works in one frame only anyway. If the dialogue
1283 * changes to a system window, we need a new implementation here
1285 if ( pBox->IsReallyVisible()
1286 && pBox->ImplGetWindowImpl()->mpFrame == mpDragBox->ImplGetWindowImpl()->mpFrame
1288 if ( !pBox->ImplIsFloatingMode() )
1290 Point aPos = pBox->GetPosPixel();
1291 aPos = pBox->GetParent()->OutputToScreenPixel( aPos );
1292 Rectangle aTempRect( aPos, pBox->GetSizePixel() );
1293 if ( aTempRect.IsOver( rRect ) )
1294 return pBox;
1299 return NULL;
1302 // -----------------------------------------------------------------------
1304 void ImplTBDragMgr::StartDragging( ToolBox* pToolBox,
1305 const Point& rPos, const Rectangle& rRect,
1306 sal_uInt16 nDragLineMode, sal_Bool bResizeItem,
1307 void* pData )
1309 mpDragBox = pToolBox;
1310 pToolBox->CaptureMouse();
1311 pToolBox->mbDragging = sal_True;
1312 Application::InsertAccel( &maAccel );
1314 if ( nDragLineMode )
1316 mnLineMode = nDragLineMode;
1317 mnStartLines = pToolBox->mnDockLines;
1319 else
1321 mpCustomizeData = pData;
1322 mbResizeMode = bResizeItem;
1323 pToolBox->Activate();
1324 pToolBox->mnCurItemId = pToolBox->mnConfigItem;
1325 pToolBox->Highlight();
1326 pToolBox->mnCurItemId = 0;
1327 if ( mbResizeMode )
1329 if ( rRect.GetWidth() < TB_MIN_WIN_WIDTH )
1330 mnMinWidth = rRect.GetWidth();
1331 else
1332 mnMinWidth = TB_MIN_WIN_WIDTH;
1333 mnMaxWidth = pToolBox->GetSizePixel().Width()-rRect.Left()-
1334 TB_SPIN_SIZE-TB_BORDER_OFFSET1-(TB_SPIN_OFFSET*2);
1338 // MouseOffset berechnen
1339 maMouseOff.X() = rRect.Left() - rPos.X();
1340 maMouseOff.Y() = rRect.Top() - rPos.Y();
1341 maRect = rRect;
1342 maStartRect = rRect;
1343 mbShowDragRect = sal_True;
1344 pToolBox->ShowTracking( maRect );
1347 // -----------------------------------------------------------------------
1349 void ImplTBDragMgr::Dragging( const Point& rPos )
1351 if ( mnLineMode )
1353 ToolBox::ImplLineSizing( mpDragBox, rPos, maRect, mnLineMode );
1354 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1355 maRect.Move( aOff.X(), aOff.Y() );
1356 mpDragBox->Docking( rPos, maRect );
1357 maRect.Move( -aOff.X(), -aOff.Y() );
1358 mpDragBox->ShowTracking( maRect );
1360 else
1362 if ( mbResizeMode )
1364 long nXOff = rPos.X()-maStartRect.Left();
1365 nXOff += maMouseOff.X()+(maStartRect.Right()-maStartRect.Left());
1366 if ( nXOff < mnMinWidth )
1367 nXOff = mnMinWidth;
1368 if ( nXOff > mnMaxWidth )
1369 nXOff = mnMaxWidth;
1370 maRect.Right() = maStartRect.Left()+nXOff;
1372 else
1374 maRect.SetPos( rPos );
1375 maRect.Move( maMouseOff.X(), maMouseOff.Y() );
1377 mpDragBox->ShowTracking( maRect );
1381 // -----------------------------------------------------------------------
1383 void ImplTBDragMgr::EndDragging( sal_Bool bOK )
1385 mpDragBox->HideTracking();
1386 mpDragBox->ReleaseMouse();
1387 mpDragBox->mbDragging = sal_False;
1388 mbShowDragRect = sal_False;
1389 Application::RemoveAccel( &maAccel );
1391 if ( mnLineMode )
1393 if ( !bOK )
1395 mpDragBox->mnDockLines = mnStartLines;
1396 mpDragBox->EndDocking( maStartRect, sal_False );
1398 else
1399 mpDragBox->EndDocking( maRect, sal_False );
1400 mnLineMode = 0;
1401 mnStartLines = 0;
1403 else
1405 sal_uInt16 nTempItem = mpDragBox->mnConfigItem;
1406 if ( nTempItem )
1408 mpDragBox->mnConfigItem = 0;
1409 if ( !mbResizeMode )
1410 mpDragBox->Invalidate( mpDragBox->GetItemRect( nTempItem ) );
1413 if ( bOK && (maRect != maStartRect) )
1415 if ( mbResizeMode )
1417 ImplToolItem* pItem = mpDragBox->ImplGetItem( nTempItem );
1418 Size aSize = pItem->mpWindow->GetSizePixel();
1419 aSize.Width() = maRect.GetWidth();
1420 pItem->mpWindow->SetSizePixel( aSize );
1422 // re-calculate and show ToolBox
1423 mpDragBox->ImplInvalidate( sal_True );
1424 mpDragBox->Customize( ToolBoxCustomizeEvent( mpDragBox, nTempItem,
1425 TOOLBOX_CUSTOMIZE_RESIZE,
1426 mpCustomizeData ) );
1428 else
1430 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1431 Rectangle aScreenRect( maRect );
1432 aScreenRect.Move( aOff.X(), aOff.Y() );
1433 ToolBox* pDropBox = FindToolBox( aScreenRect );
1434 if ( pDropBox )
1436 // Determine search position
1437 Point aPos;
1438 if ( pDropBox->mbHorz )
1440 aPos.X() = aScreenRect.Left()-TB_CUSTOMIZE_OFFSET;
1441 aPos.Y() = aScreenRect.Center().Y();
1443 else
1445 aPos.X() = aScreenRect.Center().X();
1446 aPos.Y() = aScreenRect.Top()-TB_CUSTOMIZE_OFFSET;
1449 aPos = pDropBox->ScreenToOutputPixel( aPos );
1450 sal_uInt16 nPos = ToolBox::ImplFindItemPos( pDropBox, aPos );
1451 mpDragBox->Customize( ToolBoxCustomizeEvent( pDropBox, nTempItem,
1452 nPos, mpCustomizeData ) );
1454 else
1456 mpDragBox->Customize( ToolBoxCustomizeEvent( NULL, nTempItem,
1457 0, mpCustomizeData ) );
1461 mpCustomizeData = NULL;
1462 mbResizeMode = sal_False;
1463 mpDragBox->Deactivate();
1466 mpDragBox = NULL;
1469 // -----------------------------------------------------------------------
1471 void ImplTBDragMgr::UpdateDragRect()
1473 // Only update if we're already dragging
1474 if ( !mbShowDragRect )
1475 return;
1477 mpDragBox->ShowTracking( maRect );
1480 // -----------------------------------------------------------------------
1482 IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator*, pAccel )
1484 if ( pAccel->GetCurItemId() == KEY_ESCAPE )
1485 EndDragging( sal_False );
1486 else
1487 EndDragging( sal_True );
1489 return sal_True;
1492 // -----------------------------------------------------------------------
1494 static void ImplDrawOutButton( OutputDevice* pOutDev, const Rectangle& rRect,
1495 sal_uInt16 nStyle )
1497 const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
1498 Color aShadowColor = rStyleSettings.GetShadowColor();
1499 Point aPos( rRect.TopLeft() );
1500 Size aSize( rRect.GetSize() );
1501 long nOffset = 0;
1503 if ( pOutDev->GetBackground().GetColor() == aShadowColor )
1504 aShadowColor = rStyleSettings.GetDarkShadowColor();
1506 if ( nStyle & BUTTON_DRAW_PRESSED )
1508 aPos.X()++;
1509 aPos.Y()++;
1510 nOffset++;
1513 // delete background
1514 pOutDev->Erase( rRect );
1516 // draw button
1517 pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
1518 pOutDev->DrawLine( aPos,
1519 Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ) );
1520 pOutDev->DrawLine( aPos,
1521 Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1522 pOutDev->SetLineColor( aShadowColor );
1523 pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ),
1524 Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1525 pOutDev->DrawLine( Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ),
1526 Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1527 for ( long i = 0; i < OUTBUTTON_BORDER-1-nOffset; i++ )
1529 pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+OUTBUTTON_BORDER ),
1530 Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+aSize.Height()-1 ) );
1531 pOutDev->DrawLine( Point( aPos.X()+OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ),
1532 Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ) );
1537 // -----------------------------------------------------------------------
1539 void ToolBox::ImplInit( Window* pParent, WinBits nStyle )
1542 // initialize variables
1543 ImplGetWindowImpl()->mbToolBox = sal_True;
1544 mpBtnDev = NULL;
1545 mpFloatSizeAry = NULL;
1546 mpData = new ImplToolBoxPrivateData;
1547 mpFloatWin = NULL;
1548 mnDX = 0;
1549 mnDY = 0;
1550 mnMaxItemWidth = 0;
1551 mnMaxItemHeight = 0;
1552 mnWinHeight = 0;
1553 mnBorderX = 0;
1554 mnBorderY = 0;
1555 mnLeftBorder = 0;
1556 mnTopBorder = 0;
1557 mnRightBorder = 0;
1558 mnBottomBorder = 0;
1559 mnLastResizeDY = 0;
1560 mnOutStyle = TOOLBOX_STYLE_FLAT; // force flat buttons since NWF
1561 mnHighItemId = 0;
1562 mnCurItemId = 0;
1563 mnDownItemId = 0;
1564 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1565 mnFocusPos = TOOLBOX_ITEM_NOTFOUND; // current position during keyboard access
1566 mnLines = 1;
1567 mnCurLine = 1;
1568 mnCurLines = 1;
1569 mnVisLines = 1;
1570 mnFloatLines = 0;
1571 mnConfigItem = 0;
1572 mnMouseClicks = 0;
1573 mnMouseModifier = 0;
1574 mbDrag = sal_False;
1575 mbSelection = sal_False;
1576 mbCommandDrag = sal_False;
1577 mbUpper = sal_False;
1578 mbLower = sal_False;
1579 mbNextTool = sal_False;
1580 mbIn = sal_False;
1581 mbCalc = sal_True;
1582 mbFormat = sal_False;
1583 mbFullPaint = sal_False;
1584 mbHorz = sal_True;
1585 mbScroll = (nStyle & WB_SCROLL) != 0;
1586 mbCustomize = sal_False;
1587 mbCustomizeMode = sal_False;
1588 mbDragging = sal_False;
1589 mbMenuStrings = sal_False;
1590 mbIsShift = sal_False;
1591 mbIsKeyEvent = sal_False;
1592 mbChangingHighlight = sal_False;
1593 meButtonType = BUTTON_SYMBOL;
1594 meAlign = WINDOWALIGN_TOP;
1595 meLastStyle = POINTER_ARROW;
1596 mnWinStyle = nStyle;
1597 meLayoutMode = TBX_LAYOUT_NORMAL;
1598 mnLastFocusItemId = 0;
1599 mnKeyModifier = 0;
1600 mnActivateCount = 0;
1602 maTimer.SetTimeout( 50 );
1603 maTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplUpdateHdl ) );
1605 // set timeout and handler for dropdown items
1606 mpData->maDropdownTimer.SetTimeout( 250 );
1607 mpData->maDropdownTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplDropdownLongClickHdl ) );
1609 DockingWindow::ImplInit( pParent, nStyle & ~(WB_BORDER) );
1612 // always set WB_TABSTOP for ToolBars !!! if( mnWinStyle & WB_TABSTOP )
1614 // dockingwindow's ImplInit removes some bits, so restore them here
1615 // to allow keyboard handling for toolbars
1616 ImplGetWindowImpl()->mnStyle |= WB_TABSTOP|WB_NODIALOGCONTROL;
1617 ImplGetWindowImpl()->mnStyle &= ~WB_DIALOGCONTROL;
1620 ImplInitSettings( sal_True, sal_True, sal_True );
1623 // -----------------------------------------------------------------------
1625 void ToolBox::ImplInitSettings( sal_Bool bFont,
1626 sal_Bool bForeground, sal_Bool bBackground )
1628 mpData->mbNativeButtons = IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
1630 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1632 if ( bFont )
1634 Font aFont = rStyleSettings.GetToolFont();
1635 if ( IsControlFont() )
1636 aFont.Merge( GetControlFont() );
1637 SetZoomedPointFont( aFont );
1640 if ( bForeground || bFont )
1642 Color aColor;
1643 if ( IsControlForeground() )
1644 aColor = GetControlForeground();
1645 else if ( Window::GetStyle() & WB_3DLOOK )
1646 aColor = rStyleSettings.GetButtonTextColor();
1647 else
1648 aColor = rStyleSettings.GetWindowTextColor();
1649 SetTextColor( aColor );
1650 SetTextFillColor();
1653 if ( bBackground )
1655 Color aColor;
1656 if ( IsControlBackground() )
1658 aColor = GetControlBackground();
1659 SetBackground( aColor );
1660 SetPaintTransparent( sal_False );
1661 SetParentClipMode( 0 );
1663 else
1665 if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
1667 SetBackground();
1668 SetPaintTransparent( sal_True );
1669 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
1670 mpData->maDisplayBackground = Wallpaper( rStyleSettings.GetFaceColor() );
1672 else
1674 if ( Window::GetStyle() & WB_3DLOOK )
1675 aColor = rStyleSettings.GetFaceColor();
1676 else
1677 aColor = rStyleSettings.GetWindowColor();
1679 SetBackground( aColor );
1680 SetPaintTransparent( sal_False );
1681 SetParentClipMode( 0 );
1683 ImplUpdateImageList();
1689 // -----------------------------------------------------------------------
1691 void ToolBox::ImplLoadRes( const ResId& rResId )
1693 ResMgr* pMgr = rResId.GetResMgr();
1694 if( ! pMgr )
1695 return;
1697 DockingWindow::ImplLoadRes( rResId );
1699 sal_uLong nObjMask;
1701 nObjMask = ReadLongRes();
1703 if ( nObjMask & RSC_TOOLBOX_BUTTONTYPE )
1704 SetButtonType( (ButtonType)ReadLongRes() );
1706 if ( nObjMask & RSC_TOOLBOX_ALIGN )
1707 SetAlign( (WindowAlign)ReadLongRes() );
1709 if ( nObjMask & RSC_TOOLBOX_LINECOUNT )
1710 SetLineCount( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
1712 if ( nObjMask & RSC_TOOLBOX_CUSTOMIZE )
1714 sal_Bool bCust = (sal_Bool)ReadShortRes();
1715 EnableCustomize( bCust );
1718 if ( nObjMask & RSC_TOOLBOX_MENUSTRINGS )
1720 sal_Bool bCust = (sal_Bool)ReadShortRes();
1721 EnableMenuStrings( bCust );
1724 if ( nObjMask & RSC_TOOLBOX_FLOATLINES )
1725 SetFloatingLines( ReadShortRes() );
1727 if ( nObjMask & RSC_TOOLBOX_ITEMIMAGELIST )
1729 maImageList = ImageList( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1730 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1733 if ( nObjMask & RSC_TOOLBOX_ITEMLIST )
1735 sal_uLong nEle = ReadLongRes();
1737 // insert item
1738 for ( sal_uLong i = 0; i < nEle; i++ )
1740 InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1741 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
1746 // -----------------------------------------------------------------------
1748 ToolBox::ToolBox( Window* pParent, WinBits nStyle ) :
1749 DockingWindow( WINDOW_TOOLBOX )
1751 ImplInit( pParent, nStyle );
1754 // -----------------------------------------------------------------------
1756 ToolBox::ToolBox( Window* pParent, const ResId& rResId ) :
1757 DockingWindow( WINDOW_TOOLBOX )
1759 RTL_LOGFILE_CONTEXT( aLog, "vcl: ToolBox::ToolBox( Window* pParent, const ResId& rResId )" );
1761 rResId.SetRT( RSC_TOOLBOX );
1762 WinBits nStyle = ImplInitRes( rResId );
1763 ImplInit( pParent, nStyle );
1764 ImplLoadRes( rResId );
1766 // calculate size of floating windows and switch if the
1767 // toolbox is initially in floating mode
1768 if ( ImplIsFloatingMode() )
1769 mbHorz = sal_True;
1770 else
1771 Resize();
1773 if ( !(nStyle & WB_HIDE) )
1774 Show();
1777 // -----------------------------------------------------------------------
1779 ToolBox::~ToolBox()
1781 // custom menu event still running?
1782 if( mpData->mnEventId )
1783 Application::RemoveUserEvent( mpData->mnEventId );
1785 // #103005# make sure our activate/deactivate balance is right
1786 while( mnActivateCount > 0 )
1787 Deactivate();
1789 // terminate popupmode if the floating window is
1790 // still connected
1791 if ( mpFloatWin )
1792 mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
1794 // delete private data
1795 delete mpData;
1797 // delete FloatSizeAry if required
1798 delete mpFloatSizeAry;
1800 // remove the lists when there are no more toolbox references to
1801 // the lists
1802 ImplSVData* pSVData = ImplGetSVData();
1803 if ( pSVData->maCtrlData.mpTBDragMgr )
1805 // remove if in TBDrag-Manager
1806 if ( mbCustomize )
1807 pSVData->maCtrlData.mpTBDragMgr->erase( this );
1809 if ( !pSVData->maCtrlData.mpTBDragMgr->size() )
1811 delete pSVData->maCtrlData.mpTBDragMgr;
1812 pSVData->maCtrlData.mpTBDragMgr = NULL;
1817 // -----------------------------------------------------------------------
1819 ImplToolItem* ToolBox::ImplGetItem( sal_uInt16 nItemId ) const
1821 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1822 while ( it != mpData->m_aItems.end() )
1824 if ( it->mnId == nItemId )
1825 return &(*it);
1826 ++it;
1829 return NULL;
1831 // -----------------------------------------------------------------------
1833 static void ImplAddButtonBorder( long &rWidth, long& rHeight, sal_uInt16 aOutStyle, sal_Bool bNativeButtons )
1835 if ( aOutStyle & TOOLBOX_STYLE_OUTBUTTON )
1837 rWidth += OUTBUTTON_SIZE;
1838 rHeight += OUTBUTTON_SIZE;
1840 else
1842 rWidth += SMALLBUTTON_HSIZE;
1843 rHeight += SMALLBUTTON_VSIZE;
1846 if( bNativeButtons )
1848 // give more border space for rounded buttons
1849 rWidth += 2;
1850 rHeight += 4;
1854 // -----------------------------------------------------------------------
1856 sal_Bool ToolBox::ImplCalcItem()
1858 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
1860 // recalc required ?
1861 if ( !mbCalc )
1862 return sal_False;
1864 ImplDisableFlatButtons();
1866 long nDefWidth;
1867 long nDefHeight;
1868 long nMaxWidth = 0;
1869 long nMaxHeight = 0;
1870 long nMinWidth = 6;
1871 long nMinHeight = 6;
1872 long nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
1874 // set defaults if image or text is needed but empty
1875 nDefWidth = GetDefaultImageSize().Width();
1876 nDefHeight = GetDefaultImageSize().Height();
1878 mnWinHeight = 0;
1879 // determine minimum size necessary in NWF
1881 Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1882 Rectangle aReg( aRect );
1883 ImplControlValue aVal;
1884 Rectangle aNativeBounds, aNativeContent;
1885 if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
1887 if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
1888 aReg,
1889 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1890 aVal, OUString(),
1891 aNativeBounds, aNativeContent ) )
1893 aRect = aNativeBounds;
1894 if( aRect.GetWidth() > nMinWidth )
1895 nMinWidth = aRect.GetWidth();
1896 if( aRect.GetHeight() > nMinHeight )
1897 nMinHeight = aRect.GetHeight();
1898 if( nDropDownArrowWidth < nMinWidth )
1899 nDropDownArrowWidth = nMinWidth;
1900 if( nMinWidth > mpData->mnMenuButtonWidth )
1901 mpData->mnMenuButtonWidth = nMinWidth;
1902 else if( nMinWidth < TB_MENUBUTTON_SIZE )
1903 mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
1907 // also calculate the area for comboboxes, drop down list boxes and spinfields
1908 // as these are often inserted into toolboxes; set mnWinHeight to the
1909 // greater of those values to prevent toolbar flickering (#i103385#)
1910 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1911 aReg = aRect;
1912 if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
1913 aReg,
1914 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1915 aVal, OUString(),
1916 aNativeBounds, aNativeContent ) )
1918 aRect = aNativeBounds;
1919 if( aRect.GetHeight() > mnWinHeight )
1920 mnWinHeight = aRect.GetHeight();
1922 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1923 aReg = aRect;
1924 if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
1925 aReg,
1926 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1927 aVal, OUString(),
1928 aNativeBounds, aNativeContent ) )
1930 aRect = aNativeBounds;
1931 if( aRect.GetHeight() > mnWinHeight )
1932 mnWinHeight = aRect.GetHeight();
1934 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1935 aReg = aRect;
1936 if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
1937 aReg,
1938 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1939 aVal, OUString(),
1940 aNativeBounds, aNativeContent ) )
1942 aRect = aNativeBounds;
1943 if( aRect.GetHeight() > mnWinHeight )
1944 mnWinHeight = aRect.GetHeight();
1948 if ( ! mpData->m_aItems.empty() )
1950 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1951 while ( it != mpData->m_aItems.end() )
1953 sal_Bool bImage;
1954 sal_Bool bText;
1956 it->mbVisibleText = sal_False; // indicates if text will definitely be drawn, influences dropdown pos
1958 if ( it->meType == TOOLBOXITEM_BUTTON )
1960 // check if image and/or text exists
1961 if ( !(it->maImage) )
1962 bImage = sal_False;
1963 else
1964 bImage = sal_True;
1965 if ( !it->maText.Len() )
1966 bText = sal_False;
1967 else
1968 bText = sal_True;
1969 ButtonType tmpButtonType = determineButtonType( &(*it), meButtonType ); // default to toolbox setting
1970 if ( bImage || bText )
1973 it->mbEmptyBtn = sal_False;
1975 if ( tmpButtonType == BUTTON_SYMBOL )
1977 // we're drawing images only
1978 if ( bImage || !bText )
1980 it->maItemSize = it->maImage.GetSizePixel();
1982 else
1984 it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
1985 GetTextHeight() );
1986 it->mbVisibleText = sal_True;
1989 else if ( tmpButtonType == BUTTON_TEXT )
1991 // we're drawing text only
1992 if ( bText || !bImage )
1994 it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
1995 GetTextHeight() );
1996 it->mbVisibleText = sal_True;
1998 else
2000 it->maItemSize = it->maImage.GetSizePixel();
2003 else
2005 // we're drawing images and text
2006 it->maItemSize.Width() = bText ? GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET : 0;
2007 it->maItemSize.Height() = bText ? GetTextHeight() : 0;
2009 // leave space between image and text
2010 if( bText )
2011 it->maItemSize.Width() += TB_IMAGETEXTOFFSET;
2013 // image and text side by side
2014 it->maItemSize.Width() += it->maImage.GetSizePixel().Width();
2015 if ( it->maImage.GetSizePixel().Height() > it->maItemSize.Height() )
2016 it->maItemSize.Height() = it->maImage.GetSizePixel().Height();
2018 it->mbVisibleText = bText;
2021 else
2022 { // no image and no text
2023 it->maItemSize = Size( nDefWidth, nDefHeight );
2024 it->mbEmptyBtn = sal_True;
2027 // if required, take window height into consideration
2028 if ( it->mpWindow )
2030 long nHeight = it->mpWindow->GetSizePixel().Height();
2031 if ( nHeight > mnWinHeight )
2032 mnWinHeight = nHeight;
2035 // add in drop down arrow
2036 if( it->mnBits & TIB_DROPDOWN )
2038 it->maItemSize.Width() += nDropDownArrowWidth;
2039 it->mnDropDownArrowWidth = nDropDownArrowWidth;
2042 // text items will be rotated in vertical mode
2043 // -> swap width and height
2044 if( it->mbVisibleText && !mbHorz )
2046 long tmp = it->maItemSize.Width();
2047 it->maItemSize.Width() = it->maItemSize.Height();
2048 it->maItemSize.Height() = tmp;
2051 else if ( it->meType == TOOLBOXITEM_SPACE )
2053 it->maItemSize = Size( nDefWidth, nDefHeight );
2056 if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2058 // add borders
2059 ImplAddButtonBorder( it->maItemSize.Width(), it->maItemSize.Height(), mnOutStyle, mpData->mbNativeButtons );
2061 if( it->meType == TOOLBOXITEM_BUTTON )
2063 if( it->maItemSize.Width() < nMinWidth )
2064 it->maItemSize.Width() = nMinWidth;
2065 if( it->maItemSize.Height() < nMinHeight )
2066 it->maItemSize.Height() = nMinHeight;
2069 // keep track of max item size
2070 if ( it->maItemSize.Width() > nMaxWidth )
2071 nMaxWidth = it->maItemSize.Width();
2072 if ( it->maItemSize.Height() > nMaxHeight )
2073 nMaxHeight = it->maItemSize.Height();
2076 ++it;
2079 else
2081 nMaxWidth = nDefWidth;
2082 nMaxHeight = nDefHeight;
2084 ImplAddButtonBorder( nMaxWidth, nMaxHeight, mnOutStyle, mpData->mbNativeButtons );
2087 if( !ImplIsFloatingMode() && GetToolboxButtonSize() != TOOLBOX_BUTTONSIZE_DONTCARE )
2089 // make sure all vertical toolbars have the same width and horizontal have the same height
2090 // this depends on the used button sizes
2091 // as this is used for alignement of multiple toolbars
2092 // it is only required for docked toolbars
2094 long nFixedWidth = nDefWidth+nDropDownArrowWidth;
2095 long nFixedHeight = nDefHeight;
2096 ImplAddButtonBorder( nFixedWidth, nFixedHeight, mnOutStyle, mpData->mbNativeButtons );
2098 if( mbHorz )
2099 nMaxHeight = nFixedHeight;
2100 else
2101 nMaxWidth = nFixedWidth;
2104 mbCalc = sal_False;
2105 mbFormat = sal_True;
2107 // do we have to recalc the sizes ?
2108 if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) )
2110 mnMaxItemWidth = nMaxWidth;
2111 mnMaxItemHeight = nMaxHeight;
2113 return sal_True;
2115 else
2116 return sal_False;
2119 // -----------------------------------------------------------------------
2121 sal_uInt16 ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, sal_Bool bCalcHorz )
2123 sal_uLong nLineStart = 0;
2124 sal_uLong nGroupStart = 0;
2125 long nLineWidth = 0;
2126 long nCurWidth;
2127 long nLastGroupLineWidth = 0;
2128 long nMaxLineWidth = 0;
2129 sal_uInt16 nLines = 1;
2130 sal_Bool bWindow;
2131 sal_Bool bBreak = sal_False;
2132 long nWidthTotal = nWidth;
2133 long nMenuWidth = 0;
2135 // when docked the menubutton will be in the first line
2136 if( IsMenuEnabled() && !ImplIsFloatingMode() )
2137 nMenuWidth = mpData->maMenubuttonItem.maItemSize.Width();
2139 // we need to know which item is the last visible one to be able to add
2140 // the menu width in case we are unable to show all the items
2141 std::vector< ImplToolItem >::iterator it, lastVisible;
2142 for ( it = mpData->m_aItems.begin(); it != mpData->m_aItems.end(); ++it )
2144 if ( it->mbVisible )
2145 lastVisible = it;
2148 it = mpData->m_aItems.begin();
2149 while ( it != mpData->m_aItems.end() )
2151 it->mbBreak = bBreak;
2152 bBreak = sal_False;
2154 if ( it->mbVisible )
2156 bWindow = sal_False;
2157 bBreak = sal_False;
2158 nCurWidth = 0;
2160 if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2162 if ( bCalcHorz )
2163 nCurWidth = it->maItemSize.Width();
2164 else
2165 nCurWidth = it->maItemSize.Height();
2167 if ( it->mpWindow && bCalcHorz )
2169 long nWinItemWidth = it->mpWindow->GetSizePixel().Width();
2170 if ( !mbScroll || (nWinItemWidth <= nWidthTotal) )
2172 nCurWidth = nWinItemWidth;
2173 bWindow = sal_True;
2175 else
2177 if ( it->mbEmptyBtn )
2179 nCurWidth = 0;
2184 // in case we are able to show all the items, we do not want
2185 // to show the toolbar's menu; otherwise yes
2186 if ( ( ( it == lastVisible ) && (nLineWidth+nCurWidth > nWidthTotal) && mbScroll ) ||
2187 ( ( it != lastVisible ) && (nLineWidth+nCurWidth+nMenuWidth > nWidthTotal) && mbScroll ) )
2188 bBreak = sal_True;
2190 else if ( it->meType == TOOLBOXITEM_SEPARATOR )
2192 nCurWidth = it->mnSepSize;
2193 if ( !ImplIsFloatingMode() && ( it != lastVisible ) && (nLineWidth+nCurWidth+nMenuWidth > nWidthTotal) )
2194 bBreak = sal_True;
2196 // treat breaks as separators, except when using old style toolbars (ie. no menu button)
2197 else if ( (it->meType == TOOLBOXITEM_BREAK) && !IsMenuEnabled() )
2198 bBreak = sal_True;
2200 if ( bBreak )
2202 nLines++;
2204 // Add break before the entire group or take group apart?
2205 if ( (it->meType == TOOLBOXITEM_BREAK) ||
2206 (nLineStart == nGroupStart) )
2208 if ( nLineWidth > nMaxLineWidth )
2209 nMaxLineWidth = nLineWidth;
2211 nLineWidth = 0;
2212 nLineStart = it - mpData->m_aItems.begin();
2213 nGroupStart = nLineStart;
2214 it->mbBreak = sal_True;
2215 bBreak = sal_False;
2217 else
2219 if ( nLastGroupLineWidth > nMaxLineWidth )
2220 nMaxLineWidth = nLastGroupLineWidth;
2222 // if the break is added before the group, set it to
2223 // beginning of line and re-calculate
2224 nLineWidth = 0;
2225 nLineStart = nGroupStart;
2226 it = mpData->m_aItems.begin() + nGroupStart;
2227 continue;
2230 else
2232 if( ImplIsFloatingMode() || !IsMenuEnabled() ) // no group breaking when being docked single-line
2234 if ( (it->meType != TOOLBOXITEM_BUTTON) || bWindow )
2236 // found separator or break
2237 nLastGroupLineWidth = nLineWidth;
2238 nGroupStart = it - mpData->m_aItems.begin();
2239 if ( !bWindow )
2240 nGroupStart++;
2245 nLineWidth += nCurWidth;
2248 ++it;
2252 if ( pMaxLineWidth )
2254 if ( nLineWidth > nMaxLineWidth )
2255 nMaxLineWidth = nLineWidth;
2257 if( ImplIsFloatingMode() && !ImplIsInPopupMode() )
2259 // leave enough space to display buttons in the decoration
2260 long aMinWidth = 2 * GetSettings().GetStyleSettings().GetFloatTitleHeight();
2261 if( nMaxLineWidth < aMinWidth )
2262 nMaxLineWidth = aMinWidth;
2264 *pMaxLineWidth = nMaxLineWidth;
2267 return nLines;
2270 // -----------------------------------------------------------------------
2272 Size ToolBox::ImplGetOptimalFloatingSize( FloatingSizeMode eMode )
2274 if( !ImplIsFloatingMode() )
2275 return Size();
2277 Size aCurrentSize( mnDX, mnDY );
2278 Size aSize1( aCurrentSize );
2279 Size aSize2( aCurrentSize );
2281 // try to preserve current height
2282 if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURHEIGHT )
2284 // calc number of floating lines for current window height
2285 sal_uInt16 nFloatLinesHeight = ImplCalcLines( this, mnDY );
2286 // calc window size according to this number
2287 aSize1 = ImplCalcFloatSize( this, nFloatLinesHeight );
2289 if( eMode == FSMODE_FAVOURHEIGHT || aCurrentSize == aSize1 )
2290 return aSize1;
2293 if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURWIDTH )
2295 // try to preserve current width
2296 long nLineHeight = ( mnWinHeight > mnMaxItemHeight ) ? mnWinHeight : mnMaxItemHeight;
2297 int nBorderX = 2*TB_BORDER_OFFSET1 + mnLeftBorder + mnRightBorder + 2*mnBorderX;
2298 int nBorderY = 2*TB_BORDER_OFFSET2 + mnTopBorder + mnBottomBorder + 2*mnBorderY;
2299 Size aSz( aCurrentSize );
2300 long maxX;
2301 sal_uInt16 nLines = ImplCalcBreaks( aSz.Width()-nBorderX, &maxX, mbHorz );
2303 sal_uInt16 manyLines = 1000;
2304 Size aMinimalFloatSize = ImplCalcFloatSize( this, manyLines );
2306 aSz.Height() = nBorderY + nLineHeight * nLines;
2307 // line space when more than one line
2308 if ( mnWinStyle & WB_LINESPACING )
2309 aSz.Height() += (nLines-1)*TB_LINESPACING;
2311 aSz.Width() = nBorderX + maxX;
2313 // avoid clipping of any items
2314 if( aSz.Width() < aMinimalFloatSize.Width() )
2315 aSize2 = ImplCalcFloatSize( this, nLines );
2316 else
2317 aSize2 = aSz;
2319 if( eMode == FSMODE_FAVOURWIDTH || aCurrentSize == aSize2 )
2320 return aSize2;
2321 else
2323 // set the size with the smallest delta as the current size
2324 long dx1 = abs( mnDX - aSize1.Width() );
2325 long dy1 = abs( mnDY - aSize1.Height() );
2327 long dx2 = abs( mnDX - aSize2.Width() );
2328 long dy2 = abs( mnDY - aSize2.Height() );
2330 if( dx1*dy1 < dx2*dy2 )
2331 aCurrentSize = aSize1;
2332 else
2333 aCurrentSize = aSize2;
2336 return aCurrentSize;
2339 namespace
2341 static void lcl_hideDoubleSeparators( std::vector< ImplToolItem >& rItems )
2343 bool bLastSep( true );
2344 std::vector< ImplToolItem >::iterator it;
2345 for ( it = rItems.begin(); it != rItems.end(); ++it )
2347 if ( it->meType == TOOLBOXITEM_SEPARATOR )
2349 it->mbVisible = sal_False;
2350 if ( !bLastSep )
2352 // check if any visible items have to appear behind it
2353 std::vector< ImplToolItem >::iterator temp_it;
2354 for ( temp_it = it+1; temp_it != rItems.end(); ++temp_it )
2356 if ( ((temp_it->meType == TOOLBOXITEM_BUTTON) &&
2357 temp_it->mbVisible) )
2359 it->mbVisible = sal_True;
2360 break;
2364 bLastSep = true;
2366 else if ( it->mbVisible )
2367 bLastSep = false;
2372 void ToolBox::ImplFormat( sal_Bool bResize )
2374 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2376 // Has to re-formatted
2377 if ( !mbFormat )
2378 return;
2380 mpData->ImplClearLayoutData();
2382 // recalulate positions and sizes
2383 Rectangle aEmptyRect;
2384 long nLineSize;
2385 long nLeft;
2386 long nTop;
2387 long nMax; // width of layoutarea in pixels
2388 sal_uInt16 nFormatLine;
2389 sal_Bool bMustFullPaint;
2391 std::vector< ImplToolItem >::iterator it;
2393 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2394 sal_Bool bIsInPopupMode = ImplIsInPopupMode();
2396 // delete FloatSizeAry if required
2397 if ( mpFloatSizeAry )
2399 delete mpFloatSizeAry;
2400 mpFloatSizeAry = NULL;
2403 // compute border sizes
2404 ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder, this );
2406 // update drag area (where the 'grip' will be placed)
2407 Rectangle aOldDragRect;
2408 if( pWrapper )
2409 aOldDragRect = pWrapper->GetDragArea();
2410 ImplUpdateDragArea( this );
2412 if ( ImplCalcItem() )
2413 bMustFullPaint = sal_True;
2414 else
2415 bMustFullPaint = sal_False;
2418 // calculate new size during interactive resize or
2419 // set computed size when formatting only
2420 if ( ImplIsFloatingMode() )
2422 if ( bResize )
2423 mnFloatLines = ImplCalcLines( this, mnDY );
2424 else
2425 SetOutputSizePixel( ImplGetOptimalFloatingSize( FSMODE_AUTO ) );
2428 // Horizontal
2429 if ( mbHorz )
2431 long nBottom;
2432 // nLineSize: height of a single line, will fit highest item
2433 nLineSize = mnMaxItemHeight;
2435 if ( mnWinHeight > mnMaxItemHeight )
2436 nLineSize = mnWinHeight;
2438 if ( mbScroll )
2440 nMax = mnDX;
2441 mnVisLines = ImplCalcLines( this, mnDY );
2443 else
2445 // layout over all lines
2446 mnVisLines = mnLines;
2447 nMax = TB_MAXNOSCROLL;
2450 // add in all border offsets
2451 // inner border as well as custom border (mnBorderX, mnBorderY)
2452 if ( mnWinStyle & WB_BORDER )
2454 nLeft = TB_BORDER_OFFSET1 + mnLeftBorder;
2455 nTop = TB_BORDER_OFFSET2 + mnTopBorder;
2456 nBottom = TB_BORDER_OFFSET1 + mnBottomBorder;
2457 nMax -= nLeft + TB_BORDER_OFFSET1 + mnRightBorder;
2459 else
2461 nLeft = 0;
2462 nTop = 0;
2463 nBottom = 0;
2466 nLeft += mnBorderX;
2467 nTop += mnBorderY;
2468 nBottom += mnBorderY;
2469 nMax -= mnBorderX*2;
2471 // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2472 // we have to center all items in the window height
2473 if( IsMenuEnabled() && !ImplIsFloatingMode() )
2475 long nWinHeight = mnDY - nTop - nBottom;
2476 if( nWinHeight > nLineSize )
2477 nLineSize = nWinHeight;
2480 else
2482 long nRight;
2483 nLineSize = mnMaxItemWidth;
2485 if ( mbScroll )
2487 mnVisLines = ImplCalcLines( this, mnDX );
2488 nMax = mnDY;
2490 else
2492 mnVisLines = mnLines;
2493 nMax = TB_MAXNOSCROLL;
2496 if ( mnWinStyle & WB_BORDER )
2498 nTop = TB_BORDER_OFFSET1 + mnTopBorder;
2499 nLeft = TB_BORDER_OFFSET2 + mnLeftBorder;
2500 nRight = TB_BORDER_OFFSET2 + mnRightBorder;
2501 nMax -= nTop + TB_BORDER_OFFSET1 + mnBottomBorder;
2503 else
2505 nLeft = 0;
2506 nTop = 0;
2507 nRight = 0;
2510 nLeft += mnBorderX;
2511 nRight+= mnBorderX;
2512 nTop += mnBorderY;
2513 nMax -= mnBorderY*2;
2515 // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2516 // we have to center all items in the window height
2517 if( !ImplIsFloatingMode() && IsMenuEnabled() )
2519 long nWinWidth = mnDX - nLeft - nRight;
2520 if( nWinWidth > nLineSize )
2521 nLineSize = nWinWidth;
2525 // no calculation if the window has no size (nMax=0)
2526 // non scrolling toolboxes must be computed though
2527 if ( (nMax <= 0) && mbScroll )
2529 mnVisLines = 1;
2530 mnCurLine = 1;
2531 mnCurLines = 1;
2533 it = mpData->m_aItems.begin();
2534 while ( it != mpData->m_aItems.end() )
2536 it->maRect = aEmptyRect;
2537 ++it;
2540 maLowerRect = aEmptyRect;
2541 maUpperRect = aEmptyRect;
2542 maNextToolRect = aEmptyRect;
2544 else
2546 // init start values
2547 long nX = nLeft; // top-left offset
2548 long nY = nTop;
2549 nFormatLine = 1;
2551 // save old scroll rectangles and reset them
2552 Rectangle aOldLowerRect = maLowerRect;
2553 Rectangle aOldUpperRect = maUpperRect;
2554 Rectangle aOldNextToolRect = maNextToolRect;
2555 Rectangle aOldMenubuttonRect = mpData->maMenubuttonItem.maRect;
2556 maUpperRect = aEmptyRect;
2557 maLowerRect = aEmptyRect;
2558 maNextToolRect = aEmptyRect;
2559 mpData->maMenubuttonItem.maRect = aEmptyRect;
2561 // additional toolboxes require a toggle button (maNextToolRect)
2562 if ( maNextToolBoxStr.Len() && mbScroll )
2564 nMax -= TB_NEXT_SIZE-TB_NEXT_OFFSET;
2565 if ( mbHorz )
2567 maNextToolRect.Left() = nLeft+nMax;
2568 maNextToolRect.Right() = maNextToolRect.Left()+TB_NEXT_SIZE-1;
2569 maNextToolRect.Top() = nTop;
2570 maNextToolRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2572 else
2574 maNextToolRect.Top() = nTop+nMax;
2575 maNextToolRect.Bottom() = maNextToolRect.Top()+TB_NEXT_SIZE-1;
2576 maNextToolRect.Left() = nLeft;
2577 maNextToolRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2581 // do we have any toolbox items at all ?
2582 if ( !mpData->m_aItems.empty() || IsMenuEnabled() )
2584 lcl_hideDoubleSeparators( mpData->m_aItems );
2586 // compute line breaks and visible lines give the current window width (nMax)
2587 // the break indicators will be stored within each item (it->mbBreak)
2588 mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2590 // check for scrollbar buttons or dropdown menu
2591 // (if a menu is enabled, this will be used to store clipped
2592 // items and no scroll buttons will appear)
2593 if ( (!ImplIsFloatingMode() && (mnCurLines > mnVisLines) && mbScroll ) ||
2594 IsMenuEnabled() )
2596 // compute linebreaks again, incorporating scrollbar buttons
2597 if( !IsMenuEnabled() )
2599 nMax -= TB_SPIN_SIZE+TB_SPIN_OFFSET;
2600 mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2603 // compute scroll rectangles or menu button
2604 if ( mbHorz )
2606 if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2608 if( !ImplIsFloatingMode() )
2610 mpData->maMenubuttonItem.maRect.Right() = mnDX - 2;
2611 mpData->maMenubuttonItem.maRect.Top() = nTop;
2612 mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2614 else
2616 mpData->maMenubuttonItem.maRect.Right() = mnDX - mnRightBorder-mnBorderX-TB_BORDER_OFFSET1-1;
2617 mpData->maMenubuttonItem.maRect.Top() = nTop;
2618 mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2620 mpData->maMenubuttonItem.maRect.Left() = mpData->maMenubuttonItem.maRect.Right() - mpData->mnMenuButtonWidth;
2622 else
2624 maUpperRect.Left() = nLeft+nMax+TB_SPIN_OFFSET;
2625 maUpperRect.Right() = maUpperRect.Left()+TB_SPIN_SIZE-1;
2626 maUpperRect.Top() = nTop;
2627 maLowerRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2628 maLowerRect.Left() = maUpperRect.Left();
2629 maLowerRect.Right() = maUpperRect.Right();
2630 maUpperRect.Bottom() = maUpperRect.Top() +
2631 (maLowerRect.Bottom()-maUpperRect.Top())/2;
2632 maLowerRect.Top() = maUpperRect.Bottom();
2635 else
2637 if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2639 if( !ImplIsFloatingMode() )
2641 mpData->maMenubuttonItem.maRect.Bottom() = mnDY - 2;
2642 mpData->maMenubuttonItem.maRect.Left() = nLeft;
2643 mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2645 else
2647 mpData->maMenubuttonItem.maRect.Bottom() = mnDY - mnBottomBorder-mnBorderY-TB_BORDER_OFFSET1-1;
2648 mpData->maMenubuttonItem.maRect.Left() = nLeft;
2649 mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2651 mpData->maMenubuttonItem.maRect.Top() = mpData->maMenubuttonItem.maRect.Bottom() - mpData->mnMenuButtonWidth;
2653 else
2655 maUpperRect.Top() = nTop+nMax+TB_SPIN_OFFSET;
2656 maUpperRect.Bottom() = maUpperRect.Top()+TB_SPIN_SIZE-1;
2657 maUpperRect.Left() = nLeft;
2658 maLowerRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2659 maLowerRect.Top() = maUpperRect.Top();
2660 maLowerRect.Bottom() = maUpperRect.Bottom();
2661 maUpperRect.Right() = maUpperRect.Left() +
2662 (maLowerRect.Right()-maUpperRect.Left())/2;
2663 maLowerRect.Left() = maUpperRect.Right();
2668 // no scrolling when there is a "more"-menu
2669 // anything will "fit" in a single line then
2670 if( IsMenuEnabled() )
2671 mnCurLines = 1;
2673 // determine the currently visible line
2674 if ( mnVisLines >= mnCurLines )
2675 mnCurLine = 1;
2676 else if ( mnCurLine+mnVisLines-1 > mnCurLines )
2677 mnCurLine = mnCurLines - (mnVisLines-1);
2679 it = mpData->m_aItems.begin();
2680 while ( it != mpData->m_aItems.end() )
2682 it->mbShowWindow = sal_False;
2684 // check for line break and advance nX/nY accordingly
2685 if ( it->mbBreak )
2687 nFormatLine++;
2689 // increment starting with the second line
2690 if ( nFormatLine > mnCurLine )
2692 if ( mbHorz )
2694 nX = nLeft;
2695 if ( mnWinStyle & WB_LINESPACING )
2696 nY += nLineSize+TB_LINESPACING;
2697 else
2698 nY += nLineSize;
2700 else
2702 nY = nTop;
2703 if ( mnWinStyle & WB_LINESPACING )
2704 nX += nLineSize+TB_LINESPACING;
2705 else
2706 nX += nLineSize;
2711 if ( !it->mbVisible || (nFormatLine < mnCurLine) ||
2712 (nFormatLine > mnCurLine+mnVisLines-1) )
2713 // item is not visible
2714 it->maCalcRect = aEmptyRect;
2715 else
2717 // 1. determine current item width/height
2718 // take window size and orientation into account, because this affects the size of item windows
2720 Size aCurrentItemSize( it->GetSize( mbHorz, mbScroll, nMax, Size(mnMaxItemWidth, mnMaxItemHeight) ) );
2722 // 2. position item rect and use size from step 1
2723 // items will be centered horizontally (if mbHorz) or vertically
2724 // advance nX and nY accordingly
2725 if ( mbHorz )
2727 it->maCalcRect.Left() = nX;
2728 // if special TBX_LAYOUT_LOCKVERT lock vertical position
2729 // don't recalulate the vertical position of the item
2730 if ( meLayoutMode == TBX_LAYOUT_LOCKVERT && mnLines == 1 )
2732 // Somewhat of a hack here, calc deletes and re-adds
2733 // the sum/assign & ok/cancel items dynamically.
2734 // Because TBX_LAYOUT_LOCKVERT effectively prevents
2735 // recalculation of the vertical pos of an item the
2736 // it->maRect.Top() for those newly added items is
2737 // 0. The hack here is that we want to effectively
2738 // recalculate the vertical pos for those added
2739 // items here. ( Note: assume mnMaxItemHeight is
2740 // equal to the LineSize when multibar has a single
2741 // line size )
2742 it->maCalcRect.Top() = it->maRect.Top() ? it->maRect.Top() : ( nY + ( mnMaxItemHeight-aCurrentItemSize.Height())/2 );
2744 else
2745 it->maCalcRect.Top() = nY+(nLineSize-aCurrentItemSize.Height())/2;
2746 it->maCalcRect.Right() = nX+aCurrentItemSize.Width()-1;
2747 it->maCalcRect.Bottom() = it->maCalcRect.Top()+aCurrentItemSize.Height()-1;
2748 nX += aCurrentItemSize.Width();
2750 else
2752 it->maCalcRect.Left() = nX+(nLineSize-aCurrentItemSize.Width())/2;
2753 it->maCalcRect.Top() = nY;
2754 it->maCalcRect.Right() = it->maCalcRect.Left()+aCurrentItemSize.Width()-1;
2755 it->maCalcRect.Bottom() = nY+aCurrentItemSize.Height()-1;
2756 nY += aCurrentItemSize.Height();
2760 // position window items into calculated item rect
2761 if ( it->mpWindow )
2763 if ( it->mbShowWindow )
2765 Point aPos( it->maCalcRect.Left(), it->maCalcRect.Top() );
2766 it->mpWindow->SetPosPixel( aPos );
2767 if ( !mbCustomizeMode )
2768 it->mpWindow->Show();
2770 else
2771 it->mpWindow->Hide();
2774 ++it;
2775 } // end of loop over all items
2777 else
2778 // we have no toolbox items
2779 mnCurLines = 1;
2782 if( IsMenuEnabled() && ImplIsFloatingMode() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2784 // custom menu will be the last button in floating mode
2785 ImplToolItem &rIt = mpData->maMenubuttonItem;
2787 if ( mbHorz )
2789 rIt.maRect.Left() = nX+TB_MENUBUTTON_OFFSET;
2790 rIt.maRect.Top() = nY;
2791 rIt.maRect.Right() = rIt.maRect.Left() + mpData->mnMenuButtonWidth;
2792 rIt.maRect.Bottom() = nY+nLineSize-1;
2793 nX += rIt.maItemSize.Width();
2795 else
2797 rIt.maRect.Left() = nX;
2798 rIt.maRect.Top() = nY+TB_MENUBUTTON_OFFSET;
2799 rIt.maRect.Right() = nX+nLineSize-1;
2800 rIt.maRect.Bottom() = rIt.maRect.Top() + mpData->mnMenuButtonWidth;
2801 nY += rIt.maItemSize.Height();
2806 // if toolbox visible trigger paint for changed regions
2807 if ( IsVisible() && !mbFullPaint )
2809 if ( bMustFullPaint )
2811 maPaintRect = Rectangle( mnLeftBorder, mnTopBorder,
2812 mnDX-mnRightBorder, mnDY-mnBottomBorder );
2814 else
2816 if ( aOldLowerRect != maLowerRect )
2818 maPaintRect.Union( maLowerRect );
2819 maPaintRect.Union( aOldLowerRect );
2821 if ( aOldUpperRect != maUpperRect )
2823 maPaintRect.Union( maUpperRect );
2824 maPaintRect.Union( aOldUpperRect );
2826 if ( aOldNextToolRect != maNextToolRect )
2828 maPaintRect.Union( maNextToolRect );
2829 maPaintRect.Union( aOldNextToolRect );
2831 if ( aOldMenubuttonRect != mpData->maMenubuttonItem.maRect )
2833 maPaintRect.Union( mpData->maMenubuttonItem.maRect );
2834 maPaintRect.Union( aOldMenubuttonRect );
2836 if ( pWrapper && aOldDragRect != pWrapper->GetDragArea() )
2838 maPaintRect.Union( pWrapper->GetDragArea() );
2839 maPaintRect.Union( aOldDragRect );
2842 it = mpData->m_aItems.begin();
2843 while ( it != mpData->m_aItems.end() )
2845 if ( it->maRect != it->maCalcRect )
2847 maPaintRect.Union( it->maRect );
2848 maPaintRect.Union( it->maCalcRect );
2850 ++it;
2854 Invalidate( maPaintRect );
2857 // store the new calculated item rects
2858 maPaintRect = aEmptyRect;
2859 Rectangle aVisibleRect(Point(0, 0), GetOutputSizePixel());
2860 it = mpData->m_aItems.begin();
2861 while ( it != mpData->m_aItems.end() )
2863 it->maRect = it->maCalcRect;
2864 it->maRect.IsOver(aVisibleRect);
2865 ++it;
2869 // indicate formatting is done
2870 mbFormat = sal_False;
2873 // -----------------------------------------------------------------------
2875 IMPL_LINK_NOARG(ToolBox, ImplDropdownLongClickHdl)
2877 if( mnCurPos != TOOLBOX_ITEM_NOTFOUND &&
2878 (mpData->m_aItems[ mnCurPos ].mnBits & TIB_DROPDOWN)
2881 mpData->mbDropDownByKeyboard = sal_False;
2882 GetDropdownClickHdl().Call( this );
2884 // do not reset data if the dropdown handler opened a floating window
2885 // see ImplFloatControl()
2886 if( mpFloatWin == NULL )
2888 // no floater was opened
2889 Deactivate();
2890 ImplDrawItem( mnCurPos, 0 );
2892 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
2893 mnCurItemId = 0;
2894 mnDownItemId = 0;
2895 mnMouseClicks = 0;
2896 mnMouseModifier = 0;
2897 mnHighItemId = 0;
2901 return 0;
2904 // -----------------------------------------------------------------------
2906 IMPL_LINK_NOARG(ToolBox, ImplUpdateHdl)
2908 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2910 if( mbFormat )
2911 ImplFormat();
2913 return 0;
2916 // -----------------------------------------------------------------------
2918 static void ImplDrawMoreIndicator( ToolBox *pBox, const Rectangle& rRect, sal_Bool bSetColor, sal_Bool bRotate )
2920 Color aOldFillColor = pBox->GetFillColor();
2921 Color aOldLineColor = pBox->GetLineColor();
2922 pBox->SetLineColor();
2924 if ( bSetColor )
2926 if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
2927 pBox->SetFillColor( Color( COL_WHITE ) );
2928 else
2929 pBox->SetFillColor( Color( COL_BLACK ) );
2932 if( !bRotate )
2934 long width = 8;
2935 long height = 5;
2936 long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
2937 long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
2938 while( height >= 1)
2940 pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2941 x+=4;
2942 pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2943 x-=4;
2944 y++;
2945 if( height <= 3) x--;
2946 else x++;
2947 height--;
2950 else
2952 long width = 5;
2953 long height = 8;
2954 long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
2955 long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
2956 while( width >= 1)
2958 pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
2959 y+=4;
2960 pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
2961 y-=4;
2962 x++;
2963 if( width <= 3) y--;
2964 else y++;
2965 width--;
2969 pBox->SetFillColor( aOldFillColor );
2970 pBox->SetLineColor( aOldLineColor );
2973 static void ImplDrawDropdownArrow( ToolBox *pBox, const Rectangle& rDropDownRect, sal_Bool bSetColor, sal_Bool bRotate )
2975 sal_Bool bLineColor = pBox->IsLineColor();
2976 sal_Bool bFillColor = pBox->IsFillColor();
2977 Color aOldFillColor = pBox->GetFillColor();
2978 Color aOldLineColor = pBox->GetLineColor();
2979 pBox->SetLineColor();
2981 if ( bSetColor )
2983 if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
2984 pBox->SetFillColor( Color( COL_WHITE ) );
2985 else
2986 pBox->SetFillColor( Color( COL_BLACK ) );
2989 if( !bRotate )
2991 long width = 5;
2992 long height = 3;
2993 long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
2994 long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
2995 while( width >= 1)
2997 pBox->DrawRect( Rectangle( x, y, x+width-1, y ) );
2998 y++; x++;
2999 width -= 2;
3002 else
3004 long width = 3;
3005 long height = 5;
3006 long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
3007 long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
3008 while( height >= 1)
3010 pBox->DrawRect( Rectangle( x, y, x, y+height-1 ) );
3011 y++; x++;
3012 height -= 2;
3016 if( bFillColor )
3017 pBox->SetFillColor( aOldFillColor );
3018 else
3019 pBox->SetFillColor();
3020 if( bLineColor )
3021 pBox->SetLineColor( aOldLineColor );
3022 else
3023 pBox->SetLineColor( );
3026 void ToolBox::ImplDrawToolArrow( ToolBox* pBox, long nX, long nY, sal_Bool bBlack, sal_Bool bColTransform,
3027 sal_Bool bLeft, sal_Bool bTop, long nSize )
3029 Color aOldFillColor = pBox->GetFillColor();
3030 WindowAlign eAlign = pBox->meAlign;
3031 long n = 0;
3032 long nHalfSize;
3033 if ( bLeft )
3034 eAlign = WINDOWALIGN_RIGHT;
3035 else if ( bTop )
3036 eAlign = WINDOWALIGN_BOTTOM;
3038 nHalfSize = nSize/2;
3040 switch ( eAlign )
3042 case WINDOWALIGN_LEFT:
3043 if ( bBlack )
3044 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3045 while ( n <= nHalfSize )
3047 pBox->DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
3048 n++;
3050 if ( bBlack )
3052 pBox->SetFillColor( aOldFillColor );
3053 n = 1;
3054 while ( n < nHalfSize )
3056 pBox->DrawRect( Rectangle( nX+n, nY+1+n, nX+n, nY+nSize-1-n ) );
3057 n++;
3060 break;
3061 case WINDOWALIGN_TOP:
3062 if ( bBlack )
3063 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3064 while ( n <= nHalfSize )
3066 pBox->DrawRect( Rectangle( nX+n, nY+n, nX+nSize-n, nY+n ) );
3067 n++;
3069 if ( bBlack )
3071 pBox->SetFillColor( aOldFillColor );
3072 n = 1;
3073 while ( n < nHalfSize )
3075 pBox->DrawRect( Rectangle( nX+1+n, nY+n, nX+nSize-1-n, nY+n ) );
3076 n++;
3079 break;
3080 case WINDOWALIGN_RIGHT:
3081 if ( bBlack )
3082 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3083 while ( n <= nHalfSize )
3085 pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+n, nX+nHalfSize-n, nY+nSize-n ) );
3086 n++;
3088 if ( bBlack )
3090 pBox->SetFillColor( aOldFillColor );
3091 n = 1;
3092 while ( n < nHalfSize )
3094 pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+1+n, nX+nHalfSize-n, nY+nSize-1-n ) );
3095 n++;
3098 break;
3099 case WINDOWALIGN_BOTTOM:
3100 if ( bBlack )
3101 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3102 while ( n <= nHalfSize )
3104 pBox->DrawRect( Rectangle( nX+n, nY+nHalfSize-n, nX+nSize-n, nY+nHalfSize-n ) );
3105 n++;
3107 if ( bBlack )
3109 pBox->SetFillColor( aOldFillColor );
3110 n = 1;
3111 while ( n < nHalfSize )
3113 pBox->DrawRect( Rectangle( nX+1+n, nY+nHalfSize-n, nX+nSize-1-n, nY+nHalfSize-n ) );
3114 n++;
3117 break;
3121 // -----------------------------------------------------------------------
3123 void ToolBox::ImplDrawMenubutton( ToolBox *pThis, sal_Bool bHighlight )
3125 if( !pThis->mpData->maMenubuttonItem.maRect.IsEmpty() )
3127 // #i53937# paint menu button only if necessary
3128 if( !pThis->ImplHasClippedItems() )
3129 return;
3131 // execute pending paint requests
3132 ImplCheckUpdate( pThis );
3134 sal_Bool bFillColor = pThis->IsFillColor();
3135 sal_Bool bLineColor = pThis->IsLineColor();
3136 Color aOldFillCol = pThis->GetFillColor();
3137 Color aOldLineCol = pThis->GetLineColor();
3139 // draw the 'more' indicator / button (>>)
3140 ImplErase( pThis, pThis->mpData->maMenubuttonItem.maRect, bHighlight );
3142 if( bHighlight )
3143 ImplDrawButton( pThis, pThis->mpData->maMenubuttonItem.maRect, 2, sal_False, sal_True, sal_False );
3145 if( pThis->ImplHasClippedItems() )
3146 ImplDrawMoreIndicator( pThis, pThis->mpData->maMenubuttonItem.maRect, sal_True, !pThis->mbHorz );
3148 // store highlight state
3149 pThis->mpData->mbMenubuttonSelected = bHighlight;
3151 // restore colors
3152 if( bFillColor )
3153 pThis->SetFillColor( aOldFillCol );
3154 else
3155 pThis->SetFillColor();
3156 if( bLineColor )
3157 pThis->SetLineColor( aOldLineCol );
3158 else
3159 pThis->SetLineColor();
3163 // -----------------------------------------------------------------------
3165 void ToolBox::ImplDrawSpin( sal_Bool bUpperIn, sal_Bool bLowerIn )
3167 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3169 sal_Bool bTmpUpper;
3170 sal_Bool bTmpLower;
3172 if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() )
3173 return;
3175 if ( mnCurLine > 1 )
3176 bTmpUpper = sal_True;
3177 else
3178 bTmpUpper = sal_False;
3180 if ( mnCurLine+mnVisLines-1 < mnCurLines )
3181 bTmpLower = sal_True;
3182 else
3183 bTmpLower = sal_False;
3185 if ( !IsEnabled() )
3187 bTmpUpper = sal_False;
3188 bTmpLower = sal_False;
3191 ImplDrawSpinButton( this, maUpperRect, maLowerRect,
3192 bUpperIn, bLowerIn, bTmpUpper, bTmpLower, !mbHorz );
3195 // -----------------------------------------------------------------------
3197 void ToolBox::ImplDrawNext( sal_Bool bIn )
3199 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3201 if ( maNextToolRect.IsEmpty() )
3202 return;
3204 DecorationView aDecoView( this );
3206 // Button malen
3207 long nX = SMALLBUTTON_OFF_NORMAL_X;
3208 long nY = SMALLBUTTON_OFF_NORMAL_Y;
3209 sal_uInt16 nStyle = 0;
3210 if ( bIn == 1 )
3212 nStyle |= BUTTON_DRAW_PRESSED;
3213 nX = SMALLBUTTON_OFF_PRESSED_X;
3214 nY = SMALLBUTTON_OFF_PRESSED_Y;
3216 aDecoView.DrawButton( maNextToolRect, nStyle );
3218 // Inhalt ausgeben
3219 sal_Bool bLeft = sal_False;
3220 sal_Bool bTop = sal_False;
3221 if ( mbHorz )
3223 bLeft = sal_True;
3224 nX += (maNextToolRect.GetWidth()-6)/2-4;
3225 nY += (maNextToolRect.GetHeight()-6)/2-6;
3227 else
3229 bTop = sal_True;
3230 nY += (maNextToolRect.GetHeight()-6)/2-4;
3231 nX += (maNextToolRect.GetWidth()-6)/2-6;
3234 nX += maNextToolRect.Left();
3235 nY += maNextToolRect.Top();
3236 SetLineColor();
3237 SetFillColor( COL_LIGHTBLUE );
3238 ImplDrawToolArrow( this, nX, nY, sal_True, sal_False, bLeft, bTop, 10 );
3241 // -----------------------------------------------------------------------
3243 void ToolBox::ImplDrawSeparator( sal_uInt16 nPos, Rectangle rRect )
3245 bool bNativeOk = false;
3246 ImplToolItem* pItem = &mpData->m_aItems[nPos];
3248 ControlPart nPart = IsHorizontal() ? PART_SEPARATOR_VERT : PART_SEPARATOR_HORZ;
3249 if( IsNativeControlSupported( CTRL_TOOLBAR, nPart ) )
3251 ImplControlValue aControlValue;
3252 ControlState nState = 0;
3253 bNativeOk = DrawNativeControl( CTRL_TOOLBAR, nPart,
3254 rRect, nState, aControlValue, rtl::OUString() );
3257 /* Draw the widget only if it can't be drawn natively. */
3258 if( !bNativeOk )
3260 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3261 ImplToolItem* pTempItem = &mpData->m_aItems[nPos-1];
3263 // no separator before or after windows or at breaks
3264 if ( pTempItem && !pTempItem->mbShowWindow && nPos < mpData->m_aItems.size()-1 )
3266 pTempItem = &mpData->m_aItems[nPos+1];
3267 if ( !pTempItem->mbShowWindow && !pTempItem->mbBreak )
3269 long nCenterPos, nSlim;
3270 SetLineColor( rStyleSettings.GetSeparatorColor() );
3271 if ( IsHorizontal() )
3273 nSlim = (pItem->maRect.Bottom() - pItem->maRect.Top ()) / 4;
3274 nCenterPos = pItem->maRect.Center().X();
3275 DrawLine( Point( nCenterPos, pItem->maRect.Top() + nSlim ),
3276 Point( nCenterPos, pItem->maRect.Bottom() - nSlim ) );
3278 else
3280 nSlim = (pItem->maRect.Right() - pItem->maRect.Left ()) / 4;
3281 nCenterPos = pItem->maRect.Center().Y();
3282 DrawLine( Point( pItem->maRect.Left() + nSlim, nCenterPos ),
3283 Point( pItem->maRect.Right() - nSlim, nCenterPos ) );
3290 // -----------------------------------------------------------------------
3292 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bEnabled, sal_Bool bIsWindow )
3294 // draws toolbar button background either native or using a coloured selection
3295 // if bIsWindow is sal_True, the corresponding item is a control and only a selection border will be drawn
3297 sal_Bool bNativeOk = sal_False;
3298 if( !bIsWindow && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
3300 ImplControlValue aControlValue;
3301 ControlState nState = 0;
3303 if ( highlight == 1 ) nState |= CTRL_STATE_PRESSED;
3304 if ( highlight == 2 ) nState |= CTRL_STATE_ROLLOVER;
3305 if ( bEnabled ) nState |= CTRL_STATE_ENABLED;
3307 aControlValue.setTristateVal( bChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
3310 bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
3311 rRect, nState, aControlValue, rtl::OUString() );
3314 if( !bNativeOk )
3315 pThis->DrawSelectionBackground( rRect, bIsWindow ? 3 : highlight, bChecked, sal_True, bIsWindow, 2, NULL, NULL );
3318 void ToolBox::ImplDrawItem( sal_uInt16 nPos, sal_uInt16 nHighlight, sal_Bool bPaint, sal_Bool bLayout )
3320 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3322 if( nPos >= mpData->m_aItems.size() )
3323 return;
3325 // execute pending paint requests
3326 ImplCheckUpdate( this );
3328 ImplDisableFlatButtons();
3330 SetFillColor();
3332 ImplToolItem* pItem = &mpData->m_aItems[nPos];
3333 MetricVector* pVector = bLayout ? &mpData->m_pLayoutData->m_aUnicodeBoundRects : NULL;
3334 String* pDisplayText = bLayout ? &mpData->m_pLayoutData->m_aDisplayText : NULL;
3336 if(!pItem->mbEnabled)
3337 nHighlight = 0;
3339 // if the rectangle is outside visible area
3340 if ( pItem->maRect.IsEmpty() )
3341 return;
3343 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3345 // no gradient background for items that have a popup open
3346 sal_Bool bHasOpenPopup = (mpFloatWin != NULL) && (mnDownItemId==pItem->mnId);
3348 sal_Bool bHighContrastWhite = sal_False;
3349 // check the face color as highcontrast indicator
3350 // because the toolbox itself might have a gradient
3351 if( rStyleSettings.GetFaceColor() == Color( COL_WHITE ) )
3352 bHighContrastWhite = sal_True;
3354 // Compute buttons area.
3355 Size aBtnSize = pItem->maRect.GetSize();
3356 if( ImplGetSVData()->maNWFData.mbToolboxDropDownSeparate )
3358 // separate button not for dropdown only where the whole button is painted
3359 if ( pItem->mnBits & TIB_DROPDOWN &&
3360 ((pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY) )
3362 Rectangle aArrowRect = pItem->GetDropDownRect( mbHorz );
3363 if( aArrowRect.Top() == pItem->maRect.Top() ) // dropdown arrow on right side
3364 aBtnSize.Width() -= aArrowRect.GetWidth();
3365 else // dropdown arrow on bottom side
3366 aBtnSize.Height() -= aArrowRect.GetHeight();
3370 /* Compute the button/separator rectangle here, we'll need it for
3371 * both the buttons and the separators. */
3372 Rectangle aButtonRect( pItem->maRect.TopLeft(), aBtnSize );
3373 long nOffX = SMALLBUTTON_OFF_NORMAL_X;
3374 long nOffY = SMALLBUTTON_OFF_NORMAL_Y;
3375 long nImageOffX = 0;
3376 long nImageOffY = 0;
3377 sal_uInt16 nStyle = 0;
3379 // draw separators in flat style only
3380 if ( !bLayout &&
3381 (mnOutStyle & TOOLBOX_STYLE_FLAT) &&
3382 (pItem->meType == TOOLBOXITEM_SEPARATOR) &&
3383 nPos > 0
3386 ImplDrawSeparator( nPos, aButtonRect );
3389 // do nothing if item is no button or will be displayed as window
3390 if ( (pItem->meType != TOOLBOXITEM_BUTTON) ||
3391 (pItem->mbShowWindow && !mbCustomizeMode) )
3392 return;
3394 // we need a TBDragMananger to draw the configuration item
3395 ImplTBDragMgr* pMgr;
3396 if ( pItem->mnId == mnConfigItem )
3398 pMgr = ImplGetTBDragMgr();
3399 pMgr->HideDragRect();
3401 else
3402 pMgr = NULL;
3404 // during configuration mode visible windows will be drawn in a special way
3405 if ( mbCustomizeMode && pItem->mbShowWindow )
3407 Font aOldFont = GetFont();
3408 Color aOldTextColor = GetTextColor();
3410 SetZoomedPointFont( rStyleSettings.GetAppFont() );
3411 SetLineColor( Color( COL_BLACK ) );
3412 SetFillColor( rStyleSettings.GetFieldColor() );
3413 SetTextColor( rStyleSettings.GetFieldTextColor() );
3414 if( !bLayout )
3415 DrawRect( pItem->maRect );
3417 Size aSize( GetCtrlTextWidth( pItem->maText ), GetTextHeight() );
3418 Point aPos( pItem->maRect.Left()+2, pItem->maRect.Top() );
3419 aPos.Y() += (pItem->maRect.GetHeight()-aSize.Height())/2;
3420 sal_Bool bClip;
3421 if ( (aSize.Width() > pItem->maRect.GetWidth()-2) ||
3422 (aSize.Height() > pItem->maRect.GetHeight()-2) )
3424 bClip = sal_True;
3425 Rectangle aTempRect( pItem->maRect.Left()+1, pItem->maRect.Top()+1,
3426 pItem->maRect.Right()-1, pItem->maRect.Bottom()-1 );
3427 Region aTempRegion( aTempRect );
3428 SetClipRegion( aTempRegion );
3430 else
3431 bClip = sal_False;
3432 if( bLayout )
3434 mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
3435 mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3436 mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3438 DrawCtrlText( aPos, pItem->maText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
3439 if ( bClip )
3440 SetClipRegion();
3441 SetFont( aOldFont );
3442 SetTextColor( aOldTextColor );
3444 // draw Config-Frame if required
3445 if ( pMgr && !bLayout)
3446 pMgr->UpdateDragRect();
3447 return;
3450 if ( pItem->meState == STATE_CHECK )
3452 nStyle |= BUTTON_DRAW_CHECKED;
3454 else if ( pItem->meState == STATE_DONTKNOW )
3456 nStyle |= BUTTON_DRAW_DONTKNOW;
3458 if ( nHighlight == 1 )
3460 nStyle |= BUTTON_DRAW_PRESSED;
3463 if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
3465 nOffX = OUTBUTTON_OFF_NORMAL_X;
3466 nOffY = OUTBUTTON_OFF_NORMAL_Y;
3467 if ( nHighlight != 0 )
3469 nOffX++;
3470 nOffY++;
3474 if( ! bLayout )
3476 if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
3478 if ( (pItem->meState != STATE_NOCHECK) || !bPaint )
3480 ImplErase( this, pItem->maRect, nHighlight != 0, bHasOpenPopup );
3483 else
3485 if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
3486 ImplDrawOutButton( this, aButtonRect, nStyle );
3487 else
3489 DecorationView aDecoView( this );
3490 aDecoView.DrawButton( aButtonRect, nStyle );
3495 nOffX += pItem->maRect.Left();
3496 nOffY += pItem->maRect.Top();
3498 // determine what has to be drawn on the button: image, text or both
3499 sal_Bool bImage;
3500 sal_Bool bText;
3501 ButtonType tmpButtonType = determineButtonType( pItem, meButtonType ); // default to toolbox setting
3502 pItem->DetermineButtonDrawStyle( tmpButtonType, bImage, bText );
3504 // compute output values
3505 long nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE;
3506 long nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE;
3507 Size aImageSize;
3508 Size aTxtSize;
3510 if ( bText )
3512 aTxtSize.Width() = GetCtrlTextWidth( pItem->maText );
3513 aTxtSize.Height() = GetTextHeight();
3516 if ( bImage && ! bLayout )
3518 const Image* pImage;
3519 if ( (nHighlight != 0) && (!(pItem->maHighImage)) == sal_False )
3520 pImage = &(pItem->maHighImage);
3521 else
3522 pImage = &(pItem->maImage);
3524 aImageSize = pImage->GetSizePixel();
3526 // determine drawing flags
3527 sal_uInt16 nImageStyle = 0;
3529 if ( !pItem->mbEnabled || !IsEnabled() )
3530 nImageStyle |= IMAGE_DRAW_DISABLE;
3532 // #i35563# the dontknow state indicates different states at the same time
3533 // which should not be rendered disabled but normal
3535 // draw the image
3536 nImageOffX = nOffX;
3537 nImageOffY = nOffY;
3538 if ( (pItem->mnBits & (TIB_LEFT|TIB_DROPDOWN)) || bText )
3540 // left align also to leave space for drop down arrow
3541 // and when drawing text+image
3542 // just center in y, except for vertical (ie rotated text)
3543 if( mbHorz || !bText )
3544 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3546 else
3548 nImageOffX += (nBtnWidth-aImageSize.Width())/2;
3549 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3551 if ( nHighlight != 0 || (pItem->meState == STATE_CHECK) )
3553 if( bHasOpenPopup )
3554 ImplDrawFloatwinBorder( pItem );
3555 else
3556 ImplDrawButton( this, aButtonRect, nHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? sal_True : sal_False );
3558 if( nHighlight != 0 )
3560 if( bHighContrastWhite )
3561 nImageStyle |= IMAGE_DRAW_COLORTRANSFORM;
3564 DrawImage( Point( nImageOffX, nImageOffY ), *pImage, nImageStyle );
3567 // draw the text
3568 sal_Bool bRotate = sal_False;
3569 if ( bText )
3571 long nTextOffX = nOffX;
3572 long nTextOffY = nOffY;
3574 // rotate text when vertically docked
3575 Font aOldFont = GetFont();
3576 if( pItem->mbVisibleText && !ImplIsFloatingMode() &&
3577 ((meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT)) )
3579 bRotate = sal_True;
3581 Font aRotateFont = aOldFont;
3582 aRotateFont.SetOrientation( 2700 );
3584 // center horizontally
3585 nTextOffX += aTxtSize.Height();
3586 nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
3588 // add in image offset
3589 if( bImage )
3590 nTextOffY = nImageOffY + aImageSize.Height() + TB_IMAGETEXTOFFSET;
3592 SetFont( aRotateFont );
3594 else
3596 // center vertically
3597 nTextOffY += (nBtnHeight-aTxtSize.Height())/2;
3599 // add in image offset
3600 if( bImage )
3601 nTextOffX = nImageOffX + aImageSize.Width() + TB_IMAGETEXTOFFSET;
3604 // draw selection only if not already drawn during image output (see above)
3605 if ( !bLayout && !bImage && (nHighlight != 0 || (pItem->meState == STATE_CHECK) ) )
3607 if( bHasOpenPopup )
3608 ImplDrawFloatwinBorder( pItem );
3609 else
3610 ImplDrawButton( this, pItem->maRect, nHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? sal_True : sal_False );
3613 sal_uInt16 nTextStyle = 0;
3614 if ( !pItem->mbEnabled )
3615 nTextStyle |= TEXT_DRAW_DISABLE;
3616 if( bLayout )
3618 mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
3619 mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3620 mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3622 DrawCtrlText( Point( nTextOffX, nTextOffY ), pItem->maText,
3623 0, STRING_LEN, nTextStyle, pVector, pDisplayText );
3624 if ( bRotate )
3625 SetFont( aOldFont );
3628 if( bLayout )
3629 return;
3631 // paint optional drop down arrow
3632 if ( pItem->mnBits & TIB_DROPDOWN )
3634 Rectangle aDropDownRect( pItem->GetDropDownRect( mbHorz ) );
3635 sal_Bool bSetColor = sal_True;
3636 if ( !pItem->mbEnabled || !IsEnabled() )
3638 bSetColor = sal_False;
3639 SetFillColor( rStyleSettings.GetShadowColor() );
3642 // dropdown only will be painted without inner border
3643 if( (pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY )
3645 ImplErase( this, aDropDownRect, nHighlight != 0, bHasOpenPopup );
3647 if( nHighlight != 0 || (pItem->meState == STATE_CHECK) )
3649 if( bHasOpenPopup )
3650 ImplDrawFloatwinBorder( pItem );
3651 else
3652 ImplDrawButton( this, aDropDownRect, nHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), sal_False );
3655 ImplDrawDropdownArrow( this, aDropDownRect, bSetColor, bRotate );
3658 // draw config-frame if required
3659 if ( pMgr )
3660 pMgr->UpdateDragRect();
3663 // -----------------------------------------------------------------------
3665 void ToolBox::ImplDrawFloatwinBorder( ImplToolItem* pItem )
3667 if ( !pItem->maRect.IsEmpty() )
3669 Rectangle aRect( mpFloatWin->ImplGetItemEdgeClipRect() );
3670 aRect.SetPos( AbsoluteScreenToOutputPixel( aRect.TopLeft() ) );
3671 SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
3672 Point p1, p2;
3674 p1 = pItem->maRect.TopLeft();
3675 p1.X()++;
3676 p2 = pItem->maRect.TopRight();
3677 p2.X()--;
3678 DrawLine( p1, p2);
3679 p1 = pItem->maRect.BottomLeft();
3680 p1.X()++;
3681 p2 = pItem->maRect.BottomRight();
3682 p2.X()--;
3683 DrawLine( p1, p2);
3685 p1 = pItem->maRect.TopLeft();
3686 p1.Y()++;
3687 p2 = pItem->maRect.BottomLeft();
3688 p2.Y()--;
3689 DrawLine( p1, p2);
3690 p1 = pItem->maRect.TopRight();
3691 p1.Y()++;
3692 p2 = pItem->maRect.BottomRight();
3693 p2.Y()--;
3694 DrawLine( p1, p2);
3696 //DrawRect( pItem->maRect );
3700 void ToolBox::ImplFloatControl( sal_Bool bStart, FloatingWindow* pFloatWindow )
3702 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3704 if ( bStart )
3706 mpFloatWin = pFloatWindow;
3708 // redraw item, to trigger drawing of a special border
3709 ImplDrawItem( mnCurPos, 1 );
3711 mbDrag = sal_False;
3712 EndTracking();
3713 ReleaseMouse();
3715 else
3717 mpFloatWin = NULL;
3719 // if focus is still in this toolbox, then the floater was opened by keyboard
3720 // draw current item with highlight and keep old state
3721 sal_Bool bWasKeyboardActivate = mpData->mbDropDownByKeyboard;
3724 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3725 ImplDrawItem( mnCurPos, bWasKeyboardActivate ? 2 : 0 );
3726 Deactivate();
3728 if( !bWasKeyboardActivate )
3730 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3731 mnCurItemId = 0;
3732 mnHighItemId = 0;
3734 mnDownItemId = 0;
3739 // -----------------------------------------------------------------------
3741 void ToolBox::ShowLine( sal_Bool bNext )
3743 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3745 mbFormat = sal_True;
3747 if ( mpData->mbPageScroll )
3749 sal_uInt16 delta = mnVisLines;
3750 if ( bNext )
3752 mnCurLine = mnCurLine + delta;
3753 if ( mnCurLine+mnVisLines-1 > mnCurLines )
3754 mnCurLine = mnCurLines - mnVisLines+1;
3756 else
3758 if( mnCurLine >= delta+1 )
3759 mnCurLine = mnCurLine - delta;
3760 else
3761 mnCurLine = 1;
3764 else
3766 if ( bNext )
3767 mnCurLine++;
3768 else
3769 mnCurLine--;
3772 ImplFormat();
3775 // -----------------------------------------------------------------------
3777 sal_Bool ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, sal_Bool bRepeat )
3779 Point aMousePos = rMEvt.GetPosPixel();
3781 // ToolBox active?
3782 if ( mbDrag && mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3784 // is the cursor over the item?
3785 ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
3786 if ( pItem->maRect.IsInside( aMousePos ) )
3788 if ( !mnCurItemId )
3790 ImplDrawItem( mnCurPos, 1 );
3791 mnCurItemId = pItem->mnId;
3792 Highlight();
3795 if ( (pItem->mnBits & TIB_REPEAT) && bRepeat )
3796 Select();
3798 else
3800 if ( mnCurItemId )
3802 ImplDrawItem( mnCurPos );
3803 mnCurItemId = 0;
3804 ImplDrawItem( mnCurPos );
3805 Highlight();
3809 return sal_True;
3812 if ( mbUpper )
3814 sal_Bool bNewIn = maUpperRect.IsInside( aMousePos );
3815 if ( bNewIn != mbIn )
3817 mbIn = bNewIn;
3818 ImplDrawSpin( mbIn, sal_False );
3820 return sal_True;
3823 if ( mbLower )
3825 sal_Bool bNewIn = maLowerRect.IsInside( aMousePos );
3826 if ( bNewIn != mbIn )
3828 mbIn = bNewIn;
3829 ImplDrawSpin( sal_False, mbIn );
3831 return sal_True;
3834 if ( mbNextTool )
3836 sal_Bool bNewIn = maNextToolRect.IsInside( aMousePos );
3837 if ( bNewIn != mbIn )
3839 mbIn = bNewIn;
3840 ImplDrawNext( mbIn );
3842 return sal_True;
3845 return sal_False;
3848 // -----------------------------------------------------------------------
3850 sal_Bool ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, sal_Bool bCancel )
3852 ImplDisableFlatButtons();
3854 // stop eventual running dropdown timer
3855 if( mnCurPos < mpData->m_aItems.size() &&
3856 (mpData->m_aItems[mnCurPos].mnBits & TIB_DROPDOWN ) )
3858 mpData->maDropdownTimer.Stop();
3861 if ( mbDrag || mbSelection )
3863 // set mouse data if in selection mode, as then
3864 // the MouseButtonDown handler cannot be called
3865 if ( mbSelection )
3867 mnMouseClicks = rMEvt.GetClicks();
3868 mnMouseModifier = rMEvt.GetModifier();
3871 Deactivate();
3873 if ( mbDrag )
3874 mbDrag = sal_False;
3875 else
3877 mbSelection = sal_False;
3878 if ( mnCurPos == TOOLBOX_ITEM_NOTFOUND )
3879 return sal_True;
3882 // has mouse been released on top of item?
3883 if( mnCurPos < mpData->m_aItems.size() )
3885 ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
3886 if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) )
3888 mnCurItemId = pItem->mnId;
3889 if ( !bCancel )
3891 // execute AutoCheck if required
3892 if ( pItem->mnBits & TIB_AUTOCHECK )
3894 if ( pItem->mnBits & TIB_RADIOCHECK )
3896 if ( pItem->meState != STATE_CHECK )
3897 SetItemState( pItem->mnId, STATE_CHECK );
3899 else
3901 if ( pItem->meState != STATE_CHECK )
3902 pItem->meState = STATE_CHECK;
3903 else
3904 pItem->meState = STATE_NOCHECK;
3908 // do not call Select when Repeat is active, as in this
3909 // case that was triggered already in MouseButtonDown
3910 if ( !(pItem->mnBits & TIB_REPEAT) )
3912 // prevent from being destroyed in the select handler
3913 ImplDelData aDelData;
3914 ImplAddDel( &aDelData );
3915 Select();
3916 if ( aDelData.IsDelete() )
3917 return sal_True;
3918 ImplRemoveDel( &aDelData );
3923 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3926 // Items not destroyed, in Select handler
3927 if ( mnCurItemId )
3929 sal_uInt16 nHighlight;
3930 if ( (mnCurItemId == mnHighItemId) && (mnOutStyle & TOOLBOX_STYLE_FLAT) )
3931 nHighlight = 2;
3932 else
3933 nHighlight = 0;
3934 // Get current pos for the case that items are inserted/removed
3935 // in the toolBox
3936 mnCurPos = GetItemPos( mnCurItemId );
3937 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3939 ImplDrawItem( mnCurPos, nHighlight );
3940 Flush();
3946 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3947 mnCurItemId = 0;
3948 mnDownItemId = 0;
3949 mnMouseClicks = 0;
3950 mnMouseModifier = 0;
3951 return sal_True;
3953 else if ( mbUpper || mbLower )
3955 if ( mbIn )
3956 ShowLine( !mbUpper );
3957 mbUpper = sal_False;
3958 mbLower = sal_False;
3959 mbIn = sal_False;
3960 ImplDrawSpin( sal_False, sal_False );
3961 return sal_True;
3963 else if ( mbNextTool )
3965 mbNextTool = sal_False;
3966 mbIn = sal_False;
3967 ImplDrawNext( sal_False );
3968 NextToolBox();
3969 return sal_True;
3972 return sal_False;
3975 // -----------------------------------------------------------------------
3977 void ToolBox::MouseMove( const MouseEvent& rMEvt )
3979 // pressing a modifier generates synthetic mouse moves
3980 // ignore it if keyboard selection is acive
3981 if( HasFocus() && ( rMEvt.GetMode() & MOUSE_MODIFIERCHANGED ) )
3982 return;
3984 if ( ImplHandleMouseMove( rMEvt ) )
3985 return;
3987 ImplDisableFlatButtons();
3989 Point aMousePos = rMEvt.GetPosPixel();
3991 // only highlight when the focus is not inside a child window of a toolbox
3992 // eg, in a edit control
3993 // and do not hilight when focus is in a different toolbox
3994 sal_Bool bDrawHotSpot = sal_True;
3995 Window *pWin = Application::GetFocusWindow();
3996 if( pWin && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this )
3997 bDrawHotSpot = sal_False;
3999 if ( mbSelection && bDrawHotSpot )
4001 sal_uInt16 i = 0;
4002 sal_uInt16 nNewPos = TOOLBOX_ITEM_NOTFOUND;
4004 // search the item that has been clicked
4005 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4006 while ( it != mpData->m_aItems.end() )
4008 // if the mouse position is in this item,
4009 // we can stop the search
4010 if ( it->maRect.IsInside( aMousePos ) )
4012 // select it if it is a button
4013 if ( it->meType == TOOLBOXITEM_BUTTON )
4015 // if button is disabled, do not
4016 // change it
4017 if ( !it->mbEnabled || it->mbShowWindow )
4018 nNewPos = mnCurPos;
4019 else
4020 nNewPos = i;
4023 break;
4026 i++;
4027 ++it;
4030 // was a new entery selected ?
4031 // don't change selection if keyboard selection is active and
4032 // mouse leaves the toolbox
4033 if ( nNewPos != mnCurPos && !( HasFocus() && nNewPos == TOOLBOX_ITEM_NOTFOUND ) )
4035 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4037 ImplDrawItem( mnCurPos );
4038 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( mnCurPos ) );
4041 mnCurPos = nNewPos;
4042 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4044 mnCurItemId = mnHighItemId = it->mnId;
4045 ImplDrawItem( mnCurPos, 2 ); // always use shadow effect (2)
4047 else
4048 mnCurItemId = mnHighItemId = 0;
4050 Highlight();
4052 return;
4055 if ( mbDragging )
4057 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4058 pMgr->Dragging( aMousePos );
4059 return;
4062 PointerStyle eStyle = POINTER_ARROW;
4064 // change mouse cursor over drag area
4065 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
4066 if( pWrapper && pWrapper->GetDragArea().IsInside( rMEvt.GetPosPixel() ) )
4067 eStyle = POINTER_MOVE;
4069 if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4071 if ( rMEvt.GetMode() & MOUSE_SIMPLEMOVE )
4073 sal_uInt16 nLinePtr = ImplTestLineSize( this, rMEvt.GetPosPixel() );
4074 if ( nLinePtr & DOCK_LINEHSIZE )
4076 if ( meAlign == WINDOWALIGN_LEFT )
4077 eStyle = POINTER_WINDOW_ESIZE;
4078 else
4079 eStyle = POINTER_WINDOW_WSIZE;
4081 else if ( nLinePtr & DOCK_LINEVSIZE )
4083 if ( meAlign == WINDOWALIGN_TOP )
4084 eStyle = POINTER_WINDOW_SSIZE;
4085 else
4086 eStyle = POINTER_WINDOW_NSIZE;
4091 if ( (eStyle == POINTER_ARROW) && mbCustomizeMode )
4093 // search the item which was clicked
4094 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4095 while ( it != mpData->m_aItems.end() )
4097 // show resize pointer if it is a customize window
4098 if ( it->mbShowWindow )
4100 if ( it->maRect.IsInside( aMousePos ) )
4102 if ( it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X() )
4103 eStyle = POINTER_HSIZEBAR;
4104 break;
4108 ++it;
4112 if ( bDrawHotSpot && ( ((eStyle == POINTER_ARROW) && (mnOutStyle & TOOLBOX_STYLE_HANDPOINTER)) ||
4113 (mnOutStyle & TOOLBOX_STYLE_FLAT) || !mnOutStyle ) )
4115 sal_Bool bClearHigh = sal_True;
4116 if ( !rMEvt.IsLeaveWindow() && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4118 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4119 while ( it != mpData->m_aItems.end() )
4121 if ( it->maRect.IsInside( aMousePos ) )
4123 if ( (it->meType == TOOLBOXITEM_BUTTON) && it->mbEnabled )
4125 if ( !mnOutStyle || (mnOutStyle & TOOLBOX_STYLE_FLAT) )
4127 bClearHigh = sal_False;
4128 if ( mnHighItemId != it->mnId )
4130 sal_uInt16 nTempPos = sal::static_int_cast<sal_uInt16>(it - mpData->m_aItems.begin());
4131 if ( mnHighItemId )
4133 ImplHideFocus();
4134 sal_uInt16 nPos = GetItemPos( mnHighItemId );
4135 ImplDrawItem( nPos );
4136 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
4138 if ( mpData->mbMenubuttonSelected )
4140 // remove highlight from menubutton
4141 ImplDrawMenubutton( this, sal_False );
4143 mnHighItemId = it->mnId;
4144 ImplDrawItem( nTempPos, 2 );
4145 ImplShowFocus();
4146 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
4149 if ( mnOutStyle & TOOLBOX_STYLE_HANDPOINTER )
4150 eStyle = POINTER_REFHAND;
4152 break;
4155 ++it;
4159 // only clear highlight when focus is not in toolbar
4160 sal_Bool bMenuButtonHit = mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) && ImplHasClippedItems();
4161 if ( bClearHigh || bMenuButtonHit )
4163 if ( !bMenuButtonHit && mpData->mbMenubuttonSelected )
4165 // remove highlight from menubutton
4166 ImplDrawMenubutton( this, sal_False );
4169 if( mnHighItemId )
4171 sal_uInt16 nClearPos = GetItemPos( mnHighItemId );
4172 if ( nClearPos != TOOLBOX_ITEM_NOTFOUND )
4174 ImplDrawItem( nClearPos, (nClearPos == mnCurPos) ? 1 : 0 );
4175 if( nClearPos != mnCurPos )
4176 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nClearPos ) );
4178 ImplHideFocus();
4179 mnHighItemId = 0;
4182 if( bMenuButtonHit )
4184 ImplDrawMenubutton( this, sal_True );
4189 if ( meLastStyle != eStyle )
4191 meLastStyle = eStyle;
4192 Pointer aPtr( eStyle );
4193 SetPointer( aPtr );
4196 DockingWindow::MouseMove( rMEvt );
4199 // -----------------------------------------------------------------------
4201 void ToolBox::MouseButtonDown( const MouseEvent& rMEvt )
4203 // only trigger toolbox for left mouse button and when
4204 // we're not in normal operation
4205 if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4207 // call activate already here, as items could
4208 // be exchanged
4209 Activate();
4211 // update ToolBox here, such that user knows it
4212 if ( mbFormat )
4214 ImplFormat();
4215 Update();
4218 Point aMousePos = rMEvt.GetPosPixel();
4219 sal_uInt16 i = 0;
4220 sal_uInt16 nNewPos = TOOLBOX_ITEM_NOTFOUND;
4222 // search for item that was clicked
4223 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4224 while ( it != mpData->m_aItems.end() )
4226 // is this the item?
4227 if ( it->maRect.IsInside( aMousePos ) )
4229 // do nothing if it is a separator or
4230 // if the item has been disabled
4231 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
4232 (!it->mbShowWindow || mbCustomizeMode) )
4233 nNewPos = i;
4235 break;
4238 i++;
4239 ++it;
4242 // item found
4243 if ( nNewPos != TOOLBOX_ITEM_NOTFOUND )
4245 if ( mbCustomize )
4247 if ( rMEvt.IsMod2() || mbCustomizeMode )
4249 Deactivate();
4251 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4252 Rectangle aItemRect = GetItemRect( it->mnId );
4253 mnConfigItem = it->mnId;
4255 sal_Bool bResizeItem;
4256 if ( mbCustomizeMode && it->mbShowWindow &&
4257 (it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X()) )
4258 bResizeItem = sal_True;
4259 else
4260 bResizeItem = sal_False;
4261 pMgr->StartDragging( this, aMousePos, aItemRect, 0, bResizeItem );
4262 return;
4266 if ( !it->mbEnabled )
4268 Deactivate();
4269 return;
4273 // update actual data
4274 sal_uInt16 nTrackFlags = 0;
4275 mnCurPos = i;
4276 mnCurItemId = it->mnId;
4277 mnDownItemId = mnCurItemId;
4278 mnMouseClicks = rMEvt.GetClicks();
4279 mnMouseModifier = rMEvt.GetModifier();
4280 if ( it->mnBits & TIB_REPEAT )
4281 nTrackFlags |= STARTTRACK_BUTTONREPEAT;
4284 if ( mbSelection )
4286 ImplDrawItem( mnCurPos, 1 );
4287 Highlight();
4289 else
4291 // update bDrag here, as it is evaluated in the EndSelection
4292 mbDrag = sal_True;
4294 // on double-click: only call the handler, but do so before the button
4295 // is hit, as in the handler dragging
4296 // can be terminated
4297 if ( rMEvt.GetClicks() == 2 )
4298 DoubleClick();
4301 if ( mbDrag )
4303 ImplDrawItem( mnCurPos, 1 );
4304 Highlight();
4307 // was dropdown arrow pressed
4308 if( (it->mnBits & TIB_DROPDOWN) )
4310 if( ( (it->mnBits & TIB_DROPDOWNONLY) == TIB_DROPDOWNONLY) || it->GetDropDownRect( mbHorz ).IsInside( aMousePos ))
4312 // dropdownonly always triggers the dropdown handler, over the whole button area
4314 // the drop down arrow should not trigger the item action
4315 mpData->mbDropDownByKeyboard = sal_False;
4316 GetDropdownClickHdl().Call( this );
4318 // do not reset data if the dropdown handler opened a floating window
4319 // see ImplFloatControl()
4320 if( mpFloatWin == NULL )
4322 // no floater was opened
4323 Deactivate();
4324 ImplDrawItem( mnCurPos, 0 );
4326 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
4327 mnCurItemId = 0;
4328 mnDownItemId = 0;
4329 mnMouseClicks = 0;
4330 mnMouseModifier = 0;
4331 mnHighItemId = 0;
4333 return;
4335 else // activate long click timer
4336 mpData->maDropdownTimer.Start();
4340 // call Click handler
4341 if ( rMEvt.GetClicks() != 2 )
4342 Click();
4344 // also call Select handler at repeat
4345 if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
4346 Select();
4348 // if the actions was not aborted in Click handler
4349 if ( mbDrag )
4350 StartTracking( nTrackFlags );
4353 // if mouse was clicked over an item we
4354 // can abort here
4355 return;
4358 Deactivate();
4360 // menu button hit ?
4361 if( mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) && ImplHasClippedItems() )
4363 ExecuteCustomMenu();
4364 return;
4367 // check scroll- and next-buttons here
4368 if ( maUpperRect.IsInside( aMousePos ) )
4370 if ( mnCurLine > 1 )
4372 StartTracking();
4373 mbUpper = sal_True;
4374 mbIn = sal_True;
4375 ImplDrawSpin( sal_True, sal_False );
4377 return;
4379 if ( maLowerRect.IsInside( aMousePos ) )
4381 if ( mnCurLine+mnVisLines-1 < mnCurLines )
4383 StartTracking();
4384 mbLower = sal_True;
4385 mbIn = sal_True;
4386 ImplDrawSpin( sal_False, sal_True );
4388 return;
4390 if ( maNextToolRect.IsInside( aMousePos ) )
4392 StartTracking();
4393 mbNextTool = sal_True;
4394 mbIn = sal_True;
4395 ImplDrawNext( sal_True );
4396 return;
4399 // Linesizing testen
4400 if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4402 sal_uInt16 nLineMode = ImplTestLineSize( this, aMousePos );
4403 if ( nLineMode )
4405 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4407 // call handler, such that we can set the
4408 // dock rectangles
4409 StartDocking();
4411 Point aPos = GetParent()->OutputToScreenPixel( GetPosPixel() );
4412 Size aSize = GetSizePixel();
4413 aPos = ScreenToOutputPixel( aPos );
4415 // start dragging
4416 pMgr->StartDragging( this, aMousePos, Rectangle( aPos, aSize ),
4417 nLineMode, sal_False );
4418 return;
4422 // no item, then only click or double click
4423 if ( rMEvt.GetClicks() == 2 )
4424 DoubleClick();
4425 else
4426 Click();
4429 if ( !mbDrag && !mbSelection && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4430 DockingWindow::MouseButtonDown( rMEvt );
4433 // -----------------------------------------------------------------------
4435 void ToolBox::MouseButtonUp( const MouseEvent& rMEvt )
4437 if ( ImplHandleMouseButtonUp( rMEvt ) )
4438 return;
4440 if ( mbDragging && (rMEvt.IsLeft() || mbCommandDrag) )
4442 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4443 pMgr->EndDragging();
4444 return;
4446 mbCommandDrag = sal_False;
4448 DockingWindow::MouseButtonUp( rMEvt );
4451 // -----------------------------------------------------------------------
4453 void ToolBox::Tracking( const TrackingEvent& rTEvt )
4455 ImplDelData aDelData;
4456 ImplAddDel( &aDelData );
4458 if ( rTEvt.IsTrackingEnded() )
4459 ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() );
4460 else
4461 ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() );
4463 if ( aDelData.IsDelete() )
4464 // toolbox was deleted
4465 return;
4466 ImplRemoveDel( &aDelData );
4467 DockingWindow::Tracking( rTEvt );
4470 // -----------------------------------------------------------------------
4472 void ToolBox::Paint( const Rectangle& rPaintRect )
4474 if( mpData->mbIsPaintLocked )
4475 return;
4476 if ( rPaintRect == Rectangle( 0, 0, mnDX-1, mnDY-1 ) )
4477 mbFullPaint = sal_True;
4478 ImplFormat();
4479 mbFullPaint = sal_False;
4482 ImplDrawBackground( this, rPaintRect );
4484 if ( (mnWinStyle & WB_BORDER) && !ImplIsFloatingMode() )
4485 ImplDrawBorder( this );
4487 if( !ImplIsFloatingMode() )
4488 ImplDrawGrip( this );
4490 ImplDrawMenubutton( this, mpData->mbMenubuttonSelected );
4492 // draw SpinButtons
4493 if ( mnWinStyle & WB_SCROLL )
4495 if ( mnCurLines > mnLines )
4496 ImplDrawSpin( sal_False, sal_False );
4499 // draw NextButton
4500 ImplDrawNext( sal_False );
4502 // draw buttons
4503 sal_uInt16 nHighPos;
4504 if ( mnHighItemId )
4505 nHighPos = GetItemPos( mnHighItemId );
4506 else
4507 nHighPos = TOOLBOX_ITEM_NOTFOUND;
4509 sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
4510 for( sal_uInt16 i = 0; i < nCount; i++ )
4512 ImplToolItem* pItem = &mpData->m_aItems[i];
4514 // only draw when the rectangle is in the draw rectangle
4515 if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) )
4517 sal_uInt16 nHighlight = 0;
4518 if ( i == mnCurPos )
4519 nHighlight = 1;
4520 else if ( i == nHighPos )
4521 nHighlight = 2;
4522 ImplDrawItem( i, nHighlight );
4525 ImplShowFocus();
4528 // -----------------------------------------------------------------------
4530 void ToolBox::Move()
4532 DockingWindow::Move();
4535 // -----------------------------------------------------------------------
4537 void ToolBox::Resize()
4539 Size aSize = GetOutputSizePixel();
4540 // #i31422# some WindowManagers send (0,0) sizes when
4541 // switching virtual desktops - ignore this and avoid reformatting
4542 if( !aSize.Width() && !aSize.Height() )
4543 return;
4545 long nOldDX = mnDX;
4546 long nOldDY = mnDY;
4547 mnDX = aSize.Width();
4548 mnDY = aSize.Height();
4550 mnLastResizeDY = 0;
4552 // invalidate everything to have gradient backgrounds properly drawn
4553 Invalidate();
4555 // re-format or re-draw
4556 if ( mbScroll )
4558 if ( !mbFormat )
4560 mbFormat = sal_True;
4561 if( IsReallyVisible() )
4562 ImplFormat( sal_True );
4566 // redraw border
4567 if ( mnWinStyle & WB_BORDER )
4569 // as otherwise, when painting we might think we have to re-draw everything
4570 if ( mbFormat && IsReallyVisible() )
4571 Invalidate();
4572 else
4574 if ( mnRightBorder )
4576 if ( nOldDX > mnDX )
4577 Invalidate( Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) );
4578 else
4579 Invalidate( Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) );
4582 if ( mnBottomBorder )
4584 if ( nOldDY > mnDY )
4585 Invalidate( Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) );
4586 else
4587 Invalidate( Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) );
4593 // -----------------------------------------------------------------------
4594 const XubString& ToolBox::ImplGetHelpText( sal_uInt16 nItemId ) const
4596 ImplToolItem* pItem = ImplGetItem( nItemId );
4598 if ( pItem )
4600 if ( !pItem->maHelpText.Len() && ( !pItem->maHelpId.isEmpty() || pItem->maCommandStr.Len() ))
4602 Help* pHelp = Application::GetHelp();
4603 if ( pHelp )
4605 if ( pItem->maCommandStr.Len() )
4606 pItem->maHelpText = pHelp->GetHelpText( pItem->maCommandStr, this );
4607 if ( !pItem->maHelpText.Len() && !pItem->maHelpId.isEmpty() )
4608 pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
4612 return pItem->maHelpText;
4614 else
4615 return ImplGetSVEmptyStr();
4618 // -----------------------------------------------------------------------
4620 void ToolBox::RequestHelp( const HelpEvent& rHEvt )
4622 sal_uInt16 nItemId;
4623 Point aHelpPos;
4625 if( !rHEvt.KeyboardActivated() )
4627 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
4628 aHelpPos = rHEvt.GetMousePosPixel();
4630 else
4632 if( !mnHighItemId )
4633 return;
4634 else
4635 nItemId = mnHighItemId;
4636 Rectangle aRect( GetItemRect( nItemId ) );
4637 if( aRect.IsEmpty() )
4638 return;
4639 else
4640 aHelpPos = OutputToScreenPixel( aRect.Center() );
4643 if ( nItemId )
4645 if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4647 // get rectangle
4648 Rectangle aTempRect = GetItemRect( nItemId );
4649 Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4650 aTempRect.Left() = aPt.X();
4651 aTempRect.Top() = aPt.Y();
4652 aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4653 aTempRect.Right() = aPt.X();
4654 aTempRect.Bottom() = aPt.Y();
4656 // get text and display it
4657 XubString aStr = GetQuickHelpText( nItemId );
4658 const XubString& rHelpStr = GetHelpText( nItemId );
4659 if ( !aStr.Len() )
4660 aStr = MnemonicGenerator::EraseAllMnemonicChars( GetItemText( nItemId ) );
4661 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4663 if ( rHelpStr.Len() )
4664 aStr = rHelpStr;
4665 Help::ShowBalloon( this, aHelpPos, aTempRect, aStr );
4667 else
4668 Help::ShowQuickHelp( this, aTempRect, aStr, rHelpStr, QUICKHELP_CTRLTEXT );
4669 return;
4671 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
4673 String aCommand = GetItemCommand( nItemId );
4674 rtl::OString aHelpId( GetHelpId( nItemId ) );
4676 if ( aCommand.Len() || !aHelpId.isEmpty() )
4678 // If help is available then trigger it
4679 Help* pHelp = Application::GetHelp();
4680 if ( pHelp )
4682 if ( aCommand.Len() )
4683 pHelp->Start( aCommand, this );
4684 else if ( !aHelpId.isEmpty() )
4685 pHelp->Start( rtl::OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), this );
4687 return;
4691 else if ( maNextToolRect.IsInside( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ) )
4693 if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4695 // get rectangle
4696 Rectangle aTempRect = maNextToolRect;
4697 Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4698 aTempRect.Left() = aPt.X();
4699 aTempRect.Top() = aPt.Y();
4700 aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4701 aTempRect.Right() = aPt.X();
4702 aTempRect.Bottom() = aPt.Y();
4704 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4705 Help::ShowBalloon( this, aTempRect.Center(), aTempRect, maNextToolBoxStr );
4706 else
4707 Help::ShowQuickHelp( this, aTempRect, maNextToolBoxStr );
4708 return;
4712 DockingWindow::RequestHelp( rHEvt );
4715 // -----------------------------------------------------------------------
4717 long ToolBox::Notify( NotifyEvent& rNEvt )
4719 if ( rNEvt.GetType() == EVENT_KEYINPUT )
4721 KeyEvent aKEvt = *rNEvt.GetKeyEvent();
4722 KeyCode aKeyCode = aKEvt.GetKeyCode();
4723 sal_uInt16 nKeyCode = aKeyCode.GetCode();
4724 switch( nKeyCode )
4726 case KEY_TAB:
4728 // internal TAB cycling only if parent is not a dialog or if we are the ony child
4729 // otherwise the dialog control will take over
4730 sal_Bool bNoTabCycling = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL &&
4731 ImplGetParent()->GetChildCount() != 1 );
4733 if( bNoTabCycling && ! (GetStyle() & WB_FORCETABCYCLE) )
4734 return DockingWindow::Notify( rNEvt );
4735 else if( ImplChangeHighlightUpDn( aKeyCode.IsShift() ? sal_True : sal_False , bNoTabCycling ) )
4736 return sal_False;
4737 else
4738 return DockingWindow::Notify( rNEvt );
4740 default:
4741 break;
4744 else if( rNEvt.GetType() == EVENT_GETFOCUS )
4746 if( rNEvt.GetWindow() == this )
4748 // the toolbar itself got the focus
4749 if( mnLastFocusItemId != 0 )
4751 // restore last item
4752 ImplChangeHighlight( ImplGetItem( mnLastFocusItemId ) );
4753 mnLastFocusItemId = 0;
4755 else if( (GetGetFocusFlags() & (GETFOCUS_BACKWARD|GETFOCUS_TAB) ) == (GETFOCUS_BACKWARD|GETFOCUS_TAB))
4756 // Shift-TAB was pressed in the parent
4757 ImplChangeHighlightUpDn( sal_False );
4758 else
4759 ImplChangeHighlightUpDn( sal_True );
4761 mnLastFocusItemId = 0;
4763 return true;
4765 else
4767 // a child window got the focus so update current item to
4768 // allow for proper lose focus handling in keyboard navigation
4769 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4770 while( it != mpData->m_aItems.end() )
4772 if ( it->mbVisible )
4774 if ( it->mpWindow && it->mpWindow->ImplIsWindowOrChild( rNEvt.GetWindow() ) )
4776 mnHighItemId = it->mnId;
4777 break;
4781 ++it;
4783 return DockingWindow::Notify( rNEvt );
4786 else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
4788 // deselect
4789 ImplHideFocus();
4790 mnHighItemId = 0;
4791 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
4794 return DockingWindow::Notify( rNEvt );
4797 // -----------------------------------------------------------------------
4799 void ToolBox::Command( const CommandEvent& rCEvt )
4801 // depict StartDrag on MouseButton/Left/Alt
4802 if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) && rCEvt.IsMouseEvent() &&
4803 mbCustomize && !mbDragging && !mbDrag && !mbSelection &&
4804 (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4806 // We only allow dragging of items. Therefore, we have to check
4807 // if an item was clicked, otherwise we could move the window, and
4808 // this is unwanted.
4809 // We only do this in customize mode, as otherwise
4810 // items could be moved accidentally
4811 if ( mbCustomizeMode )
4813 Point aMousePos = rCEvt.GetMousePosPixel();
4814 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4815 while ( it != mpData->m_aItems.end() )
4817 // is this the item?
4818 if ( it->maRect.IsInside( aMousePos ) )
4820 // do nothing if it is a separator or
4821 // the item has been disabled
4822 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
4823 !it->mbShowWindow )
4824 mbCommandDrag = sal_True;
4825 break;
4828 ++it;
4831 if ( mbCommandDrag )
4833 MouseEvent aMEvt( aMousePos, 1, MOUSE_SIMPLECLICK,
4834 MOUSE_LEFT, KEY_MOD2 );
4835 ToolBox::MouseButtonDown( aMEvt );
4836 return;
4840 else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
4842 if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) )
4844 const CommandWheelData* pData = rCEvt.GetWheelData();
4845 if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
4847 if ( (mnCurLine > 1) && (pData->GetDelta() > 0) )
4848 ShowLine( sal_False );
4849 else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) )
4850 ShowLine( sal_True );
4851 ImplDrawSpin( sal_False, sal_False );
4852 return;
4857 DockingWindow::Command( rCEvt );
4860 // -----------------------------------------------------------------------
4862 void ToolBox::StateChanged( StateChangedType nType )
4864 DockingWindow::StateChanged( nType );
4866 if ( nType == STATE_CHANGE_INITSHOW )
4867 ImplFormat();
4868 else if ( nType == STATE_CHANGE_ENABLE )
4869 ImplUpdateItem();
4870 else if ( nType == STATE_CHANGE_UPDATEMODE )
4872 if ( IsUpdateMode() )
4873 Invalidate();
4875 else if ( (nType == STATE_CHANGE_ZOOM) ||
4876 (nType == STATE_CHANGE_CONTROLFONT) )
4878 mbCalc = sal_True;
4879 mbFormat = sal_True;
4880 ImplInitSettings( sal_True, sal_False, sal_False );
4881 Invalidate();
4883 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
4885 ImplInitSettings( sal_False, sal_True, sal_False );
4886 Invalidate();
4888 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
4890 ImplInitSettings( sal_False, sal_False, sal_True ); // font, foreground, background
4891 Invalidate();
4895 // -----------------------------------------------------------------------
4897 void ToolBox::DataChanged( const DataChangedEvent& rDCEvt )
4899 DockingWindow::DataChanged( rDCEvt );
4901 if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
4902 (rDCEvt.GetType() == DATACHANGED_FONTS) ||
4903 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
4904 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
4905 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
4907 mbCalc = sal_True;
4908 mbFormat = sal_True;
4909 ImplInitSettings( sal_True, sal_True, sal_True );
4910 Invalidate();
4914 // -----------------------------------------------------------------------
4916 sal_Bool ToolBox::PrepareToggleFloatingMode()
4918 return DockingWindow::PrepareToggleFloatingMode();
4921 // -----------------------------------------------------------------------
4923 void ToolBox::ToggleFloatingMode()
4925 DockingWindow::ToggleFloatingMode();
4927 sal_Bool mbOldHorz = mbHorz;
4929 if ( ImplIsFloatingMode() )
4931 mbHorz = sal_True;
4932 meAlign = WINDOWALIGN_TOP;
4933 mbScroll = sal_True;
4935 if( mbOldHorz != mbHorz )
4936 mbCalc = sal_True; // orientation was changed !
4938 ImplSetMinMaxFloatSize( this );
4939 SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
4941 else
4943 mbScroll = (mnWinStyle & WB_SCROLL) ? sal_True : sal_False;
4944 if ( (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM) )
4945 mbHorz = sal_True;
4946 else
4947 mbHorz = sal_False;
4949 // set focus back to document
4950 ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
4953 if( mbOldHorz != mbHorz )
4955 // if orientation changes, the toolbox has to be initialized again
4956 // to update the direction of the gradient
4957 mbCalc = sal_True;
4958 ImplInitSettings( sal_True, sal_True, sal_True );
4961 mbFormat = sal_True;
4962 ImplFormat();
4965 // -----------------------------------------------------------------------
4967 void ToolBox::StartDocking()
4969 meDockAlign = meAlign;
4970 mnDockLines = mnLines;
4971 mbLastFloatMode = ImplIsFloatingMode();
4972 DockingWindow::StartDocking();
4975 // -----------------------------------------------------------------------
4977 sal_Bool ToolBox::Docking( const Point& rPos, Rectangle& rRect )
4979 // do nothing during dragging, it was calculated before
4980 if ( mbDragging )
4981 return sal_False;
4983 sal_Bool bFloatMode = sal_False;
4985 DockingWindow::Docking( rPos, rRect );
4987 // if the mouse is outside the area, it can only become a floating window
4988 Rectangle aDockingRect( rRect );
4989 if ( !ImplIsFloatingMode() )
4991 // don't use tracking rectangle for alignment check, because it will be too large
4992 // to get a floating mode as result - switch to floating size
4993 // so the calculation only depends on the position of the rectangle, not the current
4994 // docking state of the window
4995 sal_uInt16 nTemp = 0;
4996 aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
4998 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
4999 aDockingRect.SetPos( ImplGetFrameWindow()->GetPointerPosPixel() );
5002 Rectangle aIntersection = maOutDockRect.GetIntersection( aDockingRect );
5003 if ( !aIntersection.IsEmpty() && !IsDockingPrevented() )
5005 Rectangle aInRect = maInDockRect;
5006 Size aDockSize;
5007 aDockSize.Width() = ImplCalcSize( this, mnLines, TB_CALCMODE_VERT ).Width();
5008 aDockSize.Height() = ImplCalcSize( this, mnLines, TB_CALCMODE_HORZ ).Height();
5009 aInRect.Left() += aDockSize.Width()/2;
5010 aInRect.Top() += aDockSize.Height()/2;
5011 aInRect.Right() -= aDockSize.Width()/2;
5012 aInRect.Bottom() -= aDockSize.Height()/2;
5014 // if the window is too small, use the complete InDock-Rect
5015 if ( aInRect.Left() >= aInRect.Right() )
5017 aInRect.Left() = maInDockRect.Left();
5018 aInRect.Right() = maInDockRect.Right();
5020 if ( aInRect.Top() >= aInRect.Bottom() )
5022 aInRect.Top() = maInDockRect.Top();
5023 aInRect.Bottom() = maInDockRect.Bottom();
5026 // if the mouse is outside the Dock area, it can only
5027 // become a floating window
5028 Rectangle aIntersect = aInRect.GetIntersection( aDockingRect );
5029 if ( aIntersect == aDockingRect )
5030 bFloatMode = sal_True;
5031 else
5033 // docking rectangle is in the "sensible area"
5034 Point aPos = aDockingRect.TopLeft();
5035 Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
5036 Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
5037 Size aInSize = aInRect.GetSize();
5039 if ( aInPosTL.X() <= 0 )
5040 meDockAlign = WINDOWALIGN_LEFT;
5041 else if ( aInPosTL.Y() <= 0)
5042 meDockAlign = WINDOWALIGN_TOP;
5043 else if ( aInPosBR.X() >= aInSize.Width() )
5044 meDockAlign = WINDOWALIGN_RIGHT;
5045 else if ( aInPosBR.Y() >= aInSize.Height() )
5046 meDockAlign = WINDOWALIGN_BOTTOM;
5048 // update the Dock size if Dock-Align was changed
5049 if ( (meDockAlign == WINDOWALIGN_TOP) || (meDockAlign == WINDOWALIGN_BOTTOM) )
5050 aDockSize.Width() = maInDockRect.GetWidth();
5051 else
5052 aDockSize.Height() = maInDockRect.GetHeight();
5054 aDockingRect.SetSize( aDockSize );
5056 Point aPosTL( maInDockRect.TopLeft() );
5057 switch ( meDockAlign )
5059 case WINDOWALIGN_TOP :
5060 aDockingRect.SetPos( aPosTL );
5061 break;
5062 case WINDOWALIGN_LEFT :
5063 aDockingRect.SetPos( aPosTL );
5064 break;
5065 case WINDOWALIGN_BOTTOM :
5067 Point aPosBL( maInDockRect.BottomLeft() );
5068 aPosBL.Y() -= aDockingRect.GetHeight();
5069 aDockingRect.SetPos( aPosBL );
5070 break;
5072 case WINDOWALIGN_RIGHT :
5074 Point aPosTR( maInDockRect.TopRight() );
5075 aPosTR.X() -= aDockingRect.GetWidth();
5076 aDockingRect.SetPos( aPosTR );
5077 break;
5082 else
5083 bFloatMode = sal_True;
5085 if ( bFloatMode )
5087 meDockAlign = meAlign;
5088 if ( !mbLastFloatMode )
5090 sal_uInt16 nTemp = 0;
5091 aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
5095 rRect = aDockingRect;
5096 mbLastFloatMode = bFloatMode;
5098 return bFloatMode;
5101 // -----------------------------------------------------------------------
5103 void ToolBox::EndDocking( const Rectangle& rRect, sal_Bool bFloatMode )
5105 if ( !IsDockingCanceled() )
5107 if ( mnLines != mnDockLines )
5108 SetLineCount( mnDockLines );
5109 if ( meAlign != meDockAlign )
5110 SetAlign( meDockAlign );
5112 if ( bFloatMode || (bFloatMode != ImplIsFloatingMode()) )
5113 DockingWindow::EndDocking( rRect, bFloatMode );
5116 // -----------------------------------------------------------------------
5118 void ToolBox::Resizing( Size& rSize )
5120 sal_uInt16 nCalcLines;
5121 sal_uInt16 nTemp;
5123 // Alle Floatinggroessen berechnen
5124 ImplCalcFloatSizes( this );
5126 if ( !mnLastResizeDY )
5127 mnLastResizeDY = mnDY;
5129 // Ist vertikales Resizing angesagt
5130 if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) )
5132 nCalcLines = ImplCalcLines( this, rSize.Height() );
5133 if ( nCalcLines < 1 )
5134 nCalcLines = 1;
5135 rSize = ImplCalcFloatSize( this, nCalcLines );
5137 else
5139 nCalcLines = 1;
5140 nTemp = nCalcLines;
5141 Size aTempSize = ImplCalcFloatSize( this, nTemp );
5142 while ( (aTempSize.Width() > rSize.Width()) &&
5143 (nCalcLines <= mpFloatSizeAry->mpSize[0].mnLines) )
5145 nCalcLines++;
5146 nTemp = nCalcLines;
5147 aTempSize = ImplCalcFloatSize( this, nTemp );
5149 rSize = aTempSize;
5152 mnLastResizeDY = rSize.Height();
5155 // -----------------------------------------------------------------------
5157 Size ToolBox::CalcWindowSizePixel( sal_uInt16 nCalcLines ) const
5159 return ImplCalcSize( this, nCalcLines );
5162 Size ToolBox::CalcWindowSizePixel( sal_uInt16 nCalcLines, WindowAlign eAlign ) const
5164 return ImplCalcSize( this, nCalcLines,
5165 (eAlign == WINDOWALIGN_TOP || eAlign == WINDOWALIGN_BOTTOM) ? TB_CALCMODE_HORZ : TB_CALCMODE_VERT );
5168 sal_uInt16 ToolBox::ImplCountLineBreaks( const ToolBox *pThis )
5170 sal_uInt16 nLines = 0;
5172 std::vector< ImplToolItem >::const_iterator it = ((ToolBox*)pThis)->mpData->m_aItems.begin();
5173 while ( it != ((ToolBox*)pThis)->mpData->m_aItems.end() )
5175 if( it->meType == TOOLBOXITEM_BREAK )
5176 ++nLines;
5177 ++it;
5179 return nLines;
5182 Size ToolBox::CalcPopupWindowSizePixel() const
5184 // count number of breaks and calc corresponding floating window size
5185 sal_uInt16 nLines = ImplCountLineBreaks( this );
5187 if( nLines )
5188 ++nLines; // add the first line
5189 else
5191 // no breaks found: use quadratic layout
5192 nLines = (sal_uInt16) ceil( sqrt( (double) GetItemCount() ) );
5195 sal_Bool bPopup = mpData->mbAssumePopupMode;
5196 ToolBox *pThis = (ToolBox*) this;
5197 pThis->mpData->mbAssumePopupMode = sal_True;
5199 Size aSize = CalcFloatingWindowSizePixel( nLines );
5201 pThis->mpData->mbAssumePopupMode = bPopup;
5202 return aSize;
5205 Size ToolBox::CalcFloatingWindowSizePixel() const
5207 sal_uInt16 nLines = ImplCountLineBreaks( this );
5208 ++nLines; // add the first line
5209 return CalcFloatingWindowSizePixel( nLines );
5212 Size ToolBox::CalcFloatingWindowSizePixel( sal_uInt16 nCalcLines ) const
5214 sal_Bool bFloat = mpData->mbAssumeFloating;
5215 sal_Bool bDocking = mpData->mbAssumeDocked;
5217 // simulate floating mode and force reformat before calculating
5218 ToolBox *pThis = (ToolBox*) this;
5219 pThis->mpData->mbAssumeFloating = sal_True;
5220 pThis->mpData->mbAssumeDocked = sal_False;
5222 Size aSize = ImplCalcFloatSize( (ToolBox*) this, nCalcLines );
5224 pThis->mbFormat = sal_True;
5225 pThis->mpData->mbAssumeFloating = bFloat;
5226 pThis->mpData->mbAssumeDocked = bDocking;
5228 return aSize;
5231 // -----------------------------------------------------------------------
5233 Size ToolBox::CalcMinimumWindowSizePixel() const
5235 if( ImplIsFloatingMode() )
5236 return ImplCalcSize( this, mnFloatLines );
5237 else
5239 // create dummy toolbox for measurements
5240 ToolBox *pToolBox = new ToolBox( GetParent(), GetStyle() );
5242 // copy until first useful item
5243 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5244 while( it != mpData->m_aItems.end() )
5246 pToolBox->CopyItem( *this, it->mnId );
5247 if( (it->meType != TOOLBOXITEM_BUTTON) ||
5248 !it->mbVisible || ImplIsFixedControl( &(*it) ) )
5249 ++it;
5250 else
5251 break;
5254 // add to docking manager if required to obtain a drag area
5255 // (which is accounted for in calcwindowsizepixel)
5256 if( ImplGetDockingManager()->GetDockingWindowWrapper( this ) )
5257 ImplGetDockingManager()->AddWindow( pToolBox );
5259 // account for menu
5260 if( IsMenuEnabled() )
5261 pToolBox->SetMenuType( GetMenuType() );
5263 pToolBox->SetAlign( GetAlign() );
5264 Size aSize = pToolBox->CalcWindowSizePixel( 1 );
5266 ImplGetDockingManager()->RemoveWindow( pToolBox );
5267 pToolBox->Clear();
5268 delete pToolBox;
5270 return aSize;
5274 // -----------------------------------------------------------------------
5276 void ToolBox::EnableCustomize( sal_Bool bEnable )
5278 if ( bEnable != mbCustomize )
5280 mbCustomize = bEnable;
5282 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5283 if ( bEnable )
5284 pMgr->push_back( this );
5285 else
5286 pMgr->erase( this );
5290 // -----------------------------------------------------------------------
5292 void ToolBox::GetFocus()
5294 DockingWindow::GetFocus();
5297 // -----------------------------------------------------------------------
5299 void ToolBox::LoseFocus()
5301 ImplChangeHighlight( NULL, sal_True );
5303 DockingWindow::LoseFocus();
5306 // -----------------------------------------------------------------------
5308 // performs the action associated with an item, ie simulates clicking the item
5309 void ToolBox::TriggerItem( sal_uInt16 nItemId, sal_Bool bShift, sal_Bool bCtrl )
5311 mnHighItemId = nItemId;
5312 sal_uInt16 nModifier = 0;
5313 if( bShift )
5314 nModifier |= KEY_SHIFT;
5315 if( bCtrl )
5316 nModifier |= KEY_MOD1;
5317 KeyCode aKeyCode( 0, nModifier );
5318 ImplActivateItem( aKeyCode );
5321 // -----------------------------------------------------------------------
5323 // calls the button's action handler
5324 // returns sal_True if action was called
5325 sal_Bool ToolBox::ImplActivateItem( KeyCode aKeyCode )
5327 sal_Bool bRet = sal_True;
5328 if( mnHighItemId )
5330 ImplToolItem *pToolItem = ImplGetItem( mnHighItemId );
5332 // #107712#, activate can also be called for disabled entries
5333 if( pToolItem && !pToolItem->mbEnabled )
5334 return sal_True;
5336 if( pToolItem && pToolItem->mpWindow && HasFocus() )
5338 ImplHideFocus();
5339 mbChangingHighlight = sal_True; // avoid focus change due to loose focus
5340 pToolItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5341 mbChangingHighlight = sal_False;
5343 else
5345 mnDownItemId = mnCurItemId = mnHighItemId;
5346 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5347 if ( pItem->mnBits & TIB_AUTOCHECK )
5349 if ( pItem->mnBits & TIB_RADIOCHECK )
5351 if ( pItem->meState != STATE_CHECK )
5352 SetItemState( pItem->mnId, STATE_CHECK );
5354 else
5356 if ( pItem->meState != STATE_CHECK )
5357 pItem->meState = STATE_CHECK;
5358 else
5359 pItem->meState = STATE_NOCHECK;
5362 mnMouseModifier = aKeyCode.GetModifier();
5363 mbIsKeyEvent = sal_True;
5364 Activate();
5365 Click();
5367 // #107776# we might be destroyed in the selecthandler
5368 ImplDelData aDelData;
5369 ImplAddDel( &aDelData );
5370 Select();
5371 if ( aDelData.IsDelete() )
5372 return bRet;
5373 ImplRemoveDel( &aDelData );
5375 Deactivate();
5376 mbIsKeyEvent = sal_False;
5377 mnMouseModifier = 0;
5380 else
5381 bRet = sal_False;
5382 return bRet;
5385 // -----------------------------------------------------------------------
5387 sal_Bool ImplCloseLastPopup( Window *pParent )
5389 // close last popup toolbox (see also:
5390 // ImplHandleMouseFloatMode(...) in winproc.cxx )
5392 if( ImplGetSVData()->maWinData.mpFirstFloat )
5394 FloatingWindow* pLastLevelFloat = ImplGetSVData()->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
5395 // only close the floater if it is not our direct parent, which would kill ourself
5396 if( pLastLevelFloat && pLastLevelFloat != pParent )
5398 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
5399 return sal_True;
5402 return sal_False;
5405 // opens a drop down toolbox item
5406 // returns sal_True if item was opened
5407 sal_Bool ToolBox::ImplOpenItem( KeyCode aKeyCode )
5409 sal_uInt16 nCode = aKeyCode.GetCode();
5410 sal_Bool bRet = sal_True;
5412 // arrow keys should work only in the opposite direction of alignment (to not break cursor travelling)
5413 if ( ((nCode == KEY_LEFT || nCode == KEY_RIGHT) && IsHorizontal())
5414 || ((nCode == KEY_UP || nCode == KEY_DOWN) && !IsHorizontal()) )
5415 return sal_False;
5417 if( IsMenuEnabled() && mpData->mbMenubuttonSelected )
5419 if( ImplCloseLastPopup( GetParent() ) )
5420 return bRet;
5422 UpdateCustomMenu();
5423 Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
5425 else if( mnHighItemId && ImplGetItem( mnHighItemId ) &&
5426 (ImplGetItem( mnHighItemId )->mnBits & TIB_DROPDOWN) )
5428 if( ImplCloseLastPopup( GetParent() ) )
5429 return bRet;
5431 mnDownItemId = mnCurItemId = mnHighItemId;
5432 mnCurPos = GetItemPos( mnCurItemId );
5433 mnLastFocusItemId = mnCurItemId; // save item id for possible later focus restore
5434 mnMouseModifier = aKeyCode.GetModifier();
5435 mbIsShift = sal_True;
5436 mbIsKeyEvent = sal_True;
5437 Activate();
5439 mpData->mbDropDownByKeyboard = sal_True;
5440 GetDropdownClickHdl().Call( this );
5442 mbIsKeyEvent = sal_False;
5443 mbIsShift = sal_False;
5444 mnMouseModifier = 0;
5446 else
5447 bRet = sal_False;
5449 return bRet;
5452 // -----------------------------------------------------------------------
5454 void ToolBox::KeyInput( const KeyEvent& rKEvt )
5456 KeyCode aKeyCode = rKEvt.GetKeyCode();
5457 mnKeyModifier = aKeyCode.GetModifier();
5458 sal_uInt16 nCode = aKeyCode.GetCode();
5459 sal_Bool bParentIsDialog = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL );
5460 sal_Bool bForwardKey = sal_False;
5461 sal_Bool bGrabFocusToDocument = sal_False;
5463 // #107776# we might be destroyed in the keyhandler
5464 ImplDelData aDelData;
5465 ImplAddDel( &aDelData );
5467 switch ( nCode )
5469 case KEY_UP:
5471 // Ctrl-Cursor activates next toolbox, indicated by a blue arrow pointing to the left/up
5472 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5473 break;
5474 if( !IsHorizontal() )
5475 ImplChangeHighlightUpDn( sal_True );
5476 else
5477 ImplOpenItem( aKeyCode );
5479 break;
5480 case KEY_LEFT:
5482 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5483 break;
5484 if( IsHorizontal() )
5485 ImplChangeHighlightUpDn( sal_True );
5486 else
5487 ImplOpenItem( aKeyCode );
5489 break;
5490 case KEY_DOWN:
5492 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5493 break;
5494 if( !IsHorizontal() )
5495 ImplChangeHighlightUpDn( sal_False );
5496 else
5497 ImplOpenItem( aKeyCode );
5499 break;
5500 case KEY_RIGHT:
5502 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5503 break;
5504 if( IsHorizontal() )
5505 ImplChangeHighlightUpDn( sal_False );
5506 else
5507 ImplOpenItem( aKeyCode );
5509 break;
5510 case KEY_PAGEUP:
5511 if ( mnCurLine > 1 )
5513 if( mnCurLine > mnVisLines )
5514 mnCurLine = mnCurLine - mnVisLines;
5515 else
5516 mnCurLine = 1;
5517 mbFormat = sal_True;
5518 ImplFormat();
5519 ImplDrawSpin( sal_False, sal_False );
5520 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5522 break;
5523 case KEY_PAGEDOWN:
5524 if ( mnCurLine+mnVisLines-1 < mnCurLines )
5526 if( mnCurLine + 2*mnVisLines-1 < mnCurLines )
5527 mnCurLine = mnCurLine + mnVisLines;
5528 else
5529 mnCurLine = mnCurLines;
5530 mbFormat = sal_True;
5531 ImplFormat();
5532 ImplDrawSpin( sal_False, sal_False );
5533 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5535 break;
5536 case KEY_END:
5538 ImplChangeHighlight( NULL );
5539 ImplChangeHighlightUpDn( sal_False );
5541 break;
5542 case KEY_HOME:
5544 ImplChangeHighlight( NULL );
5545 ImplChangeHighlightUpDn( sal_True );
5547 break;
5548 case KEY_ESCAPE:
5550 if( !ImplIsFloatingMode() && bParentIsDialog )
5551 DockingWindow::KeyInput( rKEvt );
5552 else
5554 // send focus to document pane
5555 Window *pWin = this;
5556 while( pWin )
5558 if( !pWin->GetParent() )
5560 pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
5561 break;
5563 pWin = pWin->GetParent();
5567 break;
5568 case KEY_RETURN:
5570 // #107712#, disabled entries are selectable now
5571 // leave toolbox and move focus to document
5572 if( mnHighItemId )
5574 ImplToolItem *pItem = ImplGetItem( mnHighItemId );
5575 if( !pItem->mbEnabled )
5577 Sound::Beep( SOUND_DISABLE, this );
5578 bGrabFocusToDocument = sal_True;
5581 if( !bGrabFocusToDocument )
5582 bForwardKey = !ImplActivateItem( aKeyCode );
5584 break;
5585 default:
5587 sal_uInt16 aKeyGroup = aKeyCode.GetGroup();
5588 ImplToolItem *pItem = NULL;
5589 if( mnHighItemId )
5590 pItem = ImplGetItem( mnHighItemId );
5591 // #i13931# forward alphanum keyinput into embedded control
5592 if( (aKeyGroup == KEYGROUP_NUM || aKeyGroup == KEYGROUP_ALPHA ) && pItem && pItem->mpWindow && pItem->mbEnabled )
5594 Window *pFocusWindow = Application::GetFocusWindow();
5595 ImplHideFocus();
5596 mbChangingHighlight = sal_True; // avoid focus change due to loose focus
5597 pItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5598 mbChangingHighlight = sal_False;
5599 if( pFocusWindow != Application::GetFocusWindow() )
5600 Application::GetFocusWindow()->KeyInput( rKEvt );
5602 else
5604 // do nothing to avoid key presses going into the document
5605 // while the toolbox has the focus
5606 // just forward function and special keys and combinations with Alt-key
5607 if( aKeyGroup == KEYGROUP_FKEYS || aKeyGroup == KEYGROUP_MISC || aKeyCode.IsMod2() )
5608 bForwardKey = sal_True;
5613 if ( aDelData.IsDelete() )
5614 return;
5615 ImplRemoveDel( &aDelData );
5617 // #107251# move focus away if this toolbox was disabled during keyinput
5618 if( HasFocus() && mpData->mbKeyInputDisabled && (ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL)
5620 sal_uInt16 n = 0;
5621 Window *pFocusControl = ImplGetParent()->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
5622 if ( pFocusControl && pFocusControl != this )
5623 pFocusControl->ImplControlFocus( GETFOCUS_INIT );
5626 mnKeyModifier = 0;
5628 // #107712#, leave toolbox
5629 if( bGrabFocusToDocument )
5631 GrabFocusToDocument();
5632 return;
5635 if( bForwardKey )
5636 DockingWindow::KeyInput( rKEvt );
5639 // -----------------------------------------------------------------------
5641 // returns the current toolbox line of the item
5642 sal_uInt16 ToolBox::ImplGetItemLine( ImplToolItem* pCurrentItem )
5644 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
5645 sal_uInt16 nLine = 1;
5646 while( it != mpData->m_aItems.end() )
5648 if ( it->mbBreak )
5649 ++nLine;
5650 if( &(*it) == pCurrentItem)
5651 break;
5652 ++it;
5654 return nLine;
5657 // returns the first displayable item in the given line
5658 ImplToolItem* ToolBox::ImplGetFirstValidItem( sal_uInt16 nLine )
5660 if( !nLine || nLine > mnCurLines )
5661 return NULL;
5663 nLine--;
5665 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5666 while( it != mpData->m_aItems.end() )
5668 // find correct line
5669 if ( it->mbBreak )
5670 nLine--;
5671 if( !nLine )
5673 // find first useful item
5674 while( it != mpData->m_aItems.end() && ((it->meType != TOOLBOXITEM_BUTTON) ||
5675 /*!it->mbEnabled ||*/ !it->mbVisible || ImplIsFixedControl( &(*it) )) )
5677 ++it;
5678 if( it == mpData->m_aItems.end() || it->mbBreak )
5679 return NULL; // no valid items in this line
5681 return &(*it);
5683 ++it;
5686 return (it == mpData->m_aItems.end()) ? NULL : &(*it);
5689 // -----------------------------------------------------------------------
5691 sal_uInt16 ToolBox::ImplFindItemPos( const ImplToolItem* pItem, const std::vector< ImplToolItem >& rList )
5693 if( pItem )
5695 sal_uInt16 nPos;
5696 for( nPos = 0; nPos < rList.size(); ++nPos )
5697 if( &rList[ nPos ] == pItem )
5698 return nPos;
5700 return TOOLBOX_ITEM_NOTFOUND;
5703 void ToolBox::ChangeHighlight( sal_uInt16 nPos )
5705 if ( nPos < GetItemCount() ) {
5706 ImplGrabFocus( 0 );
5707 ImplChangeHighlight ( ImplGetItem ( GetItemId ( (sal_uInt16) nPos ) ), sal_False );
5711 void ToolBox::ImplChangeHighlight( ImplToolItem* pItem, sal_Bool bNoGrabFocus )
5713 // avoid recursion due to focus change
5714 if( mbChangingHighlight )
5715 return;
5717 mbChangingHighlight = sal_True;
5719 ImplToolItem* pOldItem = NULL;
5721 if ( mnHighItemId )
5723 ImplHideFocus();
5724 sal_uInt16 nPos = GetItemPos( mnHighItemId );
5725 pOldItem = ImplGetItem( mnHighItemId );
5726 // #i89962# ImplDrawItem can cause Invalidate/Update
5727 // which will in turn ImplShowFocus again
5728 // set mnHighItemId to 0 already to prevent this hen/egg problem
5729 mnHighItemId = 0;
5730 ImplDrawItem( nPos, 0 );
5731 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
5734 if( !bNoGrabFocus && pItem != pOldItem && pOldItem && pOldItem->mpWindow )
5736 // move focus into toolbox
5737 GrabFocus();
5740 if( pItem )
5742 sal_uInt16 aPos = ToolBox::ImplFindItemPos( pItem, mpData->m_aItems );
5743 if( aPos != TOOLBOX_ITEM_NOTFOUND)
5745 // check for line breaks
5746 sal_uInt16 nLine = ImplGetItemLine( pItem );
5748 if( nLine >= mnCurLine + mnVisLines )
5750 mnCurLine = nLine - mnVisLines + 1;
5751 mbFormat = sal_True;
5753 else if ( nLine < mnCurLine )
5755 mnCurLine = nLine;
5756 mbFormat = sal_True;
5759 if( mbFormat )
5761 ImplFormat();
5764 mnHighItemId = pItem->mnId;
5765 ImplDrawItem( aPos, 2 ); // always use shadow effect (2)
5767 if( mbSelection )
5768 mnCurPos = aPos;
5769 ImplShowFocus();
5771 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
5774 else
5776 ImplHideFocus();
5777 mnHighItemId = 0;
5778 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
5781 mbChangingHighlight = sal_False;
5784 // -----------------------------------------------------------------------
5786 // check for keyboard accessible items
5787 static sal_Bool ImplIsValidItem( const ImplToolItem* pItem, sal_Bool bNotClipped )
5789 sal_Bool bValid = (pItem && pItem->meType == TOOLBOXITEM_BUTTON && pItem->mbVisible && !ImplIsFixedControl( pItem ));
5790 if( bValid && bNotClipped && pItem->IsClipped() )
5791 bValid = sal_False;
5792 return bValid;
5795 // -----------------------------------------------------------------------
5797 sal_Bool ToolBox::ImplChangeHighlightUpDn( sal_Bool bUp, sal_Bool bNoCycle )
5799 ImplToolItem* pToolItem = ImplGetItem( mnHighItemId );
5801 if( !pToolItem || !mnHighItemId )
5803 // menubutton highlighted ?
5804 if( mpData->mbMenubuttonSelected )
5806 if( bUp )
5808 // select last valid non-clipped item
5809 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
5810 ImplToolItem* pItem = NULL;
5811 while( it != mpData->m_aItems.begin() )
5813 --it;
5814 if ( ImplIsValidItem( &(*it), sal_True ) )
5816 pItem = &(*it);
5817 break;
5820 ImplDrawMenubutton( this, sal_False );
5821 ImplChangeHighlight( pItem );
5823 else
5825 // select first valid non-clipped item
5826 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5827 while( it != mpData->m_aItems.end() )
5829 if ( ImplIsValidItem( &(*it), sal_True ) )
5830 break;
5831 ++it;
5833 if( it != mpData->m_aItems.end() )
5835 ImplDrawMenubutton( this, sal_False );
5836 ImplChangeHighlight( &(*it) );
5839 return sal_True;
5842 if( bUp )
5844 // Select first valid item
5845 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5846 while( it != mpData->m_aItems.end() )
5848 if ( ImplIsValidItem( &(*it), sal_False ) )
5849 break;
5850 ++it;
5853 // select the menu button if a clipped item would be selected
5854 if( (it != mpData->m_aItems.end() && &(*it) == ImplGetFirstClippedItem( this )) && IsMenuEnabled() )
5856 ImplChangeHighlight( NULL );
5857 ImplDrawMenubutton( this, sal_True );
5859 else
5860 ImplChangeHighlight( (it != mpData->m_aItems.end()) ? &(*it) : NULL );
5861 return sal_True;
5863 else
5865 // Select last valid item
5867 // docked toolbars have the menubutton as last item - if this button is enabled
5868 if( IsMenuEnabled() && !ImplIsFloatingMode() )
5870 ImplChangeHighlight( NULL );
5871 ImplDrawMenubutton( this, sal_True );
5873 else
5875 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
5876 ImplToolItem* pItem = NULL;
5877 while( it != mpData->m_aItems.begin() )
5879 --it;
5880 if ( ImplIsValidItem( &(*it), sal_False ) )
5882 pItem = &(*it);
5883 break;
5886 ImplChangeHighlight( pItem );
5888 return sal_True;
5892 if( pToolItem )
5894 sal_uLong pos = ToolBox::ImplFindItemPos( pToolItem, mpData->m_aItems );
5895 sal_uLong nCount = mpData->m_aItems.size();
5897 sal_uLong i=0;
5900 if( bUp )
5902 if( !pos-- )
5904 if( bNoCycle )
5905 return sal_False;
5907 // highlight the menu button if it is the last item
5908 if( IsMenuEnabled() && !ImplIsFloatingMode() )
5910 ImplChangeHighlight( NULL );
5911 ImplDrawMenubutton( this, sal_True );
5912 return sal_True;
5914 else
5915 pos = nCount-1;
5918 else
5920 if( ++pos >= nCount )
5922 if( bNoCycle )
5923 return sal_False;
5925 // highlight the menu button if it is the last item
5926 if( IsMenuEnabled() && !ImplIsFloatingMode() )
5928 ImplChangeHighlight( NULL );
5929 ImplDrawMenubutton( this, sal_True );
5930 return sal_True;
5932 else
5933 pos = 0;
5937 pToolItem = &mpData->m_aItems[pos];
5939 if ( ImplIsValidItem( pToolItem, sal_False ) )
5940 break;
5942 } while( ++i < nCount);
5944 if( pToolItem->IsClipped() && IsMenuEnabled() )
5946 // select the menu button if a clipped item would be selected
5947 ImplChangeHighlight( NULL );
5948 ImplDrawMenubutton( this, sal_True );
5950 else if( i != nCount )
5951 ImplChangeHighlight( pToolItem );
5952 else
5953 return sal_False;
5955 return sal_True;
5958 // -----------------------------------------------------------------------
5960 void ToolBox::ImplShowFocus()
5962 if( mnHighItemId && HasFocus() )
5964 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5965 if( pItem->mpWindow )
5967 Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
5968 pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = sal_True;
5969 pWin->Invalidate( 0 );
5974 // -----------------------------------------------------------------------
5976 void ToolBox::ImplHideFocus()
5978 if( mnHighItemId )
5980 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5981 if( pItem->mpWindow )
5983 Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
5984 pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = sal_False;
5985 pWin->Invalidate( 0 );
5989 if ( mpData->mbMenubuttonSelected )
5991 // remove highlight from menubutton
5992 ImplDrawMenubutton( this, sal_False );
5996 // -----------------------------------------------------------------------
5998 void ToolBox::ImplDisableFlatButtons()
6000 #ifdef WNT // Check in the Windows registry if an AT tool wants no flat toolboxes
6001 static bool bInit = false, bValue = false;
6002 if( ! bInit )
6004 bInit = true;
6005 HKEY hkey;
6007 if( ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER,
6008 "Software\\LibreOffice\\Accessibility\\AtToolSupport",
6009 &hkey) )
6011 DWORD dwType = 0;
6012 sal_uInt8 Data[6]; // possible values: "true", "false", "1", "0", DWORD
6013 DWORD cbData = sizeof(Data);
6015 if( ERROR_SUCCESS == RegQueryValueEx(hkey, "DisableFlatToolboxButtons",
6016 NULL, &dwType, Data, &cbData) )
6018 switch (dwType)
6020 case REG_SZ:
6021 bValue = ((0 == stricmp((const char *) Data, "1")) || (0 == stricmp((const char *) Data, "true")));
6022 break;
6023 case REG_DWORD:
6024 bValue = (bool)(((DWORD *) Data)[0]);
6025 break;
6028 RegCloseKey(hkey);
6031 if( bValue )
6032 mnOutStyle &= ~TOOLBOX_STYLE_FLAT;
6033 #endif
6036 void ToolBox::SetToolbarLayoutMode( ToolBoxLayoutMode eLayout )
6038 if ( meLayoutMode != eLayout )
6039 meLayoutMode = eLayout;
6042 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */