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