- 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:
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 )
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.");
}
}
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;
+ }
}
};
# pragma hdrstop
#endif
-#ifdef M_PREFIX
+#ifdef M_BASEDIR
# include "gui/wxllist.h"
+# include "gui/wxMDialogs.h"
#else
# include "wxllist.h"
#endif
/// 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
}
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);
{
*cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x);
wxLogDebug("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();
}
}
+#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
}
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;
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
}
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;
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;
}
//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;
{
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
{
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
&& 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
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
{
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
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);
*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)
*/
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.
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 */
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();
@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
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.
}
//@}
+ /// 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);
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. */
//@{
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
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
};
# include "gui/wxMenuDefs.h"
# include "gui/wxMApp.h"
# endif // USE_PCH
-
# include "gui/wxlwindow.h"
# include "gui/wxlparser.h"
#else
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)
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);
void
wxLayoutWindow::OnChar(wxKeyEvent& event)
{
+#ifdef WXLAYOUT_DEBUG
+ if(event.KeyCode() == WXK_F1)
+ {
+ m_llist->Debug();
+ return;
+ }
+#endif
+
if(!IsEditable()) // do nothing
{
event.Skip();
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)
{
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
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);
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
}
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
}
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. */
tmp_tctrl.Paste();
text += tmp_tctrl.GetValue();
}
-#endif
-
#endif
wxLayoutImportText( m_llist, text);
}
//@{
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); }