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:
Karsten Ballüder
1999-03-14 16:04:57 +00:00
parent 86a9c8e02f
commit 77c630ca85
6 changed files with 288 additions and 93 deletions

View File

@@ -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

View File

@@ -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());

View File

@@ -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);
} }

View File

@@ -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);
//@} //@}

View File

@@ -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
} }

View File

@@ -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;