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 "PositionAndSizeHelper.hxx"
28 #include "ObjectIdentifier.hxx"
29 #include "ChartWindow.hxx"
30 #include "ResId.hxx"
31 #include "CommonConverters.hxx"
32 #include "ChartModelHelper.hxx"
33 #include "DiagramHelper.hxx"
34 #include "TitleHelper.hxx"
35 #include "UndoGuard.hxx"
36 #include "ControllerLockGuard.hxx"
37 #include "ObjectNameProvider.hxx"
38 #include "Strings.hrc"
39 #include "SchSlotIds.hxx"
40 #include "macros.hxx"
41 #include "DragMethod_PieSegment.hxx"
42 #include "DragMethod_RotateDiagram.hxx"
43 #include "ObjectHierarchy.hxx"
44 #include "chartview/ExplicitValueProvider.hxx"
45 #include "RelativePositionHelper.hxx"
46 #include "chartview/DrawModelWrapper.hxx"
47 #include "RegressionCurveHelper.hxx"
48 #include "StatisticsHelper.hxx"
49 #include "DataSeriesHelper.hxx"
50 #include "ContainerHelper.hxx"
51 #include "AxisHelper.hxx"
52 #include "LegendHelper.hxx"
53 #include "servicenames_charttypes.hxx"
54 #include "MenuResIds.hrc"
55 #include "DrawCommandDispatch.hxx"
56 
57 #include <com/sun/star/chart2/RelativePosition.hpp>
58 #include <com/sun/star/chart2/RelativeSize.hpp>
59 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
60 
61 #include <com/sun/star/frame/XDispatchHelper.hpp>
62 #include <com/sun/star/frame/FrameSearchFlag.hpp>
63 #include <com/sun/star/util/XUpdatable.hpp>
64 #include <comphelper/InlineContainer.hxx>
65 
66 #include <svtools/contextmenuhelper.hxx>
67 #include <toolkit/awt/vclxmenu.hxx>
68 
69 #include <svx/svxids.hrc>
70 #include <svx/ActionDescriptionProvider.hxx>
71 
72 // header for class E3dObject
73 #include <svx/obj3d.hxx>
74 // header for class E3dScene
75 #include <svx/scene3d.hxx>
76 // header for class SdrDragMethod
77 #include <svx/svddrgmt.hxx>
78 #include <vcl/svapp.hxx>
79 #include <vos/mutex.hxx>
80 
81 // for InfoBox
82 #include <vcl/msgbox.hxx>
83 
84 #include <rtl/math.hxx>
85 #include <svtools/acceleratorexecute.hxx>
86 
87 #define DRGPIX	  2		// Drag MinMove in Pixel
88 
89 using namespace ::com::sun::star;
90 using namespace ::com::sun::star::chart2;
91 using ::com::sun::star::uno::Reference;
92 using ::rtl::OUString;
93 
94 //.............................................................................
95 namespace chart
96 {
97 //.............................................................................
98 
99 namespace
100 {
101 bool lcl_GrowAndShiftLogic(
102     RelativePosition &  rInOutRelPos,
103     RelativeSize &      rInOutRelSize,
104     const awt::Size &   rRefSize,
105     double              fGrowLogicX,
106     double              fGrowLogicY )
107 {
108     if( rRefSize.Width == 0 ||
109         rRefSize.Height == 0 )
110         return false;
111 
112     double fRelativeGrowX = fGrowLogicX / rRefSize.Width;
113     double fRelativeGrowY = fGrowLogicY / rRefSize.Height;
114 
115     return ::chart::RelativePositionHelper::centerGrow(
116         rInOutRelPos, rInOutRelSize,
117         fRelativeGrowX, fRelativeGrowY,
118         /* bCheck = */ true );
119 }
120 
121 bool lcl_MoveObjectLogic(
122     RelativePosition &  rInOutRelPos,
123     RelativeSize &      rObjectSize,
124     const awt::Size &   rRefSize,
125     double              fShiftLogicX,
126     double              fShiftLogicY )
127 {
128     if( rRefSize.Width == 0 ||
129         rRefSize.Height == 0 )
130         return false;
131 
132     double fRelativeShiftX = fShiftLogicX / rRefSize.Width;
133     double fRelativeShiftY = fShiftLogicY / rRefSize.Height;
134 
135     return ::chart::RelativePositionHelper::moveObject(
136         rInOutRelPos, rObjectSize,
137         fRelativeShiftX, fRelativeShiftY,
138         /* bCheck = */ true );
139 }
140 
141 void lcl_insertMenuCommand(
142     const uno::Reference< awt::XPopupMenu > & xMenu,
143     const uno::Reference< awt::XMenuExtended > & xMenuEx,
144     sal_Int16 nId, const ::rtl::OUString & rCommand )
145 {
146     static ::rtl::OUString aEmptyString;
147     xMenu->insertItem( nId, aEmptyString, 0, -1 );
148     xMenuEx->setCommand( nId, rCommand );
149 }
150 
151 OUString lcl_getFormatCommandForObjectCID( const OUString& rCID )
152 {
153     OUString aDispatchCommand( C2U(".uno:FormatSelection") );
154 
155     ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
156 
157     switch(eObjectType)
158     {
159         case OBJECTTYPE_DIAGRAM:
160         case OBJECTTYPE_DIAGRAM_WALL:
161             aDispatchCommand = C2U(".uno:FormatWall");
162             break;
163         case OBJECTTYPE_DIAGRAM_FLOOR:
164             aDispatchCommand = C2U(".uno:FormatFloor");
165             break;
166         case OBJECTTYPE_PAGE:
167             aDispatchCommand = C2U(".uno:FormatChartArea");
168             break;
169         case OBJECTTYPE_LEGEND:
170             aDispatchCommand = C2U(".uno:FormatLegend");
171             break;
172         case OBJECTTYPE_TITLE:
173             aDispatchCommand = C2U(".uno:FormatTitle");
174             break;
175         case OBJECTTYPE_LEGEND_ENTRY:
176             aDispatchCommand = C2U(".uno:FormatDataSeries");
177             break;
178         case OBJECTTYPE_AXIS:
179         case OBJECTTYPE_AXIS_UNITLABEL:
180             aDispatchCommand = C2U(".uno:FormatAxis");
181             break;
182         case OBJECTTYPE_GRID:
183             aDispatchCommand = C2U(".uno:FormatMajorGrid");
184             break;
185         case OBJECTTYPE_SUBGRID:
186             aDispatchCommand = C2U(".uno:FormatMinorGrid");
187             break;
188         case OBJECTTYPE_DATA_LABELS:
189             aDispatchCommand = C2U(".uno:FormatDataLabels");
190             break;
191         case OBJECTTYPE_DATA_SERIES:
192             aDispatchCommand = C2U(".uno:FormatDataSeries");
193             break;
194         case OBJECTTYPE_DATA_LABEL:
195             aDispatchCommand = C2U(".uno:FormatDataLabel");
196             break;
197         case OBJECTTYPE_DATA_POINT:
198             aDispatchCommand = C2U(".uno:FormatDataPoint");
199             break;
200         case OBJECTTYPE_DATA_AVERAGE_LINE:
201             aDispatchCommand = C2U(".uno:FormatMeanValue");
202             break;
203         case OBJECTTYPE_DATA_ERRORS:
204         case OBJECTTYPE_DATA_ERRORS_X:
205         case OBJECTTYPE_DATA_ERRORS_Y:
206         case OBJECTTYPE_DATA_ERRORS_Z:
207             aDispatchCommand = C2U(".uno:FormatYErrorBars");
208             break;
209         case OBJECTTYPE_DATA_CURVE:
210             aDispatchCommand = C2U(".uno:FormatTrendline");
211             break;
212         case OBJECTTYPE_DATA_CURVE_EQUATION:
213             aDispatchCommand = C2U(".uno:FormatTrendlineEquation");
214             break;
215         case OBJECTTYPE_DATA_STOCK_RANGE:
216             aDispatchCommand = C2U(".uno:FormatSelection");
217             break;
218         case OBJECTTYPE_DATA_STOCK_LOSS:
219             aDispatchCommand = C2U(".uno:FormatStockLoss");
220             break;
221         case OBJECTTYPE_DATA_STOCK_GAIN:
222             aDispatchCommand = C2U(".uno:FormatStockGain");
223             break;
224         default: //OBJECTTYPE_UNKNOWN
225             break;
226     }
227     return aDispatchCommand;
228 }
229 
230 } // anonymous namespace
231 
232 const short HITPIX=2; //hit-tolerance in pixel
233 
234 //-----------------------------------------------------------------
235 // awt::XWindow
236 //-----------------------------------------------------------------
237 	void SAL_CALL ChartController
238 ::setPosSize( sal_Int32 X, sal_Int32 Y
239 			, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags )
240 			throw (uno::RuntimeException)
241 {
242     ::vos::OGuard aGuard( Application::GetSolarMutex() );
243 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
244 
245 	if(xWindow.is() && m_pChartWindow)
246     {
247         Size aLogicSize = m_pChartWindow->PixelToLogic( Size( Width, Height ), MapMode( MAP_100TH_MM )  );
248 
249         bool bIsEmbedded = true;
250         //todo: for standalone chart: detect wether we are standalone
251         if( bIsEmbedded )
252         {
253             //change map mode to fit new size
254             awt::Size aModelPageSize = ChartModelHelper::getPageSize( getModel() );
255             sal_Int32 nScaleXNumerator = aLogicSize.Width();
256             sal_Int32 nScaleXDenominator = aModelPageSize.Width;
257             sal_Int32 nScaleYNumerator = aLogicSize.Height();
258             sal_Int32 nScaleYDenominator = aModelPageSize.Height;
259             MapMode aNewMapMode( MAP_100TH_MM, Point(0,0)
260             , Fraction(nScaleXNumerator,nScaleXDenominator)
261             , Fraction(nScaleYNumerator,nScaleYDenominator) );
262             m_pChartWindow->SetMapMode(aNewMapMode);
263             m_pChartWindow->SetPosSizePixel( X, Y, Width, Height, Flags );
264 
265             //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
266             uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY );
267             if( xProp.is() )
268             {
269                 uno::Sequence< beans::PropertyValue > aZoomFactors(4);
270                 aZoomFactors[0].Name = C2U("ScaleXNumerator");
271                 aZoomFactors[0].Value = uno::makeAny( nScaleXNumerator );
272                 aZoomFactors[1].Name = C2U("ScaleXDenominator");
273                 aZoomFactors[1].Value = uno::makeAny( nScaleXDenominator );
274                 aZoomFactors[2].Name = C2U("ScaleYNumerator");
275                 aZoomFactors[2].Value = uno::makeAny( nScaleYNumerator );
276                 aZoomFactors[3].Name = C2U("ScaleYDenominator");
277                 aZoomFactors[3].Value = uno::makeAny( nScaleYDenominator );
278                 xProp->setPropertyValue( C2U("ZoomFactors"), uno::makeAny( aZoomFactors ));
279             }
280 
281             //a correct work area is at least necessary for correct values in the position and  size dialog and for dragging area
282             if(m_pDrawViewWrapper)
283             {
284                 Rectangle aRect(Point(0,0), m_pChartWindow->GetOutputSize());
285                 m_pDrawViewWrapper->SetWorkArea( aRect );
286             }
287         }
288         else
289         {
290             //change visarea
291             ChartModelHelper::setPageSize( awt::Size( aLogicSize.Width(), aLogicSize.Height() ), getModel() );
292 	        m_pChartWindow->SetPosSizePixel( X, Y, Width, Height, Flags );
293         }
294         m_pChartWindow->Invalidate();
295     }
296 }
297 
298 	awt::Rectangle SAL_CALL ChartController
299 ::getPosSize()
300 			throw (uno::RuntimeException)
301 {
302 	//@todo
303     awt::Rectangle aRet(0,0,0,0);
304 
305     uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
306 	if(xWindow.is())
307 		aRet = xWindow->getPosSize();
308 
309     return aRet;
310 }
311 
312 	void SAL_CALL ChartController
313 ::setVisible( sal_Bool Visible )
314 			throw (uno::RuntimeException)
315 {
316 	//@todo
317 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
318 
319 	if(xWindow.is())
320 		xWindow->setVisible( Visible );
321 }
322 
323 	void SAL_CALL ChartController
324 ::setEnable( sal_Bool Enable )
325 			throw (uno::RuntimeException)
326 {
327 	//@todo
328 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
329 
330 	if(xWindow.is())
331 		xWindow->setEnable( Enable );
332 }
333 
334 	void SAL_CALL ChartController
335 ::setFocus()	throw (uno::RuntimeException)
336 {
337 	//@todo
338 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
339 
340 	if(xWindow.is())
341 		xWindow->setFocus();
342 }
343 
344 	void SAL_CALL ChartController
345 ::addWindowListener( const uno::Reference<
346 			awt::XWindowListener >& xListener )
347 			throw (uno::RuntimeException)
348 {
349 	//@todo
350 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
351 
352 	if(xWindow.is())
353 		xWindow->addWindowListener( xListener );
354 }
355 
356 	void SAL_CALL ChartController
357 ::removeWindowListener( const uno::Reference<
358 			awt::XWindowListener >& xListener )
359 			throw (uno::RuntimeException)
360 {
361 	//@todo
362 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
363 
364 	if(xWindow.is())
365 		xWindow->removeWindowListener( xListener );
366 }
367 
368 	void SAL_CALL ChartController
369 ::addFocusListener( const uno::Reference<
370 			awt::XFocusListener >& xListener )
371 			throw (uno::RuntimeException)
372 {
373 	//@todo
374 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
375 
376 	if(xWindow.is())
377 		xWindow->addFocusListener( xListener );
378 }
379 
380 	void SAL_CALL ChartController
381 ::removeFocusListener( const uno::Reference<
382 			awt::XFocusListener >& xListener )
383 			throw (uno::RuntimeException)
384 {
385 	//@todo
386 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
387 
388 	if(xWindow.is())
389 		xWindow->removeFocusListener( xListener );
390 }
391 
392 	void SAL_CALL ChartController
393 ::addKeyListener( const uno::Reference<
394 			awt::XKeyListener >& xListener )
395 			throw (uno::RuntimeException)
396 {
397 	//@todo
398 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
399 
400 	if(xWindow.is())
401 		xWindow->addKeyListener( xListener );
402 }
403 
404 	void SAL_CALL ChartController
405 ::removeKeyListener( const uno::Reference<
406 			awt::XKeyListener >& xListener )
407 			throw (uno::RuntimeException)
408 {
409 	//@todo
410 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
411 
412 	if(xWindow.is())
413 		xWindow->removeKeyListener( xListener );
414 }
415 
416 	void SAL_CALL ChartController
417 ::addMouseListener( const uno::Reference<
418 			awt::XMouseListener >& xListener )
419 			throw (uno::RuntimeException)
420 {
421 	//@todo
422 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
423 
424 	if(xWindow.is())
425 		xWindow->addMouseListener( xListener );
426 }
427 
428 	void SAL_CALL ChartController
429 ::removeMouseListener( const uno::Reference<
430 			awt::XMouseListener >& xListener )
431 			throw (uno::RuntimeException)
432 {
433 	//@todo
434 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
435 
436 	if(xWindow.is())
437 		xWindow->removeMouseListener( xListener );
438 }
439 
440 	void SAL_CALL ChartController
441 ::addMouseMotionListener( const uno::Reference<
442 			awt::XMouseMotionListener >& xListener )
443 			throw (uno::RuntimeException)
444 {
445 	//@todo
446 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
447 
448 	if(xWindow.is())
449 		xWindow->addMouseMotionListener( xListener );
450 }
451 
452 	void SAL_CALL ChartController
453 ::removeMouseMotionListener( const uno::Reference<
454 			awt::XMouseMotionListener >& xListener )
455 			throw (uno::RuntimeException)
456 {
457 	//@todo
458 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
459 
460 	if(xWindow.is())
461 		xWindow->removeMouseMotionListener( xListener );
462 }
463 
464 	void SAL_CALL ChartController
465 ::addPaintListener( const uno::Reference<
466 			awt::XPaintListener >& xListener )
467 			throw (uno::RuntimeException)
468 {
469 	//@todo
470 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
471 
472 	if(xWindow.is())
473 		xWindow->addPaintListener( xListener );
474 }
475 
476 	void SAL_CALL ChartController
477 ::removePaintListener( const uno::Reference<
478 			awt::XPaintListener >& xListener )
479 			throw (uno::RuntimeException)
480 {
481 	//@todo
482 	uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
483 
484 	if(xWindow.is())
485 		xWindow->removePaintListener( xListener );
486 }
487 
488 //-----------------------------------------------------------------
489 // impl vcl window controller methods
490 //-----------------------------------------------------------------
491 void ChartController::PrePaint()
492 {
493     // forward VCLs PrePaint window event to DrawingLayer
494     DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
495 
496     if(pDrawViewWrapper)
497     {
498         pDrawViewWrapper->PrePaint();
499     }
500 }
501 
502 void ChartController::execute_Paint( const Rectangle& rRect )
503 {
504     try
505     {
506         uno::Reference< frame::XModel > xModel( getModel() );
507         //DBG_ASSERT( xModel.is(), "ChartController::execute_Paint: have no model to paint");
508         if( !xModel.is() )
509             return;
510 
511         //better performance for big data
512         uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY );
513         if( xProp.is() )
514         {
515             awt::Size aResolution(1000,1000);
516             {
517                 ::vos::OGuard aGuard( Application::GetSolarMutex());
518                 if( m_pChartWindow )
519                 {
520                     aResolution.Width = m_pChartWindow->GetSizePixel().Width();
521                     aResolution.Height = m_pChartWindow->GetSizePixel().Height();
522                 }
523             }
524             xProp->setPropertyValue( C2U("Resolution"), uno::makeAny( aResolution ));
525         }
526         //
527 
528         uno::Reference< util::XUpdatable > xUpdatable( m_xChartView, uno::UNO_QUERY );
529         if( xUpdatable.is() )
530             xUpdatable->update();
531 
532         {
533             ::vos::OGuard aGuard( Application::GetSolarMutex());
534             DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
535             if(pDrawViewWrapper)
536                 pDrawViewWrapper->CompleteRedraw(m_pChartWindow, Region(rRect) );
537         }
538     }
539     catch( uno::Exception & ex )
540     {
541         ASSERT_EXCEPTION( ex );
542     }
543     catch( ... )
544     {
545     }
546 }
547 
548 bool isDoubleClick( const MouseEvent& rMEvt )
549 {
550     return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() &&
551 		!rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift();
552 }
553 
554 //-----------------------------------------------------------------------------
555 //-----------------------------------------------------------------------------
556 //-----------------------------------------------------------------------------
557 
558 void ChartController::startDoubleClickWaiting()
559 {
560     ::vos::OGuard aGuard( Application::GetSolarMutex() );
561 
562     m_bWaitingForDoubleClick = true;
563 
564     sal_uLong nDblClkTime = 500;
565     if( m_pChartWindow )
566     {
567         const MouseSettings& rMSettings = m_pChartWindow->GetSettings().GetMouseSettings();
568         nDblClkTime = rMSettings.GetDoubleClickTime();
569     }
570     m_aDoubleClickTimer.SetTimeout( nDblClkTime );
571     m_aDoubleClickTimer.Start();
572 }
573 
574 void ChartController::stopDoubleClickWaiting()
575 {
576     m_aDoubleClickTimer.Stop();
577     m_bWaitingForDoubleClick = false;
578 }
579 
580 IMPL_LINK( ChartController, DoubleClickWaitingHdl, void*, EMPTYARG )
581 {
582     m_bWaitingForDoubleClick = false;
583 
584     if( !m_bWaitingForMouseUp && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
585     {
586         this->impl_selectObjectAndNotiy();
587         ::vos::OGuard aGuard( Application::GetSolarMutex() );
588         if( m_pChartWindow )
589         {
590             Window::PointerState aPointerState( m_pChartWindow->GetPointerState() );
591             MouseEvent aMouseEvent( aPointerState.maPos,1/*nClicks*/,
592                                     0/*nMode*/, static_cast< sal_uInt16 >( aPointerState.mnState )/*nButtons*/,
593                                     0/*nModifier*/ );
594             impl_SetMousePointer( aMouseEvent );
595         }
596     }
597 
598     return 0;
599 }
600 
601 //------------------------------------------------------------------------
602 
603 void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt )
604 {
605     ::vos::OGuard aGuard( Application::GetSolarMutex());
606 
607     m_bWaitingForMouseUp = true;
608 
609     if( isDoubleClick(rMEvt) )
610         stopDoubleClickWaiting();
611     else
612         startDoubleClickWaiting();
613 
614     m_aSelection.remindSelectionBeforeMouseDown();
615 
616     DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
617     if(!m_pChartWindow || !pDrawViewWrapper )
618         return;
619 
620     Point	aMPos	= m_pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
621 
622     if ( MOUSE_LEFT == rMEvt.GetButtons() )
623     {
624         m_pChartWindow->GrabFocus();
625 		m_pChartWindow->CaptureMouse();
626     }
627 
628     if( pDrawViewWrapper->IsTextEdit() )
629     {
630         SdrViewEvent aVEvt;
631         if ( pDrawViewWrapper->IsTextEditHit( aMPos, HITPIX ) ||
632              // #i12587# support for shapes in chart
633              ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt ) == SDRHIT_MARKEDOBJECT ) )
634         {
635             pDrawViewWrapper->MouseButtonDown(rMEvt,m_pChartWindow);
636             return;
637         }
638         else
639         {
640             this->EndTextEdit();
641         }
642     }
643 
644     //abort running action
645 	if( pDrawViewWrapper->IsAction() )
646     {
647 		if( rMEvt.IsRight() )
648 			pDrawViewWrapper->BckAction();
649 		return;
650     }
651 
652     if( isDoubleClick(rMEvt) ) //do not change selection if double click
653         return;//double click is handled further in mousebutton up
654 
655     SdrHdl* pHitSelectionHdl = 0;
656     //switch from move to resize if handle is hit on a resizeable object
657     if( m_aSelection.isResizeableObjectSelected() )
658         pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos );
659     //only change selection if no selection handles are hit
660     if( !pHitSelectionHdl )
661     {
662         // #i12587# support for shapes in chart
663         if ( m_eDrawMode == CHARTDRAW_INSERT &&
664              ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) )
665         {
666             if ( m_aSelection.hasSelection() )
667             {
668                 m_aSelection.clearSelection();
669             }
670             if ( !pDrawViewWrapper->IsAction() )
671             {
672                 if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_CAPTION )
673                 {
674                     Size aCaptionSize( 2268, 1134 );
675                     pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize );
676                 }
677                 else
678                 {
679                     pDrawViewWrapper->BegCreateObj( aMPos);
680                 }
681                 SdrObject* pObj = pDrawViewWrapper->GetCreateObj();
682                 DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch();
683                 if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch )
684                 {
685                     SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
686                     pDrawCommandDispatch->setAttributes( pObj );
687                     pDrawCommandDispatch->setLineEnds( aSet );
688                     pObj->SetMergedItemSet( aSet );
689                 }
690             }
691             impl_SetMousePointer( rMEvt );
692             return;
693         }
694 
695         m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper
696             , rMEvt.IsRight(), m_bWaitingForDoubleClick );
697 
698         if( !m_aSelection.isRotateableObjectSelected( getModel() ) )
699         {
700                 m_eDragMode = SDRDRAG_MOVE;
701                 pDrawViewWrapper->SetDragMode(m_eDragMode);
702         }
703 
704         m_aSelection.applySelection(pDrawViewWrapper);
705     }
706     if( m_aSelection.isDragableObjectSelected()
707          && !rMEvt.IsRight() )
708     {
709         //start drag
710         sal_uInt16  nDrgLog = (sal_uInt16)m_pChartWindow->PixelToLogic(Size(DRGPIX,0)).Width();
711         SdrDragMethod* pDragMethod = NULL;
712 
713         //change selection to 3D scene if rotate mode
714         SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode();
715         if( SDRDRAG_ROTATE==eDragMode )
716         {
717             E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) );
718             if( pScene )
719             {
720                 DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE);
721                 if(pHitSelectionHdl)
722                 {
723                     SdrHdlKind eKind = pHitSelectionHdl->GetKind();
724                     if( eKind==HDL_UPPER || eKind==HDL_LOWER )
725                         eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X;
726                     else if( eKind==HDL_LEFT || eKind==HDL_RIGHT )
727                         eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y;
728                     else if( eKind==HDL_UPLFT || eKind==HDL_UPRGT || eKind==HDL_LWLFT || eKind==HDL_LWRGT )
729                         eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z;
730                 }
731                 pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel(), eRotationDirection );
732             }
733         }
734         else
735         {
736             rtl::OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) );
737             if( aDragMethodServiceName.equals( ObjectIdentifier::getPieSegmentDragMethodServiceName() ) )
738                 pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel() );
739         }
740 	    pDrawViewWrapper->SdrView::BegDragObj(aMPos, NULL, pHitSelectionHdl, nDrgLog, pDragMethod);
741     }
742 
743     impl_SetMousePointer( rMEvt );
744 }
745 
746 void ChartController::execute_MouseMove( const MouseEvent& rMEvt )
747 {
748     ::vos::OGuard aGuard( Application::GetSolarMutex());
749 
750     DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
751     if(!m_pChartWindow || !pDrawViewWrapper)
752         return;
753 
754     if( m_pDrawViewWrapper->IsTextEdit() )
755     {
756         if( m_pDrawViewWrapper->MouseMove(rMEvt,m_pChartWindow) )
757             return;
758     }
759 
760 	if(pDrawViewWrapper->IsAction())
761     {
762 		pDrawViewWrapper->MovAction( m_pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
763     }
764 
765     //??	pDrawViewWrapper->GetPageView()->DragPoly();
766 
767     impl_SetMousePointer( rMEvt );
768 }
769 void ChartController::execute_Tracking( const TrackingEvent& /* rTEvt */ )
770 {
771 }
772 
773 //-----------------
774 
775 void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt )
776 {
777     ControllerLockGuard aCLGuard( getModel() );
778     bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp;
779     m_bWaitingForMouseUp = false;
780     bool bNotifySelectionChange = false;
781     {
782         ::vos::OGuard aGuard( Application::GetSolarMutex());
783 
784 	    DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
785         if(!m_pChartWindow || !pDrawViewWrapper)
786             return;
787 
788         Point	aMPos	= m_pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
789 
790         if(pDrawViewWrapper->IsTextEdit())
791         {
792             if( pDrawViewWrapper->MouseButtonUp(rMEvt,m_pChartWindow) )
793                 return;
794         }
795 
796         // #i12587# support for shapes in chart
797         if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() )
798         {
799             pDrawViewWrapper->EndCreateObj( SDRCREATE_FORCEEND );
800             {
801                 HiddenUndoContext aUndoContext( m_xUndoManager );
802                     // don't want the positioning Undo action to appear in the UI
803                 impl_switchDiagramPositioningToExcludingPositioning();
804             }
805             if ( pDrawViewWrapper->AreObjectsMarked() )
806             {
807                 if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT )
808                 {
809                     executeDispatch_EditText();
810                 }
811                 else
812                 {
813                     SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
814                     if ( pObj )
815                     {
816                         uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY );
817                         if ( xShape.is() )
818                         {
819                             m_aSelection.setSelection( xShape );
820                             m_aSelection.applySelection( pDrawViewWrapper );
821                         }
822                     }
823                 }
824             }
825             else
826             {
827                 m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick );
828                 m_aSelection.applySelection( pDrawViewWrapper );
829                 setDrawMode( CHARTDRAW_SELECT );
830             }
831         }
832         else if ( pDrawViewWrapper->IsDragObj() )
833         {
834             bool bDraggingDone = false;
835             SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod();
836             bool bIsMoveOnly = pDragMethod ? pDragMethod->getMoveOnly() : false;
837             DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod);
838             if( pChartDragMethod )
839             {
840                 UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(),
841                         m_xUndoManager );
842 
843                 if( pDrawViewWrapper->EndDragObj(false) )
844                 {
845                     bDraggingDone = true;
846                     aUndoGuard.commit();
847                 }
848             }
849 
850             if( !bDraggingDone && pDrawViewWrapper->EndDragObj(false) )
851 	        {
852                 try
853                 {
854                     //end move or size
855                     SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
856                     if( pObj )
857                     {
858                         Rectangle aObjectRect = pObj->GetSnapRect();
859                         awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
860                         Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height );
861 
862                         const E3dObject* pE3dObject = dynamic_cast< const E3dObject*>( pObj );
863                         if( pE3dObject )
864                             aObjectRect = pE3dObject->GetScene()->GetSnapRect();
865 
866                         ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::MOVE);
867                         if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() )
868                             eActionType = ActionDescriptionProvider::RESIZE;
869 
870                         ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
871 
872                         UndoGuard aUndoGuard(
873                             ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType)),
874                             m_xUndoManager );
875 
876                         bool bChanged = false;
877                         if ( eObjectType == OBJECTTYPE_LEGEND )
878                             bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( getModel(), false , true );
879 
880                         bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID()
881                                         , getModel()
882                                         , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight())
883                                         , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) );
884 
885                         if( bMoved || bChanged )
886                         {
887                             bDraggingDone = true;
888                             aUndoGuard.commit();
889                         }
890                     }
891                 }
892                 catch( uno::Exception & ex )
893                 {
894                     ASSERT_EXCEPTION( ex );
895                 }
896                 //all wanted model changes will take effect
897                 //and all unwanted view modifications are cleaned
898 	        }
899 
900 		    if( !bDraggingDone ) //mouse wasn't moved while dragging
901 		    {
902 			    bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper );
903                 bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getModel() );
904 
905 			    //toggel between move and rotate
906 			    if( bIsRotateable && bClickedTwiceOnDragableObject && SDRDRAG_MOVE==m_eDragMode )
907 				    m_eDragMode=SDRDRAG_ROTATE;
908 			    else
909 				    m_eDragMode=SDRDRAG_MOVE;
910 
911                 pDrawViewWrapper->SetDragMode(m_eDragMode);
912 
913                 if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
914                 {
915                     this->impl_selectObjectAndNotiy();
916                 }
917 		    }
918             else
919                 m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured();
920         }
921         else if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
922         {
923             Point aMousePixel = rMEvt.GetPosPixel();
924             execute_DoubleClick( &aMousePixel );
925         }
926 
927         //@todo ForcePointer(&rMEvt);
928         m_pChartWindow->ReleaseMouse();
929 
930         if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
931             bNotifySelectionChange = true;
932     }
933 
934     impl_SetMousePointer( rMEvt );
935 
936     if(bNotifySelectionChange)
937         impl_notifySelectionChangeListeners();
938 }
939 
940 void ChartController::execute_DoubleClick( const Point* pMousePixel )
941 {
942     bool bEditText = false;
943     if ( m_aSelection.hasSelection() )
944     {
945         ::rtl::OUString aCID( m_aSelection.getSelectedCID() );
946         if ( aCID.getLength() )
947         {
948             ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
949             if ( OBJECTTYPE_TITLE == eObjectType )
950             {
951                 bEditText = true;
952             }
953         }
954         else
955         {
956             // #i12587# support for shapes in chart
957             SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() );
958             if ( pObj && pObj->ISA( SdrTextObj ) )
959             {
960                 bEditText = true;
961             }
962         }
963     }
964 
965     if ( bEditText )
966     {
967         executeDispatch_EditText( pMousePixel );
968     }
969     else
970     {
971         executeDispatch_ObjectProperties();
972     }
973 }
974 
975 void ChartController::execute_Resize()
976 {
977     ::vos::OGuard aGuard( Application::GetSolarMutex() );
978     if(m_pChartWindow)
979         m_pChartWindow->Invalidate();
980 }
981 void ChartController::execute_Activate()
982 {
983     ///// pDrawViewWrapper->SetEditMode(sal_True);
984 }
985 void ChartController::execute_Deactivate()
986 {
987     /*
988     pDrawViewWrapper->SetEditMode(sal_False);
989 	this->ReleaseMouse();
990     */
991 }
992 void ChartController::execute_GetFocus()
993 {
994 }
995 void ChartController::execute_LoseFocus()
996 {
997     //this->ReleaseMouse();
998 }
999 
1000 void ChartController::execute_Command( const CommandEvent& rCEvt )
1001 {
1002     bool bIsAction = false;
1003     {
1004         ::vos::OGuard aGuard( Application::GetSolarMutex());
1005         DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
1006         if(!m_pChartWindow || !pDrawViewWrapper)
1007             return;
1008         bIsAction = m_pDrawViewWrapper->IsAction();
1009     }
1010 
1011     // pop-up menu
1012 	if(rCEvt.GetCommand() == COMMAND_CONTEXTMENU && !bIsAction)
1013 	{
1014         {
1015             ::vos::OGuard aGuard( Application::GetSolarMutex() );
1016             if(m_pChartWindow)
1017 		        m_pChartWindow->ReleaseMouse();
1018         }
1019 
1020         if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
1021             impl_notifySelectionChangeListeners();
1022 
1023         if ( isShapeContext() )
1024         {
1025             // #i12587# support for shapes in chart
1026             PopupMenu aContextMenu( SchResId( m_pDrawViewWrapper->IsTextEdit() ?
1027                 RID_CONTEXTMENU_SHAPEEDIT : RID_CONTEXTMENU_SHAPE ) );
1028             ::svt::ContextMenuHelper aContextMenuHelper( m_xFrame );
1029             Point aPos( rCEvt.GetMousePosPixel() );
1030             if( !rCEvt.IsMouseEvent() )
1031             {
1032                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1033                 if(m_pChartWindow)
1034                     aPos = m_pChartWindow->GetPointerState().maPos;
1035             }
1036             aContextMenuHelper.completeAndExecute( aPos, aContextMenu );
1037         }
1038         else
1039         {
1040             // todo: the context menu should be specified by an xml file in uiconfig
1041             uno::Reference< awt::XPopupMenu > xPopupMenu(
1042                 m_xCC->getServiceManager()->createInstanceWithContext(
1043                     C2U("com.sun.star.awt.PopupMenu"), m_xCC ), uno::UNO_QUERY );
1044             uno::Reference< awt::XMenuExtended > xMenuEx( xPopupMenu, uno::UNO_QUERY );
1045             if( xPopupMenu.is() && xMenuEx.is())
1046             {
1047                 sal_Int16 nUniqueId = 1;
1048                 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1049                 Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( getModel() );
1050 
1051                 OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) );
1052                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, aFormatCommand );
1053 
1054                 //some commands for dataseries and points:
1055                 //-----
1056                 if( OBJECTTYPE_DATA_SERIES == eObjectType || OBJECTTYPE_DATA_POINT == eObjectType )
1057                 {
1058                     bool bIsPoint = ( OBJECTTYPE_DATA_POINT == eObjectType );
1059                     uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() );
1060                     uno::Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
1061                     Reference< chart2::XRegressionCurve > xTrendline( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ) );
1062                     bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline );
1063                     Reference< chart2::XRegressionCurve > xMeanValue( RegressionCurveHelper::getMeanValueLine( xCurveCnt ) );
1064                     bool bHasYErrorBars = StatisticsHelper::hasErrorBars( xSeries, true );
1065                     bool bHasDataLabelsAtSeries = DataSeriesHelper::hasDataLabelsAtSeries( xSeries );
1066                     bool bHasDataLabelsAtPoints = DataSeriesHelper::hasDataLabelsAtPoints( xSeries );
1067                     bool bHasDataLabelAtPoint = false;
1068                     sal_Int32 nPointIndex = -1;
1069                     if( bIsPoint )
1070                     {
1071                         nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() );
1072                         bHasDataLabelAtPoint = DataSeriesHelper::hasDataLabelAtPoint( xSeries, nPointIndex );
1073                     }
1074                     bool bSelectedPointIsFormatted = false;
1075                     bool bHasFormattedDataPointsOtherThanSelected = false;
1076 
1077                     Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
1078                     if( xSeriesProperties.is() )
1079                     {
1080                         uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
1081                         if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
1082                         {
1083                             if( aAttributedDataPointIndexList.hasElements() )
1084                             {
1085                                 if( bIsPoint )
1086                                 {
1087                                     ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) );
1088                                     ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex );
1089                                     if( aIt != aIndices.end())
1090                                         bSelectedPointIsFormatted = true;
1091                                     else
1092                                         bHasFormattedDataPointsOtherThanSelected = true;
1093                                 }
1094                                 else
1095                                     bHasFormattedDataPointsOtherThanSelected = true;
1096                             }
1097                         }
1098                     }
1099 
1100                     //const sal_Int32 nIdBeforeFormat = nUniqueId;
1101                     if( bIsPoint )
1102                     {
1103                         if( bHasDataLabelAtPoint )
1104                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatDataLabel") );
1105                         if( !bHasDataLabelAtPoint )
1106                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertDataLabel") );
1107                         else
1108                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteDataLabel") );
1109                         if( bSelectedPointIsFormatted )
1110                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:ResetDataPoint"));
1111 
1112                         xPopupMenu->insertSeparator( -1 );
1113 
1114                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatDataSeries") );
1115                     }
1116 
1117                     Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) );
1118                     if( xChartType->getChartType().equals(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
1119                     {
1120                         try
1121                         {
1122                             Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY );
1123                             if( xChartTypeProp.is() )
1124                             {
1125                                 bool bJapaneseStyle = false;
1126                                 xChartTypeProp->getPropertyValue( C2U( "Japanese" ) ) >>= bJapaneseStyle;
1127 
1128                                 if( bJapaneseStyle )
1129                                 {
1130                                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockLoss") );
1131                                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockGain") );
1132                                 }
1133                             }
1134                         }
1135                         catch( const uno::Exception & ex )
1136                         {
1137                             ASSERT_EXCEPTION( ex );
1138                         }
1139                     }
1140 
1141                     if( bHasDataLabelsAtSeries )
1142                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatDataLabels") );
1143                     if( xTrendline.is() )
1144                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatTrendline") );
1145                     if( bHasEquation )
1146                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatTrendlineEquation") );
1147                     if( xMeanValue.is() )
1148                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatMeanValue") );
1149                     if( bHasYErrorBars )
1150                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatYErrorBars") );
1151 
1152                     //if( nIdBeforeFormat != nUniqueId )
1153                         xPopupMenu->insertSeparator( -1 );
1154 
1155                     //const sal_Int32 nIdBeforeInsert = nUniqueId;
1156 
1157                     if( !bHasDataLabelsAtSeries )
1158                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertDataLabels") );
1159                     if( !xTrendline.is() )
1160                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendline") );
1161                     else if( !bHasEquation )
1162                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendlineEquation") );
1163                     if( !xMeanValue.is() )
1164                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertMeanValue") );
1165                     if( !bHasYErrorBars )
1166                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertYErrorBars") );
1167 
1168                     //if( nIdBeforeInsert != nUniqueId )
1169                     //    xPopupMenu->insertSeparator( -1 );
1170 
1171                     //const sal_Int32 nIdBeforeDelete = nUniqueId;
1172 
1173                     if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) )
1174                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteDataLabels") );
1175                     if( xTrendline.is() )
1176                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteTrendline") );
1177                     if( bHasEquation )
1178                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteTrendlineEquation") );
1179                     if( xMeanValue.is() )
1180                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteMeanValue") );
1181                     if( bHasYErrorBars )
1182                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteYErrorBars") );
1183 
1184                     if( bHasFormattedDataPointsOtherThanSelected )
1185                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:ResetAllDataPoints"));
1186 
1187                     //if( nIdBeforeDelete != nUniqueId )
1188                         xPopupMenu->insertSeparator( -1 );
1189 
1190                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId, C2U(".uno:ArrangeRow"));
1191                     uno::Reference< awt::XPopupMenu > xArrangePopupMenu(
1192                         m_xCC->getServiceManager()->createInstanceWithContext(
1193                             C2U("com.sun.star.awt.PopupMenu"), m_xCC ), uno::UNO_QUERY );
1194                     uno::Reference< awt::XMenuExtended > xArrangeMenuEx( xArrangePopupMenu, uno::UNO_QUERY );
1195                     if( xArrangePopupMenu.is() && xArrangeMenuEx.is())
1196                     {
1197                         sal_Int16 nSubId = nUniqueId + 1;
1198                         lcl_insertMenuCommand( xArrangePopupMenu, xArrangeMenuEx, nSubId++, C2U(".uno:Forward") );
1199                         lcl_insertMenuCommand( xArrangePopupMenu, xArrangeMenuEx, nSubId, C2U(".uno:Backward") );
1200                         xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu );
1201                         nUniqueId = nSubId;
1202                     }
1203                     ++nUniqueId;
1204                 }
1205                 else if( OBJECTTYPE_DATA_CURVE == eObjectType )
1206                 {
1207                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatTrendlineEquation") );
1208                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendlineEquation") );
1209                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendlineEquationAndR2") );
1210                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertR2Value") );
1211                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteTrendlineEquation") );
1212                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteR2Value") );
1213                 }
1214                 else if( OBJECTTYPE_DATA_CURVE_EQUATION == eObjectType )
1215                 {
1216                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertR2Value") );
1217                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteR2Value") );
1218                 }
1219 
1220                 //some commands for axes: and grids
1221                 //-----
1222                 else if( OBJECTTYPE_AXIS  == eObjectType || OBJECTTYPE_GRID == eObjectType || OBJECTTYPE_SUBGRID == eObjectType )
1223                 {
1224                     Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() );
1225                     if( xAxis.is() && xDiagram.is() )
1226                     {
1227                         sal_Int32 nDimensionIndex = -1;
1228                         sal_Int32 nCooSysIndex = -1;
1229                         sal_Int32 nAxisIndex = -1;
1230                         AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
1231                         bool bIsSecondaryAxis = nAxisIndex!=0;
1232                         bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis );
1233                         bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram );
1234                         bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram );
1235                         bool bHasTitle = false;
1236                         uno::Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY );
1237                         if( xTitled.is())
1238                             bHasTitle = TitleHelper::getCompleteString( xTitled->getTitleObject() ).getLength()>0;
1239 
1240                         if( OBJECTTYPE_AXIS  != eObjectType && bIsAxisVisible )
1241                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatAxis") );
1242                         if( OBJECTTYPE_GRID != eObjectType && bIsMajorGridVisible && !bIsSecondaryAxis )
1243                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatMajorGrid") );
1244                         if( OBJECTTYPE_SUBGRID != eObjectType && bIsMinorGridVisible && !bIsSecondaryAxis )
1245                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatMinorGrid") );
1246 
1247                         xPopupMenu->insertSeparator( -1 );
1248 
1249                         if( OBJECTTYPE_AXIS  != eObjectType && !bIsAxisVisible )
1250                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertAxis") );
1251                         if( OBJECTTYPE_GRID != eObjectType && !bIsMajorGridVisible && !bIsSecondaryAxis )
1252                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertMajorGrid") );
1253                         if( OBJECTTYPE_SUBGRID != eObjectType && !bIsMinorGridVisible && !bIsSecondaryAxis )
1254                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertMinorGrid") );
1255                         if( !bHasTitle )
1256                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertAxisTitle") );
1257 
1258                         if( bIsAxisVisible )
1259                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteAxis") );
1260                         if( bIsMajorGridVisible && !bIsSecondaryAxis )
1261                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteMajorGrid") );
1262                         if( bIsMinorGridVisible && !bIsSecondaryAxis )
1263                             lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteMinorGrid") );
1264                     }
1265                 }
1266 
1267                 if( OBJECTTYPE_DATA_STOCK_LOSS == eObjectType )
1268                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockGain") );
1269                 else if( OBJECTTYPE_DATA_STOCK_GAIN == eObjectType )
1270                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockLoss") );
1271 
1272                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:TransformDialog"));
1273 
1274                 if( OBJECTTYPE_PAGE == eObjectType || OBJECTTYPE_DIAGRAM == eObjectType
1275                     || OBJECTTYPE_DIAGRAM_WALL == eObjectType
1276                     || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType
1277                     || OBJECTTYPE_UNKNOWN == eObjectType )
1278                 {
1279                     if( OBJECTTYPE_UNKNOWN != eObjectType )
1280                         xPopupMenu->insertSeparator( -1 );
1281                     bool bHasLegend = LegendHelper::hasLegend( xDiagram );
1282                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTitles") );
1283                     if( !bHasLegend )
1284                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertLegend") );
1285                     lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertRemoveAxes") );
1286                     if( bHasLegend )
1287                         lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteLegend") );
1288                 }
1289                 //-----
1290 
1291                 xPopupMenu->insertSeparator( -1 );
1292                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DiagramType"));
1293                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DataRanges"));
1294                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DiagramData"));
1295                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:View3D"));
1296                 xPopupMenu->insertSeparator( -1 );
1297                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:Cut"));
1298                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:Copy"));
1299                 lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:Paste"));
1300 
1301                 ::svt::ContextMenuHelper aContextMenuHelper( m_xFrame );
1302                 Point aPos( rCEvt.GetMousePosPixel() );
1303                 if( !rCEvt.IsMouseEvent() )
1304                 {
1305                     ::vos::OGuard aGuard( Application::GetSolarMutex() );
1306                     if(m_pChartWindow)
1307                         aPos = m_pChartWindow->GetPointerState().maPos;
1308                 }
1309                 aContextMenuHelper.completeAndExecute( aPos, xPopupMenu );
1310             }
1311         }
1312 	}
1313     else if( ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT ) ||
1314              ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT ) ||
1315              ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT ) ||
1316              ( rCEvt.GetCommand() == COMMAND_INPUTCONTEXTCHANGE ) )
1317     {
1318         //#i84417# enable editing with IME
1319         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1320         if( m_pDrawViewWrapper )
1321             m_pDrawViewWrapper->Command( rCEvt, m_pChartWindow );
1322     }
1323 }
1324 
1325 bool ChartController::execute_KeyInput( const KeyEvent& rKEvt )
1326 {
1327     bool bReturn=false;
1328 
1329     DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
1330     if(!m_pChartWindow || !pDrawViewWrapper)
1331         return bReturn;
1332 
1333     // handle accelerators
1334     if( ! m_apAccelExecute.get() && m_xFrame.is() && m_xCC.is() && m_xCC->getServiceManager().is() )
1335     {
1336         m_apAccelExecute.reset( ::svt::AcceleratorExecute::createAcceleratorHelper());
1337         OSL_ASSERT( m_apAccelExecute.get());
1338         if( m_apAccelExecute.get() )
1339             m_apAccelExecute->init(
1340                 uno::Reference< lang::XMultiServiceFactory >( m_xCC->getServiceManager(), uno::UNO_QUERY ), m_xFrame );
1341     }
1342 
1343     KeyCode aKeyCode( rKEvt.GetKeyCode());
1344     sal_uInt16 nCode = aKeyCode.GetCode();
1345 //     bool bShift = aKeyCode.IsShift();
1346     bool bAlternate = aKeyCode.IsMod2();
1347 
1348     if( m_apAccelExecute.get() )
1349         bReturn = m_apAccelExecute->execute( aKeyCode );
1350     if( bReturn )
1351         return bReturn;
1352 
1353     {
1354         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1355         if( pDrawViewWrapper->IsTextEdit() )
1356         {
1357             if( pDrawViewWrapper->KeyInput(rKEvt,m_pChartWindow) )
1358             {
1359                 bReturn = true;
1360                 if( nCode == KEY_ESCAPE )
1361                 {
1362                     this->EndTextEdit();
1363                 }
1364             }
1365         }
1366     }
1367 
1368     //if( m_pDrawViewWrapper->IsAction() );
1369 
1370     // keyboard accessibility
1371     ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1372     if( ! bReturn )
1373     {
1374         // Natvigation (Tab/F3/Home/End)
1375         uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
1376         ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, ExplicitValueProvider::getExplicitValueProvider( m_xChartView ));
1377         awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode ));
1378         bReturn = aObjNav.handleKeyEvent( aKeyEvent );
1379         if( bReturn )
1380         {
1381             ObjectIdentifier aNewOID = aObjNav.getCurrentSelection();
1382             uno::Any aNewSelection;
1383             if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) )
1384             {
1385                 aNewSelection = aNewOID.getAny();
1386             }
1387             if ( m_eDragMode == SDRDRAG_ROTATE && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getModel() ) )
1388             {
1389                 m_eDragMode = SDRDRAG_MOVE;
1390             }
1391             bReturn = select( aNewSelection );
1392         }
1393     }
1394 
1395     // Position and Size (+/-/arrow-keys) or pie segment dragging
1396     if( ! bReturn  )
1397     {
1398         // pie segment dragging
1399         // note: could also be done for data series
1400         if( eObjectType == OBJECTTYPE_DATA_POINT &&
1401             ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ).equals(
1402                 ObjectIdentifier::getPieSegmentDragMethodServiceName()))
1403         {
1404             bool bDrag = false;
1405             bool bDragInside = false;
1406             if( nCode == KEY_ADD ||
1407                 nCode == KEY_SUBTRACT )
1408             {
1409                 bDrag = true;
1410                 bDragInside = ( nCode == KEY_SUBTRACT );
1411             }
1412             else if(
1413                 nCode == KEY_LEFT ||
1414                 nCode == KEY_RIGHT ||
1415                 nCode == KEY_UP ||
1416                 nCode == KEY_DOWN )
1417             {
1418                 bDrag = true;
1419                 rtl::OUString aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() ));
1420                 sal_Int32 nOffsetPercentDummy( 0 );
1421                 awt::Point aMinimumPosition( 0, 0 );
1422                 awt::Point aMaximumPosition( 0, 0 );
1423                 ObjectIdentifier::parsePieSegmentDragParameterString(
1424                     aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition );
1425                 aMaximumPosition.Y -= aMinimumPosition.Y;
1426                 aMaximumPosition.X -= aMinimumPosition.X;
1427 
1428                 bDragInside =
1429                     (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) ||
1430                     (nCode == KEY_LEFT  && (aMaximumPosition.X > 0)) ||
1431                     (nCode == KEY_DOWN  && (aMaximumPosition.Y < 0)) ||
1432                     (nCode == KEY_UP    && (aMaximumPosition.Y > 0));
1433             }
1434 
1435             if( bDrag )
1436             {
1437                 double fAmount = bAlternate ? 0.01 : 0.05;
1438                 if( bDragInside )
1439                     fAmount *= -1.0;
1440 
1441                 bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount );
1442             }
1443         }
1444         else
1445         {
1446             // size
1447             if( nCode == KEY_ADD ||
1448                 nCode == KEY_SUBTRACT )
1449             {
1450                 if( eObjectType == OBJECTTYPE_DIAGRAM )
1451                 {
1452                     // default 1 mm in each direction
1453                     double fGrowAmountX = 200.0;
1454                     double fGrowAmountY = 200.0;
1455                     if( bAlternate && m_pChartWindow )
1456                     {
1457                         // together with Alt-key: 1 px in each direction
1458                         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1459                         if( m_pChartWindow )
1460                         {
1461                             Size aPixelSize = m_pChartWindow->PixelToLogic( Size( 2, 2 ));
1462                             fGrowAmountX = static_cast< double >( aPixelSize.Width());
1463                             fGrowAmountY = static_cast< double >( aPixelSize.Height());
1464                         }
1465                     }
1466                     if( nCode == KEY_SUBTRACT )
1467                     {
1468                         fGrowAmountX = -fGrowAmountX;
1469                         fGrowAmountY = -fGrowAmountY;
1470                     }
1471                     bReturn = impl_moveOrResizeObject(
1472                         m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY );
1473                 }
1474             }
1475             // position
1476             else if( nCode == KEY_LEFT  ||
1477                      nCode == KEY_RIGHT ||
1478                      nCode == KEY_UP ||
1479                      nCode == KEY_DOWN )
1480             {
1481                 if( m_aSelection.isDragableObjectSelected() )
1482                 {
1483                     // default 1 mm
1484                     double fShiftAmountX = 100.0;
1485                     double fShiftAmountY = 100.0;
1486                     if( bAlternate && m_pChartWindow )
1487                     {
1488                         // together with Alt-key: 1 px
1489                         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1490                         if(m_pChartWindow)
1491                         {
1492                             Size aPixelSize = m_pChartWindow->PixelToLogic( Size( 1, 1 ));
1493                             fShiftAmountX = static_cast< double >( aPixelSize.Width());
1494                             fShiftAmountY = static_cast< double >( aPixelSize.Height());
1495                         }
1496                     }
1497                     switch( nCode )
1498                     {
1499                         case KEY_LEFT:
1500                             fShiftAmountX = -fShiftAmountX;
1501                             fShiftAmountY = 0.0;
1502                             break;
1503                         case KEY_RIGHT:
1504                             fShiftAmountY = 0.0;
1505                             break;
1506                         case KEY_UP:
1507                             fShiftAmountX = 0.0;
1508                             fShiftAmountY = -fShiftAmountY;
1509                             break;
1510                         case KEY_DOWN:
1511                             fShiftAmountX = 0.0;
1512                             break;
1513                     }
1514                     if( m_aSelection.getSelectedCID().getLength() )
1515                     {
1516                         //move chart objects
1517                         bReturn = impl_moveOrResizeObject(
1518                             m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY );
1519                     }
1520                     else
1521                     {
1522                         //move additional shapes
1523                         uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() );
1524                         if( xShape.is() )
1525                         {
1526                             awt::Point aPos( xShape->getPosition() );
1527                             awt::Size aSize( xShape->getSize() );
1528                             awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
1529                             aPos.X = static_cast< long >( static_cast< double >( aPos.X ) + fShiftAmountX );
1530                             aPos.Y = static_cast< long >( static_cast< double >( aPos.Y ) + fShiftAmountY );
1531                             if( aPos.X + aSize.Width > aPageSize.Width )
1532                                 aPos.X = aPageSize.Width - aSize.Width;
1533                             if( aPos.X < 0 )
1534                                 aPos.X = 0;
1535                             if( aPos.Y + aSize.Height > aPageSize.Height )
1536                                 aPos.Y = aPageSize.Height - aSize.Height;
1537                             if( aPos.Y < 0 )
1538                                 aPos.Y = 0;
1539 
1540                             xShape->setPosition( aPos );
1541                         }
1542                     }
1543                 }
1544             }
1545         }
1546     }
1547 
1548     // text edit
1549     if( ! bReturn &&
1550         nCode == KEY_F2 )
1551     {
1552         if( OBJECTTYPE_TITLE == eObjectType )
1553         {
1554             executeDispatch_EditText();
1555             bReturn = true;
1556         }
1557     }
1558 
1559     // deactivate inplace mode (this code should be unnecessary, but
1560     // unfortunately is not)
1561     if( ! bReturn &&
1562         nCode == KEY_ESCAPE )
1563     {
1564         uno::Reference< frame::XDispatchHelper > xDispatchHelper(
1565             m_xCC->getServiceManager()->createInstanceWithContext(
1566                 C2U("com.sun.star.frame.DispatchHelper"), m_xCC ), uno::UNO_QUERY );
1567         if( xDispatchHelper.is())
1568         {
1569             uno::Sequence< beans::PropertyValue > aArgs;
1570             xDispatchHelper->executeDispatch(
1571                 uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ),
1572                 C2U(".uno:TerminateInplaceActivation"),
1573                 C2U("_parent"),
1574                 frame::FrameSearchFlag::PARENT,
1575                 aArgs );
1576             bReturn = true;
1577         }
1578     }
1579 
1580     if( ! bReturn &&
1581         (nCode == KEY_DELETE || nCode == KEY_BACKSPACE ))
1582     {
1583         bReturn = executeDispatch_Delete();
1584         if( ! bReturn )
1585         {
1586             ::vos::OGuard aGuard( Application::GetSolarMutex() );
1587             InfoBox( m_pChartWindow, String(SchResId( STR_ACTION_NOTPOSSIBLE ))).Execute();
1588         }
1589     }
1590 
1591     /* old chart:
1592     // Ctrl-Shift-R: Repaint
1593 	if (!bReturn && GetWindow())
1594 	{
1595 		KeyCode aKeyCode = rKEvt.GetKeyCode();
1596 
1597 		if (aKeyCode.IsMod1() && aKeyCode.IsShift()
1598 			&& aKeyCode.GetCode() == KEY_R)
1599 		{
1600 				// 3D-Kontext wieder zerstoeren
1601 			GetWindow()->Invalidate();
1602 			bReturn = sal_True;
1603 		}
1604 	}
1605     */
1606     return bReturn;
1607 }
1608 
1609 bool ChartController::requestQuickHelp(
1610     ::Point aAtLogicPosition,
1611     bool bIsBalloonHelp,
1612     ::rtl::OUString & rOutQuickHelpText,
1613     awt::Rectangle & rOutEqualRect )
1614 {
1615     uno::Reference< frame::XModel > xChartModel;
1616     if( m_aModel.is())
1617         xChartModel.set( getModel() );
1618     if( !xChartModel.is())
1619         return false;
1620 
1621     // help text
1622     ::rtl::OUString aCID;
1623     if( m_pDrawViewWrapper )
1624     {
1625         aCID = SelectionHelper::getHitObjectCID(
1626             aAtLogicPosition, *m_pDrawViewWrapper );
1627     }
1628     bool bResult( aCID.getLength());
1629 
1630     if( bResult )
1631     {
1632         // get help text
1633         rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ );
1634 
1635         // set rectangle
1636         ExplicitValueProvider * pValueProvider(
1637             ExplicitValueProvider::getExplicitValueProvider( m_xChartView ));
1638         if( pValueProvider )
1639             rOutEqualRect = pValueProvider->getRectangleOfObject( aCID, true );
1640     }
1641 
1642     return bResult;
1643 }
1644 
1645 //-----------------------------------------------------------------
1646 // XSelectionSupplier (optional interface)
1647 //-----------------------------------------------------------------
1648 		sal_Bool SAL_CALL ChartController
1649 ::select( const uno::Any& rSelection )
1650 		throw( lang::IllegalArgumentException )
1651 {
1652     bool bSuccess = false;
1653 
1654     if ( rSelection.hasValue() )
1655     {
1656         const uno::Type& rType = rSelection.getValueType();
1657         if ( rType == ::getCppuType( static_cast< const ::rtl::OUString* >( 0 ) ) )
1658         {
1659             ::rtl::OUString aNewCID;
1660             if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) )
1661             {
1662                 bSuccess = true;
1663             }
1664         }
1665         else if ( rType == ::getCppuType( static_cast< const uno::Reference< drawing::XShape >* >( 0 ) ) )
1666         {
1667             uno::Reference< drawing::XShape > xShape;
1668             if ( ( rSelection >>= xShape ) && m_aSelection.setSelection( xShape ) )
1669             {
1670                 bSuccess = true;
1671             }
1672         }
1673     }
1674     else
1675     {
1676         if ( m_aSelection.hasSelection() )
1677         {
1678             m_aSelection.clearSelection();
1679             bSuccess = true;
1680         }
1681     }
1682 
1683     if ( bSuccess )
1684     {
1685         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1686         if ( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
1687         {
1688             this->EndTextEdit();
1689         }
1690         this->impl_selectObjectAndNotiy();
1691         if ( m_pChartWindow )
1692         {
1693             m_pChartWindow->Invalidate();
1694         }
1695         return sal_True;
1696     }
1697 
1698     return sal_False;
1699 }
1700 
1701 		uno::Any SAL_CALL ChartController
1702 ::getSelection() throw(uno::RuntimeException)
1703 {
1704     uno::Any aReturn;
1705     if ( m_aSelection.hasSelection() )
1706     {
1707         ::rtl::OUString aCID( m_aSelection.getSelectedCID() );
1708         if ( aCID.getLength() )
1709         {
1710             aReturn = uno::makeAny( aCID );
1711         }
1712         else
1713         {
1714             // #i12587# support for shapes in chart
1715             aReturn = uno::makeAny( m_aSelection.getSelectedAdditionalShape() );
1716         }
1717     }
1718     return aReturn;
1719 }
1720 
1721 		void SAL_CALL ChartController
1722 ::addSelectionChangeListener( const uno::Reference<
1723 		view::XSelectionChangeListener > & xListener )
1724 		throw(uno::RuntimeException)
1725 {
1726     ::vos::OGuard aGuard( Application::GetSolarMutex());
1727 	if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
1728 		return; //behave passive if already disposed or suspended
1729 
1730 	//--add listener
1731 	m_aLifeTimeManager.m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0), xListener );
1732 }
1733 
1734 		void SAL_CALL ChartController
1735 ::removeSelectionChangeListener( const uno::Reference<
1736 		view::XSelectionChangeListener > & xListener )
1737 		throw(uno::RuntimeException)
1738 {
1739 	::vos::OGuard aGuard( Application::GetSolarMutex());
1740 	if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode?
1741 		return; //behave passive if already disposed or suspended
1742 
1743 	//--remove listener
1744 	m_aLifeTimeManager.m_aListenerContainer.removeInterface( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0), xListener );
1745 }
1746 
1747 		void ChartController
1748 ::impl_notifySelectionChangeListeners()
1749 {
1750 	::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer
1751 		.getContainer( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0) );
1752 	if( pIC )
1753 	{
1754         uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this);
1755 		lang::EventObject aEvent( xSelectionSupplier );
1756 		::cppu::OInterfaceIteratorHelper aIt( *pIC );
1757 		while( aIt.hasMoreElements() )
1758         {
1759             uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
1760             if( xListener.is() )
1761                 xListener->selectionChanged( aEvent );
1762         }
1763 	}
1764 }
1765 
1766 void ChartController::impl_selectObjectAndNotiy()
1767 {
1768     {
1769         ::vos::OGuard aGuard( Application::GetSolarMutex() );
1770         DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
1771         if( pDrawViewWrapper )
1772         {
1773             pDrawViewWrapper->SetDragMode( m_eDragMode );
1774             m_aSelection.applySelection( m_pDrawViewWrapper );
1775         }
1776     }
1777     impl_notifySelectionChangeListeners();
1778 }
1779 
1780 bool ChartController::impl_moveOrResizeObject(
1781     const ::rtl::OUString & rCID,
1782     eMoveOrResizeType eType,
1783     double fAmountLogicX,
1784     double fAmountLogicY )
1785 {
1786     bool bResult = false;
1787     bool bNeedShift = true;
1788     bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT );
1789 
1790     uno::Reference< frame::XModel > xChartModel( getModel() );
1791     uno::Reference< beans::XPropertySet > xObjProp(
1792         ObjectIdentifier::getObjectPropertySet( rCID, xChartModel ));
1793     if( xObjProp.is())
1794     {
1795         awt::Size aRefSize = ChartModelHelper::getPageSize( xChartModel );
1796 
1797         chart2::RelativePosition aRelPos;
1798         chart2::RelativeSize     aRelSize;
1799         bool bDeterminePos  = !(xObjProp->getPropertyValue( C2U("RelativePosition")) >>= aRelPos);
1800         bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( C2U("RelativeSize")) >>= aRelSize);
1801 
1802         if( ( bDeterminePos || bDetermineSize ) &&
1803             ( aRefSize.Width > 0 && aRefSize.Height > 0 ) )
1804         {
1805             ExplicitValueProvider * pValueProvider(
1806                 ExplicitValueProvider::getExplicitValueProvider( m_xChartView ));
1807             if( pValueProvider )
1808             {
1809                 awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID ));
1810                 double fWidth = static_cast< double >( aRefSize.Width );
1811                 double fHeight = static_cast< double >( aRefSize.Height );
1812                 if( bDetermineSize )
1813                 {
1814                     aRelSize.Primary   = static_cast< double >( aRect.Width ) / fWidth;
1815                     aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight;
1816                 }
1817                 if( bDeterminePos )
1818                 {
1819                     if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 )
1820                     {
1821                         aRelPos.Primary   = (static_cast< double >( aRect.X ) / fWidth) +
1822                             (aRelSize.Primary / 2.0);
1823                         aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) +
1824                             (aRelSize.Secondary / 2.0);
1825                         aRelPos.Anchor = drawing::Alignment_CENTER;
1826                     }
1827                     else
1828                     {
1829                         aRelPos.Primary   = static_cast< double >( aRect.X ) / fWidth;
1830                         aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight;
1831                         aRelPos.Anchor = drawing::Alignment_TOP_LEFT;
1832                     }
1833                 }
1834             }
1835         }
1836 
1837         if( eType == CENTERED_RESIZE_OBJECT )
1838             bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1839         else if( eType == MOVE_OBJECT )
1840             bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1841 
1842         if( bResult )
1843         {
1844             ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::MOVE);
1845             if( bNeedResize )
1846                 eActionType = ActionDescriptionProvider::RESIZE;
1847 
1848             ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
1849             UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
1850                     eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager );
1851             {
1852                 ControllerLockGuard aCLGuard( xChartModel );
1853                 if( bNeedShift )
1854                     xObjProp->setPropertyValue( C2U("RelativePosition"), uno::makeAny( aRelPos ));
1855                 if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicat size at the diagram when an explicit position is set
1856                     xObjProp->setPropertyValue( C2U("RelativeSize"), uno::makeAny( aRelSize ));
1857             }
1858             aUndoGuard.commit();
1859         }
1860     }
1861     return bResult;
1862 }
1863 
1864 bool ChartController::impl_DragDataPoint( const ::rtl::OUString & rCID, double fAdditionalOffset )
1865 {
1866     bool bResult = false;
1867     if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 )
1868         return bResult;
1869 
1870     sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID );
1871     uno::Reference< chart2::XDataSeries > xSeries(
1872         ObjectIdentifier::getDataSeriesForCID( rCID, getModel() ));
1873     if( xSeries.is())
1874     {
1875         try
1876         {
1877             uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex ));
1878             double fOffset = 0.0;
1879             if( xPointProp.is() &&
1880                 (xPointProp->getPropertyValue( C2U("Offset" )) >>= fOffset ) &&
1881                 (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) )
1882             {
1883                 fOffset += fAdditionalOffset;
1884                 if( fOffset > 1.0 )
1885                     fOffset = 1.0;
1886                 else if( fOffset < 0.0 )
1887                     fOffset = 0.0;
1888                 xPointProp->setPropertyValue( C2U("Offset"), uno::makeAny( fOffset ));
1889                 bResult = true;
1890             }
1891         }
1892         catch( const uno::Exception & ex )
1893         {
1894             ASSERT_EXCEPTION( ex );
1895         }
1896     }
1897 
1898     return bResult;
1899 }
1900 
1901 void ChartController::impl_SetMousePointer( const MouseEvent & rEvent )
1902 {
1903     ::vos::OGuard aGuard( Application::GetSolarMutex());
1904     if( m_pDrawViewWrapper && m_pChartWindow )
1905     {
1906         Point aMousePos( m_pChartWindow->PixelToLogic( rEvent.GetPosPixel()));
1907 		sal_uInt16 nModifier = rEvent.GetModifier();
1908 		sal_Bool bLeftDown = rEvent.IsLeft();
1909 
1910         if ( m_pDrawViewWrapper->IsTextEdit() )
1911         {
1912             if( m_pDrawViewWrapper->IsTextEditHit( aMousePos, HITPIX) )
1913             {
1914                 m_pChartWindow->SetPointer( m_pDrawViewWrapper->GetPreferedPointer(
1915                     aMousePos, m_pChartWindow, nModifier, bLeftDown ) );
1916                 return;
1917             }
1918         }
1919         else if( m_pDrawViewWrapper->IsAction() )
1920         {
1921             return;//don't change pointer during running action
1922         }
1923 
1924         SdrHdl* pHitSelectionHdl = 0;
1925         if( m_aSelection.isResizeableObjectSelected() )
1926             pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos );
1927 
1928         if( pHitSelectionHdl )
1929         {
1930 
1931             Pointer aPointer = m_pDrawViewWrapper->GetPreferedPointer(
1932                 aMousePos, m_pChartWindow, nModifier, bLeftDown );
1933             bool bForceArrowPointer = false;
1934 
1935             ObjectIdentifier aOID( m_aSelection.getSelectedOID() );
1936 
1937             switch( aPointer.GetStyle())
1938             {
1939                 case POINTER_NSIZE:
1940                 case POINTER_SSIZE:
1941                 case POINTER_WSIZE:
1942                 case POINTER_ESIZE:
1943                 case POINTER_NWSIZE:
1944                 case POINTER_NESIZE:
1945                 case POINTER_SWSIZE:
1946                 case POINTER_SESIZE:
1947                     if( ! m_aSelection.isResizeableObjectSelected() )
1948                         bForceArrowPointer = true;
1949                     break;
1950                 case POINTER_MOVE:
1951                     if ( !aOID.isDragableObject() )
1952                         bForceArrowPointer = true;
1953                     break;
1954                 case POINTER_MOVEPOINT:
1955                 case POINTER_MOVEBEZIERWEIGHT:
1956                     // there is no point-editing in a chart
1957                     // the POINTER_MOVEBEZIERWEIGHT appears in 3d data points
1958                     bForceArrowPointer = true;
1959                     break;
1960                 default:
1961                     break;
1962             }
1963 
1964             if( bForceArrowPointer )
1965                 m_pChartWindow->SetPointer( Pointer( POINTER_ARROW ));
1966             else
1967                 m_pChartWindow->SetPointer( aPointer );
1968         }
1969         else
1970         {
1971             // #i12587# support for shapes in chart
1972             if ( m_eDrawMode == CHARTDRAW_INSERT &&
1973                  ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) )
1974             {
1975                 PointerStyle ePointerStyle = POINTER_DRAW_RECT;
1976                 SdrObjKind eKind = static_cast< SdrObjKind >( m_pDrawViewWrapper->GetCurrentObjIdentifier() );
1977                 switch ( eKind )
1978                 {
1979                     case OBJ_LINE:
1980                         {
1981                             ePointerStyle = POINTER_DRAW_LINE;
1982                         }
1983                         break;
1984                     case OBJ_RECT:
1985                     case OBJ_CUSTOMSHAPE:
1986                         {
1987                             ePointerStyle = POINTER_DRAW_RECT;
1988                         }
1989                         break;
1990                     case OBJ_CIRC:
1991                         {
1992                             ePointerStyle = POINTER_DRAW_ELLIPSE;
1993                         }
1994                         break;
1995                     case OBJ_FREELINE:
1996                         {
1997                             ePointerStyle = POINTER_DRAW_POLYGON;
1998                         }
1999                         break;
2000                     case OBJ_TEXT:
2001                         {
2002                             ePointerStyle = POINTER_DRAW_TEXT;
2003                         }
2004                         break;
2005                     case OBJ_CAPTION:
2006                         {
2007                             ePointerStyle = POINTER_DRAW_CAPTION;
2008                         }
2009                         break;
2010                     default:
2011                         {
2012                             ePointerStyle = POINTER_DRAW_RECT;
2013                         }
2014                         break;
2015                 }
2016                 m_pChartWindow->SetPointer( Pointer( ePointerStyle ) );
2017                 return;
2018             }
2019 
2020             ::rtl::OUString aHitObjectCID(
2021                 SelectionHelper::getHitObjectCID(
2022                     aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ ));
2023 
2024             if( m_pDrawViewWrapper->IsTextEdit() )
2025             {
2026                 if( aHitObjectCID.equals(m_aSelection.getSelectedCID()) )
2027                 {
2028                     m_pChartWindow->SetPointer( Pointer( POINTER_ARROW ));
2029                     return;
2030                 }
2031             }
2032 
2033             if( !aHitObjectCID.getLength() )
2034             {
2035                 //additional shape was hit
2036                 m_pChartWindow->SetPointer( POINTER_MOVE );
2037             }
2038             else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) )
2039             {
2040                 if( (m_eDragMode == SDRDRAG_ROTATE)
2041                     && SelectionHelper::isRotateableObject( aHitObjectCID
2042                         , getModel() ) )
2043                     m_pChartWindow->SetPointer( Pointer( POINTER_ROTATE ) );
2044                 else
2045                 {
2046                     ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID );
2047                     if( eHitObjectType == OBJECTTYPE_DATA_POINT )
2048                     {
2049                         if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID())
2050                             && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) )
2051                         {
2052                             m_pChartWindow->SetPointer( Pointer( POINTER_ARROW ));
2053                             return;
2054                         }
2055                     }
2056                     m_pChartWindow->SetPointer( POINTER_MOVE );
2057                 }
2058             }
2059             else
2060                 m_pChartWindow->SetPointer( Pointer( POINTER_ARROW ));
2061         }
2062     }
2063 }
2064 
2065 //.............................................................................
2066 } //namespace chart
2067 //.............................................................................
2068