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