/*-*- c++ -*-********************************************************
* wxLayoutList.h - a formatted text rendering engine for wxWindows *
* *
- * (C) 1999 by Karsten Ballüder (Ballueder@usa.net) *
+ * (C) 1999-2000 by Karsten Ballüder (ballueder@gmx.net) *
* *
* $Id$
*******************************************************************/
#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"
-#include "wx/dataobj.h"
+#include <wx/wx.h>
+#include <wx/print.h>
+#include <wx/printdlg.h>
+#include <wx/generic/printps.h>
+#include <wx/generic/prntdlgg.h>
+#include <wx/dataobj.h>
// skip the following defines if embedded in M application
#ifndef M_BASEDIR
# define WXMENU_LAYOUT_LCLICK 1111
# define WXMENU_LAYOUT_RCLICK 1112
# define WXMENU_LAYOUT_DBLCLICK 1113
+#else // for Mahogany only
+# include "MObject.h"
#endif
// use the wxWindows caret class instead of home grown cursor whenever possible
#ifdef __WXMSW__
- #undef WXLAYOUT_USE_CARET
- #define WXLAYOUT_USE_CARET 1
+# undef WXLAYOUT_USE_CARET
+# define WXLAYOUT_USE_CARET 1
#endif // __WXMSW__
-// do not enable debug mode within Mahogany
-#if defined(__WXDEBUG__) && ! defined(M_BASEDIR)
+// do not enable debug mode within Mahogany unless in debug mode
+#if defined(__WXDEBUG__) && (( ! defined(M_BASEDIR) )|| defined(DEBUG))
# define WXLAYOUT_DEBUG
#endif
#ifdef WXLAYOUT_DEBUG
# define WXLO_TRACE(x) wxLogDebug(x)
+// activate profiling: # define WXLO_PROFILE
#else
# define WXLO_TRACE(x)
#endif
+/* Some profiling code: */
+#if defined (WXLO_PROFILE)
+#include <sys/time.h>
+#include <unistd.h>
+
+# define WXLO_TIMER_DEFINE(x) static struct timeval x
+# define WXLO_TIMER_START(x) gettimeofday(&x,NULL)
+# define WXLO_TIMER_STOP(x) { struct timeval y; \
+ gettimeofday(&y,NULL); \
+ x.tv_sec -= y.tv_sec; x.tv_usec -= y.tv_usec; }
+# define WXLO_TIMER_PRINT(x) wxLogDebug("Timer " #x " elapsed: %ld", \
+ (long)(x.tv_sec * -1000 - x.tv_usec));
+#else
+# define WXLO_TIMER_DEFINE(x)
+# define WXLO_TIMER_START(x)
+# define WXLO_TIMER_STOP(x)
+# define WXLO_TIMER_PRINT(x)
+#endif
+
+
#define WXLO_DEBUG_URECT 0
#ifndef WXLO_DEFAULTFONTSIZE
/// command object, containing font or colour changes
WXLO_TYPE_CMD,
/// icon object, any kind of image
- WXLO_TYPE_ICON
+ WXLO_TYPE_ICON,
+ /// a linebreak, does not exist as an object
+ WXLO_TYPE_LINEBREAK
};
/// Type used for coordinates in drawing. Must be signed.
its size.
*/
class wxLayoutObject
+#ifdef M_BASEDIR
+ : public MObject
+#endif
{
public:
/** This structure can be used to contain data associated with the
virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
#ifdef WXLAYOUT_DEBUG
- virtual void Debug(void);
+ virtual wxString DebugDump(void) const;
#endif
/** Tells the object about some user data. This data is associated
*/
static wxLayoutObject *Read(wxString &istr);
//@}
+
+ /// returns TRUE if the object is shown on the screen (i.e. not cmd object)
+ bool IsVisibleObject() const { return GetType() != WXLO_TYPE_CMD; }
+
protected:
/// optional data for application's use
UserData *m_UserData;
+#if defined (M_BASEDIR) && defined (DEBUG)
+ MOBJECT_NAME(wxLayoutObject)
+#endif
};
/// Define a list type of wxLayoutObject pointers.
/// An illegal iterator to save typing.
#define NULLIT (wxLayoutObjectList::iterator(NULL))
/// The iterator type.
-#define wxLOiterator wxLayoutObjectList::iterator
+typedef wxLayoutObjectList::iterator wxLOiterator;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
static wxLayoutObjectText *Read(wxString &istr);
#ifdef WXLAYOUT_DEBUG
- virtual void Debug(void);
+ virtual wxString DebugDump(void) const;
#endif
- virtual CoordType GetLength(void) const { return strlen(m_Text.c_str()); }
+ virtual CoordType GetLength(void) const { return wxStrlen(m_Text.c_str()); }
// for editing:
wxString & GetText(void) { return m_Text; }
wxBitmap *m_Icon;
};
-/** This structure holds all formatting information. Members which are
- undefined (for a CmdObject this means: no change), are set to -1.
+/** This structure holds all formatting information.
*/
struct wxLayoutStyleInfo
{
int iul = -1,
wxColour *fg = NULL,
wxColour *bg = NULL);
- wxColour & GetBGColour()
- {
- return m_bg;
- }
wxLayoutStyleInfo & operator=(const wxLayoutStyleInfo &right);
+
+ wxColour & GetBGColour() { return m_bg; }
+
/// Font change parameters.
int size, family, style, weight, underline;
/// Colours
int m_fg_valid, m_bg_valid; // bool, but must be int!
};
-
+/// a cached font
class wxFontCacheEntry
{
public:
}
private:
wxFont *m_Font;
+
+ // VZ: I wonder why it doesn't use wxLayoutStyleInfo instead of those?
int m_Family, m_Size, m_Style, m_Weight;
bool m_Underline;
};
int underline = -1,
wxColour *fg = NULL,
wxColour *bg = NULL);
+ wxLayoutObjectCmd(const wxLayoutStyleInfo &si);
~wxLayoutObjectCmd();
/** Stores the current style in the styleinfo structure */
wxLayoutStyleInfo * GetStyle(void) const;
void Append(wxLayoutObject * obj)
{
wxASSERT(obj);
-
m_ObjectList.push_back(obj);
m_Length += obj->GetLength();
}
+ /** This function prepends an object to the line. */
+ void Prepend(wxLayoutObject * obj)
+ {
+ wxASSERT(obj);
+ m_ObjectList.push_front(obj);
+ m_Length += obj->GetLength();
+ }
+
/** This function appens the next line to this, i.e. joins the two
lines into one.
*/
*/
wxLayoutLine *Break(CoordType xpos, wxLayoutList *llist);
+ /** This function wraps the line: breaks it at a suitable point
+ and merges it with the next.
+ @param wrapmargin
+ @return TRUE if broken
+ */
+ bool Wrap(CoordType wrapmargin, wxLayoutList *llist);
+
/** Deletes the next word from this position, including leading
whitespace.
This function does not delete over font changes, i.e. a word
/** Finds the object which covers the screen position xpos in this
line.
@param dc the wxDC to use for calculations
+ @param llist the layout list to which this line belongs
@param xpos the screen x coordinate
@param offset where to store the difference between xpos and
the object's head
@return iterator to the object or NULLIT
*/
wxLayoutObjectList::iterator FindObjectScreen(wxDC &dc,
+ wxLayoutList *llist,
CoordType xpos,
CoordType *offset,
bool *found = NULL) const ;
functions to export the list.
@return iterator to the first object
*/
- wxLayoutObjectList::iterator GetFirstObject(void)
+ wxLayoutObjectList::iterator GetFirstObject(void) const
{
return m_ObjectList.begin();
}
+ /** Get the last object in the list.
+ */
+ wxLayoutObjectList::iterator GetLastObject(void) const
+ {
+ return m_ObjectList.tail();
+ }
+
/** Deletes this line, returns pointer to next line.
@param update If true, update all following lines.
*/
@param llist th e wxLayoutList
@param cursorPos if not NULL, set cursor screen position in there
@param cursorSize if not cursorPos != NULL, set cursor size in there
+ @param cursorStyle if non NULL where to store styleinfo for cursor pos
@param cx if cursorPos != NULL, the cursor x position
@param suppressStyleUpdate FALSe normally, only to suppress updating of m_StyleInfo
*/
wxLayoutList *llist,
wxPoint *cursorPos = NULL,
wxPoint *cursorSize = NULL,
+ wxLayoutStyleInfo *cursorStyle = NULL,
int cx = 0,
bool suppressStyleUpdate = FALSE);
/** This function finds an object belonging to a given cursor
for that position
@return pointer to the object
*/
- wxLayoutObject * FindObjectScreen(wxDC &dc, CoordType xpos, bool
- *found = NULL);
+ wxLayoutObject * FindObjectScreen(wxDC &dc,
+ CoordType xpos,
+ bool *found = NULL);
/** This sets the style info for the beginning of this line.
@param si styleinfo structure
*/
void ApplyStyle(const wxLayoutStyleInfo &si)
- { m_StyleInfo = si; }
+ { m_StyleInfo = si; }
//@}
CoordType GetHeight(void) const { return m_Height; }
/// Returns the width of this line.
CoordType GetWidth(void) const { return m_Width; }
- /** This will recalculate the position and size of this line.
- If called recursively it will abort if the position of an
- object is unchanged, assuming that none of the following
- objects need to move.
- @param recurse if greater 0 then it will be used as the
- minimum(!) recursion level, continue with all lines till the end of
- the list or until the coordinates no longer changed.
- */
- void RecalculatePositions(int recurse, wxLayoutList *llist);
/// Recalculates the position of this line on the canvas.
wxPoint RecalculatePosition(wxLayoutList *llist);
CoordType to = -1);
#ifdef WXLAYOUT_DEBUG
- void Debug(void);
+ void Debug(void) const;
#endif
wxLayoutStyleInfo const & GetStyleInfo() const { return m_StyleInfo; }
}
m_Dirty = true;
+ if(m_Next) m_Next->MarkDirty();
}
- /** Marks the following lines as dirty.
- @param recurse if -1 recurse to end of list, otherwise depth of recursion.
- */
- void MarkNextDirty(int recurse = 0);
/// Reset the dirty flag
void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
@param height new height
*/
void SetHeight(CoordType height, wxLayoutList *llist)
- { m_Height = height; RecalculatePositions(true, llist); }
+ { m_Height = height; MarkDirty(); }
- /** Moves the linenumbers one on, because a line has been inserted
- or deleted.
- @param delta either +1 or -1
- */
- void MoveLines(int delta)
- {
- m_LineNumber += delta;
- if(m_Next) m_Next->MoveLines(delta);
- }
+ /** Updates the line numbers. */
+ void ReNumber(void);
//@}
private:
/// The line number.
/// Empty: clear the list but leave font settings.
void Empty(void);
+ /** Enable or disable auto-formatting. Normally, while editing this
+ should be enabled which is the default. While
+ inserting/deleting lots of text, it makes sense to temporarily
+ disable this.
+ @param enable TRUE to enable, FALSE to disable
+ */
+ void SetAutoFormatting(bool enable = TRUE)
+ { m_AutoFormat = enable; }
/**@name Cursor Management */
//@{
/** Set new cursor position.
bool MoveCursorHorizontally(int n);
/** Move cursor to the left or right counting in words
@param n = number of positions in words
+ @param untilNext: puts the cursor at the start of the next word if true,
+ leaves it at the end of the current one otherwise
@return bool if it could be moved
*/
- bool MoveCursorWord(int n);
+ bool MoveCursorWord(int n, bool untilNext = true);
/// Move cursor to end of line.
void MoveCursorToEndOfLine(void)
MoveCursorHorizontally(m_CursorLine->GetLength()-m_CursorPos.x);
}
- /// Move cursor to begin of line.
+ /// Move cursor to the start of line.
void MoveCursorToBeginOfLine(void)
{ MoveCursorHorizontally(-m_CursorPos.x); }
+ /// get the number of lines in the list
+ size_t GetNumLines() const { return m_numLines; }
+
/// Returns current cursor position.
const wxPoint &GetCursorPos(wxDC &dc) const { return m_CursorPos; }
const wxPoint &GetCursorPos() const { return m_CursorPos; }
+ wxLayoutLine * GetCursorLine(void) { return m_CursorLine; }
+
+ /// move cursor to the end of text
+ void MoveCursorToEnd(void)
+ {
+ MoveCursorTo(wxPoint(0, GetNumLines() - 1));
+ MoveCursorToEndOfLine();
+ }
//@}
@return true if line got broken
*/
bool WrapLine(CoordType column);
+
+ /** Wraps the complete buffer.
+ @param column the break position for the line, maximum length
+ @return true if line got broken
+ */
+ bool WrapAll(CoordType column);
/** This function deletes npos cursor positions.
@param npos how many positions
@return true if everything got deleted
inline void SetFontColour(wxColour *fg, wxColour *bg = NULL)
{ SetFont(-1,-1,-1,-1,-1,fg,bg); }
-
/**
Returns a pointer to the default settings.
This is only valid temporarily and should not be stored
*/
wxLayoutStyleInfo &GetDefaultStyleInfo(void) { return m_DefaultStyleInfo ; }
wxLayoutStyleInfo &GetStyleInfo(void) { return m_CurrentStyleInfo ; }
+ const wxLayoutStyleInfo &GetStyleInfo(void) const { return m_CurrentStyleInfo ; }
+ const wxLayoutStyleInfo &GetCursorStyleInfo(void) const { return m_CursorStyleInfo ; }
+
+ /// is the current font underlined?
+ bool IsFontUnderlined() const { return GetCursorStyleInfo().underline != 0; }
+ /// is the current font bold?
+ bool IsFontBold() const { return GetCursorStyleInfo().weight == wxBOLD; }
+ /// is the current font italic?
+ bool IsFontItalic() const { return GetCursorStyleInfo().style == wxITALIC; }
+
+ /// set underline if it was off, turn it off if it was on
+ void ToggleFontUnderline()
+ { SetFontUnderline(!IsFontUnderlined()); }
+
+ /// make font bold if it was normal or make it normal if it was bold
+ void ToggleFontWeight()
+ { SetFontWeight(IsFontBold() ? wxNORMAL : wxBOLD); }
+
+ /// make font italic if it was normal or make it normal if it was italic
+ void ToggleFontItalics()
+ { SetFontStyle(IsFontItalic() ? wxNORMAL : wxITALIC); }
+
//@}
/**@name Drawing */
@param offset an optional offset to shift printout
@param top optional y coordinate where to start drawing
@param bottom optional y coordinate where to stop drawing
+ @param clipStrictly if set, do not draw objects which reach
+ beyond "bottom". Set this when printing.
*/
void Draw(wxDC &dc,
const wxPoint &offset = wxPoint(0,0),
- CoordType top = -1, CoordType bottom = -1);
+ CoordType top = -1, CoordType bottom = -1,
+ bool clipStrictly = false);
/** Calculates new layout for the list, like Draw() but does not
actually draw it.
@param dc the wxDC to draw on
@param bottom optional y coordinate where to stop calculating
@param forceAll force re-layout of all lines
+ @param cpos Can hold a cursorposition, and will be overwritten
+ with the corresponding DC position.
+ @param csize Will hold the cursor size relating to cpos.
*/
- void Layout(wxDC &dc, CoordType bottom = -1, bool forceAll = false);
+ void Layout(wxDC &dc, CoordType bottom = -1, bool forceAll = false,
+ wxPoint *cpos = NULL,
+ wxPoint *csize = NULL);
+
+ /** Ensure that the whole list will be recalculate on the next call
+ to Layout() or Draw().
+ @param redrawAll TRUE or FALSE to reset it
+ */
+ void ForceTotalLayout(bool redrawAll = TRUE)
+ { m_ReLayoutAll = redrawAll; }
+
+ /** Returns the screen coordinates relating to a given cursor
+ position and the size of the cursor at that position.
+ @param dc for which to calculate it
+ @param cpos Cursor position to look for.
+ @param csize If non-NULL, will be set to the cursor size.
+ @return The cursor position on the DC.
+ */
+ wxPoint GetScreenPos(wxDC &dc, const wxPoint &cpos, wxPoint *csize = NULL);
/** Calculates new sizes for everything in the list, like Layout()
but this is needed after the list got changed.
wxPoint GetSize(void) const;
/** Returns the cursor position on the screen.
- @return cursor position in pixels
- */
- wxPoint GetCursorScreenPos(wxDC &dc);
- /** Calculates the cursor position on the screen.
- @param dc the dc to use for cursor position calculations
- @param resetCursorMovedFlag: if true, reset "cursor moved" flag
- @param translate optional translation of cursor coords on screen
-
*/
- void UpdateCursorScreenPos(wxDC &dc,
- bool resetCursorMovedFlag = true,
- const wxPoint& translate = wxPoint(0,
- 0));
+ wxPoint GetCursorScreenPos(void) const;
/** Draws the cursor.
@param active If true, draw a bold cursor to mark window as
/// adds the cursor position to the update rectangle
void AddCursorPosToUpdateRect()
{
- #ifndef WXLAYOUT_USE_CARET
- SetUpdateRect(m_CursorScreenPos);
- SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+#ifndef WXLAYOUT_USE_CARET
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
//#else - the caret will take care of refreshing itself
- #endif // !WXLAYOUT_USE_CARET
+#endif // !WXLAYOUT_USE_CARET
}
/// Invalidates the update rectangle.
void InvalidateUpdateRect(void) { m_UpdateRectValid = false; }
/// Discard the current selection
void DiscardSelection();
/// Are we still selecting text?
- bool IsSelecting(void);
+ bool IsSelecting(void) const;
/// Is the given point (text coords) selected?
- bool IsSelected(const wxPoint &cursor);
+ bool IsSelected(const wxPoint &cursor) const;
/// Do we have a non null selection?
bool HasSelection() const
{ return m_Selection.m_valid || m_Selection.m_selecting; }
void Debug(void);
#endif
+ // for wxLayoutLine usage only
+ void IncNumLines() { m_numLines++; }
+ void DecNumLines() { m_numLines--; }
+
+ /// get the line by number
+ wxLayoutLine *GetLine(CoordType index) const;
+
+ /** Reads objects from a string and inserts them. Returns NULL if
+ string is empty or a linebreak was found.
+ @param istr stream to read from, will bee changed
+ */
+ void Read(wxString &istr);
+
private:
/// Clear the list.
void InternalClear(void);
/// The list of lines.
wxLayoutLine *m_FirstLine;
+ /// The number of lines in the list (store instead recalculating for speed)
+ size_t m_numLines;
+
/// The update rectangle which needs to be refreshed:
wxRect m_UpdateRect;
/// Is the update rectangle valid?
bool m_UpdateRectValid;
+
+ /// Shall we auto-format?
+ bool m_AutoFormat;
+ /// Shall we re-layout everything?
+ bool m_ReLayoutAll;
/**@name Cursor Management */
//@{
/// Where the text cursor (column,line) is.
/// selection.state and begin/end coordinates
struct Selection
{
- Selection() { m_valid = false; m_selecting = false; }
+ Selection() { m_valid = m_selecting = m_discarded = false; }
+
bool m_valid;
bool m_selecting;
+ bool m_discarded; // may be TRUE only until the next redraw
// returns true if we already have the screen coordinates of the
// selection start and end
wxLayoutStyleInfo m_DefaultStyleInfo;
/// the current setting:
wxLayoutStyleInfo m_CurrentStyleInfo;
+ /// the current setting:
+ wxLayoutStyleInfo m_CursorStyleInfo;
//@}
};
own format.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-class wxLayoutDataObject : public wxPrivateDataObject
+class wxLayoutDataObject : public wxCustomDataObject
{
public:
- wxLayoutDataObject(void)
+ wxLayoutDataObject()
{
- SetId("application/wxlayoutlist");
- //m_format.SetAtom((GdkAtom) 222222);
+ SetFormat(wxT("application/wxlayoutlist"));
}
+
+ // type safe wrappers
+ void SetLayoutData(const wxString& text)
+ { SetData(text.length() + 1, text.c_str()); }
+ const char *GetLayoutData() const { return (const char *)GetData(); }
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *