From e589112ed07376c4dea69920943e8eb3cd30e45b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Karsten=20Ball=C3=BCder?= Date: Sat, 8 May 1999 18:01:24 +0000 Subject: [PATCH] Much improved, update rectangles almost work. Selections seem to work. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2366 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- user/wxLayout/TODO | 12 +++- user/wxLayout/wxLayout.cpp | 19 +++++- user/wxLayout/wxllist.cpp | 125 ++++++++++++++++++++++++++++-------- user/wxLayout/wxllist.h | 46 +++++++++++-- user/wxLayout/wxlwindow.cpp | 89 ++++++++++++++++--------- user/wxLayout/wxlwindow.h | 1 + 6 files changed, 226 insertions(+), 66 deletions(-) diff --git a/user/wxLayout/TODO b/user/wxLayout/TODO index 4561575910..f129bd241a 100644 --- a/user/wxLayout/TODO +++ b/user/wxLayout/TODO @@ -13,25 +13,31 @@ BUGS - fix horiz scrollbar size - occasionally wraps lines wongly (twice) ?? + TODO ===================================================================== +- selections should get highlighted, add COPY +- searching for text +- moving cursor in non-edit mode + + RECENTLY FIXED (?) - fix(simplify) cursor size calculation - delete in empty line doesn't work - fix horiz scrollbar size OK here, a Mahogany problem? + - with a large number of lines, wraps to top of scrolled window + --> check where the problem lies, add a debug function showing all coordinates - - - update rectangle (needs support in wxllist and wxWindows) --> needs a bit of fixing still some code bits are commented out in wxlwindow.cpp offset handling seems a bit dodgy, white shadow to top/left of cursor + - replacement of llist in window - undo - font optimisations(!) - - copy/cut/selections - occasionally wraps lines wongly (twice) ?? - UNDO later: diff --git a/user/wxLayout/wxLayout.cpp b/user/wxLayout/wxLayout.cpp index ad3e4ebca0..74163afbef 100644 --- a/user/wxLayout/wxLayout.cpp +++ b/user/wxLayout/wxLayout.cpp @@ -37,7 +37,8 @@ IMPLEMENT_APP(MyApp) ID_PRINT_SETUP, ID_PAGE_SETUP, ID_PREVIEW, ID_PRINT_PS, ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS, ID_WRAP, ID_NOWRAP, ID_PASTE, - ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT, ID_TEST }; + ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT, + ID_TEST, ID_LONG_TEST }; IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame ) @@ -87,6 +88,7 @@ MyFrame::MyFrame(void) : wxMenu *edit_menu = new wxMenu; edit_menu->Append( ID_CLEAR, "Clear"); edit_menu->Append( ID_ADD_SAMPLE, "Example"); + edit_menu->Append( ID_LONG_TEST, "Add many lines"); edit_menu->AppendSeparator(); edit_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200."); edit_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping."); @@ -260,6 +262,21 @@ void MyFrame::OnCommand( wxCommandEvent &event ) } } break; + case ID_LONG_TEST: + { + wxString line; + wxLayoutList *llist = m_lwin->GetLayoutList(); + for(int i = 1; i < 5000; i++) + { + line.Printf("This is line number %d.", i); + llist->Insert(line); + llist->LineBreak(); + } + llist->MoveCursorTo(wxPoint(0,0)); + m_lwin->SetDirty(); + m_lwin->Refresh(); + break; + } } }; diff --git a/user/wxLayout/wxllist.cpp b/user/wxLayout/wxllist.cpp index 6e972e3ebc..c0b4110420 100644 --- a/user/wxLayout/wxllist.cpp +++ b/user/wxLayout/wxllist.cpp @@ -22,8 +22,9 @@ # pragma hdrstop #endif -#ifdef M_PREFIX +#ifdef M_BASEDIR # include "gui/wxllist.h" +# include "gui/wxMDialogs.h" #else # include "wxllist.h" #endif @@ -89,17 +90,17 @@ 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; } /// returns true if the point is in the rectangle @@ -407,7 +408,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); @@ -422,6 +425,7 @@ wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const { *cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x); wxLogDebug("wxLayoutLine::FindObjectScreen: cursor xpos = %ld", *cxpos); + if(found) *found = true; return i; } x += (**i).GetWidth(); @@ -429,6 +433,7 @@ wxLayoutLine::FindObjectScreen(wxDC &dc, CoordType xpos, CoordType *cxpos) const } // behind last object: *cxpos = cx; + if(found) *found = false; return m_ObjectList.tail(); } @@ -898,6 +903,21 @@ wxLayoutLine::GetWrapPosition(CoordType column) } +#ifdef WXLAYOUT_DEBUG +void +wxLayoutLine::Debug(void) +{ + wxString tmp; + wxPoint pos = GetPosition(); + tmp.Printf("Line %ld, Pos (%ld,%ld), Height %ld", + (long int) GetLineNumber(), + (long int) pos.x, (long int) pos.y, + (long int) GetHeight()); + + wxLogDebug(tmp); +} +#endif + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * The wxLayoutList object @@ -1320,8 +1340,10 @@ 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; @@ -1333,10 +1355,10 @@ wxLayoutList::Draw(wxDC &dc, wxPoint const &offset, 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 @@ -1347,7 +1369,9 @@ wxLayoutList::Draw(wxDC &dc, wxPoint const &offset, } 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; @@ -1363,10 +1387,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; } @@ -1425,18 +1455,15 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate) //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; @@ -1448,6 +1475,8 @@ wxLayoutList::StartSelection(void) { wxLogDebug("Starting selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y); m_Selection.m_CursorA = m_CursorPos; + m_Selection.m_selecting = true; + m_Selection.m_valid = false; } void @@ -1455,6 +1484,14 @@ wxLayoutList::EndSelection(void) { wxLogDebug("Ending selection at %ld/%ld", m_CursorPos.x, m_CursorPos.y); m_Selection.m_CursorB = m_CursorPos; + m_Selection.m_selecting = false; + m_Selection.m_valid = true; +} + +bool +wxLayoutList::IsSelecting(void) +{ + return m_Selection.m_selecting; } bool @@ -1464,6 +1501,22 @@ wxLayoutList::IsSelected(const wxPoint &cursor) && cursor <= m_Selection.m_CursorB; } +#ifdef WXLAYOUT_DEBUG + +void +wxLayoutList::Debug(void) +{ + wxLayoutLine *line; + + + for(line = m_FirstLine; + line; + line = line->GetNextLine()) + line->Debug(); +} + +#endif + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -1477,6 +1530,16 @@ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist, { m_llist = llist; m_title = title; +#ifdef M_BASEDIR + m_ProgressDialog = NULL; +#endif +} + +wxLayoutPrintout::~wxLayoutPrintout() +{ +#ifdef M_BASEDIR + if(m_ProgressDialog) delete m_ProgressDialog; +#endif } float @@ -1531,6 +1594,12 @@ wxLayoutPrintout::ScaleDC(wxDC *dc) bool wxLayoutPrintout::OnPrintPage(int page) { +#ifdef M_BASEDIR + wxString msg; + msg.Printf(_("Printing page %d..."), page); + if(! m_ProgressDialog->Update(page, msg)) + return false; +#endif wxDC *dc = GetDC(); ScaleDC(dc); @@ -1581,6 +1650,12 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, *selPageFrom = 1; *selPageTo = m_NumOfPages; wxRemoveFile(WXLLIST_TEMPFILE); + +#ifdef M_BASEDIR + m_ProgressDialog = new MProgressDialog( + title, _("Printing..."),m_NumOfPages, NULL, false, true); +#endif + } bool wxLayoutPrintout::HasPage(int pageNum) diff --git a/user/wxLayout/wxllist.h b/user/wxLayout/wxllist.h index 75019427ef..eb657e1abf 100644 --- a/user/wxLayout/wxllist.h +++ b/user/wxLayout/wxllist.h @@ -413,7 +413,8 @@ public: */ wxLayoutObjectList::iterator FindObjectScreen(wxDC &dc, CoordType xpos, - CoordType *offset) const ; + CoordType *offset, + bool *found = NULL) const ; /** Get the first object in the list. This is used by the wxlparser functions to export the list. @@ -469,9 +470,13 @@ public: position. It assumes that Layout() has been called before. @param dc the wxDC to use for calculations @param xpos screen x position + @param found if non-NULL set to false if we return the last + object before the cursor, to true if we really have an object + for that position @return pointer to the object */ - wxLayoutObject * FindObjectScreen(wxDC &dc, CoordType xpos); + wxLayoutObject * FindObjectScreen(wxDC &dc, CoordType xpos, bool + *found = NULL); //@} /**@name List traversal */ @@ -505,6 +510,11 @@ public: void RecalculatePositions(int recurse, wxLayoutList *llist); /// Recalculates the position of this line on the canvas. wxPoint RecalculatePosition(wxLayoutList *llist); + +#ifdef WXLAYOUT_DEBUG + void Debug(void); +#endif + private: /// Destructor is private. Use DeleteLine() to remove it. ~wxLayoutLine(); @@ -723,7 +733,8 @@ public: @param top optional y coordinate where to start drawing @param bottom optional y coordinate where to stop drawing */ - void Draw(wxDC &dc, const wxPoint &offset = wxPoint(0,0), + void Draw(wxDC &dc, + const wxPoint &offset = wxPoint(0,0), CoordType top = -1, CoordType bottom = -1); /** Calculates new layout for the list, like Draw() but does not @@ -766,16 +777,25 @@ public: position. It assumes that Layout() has been called before. @param pos screen position @param cursorPos if non NULL, store cursor position in there + @param found if used, set this to true if we really found an + object, to false if we had to take the object near to it @return pointer to the object */ wxLayoutObject * FindObjectScreen(wxDC &dc, wxPoint const pos, - wxPoint *cursorPos = NULL); + wxPoint *cursorPos = NULL, + bool *found = NULL); + /** Called by the objects to update the update rectangle. + @param x horizontal coordinate to include in rectangle + @param y vertical coordinate to include in rectangle + */ + void SetUpdateRect(CoordType x, CoordType y); /** Called by the objects to update the update rectangle. @param p a point to include in it */ - void SetUpdateRect(const wxPoint &p); + inline void SetUpdateRect(const wxPoint &p) + { SetUpdateRect(p.x,p.y); } /// Invalidates the update rectangle. void InvalidateUpdateRect(void) { m_UpdateRectValid = false; } /// Returns the update rectangle. @@ -792,10 +812,17 @@ public: } //@} + /// Begin selecting text. void StartSelection(void); + /// End selecting text. void EndSelection(void); + /// Are we still selecting text? + bool IsSelecting(void); bool IsSelected(const wxPoint &cursor); +#ifdef WXLAYOUT_DEBUG + void Debug(void); +#endif private: /// Clear the list. void InternalClear(void); @@ -825,7 +852,9 @@ private: struct Selection { bool m_valid; + bool m_selecting; wxPoint m_CursorA, m_CursorB; + Selection() { m_valid = false; m_selecting = true; } } m_Selection; /** @name Font parameters. */ //@{ @@ -862,6 +891,9 @@ public: wxLayoutPrintout(wxLayoutList *llist, wxString const & title = "wxLayout Printout"); + /// Destructor. + ~wxLayoutPrintout(); + /** Function which prints the n-th page. @param page the page number to print @return bool true if we are not at end of document yet @@ -906,6 +938,10 @@ private: int m_NumOfPages; /// Top left corner where we start printing. wxPoint m_Offset; +#ifdef M_BASEDIR + /// A progress dialog for printing + MProgressDialog *m_ProgressDialog; +#endif }; diff --git a/user/wxLayout/wxlwindow.cpp b/user/wxLayout/wxlwindow.cpp index fddc161486..1c45647563 100644 --- a/user/wxLayout/wxlwindow.cpp +++ b/user/wxLayout/wxlwindow.cpp @@ -23,7 +23,6 @@ # include "gui/wxMenuDefs.h" # include "gui/wxMApp.h" # endif // USE_PCH - # include "gui/wxlwindow.h" # include "gui/wxlparser.h" #else @@ -55,6 +54,7 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow) EVT_PAINT (wxLayoutWindow::OnPaint) EVT_CHAR (wxLayoutWindow::OnChar) + EVT_KEY_UP (wxLayoutWindow::OnKeyUp) EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick) EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick) EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick) @@ -128,25 +128,29 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) m_ClickPosition = wxPoint(event.GetX(), event.GetY()); #ifdef WXLAYOUT_DEBUG - wxLogDebug("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)", - event.GetX(), event.GetY(), findPos.x, findPos.y); +// wxLogDebug("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)", +// event.GetX(), event.GetY(), findPos.x, findPos.y); #endif wxPoint cursorPos; - wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, &cursorPos); + bool found; + wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, + &cursorPos, &found); #ifdef WXLAYOUT_DEBUG - if(obj) - wxLogDebug("wxLayoutWindow::OnMouse: Found object of type %d.", - obj->GetType()); - else - wxLogDebug("wxLayoutWindow::OnMouse: Found no object."); +// if(obj) +// wxLogDebug("wxLayoutWindow::OnMouse: Found object of type %d.", +// obj->GetType()); +// else +// wxLogDebug("wxLayoutWindow::OnMouse: Found no object."); #endif //has the mouse only been moved? if(eventId == WXLOWIN_MENU_MOUSEMOVE) { - if(obj && obj->GetUserData() != NULL) + // found is only true if we are really over an object, not just + // behind it + if(found && obj && obj->GetUserData() != NULL) { if(!m_HandCursor) SetCursor(wxCURSOR_HAND); @@ -195,6 +199,14 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) void wxLayoutWindow::OnChar(wxKeyEvent& event) { +#ifdef WXLAYOUT_DEBUG + if(event.KeyCode() == WXK_F1) + { + m_llist->Debug(); + return; + } +#endif + if(!IsEditable()) // do nothing { event.Skip(); @@ -320,10 +332,17 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) m_ScrollToCursor = true; //DoPaint(true); // paint and scroll to cursor wxRect r = *m_llist->GetUpdateRect(); - r.x -= WXLO_XOFFSET; r.y -= WXLO_YOFFSET; Refresh( FALSE, &r); } +void +wxLayoutWindow::OnKeyUp(wxKeyEvent& event) +{ + if(event.KeyCode() == WXK_SHIFT && m_llist->IsSelecting()) + m_llist->EndSelection(); + event.Skip(); +} + void wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc) { @@ -364,10 +383,10 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) if(y1 > m_maxy) m_maxy = y1; - m_llist->InvalidateUpdateRect(); - const wxRect *r = m_llist->GetUpdateRect(); - wxLogDebug("Update rect before calling Layout: %ld,%ld / %ld,%ld", - r->x, r->y, r->x+r->width, r->y+r->height); + //m_llist->InvalidateUpdateRect(); + //const wxRect *r = m_llist->GetUpdateRect(); + wxLogDebug("Update rect: %ld,%ld / %ld,%ld", + updateRect->x, updateRect->y, updateRect->x+updateRect->width, updateRect->y+updateRect->height); #if 0 //FIXME: we should never need to call Layout at all because the @@ -418,6 +437,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) m_bitmap = new wxBitmap(x1,y1); m_memDC->SelectObject(*m_bitmap); } + // Device origins on the memDC are suspect, we translate manually // with the translate parameter of Draw(). m_memDC->SetDeviceOrigin(0,0); @@ -438,13 +458,16 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) else m_memDC->DrawRectangle(0,0,x1, y1); - // The offsets give the window a tiny border on the left and top, looks nice. + + + /* This is the important bit: we tell the list to draw itself: */ + wxLogDebug("Update rect: %ld,%ld / %ld,%ld", + updateRect->x, updateRect->y, updateRect->x+updateRect->width, updateRect->y+updateRect->height); + wxPoint offset(-x0+WXLO_XOFFSET,-y0+WXLO_YOFFSET); - m_llist->Draw(*m_memDC,offset); - if(IsEditable()) - m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset); + m_llist->Draw(*m_memDC,offset, y0, y0+y1); - // Now copy everything to the screen: +// Now copy everything to the screen: #if 0 //FIXME: // 1. the update region as calculated by the list is wrong @@ -462,15 +485,24 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) } else #endif - // If there are no update rectangles, we got called to reflect - // a change in the list. Currently there is no mechanism to - // easily find out which bits need updating, so we update - // all. The wxLayoutList could handle this, creating a list or - // at least one large rectangle of changes. FIXME + { + // FIXME: Trying to copy only the changed parts, but it does not seem + // to work: +// x0 = updateRect->x; y0 = updateRect->y; +// if(updateRect->height < y1) +// y1 = updateRect->height; +// y1 += WXLO_YOFFSET; //FIXME might not be needed dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE); + } + //FIXME: we need to make sure we blit draw the cursor! + // How about drawing it directly to the screen? + if(IsEditable()) + //m_llist->DrawCursor(*m_memDC,m_HaveFocus,offset); + m_llist->DrawCursor(dc,m_HaveFocus, wxPoint(WXLO_XOFFSET,WXLO_YOFFSET)); //direct to screen ResetDirty(); m_ScrollToCursor = false; + m_llist->InvalidateUpdateRect(); } // change the range and position of scroll bars @@ -510,11 +542,6 @@ wxLayoutWindow::Paste(void) } wxTheClipboard->Close(); } -#ifdef __WXGTK__ - /* wxGTK's sophisticated multi-format copy/paste is not supported - by 99% of the X11 clients available. If there was no selection, - do the dumb thing, too: - */ #if 0 /* Unfortunately, this little hack doesn't work. So I'll go back to pure X11. */ @@ -524,8 +551,6 @@ wxLayoutWindow::Paste(void) tmp_tctrl.Paste(); text += tmp_tctrl.GetValue(); } -#endif - #endif wxLayoutImportText( m_llist, text); } diff --git a/user/wxLayout/wxlwindow.h b/user/wxLayout/wxlwindow.h index 0cce930123..ff019ed254 100644 --- a/user/wxLayout/wxlwindow.h +++ b/user/wxLayout/wxlwindow.h @@ -128,6 +128,7 @@ public: //@{ void OnPaint(wxPaintEvent &event); void OnChar(wxKeyEvent& event); + void OnKeyUp(wxKeyEvent& event); void OnMenu(wxCommandEvent& event); void OnLeftMouseClick(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_LCLICK, event); } void OnRightMouseClick(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_RCLICK, event); } -- 2.47.2