xref: /aoo42x/main/sd/source/ui/inc/ViewShell.hxx (revision 7a32b0c8)
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 #ifndef SD_VIEW_SHELL_HXX
25 #define SD_VIEW_SHELL_HXX
26 
27 #include <rtl/ref.hxx>
28 
29 #include <vcl/field.hxx>
30 #include <sfx2/viewsh.hxx>
31 #include <vcl/field.hxx>
32 #include <vcl/prntypes.hxx>
33 #include <svtools/transfer.hxx>
34 #include <comphelper/implementationreference.hxx>
35 #include "glob.hxx"
36 #include "pres.hxx"
37 #include "cfgids.hxx"
38 #include "View.hxx"
39 #include "sddllapi.h"
40 
41 #include <com/sun/star/drawing/XDrawSubController.hpp>
42 #include <memory>
43 #include <boost/shared_ptr.hpp>
44 
45 class SdPage;
46 class SvxRuler;
47 class SdrOle2Obj;		// fuer die, die Teile von SVDRAW rausdefiniert haben
48 class ScrollBarBox;
49 class SdDrawDocument;
50 class ScrollBar;
51 class FmFormShell;
52 class SdOptionsPrintItem;
53 class MultiSelection;
54 
55 extern const String aEmptyStr;
56 
57 namespace com { namespace sun { namespace star {
58 namespace embed {
59     class XEmbeddedObject;
60 }}}}
61 
62 namespace css = ::com::sun::star;
63 
64 namespace sd {
65 
66 class Client;
67 class DrawDocShell;
68 class DrawSubController;
69 class FrameView;
70 class FuPoor;
71 class FuSearch;
72 class SlideShow;
73 class LayerTabBar;
74 class View;
75 class ViewShellBase;
76 class ViewTabBar;
77 class Window;
78 class WindowUpdater;
79 class ZoomList;
80 
81 #undef OUTPUT_DRAWMODE_COLOR
82 #undef OUTPUT_DRAWMODE_CONTRAST
83 
84 /** Base class of the stacked shell hierarchy.
85 
86     <p>Despite its name this class is not a descendant of SfxViewShell
87     but of SfxShell.  Its name expresses the fact that it acts like a
88     view shell.  Beeing a stacked shell rather then being an actual view shell
89     there can be several instances of this class that
90     <ul>
91     <li>all are based on the same view shell and thus show the same
92     document and share common view functionality and</li>
93     <li>are all visible at the same time and live in the same
94     frame.</li>
95     <ul></p>
96 
97     <p>This class replaces the former ViewShell class.</p>
98 */
99 class ViewShell
100     : public SfxShell
101 {
102 public:
103     enum ShellType {
104         ST_NONE,
105         ST_DRAW,         // The Draw application.
106         ST_IMPRESS,      // Main view of the Impress application.
107         ST_NOTES,
108         ST_HANDOUT,
109         ST_OUTLINE,
110         ST_SLIDE_SORTER,
111         ST_PRESENTATION,
112         ST_SIDEBAR
113     };
114     static const int MAX_HSPLIT_CNT = 1;
115     static const int MAX_VSPLIT_CNT = 1;
116     static const int MIN_SCROLLBAR_SIZE	= 50;
117 
118     static const sal_uLong OUTPUT_DRAWMODE_COLOR = DRAWMODE_DEFAULT;
119     static const sal_uLong OUTPUT_DRAWMODE_GRAYSCALE
120         = DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL
121         | DRAWMODE_BLACKTEXT | DRAWMODE_GRAYBITMAP
122         | DRAWMODE_GRAYGRADIENT;
123     static const int  OUTPUT_DRAWMODE_BLACKWHITE
124         = DRAWMODE_BLACKLINE | DRAWMODE_BLACKTEXT
125         | DRAWMODE_WHITEFILL | DRAWMODE_GRAYBITMAP
126         | DRAWMODE_WHITEGRADIENT;
127     static const int OUTPUT_DRAWMODE_CONTRAST
128         = DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL
129         | DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT;
130 
131     TYPEINFO();
132 
133     ViewShell (
134         SfxViewFrame *pFrame,
135         ::Window* pParentWindow,
136         ViewShellBase& rViewShellBase,
137         bool bAllowCenter = true);
138     virtual ~ViewShell (void);
139 
140     /** The Init method has to be called from the outside directly
141         after a new object of this class has been created.  It can be
142         used for that part of the initialisation that can be run only
143         after the creation of the new object is finished.  This
144         includes registration as listener at event broadcasters.
145 
146         Derived classes should call this method at the head of their
147         Init() methods.
148         @param bIsMainViewShell
149             This flag tells the Init() method whether the new ViewShell will
150             be the main view shell.
151     */
152     virtual void Init (bool bIsMainViewShell);
153 
154     /** The Exit() method has to be called before the destructor so that the
155         view shell is still a valid object and can safely call methods that
156         rely on that.
157     */
158     virtual void Exit (void);
159 
160 	void Cancel();
161 
162     /** Return the window that is the parent of all controls of this view
163         shell.  This may or may not be the window of the frame.
164     */
165     inline ::Window* GetParentWindow (void) const;
166 
167 	inline ::sd::View* GetView (void) const;
168 	inline SdrView* GetDrawView (void) const;
169 	SD_DLLPUBLIC DrawDocShell* GetDocSh (void) const;
170 
171 	SdDrawDocument*  GetDoc (void) const;
172 
173     SD_DLLPUBLIC SfxViewFrame* GetViewFrame (void) const;
174 
175     /** The active window is usually the mpContentWindow.  When there is a
176         show running then the active window is a ShowWindow.
177     */
178 	::sd::Window* GetActiveWindow (void) const;
179 
180     /** Set the active window.  When the shell is displayed in the center
181         pane then the window of the ViewShellBase is also set to the given
182         window.
183     */
184 	void SetActiveWindow (::sd::Window* pWindow);
185 
186     /** Return the rectangle that encloses all windows of the view.  That
187         excludes the controls in the frame like rulers, scroll bars, tab
188         bar, and buttons.
189         @return
190             The rectangle is returned in screen coordinates, i.e. pixel
191             values relative to the upper left corner of the screen?.
192     */
193 	const Rectangle& GetAllWindowRect (void);
194 
195 	// Mouse- & Key-Events
196 	virtual void PrePaint();
197 	virtual void Paint (const Rectangle& rRect, ::sd::Window* pWin);
198 	virtual sal_Bool KeyInput(const KeyEvent& rKEvt, ::sd::Window* pWin);
199 	virtual void MouseMove(const MouseEvent& rMEvt, ::sd::Window* pWin);
200 	virtual void MouseButtonUp(const MouseEvent& rMEvt, ::sd::Window* pWin);
201 	virtual void MouseButtonDown(const MouseEvent& rMEvt, ::sd::Window* pWin);
202 	virtual void Command(const CommandEvent& rCEvt, ::sd::Window* pWin);
203 	virtual sal_Bool RequestHelp( const HelpEvent& rEvt, ::sd::Window* pWin );
204     virtual long Notify( NotifyEvent& rNEvt, ::sd::Window* pWin );
205 
206     virtual bool HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWin);
207 
208 	virtual void Draw(OutputDevice &rDev, const Region &rReg);
209 
210 	virtual void SetUIUnit(FieldUnit eUnit);
211 	virtual void SetDefTabHRuler( sal_uInt16 nDefTab );
212 
213     sal_Bool HasRuler (void);
214 	void SetRuler(sal_Bool bRuler);
215 
216     /** Set internal values of all scroll bars that determine thumb size and
217         position.  The external values like size and position of the scroll
218         bar controls are not modified.
219     */
220 	virtual void UpdateScrollBars (void);
221 	void	Scroll(long nX, long nY);
222 	void	ScrollLines(long nX, long nY);
223 	virtual void	SetZoom(long nZoom);
224 	virtual void	SetZoomRect(const Rectangle& rZoomRect);
225 	void	InitWindows(const Point& rViewOrigin, const Size& rViewSize,
226 						const Point& rWinPos, sal_Bool bUpdate = sal_False);
227 	void	InvalidateWindows();
228     /** This method is still used by the OutlineViewShell to update the
229         model according to the content of the outline view.  This in turn
230         updates the previews in the slide sorter.
231     */
232  	virtual void UpdatePreview (SdPage* pPage, sal_Bool bInit = sal_False);
233 
234 	void    DrawMarkRect(const Rectangle& rRect) const;
235 
236 	void	ExecReq( SfxRequest &rReq );
237 
238 	ZoomList* GetZoomList (void);
239 
240 	FrameView* GetFrameView (void);
241     /** Setting a frame view triggers ReadFrameViewData() for the new
242         frame.
243         @param pFrameView
244             The new frame view that replaces the old one.
245     */
246     void SetFrameView (FrameView* pFrameView);
247 	virtual void  ReadFrameViewData(FrameView* pView);
248 	virtual void  WriteFrameViewData();
249 	virtual void  WriteUserData(String& rString);
250 	virtual void  ReadUserData(const String& rString);
251 
252 	virtual sal_Bool  ActivateObject(SdrOle2Obj* pObj, long nVerb);
253 
254 	/** @returns
255 			current or selected page or 0. This method
256 			will fail in master page mode.
257 
258 		@deprecated, please use getCurrentPage();
259 	*/
260 	virtual SdPage*	GetActualPage() = 0;
261 
262 	/** @returns
263 			current or selected page or 0.
264 	*/
265 	virtual SdPage* getCurrentPage() const = 0;
266 
267 	FunctionReference GetOldFunction() const { return mxOldFunction; }
268 	bool HasOldFunction() const { return mxOldFunction.is(); }
269 	FunctionReference GetCurrentFunction() const { return mxCurrentFunction; }
270 	bool HasCurrentFunction( sal_uInt16 nSID ) { return mxCurrentFunction.is() && (mxCurrentFunction->GetSlotID() == nSID ); }
271 	bool HasCurrentFunction() { return mxCurrentFunction.is(); }
272 
273     void SetCurrentFunction(const FunctionReference& xFunction);
274     void SetOldFunction(const FunctionReference& xFunction);
275 	void DeactivateCurrentFunction( bool bPermanent = false );
276 
277 	void	SetPageSizeAndBorder(PageKind ePageKind, const Size& rNewSize,
278 							long nLeft, long nRight, long nUpper, long nLower,
279 							sal_Bool bScaleAll, Orientation eOrient, sal_uInt16 nPaperBin,
280 							sal_Bool bBackgroundFullSize );
281 
282 	void	SetStartShowWithDialog( sal_Bool bIn = sal_True ) { mbStartShowWithDialog = bIn; }
283 	sal_Bool	IsStartShowWithDialog() const { return mbStartShowWithDialog; }
284 
285 	sal_uInt16 GetPrintedHandoutPageNum (void) const { return mnPrintedHandoutPageNum; }
286 	void SetPrintedHandoutPageNum (sal_uInt16 nPageNumber) {mnPrintedHandoutPageNum=nPageNumber; }
287 
288     sal_uInt16 GetPrintedHandoutPageCount(void) const { return mnPrintedHandoutPageCount; }
289     void SetPrintedHandoutPageCount (sal_uInt16 nPageCount) {mnPrintedHandoutPageCount=nPageCount; }
290 
291 	virtual sal_uInt16 PrepareClose( sal_Bool bUI = sal_True, sal_Bool bForBrowsing = sal_False );
292 
293 	void GetMenuState(SfxItemSet& rSet);
294 
295 	virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt, DropTargetHelper& rTargetHelper,
296                                  ::sd::Window* pTargetWindow, sal_uInt16 nPage, sal_uInt16 nLayer );
297 	virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt, DropTargetHelper& rTargetHelper,
298                                   ::sd::Window* pTargetWindow, sal_uInt16 nPage, sal_uInt16 nLayer );
299 
300     virtual void WriteUserDataSequence ( ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool bBrowse = sal_False );
301     virtual void ReadUserDataSequence ( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool bBrowse = sal_False );
302 
303 	/** this method is called when the visible area of the view from this viewshell is changed */
304 	virtual void VisAreaChanged(const Rectangle& rRect);
305 
306     /** Create an accessible object representing the specified window.
307 	    Overload this method to provide view mode specific objects.  The
308 	    default implementation returns an empty reference.
309         @param pWindow
310             Make the document displayed in this window accessible.
311         @return
312             This default implementation returns an empty reference.
313     */
314     virtual ::com::sun::star::uno::Reference<
315         ::com::sun::star::accessibility::XAccessible>
316         CreateAccessibleDocumentView (::sd::Window* pWindow);
317 
318 	void SetWinViewPos(const Point& rWinPos, bool bUpdate);
319 	Point GetWinViewPos() const;
320 	Point GetViewOrigin() const;
321 
322     /** Return the window updater of this view shell.
323         @return
324             In rare circumstances the returned pointer may be <null/>,
325             i.e. when no memory is available anymore.
326     */
327     ::sd::WindowUpdater* GetWindowUpdater (void) const;
328 
329     /** Return the border that is drawn arround the actual document view.
330         The border contains typically rulers and scroll bars.
331         @param bOuterResize
332             When this flag is <TRUE/> then the border is used for an
333             OuterResizePixel(), i.e. there is a given window size and the
334             border elements are placed inside so that the document view has
335             the given window size minus the border.
336             When the flag is <FALSE/> then the border is used for an
337             InnerResizePixel(), i.e. the document view has a given size and
338             the border is placed outside.  In this scenario the parent
339             window has the size of the document view plus the border.
340     */
341     SvBorder GetBorder (bool bOuterResize);
342 
343     /** Notify the view shell that its parent window has been resized.
344         The ViewShell places and resizes its UI elements accordingly.
345         The new size can be obtained from the parent window.
346     */
347     virtual void Resize (void);
348 
349     /** Set the position and size of the area which contains the GUI
350         elements like rulers, sliders, and buttons as well as the document
351         view.  Both size and position are expected to be in pixel
352         coordinates.  The positions and sizes of the mentioned GUI elements
353         are updated as well.
354 
355         <p> This method is implemented by first setting copying the given
356         values to internal variables and then calling the
357         <type>ArrangeGUIElements</type> method which performs the actual
358         work of sizeing and arranging the UI elements accordingly.</p>
359         @param rPos
360             The position of the enclosing window relative to the document
361             window.  This is only interesting if a Draw/Impress document
362             view is embedded as OLE object into another document view.  For
363             normal documents this position is (0,0).
364         @param rSize
365             The new size in pixel.
366     */
367     // This is to be replaced by Resize.
368     //	virtual void AdjustPosSizePixel(const Point &rPos, const Size &rSize);
369 
370     /** Set position and size of the GUI elements that are controllerd by
371         the view shell like rulers and scroll bars as well as the actual
372         document view according to the position and size that were given
373         with the last Resize() call.
374     */
375     virtual void ArrangeGUIElements (void);
376 
377     //	virtual void OuterResizePixel(const Point &rPos, const Size &rSize);
378     //	virtual void InnerResizePixel(const Point &rPos, const Size &rSize);
379 
380     ViewShellBase& GetViewShellBase (void) const;
381 
382     /** Return <TRUE/> when the called view shell is the main sub shell of
383         its ViewShellBase object, i.e. is display in the center pane.  This
384         convenience function is equivalent to comparing the this pointer to
385         the result of ViewShellBase::GetViewShell(PT_CENTER).
386     */
387     bool IsMainViewShell (void) const;
388 
389     /** Set or reset the flag that indicates whether the called shell is the
390         one displayed in the center pane.  By default this flag is set to
391         <FALSE/>.  For the main view shell it thus has to be set to <TRUE/>.
392     */
393     void SetIsMainViewShell (bool bIsMainViewShell);
394 
395     /** Return a sub controller that implements the view shell specific
396         part of the DrawController.
397     */
398     virtual css::uno::Reference<css::drawing::XDrawSubController> CreateSubController (void) = 0;
399 
400     /** Return the type of the shell.
401     */
402     virtual ShellType GetShellType (void) const;
403 
404     /** This method is more or less an alias to Deactivate().  It is called
405         before an object of this class is taken from the stack of view
406         shells.
407 
408         <p>When this method is not called before a view shell is taken from
409         a stack then the Deactivate() call from the SFX as a response to
410         RemoveSubShell() comes to late when the view shell is not on the
411         stack anymore.</p>
412     */
413     virtual void Shutdown (void);
414 
415     /** This function is called from the underlying ViewShellBase
416         object to handle a verb execution request.
417     */
418     virtual ErrCode DoVerb (long nVerb);
419 
420     virtual void UIActivating( SfxInPlaceClient* );
421     virtual void UIDeactivated( SfxInPlaceClient* );
422 
423     /** Show controls of the UI or hide them, depending on the given flag.
424         As a result the border is adapted.
425     */
426 	virtual void ShowUIControls (bool bVisible = true);
427 	sal_Bool IsPageFlipMode(void) const;
428 
429     /** Set the given window as new parent window.  This is not possible for
430         all views, so the return value tells the caller if the relocation
431         was successfull.
432     */
433     virtual bool RelocateToParentWindow (::Window* pParentWindow);
434 
435     /** Depending on the given request create a new page or duplicate an
436         existing one.  A new page is created behind the given slide.
437         @param rRequest
438             The request as passed to an Execute() method.  Its arguments are
439             evaluated.  Its slot id determines whether to create or
440             duplicate a slide.
441         @param pPage
442             This page is either duplicated or becomes the predecessor of the
443             new slide.  If NULL a duplication request is ignored.  A new
444             slide is inserted as first slide.
445         @param nInsertPosition
446             When -1 (the default) then insert after pPage.  Otherwise insert
447             before the given index (of a standard page).
448         @return
449             The new slide is returned.  If for some reason a new page can
450             not be created then NULL is returned.
451     */
452     virtual SdPage* CreateOrDuplicatePage (
453         SfxRequest& rRequest,
454         PageKind ePageKind,
455         SdPage* pPage,
456         const sal_Int32 nInsertPosition = -1);
457 
458 
459     class Implementation;
460 
461 protected:
462 	/** must be called in the beginning of each subclass d'tor.
463 		disposes and clears both current and old function. */
464 	void DisposeFunctions();
465 
466     friend class ViewShellBase;
467 
468     /** Window inside the rulers and scroll bars that shows a view of the
469         document.
470     */
471 
472     ::boost::shared_ptr<sd::Window> mpContentWindow;
473 
474     /// Horizontal scroll bar for the current slide is displayed when needed.
475     ::boost::shared_ptr<ScrollBar> mpHorizontalScrollBar;
476     /// Vertical scroll bar for whole document is always visible.
477     ::boost::shared_ptr<ScrollBar> mpVerticalScrollBar;
478 	/// Horizontal ruler is not shown by default.
479 	::std::auto_ptr<SvxRuler> mpHorizontalRuler;
480     /// Vertical ruler is not shown by default.
481 	::std::auto_ptr<SvxRuler> mpVerticalRuler;
482     /// Filler of the little square enclosed by the two scroll bars.
483     ::boost::shared_ptr<ScrollBarBox> mpScrollBarBox;
484     /// Layer tab bar.
485     ::std::auto_ptr<LayerTabBar> mpLayerTabBar;
486 
487     /// This flag controls whether the rulers are visible.
488 	bool mbHasRulers;
489 
490 	/// The active window.
491 	::sd::Window* mpActiveWindow;
492 	::sd::View* mpView;
493 	FrameView*	mpFrameView;
494 
495 	FunctionReference	mxCurrentFunction;
496 	FunctionReference	mxOldFunction;
497 	ZoomList*	mpZoomList;
498 
499 	Point		maViewPos;
500 	Size		maViewSize;
501 	Size		maScrBarWH;
502 
503 	sal_Bool		mbCenterAllowed; 		  // wird an Fenster weitergegeben
504 
505 	sal_Bool		mbStartShowWithDialog;	// Praesentation wurde ueber Dialog gestartet
506 	sal_uInt16		mnPrintedHandoutPageNum; // Page number of the handout page that is to be printed.
507     sal_uInt16      mnPrintedHandoutPageCount; // Page count of the handout pages that are to be printed.
508 
509     //af	sal_Bool		bPrintDirectSelected;		// Print only selected objects in direct print
510 	//afString		sPageRange;					// pagerange if selected objects in direct print
511 
512     /** Area covered by all windows, i.e. the area of the parent window
513         without the controls at the borders like rulers, scroll bars, tab
514         bar, buttons.
515         This rectangle may be set in window coordinates (i.e. pixel values
516         relative to the parent window).  It is transformed by every call to
517         GetAllWindowRectangle() into screen coordinates (relative to the
518         upper left corner of the screen.
519     */
520     Rectangle maAllWindowRectangle;
521 
522     /// The type of the shell.  Returned by GetShellType().
523     ShellType meShellType;
524 
525     ::std::auto_ptr<Implementation> mpImpl;
526 
527 	// #96090# Support methods for centralized UNDO/REDO
528 	virtual ::svl::IUndoManager* ImpGetUndoManager (void) const;
529 	void ImpGetUndoStrings(SfxItemSet &rSet) const;
530 	void ImpGetRedoStrings(SfxItemSet &rSet) const;
531 	void ImpSidUndo(sal_Bool bDrawViewShell, SfxRequest& rReq);
532 	void ImpSidRedo(sal_Bool bDrawViewShell, SfxRequest& rReq);
533 
534 	DECL_LINK( HScrollHdl, ScrollBar * );
535 	DECL_LINK( VScrollHdl, ScrollBar * );
536 
537 	// virt. Scroll-Handler, hier koennen sich abgeleitete Klassen einklinken
538 	virtual long VirtHScrollHdl(ScrollBar* pHScroll);
539 	virtual long VirtVScrollHdl(ScrollBar* pVScroll);
540 
541 	// virtuelle Funktionen fuer Lineal-Handling
542 	virtual SvxRuler* CreateHRuler(::sd::Window* pWin, sal_Bool bIsFirst);
543 	virtual SvxRuler* CreateVRuler(::sd::Window* pWin);
544 	virtual void UpdateHRuler();
545 	virtual void UpdateVRuler();
546 
547 	// Zeiger auf ein zusaetzliches Control im horizontalen ScrollBar
548 	// abgeleiteter Klassen (z.B. ein TabBar) zurueckgeben
549 	virtual long GetHCtrlWidth();
550 
551 	virtual void Activate(sal_Bool IsMDIActivate);
552 	virtual void Deactivate(sal_Bool IsMDIActivate);
553 
554 	virtual void SetZoomFactor( const Fraction &rZoomX,
555 								const Fraction &rZoomY );
556 
557 private:
558     ::Window* mpParentWindow;
559     /** This window updater is used to keep all relevant windows up to date
560         with reference to the digit langugage used to display digits in text
561         shapes.
562     */
563     ::std::auto_ptr< ::sd::WindowUpdater> mpWindowUpdater;
564 
565     /** Code common to all constructors.  It generally is a bad idea
566         to call this function from outside a constructor.
567     */
568 	void construct (void);
569 
570     DECL_LINK(FrameWindowEventListener, VclSimpleEvent*);
571 
572     /** Create the rulers.
573     */
574     void SetupRulers (void);
575 };
576 
577 
578 
579 
580 ::Window* ViewShell::GetParentWindow (void) const
581 {
582     return mpParentWindow;
583 }
584 
585 ::sd::View* ViewShell::GetView (void) const
586 {
587     return mpView;
588 }
589 
590 SdrView* ViewShell::GetDrawView (void) const
591 {
592     return static_cast<SdrView*>(mpView);
593 }
594 
595 } // end of namespace sd
596 
597 #endif
598