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
lcl_getObjectName(SdrObject * pObj)54 rtl::OUString lcl_getObjectName( SdrObject* pObj )
55 {
56 if(pObj)
57 return pObj->GetName();
58 return rtl::OUString();
59 }
60
impl_selectObject(SdrObject * pObjectToSelect,DrawViewWrapper & rDrawViewWrapper)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
hasSelection()77 bool Selection::hasSelection()
78 {
79 return m_aSelectedOID.isValid();
80 }
81
getSelectedCID()82 rtl::OUString Selection::getSelectedCID()
83 {
84 return m_aSelectedOID.getObjectCID();
85 }
86
getSelectedAdditionalShape()87 uno::Reference< drawing::XShape > Selection::getSelectedAdditionalShape()
88 {
89 return m_aSelectedOID.getAdditionalShape();
90 }
91
getSelectedOID() const92 ObjectIdentifier Selection::getSelectedOID() const
93 {
94 return m_aSelectedOID;
95 }
96
setSelection(const::rtl::OUString & rCID)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
setSelection(const uno::Reference<drawing::XShape> & xShape)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
clearSelection()118 void Selection::clearSelection()
119 {
120 m_aSelectedOID = ObjectIdentifier();
121 m_aSelectedOID_beforeMouseDown = ObjectIdentifier();
122 m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
123 }
124
maybeSwitchSelectionAfterSingleClickWasEnsured()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
resetPossibleSelectionAfterSingleClickWasEnsured()137 void Selection::resetPossibleSelectionAfterSingleClickWasEnsured()
138 {
139 if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() )
140 {
141 m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier();
142 }
143 }
144
remindSelectionBeforeMouseDown()145 void Selection::remindSelectionBeforeMouseDown()
146 {
147 m_aSelectedOID_beforeMouseDown = m_aSelectedOID;
148 }
149
isSelectionDifferentFromBeforeMouseDown()150 bool Selection::isSelectionDifferentFromBeforeMouseDown()
151 {
152 return ( m_aSelectedOID != m_aSelectedOID_beforeMouseDown );
153 }
154
applySelection(DrawViewWrapper * pDrawViewWrapper)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
adaptSelectionToNewPos(const Point & rMousePos,DrawViewWrapper * pDrawViewWrapper,bool bIsRightMouse,bool bWaitingForDoubleClick)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
isResizeableObjectSelected()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
isRotateableObjectSelected(const uno::Reference<frame::XModel> & xChartModel)331 bool Selection::isRotateableObjectSelected( const uno::Reference< frame::XModel >& xChartModel )
332 {
333 return SelectionHelper::isRotateableObject( m_aSelectedOID.getObjectCID(), xChartModel );
334 }
335
isDragableObjectSelected()336 bool Selection::isDragableObjectSelected()
337 {
338 return m_aSelectedOID.isDragableObject();
339 }
340
isAdditionalShapeSelected() const341 bool Selection::isAdditionalShapeSelected() const
342 {
343 return m_aSelectedOID.isAdditionalShape();
344 }
345
346 //-----------------------------------------------------------------------------
347 //-----------------------------------------------------------------------------
348 //-----------------------------------------------------------------------------
349
findNamedParent(SdrObject * & pInOutObject,rtl::OUString & rOutName,bool bGivenObjectMayBeResult)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.isEmpty() )
376 return false;
377
378 pInOutObject = pObj;
379 rOutName = aName;
380 return true;
381 }
382
findNamedParent(SdrObject * & pInOutObject,ObjectIdentifier & rOutObject,bool bGivenObjectMayBeResult)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
isDragableObjectHitTwice(const Point & rMPos,const rtl::OUString & rNameOfSelectedObject,const DrawViewWrapper & rDrawViewWrapper)396 bool SelectionHelper::isDragableObjectHitTwice( const Point& rMPos
397 , const rtl::OUString& rNameOfSelectedObject
398 , const DrawViewWrapper& rDrawViewWrapper )
399 {
400 if( rNameOfSelectedObject.isEmpty() )
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
getHitObjectCID(const Point & rMPos,DrawViewWrapper & rDrawViewWrapper,bool bGetDiagramInsteadOf_Wall)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.isEmpty() && !pNewObj )
440 {
441 aRet = aPageCID;
442 }
443
444 //get diagram instead wall or page if hit inside diagram
445 if( !aRet.isEmpty() )
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
isRotateableObject(const::rtl::OUString & rCID,const uno::Reference<frame::XModel> & xChartModel)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
SelectionHelper(SdrObject * pSelectedObj)489 SelectionHelper::SelectionHelper( SdrObject* pSelectedObj )
490 : m_pSelectedObj( pSelectedObj )
491 {
492
493 }
~SelectionHelper()494 SelectionHelper::~SelectionHelper()
495 {
496 }
497
498 //virtual
getFrameDragSingles()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
getMarkHandlesObject(SdrObject * pObj)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.isEmpty() )//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
getObjectToMark()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
getSceneToRotate(SdrObject * pObj)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
getMarkHandles(SdrHdlList & rHdlList)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