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:
parent
362c669367
commit
23b75a2db4
@ -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
|
||||
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 :
|
||||
|
||||
@ -40,7 +40,6 @@ linebreaks) and export of objects, text or 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.
|
||||
|
||||
|
@ -50,9 +50,9 @@ wxLayoutObjectBase::Debug(void)
|
||||
<< 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_TRACE(f) cerr << #f":" << endl;
|
||||
# define WXL_TRACE(f) cerr << #f":" << endl
|
||||
#else
|
||||
# define WXL_VAR(x)
|
||||
# define WXL_DBG_POINT(p)
|
||||
@ -273,10 +273,10 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
|
||||
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
|
||||
@ -305,8 +305,6 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
|
||||
#endif
|
||||
dc.IsKindOf(CLASSINFO(wxPostScriptDC)))
|
||||
{
|
||||
WXL_VAR(wxThePrintSetupData);
|
||||
|
||||
dc.GetSize(&pageWidth, &pageHeight);
|
||||
dc.StartDoc(_("Printing..."));
|
||||
dc.StartPage();
|
||||
@ -324,7 +322,6 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
|
||||
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()
|
||||
@ -375,38 +372,34 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
|
||||
// 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();
|
||||
WXL_VAR(m_CursorPosition.x); WXL_VAR(cursor.x);
|
||||
WXL_VAR(m_CursorPosition.x);
|
||||
str = str.substr(0, cursorOffset);
|
||||
WXL_VAR(str);
|
||||
dc.GetTextExtent(Str(str), &width,&height, &descent);
|
||||
WXL_VAR(height);
|
||||
WXL_VAR(width);
|
||||
WXL_VAR(descent);
|
||||
cursorPosition = wxPoint(position.x+width,
|
||||
position.y+(baseLineSkip-height));
|
||||
position.y+(baseLineSkip-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)
|
||||
{
|
||||
WXL_VAR(cursorOffset);
|
||||
if(cursorOffset)
|
||||
cursorPosition = wxPoint(0, position.y+baseLineSkip);
|
||||
else
|
||||
cursorPosition = wxPoint(0, position.y);
|
||||
cursorSize = wxPoint(1,baseLineSkip);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
cursorPosition = wxPoint(position.x, position.y);
|
||||
cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
|
||||
}
|
||||
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;
|
||||
|
||||
i = FindCurrentObject(&offs);
|
||||
cerr << " line length: " << GetLineLength(i) << " ";
|
||||
cerr << " line length: " << GetLineLength(i,offs) << " ";
|
||||
if(i == end())
|
||||
{
|
||||
cerr << "<<no object found>>" << endl;
|
||||
@ -559,10 +552,10 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
|
||||
{
|
||||
if(cpos->x == object.x)
|
||||
{
|
||||
*offset = 0;
|
||||
if(offset) *offset = 0;
|
||||
return i;
|
||||
}
|
||||
*offset=1;
|
||||
if(offset) *offset=1;
|
||||
cpos->x = object.x;
|
||||
return i;
|
||||
}
|
||||
@ -594,7 +587,7 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
|
||||
if((**i).GetType()==WXLO_TYPE_LINEBREAK)
|
||||
{
|
||||
if(offset)
|
||||
*offset = (cpos->x > object.x) ? 1 : 0;
|
||||
*offset = 1;
|
||||
return i;
|
||||
}
|
||||
cpos->x = object.x; // would be the coordinate of next object
|
||||
@ -619,26 +612,33 @@ wxLayoutList::FindCurrentObject(CoordType *offset)
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
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)
|
||||
{
|
||||
m_CursorPosition.y = 0;
|
||||
rc = false;
|
||||
}
|
||||
else if (m_CursorPosition.y > m_MaxLine)
|
||||
{
|
||||
m_CursorPosition.y = m_MaxLine;
|
||||
rc = false;
|
||||
}
|
||||
|
||||
while(dx > 0)
|
||||
{
|
||||
i = FindCurrentObject(&offs);
|
||||
lineLength = GetLineLength(i);
|
||||
lineLength = GetLineLength(i,offs);
|
||||
if(m_CursorPosition.x < lineLength)
|
||||
{
|
||||
m_CursorPosition.x ++;
|
||||
@ -654,7 +654,10 @@ wxLayoutList::MoveCursor(int dx, int dy)
|
||||
dx--;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = false;
|
||||
break; // cannot move there
|
||||
}
|
||||
}
|
||||
}
|
||||
while(dx < 0)
|
||||
@ -671,21 +674,26 @@ wxLayoutList::MoveCursor(int dx, int dy)
|
||||
m_CursorPosition.y --;
|
||||
m_CursorPosition.x = 0;
|
||||
i = FindCurrentObject(&offs);
|
||||
lineLength = GetLineLength(i);
|
||||
lineLength = GetLineLength(i,offs);
|
||||
m_CursorPosition.x = lineLength;
|
||||
dx++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = false;
|
||||
break; // cannot move left any more
|
||||
}
|
||||
}
|
||||
}
|
||||
// final adjustment:
|
||||
i = FindCurrentObject(&offs);
|
||||
lineLength = GetLineLength(i);
|
||||
lineLength = GetLineLength(i,offs);
|
||||
if(m_CursorPosition.x > lineLength)
|
||||
{
|
||||
m_CursorPosition.x = lineLength;
|
||||
|
||||
rc = false;
|
||||
}
|
||||
#ifdef WXLAYOUT_DEBUG
|
||||
i = FindCurrentObject(&offs);
|
||||
cerr << "Cursor: "
|
||||
@ -695,7 +703,7 @@ wxLayoutList::MoveCursor(int dx, int dy)
|
||||
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)
|
||||
@ -706,6 +714,7 @@ wxLayoutList::MoveCursor(int dx, int dy)
|
||||
else
|
||||
cerr << ' ' << _t[(*i)->GetType()] << endl;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
@ -829,6 +838,8 @@ void
|
||||
wxLayoutList::Insert(String const &text)
|
||||
{
|
||||
wxLayoutObjectText *tobj = NULL;
|
||||
wxLayoutObjectList::iterator j;
|
||||
|
||||
WXL_TRACE(Insert(text));
|
||||
|
||||
if(! m_Editable)
|
||||
@ -837,22 +848,57 @@ wxLayoutList::Insert(String const &text)
|
||||
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);
|
||||
}
|
||||
else // check whether the previous object is text:
|
||||
{
|
||||
wxLayoutObjectList::iterator j = i;
|
||||
j--;
|
||||
WXL_TRACE(checking previous object);
|
||||
if(0 && j != end() && (*j)->GetType() == WXLO_TYPE_TEXT)
|
||||
break;
|
||||
case WXLO_TYPE_LINEBREAK:
|
||||
j = i;
|
||||
if(offs == 0) // try to append to previous object
|
||||
{
|
||||
tobj = (wxLayoutObjectText *)*i;
|
||||
wxASSERT(tobj);
|
||||
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);
|
||||
if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
|
||||
{
|
||||
tobj = (wxLayoutObjectText *)*j;
|
||||
tobj->GetText()+=text;
|
||||
}
|
||||
else // insert a new text object
|
||||
@ -866,13 +912,16 @@ wxLayoutList::Insert(String const &text)
|
||||
}
|
||||
|
||||
CoordType
|
||||
wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i)
|
||||
wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i, CoordType offs)
|
||||
{
|
||||
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--;
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
/// 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;
|
||||
@ -249,8 +249,8 @@ public:
|
||||
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
|
||||
@ -264,8 +264,10 @@ public:
|
||||
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:
|
||||
|
@ -68,6 +68,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
||||
|
||||
long keyCode = event.KeyCode();
|
||||
wxPoint p;
|
||||
CoordType help;
|
||||
|
||||
switch(event.KeyCode())
|
||||
{
|
||||
@ -100,11 +101,19 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
||||
m_llist.SetCursor(p);
|
||||
break;
|
||||
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;
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user