/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_chart2.hxx" #include "ChartController.hxx" #include "PositionAndSizeHelper.hxx" #include "ObjectIdentifier.hxx" #include "ChartWindow.hxx" #include "ResId.hxx" #include "CommonConverters.hxx" #include "ChartModelHelper.hxx" #include "DiagramHelper.hxx" #include "TitleHelper.hxx" #include "UndoGuard.hxx" #include "ControllerLockGuard.hxx" #include "ObjectNameProvider.hxx" #include "Strings.hrc" #include "SchSlotIds.hxx" #include "macros.hxx" #include "DragMethod_PieSegment.hxx" #include "DragMethod_RotateDiagram.hxx" #include "ObjectHierarchy.hxx" #include "chartview/ExplicitValueProvider.hxx" #include "RelativePositionHelper.hxx" #include "chartview/DrawModelWrapper.hxx" #include "RegressionCurveHelper.hxx" #include "StatisticsHelper.hxx" #include "DataSeriesHelper.hxx" #include "ContainerHelper.hxx" #include "AxisHelper.hxx" #include "LegendHelper.hxx" #include "servicenames_charttypes.hxx" #include "MenuResIds.hrc" #include "DrawCommandDispatch.hxx" #include #include #include #include #include #include #include #include #include #include #include // header for class E3dObject #include // header for class E3dScene #include // header for class SdrDragMethod #include #include #include // for InfoBox #include #include #include #define DRGPIX 2 // Drag MinMove in Pixel using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; using ::rtl::OUString; //............................................................................. namespace chart { //............................................................................. namespace { bool lcl_GrowAndShiftLogic( RelativePosition & rInOutRelPos, RelativeSize & rInOutRelSize, const awt::Size & rRefSize, double fGrowLogicX, double fGrowLogicY ) { if( rRefSize.Width == 0 || rRefSize.Height == 0 ) return false; double fRelativeGrowX = fGrowLogicX / rRefSize.Width; double fRelativeGrowY = fGrowLogicY / rRefSize.Height; return ::chart::RelativePositionHelper::centerGrow( rInOutRelPos, rInOutRelSize, fRelativeGrowX, fRelativeGrowY, /* bCheck = */ true ); } bool lcl_MoveObjectLogic( RelativePosition & rInOutRelPos, RelativeSize & rObjectSize, const awt::Size & rRefSize, double fShiftLogicX, double fShiftLogicY ) { if( rRefSize.Width == 0 || rRefSize.Height == 0 ) return false; double fRelativeShiftX = fShiftLogicX / rRefSize.Width; double fRelativeShiftY = fShiftLogicY / rRefSize.Height; return ::chart::RelativePositionHelper::moveObject( rInOutRelPos, rObjectSize, fRelativeShiftX, fRelativeShiftY, /* bCheck = */ true ); } void lcl_insertMenuCommand( const uno::Reference< awt::XPopupMenu > & xMenu, sal_Int16 nId, const ::rtl::OUString & rCommand ) { static ::rtl::OUString aEmptyString; xMenu->insertItem( nId, aEmptyString, 0, -1 ); xMenu->setCommand( nId, rCommand ); } OUString lcl_getFormatCommandForObjectCID( const OUString& rCID ) { OUString aDispatchCommand( C2U(".uno:FormatSelection") ); ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID ); switch(eObjectType) { case OBJECTTYPE_DIAGRAM: case OBJECTTYPE_DIAGRAM_WALL: aDispatchCommand = C2U(".uno:FormatWall"); break; case OBJECTTYPE_DIAGRAM_FLOOR: aDispatchCommand = C2U(".uno:FormatFloor"); break; case OBJECTTYPE_PAGE: aDispatchCommand = C2U(".uno:FormatChartArea"); break; case OBJECTTYPE_LEGEND: aDispatchCommand = C2U(".uno:FormatLegend"); break; case OBJECTTYPE_TITLE: aDispatchCommand = C2U(".uno:FormatTitle"); break; case OBJECTTYPE_LEGEND_ENTRY: aDispatchCommand = C2U(".uno:FormatDataSeries"); break; case OBJECTTYPE_AXIS: case OBJECTTYPE_AXIS_UNITLABEL: aDispatchCommand = C2U(".uno:FormatAxis"); break; case OBJECTTYPE_GRID: aDispatchCommand = C2U(".uno:FormatMajorGrid"); break; case OBJECTTYPE_SUBGRID: aDispatchCommand = C2U(".uno:FormatMinorGrid"); break; case OBJECTTYPE_DATA_LABELS: aDispatchCommand = C2U(".uno:FormatDataLabels"); break; case OBJECTTYPE_DATA_SERIES: aDispatchCommand = C2U(".uno:FormatDataSeries"); break; case OBJECTTYPE_DATA_LABEL: aDispatchCommand = C2U(".uno:FormatDataLabel"); break; case OBJECTTYPE_DATA_POINT: aDispatchCommand = C2U(".uno:FormatDataPoint"); break; case OBJECTTYPE_DATA_AVERAGE_LINE: aDispatchCommand = C2U(".uno:FormatMeanValue"); break; case OBJECTTYPE_DATA_ERRORS: case OBJECTTYPE_DATA_ERRORS_X: case OBJECTTYPE_DATA_ERRORS_Y: case OBJECTTYPE_DATA_ERRORS_Z: aDispatchCommand = C2U(".uno:FormatYErrorBars"); break; case OBJECTTYPE_DATA_CURVE: aDispatchCommand = C2U(".uno:FormatTrendline"); break; case OBJECTTYPE_DATA_CURVE_EQUATION: aDispatchCommand = C2U(".uno:FormatTrendlineEquation"); break; case OBJECTTYPE_DATA_STOCK_RANGE: aDispatchCommand = C2U(".uno:FormatSelection"); break; case OBJECTTYPE_DATA_STOCK_LOSS: aDispatchCommand = C2U(".uno:FormatStockLoss"); break; case OBJECTTYPE_DATA_STOCK_GAIN: aDispatchCommand = C2U(".uno:FormatStockGain"); break; default: //OBJECTTYPE_UNKNOWN break; } return aDispatchCommand; } } // anonymous namespace const short HITPIX=2; //hit-tolerance in pixel //----------------------------------------------------------------- // awt::XWindow //----------------------------------------------------------------- void SAL_CALL ChartController ::setPosSize( sal_Int32 X, sal_Int32 Y , sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) throw (uno::RuntimeException) { ::vos::OGuard aGuard( Application::GetSolarMutex() ); uno::Reference xWindow = m_xViewWindow; if(xWindow.is() && m_pChartWindow) { Size aLogicSize = m_pChartWindow->PixelToLogic( Size( Width, Height ), MapMode( MAP_100TH_MM ) ); bool bIsEmbedded = true; //todo: for standalone chart: detect whether we are standalone if( bIsEmbedded ) { //change map mode to fit new size awt::Size aModelPageSize = ChartModelHelper::getPageSize( getModel() ); sal_Int32 nScaleXNumerator = aLogicSize.Width(); sal_Int32 nScaleXDenominator = aModelPageSize.Width; sal_Int32 nScaleYNumerator = aLogicSize.Height(); sal_Int32 nScaleYDenominator = aModelPageSize.Height; MapMode aNewMapMode( MAP_100TH_MM, Point(0,0) , Fraction(nScaleXNumerator,nScaleXDenominator) , Fraction(nScaleYNumerator,nScaleYDenominator) ); m_pChartWindow->SetMapMode(aNewMapMode); m_pChartWindow->SetPosSizePixel( X, Y, Width, Height, Flags ); //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100% uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY ); if( xProp.is() ) { uno::Sequence< beans::PropertyValue > aZoomFactors(4); aZoomFactors[0].Name = C2U("ScaleXNumerator"); aZoomFactors[0].Value = uno::makeAny( nScaleXNumerator ); aZoomFactors[1].Name = C2U("ScaleXDenominator"); aZoomFactors[1].Value = uno::makeAny( nScaleXDenominator ); aZoomFactors[2].Name = C2U("ScaleYNumerator"); aZoomFactors[2].Value = uno::makeAny( nScaleYNumerator ); aZoomFactors[3].Name = C2U("ScaleYDenominator"); aZoomFactors[3].Value = uno::makeAny( nScaleYDenominator ); xProp->setPropertyValue( C2U("ZoomFactors"), uno::makeAny( aZoomFactors )); } //a correct work area is at least necessary for correct values in the position and size dialog and for dragging area if(m_pDrawViewWrapper) { Rectangle aRect(Point(0,0), m_pChartWindow->GetOutputSize()); m_pDrawViewWrapper->SetWorkArea( aRect ); } } else { //change visarea ChartModelHelper::setPageSize( awt::Size( aLogicSize.Width(), aLogicSize.Height() ), getModel() ); m_pChartWindow->SetPosSizePixel( X, Y, Width, Height, Flags ); } m_pChartWindow->Invalidate(); } } awt::Rectangle SAL_CALL ChartController ::getPosSize() throw (uno::RuntimeException) { //@todo awt::Rectangle aRet(0,0,0,0); uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) aRet = xWindow->getPosSize(); return aRet; } void SAL_CALL ChartController ::setVisible( sal_Bool Visible ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->setVisible( Visible ); } void SAL_CALL ChartController ::setEnable( sal_Bool Enable ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->setEnable( Enable ); } void SAL_CALL ChartController ::setFocus() throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->setFocus(); } void SAL_CALL ChartController ::addWindowListener( const uno::Reference< awt::XWindowListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->addWindowListener( xListener ); } void SAL_CALL ChartController ::removeWindowListener( const uno::Reference< awt::XWindowListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->removeWindowListener( xListener ); } void SAL_CALL ChartController ::addFocusListener( const uno::Reference< awt::XFocusListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->addFocusListener( xListener ); } void SAL_CALL ChartController ::removeFocusListener( const uno::Reference< awt::XFocusListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->removeFocusListener( xListener ); } void SAL_CALL ChartController ::addKeyListener( const uno::Reference< awt::XKeyListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->addKeyListener( xListener ); } void SAL_CALL ChartController ::removeKeyListener( const uno::Reference< awt::XKeyListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->removeKeyListener( xListener ); } void SAL_CALL ChartController ::addMouseListener( const uno::Reference< awt::XMouseListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->addMouseListener( xListener ); } void SAL_CALL ChartController ::removeMouseListener( const uno::Reference< awt::XMouseListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->removeMouseListener( xListener ); } void SAL_CALL ChartController ::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->addMouseMotionListener( xListener ); } void SAL_CALL ChartController ::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->removeMouseMotionListener( xListener ); } void SAL_CALL ChartController ::addPaintListener( const uno::Reference< awt::XPaintListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->addPaintListener( xListener ); } void SAL_CALL ChartController ::removePaintListener( const uno::Reference< awt::XPaintListener >& xListener ) throw (uno::RuntimeException) { //@todo uno::Reference xWindow = m_xViewWindow; if(xWindow.is()) xWindow->removePaintListener( xListener ); } //----------------------------------------------------------------- // impl vcl window controller methods //----------------------------------------------------------------- void ChartController::PrePaint() { // forward VCLs PrePaint window event to DrawingLayer DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(pDrawViewWrapper) { pDrawViewWrapper->PrePaint(); } } void ChartController::execute_Paint( const Rectangle& rRect ) { try { uno::Reference< frame::XModel > xModel( getModel() ); //DBG_ASSERT( xModel.is(), "ChartController::execute_Paint: have no model to paint"); if( !xModel.is() ) return; //better performance for big data uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY ); if( xProp.is() ) { awt::Size aResolution(1000,1000); { ::vos::OGuard aGuard( Application::GetSolarMutex()); if( m_pChartWindow ) { aResolution.Width = m_pChartWindow->GetSizePixel().Width(); aResolution.Height = m_pChartWindow->GetSizePixel().Height(); } } xProp->setPropertyValue( C2U("Resolution"), uno::makeAny( aResolution )); } // uno::Reference< util::XUpdatable > xUpdatable( m_xChartView, uno::UNO_QUERY ); if( xUpdatable.is() ) xUpdatable->update(); { ::vos::OGuard aGuard( Application::GetSolarMutex()); DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(pDrawViewWrapper) pDrawViewWrapper->CompleteRedraw(m_pChartWindow, Region(rRect) ); } } catch( uno::Exception & ex ) { ASSERT_EXCEPTION( ex ); } catch( ... ) { } } bool isDoubleClick( const MouseEvent& rMEvt ) { return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void ChartController::startDoubleClickWaiting() { ::vos::OGuard aGuard( Application::GetSolarMutex() ); m_bWaitingForDoubleClick = true; sal_uLong nDblClkTime = 500; if( m_pChartWindow ) { const MouseSettings& rMSettings = m_pChartWindow->GetSettings().GetMouseSettings(); nDblClkTime = rMSettings.GetDoubleClickTime(); } m_aDoubleClickTimer.SetTimeout( nDblClkTime ); m_aDoubleClickTimer.Start(); } void ChartController::stopDoubleClickWaiting() { m_aDoubleClickTimer.Stop(); m_bWaitingForDoubleClick = false; } IMPL_LINK( ChartController, DoubleClickWaitingHdl, void*, EMPTYARG ) { m_bWaitingForDoubleClick = false; if( !m_bWaitingForMouseUp && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() ) { this->impl_selectObjectAndNotiy(); ::vos::OGuard aGuard( Application::GetSolarMutex() ); if( m_pChartWindow ) { Window::PointerState aPointerState( m_pChartWindow->GetPointerState() ); MouseEvent aMouseEvent( aPointerState.maPos,1/*nClicks*/, 0/*nMode*/, static_cast< sal_uInt16 >( aPointerState.mnState )/*nButtons*/, 0/*nModifier*/ ); impl_SetMousePointer( aMouseEvent ); } } return 0; } //------------------------------------------------------------------------ void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt ) { ::vos::OGuard aGuard( Application::GetSolarMutex()); m_bWaitingForMouseUp = true; if( isDoubleClick(rMEvt) ) stopDoubleClickWaiting(); else startDoubleClickWaiting(); m_aSelection.remindSelectionBeforeMouseDown(); DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(!m_pChartWindow || !pDrawViewWrapper ) return; Point aMPos = m_pChartWindow->PixelToLogic(rMEvt.GetPosPixel()); if ( MOUSE_LEFT == rMEvt.GetButtons() ) { m_pChartWindow->GrabFocus(); m_pChartWindow->CaptureMouse(); } if( pDrawViewWrapper->IsTextEdit() ) { SdrViewEvent aVEvt; if ( pDrawViewWrapper->IsTextEditHit( aMPos, HITPIX ) || // #i12587# support for shapes in chart ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt ) == SDRHIT_MARKEDOBJECT ) ) { pDrawViewWrapper->MouseButtonDown(rMEvt,m_pChartWindow); return; } else { this->EndTextEdit(); } } //abort running action if( pDrawViewWrapper->IsAction() ) { if( rMEvt.IsRight() ) pDrawViewWrapper->BckAction(); return; } if( isDoubleClick(rMEvt) ) //do not change selection if double click return;//double click is handled further in mousebutton up SdrHdl* pHitSelectionHdl = 0; //switch from move to resize if handle is hit on a resizeable object if( m_aSelection.isResizeableObjectSelected() ) pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos ); //only change selection if no selection handles are hit if( !pHitSelectionHdl ) { // #i12587# support for shapes in chart if ( m_eDrawMode == CHARTDRAW_INSERT && ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) ) { if ( m_aSelection.hasSelection() ) { m_aSelection.clearSelection(); } if ( !pDrawViewWrapper->IsAction() ) { if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_CAPTION ) { Size aCaptionSize( 2268, 1134 ); pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize ); } else { pDrawViewWrapper->BegCreateObj( aMPos); } SdrObject* pObj = pDrawViewWrapper->GetCreateObj(); DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch(); if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch ) { SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() ); pDrawCommandDispatch->setAttributes( pObj ); pDrawCommandDispatch->setLineEnds( aSet ); pObj->SetMergedItemSet( aSet ); } } impl_SetMousePointer( rMEvt ); return; } m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper , rMEvt.IsRight(), m_bWaitingForDoubleClick ); if( !m_aSelection.isRotateableObjectSelected( getModel() ) ) { m_eDragMode = SDRDRAG_MOVE; pDrawViewWrapper->SetDragMode(m_eDragMode); } m_aSelection.applySelection(pDrawViewWrapper); } if( m_aSelection.isDragableObjectSelected() && !rMEvt.IsRight() ) { //start drag sal_uInt16 nDrgLog = (sal_uInt16)m_pChartWindow->PixelToLogic(Size(DRGPIX,0)).Width(); SdrDragMethod* pDragMethod = NULL; //change selection to 3D scene if rotate mode SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode(); if( SDRDRAG_ROTATE==eDragMode ) { E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) ); if( pScene ) { DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE); if(pHitSelectionHdl) { SdrHdlKind eKind = pHitSelectionHdl->GetKind(); if( eKind==HDL_UPPER || eKind==HDL_LOWER ) eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X; else if( eKind==HDL_LEFT || eKind==HDL_RIGHT ) eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y; else if( eKind==HDL_UPLFT || eKind==HDL_UPRGT || eKind==HDL_LWLFT || eKind==HDL_LWRGT ) eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z; } pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel(), eRotationDirection ); } } else { rtl::OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ); if( aDragMethodServiceName.equals( ObjectIdentifier::getPieSegmentDragMethodServiceName() ) ) pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel() ); } pDrawViewWrapper->SdrView::BegDragObj(aMPos, NULL, pHitSelectionHdl, nDrgLog, pDragMethod); } impl_SetMousePointer( rMEvt ); } void ChartController::execute_MouseMove( const MouseEvent& rMEvt ) { ::vos::OGuard aGuard( Application::GetSolarMutex()); DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(!m_pChartWindow || !pDrawViewWrapper) return; if( m_pDrawViewWrapper->IsTextEdit() ) { if( m_pDrawViewWrapper->MouseMove(rMEvt,m_pChartWindow) ) return; } if(pDrawViewWrapper->IsAction()) { pDrawViewWrapper->MovAction( m_pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); } //?? pDrawViewWrapper->GetPageView()->DragPoly(); impl_SetMousePointer( rMEvt ); } void ChartController::execute_Tracking( const TrackingEvent& /* rTEvt */ ) { } //----------------- void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt ) { ControllerLockGuard aCLGuard( getModel() ); bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp; m_bWaitingForMouseUp = false; bool bNotifySelectionChange = false; { ::vos::OGuard aGuard( Application::GetSolarMutex()); DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(!m_pChartWindow || !pDrawViewWrapper) return; Point aMPos = m_pChartWindow->PixelToLogic(rMEvt.GetPosPixel()); if(pDrawViewWrapper->IsTextEdit()) { if( pDrawViewWrapper->MouseButtonUp(rMEvt,m_pChartWindow) ) return; } // #i12587# support for shapes in chart if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() ) { pDrawViewWrapper->EndCreateObj( SDRCREATE_FORCEEND ); { HiddenUndoContext aUndoContext( m_xUndoManager ); // don't want the positioning Undo action to appear in the UI impl_switchDiagramPositioningToExcludingPositioning(); } if ( pDrawViewWrapper->AreObjectsMarked() ) { if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT ) { executeDispatch_EditText(); } else { SdrObject* pObj = pDrawViewWrapper->getSelectedObject(); if ( pObj ) { uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY ); if ( xShape.is() ) { m_aSelection.setSelection( xShape ); m_aSelection.applySelection( pDrawViewWrapper ); } } } } else { m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick ); m_aSelection.applySelection( pDrawViewWrapper ); setDrawMode( CHARTDRAW_SELECT ); } } else if ( pDrawViewWrapper->IsDragObj() ) { bool bDraggingDone = false; SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod(); bool bIsMoveOnly = pDragMethod ? pDragMethod->getMoveOnly() : false; DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod); if( pChartDragMethod ) { UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(), m_xUndoManager ); if( pDrawViewWrapper->EndDragObj(false) ) { bDraggingDone = true; aUndoGuard.commit(); } } if( !bDraggingDone && pDrawViewWrapper->EndDragObj(false) ) { try { //end move or size SdrObject* pObj = pDrawViewWrapper->getSelectedObject(); if( pObj ) { Rectangle aObjectRect = pObj->GetSnapRect(); awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height ); const E3dObject* pE3dObject = dynamic_cast< const E3dObject*>( pObj ); if( pE3dObject ) aObjectRect = pE3dObject->GetScene()->GetSnapRect(); ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::MOVE); if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() ) eActionType = ActionDescriptionProvider::RESIZE; ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ); UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType)), m_xUndoManager ); bool bChanged = false; if ( eObjectType == OBJECTTYPE_LEGEND ) bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( getModel(), false , true ); bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID() , getModel() , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight()) , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) ); if( bMoved || bChanged ) { bDraggingDone = true; aUndoGuard.commit(); } } } catch( uno::Exception & ex ) { ASSERT_EXCEPTION( ex ); } //all wanted model changes will take effect //and all unwanted view modifications are cleaned } if( !bDraggingDone ) //mouse wasn't moved while dragging { bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper ); bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getModel() ); //toggel between move and rotate if( bIsRotateable && bClickedTwiceOnDragableObject && SDRDRAG_MOVE==m_eDragMode ) m_eDragMode=SDRDRAG_ROTATE; else m_eDragMode=SDRDRAG_MOVE; pDrawViewWrapper->SetDragMode(m_eDragMode); if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() ) { this->impl_selectObjectAndNotiy(); } } else m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured(); } else if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ ) { Point aMousePixel = rMEvt.GetPosPixel(); execute_DoubleClick( &aMousePixel ); } //@todo ForcePointer(&rMEvt); m_pChartWindow->ReleaseMouse(); if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() ) bNotifySelectionChange = true; } impl_SetMousePointer( rMEvt ); if(bNotifySelectionChange) impl_notifySelectionChangeListeners(); } void ChartController::execute_DoubleClick( const Point* pMousePixel ) { bool bEditText = false; if ( m_aSelection.hasSelection() ) { ::rtl::OUString aCID( m_aSelection.getSelectedCID() ); if ( !aCID.isEmpty() ) { ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID ); if ( OBJECTTYPE_TITLE == eObjectType ) { bEditText = true; } } else { // #i12587# support for shapes in chart SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() ); if ( pObj && pObj->ISA( SdrTextObj ) ) { bEditText = true; } } } if ( bEditText ) { executeDispatch_EditText( pMousePixel ); } else { executeDispatch_ObjectProperties(); } } void ChartController::execute_Resize() { ::vos::OGuard aGuard( Application::GetSolarMutex() ); if(m_pChartWindow) m_pChartWindow->Invalidate(); } void ChartController::execute_Activate() { ///// pDrawViewWrapper->SetEditMode(sal_True); } void ChartController::execute_Deactivate() { /* pDrawViewWrapper->SetEditMode(sal_False); this->ReleaseMouse(); */ } void ChartController::execute_GetFocus() { } void ChartController::execute_LoseFocus() { //this->ReleaseMouse(); } void ChartController::execute_Command( const CommandEvent& rCEvt ) { bool bIsAction = false; { ::vos::OGuard aGuard( Application::GetSolarMutex()); DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(!m_pChartWindow || !pDrawViewWrapper) return; bIsAction = m_pDrawViewWrapper->IsAction(); } // pop-up menu if(rCEvt.GetCommand() == COMMAND_CONTEXTMENU && !bIsAction) { { ::vos::OGuard aGuard( Application::GetSolarMutex() ); if(m_pChartWindow) m_pChartWindow->ReleaseMouse(); } if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() ) impl_notifySelectionChangeListeners(); if ( isShapeContext() ) { // #i12587# support for shapes in chart PopupMenu aContextMenu( SchResId( m_pDrawViewWrapper->IsTextEdit() ? RID_CONTEXTMENU_SHAPEEDIT : RID_CONTEXTMENU_SHAPE ) ); ::svt::ContextMenuHelper aContextMenuHelper( m_xFrame ); Point aPos( rCEvt.GetMousePosPixel() ); if( !rCEvt.IsMouseEvent() ) { ::vos::OGuard aGuard( Application::GetSolarMutex() ); if(m_pChartWindow) aPos = m_pChartWindow->GetPointerState().maPos; } aContextMenuHelper.completeAndExecute( aPos, aContextMenu ); } else { // todo: the context menu should be specified by an xml file in uiconfig uno::Reference< awt::XPopupMenu > xPopupMenu( m_xCC->getServiceManager()->createInstanceWithContext( C2U("com.sun.star.awt.PopupMenu"), m_xCC ), uno::UNO_QUERY ); if( xPopupMenu.is()) { sal_Int16 nUniqueId = 1; ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ); Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( getModel() ); OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, aFormatCommand ); //some commands for dataseries and points: //----- if( OBJECTTYPE_DATA_SERIES == eObjectType || OBJECTTYPE_DATA_POINT == eObjectType ) { bool bIsPoint = ( OBJECTTYPE_DATA_POINT == eObjectType ); uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); uno::Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); Reference< chart2::XRegressionCurve > xTrendline( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ) ); bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline ); Reference< chart2::XRegressionCurve > xMeanValue( RegressionCurveHelper::getMeanValueLine( xCurveCnt ) ); bool bHasYErrorBars = StatisticsHelper::hasErrorBars( xSeries, true ); bool bHasDataLabelsAtSeries = DataSeriesHelper::hasDataLabelsAtSeries( xSeries ); bool bHasDataLabelsAtPoints = DataSeriesHelper::hasDataLabelsAtPoints( xSeries ); bool bHasDataLabelAtPoint = false; sal_Int32 nPointIndex = -1; if( bIsPoint ) { nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() ); bHasDataLabelAtPoint = DataSeriesHelper::hasDataLabelAtPoint( xSeries, nPointIndex ); } bool bSelectedPointIsFormatted = false; bool bHasFormattedDataPointsOtherThanSelected = false; Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); if( xSeriesProperties.is() ) { uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) { if( aAttributedDataPointIndexList.hasElements() ) { if( bIsPoint ) { ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) ); ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex ); if( aIt != aIndices.end()) bSelectedPointIsFormatted = true; else bHasFormattedDataPointsOtherThanSelected = true; } else bHasFormattedDataPointsOtherThanSelected = true; } } } //const sal_Int32 nIdBeforeFormat = nUniqueId; if( bIsPoint ) { if( bHasDataLabelAtPoint ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatDataLabel") ); if( !bHasDataLabelAtPoint ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertDataLabel") ); else lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteDataLabel") ); if( bSelectedPointIsFormatted ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:ResetDataPoint")); xPopupMenu->insertSeparator( -1 ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatDataSeries") ); } Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); if( xChartType->getChartType().equals(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) { try { Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY ); if( xChartTypeProp.is() ) { bool bJapaneseStyle = false; xChartTypeProp->getPropertyValue( C2U( "Japanese" ) ) >>= bJapaneseStyle; if( bJapaneseStyle ) { lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatStockLoss") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatStockGain") ); } } } catch( const uno::Exception & ex ) { ASSERT_EXCEPTION( ex ); } } if( bHasDataLabelsAtSeries ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatDataLabels") ); if( xTrendline.is() ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatTrendline") ); if( bHasEquation ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatTrendlineEquation") ); if( xMeanValue.is() ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatMeanValue") ); if( bHasYErrorBars ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatYErrorBars") ); //if( nIdBeforeFormat != nUniqueId ) xPopupMenu->insertSeparator( -1 ); //const sal_Int32 nIdBeforeInsert = nUniqueId; if( !bHasDataLabelsAtSeries ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertDataLabels") ); if( !xTrendline.is() ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertTrendline") ); else if( !bHasEquation ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertTrendlineEquation") ); if( !xMeanValue.is() ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertMeanValue") ); if( !bHasYErrorBars ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertYErrorBars") ); //if( nIdBeforeInsert != nUniqueId ) // xPopupMenu->insertSeparator( -1 ); //const sal_Int32 nIdBeforeDelete = nUniqueId; if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteDataLabels") ); if( xTrendline.is() ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteTrendline") ); if( bHasEquation ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteTrendlineEquation") ); if( xMeanValue.is() ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteMeanValue") ); if( bHasYErrorBars ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteYErrorBars") ); if( bHasFormattedDataPointsOtherThanSelected ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:ResetAllDataPoints")); //if( nIdBeforeDelete != nUniqueId ) xPopupMenu->insertSeparator( -1 ); lcl_insertMenuCommand( xPopupMenu, nUniqueId, C2U(".uno:ArrangeRow")); uno::Reference< awt::XPopupMenu > xArrangePopupMenu( m_xCC->getServiceManager()->createInstanceWithContext( C2U("com.sun.star.awt.PopupMenu"), m_xCC ), uno::UNO_QUERY ); if( xArrangePopupMenu.is() ) { sal_Int16 nSubId = nUniqueId + 1; lcl_insertMenuCommand( xArrangePopupMenu, nSubId++, C2U(".uno:Forward") ); lcl_insertMenuCommand( xArrangePopupMenu, nSubId, C2U(".uno:Backward") ); xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu ); nUniqueId = nSubId; } ++nUniqueId; } else if( OBJECTTYPE_DATA_CURVE == eObjectType ) { lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatTrendlineEquation") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertTrendlineEquation") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertTrendlineEquationAndR2") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertR2Value") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteTrendlineEquation") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteR2Value") ); } else if( OBJECTTYPE_DATA_CURVE_EQUATION == eObjectType ) { lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertR2Value") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteR2Value") ); } //some commands for axes: and grids //----- else if( OBJECTTYPE_AXIS == eObjectType || OBJECTTYPE_GRID == eObjectType || OBJECTTYPE_SUBGRID == eObjectType ) { Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); if( xAxis.is() && xDiagram.is() ) { sal_Int32 nDimensionIndex = -1; sal_Int32 nCooSysIndex = -1; sal_Int32 nAxisIndex = -1; AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ); bool bIsSecondaryAxis = nAxisIndex!=0; bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis ); bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram ); bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram ); bool bHasTitle = false; uno::Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY ); if( xTitled.is()) bHasTitle = ( TitleHelper::getCompleteString( xTitled->getTitleObject() ).isEmpty() == false ); if( OBJECTTYPE_AXIS != eObjectType && bIsAxisVisible ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatAxis") ); if( OBJECTTYPE_GRID != eObjectType && bIsMajorGridVisible && !bIsSecondaryAxis ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatMajorGrid") ); if( OBJECTTYPE_SUBGRID != eObjectType && bIsMinorGridVisible && !bIsSecondaryAxis ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatMinorGrid") ); xPopupMenu->insertSeparator( -1 ); if( OBJECTTYPE_AXIS != eObjectType && !bIsAxisVisible ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertAxis") ); if( OBJECTTYPE_GRID != eObjectType && !bIsMajorGridVisible && !bIsSecondaryAxis ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertMajorGrid") ); if( OBJECTTYPE_SUBGRID != eObjectType && !bIsMinorGridVisible && !bIsSecondaryAxis ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertMinorGrid") ); if( !bHasTitle ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertAxisTitle") ); if( bIsAxisVisible ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteAxis") ); if( bIsMajorGridVisible && !bIsSecondaryAxis ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteMajorGrid") ); if( bIsMinorGridVisible && !bIsSecondaryAxis ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteMinorGrid") ); } } if( OBJECTTYPE_DATA_STOCK_LOSS == eObjectType ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatStockGain") ); else if( OBJECTTYPE_DATA_STOCK_GAIN == eObjectType ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:FormatStockLoss") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:TransformDialog")); if( OBJECTTYPE_PAGE == eObjectType || OBJECTTYPE_DIAGRAM == eObjectType || OBJECTTYPE_DIAGRAM_WALL == eObjectType || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType || OBJECTTYPE_UNKNOWN == eObjectType ) { if( OBJECTTYPE_UNKNOWN != eObjectType ) xPopupMenu->insertSeparator( -1 ); bool bHasLegend = LegendHelper::hasLegend( xDiagram ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertTitles") ); if( !bHasLegend ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertLegend") ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:InsertRemoveAxes") ); if( bHasLegend ) lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DeleteLegend") ); } //----- xPopupMenu->insertSeparator( -1 ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DiagramType")); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DataRanges")); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:DiagramData")); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:View3D")); xPopupMenu->insertSeparator( -1 ); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:Cut")); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:Copy")); lcl_insertMenuCommand( xPopupMenu, nUniqueId++, C2U(".uno:Paste")); ::svt::ContextMenuHelper aContextMenuHelper( m_xFrame ); Point aPos( rCEvt.GetMousePosPixel() ); if( !rCEvt.IsMouseEvent() ) { ::vos::OGuard aGuard( Application::GetSolarMutex() ); if(m_pChartWindow) aPos = m_pChartWindow->GetPointerState().maPos; } aContextMenuHelper.completeAndExecute( aPos, xPopupMenu ); } } } else if( ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT ) || ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT ) || ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT ) || ( rCEvt.GetCommand() == COMMAND_INPUTCONTEXTCHANGE ) ) { //#i84417# enable editing with IME ::vos::OGuard aGuard( Application::GetSolarMutex() ); if( m_pDrawViewWrapper ) m_pDrawViewWrapper->Command( rCEvt, m_pChartWindow ); } } bool ChartController::execute_KeyInput( const KeyEvent& rKEvt ) { bool bReturn=false; DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if(!m_pChartWindow || !pDrawViewWrapper) return bReturn; // handle accelerators if( ! m_apAccelExecute.get() && m_xFrame.is() && m_xCC.is() && m_xCC->getServiceManager().is() ) { m_apAccelExecute.reset( ::svt::AcceleratorExecute::createAcceleratorHelper()); OSL_ASSERT( m_apAccelExecute.get()); if( m_apAccelExecute.get() ) m_apAccelExecute->init( uno::Reference< lang::XMultiServiceFactory >( m_xCC->getServiceManager(), uno::UNO_QUERY ), m_xFrame ); } KeyCode aKeyCode( rKEvt.GetKeyCode()); sal_uInt16 nCode = aKeyCode.GetCode(); // bool bShift = aKeyCode.IsShift(); bool bAlternate = aKeyCode.IsMod2(); if( m_apAccelExecute.get() ) bReturn = m_apAccelExecute->execute( aKeyCode ); if( bReturn ) return bReturn; { ::vos::OGuard aGuard( Application::GetSolarMutex() ); if( pDrawViewWrapper->IsTextEdit() ) { if( pDrawViewWrapper->KeyInput(rKEvt,m_pChartWindow) ) { bReturn = true; if( nCode == KEY_ESCAPE ) { this->EndTextEdit(); } } } } //if( m_pDrawViewWrapper->IsAction() ); // keyboard accessibility ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ); if( ! bReturn ) { // Natvigation (Tab/F3/Home/End) uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, ExplicitValueProvider::getExplicitValueProvider( m_xChartView )); awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode )); bReturn = aObjNav.handleKeyEvent( aKeyEvent ); if( bReturn ) { ObjectIdentifier aNewOID = aObjNav.getCurrentSelection(); uno::Any aNewSelection; if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) ) { aNewSelection = aNewOID.getAny(); } if ( m_eDragMode == SDRDRAG_ROTATE && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getModel() ) ) { m_eDragMode = SDRDRAG_MOVE; } bReturn = select( aNewSelection ); } } // Position and Size (+/-/arrow-keys) or pie segment dragging if( ! bReturn ) { // pie segment dragging // note: could also be done for data series if( eObjectType == OBJECTTYPE_DATA_POINT && ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ).equals( ObjectIdentifier::getPieSegmentDragMethodServiceName())) { bool bDrag = false; bool bDragInside = false; if( nCode == KEY_ADD || nCode == KEY_SUBTRACT ) { bDrag = true; bDragInside = ( nCode == KEY_SUBTRACT ); } else if( nCode == KEY_LEFT || nCode == KEY_RIGHT || nCode == KEY_UP || nCode == KEY_DOWN ) { bDrag = true; rtl::OUString aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() )); sal_Int32 nOffsetPercentDummy( 0 ); awt::Point aMinimumPosition( 0, 0 ); awt::Point aMaximumPosition( 0, 0 ); ObjectIdentifier::parsePieSegmentDragParameterString( aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition ); aMaximumPosition.Y -= aMinimumPosition.Y; aMaximumPosition.X -= aMinimumPosition.X; bDragInside = (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) || (nCode == KEY_LEFT && (aMaximumPosition.X > 0)) || (nCode == KEY_DOWN && (aMaximumPosition.Y < 0)) || (nCode == KEY_UP && (aMaximumPosition.Y > 0)); } if( bDrag ) { double fAmount = bAlternate ? 0.01 : 0.05; if( bDragInside ) fAmount *= -1.0; bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount ); } } else { // size if( nCode == KEY_ADD || nCode == KEY_SUBTRACT ) { if( eObjectType == OBJECTTYPE_DIAGRAM ) { // default 1 mm in each direction double fGrowAmountX = 200.0; double fGrowAmountY = 200.0; if( bAlternate && m_pChartWindow ) { // together with Alt-key: 1 px in each direction ::vos::OGuard aGuard( Application::GetSolarMutex() ); if( m_pChartWindow ) { Size aPixelSize = m_pChartWindow->PixelToLogic( Size( 2, 2 )); fGrowAmountX = static_cast< double >( aPixelSize.Width()); fGrowAmountY = static_cast< double >( aPixelSize.Height()); } } if( nCode == KEY_SUBTRACT ) { fGrowAmountX = -fGrowAmountX; fGrowAmountY = -fGrowAmountY; } bReturn = impl_moveOrResizeObject( m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY ); } } // position else if( nCode == KEY_LEFT || nCode == KEY_RIGHT || nCode == KEY_UP || nCode == KEY_DOWN ) { if( m_aSelection.isDragableObjectSelected() ) { // default 1 mm double fShiftAmountX = 100.0; double fShiftAmountY = 100.0; if( bAlternate && m_pChartWindow ) { // together with Alt-key: 1 px ::vos::OGuard aGuard( Application::GetSolarMutex() ); if(m_pChartWindow) { Size aPixelSize = m_pChartWindow->PixelToLogic( Size( 1, 1 )); fShiftAmountX = static_cast< double >( aPixelSize.Width()); fShiftAmountY = static_cast< double >( aPixelSize.Height()); } } switch( nCode ) { case KEY_LEFT: fShiftAmountX = -fShiftAmountX; fShiftAmountY = 0.0; break; case KEY_RIGHT: fShiftAmountY = 0.0; break; case KEY_UP: fShiftAmountX = 0.0; fShiftAmountY = -fShiftAmountY; break; case KEY_DOWN: fShiftAmountX = 0.0; break; } if( !m_aSelection.getSelectedCID().isEmpty() ) { //move chart objects bReturn = impl_moveOrResizeObject( m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY ); } else { //move additional shapes uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() ); if( xShape.is() ) { awt::Point aPos( xShape->getPosition() ); awt::Size aSize( xShape->getSize() ); awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); aPos.X = static_cast< long >( static_cast< double >( aPos.X ) + fShiftAmountX ); aPos.Y = static_cast< long >( static_cast< double >( aPos.Y ) + fShiftAmountY ); if( aPos.X + aSize.Width > aPageSize.Width ) aPos.X = aPageSize.Width - aSize.Width; if( aPos.X < 0 ) aPos.X = 0; if( aPos.Y + aSize.Height > aPageSize.Height ) aPos.Y = aPageSize.Height - aSize.Height; if( aPos.Y < 0 ) aPos.Y = 0; xShape->setPosition( aPos ); } } } } } } // text edit if( ! bReturn && nCode == KEY_F2 ) { if( OBJECTTYPE_TITLE == eObjectType ) { executeDispatch_EditText(); bReturn = true; } } // deactivate inplace mode (this code should be unnecessary, but // unfortunately is not) if( ! bReturn && nCode == KEY_ESCAPE ) { uno::Reference< frame::XDispatchHelper > xDispatchHelper( m_xCC->getServiceManager()->createInstanceWithContext( C2U("com.sun.star.frame.DispatchHelper"), m_xCC ), uno::UNO_QUERY ); if( xDispatchHelper.is()) { uno::Sequence< beans::PropertyValue > aArgs; xDispatchHelper->executeDispatch( uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ), C2U(".uno:TerminateInplaceActivation"), C2U("_parent"), frame::FrameSearchFlag::PARENT, aArgs ); bReturn = true; } } if( ! bReturn && (nCode == KEY_DELETE || nCode == KEY_BACKSPACE )) { bReturn = executeDispatch_Delete(); if( ! bReturn ) { ::vos::OGuard aGuard( Application::GetSolarMutex() ); InfoBox( m_pChartWindow, String(SchResId( STR_ACTION_NOTPOSSIBLE ))).Execute(); } } /* old chart: // Ctrl-Shift-R: Repaint if (!bReturn && GetWindow()) { KeyCode aKeyCode = rKEvt.GetKeyCode(); if (aKeyCode.IsMod1() && aKeyCode.IsShift() && aKeyCode.GetCode() == KEY_R) { // 3D-Kontext wieder zerstoeren GetWindow()->Invalidate(); bReturn = sal_True; } } */ return bReturn; } bool ChartController::requestQuickHelp( ::Point aAtLogicPosition, bool bIsBalloonHelp, ::rtl::OUString & rOutQuickHelpText, awt::Rectangle & rOutEqualRect ) { uno::Reference< frame::XModel > xChartModel; if( m_aModel.is()) xChartModel.set( getModel() ); if( !xChartModel.is()) return false; // help text ::rtl::OUString aCID; if( m_pDrawViewWrapper ) { aCID = SelectionHelper::getHitObjectCID( aAtLogicPosition, *m_pDrawViewWrapper ); } bool bResult( !aCID.isEmpty() ); if( bResult ) { // get help text rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ ); // set rectangle ExplicitValueProvider * pValueProvider( ExplicitValueProvider::getExplicitValueProvider( m_xChartView )); if( pValueProvider ) rOutEqualRect = pValueProvider->getRectangleOfObject( aCID, true ); } return bResult; } //----------------------------------------------------------------- // XSelectionSupplier (optional interface) //----------------------------------------------------------------- sal_Bool SAL_CALL ChartController ::select( const uno::Any& rSelection ) throw( lang::IllegalArgumentException ) { bool bSuccess = false; if ( rSelection.hasValue() ) { const uno::Type& rType = rSelection.getValueType(); if ( rType == ::getCppuType( static_cast< const ::rtl::OUString* >( 0 ) ) ) { ::rtl::OUString aNewCID; if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) ) { bSuccess = true; } } else if ( rType == ::getCppuType( static_cast< const uno::Reference< drawing::XShape >* >( 0 ) ) ) { uno::Reference< drawing::XShape > xShape; if ( ( rSelection >>= xShape ) && m_aSelection.setSelection( xShape ) ) { bSuccess = true; } } } else { if ( m_aSelection.hasSelection() ) { m_aSelection.clearSelection(); bSuccess = true; } } if ( bSuccess ) { ::vos::OGuard aGuard( Application::GetSolarMutex() ); if ( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() ) { this->EndTextEdit(); } this->impl_selectObjectAndNotiy(); if ( m_pChartWindow ) { m_pChartWindow->Invalidate(); } return sal_True; } return sal_False; } uno::Any SAL_CALL ChartController ::getSelection() throw(uno::RuntimeException) { uno::Any aReturn; if ( m_aSelection.hasSelection() ) { ::rtl::OUString aCID( m_aSelection.getSelectedCID() ); if ( !aCID.isEmpty() ) { aReturn = uno::makeAny( aCID ); } else { // #i12587# support for shapes in chart aReturn = uno::makeAny( m_aSelection.getSelectedAdditionalShape() ); } } return aReturn; } void SAL_CALL ChartController ::addSelectionChangeListener( const uno::Reference< view::XSelectionChangeListener > & xListener ) throw(uno::RuntimeException) { ::vos::OGuard aGuard( Application::GetSolarMutex()); if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode? return; //behave passive if already disposed or suspended //--add listener m_aLifeTimeManager.m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0), xListener ); } void SAL_CALL ChartController ::removeSelectionChangeListener( const uno::Reference< view::XSelectionChangeListener > & xListener ) throw(uno::RuntimeException) { ::vos::OGuard aGuard( Application::GetSolarMutex()); if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode? return; //behave passive if already disposed or suspended //--remove listener m_aLifeTimeManager.m_aListenerContainer.removeInterface( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0), xListener ); } void ChartController ::impl_notifySelectionChangeListeners() { ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer .getContainer( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0) ); if( pIC ) { uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this); lang::EventObject aEvent( xSelectionSupplier ); ::cppu::OInterfaceIteratorHelper aIt( *pIC ); while( aIt.hasMoreElements() ) { uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); if( xListener.is() ) xListener->selectionChanged( aEvent ); } } } void ChartController::impl_selectObjectAndNotiy() { { ::vos::OGuard aGuard( Application::GetSolarMutex() ); DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; if( pDrawViewWrapper ) { pDrawViewWrapper->SetDragMode( m_eDragMode ); m_aSelection.applySelection( m_pDrawViewWrapper ); } } impl_notifySelectionChangeListeners(); } bool ChartController::impl_moveOrResizeObject( const ::rtl::OUString & rCID, eMoveOrResizeType eType, double fAmountLogicX, double fAmountLogicY ) { bool bResult = false; bool bNeedShift = true; bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT ); uno::Reference< frame::XModel > xChartModel( getModel() ); uno::Reference< beans::XPropertySet > xObjProp( ObjectIdentifier::getObjectPropertySet( rCID, xChartModel )); if( xObjProp.is()) { awt::Size aRefSize = ChartModelHelper::getPageSize( xChartModel ); chart2::RelativePosition aRelPos; chart2::RelativeSize aRelSize; bool bDeterminePos = !(xObjProp->getPropertyValue( C2U("RelativePosition")) >>= aRelPos); bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( C2U("RelativeSize")) >>= aRelSize); if( ( bDeterminePos || bDetermineSize ) && ( aRefSize.Width > 0 && aRefSize.Height > 0 ) ) { ExplicitValueProvider * pValueProvider( ExplicitValueProvider::getExplicitValueProvider( m_xChartView )); if( pValueProvider ) { awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID )); double fWidth = static_cast< double >( aRefSize.Width ); double fHeight = static_cast< double >( aRefSize.Height ); if( bDetermineSize ) { aRelSize.Primary = static_cast< double >( aRect.Width ) / fWidth; aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight; } if( bDeterminePos ) { if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 ) { aRelPos.Primary = (static_cast< double >( aRect.X ) / fWidth) + (aRelSize.Primary / 2.0); aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) + (aRelSize.Secondary / 2.0); aRelPos.Anchor = drawing::Alignment_CENTER; } else { aRelPos.Primary = static_cast< double >( aRect.X ) / fWidth; aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight; aRelPos.Anchor = drawing::Alignment_TOP_LEFT; } } } } if( eType == CENTERED_RESIZE_OBJECT ) bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY ); else if( eType == MOVE_OBJECT ) bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY ); if( bResult ) { ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::MOVE); if( bNeedResize ) eActionType = ActionDescriptionProvider::RESIZE; ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID ); UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager ); { ControllerLockGuard aCLGuard( xChartModel ); if( bNeedShift ) xObjProp->setPropertyValue( C2U("RelativePosition"), uno::makeAny( aRelPos )); if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicat size at the diagram when an explicit position is set xObjProp->setPropertyValue( C2U("RelativeSize"), uno::makeAny( aRelSize )); } aUndoGuard.commit(); } } return bResult; } bool ChartController::impl_DragDataPoint( const ::rtl::OUString & rCID, double fAdditionalOffset ) { bool bResult = false; if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 ) return bResult; sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID ); uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rCID, getModel() )); if( xSeries.is()) { try { uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex )); double fOffset = 0.0; if( xPointProp.is() && (xPointProp->getPropertyValue( C2U("Offset" )) >>= fOffset ) && (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) ) { fOffset += fAdditionalOffset; if( fOffset > 1.0 ) fOffset = 1.0; else if( fOffset < 0.0 ) fOffset = 0.0; xPointProp->setPropertyValue( C2U("Offset"), uno::makeAny( fOffset )); bResult = true; } } catch( const uno::Exception & ex ) { ASSERT_EXCEPTION( ex ); } } return bResult; } void ChartController::impl_SetMousePointer( const MouseEvent & rEvent ) { ::vos::OGuard aGuard( Application::GetSolarMutex()); if( m_pDrawViewWrapper && m_pChartWindow ) { Point aMousePos( m_pChartWindow->PixelToLogic( rEvent.GetPosPixel())); sal_uInt16 nModifier = rEvent.GetModifier(); sal_Bool bLeftDown = rEvent.IsLeft(); if ( m_pDrawViewWrapper->IsTextEdit() ) { if( m_pDrawViewWrapper->IsTextEditHit( aMousePos, HITPIX) ) { m_pChartWindow->SetPointer( m_pDrawViewWrapper->GetPreferedPointer( aMousePos, m_pChartWindow, nModifier, bLeftDown ) ); return; } } else if( m_pDrawViewWrapper->IsAction() ) { return;//don't change pointer during running action } SdrHdl* pHitSelectionHdl = 0; if( m_aSelection.isResizeableObjectSelected() ) pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos ); if( pHitSelectionHdl ) { Pointer aPointer = m_pDrawViewWrapper->GetPreferedPointer( aMousePos, m_pChartWindow, nModifier, bLeftDown ); bool bForceArrowPointer = false; ObjectIdentifier aOID( m_aSelection.getSelectedOID() ); switch( aPointer.GetStyle()) { case POINTER_NSIZE: case POINTER_SSIZE: case POINTER_WSIZE: case POINTER_ESIZE: case POINTER_NWSIZE: case POINTER_NESIZE: case POINTER_SWSIZE: case POINTER_SESIZE: if( ! m_aSelection.isResizeableObjectSelected() ) bForceArrowPointer = true; break; case POINTER_MOVE: if ( !aOID.isDragableObject() ) bForceArrowPointer = true; break; case POINTER_MOVEPOINT: case POINTER_MOVEBEZIERWEIGHT: // there is no point-editing in a chart // the POINTER_MOVEBEZIERWEIGHT appears in 3d data points bForceArrowPointer = true; break; default: break; } if( bForceArrowPointer ) m_pChartWindow->SetPointer( Pointer( POINTER_ARROW )); else m_pChartWindow->SetPointer( aPointer ); } else { // #i12587# support for shapes in chart if ( m_eDrawMode == CHARTDRAW_INSERT && ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) ) { PointerStyle ePointerStyle = POINTER_DRAW_RECT; SdrObjKind eKind = static_cast< SdrObjKind >( m_pDrawViewWrapper->GetCurrentObjIdentifier() ); switch ( eKind ) { case OBJ_LINE: { ePointerStyle = POINTER_DRAW_LINE; } break; case OBJ_RECT: case OBJ_CUSTOMSHAPE: { ePointerStyle = POINTER_DRAW_RECT; } break; case OBJ_CIRC: { ePointerStyle = POINTER_DRAW_ELLIPSE; } break; case OBJ_FREELINE: { ePointerStyle = POINTER_DRAW_POLYGON; } break; case OBJ_TEXT: { ePointerStyle = POINTER_DRAW_TEXT; } break; case OBJ_CAPTION: { ePointerStyle = POINTER_DRAW_CAPTION; } break; default: { ePointerStyle = POINTER_DRAW_RECT; } break; } m_pChartWindow->SetPointer( Pointer( ePointerStyle ) ); return; } ::rtl::OUString aHitObjectCID( SelectionHelper::getHitObjectCID( aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ )); if( m_pDrawViewWrapper->IsTextEdit() ) { if( aHitObjectCID.equals(m_aSelection.getSelectedCID()) ) { m_pChartWindow->SetPointer( Pointer( POINTER_ARROW )); return; } } if( aHitObjectCID.isEmpty() ) { //additional shape was hit m_pChartWindow->SetPointer( POINTER_MOVE ); } else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) ) { if( (m_eDragMode == SDRDRAG_ROTATE) && SelectionHelper::isRotateableObject( aHitObjectCID , getModel() ) ) m_pChartWindow->SetPointer( Pointer( POINTER_ROTATE ) ); else { ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID ); if( eHitObjectType == OBJECTTYPE_DATA_POINT ) { if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID()) && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) ) { m_pChartWindow->SetPointer( Pointer( POINTER_ARROW )); return; } } m_pChartWindow->SetPointer( POINTER_MOVE ); } } else m_pChartWindow->SetPointer( Pointer( POINTER_ARROW )); } } } //............................................................................. } //namespace chart //.............................................................................