update credits
[LibreOffice.git] / odk / examples / cpp / complextoolbarcontrols / MyProtocolHandler.cxx
blob07003304ad2ea79e846db54ffb35b8cdf78ac970
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "ListenerHelper.h"
22 #include "MyProtocolHandler.h"
24 #include <com/sun/star/awt/MessageBoxButtons.hpp>
25 #include <com/sun/star/awt/Toolkit.hpp>
26 #include <com/sun/star/awt/XMessageBoxFactory.hpp>
27 #include <com/sun/star/frame/ControlCommand.hpp>
28 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
29 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
30 #include <com/sun/star/system/SystemShellExecute.hpp>
31 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
32 #include <com/sun/star/system/XSystemShellExecute.hpp>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <osl/diagnose.h>
36 using namespace com::sun::star::awt;
37 using namespace com::sun::star::frame;
38 using namespace com::sun::star::system;
39 using namespace com::sun::star::uno;
41 using com::sun::star::beans::NamedValue;
42 using com::sun::star::beans::PropertyValue;
43 using com::sun::star::sheet::XSpreadsheetView;
44 using com::sun::star::text::XTextViewCursorSupplier;
45 using com::sun::star::util::URL;
47 ListenerHelper aListenerHelper;
49 void BaseDispatch::ShowMessageBox( const Reference< XFrame >& rFrame, const ::rtl::OUString& aTitle, const ::rtl::OUString& aMsgText )
51 if ( !mxToolkit.is() )
52 mxToolkit = Toolkit::create(mxContext);
53 Reference< XMessageBoxFactory > xMsgBoxFactory( mxToolkit, UNO_QUERY );
54 if ( rFrame.is() && xMsgBoxFactory.is() )
56 Reference< XMessageBox > xMsgBox = xMsgBoxFactory->createMessageBox(
57 Reference< XWindowPeer >( rFrame->getContainerWindow(), UNO_QUERY ),
58 com::sun::star::awt::MessageBoxType_INFOBOX,
59 MessageBoxButtons::BUTTONS_OK,
60 aTitle,
61 aMsgText );
63 if ( xMsgBox.is() )
64 xMsgBox->execute();
68 void BaseDispatch::SendCommand( const com::sun::star::util::URL& aURL, const ::rtl::OUString& rCommand, const Sequence< NamedValue >& rArgs, sal_Bool bEnabled )
70 Reference < XDispatch > xDispatch =
71 aListenerHelper.GetDispatch( mxFrame, aURL.Path );
73 FeatureStateEvent aEvent;
75 aEvent.FeatureURL = aURL;
76 aEvent.Source = xDispatch;
77 aEvent.IsEnabled = bEnabled;
78 aEvent.Requery = sal_False;
80 ControlCommand aCtrlCmd;
81 aCtrlCmd.Command = rCommand;
82 aCtrlCmd.Arguments = rArgs;
84 aEvent.State <<= aCtrlCmd;
85 aListenerHelper.Notify( mxFrame, aEvent.FeatureURL.Path, aEvent );
88 void BaseDispatch::SendCommandTo( const Reference< XStatusListener >& xControl, const URL& aURL, const ::rtl::OUString& rCommand, const Sequence< NamedValue >& rArgs, sal_Bool bEnabled )
90 FeatureStateEvent aEvent;
92 aEvent.FeatureURL = aURL;
93 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
94 aEvent.IsEnabled = bEnabled;
95 aEvent.Requery = sal_False;
97 ControlCommand aCtrlCmd;
98 aCtrlCmd.Command = rCommand;
99 aCtrlCmd.Arguments = rArgs;
101 aEvent.State <<= aCtrlCmd;
102 xControl->statusChanged( aEvent );
105 void SAL_CALL MyProtocolHandler::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException)
107 Reference < XFrame > xFrame;
108 if ( aArguments.getLength() )
110 // the first Argument is always the Frame, as a ProtocolHandler needs to have access
111 // to the context in which it is invoked.
112 aArguments[0] >>= xFrame;
113 mxFrame = xFrame;
117 Reference< XDispatch > SAL_CALL MyProtocolHandler::queryDispatch( const URL& aURL, const ::rtl::OUString& sTargetFrameName, sal_Int32 nSearchFlags )
118 throw( RuntimeException )
120 Reference < XDispatch > xRet;
121 if ( !mxFrame.is() )
122 return 0;
124 Reference < XController > xCtrl = mxFrame->getController();
125 if ( xCtrl.is() && aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
127 Reference < XTextViewCursorSupplier > xCursor( xCtrl, UNO_QUERY );
128 Reference < XSpreadsheetView > xView( xCtrl, UNO_QUERY );
129 if ( !xCursor.is() && !xView.is() )
130 // without an appropriate corresponding document the handler doesn't function
131 return xRet;
133 if ( aURL.Path == "ImageButtonCmd" ||
134 aURL.Path == "ComboboxCmd" ||
135 aURL.Path == "ToggleDropdownButtonCmd" ||
136 aURL.Path == "DropdownButtonCmd" ||
137 aURL.Path == "SpinfieldCmd" ||
138 aURL.Path == "EditfieldCmd" ||
139 aURL.Path == "DropdownboxCmd" )
141 xRet = aListenerHelper.GetDispatch( mxFrame, aURL.Path );
142 if ( !xRet.is() )
144 xRet = xCursor.is() ? (BaseDispatch*) new WriterDispatch( mxContext, mxFrame ) :
145 (BaseDispatch*) new CalcDispatch( mxContext, mxFrame );
146 aListenerHelper.AddDispatch( xRet, mxFrame, aURL.Path );
151 return xRet;
154 Sequence < Reference< XDispatch > > SAL_CALL MyProtocolHandler::queryDispatches( const Sequence < DispatchDescriptor >& seqDescripts )
155 throw( RuntimeException )
157 sal_Int32 nCount = seqDescripts.getLength();
158 Sequence < Reference < XDispatch > > lDispatcher( nCount );
160 for( sal_Int32 i=0; i<nCount; ++i )
161 lDispatcher[i] = queryDispatch( seqDescripts[i].FeatureURL, seqDescripts[i].FrameName, seqDescripts[i].SearchFlags );
163 return lDispatcher;
166 ::rtl::OUString MyProtocolHandler_getImplementationName ()
167 throw (RuntimeException)
169 return ::rtl::OUString( MYPROTOCOLHANDLER_IMPLEMENTATIONNAME );
172 Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler_getSupportedServiceNames( )
173 throw (RuntimeException)
175 Sequence < ::rtl::OUString > aRet(1);
176 aRet[0] = ::rtl::OUString( MYPROTOCOLHANDLER_SERVICENAME );
177 return aRet;
180 #undef SERVICE_NAME
182 Reference< XInterface > SAL_CALL MyProtocolHandler_createInstance( const Reference< XComponentContext > & rSMgr)
183 throw( Exception )
185 return (cppu::OWeakObject*) new MyProtocolHandler( rSMgr );
188 // XServiceInfo
189 ::rtl::OUString SAL_CALL MyProtocolHandler::getImplementationName( )
190 throw (RuntimeException)
192 return MyProtocolHandler_getImplementationName();
195 sal_Bool SAL_CALL MyProtocolHandler::supportsService( const ::rtl::OUString& rServiceName )
196 throw (RuntimeException)
198 return cppu::supportsService(this, rServiceName);
201 Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler::getSupportedServiceNames( )
202 throw (RuntimeException)
204 return MyProtocolHandler_getSupportedServiceNames();
207 void SAL_CALL BaseDispatch::dispatch( const URL& aURL, const Sequence < PropertyValue >& lArgs ) throw (RuntimeException)
209 /* Its necessary to hold this object alive, till this method finish.
210 May the outside dispatch cache (implemented by the menu/toolbar!)
211 forget this instance during de-/activation of frames (focus!).
213 E.g. An open db beamer in combination with the My-Dialog
214 can force such strange situation :-(
216 Reference< XInterface > xSelfHold(static_cast< XDispatch* >(this), UNO_QUERY);
218 if ( aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
220 if ( aURL.Path == "ImageButtonCmd" )
222 // open the LibreOffice web page
223 ::rtl::OUString sURL("http://www.libreoffice.org");
224 Reference< XSystemShellExecute > xSystemShellExecute(
225 SystemShellExecute::create(mxContext) );
228 xSystemShellExecute->execute( sURL, ::rtl::OUString(), SystemShellExecuteFlags::URIS_ONLY );
230 catch( Exception& rEx )
232 (void)rEx;
235 else if ( aURL.Path == "ComboboxCmd" )
237 // remove the text if it's in our list
238 Sequence< NamedValue > aRemoveArgs( 1 );
239 aRemoveArgs[0].Name = rtl::OUString( "Text" );
240 aRemoveArgs[0].Value <<= maComboBoxText;
241 SendCommand( aURL, ::rtl::OUString( "RemoveEntryText" ), aRemoveArgs, sal_True );
243 // add the new text to the start of the list
244 Sequence< NamedValue > aInsertArgs( 2 );
245 aInsertArgs[0].Name = rtl::OUString( "Pos" );
246 aInsertArgs[0].Value <<= sal_Int32( 0 );
247 aInsertArgs[1].Name = rtl::OUString( "Text" );
248 aInsertArgs[1].Value <<= maComboBoxText;
249 SendCommand( aURL, ::rtl::OUString("InsertEntry"), aInsertArgs, sal_True );
251 else if ( aURL.Path == "InsertEntry" )
253 // Retrieve the text argument from the sequence property value
254 rtl::OUString aText;
255 for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
257 if ( lArgs[i].Name == "Text" )
259 lArgs[i].Value >>= aText;
260 break;
264 // create new URL to address the combox box
265 URL aCmdURL;
266 aCmdURL.Path = "ComboboxCmd";
267 aCmdURL.Protocol = "vnd.demo.complextoolbarcontrols.demoaddon:";
268 aCmdURL.Complete = aCmdURL.Path + aCmdURL.Protocol;
270 // set the selected item as text into the combobox
271 Sequence< NamedValue > aArgs( 1 );
272 aArgs[0].Name = "Text";
273 aArgs[0].Value <<= aText;
274 SendCommand( aCmdURL, ::rtl::OUString( "SetText" ), aArgs, sal_True );
276 else if ( aURL.Path == "DropdownButtonCmd" )
278 // Retrieve the text argument from the sequence property value
279 rtl::OUString aText;
280 for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
282 if ( lArgs[i].Name == "Text" )
284 lArgs[i].Value >>= aText;
285 break;
289 // just enable this command
291 // set enable flag according to selection
292 if ( aText == "Button Disabled" )
293 mbButtonEnabled = sal_False;
294 else
295 mbButtonEnabled = sal_True;
297 // create new URL to address the image button
298 URL aCmdURL;
299 aCmdURL.Path = "Command1";
300 aCmdURL.Protocol = "vnd.demo.complextoolbarcontrols.demoaddon:";
301 aCmdURL.Complete = aCmdURL.Path + aCmdURL.Protocol;
303 // create and initialize FeatureStateEvent with IsEnabled
304 ::com::sun::star::frame::FeatureStateEvent aEvent;
305 aEvent.FeatureURL = aCmdURL;
306 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
307 aEvent.IsEnabled = mbButtonEnabled;
308 aEvent.Requery = sal_False;
309 aEvent.State <<= Any();
311 // Notify listener about new state
312 Reference < XDispatch > xDispatch = aListenerHelper.GetDispatch( mxFrame, aURL.Path );
313 aListenerHelper.Notify( mxFrame, aEvent.FeatureURL.Path, aEvent );
315 else if ( aURL.Path == "SpinfieldCmd" )
318 else if ( aURL.Path == "DropdownboxCmd" )
320 // Retrieve the text argument from the sequence property value
321 rtl::OUString aText;
322 for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
324 if ( lArgs[i].Name == "Text" )
326 lArgs[i].Value >>= aText;
327 break;
330 OSL_TRACE( "Dropdownbox control - selected entry text : %s",
331 rtl::OUStringToOString( aText, RTL_TEXTENCODING_UTF8 ).getStr() );
336 void SAL_CALL BaseDispatch::addStatusListener( const Reference< XStatusListener >& xControl, const URL& aURL ) throw (RuntimeException)
338 if ( aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
340 if ( aURL.Path == "ImageButtonCmd" )
342 // just enable this command
343 ::com::sun::star::frame::FeatureStateEvent aEvent;
344 aEvent.FeatureURL = aURL;
345 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
346 aEvent.IsEnabled = mbButtonEnabled;
347 aEvent.Requery = sal_False;
348 aEvent.State <<= Any();
349 xControl->statusChanged( aEvent );
351 else if ( aURL.Path == "ComboboxCmd" )
353 // just enable this command
354 ::com::sun::star::frame::FeatureStateEvent aEvent;
355 aEvent.FeatureURL = aURL;
356 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
357 aEvent.IsEnabled = sal_True;
358 aEvent.Requery = sal_False;
359 aEvent.State <<= Any();
360 xControl->statusChanged( aEvent );
362 else if ( aURL.Path == "ToggleDropdownButtonCmd" )
364 // A toggle dropdown box is normally used for a group of commands
365 // where the user can select the last issued command easily.
366 // E.g. a typical command group would be "Insert shape"
367 Sequence< NamedValue > aArgs( 1 );
369 // send command to set context menu content
370 Sequence< rtl::OUString > aContextMenu( 3 );
371 aContextMenu[0] = "Command 1";
372 aContextMenu[1] = "Command 2";
373 aContextMenu[2] = "Command 3";
375 aArgs[0].Name = "List";
376 aArgs[0].Value <<= aContextMenu;
377 SendCommandTo( xControl, aURL, rtl::OUString( "SetList" ), aArgs, sal_True );
379 // send command to check item on pos=0
380 aArgs[0].Name = rtl::OUString( "Pos" );
381 aArgs[0].Value <<= sal_Int32( 0 );
382 SendCommandTo( xControl, aURL, ::rtl::OUString( "CheckItemPos" ), aArgs, sal_True );
384 else if ( aURL.Path == "DropdownButtonCmd" )
386 // A dropdown box is normally used for a group of dependent modes, where
387 // the user can only select one. The modes cannot be combined.
388 // E.g. a typical group would be left,right,center,block.
389 Sequence< NamedValue > aArgs( 1 );
391 // send command to set context menu content
392 Sequence< rtl::OUString > aContextMenu( 2 );
393 aContextMenu[0] = "Button Enabled";
394 aContextMenu[1] = "Button Disabled";
396 aArgs[0].Name = "List";
397 aArgs[0].Value <<= aContextMenu;
398 SendCommandTo( xControl, aURL, rtl::OUString( "SetList" ), aArgs, sal_True );
400 // set position according to enable/disable state of button
401 sal_Int32 nPos( mbButtonEnabled ? 0 : 1 );
403 // send command to check item on pos=0
404 aArgs[0].Name = "Pos";
405 aArgs[0].Value <<= nPos;
406 SendCommandTo( xControl, aURL, ::rtl::OUString( "CheckItemPos" ), aArgs, sal_True );
408 else if ( aURL.Path == "SpinfieldCmd" )
410 // A spin button
411 Sequence< NamedValue > aArgs( 5 );
413 // send command to initialize spin button
414 aArgs[0].Name = "Value";
415 aArgs[0].Value <<= double( 0.0 );
416 aArgs[1].Name = "UpperLimit";
417 aArgs[1].Value <<= double( 10.0 );
418 aArgs[2].Name = "LowerLimit";
419 aArgs[2].Value <<= double( 0.0 );
420 aArgs[3].Name = "Step";
421 aArgs[3].Value <<= double( 0.1 );
422 aArgs[4].Name = "OutputFormat";
423 aArgs[4].Value <<= rtl::OUString("%.2f cm");
425 SendCommandTo( xControl, aURL, rtl::OUString( "SetValues" ), aArgs, sal_True );
427 else if ( aURL.Path == "DropdownboxCmd" )
429 // A dropdown box is normally used for a group of commands
430 // where the user can select one of a defined set.
431 Sequence< NamedValue > aArgs( 1 );
433 // send command to set context menu content
434 Sequence< rtl::OUString > aList( 10 );
435 aList[0] = "White";
436 aList[1] = "Black";
437 aList[2] = "Red";
438 aList[3] = "Blue";
439 aList[4] = "Green";
440 aList[5] = "Grey";
441 aList[6] = "Yellow";
442 aList[7] = "Orange";
443 aList[8] = "Brown";
444 aList[9] = "Pink";
446 aArgs[0].Name = "List";
447 aArgs[0].Value <<= aList;
448 SendCommandTo( xControl, aURL, rtl::OUString( "SetList" ), aArgs, sal_True );
451 aListenerHelper.AddListener( mxFrame, xControl, aURL.Path );
455 void SAL_CALL BaseDispatch::removeStatusListener( const Reference< XStatusListener >& xControl, const URL& aURL ) throw (RuntimeException)
457 aListenerHelper.RemoveListener( mxFrame, xControl, aURL.Path );
460 void SAL_CALL BaseDispatch::controlEvent( const ControlEvent& Event ) throw (RuntimeException)
462 if ( Event.aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
464 if ( Event.aURL.Path == "ComboboxCmd" )
466 // We get notifications whenever the text inside the combobox has been changed.
467 // We store the new text into a member.
468 if ( Event.Event == "TextChanged" )
470 rtl::OUString aNewText;
471 sal_Bool bHasText( sal_False );
472 for ( sal_Int32 i = 0; i < Event.aInformation.getLength(); i++ )
474 if ( Event.aInformation[i].Name == "Text" )
476 bHasText = Event.aInformation[i].Value >>= aNewText;
477 break;
481 if ( bHasText )
482 maComboBoxText = aNewText;
488 BaseDispatch::BaseDispatch( const Reference< XComponentContext > &rxContext,
489 const Reference< XFrame >& xFrame,
490 const ::rtl::OUString& rServiceName )
491 : mxContext( rxContext )
492 , mxFrame( xFrame )
493 , msDocService( rServiceName )
494 , mbButtonEnabled( sal_True )
498 BaseDispatch::~BaseDispatch()
500 mxFrame.clear();
501 mxContext.clear();
504 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */