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 #include "precompiled_svx.hxx"
23 
24 #include "svx/sidebar/SelectionAnalyzer.hxx"
25 #include "svx/svdmrkv.hxx"
26 #include "svx/svdobj.hxx"
27 #include "svx/svdotext.hxx"
28 #include "svx/svdpage.hxx"
29 #include "svx/fmglob.hxx"
30 #include "svx/globl3d.hxx"
31 
32 using sfx2::sidebar::EnumContext;
33 
34 
35 namespace svx { namespace sidebar {
36 
GetContextForSelection_SC(const SdrMarkList & rMarkList)37 EnumContext::Context SelectionAnalyzer::GetContextForSelection_SC (const SdrMarkList& rMarkList)
38 {
39     EnumContext::Context eContext = EnumContext::Context_Unknown;
40 
41     switch (rMarkList.GetMarkCount())
42     {
43         case 0:
44             // Empty selection.  Return Context_Unknown to let the caller
45             // substitute it with the default context.
46             break;
47 
48         case 1:
49         {
50             SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
51             if ( pObj->ISA(SdrTextObj) && ((SdrTextObj*)pObj)->IsInEditMode() )
52             {
53                 eContext = EnumContext::Context_DrawText;
54             }
55             else
56             {
57                 const sal_uInt32 nInv = pObj->GetObjInventor();
58                 const sal_uInt16 nObjId = pObj->GetObjIdentifier();
59                 if (nInv == SdrInventor)
60                     eContext = GetContextForObjectId_SC(nObjId);
61                 else if (nInv == FmFormInventor)
62                     eContext = EnumContext::Context_Form;
63             }
64             break;
65         }
66 
67         default:
68         {
69             // Multi selection.
70             switch (GetInventorTypeFromMark(rMarkList))
71             {
72                 case SdrInventor:
73                 {
74                     const sal_uInt16 nObjId (GetObjectTypeFromMark(rMarkList));
75                     if (nObjId == 0)
76                         eContext = EnumContext::Context_MultiObject;
77                     else
78                         eContext = GetContextForObjectId_SC(nObjId);
79                     break;
80                 }
81 
82                 case FmFormInventor:
83                     eContext = EnumContext::Context_Form;
84                     break;
85 
86                 case 0:
87                     eContext = EnumContext::Context_MultiObject;
88                     break;
89             }
90         }
91     }
92 
93     return eContext;
94 }
95 
96 
97 
98 
GetContextForSelection_SD(const SdrMarkList & rMarkList,const ViewType eViewType)99 EnumContext::Context SelectionAnalyzer::GetContextForSelection_SD (
100     const SdrMarkList& rMarkList,
101     const ViewType eViewType)
102 {
103     EnumContext::Context eContext = EnumContext::Context_Unknown;
104 
105     // Note that some cases are handled by the caller.  They rely on
106     // sd specific data.
107     switch (rMarkList.GetMarkCount())
108     {
109         case 0:
110             switch(eViewType)
111             {
112                 case VT_Standard:
113                     eContext = EnumContext::Context_DrawPage;
114                     break;
115                 case VT_Master:
116                     eContext = EnumContext::Context_MasterPage;
117                     break;
118                 case VT_Handout:
119                     eContext = EnumContext::Context_HandoutPage;
120                     break;
121                 case VT_Notes:
122                     eContext = EnumContext::Context_NotesPage;
123                     break;
124                 case VT_Outline:
125                     eContext = EnumContext::Context_OutlineText;
126                     break;
127             }
128             break;
129 
130         case 1:
131         {
132             SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
133             if (pObj->ISA(SdrTextObj) && ((SdrTextObj*)pObj)->IsInEditMode())
134             {
135                 if (pObj->GetObjIdentifier() == OBJ_TABLE)
136                 {
137                     // Let a table object take precedence over text
138                     // edit mode.  The panels for text editing are
139                     // present for table context as well, anyway.
140                     eContext = EnumContext::Context_Table;
141                 }
142                 else
143                     eContext = EnumContext::Context_DrawText;
144             }
145             else
146             {
147                 const sal_uInt32 nInv = pObj->GetObjInventor();
148                 sal_uInt16 nObjId = pObj->GetObjIdentifier();
149                 if (nInv == SdrInventor)
150                 {
151                     if (nObjId == OBJ_GRUP)
152                     {
153                         nObjId = GetObjectTypeFromGroup(pObj);
154                         if (nObjId == 0)
155                             nObjId = OBJ_GRUP;
156                     }
157                     eContext = GetContextForObjectId_SD(nObjId, eViewType);
158                 }
159                 else if (nInv == E3dInventor)
160                 {
161                     eContext = EnumContext::Context_3DObject;
162                 }
163                 else if (nInv == FmFormInventor)
164                 {
165                     eContext = EnumContext::Context_Form;
166                 }
167             }
168             break;
169         }
170 
171         default:
172         {
173             switch (GetInventorTypeFromMark(rMarkList))
174             {
175                 case SdrInventor:
176                 {
177                     const sal_uInt16 nObjId = GetObjectTypeFromMark(rMarkList);
178                     if (nObjId == 0)
179                         eContext = EnumContext::Context_MultiObject;
180                     else
181                         eContext = GetContextForObjectId_SD(nObjId, eViewType);
182                     break;
183                 }
184 
185                 case E3dInventor:
186                     eContext = EnumContext::Context_3DObject;
187                     break;
188 
189                 case FmFormInventor:
190                     eContext = EnumContext::Context_Form;
191                     break;
192 
193                 case 0:
194                     eContext = EnumContext::Context_MultiObject;
195                     break;
196             }
197             break;
198         }
199     }
200 
201 	return eContext;
202 }
203 
204 
205 
206 
GetContextForObjectId_SC(const sal_uInt16 nObjectId)207 EnumContext::Context SelectionAnalyzer::GetContextForObjectId_SC (const sal_uInt16 nObjectId)
208 {
209     switch (nObjectId)
210     {
211         case OBJ_CAPTION:
212         case OBJ_TITLETEXT:
213         case OBJ_OUTLINETEXT:
214         case OBJ_TEXT:
215         case OBJ_TEXTEXT:
216         case OBJ_PATHLINE:
217         case OBJ_PLIN:
218         case OBJ_FREELINE:
219         case OBJ_EDGE:
220         case OBJ_LINE:
221         case OBJ_MEASURE:
222         case OBJ_RECT:
223         case OBJ_CIRC:
224         case OBJ_FREEFILL:
225         case OBJ_PATHFILL:
226         case OBJ_POLY:
227         case OBJ_SECT:
228         case OBJ_CARC:
229         case OBJ_CCUT:
230         case OBJ_CUSTOMSHAPE:
231         case OBJ_GRUP:
232             return EnumContext::Context_Draw;
233 
234         case OBJ_GRAF:
235             return EnumContext::Context_Graphic;
236 
237         case OBJ_OLE2:
238             return EnumContext::Context_OLE;
239 
240         case OBJ_MEDIA:
241             return EnumContext::Context_Media;
242             break;
243 
244         default:
245             return EnumContext::Context_Unknown;
246     }
247 }
248 
249 
250 
251 
GetContextForObjectId_SD(const sal_uInt16 nObjectId,const ViewType eViewType)252 EnumContext::Context SelectionAnalyzer::GetContextForObjectId_SD (
253     const sal_uInt16 nObjectId,
254     const ViewType eViewType)
255 {
256 	switch (nObjectId)
257 	{
258 		case OBJ_CAPTION:
259 		case OBJ_PATHLINE:
260 		case OBJ_PLIN:
261 		case OBJ_FREELINE:
262 		case OBJ_EDGE:
263 		case OBJ_LINE:
264 		case OBJ_MEASURE:
265 		case OBJ_RECT:
266 		case OBJ_CIRC:
267 		case OBJ_FREEFILL:
268 		case OBJ_PATHFILL:
269 		case OBJ_POLY:
270 		case OBJ_SECT:
271 		case OBJ_CARC:
272 		case OBJ_CCUT:
273 		case OBJ_CUSTOMSHAPE:
274 		case OBJ_GRUP:
275 			return EnumContext::Context_Draw;
276 
277 		case OBJ_TITLETEXT:
278 		case OBJ_OUTLINETEXT:
279 		case OBJ_TEXT:
280 		case OBJ_TEXTEXT:
281 			return EnumContext::Context_TextObject;
282 
283 		case OBJ_GRAF:
284 			return EnumContext::Context_Graphic;
285 
286 		case OBJ_OLE2:
287 			return EnumContext::Context_OLE;
288 
289 		case OBJ_MEDIA:
290 			return EnumContext::Context_Media;
291 
292 		case OBJ_TABLE:
293 			return EnumContext::Context_Table;
294 
295 		case OBJ_PAGE:
296             switch (eViewType)
297             {
298                 case VT_Handout:
299                     return EnumContext::Context_HandoutPage;
300                 case VT_Notes:
301                     return EnumContext::Context_NotesPage;
302                 case VT_Outline:
303                     return EnumContext::Context_OutlineText;
304                 default:
305                     return EnumContext::Context_Unknown;
306             }
307 
308         default:
309             return EnumContext::Context_Unknown;
310 	}
311 }
312 
313 
314 
315 
GetInventorTypeFromMark(const SdrMarkList & rMarkList)316 sal_uInt32 SelectionAnalyzer::GetInventorTypeFromMark (const SdrMarkList& rMarkList)
317 {
318     const sal_uLong nMarkCount (rMarkList.GetMarkCount());
319 
320     if (nMarkCount < 1)
321         return 0;
322 
323     SdrMark* pMark = rMarkList.GetMark(0);
324     SdrObject* pObj = pMark->GetMarkedSdrObj();
325     const sal_uInt32 nFirstInv = pObj->GetObjInventor();
326 
327     for (sal_uLong nIndex=1; nIndex<nMarkCount; ++nIndex)
328     {
329         pMark = rMarkList.GetMark(nIndex);
330         pObj = pMark->GetMarkedSdrObj();
331         const sal_uInt32 nInv (pObj->GetObjInventor());
332 
333         if (nInv != nFirstInv)
334             return 0;
335     }
336 
337     return nFirstInv;
338 }
339 
340 
341 
342 
GetObjectTypeFromGroup(const SdrObject * pObj)343 sal_uInt16 SelectionAnalyzer::GetObjectTypeFromGroup (const SdrObject* pObj)
344 {
345     SdrObjList* pObjList = pObj->GetSubList();
346     if (pObjList)
347     {
348         const sal_uLong nSubObjCount (pObjList->GetObjCount());
349 
350         if (nSubObjCount>0)
351         {
352             SdrObject* pObj = pObjList->GetObj(0);
353             sal_uInt16 nResultType = pObj->GetObjIdentifier();
354 
355             if (nResultType == OBJ_GRUP)
356                 nResultType = GetObjectTypeFromGroup(pObj);
357 
358             if (IsShapeType(nResultType))
359                 nResultType = OBJ_CUSTOMSHAPE;
360 
361             if (IsTextObjType(nResultType))
362                 nResultType = OBJ_TEXT;
363 
364             for (sal_uInt16 nIndex=1; nIndex<nSubObjCount; ++nIndex)
365             {
366                 pObj = pObjList->GetObj(nIndex);
367                 sal_uInt16 nType (pObj->GetObjIdentifier());
368 
369                 if(nType == OBJ_GRUP)
370                     nType = GetObjectTypeFromGroup(pObj);
371 
372                 if (IsShapeType(nType))
373                     nType = OBJ_CUSTOMSHAPE;
374 
375                 if ((nType == OBJ_CUSTOMSHAPE) && (nResultType == OBJ_TEXT))
376                     nType = OBJ_TEXT;
377 
378                 if (IsTextObjType(nType))
379                     nType = OBJ_TEXT;
380 
381                 if ((nType == OBJ_TEXT) && (nResultType == OBJ_CUSTOMSHAPE))
382                     nResultType = OBJ_TEXT;
383 
384                 if (nType != nResultType)
385                     return 0;
386             }
387 
388             return nResultType;
389         }
390     }
391 
392     return 0;
393 }
394 
395 
396 
397 
GetObjectTypeFromMark(const SdrMarkList & rMarkList)398 sal_uInt16  SelectionAnalyzer::GetObjectTypeFromMark (const SdrMarkList& rMarkList)
399 {
400     const sal_uLong nMarkCount (rMarkList.GetMarkCount());
401 
402     if (nMarkCount < 1)
403         return 0;
404 
405     SdrMark* pMark = rMarkList.GetMark(0);
406     SdrObject* pObj = pMark->GetMarkedSdrObj();
407     sal_uInt16 nResultType = pObj->GetObjIdentifier();
408 
409     if(nResultType == OBJ_GRUP)
410         nResultType = GetObjectTypeFromGroup(pObj);
411 
412     if (IsShapeType(nResultType))
413         nResultType = OBJ_CUSTOMSHAPE;
414 
415     if (IsTextObjType(nResultType))
416         nResultType = OBJ_TEXT;
417 
418     for (sal_uLong nIndex=1; nIndex<nMarkCount; ++nIndex)
419     {
420         pMark = rMarkList.GetMark(nIndex);
421         pObj = pMark->GetMarkedSdrObj();
422         sal_uInt16 nType = pObj->GetObjIdentifier();
423 
424         if(nType == OBJ_GRUP)
425             nType = GetObjectTypeFromGroup(pObj);
426 
427         if (IsShapeType(nType))
428             nType = OBJ_CUSTOMSHAPE;
429 
430         if ((nType == OBJ_CUSTOMSHAPE) && (nResultType == OBJ_TEXT))
431             nType = OBJ_TEXT;
432 
433         if (IsTextObjType(nType))
434             nType = OBJ_TEXT;
435 
436         if ((nType == OBJ_TEXT) && (nResultType == OBJ_CUSTOMSHAPE))
437             nResultType = OBJ_TEXT;
438 
439         if (nType != nResultType)
440             return 0;
441     }
442 
443     return nResultType;
444 }
445 
446 
447 
448 
IsShapeType(const sal_uInt16 nType)449 bool SelectionAnalyzer::IsShapeType (const sal_uInt16 nType)
450 {
451 	switch (nType)
452     {
453 		case OBJ_LINE:
454 		case OBJ_CARC:
455 		case OBJ_PLIN:
456 		case OBJ_PATHLINE:
457 		case OBJ_RECT:
458 		case OBJ_CIRC:
459 		case OBJ_SECT:
460 		case OBJ_CCUT:
461 		case OBJ_PATHFILL:
462 		case OBJ_CUSTOMSHAPE:
463 		case OBJ_CAPTION:
464 		case OBJ_MEASURE:
465 		case OBJ_EDGE:
466 		case OBJ_POLY:
467 		case OBJ_FREELINE:
468 		case OBJ_FREEFILL:
469 
470         // #122145# adding OBJ_OLE2 since these also allow line/fill style and may
471         // be multiselected/grouped with normal draw objects, e.g. math OLE objects
472         case OBJ_OLE2:
473 			return true;
474 
475 		default:
476             return false;
477 	}
478 }
479 
480 
481 
482 
IsTextObjType(const sal_uInt16 nType)483 bool SelectionAnalyzer::IsTextObjType (const sal_uInt16 nType)
484 {
485 	switch(nType)
486     {
487 		case OBJ_TEXT:
488 		case OBJ_TEXTEXT:
489 		case OBJ_TITLETEXT:
490 		case OBJ_OUTLINETEXT:
491 			return true;
492 
493 		default:
494             return false;
495 	}
496 }
497 
498 
499 
500 } } // end of namespace ::svx::sidebar
501