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