1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "ChartController.hxx"
27 #include "servicenames.hxx"
28 #include "ResId.hxx"
29 #include "dlg_DataSource.hxx"
30 #include "ChartModelHelper.hxx"
31 #include "ControllerCommandDispatch.hxx"
32 #include "Strings.hrc"
33 #include "chartview/ExplicitValueProvider.hxx"
34 #include "ChartViewHelper.hxx"
35
36 #include "ChartWindow.hxx"
37 #include "chartview/DrawModelWrapper.hxx"
38 #include "DrawViewWrapper.hxx"
39 #include "ObjectIdentifier.hxx"
40 #include "DiagramHelper.hxx"
41 #include "ControllerLockGuard.hxx"
42 #include "UndoGuard.hxx"
43 #include "ChartDropTargetHelper.hxx"
44
45 #include "macros.hxx"
46 #include "dlg_CreationWizard.hxx"
47 #include "dlg_ChartType.hxx"
48 #include "AccessibleChartView.hxx"
49 #include "DrawCommandDispatch.hxx"
50 #include "ShapeController.hxx"
51 #include "UndoActions.hxx"
52
53 #include <comphelper/InlineContainer.hxx>
54
55 #include <com/sun/star/awt/PosSize.hpp>
56 #include <com/sun/star/chart2/XChartDocument.hpp>
57 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
58 #include <com/sun/star/frame/XLoadable.hpp>
59 #include <com/sun/star/util/XCloneable.hpp>
60 #include <com/sun/star/embed/XEmbeddedClient.hpp>
61 #include <com/sun/star/util/XModeChangeBroadcaster.hpp>
62 #include <com/sun/star/util/XModifyBroadcaster.hpp>
63 #include <com/sun/star/frame/LayoutManagerEvents.hpp>
64 #include <com/sun/star/document/XUndoManagerSupplier.hpp>
65 #include <com/sun/star/document/XUndoAction.hpp>
66
67 //-------
68 // header for define RET_OK
69 #include <vcl/msgbox.hxx>
70 //-------
71
72 //-------
73 #include <toolkit/awt/vclxwindow.hxx>
74 #include <toolkit/helper/vclunohelper.hxx>
75 #include <vcl/svapp.hxx>
76 #include <vos/mutex.hxx>
77 //-------
78 #include <com/sun/star/frame/XLayoutManager.hpp>
79 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
80
81 // this is needed to properly destroy the auto_ptr to the AcceleratorExecute
82 // object in the DTOR
83 #include <svtools/acceleratorexecute.hxx>
84 #include <svx/ActionDescriptionProvider.hxx>
85 #include <tools/diagnose_ex.h>
86
87 // enable the following define to let the controller listen to model changes and
88 // react on this by rebuilding the view
89 #define TEST_ENABLE_MODIFY_LISTENER
90
91 /*
92 #include <vcl/svapp.hxx>
93 */
94
95 //.............................................................................
96 namespace chart
97 {
98 //.............................................................................
99
100 using namespace ::com::sun::star;
101 using namespace ::com::sun::star::accessibility;
102 using namespace ::com::sun::star::chart2;
103 using ::com::sun::star::uno::Any;
104 using ::com::sun::star::uno::Reference;
105 using ::com::sun::star::uno::Sequence;
DBG_NAME(ChartController)106 DBG_NAME(ChartController)
107 //-----------------------------------------------------------------
108 // ChartController Constructor and Destructor
109 //-----------------------------------------------------------------
110
111 ChartController::ChartController(uno::Reference<uno::XComponentContext> const & xContext)
112 : m_aLifeTimeManager( NULL )
113 , m_bSuspended( sal_False )
114 , m_bCanClose( sal_True )
115 , m_xCC(xContext) //@todo is it allowed to hold this context??
116 , m_xFrame( NULL )
117 , m_aModelMutex()
118 , m_aModel( NULL, m_aModelMutex )
119 , m_pChartWindow( NULL )
120 , m_xViewWindow()
121 , m_xChartView()
122 , m_pDrawModelWrapper()
123 , m_pDrawViewWrapper(NULL)
124 , m_eDragMode(SDRDRAG_MOVE)
125 , m_bWaitingForDoubleClick(false)
126 , m_bWaitingForMouseUp(false)
127 , m_bConnectingToView(false)
128 , m_xUndoManager( 0 )
129 , m_aDispatchContainer( m_xCC, this )
130 , m_eDrawMode( CHARTDRAW_SELECT )
131 {
132 DBG_CTOR(ChartController,NULL);
133 m_aDoubleClickTimer.SetTimeoutHdl( LINK( this, ChartController, DoubleClickWaitingHdl ) );
134 }
135
~ChartController()136 ChartController::~ChartController()
137 {
138 DBG_DTOR(ChartController,NULL);
139 stopDoubleClickWaiting();
140 }
141
142 //-----------------------------------------------------------------
143
RefCountable()144 ChartController::RefCountable::RefCountable() : m_nRefCount(0)
145 {
146 }
147
~RefCountable()148 ChartController::RefCountable::~RefCountable()
149 {
150 }
acquire()151 void ChartController::RefCountable::acquire()
152 {
153 m_nRefCount++;
154 }
release()155 void ChartController::RefCountable::release()
156 {
157 m_nRefCount--;
158 if(!m_nRefCount)
159 delete this;
160 }
161
162 //-----------------------------------------------------------------
163
TheModel(const uno::Reference<frame::XModel> & xModel)164 ChartController::TheModel::TheModel( const uno::Reference< frame::XModel > & xModel )
165 : m_xModel( xModel )
166 , m_xCloseable( NULL )
167 , m_bOwnership( sal_True )
168 , m_bOwnershipIsWellKnown( sal_False )
169 {
170 m_xCloseable =
171 uno::Reference< util::XCloseable >( xModel, uno::UNO_QUERY );
172 }
173
~TheModel()174 ChartController::TheModel::~TheModel()
175 {
176 }
177
SetOwnerShip(sal_Bool bGetsOwnership)178 void ChartController::TheModel::SetOwnerShip( sal_Bool bGetsOwnership )
179 {
180 m_bOwnership = bGetsOwnership;
181 m_bOwnershipIsWellKnown = sal_True;
182 }
183
addListener(ChartController * pController)184 void ChartController::TheModel::addListener( ChartController* pController )
185 {
186 if(m_xCloseable.is())
187 {
188 //if you need to be able to veto against the destruction of the model
189 // you must add as a close listener
190
191 //otherwise you 'can' add as closelistener or 'must' add as dispose event listener
192
193 m_xCloseable->addCloseListener(
194 static_cast<util::XCloseListener*>(pController) );
195 }
196 else if( m_xModel.is() )
197 {
198 //we need to add as dispose event listener
199 m_xModel->addEventListener(
200 static_cast<util::XCloseListener*>(pController) );
201 }
202
203 }
204
removeListener(ChartController * pController)205 void ChartController::TheModel::removeListener( ChartController* pController )
206 {
207 if(m_xCloseable.is())
208 m_xCloseable->removeCloseListener(
209 static_cast<util::XCloseListener*>(pController) );
210
211 else if( m_xModel.is() )
212 m_xModel->removeEventListener(
213 static_cast<util::XCloseListener*>(pController) );
214 }
215
tryTermination()216 void ChartController::TheModel::tryTermination()
217 {
218 if(!m_bOwnership)
219 return;
220
221 try
222 {
223 if(m_xCloseable.is())
224 {
225 try
226 {
227 //@todo ? are we allowed to use sal_True here if we have the explicit ownership?
228 //I think yes, because there might be other closelistners later in the list which might be interested still
229 //but make sure that we do not throw the CloseVetoException here ourselfs
230 //so stop listening before trying to terminate or check the source of queryclosing event
231 m_xCloseable->close(sal_True);
232
233 m_bOwnership = false;
234 m_bOwnershipIsWellKnown = sal_True;
235 }
236 catch( util::CloseVetoException& )
237 {
238 //since we have indicated to give up the ownership with paramter true in close call
239 //the one who has thrown the CloseVetoException is the new owner
240
241 #if OSL_DEBUG_LEVEL > 2
242 OSL_ENSURE( !m_bOwnership,
243 "INFO: a well known owner has catched a CloseVetoException after calling close(true)" );
244 #endif
245
246 m_bOwnership = false;
247 m_bOwnershipIsWellKnown = sal_True;
248 return;
249 }
250
251 }
252 else if( m_xModel.is() )
253 {
254 //@todo correct??
255 m_xModel->dispose();
256 return;
257 }
258 }
259 catch( uno::Exception& ex)
260 {
261 (void)(ex); // no warning in non-debug builds
262 OSL_ENSURE( sal_False, ( rtl::OString("Termination of model failed: ")
263 + rtl::OUStringToOString( ex.Message, RTL_TEXTENCODING_ASCII_US ) ).getStr() );
264 }
265 }
266
267 //-----------------------------------------------------------------
268
TheModelRef(TheModel * pTheModel,::osl::Mutex & rMutex)269 ChartController::TheModelRef::TheModelRef( TheModel* pTheModel, ::osl::Mutex& rMutex )
270 : m_pTheModel(pTheModel), m_rModelMutex(rMutex)
271 {
272 ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex );
273 if(m_pTheModel)
274 m_pTheModel->acquire();
275 }
TheModelRef(const TheModelRef & rTheModel,::osl::Mutex & rMutex)276 ChartController::TheModelRef::TheModelRef( const TheModelRef& rTheModel, ::osl::Mutex& rMutex )
277 : m_rModelMutex(rMutex)
278 {
279 ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex );
280 m_pTheModel=rTheModel.operator->();
281 if(m_pTheModel)
282 m_pTheModel->acquire();
283 }
operator =(TheModel * pTheModel)284 ChartController::TheModelRef& ChartController::TheModelRef::operator=(TheModel* pTheModel)
285 {
286 ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex );
287 if(m_pTheModel==pTheModel)
288 return *this;
289 if(m_pTheModel)
290 m_pTheModel->release();
291 m_pTheModel=pTheModel;
292 if(m_pTheModel)
293 m_pTheModel->acquire();
294 return *this;
295 }
operator =(const TheModelRef & rTheModel)296 ChartController::TheModelRef& ChartController::TheModelRef::operator=(const TheModelRef& rTheModel)
297 {
298 ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex );
299 TheModel* pNew=rTheModel.operator->();
300 if(m_pTheModel==pNew)
301 return *this;
302 if(m_pTheModel)
303 m_pTheModel->release();
304 m_pTheModel=pNew;
305 if(m_pTheModel)
306 m_pTheModel->acquire();
307 return *this;
308 }
~TheModelRef()309 ChartController::TheModelRef::~TheModelRef()
310 {
311 ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex );
312 if(m_pTheModel)
313 m_pTheModel->release();
314 }
is() const315 sal_Bool ChartController::TheModelRef::is() const
316 {
317 return (m_pTheModel != 0);
318 }
319
320
321 //-----------------------------------------------------------------
322 // private methods
323 //-----------------------------------------------------------------
324
325 sal_Bool ChartController
impl_isDisposedOrSuspended() const326 ::impl_isDisposedOrSuspended() const
327 {
328 if( m_aLifeTimeManager.impl_isDisposed() )
329 return sal_True;
330
331 if( m_bSuspended )
332 {
333 OSL_ENSURE( sal_False, "This Controller is suspended" );
334 return sal_True;
335 }
336 return sal_False;
337 }
338
339 //-----------------------------------------------------------------
340 // lang::XServiceInfo
341 //-----------------------------------------------------------------
342
APPHELPER_XSERVICEINFO_IMPL(ChartController,CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME)343 APPHELPER_XSERVICEINFO_IMPL(ChartController,CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME)
344
345 uno::Sequence< rtl::OUString > ChartController
346 ::getSupportedServiceNames_Static()
347 {
348 uno::Sequence< rtl::OUString > aSNS( 2 );
349 aSNS.getArray()[ 0 ] = CHART_CONTROLLER_SERVICE_NAME;
350 aSNS.getArray()[ 1 ] = ::rtl::OUString::createFromAscii("com.sun.star.frame.Controller");
351 //// @todo : add additional services if you support any further
352 return aSNS;
353 }
354
355 //-----------------------------------------------------------------
356 // XController
357 //-----------------------------------------------------------------
358
359 void SAL_CALL ChartController
attachFrame(const uno::Reference<frame::XFrame> & xFrame)360 ::attachFrame( const uno::Reference<frame::XFrame>& xFrame )
361 throw(uno::RuntimeException)
362 {
363 ::vos::OGuard aGuard( Application::GetSolarMutex());
364
365 if( impl_isDisposedOrSuspended() ) //@todo? allow attaching the frame while suspended?
366 return; //behave passive if already disposed or suspended
367
368 if(m_xFrame.is()) //what happens, if we do have a Frame already??
369 {
370 //@todo? throw exception?
371 OSL_ENSURE( sal_False, "there is already a frame attached to the controller" );
372 return;
373 }
374
375 //--attach frame
376 m_xFrame = xFrame; //the frameloader is responsible to call xFrame->setComponent
377
378 //add as disposelistener to the frame (due to persistent reference) ??...:
379
380 //the frame is considered to be owner of this controller and will live longer than we do
381 //the frame or the disposer of the frame has the duty to call suspend and dispose on this object
382 //so we do not need to add as lang::XEventListener for DisposingEvents right?
383
384 //@todo nothing right???
385
386
387
388 //--------------------------------------------------
389 //create view @todo is this the correct place here??
390
391 Window* pParent = NULL;
392 //get the window parent from the frame to use as parent for our new window
393 if(xFrame.is())
394 {
395 uno::Reference< awt::XWindow > xContainerWindow = xFrame->getContainerWindow();
396 VCLXWindow* pParentComponent = VCLXWindow::GetImplementation(xContainerWindow);
397 pParentComponent->setVisible(sal_True);
398
399 pParent = VCLUnoHelper::GetWindow( xContainerWindow );
400 }
401
402 if(m_pChartWindow)
403 {
404 //@todo delete ...
405 m_pChartWindow->clear();
406 m_apDropTargetHelper.reset();
407 }
408 {
409 awt::Size aPageSize( ChartModelHelper::getPageSize(getModel()) );
410
411 // calls to VCL
412 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
413 m_pChartWindow = new ChartWindow(this,pParent,pParent?pParent->GetStyle():0);
414 m_pChartWindow->SetBackground();//no Background
415 m_xViewWindow = uno::Reference< awt::XWindow >( m_pChartWindow->GetComponentInterface(), uno::UNO_QUERY );
416 m_pChartWindow->Show();
417 m_apDropTargetHelper.reset(
418 new ChartDropTargetHelper( m_pChartWindow->GetDropTarget(),
419 uno::Reference< chart2::XChartDocument >( getModel(), uno::UNO_QUERY )));
420
421 impl_createDrawViewController();
422 }
423
424 //create the menu
425 {
426 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
427 if( xPropSet.is() )
428 {
429 try
430 {
431 uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
432 xPropSet->getPropertyValue( C2U( "LayoutManager" ) ) >>= xLayoutManager;
433 if ( xLayoutManager.is() )
434 {
435 xLayoutManager->lock();
436 xLayoutManager->requestElement( C2U( "private:resource/menubar/menubar" ) );
437 //@todo: createElement should become unnecessary, remove when #i79198# is fixed
438 xLayoutManager->createElement( C2U( "private:resource/toolbar/standardbar" ) );
439 xLayoutManager->requestElement( C2U( "private:resource/toolbar/standardbar" ) );
440 //@todo: createElement should become unnecessary, remove when #i79198# is fixed
441 xLayoutManager->createElement( C2U( "private:resource/toolbar/toolbar" ) );
442 xLayoutManager->requestElement( C2U( "private:resource/toolbar/toolbar" ) );
443
444 // #i12587# support for shapes in chart
445 xLayoutManager->createElement( C2U( "private:resource/toolbar/drawbar" ) );
446 xLayoutManager->requestElement( C2U( "private:resource/toolbar/drawbar" ) );
447
448 xLayoutManager->requestElement( C2U( "private:resource/statusbar/statusbar" ) );
449 xLayoutManager->unlock();
450
451 // add as listener to get notified when
452 m_xLayoutManagerEventBroadcaster.set( xLayoutManager, uno::UNO_QUERY );
453 if( m_xLayoutManagerEventBroadcaster.is())
454 m_xLayoutManagerEventBroadcaster->addLayoutManagerEventListener( this );
455 }
456 }
457 catch( uno::Exception & ex )
458 {
459 ASSERT_EXCEPTION( ex );
460 }
461 }
462 }
463 }
464
465 //XModeChangeListener
modeChanged(const util::ModeChangeEvent & rEvent)466 void SAL_CALL ChartController::modeChanged( const util::ModeChangeEvent& rEvent )
467 throw ( uno::RuntimeException )
468 {
469 //adjust controller to view status changes
470
471 if( rEvent.NewMode.equals(C2U("dirty")) )
472 {
473 //the view has become dirty, we should repaint it if we have a window
474 ::vos::OGuard aGuard( Application::GetSolarMutex() );
475 if( m_pChartWindow )
476 m_pChartWindow->ForceInvalidate();
477 }
478 else if( rEvent.NewMode.equals(C2U("invalid")) )
479 {
480 //the view is about to become invalid so end all actions on it
481 impl_invalidateAccessible();
482 ::vos::OGuard aGuard( Application::GetSolarMutex());
483 if( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
484 this->EndTextEdit();
485 if( m_pDrawViewWrapper )
486 {
487 m_pDrawViewWrapper->UnmarkAll();
488 //m_pDrawViewWrapper->hideMarkHandles(); todo??
489 m_pDrawViewWrapper->HideSdrPage();
490 }
491 }
492 else
493 {
494 //the view was rebuild so we can start some actions on it again
495 if( !m_bConnectingToView )
496 {
497 if(m_pChartWindow && m_aModel.is() )
498 {
499 m_bConnectingToView = true;
500
501 GetDrawModelWrapper();
502 if(m_pDrawModelWrapper)
503 {
504 {
505 ::vos::OGuard aGuard( Application::GetSolarMutex());
506 if( m_pDrawViewWrapper )
507 m_pDrawViewWrapper->ReInit();
508 }
509
510 //reselect object
511 if( m_aSelection.hasSelection() )
512 this->impl_selectObjectAndNotiy();
513 else
514 ChartModelHelper::triggerRangeHighlighting( getModel() );
515
516 impl_initializeAccessible();
517
518 {
519 ::vos::OGuard aGuard( Application::GetSolarMutex() );
520 if( m_pChartWindow )
521 m_pChartWindow->Invalidate();
522 }
523 }
524
525 m_bConnectingToView = false;
526 }
527 }
528 }
529 }
530
531 sal_Bool SAL_CALL ChartController
attachModel(const uno::Reference<frame::XModel> & xModel)532 ::attachModel( const uno::Reference< frame::XModel > & xModel )
533 throw(uno::RuntimeException)
534 {
535 impl_invalidateAccessible();
536
537 //is called to attach the controller to a new model.
538 //return true if attach was successfully, false otherwise (e.g. if you do not work with a model)
539
540 ::vos::OClearableGuard aClearableGuard( Application::GetSolarMutex());
541 if( impl_isDisposedOrSuspended() ) //@todo? allow attaching a new model while suspended?
542 return sal_False; //behave passive if already disposed or suspended
543 aClearableGuard.clear();
544
545
546 TheModelRef aNewModelRef( new TheModel( xModel), m_aModelMutex);
547 TheModelRef aOldModelRef(m_aModel,m_aModelMutex);
548 m_aModel = aNewModelRef;
549
550 //--handle relations to the old model if any
551 if( aOldModelRef.is() )
552 {
553 uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY );
554 if( xViewBroadcaster.is() )
555 xViewBroadcaster->removeModeChangeListener(this);
556 m_pDrawModelWrapper.reset();
557
558 aOldModelRef->removeListener( this );
559 //@todo?? termination correct?
560 // aOldModelRef->tryTermination();
561 #ifdef TEST_ENABLE_MODIFY_LISTENER
562 uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aOldModelRef->getModel(),uno::UNO_QUERY );
563 if( xMBroadcaster.is())
564 xMBroadcaster->removeModifyListener( this );
565 #endif
566 }
567
568 //--handle relations to the new model
569 aNewModelRef->addListener( this );
570
571 // set new model at dispatchers
572 m_aDispatchContainer.setModel( aNewModelRef->getModel());
573 ControllerCommandDispatch * pDispatch = new ControllerCommandDispatch( m_xCC, this, &m_aDispatchContainer );
574 pDispatch->initialize();
575
576 // the dispatch container will return "this" for all commands returned by
577 // impl_getAvailableCommands(). That means, for those commands dispatch()
578 // is called here at the ChartController.
579 m_aDispatchContainer.setChartDispatch( pDispatch, impl_getAvailableCommands() );
580
581 DrawCommandDispatch* pDrawDispatch = new DrawCommandDispatch( m_xCC, this );
582 if ( pDrawDispatch )
583 {
584 pDrawDispatch->initialize();
585 m_aDispatchContainer.setDrawCommandDispatch( pDrawDispatch );
586 }
587
588 ShapeController* pShapeController = new ShapeController( m_xCC, this );
589 if ( pShapeController )
590 {
591 pShapeController->initialize();
592 m_aDispatchContainer.setShapeController( pShapeController );
593 }
594
595 #ifdef TEST_ENABLE_MODIFY_LISTENER
596 uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aNewModelRef->getModel(),uno::UNO_QUERY );
597 if( xMBroadcaster.is())
598 xMBroadcaster->addModifyListener( this );
599 #endif
600
601 // #119999# Do not do this per default to allow the user to deselect the chart OLE with a single press to ESC
602 // select chart area per default:
603 // select( uno::makeAny( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) ) );
604
605 uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY );
606 if( xFact.is())
607 {
608 m_xChartView = xFact->createInstance( CHART_VIEW_SERVICE_NAME );
609 GetDrawModelWrapper();
610 uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY );
611 if( xViewBroadcaster.is() )
612 xViewBroadcaster->addModeChangeListener(this);
613 }
614
615 //the frameloader is responsible to call xModel->connectController
616 {
617 ::vos::OGuard aGuard( Application::GetSolarMutex() );
618 if( m_pChartWindow )
619 m_pChartWindow->Invalidate();
620 }
621
622 uno::Reference< document::XUndoManagerSupplier > xSuppUndo( getModel(), uno::UNO_QUERY_THROW );
623 m_xUndoManager.set( xSuppUndo->getUndoManager(), uno::UNO_QUERY_THROW );
624
625 return sal_True;
626 }
627
628 uno::Reference< frame::XFrame > SAL_CALL ChartController
getFrame()629 ::getFrame() throw(uno::RuntimeException)
630 {
631 //provides access to owner frame of this controller
632 //return the frame containing this controller
633
634 return m_xFrame;
635 }
636
637 uno::Reference< frame::XModel > SAL_CALL ChartController
getModel()638 ::getModel() throw(uno::RuntimeException)
639 {
640 //provides access to currently attached model
641 //returns the currently attached model
642
643 //return nothing, if you do not have a model
644 TheModelRef aModelRef( m_aModel, m_aModelMutex);
645 if(aModelRef.is())
646 return aModelRef->getModel();
647
648 return uno::Reference< frame::XModel > ();
649 }
650
651 uno::Any SAL_CALL ChartController
getViewData()652 ::getViewData() throw(uno::RuntimeException)
653 {
654 //provides access to current view status
655 //set of data that can be used to restore the current view status at later time
656 // by using XController::restoreViewData()
657
658 ::vos::OGuard aGuard( Application::GetSolarMutex());
659 if( impl_isDisposedOrSuspended() )
660 return uno::Any(); //behave passive if already disposed or suspended //@todo? or throw an exception??
661
662 //-- collect current view state
663 uno::Any aRet;
664 //// @todo integrate specialized implementation
665
666 return aRet;
667 }
668
669 void SAL_CALL ChartController
restoreViewData(const uno::Any &)670 ::restoreViewData( const uno::Any& /* Value */ )
671 throw(uno::RuntimeException)
672 {
673 //restores the view status using the data gotten from a previous call to XController::getViewData()
674
675 ::vos::OGuard aGuard( Application::GetSolarMutex());
676 if( impl_isDisposedOrSuspended() )
677 return; //behave passive if already disposed or suspended //@todo? or throw an exception??
678
679 //// @todo integrate specialized implementation
680 }
681
682 sal_Bool SAL_CALL ChartController
suspend(sal_Bool bSuspend)683 ::suspend( sal_Bool bSuspend )
684 throw(uno::RuntimeException)
685 {
686 //is called to prepare the controller for closing the view
687 //bSuspend==true: force the controller to suspend his work
688 //bSuspend==false try to reactivate the controller
689 //returns true if request was accepted and of course successfully finished, false otherwise
690
691 //we may show dialogs here to ask the user for saving changes ... @todo?
692
693 ::vos::OGuard aGuard( Application::GetSolarMutex());
694 if( m_aLifeTimeManager.impl_isDisposed() )
695 return sal_False; //behave passive if already disposed, return false because request was not accepted //@todo? correct
696
697 if(bSuspend==m_bSuspended)
698 {
699 OSL_ENSURE( sal_False, "new suspend mode equals old suspend mode" );
700 return sal_True;
701 }
702
703 //change suspend mode
704 if(bSuspend)
705 {
706 //aGuard.clear();
707 //@todo ??? try to stop all what may prevent me from becoming disposed
708 //aGuard.reset();
709
710 m_bSuspended = bSuspend;
711 return sal_True;
712 }
713 else
714 {
715 //aGuard.clear();
716 //@todo ??? redo what was made in section bSuspend==true
717 //aGuard.reset();
718
719 m_bSuspended = bSuspend;
720 }
721 return sal_True;
722
723
724 /*
725 if ( bSuspend )
726 getFrame()->removeFrameActionListener( pImp );
727 else
728 getFrame()->addFrameActionListener( pImp );
729 */
730 }
731
732
impl_createDrawViewController()733 void ChartController::impl_createDrawViewController()
734 {
735 ::vos::OGuard aGuard( Application::GetSolarMutex());
736 if(!m_pDrawViewWrapper)
737 {
738 if( m_pDrawModelWrapper )
739 {
740 m_pDrawViewWrapper = new DrawViewWrapper(&m_pDrawModelWrapper->getSdrModel(),m_pChartWindow,true);
741 m_pDrawViewWrapper->attachParentReferenceDevice( getModel() );
742 }
743 }
744 }
impl_deleteDrawViewController()745 void ChartController::impl_deleteDrawViewController()
746 {
747 if( m_pDrawViewWrapper )
748 {
749 ::vos::OGuard aGuard( Application::GetSolarMutex());
750 if( m_pDrawViewWrapper->IsTextEdit() )
751 this->EndTextEdit();
752 DELETEZ( m_pDrawViewWrapper );
753 }
754 }
755
756 //-----------------------------------------------------------------
757 // XComponent (base of XController)
758 //-----------------------------------------------------------------
759
760 void SAL_CALL ChartController
dispose()761 ::dispose() throw(uno::RuntimeException)
762 {
763 try
764 {
765 //This object should release all resources and references in the
766 //easiest possible manner
767 //This object must notify all registered listeners using the method
768 //<member>XEventListener::disposing</member>
769
770 //hold no mutex
771 if( !m_aLifeTimeManager.dispose() )
772 return;
773
774 // OSL_ENSURE( m_bSuspended, "dispose was called but controller is not suspended" );
775
776 this->stopDoubleClickWaiting();
777
778 //end range highlighting
779 if( m_aModel.is())
780 {
781 uno::Reference< view::XSelectionChangeListener > xSelectionChangeListener;
782 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( getModel(), uno::UNO_QUERY );
783 if( xDataReceiver.is() )
784 xSelectionChangeListener = uno::Reference< view::XSelectionChangeListener >( xDataReceiver->getRangeHighlighter(), uno::UNO_QUERY );
785 if( xSelectionChangeListener.is() )
786 {
787 uno::Reference< frame::XController > xController( this );
788 uno::Reference< lang::XComponent > xComp( xController, uno::UNO_QUERY );
789 //lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) );
790 lang::EventObject aEvent( xComp );
791 xSelectionChangeListener->disposing( aEvent );
792 }
793 }
794
795 //--release all resources and references
796 {
797 uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY );
798 if( xViewBroadcaster.is() )
799 xViewBroadcaster->removeModeChangeListener(this);
800 // /--
801 impl_invalidateAccessible();
802 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
803 impl_deleteDrawViewController();
804 m_pDrawModelWrapper.reset();
805
806 m_apDropTargetHelper.reset();
807
808 //the accessible view is disposed within window destructor of m_pChartWindow
809 m_pChartWindow->clear();
810 m_pChartWindow = NULL;//m_pChartWindow is deleted via UNO due to dispose of m_xViewWindow (trigerred by Framework (Controller pretends to be XWindow also))
811 m_xViewWindow->dispose();
812 m_xChartView.clear();
813 // \--
814 }
815
816 // remove as listener to layout manager events
817 if( m_xLayoutManagerEventBroadcaster.is())
818 {
819 m_xLayoutManagerEventBroadcaster->removeLayoutManagerEventListener( this );
820 m_xLayoutManagerEventBroadcaster.set( 0 );
821 }
822
823 m_xFrame.clear();
824 m_xUndoManager.clear();
825
826 TheModelRef aModelRef( m_aModel, m_aModelMutex);
827 m_aModel = NULL;
828
829 if( aModelRef.is())
830 {
831 uno::Reference< frame::XModel > xModel( aModelRef->getModel() );
832 if(xModel.is())
833 xModel->disconnectController( uno::Reference< frame::XController >( this ));
834
835 aModelRef->removeListener( this );
836 #ifdef TEST_ENABLE_MODIFY_LISTENER
837 try
838 {
839 uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aModelRef->getModel(),uno::UNO_QUERY );
840 if( xMBroadcaster.is())
841 xMBroadcaster->removeModifyListener( this );
842 }
843 catch( const uno::Exception & ex )
844 {
845 ASSERT_EXCEPTION( ex );
846 }
847 #endif
848 aModelRef->tryTermination();
849 }
850
851 //// @todo integrate specialized implementation
852 //e.g. release further resources and references
853
854 m_aDispatchContainer.DisposeAndClear();
855 }
856 catch( const uno::Exception & ex )
857 {
858 ASSERT_EXCEPTION( ex );
859 }
860 }
861
862 void SAL_CALL ChartController
addEventListener(const uno::Reference<lang::XEventListener> & xListener)863 ::addEventListener( const uno::Reference<lang::XEventListener>& xListener )
864 throw(uno::RuntimeException)
865 {
866 ::vos::OGuard aGuard( Application::GetSolarMutex());
867 if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
868 return; //behave passive if already disposed or suspended
869
870 //--add listener
871 m_aLifeTimeManager.m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), xListener );
872 }
873
874 void SAL_CALL ChartController
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)875 ::removeEventListener( const uno::Reference<
876 lang::XEventListener>& xListener )
877 throw(uno::RuntimeException)
878 {
879 ::vos::OGuard aGuard( Application::GetSolarMutex());
880 if( m_aLifeTimeManager.impl_isDisposed(false) )
881 return; //behave passive if already disposed or suspended
882
883 //--remove listener
884 m_aLifeTimeManager.m_aListenerContainer.removeInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), xListener );
885 }
886
887
888 //-----------------------------------------------------------------
889 // util::XCloseListener
890 //-----------------------------------------------------------------
891 void SAL_CALL ChartController
queryClosing(const lang::EventObject & rSource,sal_Bool bGetsOwnership)892 ::queryClosing( const lang::EventObject& rSource, sal_Bool bGetsOwnership )
893 throw(util::CloseVetoException, uno::RuntimeException)
894 {
895 //do not use the m_aControllerMutex here because this call is not allowed to block
896
897 TheModelRef aModelRef( m_aModel, m_aModelMutex);
898
899 if( !aModelRef.is() )
900 return;
901
902 if( !(aModelRef->getModel() == rSource.Source) )
903 {
904 OSL_ENSURE( sal_False, "queryClosing was called on a controller from an unknown source" );
905 return;
906 }
907
908 if( !m_bCanClose )//@todo tryaqcuire mutex
909 {
910 if( bGetsOwnership )
911 {
912 aModelRef->SetOwnerShip( bGetsOwnership );
913 }
914
915 throw util::CloseVetoException();
916 }
917 else
918 {
919 //@ todo prepare to to closing model -> don't start any further hindering actions
920 }
921 }
922
923 void SAL_CALL ChartController
notifyClosing(const lang::EventObject & rSource)924 ::notifyClosing( const lang::EventObject& rSource )
925 throw(uno::RuntimeException)
926 {
927 //Listener should deregister himself and relaese all references to the closing object.
928
929 TheModelRef aModelRef( m_aModel, m_aModelMutex);
930 if( impl_releaseThisModel( rSource.Source ) )
931 {
932 //--stop listening to the closing model
933 aModelRef->removeListener( this );
934
935 // #i79087# If the model using this controller is closed, the frame is
936 // expected to be closed as well
937 Reference< util::XCloseable > xFrameCloseable( m_xFrame, uno::UNO_QUERY );
938 if( xFrameCloseable.is())
939 {
940 try
941 {
942 xFrameCloseable->close( sal_False /* DeliverOwnership */ );
943 m_xFrame.clear();
944 }
945 catch( util::CloseVetoException & )
946 {
947 // closing was vetoed
948 }
949 }
950 }
951 }
952
impl_releaseThisModel(const uno::Reference<uno::XInterface> & xModel)953 bool ChartController::impl_releaseThisModel( const uno::Reference< uno::XInterface > & xModel )
954 {
955 bool bReleaseModel = sal_False;
956 {
957 ::osl::Guard< ::osl::Mutex > aGuard( m_aModelMutex );
958 if( m_aModel.is() && m_aModel->getModel() == xModel )
959 {
960 m_aModel = NULL;
961 m_xUndoManager.clear();
962 bReleaseModel = true;
963 }
964 }
965 if( bReleaseModel )
966 m_aDispatchContainer.setModel( 0 );
967 return bReleaseModel;
968 }
969
970 //-----------------------------------------------------------------
971 // util::XEventListener (base of XCloseListener)
972 //-----------------------------------------------------------------
973 void SAL_CALL ChartController
disposing(const lang::EventObject & rSource)974 ::disposing( const lang::EventObject& rSource )
975 throw(uno::RuntimeException)
976 {
977 if( !impl_releaseThisModel( rSource.Source ))
978 {
979 if( rSource.Source == m_xLayoutManagerEventBroadcaster )
980 m_xLayoutManagerEventBroadcaster.set( 0 );
981 }
982 }
983
layoutEvent(const lang::EventObject & aSource,::sal_Int16 eLayoutEvent,const uno::Any &)984 void SAL_CALL ChartController::layoutEvent( const lang::EventObject& aSource, ::sal_Int16 eLayoutEvent, const uno::Any& /* aInfo */ )
985 throw (uno::RuntimeException)
986 {
987 if( eLayoutEvent == frame::LayoutManagerEvents::MERGEDMENUBAR )
988 {
989 Reference< frame::XLayoutManager > xLM( aSource.Source, uno::UNO_QUERY );
990 if( xLM.is())
991 {
992 xLM->createElement( C2U("private:resource/statusbar/statusbar"));
993 xLM->requestElement( C2U("private:resource/statusbar/statusbar"));
994 }
995 }
996 }
997
998
999 //-----------------------------------------------------------------
1000 // XDispatchProvider (required interface)
1001 //-----------------------------------------------------------------
1002
1003 namespace
1004 {
lcl_isFormatObjectCommand(const rtl::OString & aCommand)1005 bool lcl_isFormatObjectCommand( const rtl::OString& aCommand )
1006 {
1007 if( aCommand.equals("MainTitle")
1008 || aCommand.equals("SubTitle")
1009 || aCommand.equals("XTitle")
1010 || aCommand.equals("YTitle")
1011 || aCommand.equals("ZTitle")
1012 || aCommand.equals("SecondaryXTitle")
1013 || aCommand.equals("SecondaryYTitle")
1014 || aCommand.equals("AllTitles")
1015 || aCommand.equals("DiagramAxisX")
1016 || aCommand.equals("DiagramAxisY")
1017 || aCommand.equals("DiagramAxisZ")
1018 || aCommand.equals("DiagramAxisA")
1019 || aCommand.equals("DiagramAxisB")
1020 || aCommand.equals("DiagramAxisAll")
1021 || aCommand.equals("DiagramGridXMain")
1022 || aCommand.equals("DiagramGridYMain")
1023 || aCommand.equals("DiagramGridZMain")
1024 || aCommand.equals("DiagramGridXHelp")
1025 || aCommand.equals("DiagramGridYHelp")
1026 || aCommand.equals("DiagramGridZHelp")
1027 || aCommand.equals("DiagramGridAll")
1028
1029 || aCommand.equals("DiagramWall")
1030 || aCommand.equals("DiagramFloor")
1031 || aCommand.equals("DiagramArea")
1032 || aCommand.equals("Legend")
1033
1034 || aCommand.equals("FormatWall")
1035 || aCommand.equals("FormatFloor")
1036 || aCommand.equals("FormatChartArea")
1037 || aCommand.equals("FormatLegend")
1038
1039 || aCommand.equals("FormatTitle")
1040 || aCommand.equals("FormatAxis")
1041 || aCommand.equals("FormatDataSeries")
1042 || aCommand.equals("FormatDataPoint")
1043 || aCommand.equals("FormatDataLabels")
1044 || aCommand.equals("FormatDataLabel")
1045 || aCommand.equals("FormatYErrorBars")
1046 || aCommand.equals("FormatMeanValue")
1047 || aCommand.equals("FormatTrendline")
1048 || aCommand.equals("FormatTrendlineEquation")
1049 || aCommand.equals("FormatStockLoss")
1050 || aCommand.equals("FormatStockGain")
1051 || aCommand.equals("FormatMajorGrid")
1052 || aCommand.equals("FormatMinorGrid")
1053 )
1054 return true;
1055
1056 // else
1057 return false;
1058 }
1059 } // anonymous namespace
1060
1061 uno::Reference<frame::XDispatch> SAL_CALL ChartController
queryDispatch(const util::URL & rURL,const rtl::OUString & rTargetFrameName,sal_Int32)1062 ::queryDispatch( const util::URL& rURL
1063 , const rtl::OUString& rTargetFrameName
1064 , sal_Int32 /* nSearchFlags */)
1065 throw(uno::RuntimeException)
1066 {
1067 if ( !m_aLifeTimeManager.impl_isDisposed() && getModel().is() )
1068 {
1069 if( !rTargetFrameName.isEmpty() &&
1070 rTargetFrameName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_self")))
1071 return m_aDispatchContainer.getDispatchForURL( rURL );
1072 }
1073 return uno::Reference< frame::XDispatch > ();
1074 }
1075
1076 uno::Sequence<uno::Reference<frame::XDispatch > > ChartController
queryDispatches(const uno::Sequence<frame::DispatchDescriptor> & xDescripts)1077 ::queryDispatches( const uno::Sequence<
1078 frame::DispatchDescriptor>& xDescripts)
1079 throw(uno::RuntimeException)
1080 {
1081 if ( !m_aLifeTimeManager.impl_isDisposed() )
1082 {
1083 return m_aDispatchContainer.getDispatchesForURLs( xDescripts );
1084 }
1085 return uno::Sequence<uno::Reference<frame::XDispatch > > ();
1086 }
1087
1088 //-----------------------------------------------------------------
1089 // frame::XDispatch
1090 //-----------------------------------------------------------------
1091
1092 void SAL_CALL ChartController
dispatch(const util::URL & rURL,const uno::Sequence<beans::PropertyValue> & rArgs)1093 ::dispatch( const util::URL& rURL
1094 , const uno::Sequence< beans::PropertyValue >& rArgs )
1095 throw (uno::RuntimeException)
1096 {
1097 //@todo avoid OString (see Mathias mail on bug #104387#)
1098 rtl::OString aCommand( rtl::OUStringToOString( rURL.Path, RTL_TEXTENCODING_ASCII_US ) );
1099
1100 if(aCommand.equals("Paste"))
1101 this->executeDispatch_Paste();
1102 else if(aCommand.equals("Copy"))
1103 this->executeDispatch_Copy();
1104 else if(aCommand.equals("Cut"))
1105 this->executeDispatch_Cut();
1106 else if(aCommand.equals("DataRanges"))
1107 this->executeDispatch_SourceData();
1108 //----------------------------------
1109 else if(aCommand.equals("Update")) //Update Chart
1110 {
1111 ChartViewHelper::setViewToDirtyState( getModel() );
1112 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1113 if( m_pChartWindow )
1114 m_pChartWindow->Invalidate();
1115 }
1116 else if(aCommand.equals("DiagramData"))
1117 this->executeDispatch_EditData();
1118 //insert objects
1119 else if( aCommand.equals("InsertTitles")
1120 || aCommand.equals("InsertMenuTitles") )
1121 this->executeDispatch_InsertTitles();
1122 else if( aCommand.equals("InsertMenuLegend") )
1123 this->executeDispatch_OpenLegendDialog();
1124 else if( aCommand.equals("InsertLegend") )
1125 this->executeDispatch_InsertLegend();
1126 else if( aCommand.equals("DeleteLegend") )
1127 this->executeDispatch_DeleteLegend();
1128 else if( aCommand.equals("InsertMenuDataLabels"))
1129 this->executeDispatch_InsertMenu_DataLabels();
1130 else if( aCommand.equals("InsertMenuAxes")
1131 || aCommand.equals("InsertRemoveAxes") )
1132 this->executeDispatch_InsertAxes();
1133 else if( aCommand.equals("InsertMenuGrids"))
1134 this->executeDispatch_InsertGrid();
1135 else if( aCommand.equals("InsertMenuTrendlines"))
1136 this->executeDispatch_InsertMenu_Trendlines();
1137 else if( aCommand.equals("InsertMenuMeanValues"))
1138 this->executeDispatch_InsertMenu_MeanValues();
1139 else if( aCommand.equals("InsertMenuYErrorBars"))
1140 this->executeDispatch_InsertMenu_YErrorBars();
1141 else if( aCommand.equals("InsertSymbol"))
1142 this->executeDispatch_InsertSpecialCharacter();
1143 else if( aCommand.equals("InsertTrendline"))
1144 this->executeDispatch_InsertTrendline();
1145 else if( aCommand.equals("DeleteTrendline"))
1146 this->executeDispatch_DeleteTrendline();
1147 else if( aCommand.equals("InsertMeanValue"))
1148 this->executeDispatch_InsertMeanValue();
1149 else if( aCommand.equals("DeleteMeanValue"))
1150 this->executeDispatch_DeleteMeanValue();
1151 else if( aCommand.equals("InsertYErrorBars"))
1152 this->executeDispatch_InsertYErrorBars();
1153 else if( aCommand.equals("DeleteYErrorBars"))
1154 this->executeDispatch_DeleteYErrorBars();
1155 else if( aCommand.equals("InsertTrendlineEquation"))
1156 this->executeDispatch_InsertTrendlineEquation();
1157 else if( aCommand.equals("DeleteTrendlineEquation"))
1158 this->executeDispatch_DeleteTrendlineEquation();
1159 else if( aCommand.equals("InsertTrendlineEquationAndR2"))
1160 this->executeDispatch_InsertTrendlineEquation( true );
1161 else if( aCommand.equals("InsertR2Value"))
1162 this->executeDispatch_InsertR2Value();
1163 else if( aCommand.equals("DeleteR2Value"))
1164 this->executeDispatch_DeleteR2Value();
1165 else if( aCommand.equals("InsertDataLabels") )
1166 this->executeDispatch_InsertDataLabels();
1167 else if( aCommand.equals("InsertDataLabel") )
1168 this->executeDispatch_InsertDataLabel();
1169 else if( aCommand.equals("DeleteDataLabels") )
1170 this->executeDispatch_DeleteDataLabels();
1171 else if( aCommand.equals("DeleteDataLabel") )
1172 this->executeDispatch_DeleteDataLabel();
1173 else if( aCommand.equals("ResetAllDataPoints") )
1174 this->executeDispatch_ResetAllDataPoints();
1175 else if( aCommand.equals("ResetDataPoint") )
1176 this->executeDispatch_ResetDataPoint();
1177 else if( aCommand.equals("InsertAxis") )
1178 this->executeDispatch_InsertAxis();
1179 else if( aCommand.equals("InsertMajorGrid") )
1180 this->executeDispatch_InsertMajorGrid();
1181 else if( aCommand.equals("InsertMinorGrid") )
1182 this->executeDispatch_InsertMinorGrid();
1183 else if( aCommand.equals("InsertAxisTitle") )
1184 this->executeDispatch_InsertAxisTitle();
1185 else if( aCommand.equals("DeleteAxis") )
1186 this->executeDispatch_DeleteAxis();
1187 else if( aCommand.equals("DeleteMajorGrid") )
1188 this->executeDispatch_DeleteMajorGrid();
1189 else if( aCommand.equals("DeleteMinorGrid") )
1190 this->executeDispatch_DeleteMinorGrid();
1191 //format objects
1192 else if( aCommand.equals("FormatSelection") )
1193 this->executeDispatch_ObjectProperties();
1194 else if( aCommand.equals("TransformDialog"))
1195 {
1196 if ( isShapeContext() )
1197 {
1198 this->impl_ShapeControllerDispatch( rURL, rArgs );
1199 }
1200 else
1201 {
1202 this->executeDispatch_PositionAndSize();
1203 }
1204 }
1205 else if( lcl_isFormatObjectCommand(aCommand) )
1206 this->executeDispatch_FormatObject(rURL.Path);
1207 //more format
1208 //MENUCHANGE else if(aCommand.equals("SelectSourceRanges"))
1209 //MENUCHANGE this->executeDispatch_SourceData();
1210 else if( aCommand.equals("DiagramType"))
1211 this->executeDispatch_ChartType();
1212 else if( aCommand.equals("View3D"))
1213 this->executeDispatch_View3D();
1214 else if ( aCommand.equals( "Forward" ) )
1215 {
1216 if ( isShapeContext() )
1217 {
1218 this->impl_ShapeControllerDispatch( rURL, rArgs );
1219 }
1220 else
1221 {
1222 this->executeDispatch_MoveSeries( sal_True );
1223 }
1224 }
1225 else if ( aCommand.equals( "Backward" ) )
1226 {
1227 if ( isShapeContext() )
1228 {
1229 this->impl_ShapeControllerDispatch( rURL, rArgs );
1230 }
1231 else
1232 {
1233 this->executeDispatch_MoveSeries( sal_False );
1234 }
1235 }
1236 else if( aCommand.equals("NewArrangement"))
1237 this->executeDispatch_NewArrangement();
1238 else if( aCommand.equals("ToggleLegend"))
1239 this->executeDispatch_ToggleLegend();
1240 else if( aCommand.equals("ToggleGridHorizontal"))
1241 this->executeDispatch_ToggleGridHorizontal();
1242 else if( aCommand.equals("ScaleText"))
1243 this->executeDispatch_ScaleText();
1244 else if( aCommand.equals("StatusBarVisible"))
1245 {
1246 // workaround: this should not be necessary.
1247 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY );
1248 if( xPropSet.is() )
1249 {
1250 uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1251 xPropSet->getPropertyValue( C2U( "LayoutManager" ) ) >>= xLayoutManager;
1252 if ( xLayoutManager.is() )
1253 {
1254 bool bIsVisible( xLayoutManager->isElementVisible( C2U("private:resource/statusbar/statusbar")));
1255 if( bIsVisible )
1256 {
1257 xLayoutManager->hideElement( C2U( "private:resource/statusbar/statusbar"));
1258 xLayoutManager->destroyElement( C2U( "private:resource/statusbar/statusbar"));
1259 }
1260 else
1261 {
1262 xLayoutManager->createElement( C2U( "private:resource/statusbar/statusbar"));
1263 xLayoutManager->showElement( C2U( "private:resource/statusbar/statusbar"));
1264 }
1265 // @todo: update menu state (checkmark next to "Statusbar").
1266 }
1267 }
1268 }
1269
1270 /*
1271 case SID_TEXTEDIT:
1272 this->executeDispatch_EditText();
1273 */
1274 }
1275
1276 void SAL_CALL ChartController
addStatusListener(const uno::Reference<frame::XStatusListener> &,const util::URL &)1277 ::addStatusListener( const uno::Reference<frame::XStatusListener >& /* xControl */
1278 , const util::URL& /* aURL */ )
1279 throw (uno::RuntimeException)
1280 {
1281 // // TODO: add listener by URL !
1282 // ::vos::OGuard aGuard( Application::GetSolarMutex());
1283 // if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
1284 // return; //behave passive if already disposed or suspended
1285
1286 // //--add listener
1287 // m_aLifeTimeManager.m_aListenerContainer.addInterface( ::getCppuType( & xControl ), xControl );
1288 }
1289
1290 void SAL_CALL ChartController
removeStatusListener(const uno::Reference<frame::XStatusListener> &,const util::URL &)1291 ::removeStatusListener( const uno::Reference<frame::XStatusListener >& /* xControl */
1292 , const util::URL& /* aURL */ )
1293 throw (uno::RuntimeException)
1294 {
1295 // // TODO: remove listener by URL !
1296 // ::vos::OGuard aGuard( Application::GetSolarMutex());
1297 // if( m_aLifeTimeManager.impl_isDisposed() )
1298 // return; //behave passive if already disposed or suspended
1299
1300 // //--remove listener
1301 // m_aLifeTimeManager.m_aListenerContainer.removeInterface( ::getCppuType( & xControl ), xControl );
1302 }
1303
1304 //-----------------------------------------------------------------
1305 // XContextMenuInterception (optional interface)
1306 //-----------------------------------------------------------------
1307 void SAL_CALL ChartController
registerContextMenuInterceptor(const uno::Reference<ui::XContextMenuInterceptor> &)1308 ::registerContextMenuInterceptor( const uno::Reference<
1309 ui::XContextMenuInterceptor > & /* xInterceptor */)
1310 throw(uno::RuntimeException)
1311 {
1312 //@todo
1313 }
1314
1315 void SAL_CALL ChartController
releaseContextMenuInterceptor(const uno::Reference<ui::XContextMenuInterceptor> &)1316 ::releaseContextMenuInterceptor( const uno::Reference<
1317 ui::XContextMenuInterceptor > & /* xInterceptor */)
1318 throw(uno::RuntimeException)
1319 {
1320 //@todo
1321 }
1322
1323 // ____ XEmbeddedClient ____
1324 // implementation see: ChartController_EditData.cxx
1325
1326 //-----------------------------------------------------------------------------
1327 //-----------------------------------------------------------------------------
1328 //-----------------------------------------------------------------------------
1329
executeDispatch_ChartType()1330 void SAL_CALL ChartController::executeDispatch_ChartType()
1331 {
1332 // using assignment for broken gcc 3.3
1333 UndoLiveUpdateGuard aUndoGuard = UndoLiveUpdateGuard(
1334 String( SchResId( STR_ACTION_EDIT_CHARTTYPE )), m_xUndoManager );
1335
1336 // /--
1337 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
1338 //prepare and open dialog
1339 ChartTypeDialog aDlg( m_pChartWindow, getModel(), m_xCC );
1340 if( aDlg.Execute() == RET_OK )
1341 {
1342 impl_adaptDataSeriesAutoResize();
1343 aUndoGuard.commit();
1344 }
1345 // \--
1346 }
1347
executeDispatch_SourceData()1348 void SAL_CALL ChartController::executeDispatch_SourceData()
1349 {
1350 //-------------------------------------------------------------
1351 //convert properties to ItemSet
1352 uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
1353 DBG_ASSERT( xChartDoc.is(), "Invalid XChartDocument" );
1354 if( !xChartDoc.is())
1355 return;
1356
1357 // using assignment for broken gcc 3.3
1358 UndoLiveUpdateGuard aUndoGuard = UndoLiveUpdateGuard(
1359 String( SchResId( STR_ACTION_EDIT_DATA_RANGES )), m_xUndoManager );
1360 if( xChartDoc.is())
1361 {
1362 // /--
1363 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
1364 ::chart::DataSourceDialog aDlg( m_pChartWindow, xChartDoc, m_xCC );
1365 if( aDlg.Execute() == RET_OK )
1366 {
1367 impl_adaptDataSeriesAutoResize();
1368 aUndoGuard.commit();
1369 }
1370 // \--
1371 }
1372 }
1373
executeDispatch_MoveSeries(sal_Bool bForward)1374 void SAL_CALL ChartController::executeDispatch_MoveSeries( sal_Bool bForward )
1375 {
1376 ControllerLockGuard aCLGuard( getModel() );
1377
1378 //get selected series
1379 ::rtl::OUString aObjectCID(m_aSelection.getSelectedCID());
1380 uno::Reference< XDataSeries > xGivenDataSeries( ObjectIdentifier::getDataSeriesForCID( //yyy todo also legendentries and labels?
1381 aObjectCID, getModel() ) );
1382
1383 UndoGuardWithSelection aUndoGuard(
1384 ActionDescriptionProvider::createDescription(
1385 (bForward ? ActionDescriptionProvider::MOVE_TOTOP : ActionDescriptionProvider::MOVE_TOBOTTOM),
1386 String( SchResId( STR_OBJECT_DATASERIES ))),
1387 m_xUndoManager );
1388
1389 bool bChanged = DiagramHelper::moveSeries( ChartModelHelper::findDiagram( getModel() ), xGivenDataSeries, bForward );
1390 if( bChanged )
1391 {
1392 m_aSelection.setSelection( ObjectIdentifier::getMovedSeriesCID( aObjectCID, bForward ) );
1393 aUndoGuard.commit();
1394 }
1395 }
1396
1397 // ____ XMultiServiceFactory ____
1398 uno::Reference< uno::XInterface > SAL_CALL
createInstance(const::rtl::OUString & aServiceSpecifier)1399 ChartController::createInstance( const ::rtl::OUString& aServiceSpecifier )
1400 throw (uno::Exception,
1401 uno::RuntimeException)
1402 {
1403 uno::Reference< uno::XInterface > xResult;
1404
1405 if( aServiceSpecifier.equals( CHART_ACCESSIBLE_TEXT_SERVICE_NAME ))
1406 xResult.set( impl_createAccessibleTextContext());
1407 return xResult;
1408 }
1409
1410 uno::Reference< uno::XInterface > SAL_CALL
createInstanceWithArguments(const::rtl::OUString & ServiceSpecifier,const uno::Sequence<uno::Any> &)1411 ChartController::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier,
1412 const uno::Sequence< uno::Any >& /* Arguments */ )
1413 throw (uno::Exception,
1414 uno::RuntimeException)
1415 {
1416 // ignore Arguments
1417 return createInstance( ServiceSpecifier );
1418 }
1419
1420 uno::Sequence< ::rtl::OUString > SAL_CALL
getAvailableServiceNames()1421 ChartController::getAvailableServiceNames()
1422 throw (uno::RuntimeException)
1423 {
1424 static uno::Sequence< ::rtl::OUString > aServiceNames;
1425
1426 if( aServiceNames.getLength() == 0 )
1427 {
1428 aServiceNames.realloc(1);
1429 aServiceNames[0] = CHART_ACCESSIBLE_TEXT_SERVICE_NAME;
1430 }
1431
1432 return aServiceNames;
1433 }
1434
1435 // ____ XModifyListener ____
modified(const lang::EventObject &)1436 void SAL_CALL ChartController::modified( const lang::EventObject& /* aEvent */ )
1437 throw (uno::RuntimeException)
1438 {
1439 // the source can also be a subobject of the ChartModel
1440 // @todo: change the source in ChartModel to always be the model itself ?
1441 // if( getModel() == aEvent.Source )
1442
1443
1444 //todo? update menu states ?
1445 }
1446
1447 //-----------------------------------------------------------------------------
1448 //-----------------------------------------------------------------------------
1449 //-----------------------------------------------------------------------------
1450
IMPL_LINK(ChartController,NotifyUndoActionHdl,SdrUndoAction *,pUndoAction)1451 IMPL_LINK( ChartController, NotifyUndoActionHdl, SdrUndoAction*, pUndoAction )
1452 {
1453 ENSURE_OR_RETURN( pUndoAction, "invalid Undo action", 1L );
1454
1455 ::rtl::OUString aObjectCID = m_aSelection.getSelectedCID();
1456 if ( aObjectCID.isEmpty() )
1457 {
1458 try
1459 {
1460 const Reference< document::XUndoManagerSupplier > xSuppUndo( getModel(), uno::UNO_QUERY_THROW );
1461 const Reference< document::XUndoManager > xUndoManager( xSuppUndo->getUndoManager(), uno::UNO_QUERY_THROW );
1462 const Reference< document::XUndoAction > xAction( new impl::ShapeUndoElement( *pUndoAction ) );
1463 xUndoManager->addUndoAction( xAction );
1464 }
1465 catch( const uno::Exception& )
1466 {
1467 DBG_UNHANDLED_EXCEPTION();
1468 }
1469 }
1470 return 0L;
1471 }
1472
GetDrawModelWrapper()1473 DrawModelWrapper* ChartController::GetDrawModelWrapper()
1474 {
1475 if( !m_pDrawModelWrapper.get() )
1476 {
1477 ExplicitValueProvider* pProvider = ExplicitValueProvider::getExplicitValueProvider( m_xChartView );
1478 if( pProvider )
1479 m_pDrawModelWrapper = pProvider->getDrawModelWrapper();
1480 if ( m_pDrawModelWrapper.get() )
1481 {
1482 m_pDrawModelWrapper->getSdrModel().SetNotifyUndoActionHdl( LINK( this, ChartController, NotifyUndoActionHdl ) );
1483 }
1484 }
1485 return m_pDrawModelWrapper.get();
1486 }
1487
GetDrawViewWrapper()1488 DrawViewWrapper* ChartController::GetDrawViewWrapper()
1489 {
1490 if ( !m_pDrawViewWrapper )
1491 {
1492 impl_createDrawViewController();
1493 }
1494 return m_pDrawViewWrapper;
1495 }
1496
CreateAccessible()1497 uno::Reference< XAccessible > ChartController::CreateAccessible()
1498 {
1499 uno::Reference< XAccessible > xResult = new AccessibleChartView( m_xCC, GetDrawViewWrapper() );
1500 impl_initializeAccessible( uno::Reference< lang::XInitialization >( xResult, uno::UNO_QUERY ) );
1501 return xResult;
1502 }
1503
impl_invalidateAccessible()1504 void ChartController::impl_invalidateAccessible()
1505 {
1506 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1507 if( m_pChartWindow )
1508 {
1509 Reference< lang::XInitialization > xInit( m_pChartWindow->GetAccessible(false), uno::UNO_QUERY );
1510 if(xInit.is())
1511 {
1512 uno::Sequence< uno::Any > aArguments(3);//empty arguments -> invalid accessible
1513 xInit->initialize(aArguments);
1514 }
1515 }
1516 }
impl_initializeAccessible()1517 void ChartController::impl_initializeAccessible()
1518 {
1519 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1520 if( m_pChartWindow )
1521 this->impl_initializeAccessible( Reference< lang::XInitialization >( m_pChartWindow->GetAccessible(false), uno::UNO_QUERY ) );
1522 }
impl_initializeAccessible(const uno::Reference<lang::XInitialization> & xInit)1523 void ChartController::impl_initializeAccessible( const uno::Reference< lang::XInitialization >& xInit )
1524 {
1525 if(xInit.is())
1526 {
1527 uno::Sequence< uno::Any > aArguments(5);
1528 uno::Reference<view::XSelectionSupplier> xSelectionSupplier(this);
1529 aArguments[0]=uno::makeAny(xSelectionSupplier);
1530 uno::Reference<frame::XModel> xModel(getModel());
1531 aArguments[1]=uno::makeAny(xModel);
1532 aArguments[2]=uno::makeAny(m_xChartView);
1533 uno::Reference< XAccessible > xParent;
1534 {
1535 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1536 if( m_pChartWindow )
1537 {
1538 Window* pParentWin( m_pChartWindow->GetAccessibleParentWindow());
1539 if( pParentWin )
1540 xParent.set( pParentWin->GetAccessible());
1541 }
1542 }
1543 aArguments[3]=uno::makeAny(xParent);
1544 aArguments[4]=uno::makeAny(m_xViewWindow);
1545
1546 xInit->initialize(aArguments);
1547 }
1548 }
1549
impl_getAvailableCommands()1550 ::std::set< ::rtl::OUString > ChartController::impl_getAvailableCommands()
1551 {
1552 return ::comphelper::MakeSet< ::rtl::OUString >
1553 // commands for container forward
1554 ( C2U("AddDirect")) ( C2U("NewDoc")) ( C2U("Open"))
1555 ( C2U("Save")) ( C2U("SaveAs")) ( C2U("SendMail"))
1556 ( C2U("EditDoc")) ( C2U("ExportDirectToPDF")) ( C2U("PrintDefault"))
1557
1558 // own commands
1559 ( C2U("Cut") ) ( C2U("Copy") ) ( C2U("Paste") )
1560 ( C2U("DataRanges") ) ( C2U("DiagramData") )
1561 // insert objects
1562 ( C2U("InsertMenuTitles") ) ( C2U("InsertTitles") )
1563 ( C2U("InsertMenuLegend") ) ( C2U("InsertLegend") ) ( C2U("DeleteLegend") )
1564 ( C2U("InsertMenuDataLabels") )
1565 ( C2U("InsertMenuAxes") ) ( C2U("InsertRemoveAxes") ) ( C2U("InsertMenuGrids") )
1566 ( C2U("InsertSymbol") )
1567 ( C2U("InsertTrendlineEquation") ) ( C2U("InsertTrendlineEquationAndR2") )
1568 ( C2U("InsertR2Value") ) ( C2U("DeleteR2Value") )
1569 ( C2U("InsertMenuTrendlines") ) ( C2U("InsertTrendline") )
1570 ( C2U("InsertMenuMeanValues") ) ( C2U("InsertMeanValue") )
1571 ( C2U("InsertMenuYErrorBars") ) ( C2U("InsertYErrorBars") )
1572 ( C2U("InsertDataLabels") ) ( C2U("InsertDataLabel") )
1573 ( C2U("DeleteTrendline") ) ( C2U("DeleteMeanValue") ) ( C2U("DeleteTrendlineEquation") )
1574 ( C2U("DeleteYErrorBars") )
1575 ( C2U("DeleteDataLabels") ) ( C2U("DeleteDataLabel") )
1576 //format objects
1577 //MENUCHANGE ( C2U("SelectSourceRanges") )
1578 ( C2U("FormatSelection") ) ( C2U("TransformDialog") )
1579 ( C2U("DiagramType") ) ( C2U("View3D") )
1580 ( C2U("Forward") ) ( C2U("Backward") )
1581 ( C2U("MainTitle") ) ( C2U("SubTitle") )
1582 ( C2U("XTitle") ) ( C2U("YTitle") ) ( C2U("ZTitle") )
1583 ( C2U("SecondaryXTitle") ) ( C2U("SecondaryYTitle") )
1584 ( C2U("AllTitles") ) ( C2U("Legend") )
1585 ( C2U("DiagramAxisX") ) ( C2U("DiagramAxisY") ) ( C2U("DiagramAxisZ") )
1586 ( C2U("DiagramAxisA") ) ( C2U("DiagramAxisB") ) ( C2U("DiagramAxisAll") )
1587 ( C2U("DiagramGridXMain") ) ( C2U("DiagramGridYMain") ) ( C2U("DiagramGridZMain") )
1588 ( C2U("DiagramGridXHelp") ) ( C2U("DiagramGridYHelp") ) ( C2U("DiagramGridZHelp") )
1589 ( C2U("DiagramGridAll") )
1590 ( C2U("DiagramWall") ) ( C2U("DiagramFloor") ) ( C2U("DiagramArea") )
1591
1592 //context menu - format objects entries
1593 ( C2U("FormatWall") ) ( C2U("FormatFloor") ) ( C2U("FormatChartArea") )
1594 ( C2U("FormatLegend") )
1595
1596 ( C2U("FormatAxis") ) ( C2U("FormatTitle") )
1597 ( C2U("FormatDataSeries") ) ( C2U("FormatDataPoint") )
1598 ( C2U("ResetAllDataPoints") ) ( C2U("ResetDataPoint") )
1599 ( C2U("FormatDataLabels") ) ( C2U("FormatDataLabel") )
1600 ( C2U("FormatMeanValue") ) ( C2U("FormatTrendline") ) ( C2U("FormatTrendlineEquation") )
1601 ( C2U("FormatYErrorBars") )
1602 ( C2U("FormatStockLoss") ) ( C2U("FormatStockGain") )
1603
1604 ( C2U("FormatMajorGrid") ) ( C2U("InsertMajorGrid") ) ( C2U("DeleteMajorGrid") )
1605 ( C2U("FormatMinorGrid") ) ( C2U("InsertMinorGrid") ) ( C2U("DeleteMinorGrid") )
1606 ( C2U("InsertAxis") ) ( C2U("DeleteAxis") ) ( C2U("InsertAxisTitle") )
1607
1608 // toolbar commands
1609 ( C2U("ToggleGridHorizontal"))( C2U("ToggleLegend") ) ( C2U("ScaleText") )
1610 ( C2U("NewArrangement") ) ( C2U("Update") )
1611 ( C2U("DefaultColors") ) ( C2U("BarWidth") ) ( C2U("NumberOfLines") )
1612 ( C2U("ArrangeRow") )
1613 ( C2U("StatusBarVisible") )
1614 ( C2U("ChartElementSelector") )
1615 ;
1616 }
1617
1618 //.............................................................................
1619 } //namespace chart
1620 //.............................................................................
1621