X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9905086c2d34b14bb46275f5c64e0ad2b283e143..11765138636bade99a104fa6a72ef5ced752b22d:/user/wxLayout/wxllist.cpp?ds=sidebyside diff --git a/user/wxLayout/wxllist.cpp b/user/wxLayout/wxllist.cpp index 93d34099b9..69083fdeb5 100644 --- a/user/wxLayout/wxllist.cpp +++ b/user/wxLayout/wxllist.cpp @@ -20,37 +20,29 @@ is four cursor positions long. This makes sure that cursor positions are "as expected", i.e. in "abc\ndef" the 'd' would be at positions (x=0,y=1). + + + The redrawing of the cursor no longer erases it at the last + position, because the list gets redrawn anyway. */ /* TODO: - - new cursor movement calculations - - moving lines and moving across linebreaks still broken - - - word wrap - blinking cursor - mouse click positions cursor - selection (SetMark(), GetSelection()) - - DND acceptance of text - + - DND acceptance of text / clipboard support - wxlwindow: formatting menu: problem with checked/unchecked consistency gtk bug? */ -#define USE_NEW_CURSORCODE 1 - -/* - Known wxGTK bugs: - - MaxX()/MaxY() don't get set -*/ - #ifdef __GNUG__ #pragma implementation "wxllist.h" #endif //#include "Mpch.h" -#ifdef M_BASEDIR +#ifdef M_PREFIX # include "gui/wxllist.h" #else # include "wxllist.h" @@ -59,7 +51,7 @@ #ifndef USE_PCH # include "iostream.h" # include -# include +# include # include # include #endif @@ -167,7 +159,7 @@ wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon *icon) void wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint const &translate) { - dc.DrawIcon(m_Icon,m_Position.x+translate.x, m_Position.y+translate.y); + dc.DrawIcon(*m_Icon,m_Position.x+translate.x, m_Position.y+translate.y); } void @@ -229,7 +221,7 @@ void wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint const &translate) { wxASSERT(m_font); - dc.SetFont(m_font); + dc.SetFont(*m_font); if(m_ColourFG) dc.SetTextForeground(*m_ColourFG); if(m_ColourBG) @@ -248,6 +240,10 @@ wxLayoutObjectCmd::Layout(wxDC &dc, wxPoint p, CoordType baseline) wxLayoutList::wxLayoutList() { m_DefaultSetting = NULL; + m_WrapMargin = -1; + m_Editable = FALSE; + m_boldCursor = FALSE; + Clear(); } @@ -262,7 +258,6 @@ void wxLayoutList::LineBreak(void) { Insert(new wxLayoutObjectLineBreak); -// m_CursorPos.x = 0; m_CursorPos.y++; } void @@ -409,20 +404,8 @@ wxLayoutList::Layout(wxDC &dc, wxLayoutMargins *margins) headOfLine++; position_HeadOfLine = position; } -#if defined( USE_NEW_CURSORCODE ) if(i == m_CursorObject) CalculateCursor(dc); -#else - if(cursorObject == NULL && cursorPos.y == m_CursorPos.y) // look for cursor - { - if(cursorPos.x >= m_CursorPos.x && - m_CursorPos.x-cursorPos.x+(**i).CountPositions()) // cursor is in current object - { - cursorObject = *i; - CalculateCursor(dc); - } - } -#endif i++; } while(i != end()); @@ -435,7 +418,7 @@ wxLayoutList::Draw(wxDC &dc, iterator start, wxPoint const &translate) { - Layout(dc); // FIXME just for now + //Layout(dc); // FIXME just for now ResetSettings(dc); @@ -464,7 +447,7 @@ wxLayoutList::Draw(wxDC &dc, /** Erase at least to end of line */ void -wxLayoutList::EraseAndDraw(wxDC &dc, iterator start) +wxLayoutList::EraseAndDraw(wxDC &dc, iterator start, wxPoint const &translate) { //look for begin of line while(start != end() && start != begin() && (**start).GetType() != @@ -479,10 +462,11 @@ wxLayoutList::EraseAndDraw(wxDC &dc, iterator start) //FIXME: wxGTK: MaxX()/MaxY() broken //WXL_VAR(dc.MaxX()); WXL_VAR(dc.MaxY()); - dc.SetBrush(*wxWHITE_BRUSH); - dc.SetPen(wxPen(*wxWHITE,0,wxTRANSPARENT)); + + dc.SetBrush(wxBrush(*m_ColourBG, wxSOLID)); + dc.SetPen(wxPen(*m_ColourBG,0,wxTRANSPARENT)); dc.DrawRectangle(p.x,p.y,2000,2000); //dc.MaxX(),dc.MaxY()); - Draw(dc,-1,-1,start,wxPoint(0,0)); + Draw(dc,-1,-1,start,translate); //dc.DrawRectangle(p.x,p.y,2000,2000); //dc.MaxX(),dc.MaxY()); } @@ -490,39 +474,40 @@ wxLayoutList::EraseAndDraw(wxDC &dc, iterator start) void wxLayoutList::CalculateCursor(wxDC &dc) { + if(! m_CursorMoved) + return; + CoordType width, height, descent; CoordType baseLineSkip = 20; //FIXME - CoordType offset; - if( FindCurrentObject() == iterator(NULL)) // empty list + int cursorWidth = m_boldCursor ? 4 : 2; + + if( m_CursorObject == iterator(NULL)) // empty list { - DrawCursor(dc,true); // erase it m_CursorCoords = wxPoint(0,0); - m_CursorSize = wxPoint(2,baseLineSkip); + m_CursorSize = wxPoint(cursorWidth,baseLineSkip); m_CursorMoved = false; // coords are valid return; } - wxLayoutObjectBase &obj = **FindCurrentObject(&offset); - - DrawCursor(dc,true); // erase it + wxLayoutObjectBase &obj = **m_CursorObject; m_CursorCoords = obj.GetPosition(); if(obj.GetType() == WXLO_TYPE_TEXT) { wxLayoutObjectText *tobj = (wxLayoutObjectText *)&obj; String & str = tobj->GetText(); - String sstr = str.substr(0,offset); + String sstr = str.substr(0,m_CursorOffset); dc.GetTextExtent(sstr,&width,&height,&descent); m_CursorCoords = wxPoint(m_CursorCoords.x+width, m_CursorCoords.y); - m_CursorSize = wxPoint(2,height); + m_CursorSize = wxPoint(cursorWidth,height); } else if(obj.GetType() == WXLO_TYPE_LINEBREAK) { if(m_CursorOffset == 1) // behind linebreak m_CursorCoords = wxPoint(0, m_CursorCoords.y + baseLineSkip); //m_CursorCoords = wxPoint(0, m_CursorCoords.y); - m_CursorSize = wxPoint(2,baseLineSkip); + m_CursorSize = wxPoint(cursorWidth,baseLineSkip); } else { @@ -530,43 +515,52 @@ wxLayoutList::CalculateCursor(wxDC &dc) //cursorPosition = wxPoint(position.x, position.y); //cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip); m_CursorCoords = wxPoint(m_CursorCoords.x+obj.GetSize().x, m_CursorCoords.y); - m_CursorSize = wxPoint(2, obj.GetSize().y); + m_CursorSize = wxPoint(cursorWidth, obj.GetSize().y); if(m_CursorSize.y < 1) m_CursorSize.y = baseLineSkip; } m_CursorMoved = false; // coords are valid } void -wxLayoutList::DrawCursor(wxDC &dc, bool erase) +wxLayoutList::DrawCursor(wxDC &dc, bool erase, wxPoint const &translate) { if(! m_Editable) return; if(erase) - { - //dc.SetBrush(*wxWHITE_BRUSH); - //dc.SetPen(wxPen(*wxWHITE,1,wxSOLID)); - //dc.DrawRectangle(m_CursorCoords.x, m_CursorCoords.y, m_CursorSize.x, m_CursorSize.y); - dc.Blit(m_CursorCoords.x, m_CursorCoords.y, m_CursorSize.x, - m_CursorSize.y, &m_CursorMemDC, - 0, 0, 0, 0); - } + ; +#if 0 + dc.Blit(m_CursorCoords.x+translate.x, + m_CursorCoords.y+translate.y, + m_CursorSize.x,m_CursorSize.y, + &m_CursorMemDC, + 0, 0, 0, 0); +#endif else { + // erase it at the old position: if(IsDirty() || CursorMoved()) { - DrawCursor(dc,true); + // We don't need to erase the cursor because the screen gets + // redrawn completely. +// DrawCursor(dc,true); + // this is needed to update the cursor coordinates Layout(dc); } - // Save background: +#if 0 +// Save background: wxBitmap bm(m_CursorSize.x+1,m_CursorSize.y+1); m_CursorMemDC.SelectObject(bm); - m_CursorMemDC.Blit(0, 0, m_CursorSize.x, m_CursorSize.y, - &dc, m_CursorCoords.x, - m_CursorCoords.y, 0, 0); + m_CursorMemDC.Blit(0, 0, + m_CursorSize.x, m_CursorSize.y, + &dc, + m_CursorCoords.x+translate.x, + m_CursorCoords.y+translate.y, 0, 0); +#endif + // draw it: dc.SetBrush(*wxBLACK_BRUSH); dc.SetPen(wxPen(*wxBLACK,1,wxSOLID)); - dc.DrawRectangle(m_CursorCoords.x, m_CursorCoords.y, + dc.DrawRectangle(m_CursorCoords.x+translate.x, m_CursorCoords.y+translate.y, m_CursorSize.x, m_CursorSize.y); } } @@ -596,23 +590,22 @@ wxLayoutList::Debug(void) void wxLayoutList::ShowCurrentObject() { - CoordType offs; - wxLayoutObjectList::iterator i = FindCurrentObject(&offs); - wxLayoutDebug("CursorPos (%d, %d)", (int) m_CursorPos.x, (int) m_CursorPos.y); wxLayoutDebug("CursorOffset = %d", (int) m_CursorOffset); wxLayoutDebug("CursorObject = %p", m_CursorObject); - wxLayoutDebug("Line length: %d", GetLineLength(i)); - - if(i == iterator(NULL)) + if(m_CursorObject == iterator(NULL)) wxLayoutDebug("<>"); else { - if((*i)->GetType() == WXLO_TYPE_TEXT) - wxLayoutDebug(" \"%s\", offs: %d", ((wxLayoutObjectText *)(*i))->GetText().c_str(), offs); + if((*m_CursorObject)->GetType() == WXLO_TYPE_TEXT) + wxLayoutDebug(" \"%s\", offs: %d", + ((wxLayoutObjectText *)(*m_CursorObject))->GetText().c_str(), + m_CursorOffset); else - wxLayoutDebug(" %s", TypeString((*i)->GetType())); + wxLayoutDebug(" %s", TypeString((*m_CursorObject)->GetType())); } + wxLayoutDebug("Line length: %d", GetLineLength(m_CursorObject)); + } #endif @@ -715,14 +708,6 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset) return m_FoundIterator = i; // not found } -wxLayoutObjectList::iterator -wxLayoutList::FindCurrentObject(CoordType *offset) -{ - if(offset) - *offset = m_CursorOffset; - return m_CursorObject; -} - bool wxLayoutList::MoveCursor(int dx, int dy) { @@ -740,13 +725,24 @@ wxLayoutList::MoveCursor(int dx, int dy) if(newPos.y < 0) newPos.y = 0; else if(newPos.y > m_MaxLine) newPos.y = m_MaxLine; + //FIXME: quick and dirty hack: as last object in buffer should be a + // linebreak, we don't allow to go there + if(newPos.y >= m_MaxLine) + return false; + if(newPos.y > m_CursorPos.y || newPos.y == m_CursorPos.y && newPos.x >= m_CursorPos.x) direction = down; else direction = up; - + + if ( !m_CursorObject ) + { + // list is empty + return FALSE; + } + // now move cursor forwards until at the new position: // first, go to the right line: @@ -784,6 +780,12 @@ wxLayoutList::MoveCursor(int dx, int dy) newPos.y = m_CursorPos.y; // exited by break // now line is right, go to right column: + if(dx == 0) // we are moving up or down only + { + int max_x = GetLineLength(m_CursorObject); + if(max_x <= newPos.x) // ... so we don't want to cross linebreaks + newPos.x = max_x-1; // but just go to the right column + } direction = newPos.x >= m_CursorPos.x ? down : up; while(newPos.x != m_CursorPos.x) { @@ -845,8 +847,16 @@ wxLayoutList::MoveCursor(int dx, int dy) } } } + return true; // FIXME: when return what? } +void +wxLayoutList::SetCursor(wxPoint const &p) +{ + m_CursorPos = p; + m_CursorObject = FindObjectCursor(&m_CursorPos, &m_CursorOffset); + m_CursorMoved = true; +} void wxLayoutList::Delete(CoordType count) @@ -858,21 +868,21 @@ wxLayoutList::Delete(CoordType count) m_bModified = true; - CoordType offs; + CoordType offs = 0; wxLayoutObjectList::iterator i; do { - i = FindCurrentObject(&offs); + i = m_CursorObject; startover: // ugly, but easiest way to do it if(i == end()) return; // we cannot delete anything more -/* Here we need to treat linebreaks differently. - If offs==0 we are before the linebreak, otherwise behind. */ + /* Here we need to treat linebreaks differently. + If m_CursorOffset==0 we are before the linebreak, otherwise behind. */ if((*i)->GetType() == WXLO_TYPE_LINEBREAK) { - if(offs == 0) + if(m_CursorOffset == 0) { m_MaxLine--; erase(i); @@ -884,7 +894,7 @@ wxLayoutList::Delete(CoordType count) else // delete the object behind the linebreak { i++; // we increment and continue as normal - offs=0; + m_CursorOffset=0; goto startover; } } @@ -892,26 +902,32 @@ wxLayoutList::Delete(CoordType count) { wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i; CoordType len = tobj->CountPositions(); -// If we find the end of a text object, this means that we -// have to delete from the object following it. - if(len == offs) + /* If we find the end of a text object, this means that we + have to delete from the object following it. */ + if(len == m_CursorOffset) { i++; - offs = 0; - goto startover; - } - else if(len <= count) // delete this object - { - count -= len; - erase(i); - m_CursorObject = i; m_CursorOffset = 0; - continue; + goto startover; } else { - len = count; - tobj->GetText().erase(offs,len); + if(m_CursorOffset == 0 && len <= count) // delete this object + { + count -= len; + erase(i); + m_CursorObject = i; + m_CursorOffset = 0; + continue; + } + + int todelete = count; + if(todelete > len-m_CursorOffset) + todelete = len-m_CursorOffset; + + len = len - todelete; + tobj->GetText().erase(m_CursorOffset,todelete); + count -= todelete; // cursor unchanged return; // we are done } @@ -933,7 +949,7 @@ wxLayoutList::Delete(CoordType count) else // delete the following object { i++; // we increment and continue as normal - offs=0; + m_CursorOffset=0; goto startover; } } @@ -941,6 +957,7 @@ wxLayoutList::Delete(CoordType count) while(count && i != end()); } + void wxLayoutList::Insert(wxLayoutObjectBase *obj) { @@ -948,31 +965,31 @@ wxLayoutList::Insert(wxLayoutObjectBase *obj) m_bModified = true; - CoordType offs; - wxLayoutObjectList::iterator i = FindCurrentObject(&offs); + wxLayoutObjectList::iterator i = m_CursorObject; -// if(i != iterator(NULL) && (*obj).GetType() == WXLO_TYPE_LINEBREAK) -// { -// m_CursorPos.x = 0; m_CursorPos.y ++; -// } + if(i != iterator(NULL) && (*obj).GetType() == WXLO_TYPE_LINEBREAK) + { + m_CursorPos.x = 0; m_CursorPos.y ++; + } if(i == end()) { push_back(obj); m_CursorObject = tail(); } - else if(offs == 0) + else if(m_CursorOffset == 0) { insert(i,obj); m_CursorObject = i; } // do we have to split a text object? - else if((*i)->GetType() == WXLO_TYPE_TEXT && offs != (*i)->CountPositions()) + else if((*i)->GetType() == WXLO_TYPE_TEXT && m_CursorOffset != (*i)->CountPositions()) { wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i; - String left = tobj->GetText().substr(0,offs); // get part before cursor - tobj->GetText() = tobj->GetText().substr(offs,(*i)->CountPositions()-offs); // keeps the right half + String left = tobj->GetText().substr(0,m_CursorOffset); // get part before cursor + tobj->GetText() = tobj->GetText().substr(m_CursorOffset,(*i)->CountPositions()-m_CursorOffset); // keeps the right half insert(i,obj); + m_CursorObject = i; // == obj insert(i,new wxLayoutObjectText(left)); // inserts before } else @@ -1015,8 +1032,7 @@ wxLayoutList::Insert(String const &text) m_bModified = true; - CoordType offs; - wxLayoutObjectList::iterator i = FindCurrentObject(&offs); + wxLayoutObjectList::iterator i = m_CursorObject; if(i == end()) { @@ -1024,26 +1040,21 @@ wxLayoutList::Insert(String const &text) return; } - if(i != iterator(NULL) && (**i).GetType() == WXLO_TYPE_LINEBREAK) - { - m_CursorPos.x = 0; m_CursorPos.y ++; - } - switch((**i).GetType()) { case WXLO_TYPE_TEXT: // insert into an existing text object: tobj = (wxLayoutObjectText *)*i ; wxASSERT(tobj); - tobj->GetText().insert(offs,text); + tobj->GetText().insert(m_CursorOffset,text); m_CursorObject = i; - m_CursorOffset = offs + text.length(); + m_CursorOffset = m_CursorOffset + text.length(); m_CursorPos.x += text.length(); break; case WXLO_TYPE_LINEBREAK: default: j = i; - if(offs == 0) // try to append to previous object + if(m_CursorOffset == 0) // try to append to previous object { j--; if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT) @@ -1106,7 +1117,10 @@ wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i, CoordType offs) CoordType len = 0; if(offs == 0 && (**i).GetType() == WXLO_TYPE_LINEBREAK) - i--; + if(i != begin()) + i--; + else + return 0; // at begin of buffer in front of a linebreak // search backwards for beginning of line: while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK) @@ -1132,7 +1146,7 @@ wxLayoutList::Clear(int family, int size, int style, int weight, m_dirty = true; // force redraw/recalc wxLayoutObjectList::iterator i = begin(); - wxBitmap bm(1,1); + wxBitmap bm(4,4); m_CursorMemDC.SelectObject(bm); while(i != end()) // == while valid @@ -1199,6 +1213,73 @@ wxLayoutList::Find(wxPoint coords) const } +void +wxLayoutList::SetWrapMargin(long n) +{ + m_WrapMargin = n; +} + +void +wxLayoutList::WrapLine(void) +{ + wxASSERT(m_CursorObject); + + iterator i = m_CursorObject; + + if(!DoWordWrap() || !i ) // empty list + return; + int cursorpos = m_CursorPos.x, cpos, offset; + + if(cursorpos < m_WrapMargin) + return; + + // else: break line + + // find the right object to break: + // is it the current one? + + i = m_CursorObject; + cpos = cursorpos-m_CursorOffset; + while(i != begin() && cpos >= m_WrapMargin) + { + i--; + cpos -= (**i).CountPositions(); + } + // now i is the object to break and cpos its position + + offset = m_WrapMargin - cpos; + wxASSERT(offset <= (**i).CountPositions()); + + // split it + if((**i).GetType() == WXLO_TYPE_TEXT) + { + wxLayoutObjectText &t = *(wxLayoutObjectText *)*i; + for(; offset > 0; offset--) + if(t.GetText().c_str()[offset] == ' ' || t.GetText().c_str()[offset] == '\t') + { + String left = t.GetText().substr(0,offset); // get part before cursor + t.GetText() = t.GetText().substr(offset+1,t.CountPositions()-offset-1); // keeps the right halve + insert(i,new wxLayoutObjectLineBreak); + insert(i,new wxLayoutObjectText(left)); // inserts before + break; + } + if(offset == 0) + { + // only insert a line break if there isn't already one + iterator j = i; j--; + if(j && j != begin() && (**j).GetType() != WXLO_TYPE_LINEBREAK) + insert(i,new wxLayoutObjectLineBreak); + else + return; // do nothing + } + } + else + insert(i,new wxLayoutObjectLineBreak); + m_MaxLine++; + m_CursorPos.y++; + m_CursorPos.x -= offset; + m_CursorOffset -= offset; +} /******************** printing stuff ********************/ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList &llist, @@ -1277,7 +1358,7 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, bool wxLayoutPrintout::HasPage(int pageNum) { - return pageNum < m_NumOfPages; + return pageNum <= m_NumOfPages; } @@ -1287,10 +1368,9 @@ wxLayoutPrintout::DrawHeader(wxDC &dc, int pageno) { // make backups of all essential parameters - wxBrush *brush = dc.GetBrush(); - wxPen *pen = dc.GetPen(); - wxFont *font = dc.GetFont(), - *myfont;; + const wxBrush& brush = dc.GetBrush(); + const wxPen& pen = dc.GetPen(); + const wxFont& font = dc.GetFont(); dc.SetBrush(*wxWHITE_BRUSH); dc.SetPen(wxPen(*wxBLACK,0,wxSOLID)); @@ -1298,8 +1378,9 @@ wxLayoutPrintout::DrawHeader(wxDC &dc, topleft.y,bottomright.x-topleft.x, bottomright.y-topleft.y); dc.SetBrush(*wxBLACK_BRUSH); - myfont = new wxFont((WXLO_DEFAULTFONTSIZE*12)/10,wxSWISS,wxNORMAL,wxBOLD,false,"Helvetica"); - dc.SetFont(*myfont); + wxFont myfont = wxFont((WXLO_DEFAULTFONTSIZE*12)/10, + wxSWISS,wxNORMAL,wxBOLD,false,"Helvetica"); + dc.SetFont(myfont); wxString page; page = "9999/9999 "; // many pages... @@ -1311,11 +1392,9 @@ wxLayoutPrintout::DrawHeader(wxDC &dc, dc.DrawText(m_title, topleft.x+w,topleft.y+h/2); // restore settings - dc.SetPen(*pen); - dc.SetBrush(*brush); - dc.SetFont(*font); - - delete myfont; + dc.SetPen(pen); + dc.SetBrush(brush); + dc.SetFont(font); }