bugs. Delete/Insert/Home/End/Ctrl-Delete all work as expected.
Cursor gets redrawn properly.
Scroll-to-cursor still missing.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@511
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
This is still work in progress, so if you want to make any significant
changes, please get in touch with me before.
This is still work in progress, so if you want to make any significant
changes, please get in touch with me before.
-There are three building blocks for richt text editing:
+There are three building blocks for rich text editing:
Planned for the future is an html parser for importing html.
Planned for the future is an html parser for importing html.
wxLayout.cpp is a simple test program. It will export Text and HTML to
stdout and demonstrate some of the features and bugs of wxLayoutList.
wxLayout.cpp is a simple test program. It will export Text and HTML to
stdout and demonstrate some of the features and bugs of wxLayoutList.
<< GetSize(&bl).y << " bl=" << bl;
}
<< GetSize(&bl).y << " bl=" << bl;
}
-# define WXL_VAR(x) cerr << #x"=" << x << endl;
+# define WXL_VAR(x) cerr << #x"=" << x << endl
# define WXL_DBG_POINT(p) cerr << #p << ": " << p.x << ',' << p.y << endl
# define WXL_DBG_POINT(p) cerr << #p << ": " << p.x << ',' << p.y << endl
-# define WXL_TRACE(f) cerr << #f":" << endl;
+# define WXL_TRACE(f) cerr << #f":" << endl
#else
# define WXL_VAR(x)
# define WXL_DBG_POINT(p)
#else
# define WXL_VAR(x)
# define WXL_DBG_POINT(p)
CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
// where to draw the cursor
CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
// where to draw the cursor
- wxPoint cursorPosition, cursorSize;
+ wxPoint
+ cursorPosition = wxPoint(0,0),
+ cursorSize = wxPoint(1,baseLineSkip);
- // we trace the objects' cursor positions so we can draw the cursor
- wxPoint cursor = wxPoint(0,0);
// the cursor position inside the object
CoordType cursorOffset = 0;
// object under cursor
// the cursor position inside the object
CoordType cursorOffset = 0;
// object under cursor
#endif
dc.IsKindOf(CLASSINFO(wxPostScriptDC)))
{
#endif
dc.IsKindOf(CLASSINFO(wxPostScriptDC)))
{
- WXL_VAR(wxThePrintSetupData);
-
dc.GetSize(&pageWidth, &pageHeight);
dc.StartDoc(_("Printing..."));
dc.StartPage();
dc.GetSize(&pageWidth, &pageHeight);
dc.StartDoc(_("Printing..."));
dc.StartPage();
position.y = margins.right;
position.x = margins.left;
position.y = margins.right;
position.x = margins.left;
- WXL_VAR(findObject); WXL_VAR(findCoords.x); WXL_VAR(findCoords.y);
// if the cursorobject is a cmd, we need to find the first
// printable object:
while(cursorObject != end()
// if the cursorobject is a cmd, we need to find the first
// printable object:
while(cursorObject != end()
// draw the cursor
if(m_Editable && draw && i == cursorObject)
{
// draw the cursor
if(m_Editable && draw && i == cursorObject)
{
+ WXL_VAR((**cursorObject).GetType());
+ WXL_VAR(m_CursorPosition.x); WXL_VAR(m_CursorPosition.y);
if(type == WXLO_TYPE_TEXT) // special treatment
{
long descent = 0l; long width, height;
tobj = (wxLayoutObjectText *)*i;
String str = tobj->GetText();
if(type == WXLO_TYPE_TEXT) // special treatment
{
long descent = 0l; long width, height;
tobj = (wxLayoutObjectText *)*i;
String str = tobj->GetText();
- WXL_VAR(m_CursorPosition.x); WXL_VAR(cursor.x);
+ WXL_VAR(m_CursorPosition.x);
str = str.substr(0, cursorOffset);
str = str.substr(0, cursorOffset);
dc.GetTextExtent(Str(str), &width,&height, &descent);
dc.GetTextExtent(Str(str), &width,&height, &descent);
- WXL_VAR(height);
- WXL_VAR(width);
- WXL_VAR(descent);
cursorPosition = wxPoint(position.x+width,
cursorPosition = wxPoint(position.x+width,
- position.y+(baseLineSkip-height));
+ position.y+(baseLineSkip-height));
cursorSize = wxPoint(1, height);
cursorSize = wxPoint(1, height);
- //dc.DrawLine(position.x+width,
- // position.y+(baseLineSkip-height),
- // position.x+width, position.y+baseLineSkip);
+ else if(type == WXLO_TYPE_LINEBREAK)
- if(type == WXLO_TYPE_LINEBREAK)
- //dc.DrawLine(0, position.y+baseLineSkip, 0, position.y+2*baseLineSkip);
- {
- cursorPosition = wxPoint(0, position.y);
- cursorSize = wxPoint(1,baseLineSkip);
- }
+ WXL_VAR(cursorOffset);
+ if(cursorOffset)
+ cursorPosition = wxPoint(0, position.y+baseLineSkip);
- {
- cursorPosition = wxPoint(position.x, position.y);
- cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
- }
+ cursorPosition = wxPoint(0, position.y);
+ cursorSize = wxPoint(1,baseLineSkip);
+
+ }
+ else
+ {
+ cursorPosition = wxPoint(position.x, position.y);
+ cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
<< m_CursorPosition.y;
i = FindCurrentObject(&offs);
<< m_CursorPosition.y;
i = FindCurrentObject(&offs);
- cerr << " line length: " << GetLineLength(i) << " ";
+ cerr << " line length: " << GetLineLength(i,offs) << " ";
if(i == end())
{
cerr << "<<no object found>>" << endl;
if(i == end())
{
cerr << "<<no object found>>" << endl;
{
if(cpos->x == object.x)
{
{
if(cpos->x == object.x)
{
+ if(offset) *offset = 0;
cpos->x = object.x;
return i;
}
cpos->x = object.x;
return i;
}
if((**i).GetType()==WXLO_TYPE_LINEBREAK)
{
if(offset)
if((**i).GetType()==WXLO_TYPE_LINEBREAK)
{
if(offset)
- *offset = (cpos->x > object.x) ? 1 : 0;
return i;
}
cpos->x = object.x; // would be the coordinate of next object
return i;
}
cpos->x = object.x; // would be the coordinate of next object
wxLayoutList::MoveCursor(int dx, int dy)
{
CoordType offs, lineLength;
wxLayoutObjectList::iterator i;
wxLayoutList::MoveCursor(int dx, int dy)
{
CoordType offs, lineLength;
wxLayoutObjectList::iterator i;
+ bool rc = true; // have we moved?
if(dy > 0 && m_CursorPosition.y < m_MaxLine)
m_CursorPosition.y += dy;
else if(dy < 0 && m_CursorPosition.y > 0)
m_CursorPosition.y += dy; // dy is negative
if(m_CursorPosition.y < 0)
if(dy > 0 && m_CursorPosition.y < m_MaxLine)
m_CursorPosition.y += dy;
else if(dy < 0 && m_CursorPosition.y > 0)
m_CursorPosition.y += dy; // dy is negative
if(m_CursorPosition.y < 0)
else if (m_CursorPosition.y > m_MaxLine)
else if (m_CursorPosition.y > m_MaxLine)
m_CursorPosition.y = m_MaxLine;
m_CursorPosition.y = m_MaxLine;
while(dx > 0)
{
i = FindCurrentObject(&offs);
while(dx > 0)
{
i = FindCurrentObject(&offs);
- lineLength = GetLineLength(i);
+ lineLength = GetLineLength(i,offs);
if(m_CursorPosition.x < lineLength)
{
m_CursorPosition.x ++;
if(m_CursorPosition.x < lineLength)
{
m_CursorPosition.x ++;
break; // cannot move there
break; // cannot move there
m_CursorPosition.y --;
m_CursorPosition.x = 0;
i = FindCurrentObject(&offs);
m_CursorPosition.y --;
m_CursorPosition.x = 0;
i = FindCurrentObject(&offs);
- lineLength = GetLineLength(i);
+ lineLength = GetLineLength(i,offs);
m_CursorPosition.x = lineLength;
dx++;
continue;
}
else
m_CursorPosition.x = lineLength;
dx++;
continue;
}
else
break; // cannot move left any more
break; // cannot move left any more
}
}
// final adjustment:
i = FindCurrentObject(&offs);
}
}
// final adjustment:
i = FindCurrentObject(&offs);
- lineLength = GetLineLength(i);
+ lineLength = GetLineLength(i,offs);
if(m_CursorPosition.x > lineLength)
if(m_CursorPosition.x > lineLength)
m_CursorPosition.x = lineLength;
m_CursorPosition.x = lineLength;
#ifdef WXLAYOUT_DEBUG
i = FindCurrentObject(&offs);
cerr << "Cursor: "
#ifdef WXLAYOUT_DEBUG
i = FindCurrentObject(&offs);
cerr << "Cursor: "
if(i == end())
{
cerr << "<<no object found>>" << endl;
if(i == end())
{
cerr << "<<no object found>>" << endl;
- return; // FIXME we should set cursor position to maximum allowed
+ return rc; // FIXME we should set cursor position to maximum allowed
// value then
}
if((*i)->GetType() == WXLO_TYPE_TEXT)
// value then
}
if((*i)->GetType() == WXLO_TYPE_TEXT)
else
cerr << ' ' << _t[(*i)->GetType()] << endl;
#endif
else
cerr << ' ' << _t[(*i)->GetType()] << endl;
#endif
wxLayoutList::Insert(String const &text)
{
wxLayoutObjectText *tobj = NULL;
wxLayoutList::Insert(String const &text)
{
wxLayoutObjectText *tobj = NULL;
+ wxLayoutObjectList::iterator j;
+
WXL_TRACE(Insert(text));
if(! m_Editable)
WXL_TRACE(Insert(text));
if(! m_Editable)
CoordType offs;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
CoordType offs;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
- if(i != end() && (*i)->GetType() == WXLO_TYPE_TEXT)
- { // insert into an existing text object:
+ if(i == end())
+ {
+ Insert(new wxLayoutObjectText(text));
+ return;
+ }
+
+ switch((**i).GetType())
+ {
+ case WXLO_TYPE_TEXT:
+ // insert into an existing text object:
WXL_TRACE(inserting into existing object);
tobj = (wxLayoutObjectText *)*i ;
wxASSERT(tobj);
tobj->GetText().insert(offs,text);
WXL_TRACE(inserting into existing object);
tobj = (wxLayoutObjectText *)*i ;
wxASSERT(tobj);
tobj->GetText().insert(offs,text);
- }
- else // check whether the previous object is text:
- {
- wxLayoutObjectList::iterator j = i;
- j--;
+ break;
+ case WXLO_TYPE_LINEBREAK:
+ j = i;
+ if(offs == 0) // try to append to previous object
+ {
+ j--;
+ if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
+ {
+ tobj = (wxLayoutObjectText *)*j;
+ tobj->GetText()+=text;
+ }
+ else
+ insert(i,new wxLayoutObjectText(text));
+ }
+ else // cursor after linebreak
+ {
+ j++;
+ if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
+ {
+ tobj = (wxLayoutObjectText *)*j;
+ tobj->GetText()=text+tobj->GetText();
+ }
+ else
+ {
+ if(j == end())
+ push_back(new wxLayoutObjectText(text));
+ else
+ insert(j,new wxLayoutObjectText(text));
+ }
+ }
+ break;
+ default:
+ j = i; j--;
WXL_TRACE(checking previous object);
WXL_TRACE(checking previous object);
- if(0 && j != end() && (*j)->GetType() == WXLO_TYPE_TEXT)
+ if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
- tobj = (wxLayoutObjectText *)*i;
- wxASSERT(tobj);
+ tobj = (wxLayoutObjectText *)*j;
tobj->GetText()+=text;
}
else // insert a new text object
tobj->GetText()+=text;
}
else // insert a new text object
-wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i)
+wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i, CoordType offs)
{
if(i == end())
return 0;
CoordType len = 0;
{
if(i == end())
return 0;
CoordType len = 0;
+ if(offs == 0 && (**i).GetType() == WXLO_TYPE_LINEBREAK)
+ // we are before a linebrak
+ return 0;
// search backwards for beginning of line:
while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
i--;
// search backwards for beginning of line:
while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
i--;
/// Types of currently supported layout objects.
enum wxLayoutObjectType
/// Types of currently supported layout objects.
enum wxLayoutObjectType
-{ WXLO_TYPE_INVALID, WXLO_TYPE_TEXT, WXLO_TYPE_CMD, WXLO_TYPE_ICON, WXLO_TYPE_LINEBREAK };
+{ 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;
/// Type used for coordinates in drawing.
typedef long CoordType;
void SetEditable(bool editable = true) { m_Editable = editable; }
/// return true if list is editable
bool IsEditable(void) const { return m_Editable; }
void SetEditable(bool editable = true) { m_Editable = editable; }
/// return true if list is editable
bool IsEditable(void) const { return m_Editable; }
- /// move cursor
- void MoveCursor(int dx = 0, int dy = 0);
+ /// 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) { m_CursorPosition = p; }
wxPoint GetCursor(void) const { return m_CursorPosition; }
/// delete one or more cursor positions
void SetCursor(wxPoint const &p) { m_CursorPosition = p; }
wxPoint GetCursor(void) const { return m_CursorPosition; }
/// delete one or more cursor positions
wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; }
wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = NULL);
wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; }
wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = NULL);
- // get the length of the line with the object pointed to by i
- CoordType GetLineLength(wxLayoutObjectList::iterator i);
+ // 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);
//@}
protected:
/// font parameters:
//@}
protected:
/// font parameters:
long keyCode = event.KeyCode();
wxPoint p;
long keyCode = event.KeyCode();
wxPoint p;
switch(event.KeyCode())
{
switch(event.KeyCode())
{
m_llist.SetCursor(p);
break;
case WXK_DELETE :
m_llist.SetCursor(p);
break;
case WXK_DELETE :
+ if(event.ControlDown()) // delete to end of line
+ {
+ help = m_llist.GetLineLength(
+ m_llist.FindCurrentObject(NULL))
+ - m_llist.GetCursor().x;
+ m_llist.Delete(help ? help : 1);
+ }
+ else
+ m_llist.Delete(1);
break;
case WXK_BACK: // backspace
break;
case WXK_BACK: // backspace
- m_llist.MoveCursor(-1);
- m_llist.Delete(1);
+ if(m_llist.MoveCursor(-1))
+ m_llist.Delete(1);
break;
case WXK_RETURN:
m_llist.LineBreak();
break;
case WXK_RETURN:
m_llist.LineBreak();