X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9e55588fe3053b5ce068935a9a17846f3add7462..c3317e87ec1795b8471e684f06e5366ec6f645a2:/user/wxLayout/wxllist.cpp diff --git a/user/wxLayout/wxllist.cpp b/user/wxLayout/wxllist.cpp index 6e972e3ebc..d0a3bc05a5 100644 --- a/user/wxLayout/wxllist.cpp +++ b/user/wxLayout/wxllist.cpp @@ -14,7 +14,7 @@ #pragma implementation "wxllist.h" #endif -//#include "Mpch.h" +#include "Mpch.h" #include "wx/wxprec.h" @@ -22,10 +22,13 @@ # pragma hdrstop #endif -#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 @@ -89,25 +92,30 @@ bool operator <=(wxPoint const &p1, wxPoint const &p2) /// grows a wxRect so that it includes the given point static -void GrowRect(wxRect &r, const wxPoint & p) +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 + + //@} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -146,9 +154,34 @@ wxLayoutObjectText::GetSize(CoordType *top, CoordType *bottom) const } 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 @@ -177,7 +210,7 @@ wxLayoutObjectText::GetOffsetScreen(wxDC &dc, CoordType xpos) const } void -wxLayoutObjectText::Layout(wxDC &dc) +wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList * ) { long descent = 0l; @@ -221,14 +254,16 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap *icon) } 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 * ) { } @@ -244,70 +279,129 @@ wxLayoutObjectIcon::GetSize(CoordType *top, CoordType *bottom) const /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - 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 &fg, wxColour &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); - dc.SetTextForeground(m_ColourFG); - 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); } @@ -349,9 +443,13 @@ wxLayoutLine::~wxLayoutLine() wxPoint 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); @@ -407,7 +505,9 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const } 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); @@ -416,12 +516,13 @@ wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const 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(); @@ -429,9 +530,42 @@ wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const } // 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) { @@ -631,11 +765,42 @@ wxLayoutLine::Draw(wxDC &dc, 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(); } } @@ -671,7 +836,7 @@ wxLayoutLine::Layout(wxDC &dc, for(i = m_ObjectList.begin(); i != NULLIT; i++) { - (**i).Layout(dc); + (**i).Layout(dc, llist); size = (**i).GetSize(&objTopHeight, &objBottomHeight); if(cursorPos && ! cursorFound) @@ -898,6 +1063,85 @@ wxLayoutLine::GetWrapPosition(CoordType column) } +#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 @@ -944,6 +1188,14 @@ wxLayoutList::InternalClear(void) 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 @@ -951,18 +1203,32 @@ wxLayoutList::SetFont(int family, int size, int style, int weight, int underline, wxColour *fg, wxColour *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; - + 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 @@ -979,36 +1245,43 @@ wxLayoutList::SetFont(int family, int size, int style, int weight, 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 */, wxColour *fg, wxColour *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; - if(fg) m_ColourFG = *fg; - if(bg) m_ColourBG = *bg; - - m_ColourFG = *wxBLACK; - 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 @@ -1140,6 +1413,7 @@ wxLayoutList::Insert(wxString const &text) 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; } @@ -1151,6 +1425,7 @@ wxLayoutList::Insert(wxLayoutObject *obj) 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; } @@ -1166,6 +1441,7 @@ wxLayoutList::LineBreak(void) m_FirstLine = m_CursorLine->GetPreviousLine(); m_CursorPos.y++; m_CursorPos.x = 0; + m_CursorLine->RecalculatePositions(true, this); //FIXME needed? return true; } @@ -1187,6 +1463,7 @@ wxLayoutList::WrapLine(CoordType column) LineBreak(); Delete(1); // delete the space m_CursorPos.x = newpos; + m_CursorLine->RecalculatePositions(true, this); //FIXME needed? return true; } } @@ -1228,6 +1505,7 @@ wxLayoutList::Delete(CoordType npos) } } while(left); + m_CursorLine->RecalculatePositions(true, this); //FIXME needed? return left == 0; } @@ -1244,6 +1522,7 @@ wxLayoutList::DeleteLines(int n) { // we cannot delete this line, but we can clear it MoveCursorToBeginOfLine(); DeleteToEndOfLine(); + m_CursorLine->RecalculatePositions(2, this); return n-1; } //else: @@ -1265,7 +1544,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) // 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(this); // so we don't need to do it all the time @@ -1296,7 +1575,7 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom) // 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) @@ -1320,41 +1599,46 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom) } void -wxLayoutList::Draw(wxDC &dc, wxPoint const &offset, - CoordType top, CoordType bottom) +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)); + 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)) + 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(); @@ -1363,10 +1647,16 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, wxPoint *cursorPos) 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; } @@ -1395,6 +1685,7 @@ wxLayoutList::GetSize(void) const return maxPoint; } + void wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate) { @@ -1416,27 +1707,32 @@ 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; @@ -1446,25 +1742,298 @@ wxLayoutList::SetUpdateRect(const wxPoint &p) void wxLayoutList::StartSelection(void) { - wxLogDebug("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y); + 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::EndSelection(void) +wxLayoutList::ContinueSelection(void) { - wxLogDebug("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y); + 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 + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * wxLayoutPrintout @@ -1479,6 +2048,10 @@ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist, m_title = title; } +wxLayoutPrintout::~wxLayoutPrintout() +{ +} + float wxLayoutPrintout::ScaleDC(wxDC *dc) {