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:
parent
86a9c8e02f
commit
77c630ca85
@ -2,24 +2,12 @@
|
||||
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
|
||||
deleting the second half
|
||||
|
||||
TODO
|
||||
=====================================================================
|
||||
|
||||
- Add word wrap to wxlwindow/wxllist.
|
||||
- Cursor to mouseclick
|
||||
- Focus feedback for cursor
|
||||
- Selections
|
||||
|
||||
- More optimisations
|
||||
|
||||
|
@ -99,6 +99,7 @@ MyFrame::MyFrame(void) :
|
||||
m_lwin = new wxLayoutWindow(this);
|
||||
m_lwin->SetMouseTracking(true);
|
||||
m_lwin->SetEditable(true);
|
||||
m_lwin->SetWrapMargin(40);
|
||||
m_lwin->Clear(wxROMAN,16,wxNORMAL,wxNORMAL, false);
|
||||
m_lwin->SetFocus();
|
||||
};
|
||||
@ -133,14 +134,13 @@ MyFrame::AddSampleText(wxLayoutList *llist)
|
||||
llist->Insert("italics ");
|
||||
llist->SetFont(-1,-1,wxNORMAL);
|
||||
llist->LineBreak();
|
||||
|
||||
|
||||
llist->Insert("and ");
|
||||
llist->SetFont(-1,-1,wxSLANT);
|
||||
llist->Insert("slanted");
|
||||
llist->SetFont(-1,-1,wxNORMAL);
|
||||
llist->Insert(" text.");
|
||||
llist->LineBreak();
|
||||
|
||||
llist->Insert("and ");
|
||||
llist->SetFont(-1,-1,-1,-1,-1,"blue");
|
||||
llist->Insert("blue");
|
||||
@ -211,8 +211,7 @@ void MyFrame::OnCommand( wxCommandEvent &event )
|
||||
break;
|
||||
case ID_NOWRAP:
|
||||
case ID_WRAP:
|
||||
//// m_lwin->GetLayoutList()->SetWrapMargin(
|
||||
//// event.GetId() == ID_NOWRAP ? -1 : 40);
|
||||
m_lwin->SetWrapMargin(event.GetId() == ID_NOWRAP ? 0 : 40);
|
||||
break;
|
||||
case ID_ADD_SAMPLE:
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
wxLayoutObjectText::Layout(wxDC &dc)
|
||||
@ -202,8 +226,10 @@ wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */)
|
||||
{
|
||||
wxASSERT(m_font);
|
||||
dc.SetFont(*m_font);
|
||||
if(m_ColourFG) dc.SetTextForeground(*m_ColourFG);
|
||||
if(m_ColourBG) dc.SetTextBackground(*m_ColourBG);
|
||||
if(m_ColourFG)
|
||||
dc.SetTextForeground(*m_ColourFG);
|
||||
if(m_ColourBG)
|
||||
dc.SetTextBackground(*m_ColourBG);
|
||||
}
|
||||
|
||||
void
|
||||
@ -253,7 +279,7 @@ wxPoint
|
||||
wxLayoutLine::RecalculatePosition(void)
|
||||
{
|
||||
if(m_Previous)
|
||||
m_Position = m_Previous->RecalculatePosition() +
|
||||
m_Position = m_Previous->GetPosition() +
|
||||
wxPoint(0,m_Previous->GetHeight());
|
||||
else
|
||||
m_Position = wxPoint(0,0);
|
||||
@ -263,20 +289,21 @@ wxLayoutLine::RecalculatePosition(void)
|
||||
void
|
||||
wxLayoutLine::RecalculatePositions(int recurse)
|
||||
{
|
||||
wxPoint pos = RecalculatePosition();
|
||||
|
||||
if(pos != m_Position)
|
||||
wxASSERT(recurse >= 0);
|
||||
wxPoint pos = m_Position;
|
||||
CoordType height = m_Height;
|
||||
|
||||
// WXLO_TRACE("RecalculatePositions()");
|
||||
RecalculatePosition();
|
||||
if(m_Next)
|
||||
{
|
||||
m_Position = pos;
|
||||
if(m_Next) m_Next->RecalculatePositions(--recurse);
|
||||
if(recurse > 0)
|
||||
{
|
||||
if(m_Next) m_Next->RecalculatePositions(--recurse);
|
||||
}
|
||||
else if(pos != m_Position || m_Height != height)
|
||||
if(m_Next) m_Next->RecalculatePositions();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Position = pos;
|
||||
if(recurse && m_Next)
|
||||
m_Next->RecalculatePositions(--recurse);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wxLayoutObjectList::iterator
|
||||
@ -287,6 +314,7 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
|
||||
wxLayoutObjectList::iterator i;
|
||||
CoordType x = 0, len;
|
||||
|
||||
|
||||
for(i = m_ObjectList.begin(); i != NULLIT; i++)
|
||||
{
|
||||
len = (**i).GetLength();
|
||||
@ -300,6 +328,32 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const
|
||||
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
|
||||
wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
||||
{
|
||||
@ -329,16 +383,13 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
||||
if(offset == len )
|
||||
{
|
||||
if( i == m_ObjectList.tail()) // last object?
|
||||
{
|
||||
m_ObjectList.push_back(obj);
|
||||
m_Length += obj->GetLength();
|
||||
}
|
||||
else
|
||||
{ // insert after current object
|
||||
i++;
|
||||
m_ObjectList.insert(i,obj);
|
||||
m_Length += obj->GetLength();
|
||||
}
|
||||
m_Length += obj->GetLength();
|
||||
return true;
|
||||
}
|
||||
/* Otherwise we need to split the current object.
|
||||
@ -379,22 +430,23 @@ wxLayoutLine::Insert(CoordType xpos, wxString text)
|
||||
CoordType
|
||||
wxLayoutLine::Delete(CoordType xpos, CoordType npos)
|
||||
{
|
||||
CoordType offset;
|
||||
CoordType offset, len;
|
||||
|
||||
wxASSERT(xpos >= 0);
|
||||
wxASSERT(npos >= 0);
|
||||
wxLOiterator i = FindObject(xpos, &offset);
|
||||
while(npos > 0)
|
||||
{
|
||||
if(i == NULLIT) return false; // FIXME
|
||||
if(i == NULLIT) return npos;
|
||||
// now delete from that object:
|
||||
if((**i).GetType() != WXLO_TYPE_TEXT)
|
||||
{
|
||||
if(offset != 0) // at end of line after a non-text object
|
||||
return npos;
|
||||
// always len == 1:
|
||||
m_Length -= (**i).GetLength();
|
||||
npos -= m_Length;
|
||||
len = (**i).GetLength();
|
||||
m_Length -= len;
|
||||
npos -= len;
|
||||
m_ObjectList.erase(i);
|
||||
}
|
||||
else
|
||||
@ -508,8 +560,8 @@ wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const
|
||||
}
|
||||
|
||||
void
|
||||
wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos, wxPoint
|
||||
*cursorSize,
|
||||
wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
|
||||
wxPoint *cursorSize,
|
||||
int cx)
|
||||
{
|
||||
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::Break(CoordType xpos)
|
||||
@ -690,7 +727,7 @@ wxLayoutLine::Break(CoordType xpos)
|
||||
// current text object gets set to left half
|
||||
tobj->GetText() = left; // set new text
|
||||
newLine->Append(new wxLayoutObjectText(right));
|
||||
m_Length -= m_Length - offset;
|
||||
m_Length -= right.Length();
|
||||
i++; // don't move this object to the new list
|
||||
}
|
||||
else
|
||||
@ -728,6 +765,38 @@ wxLayoutLine::MergeNextLine(void)
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
wxLayoutList::Delete(CoordType npos)
|
||||
{
|
||||
@ -991,7 +1080,12 @@ wxLayoutList::Delete(CoordType npos)
|
||||
// First, check if line is empty:
|
||||
if(m_CursorLine->GetLength() == 0)
|
||||
{ // 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--;
|
||||
}
|
||||
else
|
||||
@ -1035,6 +1129,23 @@ wxLayoutList::DeleteLines(int 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
|
||||
wxLayoutList::Layout(wxDC &dc, CoordType bottom) const
|
||||
{
|
||||
@ -1083,22 +1194,27 @@ wxLayoutList::Draw(wxDC &dc, wxPoint const &offset,
|
||||
}
|
||||
|
||||
wxLayoutObject *
|
||||
wxLayoutList::FindObject(wxPoint const pos)
|
||||
wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, wxPoint *cursorPos)
|
||||
{
|
||||
// First, find the right line:
|
||||
wxLayoutLine *line = m_FirstLine;
|
||||
wxPoint p;
|
||||
|
||||
// we need to run a layout here to get font sizes right :-(
|
||||
m_DefaultSetting->Layout(dc);
|
||||
while(line)
|
||||
{
|
||||
p = line->GetPosition();
|
||||
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
|
||||
break;
|
||||
line->Layout(dc);
|
||||
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:
|
||||
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()));
|
||||
#endif
|
||||
|
||||
if(active)
|
||||
dc.SetBrush(*wxBLACK_BRUSH);
|
||||
dc.SetBrush(*wxBLACK_BRUSH);
|
||||
dc.SetLogicalFunction(wxXOR);
|
||||
dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
|
||||
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.SetBrush(wxNullBrush);
|
||||
}
|
||||
|
@ -33,10 +33,19 @@
|
||||
# define WXLAYOUT_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef WXLAYOUT_DEBUG
|
||||
# define WXLO_TRACE(x) wxLogDebug(x)
|
||||
#else
|
||||
# define WXLO_TRACE(x)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef WXLO_DEFAULTFONTSIZE
|
||||
# define WXLO_DEFAULTFONTSIZE 12
|
||||
#endif
|
||||
|
||||
|
||||
/// Types of currently supported layout objects.
|
||||
enum wxLayoutObjectType
|
||||
{
|
||||
@ -105,6 +114,13 @@ public:
|
||||
virtual CoordType GetWidth(void) const { return 0; }
|
||||
/// returns the number of cursor positions occupied by this object
|
||||
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
|
||||
wxLayoutObject() { m_UserData = NULL; }
|
||||
@ -158,6 +174,14 @@ public:
|
||||
virtual wxPoint GetSize(CoordType * top, CoordType *bottom) const;
|
||||
/// Return just the width of the object on the screen.
|
||||
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
|
||||
virtual void Debug(void);
|
||||
@ -326,6 +350,13 @@ public:
|
||||
@return true if a word was deleted
|
||||
*/
|
||||
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
|
||||
line.
|
||||
@ -337,6 +368,18 @@ public:
|
||||
wxLayoutObjectList::iterator FindObject(CoordType xpos, CoordType
|
||||
*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
|
||||
functions to export the list.
|
||||
@return iterator to the first object
|
||||
@ -384,10 +427,11 @@ public:
|
||||
int cx = 0);
|
||||
/** This function finds an object belonging to a given cursor
|
||||
position. It assumes that Layout() has been called before.
|
||||
@param dc the wxDC to use for calculations
|
||||
@param xpos screen x position
|
||||
@return pointer to the object
|
||||
*/
|
||||
wxLayoutObject * FindObject(CoordType xpos);
|
||||
wxLayoutObject * FindObjectScreen(wxDC &dc, CoordType xpos);
|
||||
//@}
|
||||
|
||||
/**@name List traversal */
|
||||
@ -419,6 +463,8 @@ public:
|
||||
the list or until the coordinates no longer changed.
|
||||
*/
|
||||
void RecalculatePositions(int recurse = 0);
|
||||
/// Recalculates the position of this line on the canvas.
|
||||
wxPoint RecalculatePosition(void);
|
||||
private:
|
||||
/// Destructor is private. Use DeleteLine() to remove it.
|
||||
~wxLayoutLine();
|
||||
@ -431,8 +477,6 @@ private:
|
||||
*/
|
||||
void SetHeight(CoordType height)
|
||||
{ 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
|
||||
or deleted.
|
||||
@ -539,6 +583,13 @@ public:
|
||||
bool Insert(wxLayoutObject *obj);
|
||||
/// Inserts a linebreak at current cursor position.
|
||||
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.
|
||||
@param npos how many positions
|
||||
@return true if everything got deleted
|
||||
@ -637,6 +688,14 @@ public:
|
||||
@param bottom optional y coordinate where to stop calculating
|
||||
*/
|
||||
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.
|
||||
The return value only makes sense after the list has been
|
||||
drawn.
|
||||
@ -660,12 +719,15 @@ public:
|
||||
bool active = true,
|
||||
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.
|
||||
@param pos screen position
|
||||
@param cursorPos if non NULL, store cursor position in there
|
||||
@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"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define WXLO_XOFFSET 4
|
||||
#define WXLO_YOFFSET 4
|
||||
|
||||
BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
|
||||
EVT_PAINT (wxLayoutWindow::OnPaint)
|
||||
EVT_CHAR (wxLayoutWindow::OnChar)
|
||||
@ -39,20 +45,6 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
|
||||
EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus)
|
||||
EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus)
|
||||
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)
|
||||
: wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
|
||||
@ -68,10 +60,12 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
|
||||
m_bitmap = new wxBitmap(4,4);
|
||||
m_bitmapSize = wxPoint(4,4);
|
||||
m_llist = new wxLayoutList();
|
||||
SetWrapMargin(0);
|
||||
wxPoint max = m_llist->GetSize();
|
||||
SetScrollbars(10, 20 /*lineHeight*/, max.x/10+1, max.y/20+1);
|
||||
EnableScrolling(true,true);
|
||||
m_maxx = max.x; m_maxy = max.y;
|
||||
SetCursor(wxCURSOR_IBEAM);
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
@ -95,9 +89,6 @@ wxLayoutWindow::MSWGetDlgCode()
|
||||
void
|
||||
wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
||||
{
|
||||
if(!m_doSendEvents) // nothing to do
|
||||
return;
|
||||
|
||||
wxPaintDC dc( this );
|
||||
PrepareDC( dc );
|
||||
SetFocus();
|
||||
@ -106,13 +97,20 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
||||
findPos.x = dc.DeviceToLogicalX(event.GetX());
|
||||
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
|
||||
wxLogDebug("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
|
||||
event.GetX(), event.GetY(), findPos.x, findPos.y);
|
||||
#endif
|
||||
|
||||
m_ClickPosition = findPos;
|
||||
wxLayoutObject *obj = m_llist->FindObject(findPos);
|
||||
wxPoint cursorPos;
|
||||
wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, &cursorPos);
|
||||
|
||||
#ifdef WXLAYOUT_DEBUG
|
||||
if(obj)
|
||||
@ -121,7 +119,16 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
||||
else
|
||||
wxLogDebug("wxLayoutWindow::OnMouse: Found no object.");
|
||||
#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
|
||||
if(eventId == WXLOWIN_MENU_RCLICK
|
||||
&& IsEditable()
|
||||
@ -176,6 +183,11 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
||||
case 'k':
|
||||
m_llist->DeleteToEndOfLine();
|
||||
break;
|
||||
#ifdef WXLAYOUT_DEBUG
|
||||
case WXK_F1:
|
||||
m_llist->SetFont(-1,-1,-1,-1,true); // underlined
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
;
|
||||
}
|
||||
@ -229,6 +241,8 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
||||
if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
|
||||
break;
|
||||
case WXK_RETURN:
|
||||
if(m_WrapMargin > 0)
|
||||
m_llist->WrapLine(m_WrapMargin);
|
||||
m_llist->LineBreak();
|
||||
break;
|
||||
default:
|
||||
@ -238,8 +252,9 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
|
||||
{
|
||||
wxString tmp;
|
||||
tmp += keyCode;
|
||||
if(m_WrapMargin > 0 && isspace(keyCode))
|
||||
m_llist->WrapLine(m_WrapMargin);
|
||||
m_llist->Insert(tmp);
|
||||
//// m_llist->WrapLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -275,8 +290,11 @@ wxLayoutWindow::DoPaint(bool scrollToCursor)
|
||||
|
||||
// Maybe we need to change the scrollbar sizes or positions,
|
||||
// so layout the list and check:
|
||||
if(IsDirty() || scrollToCursor)
|
||||
if(IsDirty())
|
||||
m_llist->Layout(dc);
|
||||
// this is needed even when only the cursor moved
|
||||
m_llist->Layout(dc,y0+y1);
|
||||
|
||||
if(IsDirty())
|
||||
ResizeScrollbars();
|
||||
|
||||
@ -315,8 +333,8 @@ wxLayoutWindow::DoPaint(bool scrollToCursor)
|
||||
m_memDC->SetDeviceOrigin(0,0);
|
||||
m_memDC->Clear();
|
||||
|
||||
// The +4 give the window a tiny border on the left and top, looks nice.
|
||||
wxPoint offset(-x0+4,-y0+4);
|
||||
// The offsets give the window a tiny border on the left and top, looks nice.
|
||||
wxPoint offset(-x0+WXLO_XOFFSET,-y0+WXLO_YOFFSET);
|
||||
m_llist->Draw(*m_memDC,offset);
|
||||
if(IsEditable())
|
||||
m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset);
|
||||
@ -409,6 +427,6 @@ wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
|
||||
void
|
||||
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
|
||||
{
|
||||
m_HaveFocus = true;
|
||||
m_HaveFocus = false;
|
||||
DoPaint(); // to repaint the cursor
|
||||
}
|
||||
|
@ -81,6 +81,11 @@ public:
|
||||
|
||||
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.
|
||||
@param scrollToCursor if true, scroll the window so that the
|
||||
cursor becomes visible
|
||||
@ -154,6 +159,8 @@ private:
|
||||
|
||||
/// Can user edit the window?
|
||||
bool m_Editable;
|
||||
/// wrap margin
|
||||
CoordType m_WrapMargin;
|
||||
/// Is list dirty?
|
||||
bool m_Dirty;
|
||||
wxMemoryDC *m_memDC;
|
||||
|
Loading…
Reference in New Issue
Block a user