xref: /AOO41X/main/svtools/source/control/toolbarmenu.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb) !
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_svtools.hxx"
31 
32 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 #include <comphelper/processfactory.hxx>
35 
36 #include <vcl/dockwin.hxx>
37 #include <vcl/decoview.hxx>
38 #include <vcl/image.hxx>
39 #include <vcl/taskpanelist.hxx>
40 #include <vcl/toolbox.hxx>
41 
42 #include "svtools/valueset.hxx"
43 #include "svtools/toolbarmenu.hxx"
44 #include "toolbarmenuimp.hxx"
45 
46 using ::rtl::OUString;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::frame;
50 using namespace ::com::sun::star::accessibility;
51 
52 namespace svtools {
53 
54 // --------------------------------------------------------------------
55 
56 static Window* GetTopMostParentSystemWindow( Window* pWindow )
57 {
58     OSL_ASSERT( pWindow );
59     if ( pWindow )
60     {
61         // ->manually search topmost system window
62         // required because their might be another system window between this and the top window
63         pWindow = pWindow->GetParent();
64         SystemWindow* pTopMostSysWin = NULL;
65         while ( pWindow )
66         {
67             if ( pWindow->IsSystemWindow() )
68                 pTopMostSysWin = (SystemWindow*)pWindow;
69             pWindow = pWindow->GetParent();
70         }
71         pWindow = pTopMostSysWin;
72         OSL_ASSERT( pWindow );
73         return pWindow;
74     }
75 
76     return NULL;
77 }
78 
79 // --------------------------------------------------------------------
80 
81 void ToolbarMenuEntry::init( int nEntryId, MenuItemBits nBits )
82 {
83 	mnEntryId = nEntryId;
84 	mnBits = nBits;
85 
86 	mbHasText = false;
87 	mbHasImage = false;
88 	mbChecked = false;
89 	mbEnabled = true;
90 
91 	mpControl = NULL;
92 }
93 
94 // --------------------------------------------------------------------
95 
96 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits )
97 : mrMenu( rMenu )
98 {
99 	init( nEntryId, nBits );
100 
101 	maText = rText;
102 	mbHasText = true;
103 }
104 
105 // --------------------------------------------------------------------
106 
107 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits )
108 : mrMenu( rMenu )
109 {
110 	init( nEntryId, nBits );
111 
112 	maImage = rImage;
113 	mbHasImage = true;
114 }
115 
116 // --------------------------------------------------------------------
117 
118 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits )
119 : mrMenu( rMenu )
120 {
121 	init( nEntryId, nBits );
122 
123 	maText = rText;
124 	mbHasText = true;
125 
126 	maImage = rImage;
127 	mbHasImage = true;
128 }
129 
130 // --------------------------------------------------------------------
131 
132 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits )
133 : mrMenu( rMenu )
134 {
135 	init( nEntryId, nBits );
136 
137 	if( pControl )
138 	{
139 		mpControl = pControl;
140 		mpControl->Show();
141 	}
142 }
143 
144 // --------------------------------------------------------------------
145 
146 ToolbarMenuEntry::~ToolbarMenuEntry()
147 {
148 	if( mxAccContext.is() )
149 	{
150 		Reference< XComponent > xComponent( mxAccContext, UNO_QUERY );
151 		if( xComponent.is() )
152 			xComponent->dispose();
153 		mxAccContext.clear();
154 	}
155 	delete mpControl;
156 }
157 
158 // --------------------------------------------------------------------
159 
160 const Reference< XAccessibleContext >& ToolbarMenuEntry::GetAccessible( bool bCreate /* = false */ )
161 {
162 	if( !mxAccContext.is() && bCreate )
163 	{
164 		if( mpControl )
165 		{
166 			mxAccContext = Reference< XAccessibleContext >( mpControl->GetAccessible( sal_True ), UNO_QUERY );
167 		}
168 		else
169 		{
170 			mxAccContext = Reference< XAccessibleContext >( new ToolbarMenuEntryAcc( this ) );
171 		}
172 	}
173 
174 	return mxAccContext;
175 }
176 
177 // --------------------------------------------------------------------
178 
179 sal_Int32 ToolbarMenuEntry::getAccessibleChildCount() throw (RuntimeException)
180 {
181 	if( mpControl )
182 	{
183 		const Reference< XAccessibleContext >& xContext = GetAccessible( true );
184 		if( xContext.is() )
185 		{
186 			return xContext->getAccessibleChildCount();
187 		}
188 	}
189 	return 1;
190 }
191 
192 // --------------------------------------------------------------------
193 
194 Reference< XAccessible > ToolbarMenuEntry::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException)
195 {
196 	const Reference< XAccessibleContext >& xContext = GetAccessible( true );
197 	if( mpControl )
198 	{
199 		if( xContext.is() )
200 		{
201 			return xContext->getAccessibleChild(index);
202 		}
203 	}
204 	else if( index == 0 )
205 	{
206 		Reference< XAccessible > xRet( xContext, UNO_QUERY );
207 		if( xRet.is() )
208 			return xRet;
209 	}
210 
211 	throw IndexOutOfBoundsException();
212 }
213 
214 // --------------------------------------------------------------------
215 
216 ToolbarMenu_Impl::ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame )
217 : mrMenu( rMenu )
218 , mxFrame( xFrame )
219 , mxServiceManager( ::comphelper::getProcessServiceFactory() )
220 , mnCheckPos(0)
221 , mnImagePos(0)
222 , mnTextPos(0)
223 , mnHighlightedEntry(-1)
224 , mnSelectedEntry(-1)
225 , mnLastColumn(0)
226 {
227 }
228 
229 // --------------------------------------------------------------------
230 
231 ToolbarMenu_Impl::~ToolbarMenu_Impl()
232 {
233 	setAccessible( 0 );
234 }
235 
236 // --------------------------------------------------------------------
237 
238 void ToolbarMenu_Impl::setAccessible( ToolbarMenuAcc* pAccessible )
239 {
240 	if( mxAccessible.get() != pAccessible )
241 	{
242 		if( mxAccessible.is() )
243 			mxAccessible->dispose();
244 
245 		mxAccessible.set( pAccessible );
246 	}
247 }
248 
249 // -----------------------------------------------------------------------
250 
251 void ToolbarMenu_Impl::fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue )
252 {
253     if( mxAccessible.is() )
254         mxAccessible->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
255 }
256 
257 // -----------------------------------------------------------------------
258 
259 bool ToolbarMenu_Impl::hasAccessibleListeners()
260 {
261     return( mxAccessible.is() && mxAccessible->HasAccessibleListeners() );
262 }
263 
264 // --------------------------------------------------------------------
265 
266 sal_Int32 ToolbarMenu_Impl::getAccessibleChildCount() throw (RuntimeException)
267 {
268 	sal_Int32 nCount = 0;
269 	const int nEntryCount = maEntryVector.size();
270 	for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
271 	{
272 		ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
273 		if( pEntry )
274 		{
275 			if( pEntry->mpControl )
276 			{
277 				nCount += pEntry->getAccessibleChildCount();
278 			}
279 			else
280 			{
281 				nCount += 1;
282 			}
283 		}
284 	}
285 
286 	return nCount;
287 }
288 
289 // --------------------------------------------------------------------
290 
291 Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException)
292 {
293 	const int nEntryCount = maEntryVector.size();
294 	for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
295 	{
296 		ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
297 		if( pEntry )
298 		{
299 			const sal_Int32 nCount = pEntry->getAccessibleChildCount();
300 			if( index < nCount )
301 			{
302 				return pEntry->getAccessibleChild( index );
303 			}
304 			index -= nCount;
305 		}
306 	}
307 
308 	throw IndexOutOfBoundsException();
309 }
310 
311 // --------------------------------------------------------------------
312 
313 Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (IndexOutOfBoundsException, RuntimeException)
314 {
315 	const int nEntryCount = maEntryVector.size();
316 	for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
317 	{
318 		ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
319 		if( pEntry && (pEntry->mpControl == pControl) )
320 		{
321 			return pEntry->getAccessibleChild( childIndex );
322 		}
323 	}
324 
325 	throw IndexOutOfBoundsException();
326 }
327 
328 // --------------------------------------------------------------------
329 
330 void ToolbarMenu_Impl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
331 {
332 	const int nEntryCount = maEntryVector.size();
333 	for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
334 	{
335 		ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
336 		if( pEntry )
337 		{
338 			const sal_Int32 nCount = pEntry->getAccessibleChildCount();
339 			if( nChildIndex < nCount )
340 			{
341 				if( pEntry->mpControl )
342 				{
343 					Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW );
344 					xSel->selectAccessibleChild(nChildIndex);
345 				}
346 				else if( pEntry->mnEntryId != TITLE_ID )
347 				{
348 					mrMenu.implSelectEntry( nEntry );
349 				}
350 				return;
351 			}
352 			nChildIndex -= nCount;
353 		}
354 	}
355 
356 	throw IndexOutOfBoundsException();
357 }
358 
359 // --------------------------------------------------------------------
360 
361 sal_Bool ToolbarMenu_Impl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
362 {
363 	const int nEntryCount = maEntryVector.size();
364 	for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
365 	{
366 		ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
367 		if( pEntry )
368 		{
369 			const sal_Int32 nCount = pEntry->getAccessibleChildCount();
370 			if( nChildIndex < nCount )
371 			{
372 				if( mnHighlightedEntry == nEntry )
373 				{
374 					if( pEntry->mpControl )
375 					{
376 						Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW );
377 						xSel->isAccessibleChildSelected(nChildIndex);
378 					}
379 					return true;
380 				}
381 				else
382 				{
383 					return false;
384 				}
385 			}
386 			nChildIndex -= nCount;
387 		}
388 	}
389 
390 	throw IndexOutOfBoundsException();
391 }
392 
393 // --------------------------------------------------------------------
394 
395 void ToolbarMenu_Impl::clearAccessibleSelection()
396 {
397 	if( mnHighlightedEntry != -1 )
398 	{
399 		mrMenu.implHighlightEntry( mnHighlightedEntry, false );
400 		mnHighlightedEntry = -1;
401 	}
402 }
403 
404 
405 // --------------------------------------------------------------------
406 
407 void ToolbarMenu_Impl::notifyHighlightedEntry()
408 {
409 	if( hasAccessibleListeners() )
410 	{
411 		ToolbarMenuEntry* pEntry = implGetEntry( mnHighlightedEntry );
412 		if( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) )
413 		{
414 			Any aNew;
415 			Any aOld( mxOldSelection );
416 			if( pEntry->mpControl )
417 			{
418 				sal_Int32 nChildIndex = 0;
419 				// todo: if other controls than ValueSet are allowed, addapt this code
420 				ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl );
421 				if( pValueSet )
422 					nChildIndex = static_cast< sal_Int32 >( pValueSet->GetItemPos( pValueSet->GetSelectItemId() ) );
423 
424 				if( nChildIndex >= pEntry->getAccessibleChildCount() )
425 					return;
426 
427 				aNew <<= getAccessibleChild( pEntry->mpControl, nChildIndex );
428 			}
429 			else
430 			{
431 				aNew <<= pEntry->GetAccessible(true);
432 			}
433 
434 			fireAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOld, aNew );
435 			fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOld, aNew );
436 			fireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) );
437 			aNew >>= mxOldSelection;
438 		}
439 	}
440 }
441 
442 // --------------------------------------------------------------------
443 
444 ToolbarMenuEntry* ToolbarMenu_Impl::implGetEntry( int nEntry ) const
445 {
446 	if( (nEntry < 0) || (nEntry >= (int)maEntryVector.size() ) )
447 		return NULL;
448 
449 	return maEntryVector[nEntry];
450 }
451 
452 
453 // --------------------------------------------------------------------
454 
455 IMPL_LINK( ToolbarMenu, HighlightHdl, Control *, pControl )
456 {
457 	(void)pControl;
458 	mpImpl->notifyHighlightedEntry();
459 	return 0;
460 }
461 
462 // ====================================================================
463 
464 ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, WinBits nBits )
465 : DockingWindow(pParentWindow, nBits)
466 {
467     implInit(rFrame);
468 }
469 
470 // --------------------------------------------------------------------
471 
472 ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, const ResId& rResId )
473 : DockingWindow(pParentWindow, rResId)
474 {
475     implInit(rFrame);
476 }
477 
478 // --------------------------------------------------------------------
479 
480 void ToolbarMenu::implInit(const Reference< XFrame >& rFrame)
481 {
482 	mpImpl = new ToolbarMenu_Impl( *this, rFrame );
483 
484     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
485 	SetControlBackground( rStyleSettings.GetMenuColor() );
486 
487     initWindow();
488 
489     Window* pWindow = GetTopMostParentSystemWindow( this );
490     if ( pWindow )
491         ((SystemWindow *)pWindow)->GetTaskPaneList()->AddWindow( this );
492 }
493 
494 // --------------------------------------------------------------------
495 
496 ToolbarMenu::~ToolbarMenu()
497 {
498     Window* pWindow = GetTopMostParentSystemWindow( this );
499     if ( pWindow )
500         ((SystemWindow *)pWindow)->GetTaskPaneList()->RemoveWindow( this );
501 
502     if ( mpImpl->mxStatusListener.is() )
503     {
504         mpImpl->mxStatusListener->dispose();
505         mpImpl->mxStatusListener.clear();
506     }
507 
508 	// delete all menu entries
509 	const int nEntryCount = mpImpl->maEntryVector.size();
510 	int nEntry;
511 	for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
512 	{
513 		delete mpImpl->maEntryVector[nEntry];
514 	}
515 
516 	delete mpImpl;
517 }
518 
519 // --------------------------------------------------------------------
520 
521 int ToolbarMenu::getSelectedEntryId() const
522 {
523 	ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnSelectedEntry );
524 	return pEntry ? pEntry->mnEntryId : -1;
525 }
526 
527 // --------------------------------------------------------------------
528 
529 int ToolbarMenu::getHighlightedEntryId() const
530 {
531 	ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry );
532 	return pEntry ? pEntry->mnEntryId : -1;
533 }
534 
535 // --------------------------------------------------------------------
536 
537 void ToolbarMenu::checkEntry( int nEntryId, bool bChecked )
538 {
539 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
540 	if( pEntry && pEntry->mbChecked != bChecked )
541 	{
542 		pEntry->mbChecked = bChecked;
543 		Invalidate();
544 	}
545 }
546 
547 // --------------------------------------------------------------------
548 
549 bool ToolbarMenu::isEntryChecked( int nEntryId ) const
550 {
551 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
552 	return pEntry && pEntry->mbChecked;
553 }
554 
555 // --------------------------------------------------------------------
556 
557 void ToolbarMenu::enableEntry( int nEntryId, bool bEnable )
558 {
559 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
560 	if( pEntry && pEntry->mbEnabled != bEnable )
561 	{
562 		pEntry->mbEnabled = bEnable;
563 		if( pEntry->mpControl )
564 		{
565 			pEntry->mpControl->Enable( bEnable );
566 
567 			// hack for the valueset to make it paint itself anew
568 			pEntry->mpControl->Resize();
569 		}
570 		Invalidate();
571 	}
572 }
573 
574 // --------------------------------------------------------------------
575 
576 bool ToolbarMenu::isEntryEnabled( int nEntryId ) const
577 {
578 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
579 	return pEntry && pEntry->mbEnabled;
580 }
581 
582 // --------------------------------------------------------------------
583 
584 void ToolbarMenu::setEntryText( int nEntryId, const String& rStr )
585 {
586 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
587 	if( pEntry && pEntry->maText != rStr )
588 	{
589 		pEntry->maText = rStr;
590 		mpImpl->maSize = implCalcSize();
591 		if( IsVisible() )
592 			Invalidate();
593 	}
594 }
595 
596 // --------------------------------------------------------------------
597 
598 const String& ToolbarMenu::getEntryText( int nEntryId ) const
599 {
600 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
601 	if( pEntry )
602 		return pEntry->maText;
603 	else
604 	{
605 		static String aEmptyStr;
606         return aEmptyStr;
607 	}
608 }
609 
610 // --------------------------------------------------------------------
611 
612 void ToolbarMenu::setEntryImage( int nEntryId, const Image& rImage )
613 {
614 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
615 	if( pEntry && pEntry->maImage != rImage )
616 	{
617 		pEntry->maImage = rImage;
618 		mpImpl->maSize = implCalcSize();
619 		if( IsVisible() )
620 			Invalidate();
621 	}
622 }
623 
624 // --------------------------------------------------------------------
625 
626 const Image& ToolbarMenu::getEntryImage( int nEntryId ) const
627 {
628 	ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
629 	if( pEntry )
630 		return pEntry->maImage;
631 	else
632 	{
633 		static Image aEmptyImage;
634         return aEmptyImage;
635 	}
636 }
637 
638 // --------------------------------------------------------------------
639 
640 void ToolbarMenu::initWindow()
641 {
642     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
643 
644 	SetPointFont( rStyleSettings.GetMenuFont() );
645     SetBackground( Wallpaper( GetControlBackground() ) );
646     SetTextColor( rStyleSettings.GetMenuTextColor() );
647     SetTextFillColor();
648     SetLineColor();
649 
650 	mpImpl->maSize = implCalcSize();
651 }
652 
653 // --------------------------------------------------------------------
654 
655 Size ToolbarMenu::implCalcSize()
656 {
657 	const long nFontHeight = GetTextHeight();
658 	long nExtra = nFontHeight/4;
659 
660     Size aSz;
661     Size aMaxImgSz;
662     long nMaxTextWidth = 0;
663     long nMinMenuItemHeight = nFontHeight+2;
664 	sal_Bool bCheckable = sal_False;
665 
666 	const int nEntryCount = mpImpl->maEntryVector.size();
667 	int nEntry;
668 
669 	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
670 	const bool bUseImages = rSettings.GetUseImagesInMenus();
671 
672 	// get maximum image size
673 	if( bUseImages )
674 	{
675 		for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
676 		{
677 			ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
678 			if( pEntry && pEntry->mbHasImage )
679 			{
680 				Size aImgSz( pEntry->maImage.GetSizePixel() );
681 				nMinMenuItemHeight = std::max( nMinMenuItemHeight, aImgSz.Height() + 6 );
682 			    aMaxImgSz.Width() = std::max( aMaxImgSz.Width(), aImgSz.Width() );
683 			}
684 		}
685 	}
686 
687 	mpImpl->mnCheckPos = nExtra;
688 	mpImpl->mnImagePos = nExtra;
689 	mpImpl->mnTextPos = mpImpl->mnImagePos + aMaxImgSz.Width();
690 
691 	if ( aMaxImgSz.Width() )
692 		mpImpl->mnTextPos += std::max( nExtra, 7L );
693 	if ( bCheckable	)
694 		mpImpl->mnTextPos += 16;
695 
696 	// set heights, calc maximum width
697     for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
698     {
699 		ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
700 
701 		if( pEntry )
702 		{
703 			if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) )
704 				bCheckable = sal_True;
705 
706             // Text:
707             if( pEntry->mbHasText || pEntry->mbHasImage )
708             {
709 				pEntry->maSize.Height() = nMinMenuItemHeight;
710 
711 				if( pEntry->mbHasText )
712 				{
713 					long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos + nExtra;
714 					nMaxTextWidth = std::max( nTextWidth, nMaxTextWidth );
715 				}
716 			}
717 			// Control:
718             else if( pEntry->mpControl )
719 			{
720 				Size aControlSize( pEntry->mpControl->GetOutputSizePixel() );
721 
722 				nMaxTextWidth = std::max( aControlSize.Width(), nMaxTextWidth );
723                 pEntry->maSize.Height() = aControlSize.Height() + 1;
724 			}
725 
726 		}
727 	}
728 
729 	aSz.Width() = nMaxTextWidth + (BORDER_X<<1);
730 
731 	// positionate controls
732 	int nY = BORDER_Y;
733     for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
734     {
735 		ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
736 
737 		if( pEntry )
738 		{
739 			pEntry->maSize.Width() = nMaxTextWidth;
740 
741 			if( pEntry->mpControl )
742 			{
743 				Size aControlSize( pEntry->mpControl->GetOutputSizePixel() );
744 				Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY);
745 
746 				pEntry->mpControl->SetPosPixel( aControlPos );
747 
748 				pEntry->maRect = Rectangle( aControlPos, aControlSize );
749 			}
750 			else
751 			{
752 				pEntry->maRect = Rectangle( Point( 0, nY ), pEntry->maSize );
753 			}
754 
755 			nY += pEntry->maSize.Height();
756 		}
757 		else
758 		{
759 			nY += SEPARATOR_HEIGHT;
760 		}
761 	}
762 
763 	aSz.Height() += nY + BORDER_Y;
764 
765     return aSz;
766 }
767 
768 // --------------------------------------------------------------------
769 
770 void ToolbarMenu::highlightFirstEntry()
771 {
772 	implChangeHighlightEntry( 0 );
773 }
774 
775 // --------------------------------------------------------------------
776 
777 void ToolbarMenu::GetFocus()
778 {
779 	if( mpImpl->mnHighlightedEntry == -1 )
780 		implChangeHighlightEntry( 0 );
781 
782 	DockingWindow::GetFocus();
783 }
784 
785 // --------------------------------------------------------------------
786 
787 void ToolbarMenu::LoseFocus()
788 {
789 	if( mpImpl->mnHighlightedEntry != -1 )
790 		implChangeHighlightEntry( -1 );
791 
792 	DockingWindow::LoseFocus();
793 }
794 
795 // --------------------------------------------------------------------
796 
797 void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits )
798 {
799 	appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) );
800 }
801 
802 // --------------------------------------------------------------------
803 
804 void ToolbarMenu::appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits )
805 {
806 	appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, nItemBits ) );
807 }
808 
809 // --------------------------------------------------------------------
810 
811 void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, const Image& rImage, MenuItemBits nItemBits )
812 {
813 	appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, rStr, nItemBits ) );
814 }
815 
816 // --------------------------------------------------------------------
817 
818 void ToolbarMenu::appendEntry( int nEntryId, Control* pControl, MenuItemBits nItemBits )
819 {
820 	appendEntry( new ToolbarMenuEntry( *this, nEntryId, pControl, nItemBits ) );
821 }
822 
823 // --------------------------------------------------------------------
824 
825 void ToolbarMenu::appendEntry( ToolbarMenuEntry* pEntry )
826 {
827 	mpImpl->maEntryVector.push_back( pEntry );
828 	mpImpl->maSize = implCalcSize();
829 	if( IsVisible() )
830 		Invalidate();
831 }
832 
833 // --------------------------------------------------------------------
834 
835 void ToolbarMenu::appendSeparator()
836 {
837 	appendEntry( 0 );
838 }
839 
840 // --------------------------------------------------------------------
841 
842 /** creates an empty ValueSet that is initialized and can be inserted with appendEntry. */
843 ValueSet* ToolbarMenu::createEmptyValueSetControl()
844 {
845 	ValueSet* pSet = new ValueSet( this, WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT );
846 	pSet->EnableFullItemMode( sal_False );
847 	pSet->SetColor( GetControlBackground() );
848 	pSet->SetHighlightHdl( LINK( this, ToolbarMenu, HighlightHdl ) );
849 	return pSet;
850 }
851 
852 // --------------------------------------------------------------------
853 
854 ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const
855 {
856 	return mpImpl->implGetEntry( nEntry );
857 }
858 
859 // --------------------------------------------------------------------
860 
861 ToolbarMenuEntry* ToolbarMenu::implSearchEntry( int nEntryId ) const
862 {
863 	const int nEntryCount = mpImpl->maEntryVector.size();
864 	int nEntry;
865 	for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
866     {
867         ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry];
868         if( p && p->mnEntryId == nEntryId )
869 		{
870 			return p;
871 		}
872 	}
873 
874 	return NULL;
875 }
876 
877 // --------------------------------------------------------------------
878 
879 void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight )
880 {
881     Size    aSz( GetOutputSizePixel() );
882     long    nX = 0, nY = 0;
883 
884 	const int nEntryCount = mpImpl->maEntryVector.size();
885 	int nEntry;
886 	for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
887     {
888         ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
889         if( pEntry && (nEntry == nHighlightEntry) )
890         {
891 			// no highlights for controls only items
892 			if( pEntry->mpControl )
893 			{
894 				if( !bHighlight )
895 				{
896 					ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl );
897 					if( pValueSet )
898 					{
899 						pValueSet->SetNoSelection();
900 					}
901 				}
902 				break;
903 			}
904 
905 			bool bRestoreLineColor = false;
906             Color oldLineColor;
907             bool bDrawItemRect = true;
908 
909             Rectangle aItemRect( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) );
910             if ( pEntry->mnBits & MIB_POPUPSELECT )
911             {
912                 long nFontHeight = GetTextHeight();
913                 aItemRect.Right() -= nFontHeight + nFontHeight/4;
914             }
915 
916             if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
917             {
918                 Size aPxSize( GetOutputSizePixel() );
919                 Push( PUSH_CLIPREGION );
920                 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ) );
921                 Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) );
922                 DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
923                                    aCtrlRect,
924                                    CTRL_STATE_ENABLED,
925                                    ImplControlValue(),
926                                    OUString() );
927                 if( bHighlight && IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) )
928                 {
929                     bDrawItemRect = false;
930                     if( sal_False == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM,
931                                                     aItemRect,
932                                                     CTRL_STATE_SELECTED | ( pEntry->mbEnabled? CTRL_STATE_ENABLED: 0 ),
933                                                     ImplControlValue(),
934                                                     OUString() ) )
935                     {
936                         bDrawItemRect = bHighlight;
937                     }
938                 }
939                 else
940                     bDrawItemRect = bHighlight;
941                 Pop();
942             }
943             if( bDrawItemRect )
944             {
945                 if ( bHighlight )
946                 {
947                     if( pEntry->mbEnabled )
948                         SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
949                     else
950                     {
951                         SetFillColor();
952                         oldLineColor = GetLineColor();
953                         SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
954                         bRestoreLineColor = true;
955                     }
956                 }
957                 else
958                     SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
959 
960                 DrawRect( aItemRect );
961             }
962             implPaint( pEntry, bHighlight );
963             if( bRestoreLineColor )
964                 SetLineColor( oldLineColor );
965             break;
966         }
967 
968         nY += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT;
969     }
970 }
971 
972 // --------------------------------------------------------------------
973 
974 void ToolbarMenu::implSelectEntry( int nSelectedEntry )
975 {
976 	mpImpl->mnSelectedEntry = nSelectedEntry;
977 
978 	ToolbarMenuEntry* pEntry = NULL;
979 	if( nSelectedEntry != -1 )
980 		pEntry = mpImpl->maEntryVector[ nSelectedEntry ];
981 
982 	if( pEntry )
983 		mpImpl->maSelectHdl.Call( this );
984 }
985 
986 // --------------------------------------------------------------------
987 
988 void ToolbarMenu::MouseButtonDown( const MouseEvent& rMEvt )
989 {
990 	implHighlightEntry( rMEvt, true );
991 
992 	implSelectEntry( mpImpl->mnHighlightedEntry );
993 }
994 
995 // --------------------------------------------------------------------
996 
997 void ToolbarMenu::MouseButtonUp( const MouseEvent& )
998 {
999 }
1000 
1001 // --------------------------------------------------------------------
1002 
1003 void ToolbarMenu::MouseMove( const MouseEvent& rMEvt )
1004 {
1005 	if ( !IsVisible() )
1006         return;
1007 
1008 	implHighlightEntry( rMEvt, false );
1009 }
1010 
1011 // --------------------------------------------------------------------
1012 
1013 void ToolbarMenu::implHighlightEntry( const MouseEvent& rMEvt, bool bMBDown )
1014 {
1015     long nY = 0;
1016     long nMouseY = rMEvt.GetPosPixel().Y();
1017     Size aOutSz = GetOutputSizePixel();
1018     if ( ( nMouseY >= 0 ) && ( nMouseY < aOutSz.Height() ) )
1019     {
1020         bool bHighlighted = sal_False;
1021 
1022 		const int nEntryCount = mpImpl->maEntryVector.size();
1023 		int nEntry;
1024 		for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
1025 		{
1026 			ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
1027             if( pEntry )
1028             {
1029                 long nOldY = nY;
1030                 nY += pEntry->maSize.Height();
1031 
1032 				if( pEntry->mnEntryId != TITLE_ID )
1033 				{
1034 					if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) )
1035 					{
1036 						if( bMBDown )
1037 						{
1038 							if( nEntry != mpImpl->mnHighlightedEntry )
1039 							{
1040 								implChangeHighlightEntry( nEntry );
1041 							}
1042 						}
1043 						else
1044 						{
1045 							if ( nEntry != mpImpl->mnHighlightedEntry )
1046 							{
1047 								implChangeHighlightEntry( nEntry );
1048 							}
1049 						}
1050 						bHighlighted = true;
1051 					}
1052                 }
1053             }
1054 			else
1055 			{
1056 				nY += SEPARATOR_HEIGHT;
1057 			}
1058         }
1059         if ( !bHighlighted )
1060             implChangeHighlightEntry( -1 );
1061     }
1062     else
1063     {
1064         implChangeHighlightEntry( -1 );
1065     }
1066 }
1067 
1068 // --------------------------------------------------------------------
1069 
1070 void ToolbarMenu::implChangeHighlightEntry( int nEntry )
1071 {
1072     if( mpImpl->mnHighlightedEntry != -1 )
1073     {
1074         implHighlightEntry( mpImpl->mnHighlightedEntry, false );
1075     }
1076 
1077 	mpImpl->mnHighlightedEntry = nEntry;
1078 	Invalidate();
1079 
1080 	if( mpImpl->mnHighlightedEntry != -1 )
1081     {
1082 		implHighlightEntry( mpImpl->mnHighlightedEntry, true );
1083     }
1084 
1085 	mpImpl->notifyHighlightedEntry();
1086 }
1087 
1088 // --------------------------------------------------------------------
1089 
1090 static bool implCheckSubControlCursorMove( Control* pControl, bool bUp, int& nLastColumn )
1091 {
1092 	ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl );
1093 	if( pValueSet )
1094 	{
1095 		sal_uInt16 nItemPos = pValueSet->GetItemPos( pValueSet->GetSelectItemId() );
1096 		if( nItemPos != VALUESET_ITEM_NOTFOUND )
1097 		{
1098 			const sal_uInt16 nColCount = pValueSet->GetColCount();
1099 			const sal_uInt16 nLine = nItemPos / nColCount;
1100 
1101 			nLastColumn = nItemPos - (nLine * nColCount);
1102 
1103 			if( bUp )
1104 			{
1105 				return nLine > 0;
1106 			}
1107 			else
1108 			{
1109 				const sal_uInt16 nLineCount = (pValueSet->GetItemCount() + nColCount - 1) / nColCount;
1110 				return (nLine+1) < nLineCount;
1111 			}
1112 		}
1113 	}
1114 
1115 	return false;
1116 }
1117 
1118 // --------------------------------------------------------------------
1119 
1120 ToolbarMenuEntry* ToolbarMenu::implCursorUpDown( bool bUp, bool bHomeEnd )
1121 {
1122     int n = 0, nLoop = 0;
1123 	if( !bHomeEnd )
1124 	{
1125 		n = mpImpl->mnHighlightedEntry;
1126 		if( n == -1 )
1127 		{
1128 			if( bUp )
1129 				n = 0;
1130 			else
1131 				n = mpImpl->maEntryVector.size()-1;
1132 		}
1133 		else
1134 		{
1135 			// if we have a currently selected entry and
1136 			// cursor keys are used than check if this entry
1137 			// has a control that can use those cursor keys
1138 			ToolbarMenuEntry* pData = mpImpl->maEntryVector[n];
1139 			if( pData && pData->mpControl && !pData->mbHasText )
1140 			{
1141 				if( implCheckSubControlCursorMove( pData->mpControl, bUp, mpImpl->mnLastColumn ) )
1142 					return pData;
1143 			}
1144 		}
1145 		nLoop = n;
1146 	}
1147 	else
1148 	{
1149 		// absolute positioning
1150 		if( bUp )
1151 		{
1152             n = mpImpl->maEntryVector.size();
1153 			nLoop = n-1;
1154 		}
1155 		else
1156 		{
1157 			n = -1;
1158 			nLoop = mpImpl->maEntryVector.size()-1;
1159 		}
1160 	}
1161 
1162     do
1163     {
1164         if( bUp )
1165         {
1166             if ( n )
1167                 n--;
1168             else
1169                 if( mpImpl->mnHighlightedEntry == -1 )
1170                     n = mpImpl->maEntryVector.size()-1;
1171                 else
1172                     break;
1173         }
1174         else
1175         {
1176 			if( n < ((int)mpImpl->maEntryVector.size()-1) )
1177 				n++;
1178 			else
1179                 if( mpImpl->mnHighlightedEntry == -1 )
1180                     n = 0;
1181                 else
1182                     break;
1183         }
1184 
1185         ToolbarMenuEntry* pData = mpImpl->maEntryVector[n];
1186         if( pData && (pData->mnEntryId != TITLE_ID) )
1187         {
1188 			implChangeHighlightEntry( n );
1189 			return pData;
1190 		}
1191     } while ( n != nLoop );
1192 
1193 	return 0;
1194 }
1195 
1196 // --------------------------------------------------------------------
1197 
1198 void ToolbarMenu_Impl::implHighlightControl( sal_uInt16 nCode, Control* pControl )
1199 {
1200 	ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl );
1201 	if( pValueSet )
1202 	{
1203 		const sal_uInt16 nItemCount = pValueSet->GetItemCount();
1204 		sal_uInt16 nItemPos = VALUESET_ITEM_NOTFOUND;
1205 		switch( nCode )
1206 		{
1207         case KEY_UP:
1208 		{
1209 			const sal_uInt16 nColCount = pValueSet->GetColCount();
1210 			const sal_uInt16 nLastLine = nItemCount / nColCount;
1211 			nItemPos = std::min( ((nLastLine-1) * nColCount) + mnLastColumn, nItemCount-1 );
1212 			break;
1213 		}
1214         case KEY_DOWN:
1215 			nItemPos = std::min( mnLastColumn, nItemCount-1 );
1216 			break;
1217         case KEY_END:
1218 			nItemPos = nItemCount -1;
1219 			break;
1220         case KEY_HOME:
1221 			nItemPos = 0;
1222 			break;
1223 		}
1224 		pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) );
1225 		notifyHighlightedEntry();
1226 	}
1227 }
1228 
1229 // --------------------------------------------------------------------
1230 
1231 void ToolbarMenu::KeyInput( const KeyEvent& rKEvent )
1232 {
1233 	Control* pForwardControl = 0;
1234     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
1235     switch ( nCode )
1236     {
1237         case KEY_UP:
1238         case KEY_DOWN:
1239         {
1240 			int nOldEntry = mpImpl->mnHighlightedEntry;
1241 			ToolbarMenuEntry*p = implCursorUpDown( nCode == KEY_UP, false );
1242 			if( p && p->mpControl )
1243 			{
1244 				if( nOldEntry != mpImpl->mnHighlightedEntry )
1245 				{
1246 					mpImpl->implHighlightControl( nCode, p->mpControl );
1247 				}
1248 				else
1249 				{
1250 					// in case we are in a system floating window, GrabFocus does not work :-/
1251 					pForwardControl = p->mpControl;
1252 				}
1253 			}
1254         }
1255         break;
1256         case KEY_END:
1257         case KEY_HOME:
1258 		{
1259 			ToolbarMenuEntry* p = implCursorUpDown( nCode == KEY_END, true );
1260 			if( p && p->mpControl )
1261 			{
1262 				mpImpl->implHighlightControl( nCode, p->mpControl );
1263 			}
1264 		}
1265 		break;
1266         case KEY_F6:
1267         case KEY_ESCAPE:
1268 		{
1269             // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
1270             if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
1271                 break;
1272 
1273 			implSelectEntry( -1 );
1274 		}
1275 		break;
1276 
1277         case KEY_RETURN:
1278         {
1279 			ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry );
1280 			if ( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) )
1281 			{
1282 				if( pEntry->mpControl )
1283 				{
1284 					pForwardControl = pEntry->mpControl;
1285 				}
1286 				else
1287 				{
1288 					implSelectEntry( mpImpl->mnHighlightedEntry );
1289 				}
1290 			}
1291         }
1292         break;
1293         default:
1294         {
1295 			ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry );
1296 			if ( pEntry && pEntry->mbEnabled && pEntry->mpControl && !pEntry->mbHasText )
1297 			{
1298 				pForwardControl = pEntry->mpControl;
1299 			}
1300         }
1301 
1302     }
1303 	if( pForwardControl )
1304 		pForwardControl->KeyInput( rKEvent );
1305 
1306 }
1307 
1308 // --------------------------------------------------------------------
1309 static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight )
1310 {
1311     sal_Bool bNativeOk = sal_False;
1312     if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
1313     {
1314         ImplControlValue    aControlValue;
1315         ControlState        nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED;
1316 
1317         aControlValue.setTristateVal( BUTTONVALUE_ON );
1318 
1319         bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
1320                                                   i_rRect, nState, aControlValue,
1321                                                   rtl::OUString() );
1322     }
1323 
1324     if( ! bNativeOk )
1325     {
1326         const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings();
1327         Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
1328         i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, sal_True, sal_False, 2, NULL, &aColor );
1329     }
1330 }
1331 
1332 static long ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth )
1333 {
1334     rMaxWidth = rCheckHeight = rRadioHeight = 0;
1335 
1336     ImplControlValue aVal;
1337     Rectangle aNativeBounds;
1338     Rectangle aNativeContent;
1339     Point tmp( 0, 0 );
1340     Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
1341     if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) )
1342     {
1343         if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
1344                                           ControlPart(PART_MENU_ITEM_CHECK_MARK),
1345                                           aCtrlRegion,
1346                                           ControlState(CTRL_STATE_ENABLED),
1347                                           aVal,
1348                                           OUString(),
1349                                           aNativeBounds,
1350                                           aNativeContent )
1351         )
1352         {
1353             rCheckHeight = aNativeBounds.GetHeight();
1354 			rMaxWidth = aNativeContent.GetWidth();
1355         }
1356     }
1357     if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) )
1358     {
1359         if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
1360                                           ControlPart(PART_MENU_ITEM_RADIO_MARK),
1361                                           aCtrlRegion,
1362                                           ControlState(CTRL_STATE_ENABLED),
1363                                           aVal,
1364                                           OUString(),
1365                                           aNativeBounds,
1366                                           aNativeContent )
1367         )
1368         {
1369             rRadioHeight = aNativeBounds.GetHeight();
1370 			rMaxWidth = Max (rMaxWidth, aNativeContent.GetWidth());
1371         }
1372     }
1373     return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight;
1374 }
1375 
1376 void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted )
1377 {
1378 	sal_uInt16 nBorder = 0; long nStartY = 0; // from Menu implementations, needed when we support native menu background & scrollable menu
1379 
1380     long nFontHeight = GetTextHeight();
1381 //    long nExtra = nFontHeight/4;
1382 
1383     long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0;
1384     ImplGetNativeCheckAndRadioSize( this, nCheckHeight, nRadioHeight, nMaxCheckWidth );
1385 
1386     DecorationView aDecoView( this );
1387     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
1388 	const bool bUseImages = rSettings.GetUseImagesInMenus();
1389 
1390 	int nOuterSpace = 0; // ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
1391 	Point aTopLeft( nOuterSpace, nOuterSpace ), aTmpPos;
1392 
1393     Size aOutSz( GetOutputSizePixel() );
1394 	const int nEntryCount = mpImpl->maEntryVector.size();
1395 	int nEntry;
1396 	for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
1397 	{
1398 		ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
1399 
1400         Point aPos( aTopLeft );
1401         aPos.Y() += nBorder;
1402         aPos.Y() += nStartY;
1403 
1404 
1405 		if( (pEntry == 0) && !pThisOnly )
1406 		{
1407 	        // Separator
1408             aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2);
1409             aTmpPos.X() = aPos.X() + 2 + nOuterSpace;
1410             SetLineColor( rSettings.GetShadowColor() );
1411             DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
1412             aTmpPos.Y()++;
1413             SetLineColor( rSettings.GetLightColor() );
1414             DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
1415             SetLineColor();
1416 		}
1417 		else if( !pThisOnly || ( pEntry == pThisOnly ) )
1418         {
1419 			const bool bTitle = pEntry->mnEntryId == TITLE_ID;
1420 
1421             if ( pThisOnly && bHighlighted )
1422                 SetTextColor( rSettings.GetMenuHighlightTextColor() );
1423 
1424             if( aPos.Y() >= 0 )
1425             {
1426 				long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2);
1427 
1428 				sal_uInt16  nTextStyle   = 0;
1429 				sal_uInt16  nSymbolStyle = 0;
1430 				sal_uInt16  nImageStyle  = 0;
1431 
1432 				if( !pEntry->mbEnabled )
1433 				{
1434 					nTextStyle   |= TEXT_DRAW_DISABLE;
1435 					nSymbolStyle |= SYMBOL_DRAW_DISABLE;
1436 					nImageStyle  |= IMAGE_DRAW_DISABLE;
1437 				}
1438 
1439 				Rectangle aOuterCheckRect( Point( aPos.X()+mpImpl->mnCheckPos, aPos.Y() ), Size( pEntry->maSize.Height(), pEntry->maSize.Height() ) );
1440 				aOuterCheckRect.Left()      += 1;
1441 				aOuterCheckRect.Right()     -= 1;
1442 				aOuterCheckRect.Top()       += 1;
1443 				aOuterCheckRect.Bottom()    -= 1;
1444 
1445 				if( bTitle )
1446 				{
1447 					// fill the background
1448 					Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) );
1449 					SetFillColor(rSettings.GetDialogColor());
1450 					SetLineColor();
1451 					DrawRect(aRect);
1452 					SetLineColor( rSettings.GetLightColor() );
1453 					DrawLine( aRect.TopLeft(), aRect.TopRight() );
1454 					SetLineColor( rSettings.GetShadowColor() );
1455 					DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
1456 				}
1457 
1458 				// CheckMark
1459 				if ( pEntry->HasCheck() )
1460 				{
1461 					// draw selection transparent marker if checked
1462 					// onto that either a checkmark or the item image
1463 					// will be painted
1464 					// however do not do this if native checks will be painted since
1465 					// the selection color too often does not fit the theme's check and/or radio
1466 
1467 					if( !pEntry->mbHasImage )
1468 					{
1469 						if( this->IsNativeControlSupported( CTRL_MENU_POPUP,
1470 															 (pEntry->mnBits & MIB_RADIOCHECK)
1471 															 ? PART_MENU_ITEM_CHECK_MARK
1472 															 : PART_MENU_ITEM_RADIO_MARK ) )
1473 						{
1474 							ControlPart nPart = ((pEntry->mnBits & MIB_RADIOCHECK)
1475 												 ? PART_MENU_ITEM_RADIO_MARK
1476 												 : PART_MENU_ITEM_CHECK_MARK);
1477 
1478 							ControlState nState = 0;
1479 
1480 							if ( pEntry->mbChecked )
1481 								nState |= CTRL_STATE_PRESSED;
1482 
1483 							if ( pEntry->mbEnabled )
1484 								nState |= CTRL_STATE_ENABLED;
1485 
1486 							if ( bHighlighted )
1487 								nState |= CTRL_STATE_SELECTED;
1488 
1489 							long nCtrlHeight = (pEntry->mnBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight;
1490 							aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2;
1491 							aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2;
1492 
1493 							Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) );
1494 							DrawNativeControl( CTRL_MENU_POPUP, nPart, aCheckRect, nState, ImplControlValue(), OUString() );
1495 						}
1496 						else if ( pEntry->mbChecked ) // by default do nothing for unchecked items
1497 						{
1498 							ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted );
1499 
1500 							SymbolType eSymbol;
1501 							Size aSymbolSize;
1502 							if ( pEntry->mnBits & MIB_RADIOCHECK )
1503 							{
1504 								eSymbol = SYMBOL_RADIOCHECKMARK;
1505 								aSymbolSize = Size( nFontHeight/2, nFontHeight/2 );
1506 							}
1507 							else
1508 							{
1509 								eSymbol = SYMBOL_CHECKMARK;
1510 								aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 );
1511 							}
1512 							aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2;
1513 							aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2;
1514 							Rectangle aRect( aTmpPos, aSymbolSize );
1515 							aDecoView.DrawSymbol( aRect, eSymbol, GetTextColor(), nSymbolStyle );
1516 						}
1517 					}
1518 				}
1519 
1520 				// Image:
1521 				if( pEntry->mbHasImage && bUseImages )
1522 				{
1523 					// Don't render an image for a check thing
1524 					 /* if((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pEntry->HasCheck() )*/
1525 					{
1526 						if( pEntry->mbChecked )
1527 							ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted );
1528 						aTmpPos = aOuterCheckRect.TopLeft();
1529 						aTmpPos.X() += (aOuterCheckRect.GetWidth()-pEntry->maImage.GetSizePixel().Width())/2;
1530 						aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pEntry->maImage.GetSizePixel().Height())/2;
1531 						DrawImage( aTmpPos, pEntry->maImage, nImageStyle );
1532 					}
1533 				}
1534 
1535 				// Text:
1536 				if( pEntry->mbHasText )
1537 				{
1538 					aTmpPos.X() = aPos.X() + (bTitle ? 4 : mpImpl->mnTextPos);
1539 					aTmpPos.Y() = aPos.Y();
1540 					aTmpPos.Y() += nTextOffsetY;
1541 					sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
1542 
1543 					DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle, NULL, NULL ); // pVector, pDisplayText );
1544 				}
1545 
1546 /*
1547 				// Accel
1548 				if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
1549 				{
1550 					XubString aAccText = pData->aAccelKey.GetName();
1551 					aTmpPos.X() = aOutSz.Width() - this->GetTextWidth( aAccText );
1552 					aTmpPos.X() -= 4*nExtra;
1553 
1554 					aTmpPos.X() -= nOuterSpace;
1555 					aTmpPos.Y() = aPos.Y();
1556 					aTmpPos.Y() += nTextOffsetY;
1557 					this->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle );
1558 				}
1559 */
1560 
1561 /*
1562 				// SubMenu?
1563 				if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
1564 				{
1565 					aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace;
1566 					aTmpPos.Y() = aPos.Y();
1567 					aTmpPos.Y() += nExtra/2;
1568 					aTmpPos.Y() += ( pEntry->maSize.Height() / 2 ) - ( nFontHeight/4 );
1569 					if ( pEntry->mnBits & MIB_POPUPSELECT )
1570 					{
1571 						this->SetTextColor( rSettings.GetMenuTextColor() );
1572 						Point aTmpPos2( aPos );
1573 						aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
1574 						aDecoView.DrawFrame(
1575 							Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pEntry->maSize.Height() ) ), FRAME_DRAW_GROUP );
1576 					}
1577 					aDecoView.DrawSymbol(
1578 						Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
1579 						SYMBOL_SPIN_RIGHT, this->GetTextColor(), nSymbolStyle );
1580 //                  if ( pEntry->mnBits & MIB_POPUPSELECT )
1581 //                  {
1582 //                      aTmpPos.Y() += nFontHeight/2 ;
1583 //                      this->SetLineColor( rSettings.GetShadowColor() );
1584 //                      this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
1585 //                      this->SetLineColor( rSettings.GetLightColor() );
1586 //                      aTmpPos.Y()++;
1587 //                      this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
1588 //                      this->SetLineColor();
1589 //                  }
1590 				}
1591 */
1592 
1593 				if ( pThisOnly && bHighlighted )
1594 				{
1595 					// This restores the normal menu or menu bar text
1596 					// color for when it is no longer highlighted.
1597 					SetTextColor( rSettings.GetMenuTextColor() );
1598 				 }
1599 			}
1600         }
1601 
1602 		aTopLeft.Y() += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT;
1603     }
1604 }
1605 
1606 // --------------------------------------------------------------------
1607 
1608 void ToolbarMenu::Paint( const Rectangle& )
1609 {
1610     SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
1611 
1612 	implPaint();
1613 
1614     if( mpImpl->mnHighlightedEntry != -1 )
1615         implHighlightEntry( mpImpl->mnHighlightedEntry, true );
1616 }
1617 
1618 // --------------------------------------------------------------------
1619 
1620 void ToolbarMenu::RequestHelp( const HelpEvent& rHEvt )
1621 {
1622 	DockingWindow::RequestHelp( rHEvt );
1623 }
1624 
1625 // --------------------------------------------------------------------
1626 
1627 void ToolbarMenu::StateChanged( StateChangedType nType )
1628 {
1629     DockingWindow::StateChanged( nType );
1630 
1631     if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
1632     {
1633 		initWindow();
1634         Invalidate();
1635     }
1636 }
1637 
1638 // --------------------------------------------------------------------
1639 
1640 void ToolbarMenu::DataChanged( const DataChangedEvent& rDCEvt )
1641 {
1642     DockingWindow::DataChanged( rDCEvt );
1643 
1644     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1645          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1646          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1647           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1648     {
1649         initWindow();
1650         Invalidate();
1651     }
1652 }
1653 
1654 // --------------------------------------------------------------------
1655 
1656 void ToolbarMenu::Command( const CommandEvent& rCEvt )
1657 {
1658     if ( rCEvt.GetCommand() == COMMAND_WHEEL )
1659     {
1660         const CommandWheelData* pData = rCEvt.GetWheelData();
1661         if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
1662         {
1663 			implCursorUpDown( pData->GetDelta() > 0L, false );
1664         }
1665     }
1666 }
1667 
1668 // --------------------------------------------------------------------
1669 
1670 Reference< ::com::sun::star::accessibility::XAccessible > ToolbarMenu::CreateAccessible()
1671 {
1672 	mpImpl->setAccessible( new ToolbarMenuAcc( *mpImpl ) );
1673 	return Reference< XAccessible >( mpImpl->mxAccessible.get() );
1674 }
1675 
1676 // --------------------------------------------------------------------
1677 
1678 // todo: move to new base class that will replace SfxPopupWindo
1679 void ToolbarMenu::AddStatusListener( const rtl::OUString& rCommandURL )
1680 {
1681 	initStatusListener();
1682 	mpImpl->mxStatusListener->addStatusListener( rCommandURL );
1683 }
1684 
1685 // --------------------------------------------------------------------
1686 
1687 void ToolbarMenu::RemoveStatusListener( const rtl::OUString& rCommandURL )
1688 {
1689 	mpImpl->mxStatusListener->removeStatusListener( rCommandURL );
1690 }
1691 // --------------------------------------------------------------------
1692 
1693 
1694 void ToolbarMenu::UpdateStatus( const rtl::OUString& rCommandURL )
1695 {
1696 	mpImpl->mxStatusListener->updateStatus( rCommandURL );
1697 }
1698 
1699 // --------------------------------------------------------------------
1700 
1701 // XStatusListener (subclasses must override this one to get the status updates
1702 void SAL_CALL ToolbarMenu::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& /*Event*/ ) throw ( ::com::sun::star::uno::RuntimeException )
1703 {
1704 }
1705 
1706 // --------------------------------------------------------------------
1707 
1708 class ToolbarMenuStatusListener : public svt::FrameStatusListener
1709 {
1710 public:
1711 	ToolbarMenuStatusListener( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager,
1712 							   const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame,
1713 							   ToolbarMenu& rToolbarMenu );
1714 
1715 	virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException);
1716 	virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );
1717 
1718 	ToolbarMenu* mpMenu;
1719 };
1720 
1721 // --------------------------------------------------------------------
1722 
1723 ToolbarMenuStatusListener::ToolbarMenuStatusListener(
1724 	const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager,
1725 	const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame,
1726 	ToolbarMenu& rToolbarMenu )
1727 : svt::FrameStatusListener( xServiceManager, xFrame )
1728 , mpMenu( &rToolbarMenu )
1729 {
1730 }
1731 
1732 // --------------------------------------------------------------------
1733 
1734 void SAL_CALL ToolbarMenuStatusListener::dispose() throw (::com::sun::star::uno::RuntimeException)
1735 {
1736 	mpMenu = 0;
1737 	svt::FrameStatusListener::dispose();
1738 }
1739 
1740 // --------------------------------------------------------------------
1741 
1742 void SAL_CALL ToolbarMenuStatusListener::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException )
1743 {
1744 	if( mpMenu )
1745 		mpMenu->statusChanged( Event );
1746 }
1747 
1748 // --------------------------------------------------------------------
1749 
1750 void ToolbarMenu::initStatusListener()
1751 {
1752 	if( !mpImpl->mxStatusListener.is() )
1753 		mpImpl->mxStatusListener.set( new ToolbarMenuStatusListener( mpImpl->mxServiceManager, mpImpl->mxFrame, *this ) );
1754 }
1755 
1756 // --------------------------------------------------------------------
1757 
1758 bool ToolbarMenu::IsInPopupMode()
1759 {
1760 	return GetDockingManager()->IsInPopupMode(this);
1761 }
1762 
1763 // --------------------------------------------------------------------
1764 
1765 void ToolbarMenu::EndPopupMode()
1766 {
1767 	GetDockingManager()->EndPopupMode(this);
1768 }
1769 
1770 // --------------------------------------------------------------------
1771 
1772 const Size& ToolbarMenu::getMenuSize() const
1773 {
1774 	return mpImpl->maSize;
1775 }
1776 
1777 // --------------------------------------------------------------------
1778 
1779 void ToolbarMenu::SetSelectHdl( const Link& rLink )
1780 {
1781 	mpImpl->maSelectHdl = rLink;
1782 }
1783 
1784 // --------------------------------------------------------------------
1785 
1786 const Link& ToolbarMenu::GetSelectHdl() const
1787 {
1788 	return mpImpl->maSelectHdl;
1789 }
1790 
1791 // --------------------------------------------------------------------
1792 
1793 Reference< XFrame >	ToolbarMenu::GetFrame() const
1794 {
1795 	return mpImpl->mxFrame;
1796 }
1797 
1798 // --------------------------------------------------------------------
1799 
1800 
1801 // --------------------------------------------------------------------
1802 
1803 }
1804 
1805 
1806