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