grlayout.h

Go to the documentation of this file.
00001 /**
00002  * \file grlayout.h <mi32/grlayout.h>
00003  * \brief GRAPHICLAYOUT class
00004  *
00005  * This class was designed for the rewrite of legends.  It should be generic enough to use 
00006  * for other things too (perhaps the rewrite for forms?)
00007  *
00008  * \if NODOC
00009  * $Id: grlayout.h_v 1.32 2004/04/01 20:22:30 dwilliss Exp $
00010  *
00011  * $Log: grlayout.h_v $
00012  * Revision 1.32  2004/04/01 20:22:30  dwilliss
00013  * Change how NAMEDTEXTSTYLES are stored to use std::vector
00014  *
00015  * Revision 1.31  2004/02/12 22:05:12  dwilliss
00016  * Deprecate old MGD
00017  *
00018  * Revision 1.30  2003/09/15 19:31:46  scowan
00019  * *** empty log message ***
00020  *
00021  * Revision 1.29  2003/09/15 13:49:56  fileserver!dwilliss
00022  * Doxygen
00023  *
00024  * Revision 1.28  2003/06/12 20:25:48  scowan
00025  * nc.
00026  *
00027  * Revision 1.27  2002/12/11 16:29:22  scowan
00028  * get text styles now returns void.
00029  *
00030  * Revision 1.26  2002/05/14 14:23:39  dwilliss
00031  * UsesTransparency now takes a MGD::CONTEXT
00032  *
00033  * Revision 1.25  2002/05/06 22:44:04  dwilliss
00034  * Added group settings for planned addition of item grouping
00035  *
00036  * Revision 1.24  2002/04/22 16:50:11  dwilliss
00037  * Added UsesTransparency method
00038  *
00039  * Revision 1.23  2002/03/15 15:11:56  dwilliss
00040  * *** empty log message ***
00041  *
00042  * Revision 1.22  2002/03/08 17:40:02  dwilliss
00043  * Had to change methods to Get/Set styles to use std::vector instead of
00044  * SIMPLE_ARRAY.  TEXTSTYLE now prohibits memset amd memcpy
00045  *
00046  * Revision 1.21  2002/03/08 15:27:57  dwilliss
00047  * Structure name change for new MGD
00048  *
00049  * Revision 1.20  2001/12/28 21:34:06  mju
00050  * SerialWrite now const.
00051  *
00052  * Revision 1.19  2001/10/01 20:32:59  dwilliss
00053  * Added a flag to TabStopMove to not sort tabs after moving
00054  * Made SortTabStops public
00055  *
00056  * Revision 1.18  2001/10/01 20:12:58  dwilliss
00057  * Added a method to remove all tab stops from a named text style
00058  *
00059  * Revision 1.17  2001/02/28 21:32:35  dwilliss
00060  * Added new method to items
00061  *
00062  * Revision 1.16  2000/12/27 17:37:08  dwilliss
00063  * NAMEDTEXTSTYLE members are all private now with methods to access
00064  *
00065  * Revision 1.15  2000/12/27 14:52:41  dwilliss
00066  * I guess scowan already fixed it.
00067  *
00068  * Revision 1.14  2000/12/27 14:43:54  scowan
00069  * Fixed MAC errors.
00070  *
00071  * Revision 1.13  2000/12/26 20:41:25  dwilliss
00072  * Changes to text blocks
00073  *
00074  * Revision 1.12  2000/12/18 20:53:53  dwilliss
00075  * Added new SetTextStyles method
00076  *
00077  * Revision 1.11  2000/10/13 15:58:30  dwilliss
00078  * Must use "friend class NAME", not "friend NAME"
00079  *
00080  * Revision 1.10  2000/09/26 20:26:17  dwilliss
00081  * *** empty log message ***
00082  *
00083  * Revision 1.9  2000/09/20 21:47:34  dwilliss
00084  * *** empty log message ***
00085  *
00086  * Revision 1.8  2000/09/15 17:19:54  dwilliss
00087  * Changed all coordinate and size things to doubles
00088  *
00089  * Revision 1.7  2000/09/05 22:37:58  dwilliss
00090  * Changed text block's SetString to take a const MISTRING instead of UNICODE*
00091  *
00092  * Revision 1.6  2000/08/23 14:26:31  dwilliss
00093  * Made some method parameters ocnst
00094  *                             const
00095  *
00096  * Revision 1.5  2000/08/22 22:16:42  dwilliss
00097  * *** empty log message ***
00098  *
00099  * Revision 1.4  2000/08/21 20:45:52  dwilliss
00100  * API somewhat finalized now
00101  *
00102  * Revision 1.3  2000/08/11 16:58:17  dwilliss
00103  * Still in development
00104  *
00105  * Revision 1.2  2000/07/17 13:58:04  dwilliss
00106  * *** empty log message ***
00107  *
00108  * Revision 1.1  2000/07/07 21:41:28  dwilliss
00109  * Initial revision
00110  *
00111  * \endif
00112  */
00113 
00114 //! Design goal...
00115 //!
00116 //!
00117 //!   Need two classes.   the GRAPHICLAYOUT class keeps track of positions
00118 //! of things and calls generic drawing methods but know nothing about X
00119 //!
00120 //!   Need another class which takes a pointer or reference to a 
00121 //! GRAPHICLAYOUT and handles all the user input associated with
00122 //! editing one.
00123 //! GRAPHICLAYOUT should be SERIALIZABLE
00124 //! For simplicity, everything's vertical position is recorded as an offset
00125 //! from either...
00126 //!      a) the item above it
00127 //!      b) a guide
00128 //! All horizontal positions are recorded as an offset from a guide
00129 //!      If I end up using this for the rewrite of forms later, this may
00130 //!      have to be extended to allow things to be tacked onto the end
00131 //!      of other things at the same "Y" position.  Shouldn't be too hard.
00132 //!
00133 //!   Sizes and distances are defined as "points at layout map scale"
00134 //! If drawing to something where "layout scale" is meaningless, treat them as pixels.
00135 
00136 
00137 
00138 #ifndef INC_MI32_GRLAYOUT_H
00139 #define INC_MI32_GRLAYOUT_H
00140    
00141 #ifndef INC_MI32_SIMPLEAR_H
00142 #include <mi32/simplear.h>
00143 #endif
00144 
00145 #ifndef INC_MI32_MILIST_H
00146 #include <mi32/milist.h>
00147 #endif
00148 
00149 #ifndef INC_MI32_SERIALIZ_H
00150 #include <mi32/serializ.h>
00151 #endif
00152 
00153 #ifndef INC_MI32_MGD_H
00154 #include <mi32/mcb.h>
00155 #endif
00156 
00157 #ifndef INC_MI32_OBSERVER_H
00158 #include <mi32/observer.h>
00159 #endif
00160 
00161 #ifndef INC_MI32_MGD2_H
00162 #include <mi32/mgd2.h>
00163 #endif
00164 
00165 #ifndef INC_MI32_RECT_H
00166 #include <mi32/rect.h>
00167 #endif
00168 
00169 #ifndef WIN32_NATIVE
00170 #include <mi32/xdefns.h>
00171 #endif
00172 
00173 #ifndef _VECTOR_
00174 #include <vector> //! std::vector
00175 #endif
00176 
00177 struct MxPromptCallbackStruct;
00178 struct UNITCONV;
00179 class MIDIALOG;
00180 
00181 
00182 class GRAPHICLAYOUT : public SERIALIZABLE {
00183    public:
00184 
00185    class ITEM;
00186    typedef MILIST<ITEM*> ITEMLIST;
00187    typedef ITEMLIST::ITERATOR ITERATOR;
00188    typedef ITEMLIST::CONST_ITERATOR CONST_ITERATOR;
00189 
00190    //! This is a base class that any class wishing to be notified
00191    //! of changes to a GRAPHICLAYOUT may derive itself from.
00192    
00193    class OBSERVER : public OBSERVER_BASE {
00194       public:
00195          OBSERVER (
00196             GRAPHICLAYOUT& layout
00197             ) :
00198             OBSERVER_BASE(layout.m_Observers)
00199             {
00200             }
00201 
00202          virtual ~OBSERVER (
00203             ) {
00204             }
00205 
00206          //! Called whenever something causes us to need to redraw.
00207          virtual void OnRedraw (
00208             ) {
00209             return;
00210             }
00211       };
00212 
00213    class OBSERVERMANAGER : public SUBJECT<OBSERVER> {
00214       public:
00215          //! Call redraw methods
00216          void Redraw (
00217             );
00218       
00219       };
00220 
00221    class NAMEDTEXTSTYLE : public TEXTSTYLE {
00222       public:
00223          struct TABSTOP {
00224             enum TYPE {
00225                TYPE_Left = 0,
00226                TYPE_Right,
00227                TYPE_Center,
00228                TYPE_Decimal
00229                };
00230 
00231             INT32 position;
00232             UINT8 type;    //!< Would make an enum, but sizeof() important.
00233             char padChar;  //!< ie, ' ', '.', '-', etc...
00234             char spare1;
00235             char spare2;   //!< so sizeof(TABSTOP) is divisable by sizeof(INT32)
00236             };
00237 
00238          NAMEDTEXTSTYLE();
00239          NAMEDTEXTSTYLE(const NAMEDTEXTSTYLE&);
00240          ~NAMEDTEXTSTYLE();
00241 
00242          NAMEDTEXTSTYLE& operator= (
00243             const NAMEDTEXTSTYLE& rhs
00244             );
00245 
00246          bool operator== (
00247             const NAMEDTEXTSTYLE& rhs
00248             ) const {
00249             return (CompareIgnoringName(rhs) && ucstrcmp(m_name, rhs.m_name) == 0);
00250             }
00251 
00252 
00253          bool operator!= (
00254             const NAMEDTEXTSTYLE& rhs
00255             ) const {
00256             return (!(*this == rhs));
00257             }
00258 /*
00259          void CompareBaseClass (
00260             const TEXTSTYLE* style
00261             ) {
00262             if (style != 0)   *(static_cast<TEXTSTYLE*>(this)) = *style;
00263             }
00264             */
00265 
00266          //! Compares this style to another one, ignoring the name.
00267          //! Returns true if the two are the same.
00268          bool CompareIgnoringName (
00269             const NAMEDTEXTSTYLE& rhs
00270             ) const;
00271 
00272          //! Frees the tab stop information.  Necessary because we store have to store these
00273          //! things in a plain old array which we realloc.
00274 
00275          void FreeData() { 
00276             MmFree(m_TabStops); 
00277             m_NumTabStops = 0;
00278             }
00279 
00280          const UNICODE* GetName (
00281             ) const {
00282             return (m_name);
00283             }
00284 
00285          INT32 GetNumTabStops (
00286             ) const {
00287             return (m_NumTabStops);
00288             }
00289 
00290          const TABSTOP& GetTabStop (
00291             INT32 num
00292             ) const {
00293             return (m_TabStops[num]);
00294             }
00295 
00296          void SetName (
00297             const UNICODE* name
00298             ) {
00299             ucstrcpy(m_name, name);
00300             }
00301 
00302          void SetStyle (
00303             const TEXTSTYLE* style
00304             ) {
00305             if (style != 0)   *(static_cast<TEXTSTYLE*>(this)) = *style;
00306             }
00307 
00308          //! Add a new tabstop.  
00309          //!Returns stop number or error < 0
00310          INT32 TabStopAdd (
00311             const TABSTOP& stop
00312             );
00313 
00314          //! Add a new tabstop.  
00315          //!Returns stop number or error < 0
00316          INT32 TabStopAdd (
00317             INT32 pos,
00318             TABSTOP::TYPE type = TABSTOP::TYPE_Left,
00319             char padChar = 0
00320             );
00321 
00322          //! Remove a tabstop given it's index
00323          void TabStopRemove (
00324             INT32 TabStopNum
00325             );
00326 
00327          void TabStopRemoveAll (
00328             ) {
00329             m_NumTabStops = 0;
00330             MmFree(m_TabStops);
00331             }
00332 
00333          void TabStopMove (
00334             INT32 TabStopNum,
00335             INT32 NewPos,
00336             bool bSort = true    //!< Resort the tab stops after the move
00337             );
00338          
00339          void SortTabStops();
00340 
00341       private:
00342          #ifndef GENERATING_DOXYGEN_OUTPUT
00343          UNICODE m_name[64];
00344          UINT32 m_NumTabStops;
00345          TABSTOP* m_TabStops;
00346 
00347          void Copy (
00348             const NAMEDTEXTSTYLE& rhs
00349             );
00350 
00351          friend class GRAPHICLAYOUT;
00352          #endif // GENERATING_DOXYGEN_OUTPUT
00353       };
00354 
00355 
00356    class TEXTBLOCK {
00357       public:
00358 
00359          static const SERIALIZER::ITEMDEF* GetSerialItemDef (
00360             );
00361 
00362          TEXTBLOCK (
00363             );
00364 
00365          TEXTBLOCK (
00366             const UNICODE* str
00367             );
00368 
00369          TEXTBLOCK (
00370             const TEXTBLOCK& rhs
00371             );
00372 
00373          ~TEXTBLOCK (
00374             ) {
00375             }
00376 
00377          void ClearSizeKnown (
00378             ) {
00379             m_bSizeKnown = false;
00380             return;
00381             }
00382 
00383          const DPOINT2D& ComputeSize (
00384             const NAMEDTEXTSTYLE* style,
00385             DOUBLE XStart = 0.0           //!< Starting location relative to left guide (for tabs)
00386             );
00387 
00388          void Draw (
00389             MGD::CONTEXT*,
00390             const DPOINT2D& basepoint,
00391             TEXTBASEORIGIN baseorigin,
00392             const NAMEDTEXTSTYLE* style,
00393             double XOffset = 0.0    //!< Left margin relateive to base point
00394             );
00395 
00396          //! Get the size of the block.
00397          //! Must have called ComputeSize() or WordWrap() first.
00398          const DPOINT2D& GetSize (
00399             ) const {
00400             return (m_size);
00401             };
00402 
00403          const MISTRING& GetString (
00404             ) const {
00405             return (m_str);
00406             }
00407 
00408          bool IsSizeKnown (
00409             ) const {
00410             return (m_bSizeKnown);
00411             }
00412 
00413          void SetString (
00414             const MISTRING& str
00415             );
00416 
00417          const DPOINT2D& WordWrap (
00418             DOUBLE width,
00419             const NAMEDTEXTSTYLE* style,
00420             DOUBLE xoffset = 0.0    //!< offset into tabs
00421             );
00422 
00423       private:
00424          void FillInBlock (
00425             MGD::TEXTBLOCK& block,
00426             const NAMEDTEXTSTYLE* style = 0,
00427             double XOffset = 0.0
00428             );
00429          
00430          //! Sets the given string to the codes needed to set tabstops for
00431          //! a given text style
00432          void SetupTabStops (
00433             MISTRING& str,
00434             const NAMEDTEXTSTYLE& style,
00435             double XOffset = 0.0
00436             );
00437 
00438          MISTRING m_str;         //!< Raw string, not word-wrapped
00439          MISTRING m_formatted;   //!< Temp string.  tab setting codes + (m_str or m_wrapped)
00440          DPOINT2D m_size;
00441          double m_WrapWidth;
00442          bool m_bSizeKnown;
00443          bool m_bDoWordWrap;
00444       };
00445 
00446    //! This class is used to create "property sheets" for various element types.
00447    //! This is only used by the GUI editor.   
00448    class ITEMPROPERTYSHEET {
00449 #ifndef WIN32_NATIVE
00450       public:
00451          ITEMPROPERTYSHEET (
00452             GRAPHICLAYOUT& grlayout,
00453             MIDIALOG* dialog
00454             ) :
00455             m_grlayout(grlayout),  
00456             m_dialog(dialog)  
00457             {
00458             }
00459 
00460          virtual ~ITEMPROPERTYSHEET() {
00461             }
00462 
00463          virtual const char* GetLabel () const = 0;
00464 
00465          virtual Widget CreateForm (
00466             Widget parent,
00467             bool isMulti
00468             ) = 0;
00469 
00470          virtual void OnApply () = 0;
00471 
00472          virtual void OnOpen (
00473             ) {
00474             }
00475 
00476          virtual ERRVALUE AddItem (
00477             ITEM* item
00478             ) = 0;
00479 
00480          virtual void OnSetDistanceUnits (
00481             UNITCONV* conv
00482             )  {
00483             return;              
00484             }
00485 
00486          virtual void OnChangeTextStyle (
00487             int StyleNum
00488             )  {
00489             return;              
00490             }
00491 
00492          void SetApplySensitive (
00493             bool sensitive = true
00494             );
00495 
00496       protected:
00497 
00498 
00499          //! Setup a modify callback for an MxPrompt.
00500          //! The (bool*) passed in should point to a bool which will be set to true if a value changes.
00501          void SetPromptModifyCallback (
00502             Widget prompt,
00503             bool& bModifiedFlag
00504             );
00505 
00506          void SetXeTextModifyCallback (
00507             Widget Widget,
00508             bool& bModifiedFlag
00509             );
00510 
00511          Widget CreateTextStyleOptionMenu (
00512             Widget parent,
00513             int DefaultStyleNum,
00514             Arg* args,
00515             int numargs
00516             );
00517 
00518       private:
00519          //! Callback that derived class can attach to a prompt so that a bool
00520          //! value will be set to true when a value is edited.
00521          //! Pass a pointer to the bool memeber for callback data
00522          //! Also pass 
00523          static void PCB_PromptModify (         
00524             MxPromptCallbackStruct*,
00525             void* cbdata
00526             );
00527 
00528          static void CB_ChangeStyle (
00529             Widget widget,
00530             void* cbdata,
00531             void*
00532             );
00533 
00534          static void CB_XeTextModify (
00535             Widget widget,
00536             void* cbdata,
00537             void*
00538             );
00539 
00540          MIDIALOG* m_dialog;
00541          GRAPHICLAYOUT& m_grlayout;
00542 #endif
00543 
00544       };      
00545 
00546    class ITEMPOSITION {
00547       public:
00548 
00549          ITEMPOSITION (
00550             );
00551 
00552          //! Copy consturctor
00553          ITEMPOSITION (
00554             const ITEMPOSITION& rhs
00555             );
00556 
00557          virtual ~ITEMPOSITION (
00558             ) { 
00559             }
00560 
00561          //! Compare two positions for item sorting
00562          //! Returns -1 if *this < rhs, 0 if this == rhs, 1 if *this > rhs
00563          int Compare (
00564             const ITEMPOSITION& rhs
00565             ) const;
00566 
00567          //! Get the group number of the item (0 if not part of a group)
00568          const INT32 GetGroup (
00569             ) const {
00570             return (m_Group);
00571             }
00572 
00573          //! Get the left guide number.
00574          //! Guide -1 means it's "floating" in that direction.  Things are allowed
00575          //! to float on either left or right, but not both.
00576          int GetLeftGuide (
00577             ) const {
00578             return m_LeftGuide;
00579             }
00580 
00581          //! Return the offset to the left guide (in points).
00582          //! Meaningless if GetLeftGuide() returns -1
00583          DOUBLE GetLeftOffset (
00584             ) const {
00585             return m_LeftOffset;
00586             }
00587 
00588          //! Get the right guide number.
00589          //! Guide -1 means it's "floating" in that direction.  Things are allowed
00590          //! to float on either left or right, but not both.
00591          int GetRightGuide (
00592             ) const {
00593             return m_RightGuide;
00594             }
00595 
00596          //! Return the offset to the right guide (in points).
00597          //! Meaningless if GetRightGuide() returns -1
00598          DOUBLE GetRightOffset (
00599             ) const {
00600             return m_RightOffset;
00601             }
00602 
00603          //! Get the top guide number.
00604          //! Guide -1 means it's attached to the item "above" it (which 
00605          //! you can get with GetTopItem()
00606          INT32 GetTopGuide (
00607             ) const {
00608             return m_TopGuide;
00609             }
00610 
00611          //! Return the offset to the item or guide above us (in points).
00612          DOUBLE GetTopOffset (
00613             ) const {
00614             return m_TopOffset;
00615             }
00616 
00617          //! Get the size rectangle for the item.
00618          const DRECT2D& GetRect (
00619             ) const {
00620             return (m_rect);
00621             }
00622 
00623          void GetRect (
00624             DRECT2D& rect
00625             ) {
00626             rect = GetRect();    //! Use other method
00627             return;
00628             }
00629 
00630          void SetGroup (
00631             INT32 group
00632             ) { m_Group = group; }
00633 
00634       protected:
00635          INT32 m_LeftGuide;
00636          INT32 m_RightGuide;
00637          INT32 m_TopGuide;    //!< if -1, relateive to m_pPrev
00638          DOUBLE m_TopOffset;
00639          DOUBLE m_LeftOffset;
00640          DOUBLE m_RightOffset;
00641          DRECT2D m_rect;
00642          INT32 m_Group;    
00643 
00644          friend class GRAPHICLAYOUT;
00645          friend class ITEM;
00646       };
00647 
00648    class ITEM : public ITEMPOSITION, SERIALIZABLE {
00649       public:
00650 
00651          //! Constructor automatically installs item in the layout.
00652          //! but do we want it to?  Serial Read wants to have it at
00653          //! the end. Normal interactive use, we want to put it at
00654          //! current insert position.  Perhaps layout should know
00655          //! insert position so we can install there by default.
00656          ITEM (
00657             GRAPHICLAYOUT& parent
00658             );
00659 
00660          //! Copy constructor (but with copy owned by a different parent)
00661          ITEM (
00662             const ITEM& rhs,
00663             GRAPHICLAYOUT& parent
00664             );
00665 
00666          //! Destructor automatically removes item from the layout
00667          virtual ~ITEM();
00668 
00669          //! Compute the size of the item.
00670          //! Should compute a default rectangle which will be used if
00671          //! the item has not been resized.
00672          //! Will only be called if m_bSizeKnown is false
00673          virtual void ComputeRect (
00674             DRECT2D& rect
00675             ) = 0;
00676 
00677          //! Make a copy of this item.  Copy will be placed in another layout
00678          virtual ITEM* Copy (
00679             GRAPHICLAYOUT& parent
00680             ) const = 0;
00681 
00682          virtual ITEMPROPERTYSHEET* CreatePropertySheet (
00683             GRAPHICLAYOUT& grlayout,
00684             MIDIALOG* dialog
00685             ) = 0;
00686             
00687          //! Draw the item.
00688          //! Derived class overrides this
00689          virtual void Draw (
00690             MGD::CONTEXT* gc,       //!< GC to use
00691             const DRECT2D& rect,    //!< Where to draw
00692             const TRANSPARM* trans,
00693             double scale
00694             ) = 0;
00695 
00696          //! Draw the item at its current location (possibly highlighting it as selected)
00697          void Draw (
00698             MGD::CONTEXT* gc,             //!< GC to use
00699             bool bSelected = false, //!< Draw as selected if true
00700             const TRANSPARM* trans = 0,
00701             double scale = 1.0
00702             );
00703 
00704          //! Return the height that the item claims it wants.
00705          //! This could be different from GetRect().height, but not likely
00706          DOUBLE GetHeight (
00707             ) const {
00708             return (m_height);
00709             }
00710 
00711          //! Get a const pointer to the text style for this item.
00712          const NAMEDTEXTSTYLE* GetTextStyle (
00713             ) const {
00714             return (m_parent.GetTextStyle(m_TextStyleNum));
00715             }
00716 
00717          //! Get the text style number for this item.
00718          int GetTextStyleNumber (
00719             ) const {
00720             return (m_TextStyleNum);
00721             }
00722 
00723          //! Get the width of the item.
00724          DOUBLE GetWidth (
00725             ) const {
00726             return (m_width);
00727             }
00728 
00729          bool IsSelected (
00730             ) const {
00731             return (m_bSelected);
00732             }
00733 
00734          //! Returns true if the item is in the correct sorted place in the layout's list of items.
00735          //! Also returns true if the item isn't the list at all, as that means the list isn't out
00736          //! of order on account of this item.
00737          bool IsSorted (
00738             ) const;
00739 
00740          //! Returns true if the item is in the layout's list of items.
00741          bool IsInLayout (
00742             ) const;
00743 
00744          //! Move this item relative to it's current location
00745          void Move (
00746             DOUBLE dx,  //!< delta x
00747             DOUBLE dy,  //!< delta y
00748             bool bSnap  //!< If true, snap to nearby guides
00749             ) {
00750             m_parent.MoveItem(this, dx, dy, bSnap);
00751             return;
00752             }
00753 
00754          //! Move this item to a new absolute position
00755          void Move (
00756             const DRECT2D& rect,    //!< New location XXX May make this a point.
00757             bool bSnap  //!< If true, snap to nearby guides
00758             ) {
00759             m_parent.MoveItem(this, rect, bSnap);
00760             return;
00761             }
00762 
00763          //! Arrange for this item to be just below a specified item
00764          void MoveBelow (
00765             const ITEMPOSITION& above
00766             ) {
00767             m_rect.yinit = above.m_rect.yinit + .0001;
00768             if (IsInLayout()) m_parent.SetLayoutNeeded();
00769             return;
00770             }
00771 
00772          //! Derived class must provide this method
00773          virtual const SERIALIZER::ITEMDEF* SerialGetItemDef (
00774             SERIALIZER& serializer
00775             ) const = 0;
00776 
00777          //! Method for implementing SERIALIZABLE behaviour.
00778          //! Derived class must provide this method
00779          virtual const char* SerialGetTagName (
00780             ) const = 0;
00781 
00782          //! Method for implementing SERIALIZABLE behaviour.
00783          //! ITEM provides this for all derived classes
00784          virtual ERRVALUE SerialRead (
00785             SERIALIZER& serializer
00786             );
00787 
00788          //! Method for implementing SERIALIZABLE behaviour.
00789          //! ITEM provides this for all derived classes
00790          virtual ERRVALUE SerialWrite (
00791             SERIALIZER& serializer,
00792             const char* tagname = 0
00793             ) const;
00794 
00795          //! Will also inform parent layout that it needs to recalculate layout.
00796          void SetAttachments (
00797             const ITEMPOSITION& newpos
00798             ) {
00799             m_LeftGuide = newpos.m_LeftGuide;
00800             m_RightGuide = newpos.m_RightGuide;
00801             m_TopGuide = newpos.m_TopGuide;
00802             m_LeftOffset = newpos.m_LeftOffset;
00803             m_RightOffset = newpos.m_RightOffset;
00804             m_TopOffset = newpos.m_TopOffset;
00805             m_rect = newpos.m_rect;
00806             m_bPosKnown = true;
00807             if (IsInLayout()) m_parent.SetLayoutNeeded();
00808             return;
00809             }
00810 
00811          //! Set the item to the default location.  That is, assume it will go at the end
00812          //! just past the last element and set it to that position.
00813          void SetDefaultLocation (
00814             );
00815 
00816          //! Set the "hidden" state of an item.  ITEM::Draw should ignore this state()
00817          //! GRAPHICLAYOUT::Draw() won't draw any hidden items, but the GUI will (to
00818          //! draw into an overlay GC while moving items)
00819          void SetHidden (
00820             bool bHidden
00821             ) {
00822             m_bHidden = bHidden;
00823             }
00824 
00825          //! Will also inform parent layout that it needs to recalculate layout.
00826          void SetLeftOffset (
00827             DOUBLE offset
00828             ) {
00829             m_LeftOffset = offset;
00830             if (IsInLayout()) m_parent.SetLayoutNeeded();
00831             return;
00832             }
00833 
00834          void SetLeftPosition (
00835             INT32 GuideNum,
00836             DOUBLE offset
00837             ) {
00838             m_LeftGuide = GuideNum;
00839             m_LeftOffset = offset;
00840             if (IsInLayout()) m_parent.SetLayoutNeeded();
00841             return;
00842             }
00843 
00844          
00845          //! Will also inform parent layout that it needs to recalculate layout.
00846          void SetRightPosition (
00847             INT32 GuideNum,
00848             DOUBLE offset
00849             ) {
00850             m_RightGuide = GuideNum;
00851             m_RightOffset = offset;
00852             if (IsInLayout()) m_parent.SetLayoutNeeded();
00853             return;
00854             }
00855 
00856          void SetSelected (
00857             bool selected
00858             ) {
00859             m_bSelected = selected;
00860             return;
00861             }
00862 
00863          void SetSize (
00864             DOUBLE height,
00865             DOUBLE width
00866             ) {
00867             if (height == m_height && width == m_width) return;
00868             m_height = height;
00869             m_width = width;
00870             if (IsInLayout()) m_parent.SetLayoutNeeded();
00871             return;
00872             }
00873 
00874          //! Set the text style number.
00875          //! Will also inform parent layout that it needs to recalculate layout.
00876          void SetTextStyleNumber (
00877             int num
00878             ) {
00879             if (num != m_TextStyleNum) {
00880                m_TextStyleNum = num;
00881                m_bSizeKnown = false;
00882                if (IsInLayout()) m_parent.SetLayoutNeeded();
00883                }
00884             }
00885 
00886          void SetTopOffset (
00887             DOUBLE offset
00888             ) {
00889             m_TopOffset = offset;
00890             if (IsInLayout()) m_parent.SetLayoutNeeded();
00891             return;
00892             }
00893 
00894          //! Will also inform parent layout that it needs to recalculate layout.
00895          void SetTopPosition (
00896             INT32 GuideNum,      //!< Use -1 if offset is relative to an item
00897             DOUBLE offset
00898             ) {
00899             m_TopGuide = GuideNum;
00900             m_TopOffset = offset;
00901             if (IsInLayout()) m_parent.SetLayoutNeeded();
00902             return;
00903             }
00904 
00905          virtual bool UsesTransparency (
00906             const MGD::CONTEXT* gc = 0 
00907             ) const { return false; }
00908 
00909          //! Called by derived classes so they can merge the ITEMDEF lists
00910          //! Should be protected, but then aparently derived classes also need to be nestet in GRAPHICLAYOUT
00911          static const SERIALIZER::ITEMDEF* GetSerialItemDef (
00912             );
00913 
00914          //! TODO: Methods to set position relative to other things
00915          //!    or relative to the "page"
00916          //! Each item should know what item is above/below it.
00917          //! Could possibly handle as one MILIST for each column
00918          //! An item could be in > 1 column if it spans columns
00919       protected:
00920          bool m_bSizeKnown;
00921          GRAPHICLAYOUT& m_parent;
00922 
00923       private:
00924          INT32 m_TextStyleNum;
00925          bool m_bHidden;      //!< Not serialized
00926          bool m_bPosKnown;
00927          bool m_bSelected;
00928          DOUBLE m_height;
00929          DOUBLE m_width;
00930          ITEMLIST::ITERATOR m_self;    //!< Used by destructor to remove self from list
00931 
00932          friend class GRAPHICLAYOUT;
00933       };
00934 
00935       //! Creating an instance of this class suspends redrawing on the
00936       //! layout.  When it goes out of scope, redrawing will be reenabled.
00937       //! This is done using a count, so multiple suspend/resumes are
00938       //! automatically handled.  When the final resume happens, the
00939       //! draw callback will be called if necessary.
00940       //! (It could do the draw itself, but has no gc)
00941 
00942       class SUSPEND_REDRAW {
00943          public:
00944             SUSPEND_REDRAW (
00945                GRAPHICLAYOUT& layout
00946                ) :
00947                m_layout(layout)
00948                {
00949                m_layout.RedrawSuspend();
00950                }  
00951 
00952             ~SUSPEND_REDRAW (
00953                ) {
00954                m_layout.RedrawResume();
00955                }  
00956 
00957          private:
00958             GRAPHICLAYOUT& m_layout;
00959          };
00960 
00961       //! Method for implementing SERIALIZABLE behaviour.
00962       static const SERIALIZER::ITEMDEF* GetSerialItemDef (
00963          );
00964 
00965       //! #include <mi32/MILIST.h>
00966       //! Constructor.
00967       GRAPHICLAYOUT (
00968          );       
00969 
00970       //! Copy constructor 
00971       GRAPHICLAYOUT (
00972          const GRAPHICLAYOUT& rhs
00973          );
00974 
00975       //! Assignment operator private and unimplemented to prevent use
00976 
00977       //! Destructor.
00978       virtual ~GRAPHICLAYOUT();
00979 
00980       //! Install handler for an ITEMTYPE.
00981       static void InstallItemType (
00982          const char* name,                            //!< Item type name for serialization
00983          int (*Construct)(GRAPHICLAYOUT&, ITEM**)     //! Function to construct an item of this type
00984          );
00985 
00986       //! Return iterator to first item in layout
00987       ITERATOR Begin (
00988          ) {
00989          return (m_ItemList.Begin());
00990          }
00991 
00992             //! Return const iterator to first item in layout
00993       CONST_ITERATOR Begin (
00994          ) const {
00995          return (m_ItemList.Begin());
00996          }
00997 
00998       //! Add a Horizontal Guide.
00999       //! Returns the new guide number or err < 0
01000       int AddHGuide (
01001          DOUBLE value
01002          );
01003 
01004       //! Add an item to the layout.
01005       //! Once added, the item is "owned" by the layout and will be destroied by the layout's destructor.
01006       //! If the position of the item hasn't been set yet, a default postion will be computed.
01007       void AddItem (
01008          ITEM* item
01009          );
01010 
01011       //! Add a named text style
01012       int AddTextStyle (
01013          const NAMEDTEXTSTYLE& style
01014          );
01015 
01016       //! Add a Vertical Guide.
01017       //! Returns the new guide number or err < 0
01018       int AddVGuide (
01019          DOUBLE value
01020          );
01021 
01022       //! Compute item attachments given a rectangle of where the item will go.
01023       //! If bSnap is true, then anything within 3 pixels of a guide will snap
01024       //! to the guide and the rectangle will be adjusted accordingly
01025       void ComputeItemAttachments (
01026          const ITEM* item,
01027          DRECT2D& rect,
01028          ITEMPOSITION& newpos,   //!< Computed and returned (Initial values unused)
01029          const ITEM *&ItemAbove,
01030          bool bSnap = true
01031          ) const;
01032 
01033       ERRVALUE Copy (
01034          const GRAPHICLAYOUT& rhs
01035          );
01036 
01037       //! Compute all item positions.
01038       //! If nothing has changed since the last layout, nothing is done.
01039       int DoLayout (
01040          );
01041 
01042       //! Draw.  
01043       //! If Rect is not 0, only draw things intersecting the rect
01044       int Draw (
01045          MGD::CONTEXT* gc,
01046          const DRECT2D* rect = 0,
01047          const TRANSPARM* trans = 0,
01048          double scale = 1.0
01049          );
01050 
01051       //! Draw "handles" showing item attachemts. (normally done while moving an item)
01052       //! SelectedDelta is the offset in output cordinates that selected items have
01053       //! been shifted.
01054       void DrawItemHandles (
01055          MGD::CONTEXT* gc,
01056          const ITEMPOSITION& position,
01057          const DRECT2D& rect,
01058          const GRAPHICLAYOUT::ITEM* ItemAbove,
01059          const DPOINT2D& SelectedDelta,
01060          double scale = 1.0
01061          ) const;
01062 
01063       //! Return iterator to compare to end of layout (0)
01064       ITERATOR End (
01065          ) {
01066          return (m_ItemList.End());
01067          }
01068 
01069       //! Return const iterator to compare to end of layout (0)
01070       CONST_ITERATOR End (
01071          ) const {
01072          return (m_ItemList.End());
01073          }
01074 
01075       const LINESTYLE& GetBorderStyle (
01076          ) const {
01077          return (m_BorderStyle);
01078          }
01079 
01080       const COLOR& GetBackgroundColor (
01081          ) const {
01082          return (m_BGColor);        
01083          }
01084 
01085       //! Control wether or not the legend background is filled
01086       bool GetDrawBackground (
01087          ) const {
01088          return (m_bDrawBackground);
01089          }
01090 
01091       //! Control wether or not a border is drawn around the legend
01092       //! Use SetBorderStyle() to set the style of the border
01093       bool GetDrawBorder (
01094          ) const {
01095          return (m_bDrawBorder);
01096          }
01097 
01098       //! Determine if DropShadow is on or off
01099       bool GetDrawDropShadow (
01100          ) const {
01101          return (m_bDrawDropShadow);
01102          }
01103 
01104       //! Get the color for the drop shadow. 
01105       const COLOR& GetDropShadowColor (
01106          ) const {
01107          return (m_DropShadowColor);
01108          }
01109 
01110       //! Get the angle for the drop shadow (in radians).
01111       double GetDropShadowDirection (
01112          ) const {
01113          return (m_DropShadowDirection);
01114          }
01115 
01116       //! Get distance for the drop shadow (in points)
01117       double GetDropShadowDistance (
01118          ) const {
01119          return (m_DropShadowDistance);
01120          }
01121 
01122       //! Return the value of a Horizontal Guide.
01123       DOUBLE GetHGuide (
01124          int GuideNum
01125          ) const {
01126          if (GuideNum < 0 || (UINT32)GuideNum >= m_NumHGuides) return 0;
01127          return m_HGuides[GuideNum];
01128          }
01129 
01130       //! Get the height of the content.
01131       DOUBLE GetHeight (
01132          ) const {   
01133          return (m_Extents.GetHeight());
01134          }
01135 
01136       //! Given an X/Y position, return the horizontal Guide number.
01137       //! Returns -1 if no guide at given location.
01138       INT32 GetHGuideFromLocation (
01139          const DPOINT2D& point,
01140          int tolerance = 2    //!< How close do we have to be (in pixels)
01141          ) const;
01142 
01143       INT32 GetVGuideFromLocation (
01144          const DPOINT2D& point,
01145          int tolerance = 2    //!< How close do we have to be (in pixels)
01146          ) const;
01147 
01148 
01149       //! Given an x/y position return the item at that location.
01150       //! Returns NULL if no item at that location.
01151       ITEM* GetItemFromLocation (
01152          const DPOINT2D& point
01153          );
01154 
01155       //! Const version of GetItemFromLocation()
01156       const ITEM* GetItemFromLocation (
01157          const DPOINT2D& point
01158          ) const;
01159 
01160       //! Get the number of Horizontal Guides.
01161       int GetNumHGuides (
01162          ) const {
01163          return m_NumHGuides;
01164          }
01165 
01166       //! Get the number of text styles.
01167       int GetNumTextStyles (
01168          ) const {
01169          return m_TextStyle.size();
01170          }
01171 
01172       //! Get the number of Vertical Guides.
01173       int GetNumVGuides (
01174          ) const {
01175          return m_NumVGuides;
01176          }
01177 
01178       //! Get a text style (const*).
01179       const NAMEDTEXTSTYLE* GetTextStyle (
01180          int num
01181          ) const {
01182          if (num < 0 || num >= GetNumTextStyles()) return NULL;
01183          return (&m_TextStyle[num]);
01184          }
01185 
01186       //! Get a copy of a text style.
01187       void GetTextStyle (
01188          int num,
01189          TEXTSTYLE& style
01190          ) const {
01191          style = m_TextStyle[num];
01192          return;
01193          }
01194 
01195       //! Get a copy of a text style.
01196       void GetTextStyle (
01197          int num,
01198          NAMEDTEXTSTYLE& style
01199          ) const {
01200          style = m_TextStyle[num];
01201          return;
01202          }
01203 
01204 
01205       //! Get the name of a text style.
01206       const UNICODE* GetTextStyleName (
01207          int num
01208          ) const {
01209          if (num < 0 || num >= GetNumTextStyles()) return NULL;
01210          return (m_TextStyle[num].m_name);
01211          }
01212 
01213       //! Get the list of text styles.
01214       //! Can't return a const SIMPLE_ARRAY<>& because they're not stored that way
01215       //! internally for serialization reasons.
01216       void GetTextStyles (
01217          std::vector<NAMEDTEXTSTYLE>& styles
01218          ) {
01219          styles.clear();
01220          for (int i = 0 ; i < GetNumTextStyles() ; ++i) styles.push_back(m_TextStyle[i]);
01221          }
01222 
01223       //! Return the value of a Vertical Guide.
01224       DOUBLE GetVGuide (
01225          int GuideNum
01226          ) const {
01227          if (GuideNum < 0 || (UINT32)GuideNum >= m_NumVGuides) return 0;
01228          return m_VGuides[GuideNum];
01229          }
01230 
01231       //! Get the width of the content.
01232       DOUBLE GetWidth (
01233          ) const { 
01234          return (m_Extents.GetWidth());
01235          }
01236 
01237       bool IsLayoutNeeded (
01238          ) const {
01239          return (m_bLayoutNeeded);
01240          }
01241 
01242       //! Move an item relative to its current position
01243       void MoveItem (
01244          ITEM* item,       //!< Item to move
01245          DOUBLE dx,        //!< Distance to move (x)
01246          DOUBLE dy,        //!< Distance to move (y, positive == down)
01247          bool bSnap        //!< Snap to guide if close
01248          );
01249 
01250 
01251       //! Move an item to an absolute location
01252       void MoveItem (
01253          ITEM* item,                   //!< Item to move
01254          const DRECT2D& location,      //!< Where to move it to (XXX May make this a point)
01255          bool bSnap                    //!< Snap to guide if close   
01256          );
01257 
01258       //! Suspend redraws.
01259       //! RedrawSuspend()/RedrawResume() calls can be nested.
01260       //! If you plan to Suspend/Resume in the same function, you're better
01261       //! off creating an instance of a GRAPHICLAYOUT::SUSPENDREDRAW, which
01262       //! will automatically resume when it goes out of scope.
01263       void RedrawSuspend (
01264          ) {
01265          ++m_RedrawSuspended;
01266          return;
01267          }
01268 
01269       //! Resume redraws.
01270       //! If anything has changd while redraws were suspended, it will redraw.
01271       //! See comments on RedrawSuspend() for more information.
01272       void RedrawResume (
01273          ) {
01274          if (m_RedrawSuspended) --m_RedrawSuspended;
01275          if (!m_RedrawSuspended && m_bRedrawNeeded) {
01276             Redraw();   //! Notifies all observers
01277             }
01278          return;
01279          }
01280 
01281       //! Remove a Horizontal Guide.
01282       //! Will not allow the removal of a guide which is in use.
01283       //! Will return true if the guide was removed, false if it was
01284       //! in use or an invalid guide number.
01285       bool RemoveHGuide (
01286          int GuideNum
01287          );
01288 
01289       //! Removes an item from the layout.
01290       //! Does not free the item.  Once removed from the layout, it is your responsibility to destroy
01291       //! the item.  Any items which are in the layout at the time the layout is destroied will get
01292       //! destroied by the layout's destructor.
01293       void RemoveItem (
01294          ITEM* item
01295          );
01296       
01297       //! Remove a Vertical Guide.
01298       //! Will not allow the removal of a guide which is in use.
01299       //! Will return true if the guide was removed, false if it was
01300       //! in use or an invalid guide number.
01301       bool RemoveVGuide (
01302          int GuideNum
01303          );
01304 
01305       //! Method for implementing SERIALIZABLE behaviour.
01306       virtual const SERIALIZER::ITEMDEF* SerialGetItemDef (
01307          SERIALIZER& serializer
01308          ) const;
01309 
01310       //! Method for implementing SERIALIZABLE behaviour.
01311       virtual const char* SerialGetTagName (
01312          ) const {
01313          return "GRAPHICLAYOUT";
01314          }
01315 
01316       //! Method for implementing SERIALIZABLE behaviour.
01317       virtual ERRVALUE SerialRead (
01318          SERIALIZER& serializer
01319          );
01320 
01321       //! Method for implementing SERIALIZABLE behaviour.
01322       virtual ERRVALUE SerialWrite (
01323          SERIALIZER& serializer,
01324          const char* itemname
01325          ) const;
01326 
01327       void SetBackgroundColor (
01328          const COLOR& color
01329          ) {
01330          m_BGColor = color;
01331          return;
01332          }
01333 
01334       //! Set the style of the border to draw around the legend.
01335       //! Use SetDrawBorder() to control wether or not this is used.
01336       void SetBorderStyle (
01337          const LINESTYLE& style
01338          ) {
01339          m_BorderStyle = style;
01340          return;
01341          }
01342 
01343       //! Control wether or not the background is filled
01344       void SetDrawBackground (
01345          bool DrawBackground
01346          ) {
01347          m_bDrawBackground = DrawBackground;
01348          return;
01349          }
01350 
01351       //! Control wether or not a border is drawn around the legend
01352       //! Use SetBorderStyle() to set the style of the border
01353       void SetDrawBorder (
01354          bool DrawBorder
01355          ) {
01356          m_bDrawBorder = DrawBorder;
01357          return;
01358          }
01359 
01360       //! Control wether or not a drop shadow is drawn around the legend
01361       //! Use SetDropShadowXxxx() to set the shadow parameters
01362       void SetDrawDropShadow (
01363          bool DrawDropShadow
01364          ) {
01365          m_bDrawDropShadow = DrawDropShadow;
01366          return;
01367          }
01368 
01369       //! Set the color for the drop shadow. 
01370       void SetDropShadowColor (
01371          const COLOR& color
01372          )  {
01373          m_DropShadowColor= color;
01374          return;
01375          }
01376 
01377       //! Set the angle for the drop shadow (in radians).
01378       //! GUI should provide intuitive way to set this.
01379       void SetDropShadowDirection (
01380          double angle
01381          )  {
01382          m_DropShadowDirection = angle;
01383          return;
01384          }
01385 
01386       //! Set the distance for the drop shadow (in points).
01387       //! GUI should provide intuitive way to set this.
01388       void SetDropShadowDistance (
01389          double distance
01390          )  {
01391          m_DropShadowDistance = distance;
01392          return;
01393          }
01394 
01395       //! Set the value of a horizontal guide.
01396       void SetHGuide (
01397          int GuideNum,
01398          DOUBLE value
01399          );
01400 
01401       //! Sets the flag indicating that layout needs to be recomputed.
01402       //! XXX This could be made private.
01403       void SetLayoutNeeded (
01404          ) {
01405          m_bLayoutNeeded = m_bRedrawNeeded = true;
01406          Redraw();   //! Inform observers if not suspended
01407          }
01408 
01409       //! Sets the flag indicating that layout needs to be redrawn
01410       //! but not necessarly layout recomputed.  Used when all was changed
01411       //! was color and things that don't effect size.
01412       void SetRedrawNeeded (
01413          ) {
01414          m_bRedrawNeeded = true;
01415          Redraw();   //! Inform observers if not suspended
01416          }
01417 
01418       //! Set a text style.
01419       /*
01420       void SetTextStyle (
01421          int num,
01422          const TEXTSTYLE& style
01423          );
01424          */
01425 
01426       //! Set a text style.
01427       void SetTextStyle (
01428          int num,
01429          const NAMEDTEXTSTYLE& style
01430          );
01431 
01432       //! Set the name of a text style.
01433       void SetTextStyleName (
01434          int num,
01435          const UNICODE* name
01436          ) {
01437          if (num < 0 || num >= GetNumTextStyles()) return;
01438          ucstrcpy(m_TextStyle[num].m_name, name);
01439          return;
01440          }
01441 
01442       //! Set the text styles
01443       ERRVALUE SetTextStyles (
01444          const std::vector<NAMEDTEXTSTYLE>& styles
01445          );
01446 
01447       //! Set the text styles, but allow for possibility of style reordering.
01448       //! The trans parameter is an array of INT32's that map old style number
01449       //! to new style number.  The size of this array should match the number
01450       //! of styles that are in the layout before the call.  If a style has been
01451       //! deleted, it's entry in the array should be -1.
01452       ERRVALUE SetTextStyles (
01453          const std::vector<NAMEDTEXTSTYLE>& styles,
01454          const SIMPLE_ARRAY<INT32>& trans
01455          );
01456 
01457 
01458       //! Set the value of a vertical guide.
01459       void SetVGuide (
01460          int GuideNum,
01461          DOUBLE value
01462          );
01463 
01464       bool UsesTransparency (
01465          const MGD::CONTEXT* gc = 0 
01466          ) const;
01467 
01468    protected:
01469 
01470 
01471    private:
01472       
01473       friend class OBSERVER;     //!< Allow its tconstructor to access m_Observers
01474 
01475       struct ITEMTYPE {
01476          const char* m_name;
01477          int (*m_Construct)(GRAPHICLAYOUT&, ITEM**);
01478          };
01479 
01480       static ERRVALUE SerializerCB_Item (
01481          SERIALIZER& serializer,
01482          const SERIALIZER::ITEMDEF *itemdef,
01483          void* cbdata,
01484          SERIALIZER::ITEMDEF::ACTION action
01485          );
01486 
01487       static ERRVALUE SerializerCB_NamedTextStyle (
01488          SERIALIZER& serializer,
01489          const SERIALIZER::ITEMDEF* itemdef,
01490          void* cbdata,
01491          SERIALIZER::ITEMDEF::ACTION action
01492          );
01493 
01494       bool m_bLayoutNeeded;
01495       bool m_bRedrawNeeded;
01496       UINT32 m_NumHGuides;
01497       DOUBLE* m_HGuides;