Countless (some half-finished) optimisations.

Started implementing selections.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2106 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Karsten Ballüder
1999-04-12 20:06:46 +00:00
parent e97a90f0a8
commit 9e55588fe3
5 changed files with 316 additions and 161 deletions

View File

@@ -15,27 +15,32 @@ BUGS
TODO TODO
===================================================================== =====================================================================
- replacement of llist in window
- undo
- Selections!!! RECENTLY FIXED (?)
- fix(simplify) cursor size calculation
- delete in empty line doesn't work
- fix horiz scrollbar size OK here, a Mahogany problem?
- update rectangle (needs support in wxllist and wxWindows)
--> needs a bit of fixing still
some code bits are commented out in wxlwindow.cpp
offset handling seems a bit dodgy, white shadow to top/left of cursor
- replacement of llist in window
- undo
- font optimisations(!)
- copy/cut/selections
- occasionally wraps lines wongly (twice) ??
- UNDO
later:
- DragNDrop ... broken in wxGTK at present
- cut&paste ... broken in wxGTK at present, Paste already implemented
- Selections
- More optimisations: - More optimisations:
- let each line have a pointer to the last layoutcommand and let that
- let each line have a pointer to the last layoutcommand and let that one only store the settings that changed, then we no longer need to
one only store the settings that changed, then we no longer need to recalculate all the lines
recalculate all the lines
- update rectangle (needs support in wxllist and wxWindows)
- fix(simplify) cursor size calculation: don't use icon cursor if there
is no cursor object
- copy/cut/selections
- UNDO
- cut&paste (paste is there but broken in wxGTK)
The current paste in wxGTK is broken, support is there.
Once selections are there, add copy (trivial).
- DragNDrop (waiting for wxGTK/gtk1.2 & GNOME 1.0 / Debian Slink)

View File

@@ -14,12 +14,14 @@
#pragma implementation "wxllist.h" #pragma implementation "wxllist.h"
#endif #endif
//#include "Mpch.h"
#include "wx/wxprec.h" #include "wx/wxprec.h"
#ifdef __BORLANDC__ #ifdef __BORLANDC__
# pragma hdrstop # pragma hdrstop
#endif #endif
//#include "Mpch.h"
#ifdef M_PREFIX #ifdef M_PREFIX
# include "gui/wxllist.h" # include "gui/wxllist.h"
#else #else
@@ -78,9 +80,16 @@ bool operator !=(wxPoint const &p1, wxPoint const &p2)
return p1.x != p2.x || p1.y != p2.y; return p1.x != p2.x || p1.y != p2.y;
} }
/// allows me to compare to wxPoints
bool operator <=(wxPoint const &p1, wxPoint const &p2)
{
return p1.y < p2.y || (p1.y == p2.y && p1.x <= p2.x);
}
/// grows a wxRect so that it includes the given point /// grows a wxRect so that it includes the given point
static void GrowRect(wxRect &r, const wxPoint & p) static
void GrowRect(wxRect &r, const wxPoint & p)
{ {
if(r.x > p.x) if(r.x > p.x)
r.x = p.x; r.x = p.x;
@@ -92,6 +101,13 @@ static void GrowRect(wxRect &r, const wxPoint & p)
else if(r.y + r.height < p.y) else if(r.y + r.height < p.y)
r.height = p.y - r.y; r.height = p.y - r.y;
} }
/// returns true if the point is in the rectangle
static
bool Contains(const wxRect &r, const wxPoint &p)
{
return r.x <= p.x && r.y <= p.y && (r.x+r.width) >= p.x && (r.y + r.height) >= p.y;
}
//@} //@}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -234,7 +250,7 @@ wxLayoutObjectIcon::GetSize(CoordType *top, CoordType *bottom) const
wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
weight, bool underline, weight, bool underline,
wxColour const *fg, wxColour const *bg) wxColour &fg, wxColour &bg)
{ {
m_font = new wxFont(size,family,style,weight,underline); m_font = new wxFont(size,family,style,weight,underline);
@@ -270,12 +286,12 @@ wxLayoutObjectCmd::GetStyle(wxLayoutStyleInfo *si) const
si->underline = m_font->GetUnderlined(); si->underline = m_font->GetUnderlined();
si->weight = m_font->GetWeight(); si->weight = m_font->GetWeight();
si->fg_red = m_ColourFG->Red(); si->fg_red = m_ColourFG.Red();
si->fg_green = m_ColourFG->Green(); si->fg_green = m_ColourFG.Green();
si->fg_blue = m_ColourFG->Blue(); si->fg_blue = m_ColourFG.Blue();
si->bg_red = m_ColourBG->Red(); si->bg_red = m_ColourBG.Red();
si->bg_green = m_ColourBG->Green(); si->bg_green = m_ColourBG.Green();
si->bg_blue = m_ColourBG->Blue(); si->bg_blue = m_ColourBG.Blue();
} }
void void
@@ -283,10 +299,8 @@ 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);
dc.SetTextForeground(*m_ColourFG); dc.SetTextBackground(m_ColourBG);
if(m_ColourBG)
dc.SetTextBackground(*m_ColourBG);
} }
void void
@@ -303,7 +317,7 @@ wxLayoutObjectCmd::Layout(wxDC &dc)
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
wxLayoutLine::wxLayoutLine(wxLayoutLine *prev) wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
{ {
m_LineNumber = 0; m_LineNumber = 0;
m_Width = m_Height = 0; m_Width = m_Height = 0;
@@ -311,7 +325,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev)
m_Dirty = true; m_Dirty = true;
m_Previous = prev; m_Previous = prev;
m_Next = NULL; m_Next = NULL;
RecalculatePosition(); RecalculatePosition(llist);
if(m_Previous) if(m_Previous)
{ {
m_LineNumber = m_Previous->GetLineNumber()+1; m_LineNumber = m_Previous->GetLineNumber()+1;
@@ -323,7 +337,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev)
{ {
m_Next->m_Previous = this; m_Next->m_Previous = this;
m_Next->MoveLines(+1); m_Next->MoveLines(+1);
m_Next->RecalculatePositions(1); m_Next->RecalculatePositions(1,llist);
} }
} }
@@ -333,33 +347,32 @@ wxLayoutLine::~wxLayoutLine()
} }
wxPoint wxPoint
wxLayoutLine::RecalculatePosition(void) wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
{ {
if(m_Previous) if(m_Previous)
m_Position = m_Previous->GetPosition() + 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);
llist->SetUpdateRect(m_Position);
return m_Position; return m_Position;
} }
void void
wxLayoutLine::RecalculatePositions(int recurse) wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist)
{ {
wxASSERT(recurse >= 0); wxASSERT(recurse >= 0);
wxPoint pos = m_Position; wxPoint pos = m_Position;
CoordType height = m_Height; CoordType height = m_Height;
// WXLO_TRACE("RecalculatePositions()"); // WXLO_TRACE("RecalculatePositions()");
RecalculatePosition(); RecalculatePosition(llist);
if(m_Next) if(m_Next)
{ {
if(recurse > 0) if(recurse > 0)
{ m_Next->RecalculatePositions(--recurse, llist);
if(m_Next) m_Next->RecalculatePositions(--recurse);
}
else if(pos != m_Position || m_Height != height) else if(pos != m_Position || m_Height != height)
if(m_Next) m_Next->RecalculatePositions(); m_Next->RecalculatePositions(0, llist);
} }
} }
@@ -368,21 +381,29 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
{ {
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
wxASSERT(offset); wxASSERT(offset);
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator
i,
found = NULLIT;
CoordType x = 0, len; CoordType x = 0, len;
/* We search through the objects. As we don't like returning the
object that the cursor is behind, we just remember such an
object in "found" so we can return it if there is really no
further object following it. */
for(i = m_ObjectList.begin(); i != NULLIT; i++) for(i = m_ObjectList.begin(); i != NULLIT; i++)
{ {
len = (**i).GetLength(); len = (**i).GetLength();
if( x <= xpos && xpos <= x + len ) if( x <= xpos && xpos <= x + len )
{ {
*offset = xpos-x; *offset = xpos-x;
return i; if(xpos == x + len) // is there another object behind?
found = i;
else // we are really inside this object
return i;
} }
x += (**i).GetLength(); x += (**i).GetLength();
} }
return NULLIT; return found; // ==NULL if really none found
} }
wxLayoutObjectList::iterator wxLayoutObjectList::iterator
@@ -586,14 +607,14 @@ wxLayoutLine::DeleteWord(CoordType xpos)
} }
wxLayoutLine * wxLayoutLine *
wxLayoutLine::DeleteLine(bool update) wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist)
{ {
if(m_Next) m_Next->m_Previous = m_Previous; if(m_Next) m_Next->m_Previous = m_Previous;
if(m_Previous) m_Previous->m_Next = m_Next; if(m_Previous) m_Previous->m_Next = m_Next;
if(update) if(update)
{ {
m_Next->MoveLines(-1); m_Next->MoveLines(-1);
m_Next->RecalculatePositions(1); m_Next->RecalculatePositions(1, llist);
} }
wxLayoutLine *next = m_Next; wxLayoutLine *next = m_Next;
delete this; delete this;
@@ -601,7 +622,9 @@ wxLayoutLine::DeleteLine(bool update)
} }
void void
wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const wxLayoutLine::Draw(wxDC &dc,
wxLayoutList *llist,
const wxPoint & offset) const
{ {
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i;
wxPoint pos = offset; wxPoint pos = offset;
@@ -617,7 +640,9 @@ wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const
} }
void void
wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos, wxLayoutLine::Layout(wxDC &dc,
wxLayoutList *llist,
wxPoint *cursorPos,
wxPoint *cursorSize, wxPoint *cursorSize,
int cx) int cx)
{ {
@@ -641,6 +666,7 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
if(cursorPos) if(cursorPos)
{ {
*cursorPos = m_Position; *cursorPos = m_Position;
if(cursorSize) *cursorSize = wxPoint(0,0);
} }
for(i = m_ObjectList.begin(); i != NULLIT; i++) for(i = m_ObjectList.begin(); i != NULLIT; i++)
@@ -718,7 +744,7 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
// tell next line about coordinate change // tell next line about coordinate change
if(m_Next && objHeight != oldHeight) if(m_Next && objHeight != oldHeight)
m_Next->RecalculatePositions(); m_Next->RecalculatePositions(0, llist);
// We need to check whether we found a valid cursor size: // We need to check whether we found a valid cursor size:
if(cursorPos) if(cursorPos)
@@ -727,18 +753,10 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
// line or on a command object: // line or on a command object:
if(cursorSize->y < WXLO_MINIMUM_CURSOR_WIDTH) if(cursorSize->y < WXLO_MINIMUM_CURSOR_WIDTH)
{ {
if(m_BaseLine > 0) CoordType width, height, descent;
{ dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
cursorSize->y = m_BaseLine; cursorSize->x = width;
if(cursorSize->x < WXLO_MINIMUM_CURSOR_WIDTH) cursorSize->x = WXLO_MINIMUM_CURSOR_WIDTH; cursorSize->y = height;
}
else // empty line
{
CoordType width, height, descent;
dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
cursorSize->x = width;
cursorSize->y = height;
}
} }
if(m_BaseLine >= cursorSize->y) // the normal case anyway if(m_BaseLine >= cursorSize->y) // the normal case anyway
cursorPos->y += m_BaseLine-cursorSize->y; cursorPos->y += m_BaseLine-cursorSize->y;
@@ -747,13 +765,13 @@ wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
wxLayoutLine * wxLayoutLine *
wxLayoutLine::Break(CoordType xpos) wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
{ {
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
if(xpos == 0) if(xpos == 0)
{ // insert an empty line before this one { // insert an empty line before this one
wxLayoutLine *prev = new wxLayoutLine(m_Previous); wxLayoutLine *prev = new wxLayoutLine(m_Previous, llist);
if(m_Previous == NULL) if(m_Previous == NULL)
{ // We were in first line, need to link in new empty line { // We were in first line, need to link in new empty line
// before this. // before this.
@@ -763,7 +781,7 @@ wxLayoutLine::Break(CoordType xpos)
} }
MoveLines(+1); MoveLines(+1);
if(m_Next) if(m_Next)
m_Next->RecalculatePositions(1); m_Next->RecalculatePositions(1, llist);
return this; return this;
} }
@@ -771,10 +789,10 @@ wxLayoutLine::Break(CoordType xpos)
wxLOiterator i = FindObject(xpos, &offset); wxLOiterator i = FindObject(xpos, &offset);
if(i == NULLIT) if(i == NULLIT)
// must be at the end of the line then // must be at the end of the line then
return new wxLayoutLine(this); return new wxLayoutLine(this, llist);
// split this line: // split this line:
wxLayoutLine *newLine = new wxLayoutLine(this); wxLayoutLine *newLine = new wxLayoutLine(this, llist);
// split object at i: // split object at i:
if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0) if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0)
{ {
@@ -799,13 +817,13 @@ wxLayoutLine::Break(CoordType xpos)
m_ObjectList.remove(i); // remove without deleting it m_ObjectList.remove(i); // remove without deleting it
} }
if(m_Next) if(m_Next)
m_Next->RecalculatePositions(2); m_Next->RecalculatePositions(2, llist);
return newLine; return newLine;
} }
void void
wxLayoutLine::MergeNextLine(void) wxLayoutLine::MergeNextLine(wxLayoutList *llist)
{ {
wxASSERT(GetNextLine()); wxASSERT(GetNextLine());
wxLayoutObjectList &list = GetNextLine()->m_ObjectList; wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
@@ -820,7 +838,7 @@ wxLayoutLine::MergeNextLine(void)
wxLayoutLine *oldnext = GetNextLine(); wxLayoutLine *oldnext = GetNextLine();
SetNext(GetNextLine()->GetNextLine()); SetNext(GetNextLine()->GetNextLine());
delete oldnext; delete oldnext;
RecalculatePositions(1); RecalculatePositions(1, llist);
} }
CoordType CoordType
@@ -890,6 +908,8 @@ wxLayoutList::wxLayoutList()
{ {
m_DefaultSetting = NULL; m_DefaultSetting = NULL;
m_FirstLine = NULL; m_FirstLine = NULL;
m_ColourFG = *wxBLACK;
m_ColourBG = *wxWHITE;
InvalidateUpdateRect(); InvalidateUpdateRect();
Clear(); Clear();
} }
@@ -897,20 +917,21 @@ wxLayoutList::wxLayoutList()
wxLayoutList::~wxLayoutList() wxLayoutList::~wxLayoutList()
{ {
InternalClear(); InternalClear();
m_FirstLine->DeleteLine(false); m_FirstLine->DeleteLine(false, this);
} }
void void
wxLayoutList::Empty(void) wxLayoutList::Empty(void)
{ {
while(m_FirstLine) while(m_FirstLine)
m_FirstLine = m_FirstLine->DeleteLine(false); m_FirstLine = m_FirstLine->DeleteLine(false, this);
m_CursorPos = wxPoint(0,0); m_CursorPos = wxPoint(0,0);
m_CursorScreenPos = wxPoint(0,0); m_CursorScreenPos = wxPoint(0,0);
m_CursorSize = wxPoint(0,0); m_CursorSize = wxPoint(0,0);
m_FirstLine = new wxLayoutLine(NULL); // empty first line m_FirstLine = new wxLayoutLine(NULL, this); // empty first line
m_CursorLine = m_FirstLine; m_CursorLine = m_FirstLine;
InvalidateUpdateRect();
} }
@@ -927,8 +948,8 @@ wxLayoutList::InternalClear(void)
void void
wxLayoutList::SetFont(int family, int size, int style, int weight, wxLayoutList::SetFont(int family, int size, int style, int weight,
int underline, wxColour const *fg, int underline, wxColour *fg,
wxColour const *bg) wxColour *bg)
{ {
if(family != -1) m_FontFamily = family; if(family != -1) m_FontFamily = family;
if(size != -1) m_FontPtSize = size; if(size != -1) m_FontPtSize = size;
@@ -936,8 +957,8 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
if(weight != -1) m_FontWeight = weight; if(weight != -1) m_FontWeight = weight;
if(underline != -1) m_FontUnderline = underline != 0; if(underline != -1) m_FontUnderline = underline != 0;
if(fg != NULL) m_ColourFG = fg; if(fg != NULL) m_ColourFG = *fg;
if(bg != NULL) m_ColourBG = bg; if(bg != NULL) m_ColourBG = *bg;
Insert( Insert(
new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline, new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
@@ -949,9 +970,9 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
int underline, char const *fg, char const *bg) int underline, char const *fg, char const *bg)
{ {
wxColour const wxColour
* cfg = NULL, *cfg = NULL,
* cbg = NULL; *cbg = NULL;
if( fg ) if( fg )
cfg = wxTheColourDatabase->FindColour(fg); cfg = wxTheColourDatabase->FindColour(fg);
@@ -963,7 +984,7 @@ wxLayoutList::SetFont(int family, int size, int style, int weight,
void void
wxLayoutList::Clear(int family, int size, int style, int weight, wxLayoutList::Clear(int family, int size, int style, int weight,
int /* underline */, char const *fg, char const *bg) int /* underline */, wxColour *fg, wxColour *bg)
{ {
InternalClear(); InternalClear();
@@ -973,11 +994,11 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
m_FontFamily = family; m_FontFamily = family;
m_FontStyle = style; m_FontStyle = style;
m_FontWeight = weight; m_FontWeight = weight;
m_ColourFG = wxTheColourDatabase->FindColour(fg); if(fg) m_ColourFG = *fg;
m_ColourBG = wxTheColourDatabase->FindColour(bg); if(bg) m_ColourBG = *bg;
if(! m_ColourFG) m_ColourFG = wxBLACK; m_ColourFG = *wxBLACK;
if(! m_ColourBG) m_ColourBG = wxWHITE; m_ColourBG = *wxWHITE;
if(m_DefaultSetting) if(m_DefaultSetting)
delete m_DefaultSetting; delete m_DefaultSetting;
@@ -993,6 +1014,8 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
bool bool
wxLayoutList::MoveCursorTo(wxPoint const &p) wxLayoutList::MoveCursorTo(wxPoint const &p)
{ {
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
wxLayoutLine *line = m_FirstLine; wxLayoutLine *line = m_FirstLine;
while(line && line->GetLineNumber() != p.y) while(line && line->GetLineNumber() != p.y)
line = line->GetNextLine(); line = line->GetNextLine();
@@ -1018,6 +1041,9 @@ wxLayoutList::MoveCursorTo(wxPoint const &p)
bool bool
wxLayoutList::MoveCursorVertically(int n) wxLayoutList::MoveCursorVertically(int n)
{ {
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
bool rc;
if(n < 0) // move up if(n < 0) // move up
{ {
if(m_CursorLine == m_FirstLine) return false; if(m_CursorLine == m_FirstLine) return false;
@@ -1031,13 +1057,13 @@ wxLayoutList::MoveCursorVertically(int n)
{ {
m_CursorLine = m_FirstLine; m_CursorLine = m_FirstLine;
m_CursorPos.y = 0; m_CursorPos.y = 0;
return false; rc = false;
} }
else else
{ {
if(m_CursorPos.x > m_CursorLine->GetLength()) if(m_CursorPos.x > m_CursorLine->GetLength())
m_CursorPos.x = m_CursorLine->GetLength(); m_CursorPos.x = m_CursorLine->GetLength();
return true; rc = true;
} }
} }
else // move down else // move down
@@ -1054,20 +1080,23 @@ wxLayoutList::MoveCursorVertically(int n)
{ {
m_CursorLine = last; m_CursorLine = last;
m_CursorPos.y ++; m_CursorPos.y ++;
return false; rc = false;
} }
else else
{ {
if(m_CursorPos.x > m_CursorLine->GetLength()) if(m_CursorPos.x > m_CursorLine->GetLength())
m_CursorPos.x = m_CursorLine->GetLength(); m_CursorPos.x = m_CursorLine->GetLength();
return true; rc = true;
} }
} }
return rc;
} }
bool bool
wxLayoutList::MoveCursorHorizontally(int n) wxLayoutList::MoveCursorHorizontally(int n)
{ {
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
int move; int move;
while(n < 0) while(n < 0)
{ {
@@ -1107,6 +1136,8 @@ bool
wxLayoutList::Insert(wxString const &text) wxLayoutList::Insert(wxString const &text)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
m_CursorLine->Insert(m_CursorPos.x, text); m_CursorLine->Insert(m_CursorPos.x, text);
m_CursorPos.x += text.Length(); m_CursorPos.x += text.Length();
return true; return true;
@@ -1116,6 +1147,8 @@ bool
wxLayoutList::Insert(wxLayoutObject *obj) wxLayoutList::Insert(wxLayoutObject *obj)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
m_CursorLine->Insert(m_CursorPos.x, obj); m_CursorLine->Insert(m_CursorPos.x, obj);
m_CursorPos.x += obj->GetLength(); m_CursorPos.x += obj->GetLength();
return true; return true;
@@ -1125,9 +1158,10 @@ bool
wxLayoutList::LineBreak(void) wxLayoutList::LineBreak(void)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0); bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
m_CursorLine = m_CursorLine->Break(m_CursorPos.x); SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
if(setFirst) // we were at beginning of first line if(setFirst) // we were at beginning of first line
m_FirstLine = m_CursorLine->GetPreviousLine(); m_FirstLine = m_CursorLine->GetPreviousLine();
m_CursorPos.y++; m_CursorPos.y++;
@@ -1148,6 +1182,8 @@ wxLayoutList::WrapLine(CoordType column)
//else: //else:
CoordType newpos = m_CursorPos.x - xpos - 1; CoordType newpos = m_CursorPos.x - xpos - 1;
m_CursorPos.x = xpos; m_CursorPos.x = xpos;
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
LineBreak(); LineBreak();
Delete(1); // delete the space Delete(1); // delete the space
m_CursorPos.x = newpos; m_CursorPos.x = newpos;
@@ -1159,6 +1195,8 @@ bool
wxLayoutList::Delete(CoordType npos) wxLayoutList::Delete(CoordType npos)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
CoordType left; CoordType left;
do do
{ {
@@ -1184,7 +1222,7 @@ wxLayoutList::Delete(CoordType npos)
break; // cannot break; // cannot
else else
{ {
m_CursorLine->MergeNextLine(); m_CursorLine->MergeNextLine(this);
left--; left--;
} }
} }
@@ -1198,6 +1236,8 @@ wxLayoutList::DeleteLines(int n)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
wxLayoutLine *line; wxLayoutLine *line;
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
while(n > 0) while(n > 0)
{ {
if(!m_CursorLine->GetNextLine()) if(!m_CursorLine->GetNextLine())
@@ -1208,18 +1248,18 @@ wxLayoutList::DeleteLines(int n)
} }
//else: //else:
line = m_CursorLine; line = m_CursorLine;
m_CursorLine = m_CursorLine->DeleteLine(true); m_CursorLine = m_CursorLine->DeleteLine(true, this);
n--; n--;
if(line == m_FirstLine) m_FirstLine = m_CursorLine; if(line == m_FirstLine) m_FirstLine = m_CursorLine;
wxASSERT(m_FirstLine); wxASSERT(m_FirstLine);
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
} }
m_CursorLine->RecalculatePositions(2); m_CursorLine->RecalculatePositions(2, this);
return n; return n;
} }
void void
wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
{ {
wxLayoutLine *line = m_FirstLine; wxLayoutLine *line = m_FirstLine;
@@ -1228,7 +1268,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
m_DefaultSetting->Layout(dc); m_DefaultSetting->Layout(dc);
while(line) while(line)
{ {
line->RecalculatePosition(); // so we don't need to do it all the time line->RecalculatePosition(this); // so we don't need to do it all the time
// little condition to speed up redrawing: // little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom) break; if(bottom != -1 && line->GetPosition().y > bottom) break;
line = line->GetNextLine(); line = line->GetNextLine();
@@ -1236,7 +1276,21 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
} }
void void
wxLayoutList::Layout(wxDC &dc, CoordType bottom) const wxLayoutList::UpdateCursorScreenPos(wxDC &dc)
{
wxASSERT(m_CursorLine);
m_CursorLine->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
}
wxPoint
wxLayoutList::GetCursorScreenPos(wxDC &dc)
{
UpdateCursorScreenPos(dc);
return m_CursorScreenPos;
}
void
wxLayoutList::Layout(wxDC &dc, CoordType bottom)
{ {
wxLayoutLine *line = m_FirstLine; wxLayoutLine *line = m_FirstLine;
@@ -1246,9 +1300,9 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
while(line) while(line)
{ {
if(line == m_CursorLine) if(line == m_CursorLine)
line->Layout(dc, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x); line->Layout(dc, this, (wxPoint *)&m_CursorScreenPos, (wxPoint *)&m_CursorSize, m_CursorPos.x);
else else
line->Layout(dc); line->Layout(dc, this);
// little condition to speed up redrawing: // little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom) break; if(bottom != -1 && line->GetPosition().y > bottom) break;
line = line->GetNextLine(); line = line->GetNextLine();
@@ -1261,25 +1315,26 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
m_CursorLine->GetNextLine() == NULL && m_CursorLine->GetNextLine() == NULL &&
m_CursorLine == m_FirstLine)); m_CursorLine == m_FirstLine));
#endif #endif
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
} }
void void
wxLayoutList::Draw(wxDC &dc, wxPoint const &offset, wxLayoutList::Draw(wxDC &dc, wxPoint const &offset,
CoordType top, CoordType bottom) const CoordType top, CoordType bottom)
{ {
wxLayoutLine *line = m_FirstLine; wxLayoutLine *line = m_FirstLine;
Layout(dc, bottom); Layout(dc, bottom);
m_DefaultSetting->Draw(dc, wxPoint(0,0)); m_DefaultSetting->Draw(dc, wxPoint(0,0));
wxBrush *brush = new wxBrush(*m_ColourBG, wxSOLID); wxBrush brush(m_ColourBG, wxSOLID);
dc.SetBrush(*brush); dc.SetBrush(brush);
delete brush;
while(line) while(line)
{ {
// only draw if between top and bottom: // only draw if between top and bottom:
if((top == -1 || line->GetPosition().y >= top)) if((top == -1 || line->GetPosition().y >= top))
line->Draw(dc, offset); line->Draw(dc, this, offset);
// little condition to speed up redrawing: // little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y + line->GetHeight() > bottom) break; if(bottom != -1 && line->GetPosition().y + line->GetHeight() > bottom) break;
line = line->GetNextLine(); line = line->GetNextLine();
@@ -1288,6 +1343,7 @@ wxLayoutList::Draw(wxDC &dc, wxPoint const &offset,
wxASSERT(m_CursorSize.x != 0 || (m_CursorLine && wxASSERT(m_CursorSize.x != 0 || (m_CursorLine &&
m_CursorLine->GetNextLine() == NULL && m_CursorLine->GetNextLine() == NULL &&
m_CursorLine == m_FirstLine)); m_CursorLine == m_FirstLine));
InvalidateUpdateRect();
} }
wxLayoutObject * wxLayoutObject *
@@ -1304,7 +1360,7 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, wxPoint *cursorPos)
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->Layout(dc, this);
line = line->GetNextLine(); line = line->GetNextLine();
} }
if(line == NULL) return NULL; // not found if(line == NULL) return NULL; // not found
@@ -1387,6 +1443,27 @@ wxLayoutList::SetUpdateRect(const wxPoint &p)
} }
} }
void
wxLayoutList::StartSelection(void)
{
wxLogDebug("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y);
m_Selection.m_CursorA = m_CursorPos;
}
void
wxLayoutList::EndSelection(void)
{
wxLogDebug("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y);
m_Selection.m_CursorB = m_CursorPos;
}
bool
wxLayoutList::IsSelected(const wxPoint &cursor)
{
return m_Selection.m_CursorA <= cursor
&& cursor <= m_Selection.m_CursorB;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

View File

@@ -291,12 +291,12 @@ public:
virtual void Draw(wxDC &dc, wxPoint const &coords); virtual void Draw(wxDC &dc, wxPoint const &coords);
wxLayoutObjectCmd(int size, int family, int style, int weight, wxLayoutObjectCmd(int size, int family, int style, int weight,
bool underline, bool underline,
wxColour const *fg, wxColour const *bg); wxColour &fg, wxColour &bg);
~wxLayoutObjectCmd(); ~wxLayoutObjectCmd();
/** Stores the current style in the styleinfo structure */ /** Stores the current style in the styleinfo structure */
void GetStyle(wxLayoutStyleInfo *si) const; void GetStyle(wxLayoutStyleInfo *si) const;
/// return the background colour for setting colour of window /// return the background colour for setting colour of window
wxColour const *GetBGColour(void) const { return m_ColourBG; } wxColour &GetBGColour(void) { return m_ColourBG; }
/** Makes a copy of this object. /** Makes a copy of this object.
*/ */
virtual wxLayoutObject *Copy(void); virtual wxLayoutObject *Copy(void);
@@ -304,9 +304,9 @@ private:
/// the font to use /// the font to use
wxFont *m_font; wxFont *m_font;
/// foreground colour /// foreground colour
wxColour const *m_ColourFG; wxColour m_ColourFG;
/// background colour /// background colour
wxColour const *m_ColourBG; wxColour m_ColourBG;
}; };
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -315,6 +315,9 @@ private:
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/// forward declaration
class wxLayoutList;
/** This class represents a single line of objects to be displayed. /** This class represents a single line of objects to be displayed.
It knows its height and total size and whether it needs to be It knows its height and total size and whether it needs to be
redrawn or not. redrawn or not.
@@ -327,8 +330,9 @@ public:
/** Constructor. /** Constructor.
@param prev pointer to previous line or NULL @param prev pointer to previous line or NULL
@param next pointer to following line or NULL @param next pointer to following line or NULL
@param llist pointer to layout list
*/ */
wxLayoutLine(wxLayoutLine *prev); wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist);
/** This function inserts a new object at cursor position xpos. /** This function inserts a new object at cursor position xpos.
@param xpos where to insert new object @param xpos where to insert new object
@param obj the object to insert @param obj the object to insert
@@ -356,7 +360,7 @@ public:
/** This function appens the next line to this, i.e. joins the two /** This function appens the next line to this, i.e. joins the two
lines into one. lines into one.
*/ */
void MergeNextLine(void); void MergeNextLine(wxLayoutList *llist);
/** This function deletes npos cursor positions from position xpos. /** This function deletes npos cursor positions from position xpos.
@param xpos where to delete @param xpos where to delete
@@ -369,7 +373,7 @@ public:
@param xpos where to break it @param xpos where to break it
@return pointer to the new line object replacing the old one @return pointer to the new line object replacing the old one
*/ */
wxLayoutLine *Break(CoordType xpos); wxLayoutLine *Break(CoordType xpos, wxLayoutList *llist);
/** Deletes the next word from this position, including leading /** Deletes the next word from this position, including leading
whitespace. whitespace.
@@ -423,7 +427,7 @@ public:
/** Deletes this line, returns pointer to next line. /** Deletes this line, returns pointer to next line.
@param update If true, update all following lines. @param update If true, update all following lines.
*/ */
wxLayoutLine *DeleteLine(bool update); wxLayoutLine *DeleteLine(bool update, wxLayoutList *llist);
/**@name Cursor Management */ /**@name Cursor Management */
//@{ //@{
@@ -441,18 +445,23 @@ public:
//@{ //@{
/** Draws the line on a wxDC. /** Draws the line on a wxDC.
@param dc the wxDC to draw on @param dc the wxDC to draw on
@param llist the wxLayoutList
@param offset an optional offset to shift printout @param offset an optional offset to shift printout
*/ */
void Draw(wxDC &dc, const wxPoint &offset = wxPoint(0,0)) const; void Draw(wxDC &dc,
wxLayoutList *llist,
const wxPoint &offset = wxPoint(0,0)) const;
/** Recalculates the positions of objects and the height of the /** Recalculates the positions of objects and the height of the
line. line.
@param dc the wxDC to draw on @param dc the wxDC to draw on
@param llist th e wxLayoutList
@param cursorPos if not NULL, set cursor screen position in there @param cursorPos if not NULL, set cursor screen position in there
@param cursorSize if not cursorPos != NULL, set cursor size in there @param cursorSize if not cursorPos != NULL, set cursor size in there
@param cx if cursorPos != NULL, the cursor x position @param cx if cursorPos != NULL, the cursor x position
*/ */
void Layout(wxDC &dc, void Layout(wxDC &dc,
wxLayoutList *llist,
wxPoint *cursorPos = NULL, wxPoint *cursorPos = NULL,
wxPoint *cursorSize = NULL, wxPoint *cursorSize = NULL,
int cx = 0); int cx = 0);
@@ -493,9 +502,9 @@ public:
minimum(!) recursion level, continue with all lines till the end of minimum(!) recursion level, continue with all lines till the end of
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, wxLayoutList *llist);
/// Recalculates the position of this line on the canvas. /// Recalculates the position of this line on the canvas.
wxPoint RecalculatePosition(void); wxPoint RecalculatePosition(wxLayoutList *llist);
private: private:
/// Destructor is private. Use DeleteLine() to remove it. /// Destructor is private. Use DeleteLine() to remove it.
~wxLayoutLine(); ~wxLayoutLine();
@@ -506,8 +515,8 @@ private:
dirty. dirty.
@param height new height @param height new height
*/ */
void SetHeight(CoordType height) void SetHeight(CoordType height, wxLayoutList *llist)
{ m_Height = height; RecalculatePositions(true); } { m_Height = height; RecalculatePositions(true, llist); }
/** 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.
@@ -542,6 +551,8 @@ private:
wxLayoutLine *m_Next; wxLayoutLine *m_Next;
/// Just to suppress gcc compiler warnings. /// Just to suppress gcc compiler warnings.
friend class dummy; friend class dummy;
private:
wxLayoutLine(const wxLayoutLine &);
}; };
@@ -568,8 +579,8 @@ public:
int style=wxNORMAL, int style=wxNORMAL,
int weight=wxNORMAL, int weight=wxNORMAL,
int underline=0, int underline=0,
char const *fg="black", wxColour *fg=NULL,
char const *bg="white"); wxColour *bg=NULL);
/// Empty: clear the list but leave font settings. /// Empty: clear the list but leave font settings.
void Empty(void); void Empty(void);
@@ -603,7 +614,7 @@ public:
{ MoveCursorHorizontally(-m_CursorPos.x); } { MoveCursorHorizontally(-m_CursorPos.x); }
/// Returns current cursor position. /// Returns current cursor position.
wxPoint GetCursorPos(void) const { return m_CursorPos; } wxPoint GetCursorPos(wxDC &dc) const { return m_CursorPos; }
//@} //@}
/**@name Editing functions. /**@name Editing functions.
@@ -669,8 +680,8 @@ public:
/// sets font parameters /// sets font parameters
void SetFont(int family, int size, int style, void SetFont(int family, int size, int style,
int weight, int underline, int weight, int underline,
wxColour const *fg, wxColour *fg,
wxColour const *bg); wxColour *bg);
/// sets font parameters, colours by name /// sets font parameters, colours by name
void SetFont(int family=-1, int size = -1, int style=-1, void SetFont(int family=-1, int size = -1, int style=-1,
int weight=-1, int underline = -1, int weight=-1, int underline = -1,
@@ -701,7 +712,7 @@ public:
anywhere. anywhere.
@return the default settings of the list @return the default settings of the list
*/ */
wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; } wxLayoutObjectCmd *GetDefaults(void) { return m_DefaultSetting ; }
//@} //@}
/**@name Drawing */ /**@name Drawing */
@@ -713,21 +724,21 @@ public:
@param bottom optional y coordinate where to stop drawing @param bottom optional y coordinate where to stop drawing
*/ */
void Draw(wxDC &dc, const wxPoint &offset = wxPoint(0,0), void Draw(wxDC &dc, const wxPoint &offset = wxPoint(0,0),
CoordType top = -1, CoordType bottom = -1) const; CoordType top = -1, CoordType bottom = -1);
/** Calculates new layout for the list, like Draw() but does not /** Calculates new layout for the list, like Draw() but does not
actually draw it. actually draw it.
@param dc the wxDC to draw on @param dc the wxDC to draw on
@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);
/** Calculates new sizes for everything in the list, like Layout() /** Calculates new sizes for everything in the list, like Layout()
but this is needed after the list got changed. but this is needed after the list got changed.
@param dc the wxDC to draw on @param dc the wxDC to draw on
@param bottom optional y coordinate where to stop calculating @param bottom optional y coordinate where to stop calculating
*/ */
void Recalculate(wxDC &dc, CoordType bottom = -1) const; void Recalculate(wxDC &dc, CoordType bottom = -1);
/** 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
@@ -740,8 +751,7 @@ public:
/** Returns the cursor position on the screen. /** Returns the cursor position on the screen.
@return cursor position in pixels @return cursor position in pixels
*/ */
wxPoint GetCursorScreenPos(void) const wxPoint GetCursorScreenPos(wxDC &dc);
{ return m_CursorScreenPos; }
/** Draws the cursor. /** Draws the cursor.
@param active If true, draw a bold cursor to mark window as @param active If true, draw a bold cursor to mark window as
@@ -781,9 +791,17 @@ public:
return m_FirstLine; return m_FirstLine;
} }
//@} //@}
void StartSelection(void);
void EndSelection(void);
bool IsSelected(const wxPoint &cursor);
private: private:
/// Clear the list. /// Clear the list.
void InternalClear(void); void InternalClear(void);
/** Calculates the cursor position on the screen.
*/
void UpdateCursorScreenPos(wxDC &dc);
/// The list of lines. /// The list of lines.
wxLayoutLine *m_FirstLine; wxLayoutLine *m_FirstLine;
@@ -803,14 +821,20 @@ private:
wxLayoutLine *m_CursorLine; wxLayoutLine *m_CursorLine;
//@} //@}
/// A structure for the selection.
struct
{
bool m_valid;
wxPoint m_CursorA, m_CursorB;
}m_Selection;
/** @name Font parameters. */ /** @name Font parameters. */
//@{ //@{
int m_FontFamily, m_FontStyle, m_FontWeight; int m_FontFamily, m_FontStyle, m_FontWeight;
int m_FontPtSize; int m_FontPtSize;
bool m_FontUnderline; bool m_FontUnderline;
/// colours: /// colours:
wxColour const * m_ColourFG; wxColour m_ColourFG;
wxColour const * m_ColourBG; wxColour m_ColourBG;
/// the default setting: /// the default setting:
wxLayoutObjectCmd *m_DefaultSetting; wxLayoutObjectCmd *m_DefaultSetting;
//@} //@}

View File

@@ -78,11 +78,13 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
m_bitmapSize = wxPoint(4,4); m_bitmapSize = wxPoint(4,4);
m_llist = new wxLayoutList(); m_llist = new wxLayoutList();
m_BGbitmap = NULL; m_BGbitmap = NULL;
m_ScrollToCursor = false;
SetWrapMargin(0); 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;
m_Selecting = false;
SetCursor(wxCURSOR_IBEAM); SetCursor(wxCURSOR_IBEAM);
SetDirty(); SetDirty();
} }
@@ -144,7 +146,7 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
if(obj && eventId == WXLOWIN_MENU_LCLICK) if(obj && eventId == WXLOWIN_MENU_LCLICK)
{ {
m_llist->MoveCursorTo(cursorPos); m_llist->MoveCursorTo(cursorPos);
DoPaint(false); m_ScrollToCursor = true; //FIXME: needed? DoPaint(m_llist->GetUpdateRect());
} }
if(!m_doSendEvents) // nothing to do if(!m_doSendEvents) // nothing to do
return; return;
@@ -181,11 +183,18 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
} }
long keyCode = event.KeyCode(); long keyCode = event.KeyCode();
if(event.ShiftDown())
m_Selecting = true;
else
{
if(m_Selecting)
m_llist->EndSelection();
m_Selecting = false;
}
/* First, handle control keys */ /* First, handle control keys */
if(event.ControlDown() && ! event.AltDown()) if(event.ControlDown() && ! event.AltDown())
{ {
switch(event.KeyCode()) switch(keyCode)
{ {
case WXK_DELETE : case WXK_DELETE :
case 'd': case 'd':
@@ -215,7 +224,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
// ALT only: // ALT only:
else if( event.AltDown() && ! event.ControlDown() ) else if( event.AltDown() && ! event.ControlDown() )
{ {
switch(event.KeyCode()) switch(keyCode)
{ {
case WXK_DELETE: case WXK_DELETE:
case 'd': case 'd':
@@ -228,30 +237,38 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
// no control keys: // no control keys:
else if ( ! event.AltDown() && ! event.ControlDown()) else if ( ! event.AltDown() && ! event.ControlDown())
{ {
switch(event.KeyCode()) switch(keyCode)
{ {
case WXK_RIGHT: case WXK_RIGHT:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorHorizontally(1); m_llist->MoveCursorHorizontally(1);
break; break;
case WXK_LEFT: case WXK_LEFT:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorHorizontally(-1); m_llist->MoveCursorHorizontally(-1);
break; break;
case WXK_UP: case WXK_UP:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorVertically(-1); m_llist->MoveCursorVertically(-1);
break; break;
case WXK_DOWN: case WXK_DOWN:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorVertically(1); m_llist->MoveCursorVertically(1);
break; break;
case WXK_PRIOR: case WXK_PRIOR:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorVertically(-20); m_llist->MoveCursorVertically(-20);
break; break;
case WXK_NEXT: case WXK_NEXT:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorVertically(20); m_llist->MoveCursorVertically(20);
break; break;
case WXK_HOME: case WXK_HOME:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorToBeginOfLine(); m_llist->MoveCursorToBeginOfLine();
break; break;
case WXK_END: case WXK_END:
if(m_Selecting) m_llist->StartSelection();
m_llist->MoveCursorToEndOfLine(); m_llist->MoveCursorToEndOfLine();
break; break;
case WXK_DELETE : case WXK_DELETE :
@@ -281,29 +298,32 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
} }
SetDirty(); SetDirty();
SetModified(); SetModified();
DoPaint(true); // paint and scroll to cursor m_ScrollToCursor = true;
//DoPaint(true); // paint and scroll to cursor
wxRect r = *m_llist->GetUpdateRect();
r.x -= WXLO_XOFFSET; r.y -= WXLO_YOFFSET;
Refresh( FALSE, &r);
} }
void void
wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc) wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
{ {
m_ScrollToCursor = false; wxRect region = GetUpdateRegion().GetBox();
InternalPaint(); InternalPaint(& region);
} }
void void
wxLayoutWindow::DoPaint(bool scrollToCursor) wxLayoutWindow::DoPaint(const wxRect *updateRect)
{ {
m_ScrollToCursor = scrollToCursor;
#ifdef __WXGTK__ #ifdef __WXGTK__
InternalPaint(); InternalPaint(updateRect);
#else #else
Refresh(FALSE); // Causes bad flicker under wxGTK!!! Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!!
#endif #endif
} }
void void
wxLayoutWindow::InternalPaint(void) wxLayoutWindow::InternalPaint(const wxRect *updateRect)
{ {
wxPaintDC dc( this ); wxPaintDC dc( this );
PrepareDC( dc ); PrepareDC( dc );
@@ -324,12 +344,26 @@ wxLayoutWindow::InternalPaint(void)
if(x1 > m_maxx) m_maxx = x1; if(x1 > m_maxx) m_maxx = x1;
if(y1 > m_maxy) m_maxy = y1; if(y1 > m_maxy) m_maxy = y1;
// Maybe we need to change the scrollbar sizes or positions,
m_llist->InvalidateUpdateRect();
const wxRect *r = m_llist->GetUpdateRect();
wxLogDebug("Update rect before calling Layout: %ld,%ld / %ld,%ld",
r->x, r->y, r->x+r->width, r->y+r->height);
#if 0
//FIXME: we should never need to call Layout at all because the
// list does it automatically.
// Maybe we need to change the scrollbar sizes or positions,
// so layout the list and check: // so layout the list and check:
if(IsDirty()) if(IsDirty())
m_llist->Layout(dc); m_llist->Layout(dc);
wxLogDebug("Update rect after calling Layout: %ld,%ld / %ld,%ld",
r->x, r->y, r->x+r->width, r->y+r->height);
// this is needed even when only the cursor moved // this is needed even when only the cursor moved
m_llist->Layout(dc,y0+y1); m_llist->Layout(dc,y0+y1);
wxLogDebug("Update rect after calling Layout again: %ld,%ld / %ld,%ld",
r->x, r->y, r->x+r->width, r->y+r->height);
#endif
if(IsDirty()) if(IsDirty())
ResizeScrollbars(); ResizeScrollbars();
@@ -337,9 +371,10 @@ wxLayoutWindow::InternalPaint(void)
/* Make sure that the scrollbars are at a position so that the /* Make sure that the scrollbars are at a position so that the
cursor is visible if we are editing. */ cursor is visible if we are editing. */
/** Scroll so that cursor is visible! */ /** Scroll so that cursor is visible! */
wxLogDebug("m_ScrollToCursor = %d", (int) m_ScrollToCursor);
if(IsEditable() && m_ScrollToCursor) if(IsEditable() && m_ScrollToCursor)
{ {
wxPoint cc = m_llist->GetCursorScreenPos(); wxPoint cc = m_llist->GetCursorScreenPos(*m_memDC);
if(cc.x < x0 || cc.y < y0 if(cc.x < x0 || cc.y < y0
|| cc.x >= x0+(9*x1)/10 || cc.y >= y0+(9*y1/10)) // (9*x)/10 == 90% || cc.x >= x0+(9*x1)/10 || cc.y >= y0+(9*y1/10)) // (9*x)/10 == 90%
{ {
@@ -368,8 +403,8 @@ wxLayoutWindow::InternalPaint(void)
// with the translate parameter of Draw(). // with the translate parameter of Draw().
m_memDC->SetDeviceOrigin(0,0); m_memDC->SetDeviceOrigin(0,0);
m_memDC->SetBackgroundMode(wxTRANSPARENT); m_memDC->SetBackgroundMode(wxTRANSPARENT);
m_memDC->SetBrush(wxBrush(*m_llist->GetDefaults()->GetBGColour(), wxSOLID)); m_memDC->SetBrush(wxBrush(m_llist->GetDefaults()->GetBGColour(), wxSOLID));
m_memDC->SetPen(wxPen(*m_llist->GetDefaults()->GetBGColour(),0,wxTRANSPARENT)); m_memDC->SetPen(wxPen(m_llist->GetDefaults()->GetBGColour(),0,wxTRANSPARENT));
m_memDC->SetLogicalFunction(wxCOPY); m_memDC->SetLogicalFunction(wxCOPY);
if(m_BGbitmap) if(m_BGbitmap)
{ {
@@ -391,15 +426,23 @@ wxLayoutWindow::InternalPaint(void)
m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset); m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset);
// Now copy everything to the screen: // Now copy everything to the screen:
#if 0
//FIXME:
// 1. the update region as calculated by the list is wrong
// 2. we get wrong values here
// 3. how about the offset?
wxRegionIterator ri ( GetUpdateRegion() ); wxRegionIterator ri ( GetUpdateRegion() );
if(ri) if(ri)
while(ri) while(ri)
{ {
wxLogDebug("UpdateRegion: %ld,%ld, %ld,%ld",
ri.GetX(),ri.GetY(),ri.GetW(),ri.GetH());
dc.Blit(x0+ri.GetX(),y0+ri.GetY(),ri.GetW(),ri.GetH(), dc.Blit(x0+ri.GetX(),y0+ri.GetY(),ri.GetW(),ri.GetH(),
m_memDC,ri.GetX(),ri.GetY(),wxCOPY,FALSE); m_memDC,ri.GetX(),ri.GetY(),wxCOPY,FALSE);
ri++; ri++;
} }
else else
#endif
// If there are no update rectangles, we got called to reflect // If there are no update rectangles, we got called to reflect
// a change in the list. Currently there is no mechanism to // a change in the list. Currently there is no mechanism to
// easily find out which bits need updating, so we update // easily find out which bits need updating, so we update
@@ -408,6 +451,7 @@ wxLayoutWindow::InternalPaint(void)
dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE); dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE);
ResetDirty(); ResetDirty();
m_ScrollToCursor = false;
} }
// change the range and position of scroll bars // change the range and position of scroll bars
@@ -522,12 +566,12 @@ void
wxLayoutWindow::OnSetFocus(wxFocusEvent &ev) wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
{ {
m_HaveFocus = true; m_HaveFocus = true;
DoPaint(); // to repaint the cursor //FIXME DoPaint(); // to repaint the cursor
} }
void void
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev) wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
{ {
m_HaveFocus = false; m_HaveFocus = false;
DoPaint(); // to repaint the cursor //FIXME DoPaint(); // to repaint the cursor
} }

View File

@@ -63,15 +63,20 @@ public:
int style=wxNORMAL, int style=wxNORMAL,
int weight=wxNORMAL, int weight=wxNORMAL,
int underline=0, int underline=0,
char const *fg="black", wxColour *fg=NULL,
char const *bg="white") wxColour *bg=NULL)
{ {
GetLayoutList()->Clear(family,size,style,weight,underline,fg,bg); GetLayoutList()->Clear(family,size,style,weight,underline,fg,bg);
SetBackgroundColour(*GetLayoutList()->GetDefaults()->GetBGColour()); SetBackgroundColour(GetLayoutList()->GetDefaults()->GetBGColour());
ResizeScrollbars(true); ResizeScrollbars(true);
SetDirty(); SetDirty();
SetModified(false); SetModified(false);
DoPaint(); wxRect r;
int w,h;
r.x = r.y = 0; GetSize(&w,&h);
r.width = w;
r.height = h;
DoPaint(&r);
} }
/** Sets a background image, only used on screen, not on printouts. /** Sets a background image, only used on screen, not on printouts.
@param bitmap a pointer to a wxBitmap or NULL to remove it @param bitmap a pointer to a wxBitmap or NULL to remove it
@@ -100,10 +105,8 @@ public:
/** Redraws the window. /** Redraws the window.
Internally, this stores the parameter and calls a refresh on Internally, this stores the parameter and calls a refresh on
wxMSW, draws directly on wxGTK. wxMSW, draws directly on wxGTK.
@param scrollToCursor if true, scroll the window so that the
cursor becomes visible
*/ */
void DoPaint(bool scrollToCursor = false); void DoPaint(const wxRect *updateRect);
#ifdef __WXMSW__ #ifdef __WXMSW__
virtual long MSWGetDlgCode(); virtual long MSWGetDlgCode();
@@ -144,7 +147,7 @@ public:
void ResetDirty(void) { m_Dirty = false; } void ResetDirty(void) { m_Dirty = false; }
//@} //@}
/// Redraws the window, used by DoPaint() or OnPaint(). /// Redraws the window, used by DoPaint() or OnPaint().
void InternalPaint(void); void InternalPaint(const wxRect *updateRect);
/// Has list been modified/edited? /// Has list been modified/edited?
bool IsModified(void) const { return m_Modified; } bool IsModified(void) const { return m_Modified; }
@@ -180,6 +183,8 @@ private:
wxLayoutList *m_llist; wxLayoutList *m_llist;
/// Can user edit the window? /// Can user edit the window?
bool m_Editable; bool m_Editable;
/// Are we currently building a selection with the keyboard?
bool m_Selecting;
/// wrap margin /// wrap margin
CoordType m_WrapMargin; CoordType m_WrapMargin;
/// Is list dirty (for redraws, internal use)? /// Is list dirty (for redraws, internal use)?