Should work very well now.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1928 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -2,24 +2,12 @@
|
|||||||
BUGS
|
BUGS
|
||||||
=====================================================================
|
=====================================================================
|
||||||
|
|
||||||
- Delete():
|
|
||||||
1 - occasionally delete deletes too much, maybe when at begin of
|
|
||||||
line?
|
|
||||||
2 - when in an empty line, Delete() doesn't always merge lines
|
|
||||||
3 - line numbers aren't updated properly, may be related to 2.
|
|
||||||
4 - deleting lines leaves later parts of the list unaffected
|
|
||||||
--> just redrawing at least the next two lines doesn't seem
|
|
||||||
enough, strange, don't positions change?
|
|
||||||
- dmalloc shows duplicate deletion after merging two lines and
|
- dmalloc shows duplicate deletion after merging two lines and
|
||||||
deleting the second half
|
deleting the second half
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
=====================================================================
|
=====================================================================
|
||||||
|
|
||||||
- Add word wrap to wxlwindow/wxllist.
|
|
||||||
- Cursor to mouseclick
|
|
||||||
- Focus feedback for cursor
|
|
||||||
- Selections
|
- Selections
|
||||||
|
|
||||||
- More optimisations
|
- More optimisations
|
||||||
|
|
||||||
|
@@ -99,6 +99,7 @@ MyFrame::MyFrame(void) :
|
|||||||
m_lwin = new wxLayoutWindow(this);
|
m_lwin = new wxLayoutWindow(this);
|
||||||
m_lwin->SetMouseTracking(true);
|
m_lwin->SetMouseTracking(true);
|
||||||
m_lwin->SetEditable(true);
|
m_lwin->SetEditable(true);
|
||||||
|
m_lwin->SetWrapMargin(40);
|
||||||
m_lwin->Clear(wxROMAN,16,wxNORMAL,wxNORMAL, false);
|
m_lwin->Clear(wxROMAN,16,wxNORMAL,wxNORMAL, false);
|
||||||
m_lwin->SetFocus();
|
m_lwin->SetFocus();
|
||||||
};
|
};
|
||||||
@@ -140,7 +141,6 @@ MyFrame::AddSampleText(wxLayoutList *llist)
|
|||||||
llist->SetFont(-1,-1,wxNORMAL);
|
llist->SetFont(-1,-1,wxNORMAL);
|
||||||
llist->Insert(" text.");
|
llist->Insert(" text.");
|
||||||
llist->LineBreak();
|
llist->LineBreak();
|
||||||
|
|
||||||
llist->Insert("and ");
|
llist->Insert("and ");
|
||||||
llist->SetFont(-1,-1,-1,-1,-1,"blue");
|
llist->SetFont(-1,-1,-1,-1,-1,"blue");
|
||||||
llist->Insert("blue");
|
llist->Insert("blue");
|
||||||
@@ -211,8 +211,7 @@ void MyFrame::OnCommand( wxCommandEvent &event )
|
|||||||
break;
|
break;
|
||||||
case ID_NOWRAP:
|
case ID_NOWRAP:
|
||||||
case ID_WRAP:
|
case ID_WRAP:
|
||||||
//// m_lwin->GetLayoutList()->SetWrapMargin(
|
m_lwin->SetWrapMargin(event.GetId() == ID_NOWRAP ? 0 : 40);
|
||||||
//// event.GetId() == ID_NOWRAP ? -1 : 40);
|
|
||||||
break;
|
break;
|
||||||
case ID_ADD_SAMPLE:
|
case ID_ADD_SAMPLE:
|
||||||
AddSampleText(m_lwin->GetLayoutList());
|
AddSampleText(m_lwin->GetLayoutList());
|
||||||
|
@@ -102,6 +102,30 @@ wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords)
|
|||||||
dc.DrawText(m_Text, coords.x, coords.y-m_Top);
|
dc.DrawText(m_Text, coords.x, coords.y-m_Top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoordType
|
||||||
|
wxLayoutObjectText::GetOffsetScreen(wxDC &dc, CoordType xpos) const
|
||||||
|
{
|
||||||
|
CoordType
|
||||||
|
offs = 1,
|
||||||
|
maxlen = m_Text.Length();
|
||||||
|
long
|
||||||
|
width = 0,
|
||||||
|
height, descent = 0l;
|
||||||
|
|
||||||
|
if(xpos == 0) return 0; // easy
|
||||||
|
|
||||||
|
while(width < xpos && offs < maxlen)
|
||||||
|
{
|
||||||
|
dc.GetTextExtent(m_Text.substr(0,offs),
|
||||||
|
&width, &height, &descent);
|
||||||
|
offs++;
|
||||||
|
}
|
||||||
|
/* We have to substract 1 to compensate for the offs++, and another
|
||||||
|
one because we don't want to position the cursor behind the
|
||||||
|
object what we clicked on, but before - otherwise it looks
|
||||||
|
funny. */
|
||||||
|
return (xpos > 2) ? offs-2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wxLayoutObjectText::Layout(wxDC &dc)
|
wxLayoutObjectText::Layout(wxDC &dc)
|
||||||
@@ -202,8 +226,10 @@ wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */)
|
|||||||
{
|
{
|
||||||
wxASSERT(m_font);
|
wxASSERT(m_font);
|
||||||
dc.SetFont(*m_font);
|
dc.SetFont(*m_font);
|
||||||
if(m_ColourFG) dc.SetTextForeground(*m_ColourFG);
|
if(m_ColourFG)
|
||||||
if(m_ColourBG) dc.SetTextBackground(*m_ColourBG);
|
dc.SetTextForeground(*m_ColourFG);
|
||||||
|
if(m_ColourBG)
|
||||||
|
dc.SetTextBackground(*m_ColourBG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -253,7 +279,7 @@ wxPoint
|
|||||||
wxLayoutLine::RecalculatePosition(void)
|
wxLayoutLine::RecalculatePosition(void)
|
||||||
{
|
{
|
||||||
if(m_Previous)
|
if(m_Previous)
|
||||||
m_Position = m_Previous->RecalculatePosition() +
|
m_Position = m_Previous->GetPosition() +
|
||||||
wxPoint(0,m_Previous->GetHeight());
|
wxPoint(0,m_Previous->GetHeight());
|
||||||
else
|
else
|
||||||
m_Position = wxPoint(0,0);
|
m_Position = wxPoint(0,0);
|
||||||
@@ -263,20 +289,21 @@ wxLayoutLine::RecalculatePosition(void)
|
|||||||
void
|
void
|
||||||
wxLayoutLine::RecalculatePositions(int recurse)
|
wxLayoutLine::RecalculatePositions(int recurse)
|
||||||
{
|
{
|
||||||
wxPoint pos = RecalculatePosition();
|
wxASSERT(recurse >= 0);
|
||||||
|
wxPoint pos = m_Position;
|
||||||
|
CoordType height = m_Height;
|
||||||
|
|
||||||
if(pos != m_Position)
|
// WXLO_TRACE("RecalculatePositions()");
|
||||||
|
RecalculatePosition();
|
||||||
|
if(m_Next)
|
||||||
|
{
|
||||||
|
if(recurse > 0)
|
||||||
{
|
{
|
||||||
m_Position = pos;
|
|
||||||
if(m_Next) m_Next->RecalculatePositions(--recurse);
|
if(m_Next) m_Next->RecalculatePositions(--recurse);
|
||||||
}
|
}
|
||||||
else
|
else if(pos != m_Position || m_Height != height)
|
||||||
{
|
if(m_Next) m_Next->RecalculatePositions();
|
||||||
m_Position = pos;
|
|
||||||
if(recurse && m_Next)
|
|
||||||
m_Next->RecalculatePositions(--recurse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLayoutObjectList::iterator
|
wxLayoutObjectList::iterator
|
||||||
@@ -287,6 +314,7 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
|
|||||||
wxLayoutObjectList::iterator i;
|
wxLayoutObjectList::iterator i;
|
||||||
CoordType x = 0, len;
|
CoordType x = 0, len;
|
||||||
|
|
||||||
|
|
||||||
for(i = m_ObjectList.begin(); i != NULLIT; i++)
|
for(i = m_ObjectList.begin(); i != NULLIT; i++)
|
||||||
{
|
{
|
||||||
len = (**i).GetLength();
|
len = (**i).GetLength();
|
||||||
@@ -300,6 +328,32 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
|
|||||||
return NULLIT;
|
return NULLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxLayoutObjectList::iterator
|
||||||
|
wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const
|
||||||
|
{
|
||||||
|
wxASSERT(cxpos);
|
||||||
|
wxASSERT(xpos);
|
||||||
|
wxLayoutObjectList::iterator i;
|
||||||
|
CoordType x = 0, cx = 0, width;
|
||||||
|
|
||||||
|
for(i = m_ObjectList.begin(); i != NULLIT; i++)
|
||||||
|
{
|
||||||
|
(**i).Layout(dc);
|
||||||
|
width = (**i).GetWidth();
|
||||||
|
if( x <= xpos && xpos <= x + width )
|
||||||
|
{
|
||||||
|
*cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
|
||||||
|
wxLogDebug("wxLayoutLine::FindObjectScreen: cursor xpos = %ld", *cxpos);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
x += (**i).GetWidth();
|
||||||
|
cx += (**i).GetLength();
|
||||||
|
}
|
||||||
|
// behind last object:
|
||||||
|
*cxpos = cx;
|
||||||
|
return m_ObjectList.tail();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
||||||
{
|
{
|
||||||
@@ -329,16 +383,13 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
|||||||
if(offset == len )
|
if(offset == len )
|
||||||
{
|
{
|
||||||
if( i == m_ObjectList.tail()) // last object?
|
if( i == m_ObjectList.tail()) // last object?
|
||||||
{
|
|
||||||
m_ObjectList.push_back(obj);
|
m_ObjectList.push_back(obj);
|
||||||
m_Length += obj->GetLength();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{ // insert after current object
|
{ // insert after current object
|
||||||
i++;
|
i++;
|
||||||
m_ObjectList.insert(i,obj);
|
m_ObjectList.insert(i,obj);
|
||||||
m_Length += obj->GetLength();
|
|
||||||
}
|
}
|
||||||
|
m_Length += obj->GetLength();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* Otherwise we need to split the current object.
|
/* Otherwise we need to split the current object.
|
||||||
@@ -379,22 +430,23 @@ wxLayoutLine::Insert(CoordType xpos, wxString text)
|
|||||||
CoordType
|
CoordType
|
||||||
wxLayoutLine::Delete(CoordType xpos, CoordType npos)
|
wxLayoutLine::Delete(CoordType xpos, CoordType npos)
|
||||||
{
|
{
|
||||||
CoordType offset;
|
CoordType offset, len;
|
||||||
|
|
||||||
wxASSERT(xpos >= 0);
|
wxASSERT(xpos >= 0);
|
||||||
wxASSERT(npos >= 0);
|
wxASSERT(npos >= 0);
|
||||||
wxLOiterator i = FindObject(xpos, &offset);
|
wxLOiterator i = FindObject(xpos, &offset);
|
||||||
while(npos > 0)
|
while(npos > 0)
|
||||||
{
|
{
|
||||||
if(i == NULLIT) return false; // FIXME
|
if(i == NULLIT) return npos;
|
||||||
// now delete from that object:
|
// now delete from that object:
|
||||||
if((**i).GetType() != WXLO_TYPE_TEXT)
|
if((**i).GetType() != WXLO_TYPE_TEXT)
|
||||||
{
|
{
|
||||||
if(offset != 0) // at end of line after a non-text object
|
if(offset != 0) // at end of line after a non-text object
|
||||||
return npos;
|
return npos;
|
||||||
// always len == 1:
|
// always len == 1:
|
||||||
m_Length -= (**i).GetLength();
|
len = (**i).GetLength();
|
||||||
npos -= m_Length;
|
m_Length -= len;
|
||||||
|
npos -= len;
|
||||||
m_ObjectList.erase(i);
|
m_ObjectList.erase(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -508,8 +560,8 @@ wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos, wxPoint
|
wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
|
||||||
*cursorSize,
|
wxPoint *cursorSize,
|
||||||
int cx)
|
int cx)
|
||||||
{
|
{
|
||||||
wxLayoutObjectList::iterator i;
|
wxLayoutObjectList::iterator i;
|
||||||
@@ -635,21 +687,6 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos, wxPoint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLayoutObject *
|
|
||||||
wxLayoutLine::FindObject(CoordType xpos)
|
|
||||||
{
|
|
||||||
wxASSERT(xpos >= 0);
|
|
||||||
if(xpos > GetWidth()) return NULL;
|
|
||||||
|
|
||||||
CoordType x = 0;
|
|
||||||
for(wxLOiterator i = m_ObjectList.begin(); i != NULLIT; i++)
|
|
||||||
{
|
|
||||||
x += (**i).GetWidth();
|
|
||||||
if(x > xpos) // we just crossed it
|
|
||||||
return *i;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLayoutLine *
|
wxLayoutLine *
|
||||||
wxLayoutLine::Break(CoordType xpos)
|
wxLayoutLine::Break(CoordType xpos)
|
||||||
@@ -690,7 +727,7 @@ wxLayoutLine::Break(CoordType xpos)
|
|||||||
// current text object gets set to left half
|
// current text object gets set to left half
|
||||||
tobj->GetText() = left; // set new text
|
tobj->GetText() = left; // set new text
|
||||||
newLine->Append(new wxLayoutObjectText(right));
|
newLine->Append(new wxLayoutObjectText(right));
|
||||||
m_Length -= m_Length - offset;
|
m_Length -= right.Length();
|
||||||
i++; // don't move this object to the new list
|
i++; // don't move this object to the new list
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -728,6 +765,38 @@ wxLayoutLine::MergeNextLine(void)
|
|||||||
RecalculatePositions(1);
|
RecalculatePositions(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoordType
|
||||||
|
wxLayoutLine::GetWrapPosition(CoordType column)
|
||||||
|
{
|
||||||
|
CoordType offset;
|
||||||
|
wxLOiterator i = FindObject(column, &offset);
|
||||||
|
if(i == NULLIT) return -1; // cannot wrap
|
||||||
|
|
||||||
|
// go backwards through the list and look for space in text objects
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if((**i).GetType() == WXLO_TYPE_TEXT)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( isspace(((wxLayoutObjectText*)*i)->GetText()[offset]))
|
||||||
|
return column;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset--;
|
||||||
|
column--;
|
||||||
|
}
|
||||||
|
}while(offset != -1);
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}while(i != NULLIT);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
@@ -977,6 +1046,26 @@ wxLayoutList::LineBreak(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wxLayoutList::WrapLine(CoordType column)
|
||||||
|
{
|
||||||
|
if(m_CursorPos.x <= column || column < 1)
|
||||||
|
return false; // do nothing yet
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CoordType xpos = m_CursorLine->GetWrapPosition(column);
|
||||||
|
if(xpos == -1)
|
||||||
|
return false; // cannot break line
|
||||||
|
//else:
|
||||||
|
CoordType newpos = m_CursorPos.x - xpos - 1;
|
||||||
|
m_CursorPos.x = xpos;
|
||||||
|
LineBreak();
|
||||||
|
Delete(1); // delete the space
|
||||||
|
m_CursorPos.x = newpos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wxLayoutList::Delete(CoordType npos)
|
wxLayoutList::Delete(CoordType npos)
|
||||||
{
|
{
|
||||||
@@ -991,7 +1080,12 @@ wxLayoutList::Delete(CoordType npos)
|
|||||||
// First, check if line is empty:
|
// First, check if line is empty:
|
||||||
if(m_CursorLine->GetLength() == 0)
|
if(m_CursorLine->GetLength() == 0)
|
||||||
{ // in this case, updating could probably be optimised
|
{ // in this case, updating could probably be optimised
|
||||||
m_CursorLine = m_CursorLine->DeleteLine(true);
|
#ifdef WXLO_DEBUG
|
||||||
|
wxASSERT(DeleteLines(1) == 0);
|
||||||
|
#else
|
||||||
|
DeleteLines(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
left--;
|
left--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1035,6 +1129,23 @@ wxLayoutList::DeleteLines(int n)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
|
||||||
|
{
|
||||||
|
wxLayoutLine *line = m_FirstLine;
|
||||||
|
|
||||||
|
// first, make sure everything is calculated - this might not be
|
||||||
|
// needed, optimise it later
|
||||||
|
m_DefaultSetting->Layout(dc);
|
||||||
|
while(line)
|
||||||
|
{
|
||||||
|
line->RecalculatePosition(); // so we don't need to do it all the time
|
||||||
|
// little condition to speed up redrawing:
|
||||||
|
if(bottom != -1 && line->GetPosition().y > bottom) break;
|
||||||
|
line = line->GetNextLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
|
wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
|
||||||
{
|
{
|
||||||
@@ -1083,22 +1194,27 @@ wxLayoutList::Draw(wxDC &dc, wxPoint const &offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxLayoutObject *
|
wxLayoutObject *
|
||||||
wxLayoutList::FindObject(wxPoint const pos)
|
wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, wxPoint *cursorPos)
|
||||||
{
|
{
|
||||||
// First, find the right line:
|
// First, find the right line:
|
||||||
wxLayoutLine *line = m_FirstLine;
|
wxLayoutLine *line = m_FirstLine;
|
||||||
wxPoint p;
|
wxPoint p;
|
||||||
|
|
||||||
|
// we need to run a layout here to get font sizes right :-(
|
||||||
|
m_DefaultSetting->Layout(dc);
|
||||||
while(line)
|
while(line)
|
||||||
{
|
{
|
||||||
p = line->GetPosition();
|
p = line->GetPosition();
|
||||||
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
|
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
|
||||||
break;
|
break;
|
||||||
|
line->Layout(dc);
|
||||||
line = line->GetNextLine();
|
line = line->GetNextLine();
|
||||||
}
|
}
|
||||||
if(! line) return NULL; // not found
|
if(line == NULL) return NULL; // not found
|
||||||
|
if(cursorPos) cursorPos->y = line->GetLineNumber();
|
||||||
// Now, find the object in the line:
|
// Now, find the object in the line:
|
||||||
return line->FindObject(pos.x);
|
wxLOiterator i = line->FindObjectScreen(dc, pos.x, & cursorPos->x);
|
||||||
|
return (i == NULLIT) ? NULL : *i;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1142,11 +1258,16 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
|
|||||||
(long)m_CursorLine->GetLength()));
|
(long)m_CursorLine->GetLength()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(active)
|
|
||||||
dc.SetBrush(*wxBLACK_BRUSH);
|
dc.SetBrush(*wxBLACK_BRUSH);
|
||||||
|
dc.SetLogicalFunction(wxXOR);
|
||||||
dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
|
dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
|
||||||
dc.SetLogicalFunction(wxXOR);
|
dc.SetLogicalFunction(wxXOR);
|
||||||
dc.DrawRectangle(coords.x, coords.y, m_CursorSize.x, m_CursorSize.y);
|
if(active)
|
||||||
|
dc.DrawRectangle(coords.x, coords.y, m_CursorSize.x,
|
||||||
|
m_CursorSize.y);
|
||||||
|
else
|
||||||
|
dc.DrawLine(coords.x, coords.y+m_CursorSize.y-1,
|
||||||
|
coords.x+m_CursorSize.x, coords.y+m_CursorSize.y-1);
|
||||||
dc.SetLogicalFunction(wxCOPY);
|
dc.SetLogicalFunction(wxCOPY);
|
||||||
dc.SetBrush(wxNullBrush);
|
dc.SetBrush(wxNullBrush);
|
||||||
}
|
}
|
||||||
|
@@ -33,10 +33,19 @@
|
|||||||
# define WXLAYOUT_DEBUG
|
# define WXLAYOUT_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WXLAYOUT_DEBUG
|
||||||
|
# define WXLO_TRACE(x) wxLogDebug(x)
|
||||||
|
#else
|
||||||
|
# define WXLO_TRACE(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef WXLO_DEFAULTFONTSIZE
|
#ifndef WXLO_DEFAULTFONTSIZE
|
||||||
# define WXLO_DEFAULTFONTSIZE 12
|
# define WXLO_DEFAULTFONTSIZE 12
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// Types of currently supported layout objects.
|
/// Types of currently supported layout objects.
|
||||||
enum wxLayoutObjectType
|
enum wxLayoutObjectType
|
||||||
{
|
{
|
||||||
@@ -105,6 +114,13 @@ public:
|
|||||||
virtual CoordType GetWidth(void) const { return 0; }
|
virtual CoordType GetWidth(void) const { return 0; }
|
||||||
/// returns the number of cursor positions occupied by this object
|
/// returns the number of cursor positions occupied by this object
|
||||||
virtual CoordType GetLength(void) const { return 1; }
|
virtual CoordType GetLength(void) const { return 1; }
|
||||||
|
/** Returns the cursor offset relating to the screen x position
|
||||||
|
relative to begin of object.
|
||||||
|
@param dc the wxDC to use for calculations
|
||||||
|
@param xpos relative x position from head of object
|
||||||
|
@return cursor coordinate offset
|
||||||
|
*/
|
||||||
|
virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; }
|
||||||
|
|
||||||
/// constructor
|
/// constructor
|
||||||
wxLayoutObject() { m_UserData = NULL; }
|
wxLayoutObject() { m_UserData = NULL; }
|
||||||
@@ -158,6 +174,14 @@ public:
|
|||||||
virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const;
|
virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const;
|
||||||
/// Return just the width of the object on the screen.
|
/// Return just the width of the object on the screen.
|
||||||
virtual CoordType GetWidth(void) const { return m_Width; }
|
virtual CoordType GetWidth(void) const { return m_Width; }
|
||||||
|
/** Returns the cursor offset relating to the screen x position
|
||||||
|
relative to begin of object.
|
||||||
|
@param dc the wxDC to use for calculations
|
||||||
|
@param xpos relative x position from head of object
|
||||||
|
@return cursor coordinate offset
|
||||||
|
*/
|
||||||
|
virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const;
|
||||||
|
|
||||||
|
|
||||||
#ifdef WXLAYOUT_DEBUG
|
#ifdef WXLAYOUT_DEBUG
|
||||||
virtual void Debug(void);
|
virtual void Debug(void);
|
||||||
@@ -327,6 +351,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool DeleteWord(CoordType npos);
|
bool DeleteWord(CoordType npos);
|
||||||
|
|
||||||
|
/** Finds a suitable position left to the given column to break the
|
||||||
|
line.
|
||||||
|
@param column we want to break the line to the left of this
|
||||||
|
@return column for breaking line or -1 if no suitable location found
|
||||||
|
*/
|
||||||
|
CoordType GetWrapPosition(CoordType column);
|
||||||
|
|
||||||
/** Finds the object which covers the cursor position xpos in this
|
/** Finds the object which covers the cursor position xpos in this
|
||||||
line.
|
line.
|
||||||
@param xpos the column number
|
@param xpos the column number
|
||||||
@@ -337,6 +368,18 @@ public:
|
|||||||
wxLayoutObjectList::iterator FindObject(CoordType xpos, CoordType
|
wxLayoutObjectList::iterator FindObject(CoordType xpos, CoordType
|
||||||
*offset) const ;
|
*offset) const ;
|
||||||
|
|
||||||
|
/** Finds the object which covers the screen position xpos in this
|
||||||
|
line.
|
||||||
|
@param dc the wxDC to use for calculations
|
||||||
|
@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,
|
||||||
|
CoordType xpos,
|
||||||
|
CoordType *offset) const ;
|
||||||
|
|
||||||
/** Get the first object in the list. This is used by the wxlparser
|
/** Get the first object in the list. This is used by the wxlparser
|
||||||
functions to export the list.
|
functions to export the list.
|
||||||
@return iterator to the first object
|
@return iterator to the first object
|
||||||
@@ -384,10 +427,11 @@ public:
|
|||||||
int cx = 0);
|
int cx = 0);
|
||||||
/** This function finds an object belonging to a given cursor
|
/** This function finds an object belonging to a given cursor
|
||||||
position. It assumes that Layout() has been called before.
|
position. It assumes that Layout() has been called before.
|
||||||
|
@param dc the wxDC to use for calculations
|
||||||
@param xpos screen x position
|
@param xpos screen x position
|
||||||
@return pointer to the object
|
@return pointer to the object
|
||||||
*/
|
*/
|
||||||
wxLayoutObject * FindObject(CoordType xpos);
|
wxLayoutObject * FindObjectScreen(wxDC &dc, CoordType xpos);
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/**@name List traversal */
|
/**@name List traversal */
|
||||||
@@ -419,6 +463,8 @@ public:
|
|||||||
the list or until the coordinates no longer changed.
|
the list or until the coordinates no longer changed.
|
||||||
*/
|
*/
|
||||||
void RecalculatePositions(int recurse = 0);
|
void RecalculatePositions(int recurse = 0);
|
||||||
|
/// Recalculates the position of this line on the canvas.
|
||||||
|
wxPoint RecalculatePosition(void);
|
||||||
private:
|
private:
|
||||||
/// Destructor is private. Use DeleteLine() to remove it.
|
/// Destructor is private. Use DeleteLine() to remove it.
|
||||||
~wxLayoutLine();
|
~wxLayoutLine();
|
||||||
@@ -431,8 +477,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
void SetHeight(CoordType height)
|
void SetHeight(CoordType height)
|
||||||
{ m_Height = height; RecalculatePositions(true); }
|
{ m_Height = height; RecalculatePositions(true); }
|
||||||
/// Recalculates the position of this line on the canvas.
|
|
||||||
wxPoint RecalculatePosition(void);
|
|
||||||
|
|
||||||
/** Moves the linenumbers one on, because a line has been inserted
|
/** Moves the linenumbers one on, because a line has been inserted
|
||||||
or deleted.
|
or deleted.
|
||||||
@@ -539,6 +583,13 @@ public:
|
|||||||
bool Insert(wxLayoutObject *obj);
|
bool Insert(wxLayoutObject *obj);
|
||||||
/// Inserts a linebreak at current cursor position.
|
/// Inserts a linebreak at current cursor position.
|
||||||
bool LineBreak(void);
|
bool LineBreak(void);
|
||||||
|
/** Wraps the current line. Searches to the left of the cursor to
|
||||||
|
break the line. Does nothing if the cursor position is before
|
||||||
|
the break position parameter.
|
||||||
|
@param column the break position for the line, maximum length
|
||||||
|
@return true if line got broken
|
||||||
|
*/
|
||||||
|
bool WrapLine(CoordType column);
|
||||||
/** This function deletes npos cursor positions.
|
/** This function deletes npos cursor positions.
|
||||||
@param npos how many positions
|
@param npos how many positions
|
||||||
@return true if everything got deleted
|
@return true if everything got deleted
|
||||||
@@ -637,6 +688,14 @@ public:
|
|||||||
@param bottom optional y coordinate where to stop calculating
|
@param bottom optional y coordinate where to stop calculating
|
||||||
*/
|
*/
|
||||||
void Layout(wxDC &dc, CoordType bottom = -1) const;
|
void Layout(wxDC &dc, CoordType bottom = -1) const;
|
||||||
|
|
||||||
|
/** Calculates new sizes for everything in the list, like Layout()
|
||||||
|
but this is needed after the list got changed.
|
||||||
|
@param dc the wxDC to draw on
|
||||||
|
@param bottom optional y coordinate where to stop calculating
|
||||||
|
*/
|
||||||
|
void Recalculate(wxDC &dc, CoordType bottom = -1) const;
|
||||||
|
|
||||||
/** Returns the size of the list in screen coordinates.
|
/** Returns the size of the list in screen coordinates.
|
||||||
The return value only makes sense after the list has been
|
The return value only makes sense after the list has been
|
||||||
drawn.
|
drawn.
|
||||||
@@ -660,12 +719,15 @@ public:
|
|||||||
bool active = true,
|
bool active = true,
|
||||||
const wxPoint & translate = wxPoint(0,0));
|
const wxPoint & translate = wxPoint(0,0));
|
||||||
|
|
||||||
/** This function finds an object belonging to a given cursor
|
/** This function finds an object belonging to a given screen
|
||||||
position. It assumes that Layout() has been called before.
|
position. It assumes that Layout() has been called before.
|
||||||
@param pos screen position
|
@param pos screen position
|
||||||
|
@param cursorPos if non NULL, store cursor position in there
|
||||||
@return pointer to the object
|
@return pointer to the object
|
||||||
*/
|
*/
|
||||||
wxLayoutObject * FindObject(wxPoint const pos);
|
wxLayoutObject * FindObjectScreen(wxDC &dc,
|
||||||
|
wxPoint const pos,
|
||||||
|
wxPoint *cursorPos = NULL);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
@@ -29,6 +29,12 @@
|
|||||||
# include "wxlwindow.h"
|
# include "wxlwindow.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define WXLO_XOFFSET 4
|
||||||
|
#define WXLO_YOFFSET 4
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
|
BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
|
||||||
EVT_PAINT (wxLayoutWindow::OnPaint)
|
EVT_PAINT (wxLayoutWindow::OnPaint)
|
||||||
EVT_CHAR (wxLayoutWindow::OnChar)
|
EVT_CHAR (wxLayoutWindow::OnChar)
|
||||||
@@ -39,20 +45,6 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
|
|||||||
EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus)
|
EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus)
|
||||||
EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus)
|
EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
/*
|
|
||||||
|
|
||||||
EVT_MENU(WXLOWIN_MENU_LARGER, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_SMALLER, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_UNDERLINE_ON, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_UNDERLINE_OFF, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_BOLD_ON, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_BOLD_OFF, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_ITALICS_ON, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_ITALICS_OFF, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_ROMAN, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_TYPEWRITER, wxLayoutWindow::OnMenu)
|
|
||||||
EVT_MENU(WXLOWIN_MENU_SANSSERIF, wxLayoutWindow::OnMenu)
|
|
||||||
*/
|
|
||||||
|
|
||||||
wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
|
wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
|
||||||
: wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
|
: wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
|
||||||
@@ -68,10 +60,12 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
|
|||||||
m_bitmap = new wxBitmap(4,4);
|
m_bitmap = new wxBitmap(4,4);
|
||||||
m_bitmapSize = wxPoint(4,4);
|
m_bitmapSize = wxPoint(4,4);
|
||||||
m_llist = new wxLayoutList();
|
m_llist = new wxLayoutList();
|
||||||
|
SetWrapMargin(0);
|
||||||
wxPoint max = m_llist->GetSize();
|
wxPoint max = m_llist->GetSize();
|
||||||
SetScrollbars(10, 20 /*lineHeight*/, max.x/10+1, max.y/20+1);
|
SetScrollbars(10, 20 /*lineHeight*/, max.x/10+1, max.y/20+1);
|
||||||
EnableScrolling(true,true);
|
EnableScrolling(true,true);
|
||||||
m_maxx = max.x; m_maxy = max.y;
|
m_maxx = max.x; m_maxy = max.y;
|
||||||
|
SetCursor(wxCURSOR_IBEAM);
|
||||||
SetDirty();
|
SetDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,9 +89,6 @@ wxLayoutWindow::MSWGetDlgCode()
|
|||||||
void
|
void
|
||||||
wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
if(!m_doSendEvents) // nothing to do
|
|
||||||
return;
|
|
||||||
|
|
||||||
wxPaintDC dc( this );
|
wxPaintDC dc( this );
|
||||||
PrepareDC( dc );
|
PrepareDC( dc );
|
||||||
SetFocus();
|
SetFocus();
|
||||||
@@ -106,13 +97,20 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
|||||||
findPos.x = dc.DeviceToLogicalX(event.GetX());
|
findPos.x = dc.DeviceToLogicalX(event.GetX());
|
||||||
findPos.y = dc.DeviceToLogicalY(event.GetY());
|
findPos.y = dc.DeviceToLogicalY(event.GetY());
|
||||||
|
|
||||||
|
findPos.x -= WXLO_XOFFSET;
|
||||||
|
findPos.y -= WXLO_YOFFSET;
|
||||||
|
|
||||||
|
if(findPos.x < 0) findPos.x = 0;
|
||||||
|
if(findPos.y < 0) findPos.y = 0;
|
||||||
|
|
||||||
#ifdef WXLAYOUT_DEBUG
|
#ifdef WXLAYOUT_DEBUG
|
||||||
wxLogDebug("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
|
wxLogDebug("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
|
||||||
event.GetX(), event.GetY(), findPos.x, findPos.y);
|
event.GetX(), event.GetY(), findPos.x, findPos.y);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_ClickPosition = findPos;
|
m_ClickPosition = findPos;
|
||||||
wxLayoutObject *obj = m_llist->FindObject(findPos);
|
wxPoint cursorPos;
|
||||||
|
wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, &cursorPos);
|
||||||
|
|
||||||
#ifdef WXLAYOUT_DEBUG
|
#ifdef WXLAYOUT_DEBUG
|
||||||
if(obj)
|
if(obj)
|
||||||
@@ -122,6 +120,15 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
|||||||
wxLogDebug("wxLayoutWindow::OnMouse: Found no object.");
|
wxLogDebug("wxLayoutWindow::OnMouse: Found no object.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// always move cursor to mouse click:
|
||||||
|
if(obj && eventId == WXLOWIN_MENU_LCLICK)
|
||||||
|
{
|
||||||
|
m_llist->MoveCursorTo(cursorPos);
|
||||||
|
DoPaint(false);
|
||||||
|
}
|
||||||
|
if(!m_doSendEvents) // nothing to do
|
||||||
|
return;
|
||||||
|
|
||||||
// only do the menu if activated, editable and not on a clickable object
|
// only do the menu if activated, editable and not on a clickable object
|
||||||
if(eventId == WXLOWIN_MENU_RCLICK
|
if(eventId == WXLOWIN_MENU_RCLICK
|
||||||
&& IsEditable()
|
&& IsEditable()
|
||||||
@@ -176,6 +183,11 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
|||||||
case 'k':
|
case 'k':
|
||||||
m_llist->DeleteToEndOfLine();
|
m_llist->DeleteToEndOfLine();
|
||||||
break;
|
break;
|
||||||
|
#ifdef WXLAYOUT_DEBUG
|
||||||
|
case WXK_F1:
|
||||||
|
m_llist->SetFont(-1,-1,-1,-1,true); // underlined
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -229,6 +241,8 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
|||||||
if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
|
if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
|
||||||
break;
|
break;
|
||||||
case WXK_RETURN:
|
case WXK_RETURN:
|
||||||
|
if(m_WrapMargin > 0)
|
||||||
|
m_llist->WrapLine(m_WrapMargin);
|
||||||
m_llist->LineBreak();
|
m_llist->LineBreak();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -238,8 +252,9 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
|||||||
{
|
{
|
||||||
wxString tmp;
|
wxString tmp;
|
||||||
tmp += keyCode;
|
tmp += keyCode;
|
||||||
|
if(m_WrapMargin > 0 && isspace(keyCode))
|
||||||
|
m_llist->WrapLine(m_WrapMargin);
|
||||||
m_llist->Insert(tmp);
|
m_llist->Insert(tmp);
|
||||||
//// m_llist->WrapLine();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -275,8 +290,11 @@ wxLayoutWindow::DoPaint(bool scrollToCursor)
|
|||||||
|
|
||||||
// Maybe we need to change the scrollbar sizes or positions,
|
// Maybe we need to change the scrollbar sizes or positions,
|
||||||
// so layout the list and check:
|
// so layout the list and check:
|
||||||
if(IsDirty() || scrollToCursor)
|
if(IsDirty())
|
||||||
m_llist->Layout(dc);
|
m_llist->Layout(dc);
|
||||||
|
// this is needed even when only the cursor moved
|
||||||
|
m_llist->Layout(dc,y0+y1);
|
||||||
|
|
||||||
if(IsDirty())
|
if(IsDirty())
|
||||||
ResizeScrollbars();
|
ResizeScrollbars();
|
||||||
|
|
||||||
@@ -315,8 +333,8 @@ wxLayoutWindow::DoPaint(bool scrollToCursor)
|
|||||||
m_memDC->SetDeviceOrigin(0,0);
|
m_memDC->SetDeviceOrigin(0,0);
|
||||||
m_memDC->Clear();
|
m_memDC->Clear();
|
||||||
|
|
||||||
// The +4 give the window a tiny border on the left and top, looks nice.
|
// The offsets give the window a tiny border on the left and top, looks nice.
|
||||||
wxPoint offset(-x0+4,-y0+4);
|
wxPoint offset(-x0+WXLO_XOFFSET,-y0+WXLO_YOFFSET);
|
||||||
m_llist->Draw(*m_memDC,offset);
|
m_llist->Draw(*m_memDC,offset);
|
||||||
if(IsEditable())
|
if(IsEditable())
|
||||||
m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset);
|
m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset);
|
||||||
@@ -409,6 +427,6 @@ wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
|
|||||||
void
|
void
|
||||||
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
|
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
|
||||||
{
|
{
|
||||||
m_HaveFocus = true;
|
m_HaveFocus = false;
|
||||||
DoPaint(); // to repaint the cursor
|
DoPaint(); // to repaint the cursor
|
||||||
}
|
}
|
||||||
|
@@ -81,6 +81,11 @@ public:
|
|||||||
|
|
||||||
void EnablePopup(bool enable = true) { m_DoPopupMenu = enable; }
|
void EnablePopup(bool enable = true) { m_DoPopupMenu = enable; }
|
||||||
|
|
||||||
|
/** Sets the wrap margin.
|
||||||
|
@param margin set this to 0 to disable it
|
||||||
|
*/
|
||||||
|
void SetWrapMargin(CoordType margin) { m_WrapMargin = margin; }
|
||||||
|
|
||||||
/** Redraws the window.
|
/** Redraws the window.
|
||||||
@param scrollToCursor if true, scroll the window so that the
|
@param scrollToCursor if true, scroll the window so that the
|
||||||
cursor becomes visible
|
cursor becomes visible
|
||||||
@@ -154,6 +159,8 @@ private:
|
|||||||
|
|
||||||
/// Can user edit the window?
|
/// Can user edit the window?
|
||||||
bool m_Editable;
|
bool m_Editable;
|
||||||
|
/// wrap margin
|
||||||
|
CoordType m_WrapMargin;
|
||||||
/// Is list dirty?
|
/// Is list dirty?
|
||||||
bool m_Dirty;
|
bool m_Dirty;
|
||||||
wxMemoryDC *m_memDC;
|
wxMemoryDC *m_memDC;
|
||||||
|
Reference in New Issue
Block a user