#pragma implementation "wxllist.h"
#endif
+#include "Mpch.h"
+
+
#include "wx/wxprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#endif
-//#include "Mpch.h"
-#ifdef M_PREFIX
+#ifdef M_BASEDIR
# include "gui/wxllist.h"
+# define SHOW_SELECTIONS 1
#else
# include "wxllist.h"
+# include "wxlparser.h"
+# define SHOW_SELECTIONS 1
#endif
#ifndef USE_PCH
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, CoordType x, CoordType y)
{
- if(r.x > p.x)
- r.x = p.x;
- else if(r.x + r.width < p.x)
- r.width = p.x - r.x;
+ if(r.x > x)
+ r.x = x;
+ else if(r.x + r.width < x)
+ r.width = x - r.x;
- if(r.y > p.y)
- r.y = p.y;
- else if(r.y + r.height < p.y)
- r.height = p.y - r.y;
+ if(r.y > y)
+ r.y = y;
+ else if(r.y + r.height < y)
+ r.height = y - r.y;
+}
+
+#if 0
+// unused
+/// 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;
}
+#endif
+
+
//@}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
}
void
-wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords)
+wxLayoutObjectText::Draw(wxDC &dc, wxPoint const &coords,
+ wxLayoutList *wxllist,
+ CoordType begin, CoordType end)
{
- dc.DrawText(m_Text, coords.x, coords.y-m_Top);
+ if(begin == -1)
+ dc.DrawText(m_Text, coords.x, coords.y-m_Top);
+ else
+ {
+ // highlight the bit between begin and len
+ wxString str;
+ CoordType
+ xpos = coords.x,
+ ypos = coords.y-m_Top;
+ long width, height, descent;
+
+ str = m_Text.Mid(0, begin);
+ dc.DrawText(str, xpos, ypos);
+ dc.GetTextExtent(str, &width, &height, &descent);
+ xpos += width;
+ wxllist->StartHighlighting(dc);
+ str = m_Text.Mid(begin, end-begin);
+ dc.DrawText(str, xpos, ypos);
+ dc.GetTextExtent(str, &width, &height, &descent);
+ xpos += width;
+ wxllist->EndHighlighting(dc);
+ str = m_Text.Mid(end, m_Text.Length()-end);
+ dc.DrawText(str, xpos, ypos);
+ }
}
CoordType
}
void
-wxLayoutObjectText::Layout(wxDC &dc)
+wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList * )
{
long descent = 0l;
}
void
-wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint const &coords)
+wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint const &coords,
+ wxLayoutList *wxllist,
+ CoordType begin, CoordType /* len */)
{
dc.DrawBitmap(*m_Icon, coords.x, coords.y-m_Icon->GetHeight(),
(m_Icon->GetMask() == NULL) ? FALSE : TRUE);
}
void
-wxLayoutObjectIcon::Layout(wxDC & /* dc */)
+wxLayoutObjectIcon::Layout(wxDC & /* dc */, class wxLayoutList * )
{
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- wxLayoutObjectIcon
+ wxLayoutObjectCmd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+wxLayoutStyleInfo::wxLayoutStyleInfo(int ifamily,
+ int isize,
+ int istyle,
+ int iweight,
+ int iul,
+ wxColour *fg,
+ wxColour *bg)
+{
+ family = ifamily; size = isize;
+ style = istyle; weight = iweight;
+ underline = iul;
+ if(fg)
+ {
+ fg_valid = true;
+ fg_red = fg->Red();
+ fg_blue = fg->Blue();
+ fg_green = fg->Green();
+ }
+ else
+ fg_valid = false;
+ if(bg)
+ {
+ bg_valid = true;
+ bg_red = bg->Red();
+ bg_blue = bg->Blue();
+ bg_green = bg->Green();
+ }
+ else
+ bg_valid = false;
+}
+
+#define SET_SI(what) tmp.what = (what != -1) ? what : ( si ? si->what : wxNORMAL);
+
+
+wxFont *
+wxLayoutStyleInfo::GetFont(wxLayoutStyleInfo *si)
+{
+ wxLayoutStyleInfo tmp;
+
+ SET_SI(family);
+ SET_SI(size);
+ SET_SI(style);
+ SET_SI(weight);
+ SET_SI(underline);
+
+ return new wxFont(tmp.size,tmp.family,tmp.style,tmp.weight,tmp.underline);
+
+}
+
wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
- weight, bool underline,
- wxColour const *fg, wxColour const *bg)
+ weight, int underline,
+ wxColour *fg, wxColour *bg)
{
- m_font = new wxFont(size,family,style,weight,underline);
- m_ColourFG = fg;
- m_ColourBG = bg;
+ m_StyleInfo = new
+ wxLayoutStyleInfo(size,family,style,weight,underline,fg,bg);
+ m_font = NULL;
}
wxLayoutObject *
wxLayoutObjectCmd::Copy(void)
{
- wxLayoutStyleInfo si;
- GetStyle(&si);
+ wxColour
+ * fg = NULL,
+ * bg = NULL;
+ if(m_StyleInfo->fg_valid)
+ fg = new
+ wxColour(m_StyleInfo->fg_red,m_StyleInfo->fg_green,m_StyleInfo->fg_blue);
+ if(m_StyleInfo->bg_valid)
+ bg = new
+ wxColour(m_StyleInfo->bg_red,m_StyleInfo->bg_green,m_StyleInfo->bg_blue);
wxLayoutObjectCmd *obj = new wxLayoutObjectCmd(
- si.size, si.family, si.style, si.weight, si.underline,
- m_ColourFG, m_ColourBG);
+ m_StyleInfo->size,
+ m_StyleInfo->family,
+ m_StyleInfo->style,
+ m_StyleInfo->weight,
+ m_StyleInfo->underline,
+ fg, bg);
obj->SetUserData(m_UserData);
+
+ if(fg) delete fg;
+ if(bg) delete bg;
return obj;
}
wxLayoutObjectCmd::~wxLayoutObjectCmd()
{
- delete m_font;
+ delete m_StyleInfo;
+ if(m_font) delete m_font;
}
-void
-wxLayoutObjectCmd::GetStyle(wxLayoutStyleInfo *si) const
+wxLayoutStyleInfo *
+wxLayoutObjectCmd::GetStyle(void) const
{
- si->size = m_font->GetPointSize();
- si->family = m_font->GetFamily();
- si->style = m_font->GetStyle();
- 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();
+ return m_StyleInfo;
}
void
-wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */)
+wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const & /* coords */,
+ wxLayoutList *wxllist,
+ CoordType begin, CoordType /* len */)
{
- wxASSERT(m_font);
+ wxASSERT(m_StyleInfo);
dc.SetFont(*m_font);
- if(m_ColourFG)
- dc.SetTextForeground(*m_ColourFG);
- if(m_ColourBG)
- dc.SetTextBackground(*m_ColourBG);
+ wxllist->ApplyStyle(m_StyleInfo, dc);
}
void
-wxLayoutObjectCmd::Layout(wxDC &dc)
+wxLayoutObjectCmd::Layout(wxDC &dc, class wxLayoutList * llist)
{
+ if(m_font) delete m_font;
+ m_font = m_StyleInfo->GetFont(llist->GetStyleInfo());
+
+
// this get called, so that recalculation uses right font sizes
- Draw(dc, wxPoint(0,0));
+ Draw(dc, wxPoint(0,0), llist);
}
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-wxLayoutLine::wxLayoutLine(wxLayoutLine *prev)
+wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
{
m_LineNumber = 0;
m_Width = m_Height = 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)
{
+ wxASSERT(m_Previous || GetLineNumber() == 0);
+
if(m_Previous)
- m_Position = m_Previous->GetPosition() +
- wxPoint(0,m_Previous->GetHeight());
+ {
+ m_Position = m_Previous->GetPosition();
+ m_Position.y += 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
-wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const
+wxLayoutLine::FindObjectScreen(wxDC &dc,
+ CoordType xpos, CoordType *cxpos,
+ bool *found) const
{
wxASSERT(cxpos);
wxASSERT(cxpos);
for(i = m_ObjectList.begin(); i != NULLIT; i++)
{
- (**i).Layout(dc);
+//FIXME! (**i).Layout(dc, NULL);
width = (**i).GetWidth();
if( x <= xpos && xpos <= x + width )
{
*cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
- wxLogDebug("wxLayoutLine::FindObjectScreen: cursor xpos = %ld", *cxpos);
+// WXLO_DEBUG(("wxLayoutLine::FindObjectScreen: cursor xpos = %ld", *cxpos));
+ if(found) *found = true;
return i;
}
x += (**i).GetWidth();
}
// behind last object:
*cxpos = cx;
+ if(found) *found = false;
return m_ObjectList.tail();
}
+/** Finds text in this line.
+ @param needle the text to find
+ @param xpos the position where to start the search
+ @return the cursoor coord where it was found or -1
+*/
+CoordType
+wxLayoutLine::FindText(const wxString &needle, CoordType xpos = 0) const
+{
+ int
+ cpos = 0,
+ relpos = -1;
+ wxString const *text;
+
+ for(wxLOiterator i = m_ObjectList.begin(); i != m_ObjectList.end(); i++)
+ {
+ if(cpos >= xpos) // search from here!
+ {
+ if((**i).GetType() == WXLO_TYPE_TEXT)
+ {
+ text = & ((wxLayoutObjectText*)(*i))->GetText();
+ relpos = text->Find(needle);
+ if(relpos >= cpos-xpos) // -1 if not found
+ {
+ return cpos+relpos;
+ }
+ }
+ cpos += (**i).GetLength();
+ }
+ }
+ return -1; // not found
+}
+
bool
wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
{
}
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;
pos = pos + GetPosition();
pos.y += m_BaseLine;
-
+
+ CoordType xpos = 0; // cursorpos, lenght of line
+
+ CoordType from, to, tempto;
+ int highlight = llist->IsSelected(this, &from, &to);
+// WXLO_DEBUG(("highlight=%d", highlight ));
+ if(highlight == 1) // we need to draw the whole line inverted!
+ llist->StartHighlighting(dc);
+ else
+ llist->EndHighlighting(dc);
+
for(i = m_ObjectList.begin(); i != NULLIT; i++)
{
- (**i).Draw(dc, pos);
+ if(highlight == -1) // partially highlight line
+ {
+ // parts of the line need highlighting
+ tempto = xpos+(**i).GetLength();
+ if(tempto >= from && xpos <= to)
+ {
+ tempto = to-xpos;
+ if(tempto > (**i).GetLength())
+ tempto = (**i).GetLength();
+ CoordType tmp = from-xpos;
+ if(tmp < 0) tmp = 0;
+ (**i).Draw(dc, pos, llist, from-xpos, tempto);
+ }
+ else
+ {
+ llist->EndHighlighting(dc); // FIXME! inefficient
+ (**i).Draw(dc, pos, llist);
+ }
+ }
+ else
+ (**i).Draw(dc, pos, llist);
pos.x += (**i).GetWidth();
+ xpos += (**i).GetLength();
}
}
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++)
{
- (**i).Layout(dc);
+ (**i).Layout(dc, llist);
size = (**i).GetSize(&objTopHeight, &objBottomHeight);
if(cursorPos && ! cursorFound)
// 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
}
+#ifdef WXLAYOUT_DEBUG
+void
+wxLayoutLine::Debug(void)
+{
+ wxString tmp;
+ wxPoint pos = GetPosition();
+ WXLO_DEBUG(("Line %ld, Pos (%ld,%ld), Height %ld",
+ (long int) GetLineNumber(),
+ (long int) pos.x, (long int) pos.y,
+ (long int) GetHeight()));
+ if(m_ObjectList.begin() != NULLIT)
+ (**m_ObjectList.begin()).Debug();
+
+}
+#endif
+
+void
+wxLayoutLine::Copy(wxLayoutList *llist,
+ CoordType from,
+ CoordType to)
+{
+ CoordType firstOffset, lastOffset;
+
+ if(to == -1) to = GetLength();
+
+ wxLOiterator first = FindObject(from, &firstOffset);
+ wxLOiterator last = FindObject(to, &lastOffset);
+
+ // Common special case: only one object
+ if( *first == *last )
+ {
+ if( (**first).GetType() == WXLO_TYPE_TEXT )
+ {
+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText
+ *)*first)->GetText().substr(firstOffset,
+ lastOffset-firstOffset))
+ );
+ return;
+ }
+ else // what can we do?
+ {
+ if(lastOffset > firstOffset) // i.e. +1 :-)
+ llist->Insert( (**first).Copy() );
+ return;
+ }
+ }
+
+ // If we reach here, we can safely copy the whole first object from
+ // the firstOffset position on:
+ if((**first).GetType() == WXLO_TYPE_TEXT && firstOffset != 0)
+ {
+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText *)*first)->GetText().substr(firstOffset))
+ );
+ }
+ else if(firstOffset == 0)
+ llist->Insert( (**first).Copy() );
+ // else nothing to copy :-(
+
+ // Now we copy all objects before the last one:
+ wxLOiterator i = first; i++;
+ for( ; i != last; i++)
+ llist->Insert( (**i).Copy() );
+
+ // And now the last object:
+ if(lastOffset != 0)
+ {
+ if( (**last).GetType() == WXLO_TYPE_TEXT )
+ {
+ llist->Insert(new wxLayoutObjectText(
+ ((wxLayoutObjectText *)*last)->GetText().substr(0,lastOffset))
+ );
+ }
+ else
+ llist->Insert( (**last).Copy() );
+ }
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
The wxLayoutList object
{
m_DefaultSetting = NULL;
m_FirstLine = NULL;
+ m_ColourFG = *wxBLACK;
+ m_ColourBG = *wxWHITE;
InvalidateUpdateRect();
Clear();
}
wxLayoutList::~wxLayoutList()
{
InternalClear();
- m_FirstLine->DeleteLine(false);
+ 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();
}
delete m_DefaultSetting;
m_DefaultSetting = NULL;
}
+ m_Selection.m_selecting = false;
+ m_Selection.m_valid = false;
+
+ m_CurrentSetting.family = wxSWISS;
+ m_CurrentSetting.size = WXLO_DEFAULTFONTSIZE;
+ m_CurrentSetting.style = wxNORMAL;
+ m_CurrentSetting.weight = wxNORMAL;
+ m_CurrentSetting.underline = 0;
}
void
wxLayoutList::SetFont(int family, int size, int style, int weight,
- int underline, wxColour const *fg,
- wxColour const *bg)
-{
- if(family != -1) m_FontFamily = family;
- if(size != -1) m_FontPtSize = size;
- if(style != -1) m_FontStyle = style;
- 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;
-
+ int underline, wxColour *fg,
+ wxColour *bg)
+{
+ if(family != -1) m_CurrentSetting.family = family;
+ if(size != -1) m_CurrentSetting.size = size;
+ if(style != -1) m_CurrentSetting.style = style;
+ if(weight != -1) m_CurrentSetting.weight = weight;
+ if(underline != -1) m_CurrentSetting.underline = underline != 0;
+ if(fg)
+ {
+ m_CurrentSetting.fg_valid = true;
+ m_CurrentSetting.fg_red = fg->Red();
+ m_CurrentSetting.fg_blue = fg->Blue();
+ m_CurrentSetting.fg_green = fg->Green();
+ }
+ if(bg)
+ {
+ m_CurrentSetting.bg_valid = true;
+ m_CurrentSetting.bg_red = bg->Red();
+ m_CurrentSetting.bg_blue = bg->Blue();
+ m_CurrentSetting.bg_green = bg->Green();
+ }
Insert(
- new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
- m_ColourFG, m_ColourBG));
+ new wxLayoutObjectCmd(
+ m_CurrentSetting.size,
+ m_CurrentSetting.family,
+ m_CurrentSetting.style,
+ m_CurrentSetting.weight,
+ m_CurrentSetting.underline, fg, bg));
}
void
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);
if( bg )
cbg = wxTheColourDatabase->FindColour(bg);
- SetFont(family,size,style,weight,underline,cfg,cbg);
+ SetFont(size,family,style,weight,underline,cfg,cbg);
}
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();
- // set defaults
- m_FontPtSize = size;
- m_FontUnderline = false;
- m_FontFamily = family;
- m_FontStyle = style;
- m_FontWeight = weight;
- m_ColourFG = wxTheColourDatabase->FindColour(fg);
- m_ColourBG = wxTheColourDatabase->FindColour(bg);
-
- if(! m_ColourFG) m_ColourFG = wxBLACK;
- if(! m_ColourBG) m_ColourBG = wxWHITE;
-
if(m_DefaultSetting)
delete m_DefaultSetting;
- m_DefaultSetting = new
- wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,
- m_FontWeight,m_FontUnderline,
- m_ColourFG, m_ColourBG);
+ m_DefaultSetting = new
+ wxLayoutStyleInfo(family,size,style,weight,underline,fg,bg);
}
+wxPoint
+wxLayoutList::FindText(const wxString &needle, const wxPoint &cpos) const
+{
+ int xpos;
+
+ wxLayoutLine *line;
+ for(line = m_FirstLine;
+ line;
+ line = line->GetNextLine())
+ {
+ if(line->GetLineNumber() >= cpos.y)
+ {
+ xpos = line->FindText(needle,
+ (line->GetLineNumber() == cpos.y) ?
+ cpos.x : 0);
+ if(xpos != -1)
+ return wxPoint(xpos, line->GetLineNumber());
+ }
+ }
+ return wxPoint(-1,-1);
+}
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();
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
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();
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
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++;
m_CursorPos.x = 0;
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
return true;
}
//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;
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
return true;
}
}
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--;
}
}
}
while(left);
+ m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
return left == 0;
}
{
wxASSERT(m_CursorLine);
wxLayoutLine *line;
+ SetUpdateRect(m_CursorScreenPos);
+ SetUpdateRect(m_CursorScreenPos+m_CursorSize);
while(n > 0)
{
if(!m_CursorLine->GetNextLine())
{ // we cannot delete this line, but we can clear it
MoveCursorToBeginOfLine();
DeleteToEndOfLine();
+ m_CursorLine->RecalculatePositions(2, this);
return n-1;
}
//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;
// first, make sure everything is calculated - this might not be
// needed, optimise it later
- m_DefaultSetting->Layout(dc);
+ ApplyStyle(m_DefaultSetting, 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;
// first, make sure everything is calculated - this might not be
// needed, optimise it later
- m_DefaultSetting->Layout(dc);
+ ApplyStyle(m_DefaultSetting, dc);
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
+wxLayoutList::Draw(wxDC &dc,
+ wxPoint const &offset,
+ 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;
+ ApplyStyle(m_DefaultSetting, dc);
+ 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);
+ if((top == -1 || line->GetPosition().y + line->GetHeight() >= top))
+ line->Draw(dc, this, offset);
// little condition to speed up redrawing:
- if(bottom != -1 && line->GetPosition().y + line->GetHeight() > bottom) break;
+ if(bottom != -1 && line->GetPosition().y > bottom) break;
line = line->GetNextLine();
}
- // can only be 0 if we are on the first line and have no next line
- wxASSERT(m_CursorSize.x != 0 || (m_CursorLine &&
- m_CursorLine->GetNextLine() == NULL &&
- m_CursorLine == m_FirstLine));
+ InvalidateUpdateRect();
+
+ WXLO_DEBUG(("Selection is %s : l%d,%ld/%ld,%ld",
+ m_Selection.m_valid ? "valid" : "invalid",
+ m_Selection.m_CursorA.x, m_Selection.m_CursorA.y,
+ m_Selection.m_CursorB.x, m_Selection.m_CursorB.y));
}
wxLayoutObject *
-wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, wxPoint *cursorPos)
+wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
+ wxPoint *cursorPos,
+ bool *found)
{
// 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);
+ ApplyStyle(m_DefaultSetting, dc);
while(line)
{
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
+ if(line == NULL)
+ {
+ if(found) *found = false;
+ return NULL; // not found
+ }
if(cursorPos) cursorPos->y = line->GetLineNumber();
// Now, find the object in the line:
- wxLOiterator i = line->FindObjectScreen(dc, pos.x, & cursorPos->x);
+ wxLOiterator i = line->FindObjectScreen(dc, pos.x,
+ cursorPos ? & cursorPos->x : NULL ,
+ found);
return (i == NULLIT) ? NULL : *i;
}
return maxPoint;
}
+
void
wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
{
dc.SetLogicalFunction(wxXOR);
dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
if(active)
- dc.DrawRectangle(coords.x, coords.y, m_CursorSize.x,
- m_CursorSize.y);
+ {
+ dc.DrawRectangle(coords.x, coords.y,
+ m_CursorSize.x, m_CursorSize.y);
+ SetUpdateRect(coords.x, coords.y);
+ SetUpdateRect(coords.x+m_CursorSize.x, coords.y+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);
+ coords.x, coords.y);
+ SetUpdateRect(coords.x, coords.y+m_CursorSize.y-1);
+ SetUpdateRect(coords.x, coords.y);
+ }
dc.SetLogicalFunction(wxCOPY);
//dc.SetBrush(wxNullBrush);
}
-/** Called by the objects to update the update rectangle.
- @param p a point to include in it
-*/
void
-wxLayoutList::SetUpdateRect(const wxPoint &p)
+wxLayoutList::SetUpdateRect(CoordType x, CoordType y)
{
if(m_UpdateRectValid)
- GrowRect(m_UpdateRect, p);
+ GrowRect(m_UpdateRect, x, y);
else
{
- m_UpdateRect.x = p.x;
- m_UpdateRect.y = p.y;
+ m_UpdateRect.x = x;
+ m_UpdateRect.y = y;
m_UpdateRect.width = 4; // large enough to avoid surprises from
m_UpdateRect.height = 4;// wxGTK :-)
m_UpdateRectValid = true;
}
}
+void
+wxLayoutList::StartSelection(void)
+{
+ WXLO_DEBUG(("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
+ m_Selection.m_CursorA = m_CursorPos;
+ m_Selection.m_CursorB = m_CursorPos;
+ m_Selection.m_selecting = true;
+ m_Selection.m_valid = false;
+}
+
+void
+wxLayoutList::ContinueSelection(void)
+{
+ wxASSERT(m_Selection.m_selecting == true);
+ wxASSERT(m_Selection.m_valid == false);
+ WXLO_DEBUG(("Continuing selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
+ m_Selection.m_CursorB = m_CursorPos;
+ // We always want m_CursorA <= m_CursorB!
+ if(! (m_Selection.m_CursorA <= m_Selection.m_CursorB))
+ {
+ wxPoint help = m_Selection.m_CursorB;
+ m_Selection.m_CursorB = m_Selection.m_CursorA;
+ m_Selection.m_CursorA = help;
+ }
+}
+
+void
+wxLayoutList::EndSelection(void)
+{
+ ContinueSelection();
+ WXLO_DEBUG(("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y));
+ m_Selection.m_selecting = false;
+ m_Selection.m_valid = true;
+}
+
+
+bool
+wxLayoutList::IsSelecting(void)
+{
+ return m_Selection.m_selecting;
+}
+
+bool
+wxLayoutList::IsSelected(const wxPoint &cursor)
+{
+ if(! m_Selection.m_valid && ! m_Selection.m_selecting)
+ return false;
+ return m_Selection.m_CursorA <= cursor
+ && cursor <= m_Selection.m_CursorB;
+}
+
+
+/** Tests whether this layout line is selected and needs
+ highlighting.
+ @param line to test for
+ @return 0 = not selected, 1 = fully selected, -1 = partially
+ selected
+ */
+int
+wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from,
+ CoordType *to)
+{
+ wxASSERT(line); wxASSERT(to); wxASSERT(from);
+
+ if(! m_Selection.m_valid && ! m_Selection.m_selecting)
+ return 0;
+
+ CoordType y = line->GetLineNumber();
+ if(m_Selection.m_CursorA.y < y && m_Selection.m_CursorB.y > y)
+ return 1;
+ else if(m_Selection.m_CursorA.y == y)
+ {
+ *from = m_Selection.m_CursorA.x;
+ if(m_Selection.m_CursorB.y == y)
+ *to = m_Selection.m_CursorB.x;
+ else
+ *to = line->GetLength();
+ return -1;
+ }
+ else if(m_Selection.m_CursorB.y == y)
+ {
+ *to = m_Selection.m_CursorB.x;
+ if(m_Selection.m_CursorA.y == y)
+ *from = m_Selection.m_CursorA.x;
+ else
+ *from = 0;
+ return -1;
+ }
+ else
+ return 0;
+}
+
+void
+wxLayoutList::DeleteSelection(void)
+{
+ if(! m_Selection.m_valid)
+ return;
+
+ m_Selection.m_valid = false;
+
+ // Only delete part of the current line?
+ if(m_Selection.m_CursorA.y == m_Selection.m_CursorB.y)
+ {
+ MoveCursorTo(m_Selection.m_CursorA);
+ Delete(m_Selection.m_CursorB.x - m_Selection.m_CursorA.x);
+ return;
+ }
+
+
+ wxLayoutLine
+ * firstLine = NULL,
+ * lastLine = NULL;
+
+ for(firstLine = m_FirstLine;
+ firstLine && firstLine->GetLineNumber() < m_Selection.m_CursorA.y;
+ firstLine=firstLine->GetNextLine())
+ ;
+ if(!firstLine || firstLine->GetLineNumber() != m_Selection.m_CursorA.y)
+ return;
+
+
+ for(lastLine = m_FirstLine;
+ lastLine && lastLine->GetLineNumber() < m_Selection.m_CursorB.y;
+ lastLine=lastLine->GetNextLine())
+ ;
+ if(!lastLine || lastLine->GetLineNumber() != m_Selection.m_CursorB.y)
+ return;
+
+
+ // We now know that the two lines are different:
+
+ // First, delete what's left of this line:
+ MoveCursorTo(m_Selection.m_CursorA);
+ DeleteToEndOfLine();
+
+ wxLayoutLine *nextLine = firstLine->GetNextLine();
+ while(nextLine && nextLine != lastLine)
+ nextLine = nextLine->DeleteLine(false, this);
+
+ // Now nextLine = lastLine;
+ Delete(1); // This joins firstLine and nextLine
+ Delete(m_Selection.m_CursorB.x); // This deletes the first x
+ // positions
+
+ /// Recalculate:
+ firstLine->RecalculatePositions(1, this);
+}
+
+/// Starts highlighting the selection
+void
+wxLayoutList::StartHighlighting(wxDC &dc)
+{
+#if SHOW_SELECTIONS
+ dc.SetTextForeground(m_ColourBG);
+ dc.SetTextBackground(m_ColourFG);
+#endif
+}
+
+/// Ends highlighting the selection
+void
+wxLayoutList::EndHighlighting(wxDC &dc)
+{
+#if SHOW_SELECTIONS
+ dc.SetTextForeground(m_ColourFG);
+ dc.SetTextBackground(m_ColourBG);
+#endif
+}
+
+
+wxLayoutList *
+wxLayoutList::Copy(const wxPoint &from,
+ const wxPoint &to)
+{
+ wxLayoutLine
+ * firstLine = NULL,
+ * lastLine = NULL;
+
+ for(firstLine = m_FirstLine;
+ firstLine && firstLine->GetLineNumber() < from.y;
+ firstLine=firstLine->GetNextLine())
+ ;
+ if(!firstLine || firstLine->GetLineNumber() != from.y)
+ return NULL;
+
+ for(lastLine = m_FirstLine;
+ lastLine && lastLine->GetLineNumber() < to.y;
+ lastLine=lastLine->GetNextLine())
+ ;
+ if(!lastLine || lastLine->GetLineNumber() != to.y)
+ return NULL;
+
+ if(to <= from)
+ {
+ wxLayoutLine *tmp = firstLine;
+ firstLine = lastLine;
+ lastLine = tmp;
+ }
+
+ wxLayoutList *llist = new wxLayoutList();
+
+ if(firstLine == lastLine)
+ {
+ firstLine->Copy(llist, from.x, to.x);
+ }
+ else
+ {
+ // Extract objects from first line
+ firstLine->Copy(llist, from.x);
+ llist->LineBreak();
+ // Extract all lines between
+ for(wxLayoutLine *line = firstLine->GetNextLine();
+ line != lastLine;
+ line = line->GetNextLine())
+ {
+ line->Copy(llist);
+ llist->LineBreak();
+ }
+ // Extract objects from last line
+ lastLine->Copy(llist, 0, to.x);
+ }
+ return llist;
+}
+
+wxLayoutList *
+wxLayoutList::GetSelection(void)
+{
+ if(! m_Selection.m_valid)
+ {
+ if(m_Selection.m_selecting)
+ EndSelection();
+ else
+ return NULL;
+ }
+
+ m_Selection.m_valid = false;
+ return Copy( m_Selection.m_CursorA, m_Selection.m_CursorB );
+}
+
+
+
+#define COPY_SI(what) if(si->what != -1) m_CurrentSetting.what = si->what;
+
+void
+wxLayoutList::ApplyStyle(wxLayoutStyleInfo *si, wxDC &dc)
+{
+ COPY_SI(family);
+ COPY_SI(size);
+ COPY_SI(style);
+ COPY_SI(weight);
+ COPY_SI(underline);
+
+
+ if(si->fg_valid)
+ {
+ m_CurrentSetting.fg_valid = true;
+ m_CurrentSetting.fg_red = si->fg_red;
+ m_CurrentSetting.fg_green = si->fg_green;
+ m_CurrentSetting.fg_blue = si->fg_blue;
+ }
+ if(si->bg_valid)
+ {
+ m_CurrentSetting.bg_valid = true;
+ m_CurrentSetting.bg_red = si->bg_red;
+ m_CurrentSetting.bg_green = si->bg_green;
+ m_CurrentSetting.bg_blue = si->bg_blue;
+ }
+
+ m_ColourFG = wxColour(m_CurrentSetting.fg_red,
+ m_CurrentSetting.fg_green,
+ m_CurrentSetting.fg_blue);
+ m_ColourBG = wxColour(m_CurrentSetting.bg_red,
+ m_CurrentSetting.bg_green,
+ m_CurrentSetting.bg_blue);
+ dc.SetTextForeground(m_ColourFG);
+ dc.SetTextBackground(m_ColourBG);
+}
+
+
+#ifdef WXLAYOUT_DEBUG
+
+void
+wxLayoutList::Debug(void)
+{
+ wxLayoutLine *line;
+
+
+ for(line = m_FirstLine;
+ line;
+ line = line->GetNextLine())
+ line->Debug();
+}
+
+#endif
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
m_title = title;
}
+wxLayoutPrintout::~wxLayoutPrintout()
+{
+}
+
float
wxLayoutPrintout::ScaleDC(wxDC *dc)
{