- dmalloc shows duplicate deletion after merging two lines and
deleting the second half
+- printout page calculation still a bit wrong
+- word wrap for objects with lots of non-space needs to search in positive
+direction if begin of first object is reached
+
TODO
=====================================================================
-
+- replacement of llist in window
+- undo
- Selections
- More optimisations
enum ids{ ID_ADD_SAMPLE = 1, ID_CLEAR, ID_PRINT,
ID_PRINT_SETUP, ID_PAGE_SETUP, ID_PREVIEW, ID_PRINT_PS,
ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS,
- ID_WRAP, ID_NOWRAP,
+ ID_WRAP, ID_NOWRAP, ID_PASTE,
ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT, ID_TEST };
SetStatusText( "wxLayout by Karsten Ballüder." );
+ wxMenuBar *menu_bar = new wxMenuBar();
+
wxMenu *file_menu = new wxMenu;
- file_menu->Append( ID_CLEAR, "Clear");
- file_menu->Append( ID_ADD_SAMPLE, "Example");
-
file_menu->Append(ID_PRINT, "&Print...", "Print");
file_menu->Append(ID_PRINT_SETUP, "Print &Setup...","Setup printer properties");
file_menu->Append(ID_PAGE_SETUP, "Page Set&up...", "Page setup");
file_menu->Append(ID_PAGE_SETUP_PS, "Page Setup PostScript...", "Page setup (PostScript)");
file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)");
#endif
- file_menu->AppendSeparator();
- file_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200.");
- file_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping.");
-
file_menu->AppendSeparator();
file_menu->Append( ID_TEXT, "Export Text");
file_menu->Append( ID_HTML, "Export HTML");
file_menu->Append( ID_QUIT, "Exit");
-
- wxMenuBar *menu_bar = new wxMenuBar();
menu_bar->Append(file_menu, "File" );
+ wxMenu *edit_menu = new wxMenu;
+ edit_menu->Append( ID_CLEAR, "Clear");
+ edit_menu->Append( ID_ADD_SAMPLE, "Example");
+ edit_menu->AppendSeparator();
+ edit_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200.");
+ edit_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping.");
+ edit_menu->AppendSeparator();
+ edit_menu->Append(ID_PASTE, "Paste", "Paste text from clipboard.");
+ menu_bar->Append(edit_menu, "Edit" );
+
#ifndef __WXMSW__
menu_bar->Show( TRUE );
#endif // MSW
case ID_CLICK:
cerr << "Received click event." << endl;
break;
+ case ID_PASTE:
+ m_lwin->Paste();
+ break;
case ID_HTML:
{
wxLayoutExportObject *export;
return p1.x != p2.x || p1.y != p2.y;
}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
wxLayoutObjectText
m_Bottom = 0;
}
+wxLayoutObject *
+wxLayoutObjectText::Copy(void)
+{
+ wxLayoutObjectText *obj = new wxLayoutObjectText(m_Text);
+ obj->m_Width = m_Width;
+ obj->m_Height = m_Height;
+ obj->m_Top = m_Top;
+ obj->m_Bottom = m_Bottom;
+ obj->SetUserData(m_UserData);
+ return obj;
+}
wxPoint
wxLayoutObjectText::GetSize(CoordType *top, CoordType *bottom) const
m_Icon = new wxBitmap(icon);
}
+wxLayoutObject *
+wxLayoutObjectIcon::Copy(void)
+{
+ wxLayoutObjectIcon *obj = new wxLayoutObjectIcon(new
+ wxBitmap(*m_Icon));
+ obj->SetUserData(m_UserData);
+ return obj;
+}
+
wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon)
{
m_Icon = icon;
m_ColourBG = bg;
}
+wxLayoutObject *
+wxLayoutObjectCmd::Copy(void)
+{
+ wxLayoutStyleInfo si;
+ GetStyle(&si);
+
+ wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
+ si.size, si.family, si.style, si.weight, si.underline,
+ m_ColourFG, m_ColourBG);
+ obj->SetUserData(m_UserData);
+ return obj;
+}
+
+
wxLayoutObjectCmd::~wxLayoutObjectCmd()
{
delete m_font;
column--;
}
}while(offset != -1);
+ i--; // move on to previous object
}
else
+ {
column -= (**i).GetLength();
- // This is both "else" and what has to be done after checking
- // all positions of the text object:
- i--;
- offset = (**i).GetLength();
+ i--;
+ }
+ if( i != NULLIT)
+ offset = (**i).GetLength();
}while(i != NULLIT);
- return -1;
+ /* If we reached the begin of the list and have more than one
+ object, that one is longer than the margin, so break behind
+ it. */
+ CoordType pos = 0;
+ i = m_ObjectList.begin();
+ while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
+ {
+ pos += (**i).GetLength();
+ i++;
+ }
+ if(i == NULLIT) return -1; //why should this happen?
+ pos += (**i).GetLength();
+ i++;
+ while(i != NULLIT && (**i).GetType() != WXLO_TYPE_TEXT)
+ {
+ pos += (**i).GetLength();
+ i++;
+ }
+ if(i == NULLIT) return -1; //this is possible, if there is only one text object
+ // now we are at the second text object:
+ pos -= (**i).GetLength();
+ return pos; // in front of it
}
{
m_DefaultSetting = NULL;
m_FirstLine = NULL;
- InternalClear();
+ Clear();
}
wxLayoutList::~wxLayoutList()
}
void
-wxLayoutList::InternalClear(void)
+wxLayoutList::Empty(void)
{
while(m_FirstLine)
m_FirstLine = m_FirstLine->DeleteLine(false);
- if(m_DefaultSetting)
- {
- delete m_DefaultSetting;
- m_DefaultSetting = NULL;
- }
-
m_CursorPos = wxPoint(0,0);
m_CursorScreenPos = wxPoint(0,0);
m_CursorSize = wxPoint(0,0);
m_CursorLine = m_FirstLine;
}
+
+void
+wxLayoutList::InternalClear(void)
+{
+ Empty();
+ if(m_DefaultSetting)
+ {
+ delete m_DefaultSetting;
+ m_DefaultSetting = NULL;
+ }
+}
+
void
wxLayoutList::SetFont(int family, int size, int style, int weight,
int underline, wxColour const *fg,
{
wxLayoutLine *line = m_FirstLine;
while(line && line->GetLineNumber() != p.y)
- ;
+ line = line->GetNextLine();
if(line && line->GetLineNumber() == p.y) // found it
{
m_CursorPos.y = p.y;
class wxLayoutObject
{
public:
- /// This structure can be used to contain data associated with the object.
+ /** This structure can be used to contain data associated with the
+ object.
+ It is refcounted, so the caller has to do a DecRef() on it
+ instead of a delete.
+ */
struct UserData
{
- virtual ~UserData() { }
+ UserData() { m_refcount = 1; }
+ void IncRef(void) { m_refcount++; }
+ void DecRef(void) { m_refcount--; if(m_refcount == 0) delete this;}
+ private:
+ int m_refcount;
+ protected:
+ virtual ~UserData() { wxASSERT(m_refcount == 0); }
+ /// prevents gcc from generating stupid warnings
+ friend class dummy_UserData;
};
/// return the type of this object
/// constructor
wxLayoutObject() { m_UserData = NULL; }
/// delete the user data
- virtual ~wxLayoutObject() { if(m_UserData) delete m_UserData; }
+ virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
#ifdef WXLAYOUT_DEBUG
virtual void Debug(void);
/** 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; }
+ void SetUserData(UserData *data)
+ {
+ if(m_UserData)
+ m_UserData->DecRef();
+ m_UserData = data;
+ m_UserData->IncRef();
+ }
+ /** Return the user data. */
+ void * GetUserData(void) const { if(m_UserData) m_UserData->IncRef(); return m_UserData; }
+
+ /** Makes a copy of this object.
+ */
+ virtual wxLayoutObject *Copy(void) = 0;
private:
/// optional data for application's use
UserData *m_UserData;
// for editing:
wxString & GetText(void) { return m_Text; }
void SetText(wxString const &text) { m_Text = text; }
-
+ /** Makes a copy of this object.
+ */
+ virtual wxLayoutObject *Copy(void);
private:
wxString m_Text;
/// size of the box containing text
virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const;
/// Return just the width of the object on the screen.
virtual CoordType GetWidth(void) const { return m_Icon->GetWidth(); }
-
+ // return a pointer to the icon
+ wxBitmap *GetIcon(void) const { return m_Icon; }
+ /** Makes a copy of this object.
+ */
+ virtual wxLayoutObject *Copy(void);
private:
wxBitmap *m_Icon;
};
void GetStyle(wxLayoutStyleInfo *si) const;
/// return the background colour for setting colour of window
wxColour const *GetBGColour(void) const { return m_ColourBG; }
+ /** Makes a copy of this object.
+ */
+ virtual wxLayoutObject *Copy(void);
private:
/// the font to use
wxFont *m_font;
int underline=0,
char const *fg="black",
char const *bg="white");
-
+ /// Empty: clear the list but leave font settings.
+ void Empty(void);
+
/**@name Cursor Management */
//@{
/** Set new cursor position.
(((*p == '\r') && (*(p + 1) == '\n'))||(*p == '\n'));
}
-void wxLayoutImportText(wxLayoutList &list, wxString const &str, int withflag)
+void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
{
char * cptr = (char *)str.c_str(); // string gets changed only temporarily
const char * begin = cptr;
cptr++;
backup = *cptr;
*cptr = '\0';
- list.Insert(begin);
+ list->Insert(begin);
*cptr = backup;
// check if it's the end of this line
// if it was "\r\n", skip the following '\n'
if ( *cptr == '\r' )
cptr++;
- list.LineBreak();
+ list->LineBreak();
}
else if(backup == '\0') // reached end of string
break;
{
wxASSERT(status);
wxLayoutExportObject * export;
-
+
if(status->m_iterator == NULLIT) // end of line
{
if(!status->m_line || status->m_line->GetNextLine() == NULL) // reached end of list
status->m_line = status->m_line->GetNextLine();
status->m_iterator = status->m_line->GetFirstObject();
export = new wxLayoutExportObject();;
+ if( (mode & WXLO_EXPORT_AS_MASK) == WXLO_EXPORT_AS_OBJECTS) // simple case
+ {
+ export->type = WXLO_EXPORT_OBJECT;
+ export->content.object = *status->m_iterator;
+ status->m_iterator++;
+ return export;
+ }
+ //else: text object:
export->type = ((mode & WXLO_EXPORT_AS_MASK) == WXLO_EXPORT_AS_HTML)
? WXLO_EXPORT_HTML : WXLO_EXPORT_TEXT;
if((mode & WXLO_EXPORT_WITH_CRLF) == WXLO_EXPORT_WITH_CRLF)
#ifdef OS_WIN
/// import text into a wxLayoutList (including linefeeds):
-void wxLayoutImportText(wxLayoutList &list, wxString const &str,
+void wxLayoutImportText(wxLayoutList *list, wxString const &str,
int withflag = WXLO_EXPORT_WITH_CRLF);
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
int mode = WXLO_EXPORT_AS_TEXT|WXLO_EXPORT_WITH_CRLF);
#else
/// import text into a wxLayoutList (including linefeeds):
-void wxLayoutImportText(wxLayoutList &list, wxString const &str,
+void wxLayoutImportText(wxLayoutList *list, wxString const &str,
int withflag = WXLO_EXPORT_WITH_LF_ONLY);
/// export text in a given format FIXME-MT: not thread safe, uses static variable
# undef StartDoc
# endif
# include "wxlwindow.h"
+# include "wxlparser.h"
#endif
#include <ctype.h>
-
+#include <wx/clipbrd.h>
#define WXLO_XOFFSET 4
#define WXLO_YOFFSET 4
void
wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
{
- DoPaint();
+ m_ScrollToCursor = false;
+ InternalPaint();
}
void
wxLayoutWindow::DoPaint(bool scrollToCursor)
+{
+ m_ScrollToCursor = scrollToCursor;
+#ifdef __WXGTK__
+ InternalPaint();
+#else
+ Refresh();
+#endif
+}
+
+void
+wxLayoutWindow::InternalPaint(void)
{
wxPaintDC dc( this );
PrepareDC( dc );
/* Make sure that the scrollbars are at a position so that the
cursor is visible if we are editing. */
/** Scroll so that cursor is visible! */
- if(IsEditable() && scrollToCursor)
+ if(IsEditable() && m_ScrollToCursor)
{
wxPoint cc = m_llist->GetCursorScreenPos();
if(cc.x < x0 || cc.y < y0
}
}
+void
+wxLayoutWindow::Paste(void)
+{
+ // Read some text
+ if (wxTheClipboard->Open())
+ {
+ wxTextDataObject data;
+ if (wxTheClipboard->IsSupported(wxDF_TEXT))
+ {
+ wxTheClipboard->GetData(&data);
+ wxLayoutImportText( m_llist, data.GetText());
+ }
+ wxTheClipboard->Close();
+ }
+}
+
wxMenu *
wxLayoutWindow::MakeFormatMenu()
# include <wx/wx.h>
#endif
-#include "wxllist.h"
+#include "wxllist.h"
#ifndef WXLOWIN_MENU_FIRST
# define WXLOWIN_MENU_FIRST 12000
void SetEditable(bool toggle) { m_Editable = toggle; }
/// Query whether list can be edited by user.
bool IsEditable(void) const { return m_Editable; }
-
+ /// Pastes text from clipboard.
+ void Paste(void);
+
//@}
void EnablePopup(bool enable = true) { m_DoPopupMenu = enable; }
void SetWrapMargin(CoordType margin) { m_WrapMargin = margin; }
/** Redraws the window.
+ Internally, this stores the parameter and calls a refresh on
+ wxMSW, draws directly on wxGTK.
@param scrollToCursor if true, scroll the window so that the
cursor becomes visible
*/
/// Creates a wxMenu for use as a format popup.
static wxMenu * MakeFormatMenu(void);
- /// Set dirty flag.
- void SetDirty(void) { m_Dirty = true; }
-protected:
/**@name Dirty flag handling for optimisations. */
//@{
+ /// Set dirty flag.
+ void SetDirty(void) { m_Dirty = true; }
/// Query whether window needs redrawing.
bool IsDirty(void) const { return m_Dirty; }
/// Reset dirty flag.
void ResetDirty(void) { m_Dirty = false; }
//@}
+ /// Redraws the window, used by DoPaint() or OnPaint().
+ void InternalPaint(void);
protected:
/// generic function for mouse events processing
void OnMouse(int eventId, wxMouseEvent& event);
bool m_HaveFocus;
/// do we handle clicks of the right mouse button?
bool m_DoPopupMenu;
+ /// Should InternalPaint() scroll to cursor.
+ bool m_ScrollToCursor;
/// the menu
wxMenu * m_PopupMenu;
/// for derived classes, set when mouse is clicked