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