1cde9e8dcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3cde9e8dcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4cde9e8dcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5cde9e8dcSAndrew Rist  * distributed with this work for additional information
6cde9e8dcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7cde9e8dcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8cde9e8dcSAndrew Rist  * "License"); you may not use this file except in compliance
9cde9e8dcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cde9e8dcSAndrew Rist  *
11cde9e8dcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cde9e8dcSAndrew Rist  *
13cde9e8dcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14cde9e8dcSAndrew Rist  * software distributed under the License is distributed on an
15cde9e8dcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16cde9e8dcSAndrew Rist  * KIND, either express or implied.  See the License for the
17cde9e8dcSAndrew Rist  * specific language governing permissions and limitations
18cde9e8dcSAndrew Rist  * under the License.
19cde9e8dcSAndrew Rist  *
20cde9e8dcSAndrew Rist  *************************************************************/
21cde9e8dcSAndrew Rist 
22cde9e8dcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_chart2.hxx"
26cdf0e10cSrcweir #include "SelectionHelper.hxx"
27cdf0e10cSrcweir #include "ObjectIdentifier.hxx"
28cdf0e10cSrcweir //for C2U
29cdf0e10cSrcweir #include "macros.hxx"
30cdf0e10cSrcweir #include "DiagramHelper.hxx"
31cdf0e10cSrcweir #include "ChartModelHelper.hxx"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir // header for class SdrObjList
34cdf0e10cSrcweir #include <svx/svdpage.hxx>
35cdf0e10cSrcweir #include <svx/svditer.hxx>
36cdf0e10cSrcweir #include "svx/obj3d.hxx"
37cdf0e10cSrcweir // header for class SdrPathObj
38cdf0e10cSrcweir #include <svx/svdopath.hxx>
39cdf0e10cSrcweir #include <vcl/svapp.hxx>
40cdf0e10cSrcweir #include <vos/mutex.hxx>
41cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
42cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
43cdf0e10cSrcweir 
44cdf0e10cSrcweir //.............................................................................
45cdf0e10cSrcweir namespace chart
46cdf0e10cSrcweir {
47cdf0e10cSrcweir //.............................................................................
48cdf0e10cSrcweir using namespace ::com::sun::star;
49cdf0e10cSrcweir //using namespace ::com::sun::star::chart2;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir namespace
52cdf0e10cSrcweir {
53cdf0e10cSrcweir 
lcl_getObjectName(SdrObject * pObj)54cdf0e10cSrcweir rtl::OUString lcl_getObjectName( SdrObject* pObj )
55cdf0e10cSrcweir {
56cdf0e10cSrcweir     if(pObj)
57cdf0e10cSrcweir        return pObj->GetName();
58cdf0e10cSrcweir     return rtl::OUString();
59cdf0e10cSrcweir }
60cdf0e10cSrcweir 
impl_selectObject(SdrObject * pObjectToSelect,DrawViewWrapper & rDrawViewWrapper)61cdf0e10cSrcweir void impl_selectObject( SdrObject* pObjectToSelect, DrawViewWrapper& rDrawViewWrapper )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
64cdf0e10cSrcweir 
65cdf0e10cSrcweir     if(pObjectToSelect)
66cdf0e10cSrcweir     {
67cdf0e10cSrcweir         SelectionHelper aSelectionHelper( pObjectToSelect );
68cdf0e10cSrcweir         SdrObject* pMarkObj = aSelectionHelper.getObjectToMark();
69cdf0e10cSrcweir         rDrawViewWrapper.setMarkHandleProvider(&aSelectionHelper);
70cdf0e10cSrcweir         rDrawViewWrapper.MarkObject(pMarkObj);
71cdf0e10cSrcweir         rDrawViewWrapper.setMarkHandleProvider(NULL);
72cdf0e10cSrcweir     }
73cdf0e10cSrcweir }
74cdf0e10cSrcweir 
75cdf0e10cSrcweir }//anonymous namespace
76cdf0e10cSrcweir 
hasSelection()77cdf0e10cSrcweir bool Selection::hasSelection()
78cdf0e10cSrcweir {
79cdf0e10cSrcweir     return m_aSelectedOID.isValid();
80cdf0e10cSrcweir }
81cdf0e10cSrcweir 
getSelectedCID()82cdf0e10cSrcweir rtl::OUString Selection::getSelectedCID()
83cdf0e10cSrcweir {
84cdf0e10cSrcweir     return m_aSelectedOID.getObjectCID();
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
getSelectedAdditionalShape()87cdf0e10cSrcweir uno::Reference< drawing::XShape > Selection::getSelectedAdditionalShape()
88cdf0e10cSrcweir {
89cdf0e10cSrcweir     return m_aSelectedOID.getAdditionalShape();
90cdf0e10cSrcweir }
91cdf0e10cSrcweir 
getSelectedOID() const92cdf0e10cSrcweir ObjectIdentifier Selection::getSelectedOID() const
93cdf0e10cSrcweir {
94cdf0e10cSrcweir     return m_aSelectedOID;
95cdf0e10cSrcweir }
96cdf0e10cSrcweir 
setSelection(const::rtl::OUString & rCID)97cdf0e10cSrcweir bool Selection::setSelection( const ::rtl::OUString& rCID )
98cdf0e10cSrcweir {
99cdf0e10cSrcweir     if ( !rCID.equals( m_aSelectedOID.getObjectCID() ) )
100cdf0e10cSrcweir     {
101cdf0e10cSrcweir         m_aSelectedOID = ObjectIdentifier( rCID );
102cdf0e10cSrcweir         return true;
103cdf0e10cSrcweir     }
104cdf0e10cSrcweir     return false;
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
setSelection(const uno::Reference<drawing::XShape> & xShape)107cdf0e10cSrcweir bool Selection::setSelection( const uno::Reference< drawing::XShape >& xShape )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir     if ( !( xShape == m_aSelectedOID.getAdditionalShape() ) )
110cdf0e10cSrcweir     {
111cdf0e10cSrcweir         clearSelection();
112cdf0e10cSrcweir         m_aSelectedOID = ObjectIdentifier( xShape );
113cdf0e10cSrcweir         return true;
114cdf0e10cSrcweir     }
115cdf0e10cSrcweir     return false;
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
clearSelection()118cdf0e10cSrcweir void Selection::clearSelection()
119cdf0e10cSrcweir {
120cdf0e10cSrcweir     m_aSelectedOID = ObjectIdentifier();
121cdf0e10cSrcweir     m_aSelectedOID_beforeMouseDown = ObjectIdentifier();
122cdf0e10cSrcweir     m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
123cdf0e10cSrcweir }
124cdf0e10cSrcweir 
maybeSwitchSelectionAfterSingleClickWasEnsured()125cdf0e10cSrcweir bool Selection::maybeSwitchSelectionAfterSingleClickWasEnsured()
126cdf0e10cSrcweir {
127cdf0e10cSrcweir     if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid()
128cdf0e10cSrcweir          && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing != m_aSelectedOID )
129cdf0e10cSrcweir     {
130cdf0e10cSrcweir         m_aSelectedOID = m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing;
131cdf0e10cSrcweir         m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
132cdf0e10cSrcweir         return true;
133cdf0e10cSrcweir     }
134cdf0e10cSrcweir     return false;
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
resetPossibleSelectionAfterSingleClickWasEnsured()137cdf0e10cSrcweir void Selection::resetPossibleSelectionAfterSingleClickWasEnsured()
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
140cdf0e10cSrcweir     {
141cdf0e10cSrcweir         m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
142cdf0e10cSrcweir     }
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
remindSelectionBeforeMouseDown()145cdf0e10cSrcweir void Selection::remindSelectionBeforeMouseDown()
146cdf0e10cSrcweir {
147cdf0e10cSrcweir     m_aSelectedOID_beforeMouseDown = m_aSelectedOID;
148cdf0e10cSrcweir }
149cdf0e10cSrcweir 
isSelectionDifferentFromBeforeMouseDown()150cdf0e10cSrcweir bool Selection::isSelectionDifferentFromBeforeMouseDown()
151cdf0e10cSrcweir {
152cdf0e10cSrcweir     return ( m_aSelectedOID != m_aSelectedOID_beforeMouseDown );
153cdf0e10cSrcweir }
154cdf0e10cSrcweir 
applySelection(DrawViewWrapper * pDrawViewWrapper)155cdf0e10cSrcweir void Selection::applySelection( DrawViewWrapper* pDrawViewWrapper )
156cdf0e10cSrcweir {
157cdf0e10cSrcweir     if( pDrawViewWrapper )
158cdf0e10cSrcweir     {
159cdf0e10cSrcweir         {
160cdf0e10cSrcweir             ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
161cdf0e10cSrcweir             pDrawViewWrapper->UnmarkAll();
162cdf0e10cSrcweir         }
163cdf0e10cSrcweir         SdrObject* pObjectToSelect = 0;
164cdf0e10cSrcweir         if ( m_aSelectedOID.isAutoGeneratedObject() )
165cdf0e10cSrcweir         {
166cdf0e10cSrcweir             pObjectToSelect = pDrawViewWrapper->getNamedSdrObject( m_aSelectedOID.getObjectCID() );
167cdf0e10cSrcweir         }
168cdf0e10cSrcweir         else if( m_aSelectedOID.isAdditionalShape() )
169cdf0e10cSrcweir         {
170cdf0e10cSrcweir             pObjectToSelect = DrawViewWrapper::getSdrObject( m_aSelectedOID.getAdditionalShape() );
171cdf0e10cSrcweir         }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir         impl_selectObject( pObjectToSelect, *pDrawViewWrapper );
174cdf0e10cSrcweir     }
175cdf0e10cSrcweir }
176cdf0e10cSrcweir 
adaptSelectionToNewPos(const Point & rMousePos,DrawViewWrapper * pDrawViewWrapper,bool bIsRightMouse,bool bWaitingForDoubleClick)177cdf0e10cSrcweir void Selection::adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper* pDrawViewWrapper
178cdf0e10cSrcweir                                        , bool bIsRightMouse, bool bWaitingForDoubleClick )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir     if( pDrawViewWrapper )
181cdf0e10cSrcweir     {
182cdf0e10cSrcweir         //do not toggel multiclick selection if right clicked on the selected object or waiting for double click
183cdf0e10cSrcweir         bool bAllowMultiClickSelectionChange = !bIsRightMouse && !bWaitingForDoubleClick;
184cdf0e10cSrcweir 
185cdf0e10cSrcweir         ObjectIdentifier aLastSelectedObject( m_aSelectedOID );
186cdf0e10cSrcweir 
187cdf0e10cSrcweir         ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
188cdf0e10cSrcweir 
189cdf0e10cSrcweir         //bAllowMultiClickSelectionChange==true -> a second click on the same object can lead to a changed selection (e.g. series -> single data point)
190cdf0e10cSrcweir 
191cdf0e10cSrcweir         //get object to select:
192cdf0e10cSrcweir         SdrObject* pNewObj = 0;
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
195cdf0e10cSrcweir 
196cdf0e10cSrcweir             //the search for the object to select starts with the hit object deepest in the grouping hierarchy (a leaf in the tree)
197cdf0e10cSrcweir             //further we travel along the grouping hierarchy from child to parent
198cdf0e10cSrcweir 	        pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
199cdf0e10cSrcweir             m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );//name of pNewObj
200cdf0e10cSrcweir 
201cdf0e10cSrcweir             //ignore handle only objects for hit test
202cdf0e10cSrcweir             while( pNewObj && m_aSelectedOID.getObjectCID().match( C2U( "HandlesOnly" ) ) )
203cdf0e10cSrcweir             {
204cdf0e10cSrcweir                 pNewObj->SetMarkProtect(true);
205cdf0e10cSrcweir                 pNewObj = pDrawViewWrapper->getHitObject(rMousePos);
206cdf0e10cSrcweir                 m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );
207cdf0e10cSrcweir             }
208cdf0e10cSrcweir 
209cdf0e10cSrcweir             //accept only named objects while searching for the object to select
210cdf0e10cSrcweir             //this call may change m_aSelectedOID
211cdf0e10cSrcweir             if ( SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, true ) )
212cdf0e10cSrcweir             {
213cdf0e10cSrcweir                 //if the so far found object is a multi click object further steps are necessary
214cdf0e10cSrcweir                 while( ObjectIdentifier::isMultiClickObject( m_aSelectedOID.getObjectCID() ) )
215cdf0e10cSrcweir                 {
216cdf0e10cSrcweir                     bool bSameObjectAsLastSelected = ( aLastSelectedObject == m_aSelectedOID );
217cdf0e10cSrcweir                     if( bSameObjectAsLastSelected )
218cdf0e10cSrcweir                     {
219cdf0e10cSrcweir                         //if the same child is clicked again don't go up further
220cdf0e10cSrcweir                         break;
221cdf0e10cSrcweir                     }
222cdf0e10cSrcweir                     if ( ObjectIdentifier::areSiblings( aLastSelectedObject.getObjectCID(), m_aSelectedOID.getObjectCID() ) )
223cdf0e10cSrcweir                     {
224cdf0e10cSrcweir                         //if a sibling of the last selected object is clicked don't go up further
225cdf0e10cSrcweir                         break;
226cdf0e10cSrcweir                     }
227cdf0e10cSrcweir                     SdrObject*    pLastChild     = pNewObj;
228cdf0e10cSrcweir                     ObjectIdentifier aLastChild = m_aSelectedOID;
229cdf0e10cSrcweir                     if ( !SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, false ) )
230cdf0e10cSrcweir                     {
231cdf0e10cSrcweir                         //take the one found so far
232cdf0e10cSrcweir                         break;
233cdf0e10cSrcweir                     }
234cdf0e10cSrcweir                     //if the last selected object is found don't go up further
235cdf0e10cSrcweir                     //but take the last child if selection change is allowed
236cdf0e10cSrcweir                     if ( aLastSelectedObject == m_aSelectedOID )
237cdf0e10cSrcweir                     {
238cdf0e10cSrcweir                         if( bAllowMultiClickSelectionChange )
239cdf0e10cSrcweir                         {
240cdf0e10cSrcweir                             pNewObj  = pLastChild;
241cdf0e10cSrcweir                             m_aSelectedOID = aLastChild;
242cdf0e10cSrcweir                         }
243cdf0e10cSrcweir                         else
244cdf0e10cSrcweir                             m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = aLastChild;
245cdf0e10cSrcweir 
246cdf0e10cSrcweir                         break;
247cdf0e10cSrcweir                     }
248cdf0e10cSrcweir                 }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir                 DBG_ASSERT( pNewObj && m_aSelectedOID.isValid(), "somehow lost selected object" );
251cdf0e10cSrcweir             }
252cdf0e10cSrcweir             else
253cdf0e10cSrcweir             {
254cdf0e10cSrcweir                 //maybe an additional shape was hit
255cdf0e10cSrcweir                 if ( pNewObj )
256cdf0e10cSrcweir                 {
257cdf0e10cSrcweir                     m_aSelectedOID = ObjectIdentifier( uno::Reference< drawing::XShape >( pNewObj->getUnoShape(), uno::UNO_QUERY ) );
258cdf0e10cSrcweir                 }
259cdf0e10cSrcweir                 else
260cdf0e10cSrcweir                 {
261cdf0e10cSrcweir                     m_aSelectedOID = ObjectIdentifier();
262cdf0e10cSrcweir                 }
263cdf0e10cSrcweir             }
264cdf0e10cSrcweir 
265cdf0e10cSrcweir             if ( !m_aSelectedOID.isAdditionalShape() )
266cdf0e10cSrcweir             {
267cdf0e10cSrcweir                 rtl::OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );//@todo read CID from model
268cdf0e10cSrcweir 
269cdf0e10cSrcweir                 if ( !m_aSelectedOID.isAutoGeneratedObject() )
270cdf0e10cSrcweir                 {
271cdf0e10cSrcweir                     m_aSelectedOID = ObjectIdentifier( aPageCID );
272cdf0e10cSrcweir                 }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir                 //check wether the diagram was hit but not selected (e.g. because it has no filling):
275cdf0e10cSrcweir                 rtl::OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) );
276cdf0e10cSrcweir                 rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
277cdf0e10cSrcweir                 bool bBackGroundHit = m_aSelectedOID.getObjectCID().equals( aPageCID ) || m_aSelectedOID.getObjectCID().equals( aWallCID ) || !m_aSelectedOID.isAutoGeneratedObject();
278cdf0e10cSrcweir                 if( bBackGroundHit )
279cdf0e10cSrcweir                 {
280cdf0e10cSrcweir                     //todo: if more than one diagram is available in future do chack the list of all diagrams here
281cdf0e10cSrcweir                     SdrObject* pDiagram = pDrawViewWrapper->getNamedSdrObject( aDiagramCID );
282cdf0e10cSrcweir                     if( pDiagram )
283cdf0e10cSrcweir                     {
284cdf0e10cSrcweir                         if( pDrawViewWrapper->IsObjectHit( pDiagram, rMousePos ) )
285cdf0e10cSrcweir                         {
286cdf0e10cSrcweir                             m_aSelectedOID = ObjectIdentifier( aDiagramCID );
287cdf0e10cSrcweir                             pNewObj = pDiagram;
288cdf0e10cSrcweir                         }
289cdf0e10cSrcweir                     }
290cdf0e10cSrcweir                 }
291cdf0e10cSrcweir                 //check wether the legend was hit but not selected (e.g. because it has no filling):
292cdf0e10cSrcweir                 if( bBackGroundHit || m_aSelectedOID.getObjectCID().equals( aDiagramCID ) )
293cdf0e10cSrcweir                 {
294cdf0e10cSrcweir                     rtl::OUString aLegendCID( ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::createParticleForLegend(0,0) ) );//@todo read CID from model
295cdf0e10cSrcweir                     SdrObject* pLegend = pDrawViewWrapper->getNamedSdrObject( aLegendCID );
296cdf0e10cSrcweir                     if( pLegend )
297cdf0e10cSrcweir                     {
298cdf0e10cSrcweir                         if( pDrawViewWrapper->IsObjectHit( pLegend, rMousePos ) )
299cdf0e10cSrcweir                         {
300cdf0e10cSrcweir                             m_aSelectedOID = ObjectIdentifier( aLegendCID );
301cdf0e10cSrcweir                             pNewObj = pLegend;
302cdf0e10cSrcweir                         }
303cdf0e10cSrcweir                     }
304cdf0e10cSrcweir                 }
305cdf0e10cSrcweir             }
306cdf0e10cSrcweir         }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir         if ( bIsRightMouse && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
309cdf0e10cSrcweir         {
310cdf0e10cSrcweir             m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
311cdf0e10cSrcweir         }
312cdf0e10cSrcweir     }
313cdf0e10cSrcweir }
314cdf0e10cSrcweir 
isResizeableObjectSelected()315cdf0e10cSrcweir bool Selection::isResizeableObjectSelected()
316cdf0e10cSrcweir {
317cdf0e10cSrcweir     ObjectType eObjectType = m_aSelectedOID.getObjectType();
318cdf0e10cSrcweir     switch( eObjectType )
319cdf0e10cSrcweir     {
320cdf0e10cSrcweir         case OBJECTTYPE_DIAGRAM:
321cdf0e10cSrcweir         case OBJECTTYPE_DIAGRAM_WALL:
322cdf0e10cSrcweir         case OBJECTTYPE_SHAPE:
323cdf0e10cSrcweir         case OBJECTTYPE_LEGEND:
324cdf0e10cSrcweir             return true;
325cdf0e10cSrcweir         default:
326cdf0e10cSrcweir             return false;
327cdf0e10cSrcweir     }
328cdf0e10cSrcweir     return false;
329cdf0e10cSrcweir }
330cdf0e10cSrcweir 
isRotateableObjectSelected(const uno::Reference<frame::XModel> & xChartModel)331cdf0e10cSrcweir bool Selection::isRotateableObjectSelected( const uno::Reference< frame::XModel >& xChartModel )
332cdf0e10cSrcweir {
333cdf0e10cSrcweir     return SelectionHelper::isRotateableObject( m_aSelectedOID.getObjectCID(), xChartModel );
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
isDragableObjectSelected()336cdf0e10cSrcweir bool Selection::isDragableObjectSelected()
337cdf0e10cSrcweir {
338cdf0e10cSrcweir     return m_aSelectedOID.isDragableObject();
339cdf0e10cSrcweir }
340cdf0e10cSrcweir 
isAdditionalShapeSelected() const341cdf0e10cSrcweir bool Selection::isAdditionalShapeSelected() const
342cdf0e10cSrcweir {
343cdf0e10cSrcweir     return m_aSelectedOID.isAdditionalShape();
344cdf0e10cSrcweir }
345cdf0e10cSrcweir 
346cdf0e10cSrcweir //-----------------------------------------------------------------------------
347cdf0e10cSrcweir //-----------------------------------------------------------------------------
348cdf0e10cSrcweir //-----------------------------------------------------------------------------
349cdf0e10cSrcweir 
findNamedParent(SdrObject * & pInOutObject,rtl::OUString & rOutName,bool bGivenObjectMayBeResult)350cdf0e10cSrcweir bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
351cdf0e10cSrcweir                                       , rtl::OUString& rOutName
352cdf0e10cSrcweir                                       , bool bGivenObjectMayBeResult )
353cdf0e10cSrcweir {
354cdf0e10cSrcweir     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
355cdf0e10cSrcweir     //find the deepest named group
356cdf0e10cSrcweir     SdrObject* pObj = pInOutObject;
357cdf0e10cSrcweir     rtl::OUString aName;
358cdf0e10cSrcweir     if( bGivenObjectMayBeResult )
359cdf0e10cSrcweir         aName = lcl_getObjectName( pObj );
360cdf0e10cSrcweir 
361cdf0e10cSrcweir     while( pObj && !ObjectIdentifier::isCID( aName  )  )
362cdf0e10cSrcweir     {
363cdf0e10cSrcweir         SdrObjList* pObjList = pObj->GetObjList();
364cdf0e10cSrcweir         if( !pObjList )
365cdf0e10cSrcweir             return false;;
366cdf0e10cSrcweir         SdrObject* pOwner = pObjList->GetOwnerObj();
367cdf0e10cSrcweir         if( !pOwner )
368cdf0e10cSrcweir             return false;
369cdf0e10cSrcweir         pObj = pOwner;
370cdf0e10cSrcweir         aName = lcl_getObjectName( pObj );
371cdf0e10cSrcweir     }
372cdf0e10cSrcweir 
373cdf0e10cSrcweir     if(!pObj)
374cdf0e10cSrcweir         return false;
375*9ec58d04SHerbert Dürr     if( aName.isEmpty() )
376cdf0e10cSrcweir         return false;
377cdf0e10cSrcweir 
378cdf0e10cSrcweir     pInOutObject = pObj;
379cdf0e10cSrcweir     rOutName = aName;
380cdf0e10cSrcweir     return true;
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
findNamedParent(SdrObject * & pInOutObject,ObjectIdentifier & rOutObject,bool bGivenObjectMayBeResult)383cdf0e10cSrcweir bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject
384cdf0e10cSrcweir                                       , ObjectIdentifier& rOutObject
385cdf0e10cSrcweir                                       , bool bGivenObjectMayBeResult )
386cdf0e10cSrcweir {
387cdf0e10cSrcweir     rtl::OUString aName;
388cdf0e10cSrcweir     if ( findNamedParent( pInOutObject, aName, bGivenObjectMayBeResult ) )
389cdf0e10cSrcweir     {
390cdf0e10cSrcweir         rOutObject = ObjectIdentifier( aName );
391cdf0e10cSrcweir         return true;
392cdf0e10cSrcweir     }
393cdf0e10cSrcweir     return false;
394cdf0e10cSrcweir }
395cdf0e10cSrcweir 
isDragableObjectHitTwice(const Point & rMPos,const rtl::OUString & rNameOfSelectedObject,const DrawViewWrapper & rDrawViewWrapper)396cdf0e10cSrcweir bool SelectionHelper::isDragableObjectHitTwice( const Point& rMPos
397cdf0e10cSrcweir                     , const rtl::OUString& rNameOfSelectedObject
398cdf0e10cSrcweir                     , const DrawViewWrapper& rDrawViewWrapper )
399cdf0e10cSrcweir {
400*9ec58d04SHerbert Dürr     if( rNameOfSelectedObject.isEmpty() )
401cdf0e10cSrcweir         return false;
402cdf0e10cSrcweir     if( !ObjectIdentifier::isDragableObject(rNameOfSelectedObject) )
403cdf0e10cSrcweir         return false;
404cdf0e10cSrcweir     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
405cdf0e10cSrcweir     SdrObject* pObj = rDrawViewWrapper.getNamedSdrObject( rNameOfSelectedObject );
406cdf0e10cSrcweir     if( !rDrawViewWrapper.IsObjectHit( pObj, rMPos ) )
407cdf0e10cSrcweir         return false;
408cdf0e10cSrcweir     return true;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir 
getHitObjectCID(const Point & rMPos,DrawViewWrapper & rDrawViewWrapper,bool bGetDiagramInsteadOf_Wall)411cdf0e10cSrcweir ::rtl::OUString SelectionHelper::getHitObjectCID(
412cdf0e10cSrcweir     const Point& rMPos,
413cdf0e10cSrcweir     DrawViewWrapper& rDrawViewWrapper,
414cdf0e10cSrcweir     bool bGetDiagramInsteadOf_Wall )
415cdf0e10cSrcweir {
416cdf0e10cSrcweir     // //- solar mutex
417cdf0e10cSrcweir     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
418cdf0e10cSrcweir     rtl::OUString aRet;
419cdf0e10cSrcweir 
420cdf0e10cSrcweir     SdrObject* pNewObj = rDrawViewWrapper.getHitObject(rMPos);
421cdf0e10cSrcweir     aRet = lcl_getObjectName( pNewObj );//name of pNewObj
422cdf0e10cSrcweir 
423cdf0e10cSrcweir     //ignore handle only objects for hit test
424cdf0e10cSrcweir     while( pNewObj && aRet.match(C2U("HandlesOnly")) )
425cdf0e10cSrcweir     {
426cdf0e10cSrcweir         pNewObj->SetMarkProtect(true);
427cdf0e10cSrcweir         pNewObj = rDrawViewWrapper.getHitObject(rMPos);
428cdf0e10cSrcweir         aRet = lcl_getObjectName( pNewObj );
429cdf0e10cSrcweir     }
430cdf0e10cSrcweir 
431cdf0e10cSrcweir     //accept only named objects while searching for the object to select
432cdf0e10cSrcweir     if( !findNamedParent( pNewObj, aRet, true ) )
433cdf0e10cSrcweir     {
434cdf0e10cSrcweir         aRet = ::rtl::OUString();
435cdf0e10cSrcweir     }
436cdf0e10cSrcweir 
437cdf0e10cSrcweir     rtl::OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );//@todo read CID from model
438cdf0e10cSrcweir     //get page when nothing was hit
439*9ec58d04SHerbert Dürr     if( aRet.isEmpty()  && !pNewObj )
440cdf0e10cSrcweir     {
441cdf0e10cSrcweir         aRet = aPageCID;
442cdf0e10cSrcweir     }
443cdf0e10cSrcweir 
444cdf0e10cSrcweir     //get diagram instead wall or page if hit inside diagram
445*9ec58d04SHerbert Dürr     if( !aRet.isEmpty()  )
446cdf0e10cSrcweir     {
447cdf0e10cSrcweir         if( aRet.equals( aPageCID ) )
448cdf0e10cSrcweir         {
449cdf0e10cSrcweir             rtl::OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) );
450cdf0e10cSrcweir             //todo: if more than one diagram is available in future do chack the list of all diagrams here
451cdf0e10cSrcweir             SdrObject* pDiagram = rDrawViewWrapper.getNamedSdrObject( aDiagramCID );
452cdf0e10cSrcweir             if( pDiagram )
453cdf0e10cSrcweir             {
454cdf0e10cSrcweir                 if( rDrawViewWrapper.IsObjectHit( pDiagram, rMPos ) )
455cdf0e10cSrcweir                 {
456cdf0e10cSrcweir                     aRet = aDiagramCID;
457cdf0e10cSrcweir                 }
458cdf0e10cSrcweir             }
459cdf0e10cSrcweir         }
460cdf0e10cSrcweir         else if( bGetDiagramInsteadOf_Wall )
461cdf0e10cSrcweir         {
462cdf0e10cSrcweir             rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
463cdf0e10cSrcweir 
464cdf0e10cSrcweir             if( aRet.equals( aWallCID ) )
465cdf0e10cSrcweir             {
466cdf0e10cSrcweir                 rtl::OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) );
467cdf0e10cSrcweir                 aRet = aDiagramCID;
468cdf0e10cSrcweir             }
469cdf0e10cSrcweir         }
470cdf0e10cSrcweir     }
471cdf0e10cSrcweir 
472cdf0e10cSrcweir     return aRet;
473cdf0e10cSrcweir     // \\- solar mutex
474cdf0e10cSrcweir }
475cdf0e10cSrcweir 
isRotateableObject(const::rtl::OUString & rCID,const uno::Reference<frame::XModel> & xChartModel)476cdf0e10cSrcweir bool SelectionHelper::isRotateableObject( const ::rtl::OUString& rCID
477cdf0e10cSrcweir                     , const uno::Reference< frame::XModel >& xChartModel )
478cdf0e10cSrcweir {
479cdf0e10cSrcweir     if( !ObjectIdentifier::isRotateableObject( rCID ) )
480cdf0e10cSrcweir         return false;
481cdf0e10cSrcweir 
482cdf0e10cSrcweir     sal_Int32 nDimensionCount = DiagramHelper::getDimension( ChartModelHelper::findDiagram( xChartModel ) );
483cdf0e10cSrcweir 
484cdf0e10cSrcweir     if( nDimensionCount == 3 )
485cdf0e10cSrcweir         return true;
486cdf0e10cSrcweir     return false;
487cdf0e10cSrcweir }
488cdf0e10cSrcweir 
SelectionHelper(SdrObject * pSelectedObj)489cdf0e10cSrcweir SelectionHelper::SelectionHelper( SdrObject* pSelectedObj )
490cdf0e10cSrcweir                       : m_pSelectedObj( pSelectedObj )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir 
493cdf0e10cSrcweir }
~SelectionHelper()494cdf0e10cSrcweir SelectionHelper::~SelectionHelper()
495cdf0e10cSrcweir {
496cdf0e10cSrcweir }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir //virtual
getFrameDragSingles()499cdf0e10cSrcweir bool SelectionHelper::getFrameDragSingles()
500cdf0e10cSrcweir {
501cdf0e10cSrcweir     bool bFrameDragSingles = true;//true == green == surrounding handles
502cdf0e10cSrcweir     if( m_pSelectedObj && m_pSelectedObj->ISA(E3dObject) )
503cdf0e10cSrcweir         bFrameDragSingles = false;
504cdf0e10cSrcweir     return bFrameDragSingles;
505cdf0e10cSrcweir }
506cdf0e10cSrcweir 
getMarkHandlesObject(SdrObject * pObj)507cdf0e10cSrcweir SdrObject* SelectionHelper::getMarkHandlesObject( SdrObject* pObj )
508cdf0e10cSrcweir {
509cdf0e10cSrcweir     if(!pObj)
510cdf0e10cSrcweir         return 0;
511cdf0e10cSrcweir     rtl::OUString aName( lcl_getObjectName( pObj ) );
512cdf0e10cSrcweir     if( aName.match(C2U("MarkHandles")) || aName.match(C2U("HandlesOnly")) )
513cdf0e10cSrcweir         return pObj;
514*9ec58d04SHerbert Dürr     if( !aName.isEmpty() )//dont't get the markhandles of a different object
515cdf0e10cSrcweir         return 0;
516cdf0e10cSrcweir 
517cdf0e10cSrcweir     //search for a child with name "MarkHandles" or "HandlesOnly"
518cdf0e10cSrcweir     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
519cdf0e10cSrcweir     SdrObjList* pSubList = pObj->GetSubList();
520cdf0e10cSrcweir     if(pSubList)
521cdf0e10cSrcweir     {
522cdf0e10cSrcweir         SdrObjListIter aIterator(*pSubList, IM_FLAT);
523cdf0e10cSrcweir         while (aIterator.IsMore())
524cdf0e10cSrcweir 	    {
525cdf0e10cSrcweir 		    SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
526cdf0e10cSrcweir             if( pMarkHandles )
527cdf0e10cSrcweir                 return pMarkHandles;
528cdf0e10cSrcweir         }
529cdf0e10cSrcweir     }
530cdf0e10cSrcweir     return 0;
531cdf0e10cSrcweir }
532cdf0e10cSrcweir 
getObjectToMark()533cdf0e10cSrcweir SdrObject* SelectionHelper::getObjectToMark()
534cdf0e10cSrcweir {
535cdf0e10cSrcweir     //return the selected object itself
536cdf0e10cSrcweir     //or a specific other object if that exsists
537cdf0e10cSrcweir     SdrObject* pObj = m_pSelectedObj;
538cdf0e10cSrcweir     m_pMarkObj = pObj;
539cdf0e10cSrcweir 
540cdf0e10cSrcweir     //search for a child with name "MarkHandles" or "HandlesOnly"
541cdf0e10cSrcweir     if(pObj)
542cdf0e10cSrcweir     {
543cdf0e10cSrcweir         ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
544cdf0e10cSrcweir         SdrObjList* pSubList = pObj->GetSubList();
545cdf0e10cSrcweir         if(pSubList)
546cdf0e10cSrcweir         {
547cdf0e10cSrcweir             SdrObjListIter aIterator(*pSubList, IM_FLAT);
548cdf0e10cSrcweir             while (aIterator.IsMore())
549cdf0e10cSrcweir 	        {
550cdf0e10cSrcweir 		        SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() );
551cdf0e10cSrcweir                 if( pMarkHandles )
552cdf0e10cSrcweir                 {
553cdf0e10cSrcweir                     m_pMarkObj = pMarkHandles;
554cdf0e10cSrcweir                     break;
555cdf0e10cSrcweir                 }
556cdf0e10cSrcweir             }
557cdf0e10cSrcweir         }
558cdf0e10cSrcweir     }
559cdf0e10cSrcweir     return m_pMarkObj;
560cdf0e10cSrcweir }
561cdf0e10cSrcweir 
getSceneToRotate(SdrObject * pObj)562cdf0e10cSrcweir E3dScene* SelectionHelper::getSceneToRotate( SdrObject* pObj )
563cdf0e10cSrcweir {
564cdf0e10cSrcweir     //search wether the object or one of its children is a 3D object
565cdf0e10cSrcweir     //if so, return the accessory 3DScene
566cdf0e10cSrcweir 
567cdf0e10cSrcweir     E3dObject* pRotateable = 0;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir     if(pObj)
570cdf0e10cSrcweir     {
571cdf0e10cSrcweir         pRotateable = dynamic_cast<E3dObject*>(pObj);
572cdf0e10cSrcweir         if( !pRotateable )
573cdf0e10cSrcweir         {
574cdf0e10cSrcweir             ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
575cdf0e10cSrcweir             SdrObjList* pSubList = pObj->GetSubList();
576cdf0e10cSrcweir             if(pSubList)
577cdf0e10cSrcweir             {
578cdf0e10cSrcweir                 SdrObjListIter aIterator(*pSubList, IM_DEEPWITHGROUPS);
579cdf0e10cSrcweir                 while( aIterator.IsMore() && !pRotateable )
580cdf0e10cSrcweir 	            {
581cdf0e10cSrcweir 		            SdrObject* pSubObj = aIterator.Next();
582cdf0e10cSrcweir                     pRotateable = dynamic_cast<E3dObject*>(pSubObj);
583cdf0e10cSrcweir                 }
584cdf0e10cSrcweir             }
585cdf0e10cSrcweir         }
586cdf0e10cSrcweir     }
587cdf0e10cSrcweir 
588cdf0e10cSrcweir     E3dScene* pScene = 0;
589cdf0e10cSrcweir     if(pRotateable)
590cdf0e10cSrcweir     {
591cdf0e10cSrcweir         ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
592cdf0e10cSrcweir         pScene = pRotateable->GetScene();
593cdf0e10cSrcweir     }
594cdf0e10cSrcweir     return pScene;
595cdf0e10cSrcweir 
596cdf0e10cSrcweir }
597cdf0e10cSrcweir 
598cdf0e10cSrcweir //virtual
getMarkHandles(SdrHdlList & rHdlList)599cdf0e10cSrcweir bool SelectionHelper::getMarkHandles( SdrHdlList& rHdlList )
600cdf0e10cSrcweir {
601cdf0e10cSrcweir     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
602cdf0e10cSrcweir 
603cdf0e10cSrcweir     //@todo -> more flexible handle creation
604cdf0e10cSrcweir     //2 scenarios possible:
605cdf0e10cSrcweir     //1. add an additional invisible shape as a child to the selected object
606cdf0e10cSrcweir     //this child needs to be named somehow and handles need to be generated therefrom ...
607cdf0e10cSrcweir     //or 2. offer a central service per view where renderer and so can register for handle creation for a special shape
608cdf0e10cSrcweir     //.. or 3. feature from drawinglayer to create handles for each shape ... (bad performance ... ?) ?
609cdf0e10cSrcweir 
610cdf0e10cSrcweir     //scenario 1 is now used:
611cdf0e10cSrcweir     //if a child with name MarkHandles exsists
612cdf0e10cSrcweir     //this child is marked instead of the logical selected object
613cdf0e10cSrcweir 
614cdf0e10cSrcweir /*
615cdf0e10cSrcweir     //if a special mark object was found
616cdf0e10cSrcweir     //that object should be used for marking only
617cdf0e10cSrcweir     if( m_pMarkObj != m_pSelectedObj)
618cdf0e10cSrcweir         return false;
619cdf0e10cSrcweir */
620cdf0e10cSrcweir     //if a special mark object was found
621cdf0e10cSrcweir     //that object should be used to create handles from
622cdf0e10cSrcweir     if( m_pMarkObj && m_pMarkObj != m_pSelectedObj)
623cdf0e10cSrcweir     {
624cdf0e10cSrcweir         rHdlList.Clear();
625cdf0e10cSrcweir         if( m_pMarkObj->ISA(SdrPathObj) )
626cdf0e10cSrcweir         {
627cdf0e10cSrcweir             //if th object is a polygon
628cdf0e10cSrcweir             //from each point a handle is generated
629cdf0e10cSrcweir             const ::basegfx::B2DPolyPolygon& rPolyPolygon = ((SdrPathObj*)m_pMarkObj)->GetPathPoly();
630cdf0e10cSrcweir             for( sal_uInt32 nN = 0L; nN < rPolyPolygon.count(); nN++)
631cdf0e10cSrcweir             {
632cdf0e10cSrcweir                 const ::basegfx::B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(nN));
633cdf0e10cSrcweir                 for( sal_uInt32 nM = 0L; nM < aPolygon.count(); nM++)
634cdf0e10cSrcweir                 {
635cdf0e10cSrcweir 					const ::basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(nM));
636cdf0e10cSrcweir                     SdrHdl* pHdl = new SdrHdl(Point(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY())), HDL_POLY);
637cdf0e10cSrcweir 	                rHdlList.AddHdl(pHdl);
638cdf0e10cSrcweir                 }
639cdf0e10cSrcweir             }
640cdf0e10cSrcweir             return true;
641cdf0e10cSrcweir         }
642cdf0e10cSrcweir         else
643cdf0e10cSrcweir             return false; //use the special MarkObject for marking
644cdf0e10cSrcweir     }
645cdf0e10cSrcweir 
646cdf0e10cSrcweir     //@todo:
647cdf0e10cSrcweir     //add and document good marking defaults ...
648cdf0e10cSrcweir 
649cdf0e10cSrcweir     rHdlList.Clear();
650cdf0e10cSrcweir 
651cdf0e10cSrcweir     SdrObject* pObj = m_pSelectedObj;
652cdf0e10cSrcweir     if(!pObj)
653cdf0e10cSrcweir         return false;
654cdf0e10cSrcweir     SdrObjList* pSubList = pObj->GetSubList();
655cdf0e10cSrcweir     if( !pSubList )//no group object !pObj->IsGroupObject()
656cdf0e10cSrcweir         return false;
657cdf0e10cSrcweir 
658cdf0e10cSrcweir     rtl::OUString aName( lcl_getObjectName( pObj ) );
659cdf0e10cSrcweir     ObjectType eObjectType( ObjectIdentifier::getObjectType( aName ) );
660cdf0e10cSrcweir     if( OBJECTTYPE_DATA_POINT == eObjectType
661cdf0e10cSrcweir         || OBJECTTYPE_DATA_LABEL == eObjectType
662cdf0e10cSrcweir         || OBJECTTYPE_LEGEND_ENTRY == eObjectType
663cdf0e10cSrcweir         || OBJECTTYPE_AXIS_UNITLABEL == eObjectType )
664cdf0e10cSrcweir     {
665cdf0e10cSrcweir         return false;
666cdf0e10cSrcweir     }
667cdf0e10cSrcweir 
668cdf0e10cSrcweir     SdrObjListIter aIterator(*pSubList, IM_FLAT);
669cdf0e10cSrcweir 
670cdf0e10cSrcweir     while (aIterator.IsMore())
671cdf0e10cSrcweir 	{
672cdf0e10cSrcweir 		SdrObject* pSubObj = aIterator.Next();
673cdf0e10cSrcweir         if( OBJECTTYPE_DATA_SERIES == eObjectType )
674cdf0e10cSrcweir         {
675cdf0e10cSrcweir             rtl::OUString aSubName( lcl_getObjectName( pSubObj ) );
676cdf0e10cSrcweir             ObjectType eSubObjectType( ObjectIdentifier::getObjectType( aSubName ) );
677cdf0e10cSrcweir             if( eSubObjectType!=OBJECTTYPE_DATA_POINT  )
678cdf0e10cSrcweir                 return false;
679cdf0e10cSrcweir         }
680cdf0e10cSrcweir 
681cdf0e10cSrcweir         Point aPos = pSubObj->GetCurrentBoundRect().Center();
682cdf0e10cSrcweir 	    SdrHdl* pHdl = new SdrHdl(aPos,HDL_POLY);
683cdf0e10cSrcweir 	    rHdlList.AddHdl(pHdl);
684cdf0e10cSrcweir     }
685cdf0e10cSrcweir     return true;
686cdf0e10cSrcweir }
687cdf0e10cSrcweir 
688cdf0e10cSrcweir //.............................................................................
689cdf0e10cSrcweir } //namespace chart
690cdf0e10cSrcweir //.............................................................................
691