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_svx.hxx"
26 
27 #include <svx/ShapeTypeHandler.hxx>
28 #include <svx/SvxShapeTypes.hxx>
29 #include <svx/AccessibleShapeInfo.hxx>
30 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
31 #include <vos/mutex.hxx>
32 #include <vcl/svapp.hxx>
33 #include <svx/dialmgr.hxx>
34 
35 #include <svx/unoshape.hxx>
36 #include <svx/svdoashp.hxx>
37 #include "svx/unoapi.hxx"
38 
39 #include "svx/svdstr.hrc"
40 
41 using namespace ::rtl;
42 using namespace ::com::sun::star;
43 using namespace	::com::sun::star::accessibility;
44 
45 namespace accessibility {
46 
47 // Pointer to the shape type handler singleton.
48 ShapeTypeHandler* ShapeTypeHandler::instance = NULL;
49 
50 
51 // Create an empty reference to an accessible object.
52 AccessibleShape*
CreateEmptyShapeReference(const AccessibleShapeInfo &,const AccessibleShapeTreeInfo &,ShapeTypeId)53     CreateEmptyShapeReference (
54         const AccessibleShapeInfo& /*rShapeInfo*/,
55         const AccessibleShapeTreeInfo& /*rShapeTreeInfo*/,
56         ShapeTypeId /*nId*/)
57 {
58     return NULL;
59 }
60 
61 
62 
63 
Instance(void)64 ShapeTypeHandler& ShapeTypeHandler::Instance (void)
65 {
66     // Using double check pattern to make sure that exactly one instance of
67     // the shape type handler is instantiated.
68     if (instance == NULL)
69     {
70         ::vos::OGuard aGuard (::Application::GetSolarMutex());
71         if (instance == NULL)
72         {
73             // Create the single instance of the shape type handler.
74             instance = new ShapeTypeHandler;
75 
76             // Register the basic SVX shape types.
77             RegisterDrawShapeTypes ();
78         }
79     }
80 
81     return *instance;
82 }
83 
84 
85 
86 
87 /** The given service name is first transformed into a slot id that
88     identifies the place of the type descriptor.  From that descriptor the
89     shape type id is returned.
90 */
GetTypeId(const OUString & aServiceName) const91 ShapeTypeId ShapeTypeHandler::GetTypeId (const OUString& aServiceName) const
92 {
93     tServiceNameToSlotId::iterator I (maServiceNameToSlotId.find (aServiceName));
94     if (I != maServiceNameToSlotId.end())
95     {
96         //	long nSlotId = maServiceNameToSlotId[aServiceName];
97         return maShapeTypeDescriptorList[I->second].mnShapeTypeId;
98     }
99     else
100         return -1;
101 }
102 
103 
104 
105 /** Extract the specified shape's service name and forward the request to
106     the appropriate method.
107 */
GetTypeId(const uno::Reference<drawing::XShape> & rxShape) const108 ShapeTypeId ShapeTypeHandler::GetTypeId (const uno::Reference<drawing::XShape>& rxShape) const
109 {
110     uno::Reference<drawing::XShapeDescriptor> xDescriptor (rxShape, uno::UNO_QUERY);
111     if (xDescriptor.is())
112         return GetTypeId (xDescriptor->getShapeType());
113     else
114         return -1;
115 }
116 
117 
118 
119 
GetServiceName(ShapeTypeId aTypeId) const120 const OUString& ShapeTypeHandler::GetServiceName (ShapeTypeId aTypeId) const
121 {
122     return maShapeTypeDescriptorList[aTypeId].msServiceName;
123 }
124 
125 
126 
127 
128 /** This factory method determines the type descriptor for the type of the
129     given shape, then calls the descriptor's create function, and finally
130     initializes the new object.
131 */
132 AccessibleShape*
CreateAccessibleObject(const AccessibleShapeInfo & rShapeInfo,const AccessibleShapeTreeInfo & rShapeTreeInfo) const133     ShapeTypeHandler::CreateAccessibleObject (
134         const AccessibleShapeInfo& rShapeInfo,
135         const AccessibleShapeTreeInfo& rShapeTreeInfo) const
136 {
137     ShapeTypeId nSlotId (GetSlotId (rShapeInfo.mxShape));
138     AccessibleShape* pShape =
139         maShapeTypeDescriptorList[nSlotId].maCreateFunction (
140             rShapeInfo,
141             rShapeTreeInfo,
142             maShapeTypeDescriptorList[nSlotId].mnShapeTypeId);
143     return pShape;
144 }
145 
146 
147 
148 
149 /** Create the single instance of this class and initialize its list of
150     type descriptors with an entry of an unknown type.
151 */
ShapeTypeHandler(void)152 ShapeTypeHandler::ShapeTypeHandler (void)
153     : maShapeTypeDescriptorList (1)
154 {
155     // Make sure that at least the UNKNOWN entry is present.
156     // Resize the list, if necessary, so that the new type can be inserted.
157     maShapeTypeDescriptorList[0].mnShapeTypeId = UNKNOWN_SHAPE_TYPE;
158     maShapeTypeDescriptorList[0].msServiceName =
159         OUString::createFromAscii ("UNKNOWN_SHAPE_TYPE");
160     maShapeTypeDescriptorList[0].maCreateFunction = CreateEmptyShapeReference;
161     maServiceNameToSlotId[maShapeTypeDescriptorList[0].msServiceName] = 0;
162 }
163 
164 
165 
166 
~ShapeTypeHandler(void)167 ShapeTypeHandler::~ShapeTypeHandler	(void)
168 {
169     //  Because this class is a singleton and the only instance, whose
170     //  destructor has just been called, is pointed to from instance,
171     //  we reset the static variable instance, so that further calls to
172     //  getInstance do not return an undefined object but create a new
173     //  singleton.
174     instance = NULL;
175 }
176 
177 
178 
179 
AddShapeTypeList(int nDescriptorCount,ShapeTypeDescriptor aDescriptorList[])180 bool ShapeTypeHandler::AddShapeTypeList (int nDescriptorCount,
181     ShapeTypeDescriptor aDescriptorList[])
182 {
183     ::vos::OGuard aGuard (::Application::GetSolarMutex());
184 
185     // Determine first id of new type descriptor(s).
186     int nFirstId = maShapeTypeDescriptorList.size();
187 
188     // Resize the list, if necessary, so that the types can be inserted.
189     maShapeTypeDescriptorList.resize (nFirstId + nDescriptorCount);
190 
191     for (int i=0; i<nDescriptorCount; i++)
192     {
193     #if OSL_DEBUG_LEVEL > 0
194         ShapeTypeId nId (aDescriptorList[i].mnShapeTypeId);
195         (void)nId;
196     #endif
197 
198         // Fill Type descriptor.
199         maShapeTypeDescriptorList[nFirstId+i].mnShapeTypeId = aDescriptorList[i].mnShapeTypeId;
200         maShapeTypeDescriptorList[nFirstId+i].msServiceName = aDescriptorList[i].msServiceName;
201         maShapeTypeDescriptorList[nFirstId+i].maCreateFunction = aDescriptorList[i].maCreateFunction;
202 
203         // Update inverse mapping from service name to the descriptor's position.
204         maServiceNameToSlotId[aDescriptorList[i].msServiceName] = nFirstId+i;
205     }
206 
207     return true;
208 }
209 
210 
211 
212 
213 #include <tools/string.hxx>
GetSlotId(const OUString & aServiceName) const214 long ShapeTypeHandler::GetSlotId (const OUString& aServiceName) const
215 {
216     tServiceNameToSlotId::iterator I (maServiceNameToSlotId.find (aServiceName));
217     if (I != maServiceNameToSlotId.end())
218         return I->second;
219     else
220         return 0;
221 }
222 
223 
224 
225 
226 // Extract the given shape's service name and forward request to appropriate
227 // method.
GetSlotId(const uno::Reference<drawing::XShape> & rxShape) const228 long ShapeTypeHandler::GetSlotId (const uno::Reference<drawing::XShape>& rxShape) const
229 {
230     uno::Reference<drawing::XShapeDescriptor> xDescriptor (rxShape, uno::UNO_QUERY);
231     if (xDescriptor.is())
232         return GetSlotId (xDescriptor->getShapeType());
233     else
234         return 0;
235 }
236 
237 ///	get the accessible base name for an object
238 ::rtl::OUString
CreateAccessibleBaseName(const uno::Reference<drawing::XShape> & rxShape)239     ShapeTypeHandler::CreateAccessibleBaseName (const uno::Reference<drawing::XShape>& rxShape)
240     throw (::com::sun::star::uno::RuntimeException)
241 {
242     sal_Int32 nResourceId;
243     OUString sName;
244 
245     switch (ShapeTypeHandler::Instance().GetTypeId (rxShape))
246     {
247 	  // case DRAWING_3D_POLYGON: was removed in original code in
248 	  // AccessibleShape::CreateAccessibleBaseName.  See issue 11190 for details.
249 	  // Id can be removed from SvxShapeTypes.hxx as well.
250         case DRAWING_3D_CUBE:
251             nResourceId = STR_ObjNameSingulCube3d;
252             break;
253         case DRAWING_3D_EXTRUDE:
254             nResourceId = STR_ObjNameSingulExtrude3d;
255             break;
256         case DRAWING_3D_LATHE:
257             nResourceId = STR_ObjNameSingulLathe3d;
258             break;
259         case DRAWING_3D_SCENE:
260             nResourceId = STR_ObjNameSingulScene3d;
261             break;
262         case DRAWING_3D_SPHERE:
263             nResourceId = STR_ObjNameSingulSphere3d;
264             break;
265         case DRAWING_CAPTION:
266             nResourceId = STR_ObjNameSingulCAPTION;
267             break;
268         case DRAWING_CLOSED_BEZIER:
269             nResourceId = STR_ObjNameSingulPATHFILL;
270             break;
271         case DRAWING_CLOSED_FREEHAND:
272             nResourceId = STR_ObjNameSingulFREEFILL;
273             break;
274         case DRAWING_CONNECTOR:
275             nResourceId = STR_ObjNameSingulEDGE;
276             break;
277         case DRAWING_CONTROL:
278             nResourceId = STR_ObjNameSingulUno;
279             break;
280         case DRAWING_ELLIPSE:
281             nResourceId = STR_ObjNameSingulCIRCE;
282             break;
283         case DRAWING_GROUP:
284             nResourceId = STR_ObjNameSingulGRUP;
285             break;
286         case DRAWING_LINE:
287             nResourceId = STR_ObjNameSingulLINE;
288             break;
289         case DRAWING_MEASURE:
290             nResourceId = STR_ObjNameSingulMEASURE;
291             break;
292         case DRAWING_OPEN_BEZIER:
293             nResourceId = STR_ObjNameSingulPATHLINE;
294             break;
295         case DRAWING_OPEN_FREEHAND:
296             nResourceId = STR_ObjNameSingulFREELINE;
297             break;
298         case DRAWING_PAGE:
299             nResourceId = STR_ObjNameSingulPAGE;
300             break;
301         case DRAWING_POLY_LINE:
302             nResourceId = STR_ObjNameSingulPLIN;
303             break;
304         case DRAWING_POLY_LINE_PATH:
305             nResourceId = STR_ObjNameSingulPLIN;
306             break;
307         case DRAWING_POLY_POLYGON:
308             nResourceId = STR_ObjNameSingulPOLY;
309             break;
310         case DRAWING_POLY_POLYGON_PATH:
311             nResourceId = STR_ObjNameSingulPOLY;
312             break;
313         case DRAWING_RECTANGLE:
314             nResourceId = STR_ObjNameSingulRECT;
315             break;
316         case DRAWING_CUSTOM:
317 			{
318 				nResourceId = STR_ObjNameSingulCUSTOMSHAPE;
319 
320 				SvxShape* pShape = SvxShape::getImplementation( rxShape );
321 				if (pShape)
322 				{
323 					SdrObject *pSdrObj = pShape->GetSdrObject();
324 					if (pSdrObj)
325 					{
326 						String aTmp;
327 						pSdrObj->TakeObjNameSingul( aTmp );
328 
329 						if(pSdrObj->ISA(SdrObjCustomShape))
330 						{
331 							SdrObjCustomShape* pCustomShape = (SdrObjCustomShape*)pSdrObj;
332 							if(pCustomShape)
333 								if (pCustomShape->IsTextPath())
334 					 				nResourceId = STR_ObjNameSingulFONTWORK;
335 								else
336 								{
337 									nResourceId = -1;
338 									sName = pCustomShape->GetCustomShapeName();
339 								}
340 						}
341 					}
342 				}
343                 break;
344 			}
345         case DRAWING_TEXT:
346             nResourceId = STR_ObjNameSingulTEXT;
347             break;
348         default:
349             nResourceId = -1;
350             sName = ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("UnknownAccessibleShape"));
351             uno::Reference<drawing::XShapeDescriptor> xDescriptor (rxShape, uno::UNO_QUERY);
352             if (xDescriptor.is())
353                 sName += ::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM(": "))
354                     + xDescriptor->getShapeType();
355             break;
356     }
357 
358     if (nResourceId != -1)
359     {
360         ::vos::OGuard aGuard (::Application::GetSolarMutex());
361         sName = OUString (SVX_RESSTR((unsigned short)nResourceId));
362     }
363 
364     return sName;
365 }
366 
367 } // end of namespace accessibility
368