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 #include "ListenerHelper.h"
29 #include "MyProtocolHandler.h"
30 
31 #include <com/sun/star/awt/MessageBoxButtons.hpp>
32 #include <com/sun/star/awt/XMessageBoxFactory.hpp>
33 #include <com/sun/star/frame/ControlCommand.hpp>
34 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
35 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
36 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
37 #include <com/sun/star/system/XSystemShellExecute.hpp>
38 
39 
40 using namespace com::sun::star::awt;
41 using namespace com::sun::star::frame;
42 using namespace com::sun::star::system;
43 using namespace com::sun::star::uno;
44 
45 using com::sun::star::beans::NamedValue;
46 using com::sun::star::beans::PropertyValue;
47 using com::sun::star::lang::XMultiServiceFactory;
48 using com::sun::star::sheet::XSpreadsheetView;
49 using com::sun::star::text::XTextViewCursorSupplier;
50 using com::sun::star::util::URL;
51 
52 ListenerHelper aListenerHelper;
53 
54 void BaseDispatch::ShowMessageBox( const Reference< XFrame >& rFrame, const ::rtl::OUString& aTitle, const ::rtl::OUString& aMsgText )
55 {
56 	if ( !mxToolkit.is() )
57 		mxToolkit = Reference< XToolkit > ( mxMSF->createInstance(
58 			::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ))), UNO_QUERY );
59 
60     Reference< XMessageBoxFactory > xMsgBoxFactory( mxToolkit, UNO_QUERY );
61     if ( rFrame.is() && xMsgBoxFactory.is() )
62     {
63         Reference< XMessageBox > xMsgBox = xMsgBoxFactory->createMessageBox(
64             Reference< XWindowPeer >( rFrame->getContainerWindow(), UNO_QUERY ),
65             Rectangle(0,0,300,200),
66             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "infobox" ) ),
67             MessageBoxButtons::BUTTONS_OK,
68             aTitle,
69             aMsgText );
70 
71         if ( xMsgBox.is() )
72             xMsgBox->execute();
73     }
74 }
75 
76 void BaseDispatch::SendCommand( const com::sun::star::util::URL& aURL, const ::rtl::OUString& rCommand, const Sequence< NamedValue >& rArgs, sal_Bool bEnabled )
77 {
78     Reference < XDispatch > xDispatch =
79             aListenerHelper.GetDispatch( mxFrame, aURL.Path );
80 
81     FeatureStateEvent aEvent;
82 
83     aEvent.FeatureURL = aURL;
84     aEvent.Source     = xDispatch;
85     aEvent.IsEnabled  = bEnabled;
86     aEvent.Requery    = sal_False;
87 
88     ControlCommand aCtrlCmd;
89     aCtrlCmd.Command   = rCommand;
90     aCtrlCmd.Arguments = rArgs;
91 
92     aEvent.State <<= aCtrlCmd;
93     aListenerHelper.Notify( mxFrame, aEvent.FeatureURL.Path, aEvent );
94 }
95 
96 void BaseDispatch::SendCommandTo( const Reference< XStatusListener >& xControl, const URL& aURL, const ::rtl::OUString& rCommand, const Sequence< NamedValue >& rArgs, sal_Bool bEnabled )
97 {
98     FeatureStateEvent aEvent;
99 
100     aEvent.FeatureURL = aURL;
101     aEvent.Source     = (::com::sun::star::frame::XDispatch*) this;
102     aEvent.IsEnabled  = bEnabled;
103     aEvent.Requery    = sal_False;
104 
105     ControlCommand aCtrlCmd;
106     aCtrlCmd.Command   = rCommand;
107     aCtrlCmd.Arguments = rArgs;
108 
109     aEvent.State <<= aCtrlCmd;
110     xControl->statusChanged( aEvent );
111 }
112 
113 void SAL_CALL MyProtocolHandler::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException)
114 {
115 	Reference < XFrame > xFrame;
116 	if ( aArguments.getLength() )
117 	{
118 		// das erste Argument ist immer der Frame, da ein ProtocolHandler den braucht um Zugriff
119 		// auf den Context zu haben, in dem er aufgerufen wird
120 		aArguments[0] >>= xFrame;
121 		mxFrame = xFrame;
122 	}
123 }
124 
125 Reference< XDispatch > SAL_CALL MyProtocolHandler::queryDispatch(	const URL& aURL, const ::rtl::OUString& sTargetFrameName, sal_Int32 nSearchFlags )
126 				throw( RuntimeException )
127 {
128 	Reference < XDispatch > xRet;
129 	if ( !mxFrame.is() )
130 		return 0;
131 
132 	Reference < XController > xCtrl = mxFrame->getController();
133 	if ( xCtrl.is() && !aURL.Protocol.compareToAscii(
134         RTL_CONSTASCII_STRINGPARAM( "vnd.demo.complextoolbarcontrols.demoaddon:" ) ) )
135 	{
136 		Reference < XTextViewCursorSupplier > xCursor( xCtrl, UNO_QUERY );
137 		Reference < XSpreadsheetView > xView( xCtrl, UNO_QUERY );
138 		if ( !xCursor.is() && !xView.is() )
139 			// ohne ein entsprechendes Dokument funktioniert der Handler nicht
140 			return xRet;
141 
142 		if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ImageButtonCmd" ) ) ||
143 			 aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ComboboxCmd" ) ) ||
144 			 aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ToggleDropdownButtonCmd" ) ) ||
145 			 aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DropdownButtonCmd" ) ) ||
146 			 aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SpinfieldCmd" ) ) ||
147 			 aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EditfieldCmd" ) ) ||
148              aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DropdownboxCmd" ) ) )
149 		{
150 			xRet = aListenerHelper.GetDispatch( mxFrame, aURL.Path );
151 			if ( !xRet.is() )
152 			{
153 				xRet = xCursor.is() ? (BaseDispatch*) new WriterDispatch( mxMSF, mxFrame ) :
154 					(BaseDispatch*) new CalcDispatch( mxMSF, mxFrame );
155 				aListenerHelper.AddDispatch( xRet, mxFrame, aURL.Path );
156 			}
157 		}
158 	}
159 
160 	return xRet;
161 }
162 
163 Sequence < Reference< XDispatch > > SAL_CALL MyProtocolHandler::queryDispatches( const Sequence < DispatchDescriptor >& seqDescripts )
164 			throw( RuntimeException )
165 {
166     sal_Int32 nCount = seqDescripts.getLength();
167     Sequence < Reference < XDispatch > > lDispatcher( nCount );
168 
169     for( sal_Int32 i=0; i<nCount; ++i )
170         lDispatcher[i] = queryDispatch( seqDescripts[i].FeatureURL, seqDescripts[i].FrameName, seqDescripts[i].SearchFlags );
171 
172     return lDispatcher;
173 }
174 
175 ::rtl::OUString MyProtocolHandler_getImplementationName ()
176 	throw (RuntimeException)
177 {
178     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MYPROTOCOLHANDLER_IMPLEMENTATIONNAME ) );
179 }
180 
181 sal_Bool SAL_CALL MyProtocolHandler_supportsService( const ::rtl::OUString& ServiceName )
182 	throw (RuntimeException)
183 {
184     return (
185             ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MYPROTOCOLHANDLER_SERVICENAME ) ) ||
186             ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.frame.ProtocolHandler" ) )
187            );
188 }
189 
190 Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler_getSupportedServiceNames(  )
191 	throw (RuntimeException)
192 {
193 	Sequence < ::rtl::OUString > aRet(1);
194     aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MYPROTOCOLHANDLER_SERVICENAME ) );
195     return aRet;
196 }
197 
198 #undef SERVICE_NAME
199 
200 Reference< XInterface > SAL_CALL MyProtocolHandler_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
201 	throw( Exception )
202 {
203 	return (cppu::OWeakObject*) new MyProtocolHandler( rSMgr );
204 }
205 
206 // XServiceInfo
207 ::rtl::OUString SAL_CALL MyProtocolHandler::getImplementationName(  )
208 	throw (RuntimeException)
209 {
210 	return MyProtocolHandler_getImplementationName();
211 }
212 
213 sal_Bool SAL_CALL MyProtocolHandler::supportsService( const ::rtl::OUString& rServiceName )
214 	throw (RuntimeException)
215 {
216     return MyProtocolHandler_supportsService( rServiceName );
217 }
218 
219 Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler::getSupportedServiceNames(  )
220 	throw (RuntimeException)
221 {
222     return MyProtocolHandler_getSupportedServiceNames();
223 }
224 
225 void SAL_CALL BaseDispatch::dispatch( const URL& aURL, const Sequence < PropertyValue >& lArgs ) throw (RuntimeException)
226 {
227 	/* Its neccessary to hold this object alive, till this method finish.
228 	   May the outside dispatch cache (implemented by the menu/toolbar!)
229 	   forget this instance during de-/activation of frames (focus!).
230 
231 		E.g. An open db beamer in combination with the My-Dialog
232 		can force such strange situation :-(
233 	 */
234 	Reference< XInterface > xSelfHold(static_cast< XDispatch* >(this), UNO_QUERY);
235 
236 	if ( !aURL.Protocol.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "vnd.demo.complextoolbarcontrols.demoaddon:" ) ) )
237 	{
238 		if ( !aURL.Path.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "ImageButtonCmd" ) ) )
239 		{
240             // open the OpenOffice.org web page
241             ::rtl::OUString sURL( RTL_CONSTASCII_USTRINGPARAM( "http://www.openoffice.org" ) );
242             Reference< XSystemShellExecute > xSystemShellExecute( mxMSF->createInstance(
243                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SystemShellExecute" ) ) ), UNO_QUERY );
244             if ( xSystemShellExecute.is() )
245             {
246                 try
247                 {
248                     xSystemShellExecute->execute( sURL, ::rtl::OUString(), SystemShellExecuteFlags::DEFAULTS );
249                 }
250                 catch( Exception& rEx )
251                 {
252                     (void)rEx;
253                 }
254             }
255         }
256 		else if ( !aURL.Path.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "ComboboxCmd" ) ) )
257 		{
258             // remove the text if it's in our list
259             Sequence< NamedValue > aRemoveArgs( 1 );
260             aRemoveArgs[0].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ));
261             aRemoveArgs[0].Value <<= maComboBoxText;
262             SendCommand( aURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RemoveEntryText" ) ), aRemoveArgs, sal_True );
263 
264             // add the new text to the start of the list
265             Sequence< NamedValue > aInsertArgs( 2 );
266             aInsertArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pos" ));
267             aInsertArgs[0].Value <<= sal_Int32( 0 );
268             aInsertArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ));
269             aInsertArgs[1].Value <<= maComboBoxText;
270             SendCommand( aURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InsertEntry" ) ), aInsertArgs, sal_True );
271         }
272 		else if ( !aURL.Path.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "ToggleDropdownButtonCmd" ) ) )
273 		{
274             // Retrieve the text argument from the sequence property value
275             rtl::OUString aText;
276             for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
277             {
278                 if ( lArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Text" ) ) )
279                 {
280                     lArgs[i].Value >>= aText;
281                     break;
282                 }
283             }
284 
285             // create new URL to address the combox box
286             URL aCmdURL;
287             aCmdURL.Path = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ComboboxCmd" ) );
288             aCmdURL.Protocol = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.demo.complextoolbarcontrols.demoaddon:" ) );
289             aCmdURL.Complete = aCmdURL.Path + aCmdURL.Protocol;
290 
291             // set the selected item as text into the combobox
292             Sequence< NamedValue > aArgs( 1 );
293             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ) );
294             aArgs[0].Value <<= aText;
295             SendCommand( aCmdURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SetText" ) ), aArgs, sal_True );
296 		}
297 		else if ( !aURL.Path.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "DropdownButtonCmd" ) ) )
298 		{
299             // Retrieve the text argument from the sequence property value
300             rtl::OUString aText;
301             for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
302             {
303                 if ( lArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Text" ) ) )
304                 {
305                     lArgs[i].Value >>= aText;
306                     break;
307                 }
308             }
309 
310             // just enable this command
311 
312             // set enable flag according to selection
313             if ( aText.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Button Disabled" ) ))
314                 mbButtonEnabled = sal_False;
315             else
316                 mbButtonEnabled = sal_True;
317 
318             // create new URL to address the image button
319             URL aCmdURL;
320             aCmdURL.Path = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ImageButtonCmd" ) );
321             aCmdURL.Protocol = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.demo.complextoolbarcontrols.demoaddon:" ) );
322             aCmdURL.Complete = aCmdURL.Path + aCmdURL.Protocol;
323 
324             // create and initialize FeatureStateEvent with IsEnabled
325             ::com::sun::star::frame::FeatureStateEvent aEvent;
326 			aEvent.FeatureURL = aCmdURL;
327 		    aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
328 			aEvent.IsEnabled = mbButtonEnabled;
329 			aEvent.Requery = sal_False;
330 			aEvent.State <<= Any();
331 
332             // Notify listener about new state
333             Reference < XDispatch > xDispatch = aListenerHelper.GetDispatch( mxFrame, aURL.Path );
334             aListenerHelper.Notify( mxFrame, aEvent.FeatureURL.Path, aEvent );
335         }
336         else if ( !aURL.Path.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "SpinfieldCmd" ) ) )
337         {
338         }
339         else if ( !aURL.Path.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "DropdownboxCmd" ) ) )
340         {
341             // Retrieve the text argument from the sequence property value
342             rtl::OUString aText;
343             for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
344             {
345                 if ( lArgs[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Text" ) ) )
346                 {
347                     lArgs[i].Value >>= aText;
348                     break;
349                 }
350             }
351             OSL_TRACE( "Dropdownbox control - selected entry text : %s",
352                        rtl::OUStringToOString( aText, RTL_TEXTENCODING_UTF8 ).getStr() );
353         }
354 	}
355 }
356 
357 void SAL_CALL BaseDispatch::addStatusListener( const Reference< XStatusListener >& xControl, const URL& aURL ) throw (RuntimeException)
358 {
359 	if ( aURL.Protocol.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.demo.complextoolbarcontrols.demoaddon:" ) ) )
360 	{
361 		if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ImageButtonCmd" ) ) )
362         {
363 			// just enable this command
364 		    ::com::sun::star::frame::FeatureStateEvent aEvent;
365 			aEvent.FeatureURL = aURL;
366 		    aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
367 			aEvent.IsEnabled = mbButtonEnabled;
368 			aEvent.Requery = sal_False;
369 			aEvent.State <<= Any();
370 			xControl->statusChanged( aEvent );
371         }
372         else if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ComboboxCmd" ) ) )
373 		{
374 			// just enable this command
375 		    ::com::sun::star::frame::FeatureStateEvent aEvent;
376 			aEvent.FeatureURL = aURL;
377 		    aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
378 			aEvent.IsEnabled = sal_True;
379 			aEvent.Requery = sal_False;
380 			aEvent.State <<= Any();
381 			xControl->statusChanged( aEvent );
382 		}
383 		else if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ToggleDropdownButtonCmd" ) ) )
384 		{
385             // A toggle dropdown box is normally used for a group of commands
386             // where the user can select the last issued command easily.
387             // E.g. a typical command group would be "Insert shape"
388             Sequence< NamedValue > aArgs( 1 );
389 
390             // send command to set context menu content
391             Sequence< rtl::OUString > aContextMenu( 3 );
392             aContextMenu[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Command 1" ) );
393             aContextMenu[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Command 2" ) );
394             aContextMenu[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Command 3" ) );
395 
396             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) );
397             aArgs[0].Value <<= aContextMenu;
398             SendCommandTo( xControl, aURL, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SetList" ) ), aArgs, sal_True );
399 
400             // send command to check item on pos=0
401             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pos" ));
402             aArgs[0].Value <<= sal_Int32( 0 );
403             SendCommandTo( xControl, aURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CheckItemPos" ) ), aArgs, sal_True );
404         }
405         else if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DropdownButtonCmd" ) ) )
406         {
407             // A dropdown box is normally used for a group of dependent modes, where
408             // the user can only select one. The modes cannot be combined.
409             // E.g. a typical group would be left,right,center,block.
410             Sequence< NamedValue > aArgs( 1 );
411 
412             // send command to set context menu content
413             Sequence< rtl::OUString > aContextMenu( 2 );
414             aContextMenu[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Button Enabled" ) );
415             aContextMenu[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Button Disabled" ) );
416 
417             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) );
418             aArgs[0].Value <<= aContextMenu;
419             SendCommandTo( xControl, aURL, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SetList" ) ), aArgs, sal_True );
420 
421             // set position according to enable/disable state of button
422             sal_Int32 nPos( mbButtonEnabled ? 0 : 1 );
423 
424             // send command to check item on pos=0
425             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pos" ) );
426             aArgs[0].Value <<= nPos;
427             SendCommandTo( xControl, aURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CheckItemPos" ) ), aArgs, sal_True );
428         }
429         else if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SpinfieldCmd" ) ) )
430         {
431             // A spin button
432             Sequence< NamedValue > aArgs( 5 );
433 
434             // send command to initialize spin button
435             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" ) );
436             aArgs[0].Value <<= double( 0.0 );
437             aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UpperLimit" ) );
438             aArgs[1].Value <<= double( 10.0 );
439             aArgs[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LowerLimit" ) );
440             aArgs[2].Value <<= double( 0.0 );
441             aArgs[3].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Step" ) );
442             aArgs[3].Value <<= double( 0.1 );
443             aArgs[4].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OutputFormat" ) );
444             aArgs[4].Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "%.2f cm" ) );
445 
446             SendCommandTo( xControl, aURL, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SetValues" ) ), aArgs, sal_True );
447         }
448         else if ( aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DropdownboxCmd" ) ) )
449         {
450             // A dropdown box is normally used for a group of commands
451             // where the user can select one of a defined set.
452             Sequence< NamedValue > aArgs( 1 );
453 
454             // send command to set context menu content
455             Sequence< rtl::OUString > aList( 10 );
456             aList[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "White" ) );
457             aList[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Black" ) );
458             aList[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Red" ) );
459             aList[3] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Blue" ) );
460             aList[4] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Green" ) );
461             aList[5] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grey" ) );
462             aList[6] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Yellow" ) );
463             aList[7] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Orange" ) );
464             aList[8] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Brown" ) );
465             aList[9] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pink" ) );
466 
467             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) );
468             aArgs[0].Value <<= aList;
469             SendCommandTo( xControl, aURL, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SetList" ) ), aArgs, sal_True );
470         }
471 
472 		aListenerHelper.AddListener( mxFrame, xControl, aURL.Path );
473 	}
474 }
475 
476 void SAL_CALL BaseDispatch::removeStatusListener( const Reference< XStatusListener >& xControl, const URL& aURL ) throw (RuntimeException)
477 {
478 	aListenerHelper.RemoveListener( mxFrame, xControl, aURL.Path );
479 }
480 
481 void SAL_CALL BaseDispatch::controlEvent( const ControlEvent& Event ) throw (RuntimeException)
482 {
483     if ( Event.aURL.Protocol.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.demo.complextoolbarcontrols.demoaddon:" ) ) )
484 	{
485         if ( Event.aURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ComboboxCmd" ) ) )
486         {
487             // We get notifications whenever the text inside the combobox has been changed.
488             // We store the new text into a member.
489             if ( Event.Event.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "TextChanged" ) ) )
490             {
491                 rtl::OUString aNewText;
492                 sal_Bool      bHasText( sal_False );
493                 for ( sal_Int32 i = 0; i < Event.aInformation.getLength(); i++ )
494                 {
495                     if ( Event.aInformation[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Text" ) ) )
496                     {
497                         bHasText = Event.aInformation[i].Value >>= aNewText;
498                         break;
499                     }
500                 }
501 
502                 if ( bHasText )
503                     maComboBoxText = aNewText;
504             }
505         }
506     }
507 }
508 
509 BaseDispatch::BaseDispatch( const Reference< XMultiServiceFactory > &rxMSF,
510         const Reference< XFrame >& xFrame, const rtl::OUString& rServiceName )
511         : mxMSF( rxMSF )
512 		, mxFrame( xFrame )
513         , msDocService( rServiceName )
514         , mbButtonEnabled( sal_True )
515 {
516 }
517 
518 
519 BaseDispatch::~BaseDispatch()
520 {
521 	mxFrame.clear();
522 	mxMSF.clear();
523 }
524