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