update dev300-m58
[ooovba.git] / vcl / source / window / toolbox.cxx
blob904a78e6ef6cd4717979969d7cb4a4bcce66eaff
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: toolbox.cxx,v $
10 * $Revision: 1.109 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #ifndef _SV_SVSYS_HXX
35 #include <svsys.h>
36 #endif
37 #include <rtl/logfile.hxx>
38 #include <tools/list.hxx>
39 #include <tools/debug.hxx>
41 #ifndef _SV_RC_H
42 #include <tools/rc.h>
43 #endif
44 #include <vcl/svdata.hxx>
45 #include <vcl/event.hxx>
46 #include <vcl/decoview.hxx>
47 #include <vcl/accel.hxx>
48 #include <vcl/svapp.hxx>
49 #include <vcl/help.hxx>
50 #include <vcl/sound.hxx>
51 #include <vcl/virdev.hxx>
52 #include <vcl/spin.h>
53 #include <vcl/toolbox.hxx>
54 #include <vcl/toolbox.h>
55 #include <vcl/bitmap.hxx>
56 #include <tools/poly.hxx>
57 #include <vcl/salframe.hxx>
58 #include <vcl/mnemonic.hxx>
59 #include <vcl/gradient.hxx>
60 #include <vcl/menu.hxx>
61 #include <vcl/window.h>
63 #include <string.h>
64 #include <vector>
65 #include <math.h>
67 // =======================================================================
69 DBG_NAMEEX( Window )
71 // =======================================================================
73 #define SMALLBUTTON_HSIZE 7
74 #define SMALLBUTTON_VSIZE 7
76 #define SMALLBUTTON_OFF_NORMAL_X 3
77 #define SMALLBUTTON_OFF_NORMAL_Y 3
78 #define SMALLBUTTON_OFF_CHECKED_X 4
79 #define SMALLBUTTON_OFF_CHECKED_Y 4
80 #define SMALLBUTTON_OFF_PRESSED_X 5
81 #define SMALLBUTTON_OFF_PRESSED_Y 5
83 #define OUTBUTTON_SIZE 6
84 #define OUTBUTTON_BORDER 4
85 #define OUTBUTTON_OFF_NORMAL_X 1
86 #define OUTBUTTON_OFF_NORMAL_Y 1
88 // -----------------------------------------------------------------------
90 #define DEF_MIN_WIDTH 8
91 #define DEF_MIN_HEIGHT 8
92 #define DEF_TEXT_WIDTH 40
94 #define TB_TEXTOFFSET 2
95 #define TB_IMAGETEXTOFFSET 3
96 #define TB_LINESPACING 3
97 #define TB_SPIN_SIZE 14
98 #define TB_SPIN_OFFSET 2
99 #define TB_NEXT_SIZE 22
100 #define TB_NEXT_OFFSET 2
101 #define TB_BORDER_OFFSET1 4
102 #define TB_BORDER_OFFSET2 2
103 #define TB_CUSTOMIZE_OFFSET 2
104 #define TB_RESIZE_OFFSET 3
105 #define TB_MAXLINES 5
106 #define TB_MAXNOSCROLL 32765
108 #define TB_MIN_WIN_WIDTH 20
110 #define TB_CALCMODE_HORZ 1
111 #define TB_CALCMODE_VERT 2
112 #define TB_CALCMODE_FLOAT 3
114 #define TB_WBLINESIZING (WB_SIZEABLE | WB_DOCKABLE | WB_SCROLL)
116 #define TB_MAX_GROUPS 100
118 #define DOCK_LINEHSIZE ((USHORT)0x0001)
119 #define DOCK_LINEVSIZE ((USHORT)0x0002)
120 #define DOCK_LINERIGHT ((USHORT)0x1000)
121 #define DOCK_LINEBOTTOM ((USHORT)0x2000)
122 #define DOCK_LINELEFT ((USHORT)0x4000)
123 #define DOCK_LINETOP ((USHORT)0x8000)
124 #define DOCK_LINEOFFSET 3
127 // -----------------------------------------------------------------------
128 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, USHORT highlight, BOOL bChecked, BOOL bEnabled, BOOL bIsWindow );
129 // -----------------------------------------------------------------------
131 struct ImplToolSize
133 long mnWidth;
134 long mnHeight;
135 USHORT mnLines;
138 struct ImplToolSizeArray
140 long mnLength;
141 long mnLastEntry;
142 ImplToolSize* mpSize;
144 ImplToolSizeArray() { mpSize = NULL; mnLength = 0; mnLastEntry = 0; }
145 ~ImplToolSizeArray() { if( mpSize ) delete [] mpSize; mnLength = 0; }
148 // -----------------------------------------------------------------------
150 DECLARE_LIST( ImplTBList, ToolBox* )
152 class ImplTBDragMgr
154 private:
155 ImplTBList* mpBoxList;
156 ToolBox* mpDragBox;
157 Point maMouseOff;
158 Rectangle maRect;
159 Rectangle maStartRect;
160 Accelerator maAccel;
161 long mnMinWidth;
162 long mnMaxWidth;
163 USHORT mnLineMode;
164 USHORT mnStartLines;
165 void* mpCustomizeData;
166 BOOL mbCustomizeMode;
167 BOOL mbResizeMode;
168 BOOL mbShowDragRect;
170 public:
171 ImplTBDragMgr();
172 ~ImplTBDragMgr();
174 void Insert( ToolBox* pBox )
175 { mpBoxList->Insert( pBox ); }
176 void Remove( ToolBox* pBox )
177 { mpBoxList->Remove( pBox ); }
178 ULONG Count() const
179 { return mpBoxList->Count(); }
181 ToolBox* FindToolBox( const Rectangle& rRect );
183 void StartDragging( ToolBox* pDragBox,
184 const Point& rPos, const Rectangle& rRect,
185 USHORT nLineMode, BOOL bResizeItem,
186 void* pData = NULL );
187 void Dragging( const Point& rPos );
188 void EndDragging( BOOL bOK = TRUE );
189 void HideDragRect() { if ( mbShowDragRect ) mpDragBox->HideTracking(); }
190 void UpdateDragRect();
191 DECL_LINK( SelectHdl, Accelerator* );
193 void StartCustomizeMode();
194 void EndCustomizeMode();
195 BOOL IsCustomizeMode() { return mbCustomizeMode; }
196 BOOL IsResizeMode() { return mbResizeMode; }
199 // -----------------------------------------------------------------------
201 static ImplTBDragMgr* ImplGetTBDragMgr()
203 ImplSVData* pSVData = ImplGetSVData();
204 if ( !pSVData->maCtrlData.mpTBDragMgr )
205 pSVData->maCtrlData.mpTBDragMgr = new ImplTBDragMgr;
206 return pSVData->maCtrlData.mpTBDragMgr;
209 // -----------------------------------------------------------------------
211 int ToolBox::ImplGetDragWidth( ToolBox* pThis )
213 #define TB_DRAGWIDTH 8 // the default width of the grip
215 int width = TB_DRAGWIDTH;
216 if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
219 ImplControlValue aControlValue;
220 Point aPoint;
221 Region aContent, aBound;
222 Region aArea( Rectangle(aPoint, pThis->GetOutputSizePixel()) );
224 if ( pThis->GetNativeControlRegion(CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
225 aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
227 width = pThis->mbHorz ? aContent.GetBoundRect().GetWidth() : aContent.GetBoundRect().GetHeight();
230 return width;
233 ButtonType determineButtonType( ImplToolItem* pItem, ButtonType defaultType )
235 ButtonType tmpButtonType = defaultType;
236 ToolBoxItemBits nBits( pItem->mnBits & 0x300 );
237 if ( nBits & TIB_TEXTICON ) // item has custom setting
239 tmpButtonType = BUTTON_SYMBOLTEXT;
240 if ( nBits == TIB_TEXT_ONLY )
241 tmpButtonType = BUTTON_TEXT;
242 else if ( nBits == TIB_ICON_ONLY )
243 tmpButtonType = BUTTON_SYMBOL;
245 return tmpButtonType;
248 // -----------------------------------------------------------------------
250 void ToolBox::ImplUpdateDragArea( ToolBox *pThis )
252 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
253 if( pWrapper )
255 if ( pThis->ImplIsFloatingMode() || pWrapper->IsLocked() )
256 pWrapper->SetDragArea( Rectangle() );
257 else
259 if( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
260 pWrapper->SetDragArea( Rectangle( 0, 0, ImplGetDragWidth( pThis ), pThis->GetOutputSizePixel().Height() ) );
261 else
262 pWrapper->SetDragArea( Rectangle( 0, 0, pThis->GetOutputSizePixel().Width(), ImplGetDragWidth( pThis ) ) );
267 // -----------------------------------------------------------------------
269 void ToolBox::ImplCalcBorder( WindowAlign eAlign, long& rLeft, long& rTop,
270 long& rRight, long& rBottom, const ToolBox *pThis )
272 if( pThis->ImplIsFloatingMode() || !(pThis->mnWinStyle & WB_BORDER) )
274 // no border in floating mode
275 rLeft = rTop = rRight = rBottom = 0;
276 return;
279 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
281 // reserve dragarea only for dockable toolbars
282 int dragwidth = ( pWrapper && !pWrapper->IsLocked() ) ? ImplGetDragWidth( (ToolBox*)pThis ) : 0;
284 // no shadow border for dockable toolbars
285 int borderwidth = pWrapper ? 0: 2;
287 if ( eAlign == WINDOWALIGN_TOP )
289 rLeft = borderwidth+dragwidth;
290 rTop = borderwidth;
291 rRight = borderwidth;
292 rBottom = 0;
294 else if ( eAlign == WINDOWALIGN_LEFT )
296 rLeft = borderwidth;
297 rTop = borderwidth+dragwidth;
298 rRight = 0;
299 rBottom = borderwidth;
301 else if ( eAlign == WINDOWALIGN_BOTTOM )
303 rLeft = borderwidth+dragwidth;
304 rTop = 0;
305 rRight = borderwidth;
306 rBottom = borderwidth;
308 else
310 rLeft = 0;
311 rTop = borderwidth+dragwidth;
312 rRight = borderwidth;
313 rBottom = borderwidth;
317 // -----------------------------------------------------------------------
319 static void ImplCheckUpdate( ToolBox *pThis )
321 // remove any pending invalidates to avoid
322 // have them triggered when paint is locked (see mpData->mbIsPaintLocked)
323 // which would result in erasing the background only and not painting any items
324 // this must not be done when we're already in Paint()
326 // this is only required for transparent toolbars (see ImplDrawTransparentBackground() )
327 if( !pThis->IsBackground() && pThis->HasPaintEvent() && !pThis->IsInPaint() )
328 pThis->Update();
331 // -----------------------------------------------------------------------
333 void ToolBox::ImplDrawGrip( ToolBox* pThis )
335 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
336 if( pWrapper && !pWrapper->GetDragArea().IsEmpty() )
338 // execute pending paint requests
339 ImplCheckUpdate( pThis );
341 BOOL bNativeOk = FALSE;
342 if( pThis->IsNativeControlSupported( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_HORZ : PART_THUMB_VERT ) )
344 ImplControlValue aControlValue;
345 ToolbarValue aToolbarValue;
346 aToolbarValue.maGripRect = pWrapper->GetDragArea();
347 aControlValue.setOptionalVal( (void *)(&aToolbarValue) );
348 Point aPt;
349 Region aCtrlRegion( Rectangle( aPt, pThis->GetOutputSizePixel() ) );
350 ControlState nState = CTRL_STATE_ENABLED;
352 bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_THUMB_VERT : PART_THUMB_HORZ,
353 aCtrlRegion, nState, aControlValue, rtl::OUString() );
356 if( bNativeOk )
357 return;
359 const StyleSettings& rStyleSettings = pThis->GetSettings().GetStyleSettings();
360 pThis->SetLineColor( rStyleSettings.GetShadowColor() );
362 Size aSz ( pThis->GetOutputSizePixel() );
364 if ( pThis->meAlign == WINDOWALIGN_TOP || pThis->meAlign == WINDOWALIGN_BOTTOM )
366 int height = (int) (0.6 * aSz.Height() + 0.5);
367 int i = (aSz.Height() - height) / 2;
368 height += i;
369 while( i <= height )
371 int x = ImplGetDragWidth( pThis ) / 2;
373 pThis->DrawPixel( Point(x, i), rStyleSettings.GetDarkShadowColor() );
374 pThis->DrawPixel( Point(x+1, i), rStyleSettings.GetShadowColor() );
376 pThis->DrawPixel( Point(x, i+1), rStyleSettings.GetShadowColor() );
377 pThis->DrawPixel( Point(x+1, i+1), rStyleSettings.GetFaceColor() );
378 pThis->DrawPixel( Point(x+2, i+1), Color(COL_WHITE) );
380 pThis->DrawPixel( Point(x+1, i+2), Color(COL_WHITE) );
381 pThis->DrawPixel( Point(x+2, i+2), Color(COL_WHITE) );
382 i+=4;
385 else
387 int width = (int) (0.6 * aSz.Width() + 0.5);
388 int i = (aSz.Width() - width) / 2;
389 width += i;
390 while( i <= width )
392 int y = ImplGetDragWidth(pThis) / 2;
394 pThis->DrawPixel( Point(i, y), rStyleSettings.GetDarkShadowColor() );
395 pThis->DrawPixel( Point(i+1, y), rStyleSettings.GetShadowColor() );
397 pThis->DrawPixel( Point(i, y+1), rStyleSettings.GetShadowColor() );
398 pThis->DrawPixel( Point(i+1, y+1), rStyleSettings.GetFaceColor() );
399 pThis->DrawPixel( Point(i+2, y+1), Color(COL_WHITE) );
401 pThis->DrawPixel( Point(i+1, y+2), Color(COL_WHITE) );
402 pThis->DrawPixel( Point(i+2, y+2), Color(COL_WHITE) );
403 i+=4;
409 void ToolBox::ImplDrawGradientBackground( ToolBox* pThis, ImplDockingWindowWrapper * )
411 // draw a nice gradient
413 Color startCol, endCol;
414 startCol = pThis->GetSettings().GetStyleSettings().GetFaceGradientColor();
415 endCol = pThis->GetSettings().GetStyleSettings().GetFaceColor();
416 if( endCol.IsDark() )
417 // no 'extreme' gradient when high contrast
418 startCol = endCol;
420 Gradient g;
421 g.SetAngle( pThis->mbHorz ? 0 : 900 );
422 g.SetStyle( GRADIENT_LINEAR );
424 g.SetStartColor( startCol );
425 g.SetEndColor( endCol );
427 BOOL bLineColor = pThis->IsLineColor();
428 Color aOldCol = pThis->GetLineColor();
429 pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
431 Size aFullSz( pThis->GetOutputSizePixel() );
432 Size aLineSz( aFullSz );
434 // use the linesize only when floating
435 // full window height is used when docked (single line)
436 if( pThis->ImplIsFloatingMode() )
438 long nLineSize;
439 if( pThis->mbHorz )
441 nLineSize = pThis->mnMaxItemHeight;
442 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
443 nLineSize = pThis->mnWinHeight;
445 aLineSz.Height() = nLineSize;
447 else
449 nLineSize = pThis->mnMaxItemWidth;
450 aLineSz.Width() = nLineSize;
454 long nLeft, nTop, nRight, nBottom;
455 ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
457 Size aTopLineSz( aLineSz );
458 Size aBottomLineSz( aLineSz );
460 if ( pThis->mnWinStyle & WB_BORDER )
462 if( pThis->mbHorz )
464 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nTop;
465 aBottomLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
467 if( pThis->mnCurLines == 1 )
468 aTopLineSz.Height() += TB_BORDER_OFFSET2 + nBottom;
470 else
472 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
473 aBottomLineSz.Width() += TB_BORDER_OFFSET1 + nRight;
475 if( pThis->mnCurLines == 1 )
476 aTopLineSz.Width() += TB_BORDER_OFFSET1 + nLeft;
480 if( pThis->mbHorz )
482 aTopLineSz.Height() += pThis->mnBorderY;
483 if( pThis->mnCurLines == 1 )
484 aTopLineSz.Height() += pThis->mnBorderY;
486 aBottomLineSz.Height() += pThis->mnBorderY;
488 else
490 aTopLineSz.Width() += pThis->mnBorderX;
491 if( pThis->mnCurLines == 1 )
492 aTopLineSz.Width() += pThis->mnBorderX;
494 aBottomLineSz.Width() += pThis->mnBorderX;
498 if ( pThis->mnWinStyle & WB_LINESPACING )
500 if( pThis->mbHorz )
502 aLineSz.Height() += TB_LINESPACING;
503 if( pThis->mnCurLines > 1 )
504 aTopLineSz.Height() += TB_LINESPACING;
506 else
508 aLineSz.Width() += TB_LINESPACING;
509 if( pThis->mnCurLines > 1 )
510 aTopLineSz.Width() += TB_LINESPACING;
514 if( pThis->mbHorz )
516 long y = 0;
517 BOOL bDrawSep = FALSE; // pThis->ImplIsFloatingMode() && ( pThis->mnWinStyle & WB_LINESPACING );
519 pThis->DrawGradient( Rectangle( 0, y, aTopLineSz.Width(), y+aTopLineSz.Height()), g );
520 y += aTopLineSz.Height();
522 if ( bDrawSep )
523 pThis->DrawLine( Point(0, y-2), Point(aTopLineSz.Width(), y-2) );
525 while( y < (pThis->mnDY - aBottomLineSz.Height()) )
527 pThis->DrawGradient( Rectangle( 0, y, aLineSz.Width(), y+aLineSz.Height()), g);
528 y += aLineSz.Height();
530 if ( bDrawSep )
531 pThis->DrawLine( Point(0, y-2), Point(aLineSz.Width(), y-2) );
534 pThis->DrawGradient( Rectangle( 0, y, aBottomLineSz.Width(), y+aBottomLineSz.Height()), g );
535 if ( bDrawSep )
536 pThis->DrawLine( Point(0, y-2), Point(aBottomLineSz.Width(), y-2) );
538 else
540 long x = 0;
542 pThis->DrawGradient( Rectangle( x, 0, x+aTopLineSz.Width(), aTopLineSz.Height()), g );
543 x += aTopLineSz.Width();
545 while( x < (pThis->mnDX - aBottomLineSz.Width()) )
547 pThis->DrawGradient( Rectangle( x, 0, x+aLineSz.Width(), aLineSz.Height()), g);
548 x += aLineSz.Width();
551 pThis->DrawGradient( Rectangle( x, 0, x+aBottomLineSz.Width(), aBottomLineSz.Height()), g );
554 if( bLineColor )
555 pThis->SetLineColor( aOldCol );
559 BOOL ToolBox::ImplDrawNativeBackground( ToolBox* pThis, const Region & )
561 // use NWF
562 Point aPt;
563 Region aCtrlRegion( Rectangle( aPt, pThis->GetOutputSizePixel() ) );
564 ControlState nState = CTRL_STATE_ENABLED;
566 return pThis->DrawNativeControl( CTRL_TOOLBAR, pThis->mbHorz ? PART_DRAW_BACKGROUND_HORZ : PART_DRAW_BACKGROUND_VERT,
567 aCtrlRegion, nState, ImplControlValue(), rtl::OUString() );
570 void ToolBox::ImplDrawTransparentBackground( ToolBox* pThis, const Region &rRegion )
572 // just invalidate to trigger paint of the parent
574 const bool bOldPaintLock = pThis->mpData->mbIsPaintLocked;
575 pThis->mpData->mbIsPaintLocked = true;
577 // send an invalidate to the first opaque parent and invalidate the whole hierarchy from there (noclipchildren)
578 pThis->Invalidate( rRegion, INVALIDATE_UPDATE|INVALIDATE_NOCLIPCHILDREN );
580 pThis->mpData->mbIsPaintLocked = bOldPaintLock;
583 void ToolBox::ImplDrawConstantBackground( ToolBox* pThis, const Region &rRegion, BOOL bIsInPopupMode )
585 // draw a constant color
586 if( !bIsInPopupMode )
587 // default background
588 pThis->Erase( rRegion.GetBoundRect() );
589 else
591 // use different color in popupmode
592 pThis->DrawWallpaper( rRegion.GetBoundRect(),
593 Wallpaper( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() ) );
598 void ToolBox::ImplDrawBackground( ToolBox* pThis, const Rectangle &rRect )
600 // execute pending paint requests
601 ImplCheckUpdate( pThis );
603 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
604 BOOL bIsInPopupMode = pThis->ImplIsInPopupMode();
606 Region aPaintRegion( rRect );
608 // make sure we do not invalidate/erase too much
609 if( pThis->IsInPaint() )
610 aPaintRegion.Intersect( pThis->GetActiveClipRegion() );
612 pThis->Push( PUSH_CLIPREGION );
613 pThis->IntersectClipRegion( aPaintRegion );
616 if( !pWrapper /*|| bIsInPopupMode*/ )
618 // no gradient for ordinary toolbars (not dockable)
619 if( !pThis->IsBackground() && !pThis->IsInPaint() )
620 ImplDrawTransparentBackground( pThis, aPaintRegion );
621 else
622 ImplDrawConstantBackground( pThis, aPaintRegion, bIsInPopupMode );
624 else
626 // toolbars known to the dockingmanager will be drawn using NWF or a gradient
627 // docked toolbars are transparent and NWF is already used in the docking area which is their common background
628 // so NWF is used here for floating toolbars only
629 BOOL bNativeOk = FALSE;
630 if( pThis->ImplIsFloatingMode() && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL) )
631 bNativeOk = ImplDrawNativeBackground( pThis, aPaintRegion );
633 if( !bNativeOk )
635 if( !pThis->IsBackground() )
637 if( !pThis->IsInPaint() )
638 ImplDrawTransparentBackground( pThis, aPaintRegion );
640 else
641 ImplDrawGradientBackground( pThis, pWrapper );
645 // restore clip region
646 pThis->Pop();
649 void ToolBox::ImplErase( ToolBox* pThis, const Rectangle &rRect, BOOL bHighlight, BOOL bHasOpenPopup )
651 // the background of non NWF buttons is painted in a constant color
652 // to have the same highlight color (transparency in DrawSelectionBackground())
653 // items with open popups will also painted using a constant color
654 if( !pThis->mpData->mbNativeButtons &&
655 (bHighlight || ! (((Window*) pThis)->GetStyle() & WB_3DLOOK ) ) )
657 if( (((Window*) pThis)->GetStyle() & WB_3DLOOK ) )
659 pThis->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
660 pThis->SetLineColor();
661 if( bHasOpenPopup )
662 // choose the same color as the popup will use
663 pThis->SetFillColor( pThis->GetSettings().GetStyleSettings().GetFaceGradientColor() );
664 else
665 pThis->SetFillColor( Color( COL_WHITE ) );
667 pThis->DrawRect( rRect );
668 pThis->Pop();
670 else
671 ImplDrawBackground( pThis, rRect );
673 else
674 ImplDrawBackground( pThis, rRect );
677 void ToolBox::ImplDrawBorder( ToolBox* pWin )
679 const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
680 long nDX = pWin->mnDX;
681 long nDY = pWin->mnDY;
683 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pWin );
685 // draw borders for ordinary toolbars only (not dockable)
686 if( pWrapper )
687 return;
689 if ( pWin->meAlign == WINDOWALIGN_BOTTOM )
691 // draw bottom border
692 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
693 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
694 pWin->SetLineColor( rStyleSettings.GetLightColor() );
695 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
697 else
699 // draw top border
700 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
701 pWin->DrawLine( Point( 0, 0 ), Point( nDX-1, 0 ) );
702 pWin->SetLineColor( rStyleSettings.GetLightColor() );
703 pWin->DrawLine( Point( 0, 1 ), Point( nDX-1, 1 ) );
705 if ( (pWin->meAlign == WINDOWALIGN_LEFT) || (pWin->meAlign == WINDOWALIGN_RIGHT) )
707 if ( pWin->meAlign == WINDOWALIGN_LEFT )
709 // draw left-bottom border
710 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
711 pWin->DrawLine( Point( 0, 0 ), Point( 0, nDY-1 ) );
712 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-1, nDY-2 ) );
713 pWin->SetLineColor( rStyleSettings.GetLightColor() );
714 pWin->DrawLine( Point( 1, 1 ), Point( 1, nDY-3 ) );
715 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
717 else
719 // draw right-bottom border
720 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
721 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-3 ) );
722 pWin->DrawLine( Point( 0, nDY-2 ), Point( nDX-2, nDY-2 ) );
723 pWin->SetLineColor( rStyleSettings.GetLightColor() );
724 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
725 pWin->DrawLine( Point( 0, nDY-1 ), Point( nDX-1, nDY-1 ) );
731 if ( pWin->meAlign == WINDOWALIGN_BOTTOM || pWin->meAlign == WINDOWALIGN_TOP )
733 // draw right border
734 pWin->SetLineColor( rStyleSettings.GetShadowColor() );
735 pWin->DrawLine( Point( nDX-2, 0 ), Point( nDX-2, nDY-1 ) );
736 pWin->SetLineColor( rStyleSettings.GetLightColor() );
737 pWin->DrawLine( Point( nDX-1, 0 ), Point( nDX-1, nDY-1 ) );
741 // -----------------------------------------------------------------------
743 static bool ImplIsFixedControl( const ImplToolItem *pItem )
745 return ( pItem->mpWindow &&
746 (pItem->mpWindow->GetType() == WINDOW_FIXEDTEXT ||
747 pItem->mpWindow->GetType() == WINDOW_FIXEDLINE ||
748 pItem->mpWindow->GetType() == WINDOW_GROUPBOX) );
751 // -----------------------------------------------------------------------
753 const ImplToolItem *ToolBox::ImplGetFirstClippedItem( const ToolBox* pThis )
755 std::vector< ImplToolItem >::const_iterator it;
756 it = pThis->mpData->m_aItems.begin();
757 while ( it != pThis->mpData->m_aItems.end() )
759 if( it->IsClipped() )
760 return &(*it);
761 ++it;
763 return NULL;
766 // -----------------------------------------------------------------------
768 Size ToolBox::ImplCalcSize( const ToolBox* pThis, USHORT nCalcLines, USHORT nCalcMode )
770 long nMax;
771 long nLeft = 0;
772 long nTop = 0;
773 long nRight = 0;
774 long nBottom = 0;
775 Size aSize;
776 WindowAlign eOldAlign = pThis->meAlign;
777 BOOL bOldHorz = pThis->mbHorz;
778 BOOL bOldAssumeDocked = pThis->mpData->mbAssumeDocked;
779 BOOL bOldAssumeFloating = pThis->mpData->mbAssumeFloating;
781 if ( nCalcMode )
783 BOOL bOldFloatingMode = pThis->ImplIsFloatingMode();
785 pThis->mpData->mbAssumeDocked = FALSE;
786 pThis->mpData->mbAssumeFloating = FALSE;
788 if ( nCalcMode == TB_CALCMODE_HORZ )
790 pThis->mpData->mbAssumeDocked = TRUE; // force non-floating mode during calculation
791 ImplCalcBorder( WINDOWALIGN_TOP, nLeft, nTop, nRight, nBottom, pThis );
792 ((ToolBox*)pThis)->mbHorz = TRUE;
793 if ( pThis->mbHorz != bOldHorz )
794 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
796 else if ( nCalcMode == TB_CALCMODE_VERT )
798 pThis->mpData->mbAssumeDocked = TRUE; // force non-floating mode during calculation
799 ImplCalcBorder( WINDOWALIGN_LEFT, nLeft, nTop, nRight, nBottom, pThis );
800 ((ToolBox*)pThis)->mbHorz = FALSE;
801 if ( pThis->mbHorz != bOldHorz )
802 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_LEFT;
804 else if ( nCalcMode == TB_CALCMODE_FLOAT )
806 pThis->mpData->mbAssumeFloating = TRUE; // force non-floating mode during calculation
807 nLeft = nTop = nRight = nBottom = 0;
808 ((ToolBox*)pThis)->mbHorz = TRUE;
809 if ( pThis->mbHorz != bOldHorz )
810 ((ToolBox*)pThis)->meAlign = WINDOWALIGN_TOP;
813 if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) ||
814 (pThis->ImplIsFloatingMode() != bOldFloatingMode ) )
815 ((ToolBox*)pThis)->mbCalc = TRUE;
817 else
818 ImplCalcBorder( pThis->meAlign, nLeft, nTop, nRight, nBottom, pThis );
820 ((ToolBox*)pThis)->ImplCalcItem();
822 if( !nCalcMode && pThis->ImplIsFloatingMode() )
824 aSize = ImplCalcFloatSize( ((ToolBox*)pThis), nCalcLines );
826 else
828 if ( pThis->mbHorz )
830 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
831 aSize.Height() = nCalcLines * pThis->mnWinHeight;
832 else
833 aSize.Height() = nCalcLines * pThis->mnMaxItemHeight;
835 if ( pThis->mnWinStyle & WB_LINESPACING )
836 aSize.Height() += (nCalcLines-1)*TB_LINESPACING;
838 if ( pThis->mnWinStyle & WB_BORDER )
839 aSize.Height() += (TB_BORDER_OFFSET2*2) + nTop + nBottom;
841 nMax = 0;
842 ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
843 if ( nMax )
844 aSize.Width() += nMax;
846 if ( pThis->mnWinStyle & WB_BORDER )
847 aSize.Width() += (TB_BORDER_OFFSET1*2) + nLeft + nRight;
849 else
851 aSize.Width() = nCalcLines * pThis->mnMaxItemWidth;
853 if ( pThis->mnWinStyle & WB_LINESPACING )
854 aSize.Width() += (nCalcLines-1)*TB_LINESPACING;
856 if ( pThis->mnWinStyle & WB_BORDER )
857 aSize.Width() += (TB_BORDER_OFFSET2*2) + nLeft + nRight;
859 nMax = 0;
860 ((ToolBox*)pThis)->ImplCalcBreaks( TB_MAXNOSCROLL, &nMax, pThis->mbHorz );
861 if ( nMax )
862 aSize.Height() += nMax;
864 if ( pThis->mnWinStyle & WB_BORDER )
865 aSize.Height() += (TB_BORDER_OFFSET1*2) + nTop + nBottom;
868 // restore previous values
869 if ( nCalcMode )
871 pThis->mpData->mbAssumeDocked = bOldAssumeDocked;
872 pThis->mpData->mbAssumeFloating = bOldAssumeFloating;
873 if ( (pThis->meAlign != eOldAlign) || (pThis->mbHorz != bOldHorz) )
875 ((ToolBox*)pThis)->meAlign = eOldAlign;
876 ((ToolBox*)pThis)->mbHorz = bOldHorz;
877 ((ToolBox*)pThis)->mbCalc = TRUE;
881 if ( aSize.Width() )
882 aSize.Width() += pThis->mnBorderX*2;
883 if ( aSize.Height() )
884 aSize.Height() += pThis->mnBorderY*2;
886 return aSize;
889 // -----------------------------------------------------------------------
891 void ToolBox::ImplCalcFloatSizes( ToolBox* pThis )
893 if ( pThis->mpFloatSizeAry )
894 return;
896 // calculate the minimal size, i.e. where the biggest item just fits
897 long nCalcSize = 0;
899 std::vector< ImplToolItem >::const_iterator it;
900 it = pThis->mpData->m_aItems.begin();
901 while ( it != pThis->mpData->m_aItems.end() )
903 if ( it->mbVisible )
905 if ( it->mpWindow )
907 long nTempSize = it->mpWindow->GetSizePixel().Width();
908 if ( nTempSize > nCalcSize )
909 nCalcSize = nTempSize;
911 else
913 if( it->maItemSize.Width() > nCalcSize )
914 nCalcSize = it->maItemSize.Width();
917 ++it;
920 // calc an upper bound for ImplCalcBreaks below
921 long upperBoundWidth = nCalcSize * pThis->mpData->m_aItems.size();
923 USHORT i;
924 USHORT nLines;
925 USHORT nCalcLines;
926 USHORT nTempLines;
927 long nHeight;
928 long nMaxLineWidth;
929 nCalcLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, TRUE );
931 pThis->mpFloatSizeAry = new ImplToolSizeArray;
932 pThis->mpFloatSizeAry->mpSize = new ImplToolSize[nCalcLines];
933 pThis->mpFloatSizeAry->mnLength = nCalcLines;
935 memset( pThis->mpFloatSizeAry->mpSize, 0, sizeof( ImplToolSize )*nCalcLines );
936 i = 0;
937 nTempLines = nLines = nCalcLines;
938 while ( nLines )
940 nHeight = ImplCalcSize( pThis, nTempLines, TB_CALCMODE_FLOAT ).Height();
941 pThis->mpFloatSizeAry->mnLastEntry = i;
942 pThis->mpFloatSizeAry->mpSize[i].mnHeight = nHeight;
943 pThis->mpFloatSizeAry->mpSize[i].mnLines = nTempLines;
944 pThis->mpFloatSizeAry->mpSize[i].mnWidth = nMaxLineWidth+(TB_BORDER_OFFSET1*2);
945 nLines--;
946 if ( nLines )
950 nCalcSize += pThis->mnMaxItemWidth;
951 nTempLines = pThis->ImplCalcBreaks( nCalcSize, &nMaxLineWidth, TRUE );
953 while ( (nCalcSize < upperBoundWidth) && (nLines < nTempLines) && (nTempLines != 1) );
954 if ( nTempLines < nLines )
955 nLines = nTempLines;
957 i++;
961 // -----------------------------------------------------------------------
963 Size ToolBox::ImplCalcFloatSize( ToolBox* pThis, USHORT& rLines )
965 ImplCalcFloatSizes( pThis );
967 if ( !rLines )
969 rLines = pThis->mnFloatLines;
970 if ( !rLines )
971 rLines = pThis->mnLines;
974 USHORT i = 0;
975 while ( i < pThis->mpFloatSizeAry->mnLastEntry &&
976 rLines < pThis->mpFloatSizeAry->mpSize[i].mnLines )
977 i++;
979 Size aSize( pThis->mpFloatSizeAry->mpSize[i].mnWidth,
980 pThis->mpFloatSizeAry->mpSize[i].mnHeight );
981 rLines = pThis->mpFloatSizeAry->mpSize[i].mnLines;
982 if ( pThis->maNextToolBoxStr.Len() && pThis->mbScroll )
983 aSize.Width() += TB_NEXT_SIZE-TB_NEXT_OFFSET;
984 return aSize;
987 // -----------------------------------------------------------------------
989 void ToolBox::ImplCalcMinMaxFloatSize( ToolBox* pThis, Size& rMinSize, Size& rMaxSize )
991 ImplCalcFloatSizes( pThis );
993 USHORT i = 0;
994 rMinSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
995 rMaxSize = Size( pThis->mpFloatSizeAry->mpSize[i].mnWidth, pThis->mpFloatSizeAry->mpSize[i].mnHeight );
996 while ( ++i <= pThis->mpFloatSizeAry->mnLastEntry )
998 if( pThis->mpFloatSizeAry->mpSize[i].mnWidth < rMinSize.Width() )
999 rMinSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
1000 if( pThis->mpFloatSizeAry->mpSize[i].mnHeight < rMinSize.Height() )
1001 rMinSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
1003 if( pThis->mpFloatSizeAry->mpSize[i].mnWidth > rMaxSize.Width() )
1004 rMaxSize.Width() = pThis->mpFloatSizeAry->mpSize[i].mnWidth;
1005 if( pThis->mpFloatSizeAry->mpSize[i].mnHeight > rMaxSize.Height() )
1006 rMaxSize.Height() = pThis->mpFloatSizeAry->mpSize[i].mnHeight;
1010 void ToolBox::ImplSetMinMaxFloatSize( ToolBox *pThis )
1012 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( pThis );
1013 Size aMinSize, aMaxSize;
1014 ImplCalcMinMaxFloatSize( pThis, aMinSize, aMaxSize );
1015 if( pWrapper )
1017 pWrapper->SetMinOutputSizePixel( aMinSize );
1018 pWrapper->SetMaxOutputSizePixel( aMaxSize );
1019 pWrapper->ShowTitleButton( TITLE_BUTTON_MENU, ( pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) ? TRUE : FALSE );
1021 else
1023 // TODO: change SetMinOutputSizePixel to be not inline
1024 pThis->SetMinOutputSizePixel( aMinSize );
1025 pThis->SetMaxOutputSizePixel( aMaxSize );
1029 // -----------------------------------------------------------------------
1032 USHORT ToolBox::ImplCalcLines( ToolBox* pThis, long nToolSize )
1034 long nLineHeight;
1036 if ( pThis->mbHorz )
1038 if ( pThis->mnWinHeight > pThis->mnMaxItemHeight )
1039 nLineHeight = pThis->mnWinHeight;
1040 else
1041 nLineHeight = pThis->mnMaxItemHeight;
1043 else
1044 nLineHeight = pThis->mnMaxItemWidth;
1046 if ( pThis->mnWinStyle & WB_BORDER )
1047 nToolSize -= TB_BORDER_OFFSET2*2;
1049 if ( pThis->mnWinStyle & WB_LINESPACING )
1051 nLineHeight += TB_LINESPACING;
1052 nToolSize += TB_LINESPACING;
1055 // #i91917# always report at least one line
1056 long nLines = nToolSize/nLineHeight;
1057 if( nLines < 1 )
1058 nLines = 1;
1060 return static_cast<USHORT>(nLines);
1063 // -----------------------------------------------------------------------
1065 USHORT ToolBox::ImplTestLineSize( ToolBox* pThis, const Point& rPos )
1067 if ( !pThis->ImplIsFloatingMode() &&
1068 (!pThis->mbScroll || (pThis->mnLines > 1) || (pThis->mnCurLines > pThis->mnVisLines)) )
1070 WindowAlign eAlign = pThis->GetAlign();
1072 if ( eAlign == WINDOWALIGN_LEFT )
1074 if ( rPos.X() > pThis->mnDX-DOCK_LINEOFFSET )
1075 return DOCK_LINEHSIZE | DOCK_LINERIGHT;
1077 else if ( eAlign == WINDOWALIGN_TOP )
1079 if ( rPos.Y() > pThis->mnDY-DOCK_LINEOFFSET )
1080 return DOCK_LINEVSIZE | DOCK_LINEBOTTOM;
1082 else if ( eAlign == WINDOWALIGN_RIGHT )
1084 if ( rPos.X() < DOCK_LINEOFFSET )
1085 return DOCK_LINEHSIZE | DOCK_LINELEFT;
1087 else if ( eAlign == WINDOWALIGN_BOTTOM )
1089 if ( rPos.Y() < DOCK_LINEOFFSET )
1090 return DOCK_LINEVSIZE | DOCK_LINETOP;
1094 return 0;
1097 // -----------------------------------------------------------------------
1099 void ToolBox::ImplLineSizing( ToolBox* pThis, const Point& rPos, Rectangle& rRect,
1100 USHORT nLineMode )
1102 BOOL mbHorz;
1103 long nOneLineSize;
1104 long nCurSize;
1105 long nMaxSize;
1106 long nSize;
1107 Size aSize;
1109 if ( nLineMode & DOCK_LINERIGHT )
1111 nCurSize = rPos.X() - rRect.Left();
1112 mbHorz = FALSE;
1114 else if ( nLineMode & DOCK_LINEBOTTOM )
1116 nCurSize = rPos.Y() - rRect.Top();
1117 mbHorz = TRUE;
1119 else if ( nLineMode & DOCK_LINELEFT )
1121 nCurSize = rRect.Right() - rPos.X();
1122 mbHorz = FALSE;
1124 else if ( nLineMode & DOCK_LINETOP )
1126 nCurSize = rRect.Bottom() - rPos.Y();
1127 mbHorz = TRUE;
1129 else {
1130 DBG_ERROR( "ImplLineSizing: Trailing else" );
1131 nCurSize = 0;
1132 mbHorz = FALSE;
1135 Size aWinSize = pThis->GetSizePixel();
1136 USHORT nMaxLines = (pThis->mnLines > pThis->mnCurLines) ? pThis->mnLines : pThis->mnCurLines;
1137 if ( nMaxLines > TB_MAXLINES )
1138 nMaxLines = TB_MAXLINES;
1139 if ( mbHorz )
1141 nOneLineSize = ImplCalcSize( pThis, 1 ).Height();
1142 nMaxSize = pThis->maOutDockRect.GetHeight() - 20;
1143 if ( nMaxSize < aWinSize.Height() )
1144 nMaxSize = aWinSize.Height();
1146 else
1148 nOneLineSize = ImplCalcSize( pThis, 1 ).Width();
1149 nMaxSize = pThis->maOutDockRect.GetWidth() - 20;
1150 if ( nMaxSize < aWinSize.Width() )
1151 nMaxSize = aWinSize.Width();
1154 USHORT i = 1;
1155 if ( nCurSize <= nOneLineSize )
1156 nSize = nOneLineSize;
1157 else
1159 nSize = 0;
1160 while ( (nSize < nCurSize) && (i < nMaxLines) )
1162 i++;
1163 aSize = ImplCalcSize( pThis, i );
1164 if ( mbHorz )
1165 nSize = aSize.Height();
1166 else
1167 nSize = aSize.Width();
1168 if ( nSize > nMaxSize )
1170 i--;
1171 aSize = ImplCalcSize( pThis, i );
1172 if ( mbHorz )
1173 nSize = aSize.Height();
1174 else
1175 nSize = aSize.Width();
1176 break;
1181 if ( nLineMode & DOCK_LINERIGHT )
1182 rRect.Right() = rRect.Left()+nSize-1;
1183 else if ( nLineMode & DOCK_LINEBOTTOM )
1184 rRect.Bottom() = rRect.Top()+nSize-1;
1185 else if ( nLineMode & DOCK_LINELEFT )
1186 rRect.Left() = rRect.Right()-nSize;
1187 else //if ( nLineMode & DOCK_LINETOP )
1188 rRect.Top() = rRect.Bottom()-nSize;
1190 pThis->mnDockLines = i;
1193 // -----------------------------------------------------------------------
1195 USHORT ToolBox::ImplFindItemPos( ToolBox* pBox, const Point& rPos )
1197 USHORT nPos = 0;
1198 long nLast = 0;
1199 Point aPos = rPos;
1200 Size aSize( pBox->mnDX, pBox->mnDY );
1202 if ( aPos.X() > aSize.Width()-TB_BORDER_OFFSET1 )
1203 aPos.X() = aSize.Width()-TB_BORDER_OFFSET1;
1204 if ( aPos.Y() > aSize.Height()-TB_BORDER_OFFSET1 )
1205 aPos.Y() = aSize.Height()-TB_BORDER_OFFSET1;
1207 // Item suchen, das geklickt wurde
1208 std::vector< ImplToolItem >::const_iterator it = pBox->mpData->m_aItems.begin();
1209 while ( it != pBox->mpData->m_aItems.end() )
1211 if ( it->mbVisible )
1213 if ( nLast || !it->maRect.IsEmpty() )
1215 if ( pBox->mbHorz )
1217 if ( nLast &&
1218 ((nLast < it->maRect.Top()) || it->maRect.IsEmpty()) )
1219 return nPos;
1221 if ( aPos.Y() <= it->maRect.Bottom() )
1223 if ( aPos.X() < it->maRect.Left() )
1224 return nPos;
1225 else if ( aPos.X() < it->maRect.Right() )
1226 return nPos+1;
1227 else if ( !nLast )
1228 nLast = it->maRect.Bottom();
1231 else
1233 if ( nLast &&
1234 ((nLast < it->maRect.Left()) || it->maRect.IsEmpty()) )
1235 return nPos;
1237 if ( aPos.X() <= it->maRect.Right() )
1239 if ( aPos.Y() < it->maRect.Top() )
1240 return nPos;
1241 else if ( aPos.Y() < it->maRect.Bottom() )
1242 return nPos+1;
1243 else if ( !nLast )
1244 nLast = it->maRect.Right();
1250 nPos++;
1251 ++it;
1254 return nPos;
1257 // -----------------------------------------------------------------------
1259 ImplTBDragMgr::ImplTBDragMgr()
1261 mpBoxList = new ImplTBList( 4, 4 );
1262 mnLineMode = 0;
1263 mnStartLines = 0;
1264 mbCustomizeMode = FALSE;
1265 mbResizeMode = FALSE;
1266 mbShowDragRect = FALSE;
1267 mpDragBox = NULL;
1269 maAccel.InsertItem( KEY_RETURN, KeyCode( KEY_RETURN ) );
1270 maAccel.InsertItem( KEY_ESCAPE, KeyCode( KEY_ESCAPE ) );
1271 maAccel.SetSelectHdl( LINK( this, ImplTBDragMgr, SelectHdl ) );
1274 // -----------------------------------------------------------------------
1276 ImplTBDragMgr::~ImplTBDragMgr()
1278 delete mpBoxList;
1281 // -----------------------------------------------------------------------
1283 ToolBox* ImplTBDragMgr::FindToolBox( const Rectangle& rRect )
1285 ToolBox* pBox = mpBoxList->First();
1286 while ( pBox )
1289 * FIXME: since we can have multiple frames now we cannot
1290 * find the drag target by its position alone.
1291 * As long as the toolbar config dialogue is not a system window
1292 * this works in one frame only anyway. If the dialogue
1293 * changes to a system window, we need a new implementation here
1295 if ( pBox->IsReallyVisible() && pBox->ImplGetWindowImpl()->mpFrame == mpDragBox->ImplGetWindowImpl()->mpFrame )
1297 if ( !pBox->ImplIsFloatingMode() )
1299 Point aPos = pBox->GetPosPixel();
1300 aPos = pBox->GetParent()->OutputToScreenPixel( aPos );
1301 Rectangle aTempRect( aPos, pBox->GetSizePixel() );
1302 if ( aTempRect.IsOver( rRect ) )
1303 return pBox;
1307 pBox = mpBoxList->Next();
1310 return pBox;
1313 // -----------------------------------------------------------------------
1315 void ImplTBDragMgr::StartDragging( ToolBox* pToolBox,
1316 const Point& rPos, const Rectangle& rRect,
1317 USHORT nDragLineMode, BOOL bResizeItem,
1318 void* pData )
1320 mpDragBox = pToolBox;
1321 pToolBox->CaptureMouse();
1322 pToolBox->mbDragging = TRUE;
1323 Application::InsertAccel( &maAccel );
1325 if ( nDragLineMode )
1327 mnLineMode = nDragLineMode;
1328 mnStartLines = pToolBox->mnDockLines;
1330 else
1332 mpCustomizeData = pData;
1333 mbResizeMode = bResizeItem;
1334 pToolBox->Activate();
1335 pToolBox->mnCurItemId = pToolBox->mnConfigItem;
1336 pToolBox->Highlight();
1337 pToolBox->mnCurItemId = 0;
1338 if ( mbResizeMode )
1340 if ( rRect.GetWidth() < TB_MIN_WIN_WIDTH )
1341 mnMinWidth = rRect.GetWidth();
1342 else
1343 mnMinWidth = TB_MIN_WIN_WIDTH;
1344 mnMaxWidth = pToolBox->GetSizePixel().Width()-rRect.Left()-
1345 TB_SPIN_SIZE-TB_BORDER_OFFSET1-(TB_SPIN_OFFSET*2);
1349 // MouseOffset berechnen
1350 maMouseOff.X() = rRect.Left() - rPos.X();
1351 maMouseOff.Y() = rRect.Top() - rPos.Y();
1352 maRect = rRect;
1353 maStartRect = rRect;
1354 mbShowDragRect = TRUE;
1355 pToolBox->ShowTracking( maRect );
1358 // -----------------------------------------------------------------------
1360 void ImplTBDragMgr::Dragging( const Point& rPos )
1362 if ( mnLineMode )
1364 ToolBox::ImplLineSizing( mpDragBox, rPos, maRect, mnLineMode );
1365 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1366 maRect.Move( aOff.X(), aOff.Y() );
1367 mpDragBox->Docking( rPos, maRect );
1368 maRect.Move( -aOff.X(), -aOff.Y() );
1369 mpDragBox->ShowTracking( maRect );
1371 else
1373 if ( mbResizeMode )
1375 long nXOff = rPos.X()-maStartRect.Left();
1376 nXOff += maMouseOff.X()+(maStartRect.Right()-maStartRect.Left());
1377 if ( nXOff < mnMinWidth )
1378 nXOff = mnMinWidth;
1379 if ( nXOff > mnMaxWidth )
1380 nXOff = mnMaxWidth;
1381 maRect.Right() = maStartRect.Left()+nXOff;
1383 else
1385 maRect.SetPos( rPos );
1386 maRect.Move( maMouseOff.X(), maMouseOff.Y() );
1388 mpDragBox->ShowTracking( maRect );
1392 // -----------------------------------------------------------------------
1394 void ImplTBDragMgr::EndDragging( BOOL bOK )
1396 mpDragBox->HideTracking();
1397 mpDragBox->ReleaseMouse();
1398 mpDragBox->mbDragging = FALSE;
1399 mbShowDragRect = FALSE;
1400 Application::RemoveAccel( &maAccel );
1402 if ( mnLineMode )
1404 if ( !bOK )
1406 mpDragBox->mnDockLines = mnStartLines;
1407 mpDragBox->EndDocking( maStartRect, FALSE );
1409 else
1410 mpDragBox->EndDocking( maRect, FALSE );
1411 mnLineMode = 0;
1412 mnStartLines = 0;
1414 else
1416 USHORT nTempItem = mpDragBox->mnConfigItem;
1417 if ( nTempItem )
1419 mpDragBox->mnConfigItem = 0;
1420 if ( !mbResizeMode )
1421 mpDragBox->Invalidate( mpDragBox->GetItemRect( nTempItem ) );
1424 if ( bOK && (maRect != maStartRect) )
1426 if ( mbResizeMode )
1428 ImplToolItem* pItem = mpDragBox->ImplGetItem( nTempItem );
1429 Size aSize = pItem->mpWindow->GetSizePixel();
1430 aSize.Width() = maRect.GetWidth();
1431 pItem->mpWindow->SetSizePixel( aSize );
1433 // ToolBox neu brechnen und neu ausgeben
1434 mpDragBox->ImplInvalidate( TRUE );
1435 mpDragBox->Customize( ToolBoxCustomizeEvent( mpDragBox, nTempItem,
1436 TOOLBOX_CUSTOMIZE_RESIZE,
1437 mpCustomizeData ) );
1439 else
1441 Point aOff = mpDragBox->OutputToScreenPixel( Point() );
1442 Rectangle aScreenRect( maRect );
1443 aScreenRect.Move( aOff.X(), aOff.Y() );
1444 ToolBox* pDropBox = FindToolBox( aScreenRect );
1445 if ( pDropBox )
1447 // Such-Position bestimmen
1448 Point aPos;
1449 if ( pDropBox->mbHorz )
1451 aPos.X() = aScreenRect.Left()-TB_CUSTOMIZE_OFFSET;
1452 aPos.Y() = aScreenRect.Center().Y();
1454 else
1456 aPos.X() = aScreenRect.Center().X();
1457 aPos.Y() = aScreenRect.Top()-TB_CUSTOMIZE_OFFSET;
1460 aPos = pDropBox->ScreenToOutputPixel( aPos );
1461 USHORT nPos = ToolBox::ImplFindItemPos( pDropBox, aPos );
1462 mpDragBox->Customize( ToolBoxCustomizeEvent( pDropBox, nTempItem,
1463 nPos, mpCustomizeData ) );
1465 else
1467 mpDragBox->Customize( ToolBoxCustomizeEvent( NULL, nTempItem,
1468 0, mpCustomizeData ) );
1472 mpCustomizeData = NULL;
1473 mbResizeMode = FALSE;
1474 mpDragBox->Deactivate();
1477 mpDragBox = NULL;
1480 // -----------------------------------------------------------------------
1482 void ImplTBDragMgr::UpdateDragRect()
1484 // Nur Updaten, wenn wir schon im Dragging sind
1485 if ( !mbShowDragRect )
1486 return;
1488 mpDragBox->ShowTracking( maRect );
1491 // -----------------------------------------------------------------------
1493 IMPL_LINK( ImplTBDragMgr, SelectHdl, Accelerator*, pAccel )
1495 if ( pAccel->GetCurItemId() == KEY_ESCAPE )
1496 EndDragging( FALSE );
1497 else
1498 EndDragging( TRUE );
1500 return TRUE;
1503 // -----------------------------------------------------------------------
1505 void ImplTBDragMgr::StartCustomizeMode()
1507 mbCustomizeMode = TRUE;
1509 ToolBox* pBox = mpBoxList->First();
1510 while ( pBox )
1512 pBox->ImplStartCustomizeMode();
1513 pBox = mpBoxList->Next();
1517 // -----------------------------------------------------------------------
1519 void ImplTBDragMgr::EndCustomizeMode()
1521 mbCustomizeMode = FALSE;
1523 ToolBox* pBox = mpBoxList->First();
1524 while ( pBox )
1526 pBox->ImplEndCustomizeMode();
1527 pBox = mpBoxList->Next();
1531 // -----------------------------------------------------------------------
1534 static void ImplDrawOutButton( OutputDevice* pOutDev, const Rectangle& rRect,
1535 USHORT nStyle )
1537 const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings();
1538 Color aShadowColor = rStyleSettings.GetShadowColor();
1539 Point aPos( rRect.TopLeft() );
1540 Size aSize( rRect.GetSize() );
1541 long nOffset = 0;
1543 if ( pOutDev->GetBackground().GetColor() == aShadowColor )
1544 aShadowColor = rStyleSettings.GetDarkShadowColor();
1546 if ( nStyle & BUTTON_DRAW_PRESSED )
1548 aPos.X()++;
1549 aPos.Y()++;
1550 nOffset++;
1553 // Hintergrund loeschen
1554 pOutDev->Erase( rRect );
1556 // Button zeichnen
1557 pOutDev->SetLineColor( rStyleSettings.GetLightColor() );
1558 pOutDev->DrawLine( aPos,
1559 Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ) );
1560 pOutDev->DrawLine( aPos,
1561 Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1562 pOutDev->SetLineColor( aShadowColor );
1563 pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y() ),
1564 Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1565 pOutDev->DrawLine( Point( aPos.X(), aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ),
1566 Point( aPos.X()+aSize.Width()-OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-OUTBUTTON_BORDER ) );
1567 for ( long i = 0; i < OUTBUTTON_BORDER-1-nOffset; i++ )
1569 pOutDev->DrawLine( Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+OUTBUTTON_BORDER ),
1570 Point( aPos.X()+aSize.Width()-(OUTBUTTON_BORDER-i-1), aPos.Y()+aSize.Height()-1 ) );
1571 pOutDev->DrawLine( Point( aPos.X()+OUTBUTTON_BORDER, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ),
1572 Point( aPos.X()+aSize.Width()-1, aPos.Y()+aSize.Height()-(OUTBUTTON_BORDER-i-1) ) );
1577 // -----------------------------------------------------------------------
1579 void ToolBox::ImplInit( Window* pParent, WinBits nStyle )
1582 // Variablen initialisieren
1583 ImplGetWindowImpl()->mbToolBox = TRUE;
1584 mpBtnDev = NULL;
1585 mpFloatSizeAry = NULL;
1586 mpData = new ImplToolBoxPrivateData;
1587 mpFloatWin = NULL;
1588 mnDX = 0;
1589 mnDY = 0;
1590 mnMaxItemWidth = 0;
1591 mnMaxItemHeight = 0;
1592 mnWinHeight = 0;
1593 mnBorderX = 0;
1594 mnBorderY = 0;
1595 mnLeftBorder = 0;
1596 mnTopBorder = 0;
1597 mnRightBorder = 0;
1598 mnBottomBorder = 0;
1599 mnLastResizeDY = 0;
1600 mnOutStyle = TOOLBOX_STYLE_FLAT; // force flat buttons since NWF
1601 mnHighItemId = 0;
1602 mnCurItemId = 0;
1603 mnDownItemId = 0;
1604 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1605 mnFocusPos = TOOLBOX_ITEM_NOTFOUND; // current position during keyboard access
1606 mnLines = 1;
1607 mnCurLine = 1;
1608 mnCurLines = 1;
1609 mnVisLines = 1;
1610 mnFloatLines = 0;
1611 mnConfigItem = 0;
1612 mnMouseClicks = 0;
1613 mnMouseModifier = 0;
1614 mbDrag = FALSE;
1615 mbSelection = FALSE;
1616 mbCommandDrag = FALSE;
1617 mbUpper = FALSE;
1618 mbLower = FALSE;
1619 mbNextTool = FALSE;
1620 mbIn = FALSE;
1621 mbCalc = TRUE;
1622 mbFormat = FALSE;
1623 mbFullPaint = FALSE;
1624 mbHorz = TRUE;
1625 mbScroll = (nStyle & WB_SCROLL) != 0;
1626 mbCustomize = FALSE;
1627 mbCustomizeMode = FALSE;
1628 mbDragging = FALSE;
1629 mbHideStatusText = FALSE;
1630 mbMenuStrings = FALSE;
1631 mbIsShift = FALSE;
1632 mbIsKeyEvent = FALSE;
1633 mbChangingHighlight = FALSE;
1634 meButtonType = BUTTON_SYMBOL;
1635 meAlign = WINDOWALIGN_TOP;
1636 meLastStyle = POINTER_ARROW;
1637 mnWinStyle = nStyle;
1638 mnLastFocusItemId = 0;
1639 mnKeyModifier = 0;
1640 mnActivateCount = 0;
1642 maTimer.SetTimeout( 50 );
1643 maTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplUpdateHdl ) );
1645 // set timeout and handler for dropdown items
1646 mpData->maDropdownTimer.SetTimeout( 250 );
1647 mpData->maDropdownTimer.SetTimeoutHdl( LINK( this, ToolBox, ImplDropdownLongClickHdl ) );
1649 DockingWindow::ImplInit( pParent, nStyle & ~(WB_BORDER) );
1652 // always set WB_TABSTOP for ToolBars !!! if( mnWinStyle & WB_TABSTOP )
1654 // dockingwindow's ImplInit removes some bits, so restore them here
1655 // to allow keyboard handling for toolbars
1656 ImplGetWindowImpl()->mnStyle |= WB_TABSTOP|WB_NODIALOGCONTROL;
1657 ImplGetWindowImpl()->mnStyle &= ~WB_DIALOGCONTROL;
1660 ImplInitSettings( TRUE, TRUE, TRUE );
1663 // -----------------------------------------------------------------------
1665 void ToolBox::ImplInitSettings( BOOL bFont,
1666 BOOL bForeground, BOOL bBackground )
1668 mpData->mbNativeButtons = IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
1670 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1672 if ( bFont )
1674 Font aFont = rStyleSettings.GetToolFont();
1675 if ( IsControlFont() )
1676 aFont.Merge( GetControlFont() );
1677 SetZoomedPointFont( aFont );
1680 if ( bForeground || bFont )
1682 Color aColor;
1683 if ( IsControlForeground() )
1684 aColor = GetControlForeground();
1685 else if ( Window::GetStyle() & WB_3DLOOK )
1686 aColor = rStyleSettings.GetButtonTextColor();
1687 else
1688 aColor = rStyleSettings.GetWindowTextColor();
1689 SetTextColor( aColor );
1690 SetTextFillColor();
1693 if ( bBackground )
1695 Color aColor;
1696 if ( IsControlBackground() )
1698 aColor = GetControlBackground();
1699 SetBackground( aColor );
1700 SetPaintTransparent( FALSE );
1701 SetParentClipMode( 0 );
1703 else
1705 if( IsNativeControlSupported( CTRL_TOOLBAR, PART_ENTIRE_CONTROL ) )
1707 SetBackground();
1708 SetPaintTransparent( TRUE );
1709 SetParentClipMode( PARENTCLIPMODE_NOCLIP );
1710 mpData->maDisplayBackground = Wallpaper( rStyleSettings.GetFaceColor() );
1712 else
1714 if ( Window::GetStyle() & WB_3DLOOK )
1715 aColor = rStyleSettings.GetFaceColor();
1716 else
1717 aColor = rStyleSettings.GetWindowColor();
1719 SetBackground( aColor );
1720 SetPaintTransparent( FALSE );
1721 SetParentClipMode( 0 );
1723 ImplUpdateImageList();
1729 // -----------------------------------------------------------------------
1731 void ToolBox::ImplLoadRes( const ResId& rResId )
1733 ResMgr* pMgr = rResId.GetResMgr();
1734 if( ! pMgr )
1735 return;
1737 DockingWindow::ImplLoadRes( rResId );
1739 ULONG nObjMask;
1741 nObjMask = ReadLongRes();
1743 if ( nObjMask & RSC_TOOLBOX_BUTTONTYPE )
1744 SetButtonType( (ButtonType)ReadLongRes() );
1746 if ( nObjMask & RSC_TOOLBOX_ALIGN )
1747 SetAlign( (WindowAlign)ReadLongRes() );
1749 if ( nObjMask & RSC_TOOLBOX_LINECOUNT )
1750 SetLineCount( sal::static_int_cast<USHORT>(ReadLongRes()) );
1752 if ( nObjMask & RSC_TOOLBOX_CUSTOMIZE )
1754 BOOL bCust = (BOOL)ReadShortRes();
1755 EnableCustomize( bCust );
1758 if ( nObjMask & RSC_TOOLBOX_MENUSTRINGS )
1760 BOOL bCust = (BOOL)ReadShortRes();
1761 EnableMenuStrings( bCust );
1764 if ( nObjMask & RSC_TOOLBOX_FLOATLINES )
1765 SetFloatingLines( ReadShortRes() );
1767 if ( nObjMask & RSC_TOOLBOX_ITEMIMAGELIST )
1769 maImageList = ImageList( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1770 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1773 if ( nObjMask & RSC_TOOLBOX_ITEMLIST )
1775 ULONG nEle = ReadLongRes();
1777 // Item hinzufuegen
1778 for ( ULONG i = 0; i < nEle; i++ )
1780 InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *pMgr ) );
1781 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
1786 // -----------------------------------------------------------------------
1788 ToolBox::ToolBox( Window* pParent, WinBits nStyle ) :
1789 DockingWindow( WINDOW_TOOLBOX )
1791 ImplInit( pParent, nStyle );
1794 // -----------------------------------------------------------------------
1796 ToolBox::ToolBox( Window* pParent, const ResId& rResId ) :
1797 DockingWindow( WINDOW_TOOLBOX )
1799 RTL_LOGFILE_CONTEXT( aLog, "vcl: ToolBox::ToolBox( Window* pParent, const ResId& rResId )" );
1801 rResId.SetRT( RSC_TOOLBOX );
1802 WinBits nStyle = ImplInitRes( rResId );
1803 ImplInit( pParent, nStyle );
1804 ImplLoadRes( rResId );
1806 // Groesse des FloatingWindows berechnen und umschalten, wenn die
1807 // ToolBox initial im FloatingModus ist
1808 if ( ImplIsFloatingMode() )
1809 mbHorz = TRUE;
1810 else
1811 Resize();
1813 if ( !(nStyle & WB_HIDE) )
1814 Show();
1817 // -----------------------------------------------------------------------
1819 ToolBox::~ToolBox()
1821 // custom menu event still running?
1822 if( mpData->mnEventId )
1823 Application::RemoveUserEvent( mpData->mnEventId );
1825 // #103005# make sure our activate/deactivate balance is right
1826 while( mnActivateCount > 0 )
1827 Deactivate();
1829 // Falls noch ein Floating-Window connected ist, dann den
1830 // PopupModus beenden
1831 if ( mpFloatWin )
1832 mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
1834 // delete private data
1835 delete mpData;
1837 // FloatSizeAry gegebenenfalls loeschen
1838 if ( mpFloatSizeAry )
1839 delete mpFloatSizeAry;
1841 // Wenn keine ToolBox-Referenzen mehr auf die Listen bestehen, dann
1842 // Listen mit wegloeschen
1843 ImplSVData* pSVData = ImplGetSVData();
1844 if ( pSVData->maCtrlData.mpTBDragMgr )
1846 // Wenn im TBDrag-Manager, dann wieder rausnehmen
1847 if ( mbCustomize )
1848 pSVData->maCtrlData.mpTBDragMgr->Remove( this );
1850 if ( !pSVData->maCtrlData.mpTBDragMgr->Count() )
1852 delete pSVData->maCtrlData.mpTBDragMgr;
1853 pSVData->maCtrlData.mpTBDragMgr = NULL;
1858 // -----------------------------------------------------------------------
1860 ImplToolItem* ToolBox::ImplGetItem( USHORT nItemId ) const
1862 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1863 while ( it != mpData->m_aItems.end() )
1865 if ( it->mnId == nItemId )
1866 return &(*it);
1867 ++it;
1870 return NULL;
1872 // -----------------------------------------------------------------------
1874 static void ImplAddButtonBorder( long &rWidth, long& rHeight, USHORT aOutStyle, BOOL bNativeButtons )
1876 if ( aOutStyle & TOOLBOX_STYLE_OUTBUTTON )
1878 rWidth += OUTBUTTON_SIZE;
1879 rHeight += OUTBUTTON_SIZE;
1881 else
1883 rWidth += SMALLBUTTON_HSIZE;
1884 rHeight += SMALLBUTTON_VSIZE;
1887 if( bNativeButtons )
1889 // give more border space for rounded buttons
1890 rWidth += 2;
1891 rHeight += 4;
1895 // -----------------------------------------------------------------------
1897 BOOL ToolBox::ImplCalcItem()
1899 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
1901 // recalc required ?
1902 if ( !mbCalc )
1903 return FALSE;
1905 ImplDisableFlatButtons();
1907 long nDefWidth;
1908 long nDefHeight;
1909 long nMaxWidth = 0;
1910 long nMaxHeight = 0;
1911 long nHeight;
1912 long nMinWidth = 6;
1913 long nMinHeight = 6;
1914 long nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
1916 // set defaults if image or text is needed but empty
1917 nDefWidth = GetDefaultImageSize().Width();
1918 nDefHeight = GetDefaultImageSize().Height();
1920 mnWinHeight = 0;
1921 // determine minimum size necessary in NWF
1923 Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1924 Region aReg = aRect;
1925 ImplControlValue aVal;
1926 Region aNativeBounds, aNativeContent;
1927 if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
1929 if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
1930 aReg,
1931 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1932 aVal, OUString(),
1933 aNativeBounds, aNativeContent ) )
1935 aRect = aNativeBounds.GetBoundRect();
1936 if( aRect.GetWidth() > nMinWidth )
1937 nMinWidth = aRect.GetWidth();
1938 if( aRect.GetHeight() > nMinHeight )
1939 nMinHeight = aRect.GetHeight();
1940 if( nDropDownArrowWidth < nMinWidth )
1941 nDropDownArrowWidth = nMinWidth;
1942 if( nMinWidth > mpData->mnMenuButtonWidth )
1943 mpData->mnMenuButtonWidth = nMinWidth;
1944 else if( nMinWidth < TB_MENUBUTTON_SIZE )
1945 mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
1949 // also calculate the area for comboboxes, drop down list boxes and spinfields
1950 // as these are often inserted into toolboxes; set mnWinHeight to the
1951 // greater of those values to prevent toolbar flickering (#i103385#)
1952 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1953 aReg = aRect;
1954 if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
1955 aReg,
1956 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1957 aVal, OUString(),
1958 aNativeBounds, aNativeContent ) )
1960 aRect = aNativeBounds.GetBoundRect();
1961 if( aRect.GetHeight() > mnWinHeight )
1962 mnWinHeight = aRect.GetHeight();
1964 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1965 aReg = aRect;
1966 if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
1967 aReg,
1968 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1969 aVal, OUString(),
1970 aNativeBounds, aNativeContent ) )
1972 aRect = aNativeBounds.GetBoundRect();
1973 if( aRect.GetHeight() > mnWinHeight )
1974 mnWinHeight = aRect.GetHeight();
1976 aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
1977 aReg = aRect;
1978 if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
1979 aReg,
1980 CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
1981 aVal, OUString(),
1982 aNativeBounds, aNativeContent ) )
1984 aRect = aNativeBounds.GetBoundRect();
1985 if( aRect.GetHeight() > mnWinHeight )
1986 mnWinHeight = aRect.GetHeight();
1990 if ( ! mpData->m_aItems.empty() )
1992 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
1993 while ( it != mpData->m_aItems.end() )
1995 BOOL bImage;
1996 BOOL bText;
1998 it->mbVisibleText = FALSE; // indicates if text will definitely be drawn, influences dropdown pos
2000 if ( it->meType == TOOLBOXITEM_BUTTON )
2002 // check if image and/or text exists
2003 if ( !(it->maImage) )
2004 bImage = FALSE;
2005 else
2006 bImage = TRUE;
2007 if ( !it->maText.Len() )
2008 bText = FALSE;
2009 else
2010 bText = TRUE;
2011 ButtonType tmpButtonType = determineButtonType( &(*it), meButtonType ); // default to toolbox setting
2012 if ( bImage || bText )
2015 it->mbEmptyBtn = FALSE;
2017 if ( tmpButtonType == BUTTON_SYMBOL )
2019 // we're drawing images only
2020 if ( bImage || !bText )
2022 it->maItemSize = it->maImage.GetSizePixel();
2024 else
2026 it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
2027 GetTextHeight() );
2028 it->mbVisibleText = TRUE;
2031 else if ( tmpButtonType == BUTTON_TEXT )
2033 // we're drawing text only
2034 if ( bText || !bImage )
2036 it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
2037 GetTextHeight() );
2038 it->mbVisibleText = TRUE;
2040 else
2042 it->maItemSize = it->maImage.GetSizePixel();
2045 else
2047 // we're drawing images and text
2048 it->maItemSize.Width() = bText ? GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET : 0;
2049 it->maItemSize.Height() = bText ? GetTextHeight() : 0;
2051 // leave space between image and text
2052 if( bText )
2053 it->maItemSize.Width() += TB_IMAGETEXTOFFSET;
2055 // image and text side by side
2056 it->maItemSize.Width() += it->maImage.GetSizePixel().Width();
2057 if ( it->maImage.GetSizePixel().Height() > it->maItemSize.Height() )
2058 it->maItemSize.Height() = it->maImage.GetSizePixel().Height();
2060 it->mbVisibleText = bText;
2063 else
2064 { // no image and no text
2065 it->maItemSize = Size( nDefWidth, nDefHeight );
2066 it->mbEmptyBtn = TRUE;
2069 // Gegebenenfalls die Fensterhoehe mit beruecksichtigen
2070 if ( it->mpWindow )
2072 nHeight = it->mpWindow->GetSizePixel().Height();
2073 if ( nHeight > mnWinHeight )
2074 mnWinHeight = nHeight;
2077 // add in drop down arrow
2078 if( it->mnBits & TIB_DROPDOWN )
2080 it->maItemSize.Width() += nDropDownArrowWidth;
2081 it->mnDropDownArrowWidth = nDropDownArrowWidth;
2084 // text items will be rotated in vertical mode
2085 // -> swap width and height
2086 if( it->mbVisibleText && !mbHorz )
2088 long tmp = it->maItemSize.Width();
2089 it->maItemSize.Width() = it->maItemSize.Height();
2090 it->maItemSize.Height() = tmp;
2093 else if ( it->meType == TOOLBOXITEM_SPACE )
2095 it->maItemSize = Size( nDefWidth, nDefHeight );
2098 if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2100 // add borders
2101 ImplAddButtonBorder( it->maItemSize.Width(), it->maItemSize.Height(), mnOutStyle, mpData->mbNativeButtons );
2103 if( it->meType == TOOLBOXITEM_BUTTON )
2105 if( it->maItemSize.Width() < nMinWidth )
2106 it->maItemSize.Width() = nMinWidth;
2107 if( it->maItemSize.Height() < nMinHeight )
2108 it->maItemSize.Height() = nMinHeight;
2111 // keep track of max item size
2112 if ( it->maItemSize.Width() > nMaxWidth )
2113 nMaxWidth = it->maItemSize.Width();
2114 if ( it->maItemSize.Height() > nMaxHeight )
2115 nMaxHeight = it->maItemSize.Height();
2118 ++it;
2121 else
2123 nMaxWidth = nDefWidth;
2124 nMaxHeight = nDefHeight;
2126 ImplAddButtonBorder( nMaxWidth, nMaxHeight, mnOutStyle, mpData->mbNativeButtons );
2129 if( !ImplIsFloatingMode() && GetToolboxButtonSize() != TOOLBOX_BUTTONSIZE_DONTCARE )
2131 // make sure all vertical toolbars have the same width and horizontal have the same height
2132 // this depends on the used button sizes
2133 // as this is used for alignement of multiple toolbars
2134 // it is only required for docked toolbars
2136 long nFixedWidth = nDefWidth+nDropDownArrowWidth;
2137 long nFixedHeight = nDefHeight;
2138 ImplAddButtonBorder( nFixedWidth, nFixedHeight, mnOutStyle, mpData->mbNativeButtons );
2140 if( mbHorz )
2141 nMaxHeight = nFixedHeight;
2142 else
2143 nMaxWidth = nFixedWidth;
2146 mbCalc = FALSE;
2147 mbFormat = TRUE;
2149 // do we have to recalc the sizes ?
2150 if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) )
2152 mnMaxItemWidth = nMaxWidth;
2153 mnMaxItemHeight = nMaxHeight;
2155 return TRUE;
2157 else
2158 return FALSE;
2161 // -----------------------------------------------------------------------
2163 USHORT ToolBox::ImplCalcBreaks( long nWidth, long* pMaxLineWidth, BOOL bCalcHorz )
2165 ULONG nLineStart = 0;
2166 ULONG nGroupStart = 0;
2167 long nLineWidth = 0;
2168 long nCurWidth;
2169 long nLastGroupLineWidth = 0;
2170 long nMaxLineWidth = 0;
2171 USHORT nLines = 1;
2172 BOOL bWindow;
2173 BOOL bBreak = FALSE;
2174 long nWidthTotal = nWidth;
2176 // when docked the menubutton will be in the first line
2177 // ->initialize first linewidth with button
2178 if( IsMenuEnabled() && !ImplIsFloatingMode() )
2179 nLineWidth = mpData->maMenubuttonItem.maItemSize.Width();
2181 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
2182 while ( it != mpData->m_aItems.end() )
2184 it->mbBreak = bBreak;
2185 bBreak = FALSE;
2187 if ( it->mbVisible )
2189 bWindow = FALSE;
2190 bBreak = FALSE;
2191 nCurWidth = 0;
2193 if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
2195 if ( bCalcHorz )
2196 nCurWidth = it->maItemSize.Width();
2197 else
2198 nCurWidth = it->maItemSize.Height();
2200 if ( it->mpWindow && bCalcHorz )
2202 long nWinItemWidth = it->mpWindow->GetSizePixel().Width();
2203 if ( !mbScroll || (nWinItemWidth <= nWidthTotal) )
2205 nCurWidth = nWinItemWidth;
2206 bWindow = TRUE;
2208 else
2210 if ( it->mbEmptyBtn )
2212 nCurWidth = 0;
2217 // check for line break
2218 if ( (nLineWidth+nCurWidth > nWidthTotal) && mbScroll )
2219 bBreak = TRUE;
2221 else if ( it->meType == TOOLBOXITEM_SEPARATOR )
2222 nCurWidth = it->mnSepSize;
2223 // treat breaks as separators, except when using old style toolbars (ie. no menu button)
2224 else if ( (it->meType == TOOLBOXITEM_BREAK) && !IsMenuEnabled() )
2225 bBreak = TRUE;
2227 if ( bBreak )
2229 nLines++;
2231 // Gruppe auseinanderbrechen oder ganze Gruppe umbrechen?
2232 if ( (it->meType == TOOLBOXITEM_BREAK) ||
2233 (nLineStart == nGroupStart) )
2235 if ( nLineWidth > nMaxLineWidth )
2236 nMaxLineWidth = nLineWidth;
2238 nLineWidth = 0;
2239 nLineStart = it - mpData->m_aItems.begin();
2240 nGroupStart = nLineStart;
2241 it->mbBreak = TRUE;
2242 bBreak = FALSE;
2244 else
2246 if ( nLastGroupLineWidth > nMaxLineWidth )
2247 nMaxLineWidth = nLastGroupLineWidth;
2249 // Wenn ganze Gruppe umgebrochen wird, diese auf
2250 // Zeilenanfang setzen und wieder neu berechnen
2251 nLineWidth = 0;
2252 nLineStart = nGroupStart;
2253 it = mpData->m_aItems.begin() + nGroupStart;
2254 continue;
2257 else
2259 if( ImplIsFloatingMode() || !IsMenuEnabled() ) // no group breaking when being docked single-line
2261 if ( (it->meType != TOOLBOXITEM_BUTTON) || bWindow )
2263 // found separator or break
2264 nLastGroupLineWidth = nLineWidth;
2265 nGroupStart = it - mpData->m_aItems.begin();
2266 if ( !bWindow )
2267 nGroupStart++;
2272 nLineWidth += nCurWidth;
2275 ++it;
2279 if ( pMaxLineWidth )
2281 if ( nLineWidth > nMaxLineWidth )
2282 nMaxLineWidth = nLineWidth;
2284 if( ImplIsFloatingMode() && !ImplIsInPopupMode() )
2286 // leave enough space to display buttons in the decoration
2287 long aMinWidth = 2 * GetSettings().GetStyleSettings().GetFloatTitleHeight();
2288 if( nMaxLineWidth < aMinWidth )
2289 nMaxLineWidth = aMinWidth;
2292 // Wegen Separatoren kann MaxLineWidth > Width werden, hat aber
2293 // auf die Umbrueche keine Auswirkung
2294 //if ( nMaxLineWidth > nWidth )
2295 // nMaxLineWidth = nWidth;
2297 *pMaxLineWidth = nMaxLineWidth;
2300 return nLines;
2303 // -----------------------------------------------------------------------
2304 namespace
2306 BOOL ImplFollowedByVisibleButton( std::vector< ImplToolItem >::iterator _aSeparator, std::vector< ImplToolItem >::iterator _aEnd )
2308 std::vector< ImplToolItem >::iterator aLookup = _aSeparator;
2309 while ( ++aLookup != _aEnd )
2311 if ( aLookup->meType == TOOLBOXITEM_SEPARATOR )
2312 return ImplFollowedByVisibleButton( aLookup, _aEnd );
2314 if ( ( aLookup->meType == TOOLBOXITEM_BUTTON ) && aLookup->mbVisible )
2315 return TRUE;
2317 return FALSE;
2322 // -----------------------------------------------------------------------
2324 Size ToolBox::ImplGetOptimalFloatingSize( FloatingSizeMode eMode )
2326 if( !ImplIsFloatingMode() )
2327 return Size();
2329 Size aCurrentSize( mnDX, mnDY );
2330 Size aSize1( aCurrentSize );
2331 Size aSize2( aCurrentSize );
2333 // try to preserve current height
2334 if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURHEIGHT )
2336 // calc number of floating lines for current window height
2337 USHORT nFloatLinesHeight = ImplCalcLines( this, mnDY );
2338 // calc window size according to this number
2339 aSize1 = ImplCalcFloatSize( this, nFloatLinesHeight );
2341 if( eMode == FSMODE_FAVOURHEIGHT || aCurrentSize == aSize1 )
2342 return aSize1;
2345 if( eMode == FSMODE_AUTO || eMode == FSMODE_FAVOURWIDTH )
2347 // try to preserve current width
2348 long nLineHeight = ( mnWinHeight > mnMaxItemHeight ) ? mnWinHeight : mnMaxItemHeight;
2349 int nBorderX = 2*TB_BORDER_OFFSET1 + mnLeftBorder + mnRightBorder + 2*mnBorderX;
2350 int nBorderY = 2*TB_BORDER_OFFSET2 + mnTopBorder + mnBottomBorder + 2*mnBorderY;
2351 Size aSz( aCurrentSize );
2352 long maxX;
2353 USHORT nLines = ImplCalcBreaks( aSz.Width()-nBorderX, &maxX, mbHorz );
2355 USHORT manyLines = 1000;
2356 Size aMinimalFloatSize = ImplCalcFloatSize( this, manyLines );
2358 aSz.Height() = nBorderY + nLineHeight * nLines;
2359 // line space when more than one line
2360 if ( mnWinStyle & WB_LINESPACING )
2361 aSz.Height() += (nLines-1)*TB_LINESPACING;
2363 aSz.Width() = nBorderX + maxX;
2365 // avoid clipping of any items
2366 if( aSz.Width() < aMinimalFloatSize.Width() )
2367 aSize2 = ImplCalcFloatSize( this, nLines );
2368 else
2369 aSize2 = aSz;
2371 if( eMode == FSMODE_FAVOURWIDTH || aCurrentSize == aSize2 )
2372 return aSize2;
2373 else
2375 // set the size with the smallest delta as the current size
2376 long dx1 = abs( mnDX - aSize1.Width() );
2377 long dy1 = abs( mnDY - aSize1.Height() );
2379 long dx2 = abs( mnDX - aSize2.Width() );
2380 long dy2 = abs( mnDY - aSize2.Height() );
2382 if( dx1*dy1 < dx2*dy2 )
2383 aCurrentSize = aSize1;
2384 else
2385 aCurrentSize = aSize2;
2388 return aCurrentSize;
2392 void ToolBox::ImplFormat( BOOL bResize )
2394 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2396 // Muss ueberhaupt neu formatiert werden
2397 if ( !mbFormat )
2398 return;
2400 mpData->ImplClearLayoutData();
2402 // Positionen/Groessen berechnen
2403 Rectangle aEmptyRect;
2404 long nLineSize;
2405 long nLeft;
2406 long nRight;
2407 long nTop;
2408 long nBottom;
2409 long nMax; // width of layoutarea in pixels
2410 long nX;
2411 long nY;
2412 USHORT nFormatLine;
2413 BOOL bMustFullPaint;
2414 BOOL bLastSep;
2416 std::vector< ImplToolItem >::iterator it;
2417 std::vector< ImplToolItem >::iterator temp_it;
2419 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
2420 BOOL bIsInPopupMode = ImplIsInPopupMode();
2422 // FloatSizeAry gegebenenfalls loeschen
2423 if ( mpFloatSizeAry )
2425 delete mpFloatSizeAry;
2426 mpFloatSizeAry = NULL;
2429 // compute border sizes
2430 ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder, mnRightBorder, mnBottomBorder, this );
2432 // update drag area (where the 'grip' will be placed)
2433 Rectangle aOldDragRect;
2434 if( pWrapper )
2435 aOldDragRect = pWrapper->GetDragArea();
2436 ImplUpdateDragArea( this );
2438 if ( ImplCalcItem() )
2439 bMustFullPaint = TRUE;
2440 else
2441 bMustFullPaint = FALSE;
2444 // calculate new size during interactive resize or
2445 // set computed size when formatting only
2446 if ( ImplIsFloatingMode() )
2448 if ( bResize )
2449 mnFloatLines = ImplCalcLines( this, mnDY );
2450 else
2451 SetOutputSizePixel( ImplGetOptimalFloatingSize( FSMODE_AUTO ) );
2454 // Horizontal
2455 if ( mbHorz )
2457 // nLineSize: height of a single line, will fit highest item
2458 nLineSize = mnMaxItemHeight;
2460 if ( mnWinHeight > mnMaxItemHeight )
2461 nLineSize = mnWinHeight;
2463 if ( mbScroll )
2465 nMax = mnDX;
2466 mnVisLines = ImplCalcLines( this, mnDY );
2468 else
2470 // layout over all lines
2471 mnVisLines = mnLines;
2472 nMax = TB_MAXNOSCROLL;
2475 // add in all border offsets
2476 // inner border as well as custom border (mnBorderX, mnBorderY)
2477 if ( mnWinStyle & WB_BORDER )
2479 nLeft = TB_BORDER_OFFSET1 + mnLeftBorder;
2480 nTop = TB_BORDER_OFFSET2 + mnTopBorder;
2481 nBottom = TB_BORDER_OFFSET1 + mnBottomBorder;
2482 nMax -= nLeft + TB_BORDER_OFFSET1 + mnRightBorder;
2484 else
2486 nLeft = 0;
2487 nTop = 0;
2488 nBottom = 0;
2491 nLeft += mnBorderX;
2492 nTop += mnBorderY;
2493 nBottom += mnBorderY;
2494 nMax -= mnBorderX*2;
2496 // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2497 // we have to center all items in the window height
2498 if( IsMenuEnabled() && !ImplIsFloatingMode() )
2500 long nWinHeight = mnDY - nTop - nBottom;
2501 if( nWinHeight > nLineSize )
2502 nLineSize = nWinHeight;
2505 else
2507 nLineSize = mnMaxItemWidth;
2509 if ( mbScroll )
2511 mnVisLines = ImplCalcLines( this, mnDX );
2512 nMax = mnDY;
2514 else
2516 mnVisLines = mnLines;
2517 nMax = TB_MAXNOSCROLL;
2520 if ( mnWinStyle & WB_BORDER )
2522 nTop = TB_BORDER_OFFSET1 + mnTopBorder;
2523 nLeft = TB_BORDER_OFFSET2 + mnLeftBorder;
2524 nRight = TB_BORDER_OFFSET2 + mnRightBorder;
2525 nMax -= nTop + TB_BORDER_OFFSET1 + mnBottomBorder;
2527 else
2529 nLeft = 0;
2530 nTop = 0;
2531 nRight = 0;
2534 nLeft += mnBorderX;
2535 nRight+= mnBorderX;
2536 nTop += mnBorderY;
2537 nMax -= mnBorderY*2;
2539 // adjust linesize if docked in single-line mode (i.e. when using a clipped item menu)
2540 // we have to center all items in the window height
2541 if( !ImplIsFloatingMode() && IsMenuEnabled() )
2543 long nWinWidth = mnDX - nLeft - nRight;
2544 if( nWinWidth > nLineSize )
2545 nLineSize = nWinWidth;
2549 // no calculation if the window has no size (nMax=0)
2550 // non scrolling toolboxes must be computed though
2551 if ( (nMax <= 0) && mbScroll )
2553 mnVisLines = 1;
2554 mnCurLine = 1;
2555 mnCurLines = 1;
2557 it = mpData->m_aItems.begin();
2558 while ( it != mpData->m_aItems.end() )
2560 it->maRect = aEmptyRect;
2562 // For items not visible, release resources only needed during
2563 // painting the items (on Win98, for example, these are system-wide
2564 // resources that are easily exhausted, so be nice):
2566 /* !!!
2567 it->maImage.ClearCaches();
2568 it->maHighImage.ClearCaches();
2571 ++it;
2574 maLowerRect = aEmptyRect;
2575 maUpperRect = aEmptyRect;
2576 maNextToolRect = aEmptyRect;
2578 else
2580 // init start values
2581 nX = nLeft; // top-left offset
2582 nY = nTop;
2583 nFormatLine = 1;
2584 bLastSep = TRUE;
2586 // save old scroll rectangles and reset them
2587 Rectangle aOldLowerRect = maLowerRect;
2588 Rectangle aOldUpperRect = maUpperRect;
2589 Rectangle aOldNextToolRect = maNextToolRect;
2590 Rectangle aOldMenubuttonRect = mpData->maMenubuttonItem.maRect;
2591 maUpperRect = aEmptyRect;
2592 maLowerRect = aEmptyRect;
2593 maNextToolRect = aEmptyRect;
2594 mpData->maMenubuttonItem.maRect = aEmptyRect;
2596 // additional toolboxes require a toggle button (maNextToolRect)
2597 if ( maNextToolBoxStr.Len() && mbScroll )
2599 nMax -= TB_NEXT_SIZE-TB_NEXT_OFFSET;
2600 if ( mbHorz )
2602 maNextToolRect.Left() = nLeft+nMax;
2603 maNextToolRect.Right() = maNextToolRect.Left()+TB_NEXT_SIZE-1;
2604 maNextToolRect.Top() = nTop;
2605 maNextToolRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2607 else
2609 maNextToolRect.Top() = nTop+nMax;
2610 maNextToolRect.Bottom() = maNextToolRect.Top()+TB_NEXT_SIZE-1;
2611 maNextToolRect.Left() = nLeft;
2612 maNextToolRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2616 // do we have any toolbox items at all ?
2617 if ( !mpData->m_aItems.empty() || IsMenuEnabled() )
2619 // compute line breaks and visible lines give the current window width (nMax)
2620 // the break indicators will be stored within each item (it->mbBreak)
2621 mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2623 // check for scrollbar buttons or dropdown menu
2624 // (if a menu is enabled, this will be used to store clipped
2625 // items and no scroll buttons will appear)
2626 if ( (!ImplIsFloatingMode() && (mnCurLines > mnVisLines) && mbScroll ) ||
2627 IsMenuEnabled() )
2629 // compute linebreaks again, incorporating scrollbar buttons
2630 if( !IsMenuEnabled() )
2632 nMax -= TB_SPIN_SIZE+TB_SPIN_OFFSET;
2633 mnCurLines = ImplCalcBreaks( nMax, NULL, mbHorz );
2636 // compute scroll rectangles or menu button
2637 if ( mbHorz )
2639 if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2641 if( !ImplIsFloatingMode() )
2643 mpData->maMenubuttonItem.maRect.Right() = mnDX - 2;
2644 mpData->maMenubuttonItem.maRect.Top() = nTop;
2645 mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2647 else
2649 mpData->maMenubuttonItem.maRect.Right() = mnDX - mnRightBorder-mnBorderX-TB_BORDER_OFFSET1-1;
2650 mpData->maMenubuttonItem.maRect.Top() = nTop;
2651 mpData->maMenubuttonItem.maRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2653 mpData->maMenubuttonItem.maRect.Left() = mpData->maMenubuttonItem.maRect.Right() - mpData->mnMenuButtonWidth;
2655 else
2657 maUpperRect.Left() = nLeft+nMax+TB_SPIN_OFFSET;
2658 maUpperRect.Right() = maUpperRect.Left()+TB_SPIN_SIZE-1;
2659 maUpperRect.Top() = nTop;
2660 maLowerRect.Bottom() = mnDY-mnBottomBorder-mnBorderY-TB_BORDER_OFFSET2-1;
2661 maLowerRect.Left() = maUpperRect.Left();
2662 maLowerRect.Right() = maUpperRect.Right();
2663 maUpperRect.Bottom() = maUpperRect.Top() +
2664 (maLowerRect.Bottom()-maUpperRect.Top())/2;
2665 maLowerRect.Top() = maUpperRect.Bottom();
2668 else
2670 if( IsMenuEnabled() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2672 if( !ImplIsFloatingMode() )
2674 mpData->maMenubuttonItem.maRect.Bottom() = mnDY - 2;
2675 mpData->maMenubuttonItem.maRect.Left() = nLeft;
2676 mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2678 else
2680 mpData->maMenubuttonItem.maRect.Bottom() = mnDY - mnBottomBorder-mnBorderY-TB_BORDER_OFFSET1-1;
2681 mpData->maMenubuttonItem.maRect.Left() = nLeft;
2682 mpData->maMenubuttonItem.maRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2684 mpData->maMenubuttonItem.maRect.Top() = mpData->maMenubuttonItem.maRect.Bottom() - mpData->mnMenuButtonWidth;
2686 else
2688 maUpperRect.Top() = nTop+nMax+TB_SPIN_OFFSET;;
2689 maUpperRect.Bottom() = maUpperRect.Top()+TB_SPIN_SIZE-1;
2690 maUpperRect.Left() = nLeft;
2691 maLowerRect.Right() = mnDX-mnRightBorder-mnBorderX-TB_BORDER_OFFSET2-1;
2692 maLowerRect.Top() = maUpperRect.Top();
2693 maLowerRect.Bottom() = maUpperRect.Bottom();
2694 maUpperRect.Right() = maUpperRect.Left() +
2695 (maLowerRect.Right()-maUpperRect.Left())/2;
2696 maLowerRect.Left() = maUpperRect.Right();
2701 // no scrolling when there is a "more"-menu
2702 // anything will "fit" in a single line then
2703 if( IsMenuEnabled() )
2704 mnCurLines = 1;
2706 // determine the currently visible line
2707 if ( mnVisLines >= mnCurLines )
2708 mnCurLine = 1;
2709 else if ( mnCurLine+mnVisLines-1 > mnCurLines )
2710 mnCurLine = mnCurLines - (mnVisLines-1);
2712 it = mpData->m_aItems.begin();
2713 while ( it != mpData->m_aItems.end() )
2715 // hide double separators
2716 if ( it->meType == TOOLBOXITEM_SEPARATOR )
2718 it->mbVisible = FALSE;
2719 if ( !bLastSep )
2721 // check if any visible items have to appear behind it
2722 temp_it = it+1;
2723 while ( temp_it != mpData->m_aItems.end() )
2725 if ( (temp_it->meType == TOOLBOXITEM_SEPARATOR) ||
2726 ((temp_it->meType == TOOLBOXITEM_BUTTON) &&
2727 temp_it->mbVisible) )
2729 it->mbVisible = TRUE;
2730 break;
2732 ++temp_it;
2735 bLastSep = TRUE;
2737 else if ( it->mbVisible )
2738 bLastSep = FALSE;
2740 it->mbShowWindow = FALSE;
2742 // check for line break and advance nX/nY accordingly
2743 if ( it->mbBreak )
2745 nFormatLine++;
2747 // increment starting with the second line
2748 if ( nFormatLine > mnCurLine )
2750 if ( mbHorz )
2752 nX = nLeft;
2753 if ( mnWinStyle & WB_LINESPACING )
2754 nY += nLineSize+TB_LINESPACING;
2755 else
2756 nY += nLineSize;
2758 else
2760 nY = nTop;
2761 if ( mnWinStyle & WB_LINESPACING )
2762 nX += nLineSize+TB_LINESPACING;
2763 else
2764 nX += nLineSize;
2769 if ( !it->mbVisible || (nFormatLine < mnCurLine) ||
2770 (nFormatLine > mnCurLine+mnVisLines-1) )
2771 // item is not visible
2772 it->maCalcRect = aEmptyRect;
2773 else
2775 // 1. determine current item width/height
2776 // take window size and orientation into account, because this affects the size of item windows
2778 Size aCurrentItemSize( it->GetSize( mbHorz, mbScroll, nMax, Size(mnMaxItemWidth, mnMaxItemHeight) ) );
2780 // 2. position item rect and use size from step 1
2781 // items will be centered horizontally (if mbHorz) or vertically
2782 // advance nX and nY accordingly
2783 if ( mbHorz )
2785 it->maCalcRect.Left() = nX;
2786 it->maCalcRect.Top() = nY+(nLineSize-aCurrentItemSize.Height())/2;
2787 it->maCalcRect.Right() = nX+aCurrentItemSize.Width()-1;
2788 it->maCalcRect.Bottom() = it->maCalcRect.Top()+aCurrentItemSize.Height()-1;
2789 nX += aCurrentItemSize.Width();
2791 else
2793 it->maCalcRect.Left() = nX+(nLineSize-aCurrentItemSize.Width())/2;
2794 it->maCalcRect.Top() = nY;
2795 it->maCalcRect.Right() = it->maCalcRect.Left()+aCurrentItemSize.Width()-1;
2796 it->maCalcRect.Bottom() = nY+aCurrentItemSize.Height()-1;
2797 nY += aCurrentItemSize.Height();
2801 // position window items into calculated item rect
2802 if ( it->mpWindow )
2804 if ( it->mbShowWindow )
2806 Point aPos( it->maCalcRect.Left(), it->maCalcRect.Top() );
2807 it->mpWindow->SetPosPixel( aPos );
2808 if ( !mbCustomizeMode )
2809 it->mpWindow->Show();
2811 else
2812 it->mpWindow->Hide();
2815 ++it;
2816 } // end of loop over all items
2818 else
2819 // we have no toolbox items
2820 mnCurLines = 1;
2823 if( IsMenuEnabled() && ImplIsFloatingMode() && !ImplHasExternalMenubutton() && !bIsInPopupMode )
2825 // custom menu will be the last button in floating mode
2826 ImplToolItem &rIt = mpData->maMenubuttonItem;
2828 if ( mbHorz )
2830 rIt.maRect.Left() = nX+TB_MENUBUTTON_OFFSET;
2831 rIt.maRect.Top() = nY;
2832 rIt.maRect.Right() = rIt.maRect.Left() + mpData->mnMenuButtonWidth;
2833 rIt.maRect.Bottom() = nY+nLineSize-1;
2834 nX += rIt.maItemSize.Width();
2836 else
2838 rIt.maRect.Left() = nX;
2839 rIt.maRect.Top() = nY+TB_MENUBUTTON_OFFSET;
2840 rIt.maRect.Right() = nX+nLineSize-1;
2841 rIt.maRect.Bottom() = rIt.maRect.Top() + mpData->mnMenuButtonWidth;
2842 nY += rIt.maItemSize.Height();
2847 // if toolbox visible trigger paint for changed regions
2848 if ( IsVisible() && !mbFullPaint )
2850 if ( bMustFullPaint )
2852 maPaintRect = Rectangle( mnLeftBorder, mnTopBorder,
2853 mnDX-mnRightBorder, mnDY-mnBottomBorder );
2855 else
2857 if ( aOldLowerRect != maLowerRect )
2859 maPaintRect.Union( maLowerRect );
2860 maPaintRect.Union( aOldLowerRect );
2862 if ( aOldUpperRect != maUpperRect )
2864 maPaintRect.Union( maUpperRect );
2865 maPaintRect.Union( aOldUpperRect );
2867 if ( aOldNextToolRect != maNextToolRect )
2869 maPaintRect.Union( maNextToolRect );
2870 maPaintRect.Union( aOldNextToolRect );
2872 if ( aOldMenubuttonRect != mpData->maMenubuttonItem.maRect )
2874 maPaintRect.Union( mpData->maMenubuttonItem.maRect );
2875 maPaintRect.Union( aOldMenubuttonRect );
2877 if ( pWrapper && aOldDragRect != pWrapper->GetDragArea() )
2879 maPaintRect.Union( pWrapper->GetDragArea() );
2880 maPaintRect.Union( aOldDragRect );
2883 it = mpData->m_aItems.begin();
2884 while ( it != mpData->m_aItems.end() )
2886 if ( it->maRect != it->maCalcRect )
2888 maPaintRect.Union( it->maRect );
2889 maPaintRect.Union( it->maCalcRect );
2891 ++it;
2895 Invalidate( maPaintRect );
2898 // store the new calculated item rects
2899 maPaintRect = aEmptyRect;
2900 Rectangle aVisibleRect(Point(0, 0), GetOutputSizePixel());
2901 it = mpData->m_aItems.begin();
2902 while ( it != mpData->m_aItems.end() )
2904 it->maRect = it->maCalcRect;
2905 if (!it->maRect.IsOver(aVisibleRect))
2907 // For items not visible, release resources only needed during
2908 // painting the items (on Win98, for example, these are system-
2909 // wide resources that are easily exhausted, so be nice):
2911 /* !!!
2912 it->maImage.ClearCaches();
2913 it->maHighImage.ClearCaches();
2916 ++it;
2920 // indicate formatting is done
2921 mbFormat = FALSE;
2924 // -----------------------------------------------------------------------
2926 IMPL_LINK( ToolBox, ImplDropdownLongClickHdl, ToolBox*, EMPTYARG )
2928 if( mnCurPos != TOOLBOX_ITEM_NOTFOUND &&
2929 (mpData->m_aItems[ mnCurPos ].mnBits & TIB_DROPDOWN)
2932 mpData->mbDropDownByKeyboard = FALSE;
2933 GetDropdownClickHdl().Call( this );
2935 // do not reset data if the dropdown handler opened a floating window
2936 // see ImplFloatControl()
2937 if( mpFloatWin == NULL )
2939 // no floater was opened
2940 Deactivate();
2941 ImplDrawItem( mnCurPos, FALSE );
2943 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
2944 mnCurItemId = 0;
2945 mnDownItemId = 0;
2946 mnMouseClicks = 0;
2947 mnMouseModifier = 0;
2948 mnHighItemId = 0;
2952 return 0;
2955 // -----------------------------------------------------------------------
2957 IMPL_LINK( ToolBox, ImplUpdateHdl, void*, EMPTYARG )
2959 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
2961 if( mbFormat )
2962 ImplFormat();
2964 return 0;
2967 // -----------------------------------------------------------------------
2969 static void ImplDrawMoreIndicator( ToolBox *pBox, const Rectangle& rRect, BOOL bSetColor, BOOL bRotate )
2971 Color aOldFillColor = pBox->GetFillColor();
2972 Color aOldLineColor = pBox->GetLineColor();
2973 pBox->SetLineColor();
2975 if ( bSetColor )
2977 if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
2978 pBox->SetFillColor( Color( COL_WHITE ) );
2979 else
2980 pBox->SetFillColor( Color( COL_BLACK ) );
2983 if( !bRotate )
2985 long width = 8;
2986 long height = 5;
2987 long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
2988 long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
2989 while( height >= 1)
2991 pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2992 x+=4;
2993 pBox->DrawRect( Rectangle( x, y, x+1, y ) );
2994 x-=4;
2995 y++;
2996 if( height <= 3) x--;
2997 else x++;
2998 height--;
3001 else
3003 long width = 5;
3004 long height = 8;
3005 long x = rRect.Left() + (rRect.getWidth() - width)/2 + 1;
3006 long y = rRect.Top() + (rRect.getHeight() - height)/2 + 1;
3007 while( width >= 1)
3009 pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
3010 y+=4;
3011 pBox->DrawRect( Rectangle( x, y, x, y+1 ) );
3012 y-=4;
3013 x++;
3014 if( width <= 3) y--;
3015 else y++;
3016 width--;
3020 pBox->SetFillColor( aOldFillColor );
3021 pBox->SetLineColor( aOldLineColor );
3024 static void ImplDrawDropdownArrow( ToolBox *pBox, const Rectangle& rDropDownRect, BOOL bSetColor, BOOL bRotate )
3026 BOOL bLineColor = pBox->IsLineColor();
3027 BOOL bFillColor = pBox->IsFillColor();
3028 Color aOldFillColor = pBox->GetFillColor();
3029 Color aOldLineColor = pBox->GetLineColor();
3030 pBox->SetLineColor();
3032 if ( bSetColor )
3034 if ( pBox->GetSettings().GetStyleSettings().GetFaceColor().IsDark() )
3035 pBox->SetFillColor( Color( COL_WHITE ) );
3036 else
3037 pBox->SetFillColor( Color( COL_BLACK ) );
3040 if( !bRotate )
3042 long width = 5;
3043 long height = 3;
3044 long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
3045 long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
3046 while( width >= 1)
3048 pBox->DrawRect( Rectangle( x, y, x+width-1, y ) );
3049 y++; x++;
3050 width -= 2;
3053 else
3055 long width = 3;
3056 long height = 5;
3057 long x = rDropDownRect.Left() + (rDropDownRect.getWidth() - width)/2;
3058 long y = rDropDownRect.Top() + (rDropDownRect.getHeight() - height)/2;
3059 while( height >= 1)
3061 pBox->DrawRect( Rectangle( x, y, x, y+height-1 ) );
3062 y++; x++;
3063 height -= 2;
3067 if( bFillColor )
3068 pBox->SetFillColor( aOldFillColor );
3069 else
3070 pBox->SetFillColor();
3071 if( bLineColor )
3072 pBox->SetLineColor( aOldLineColor );
3073 else
3074 pBox->SetLineColor( );
3077 void ToolBox::ImplDrawToolArrow( ToolBox* pBox, long nX, long nY, BOOL bBlack, BOOL bColTransform,
3078 BOOL bLeft, BOOL bTop, long nSize )
3080 Color aOldFillColor = pBox->GetFillColor();
3081 WindowAlign eAlign = pBox->meAlign;
3082 long n = 0;
3083 long nHalfSize;
3084 if ( bLeft )
3085 eAlign = WINDOWALIGN_RIGHT;
3086 else if ( bTop )
3087 eAlign = WINDOWALIGN_BOTTOM;
3089 nHalfSize = nSize/2;
3091 switch ( eAlign )
3093 case WINDOWALIGN_LEFT:
3094 if ( bBlack )
3095 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3096 while ( n <= nHalfSize )
3098 pBox->DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
3099 n++;
3101 if ( bBlack )
3103 pBox->SetFillColor( aOldFillColor );
3104 n = 1;
3105 while ( n < nHalfSize )
3107 pBox->DrawRect( Rectangle( nX+n, nY+1+n, nX+n, nY+nSize-1-n ) );
3108 n++;
3111 break;
3112 case WINDOWALIGN_TOP:
3113 if ( bBlack )
3114 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3115 while ( n <= nHalfSize )
3117 pBox->DrawRect( Rectangle( nX+n, nY+n, nX+nSize-n, nY+n ) );
3118 n++;
3120 if ( bBlack )
3122 pBox->SetFillColor( aOldFillColor );
3123 n = 1;
3124 while ( n < nHalfSize )
3126 pBox->DrawRect( Rectangle( nX+1+n, nY+n, nX+nSize-1-n, nY+n ) );
3127 n++;
3130 break;
3131 case WINDOWALIGN_RIGHT:
3132 if ( bBlack )
3133 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3134 while ( n <= nHalfSize )
3136 pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+n, nX+nHalfSize-n, nY+nSize-n ) );
3137 n++;
3139 if ( bBlack )
3141 pBox->SetFillColor( aOldFillColor );
3142 n = 1;
3143 while ( n < nHalfSize )
3145 pBox->DrawRect( Rectangle( nX+nHalfSize-n, nY+1+n, nX+nHalfSize-n, nY+nSize-1-n ) );
3146 n++;
3149 break;
3150 case WINDOWALIGN_BOTTOM:
3151 if ( bBlack )
3152 pBox->SetFillColor( Color( bColTransform ? COL_WHITE : COL_BLACK ) );
3153 while ( n <= nHalfSize )
3155 pBox->DrawRect( Rectangle( nX+n, nY+nHalfSize-n, nX+nSize-n, nY+nHalfSize-n ) );
3156 n++;
3158 if ( bBlack )
3160 pBox->SetFillColor( aOldFillColor );
3161 n = 1;
3162 while ( n < nHalfSize )
3164 pBox->DrawRect( Rectangle( nX+1+n, nY+nHalfSize-n, nX+nSize-1-n, nY+nHalfSize-n ) );
3165 n++;
3168 break;
3172 void ToolBox::SetToolArrowClipregion( ToolBox* pBox, long nX, long nY,
3173 BOOL bLeft, BOOL bTop, long nSize )
3175 WindowAlign eAlign = pBox->meAlign;
3176 long nHalfSize;
3177 if ( bLeft )
3178 eAlign = WINDOWALIGN_RIGHT;
3179 else if ( bTop )
3180 eAlign = WINDOWALIGN_BOTTOM;
3182 nHalfSize = nSize/2;
3184 Point p[6];
3186 switch ( eAlign )
3188 case WINDOWALIGN_LEFT:
3189 p[0].X() = nX-1; p[0].Y() = nY-1;
3190 p[1].X() = nX-1; p[1].Y() = nY+nSize+1;
3191 p[2].X() = nX+1; p[2].Y() = nY+nSize+1;
3192 p[3].X() = nX+nHalfSize+1; p[3].Y() = nY+nHalfSize+1;
3193 p[4].X() = nX+nHalfSize+1; p[4].Y() = nY+nHalfSize-1;
3194 p[5].X() = nX+1; p[5].Y() = nY-1;
3195 break;
3196 case WINDOWALIGN_TOP:
3197 p[0].X() = nX-1; p[0].Y() = nY-1;
3198 p[1].X() = nX-1; p[1].Y() = nY+1;
3199 p[2].X() = nX+nHalfSize-1; p[2].Y() = nY+nHalfSize+1;
3200 p[3].X() = nX+nHalfSize+1; p[3].Y() = nY+nHalfSize+1;
3201 p[4].X() = nX+nSize+1; p[4].Y() = nY+1;
3202 p[5].X() = nX+nSize+1; p[5].Y() = nY-1;
3203 break;
3204 case WINDOWALIGN_RIGHT:
3205 p[0].X() = nX+nHalfSize-1; p[0].Y() = nY-1;
3206 p[1].X() = nX-1; p[1].Y() = nY+nHalfSize-1;
3207 p[2].X() = nX-1; p[2].Y() = nY+nHalfSize+1;
3208 p[3].X() = nX+nHalfSize-1; p[3].Y() = nY+nSize+1;
3209 p[4].X() = nX+nHalfSize+1; p[4].Y() = nY+nSize+1;
3210 p[5].X() = nX+nHalfSize+1; p[5].Y() = nY-1;
3211 break;
3212 case WINDOWALIGN_BOTTOM:
3213 p[0].X() = nX-1; p[0].Y() = nY+nHalfSize-1;
3214 p[1].X() = nX-1; p[1].Y() = nY+nHalfSize+1;
3215 p[2].X() = nX+nSize+1; p[2].Y() = nY+nHalfSize+1;
3216 p[3].X() = nX+nSize+1; p[3].Y() = nY+nHalfSize-1;
3217 p[4].X() = nX+nHalfSize+1; p[4].Y() = nY-1;
3218 p[5].X() = nX+nHalfSize-1; p[5].Y() = nY-1;
3219 break;
3221 Polygon aPoly(6,p);
3222 Region aRgn( aPoly );
3223 pBox->SetClipRegion( aRgn );
3226 // -----------------------------------------------------------------------
3228 void ToolBox::ImplDrawMenubutton( ToolBox *pThis, BOOL bHighlight )
3230 if( !pThis->mpData->maMenubuttonItem.maRect.IsEmpty() )
3232 // #i53937# paint menu button only if necessary
3233 if( !(pThis->GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE) && !pThis->ImplHasClippedItems() )
3234 return;
3236 // execute pending paint requests
3237 ImplCheckUpdate( pThis );
3239 BOOL bFillColor = pThis->IsFillColor();
3240 BOOL bLineColor = pThis->IsLineColor();
3241 Color aOldFillCol = pThis->GetFillColor();
3242 Color aOldLineCol = pThis->GetLineColor();
3243 BOOL bNativeButtons = pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON );
3245 Rectangle aInnerRect( pThis->mpData->maMenubuttonItem.maRect );
3246 if( pThis->mpData->mnMenuButtonWidth > TB_MENUBUTTON_SIZE )
3248 long nDiff = pThis->mpData->mnMenuButtonWidth - TB_MENUBUTTON_SIZE;
3249 long nDiff1 = nDiff/2;
3250 long nDiff2 = nDiff - nDiff1;
3251 if( pThis->IsHorizontal() )
3253 aInnerRect.Left() += nDiff1;
3254 aInnerRect.Right() -= nDiff2;
3256 else
3258 aInnerRect.Top() += nDiff1;
3259 aInnerRect.Bottom() -= nDiff2;
3263 if( pThis->IsHorizontal() )
3265 aInnerRect.nLeft+=2;
3266 aInnerRect.nRight-=1;
3267 aInnerRect.nTop+=1;
3268 aInnerRect.nBottom-=1;
3270 else
3272 aInnerRect.nLeft+=1;
3273 aInnerRect.nRight-=1;
3274 aInnerRect.nTop+=2;
3275 aInnerRect.nBottom-=1;
3278 ImplErase( pThis, bNativeButtons ? pThis->mpData->maMenubuttonItem.maRect : aInnerRect, bHighlight );
3280 if( bHighlight )
3282 if( bNativeButtons )
3283 ImplDrawButton( pThis, pThis->mpData->maMenubuttonItem.maRect, 2, FALSE, TRUE, FALSE );
3284 else
3285 pThis->DrawSelectionBackground( aInnerRect, 2, FALSE, FALSE, FALSE );
3287 else
3289 // improve visibility by using a dark gradient
3290 Gradient g;
3291 g.SetAngle( pThis->mbHorz ? 0 : 900 );
3292 g.SetStyle( GRADIENT_LINEAR );
3294 g.SetStartColor( pThis->GetSettings().GetStyleSettings().GetFaceColor() );
3295 g.SetEndColor( pThis->GetSettings().GetStyleSettings().GetShadowColor() );
3297 pThis->DrawGradient( aInnerRect, g );
3300 Rectangle aRect( aInnerRect );
3301 if( pThis->mbHorz )
3302 aRect.Top() = aRect.Bottom() - aRect.getHeight()/3;
3303 else
3304 aRect.Left() = aRect.Right() - aRect.getWidth()/3;
3306 if( pThis->mpData->maMenuType & TOOLBOX_MENUTYPE_CUSTOMIZE )
3307 ImplDrawDropdownArrow( pThis, aRect, TRUE, !pThis->mbHorz );
3309 if( pThis->ImplHasClippedItems() )
3311 aRect = aInnerRect;
3312 if( pThis->mbHorz )
3313 aRect.Bottom() = aRect.Top() + aRect.getHeight()/3;
3314 else
3315 aRect.Right() = aRect.Left() + aRect.getWidth()/3;
3317 ImplDrawMoreIndicator( pThis, aRect, TRUE, !pThis->mbHorz );
3320 // store highlight state
3321 pThis->mpData->mbMenubuttonSelected = bHighlight;
3323 // restore colors
3324 if( bFillColor )
3325 pThis->SetFillColor( aOldFillCol );
3326 else
3327 pThis->SetFillColor();
3328 if( bLineColor )
3329 pThis->SetLineColor( aOldLineCol );
3330 else
3331 pThis->SetLineColor();
3335 // -----------------------------------------------------------------------
3337 void ToolBox::ImplDrawSpin( BOOL bUpperIn, BOOL bLowerIn )
3339 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3341 BOOL bTmpUpper;
3342 BOOL bTmpLower;
3344 if ( maUpperRect.IsEmpty() || maLowerRect.IsEmpty() )
3345 return;
3347 if ( mnCurLine > 1 )
3348 bTmpUpper = TRUE;
3349 else
3350 bTmpUpper = FALSE;
3352 if ( mnCurLine+mnVisLines-1 < mnCurLines )
3353 bTmpLower = TRUE;
3354 else
3355 bTmpLower = FALSE;
3357 if ( !IsEnabled() )
3359 bTmpUpper = FALSE;
3360 bTmpLower = FALSE;
3363 ImplDrawSpinButton( this, maUpperRect, maLowerRect,
3364 bUpperIn, bLowerIn, bTmpUpper, bTmpLower, !mbHorz );
3367 // -----------------------------------------------------------------------
3369 void ToolBox::ImplDrawNext( BOOL bIn )
3371 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3373 if ( maNextToolRect.IsEmpty() )
3374 return;
3376 DecorationView aDecoView( this );
3378 // Button malen
3379 long nX = SMALLBUTTON_OFF_NORMAL_X;
3380 long nY = SMALLBUTTON_OFF_NORMAL_Y;
3381 USHORT nStyle = 0;
3382 if ( bIn == 1 )
3384 nStyle |= BUTTON_DRAW_PRESSED;
3385 nX = SMALLBUTTON_OFF_PRESSED_X;
3386 nY = SMALLBUTTON_OFF_PRESSED_Y;
3388 aDecoView.DrawButton( maNextToolRect, nStyle );
3390 // Inhalt ausgeben
3391 BOOL bLeft = FALSE;
3392 BOOL bTop = FALSE;
3393 if ( mbHorz )
3395 bLeft = TRUE;
3396 nX += (maNextToolRect.GetWidth()-6)/2-4;
3397 nY += (maNextToolRect.GetHeight()-6)/2-6;
3399 else
3401 bTop = TRUE;
3402 nY += (maNextToolRect.GetHeight()-6)/2-4;
3403 nX += (maNextToolRect.GetWidth()-6)/2-6;
3406 nX += maNextToolRect.Left();
3407 nY += maNextToolRect.Top();
3408 SetLineColor();
3409 SetFillColor( COL_LIGHTBLUE );
3410 ImplDrawToolArrow( this, nX, nY, TRUE, FALSE, bLeft, bTop, 10 );
3413 // -----------------------------------------------------------------------
3415 static void ImplDrawButton( ToolBox* pThis, const Rectangle &rRect, USHORT highlight, BOOL bChecked, BOOL bEnabled, BOOL bIsWindow )
3417 // draws toolbar button background either native or using a coloured selection
3418 // if bIsWindow is TRUE, the corresponding item is a control and only a selection border will be drawn
3420 BOOL bNativeOk = FALSE;
3421 if( !bIsWindow && pThis->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
3423 ImplControlValue aControlValue;
3424 Region aCtrlRegion( rRect );
3425 ControlState nState = 0;
3427 if ( highlight == 1 ) nState |= CTRL_STATE_PRESSED;
3428 if ( highlight == 2 ) nState |= CTRL_STATE_ROLLOVER;
3429 if ( bEnabled ) nState |= CTRL_STATE_ENABLED;
3431 aControlValue.setTristateVal( bChecked ? BUTTONVALUE_ON : BUTTONVALUE_OFF );
3434 bNativeOk = pThis->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
3435 aCtrlRegion, nState, aControlValue, rtl::OUString() );
3438 if( !bNativeOk )
3439 pThis->DrawSelectionBackground( rRect, bIsWindow ? 3 : highlight, bChecked, TRUE, bIsWindow, 2, NULL, NULL );
3442 void ToolBox::ImplDrawItem( USHORT nPos, BOOL bHighlight, BOOL bPaint, BOOL bLayout )
3444 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3446 if( nPos >= mpData->m_aItems.size() )
3447 return;
3449 // execute pending paint requests
3450 ImplCheckUpdate( this );
3452 ImplDisableFlatButtons();
3454 SetFillColor();
3456 ImplToolItem* pItem = &mpData->m_aItems[nPos];
3457 MetricVector* pVector = bLayout ? &mpData->m_pLayoutData->m_aUnicodeBoundRects : NULL;
3458 String* pDisplayText = bLayout ? &mpData->m_pLayoutData->m_aDisplayText : NULL;
3460 // Falls Rechteck ausserhalb des sichbaren Bereichs liegt
3461 if ( pItem->maRect.IsEmpty() )
3462 return;
3464 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3466 // no gradient background for items that have a popup open
3467 BOOL bHasOpenPopup = (mpFloatWin != NULL) && (mnDownItemId==pItem->mnId);
3469 BOOL bHighContrastWhite = FALSE;
3470 // check the face color as highcontrast indicator
3471 // because the toolbox itself might have a gradient
3472 if( rStyleSettings.GetFaceColor() == Color( COL_WHITE ) )
3473 bHighContrastWhite = TRUE;
3475 // draw separators in flat style only
3476 if ( !bLayout &&
3477 (mnOutStyle & TOOLBOX_STYLE_FLAT) &&
3478 (pItem->meType == TOOLBOXITEM_SEPARATOR) &&
3479 nPos > 0
3482 // no separator before or after windows or at breaks
3483 ImplToolItem* pTempItem = &mpData->m_aItems[nPos-1];
3484 if ( pTempItem && !pTempItem->mbShowWindow && nPos < mpData->m_aItems.size()-1 )
3486 pTempItem = &mpData->m_aItems[nPos+1];
3487 if ( !pTempItem->mbShowWindow && !pTempItem->mbBreak )
3489 long nCenterPos, nSlim;
3490 SetLineColor( rStyleSettings.GetSeparatorColor() );
3491 if ( IsHorizontal() )
3493 nSlim = (pItem->maRect.Bottom() - pItem->maRect.Top ()) / 4;
3494 nCenterPos = pItem->maRect.Center().X();
3495 DrawLine( Point( nCenterPos, pItem->maRect.Top() + nSlim ),
3496 Point( nCenterPos, pItem->maRect.Bottom() - nSlim ) );
3498 else
3500 nSlim = (pItem->maRect.Right() - pItem->maRect.Left ()) / 4;
3501 nCenterPos = pItem->maRect.Center().Y();
3502 DrawLine( Point( pItem->maRect.Left() + nSlim, nCenterPos ),
3503 Point( pItem->maRect.Right() - nSlim, nCenterPos ) );
3509 // do nothing if item is no button or will be displayed as window
3510 if ( (pItem->meType != TOOLBOXITEM_BUTTON) ||
3511 (pItem->mbShowWindow && !mbCustomizeMode) )
3512 return;
3514 // we need a TBDragMananger to draw the configuration item
3515 ImplTBDragMgr* pMgr;
3516 if ( pItem->mnId == mnConfigItem )
3518 pMgr = ImplGetTBDragMgr();
3519 pMgr->HideDragRect();
3521 else
3522 pMgr = NULL;
3524 // during configuration mode visible windows will be drawn in a special way
3525 if ( mbCustomizeMode && pItem->mbShowWindow )
3527 Font aOldFont = GetFont();
3528 Color aOldTextColor = GetTextColor();
3530 SetZoomedPointFont( rStyleSettings.GetAppFont() );
3531 SetLineColor( Color( COL_BLACK ) );
3532 SetFillColor( rStyleSettings.GetFieldColor() );
3533 SetTextColor( rStyleSettings.GetFieldTextColor() );
3534 if( !bLayout )
3535 DrawRect( pItem->maRect );
3537 Size aSize( GetCtrlTextWidth( pItem->maText ), GetTextHeight() );
3538 Point aPos( pItem->maRect.Left()+2, pItem->maRect.Top() );
3539 aPos.Y() += (pItem->maRect.GetHeight()-aSize.Height())/2;
3540 BOOL bClip;
3541 if ( (aSize.Width() > pItem->maRect.GetWidth()-2) ||
3542 (aSize.Height() > pItem->maRect.GetHeight()-2) )
3544 bClip = TRUE;
3545 Rectangle aTempRect( pItem->maRect.Left()+1, pItem->maRect.Top()+1,
3546 pItem->maRect.Right()-1, pItem->maRect.Bottom()-1 );
3547 Region aTempRegion( aTempRect );
3548 SetClipRegion( aTempRegion );
3550 else
3551 bClip = FALSE;
3552 if( bLayout )
3554 mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
3555 mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3556 mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3558 DrawCtrlText( aPos, pItem->maText, 0, STRING_LEN, TEXT_DRAW_MNEMONIC, pVector, pDisplayText );
3559 if ( bClip )
3560 SetClipRegion();
3561 SetFont( aOldFont );
3562 SetTextColor( aOldTextColor );
3564 // Gegebenenfalls noch Config-Frame zeichnen
3565 if ( pMgr && !bLayout)
3566 pMgr->UpdateDragRect();
3567 return;
3570 // draw button
3571 Size aBtnSize = pItem->maRect.GetSize();
3572 if( ImplGetSVData()->maNWFData.mbToolboxDropDownSeparate )
3574 // separate button not for dropdown only where the whole button is painted
3575 if ( pItem->mnBits & TIB_DROPDOWN &&
3576 ((pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY) )
3578 Rectangle aArrowRect = pItem->GetDropDownRect( mbHorz );
3579 if( aArrowRect.Top() == pItem->maRect.Top() ) // dropdown arrow on right side
3580 aBtnSize.Width() -= aArrowRect.GetWidth();
3581 else // dropdown arrow on bottom side
3582 aBtnSize.Height() -= aArrowRect.GetHeight();
3585 Rectangle aButtonRect( pItem->maRect.TopLeft(), aBtnSize );
3586 long nOffX = SMALLBUTTON_OFF_NORMAL_X;
3587 long nOffY = SMALLBUTTON_OFF_NORMAL_Y;
3588 long nImageOffX=0;
3589 long nImageOffY=0;
3590 long nTextOffX=0;
3591 long nTextOffY=0;
3592 USHORT nStyle = 0;
3594 if ( pItem->meState == STATE_CHECK )
3596 nStyle |= BUTTON_DRAW_CHECKED;
3598 else if ( pItem->meState == STATE_DONTKNOW )
3600 nStyle |= BUTTON_DRAW_DONTKNOW;
3602 if ( bHighlight == 1 )
3604 nStyle |= BUTTON_DRAW_PRESSED;
3607 if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
3609 nOffX = OUTBUTTON_OFF_NORMAL_X;
3610 nOffY = OUTBUTTON_OFF_NORMAL_Y;
3611 if ( bHighlight )
3613 nOffX++;
3614 nOffY++;
3618 if( ! bLayout )
3620 if ( mnOutStyle & TOOLBOX_STYLE_FLAT )
3622 if ( (pItem->meState != STATE_NOCHECK) || !bPaint )
3624 ImplErase( this, pItem->maRect, bHighlight, bHasOpenPopup );
3627 else
3629 if ( mnOutStyle & TOOLBOX_STYLE_OUTBUTTON )
3630 ImplDrawOutButton( this, aButtonRect, nStyle );
3631 else
3633 DecorationView aDecoView( this );
3634 aDecoView.DrawButton( aButtonRect, nStyle );
3639 nOffX += pItem->maRect.Left();
3640 nOffY += pItem->maRect.Top();
3642 // determine what has to be drawn on the button: image, text or both
3643 BOOL bImage;
3644 BOOL bText;
3645 ButtonType tmpButtonType = determineButtonType( pItem, meButtonType ); // default to toolbox setting
3646 pItem->DetermineButtonDrawStyle( tmpButtonType, bImage, bText );
3648 // compute output values
3649 long nBtnWidth = aBtnSize.Width()-SMALLBUTTON_HSIZE;
3650 long nBtnHeight = aBtnSize.Height()-SMALLBUTTON_VSIZE;
3651 Size aImageSize;
3652 Size aTxtSize;
3654 if ( bText )
3656 aTxtSize.Width() = GetCtrlTextWidth( pItem->maText );
3657 aTxtSize.Height() = GetTextHeight();
3660 if ( bImage && ! bLayout )
3662 const Image* pImage;
3663 if ( bHighlight && (!(pItem->maHighImage)) == FALSE )
3664 pImage = &(pItem->maHighImage);
3665 else
3666 pImage = &(pItem->maImage);
3668 aImageSize = pImage->GetSizePixel();
3670 // determine drawing flags
3671 USHORT nImageStyle = 0;
3673 if ( !pItem->mbEnabled || !IsEnabled() )
3674 nImageStyle |= IMAGE_DRAW_DISABLE;
3676 // #i35563# the dontknow state indicates different states at the same time
3677 // which should not be rendered disabled but normal
3678 //if ( pItem->meState == STATE_DONTKNOW )
3679 // nImageStyle |= IMAGE_DRAW_DISABLE;
3681 // draw the image
3682 nImageOffX = nOffX;
3683 nImageOffY = nOffY;
3684 if ( (pItem->mnBits & (TIB_LEFT|TIB_DROPDOWN)) || bText )
3686 // left align also to leave space for drop down arrow
3687 // and when drawing text+image
3688 // just center in y, except for vertical (ie rotated text)
3689 if( mbHorz || !bText )
3690 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3692 else
3694 nImageOffX += (nBtnWidth-aImageSize.Width())/2;
3695 nImageOffY += (nBtnHeight-aImageSize.Height())/2;
3697 if ( bHighlight || (pItem->meState == STATE_CHECK) )
3699 if( bHasOpenPopup )
3700 ImplDrawFloatwinBorder( pItem );
3701 else
3702 ImplDrawButton( this, aButtonRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? TRUE : FALSE );
3704 if( bHighlight )
3706 if( bHighContrastWhite )
3707 nImageStyle |= IMAGE_DRAW_COLORTRANSFORM;
3710 DrawImage( Point( nImageOffX, nImageOffY ), *pImage, nImageStyle );
3713 // draw the text
3714 BOOL bRotate = FALSE;
3715 if ( bText )
3717 nTextOffX = nOffX;
3718 nTextOffY = nOffY;
3720 // rotate text when vertically docked
3721 Font aOldFont = GetFont();
3722 if( pItem->mbVisibleText && !ImplIsFloatingMode() &&
3723 ((meAlign == WINDOWALIGN_LEFT) || (meAlign == WINDOWALIGN_RIGHT)) )
3725 bRotate = TRUE;
3727 Font aRotateFont = aOldFont;
3729 if ( meAlign == WINDOWALIGN_LEFT )
3731 aRotateFont.SetOrientation( 900 );
3732 nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
3733 nTextOffY += aTxtSize.Width();
3734 nTextOffY += (nBtnHeight-aTxtSize.Width())/2;
3736 else*/
3738 aRotateFont.SetOrientation( 2700 );
3740 // center horizontally
3741 nTextOffX += aTxtSize.Height();
3742 nTextOffX += (nBtnWidth-aTxtSize.Height())/2;
3744 // add in image offset
3745 if( bImage )
3746 nTextOffY = nImageOffY + aImageSize.Height() + TB_IMAGETEXTOFFSET;
3749 SetFont( aRotateFont );
3751 else
3753 // center vertically
3754 nTextOffY += (nBtnHeight-aTxtSize.Height())/2;
3756 // add in image offset
3757 if( bImage )
3758 nTextOffX = nImageOffX + aImageSize.Width() + TB_IMAGETEXTOFFSET;
3759 //nTextOffX += TB_TEXTOFFSET/2;
3762 // draw selection only if not already drawn during image output (see above)
3763 if ( !bLayout && !bImage && (bHighlight || (pItem->meState == STATE_CHECK) ) )
3765 if( bHasOpenPopup )
3766 ImplDrawFloatwinBorder( pItem );
3767 else
3768 ImplDrawButton( this, pItem->maRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), pItem->mbShowWindow ? TRUE : FALSE );
3771 USHORT nTextStyle = 0;
3772 if ( !pItem->mbEnabled )
3773 nTextStyle |= TEXT_DRAW_DISABLE;
3774 if( bLayout )
3776 mpData->m_pLayoutData->m_aLineIndices.push_back( mpData->m_pLayoutData->m_aDisplayText.Len() );
3777 mpData->m_pLayoutData->m_aLineItemIds.push_back( pItem->mnId );
3778 mpData->m_pLayoutData->m_aLineItemPositions.push_back( nPos );
3780 DrawCtrlText( Point( nTextOffX, nTextOffY ), pItem->maText,
3781 0, STRING_LEN, nTextStyle, pVector, pDisplayText );
3782 if ( bRotate )
3783 SetFont( aOldFont );
3786 if( bLayout )
3787 return;
3789 // paint optional drop down arrow
3790 if ( pItem->mnBits & TIB_DROPDOWN )
3792 Rectangle aDropDownRect( pItem->GetDropDownRect( mbHorz ) );
3793 BOOL bSetColor = TRUE;
3794 if ( !pItem->mbEnabled || !IsEnabled() )
3796 bSetColor = FALSE;
3797 SetFillColor( rStyleSettings.GetShadowColor() );
3800 // dropdown only will be painted without inner border
3801 if( (pItem->mnBits & TIB_DROPDOWNONLY) != TIB_DROPDOWNONLY )
3803 ImplErase( this, aDropDownRect, bHighlight, bHasOpenPopup );
3805 if( bHighlight || (pItem->meState == STATE_CHECK) )
3807 if( bHasOpenPopup )
3808 ImplDrawFloatwinBorder( pItem );
3809 else
3810 ImplDrawButton( this, aDropDownRect, bHighlight, pItem->meState == STATE_CHECK, pItem->mbEnabled && IsEnabled(), FALSE );
3813 ImplDrawDropdownArrow( this, aDropDownRect, bSetColor, bRotate );
3816 // Gegebenenfalls noch Config-Frame zeichnen
3817 if ( pMgr )
3818 pMgr->UpdateDragRect();
3821 // -----------------------------------------------------------------------
3823 void ToolBox::ImplStartCustomizeMode()
3825 mbCustomizeMode = TRUE;
3827 mpData->ImplClearLayoutData();
3829 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3830 while ( it != mpData->m_aItems.end() )
3832 if ( it->mbShowWindow )
3834 it->mpWindow->Hide();
3836 if ( !(it->maRect.IsEmpty()) )
3837 Invalidate( it->maRect );
3840 ++it;
3844 void ToolBox::SetCustomizeMode( BOOL bSet )
3846 if ( bSet )
3847 ImplStartCustomizeMode();
3848 else
3849 ImplEndCustomizeMode();
3852 // -----------------------------------------------------------------------
3854 void ToolBox::ImplEndCustomizeMode()
3856 mbCustomizeMode = FALSE;
3858 mpData->ImplClearLayoutData();
3860 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
3861 while ( it != mpData->m_aItems.end() )
3863 if ( it->mbShowWindow )
3865 if ( !(it->maRect.IsEmpty()) )
3866 Invalidate( it->maRect );
3868 it->mpWindow->Show();
3871 ++it;
3875 // -----------------------------------------------------------------------
3877 void ToolBox::ImplDrawFloatwinBorder( ImplToolItem* pItem )
3879 if ( !pItem->maRect.IsEmpty() )
3881 Rectangle aRect( mpFloatWin->ImplGetItemEdgeClipRect() );
3882 aRect.SetPos( AbsoluteScreenToOutputPixel( aRect.TopLeft() ) );
3883 SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() );
3884 Point p1, p2;
3886 p1 = pItem->maRect.TopLeft();
3887 p1.X()++;
3888 p2 = pItem->maRect.TopRight();
3889 p2.X()--;
3890 DrawLine( p1, p2);
3891 p1 = pItem->maRect.BottomLeft();
3892 p1.X()++;
3893 p2 = pItem->maRect.BottomRight();
3894 p2.X()--;
3895 DrawLine( p1, p2);
3897 p1 = pItem->maRect.TopLeft();
3898 p1.Y()++;
3899 p2 = pItem->maRect.BottomLeft();
3900 p2.Y()--;
3901 DrawLine( p1, p2);
3902 p1 = pItem->maRect.TopRight();
3903 p1.Y()++;
3904 p2 = pItem->maRect.BottomRight();
3905 p2.Y()--;
3906 DrawLine( p1, p2);
3908 //DrawRect( pItem->maRect );
3912 void ToolBox::ImplFloatControl( BOOL bStart, FloatingWindow* pFloatWindow )
3914 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3916 if ( bStart )
3918 mpFloatWin = pFloatWindow;
3920 // redraw item, to trigger drawing of a special border
3921 ImplDrawItem( mnCurPos, TRUE );
3923 mbDrag = FALSE;
3924 EndTracking();
3925 ReleaseMouse();
3927 else
3929 mpFloatWin = NULL;
3931 // if focus is still in this toolbox, then the floater was opened by keyboard
3932 // draw current item with highlight and keep old state
3933 BOOL bWasKeyboardActivate = mpData->mbDropDownByKeyboard;
3936 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3937 ImplDrawItem( mnCurPos, bWasKeyboardActivate ? 2 : 0 );
3938 Deactivate();
3940 if( !bWasKeyboardActivate )
3942 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
3943 mnCurItemId = 0;
3944 mnHighItemId = 0;
3946 mnDownItemId = 0;
3951 // -----------------------------------------------------------------------
3953 void ToolBox::ShowLine( BOOL bNext )
3955 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
3957 mbFormat = TRUE;
3959 if ( mpData->mbPageScroll )
3961 USHORT delta = mnVisLines;
3962 if ( bNext )
3964 mnCurLine = mnCurLine + delta;
3965 if ( mnCurLine+mnVisLines-1 > mnCurLines )
3966 mnCurLine = mnCurLines - mnVisLines+1;
3968 else
3970 if( mnCurLine >= delta+1 )
3971 mnCurLine = mnCurLine - delta;
3972 else
3973 mnCurLine = 1;
3976 else
3978 if ( bNext )
3979 mnCurLine++;
3980 else
3981 mnCurLine--;
3984 ImplFormat();
3987 // -----------------------------------------------------------------------
3989 BOOL ToolBox::ImplHandleMouseMove( const MouseEvent& rMEvt, BOOL bRepeat )
3991 Point aMousePos = rMEvt.GetPosPixel();
3993 // Ist ToolBox aktiv
3994 if ( mbDrag && mnCurPos != TOOLBOX_ITEM_NOTFOUND )
3996 // Befindet sich Maus ueber dem Item
3997 ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
3998 if ( pItem->maRect.IsInside( aMousePos ) )
4000 if ( !mnCurItemId )
4002 ImplDrawItem( mnCurPos, TRUE );
4003 mnCurItemId = pItem->mnId;
4004 Highlight();
4007 if ( (pItem->mnBits & TIB_REPEAT) && bRepeat )
4008 Select();
4010 else
4012 if ( mnCurItemId )
4014 ImplDrawItem( mnCurPos );
4015 mnCurItemId = 0;
4016 ImplDrawItem( mnCurPos );
4017 Highlight();
4021 return TRUE;
4024 if ( mbUpper )
4026 BOOL bNewIn = maUpperRect.IsInside( aMousePos );
4027 if ( bNewIn != mbIn )
4029 mbIn = bNewIn;
4030 ImplDrawSpin( mbIn, FALSE );
4032 return TRUE;
4035 if ( mbLower )
4037 BOOL bNewIn = maLowerRect.IsInside( aMousePos );
4038 if ( bNewIn != mbIn )
4040 mbIn = bNewIn;
4041 ImplDrawSpin( FALSE, mbIn );
4043 return TRUE;
4046 if ( mbNextTool )
4048 BOOL bNewIn = maNextToolRect.IsInside( aMousePos );
4049 if ( bNewIn != mbIn )
4051 mbIn = bNewIn;
4052 ImplDrawNext( mbIn );
4054 return TRUE;
4057 return FALSE;
4060 // -----------------------------------------------------------------------
4062 BOOL ToolBox::ImplHandleMouseButtonUp( const MouseEvent& rMEvt, BOOL bCancel )
4064 ImplDisableFlatButtons();
4066 // stop eventual running dropdown timer
4067 if( mnCurPos < mpData->m_aItems.size() &&
4068 (mpData->m_aItems[mnCurPos].mnBits & TIB_DROPDOWN ) )
4070 mpData->maDropdownTimer.Stop();
4073 if ( mbDrag || mbSelection )
4075 // Hier die MouseDaten setzen, wenn Selection-Modus, da dann kein
4076 // MouseButtonDown-Handler gerufen wird
4077 if ( mbSelection )
4079 mnMouseClicks = rMEvt.GetClicks();
4080 mnMouseModifier = rMEvt.GetModifier();
4083 Deactivate();
4085 if ( mbDrag )
4086 mbDrag = FALSE;
4087 else
4089 mbSelection = FALSE;
4090 if ( mnCurPos == TOOLBOX_ITEM_NOTFOUND )
4091 return TRUE;
4094 // Wurde Maus ueber dem Item losgelassen
4095 if( mnCurPos < mpData->m_aItems.size() )
4097 ImplToolItem* pItem = &mpData->m_aItems[mnCurPos];
4098 if ( pItem->maRect.IsInside( rMEvt.GetPosPixel() ) )
4100 mnCurItemId = pItem->mnId;
4101 if ( !bCancel )
4103 // Gegebenenfalls ein AutoCheck durchfuehren
4104 if ( pItem->mnBits & TIB_AUTOCHECK )
4106 if ( pItem->mnBits & TIB_RADIOCHECK )
4108 if ( pItem->meState != STATE_CHECK )
4109 SetItemState( pItem->mnId, STATE_CHECK );
4111 else
4113 if ( pItem->meState != STATE_CHECK )
4114 pItem->meState = STATE_CHECK;
4115 else
4116 pItem->meState = STATE_NOCHECK;
4120 // Select nicht bei Repeat ausloesen, da dies schon im
4121 // MouseButtonDown ausgeloest wurde
4122 if ( !(pItem->mnBits & TIB_REPEAT) )
4124 // Gegen zerstoeren im Select-Handler sichern
4125 ImplDelData aDelData;
4126 ImplAddDel( &aDelData );
4127 Select();
4128 if ( aDelData.IsDelete() )
4129 return TRUE;
4130 ImplRemoveDel( &aDelData );
4135 DBG_CHKTHIS( Window, ImplDbgCheckWindow );
4138 // Items nicht geloescht, im Select-Handler
4139 if ( mnCurItemId )
4141 BOOL bHighlight;
4142 if ( (mnCurItemId == mnHighItemId) && (mnOutStyle & TOOLBOX_STYLE_FLAT) )
4143 bHighlight = 2;
4144 else
4145 bHighlight = FALSE;
4146 // Get current pos for the case that items are inserted/removed
4147 // in the toolBox
4148 mnCurPos = GetItemPos( mnCurItemId );
4149 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4151 ImplDrawItem( mnCurPos, bHighlight );
4152 Flush();
4158 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
4159 mnCurItemId = 0;
4160 mnDownItemId = 0;
4161 mnMouseClicks = 0;
4162 mnMouseModifier = 0;
4163 return TRUE;
4165 else if ( mbUpper || mbLower )
4167 if ( mbIn )
4168 ShowLine( !mbUpper );
4169 mbUpper = FALSE;
4170 mbLower = FALSE;
4171 mbIn = FALSE;
4172 ImplDrawSpin( FALSE, FALSE );
4173 return TRUE;
4175 else if ( mbNextTool )
4177 mbNextTool = FALSE;
4178 mbIn = FALSE;
4179 ImplDrawNext( FALSE );
4180 NextToolBox();
4181 return TRUE;
4184 return FALSE;
4187 // -----------------------------------------------------------------------
4189 void ToolBox::MouseMove( const MouseEvent& rMEvt )
4191 // pressing a modifier generates synthetic mouse moves
4192 // ignore it if keyboard selection is acive
4193 if( HasFocus() && ( rMEvt.GetMode() & MOUSE_MODIFIERCHANGED ) )
4194 return;
4196 if ( ImplHandleMouseMove( rMEvt ) )
4197 return;
4199 ImplDisableFlatButtons();
4201 Point aMousePos = rMEvt.GetPosPixel();
4203 // only highlight when the focus is not inside a child window of a toolbox
4204 // eg, in a edit control
4205 // and do not hilight when focus is in a different toolbox
4206 BOOL bDrawHotSpot = TRUE;
4207 Window *pWin = Application::GetFocusWindow();
4208 if( pWin && pWin->ImplGetWindowImpl()->mbToolBox && pWin != this )
4209 bDrawHotSpot = FALSE;
4211 else
4212 if( pWin && !pWin->ImplGetWindowImpl()->mbToolBox )
4213 while( pWin )
4215 pWin = pWin->GetParent();
4216 if( pWin && pWin->ImplGetWindowImpl()->mbToolBox )
4218 bDrawHotSpot = FALSE;
4219 break;
4224 if ( mbSelection && bDrawHotSpot )
4226 USHORT i = 0;
4227 USHORT nNewPos = TOOLBOX_ITEM_NOTFOUND;
4229 // Item suchen, das geklickt wurde
4230 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4231 while ( it != mpData->m_aItems.end() )
4233 // Wenn Mausposition in diesem Item vorhanden, kann die
4234 // Suche abgebrochen werden
4235 if ( it->maRect.IsInside( aMousePos ) )
4237 // Wenn es ein Button ist, dann wird er selektiert
4238 if ( it->meType == TOOLBOXITEM_BUTTON )
4240 // Wenn er disablet ist, findet keine Aenderung
4241 // statt
4242 if ( !it->mbEnabled || it->mbShowWindow )
4243 nNewPos = mnCurPos;
4244 else
4245 nNewPos = i;
4248 break;
4251 i++;
4252 ++it;
4255 // was a new entery selected ?
4256 // don't change selection if keyboard selection is active and
4257 // mouse leaves the toolbox
4258 if ( nNewPos != mnCurPos && !( HasFocus() && nNewPos == TOOLBOX_ITEM_NOTFOUND ) )
4260 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4262 ImplDrawItem( mnCurPos );
4263 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( mnCurPos ) );
4266 mnCurPos = nNewPos;
4267 if ( mnCurPos != TOOLBOX_ITEM_NOTFOUND )
4269 mnCurItemId = mnHighItemId = it->mnId;
4270 ImplDrawItem( mnCurPos, 2 /*TRUE*/ ); // always use shadow effect (2)
4272 else
4273 mnCurItemId = mnHighItemId = 0;
4275 Highlight();
4277 return;
4280 if ( mbDragging )
4282 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4283 pMgr->Dragging( aMousePos );
4284 return;
4287 PointerStyle eStyle = POINTER_ARROW;
4289 // change mouse cursor over drag area
4290 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
4291 if( pWrapper && pWrapper->GetDragArea().IsInside( rMEvt.GetPosPixel() ) )
4292 eStyle = POINTER_MOVE;
4294 if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4296 if ( rMEvt.GetMode() & MOUSE_SIMPLEMOVE )
4298 USHORT nLinePtr = ImplTestLineSize( this, rMEvt.GetPosPixel() );
4299 if ( nLinePtr & DOCK_LINEHSIZE )
4301 if ( meAlign == WINDOWALIGN_LEFT )
4302 eStyle = POINTER_WINDOW_ESIZE;
4303 else
4304 eStyle = POINTER_WINDOW_WSIZE;
4306 else if ( nLinePtr & DOCK_LINEVSIZE )
4308 if ( meAlign == WINDOWALIGN_TOP )
4309 eStyle = POINTER_WINDOW_SSIZE;
4310 else
4311 eStyle = POINTER_WINDOW_NSIZE;
4316 if ( (eStyle == POINTER_ARROW) && mbCustomizeMode )
4318 // Item suchen, das geklickt wurde
4319 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4320 while ( it != mpData->m_aItems.end() )
4322 // Wenn es ein Customize-Window ist, gegebenenfalls den
4323 // Resize-Pointer anzeigen
4324 if ( it->mbShowWindow )
4326 if ( it->maRect.IsInside( aMousePos ) )
4328 if ( it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X() )
4329 eStyle = POINTER_HSIZEBAR;
4330 break;
4334 ++it;
4338 if ( bDrawHotSpot && ( ((eStyle == POINTER_ARROW) && (mnOutStyle & TOOLBOX_STYLE_HANDPOINTER)) ||
4339 (mnOutStyle & TOOLBOX_STYLE_FLAT) || !mnOutStyle ) )
4341 BOOL bClearHigh = TRUE;
4342 if ( !rMEvt.IsLeaveWindow() && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4344 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4345 while ( it != mpData->m_aItems.end() )
4347 if ( it->maRect.IsInside( aMousePos ) )
4349 if ( (it->meType == TOOLBOXITEM_BUTTON) && it->mbEnabled )
4351 if ( !mnOutStyle || (mnOutStyle & TOOLBOX_STYLE_FLAT) )
4353 bClearHigh = FALSE;
4354 if ( mnHighItemId != it->mnId )
4356 USHORT nTempPos = sal::static_int_cast<USHORT>(it - mpData->m_aItems.begin());
4357 if ( mnHighItemId )
4359 ImplHideFocus();
4360 USHORT nPos = GetItemPos( mnHighItemId );
4361 ImplDrawItem( nPos );
4362 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
4364 if ( mpData->mbMenubuttonSelected )
4366 // remove highlight from menubutton
4367 ImplDrawMenubutton( this, FALSE );
4369 mnHighItemId = it->mnId;
4370 ImplDrawItem( nTempPos, 2 );
4371 ImplShowFocus();
4372 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
4375 if ( mnOutStyle & TOOLBOX_STYLE_HANDPOINTER )
4376 eStyle = POINTER_REFHAND;
4378 break;
4381 ++it;
4385 // only clear highlight when focus is not in toolbar
4386 BOOL bMenuButtonHit = mpData->maMenubuttonItem.maRect.IsInside( aMousePos );
4387 if ( bClearHigh || bMenuButtonHit )
4389 if ( !bMenuButtonHit && mpData->mbMenubuttonSelected )
4391 // remove highlight from menubutton
4392 ImplDrawMenubutton( this, FALSE );
4395 if( mnHighItemId )
4397 USHORT nClearPos = GetItemPos( mnHighItemId );
4398 if ( nClearPos != TOOLBOX_ITEM_NOTFOUND )
4400 ImplDrawItem( nClearPos, (nClearPos == mnCurPos) ? TRUE : FALSE );
4401 if( nClearPos != mnCurPos )
4402 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nClearPos ) );
4404 ImplHideFocus();
4405 mnHighItemId = 0;
4408 if( bMenuButtonHit )
4410 ImplDrawMenubutton( this, TRUE );
4415 if ( meLastStyle != eStyle )
4417 meLastStyle = eStyle;
4418 Pointer aPtr( eStyle );
4419 SetPointer( aPtr );
4422 DockingWindow::MouseMove( rMEvt );
4425 // -----------------------------------------------------------------------
4427 void ToolBox::MouseButtonDown( const MouseEvent& rMEvt )
4429 // Nur bei linker Maustaste ToolBox ausloesen und wenn wir uns nicht
4430 // noch in der normalen Bearbeitung befinden
4431 if ( rMEvt.IsLeft() && !mbDrag && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4433 // Activate schon hier rufen, da gegebenenfalls noch Items
4434 // ausgetauscht werden
4435 Activate();
4437 // ToolBox hier updaten, damit der Anwender weiss, was Sache ist
4438 if ( mbFormat )
4440 ImplFormat();
4441 Update();
4444 Point aMousePos = rMEvt.GetPosPixel();
4445 USHORT i = 0;
4446 USHORT nNewPos = TOOLBOX_ITEM_NOTFOUND;
4448 // Item suchen, das geklickt wurde
4449 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4450 while ( it != mpData->m_aItems.end() )
4452 // Ist es dieses Item
4453 if ( it->maRect.IsInside( aMousePos ) )
4455 // Ist es ein Separator oder ist das Item disabled,
4456 // dann mache nichts
4457 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
4458 (!it->mbShowWindow || mbCustomizeMode) )
4459 nNewPos = i;
4461 break;
4464 i++;
4465 ++it;
4468 // Item gefunden
4469 if ( nNewPos != TOOLBOX_ITEM_NOTFOUND )
4471 if ( mbCustomize )
4473 if ( rMEvt.IsMod2() || mbCustomizeMode )
4475 Deactivate();
4477 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4478 Rectangle aItemRect = GetItemRect( it->mnId );
4479 mnConfigItem = it->mnId;
4481 BOOL bResizeItem;
4482 if ( mbCustomizeMode && it->mbShowWindow &&
4483 (it->maRect.Right()-TB_RESIZE_OFFSET <= aMousePos.X()) )
4484 bResizeItem = TRUE;
4485 else
4486 bResizeItem = FALSE;
4487 pMgr->StartDragging( this, aMousePos, aItemRect, 0, bResizeItem );
4488 return;
4492 if ( !it->mbEnabled )
4494 Deactivate();
4495 return;
4499 // Aktuelle Daten setzen
4500 USHORT nTrackFlags = 0;
4501 mnCurPos = i;
4502 mnCurItemId = it->mnId;
4503 mnDownItemId = mnCurItemId;
4504 mnMouseClicks = rMEvt.GetClicks();
4505 mnMouseModifier = rMEvt.GetModifier();
4506 if ( it->mnBits & TIB_REPEAT )
4507 nTrackFlags |= STARTTRACK_BUTTONREPEAT;
4510 if ( mbSelection )
4512 ImplDrawItem( mnCurPos, TRUE );
4513 Highlight();
4515 else
4517 // Hier schon bDrag setzen, da in EndSelection ausgewertet wird
4518 mbDrag = TRUE;
4520 // Bei Doppelklick nur den Handler rufen, aber bevor der
4521 // Button gehiltet wird, da evt. in diesem Handler der
4522 // Drag-Vorgang abgebrochen wird
4523 if ( rMEvt.GetClicks() == 2 )
4524 DoubleClick();
4527 if ( mbDrag )
4529 ImplDrawItem( mnCurPos, TRUE );
4530 Highlight();
4533 // was dropdown arrow pressed
4534 if( (it->mnBits & TIB_DROPDOWN) )
4536 if( ( (it->mnBits & TIB_DROPDOWNONLY) == TIB_DROPDOWNONLY) || it->GetDropDownRect( mbHorz ).IsInside( aMousePos ))
4538 // dropdownonly always triggers the dropdown handler, over the whole button area
4540 // the drop down arrow should not trigger the item action
4541 mpData->mbDropDownByKeyboard = FALSE;
4542 GetDropdownClickHdl().Call( this );
4544 // do not reset data if the dropdown handler opened a floating window
4545 // see ImplFloatControl()
4546 if( mpFloatWin == NULL )
4548 // no floater was opened
4549 Deactivate();
4550 ImplDrawItem( mnCurPos, FALSE );
4552 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
4553 mnCurItemId = 0;
4554 mnDownItemId = 0;
4555 mnMouseClicks = 0;
4556 mnMouseModifier = 0;
4557 mnHighItemId = 0;
4559 return;
4561 else // activate long click timer
4562 mpData->maDropdownTimer.Start();
4566 // Click-Handler aufrufen
4567 if ( rMEvt.GetClicks() != 2 )
4568 Click();
4570 // Bei Repeat auch den Select-Handler rufen
4571 if ( nTrackFlags & STARTTRACK_BUTTONREPEAT )
4572 Select();
4574 // Wenn die Aktion nicht im Click-Handler abgebrochen wurde
4575 if ( mbDrag )
4576 StartTracking( nTrackFlags );
4579 // Wenn Maus ueber einem Item gedrueckt wurde, koennen wir
4580 // die Bearbeitung abbrechen
4581 return;
4584 Deactivate();
4586 // menu button hit ?
4587 if( mpData->maMenubuttonItem.maRect.IsInside( aMousePos ) )
4589 ExecuteCustomMenu();
4590 return;
4594 // Gegebenenfalls noch Scroll- und Next-Buttons ueberpruefen
4595 if ( maUpperRect.IsInside( aMousePos ) )
4597 if ( mnCurLine > 1 )
4599 StartTracking();
4600 mbUpper = TRUE;
4601 mbIn = TRUE;
4602 ImplDrawSpin( TRUE, FALSE );
4604 return;
4606 if ( maLowerRect.IsInside( aMousePos ) )
4608 if ( mnCurLine+mnVisLines-1 < mnCurLines )
4610 StartTracking();
4611 mbLower = TRUE;
4612 mbIn = TRUE;
4613 ImplDrawSpin( FALSE, TRUE );
4615 return;
4617 if ( maNextToolRect.IsInside( aMousePos ) )
4619 StartTracking();
4620 mbNextTool = TRUE;
4621 mbIn = TRUE;
4622 ImplDrawNext( TRUE );
4623 return;
4626 // Linesizing testen
4627 if ( (mnWinStyle & TB_WBLINESIZING) == TB_WBLINESIZING )
4629 USHORT nLineMode = ImplTestLineSize( this, aMousePos );
4630 if ( nLineMode )
4632 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4634 // Handler rufen, damit die Dock-Rectangles gesetzt werden
4635 // koenen
4636 StartDocking();
4638 Point aPos = GetParent()->OutputToScreenPixel( GetPosPixel() );
4639 Size aSize = GetSizePixel();
4640 aPos = ScreenToOutputPixel( aPos );
4642 // Dragging starten
4643 pMgr->StartDragging( this, aMousePos, Rectangle( aPos, aSize ),
4644 nLineMode, FALSE );
4645 return;
4649 // Kein Item, dann nur Click oder DoubleClick
4650 if ( rMEvt.GetClicks() == 2 )
4651 DoubleClick();
4652 else
4653 Click();
4656 if ( !mbDrag && !mbSelection && (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
4657 DockingWindow::MouseButtonDown( rMEvt );
4660 // -----------------------------------------------------------------------
4662 void ToolBox::MouseButtonUp( const MouseEvent& rMEvt )
4664 if ( ImplHandleMouseButtonUp( rMEvt ) )
4665 return;
4667 if ( mbDragging && (rMEvt.IsLeft() || mbCommandDrag) )
4669 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
4670 pMgr->EndDragging();
4671 return;
4673 mbCommandDrag = FALSE;
4675 DockingWindow::MouseButtonUp( rMEvt );
4678 // -----------------------------------------------------------------------
4680 void ToolBox::Tracking( const TrackingEvent& rTEvt )
4682 ImplDelData aDelData;
4683 ImplAddDel( &aDelData );
4685 if ( rTEvt.IsTrackingEnded() )
4686 ImplHandleMouseButtonUp( rTEvt.GetMouseEvent(), rTEvt.IsTrackingCanceled() );
4687 else
4688 ImplHandleMouseMove( rTEvt.GetMouseEvent(), rTEvt.IsTrackingRepeat() );
4690 if ( aDelData.IsDelete() )
4691 // toolbox was deleted
4692 return;
4693 ImplRemoveDel( &aDelData );
4694 DockingWindow::Tracking( rTEvt );
4697 // -----------------------------------------------------------------------
4699 void ToolBox::Paint( const Rectangle& rPaintRect )
4701 if( mpData->mbIsPaintLocked )
4702 return;
4703 if ( rPaintRect == Rectangle( 0, 0, mnDX-1, mnDY-1 ) )
4704 mbFullPaint = TRUE;
4705 ImplFormat();
4706 mbFullPaint = FALSE;
4709 ImplDrawBackground( this, rPaintRect );
4711 if ( (mnWinStyle & WB_BORDER) && !ImplIsFloatingMode() )
4712 ImplDrawBorder( this );
4714 if( !ImplIsFloatingMode() )
4715 ImplDrawGrip( this );
4717 ImplDrawMenubutton( this, mpData->mbMenubuttonSelected );
4719 // SpinButtons zeichnen
4720 if ( mnWinStyle & WB_SCROLL )
4722 if ( mnCurLines > mnLines )
4723 ImplDrawSpin( FALSE, FALSE );
4726 // NextButton zeichnen
4727 ImplDrawNext( FALSE );
4729 // Buttons zeichnen
4730 USHORT nHighPos;
4731 if ( mnHighItemId )
4732 nHighPos = GetItemPos( mnHighItemId );
4733 else
4734 nHighPos = TOOLBOX_ITEM_NOTFOUND;
4736 USHORT nCount = (USHORT)mpData->m_aItems.size();
4737 for( USHORT i = 0; i < nCount; i++ )
4739 ImplToolItem* pItem = &mpData->m_aItems[i];
4741 // Nur malen, wenn Rechteck im PaintRectangle liegt
4742 if ( !pItem->maRect.IsEmpty() && rPaintRect.IsOver( pItem->maRect ) )
4744 BOOL bHighlight = FALSE;
4745 if ( i == mnCurPos )
4746 bHighlight = 1;
4747 else if ( i == nHighPos )
4748 bHighlight = 2;
4749 ImplDrawItem( i, bHighlight );
4752 ImplShowFocus();
4755 // -----------------------------------------------------------------------
4757 void ToolBox::Move()
4759 DockingWindow::Move();
4762 // -----------------------------------------------------------------------
4764 void ToolBox::Resize()
4766 Size aSize = GetOutputSizePixel();
4767 // #i31422# some WindowManagers send (0,0) sizes when
4768 // switching virtual desktops - ignore this and avoid reformatting
4769 if( !aSize.Width() && !aSize.Height() )
4770 return;
4772 long nOldDX = mnDX;
4773 long nOldDY = mnDY;
4774 mnDX = aSize.Width();
4775 mnDY = aSize.Height();
4777 mnLastResizeDY = 0;
4779 // invalidate everything to have gradient backgrounds properly drawn
4780 Invalidate();
4782 // Evt. neu formatieren oder neu painten
4783 if ( mbScroll )
4785 if ( !mbFormat )
4787 mbFormat = TRUE;
4788 if( IsReallyVisible() )
4789 ImplFormat( TRUE );
4793 // Border muss neu ausgegeben werden
4794 if ( mnWinStyle & WB_BORDER )
4796 // Da wir sonst beim Paint denken, das alles neu gepaintet wird
4797 if ( mbFormat && IsReallyVisible() )
4798 Invalidate();
4799 else
4801 if ( mnRightBorder )
4803 if ( nOldDX > mnDX )
4804 Invalidate( Rectangle( mnDX-mnRightBorder-1, 0, mnDX, mnDY ) );
4805 else
4806 Invalidate( Rectangle( nOldDX-mnRightBorder-1, 0, nOldDX, nOldDY ) );
4809 if ( mnBottomBorder )
4811 if ( nOldDY > mnDY )
4812 Invalidate( Rectangle( 0, mnDY-mnBottomBorder-1, mnDX, mnDY ) );
4813 else
4814 Invalidate( Rectangle( 0, nOldDY-mnBottomBorder-1, nOldDX, nOldDY ) );
4820 // -----------------------------------------------------------------------
4821 const XubString& ToolBox::ImplGetHelpText( USHORT nItemId ) const
4823 ImplToolItem* pItem = ImplGetItem( nItemId );
4825 if ( pItem )
4827 if ( !pItem->maHelpText.Len() && ( pItem->mnHelpId || pItem->maCommandStr.Len() ))
4829 Help* pHelp = Application::GetHelp();
4830 if ( pHelp )
4832 if ( pItem->maCommandStr.Len() )
4833 pItem->maHelpText = pHelp->GetHelpText( pItem->maCommandStr, this );
4834 if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
4835 pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId, this );
4839 return pItem->maHelpText;
4841 else
4842 return ImplGetSVEmptyStr();
4845 // -----------------------------------------------------------------------
4847 void ToolBox::RequestHelp( const HelpEvent& rHEvt )
4849 USHORT nItemId;
4850 Point aHelpPos;
4852 if( !rHEvt.KeyboardActivated() )
4854 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
4855 aHelpPos = rHEvt.GetMousePosPixel();
4857 else
4859 if( !mnHighItemId )
4860 return;
4861 else
4862 nItemId = mnHighItemId;
4863 Rectangle aRect( GetItemRect( nItemId ) );
4864 if( aRect.IsEmpty() )
4865 return;
4866 else
4867 aHelpPos = OutputToScreenPixel( aRect.Center() );
4870 if ( nItemId )
4872 if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4874 // Rechteck ermitteln
4875 Rectangle aTempRect = GetItemRect( nItemId );
4876 Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4877 aTempRect.Left() = aPt.X();
4878 aTempRect.Top() = aPt.Y();
4879 aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4880 aTempRect.Right() = aPt.X();
4881 aTempRect.Bottom() = aPt.Y();
4883 // Text ermitteln und anzeigen
4884 XubString aStr = GetQuickHelpText( nItemId );
4885 const XubString& rHelpStr = GetHelpText( nItemId );
4886 if ( !aStr.Len() )
4887 aStr = MnemonicGenerator::EraseAllMnemonicChars( GetItemText( nItemId ) );
4888 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4890 if ( rHelpStr.Len() )
4891 aStr = rHelpStr;
4892 Help::ShowBalloon( this, aHelpPos, aTempRect, aStr );
4894 else
4895 Help::ShowQuickHelp( this, aTempRect, aStr, rHelpStr, QUICKHELP_CTRLTEXT );
4896 return;
4898 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
4900 String aCommand = GetItemCommand( nItemId );
4901 ULONG nHelpId = GetHelpId( nItemId );
4903 if ( aCommand.Len() || nHelpId )
4905 // Wenn eine Hilfe existiert, dann ausloesen
4906 Help* pHelp = Application::GetHelp();
4907 if ( pHelp )
4909 if ( aCommand.Len() )
4910 pHelp->Start( aCommand, this );
4911 else if ( nHelpId )
4912 pHelp->Start( nHelpId, this );
4914 return;
4918 else if ( maNextToolRect.IsInside( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ) )
4920 if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
4922 // Rechteck ermitteln
4923 Rectangle aTempRect = maNextToolRect;
4924 Point aPt = OutputToScreenPixel( aTempRect.TopLeft() );
4925 aTempRect.Left() = aPt.X();
4926 aTempRect.Top() = aPt.Y();
4927 aPt = OutputToScreenPixel( aTempRect.BottomRight() );
4928 aTempRect.Right() = aPt.X();
4929 aTempRect.Bottom() = aPt.Y();
4931 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
4932 Help::ShowBalloon( this, aTempRect.Center(), aTempRect, maNextToolBoxStr );
4933 else
4934 Help::ShowQuickHelp( this, aTempRect, maNextToolBoxStr );
4935 return;
4939 DockingWindow::RequestHelp( rHEvt );
4942 // -----------------------------------------------------------------------
4944 long ToolBox::Notify( NotifyEvent& rNEvt )
4946 if ( rNEvt.GetType() == EVENT_KEYINPUT )
4948 KeyEvent aKEvt = *rNEvt.GetKeyEvent();
4949 KeyCode aKeyCode = aKEvt.GetKeyCode();
4950 USHORT nKeyCode = aKeyCode.GetCode();
4951 switch( nKeyCode )
4953 case KEY_TAB:
4955 // internal TAB cycling only if parent is not a dialog or if we are the ony child
4956 // otherwise the dialog control will take over
4957 BOOL bNoTabCycling = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL &&
4958 ImplGetParent()->GetChildCount() != 1 );
4960 if( bNoTabCycling && ! (GetStyle() & WB_FORCETABCYCLE) )
4961 return DockingWindow::Notify( rNEvt );
4962 else if( ImplChangeHighlightUpDn( aKeyCode.IsShift() ? TRUE : FALSE , bNoTabCycling ) )
4963 return FALSE;
4964 else
4965 return DockingWindow::Notify( rNEvt );
4967 default:
4968 break;
4971 else if( rNEvt.GetType() == EVENT_GETFOCUS )
4973 if( rNEvt.GetWindow() == this )
4975 // the toolbar itself got the focus
4976 if( mnLastFocusItemId != 0 )
4978 // restore last item
4979 ImplChangeHighlight( ImplGetItem( mnLastFocusItemId ) );
4980 mnLastFocusItemId = 0;
4982 else if( (GetGetFocusFlags() & (GETFOCUS_BACKWARD|GETFOCUS_TAB) ) == (GETFOCUS_BACKWARD|GETFOCUS_TAB))
4983 // Shift-TAB was pressed in the parent
4984 ImplChangeHighlightUpDn( FALSE );
4985 else
4986 ImplChangeHighlightUpDn( TRUE );
4988 mnLastFocusItemId = 0;
4990 return true;
4992 else
4994 // a child window got the focus so update current item to
4995 // allow for proper lose focus handling in keyboard navigation
4996 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
4997 while( it != mpData->m_aItems.end() )
4999 if ( it->mbVisible )
5001 if ( it->mpWindow && it->mpWindow->ImplIsWindowOrChild( rNEvt.GetWindow() ) )
5003 mnHighItemId = it->mnId;
5004 break;
5008 ++it;
5010 return DockingWindow::Notify( rNEvt );
5013 else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
5015 // deselect
5016 ImplHideFocus();
5017 mnHighItemId = 0;
5018 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
5021 return DockingWindow::Notify( rNEvt );
5024 // -----------------------------------------------------------------------
5026 void ToolBox::Command( const CommandEvent& rCEvt )
5028 // StartDrag auf MouseButton/Left/Alt abbilden
5029 if ( (rCEvt.GetCommand() == COMMAND_STARTDRAG) && rCEvt.IsMouseEvent() &&
5030 mbCustomize && !mbDragging && !mbDrag && !mbSelection &&
5031 (mnCurPos == TOOLBOX_ITEM_NOTFOUND) )
5033 // Wir erlauben nur das Draggen von Items. Deshalb muessen wir
5034 // testen, ob auch ein Item angeklickt wurde, ansonsten wuerden
5035 // wir evt. das Fenster verschieben, was nicht gewollt waere.
5036 // Wir machen dieses jedoch nur im Customize-Mode, da ansonsten
5037 // Items zuhaeufig ausversehen verschoben werden.
5038 if ( mbCustomizeMode )
5040 Point aMousePos = rCEvt.GetMousePosPixel();
5041 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
5042 while ( it != mpData->m_aItems.end() )
5044 // Ist es dieses Item
5045 if ( it->maRect.IsInside( aMousePos ) )
5047 // Ist es ein Separator oder ist das Item disabled,
5048 // dann mache nichts
5049 if ( (it->meType == TOOLBOXITEM_BUTTON) &&
5050 !it->mbShowWindow )
5051 mbCommandDrag = TRUE;
5052 break;
5055 ++it;
5058 if ( mbCommandDrag )
5060 MouseEvent aMEvt( aMousePos, 1, MOUSE_SIMPLECLICK,
5061 MOUSE_LEFT, KEY_MOD2 );
5062 ToolBox::MouseButtonDown( aMEvt );
5063 return;
5067 else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
5069 if ( (mnCurLine > 1) || (mnCurLine+mnVisLines-1 < mnCurLines) )
5071 const CommandWheelData* pData = rCEvt.GetWheelData();
5072 if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
5074 if ( (mnCurLine > 1) && (pData->GetDelta() > 0) )
5075 ShowLine( FALSE );
5076 else if ( (mnCurLine+mnVisLines-1 < mnCurLines) && (pData->GetDelta() < 0) )
5077 ShowLine( TRUE );
5078 ImplDrawSpin( FALSE, FALSE );
5079 return;
5084 DockingWindow::Command( rCEvt );
5087 // -----------------------------------------------------------------------
5089 void ToolBox::StateChanged( StateChangedType nType )
5091 DockingWindow::StateChanged( nType );
5093 if ( nType == STATE_CHANGE_INITSHOW )
5094 ImplFormat();
5095 else if ( nType == STATE_CHANGE_ENABLE )
5096 ImplUpdateItem();
5097 else if ( nType == STATE_CHANGE_UPDATEMODE )
5099 if ( IsUpdateMode() )
5100 Invalidate();
5102 else if ( (nType == STATE_CHANGE_ZOOM) ||
5103 (nType == STATE_CHANGE_CONTROLFONT) )
5105 mbCalc = TRUE;
5106 mbFormat = TRUE;
5107 ImplInitSettings( TRUE, FALSE, FALSE );
5108 Invalidate();
5110 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
5112 ImplInitSettings( FALSE, TRUE, FALSE );
5113 Invalidate();
5115 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
5117 ImplInitSettings( FALSE, FALSE, TRUE ); // font, foreground, background
5118 Invalidate();
5122 // -----------------------------------------------------------------------
5124 void ToolBox::DataChanged( const DataChangedEvent& rDCEvt )
5126 DockingWindow::DataChanged( rDCEvt );
5128 if ( (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
5129 (rDCEvt.GetType() == DATACHANGED_FONTS) ||
5130 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
5131 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
5132 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
5134 mbCalc = TRUE;
5135 mbFormat = TRUE;
5136 ImplInitSettings( TRUE, TRUE, TRUE );
5137 Invalidate();
5141 // -----------------------------------------------------------------------
5143 BOOL ToolBox::PrepareToggleFloatingMode()
5145 return DockingWindow::PrepareToggleFloatingMode();
5148 // -----------------------------------------------------------------------
5150 void ToolBox::ToggleFloatingMode()
5152 DockingWindow::ToggleFloatingMode();
5154 BOOL mbOldHorz = mbHorz;
5156 if ( ImplIsFloatingMode() )
5158 mbHorz = TRUE;
5159 meAlign = WINDOWALIGN_TOP;
5160 mbScroll = TRUE;
5162 if( mbOldHorz != mbHorz )
5163 mbCalc = TRUE; // orientation was changed !
5165 ImplSetMinMaxFloatSize( this );
5166 SetOutputSizePixel( ImplCalcFloatSize( this, mnFloatLines ) );
5168 else
5170 mbScroll = (mnWinStyle & WB_SCROLL) ? TRUE : FALSE;
5171 if ( (meAlign == WINDOWALIGN_TOP) || (meAlign == WINDOWALIGN_BOTTOM) )
5172 mbHorz = TRUE;
5173 else
5174 mbHorz = FALSE;
5176 // set focus back to document
5177 ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
5180 if( mbOldHorz != mbHorz )
5182 // if orientation changes, the toolbox has to be initialized again
5183 // to update the direction of the gradient
5184 mbCalc = TRUE;
5185 ImplInitSettings( TRUE, TRUE, TRUE );
5188 mbFormat = TRUE;
5189 ImplFormat();
5192 // -----------------------------------------------------------------------
5194 void ToolBox::StartDocking()
5196 meDockAlign = meAlign;
5197 mnDockLines = mnLines;
5198 mbLastFloatMode = ImplIsFloatingMode();
5199 DockingWindow::StartDocking();
5202 // -----------------------------------------------------------------------
5204 BOOL ToolBox::Docking( const Point& rPos, Rectangle& rRect )
5206 // Wenn Dragging, dann nicht machen, da vorher schon berechnet
5207 if ( mbDragging )
5208 return FALSE;
5210 BOOL bFloatMode = FALSE;
5212 DockingWindow::Docking( rPos, rRect );
5214 // Befindet sich die Maus ausserhalb des Bereichs befindet, kann es nur ein
5215 // FloatWindow werden
5216 Rectangle aDockingRect( rRect );
5217 if ( !ImplIsFloatingMode() )
5219 // don't use tracking rectangle for alignment check, because it will be too large
5220 // to get a floating mode as result - switch to floating size
5221 // so the calculation only depends on the position of the rectangle, not the current
5222 // docking state of the window
5223 USHORT nTemp = 0;
5224 aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
5226 // in this mode docking is never done by keyboard, so it's OK to use the mouse position
5227 aDockingRect.SetPos( ImplGetFrameWindow()->GetPointerPosPixel() );
5230 Rectangle aIntersection = maOutDockRect.GetIntersection( aDockingRect );
5231 if ( !aIntersection.IsEmpty() && !IsDockingPrevented() )
5233 Rectangle aInRect = maInDockRect;
5234 Size aDockSize;
5235 aDockSize.Width() = ImplCalcSize( this, mnLines, TB_CALCMODE_VERT ).Width();
5236 aDockSize.Height() = ImplCalcSize( this, mnLines, TB_CALCMODE_HORZ ).Height();
5237 aInRect.Left() += aDockSize.Width()/2;
5238 aInRect.Top() += aDockSize.Height()/2;
5239 aInRect.Right() -= aDockSize.Width()/2;
5240 aInRect.Bottom() -= aDockSize.Height()/2;
5242 // Wenn Fenster zu klein, wird das gesammte InDock-Rect genommen
5243 if ( aInRect.Left() >= aInRect.Right() )
5245 aInRect.Left() = maInDockRect.Left();
5246 aInRect.Right() = maInDockRect.Right();
5248 if ( aInRect.Top() >= aInRect.Bottom() )
5250 aInRect.Top() = maInDockRect.Top();
5251 aInRect.Bottom() = maInDockRect.Bottom();
5254 // Wenn Maus nicht im Dock-Bereich, dann kann es nur zum
5255 // FloatWindow werden
5256 Rectangle aIntersect = aInRect.GetIntersection( aDockingRect );
5257 if ( aIntersect == aDockingRect )
5258 bFloatMode = TRUE;
5259 else
5261 // docking rectangle is in the "sensible area"
5262 Point aPos = aDockingRect.TopLeft();
5263 Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() );
5264 Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() );
5265 Size aInSize = aInRect.GetSize();
5267 if ( aInPosTL.X() <= 0 )
5268 meDockAlign = WINDOWALIGN_LEFT;
5269 else if ( aInPosTL.Y() <= 0)
5270 meDockAlign = WINDOWALIGN_TOP;
5271 else if ( aInPosBR.X() >= aInSize.Width() )
5272 meDockAlign = WINDOWALIGN_RIGHT;
5273 else if ( aInPosBR.Y() >= aInSize.Height() )
5274 meDockAlign = WINDOWALIGN_BOTTOM;
5276 // Wenn sich Dock-Align geaendert hat, muessen wir die
5277 // neue Dock-Groesse setzen
5278 if ( (meDockAlign == WINDOWALIGN_TOP) || (meDockAlign == WINDOWALIGN_BOTTOM) )
5279 aDockSize.Width() = maInDockRect.GetWidth();
5280 else
5281 aDockSize.Height() = maInDockRect.GetHeight();
5283 aDockingRect.SetSize( aDockSize );
5285 Point aPosTL( maInDockRect.TopLeft() );
5286 switch ( meDockAlign )
5288 case WINDOWALIGN_TOP :
5289 aDockingRect.SetPos( aPosTL );
5290 break;
5291 case WINDOWALIGN_LEFT :
5292 aDockingRect.SetPos( aPosTL );
5293 break;
5294 case WINDOWALIGN_BOTTOM :
5296 Point aPosBL( maInDockRect.BottomLeft() );
5297 aPosBL.Y() -= aDockingRect.GetHeight();
5298 aDockingRect.SetPos( aPosBL );
5299 break;
5301 case WINDOWALIGN_RIGHT :
5303 Point aPosTR( maInDockRect.TopRight() );
5304 aPosTR.X() -= aDockingRect.GetWidth();
5305 aDockingRect.SetPos( aPosTR );
5306 break;
5311 else
5312 bFloatMode = TRUE;
5314 if ( bFloatMode )
5316 meDockAlign = meAlign;
5317 if ( !mbLastFloatMode )
5319 USHORT nTemp = 0;
5320 aDockingRect.SetSize( ImplCalcFloatSize( this, nTemp ) );
5324 rRect = aDockingRect;
5325 mbLastFloatMode = bFloatMode;
5327 return bFloatMode;
5330 // -----------------------------------------------------------------------
5332 void ToolBox::EndDocking( const Rectangle& rRect, BOOL bFloatMode )
5334 if ( !IsDockingCanceled() )
5336 if ( mnLines != mnDockLines )
5337 SetLineCount( mnDockLines );
5338 if ( meAlign != meDockAlign )
5339 SetAlign( meDockAlign );
5341 if ( bFloatMode || (bFloatMode != ImplIsFloatingMode()) )
5342 DockingWindow::EndDocking( rRect, bFloatMode );
5345 // -----------------------------------------------------------------------
5347 void ToolBox::Resizing( Size& rSize )
5349 USHORT nCalcLines;
5350 USHORT nTemp;
5352 // Alle Floatinggroessen berechnen
5353 ImplCalcFloatSizes( this );
5355 if ( !mnLastResizeDY )
5356 mnLastResizeDY = mnDY;
5358 // Ist vertikales Resizing angesagt
5359 if ( (mnLastResizeDY != rSize.Height()) && (mnDY != rSize.Height()) )
5361 nCalcLines = ImplCalcLines( this, rSize.Height() );
5362 if ( nCalcLines < 1 )
5363 nCalcLines = 1;
5364 rSize = ImplCalcFloatSize( this, nCalcLines );
5366 else
5368 nCalcLines = 1;
5369 nTemp = nCalcLines;
5370 Size aTempSize = ImplCalcFloatSize( this, nTemp );
5371 while ( (aTempSize.Width() > rSize.Width()) &&
5372 (nCalcLines <= mpFloatSizeAry->mpSize[0].mnLines) )
5374 nCalcLines++;
5375 nTemp = nCalcLines;
5376 aTempSize = ImplCalcFloatSize( this, nTemp );
5378 rSize = aTempSize;
5381 mnLastResizeDY = rSize.Height();
5384 // -----------------------------------------------------------------------
5386 Size ToolBox::CalcWindowSizePixel( USHORT nCalcLines ) const
5388 return ImplCalcSize( this, nCalcLines );
5391 Size ToolBox::CalcWindowSizePixel( USHORT nCalcLines, WindowAlign eAlign ) const
5393 return ImplCalcSize( this, nCalcLines,
5394 (eAlign == WINDOWALIGN_TOP || eAlign == WINDOWALIGN_BOTTOM) ? TB_CALCMODE_HORZ : TB_CALCMODE_VERT );
5397 USHORT ToolBox::ImplCountLineBreaks( const ToolBox *pThis )
5399 USHORT nLines = 0;
5401 std::vector< ImplToolItem >::const_iterator it = ((ToolBox*)pThis)->mpData->m_aItems.begin();
5402 while ( it != ((ToolBox*)pThis)->mpData->m_aItems.end() )
5404 if( it->meType == TOOLBOXITEM_BREAK )
5405 nLines++;
5406 it++;
5408 return nLines;
5411 Size ToolBox::CalcPopupWindowSizePixel() const
5413 // count number of breaks and calc corresponding floating window size
5414 USHORT nLines = ImplCountLineBreaks( this );
5416 if( nLines )
5417 nLines++; // add the first line
5418 else
5420 // no breaks found: use quadratic layout
5421 nLines = (USHORT) ceil( sqrt( (double) GetItemCount() ) );
5424 BOOL bPopup = mpData->mbAssumePopupMode;
5425 ToolBox *pThis = (ToolBox*) this;
5426 pThis->mpData->mbAssumePopupMode = TRUE;
5428 Size aSize = CalcFloatingWindowSizePixel( nLines );
5430 pThis->mpData->mbAssumePopupMode = bPopup;
5431 return aSize;
5434 Size ToolBox::CalcFloatingWindowSizePixel() const
5436 USHORT nLines = ImplCountLineBreaks( this );
5437 nLines++; // add the first line
5438 return CalcFloatingWindowSizePixel( nLines );
5441 Size ToolBox::CalcFloatingWindowSizePixel( USHORT nCalcLines ) const
5443 BOOL bFloat = mpData->mbAssumeFloating;
5444 BOOL bDocking = mpData->mbAssumeDocked;
5446 // simulate floating mode and force reformat before calculating
5447 ToolBox *pThis = (ToolBox*) this;
5448 pThis->mpData->mbAssumeFloating = TRUE;
5449 pThis->mpData->mbAssumeDocked = FALSE;
5451 Size aSize = ImplCalcFloatSize( (ToolBox*) this, nCalcLines );
5453 pThis->mbFormat = TRUE;
5454 pThis->mpData->mbAssumeFloating = bFloat;
5455 pThis->mpData->mbAssumeDocked = bDocking;
5457 return aSize;
5460 // -----------------------------------------------------------------------
5462 Size ToolBox::CalcMinimumWindowSizePixel() const
5464 if( ImplIsFloatingMode() )
5465 return ImplCalcSize( this, mnFloatLines );
5466 else
5468 // create dummy toolbox for measurements
5469 ToolBox *pToolBox = new ToolBox( GetParent(), GetStyle() );
5471 // copy until first useful item
5472 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5473 while( it != mpData->m_aItems.end() )
5475 pToolBox->CopyItem( *this, it->mnId );
5476 if( (it->meType != TOOLBOXITEM_BUTTON) ||
5477 !it->mbVisible || ImplIsFixedControl( &(*it) ) )
5478 it++;
5479 else
5480 break;
5483 // add to docking manager if required to obtain a drag area
5484 // (which is accounted for in calcwindowsizepixel)
5485 if( ImplGetDockingManager()->GetDockingWindowWrapper( this ) )
5486 ImplGetDockingManager()->AddWindow( pToolBox );
5488 // account for menu
5489 if( IsMenuEnabled() )
5490 pToolBox->SetMenuType( GetMenuType() );
5492 pToolBox->SetAlign( GetAlign() );
5493 Size aSize = pToolBox->CalcWindowSizePixel( 1 );
5495 ImplGetDockingManager()->RemoveWindow( pToolBox );
5496 pToolBox->Clear();
5497 delete pToolBox;
5499 return aSize;
5503 // -----------------------------------------------------------------------
5505 void ToolBox::EnableCustomize( BOOL bEnable )
5507 if ( bEnable != mbCustomize )
5509 mbCustomize = bEnable;
5511 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5512 if ( bEnable )
5513 pMgr->Insert( this );
5514 else
5515 pMgr->Remove( this );
5519 // -----------------------------------------------------------------------
5521 void ToolBox::StartCustomize( const Rectangle& rRect, void* pData )
5523 DBG_ASSERT( mbCustomize,
5524 "ToolBox::StartCustomize(): ToolBox must be customized" );
5526 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5527 Point aMousePos = GetPointerPosPixel();
5528 Point aPos = ScreenToOutputPixel( rRect.TopLeft() );
5529 Rectangle aRect( aPos.X(), aPos.Y(),
5530 aPos.X()+rRect.GetWidth()+SMALLBUTTON_HSIZE,
5531 aPos.Y()+rRect.GetHeight()+SMALLBUTTON_VSIZE );
5532 aMousePos = ScreenToOutputPixel( aPos );
5533 Pointer aPtr;
5534 SetPointer( aPtr );
5535 pMgr->StartDragging( this, aMousePos, aRect, 0, FALSE, pData );
5538 // -----------------------------------------------------------------------
5540 void ToolBox::StartCustomizeMode()
5542 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5543 pMgr->StartCustomizeMode();
5546 // -----------------------------------------------------------------------
5548 void ToolBox::EndCustomizeMode()
5550 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5551 pMgr->EndCustomizeMode();
5554 // -----------------------------------------------------------------------
5556 BOOL ToolBox::IsCustomizeMode()
5558 ImplTBDragMgr* pMgr = ImplGetTBDragMgr();
5559 return pMgr->IsCustomizeMode();
5562 // -----------------------------------------------------------------------
5564 void ToolBox::GetFocus()
5566 DockingWindow::GetFocus();
5569 // -----------------------------------------------------------------------
5571 void ToolBox::LoseFocus()
5573 ImplChangeHighlight( NULL, TRUE );
5575 DockingWindow::LoseFocus();
5578 // -----------------------------------------------------------------------
5580 // performs the action associated with an item, ie simulates clicking the item
5581 void ToolBox::TriggerItem( USHORT nItemId, BOOL bShift, BOOL bCtrl )
5583 mnHighItemId = nItemId;
5584 USHORT nModifier = 0;
5585 if( bShift )
5586 nModifier |= KEY_SHIFT;
5587 if( bCtrl )
5588 nModifier |= KEY_MOD1;
5589 KeyCode aKeyCode( 0, nModifier );
5590 ImplActivateItem( aKeyCode );
5593 // -----------------------------------------------------------------------
5595 // calls the button's action handler
5596 // returns TRUE if action was called
5597 BOOL ToolBox::ImplActivateItem( KeyCode aKeyCode )
5599 BOOL bRet = TRUE;
5600 if( mnHighItemId )
5602 ImplToolItem *pToolItem = ImplGetItem( mnHighItemId );
5604 // #107712#, activate can also be called for disabled entries
5605 if( pToolItem && !pToolItem->mbEnabled )
5606 return TRUE;
5608 if( pToolItem && pToolItem->mpWindow && HasFocus() )
5610 ImplHideFocus();
5611 mbChangingHighlight = TRUE; // avoid focus change due to loose focus
5612 pToolItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5613 mbChangingHighlight = FALSE;
5615 else
5617 mnDownItemId = mnCurItemId = mnHighItemId;
5618 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
5619 if ( pItem->mnBits & TIB_AUTOCHECK )
5621 if ( pItem->mnBits & TIB_RADIOCHECK )
5623 if ( pItem->meState != STATE_CHECK )
5624 SetItemState( pItem->mnId, STATE_CHECK );
5626 else
5628 if ( pItem->meState != STATE_CHECK )
5629 pItem->meState = STATE_CHECK;
5630 else
5631 pItem->meState = STATE_NOCHECK;
5634 mnMouseModifier = aKeyCode.GetModifier();
5635 mbIsKeyEvent = TRUE;
5636 Activate();
5637 Click();
5639 // #107776# we might be destroyed in the selecthandler
5640 ImplDelData aDelData;
5641 ImplAddDel( &aDelData );
5642 Select();
5643 if ( aDelData.IsDelete() )
5644 return bRet;
5645 ImplRemoveDel( &aDelData );
5647 Deactivate();
5648 mbIsKeyEvent = FALSE;
5649 mnMouseModifier = 0;
5652 else
5653 bRet = FALSE;
5654 return bRet;
5657 // -----------------------------------------------------------------------
5659 BOOL ImplCloseLastPopup( Window *pParent )
5661 // close last popup toolbox (see also:
5662 // ImplHandleMouseFloatMode(...) in winproc.cxx )
5664 if( ImplGetSVData()->maWinData.mpFirstFloat )
5666 FloatingWindow* pLastLevelFloat = ImplGetSVData()->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
5667 // only close the floater if it is not our direct parent, which would kill ourself
5668 if( pLastLevelFloat && pLastLevelFloat != pParent )
5670 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
5671 return TRUE;
5674 return FALSE;
5677 // opens a drop down toolbox item
5678 // returns TRUE if item was opened
5679 BOOL ToolBox::ImplOpenItem( KeyCode aKeyCode )
5681 USHORT nCode = aKeyCode.GetCode();
5682 BOOL bRet = TRUE;
5684 // arrow keys should work only in the opposite direction of alignment (to not break cursor travelling)
5685 if ( ((nCode == KEY_LEFT || nCode == KEY_RIGHT) && IsHorizontal())
5686 || ((nCode == KEY_UP || nCode == KEY_DOWN) && !IsHorizontal()) )
5687 return FALSE;
5689 if( IsMenuEnabled() && mpData->mbMenubuttonSelected )
5691 if( ImplCloseLastPopup( GetParent() ) )
5692 return bRet;
5694 ImplUpdateCustomMenu();
5695 Application::PostUserEvent( mpData->mnEventId, LINK( this, ToolBox, ImplCallExecuteCustomMenu ) );
5697 else if( mnHighItemId && ImplGetItem( mnHighItemId ) &&
5698 (ImplGetItem( mnHighItemId )->mnBits & TIB_DROPDOWN) )
5700 if( ImplCloseLastPopup( GetParent() ) )
5701 return bRet;
5703 mnDownItemId = mnCurItemId = mnHighItemId;
5704 mnCurPos = GetItemPos( mnCurItemId );
5705 mnLastFocusItemId = mnCurItemId; // save item id for possible later focus restore
5706 mnMouseModifier = aKeyCode.GetModifier();
5707 mbIsShift = TRUE;
5708 mbIsKeyEvent = TRUE;
5709 Activate();
5711 mpData->mbDropDownByKeyboard = TRUE;
5712 GetDropdownClickHdl().Call( this );
5714 mbIsKeyEvent = FALSE;
5715 mbIsShift = FALSE;
5716 mnMouseModifier = 0;
5718 else
5719 bRet = FALSE;
5721 return bRet;
5724 // -----------------------------------------------------------------------
5726 void ToolBox::KeyInput( const KeyEvent& rKEvt )
5728 KeyCode aKeyCode = rKEvt.GetKeyCode();
5729 mnKeyModifier = aKeyCode.GetModifier();
5730 USHORT nCode = aKeyCode.GetCode();
5731 BOOL bParentIsDialog = ( ( ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL );
5732 BOOL bForwardKey = FALSE;
5733 BOOL bGrabFocusToDocument = FALSE;
5735 // #107776# we might be destroyed in the keyhandler
5736 ImplDelData aDelData;
5737 ImplAddDel( &aDelData );
5739 switch ( nCode )
5741 case KEY_UP:
5743 // Ctrl-Cursor activates next toolbox, indicated by a blue arrow pointing to the left/up
5744 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5745 break;
5746 if( !IsHorizontal() )
5747 ImplChangeHighlightUpDn( TRUE );
5748 else
5749 ImplOpenItem( aKeyCode );
5751 break;
5752 case KEY_LEFT:
5754 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5755 break;
5756 if( IsHorizontal() )
5757 ImplChangeHighlightUpDn( TRUE );
5758 else
5759 ImplOpenItem( aKeyCode );
5761 break;
5762 case KEY_DOWN:
5764 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5765 break;
5766 if( !IsHorizontal() )
5767 ImplChangeHighlightUpDn( FALSE );
5768 else
5769 ImplOpenItem( aKeyCode );
5771 break;
5772 case KEY_RIGHT:
5774 if( aKeyCode.GetModifier() ) // allow only pure cursor keys
5775 break;
5776 if( IsHorizontal() )
5777 ImplChangeHighlightUpDn( FALSE );
5778 else
5779 ImplOpenItem( aKeyCode );
5781 break;
5782 case KEY_PAGEUP:
5783 if ( mnCurLine > 1 )
5785 if( mnCurLine > mnVisLines )
5786 mnCurLine = mnCurLine - mnVisLines;
5787 else
5788 mnCurLine = 1;
5789 mbFormat = TRUE;
5790 ImplFormat();
5791 ImplDrawSpin( FALSE, FALSE );
5792 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5794 break;
5795 case KEY_PAGEDOWN:
5796 if ( mnCurLine+mnVisLines-1 < mnCurLines )
5798 if( mnCurLine + 2*mnVisLines-1 < mnCurLines )
5799 mnCurLine = mnCurLine + mnVisLines;
5800 else
5801 mnCurLine = mnCurLines;
5802 mbFormat = TRUE;
5803 ImplFormat();
5804 ImplDrawSpin( FALSE, FALSE );
5805 ImplChangeHighlight( ImplGetFirstValidItem( mnCurLine ) );
5807 break;
5808 case KEY_END:
5810 ImplChangeHighlight( NULL );
5811 ImplChangeHighlightUpDn( FALSE );
5813 break;
5814 case KEY_HOME:
5816 ImplChangeHighlight( NULL );
5817 ImplChangeHighlightUpDn( TRUE );
5819 break;
5820 case KEY_ESCAPE:
5822 if( !ImplIsFloatingMode() && bParentIsDialog )
5823 DockingWindow::KeyInput( rKEvt );
5824 else
5826 // send focus to document pane
5827 Window *pWin = this;
5828 while( pWin )
5830 if( !pWin->GetParent() )
5832 pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
5833 break;
5835 pWin = pWin->GetParent();
5839 break;
5840 case KEY_RETURN:
5842 // #107712#, disabled entries are selectable now
5843 // leave toolbox and move focus to document
5844 if( mnHighItemId )
5846 ImplToolItem *pItem = ImplGetItem( mnHighItemId );
5847 if( !pItem->mbEnabled )
5849 Sound::Beep( SOUND_DISABLE, this );
5850 bGrabFocusToDocument = TRUE;
5853 if( !bGrabFocusToDocument )
5854 bForwardKey = !ImplActivateItem( aKeyCode );
5856 break;
5857 default:
5859 USHORT aKeyGroup = aKeyCode.GetGroup();
5860 ImplToolItem *pItem = NULL;
5861 if( mnHighItemId )
5862 pItem = ImplGetItem( mnHighItemId );
5863 // #i13931# forward alphanum keyinput into embedded control
5864 if( (aKeyGroup == KEYGROUP_NUM || aKeyGroup == KEYGROUP_ALPHA ) && pItem && pItem->mpWindow && pItem->mbEnabled )
5866 Window *pFocusWindow = Application::GetFocusWindow();
5867 ImplHideFocus();
5868 mbChangingHighlight = TRUE; // avoid focus change due to loose focus
5869 pItem->mpWindow->ImplControlFocus( GETFOCUS_TAB );
5870 mbChangingHighlight = FALSE;
5871 if( pFocusWindow != Application::GetFocusWindow() )
5872 Application::GetFocusWindow()->KeyInput( rKEvt );
5874 else
5876 // do nothing to avoid key presses going into the document
5877 // while the toolbox has the focus
5878 // just forward function and special keys and combinations with Alt-key
5879 if( aKeyGroup == KEYGROUP_FKEYS || aKeyGroup == KEYGROUP_MISC || aKeyCode.IsMod2() )
5880 bForwardKey = TRUE;
5885 if ( aDelData.IsDelete() )
5886 return;
5887 ImplRemoveDel( &aDelData );
5889 // #107251# move focus away if this toolbox was disabled during keyinput
5890 if( HasFocus() && mpData->mbKeyInputDisabled && (ImplGetParent()->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL) ) == WB_DIALOGCONTROL)
5892 USHORT n = 0;
5893 Window *pFocusControl = ImplGetParent()->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
5894 if ( pFocusControl && pFocusControl != this )
5895 pFocusControl->ImplControlFocus( GETFOCUS_INIT );
5898 mnKeyModifier = 0;
5900 // #107712#, leave toolbox
5901 if( bGrabFocusToDocument )
5903 GrabFocusToDocument();
5904 return;
5907 if( bForwardKey )
5908 DockingWindow::KeyInput( rKEvt );
5911 // -----------------------------------------------------------------------
5913 // returns the current toolbox line of the item
5914 USHORT ToolBox::ImplGetItemLine( ImplToolItem* pCurrentItem )
5916 std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
5917 USHORT nLine = 1;
5918 while( it != mpData->m_aItems.end() )
5920 if ( it->mbBreak )
5921 nLine++;
5922 if( &(*it) == pCurrentItem)
5923 break;
5924 ++it;
5926 return nLine;
5929 // returns the first displayable item in the given line
5930 ImplToolItem* ToolBox::ImplGetFirstValidItem( USHORT nLine )
5932 if( !nLine || nLine > mnCurLines )
5933 return NULL;
5935 nLine--;
5937 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5938 while( it != mpData->m_aItems.end() )
5940 // find correct line
5941 if ( it->mbBreak )
5942 nLine--;
5943 if( !nLine )
5945 // find first useful item
5946 while( it != mpData->m_aItems.end() && ((it->meType != TOOLBOXITEM_BUTTON) ||
5947 /*!it->mbEnabled ||*/ !it->mbVisible || ImplIsFixedControl( &(*it) )) )
5949 ++it;
5950 if( it == mpData->m_aItems.end() || it->mbBreak )
5951 return NULL; // no valid items in this line
5953 return &(*it);
5955 ++it;
5958 return (it == mpData->m_aItems.end()) ? NULL : &(*it);
5961 // returns the last displayable item in the given line
5962 ImplToolItem* ToolBox::ImplGetLastValidItem( USHORT nLine )
5964 if( !nLine || nLine > mnCurLines )
5965 return NULL;
5967 nLine--;
5968 ImplToolItem *pFound = NULL;
5969 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
5970 while( it != mpData->m_aItems.end() )
5972 // find correct line
5973 if ( it->mbBreak )
5974 nLine--;
5975 if( !nLine )
5977 // find last useful item
5978 while( it != mpData->m_aItems.end() && ((it->meType == TOOLBOXITEM_BUTTON) &&
5979 /*it->mbEnabled &&*/ it->mbVisible && !ImplIsFixedControl( &(*it) )) )
5981 pFound = &(*it);
5982 ++it;
5983 if( it == mpData->m_aItems.end() || it->mbBreak )
5984 return pFound; // end of line: return last useful item
5986 return pFound;
5988 ++it;
5991 return pFound;
5994 // -----------------------------------------------------------------------
5996 USHORT ToolBox::ImplFindItemPos( const ImplToolItem* pItem, const std::vector< ImplToolItem >& rList )
5998 if( pItem )
6000 USHORT nPos;
6001 for( nPos = 0; nPos < rList.size(); nPos++ )
6002 if( &rList[ nPos ] == pItem )
6003 return nPos;
6005 return TOOLBOX_ITEM_NOTFOUND;
6008 void ToolBox::ChangeHighlight( USHORT nPos )
6010 if ( nPos < GetItemCount() ) {
6011 ImplGrabFocus( 0 );
6012 ImplChangeHighlight ( ImplGetItem ( GetItemId ( (USHORT) nPos ) ), FALSE );
6016 void ToolBox::ImplChangeHighlight( ImplToolItem* pItem, BOOL bNoGrabFocus )
6018 // avoid recursion due to focus change
6019 if( mbChangingHighlight )
6020 return;
6022 mbChangingHighlight = TRUE;
6024 ImplToolItem* pOldItem = NULL;
6026 if ( mnHighItemId )
6028 ImplHideFocus();
6029 USHORT nPos = GetItemPos( mnHighItemId );
6030 pOldItem = ImplGetItem( mnHighItemId );
6031 // #i89962# ImplDrawItem can cause Invalidate/Update
6032 // which will in turn ImplShowFocus again
6033 // set mnHighItemId to 0 already to prevent this hen/egg problem
6034 mnHighItemId = 0;
6035 ImplDrawItem( nPos, FALSE );
6036 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHTOFF, reinterpret_cast< void* >( nPos ) );
6039 if( !bNoGrabFocus && pItem != pOldItem && pOldItem && pOldItem->mpWindow )
6041 // move focus into toolbox
6042 GrabFocus();
6045 if( pItem )
6047 USHORT aPos = ToolBox::ImplFindItemPos( pItem, mpData->m_aItems );
6048 if( aPos != TOOLBOX_ITEM_NOTFOUND)
6050 // check for line breaks
6051 USHORT nLine = ImplGetItemLine( pItem );
6053 if( nLine >= mnCurLine + mnVisLines )
6055 mnCurLine = nLine - mnVisLines + 1;
6056 mbFormat = TRUE;
6058 else if ( nLine < mnCurLine )
6060 mnCurLine = nLine;
6061 mbFormat = TRUE;
6064 if( mbFormat )
6066 ImplFormat();
6069 mnHighItemId = pItem->mnId;
6070 ImplDrawItem( aPos, 2 ); // always use shadow effect (2)
6072 if( mbSelection )
6073 mnCurPos = aPos;
6074 ImplShowFocus();
6076 ImplCallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
6079 else
6081 ImplHideFocus();
6082 mnHighItemId = 0;
6083 mnCurPos = TOOLBOX_ITEM_NOTFOUND;
6086 mbChangingHighlight = FALSE;
6089 // -----------------------------------------------------------------------
6091 // check for keyboard accessible items
6092 static BOOL ImplIsValidItem( const ImplToolItem* pItem, BOOL bNotClipped )
6094 BOOL bValid = (pItem && pItem->meType == TOOLBOXITEM_BUTTON && pItem->mbVisible && !ImplIsFixedControl( pItem ));
6095 if( bValid && bNotClipped && pItem->IsClipped() )
6096 bValid = FALSE;
6097 return bValid;
6100 // -----------------------------------------------------------------------
6102 BOOL ToolBox::ImplChangeHighlightUpDn( BOOL bUp, BOOL bNoCycle )
6104 ImplToolItem* pToolItem = ImplGetItem( mnHighItemId );
6106 if( !pToolItem || !mnHighItemId )
6108 // menubutton highlighted ?
6109 if( mpData->mbMenubuttonSelected )
6111 if( bUp )
6113 // select last valid non-clipped item
6114 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
6115 ImplToolItem* pItem = NULL;
6116 while( it != mpData->m_aItems.begin() )
6118 --it;
6119 if ( ImplIsValidItem( &(*it), TRUE ) )
6121 pItem = &(*it);
6122 break;
6125 ImplDrawMenubutton( this, FALSE );
6126 ImplChangeHighlight( pItem );
6128 else
6130 // select first valid non-clipped item
6131 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
6132 while( it != mpData->m_aItems.end() )
6134 if ( ImplIsValidItem( &(*it), TRUE ) )
6135 break;
6136 ++it;
6138 if( it != mpData->m_aItems.end() )
6140 ImplDrawMenubutton( this, FALSE );
6141 ImplChangeHighlight( &(*it) );
6144 return TRUE;
6147 if( bUp )
6149 // Select first valid item
6150 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
6151 while( it != mpData->m_aItems.end() )
6153 if ( ImplIsValidItem( &(*it), FALSE ) )
6154 break;
6155 ++it;
6158 // select the menu button if a clipped item would be selected
6159 if( (it != mpData->m_aItems.end() && &(*it) == ImplGetFirstClippedItem( this )) && IsMenuEnabled() )
6161 ImplChangeHighlight( NULL );
6162 ImplDrawMenubutton( this, TRUE );
6164 else
6165 ImplChangeHighlight( (it != mpData->m_aItems.end()) ? &(*it) : NULL );
6166 return TRUE;
6168 else
6170 // Select last valid item
6172 // docked toolbars have the menubutton as last item - if this button is enabled
6173 if( IsMenuEnabled() && !ImplIsFloatingMode() )
6175 ImplChangeHighlight( NULL );
6176 ImplDrawMenubutton( this, TRUE );
6178 else
6180 std::vector< ImplToolItem >::iterator it = mpData->m_aItems.end();
6181 ImplToolItem* pItem = NULL;
6182 while( it != mpData->m_aItems.begin() )
6184 --it;
6185 if ( ImplIsValidItem( &(*it), FALSE ) )
6187 pItem = &(*it);
6188 break;
6191 ImplChangeHighlight( pItem );
6193 return TRUE;
6197 if( pToolItem )
6199 ULONG pos = ToolBox::ImplFindItemPos( pToolItem, mpData->m_aItems );
6200 ULONG nCount = mpData->m_aItems.size();
6202 ULONG i=0;
6205 if( bUp )
6207 if( !pos-- )
6209 if( bNoCycle )
6210 return FALSE;
6212 // highlight the menu button if it is the last item
6213 if( IsMenuEnabled() && !ImplIsFloatingMode() )
6215 ImplChangeHighlight( NULL );
6216 ImplDrawMenubutton( this, TRUE );
6217 return TRUE;
6219 else
6220 pos = nCount-1;
6223 else
6225 if( ++pos >= nCount )
6227 if( bNoCycle )
6228 return FALSE;
6230 // highlight the menu button if it is the last item
6231 if( IsMenuEnabled() && !ImplIsFloatingMode() )
6233 ImplChangeHighlight( NULL );
6234 ImplDrawMenubutton( this, TRUE );
6235 return TRUE;
6237 else
6238 pos = 0;
6242 pToolItem = &mpData->m_aItems[pos];
6244 if ( ImplIsValidItem( pToolItem, FALSE ) )
6245 break;
6247 } while( ++i < nCount);
6249 if( pToolItem->IsClipped() && IsMenuEnabled() )
6251 // select the menu button if a clipped item would be selected
6252 ImplChangeHighlight( NULL );
6253 ImplDrawMenubutton( this, TRUE );
6255 else if( i != nCount )
6256 ImplChangeHighlight( pToolItem );
6257 else
6258 return FALSE;
6260 return TRUE;
6263 // -----------------------------------------------------------------------
6265 void ToolBox::ImplShowFocus()
6267 if( mnHighItemId && HasFocus() )
6269 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
6270 if( pItem->mpWindow )
6272 Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
6273 pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = TRUE;
6274 pWin->Invalidate( 0 );
6279 // -----------------------------------------------------------------------
6281 void ToolBox::ImplHideFocus()
6283 if( mnHighItemId )
6285 ImplToolItem* pItem = ImplGetItem( mnHighItemId );
6286 if( pItem->mpWindow )
6288 Window *pWin = pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow ? pItem->mpWindow->ImplGetWindowImpl()->mpBorderWindow : pItem->mpWindow;
6289 pWin->ImplGetWindowImpl()->mbDrawSelectionBackground = FALSE;
6290 pWin->Invalidate( 0 );
6294 if ( mpData->mbMenubuttonSelected )
6296 // remove highlight from menubutton
6297 ImplDrawMenubutton( this, FALSE );
6301 // -----------------------------------------------------------------------
6303 void ToolBox::ImplDisableFlatButtons()
6305 #ifdef WNT // Check in the Windows registry if an AT tool wants no flat toolboxes
6306 static bool bInit = false, bValue = false;
6307 if( ! bInit )
6309 bInit = true;
6310 HKEY hkey;
6312 if( ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER,
6313 "Software\\OpenOffice.org\\Accessibility\\AtToolSupport",
6314 &hkey) )
6316 DWORD dwType = 0;
6317 WIN_BYTE Data[6]; // possible values: "true", "false", "1", "0", DWORD
6318 DWORD cbData = sizeof(Data);
6320 if( ERROR_SUCCESS == RegQueryValueEx(hkey, "DisableFlatToolboxButtons",
6321 NULL, &dwType, Data, &cbData) )
6323 switch (dwType)
6325 case REG_SZ:
6326 bValue = ((0 == stricmp((const char *) Data, "1")) || (0 == stricmp((const char *) Data, "true")));
6327 break;
6328 case REG_DWORD:
6329 bValue = (bool)(((DWORD *) Data)[0]);
6330 break;
6333 RegCloseKey(hkey);
6336 if( bValue )
6337 mnOutStyle &= ~TOOLBOX_STYLE_FLAT;
6338 #endif