Looks like I've fixed the editing

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 commit is contained in:
Karsten Ballüder
1998-08-12 16:14:15 +00:00
parent 362c669367
commit 23b75a2db4
4 changed files with 119 additions and 60 deletions

View File

@@ -9,7 +9,7 @@ LGPL (GNU LIBRARY PUBLIC LICENSE), by Karsten Ballueder <ballueder@usa.net>.
This is still work in progress, so if you want to make any significant This is still work in progress, so if you want to make any significant
changes, please get in touch with me before. 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:
wxllist : wxllist :
@@ -40,7 +40,6 @@ linebreaks) and export of objects, text or html.
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 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. stdout and demonstrate some of the features and bugs of wxLayoutList.

View File

@@ -50,9 +50,9 @@ wxLayoutObjectBase::Debug(void)
<< 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 #else
# define WXL_VAR(x) # define WXL_VAR(x)
# define WXL_DBG_POINT(p) # define WXL_DBG_POINT(p)
@@ -273,10 +273,10 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10; CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
// where to draw the cursor // 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 // the cursor position inside the object
CoordType cursorOffset = 0; CoordType cursorOffset = 0;
// object under cursor // object under cursor
@@ -305,8 +305,6 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
#endif #endif
dc.IsKindOf(CLASSINFO(wxPostScriptDC))) dc.IsKindOf(CLASSINFO(wxPostScriptDC)))
{ {
WXL_VAR(wxThePrintSetupData);
dc.GetSize(&pageWidth, &pageHeight); dc.GetSize(&pageWidth, &pageHeight);
dc.StartDoc(_("Printing...")); dc.StartDoc(_("Printing..."));
dc.StartPage(); dc.StartPage();
@@ -324,7 +322,6 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
position.y = margins.right; position.y = margins.right;
position.x = margins.left; 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 // if the cursorobject is a cmd, we need to find the first
// printable object: // printable object:
while(cursorObject != end() while(cursorObject != end()
@@ -375,38 +372,34 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
// draw the cursor // draw the cursor
if(m_Editable && draw && i == cursorObject) 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 if(type == WXLO_TYPE_TEXT) // special treatment
{ {
long descent = 0l; long width, height; long descent = 0l; long width, height;
tobj = (wxLayoutObjectText *)*i; tobj = (wxLayoutObjectText *)*i;
String str = tobj->GetText(); 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);
WXL_VAR(str);
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), else if(type == WXLO_TYPE_LINEBREAK)
// position.x+width, position.y+baseLineSkip); {
WXL_VAR(cursorOffset);
if(cursorOffset)
cursorPosition = wxPoint(0, position.y+baseLineSkip);
else
cursorPosition = wxPoint(0, position.y);
cursorSize = wxPoint(1,baseLineSkip);
} }
else else
{ {
if(type == WXLO_TYPE_LINEBREAK) cursorPosition = wxPoint(position.x, position.y);
//dc.DrawLine(0, position.y+baseLineSkip, 0, position.y+2*baseLineSkip); 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);
}
} }
} }
@@ -505,7 +498,7 @@ wxLayoutList::Debug(void)
<< m_CursorPosition.y; << m_CursorPosition.y;
i = FindCurrentObject(&offs); i = FindCurrentObject(&offs);
cerr << " line length: " << GetLineLength(i) << " "; cerr << " line length: " << GetLineLength(i,offs) << " ";
if(i == end()) if(i == end())
{ {
cerr << "<<no object found>>" << endl; cerr << "<<no object found>>" << endl;
@@ -559,10 +552,10 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
{ {
if(cpos->x == object.x) if(cpos->x == object.x)
{ {
*offset = 0; if(offset) *offset = 0;
return i; return i;
} }
*offset=1; if(offset) *offset=1;
cpos->x = object.x; cpos->x = object.x;
return i; return i;
} }
@@ -594,7 +587,7 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
if((**i).GetType()==WXLO_TYPE_LINEBREAK) if((**i).GetType()==WXLO_TYPE_LINEBREAK)
{ {
if(offset) if(offset)
*offset = (cpos->x > object.x) ? 1 : 0; *offset = 1;
return i; return i;
} }
cpos->x = object.x; // would be the coordinate of next object cpos->x = object.x; // would be the coordinate of next object
@@ -619,26 +612,33 @@ wxLayoutList::FindCurrentObject(CoordType *offset)
return obj; return obj;
} }
void bool
wxLayoutList::MoveCursor(int dx, int dy) wxLayoutList::MoveCursor(int dx, int dy)
{ {
CoordType offs, lineLength; CoordType offs, lineLength;
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i;
bool rc = true; // have we moved?
if(dy > 0 && m_CursorPosition.y < m_MaxLine) if(dy > 0 && m_CursorPosition.y < m_MaxLine)
m_CursorPosition.y += dy; m_CursorPosition.y += dy;
else if(dy < 0 && m_CursorPosition.y > 0) else if(dy < 0 && m_CursorPosition.y > 0)
m_CursorPosition.y += dy; // dy is negative m_CursorPosition.y += dy; // dy is negative
if(m_CursorPosition.y < 0) if(m_CursorPosition.y < 0)
{
m_CursorPosition.y = 0; m_CursorPosition.y = 0;
rc = false;
}
else if (m_CursorPosition.y > m_MaxLine) else if (m_CursorPosition.y > m_MaxLine)
{
m_CursorPosition.y = m_MaxLine; m_CursorPosition.y = m_MaxLine;
rc = false;
}
while(dx > 0) while(dx > 0)
{ {
i = FindCurrentObject(&offs); i = FindCurrentObject(&offs);
lineLength = GetLineLength(i); lineLength = GetLineLength(i,offs);
if(m_CursorPosition.x < lineLength) if(m_CursorPosition.x < lineLength)
{ {
m_CursorPosition.x ++; m_CursorPosition.x ++;
@@ -654,7 +654,10 @@ wxLayoutList::MoveCursor(int dx, int dy)
dx--; dx--;
} }
else else
{
rc = false;
break; // cannot move there break; // cannot move there
}
} }
} }
while(dx < 0) while(dx < 0)
@@ -671,21 +674,26 @@ wxLayoutList::MoveCursor(int dx, int dy)
m_CursorPosition.y --; m_CursorPosition.y --;
m_CursorPosition.x = 0; m_CursorPosition.x = 0;
i = FindCurrentObject(&offs); i = FindCurrentObject(&offs);
lineLength = GetLineLength(i); lineLength = GetLineLength(i,offs);
m_CursorPosition.x = lineLength; m_CursorPosition.x = lineLength;
dx++; dx++;
continue; continue;
} }
else else
{
rc = false;
break; // cannot move left any more break; // cannot move left any more
}
} }
} }
// final adjustment: // final adjustment:
i = FindCurrentObject(&offs); 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;
rc = false;
}
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
i = FindCurrentObject(&offs); i = FindCurrentObject(&offs);
cerr << "Cursor: " cerr << "Cursor: "
@@ -695,7 +703,7 @@ wxLayoutList::MoveCursor(int dx, int dy)
if(i == end()) if(i == end())
{ {
cerr << "<<no object found>>" << endl; 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 // value then
} }
if((*i)->GetType() == WXLO_TYPE_TEXT) if((*i)->GetType() == WXLO_TYPE_TEXT)
@@ -706,6 +714,7 @@ wxLayoutList::MoveCursor(int dx, int dy)
else else
cerr << ' ' << _t[(*i)->GetType()] << endl; cerr << ' ' << _t[(*i)->GetType()] << endl;
#endif #endif
return rc;
} }
void void
@@ -829,6 +838,8 @@ void
wxLayoutList::Insert(String const &text) wxLayoutList::Insert(String const &text)
{ {
wxLayoutObjectText *tobj = NULL; wxLayoutObjectText *tobj = NULL;
wxLayoutObjectList::iterator j;
WXL_TRACE(Insert(text)); WXL_TRACE(Insert(text));
if(! m_Editable) if(! m_Editable)
@@ -837,22 +848,57 @@ wxLayoutList::Insert(String const &text)
CoordType offs; CoordType offs;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs); wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
if(i != end() && (*i)->GetType() == WXLO_TYPE_TEXT) if(i == end())
{ // insert into an existing text object: {
Insert(new wxLayoutObjectText(text));
return;
}
switch((**i).GetType())
{
case WXLO_TYPE_TEXT:
// insert into an existing text object:
WXL_TRACE(inserting into existing object); WXL_TRACE(inserting into existing object);
tobj = (wxLayoutObjectText *)*i ; tobj = (wxLayoutObjectText *)*i ;
wxASSERT(tobj); wxASSERT(tobj);
tobj->GetText().insert(offs,text); tobj->GetText().insert(offs,text);
} break;
else // check whether the previous object is text: case WXLO_TYPE_LINEBREAK:
{ j = i;
wxLayoutObjectList::iterator j = i; if(offs == 0) // try to append to previous object
j--;
WXL_TRACE(checking previous object);
if(0 && j != end() && (*j)->GetType() == WXLO_TYPE_TEXT)
{ {
tobj = (wxLayoutObjectText *)*i; j--;
wxASSERT(tobj); 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);
if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
{
tobj = (wxLayoutObjectText *)*j;
tobj->GetText()+=text; tobj->GetText()+=text;
} }
else // insert a new text object else // insert a new text object
@@ -866,13 +912,16 @@ wxLayoutList::Insert(String const &text)
} }
CoordType CoordType
wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i) wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i, CoordType offs)
{ {
if(i == end()) if(i == end())
return 0; return 0;
CoordType len = 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: // search backwards for beginning of line:
while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK) while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
i--; i--;

View File

@@ -39,7 +39,7 @@
/// Types of currently supported layout objects. /// Types of currently supported layout objects.
enum wxLayoutObjectType 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. /// Type used for coordinates in drawing.
typedef long CoordType; typedef long CoordType;
@@ -249,8 +249,8 @@ public:
void SetEditable(bool editable = true) { m_Editable = editable; } void SetEditable(bool editable = true) { m_Editable = editable; }
/// return true if list is editable /// return true if list is editable
bool IsEditable(void) const { return m_Editable; } bool IsEditable(void) const { return m_Editable; }
/// move cursor /// move cursor, returns true if it could move to the desired position
void MoveCursor(int dx = 0, int dy = 0); bool MoveCursor(int dx = 0, int dy = 0);
void SetCursor(wxPoint const &p) { m_CursorPosition = p; } void SetCursor(wxPoint const &p) { m_CursorPosition = p; }
wxPoint GetCursor(void) const { return m_CursorPosition; } wxPoint GetCursor(void) const { return m_CursorPosition; }
/// delete one or more cursor positions /// delete one or more cursor positions
@@ -264,8 +264,10 @@ public:
wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; } wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; }
wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = NULL); wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = NULL);
// get the length of the line with the object pointed to by i // get the length of the line with the object pointed to by i, offs
CoordType GetLineLength(wxLayoutObjectList::iterator i); // only used to decide whether we are before or after linebreak
CoordType GetLineLength(wxLayoutObjectList::iterator i,
CoordType offs = 0);
//@} //@}
protected: protected:
/// font parameters: /// font parameters:

View File

@@ -68,6 +68,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
long keyCode = event.KeyCode(); long keyCode = event.KeyCode();
wxPoint p; wxPoint p;
CoordType help;
switch(event.KeyCode()) switch(event.KeyCode())
{ {
@@ -100,11 +101,19 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
m_llist.SetCursor(p); m_llist.SetCursor(p);
break; break;
case WXK_DELETE : case WXK_DELETE :
m_llist.Delete(1); 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; break;
case WXK_BACK: // backspace case WXK_BACK: // backspace
m_llist.MoveCursor(-1); if(m_llist.MoveCursor(-1))
m_llist.Delete(1); m_llist.Delete(1);
break; break;
case WXK_RETURN: case WXK_RETURN:
m_llist.LineBreak(); m_llist.LineBreak();