Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / odk / examples / cpp / complextoolbarcontrols / MyProtocolHandler.cxx
blob4020953b68a8356b610eab182c72fadf5ee70850
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>
35 using namespace com::sun::star::awt;
36 using namespace com::sun::star::frame;
37 using namespace com::sun::star::system;
38 using namespace com::sun::star::uno;
40 using com::sun::star::beans::NamedValue;
41 using com::sun::star::beans::PropertyValue;
42 using com::sun::star::sheet::XSpreadsheetView;
43 using com::sun::star::text::XTextViewCursorSupplier;
44 using com::sun::star::util::URL;
46 ListenerHelper aListenerHelper;
48 void BaseDispatch::ShowMessageBox( const Reference< XFrame >& rFrame, const ::rtl::OUString& aTitle, const ::rtl::OUString& aMsgText )
50 if ( !mxToolkit.is() )
51 mxToolkit = Toolkit::create(mxContext);
52 Reference< XMessageBoxFactory > xMsgBoxFactory( mxToolkit, UNO_QUERY );
53 if ( rFrame.is() && xMsgBoxFactory.is() )
55 Reference< XMessageBox > xMsgBox = xMsgBoxFactory->createMessageBox(
56 Reference< XWindowPeer >( rFrame->getContainerWindow(), UNO_QUERY ),
57 com::sun::star::awt::MessageBoxType_INFOBOX,
58 MessageBoxButtons::BUTTONS_OK,
59 aTitle,
60 aMsgText );
62 if ( xMsgBox.is() )
63 xMsgBox->execute();
67 void BaseDispatch::SendCommand( const com::sun::star::util::URL& aURL, const ::rtl::OUString& rCommand, const Sequence< NamedValue >& rArgs, sal_Bool bEnabled )
69 Reference < XDispatch > xDispatch =
70 aListenerHelper.GetDispatch( mxFrame, aURL.Path );
72 FeatureStateEvent aEvent;
74 aEvent.FeatureURL = aURL;
75 aEvent.Source = xDispatch;
76 aEvent.IsEnabled = bEnabled;
77 aEvent.Requery = sal_False;
79 ControlCommand aCtrlCmd;
80 aCtrlCmd.Command = rCommand;
81 aCtrlCmd.Arguments = rArgs;
83 aEvent.State <<= aCtrlCmd;
84 aListenerHelper.Notify( mxFrame, aEvent.FeatureURL.Path, aEvent );
87 void BaseDispatch::SendCommandTo( const Reference< XStatusListener >& xControl, const URL& aURL, const ::rtl::OUString& rCommand, const Sequence< NamedValue >& rArgs, sal_Bool bEnabled )
89 FeatureStateEvent aEvent;
91 aEvent.FeatureURL = aURL;
92 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
93 aEvent.IsEnabled = bEnabled;
94 aEvent.Requery = sal_False;
96 ControlCommand aCtrlCmd;
97 aCtrlCmd.Command = rCommand;
98 aCtrlCmd.Arguments = rArgs;
100 aEvent.State <<= aCtrlCmd;
101 xControl->statusChanged( aEvent );
104 void SAL_CALL MyProtocolHandler::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException)
106 Reference < XFrame > xFrame;
107 if ( aArguments.getLength() )
109 // the first Argument is always the Frame, as a ProtocolHandler needs to have access
110 // to the context in which it is invoked.
111 aArguments[0] >>= xFrame;
112 mxFrame = xFrame;
116 Reference< XDispatch > SAL_CALL MyProtocolHandler::queryDispatch( const URL& aURL, const ::rtl::OUString& sTargetFrameName, sal_Int32 nSearchFlags )
117 throw( RuntimeException )
119 Reference < XDispatch > xRet;
120 if ( !mxFrame.is() )
121 return 0;
123 Reference < XController > xCtrl = mxFrame->getController();
124 if ( xCtrl.is() && aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
126 Reference < XTextViewCursorSupplier > xCursor( xCtrl, UNO_QUERY );
127 Reference < XSpreadsheetView > xView( xCtrl, UNO_QUERY );
128 if ( !xCursor.is() && !xView.is() )
129 // without an appropriate corresponding document the handler doesn't function
130 return xRet;
132 if ( aURL.Path == "ImageButtonCmd" ||
133 aURL.Path == "ComboboxCmd" ||
134 aURL.Path == "ToggleDropdownButtonCmd" ||
135 aURL.Path == "DropdownButtonCmd" ||
136 aURL.Path == "SpinfieldCmd" ||
137 aURL.Path == "EditfieldCmd" ||
138 aURL.Path == "DropdownboxCmd" )
140 xRet = aListenerHelper.GetDispatch( mxFrame, aURL.Path );
141 if ( !xRet.is() )
143 xRet = xCursor.is() ? (BaseDispatch*) new WriterDispatch( mxContext, mxFrame ) :
144 (BaseDispatch*) new CalcDispatch( mxContext, mxFrame );
145 aListenerHelper.AddDispatch( xRet, mxFrame, aURL.Path );
150 return xRet;
153 Sequence < Reference< XDispatch > > SAL_CALL MyProtocolHandler::queryDispatches( const Sequence < DispatchDescriptor >& seqDescripts )
154 throw( RuntimeException )
156 sal_Int32 nCount = seqDescripts.getLength();
157 Sequence < Reference < XDispatch > > lDispatcher( nCount );
159 for( sal_Int32 i=0; i<nCount; ++i )
160 lDispatcher[i] = queryDispatch( seqDescripts[i].FeatureURL, seqDescripts[i].FrameName, seqDescripts[i].SearchFlags );
162 return lDispatcher;
165 ::rtl::OUString MyProtocolHandler_getImplementationName ()
166 throw (RuntimeException)
168 return ::rtl::OUString( MYPROTOCOLHANDLER_IMPLEMENTATIONNAME );
171 Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler_getSupportedServiceNames( )
172 throw (RuntimeException)
174 Sequence < ::rtl::OUString > aRet(1);
175 aRet[0] = ::rtl::OUString( MYPROTOCOLHANDLER_SERVICENAME );
176 return aRet;
179 #undef SERVICE_NAME
181 Reference< XInterface > SAL_CALL MyProtocolHandler_createInstance( const Reference< XComponentContext > & rSMgr)
182 throw( Exception )
184 return (cppu::OWeakObject*) new MyProtocolHandler( rSMgr );
187 // XServiceInfo
188 ::rtl::OUString SAL_CALL MyProtocolHandler::getImplementationName( )
189 throw (RuntimeException)
191 return MyProtocolHandler_getImplementationName();
194 sal_Bool SAL_CALL MyProtocolHandler::supportsService( const ::rtl::OUString& rServiceName )
195 throw (RuntimeException)
197 return cppu::supportsService(this, rServiceName);
200 Sequence< ::rtl::OUString > SAL_CALL MyProtocolHandler::getSupportedServiceNames( )
201 throw (RuntimeException)
203 return MyProtocolHandler_getSupportedServiceNames();
206 void SAL_CALL BaseDispatch::dispatch( const URL& aURL, const Sequence < PropertyValue >& lArgs ) throw (RuntimeException)
208 /* It's necessary to hold this object alive, till this method finishes.
209 May the outside dispatch cache (implemented by the menu/toolbar!)
210 forget this instance during de-/activation of frames (focus!).
212 E.g. An open db beamer in combination with the My-Dialog
213 can force such strange situation :-(
215 Reference< XInterface > xSelfHold(static_cast< XDispatch* >(this), UNO_QUERY);
217 if ( aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
219 if ( aURL.Path == "ImageButtonCmd" )
221 // open the LibreOffice web page
222 ::rtl::OUString sURL("http://www.libreoffice.org");
223 Reference< XSystemShellExecute > xSystemShellExecute(
224 SystemShellExecute::create(mxContext) );
227 xSystemShellExecute->execute( sURL, ::rtl::OUString(), SystemShellExecuteFlags::URIS_ONLY );
229 catch( Exception& rEx )
231 (void)rEx;
234 else if ( aURL.Path == "ComboboxCmd" )
236 // remove the text if it's in our list
237 Sequence< NamedValue > aRemoveArgs( 1 );
238 aRemoveArgs[0].Name = rtl::OUString( "Text" );
239 aRemoveArgs[0].Value <<= maComboBoxText;
240 SendCommand( aURL, ::rtl::OUString( "RemoveEntryText" ), aRemoveArgs, sal_True );
242 // add the new text to the start of the list
243 Sequence< NamedValue > aInsertArgs( 2 );
244 aInsertArgs[0].Name = rtl::OUString( "Pos" );
245 aInsertArgs[0].Value <<= sal_Int32( 0 );
246 aInsertArgs[1].Name = rtl::OUString( "Text" );
247 aInsertArgs[1].Value <<= maComboBoxText;
248 SendCommand( aURL, ::rtl::OUString("InsertEntry"), aInsertArgs, sal_True );
250 else if ( aURL.Path == "InsertEntry" )
252 // Retrieve the text argument from the sequence property value
253 rtl::OUString aText;
254 for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
256 if ( lArgs[i].Name == "Text" )
258 lArgs[i].Value >>= aText;
259 break;
263 // create new URL to address the combox box
264 URL aCmdURL;
265 aCmdURL.Path = "ComboboxCmd";
266 aCmdURL.Protocol = "vnd.demo.complextoolbarcontrols.demoaddon:";
267 aCmdURL.Complete = aCmdURL.Path + aCmdURL.Protocol;
269 // set the selected item as text into the combobox
270 Sequence< NamedValue > aArgs( 1 );
271 aArgs[0].Name = "Text";
272 aArgs[0].Value <<= aText;
273 SendCommand( aCmdURL, ::rtl::OUString( "SetText" ), aArgs, sal_True );
275 else if ( aURL.Path == "DropdownButtonCmd" )
277 // Retrieve the text argument from the sequence property value
278 rtl::OUString aText;
279 for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
281 if ( lArgs[i].Name == "Text" )
283 lArgs[i].Value >>= aText;
284 break;
288 // just enable this command
290 // set enable flag according to selection
291 if ( aText == "Button Disabled" )
292 mbButtonEnabled = sal_False;
293 else
294 mbButtonEnabled = sal_True;
296 // create new URL to address the image button
297 URL aCmdURL;
298 aCmdURL.Path = "Command1";
299 aCmdURL.Protocol = "vnd.demo.complextoolbarcontrols.demoaddon:";
300 aCmdURL.Complete = aCmdURL.Path + aCmdURL.Protocol;
302 // create and initialize FeatureStateEvent with IsEnabled
303 ::com::sun::star::frame::FeatureStateEvent aEvent;
304 aEvent.FeatureURL = aCmdURL;
305 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
306 aEvent.IsEnabled = mbButtonEnabled;
307 aEvent.Requery = sal_False;
308 aEvent.State = Any();
310 // Notify listener about new state
311 Reference < XDispatch > xDispatch = aListenerHelper.GetDispatch( mxFrame, aURL.Path );
312 aListenerHelper.Notify( mxFrame, aEvent.FeatureURL.Path, aEvent );
314 else if ( aURL.Path == "SpinfieldCmd" )
317 else if ( aURL.Path == "DropdownboxCmd" )
319 // Retrieve the text argument from the sequence property value
320 rtl::OUString aText;
321 for ( sal_Int32 i = 0; i < lArgs.getLength(); i++ )
323 if ( lArgs[i].Name == "Text" )
325 lArgs[i].Value >>= aText;
326 break;
333 void SAL_CALL BaseDispatch::addStatusListener( const Reference< XStatusListener >& xControl, const URL& aURL ) throw (RuntimeException)
335 if ( aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
337 if ( aURL.Path == "ImageButtonCmd" )
339 // just enable this command
340 ::com::sun::star::frame::FeatureStateEvent aEvent;
341 aEvent.FeatureURL = aURL;
342 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
343 aEvent.IsEnabled = mbButtonEnabled;
344 aEvent.Requery = sal_False;
345 aEvent.State = Any();
346 xControl->statusChanged( aEvent );
348 else if ( aURL.Path == "ComboboxCmd" )
350 // just enable this command
351 ::com::sun::star::frame::FeatureStateEvent aEvent;
352 aEvent.FeatureURL = aURL;
353 aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
354 aEvent.IsEnabled = sal_True;
355 aEvent.Requery = sal_False;
356 aEvent.State = Any();
357 xControl->statusChanged( aEvent );
359 else if ( aURL.Path == "ToggleDropdownButtonCmd" )
361 // A toggle dropdown box is normally used for a group of commands
362 // where the user can select the last issued command easily.
363 // E.g. a typical command group would be "Insert shape"
364 Sequence< NamedValue > aArgs( 1 );
366 // send command to set context menu content
367 Sequence< rtl::OUString > aContextMenu( 3 );
368 aContextMenu[0] = "Command 1";
369 aContextMenu[1] = "Command 2";
370 aContextMenu[2] = "Command 3";
372 aArgs[0].Name = "List";
373 aArgs[0].Value <<= aContextMenu;
374 SendCommandTo( xControl, aURL, rtl::OUString( "SetList" ), aArgs, sal_True );
376 // send command to check item on pos=0
377 aArgs[0].Name = rtl::OUString( "Pos" );
378 aArgs[0].Value <<= sal_Int32( 0 );
379 SendCommandTo( xControl, aURL, ::rtl::OUString( "CheckItemPos" ), aArgs, sal_True );
381 else if ( aURL.Path == "DropdownButtonCmd" )
383 // A dropdown box is normally used for a group of dependent modes, where
384 // the user can only select one. The modes cannot be combined.
385 // E.g. a typical group would be left,right,center,block.
386 Sequence< NamedValue > aArgs( 1 );
388 // send command to set context menu content
389 Sequence< rtl::OUString > aContextMenu( 2 );
390 aContextMenu[0] = "Button Enabled";
391 aContextMenu[1] = "Button Disabled";
393 aArgs[0].Name = "List";
394 aArgs[0].Value <<= aContextMenu;
395 SendCommandTo( xControl, aURL, rtl::OUString( "SetList" ), aArgs, sal_True );
397 // set position according to enable/disable state of button
398 sal_Int32 nPos( mbButtonEnabled ? 0 : 1 );
400 // send command to check item on pos=0
401 aArgs[0].Name = "Pos";
402 aArgs[0].Value <<= nPos;
403 SendCommandTo( xControl, aURL, ::rtl::OUString( "CheckItemPos" ), aArgs, sal_True );
405 else if ( aURL.Path == "SpinfieldCmd" )
407 // A spin button
408 Sequence< NamedValue > aArgs( 5 );
410 // send command to initialize spin button
411 aArgs[0].Name = "Value";
412 aArgs[0].Value <<= double( 0.0 );
413 aArgs[1].Name = "UpperLimit";
414 aArgs[1].Value <<= double( 10.0 );
415 aArgs[2].Name = "LowerLimit";
416 aArgs[2].Value <<= double( 0.0 );
417 aArgs[3].Name = "Step";
418 aArgs[3].Value <<= double( 0.1 );
419 aArgs[4].Name = "OutputFormat";
420 aArgs[4].Value <<= rtl::OUString("%.2f cm");
422 SendCommandTo( xControl, aURL, rtl::OUString( "SetValues" ), aArgs, sal_True );
424 else if ( aURL.Path == "DropdownboxCmd" )
426 // A dropdown box is normally used for a group of commands
427 // where the user can select one of a defined set.
428 Sequence< NamedValue > aArgs( 1 );
430 // send command to set context menu content
431 Sequence< rtl::OUString > aList( 10 );
432 aList[0] = "White";
433 aList[1] = "Black";
434 aList[2] = "Red";
435 aList[3] = "Blue";
436 aList[4] = "Green";
437 aList[5] = "Grey";
438 aList[6] = "Yellow";
439 aList[7] = "Orange";
440 aList[8] = "Brown";
441 aList[9] = "Pink";
443 aArgs[0].Name = "List";
444 aArgs[0].Value <<= aList;
445 SendCommandTo( xControl, aURL, rtl::OUString( "SetList" ), aArgs, sal_True );
448 aListenerHelper.AddListener( mxFrame, xControl, aURL.Path );
452 void SAL_CALL BaseDispatch::removeStatusListener( const Reference< XStatusListener >& xControl, const URL& aURL ) throw (RuntimeException)
454 aListenerHelper.RemoveListener( mxFrame, xControl, aURL.Path );
457 void SAL_CALL BaseDispatch::controlEvent( const ControlEvent& Event ) throw (RuntimeException)
459 if ( Event.aURL.Protocol == "vnd.demo.complextoolbarcontrols.demoaddon:" )
461 if ( Event.aURL.Path == "ComboboxCmd" )
463 // We get notifications whenever the text inside the combobox has been changed.
464 // We store the new text into a member.
465 if ( Event.Event == "TextChanged" )
467 rtl::OUString aNewText;
468 sal_Bool bHasText( sal_False );
469 for ( sal_Int32 i = 0; i < Event.aInformation.getLength(); i++ )
471 if ( Event.aInformation[i].Name == "Text" )
473 bHasText = Event.aInformation[i].Value >>= aNewText;
474 break;
478 if ( bHasText )
479 maComboBoxText = aNewText;
485 BaseDispatch::BaseDispatch( const Reference< XComponentContext > &rxContext,
486 const Reference< XFrame >& xFrame,
487 const ::rtl::OUString& rServiceName )
488 : mxContext( rxContext )
489 , mxFrame( xFrame )
490 , msDocService( rServiceName )
491 , mbButtonEnabled( sal_True )
495 BaseDispatch::~BaseDispatch()
497 mxFrame.clear();
498 mxContext.clear();
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */