Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <comphelper/processfactory.hxx>
23 : #include <comphelper/string.hxx>
24 : #include <tools/debug.hxx>
25 : #include <tools/rc.h>
26 :
27 : #include <vcl/svapp.hxx>
28 : #include <vcl/help.hxx>
29 : #include <vcl/bitmap.hxx>
30 : #include <vcl/toolbox.hxx>
31 : #include <vcl/mnemonic.hxx>
32 : #include <vcl/menu.hxx>
33 : #include <vcl/settings.hxx>
34 : #include <vcl/IconThemeInfo.hxx>
35 :
36 : #include <svdata.hxx>
37 : #include <brdwin.hxx>
38 : #include <toolbox.h>
39 :
40 : #include <unotools/confignode.hxx>
41 :
42 : #include <com/sun/star/frame/ModuleManager.hpp>
43 : #include <com/sun/star/frame/XController.hpp>
44 : #include <com/sun/star/frame/XModel.hpp>
45 : #include <com/sun/star/frame/XModuleManager2.hpp>
46 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
47 :
48 : using namespace vcl;
49 : using namespace com::sun::star;
50 :
51 : #define TB_SEP_SIZE 8
52 :
53 37394 : ImplToolBoxPrivateData::ImplToolBoxPrivateData() :
54 37394 : m_pLayoutData( NULL )
55 : {
56 37394 : meButtonSize = TOOLBOX_BUTTONSIZE_DONTCARE;
57 37394 : mpMenu = new PopupMenu();
58 37394 : mnEventId = 0;
59 :
60 37394 : maMenuType = TOOLBOX_MENUTYPE_NONE;
61 37394 : maMenubuttonItem.maItemSize = Size( TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET, TB_MENUBUTTON_SIZE+TB_MENUBUTTON_OFFSET );
62 37394 : maMenubuttonItem.meState = TRISTATE_FALSE;
63 37394 : mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
64 :
65 37394 : mbIsLocked = false;
66 37394 : mbNativeButtons = false;
67 37394 : mbIsPaintLocked = false;
68 37394 : mbAssumeDocked = false;
69 37394 : mbAssumePopupMode = false;
70 37394 : mbAssumeFloating = false;
71 37394 : mbKeyInputDisabled = false;
72 37394 : mbMenubuttonSelected = false;
73 37394 : mbPageScroll = false;
74 37394 : mbWillUsePopupMode = false;
75 37394 : mbDropDownByKeyboard = false;
76 37394 : }
77 :
78 74742 : ImplToolBoxPrivateData::~ImplToolBoxPrivateData()
79 : {
80 37371 : if( m_pLayoutData )
81 0 : delete m_pLayoutData;
82 37371 : delete mpMenu;
83 37371 : }
84 :
85 167159 : void ImplToolItem::init(sal_uInt16 nItemId, ToolBoxItemBits nItemBits,
86 : bool bEmptyBtn)
87 : {
88 167159 : mnId = nItemId;
89 167159 : mpWindow = NULL;
90 167159 : mpUserData = NULL;
91 167159 : meType = ToolBoxItemType::BUTTON;
92 167159 : mnBits = nItemBits;
93 167159 : meState = TRISTATE_FALSE;
94 167159 : mbEnabled = true;
95 167159 : mbVisible = true;
96 167159 : mbEmptyBtn = bEmptyBtn;
97 167159 : mbShowWindow = false;
98 167159 : mbBreak = false;
99 167159 : mnSepSize = TB_SEP_SIZE;
100 167159 : mnDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;
101 167159 : mnImageAngle = 0;
102 167159 : mbMirrorMode = false;
103 167159 : mbVisibleText = false;
104 167159 : mbExpand = false;
105 167159 : }
106 :
107 54215 : ImplToolItem::ImplToolItem()
108 : {
109 54215 : init(0, ToolBoxItemBits::NONE, true);
110 54215 : }
111 :
112 12254 : ImplToolItem::ImplToolItem( sal_uInt16 nItemId, const Image& rImage,
113 : ToolBoxItemBits nItemBits ) :
114 12254 : maImage( rImage )
115 : {
116 12254 : init(nItemId, nItemBits, false);
117 12254 : }
118 :
119 81308 : ImplToolItem::ImplToolItem( sal_uInt16 nItemId, const OUString& rText,
120 : ToolBoxItemBits nItemBits ) :
121 81308 : maText( rText )
122 : {
123 81308 : init(nItemId, nItemBits, false);
124 81308 : }
125 :
126 19382 : ImplToolItem::ImplToolItem( sal_uInt16 nItemId, const Image& rImage,
127 : const OUString& rText, ToolBoxItemBits nItemBits ) :
128 : maImage( rImage ),
129 19382 : maText( rText )
130 : {
131 19382 : init(nItemId, nItemBits, false);
132 19382 : }
133 :
134 288992 : ImplToolItem::ImplToolItem( const ImplToolItem& rItem ) :
135 : mpWindow ( rItem.mpWindow ),
136 : mpUserData ( rItem.mpUserData ),
137 : maImage ( rItem.maImage ),
138 : mnImageAngle ( rItem.mnImageAngle ),
139 : mbMirrorMode ( rItem.mbMirrorMode ),
140 : maText ( rItem.maText ),
141 : maQuickHelpText ( rItem.maQuickHelpText ),
142 : maHelpText ( rItem.maHelpText ),
143 : maCommandStr ( rItem.maCommandStr ),
144 : maHelpId ( rItem.maHelpId ),
145 : maRect ( rItem.maRect ),
146 : maCalcRect ( rItem.maCalcRect ),
147 : maMinimalItemSize ( rItem.maMinimalItemSize ),
148 : maItemSize ( rItem.maItemSize ),
149 : mnSepSize ( rItem.mnSepSize ),
150 : mnDropDownArrowWidth ( rItem.mnDropDownArrowWidth ),
151 : maContentSize ( rItem.maContentSize ),
152 : meType ( rItem.meType ),
153 : mnBits ( rItem.mnBits ),
154 : meState ( rItem.meState ),
155 : mnId ( rItem.mnId ),
156 : mbEnabled ( rItem.mbEnabled ),
157 : mbVisible ( rItem.mbVisible ),
158 : mbEmptyBtn ( rItem.mbEmptyBtn ),
159 : mbShowWindow ( rItem.mbShowWindow ),
160 : mbBreak ( rItem.mbBreak ),
161 : mbVisibleText ( rItem.mbVisibleText ),
162 288992 : mbExpand ( rItem.mbExpand )
163 : {
164 288992 : }
165 :
166 456076 : ImplToolItem::~ImplToolItem()
167 : {
168 : // don't dispose mpWindow - we get copied around.
169 456076 : }
170 :
171 468 : ImplToolItem& ImplToolItem::operator=( const ImplToolItem& rItem )
172 : {
173 468 : mpWindow = rItem.mpWindow;
174 468 : mpUserData = rItem.mpUserData;
175 468 : maImage = rItem.maImage;
176 468 : mnImageAngle = rItem.mnImageAngle;
177 468 : mbMirrorMode = rItem.mbMirrorMode;
178 468 : maText = rItem.maText;
179 468 : maQuickHelpText = rItem.maQuickHelpText;
180 468 : maHelpText = rItem.maHelpText;
181 468 : maCommandStr = rItem.maCommandStr;
182 468 : maHelpId = rItem.maHelpId;
183 468 : maRect = rItem.maRect;
184 468 : maCalcRect = rItem.maCalcRect;
185 468 : mnSepSize = rItem.mnSepSize;
186 468 : mnDropDownArrowWidth = rItem.mnDropDownArrowWidth;
187 468 : maContentSize = rItem.maContentSize;
188 468 : maMinimalItemSize = rItem.maMinimalItemSize;
189 468 : maItemSize = rItem.maItemSize;
190 468 : mbVisibleText = rItem.mbVisibleText;
191 468 : mbExpand = rItem.mbExpand;
192 468 : meType = rItem.meType;
193 468 : mnBits = rItem.mnBits;
194 468 : meState = rItem.meState;
195 468 : mnId = rItem.mnId;
196 468 : mbEnabled = rItem.mbEnabled;
197 468 : mbVisible = rItem.mbVisible;
198 468 : mbEmptyBtn = rItem.mbEmptyBtn;
199 468 : mbShowWindow = rItem.mbShowWindow;
200 468 : mbBreak = rItem.mbBreak;
201 468 : return *this;
202 : }
203 :
204 60341 : Size ImplToolItem::GetSize( bool bHorz, bool bCheckMaxWidth, long maxWidth, const Size& rDefaultSize )
205 : {
206 60341 : Size aSize( rDefaultSize ); // the size of 'standard' toolbox items
207 : // non-standard items are eg windows or buttons with text
208 :
209 60341 : if ( (meType == ToolBoxItemType::BUTTON) || (meType == ToolBoxItemType::SPACE) )
210 : {
211 49513 : aSize = maItemSize;
212 :
213 49513 : if ( mpWindow && bHorz )
214 : {
215 : // get size of item window and check if it fits
216 : // no windows in vertical toolbars (the default is mbShowWindow=false)
217 4703 : Size aWinSize = mpWindow->GetSizePixel();
218 4703 : if ( !bCheckMaxWidth || (aWinSize.Width() <= maxWidth) )
219 : {
220 4703 : aSize.Width() = aWinSize.Width();
221 4703 : aSize.Height() = aWinSize.Height();
222 4703 : mbShowWindow = true;
223 : }
224 : else
225 : {
226 0 : if ( mbEmptyBtn )
227 : {
228 0 : aSize.Width() = 0;
229 0 : aSize.Height() = 0;
230 : }
231 : }
232 49513 : }
233 : }
234 10828 : else if ( meType == ToolBoxItemType::SEPARATOR )
235 : {
236 10813 : if ( bHorz )
237 : {
238 10417 : aSize.Width() = mnSepSize;
239 10417 : aSize.Height() = rDefaultSize.Height();
240 : }
241 : else
242 : {
243 396 : aSize.Width() = rDefaultSize.Width();
244 396 : aSize.Height() = mnSepSize;
245 : }
246 : }
247 15 : else if ( meType == ToolBoxItemType::BREAK )
248 : {
249 15 : aSize.Width() = 0;
250 15 : aSize.Height() = 0;
251 : }
252 :
253 60341 : return aSize;
254 : }
255 :
256 57705 : void ImplToolItem::DetermineButtonDrawStyle( ButtonType eButtonType, bool& rbImage, bool& rbText ) const
257 : {
258 57705 : if ( meType != ToolBoxItemType::BUTTON )
259 : {
260 : // no button -> draw nothing
261 0 : rbImage = rbText = false;
262 57705 : return;
263 : }
264 :
265 : bool bHasImage;
266 : bool bHasText;
267 :
268 : // check for image and/or text
269 57705 : if ( !(maImage) )
270 258 : bHasImage = false;
271 : else
272 57447 : bHasImage = true;
273 57705 : if ( maText.isEmpty() )
274 1696 : bHasText = false;
275 : else
276 56009 : bHasText = true;
277 :
278 : // prefer images if symbolonly buttons are drawn
279 : // prefer texts if textonly buttons are dreawn
280 :
281 57705 : if ( eButtonType == ButtonType::SYMBOLONLY ) // drawing icons only
282 : {
283 57705 : if( bHasImage || !bHasText )
284 : {
285 57447 : rbImage = true;
286 57447 : rbText = false;
287 : }
288 : else
289 : {
290 258 : rbImage = false;
291 258 : rbText = true;
292 : }
293 : }
294 0 : else if ( eButtonType == ButtonType::TEXT ) // drawing text only
295 : {
296 0 : if( bHasText || !bHasImage )
297 : {
298 0 : rbImage = false;
299 0 : rbText = true;
300 : }
301 : else
302 : {
303 0 : rbImage = true;
304 0 : rbText = false;
305 : }
306 : }
307 : else // drawing icons and text both
308 : {
309 0 : rbImage = true;
310 0 : rbText = true;
311 : }
312 : }
313 :
314 14266 : Rectangle ImplToolItem::GetDropDownRect( bool bHorz ) const
315 : {
316 14266 : Rectangle aRect;
317 14266 : if( (mnBits & ToolBoxItemBits::DROPDOWN) && !maRect.IsEmpty() )
318 : {
319 14266 : aRect = maRect;
320 14266 : if( mbVisibleText && !bHorz )
321 : // item will be rotated -> place dropdown to the bottom
322 0 : aRect.Top() = aRect.Bottom() - mnDropDownArrowWidth;
323 : else
324 : // place dropdown to the right
325 14266 : aRect.Left() = aRect.Right() - mnDropDownArrowWidth;
326 : }
327 14266 : return aRect;
328 : }
329 :
330 272301 : bool ImplToolItem::IsClipped() const
331 : {
332 272301 : return ( meType == ToolBoxItemType::BUTTON && mbVisible && maRect.IsEmpty() );
333 : }
334 :
335 0 : bool ImplToolItem::IsItemHidden() const
336 : {
337 0 : return ( meType == ToolBoxItemType::BUTTON && !mbVisible );
338 : }
339 :
340 157620 : const OUString ToolBox::ImplConvertMenuString( const OUString& rStr )
341 : {
342 157620 : OUString aCvtStr( rStr );
343 157620 : if ( mbMenuStrings )
344 3 : aCvtStr = comphelper::string::stripEnd(aCvtStr, '.');
345 157620 : aCvtStr = MnemonicGenerator::EraseAllMnemonicChars( aCvtStr );
346 157620 : return aCvtStr;
347 : }
348 :
349 284153 : void ToolBox::ImplInvalidate( bool bNewCalc, bool bFullPaint )
350 : {
351 284153 : ImplUpdateInputEnable();
352 :
353 284153 : if ( bNewCalc )
354 236031 : mbCalc = true;
355 :
356 284153 : if ( bFullPaint )
357 : {
358 15176 : mbFormat = true;
359 :
360 : // do we need to redraw?
361 15176 : if ( IsReallyVisible() && IsUpdateMode() )
362 : {
363 : Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
364 0 : mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
365 0 : maIdle.Stop();
366 : }
367 : }
368 : else
369 : {
370 268977 : if ( !mbFormat )
371 : {
372 16442 : mbFormat = true;
373 :
374 : // do we need to redraw?
375 16442 : if ( IsReallyVisible() && IsUpdateMode() )
376 1253 : maIdle.Start();
377 : }
378 : }
379 :
380 : // request new layout by layoutmanager
381 284153 : CallEventListeners( VCLEVENT_TOOLBOX_FORMATCHANGED );
382 284153 : }
383 :
384 120383 : void ToolBox::ImplUpdateItem( sal_uInt16 nIndex )
385 : {
386 : // do we need to redraw?
387 120383 : if ( IsReallyVisible() && IsUpdateMode() )
388 : {
389 19137 : if ( nIndex == 0xFFFF )
390 : {
391 : // #i52217# no immediate draw as this might lead to paint problems
392 : Invalidate( Rectangle( mnLeftBorder, mnTopBorder,
393 4279 : mnDX-mnRightBorder-1, mnDY-mnBottomBorder-1 ) );
394 : }
395 : else
396 : {
397 14858 : if ( !mbFormat )
398 : {
399 : // #i52217# no immediate draw as this might lead to paint problems
400 14858 : Invalidate( mpData->m_aItems[nIndex].maRect );
401 : }
402 : else
403 0 : maPaintRect.Union( mpData->m_aItems[nIndex].maRect );
404 : }
405 : }
406 120383 : }
407 :
408 2 : void ToolBox::Click()
409 : {
410 2 : CallEventListeners( VCLEVENT_TOOLBOX_CLICK );
411 2 : maClickHdl.Call( this );
412 2 : }
413 :
414 0 : void ToolBox::DoubleClick()
415 : {
416 0 : CallEventListeners( VCLEVENT_TOOLBOX_DOUBLECLICK );
417 0 : maDoubleClickHdl.Call( this );
418 0 : }
419 :
420 2 : void ToolBox::Activate()
421 : {
422 2 : mnActivateCount++;
423 2 : CallEventListeners( VCLEVENT_TOOLBOX_ACTIVATE );
424 2 : maActivateHdl.Call( this );
425 2 : }
426 :
427 2 : void ToolBox::Deactivate()
428 : {
429 2 : mnActivateCount--;
430 2 : CallEventListeners( VCLEVENT_TOOLBOX_DEACTIVATE );
431 2 : maDeactivateHdl.Call( this );
432 2 : }
433 :
434 0 : void ToolBox::Highlight()
435 : {
436 0 : CallEventListeners( VCLEVENT_TOOLBOX_HIGHLIGHT );
437 0 : }
438 :
439 2 : void ToolBox::Select()
440 : {
441 2 : ImplDelData aDelData;
442 2 : ImplAddDel( &aDelData );
443 :
444 2 : CallEventListeners( VCLEVENT_TOOLBOX_SELECT );
445 2 : maSelectHdl.Call( this );
446 :
447 2 : if ( aDelData.IsDead() )
448 2 : return;
449 2 : ImplRemoveDel( &aDelData );
450 :
451 : // TODO: GetFloatingWindow in DockingWindow is currently inline, change it to check dockingwrapper
452 2 : ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
453 2 : if( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() )
454 0 : pWrapper->GetFloatingWindow()->EndPopupMode();
455 : }
456 :
457 265 : void ToolBox::InsertItem( const ResId& rResId, sal_uInt16 nPos )
458 : {
459 : sal_uLong nObjMask;
460 265 : bool bImage = false; // has image
461 :
462 : // create item
463 265 : ImplToolItem aItem;
464 :
465 265 : GetRes( rResId.SetRT( RSC_TOOLBOXITEM ) );
466 265 : nObjMask = ReadLongRes();
467 :
468 265 : if ( nObjMask & RSC_TOOLBOXITEM_ID )
469 191 : aItem.mnId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
470 : else
471 74 : aItem.mnId = 1;
472 :
473 265 : if ( nObjMask & RSC_TOOLBOXITEM_TYPE )
474 74 : aItem.meType = (ToolBoxItemType)ReadLongRes();
475 :
476 265 : if ( nObjMask & RSC_TOOLBOXITEM_STATUS )
477 27 : aItem.mnBits = (ToolBoxItemBits)ReadLongRes();
478 :
479 265 : if( nObjMask & RSC_TOOLBOXITEM_HELPID )
480 191 : aItem.maHelpId = ReadByteStringRes();
481 :
482 265 : if ( nObjMask & RSC_TOOLBOXITEM_TEXT )
483 : {
484 191 : aItem.maText = ReadStringRes();
485 191 : aItem.maText = ImplConvertMenuString( aItem.maText );
486 : }
487 265 : if ( nObjMask & RSC_TOOLBOXITEM_HELPTEXT )
488 0 : aItem.maHelpText = ReadStringRes();
489 :
490 265 : if ( nObjMask & RSC_TOOLBOXITEM_BITMAP )
491 : {
492 0 : Bitmap aBmp = Bitmap( ResId( static_cast<RSHEADER_TYPE*>(GetClassRes()), *rResId.GetResMgr() ) );
493 0 : IncrementRes( GetObjSizeRes( static_cast<RSHEADER_TYPE*>(GetClassRes()) ) );
494 0 : aItem.maImage = Image( aBmp, IMAGE_STDBTN_COLOR );
495 0 : bImage = true;
496 : }
497 265 : if ( nObjMask & RSC_TOOLBOXITEM_IMAGE )
498 : {
499 0 : aItem.maImage = Image( ResId( static_cast<RSHEADER_TYPE*>(GetClassRes()), *rResId.GetResMgr() ) );
500 0 : IncrementRes( GetObjSizeRes( static_cast<RSHEADER_TYPE*>(GetClassRes()) ) );
501 0 : bImage = true;
502 : }
503 265 : if ( nObjMask & RSC_TOOLBOXITEM_DISABLE )
504 0 : aItem.mbEnabled = ReadShortRes() == 0;
505 :
506 265 : if ( nObjMask & RSC_TOOLBOXITEM_STATE )
507 0 : aItem.meState = (TriState)ReadLongRes();
508 :
509 265 : if ( nObjMask & RSC_TOOLBOXITEM_HIDE )
510 0 : aItem.mbVisible = ReadShortRes() == 0;
511 :
512 265 : if ( nObjMask & RSC_TOOLBOXITEM_COMMAND )
513 0 : aItem.maCommandStr = ReadStringRes();
514 :
515 : // if no image is loaded, try to load one from the image list
516 265 : if ( !bImage && aItem.mnId )
517 265 : aItem.maImage = maImageList.GetImage( aItem.mnId );
518 :
519 : // if this is a ButtonItem, check ID
520 : bool bNewCalc;
521 265 : if ( aItem.meType != ToolBoxItemType::BUTTON )
522 : {
523 74 : bNewCalc = false;
524 74 : aItem.mnId = 0;
525 : }
526 : else
527 : {
528 191 : bNewCalc = true;
529 :
530 : DBG_ASSERT( aItem.mnId, "ToolBox::InsertItem(): ItemId == 0" );
531 : DBG_ASSERT( GetItemPos( aItem.mnId ) == TOOLBOX_ITEM_NOTFOUND,
532 : "ToolBox::InsertItem(): ItemId already exists" );
533 : }
534 :
535 : // create item and add to list
536 265 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
537 265 : mpData->ImplClearLayoutData();
538 :
539 : // recalculate ToolBox and redraw
540 265 : ImplInvalidate( bNewCalc );
541 :
542 : // Notify
543 265 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
544 265 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
545 265 : }
546 :
547 12254 : void ToolBox::InsertItem( sal_uInt16 nItemId, const Image& rImage,
548 : ToolBoxItemBits nBits, sal_uInt16 nPos )
549 : {
550 : DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
551 : DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
552 : "ToolBox::InsertItem(): ItemId already exists" );
553 :
554 : // create item and add to list
555 12254 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, rImage, nBits ) );
556 12254 : SetItemImage(nItemId, rImage);
557 12254 : mpData->ImplClearLayoutData();
558 :
559 12254 : ImplInvalidate( true );
560 :
561 : // Notify
562 12254 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
563 12254 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >(nNewPos ) );
564 12254 : }
565 :
566 19382 : void ToolBox::InsertItem( sal_uInt16 nItemId, const Image& rImage,
567 : const OUString& rText,
568 : ToolBoxItemBits nBits, sal_uInt16 nPos )
569 : {
570 : DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
571 : DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
572 : "ToolBox::InsertItem(): ItemId already exists" );
573 :
574 : // create item and add to list
575 19382 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, rImage, ImplConvertMenuString( rText ), nBits ) );
576 19382 : SetItemImage(nItemId, rImage);
577 19382 : mpData->ImplClearLayoutData();
578 :
579 19382 : ImplInvalidate( true );
580 :
581 : // Notify
582 19382 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
583 19382 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
584 19382 : }
585 :
586 81308 : void ToolBox::InsertItem( sal_uInt16 nItemId, const OUString& rText,
587 : ToolBoxItemBits nBits, sal_uInt16 nPos )
588 : {
589 : DBG_ASSERT( nItemId, "ToolBox::InsertItem(): ItemId == 0" );
590 : DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
591 : "ToolBox::InsertItem(): ItemId already exists" );
592 :
593 : // create item and add to list
594 81308 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), ImplToolItem( nItemId, ImplConvertMenuString( rText ), nBits ) );
595 81308 : mpData->ImplClearLayoutData();
596 :
597 81308 : ImplInvalidate( true );
598 :
599 : // Notify
600 81308 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
601 81308 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
602 81308 : }
603 :
604 19382 : void ToolBox::InsertItem(const OUString& rCommand, const uno::Reference<frame::XFrame>& rFrame, ToolBoxItemBits nBits, const Size& rRequestedSize, sal_uInt16 nPos)
605 : {
606 19382 : uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
607 38764 : uno::Reference<frame::XModuleManager2> xModuleManager(frame::ModuleManager::create(xContext));
608 38764 : OUString aModuleId(xModuleManager->identify(rFrame));
609 :
610 38764 : OUString aLabel(VclBuilder::getCommandLabel(rCommand, xContext, aModuleId));
611 38764 : Image aImage(VclBuilder::getCommandImage(rCommand, (GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE), xContext, rFrame, aModuleId));
612 :
613 : // let's invent an ItemId
614 19382 : const sal_uInt16 COMMAND_ITEMID_START = 30000;
615 19382 : sal_uInt16 nItemId = COMMAND_ITEMID_START + GetItemCount();
616 :
617 19382 : InsertItem(nItemId, aImage, aLabel, nBits, nPos);
618 19382 : SetItemCommand(nItemId, rCommand);
619 :
620 : // set the minimal size
621 19382 : ImplToolItem* pItem = ImplGetItem( nItemId );
622 19382 : if ( pItem )
623 38764 : pItem->maMinimalItemSize = rRequestedSize;
624 19382 : }
625 :
626 684 : void ToolBox::InsertWindow( sal_uInt16 nItemId, vcl::Window* pWindow,
627 : ToolBoxItemBits nBits, sal_uInt16 nPos )
628 : {
629 : DBG_ASSERT( nItemId, "ToolBox::InsertWindow(): ItemId == 0" );
630 : DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
631 : "ToolBox::InsertWindow(): ItemId already exists" );
632 :
633 : // create item and add to list
634 684 : ImplToolItem aItem;
635 684 : aItem.mnId = nItemId;
636 684 : aItem.meType = ToolBoxItemType::BUTTON;
637 684 : aItem.mnBits = nBits;
638 684 : aItem.mpWindow = pWindow;
639 684 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
640 684 : mpData->ImplClearLayoutData();
641 :
642 684 : if ( pWindow )
643 684 : pWindow->Hide();
644 :
645 684 : ImplInvalidate( true );
646 :
647 : // Notify
648 684 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
649 684 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
650 684 : }
651 :
652 0 : void ToolBox::InsertSpace( sal_uInt16 nPos )
653 : {
654 : // create item and add to list
655 0 : ImplToolItem aItem;
656 0 : aItem.meType = ToolBoxItemType::SPACE;
657 0 : aItem.mbEnabled = false;
658 0 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
659 0 : mpData->ImplClearLayoutData();
660 :
661 0 : ImplInvalidate( false );
662 :
663 : // Notify
664 0 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
665 0 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
666 0 : }
667 :
668 15872 : void ToolBox::InsertSeparator( sal_uInt16 nPos, sal_uInt16 nPixSize )
669 : {
670 : // create item and add to list
671 15872 : ImplToolItem aItem;
672 15872 : aItem.meType = ToolBoxItemType::SEPARATOR;
673 15872 : aItem.mbEnabled = false;
674 15872 : if ( nPixSize )
675 0 : aItem.mnSepSize = nPixSize;
676 15872 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
677 15872 : mpData->ImplClearLayoutData();
678 :
679 15872 : ImplInvalidate( false );
680 :
681 : // Notify
682 15872 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
683 15872 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
684 15872 : }
685 :
686 0 : void ToolBox::InsertBreak( sal_uInt16 nPos )
687 : {
688 : // create item and add to list
689 0 : ImplToolItem aItem;
690 0 : aItem.meType = ToolBoxItemType::BREAK;
691 0 : aItem.mbEnabled = false;
692 0 : mpData->m_aItems.insert( (nPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nPos : mpData->m_aItems.end(), aItem );
693 0 : mpData->ImplClearLayoutData();
694 :
695 0 : ImplInvalidate( false );
696 :
697 : // Notify
698 0 : sal_uInt16 nNewPos = sal::static_int_cast<sal_uInt16>(( nPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nPos);
699 0 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
700 0 : }
701 :
702 1 : void ToolBox::RemoveItem( sal_uInt16 nPos )
703 : {
704 1 : if( nPos < mpData->m_aItems.size() )
705 : {
706 : bool bMustCalc;
707 1 : if ( mpData->m_aItems[nPos].meType == ToolBoxItemType::BUTTON )
708 1 : bMustCalc = true;
709 : else
710 0 : bMustCalc = false;
711 :
712 1 : if ( mpData->m_aItems[nPos].mpWindow )
713 0 : mpData->m_aItems[nPos].mpWindow->Hide();
714 :
715 : // add the removed item to PaintRect
716 1 : maPaintRect.Union( mpData->m_aItems[nPos].maRect );
717 :
718 : // ensure not to delete in the Select-Handler
719 1 : if ( mpData->m_aItems[nPos].mnId == mnCurItemId )
720 0 : mnCurItemId = 0;
721 1 : if ( mpData->m_aItems[nPos].mnId == mnHighItemId )
722 0 : mnHighItemId = 0;
723 :
724 1 : ImplInvalidate( bMustCalc );
725 :
726 1 : mpData->m_aItems.erase( mpData->m_aItems.begin()+nPos );
727 1 : mpData->ImplClearLayoutData();
728 :
729 : // Notify
730 1 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMREMOVED, reinterpret_cast< void* >( nPos ) );
731 : }
732 1 : }
733 :
734 7011 : void ToolBox::CopyItem( const ToolBox& rToolBox, sal_uInt16 nItemId,
735 : sal_uInt16 nNewPos )
736 : {
737 : DBG_ASSERT( GetItemPos( nItemId ) == TOOLBOX_ITEM_NOTFOUND,
738 : "ToolBox::CopyItem(): ItemId already exists" );
739 :
740 7011 : sal_uInt16 nPos = rToolBox.GetItemPos( nItemId );
741 :
742 : // found item
743 7011 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
744 : {
745 : // push ToolBox item onto the list
746 7011 : ImplToolItem aNewItem = rToolBox.mpData->m_aItems[nPos];
747 : // reset state
748 7011 : aNewItem.mpWindow = NULL;
749 7011 : aNewItem.mbShowWindow = false;
750 :
751 7011 : mpData->m_aItems.insert( (nNewPos < mpData->m_aItems.size()) ? mpData->m_aItems.begin()+nNewPos : mpData->m_aItems.end(), aNewItem );
752 7011 : mpData->ImplClearLayoutData();
753 : // redraw ToolBox
754 7011 : ImplInvalidate( false );
755 :
756 : // Notify
757 7011 : sal_uInt16 nNewPos2 = sal::static_int_cast<sal_uInt16>(( nNewPos == TOOLBOX_APPEND ) ? ( mpData->m_aItems.size() - 1 ) : nNewPos);
758 7011 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos2 ) );
759 : }
760 7011 : }
761 :
762 6808 : void ToolBox::Clear()
763 : {
764 6808 : mpData->m_aItems.clear();
765 6808 : mpData->ImplClearLayoutData();
766 :
767 : // ensure not to delete in the Select-Handler
768 6808 : mnCurItemId = 0;
769 6808 : mnHighItemId = 0;
770 :
771 6808 : ImplInvalidate( true, true );
772 :
773 : // Notify
774 6808 : CallEventListeners( VCLEVENT_TOOLBOX_ALLITEMSCHANGED );
775 6808 : }
776 :
777 9522 : void ToolBox::SetButtonType( ButtonType eNewType )
778 : {
779 9522 : if ( meButtonType != eNewType )
780 : {
781 0 : meButtonType = eNewType;
782 :
783 : // better redraw everything, as otherwise there might be problems
784 : // with regions that were copied with CopyBits
785 0 : ImplInvalidate( true );
786 : }
787 9522 : }
788 :
789 25668 : void ToolBox::SetToolboxButtonSize( ToolBoxButtonSize eSize )
790 : {
791 25668 : if( mpData->meButtonSize != eSize )
792 : {
793 25668 : mpData->meButtonSize = eSize;
794 25668 : mbCalc = true;
795 25668 : mbFormat = true;
796 : }
797 25668 : }
798 :
799 118929 : ToolBoxButtonSize ToolBox::GetToolboxButtonSize() const
800 : {
801 118929 : return mpData->meButtonSize;
802 : }
803 :
804 : /*static*/ Size
805 66372 : ToolBox::GetDefaultImageSize(bool bLarge)
806 : {
807 66372 : const long TB_SMALLIMAGESIZE = 16;
808 66372 : if (!bLarge) {
809 66348 : return Size(TB_SMALLIMAGESIZE, TB_SMALLIMAGESIZE);
810 : }
811 :
812 24 : OUString iconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
813 24 : return vcl::IconThemeInfo::SizeByThemeName(iconTheme);
814 : }
815 :
816 66372 : Size ToolBox::GetDefaultImageSize() const
817 : {
818 66372 : return GetDefaultImageSize( GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE );
819 : }
820 :
821 12262 : void ToolBox::SetAlign( WindowAlign eNewAlign )
822 : {
823 12262 : if ( meAlign != eNewAlign )
824 : {
825 489 : meAlign = eNewAlign;
826 :
827 489 : if ( !ImplIsFloatingMode() )
828 : {
829 : // set horizontal/vertical alignment
830 489 : if ( (eNewAlign == WINDOWALIGN_LEFT) || (eNewAlign == WINDOWALIGN_RIGHT) )
831 134 : mbHorz = false;
832 : else
833 355 : mbHorz = true;
834 :
835 : // Update the background according to Persona if necessary
836 489 : ImplInitSettings( false, false, true );
837 :
838 : // redraw everything, as the border has changed
839 489 : mbCalc = true;
840 489 : mbFormat = true;
841 489 : if ( IsReallyVisible() && IsUpdateMode() )
842 0 : Invalidate();
843 : }
844 : }
845 12262 : }
846 :
847 9530 : void ToolBox::SetLineCount( sal_uInt16 nNewLines )
848 : {
849 9530 : if ( !nNewLines )
850 0 : nNewLines = 1;
851 :
852 9530 : if ( mnLines != nNewLines )
853 : {
854 8 : mnLines = nNewLines;
855 :
856 : // better redraw everything, as otherwise there might be problems
857 : // with regions that were copied with CopyBits
858 8 : Invalidate();
859 : }
860 9530 : }
861 :
862 0 : void ToolBox::SetPageScroll( bool b )
863 : {
864 0 : mpData->mbPageScroll = b;
865 0 : }
866 :
867 495471 : sal_uInt16 ToolBox::GetItemCount() const
868 : {
869 495471 : return mpData ? (sal_uInt16)mpData->m_aItems.size() : 0;
870 : }
871 :
872 1831 : ToolBoxItemType ToolBox::GetItemType( sal_uInt16 nPos ) const
873 : {
874 1831 : return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].meType : ToolBoxItemType::DONTKNOW;
875 : }
876 :
877 1026135 : sal_uInt16 ToolBox::GetItemPos( sal_uInt16 nItemId ) const
878 : {
879 1026135 : if (mpData)
880 : {
881 1026135 : int nCount = mpData->m_aItems.size();
882 20937236 : for( int nPos = 0; nPos < nCount; nPos++ )
883 20937228 : if( mpData->m_aItems[nPos].mnId == nItemId )
884 1026127 : return (sal_uInt16)nPos;
885 : }
886 8 : return TOOLBOX_ITEM_NOTFOUND;
887 : }
888 :
889 0 : sal_uInt16 ToolBox::GetItemPos( const Point& rPos ) const
890 : {
891 : // search the item position on the given point
892 0 : sal_uInt16 nRet = TOOLBOX_ITEM_NOTFOUND;
893 0 : sal_uInt16 nPos = 0;
894 0 : std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
895 0 : while( it != mpData->m_aItems.end() )
896 : {
897 0 : if ( it->maRect.IsInside( rPos ) )
898 : {
899 : // item found -> save position and break
900 0 : nRet = nPos;
901 0 : break;
902 : }
903 :
904 0 : ++it;
905 0 : ++nPos;
906 : }
907 :
908 0 : return nRet;
909 : }
910 :
911 421760 : sal_uInt16 ToolBox::GetItemId( sal_uInt16 nPos ) const
912 : {
913 421760 : return (nPos < mpData->m_aItems.size()) ? mpData->m_aItems[nPos].mnId : 0;
914 : }
915 :
916 0 : sal_uInt16 ToolBox::GetItemId( const Point& rPos ) const
917 : {
918 : // find item that was clicked
919 0 : std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
920 0 : while( it != mpData->m_aItems.end() )
921 : {
922 : // is it this item?
923 0 : if ( it->maRect.IsInside( rPos ) )
924 : {
925 0 : if ( it->meType == ToolBoxItemType::BUTTON )
926 0 : return it->mnId;
927 : else
928 0 : return 0;
929 : }
930 :
931 0 : ++it;
932 : }
933 :
934 0 : return 0;
935 : }
936 :
937 5098 : Size ToolBox::GetItemContentSize( sal_uInt16 nItemId ) const
938 : {
939 5098 : if ( mbCalc || mbFormat )
940 4025 : (const_cast<ToolBox*>(this))->ImplFormat();
941 :
942 5098 : sal_uInt16 nPos = GetItemPos( nItemId );
943 5098 : if ( nPos < mpData->m_aItems.size() )
944 5098 : return mpData->m_aItems[nPos].maContentSize;
945 : else
946 0 : return Size();
947 : }
948 :
949 44415 : sal_uInt16 ToolBox::GetItemId(const OUString &rCommand) const
950 : {
951 44415 : if (!mpData)
952 0 : return TOOLBOX_ITEM_NOTFOUND;
953 :
954 77382 : for (std::vector<ImplToolItem>::const_iterator it = mpData->m_aItems.begin(); it != mpData->m_aItems.end(); ++it)
955 : {
956 77382 : if (it->maCommandStr == rCommand)
957 44415 : return it->mnId;
958 : }
959 :
960 0 : return 0;
961 : }
962 :
963 0 : Point ToolBox::ImplGetPopupPosition( const Rectangle& rRect, const Size& rSize ) const
964 : {
965 0 : Point aPos;
966 0 : if( !rRect.IsEmpty() )
967 : {
968 0 : Rectangle aScreen = GetDesktopRectPixel();
969 :
970 : // the popup should be positioned so that it will not cover
971 : // the item rect and that it fits the desktop
972 : // the preferred direction is always towards the center of
973 : // the application window
974 :
975 0 : Point devPos; // the position in device coordinates for screen comparison
976 0 : switch( meAlign )
977 : {
978 : case WINDOWALIGN_TOP:
979 0 : aPos = rRect.BottomLeft();
980 0 : aPos.Y()++;
981 0 : devPos = OutputToAbsoluteScreenPixel( aPos );
982 0 : if( devPos.Y() + rSize.Height() >= aScreen.Bottom() )
983 0 : aPos.Y() = rRect.Top() - rSize.Height();
984 0 : break;
985 : case WINDOWALIGN_BOTTOM:
986 0 : aPos = rRect.TopLeft();
987 0 : aPos.Y()--;
988 0 : devPos = OutputToAbsoluteScreenPixel( aPos );
989 0 : if( devPos.Y() - rSize.Height() > aScreen.Top() )
990 0 : aPos.Y() -= rSize.Height();
991 : else
992 0 : aPos.Y() = rRect.Bottom();
993 0 : break;
994 : case WINDOWALIGN_LEFT:
995 0 : aPos = rRect.TopRight();
996 0 : aPos.X()++;
997 0 : devPos = OutputToAbsoluteScreenPixel( aPos );
998 0 : if( devPos.X() + rSize.Width() >= aScreen.Right() )
999 0 : aPos.X() = rRect.Left() - rSize.Width();
1000 0 : break;
1001 : case WINDOWALIGN_RIGHT:
1002 0 : aPos = rRect.TopLeft();
1003 0 : aPos.X()--;
1004 0 : devPos = OutputToAbsoluteScreenPixel( aPos );
1005 0 : if( devPos.X() - rSize.Width() > aScreen.Left() )
1006 0 : aPos.X() -= rSize.Width();
1007 : else
1008 0 : aPos.X() = rRect.Right();
1009 0 : break;
1010 : default:
1011 0 : break;
1012 : }
1013 : }
1014 0 : return aPos;
1015 : }
1016 :
1017 0 : Point ToolBox::GetItemPopupPosition( sal_uInt16 nItemId, const Size& rSize ) const
1018 : {
1019 0 : return ImplGetPopupPosition( GetItemRect( nItemId ), rSize );
1020 : }
1021 :
1022 981 : Rectangle ToolBox::GetItemRect( sal_uInt16 nItemId ) const
1023 : {
1024 981 : if ( mbCalc || mbFormat )
1025 8 : const_cast<ToolBox*>(this)->ImplFormat();
1026 :
1027 981 : sal_uInt16 nPos = GetItemPos( nItemId );
1028 981 : return GetItemPosRect( nPos );
1029 : }
1030 :
1031 5601 : Rectangle ToolBox::GetItemPosRect( sal_uInt16 nPos ) const
1032 : {
1033 5601 : if ( mbCalc || mbFormat )
1034 1709 : const_cast<ToolBox*>(this)->ImplFormat();
1035 :
1036 5601 : if ( nPos < mpData->m_aItems.size() )
1037 5569 : return mpData->m_aItems[nPos].maRect;
1038 : else
1039 32 : return Rectangle();
1040 : }
1041 :
1042 1335 : bool ToolBox::ImplHasExternalMenubutton()
1043 : {
1044 : // check if the borderwindow (i.e. the decoration) provides the menu button
1045 1335 : bool bRet = false;
1046 1335 : if( ImplIsFloatingMode() )
1047 : {
1048 : // custom menu is placed in the decoration
1049 0 : ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( GetWindowType::Border ) );
1050 0 : if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
1051 0 : bRet = true;
1052 : }
1053 1335 : return bRet;
1054 : }
1055 :
1056 173756 : void ToolBox::SetItemBits( sal_uInt16 nItemId, ToolBoxItemBits nBits )
1057 : {
1058 173756 : sal_uInt16 nPos = GetItemPos( nItemId );
1059 :
1060 173756 : if ( nPos < mpData->m_aItems.size() )
1061 : {
1062 173756 : ToolBoxItemBits nOldBits = mpData->m_aItems[nPos].mnBits;
1063 173756 : mpData->m_aItems[nPos].mnBits = nBits;
1064 173756 : nBits &= ToolBoxItemBits::LEFT | ToolBoxItemBits::AUTOSIZE | ToolBoxItemBits::DROPDOWN;
1065 173756 : nOldBits &= ToolBoxItemBits::LEFT | ToolBoxItemBits::AUTOSIZE | ToolBoxItemBits::DROPDOWN;
1066 : // trigger reformat when the item width has changed (dropdown arrow)
1067 173756 : bool bFormat = ToolBoxItemBits(nBits & ToolBoxItemBits::DROPDOWN) != ToolBoxItemBits(nOldBits & ToolBoxItemBits::DROPDOWN);
1068 173756 : if ( nBits != nOldBits )
1069 6782 : ImplInvalidate( true, bFormat );
1070 : }
1071 173756 : }
1072 :
1073 164813 : ToolBoxItemBits ToolBox::GetItemBits( sal_uInt16 nItemId ) const
1074 : {
1075 164813 : ImplToolItem* pItem = ImplGetItem( nItemId );
1076 :
1077 164813 : if ( pItem )
1078 164813 : return pItem->mnBits;
1079 : else
1080 0 : return ToolBoxItemBits::NONE;
1081 : }
1082 :
1083 19332 : void ToolBox::SetItemExpand( sal_uInt16 nItemId, bool bExpand )
1084 : {
1085 19332 : ImplToolItem* pItem = ImplGetItem( nItemId );
1086 19332 : if (!pItem)
1087 19332 : return;
1088 :
1089 19332 : if (pItem->mbExpand != bExpand)
1090 : {
1091 1586 : pItem->mbExpand = bExpand;
1092 1586 : ImplInvalidate(true, true);
1093 : }
1094 : }
1095 :
1096 55130 : void ToolBox::SetItemData( sal_uInt16 nItemId, void* pNewData )
1097 : {
1098 55130 : sal_uInt16 nPos = GetItemPos( nItemId );
1099 :
1100 55130 : if ( nPos < mpData->m_aItems.size() )
1101 : {
1102 55130 : mpData->m_aItems[nPos].mpUserData = pNewData;
1103 55130 : ImplUpdateItem( nPos );
1104 : }
1105 55130 : }
1106 :
1107 148536 : void* ToolBox::GetItemData( sal_uInt16 nItemId ) const
1108 : {
1109 148536 : ImplToolItem* pItem = ImplGetItem( nItemId );
1110 :
1111 148536 : if ( pItem )
1112 148536 : return pItem->mpUserData;
1113 : else
1114 0 : return NULL;
1115 : }
1116 :
1117 101246 : void ToolBox::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
1118 : {
1119 101246 : sal_uInt16 nPos = GetItemPos( nItemId );
1120 :
1121 101246 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1122 : {
1123 101246 : Image aImage(rImage);
1124 :
1125 101246 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1126 101246 : Size aOldSize = pItem->maImage.GetSizePixel();
1127 :
1128 101246 : pItem->maImageOriginal = aImage;
1129 :
1130 101246 : if (GetDPIScaleFactor() > 1)
1131 : {
1132 0 : BitmapEx aBitmap(aImage.GetBitmapEx());
1133 :
1134 : // Some code calls this twice, so add a sanity check
1135 : // FIXME find out what that code is & fix accordingly
1136 0 : if (aBitmap.GetSizePixel().Width() < 32)
1137 : {
1138 0 : aBitmap.Scale(GetDPIScaleFactor(), GetDPIScaleFactor(), BmpScaleFlag::Fast);
1139 0 : aImage = Image(aBitmap);
1140 0 : }
1141 : }
1142 :
1143 101246 : pItem->maImage = aImage;
1144 :
1145 : // only once all is calculated, do extra work
1146 101246 : if (!mbCalc)
1147 : {
1148 9622 : if (aOldSize != pItem->maImage.GetSizePixel())
1149 696 : ImplInvalidate( true );
1150 : else
1151 8926 : ImplUpdateItem( nPos );
1152 101246 : }
1153 : }
1154 101246 : }
1155 :
1156 1 : void ToolBox::SetImageList( const ImageList& rImageList )
1157 : {
1158 1 : maImageList = rImageList;
1159 :
1160 1 : sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
1161 10 : for( sal_uInt16 i = 0; i < nCount; i++ )
1162 : {
1163 9 : Image aImage;
1164 9 : if ( mpData->m_aItems[i].mnId )
1165 7 : aImage = maImageList.GetImage( mpData->m_aItems[i].mnId );
1166 9 : if( !!aImage )
1167 5 : SetItemImage( mpData->m_aItems[i].mnId, aImage );
1168 9 : }
1169 1 : }
1170 :
1171 0 : static Image ImplRotImage( const Image& rImage, long nAngle10 )
1172 : {
1173 0 : Image aRet;
1174 0 : BitmapEx aRotBitmapEx( rImage.GetBitmapEx() );
1175 :
1176 0 : aRotBitmapEx.Rotate( nAngle10, Color( COL_WHITE ) );
1177 :
1178 0 : return Image( aRotBitmapEx );
1179 : }
1180 :
1181 10473 : void ToolBox::SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 )
1182 : {
1183 10473 : sal_uInt16 nPos = GetItemPos( nItemId );
1184 :
1185 10473 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1186 : {
1187 10473 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1188 10473 : Size aOldSize = pItem->maImage.GetSizePixel();
1189 :
1190 10473 : long nDeltaAngle = (nAngle10 - pItem->mnImageAngle) % 3600;
1191 20946 : while( nDeltaAngle < 0 )
1192 0 : nDeltaAngle += 3600;
1193 :
1194 10473 : pItem->mnImageAngle = nAngle10;
1195 10473 : if( nDeltaAngle && !!pItem->maImage )
1196 : {
1197 0 : pItem->maImage = ImplRotImage( pItem->maImage, nDeltaAngle );
1198 0 : pItem->maImageOriginal = ImplRotImage( pItem->maImageOriginal, nDeltaAngle );
1199 : }
1200 :
1201 10473 : if (!mbCalc)
1202 : {
1203 2915 : if (aOldSize != pItem->maImage.GetSizePixel())
1204 0 : ImplInvalidate(true);
1205 : else
1206 2915 : ImplUpdateItem(nPos);
1207 : }
1208 : }
1209 10473 : }
1210 :
1211 0 : static Image ImplMirrorImage( const Image& rImage )
1212 : {
1213 0 : Image aRet;
1214 0 : BitmapEx aMirrBitmapEx( rImage.GetBitmapEx() );
1215 :
1216 0 : aMirrBitmapEx.Mirror( BmpMirrorFlags::Horizontal );
1217 :
1218 0 : return Image( aMirrBitmapEx );
1219 : }
1220 :
1221 16191 : void ToolBox::SetItemImageMirrorMode( sal_uInt16 nItemId, bool bMirror )
1222 : {
1223 16191 : sal_uInt16 nPos = GetItemPos( nItemId );
1224 :
1225 16191 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1226 : {
1227 16191 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1228 :
1229 32382 : if ((pItem->mbMirrorMode && !bMirror) ||
1230 32382 : (!pItem->mbMirrorMode && bMirror))
1231 : {
1232 0 : pItem->mbMirrorMode = bMirror;
1233 0 : if (!!pItem->maImage)
1234 : {
1235 0 : pItem->maImage = ImplMirrorImage(pItem->maImage);
1236 0 : pItem->maImageOriginal = ImplMirrorImage(pItem->maImageOriginal);
1237 : }
1238 :
1239 0 : if (!mbCalc)
1240 0 : ImplUpdateItem(nPos);
1241 : }
1242 : }
1243 16191 : }
1244 :
1245 0 : Image ToolBox::GetItemImage(sal_uInt16 nItemId) const
1246 : {
1247 0 : ImplToolItem* pItem = ImplGetItem(nItemId);
1248 0 : return pItem ? pItem->maImage : Image();
1249 : }
1250 :
1251 5098 : Image ToolBox::GetItemImageOriginal(sal_uInt16 nItemId) const
1252 : {
1253 5098 : ImplToolItem* pItem = ImplGetItem(nItemId);
1254 5098 : return pItem ? pItem->maImageOriginal : Image();
1255 : }
1256 :
1257 56739 : void ToolBox::SetItemText( sal_uInt16 nItemId, const OUString& rText )
1258 : {
1259 56739 : sal_uInt16 nPos = GetItemPos( nItemId );
1260 :
1261 56739 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1262 : {
1263 56739 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1264 : // only once all is calculated, do extra work
1265 59124 : if ( !mbCalc &&
1266 4764 : ((meButtonType != ButtonType::SYMBOLONLY) || !pItem->maImage) )
1267 : {
1268 3 : long nOldWidth = GetCtrlTextWidth( pItem->maText );
1269 3 : pItem->maText = ImplConvertMenuString( rText );
1270 3 : mpData->ImplClearLayoutData();
1271 3 : if ( nOldWidth != GetCtrlTextWidth( pItem->maText ) )
1272 0 : ImplInvalidate( true );
1273 : else
1274 3 : ImplUpdateItem( nPos );
1275 : }
1276 : else
1277 56736 : pItem->maText = ImplConvertMenuString( rText );
1278 :
1279 : // Notify button changed event to prepare accessibility bridge
1280 56739 : CallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
1281 :
1282 : // Notify
1283 56739 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMTEXTCHANGED, reinterpret_cast< void* >( nPos ) );
1284 : }
1285 56739 : }
1286 :
1287 4428 : const OUString& ToolBox::GetItemText( sal_uInt16 nItemId ) const
1288 : {
1289 :
1290 4428 : ImplToolItem* pItem = ImplGetItem( nItemId );
1291 :
1292 : assert( pItem );
1293 :
1294 4428 : return pItem->maText;
1295 : }
1296 :
1297 106339 : void ToolBox::SetItemWindow( sal_uInt16 nItemId, vcl::Window* pNewWindow )
1298 : {
1299 106339 : sal_uInt16 nPos = GetItemPos( nItemId );
1300 :
1301 106339 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1302 : {
1303 106339 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1304 106339 : pItem->mpWindow = pNewWindow;
1305 106339 : if ( pNewWindow )
1306 5646 : pNewWindow->Hide();
1307 106339 : ImplInvalidate( true );
1308 106339 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED, reinterpret_cast< void* >( nPos ) );
1309 : }
1310 106339 : }
1311 :
1312 35868 : vcl::Window* ToolBox::GetItemWindow( sal_uInt16 nItemId ) const
1313 : {
1314 35868 : ImplToolItem* pItem = ImplGetItem( nItemId );
1315 :
1316 35868 : if ( pItem )
1317 35868 : return pItem->mpWindow;
1318 : else
1319 0 : return NULL;
1320 : }
1321 :
1322 0 : void ToolBox::StartSelection()
1323 : {
1324 0 : if ( mbDrag )
1325 0 : EndSelection();
1326 :
1327 0 : if ( !mbSelection )
1328 : {
1329 0 : mbSelection = true;
1330 0 : mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1331 0 : mnCurItemId = 0;
1332 0 : Activate();
1333 : }
1334 0 : }
1335 :
1336 0 : void ToolBox::EndSelection()
1337 : {
1338 0 : mbCommandDrag = false;
1339 :
1340 0 : if ( mbDrag || mbSelection )
1341 : {
1342 : // reset
1343 0 : mbDrag = false;
1344 0 : mbSelection = false;
1345 0 : if (mnCurPos != TOOLBOX_ITEM_NOTFOUND)
1346 0 : InvalidateItem(mnCurPos);
1347 0 : EndTracking();
1348 0 : ReleaseMouse();
1349 0 : Deactivate();
1350 : }
1351 :
1352 0 : mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1353 0 : mnCurItemId = 0;
1354 0 : mnDownItemId = 0;
1355 0 : mnMouseClicks = 0;
1356 0 : mnMouseModifier = 0;
1357 0 : }
1358 :
1359 0 : void ToolBox::SetItemDown( sal_uInt16 nItemId, bool bDown, bool bRelease )
1360 : {
1361 0 : sal_uInt16 nPos = GetItemPos( nItemId );
1362 :
1363 0 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1364 : {
1365 0 : if ( bDown )
1366 : {
1367 0 : if ( nPos != mnCurPos )
1368 : {
1369 0 : mnCurPos = nPos;
1370 0 : InvalidateItem(mnCurPos);
1371 0 : Flush();
1372 : }
1373 : }
1374 : else
1375 : {
1376 0 : if ( nPos == mnCurPos )
1377 : {
1378 0 : InvalidateItem(mnCurPos);
1379 0 : Flush();
1380 0 : mnCurPos = TOOLBOX_ITEM_NOTFOUND;
1381 : }
1382 : }
1383 :
1384 0 : if ( bRelease )
1385 : {
1386 0 : if ( mbDrag || mbSelection )
1387 : {
1388 0 : mbDrag = false;
1389 0 : mbSelection = false;
1390 0 : EndTracking();
1391 0 : ReleaseMouse();
1392 0 : Deactivate();
1393 : }
1394 :
1395 0 : mnCurItemId = 0;
1396 0 : mnDownItemId = 0;
1397 0 : mnMouseClicks = 0;
1398 0 : mnMouseModifier = 0;
1399 : }
1400 : }
1401 0 : }
1402 :
1403 232307 : void ToolBox::SetItemState( sal_uInt16 nItemId, TriState eState )
1404 : {
1405 232307 : sal_uInt16 nPos = GetItemPos( nItemId );
1406 :
1407 232307 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1408 : {
1409 232307 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1410 :
1411 : // the state has changed
1412 232307 : if ( pItem->meState != eState )
1413 : {
1414 : // if RadioCheck, un-check the previous
1415 6806 : if ( (eState == TRISTATE_TRUE) && (pItem->mnBits & ToolBoxItemBits::AUTOCHECK) &&
1416 3403 : (pItem->mnBits & ToolBoxItemBits::RADIOCHECK) )
1417 : {
1418 : ImplToolItem* pGroupItem;
1419 : sal_uInt16 nGroupPos;
1420 0 : sal_uInt16 nItemCount = GetItemCount();
1421 :
1422 0 : nGroupPos = nPos;
1423 0 : while ( nGroupPos )
1424 : {
1425 0 : pGroupItem = &mpData->m_aItems[nGroupPos-1];
1426 0 : if ( pGroupItem->mnBits & ToolBoxItemBits::RADIOCHECK )
1427 : {
1428 0 : if ( pGroupItem->meState != TRISTATE_FALSE )
1429 0 : SetItemState( pGroupItem->mnId, TRISTATE_FALSE );
1430 : }
1431 : else
1432 0 : break;
1433 0 : nGroupPos--;
1434 : }
1435 :
1436 0 : nGroupPos = nPos+1;
1437 0 : while ( nGroupPos < nItemCount )
1438 : {
1439 0 : pGroupItem = &mpData->m_aItems[nGroupPos];
1440 0 : if ( pGroupItem->mnBits & ToolBoxItemBits::RADIOCHECK )
1441 : {
1442 0 : if ( pGroupItem->meState != TRISTATE_FALSE )
1443 0 : SetItemState( pGroupItem->mnId, TRISTATE_FALSE );
1444 : }
1445 : else
1446 0 : break;
1447 0 : nGroupPos++;
1448 : }
1449 : }
1450 :
1451 3403 : pItem->meState = eState;
1452 3403 : ImplUpdateItem( nPos );
1453 :
1454 : // Notify button changed event to prepare accessibility bridge
1455 3403 : CallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
1456 :
1457 : // Call accessible listener to notify state_changed event
1458 3403 : CallEventListeners( VCLEVENT_TOOLBOX_ITEMUPDATED, reinterpret_cast< void* >(nPos) );
1459 : }
1460 : }
1461 232307 : }
1462 :
1463 3685 : TriState ToolBox::GetItemState( sal_uInt16 nItemId ) const
1464 : {
1465 3685 : ImplToolItem* pItem = ImplGetItem( nItemId );
1466 :
1467 3685 : if ( pItem )
1468 3216 : return pItem->meState;
1469 : else
1470 469 : return TRISTATE_FALSE;
1471 : }
1472 :
1473 235263 : void ToolBox::EnableItem( sal_uInt16 nItemId, bool bEnable )
1474 : {
1475 235263 : sal_uInt16 nPos = GetItemPos( nItemId );
1476 :
1477 235263 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1478 : {
1479 235263 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1480 235263 : if ( bEnable )
1481 180918 : bEnable = true;
1482 235263 : if ( pItem->mbEnabled != bEnable )
1483 : {
1484 41326 : pItem->mbEnabled = bEnable;
1485 :
1486 : // if existing, also redraw the window
1487 41326 : if ( pItem->mpWindow )
1488 2142 : pItem->mpWindow->Enable( pItem->mbEnabled );
1489 :
1490 : // update item
1491 41326 : ImplUpdateItem( nPos );
1492 :
1493 41326 : ImplUpdateInputEnable();
1494 :
1495 : // Notify button changed event to prepare accessibility bridge
1496 41326 : CallEventListeners( VCLEVENT_TOOLBOX_BUTTONSTATECHANGED, reinterpret_cast< void* >( nPos ) );
1497 :
1498 41326 : CallEventListeners( bEnable ? VCLEVENT_TOOLBOX_ITEMENABLED : VCLEVENT_TOOLBOX_ITEMDISABLED, reinterpret_cast< void* >( nPos ) );
1499 : }
1500 : }
1501 235263 : }
1502 :
1503 402 : bool ToolBox::IsItemEnabled( sal_uInt16 nItemId ) const
1504 : {
1505 402 : ImplToolItem* pItem = ImplGetItem( nItemId );
1506 :
1507 402 : if ( pItem )
1508 402 : return pItem->mbEnabled;
1509 : else
1510 0 : return false;
1511 : }
1512 :
1513 25588 : void ToolBox::ShowItem( sal_uInt16 nItemId, bool bVisible )
1514 : {
1515 25588 : sal_uInt16 nPos = GetItemPos( nItemId );
1516 25588 : mpData->ImplClearLayoutData();
1517 :
1518 25588 : if ( nPos != TOOLBOX_ITEM_NOTFOUND )
1519 : {
1520 25580 : ImplToolItem* pItem = &mpData->m_aItems[nPos];
1521 25580 : if ( pItem->mbVisible != bVisible )
1522 : {
1523 25165 : pItem->mbVisible = bVisible;
1524 25165 : ImplInvalidate( false );
1525 : }
1526 : }
1527 25588 : }
1528 :
1529 991 : bool ToolBox::IsItemVisible( sal_uInt16 nItemId ) const
1530 : {
1531 991 : ImplToolItem* pItem = ImplGetItem( nItemId );
1532 :
1533 991 : if ( pItem )
1534 983 : return pItem->mbVisible;
1535 : else
1536 8 : return false;
1537 : }
1538 :
1539 394 : bool ToolBox::IsItemReallyVisible( sal_uInt16 nItemId ) const
1540 : {
1541 : // is the item on the visible area of the toolbox?
1542 394 : bool bRet = false;
1543 394 : Rectangle aRect( mnLeftBorder, mnTopBorder, mnDX-mnRightBorder, mnDY-mnBottomBorder );
1544 394 : ImplToolItem* pItem = ImplGetItem( nItemId );
1545 :
1546 1078 : if ( pItem && pItem->mbVisible &&
1547 944 : !pItem->maRect.IsEmpty() && aRect.IsOver( pItem->maRect ) )
1548 : {
1549 260 : bRet = true;
1550 : }
1551 :
1552 394 : return bRet;
1553 : }
1554 :
1555 100647 : void ToolBox::SetItemCommand(sal_uInt16 nItemId, const OUString& rCommand)
1556 : {
1557 100647 : ImplToolItem* pItem = ImplGetItem( nItemId );
1558 :
1559 100647 : if (pItem)
1560 100647 : pItem->maCommandStr = rCommand;
1561 100647 : }
1562 :
1563 157073 : const OUString ToolBox::GetItemCommand( sal_uInt16 nItemId ) const
1564 : {
1565 157073 : ImplToolItem* pItem = ImplGetItem( nItemId );
1566 :
1567 157073 : if (pItem)
1568 157073 : return pItem->maCommandStr;
1569 :
1570 0 : return OUString();
1571 : }
1572 :
1573 86356 : void ToolBox::SetQuickHelpText( sal_uInt16 nItemId, const OUString& rText )
1574 : {
1575 86356 : ImplToolItem* pItem = ImplGetItem( nItemId );
1576 :
1577 86356 : if ( pItem )
1578 86356 : pItem->maQuickHelpText = rText;
1579 86356 : }
1580 :
1581 5 : const OUString& ToolBox::GetQuickHelpText( sal_uInt16 nItemId ) const
1582 : {
1583 5 : static const OUString sEmpty;
1584 :
1585 5 : ImplToolItem* pItem = ImplGetItem( nItemId );
1586 :
1587 5 : if ( pItem )
1588 5 : return pItem->maQuickHelpText;
1589 : else
1590 0 : return sEmpty;
1591 : }
1592 :
1593 978 : void ToolBox::SetHelpText( sal_uInt16 nItemId, const OUString& rText )
1594 : {
1595 978 : ImplToolItem* pItem = ImplGetItem( nItemId );
1596 :
1597 978 : if ( pItem )
1598 978 : pItem->maHelpText = rText;
1599 978 : }
1600 :
1601 0 : const OUString& ToolBox::GetHelpText( sal_uInt16 nItemId ) const
1602 : {
1603 0 : return ImplGetHelpText( nItemId );
1604 : }
1605 :
1606 1022 : void ToolBox::SetHelpId( sal_uInt16 nItemId, const OString& rHelpId )
1607 : {
1608 1022 : ImplToolItem* pItem = ImplGetItem( nItemId );
1609 :
1610 1022 : if ( pItem )
1611 1022 : pItem->maHelpId = rHelpId;
1612 1022 : }
1613 :
1614 0 : OString ToolBox::GetHelpId( sal_uInt16 nItemId ) const
1615 : {
1616 0 : OString aRet;
1617 :
1618 0 : ImplToolItem* pItem = ImplGetItem( nItemId );
1619 :
1620 0 : if ( pItem )
1621 : {
1622 0 : if ( !pItem->maHelpId.isEmpty() )
1623 0 : aRet = pItem->maHelpId;
1624 : else
1625 0 : aRet = OUStringToOString( pItem->maCommandStr, RTL_TEXTENCODING_UTF8 );
1626 : }
1627 :
1628 0 : return aRet;
1629 : }
1630 :
1631 17631 : void ToolBox::SetOutStyle( sal_uInt16 nNewStyle )
1632 : {
1633 : // always force flat looking toolbars since NWF
1634 17631 : nNewStyle |= TOOLBOX_STYLE_FLAT;
1635 :
1636 17631 : if ( mnOutStyle != nNewStyle )
1637 : {
1638 0 : mnOutStyle = nNewStyle;
1639 0 : ImplDisableFlatButtons();
1640 :
1641 : // so as to redo the ButtonDevice
1642 0 : if ( !(mnOutStyle & TOOLBOX_STYLE_FLAT) )
1643 : {
1644 0 : mnMaxItemWidth = 1;
1645 0 : mnMaxItemHeight = 1;
1646 : }
1647 :
1648 0 : ImplInvalidate( true, true );
1649 : }
1650 17631 : }
1651 :
1652 : // disable key input if all items are disabled
1653 325479 : void ToolBox::ImplUpdateInputEnable()
1654 : {
1655 2447685 : for( std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
1656 1631790 : it != mpData->m_aItems.end(); ++it )
1657 : {
1658 760892 : if( it->mbEnabled )
1659 : {
1660 : // at least one useful entry
1661 270476 : mpData->mbKeyInputDisabled = false;
1662 595955 : return;
1663 : }
1664 : }
1665 55003 : mpData->mbKeyInputDisabled = true;
1666 : }
1667 :
1668 0 : void ToolBox::ImplFillLayoutData() const
1669 : {
1670 0 : mpData->m_pLayoutData = new ToolBoxLayoutData();
1671 :
1672 0 : sal_uInt16 nCount = (sal_uInt16)mpData->m_aItems.size();
1673 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
1674 : {
1675 0 : ImplToolItem* pItem = &mpData->m_aItems[i];
1676 :
1677 : // only draw, if the rectangle is within PaintRectangle
1678 0 : if (!pItem->maRect.IsEmpty())
1679 0 : const_cast<ToolBox*>(this)->InvalidateItem(i);
1680 : }
1681 0 : }
1682 :
1683 0 : OUString ToolBox::GetDisplayText() const
1684 : {
1685 0 : if( ! mpData->m_pLayoutData )
1686 0 : ImplFillLayoutData();
1687 0 : return mpData->m_pLayoutData ? OUString(mpData->m_pLayoutData->m_aDisplayText) : OUString();
1688 : }
1689 :
1690 0 : Rectangle ToolBox::GetCharacterBounds( sal_uInt16 nItemID, long nIndex ) const
1691 : {
1692 0 : long nItemIndex = -1;
1693 0 : if( ! mpData->m_pLayoutData )
1694 0 : ImplFillLayoutData();
1695 0 : if( mpData->m_pLayoutData )
1696 : {
1697 0 : for( sal_uLong i = 0; i < mpData->m_pLayoutData->m_aLineItemIds.size(); i++ )
1698 : {
1699 0 : if( mpData->m_pLayoutData->m_aLineItemIds[i] == nItemID )
1700 : {
1701 0 : nItemIndex = mpData->m_pLayoutData->m_aLineIndices[i];
1702 0 : break;
1703 : }
1704 : }
1705 : }
1706 0 : return (mpData->m_pLayoutData && nItemIndex != -1) ? mpData->m_pLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
1707 : }
1708 :
1709 0 : long ToolBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const
1710 : {
1711 0 : long nIndex = -1;
1712 0 : rItemID = 0;
1713 0 : if( ! mpData->m_pLayoutData )
1714 0 : ImplFillLayoutData();
1715 0 : if( mpData->m_pLayoutData )
1716 : {
1717 0 : nIndex = mpData->m_pLayoutData->GetIndexForPoint( rPoint );
1718 0 : for( sal_uLong i = 0; i < mpData->m_pLayoutData->m_aLineIndices.size(); i++ )
1719 : {
1720 0 : if( mpData->m_pLayoutData->m_aLineIndices[i] <= nIndex &&
1721 0 : (i == mpData->m_pLayoutData->m_aLineIndices.size()-1 || mpData->m_pLayoutData->m_aLineIndices[i+1] > nIndex) )
1722 : {
1723 0 : rItemID = mpData->m_pLayoutData->m_aLineItemIds[i];
1724 0 : break;
1725 : }
1726 : }
1727 : }
1728 0 : return nIndex;
1729 : }
1730 :
1731 41051 : void ToolBox::SetDropdownClickHdl( const Link<ToolBox *, void>& rLink )
1732 : {
1733 41051 : mpData->maDropdownClickHdl = rLink;
1734 41051 : }
1735 :
1736 24542 : void ToolBox::SetMenuType( sal_uInt16 aType )
1737 : {
1738 24542 : if( aType != mpData->maMenuType )
1739 : {
1740 17778 : mpData->maMenuType = aType;
1741 17778 : if( IsFloatingMode() )
1742 : {
1743 : // the menu button may have to be moved into the decoration which changes the layout
1744 0 : ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1745 0 : if( pWrapper )
1746 0 : pWrapper->ShowTitleButton( TitleButton::Menu, ( aType & TOOLBOX_MENUTYPE_CUSTOMIZE) != 0 );
1747 :
1748 0 : mbFormat = true;
1749 0 : ImplFormat();
1750 0 : ImplSetMinMaxFloatSize( this );
1751 : }
1752 : else
1753 : {
1754 : // trigger redraw of menu button
1755 17778 : if( !mpData->maMenubuttonItem.maRect.IsEmpty() )
1756 0 : Invalidate(mpData->maMenubuttonItem.maRect);
1757 : }
1758 : }
1759 24542 : }
1760 :
1761 9504 : sal_uInt16 ToolBox::GetMenuType() const
1762 : {
1763 9504 : return mpData->maMenuType;
1764 : }
1765 :
1766 533939 : bool ToolBox::IsMenuEnabled() const
1767 : {
1768 533939 : return mpData->maMenuType != TOOLBOX_MENUTYPE_NONE;
1769 : }
1770 :
1771 9509 : PopupMenu* ToolBox::GetMenu() const
1772 : {
1773 9509 : return mpData->mpMenu;
1774 : }
1775 :
1776 9522 : void ToolBox::SetMenuButtonHdl( const Link<ToolBox *, void>& rLink )
1777 : {
1778 9522 : mpData->maMenuButtonHdl = rLink;
1779 9522 : }
1780 :
1781 6311 : bool ToolBox::ImplHasClippedItems()
1782 : {
1783 : // are any items currently clipped ?
1784 6311 : ImplFormat();
1785 6311 : std::vector< ImplToolItem >::const_iterator it = mpData->m_aItems.begin();
1786 279036 : while ( it != mpData->m_aItems.end() )
1787 : {
1788 272264 : if( it->IsClipped() )
1789 5850 : return true;
1790 266414 : ++it;
1791 : }
1792 461 : return false;
1793 : }
1794 :
1795 0 : void ToolBox::UpdateCustomMenu()
1796 : {
1797 : // fill clipped items into menu
1798 0 : if( !IsMenuEnabled() )
1799 0 : return;
1800 :
1801 0 : PopupMenu *pMenu = GetMenu();
1802 :
1803 0 : sal_uInt16 i = 0;
1804 : // remove old entries
1805 0 : while( i < pMenu->GetItemCount() )
1806 : {
1807 0 : if( pMenu->GetItemId( i ) >= TOOLBOX_MENUITEM_START )
1808 : {
1809 0 : pMenu->RemoveItem( i );
1810 0 : i = 0;
1811 : }
1812 : else
1813 0 : i++;
1814 : }
1815 :
1816 : // add menu items: first the overflow items, then hidden items, both in the
1817 : // order they would usually appear in the toolbar. Separators that would be
1818 : // in the toolbar are ignored as they would introduce too much clutter,
1819 : // instead we have a single separator to help distinguish between overflow
1820 : // and hidden items.
1821 0 : if ( !mpData->m_aItems.empty() )
1822 : {
1823 : // nStartPos will hold the number of clipped items appended from first loop
1824 0 : for ( std::vector< ImplToolItem >::iterator it(mpData->m_aItems.begin());
1825 0 : it != mpData->m_aItems.end(); ++it)
1826 : {
1827 0 : if( it->IsClipped() )
1828 : {
1829 0 : sal_uInt16 id = it->mnId + TOOLBOX_MENUITEM_START;
1830 0 : pMenu->InsertItem( id, it->maText, it->maImageOriginal, MenuItemBits::NONE, OString());
1831 0 : pMenu->EnableItem( id, it->mbEnabled );
1832 0 : pMenu->CheckItem ( id, it->meState == TRISTATE_TRUE );
1833 : }
1834 : }
1835 :
1836 : // add a separator below the inserted clipped-items
1837 0 : pMenu->InsertSeparator();
1838 :
1839 : // now append the items that are explicitly disabled
1840 0 : for ( std::vector< ImplToolItem >::iterator it(mpData->m_aItems.begin());
1841 0 : it != mpData->m_aItems.end(); ++it)
1842 : {
1843 0 : if( it->IsItemHidden() )
1844 : {
1845 0 : sal_uInt16 id = it->mnId + TOOLBOX_MENUITEM_START;
1846 0 : pMenu->InsertItem( id, it->maText, it->maImageOriginal, MenuItemBits::NONE, OString() );
1847 0 : pMenu->EnableItem( id, it->mbEnabled );
1848 0 : pMenu->CheckItem( id, it->meState == TRISTATE_TRUE );
1849 : }
1850 : }
1851 :
1852 : }
1853 : }
1854 :
1855 0 : IMPL_LINK( ToolBox, ImplCustomMenuListener, VclMenuEvent*, pEvent )
1856 : {
1857 0 : if( pEvent->GetMenu() == GetMenu() && pEvent->GetId() == VCLEVENT_MENU_SELECT )
1858 : {
1859 0 : sal_uInt16 id = GetMenu()->GetItemId( pEvent->GetItemPos() );
1860 0 : if( id >= TOOLBOX_MENUITEM_START )
1861 0 : TriggerItem( id - TOOLBOX_MENUITEM_START, false, false );
1862 : }
1863 0 : return 0;
1864 : }
1865 :
1866 0 : IMPL_LINK_NOARG(ToolBox, ImplCallExecuteCustomMenu)
1867 : {
1868 0 : mpData->mnEventId = 0;
1869 0 : ImplExecuteCustomMenu();
1870 0 : return 0;
1871 : }
1872 :
1873 0 : void ToolBox::ImplExecuteCustomMenu()
1874 : {
1875 0 : if( IsMenuEnabled() )
1876 : {
1877 0 : if( GetMenuType() & TOOLBOX_MENUTYPE_CUSTOMIZE )
1878 : // call button handler to allow for menu customization
1879 0 : mpData->maMenuButtonHdl.Call( this );
1880 :
1881 : // We specifically only register this event listener when executing our
1882 : // overflow menu (and remove it directly afterwards), as the same menu
1883 : // is reused for both the overflow menu (as managed here in ToolBox),
1884 : // but also by ToolBarManager for its context menu. If we leave event
1885 : // listeners alive beyond when the menu is showing in the desired mode
1886 : // then duplicate events can happen as the context menu "duplicates"
1887 : // items from the overflow menu, which both listeners would then act on.
1888 0 : GetMenu()->AddEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
1889 :
1890 : // make sure all disabled entries will be shown
1891 0 : GetMenu()->SetMenuFlags(
1892 0 : GetMenu()->GetMenuFlags() | MenuFlags::AlwaysShowDisabledEntries );
1893 :
1894 : // toolbox might be destroyed during execute
1895 0 : ImplDelData aDelData;
1896 0 : ImplAddDel( &aDelData );
1897 0 : ImplDelData aBorderDel;
1898 0 : bool bBorderDel = false;
1899 :
1900 0 : vcl::Window *pWin = this;
1901 0 : Rectangle aMenuRect = mpData->maMenubuttonItem.maRect;
1902 0 : if( IsFloatingMode() )
1903 : {
1904 : // custom menu is placed in the decoration
1905 0 : ImplBorderWindow *pBorderWin = dynamic_cast<ImplBorderWindow*>( GetWindow( GetWindowType::Border ) );
1906 0 : if( pBorderWin && !pBorderWin->GetMenuRect().IsEmpty() )
1907 : {
1908 0 : pWin = pBorderWin;
1909 0 : aMenuRect = pBorderWin->GetMenuRect();
1910 0 : pWin->ImplAddDel( &aBorderDel );
1911 0 : bBorderDel = true;
1912 : }
1913 : }
1914 :
1915 0 : sal_uInt16 uId = GetMenu()->Execute( pWin, Rectangle( ImplGetPopupPosition( aMenuRect, Size() ), Size() ),
1916 0 : PopupMenuFlags::ExecuteDown | PopupMenuFlags::NoMouseUpClose );
1917 :
1918 0 : if ( aDelData.IsDead() )
1919 0 : return;
1920 0 : ImplRemoveDel( &aDelData );
1921 :
1922 0 : if( GetMenu() )
1923 0 : GetMenu()->RemoveEventListener( LINK( this, ToolBox, ImplCustomMenuListener ) );
1924 0 : if( bBorderDel )
1925 : {
1926 0 : if( aBorderDel.IsDead() )
1927 0 : return;
1928 0 : pWin->ImplRemoveDel( &aBorderDel );
1929 : }
1930 :
1931 0 : pWin->Invalidate( aMenuRect );
1932 :
1933 0 : if( uId )
1934 0 : GrabFocusToDocument();
1935 : }
1936 : }
1937 :
1938 0 : void ToolBox::ExecuteCustomMenu()
1939 : {
1940 0 : if( IsMenuEnabled() )
1941 : {
1942 : // handle custom menu asynchronously
1943 : // to avoid problems if the toolbox is closed during menu execute
1944 0 : UpdateCustomMenu();
1945 0 : mpData->mnEventId = Application::PostUserEvent( LINK( this, ToolBox, ImplCallExecuteCustomMenu ), NULL, true );
1946 : }
1947 0 : }
1948 :
1949 : // checks override first, useful during calculation of sizes
1950 1056259 : bool ToolBox::ImplIsFloatingMode() const
1951 : {
1952 : DBG_ASSERT( !(mpData->mbAssumeDocked && mpData->mbAssumeFloating),
1953 : "ToolBox::ImplIsFloatingMode(): cannot assume docked and floating" );
1954 :
1955 1056259 : if( mpData->mbAssumeDocked )
1956 0 : return false;
1957 1056259 : else if( mpData->mbAssumeFloating )
1958 0 : return true;
1959 : else
1960 1056259 : return IsFloatingMode();
1961 : }
1962 :
1963 : // checks override first, useful during calculation of sizes
1964 108591 : bool ToolBox::ImplIsInPopupMode() const
1965 : {
1966 108591 : if( mpData->mbAssumePopupMode )
1967 0 : return true;
1968 : else
1969 : {
1970 108591 : ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1971 108591 : return ( pWrapper && pWrapper->GetFloatingWindow() && pWrapper->GetFloatingWindow()->IsInPopupMode() );
1972 : }
1973 : }
1974 :
1975 0 : void ToolBox::Lock( bool bLock )
1976 : {
1977 0 : ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1978 0 : if( !pWrapper )
1979 0 : return;
1980 0 : if( mpData->mbIsLocked != bLock )
1981 : {
1982 0 : mpData->mbIsLocked = bLock;
1983 0 : if( !ImplIsFloatingMode() )
1984 : {
1985 0 : mbCalc = true;
1986 0 : mbFormat = true;
1987 0 : SetSizePixel( CalcWindowSizePixel(1) );
1988 0 : Invalidate();
1989 : }
1990 : }
1991 : }
1992 :
1993 0 : bool ToolBox::AlwaysLocked()
1994 : {
1995 : // read config item to determine toolbox behaviour, used for subtoolbars
1996 :
1997 : static int nAlwaysLocked = -1;
1998 :
1999 0 : if( nAlwaysLocked == -1 )
2000 : {
2001 0 : nAlwaysLocked = 0; // ask configuration only once
2002 :
2003 : utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithComponentContext(
2004 : comphelper::getProcessComponentContext(),
2005 0 : OUString("/org.openoffice.Office.UI.GlobalSettings/Toolbars") ); // note: case sensitive !
2006 0 : if ( aNode.isValid() )
2007 : {
2008 : // feature enabled ?
2009 0 : bool bStatesEnabled = bool();
2010 0 : ::com::sun::star::uno::Any aValue = aNode.getNodeValue( OUString("StatesEnabled") );
2011 0 : if( aValue >>= bStatesEnabled )
2012 : {
2013 0 : if( bStatesEnabled )
2014 : {
2015 : // now read the locking state
2016 : utl::OConfigurationNode aNode2 = utl::OConfigurationTreeRoot::tryCreateWithComponentContext(
2017 : comphelper::getProcessComponentContext(),
2018 0 : OUString("/org.openoffice.Office.UI.GlobalSettings/Toolbars/States") ); // note: case sensitive !
2019 :
2020 0 : bool bLocked = bool();
2021 0 : ::com::sun::star::uno::Any aValue2 = aNode2.getNodeValue( OUString("Locked") );
2022 0 : if( aValue2 >>= bLocked )
2023 0 : nAlwaysLocked = bLocked ? 1 : 0;
2024 : }
2025 0 : }
2026 0 : }
2027 : }
2028 :
2029 0 : return nAlwaysLocked == 1;
2030 : }
2031 :
2032 1236 : bool ToolBox::WillUsePopupMode() const
2033 : {
2034 1236 : return mpData->mbWillUsePopupMode;
2035 : }
2036 :
2037 6764 : void ToolBox::WillUsePopupMode( bool b )
2038 : {
2039 6764 : mpData->mbWillUsePopupMode = b;
2040 6764 : }
2041 :
2042 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|