/*-*- c++ -*-******************************************************** * wxLayoutList.h - a formatted text rendering engine for wxWindows * * * * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) * * * * $Id$ *******************************************************************/ #ifndef WXLLIST_H #define WXLLIST_H #ifdef __GNUG__ # pragma interface "wxllist.h" #endif #include "kbList.h" #include "wx/wx.h" #include "wx/print.h" #include "wx/printdlg.h" #include "wx/generic/printps.h" #include "wx/generic/prntdlgg.h" // skip the following defines if embedded in M application #ifdef M_BASEDIR # ifdef DEBUG # define WXLAYOUT_DEBUG # endif #else // for testing only: # define WXLAYOUT_DEBUG // The wxLayout classes can be compiled with std::string instead of wxString //# define USE_STD_STRING # define WXMENU_LAYOUT_LCLICK 1111 # define WXMENU_LAYOUT_RCLICK 1112 # define WXMENU_LAYOUT_DBLCLICK 1113 #endif #ifdef USE_STD_STRING # include typedef std::string String; # define Str(str)(str.c_str()) #else typedef wxString String; # define Str(str) str #endif #define WXLO_DEFAULTFONTSIZE 12 /// Types of currently supported layout objects. enum wxLayoutObjectType { WXLO_TYPE_INVALID = 0, WXLO_TYPE_TEXT, WXLO_TYPE_CMD, WXLO_TYPE_ICON, WXLO_TYPE_LINEBREAK }; /// Type used for coordinates in drawing. typedef long CoordType; class wxLayoutList; class wxLayoutObjectBase; class wxDC; class wxColour; class wxFont; /** The base class defining the interface to each object which can be part of the layout. Each object needs to draw itself and calculate its size. */ class wxLayoutObjectBase { public: struct UserData { virtual ~UserData() { } }; /// return the type of this object virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_INVALID; } ; /** Calculates the position etc of an object. @param dc the wxDC to draw on @param position where to draw the top left corner @param baseLine the baseline for alignment, from top of box */ virtual void Layout(wxDC & dc, wxPoint position, CoordType baseLine) { m_Position = position; } /** Draws an object. @param dc the wxDC to draw on @param translation to be added to coordinates */ virtual void Draw(wxDC & dc, wxPoint const &translate) {} /** Calculates and returns the size of the object. @param baseLine pointer where to store the baseline position of this object (i.e. the height from the top of the box to the baseline) @return the size of the object's box in pixels */ virtual wxPoint GetSize(CoordType * baseLine = NULL) const { return wxPoint(0,0); } /** Calculates and returns the position of the object. @return the size of the object's box in pixels */ virtual wxPoint GetPosition(void) const { return m_Position; } /// returns the number of cursor positions occupied by this object virtual CoordType CountPositions(void) const { return 1; } /// constructor wxLayoutObjectBase() { m_UserData = NULL; } /// delete the user data virtual ~wxLayoutObjectBase() { if(m_UserData) delete m_UserData; } #ifdef WXLAYOUT_DEBUG virtual void Debug(void); #endif /// query whether coordinates have changed since last drawing virtual bool IsDirty(void) const { return true; } /** Tells the object about some user data. This data is associated with the object and will be deleted at destruction time. */ void SetUserData(UserData *data) { m_UserData = data; } /** Return the user data. */ void * GetUserData(void) const { return m_UserData; } private: /// optional data for application's use UserData *m_UserData; protected: wxPoint m_Position; }; /// Define a list type of wxLayoutObjectBase pointers. KBLIST_DEFINE(wxLayoutObjectList, wxLayoutObjectBase); /// object for text block class wxLayoutObjectText : public wxLayoutObjectBase { public: wxLayoutObjectText(const String &txt); virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; } virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine); virtual void Draw(wxDC &dc, wxPoint const &translate); /** This returns the height and in baseLine the position of the text's baseline within it's box. This is needed to properly align text objects. */ virtual wxPoint GetSize(CoordType *baseLine = NULL) const; #ifdef WXLAYOUT_DEBUG virtual void Debug(void); #endif virtual CoordType CountPositions(void) const { return strlen(m_Text.c_str()); } virtual bool IsDirty(void) const { return m_IsDirty; } // for editing: String & GetText(void) { return m_Text; } void SetText(String const &text) { m_Text = text; } private: String m_Text; /// size of the box containing text long m_Width, m_Height; /// the position of the baseline counted from the top of the box long m_BaseLine; /// coordinates have changed bool m_IsDirty; }; /// icon/pictures: class wxLayoutObjectIcon : public wxLayoutObjectBase { public: wxLayoutObjectIcon(wxIcon *icon); wxLayoutObjectIcon(wxIcon const &icon); ~wxLayoutObjectIcon() { delete m_Icon; } virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_ICON; } virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine); virtual void Draw(wxDC &dc, wxPoint const &translate); virtual wxPoint GetSize(CoordType *baseLine = NULL) const; virtual bool IsDirty(void) const { return m_IsDirty; } private: wxIcon *m_Icon; /// coordinates have changed bool m_IsDirty; }; /// for export to html: struct wxLayoutStyleInfo { int size, family, style, weight; bool underline; unsigned fg_red, fg_green, fg_blue; unsigned bg_red, bg_green, bg_blue; }; /// pseudo-object executing a formatting command in Draw() class wxLayoutObjectCmd : public wxLayoutObjectBase { public: virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; } virtual void Draw(wxDC &dc, wxPoint const &translate); virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine); wxLayoutObjectCmd(int size, int family, int style, int weight, bool underline, wxColour const *fg, wxColour const *bg); ~wxLayoutObjectCmd(); /// caller must free pointer: wxLayoutStyleInfo *GetStyle(void) const ; /// return the background colour for setting colour of window wxColour const *GetBGColour(void) const { return m_ColourBG; } private: /// the font to use wxFont *m_font; /// foreground colour wxColour const *m_ColourFG; /// background colour wxColour const *m_ColourBG; }; /// this object doesn't do anything at all class wxLayoutObjectLineBreak : public wxLayoutObjectBase { public: virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_LINEBREAK; } }; class wxLayoutPrintout; class wxLayoutMargins { public: wxLayoutMargins() { top = left = 0; bottom = right = -1; } int top; int left; int bottom; int right; }; /** This class provides a high level abstraction to the wxFText classes. It handles most of the character events with its own callback functions, providing an editing ability. All events which cannot be handled get passed to the parent window's handlers. */ class wxLayoutList : public wxLayoutObjectList { public: wxLayoutList(); /// Destructor. ~wxLayoutList(); /// adds an object: void AddObject(wxLayoutObjectBase *obj); /// adds a text object void AddText(String const &txt); /// adds a line break void LineBreak(void); /// sets font parameters void SetFont(int family, int size, int style, int weight, int underline, wxColour const *fg, wxColour const *bg); /// sets font parameters, colours by name void SetFont(int family=-1, int size = -1, int style=-1, int weight=-1, int underline = -1, char const *fg = NULL, char const *bg = NULL); /// changes to the next larger font size inline void SetFontLarger(void) { SetFont(-1,(12*m_FontPtSize)/10); } /// changes to the next smaller font size inline void SetFontSmaller(void) { SetFont(-1,(10*m_FontPtSize)/12); } /// set font family inline void SetFontFamily(int family) { SetFont(family); } /// set font size inline void SetFontSize(int size) { SetFont(-1,size); } /// set font style inline void SetFontStyle(int style) { SetFont(-1,-1,style); } /// set font weight inline void SetFontWeight(int weight) { SetFont(-1,-1,-1,weight); } /// toggle underline flag inline void SetFontUnderline(bool ul) { SetFont(-1,-1,-1,-1,(int)ul); } /// set font colours by name inline void SetFontColour(char const *fg, char const *bg = NULL) { SetFont(-1,-1,-1,-1,-1,fg,bg); } /** Sets the wrap margin in cursor positions. @param n the wrap margin, -1 to disable auto wrap */ void SetWrapMargin(long n = -1); /// Wraps the current line if word wrap is enabled. void WrapLine(void); /** Re-layouts the list on a DC. @param dc the dc to layout for @param margins if not NULL, use these top and left margins */ void Layout(wxDC &dc, wxLayoutMargins *margins = NULL); /** Draw the list on a given DC. @param dc the dc to layout for @param fromLine the first graphics line from where to draw @param toLine the last line at which to draw @param start if != iterator(NULL) start drawing from here */ void Draw(wxDC &dc, CoordType fromLine = -1, CoordType toLine = -1, iterator start = iterator(NULL), wxPoint const &translate = wxPoint(0,0)); /** Deletes at least to the end of line and redraws */ void EraseAndDraw(wxDC &dc, iterator start = iterator(NULL), wxPoint const &translate = wxPoint(0,0)); /** Finds the object occupying a certain screen position. @return pointer to wxLayoutObjectBase or NULL if not found */ wxLayoutObjectBase *Find(wxPoint coords) const; #ifdef WXLAYOUT_DEBUG void Debug(void); void ShowCurrentObject(); #endif /// dirty? bool IsDirty() const { return m_bModified; } bool CursorMoved(void) const { return m_CursorMoved; } /// called after the contents is saved, for example void ResetDirty() { m_bModified = FALSE; } /// for access by wxLayoutWindow: void GetSize(CoordType *max_x, CoordType *max_y, CoordType *lineHeight); /**@name Functionality for editing */ //@{ /// set list editable or read only void SetEditable(bool editable = true) { m_Editable = editable; } /// return true if list is editable bool IsEditable(void) const { return m_Editable; } /// move cursor, returns true if it could move to the desired position bool MoveCursor(int dx = 0, int dy = 0); void SetCursor(wxPoint const &p); void DrawCursor(wxDC &dc, bool erase = false,wxPoint const &translate = wxPoint(0,0)); /// Get current cursor position cursor coords wxPoint GetCursor(void) const { return m_CursorPos; } /// Gets graphical coordinates of cursor wxPoint GetCursorCoords(void) const { return m_CursorCoords; } /// delete one or more cursor positions void Delete(CoordType count = 1); void Insert(String const &text); void Insert(wxLayoutObjectBase *obj); void Clear(int family = wxROMAN, int size=WXLO_DEFAULTFONTSIZE, int style=wxNORMAL, int weight=wxNORMAL, int underline=0, char const *fg="black", char const *bg="white"); /// return a pointer to the default settings (dangerous, why?) FIXME: wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; } /// returns the iterator for the object under the cursor wxLayoutObjectList::iterator GetCurrentObject(CoordType *offset = NULL) { if(offset) *offset = m_CursorOffset; return m_CursorObject; } // get the length of the line with the object pointed to by i, offs // only used to decide whether we are before or after linebreak CoordType GetLineLength(wxLayoutObjectList::iterator i, CoordType offs = 0); wxLayoutPrintout *MakePrintout(wxString const &name); /// Return maximum X,Y coordinates wxPoint GetSize(void) const { return wxPoint(m_MaxX, m_MaxY); } /// calculates current cursor coordinates, called in Layout() void CalculateCursor(wxDC &dc); /// toggle normal/bold cursor void SetBoldCursor(bool bold = true) { m_boldCursor = bold; m_CursorMoved = true;} //@} protected: /// font parameters: int m_FontFamily, m_FontStyle, m_FontWeight; int m_FontPtSize; bool m_FontUnderline; /// colours: wxColour const * m_ColourFG; wxColour const * m_ColourBG; /// the default setting: wxLayoutObjectCmd *m_DefaultSetting; /// needs recalculation? bool m_dirty; /// cursor moved bool m_CursorMoved; /// needs saving (i.e., was modified?) bool m_bModified; // the currently updated line: /// where do we draw next: wxPoint m_Position; /// the height of the current line: CoordType m_LineHeight; /// maximum drawn x position so far CoordType m_MaxX; /// maximum drawn y position: CoordType m_MaxY; //---- this is needed for editing: /// where is the text cursor (column,line): wxPoint m_CursorPos; /// where to draw the cursor wxPoint m_CursorCoords; /// how large to draw it wxPoint m_CursorSize; /// object iterator for current cursor position: iterator m_CursorObject; /// position of cursor within m_CursorObject: CoordType m_CursorOffset; /// to store content overwritten by cursor wxMemoryDC m_CursorMemDC; /// which is the last line CoordType m_MaxLine; /// can we edit it? bool m_Editable; /// find the object to the cursor position and returns the offset /// in there wxLayoutObjectList::iterator FindObjectCursor(wxPoint *cpos, CoordType *offset = NULL); /// get the wrap margin inline long GetWrapMargin(void) const { return m_WrapMargin; } /// do we do wrapping? inline bool DoWordWrap(void) const { return m_WrapMargin != -1; } private: /// Resets the font settings etc to default values void ResetSettings(wxDC &dc); /// remembers the last cursor position for which FindObjectCursor was called wxPoint m_FoundCursor; /// remembers the iterator to the object related to m_FoundCursor wxLayoutObjectList::iterator m_FoundIterator; /// the wrap margin long m_WrapMargin; /// draw a bold cursor? bool m_boldCursor; }; class wxLayoutPrintout: public wxPrintout { public: wxLayoutPrintout(wxLayoutList &llist, wxString const & title = "wxLayout Printout"); bool OnPrintPage(int page); bool HasPage(int page); bool OnBeginDocument(int startPage, int endPage); void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo); void OnPreparePrinting(void); protected: virtual void DrawHeader(wxDC &dc, wxPoint topleft, wxPoint bottomright, int pageno); private: wxLayoutList *m_llist; wxString m_title; int m_PageHeight, m_PageWidth; // how much we actually print per page int m_PrintoutHeight; wxLayoutMargins m_Margins; int m_NumOfPages; }; #endif // WXLLIST_H