* $Id$
*******************************************************************/
+/*
+
+ */
+
#ifdef __GNUG__
#pragma implementation "wxllist.h"
#endif
+//#include "Mpch.h"
+
+
#include "wx/wxprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#endif
-
-//#include "Mpch.h"
#ifdef M_PREFIX
# include "gui/wxllist.h"
#else
# include "wxllist.h"
#endif
+
#ifndef USE_PCH
# include "iostream.h"
# include <wx/dc.h>
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
-static void GrowRect(wxRect &r, const wxPoint & p)
+static
+void GrowRect(wxRect &r, const wxPoint & p)
{
if(r.x > p.x)
r.x = p.x;
else if(r.y + r.height < p.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;
+}
//@}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
weight, bool underline,
- wxColour const *fg, wxColour const *bg)
+ wxColour &fg, wxColour &bg)
{
m_font = new wxFont(size,family,style,weight,underline);
si->underline = m_font->GetUnderlined();
si->weight = m_font->GetWeight();
- si->fg_red = m_ColourFG->Red();
- si->fg_green = m_ColourFG->Green();
- si->fg_blue = m_ColourFG->Blue();
- si->bg_red = m_ColourBG->Red();
- si->bg_green = m_ColourBG->Green();
- si->bg_blue = m_ColourBG->Blue();
+ si->fg_red = m_ColourFG.Red();
+ si->fg_green = m_ColourFG.Green();
+ si->fg_blue = m_ColourFG.Blue();
+ si->bg_red = m_ColourBG.Red();
+ si->bg_green = m_ColourBG.Green();
+ si->bg_blue = m_ColourBG.Blue();
}
void
{
wxASSERT(m_font);
dc.SetFont(*m_font);
- if(m_ColourFG)
- dc.SetTextForeground(*m_ColourFG);
- if(m_ColourBG)
- dc.SetTextBackground(*m_ColourBG);
+ dc.SetTextForeground(m_ColourFG);
+ dc.SetTextBackground(m_ColourBG);
}
void
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-wxLayoutLine::wxLayoutLine(wxLayoutLine *prev)
+wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
{
m_LineNumber = 0;
- m_Height = 0;
+ m_Width = m_Height = 0;
m_Length = 0;
m_Dirty = true;
m_Previous = prev;
m_Next = NULL;
- RecalculatePosition();
+ RecalculatePosition(llist);
if(m_Previous)
{
m_LineNumber = m_Previous->GetLineNumber()+1;
{
m_Next->m_Previous = this;
m_Next->MoveLines(+1);
- m_Next->RecalculatePositions(1);
+ m_Next->RecalculatePositions(1,llist);
}
}
}
wxPoint
-wxLayoutLine::RecalculatePosition(void)
+wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
{
if(m_Previous)
m_Position = m_Previous->GetPosition() +
wxPoint(0,m_Previous->GetHeight());
else
m_Position = wxPoint(0,0);
+ llist->SetUpdateRect(m_Position);
return m_Position;
}
void
-wxLayoutLine::RecalculatePositions(int recurse)
+wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist)
{
wxASSERT(recurse >= 0);
wxPoint pos = m_Position;
CoordType height = m_Height;
// WXLO_TRACE("RecalculatePositions()");
- RecalculatePosition();
+ RecalculatePosition(llist);
if(m_Next)
{
if(recurse > 0)
- {
- if(m_Next) m_Next->RecalculatePositions(--recurse);
- }
+ m_Next->RecalculatePositions(--recurse, llist);
else if(pos != m_Position || m_Height != height)
- if(m_Next) m_Next->RecalculatePositions();
+ m_Next->RecalculatePositions(0, llist);
}
}
{
wxASSERT(xpos >= 0);
wxASSERT(offset);
- wxLayoutObjectList::iterator i;
+ wxLayoutObjectList::iterator
+ i,
+ found = NULLIT;
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++)
{
len = (**i).GetLength();
if( x <= xpos && xpos <= x + len )
{
*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();
}
- return NULLIT;
+ return found; // ==NULL if really none found
}
wxLayoutObjectList::iterator
str = str.substr(offset,str.Length()-offset);
// Find out how many positions we need to delete:
// 1. eat leading space
- while(isspace(str[count])) count++;
+ while(isspace(str.c_str()[count])) count++;
// 2. eat the word itself:
- while(isalnum(str[count])) count++;
+ while(isalnum(str.c_str()[count])) count++;
// now delete it:
wxASSERT(count+offset <= (size_t) (**i).GetLength());
((wxLayoutObjectText *)*i)->GetText().erase(offset,count);
}
wxLayoutLine *
-wxLayoutLine::DeleteLine(bool update)
+wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist)
{
if(m_Next) m_Next->m_Previous = m_Previous;
if(m_Previous) m_Previous->m_Next = m_Next;
if(update)
{
m_Next->MoveLines(-1);
- m_Next->RecalculatePositions(1);
+ m_Next->RecalculatePositions(1, llist);
}
wxLayoutLine *next = m_Next;
delete this;
}
void
-wxLayoutLine::Draw(wxDC &dc, const wxPoint & offset) const
+wxLayoutLine::Draw(wxDC &dc,
+ wxLayoutList *llist,
+ const wxPoint & offset) const
{
wxLayoutObjectList::iterator i;
wxPoint pos = offset;
}
void
-wxLayoutLine::Layout(wxDC &dc, wxPoint *cursorPos,
+wxLayoutLine::Layout(wxDC &dc,
+ wxLayoutList *llist,
+ wxPoint *cursorPos,
wxPoint *cursorSize,
int cx)
{
if(cursorPos)
{
*cursorPos = m_Position;
+ if(cursorSize) *cursorSize = wxPoint(0,0);
}
for(i = m_ObjectList.begin(); i != NULLIT; i++)
// tell next line about coordinate change
if(m_Next && objHeight != oldHeight)
- m_Next->RecalculatePositions();
+ m_Next->RecalculatePositions(0, llist);
// We need to check whether we found a valid cursor size:
if(cursorPos)
// line or on a command object:
if(cursorSize->y < WXLO_MINIMUM_CURSOR_WIDTH)
{
- if(m_BaseLine > 0)
- {
- cursorSize->y = m_BaseLine;
- if(cursorSize->x < WXLO_MINIMUM_CURSOR_WIDTH) cursorSize->x = WXLO_MINIMUM_CURSOR_WIDTH;
- }
- else // empty line
- {
- CoordType width, height, descent;
- dc.GetTextExtent(WXLO_CURSORCHAR, &width, &height, &descent);
- cursorSize->x = width;
- cursorSize->y = height;
- }
+ 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
cursorPos->y += m_BaseLine-cursorSize->y;
wxLayoutLine *
-wxLayoutLine::Break(CoordType xpos)
+wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
{
wxASSERT(xpos >= 0);
if(xpos == 0)
{ // insert an empty line before this one
- wxLayoutLine *prev = new wxLayoutLine(m_Previous);
+ wxLayoutLine *prev = new wxLayoutLine(m_Previous, llist);
if(m_Previous == NULL)
{ // We were in first line, need to link in new empty line
// before this.
}
MoveLines(+1);
if(m_Next)
- m_Next->RecalculatePositions(1);
+ m_Next->RecalculatePositions(1, llist);
return this;
}
wxLOiterator i = FindObject(xpos, &offset);
if(i == NULLIT)
// must be at the end of the line then
- return new wxLayoutLine(this);
+ return new wxLayoutLine(this, llist);
// split this line:
- wxLayoutLine *newLine = new wxLayoutLine(this);
+ wxLayoutLine *newLine = new wxLayoutLine(this, llist);
// split object at i:
if((**i).GetType() == WXLO_TYPE_TEXT && offset != 0)
{
m_ObjectList.remove(i); // remove without deleting it
}
if(m_Next)
- m_Next->RecalculatePositions(2);
+ m_Next->RecalculatePositions(2, llist);
return newLine;
}
void
-wxLayoutLine::MergeNextLine(void)
+wxLayoutLine::MergeNextLine(wxLayoutList *llist)
{
wxASSERT(GetNextLine());
wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
wxLayoutLine *oldnext = GetNextLine();
SetNext(GetNextLine()->GetNextLine());
delete oldnext;
- RecalculatePositions(1);
+ RecalculatePositions(1, llist);
}
CoordType
{
do
{
- if( isspace(((wxLayoutObjectText*)*i)->GetText()[(size_t)offset]))
+ if( isspace(((wxLayoutObjectText*)*i)->GetText().c_str()[(size_t)offset]))
return column;
else
{
{
m_DefaultSetting = NULL;
m_FirstLine = NULL;
+ m_ColourFG = *wxBLACK;
+ m_ColourBG = *wxWHITE;
InvalidateUpdateRect();
Clear();
}
wxLayoutList::~wxLayoutList()
{
InternalClear();
+ m_FirstLine->DeleteLine(false, this);
}
void
wxLayoutList::Empty(void)
{
while(m_FirstLine)
- m_FirstLine = m_FirstLine->DeleteLine(false);
+ m_FirstLine = m_FirstLine->DeleteLine(false, this);
m_CursorPos = wxPoint(0,0);
m_CursorScreenPos = 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;
+ InvalidateUpdateRect();
}
void
wxLayoutList::SetFont(int family, int size, int style, int weight,
- int underline, wxColour const *fg,
- wxColour const *bg)
+ int underline, wxColour *fg,
+ wxColour *bg)
{
if(family != -1) m_FontFamily = family;
if(size != -1) m_FontPtSize = size;
if(weight != -1) m_FontWeight = weight;
if(underline != -1) m_FontUnderline = underline != 0;
- if(fg != NULL) m_ColourFG = fg;
- if(bg != NULL) m_ColourBG = bg;
+ if(fg != NULL) m_ColourFG = *fg;
+ if(bg != NULL) m_ColourBG = *bg;
Insert(
new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
int underline, char const *fg, char const *bg)
{
- wxColour const
- * cfg = NULL,
- * cbg = NULL;
+ wxColour
+ *cfg = NULL,
+ *cbg = NULL;
if( fg )
cfg = wxTheColourDatabase->FindColour(fg);
void
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();
m_FontFamily = family;
m_FontStyle = style;
m_FontWeight = weight;
- m_ColourFG = wxTheColourDatabase->FindColour(fg);
- m_ColourBG = wxTheColourDatabase->FindColour(bg);
+ if(fg) m_ColourFG = *fg;
+ if(bg) m_ColourBG = *bg;
- if(! m_ColourFG) m_ColourFG = wxBLACK;
- if(! m_ColourBG) m_ColourBG = wxWHITE;
+ m_ColourFG = *wxBLACK;
+ m_ColourBG = *wxWHITE;
if(m_DefaultSetting)
delete m_DefaultSetting;
bool
wxLayoutList::MoveCursorTo(wxPoint const &p)
{
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
wxLayoutLine *line = m_FirstLine;
while(line && line->GetLineNumber() != p.y)
line = line->GetNextLine();
bool
wxLayoutList::MoveCursorVertically(int n)
{
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
+ bool rc;
if(n < 0) // move up
{
if(m_CursorLine == m_FirstLine) return false;
{
m_CursorLine = m_FirstLine;
m_CursorPos.y = 0;
- return false;
+ rc = false;
}
else
{
if(m_CursorPos.x > m_CursorLine->GetLength())
m_CursorPos.x = m_CursorLine->GetLength();
- return true;
+ rc = true;
}
}
else // move down
{
m_CursorLine = last;
m_CursorPos.y ++;
- return false;
+ rc = false;
}
else
{
if(m_CursorPos.x > m_CursorLine->GetLength())
m_CursorPos.x = m_CursorLine->GetLength();
- return true;
+ rc = true;
}
}
+ return rc;
}
bool
wxLayoutList::MoveCursorHorizontally(int n)
{
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
int move;
while(n < 0)
{
wxLayoutList::Insert(wxString const &text)
{
wxASSERT(m_CursorLine);
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
m_CursorLine->Insert(m_CursorPos.x, text);
m_CursorPos.x += text.Length();
return true;
wxLayoutList::Insert(wxLayoutObject *obj)
{
wxASSERT(m_CursorLine);
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
m_CursorLine->Insert(m_CursorPos.x, obj);
m_CursorPos.x += obj->GetLength();
return true;
wxLayoutList::LineBreak(void)
{
wxASSERT(m_CursorLine);
-
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
m_FirstLine = m_CursorLine->GetPreviousLine();
m_CursorPos.y++;
//else:
CoordType newpos = m_CursorPos.x - xpos - 1;
m_CursorPos.x = xpos;
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
LineBreak();
Delete(1); // delete the space
m_CursorPos.x = newpos;
wxLayoutList::Delete(CoordType npos)
{
wxASSERT(m_CursorLine);
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
CoordType left;
do
{
break; // cannot
else
{
- m_CursorLine->MergeNextLine();
+ m_CursorLine->MergeNextLine(this);
left--;
}
}
{
wxASSERT(m_CursorLine);
wxLayoutLine *line;
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
while(n > 0)
{
if(!m_CursorLine->GetNextLine())
}
//else:
line = m_CursorLine;
- m_CursorLine = m_CursorLine->DeleteLine(true);
+ m_CursorLine = m_CursorLine->DeleteLine(true, this);
n--;
if(line == m_FirstLine) m_FirstLine = m_CursorLine;
wxASSERT(m_FirstLine);
wxASSERT(m_CursorLine);
}
- m_CursorLine->RecalculatePositions(2);
+ m_CursorLine->RecalculatePositions(2, this);
return n;
}
void
-wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) const
+wxLayoutList::Recalculate(wxDC &dc, CoordType bottom)
{
wxLayoutLine *line = m_FirstLine;
m_DefaultSetting->Layout(dc);
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:
if(bottom != -1 && line->GetPosition().y > bottom) break;
line = line->GetNextLine();
}
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;
while(line)
{
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
- line->Layout(dc);
+ line->Layout(dc, this);
// little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y > bottom) break;
line = line->GetNextLine();
m_CursorLine->GetNextLine() == NULL &&
m_CursorLine == m_FirstLine));
#endif
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
}
void
wxLayoutList::Draw(wxDC &dc, wxPoint const &offset,
- CoordType top, CoordType bottom) const
+ CoordType top, CoordType bottom)
{
wxLayoutLine *line = m_FirstLine;
Layout(dc, bottom);
m_DefaultSetting->Draw(dc, wxPoint(0,0));
- wxBrush *brush = new wxBrush(*m_ColourBG, wxSOLID);
- dc.SetBrush(*brush);
- delete brush;
+ wxBrush brush(m_ColourBG, wxSOLID);
+ dc.SetBrush(brush);
while(line)
{
// only draw if between top and bottom:
if((top == -1 || line->GetPosition().y >= top))
- line->Draw(dc, offset);
+ line->Draw(dc, this, offset);
// little condition to speed up redrawing:
if(bottom != -1 && line->GetPosition().y + line->GetHeight() > bottom) break;
line = line->GetNextLine();
wxASSERT(m_CursorSize.x != 0 || (m_CursorLine &&
m_CursorLine->GetNextLine() == NULL &&
m_CursorLine == m_FirstLine));
+ InvalidateUpdateRect();
}
wxLayoutObject *
p = line->GetPosition();
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
break;
- line->Layout(dc);
+ line->Layout(dc, this);
line = line->GetNextLine();
}
if(line == NULL) return NULL; // not found
}
}
+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;
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
float scale = ScaleDC(&psdc);
psdc.GetSize(&m_PageWidth, &m_PageHeight);
- // This sets a left/top origin of 10% and 5%:
- m_Offset = wxPoint(m_PageWidth/10, m_PageHeight/20);
+ // This sets a left/top origin of 15% and 20%:
+ m_Offset = wxPoint((15*m_PageWidth)/100, m_PageHeight/20);
// This is the length of the printable area.
m_PrintoutHeight = m_PageHeight - (int) (m_PageHeight * 0.15);