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