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