xref: /trunk/main/sd/source/ui/view/drbezob.cxx (revision 79aad27f)
1*5b190011SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*5b190011SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*5b190011SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*5b190011SAndrew Rist  * distributed with this work for additional information
6*5b190011SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*5b190011SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*5b190011SAndrew Rist  * "License"); you may not use this file except in compliance
9*5b190011SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*5b190011SAndrew Rist  *
11*5b190011SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*5b190011SAndrew Rist  *
13*5b190011SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*5b190011SAndrew Rist  * software distributed under the License is distributed on an
15*5b190011SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*5b190011SAndrew Rist  * KIND, either express or implied.  See the License for the
17*5b190011SAndrew Rist  * specific language governing permissions and limitations
18*5b190011SAndrew Rist  * under the License.
19*5b190011SAndrew Rist  *
20*5b190011SAndrew Rist  *************************************************************/
21*5b190011SAndrew Rist 
22*5b190011SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sd.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "BezierObjectBar.hxx"
28cdf0e10cSrcweir #include <sfx2/app.hxx>
29cdf0e10cSrcweir #include <sfx2/msg.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <sfx2/viewfrm.hxx>
32cdf0e10cSrcweir #include <sfx2/objface.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <svx/svxids.hrc>
35cdf0e10cSrcweir #include <svl/eitem.hxx>
36cdf0e10cSrcweir #include <sfx2/request.hxx>
37cdf0e10cSrcweir #include <svx/svdopath.hxx>
38cdf0e10cSrcweir #include <svl/aeitem.hxx>
39cdf0e10cSrcweir #include <svx/svdundo.hxx>
40cdf0e10cSrcweir #include <sfx2/dispatch.hxx>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include "sdresid.hxx"
44cdf0e10cSrcweir 
45cdf0e10cSrcweir 
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include "res_bmp.hrc"
48cdf0e10cSrcweir #include "glob.hrc"
49cdf0e10cSrcweir #include "strings.hrc"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir #include "DrawDocShell.hxx"
52cdf0e10cSrcweir #include "ViewShell.hxx"
53cdf0e10cSrcweir #include "Window.hxx"
54cdf0e10cSrcweir #include "drawview.hxx"
55cdf0e10cSrcweir #include "drawdoc.hxx"
56cdf0e10cSrcweir #include "sdresid.hxx"
57cdf0e10cSrcweir #include "fusel.hxx"
58cdf0e10cSrcweir #include "fuconbez.hxx"
59cdf0e10cSrcweir 
60cdf0e10cSrcweir 
61cdf0e10cSrcweir using namespace sd;
62cdf0e10cSrcweir #define BezierObjectBar
63cdf0e10cSrcweir #include "sdslots.hxx"
64cdf0e10cSrcweir 
65cdf0e10cSrcweir namespace sd {
66cdf0e10cSrcweir 
67cdf0e10cSrcweir /*************************************************************************
68cdf0e10cSrcweir |*
69cdf0e10cSrcweir |* Standardinterface deklarieren (Die Slotmap darf nicht leer sein)
70cdf0e10cSrcweir |*
71cdf0e10cSrcweir \************************************************************************/
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 
SFX_IMPL_INTERFACE(BezierObjectBar,::SfxShell,SdResId (STR_BEZIEROBJECTBARSHELL))75cdf0e10cSrcweir SFX_IMPL_INTERFACE(BezierObjectBar, ::SfxShell, SdResId(STR_BEZIEROBJECTBARSHELL))
76cdf0e10cSrcweir {
77cdf0e10cSrcweir }
78cdf0e10cSrcweir 
79cdf0e10cSrcweir TYPEINIT1(BezierObjectBar, ::SfxShell);
80cdf0e10cSrcweir 
81cdf0e10cSrcweir /*************************************************************************
82cdf0e10cSrcweir |*
83cdf0e10cSrcweir |* Standard-Konstruktor
84cdf0e10cSrcweir |*
85cdf0e10cSrcweir \************************************************************************/
86cdf0e10cSrcweir 
BezierObjectBar(ViewShell * pSdViewShell,::sd::View * pSdView)87cdf0e10cSrcweir BezierObjectBar::BezierObjectBar(
88cdf0e10cSrcweir     ViewShell* pSdViewShell,
89cdf0e10cSrcweir     ::sd::View* pSdView)
90cdf0e10cSrcweir     : SfxShell(pSdViewShell->GetViewShell()),
91cdf0e10cSrcweir       mpView(pSdView),
92cdf0e10cSrcweir       mpViewSh(pSdViewShell)
93cdf0e10cSrcweir {
94cdf0e10cSrcweir 	DrawDocShell* pDocShell = mpViewSh->GetDocSh();
95cdf0e10cSrcweir 	SetPool(&pDocShell->GetPool());
96cdf0e10cSrcweir 	SetUndoManager(pDocShell->GetUndoManager());
97cdf0e10cSrcweir 	SetRepeatTarget(mpView);
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 	SetHelpId( SD_IF_SDDRAWBEZIEROBJECTBAR );
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
102cdf0e10cSrcweir /*************************************************************************
103cdf0e10cSrcweir |*
104cdf0e10cSrcweir |* Destruktor
105cdf0e10cSrcweir |*
106cdf0e10cSrcweir \************************************************************************/
107cdf0e10cSrcweir 
~BezierObjectBar()108cdf0e10cSrcweir BezierObjectBar::~BezierObjectBar()
109cdf0e10cSrcweir {
110cdf0e10cSrcweir 	SetRepeatTarget(NULL);
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 
114cdf0e10cSrcweir /*************************************************************************
115cdf0e10cSrcweir |*
116cdf0e10cSrcweir |* Status der Attribut-Items
117cdf0e10cSrcweir |*
118cdf0e10cSrcweir \************************************************************************/
119cdf0e10cSrcweir 
GetAttrState(SfxItemSet & rSet)120cdf0e10cSrcweir void BezierObjectBar::GetAttrState(SfxItemSet& rSet)
121cdf0e10cSrcweir {
122cdf0e10cSrcweir 	SfxItemSet aAttrSet( mpView->GetDoc()->GetPool() );
123cdf0e10cSrcweir 	mpView->GetAttributes( aAttrSet );
124cdf0e10cSrcweir 	rSet.Put(aAttrSet, sal_False); // <- sal_False, damit DontCare-Status uebernommen wird
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 	FunctionReference xFunc( mpViewSh->GetCurrentFunction() );
127cdf0e10cSrcweir 
128cdf0e10cSrcweir 	if(xFunc.is())
129cdf0e10cSrcweir 	{
130cdf0e10cSrcweir 		if(xFunc->ISA(FuSelection))
131cdf0e10cSrcweir 		{
132cdf0e10cSrcweir 			sal_uInt16 nEditMode = static_cast<FuSelection*>(xFunc.get())->GetEditMode();
133cdf0e10cSrcweir 			rSet.Put(SfxBoolItem(nEditMode, sal_True));
134cdf0e10cSrcweir 		}
135cdf0e10cSrcweir 		else if (xFunc->ISA(FuConstructBezierPolygon))
136cdf0e10cSrcweir 		{
137cdf0e10cSrcweir 			sal_uInt16 nEditMode = static_cast<FuConstructBezierPolygon*>(xFunc.get())->GetEditMode();
138cdf0e10cSrcweir 			rSet.Put(SfxBoolItem(nEditMode, sal_True));
139cdf0e10cSrcweir 		}
140cdf0e10cSrcweir 	}
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 	if(!mpView->IsMoveAllowed() || !mpView->IsResizeAllowed())
143cdf0e10cSrcweir 	{
144cdf0e10cSrcweir 		// #i77187# if object is move and/or size protected, do not allow point editing at all
145cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_MOVE);
146cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_INSERT);
147cdf0e10cSrcweir 
148cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_DELETE);
149cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_CUTLINE);
150cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_CONVERT);
151cdf0e10cSrcweir 
152cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_EDGE);
153cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_SMOOTH);
154cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_SYMMTR);
155cdf0e10cSrcweir 
156cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_CLOSE);
157cdf0e10cSrcweir 
158cdf0e10cSrcweir 		rSet.DisableItem(SID_BEZIER_ELIMINATE_POINTS);
159cdf0e10cSrcweir 	}
160cdf0e10cSrcweir 	else
161cdf0e10cSrcweir 	{
162cdf0e10cSrcweir 		IPolyPolygonEditorController* pIPPEC = 0;
163cdf0e10cSrcweir 		if( mpView->GetMarkedObjectList().GetMarkCount() )
164cdf0e10cSrcweir 			pIPPEC = mpView;
165cdf0e10cSrcweir 		else
166cdf0e10cSrcweir 			pIPPEC = dynamic_cast< IPolyPolygonEditorController* >( mpView->getSmartTags().getSelected().get() );
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 		if ( !pIPPEC || !pIPPEC->IsRipUpAtMarkedPointsPossible())
169cdf0e10cSrcweir 		{
170cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_CUTLINE);
171cdf0e10cSrcweir 		}
172cdf0e10cSrcweir 		if (!pIPPEC || !pIPPEC->IsDeleteMarkedPointsPossible())
173cdf0e10cSrcweir 		{
174cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_DELETE);
175cdf0e10cSrcweir 		}
176cdf0e10cSrcweir 		if (!pIPPEC || !pIPPEC->IsSetMarkedSegmentsKindPossible())
177cdf0e10cSrcweir 		{
178cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_CONVERT);
179cdf0e10cSrcweir 		}
180cdf0e10cSrcweir 		else
181cdf0e10cSrcweir 		{
182cdf0e10cSrcweir 			SdrPathSegmentKind eSegm = pIPPEC->GetMarkedSegmentsKind();
183cdf0e10cSrcweir 			switch (eSegm)
184cdf0e10cSrcweir 			{
185cdf0e10cSrcweir 				case SDRPATHSEGMENT_DONTCARE: rSet.InvalidateItem(SID_BEZIER_CONVERT); break;
186cdf0e10cSrcweir 				case SDRPATHSEGMENT_LINE    : rSet.Put(SfxBoolItem(SID_BEZIER_CONVERT,sal_False)); break; // Button reingedrueckt = Kurve
187cdf0e10cSrcweir 				case SDRPATHSEGMENT_CURVE   : rSet.Put(SfxBoolItem(SID_BEZIER_CONVERT,sal_True));  break;
188cdf0e10cSrcweir 				default: break;
189cdf0e10cSrcweir 			}
190cdf0e10cSrcweir 		}
191cdf0e10cSrcweir 		if (!pIPPEC || !pIPPEC->IsSetMarkedPointsSmoothPossible())
192cdf0e10cSrcweir 		{
193cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_EDGE);
194cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_SMOOTH);
195cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_SYMMTR);
196cdf0e10cSrcweir 		}
197cdf0e10cSrcweir 		else
198cdf0e10cSrcweir 		{
199cdf0e10cSrcweir 			SdrPathSmoothKind eSmooth = pIPPEC->GetMarkedPointsSmooth();
200cdf0e10cSrcweir 			switch (eSmooth)
201cdf0e10cSrcweir 			{
202cdf0e10cSrcweir 				case SDRPATHSMOOTH_DONTCARE  : break;
203cdf0e10cSrcweir 				case SDRPATHSMOOTH_ANGULAR   : rSet.Put(SfxBoolItem(SID_BEZIER_EDGE,  sal_True)); break;
204cdf0e10cSrcweir 				case SDRPATHSMOOTH_ASYMMETRIC: rSet.Put(SfxBoolItem(SID_BEZIER_SMOOTH,sal_True)); break;
205cdf0e10cSrcweir 				case SDRPATHSMOOTH_SYMMETRIC : rSet.Put(SfxBoolItem(SID_BEZIER_SYMMTR,sal_True)); break;
206cdf0e10cSrcweir 			}
207cdf0e10cSrcweir 		}
208cdf0e10cSrcweir 		if (!pIPPEC || !pIPPEC->IsOpenCloseMarkedObjectsPossible())
209cdf0e10cSrcweir 		{
210cdf0e10cSrcweir 			rSet.DisableItem(SID_BEZIER_CLOSE);
211cdf0e10cSrcweir 		}
212cdf0e10cSrcweir 		else
213cdf0e10cSrcweir 		{
214cdf0e10cSrcweir 			SdrObjClosedKind eClose = pIPPEC->GetMarkedObjectsClosedState();
215cdf0e10cSrcweir 			switch (eClose)
216cdf0e10cSrcweir 			{
217cdf0e10cSrcweir 				case SDROBJCLOSED_DONTCARE: rSet.InvalidateItem(SID_BEZIER_CLOSE); break;
218cdf0e10cSrcweir 				case SDROBJCLOSED_OPEN    : rSet.Put(SfxBoolItem(SID_BEZIER_CLOSE,sal_False)); break;
219cdf0e10cSrcweir 				case SDROBJCLOSED_CLOSED  : rSet.Put(SfxBoolItem(SID_BEZIER_CLOSE,sal_True)); break;
220cdf0e10cSrcweir 				default: break;
221cdf0e10cSrcweir 			}
222cdf0e10cSrcweir 		}
223cdf0e10cSrcweir 
224cdf0e10cSrcweir 		if(pIPPEC == mpView)
225cdf0e10cSrcweir 			rSet.Put(SfxBoolItem(SID_BEZIER_ELIMINATE_POINTS, mpView->IsEliminatePolyPoints()));
226cdf0e10cSrcweir 		else
227cdf0e10cSrcweir 			rSet.DisableItem( SID_BEZIER_ELIMINATE_POINTS ); // only works for views
228cdf0e10cSrcweir 	}
229cdf0e10cSrcweir }
230cdf0e10cSrcweir 
231cdf0e10cSrcweir 
232cdf0e10cSrcweir /*************************************************************************
233cdf0e10cSrcweir |*
234cdf0e10cSrcweir |* Bearbeitung der SfxRequests
235cdf0e10cSrcweir |*
236cdf0e10cSrcweir \************************************************************************/
237cdf0e10cSrcweir 
Execute(SfxRequest & rReq)238cdf0e10cSrcweir void BezierObjectBar::Execute(SfxRequest& rReq)
239cdf0e10cSrcweir {
240cdf0e10cSrcweir 	sal_uInt16 nSId = rReq.GetSlot();
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 	switch (nSId)
243cdf0e10cSrcweir 	{
244cdf0e10cSrcweir 		case SID_BEZIER_CUTLINE:
245cdf0e10cSrcweir 		case SID_BEZIER_CONVERT:
246cdf0e10cSrcweir 		case SID_BEZIER_DELETE:
247cdf0e10cSrcweir 		case SID_BEZIER_EDGE:
248cdf0e10cSrcweir 		case SID_BEZIER_SMOOTH:
249cdf0e10cSrcweir 		case SID_BEZIER_SYMMTR:
250cdf0e10cSrcweir 		case SID_BEZIER_CLOSE:
251cdf0e10cSrcweir 		{
252cdf0e10cSrcweir 			const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 			IPolyPolygonEditorController* pIPPEC = 0;
255cdf0e10cSrcweir 			if( rMarkList.GetMarkCount() )
256cdf0e10cSrcweir 				pIPPEC = mpView;
257cdf0e10cSrcweir 			else
258cdf0e10cSrcweir 				pIPPEC = dynamic_cast< IPolyPolygonEditorController* >( mpView->getSmartTags().getSelected().get() );
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 			if( pIPPEC && !mpView->IsAction())
261cdf0e10cSrcweir 			{
262cdf0e10cSrcweir 				switch (nSId)
263cdf0e10cSrcweir 				{
264cdf0e10cSrcweir 					case SID_BEZIER_DELETE:
265cdf0e10cSrcweir 						pIPPEC->DeleteMarkedPoints();
266cdf0e10cSrcweir 						break;
267cdf0e10cSrcweir 
268cdf0e10cSrcweir 					case SID_BEZIER_CUTLINE:
269cdf0e10cSrcweir 						pIPPEC->RipUpAtMarkedPoints();
270cdf0e10cSrcweir 						break;
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 					case SID_BEZIER_CONVERT:
273cdf0e10cSrcweir 					{
274cdf0e10cSrcweir 						pIPPEC->SetMarkedSegmentsKind(SDRPATHSEGMENT_TOGGLE);
275cdf0e10cSrcweir 						break;
276cdf0e10cSrcweir 					}
277cdf0e10cSrcweir 
278cdf0e10cSrcweir 					case SID_BEZIER_EDGE:
279cdf0e10cSrcweir 					case SID_BEZIER_SMOOTH:
280cdf0e10cSrcweir 					case SID_BEZIER_SYMMTR:
281cdf0e10cSrcweir 					{
282cdf0e10cSrcweir 						SdrPathSmoothKind eKind;
283cdf0e10cSrcweir 
284cdf0e10cSrcweir 						switch (nSId)
285cdf0e10cSrcweir 						{
286cdf0e10cSrcweir 							default:
287cdf0e10cSrcweir 							case SID_BEZIER_EDGE:   eKind = SDRPATHSMOOTH_ANGULAR; break;
288cdf0e10cSrcweir 							case SID_BEZIER_SMOOTH: eKind = SDRPATHSMOOTH_ASYMMETRIC; break;
289cdf0e10cSrcweir 							case SID_BEZIER_SYMMTR: eKind = SDRPATHSMOOTH_SYMMETRIC; break;
290cdf0e10cSrcweir 						}
291cdf0e10cSrcweir 
292cdf0e10cSrcweir 						pIPPEC->SetMarkedPointsSmooth(eKind);
293cdf0e10cSrcweir 						break;
294cdf0e10cSrcweir 					}
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 					case SID_BEZIER_CLOSE:
297cdf0e10cSrcweir 					{
298cdf0e10cSrcweir 						SdrPathObj* pPathObj = (SdrPathObj*) rMarkList.GetMark(0)->GetMarkedSdrObj();
299cdf0e10cSrcweir 						const bool bUndo = mpView->IsUndoEnabled();
300cdf0e10cSrcweir 						if( bUndo )
301cdf0e10cSrcweir 							mpView->BegUndo(String(SdResId(STR_UNDO_BEZCLOSE)));
302cdf0e10cSrcweir 
303cdf0e10cSrcweir 						mpView->UnmarkAllPoints();
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 						if( bUndo )
306cdf0e10cSrcweir 							mpView->AddUndo(mpView->GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPathObj));
307cdf0e10cSrcweir 
308cdf0e10cSrcweir 						pPathObj->ToggleClosed();
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 						if( bUndo )
311cdf0e10cSrcweir 							mpView->EndUndo();
312cdf0e10cSrcweir 						break;
313cdf0e10cSrcweir 					}
314cdf0e10cSrcweir 				}
315cdf0e10cSrcweir 			}
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 			if( (pIPPEC == mpView) && !mpView->AreObjectsMarked() )
318cdf0e10cSrcweir 				mpViewSh->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SFX_CALLMODE_ASYNCHRON);
319cdf0e10cSrcweir 
320cdf0e10cSrcweir 			rReq.Ignore();
321cdf0e10cSrcweir 		}
322cdf0e10cSrcweir 		break;
323cdf0e10cSrcweir 
324cdf0e10cSrcweir 		case SID_BEZIER_ELIMINATE_POINTS:
325cdf0e10cSrcweir 		{
326cdf0e10cSrcweir 			mpView->SetEliminatePolyPoints(!mpView->IsEliminatePolyPoints());
327cdf0e10cSrcweir 			Invalidate(SID_BEZIER_ELIMINATE_POINTS);
328cdf0e10cSrcweir 			rReq.Done();
329cdf0e10cSrcweir 		}
330cdf0e10cSrcweir 		break;
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 		case SID_BEZIER_MOVE:
333cdf0e10cSrcweir 		case SID_BEZIER_INSERT:
334cdf0e10cSrcweir 		{
335cdf0e10cSrcweir 			FunctionReference xFunc( mpViewSh->GetCurrentFunction() );
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 			if(xFunc.is())
338cdf0e10cSrcweir 			{
339cdf0e10cSrcweir 				if(xFunc->ISA(FuSelection))
340cdf0e10cSrcweir 				{
341cdf0e10cSrcweir 					static_cast<FuSelection*>(xFunc.get())->SetEditMode(rReq.GetSlot());
342cdf0e10cSrcweir 				}
343cdf0e10cSrcweir 				else if(xFunc->ISA(FuConstructBezierPolygon))
344cdf0e10cSrcweir 				{
345cdf0e10cSrcweir 					static_cast<FuConstructBezierPolygon*>(xFunc.get())->SetEditMode(rReq.GetSlot());
346cdf0e10cSrcweir 				}
347cdf0e10cSrcweir 			}
348cdf0e10cSrcweir 
349cdf0e10cSrcweir 			rReq.Ignore ();
350cdf0e10cSrcweir 		}
351cdf0e10cSrcweir 		break;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir 		default:
354cdf0e10cSrcweir 		break;
355cdf0e10cSrcweir 	}
356cdf0e10cSrcweir 
357cdf0e10cSrcweir 	Invalidate();
358cdf0e10cSrcweir }
359cdf0e10cSrcweir 
360cdf0e10cSrcweir 
361cdf0e10cSrcweir } // end of namespace sd
362