llist->Insert("And here the source for the test program:");
llist->LineBreak();
llist->Insert("And here the source for the test program:");
-#if 0
+
char buffer[1024];
FILE *in = fopen("wxLayout.cpp","r");
if(in)
wxLayoutImportText(llist, buffer);
}
}
-#endif
+
llist->MoveCursorTo(wxPoint(0,0));
m_lwin->SetDirty();
m_lwin->Refresh();
"This is a text\n"
"with embedded line\n"
"breaks.\n");
+ m_lwin->SetDirty();
+ m_lwin->Refresh();
break;
case ID_URL_TEST:
Draw() just draws them with the current settings, without
re-layout()ing them again
- Each line has its own wxLayoutStyleInfo structure which gets updated
- from within Layout(). Thanks to this, we don't need to re-layout all
+ Each line has its own wxLayoutStyleInfo structure which gets updated
+ from within Layout(). Thanks to this, we don't need to re-layout all
lines if we want to draw one, but can just use its styleinfo to set
the right font.
-
+
*/
#ifdef __GNUG__
#define WXLO_CURSORCHAR "E"
/** @name Helper functions */
//@{
+/// 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);
+}
+
/*
The following STAY HERE until we have a working wxGTK again!!!
*/
+#ifdef __WXGTK__
/// allows me to compare to wxPoints
bool operator ==(wxPoint const &p1, wxPoint const &p2)
{
p1.y += p2.y;
return p1;
}
+#endif // wxGTK
/// allows me to compare to wxPoints
-bool operator <=(wxPoint const &p1, wxPoint const &p2)
+bool operator>(wxPoint const &p1, wxPoint const &p2)
{
- return p1.y < p2.y || (p1.y == p2.y && p1.x <= p2.x);
+ return !(p1 <= p2);
}
/// grows a wxRect so that it includes the given point
wxLayoutList *wxllist,
CoordType begin, CoordType end)
{
- if( end <= 0)
+ if( end <= 0 )
+ {
+ // draw the whole object normally
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;
if( end > (signed)m_Text.Length() )
end = m_Text.Length();
- str = m_Text.Mid(0, begin);
+ wxString str = m_Text.Mid(0, begin);
dc.DrawText(str, xpos, ypos);
dc.GetTextExtent(str, &width, &height, &descent);
xpos += width;
// to update their styleinfo structure.
if(obj->GetType() == WXLO_TYPE_CMD)
MarkNextDirty(-1);
-
+
CoordType offset;
wxLOiterator i = FindObject(xpos, &offset);
if(i == NULLIT)
}
/*
- This function does all the recalculation, that is, it should only be
+ This function does all the recalculation, that is, it should only be
called from within wxLayoutList::Layout(), as it uses the current
list's styleinfo and updates it.
*/
bool resetCursorMovedFlag,
const wxPoint& translate)
{
- return;
wxCHECK_RET( m_CursorLine, "no cursor line" );
if ( m_movedCursor )
m_CursorPos.x,
/* suppress update */ true);
ApplyStyle(SiBackup, dc); // restore it
-
+
if ( resetCursorMovedFlag )
{
#ifdef WXLAYOUT_USE_CARET
// This one we always Layout() to get the current cursor
// coordinates on the screen:
m_CursorLine->MarkDirty();
- // FIXME this is completely wrong - we should start by first *visible* line
- // (and stop on the last one) instead of looping over all lines!!
bool wasDirty = false;
wxLayoutLine *line = m_FirstLine;
while(line)
}
void
-wxLayoutList::StartSelection(wxPoint cpos)
+wxLayoutList::StartSelection(const wxPoint& cposOrig, const wxPoint& spos)
{
- if(cpos.x == -1)
+ wxPoint cpos(cposOrig);
+ if ( cpos.x == -1 )
cpos = m_CursorPos;
WXLO_DEBUG(("Starting selection at %ld/%ld", cpos.x, cpos.y));
m_Selection.m_CursorA = cpos;
m_Selection.m_CursorB = cpos;
+ m_Selection.m_ScreenA = spos;
+ m_Selection.m_ScreenB = spos;
m_Selection.m_selecting = true;
m_Selection.m_valid = false;
}
void
-wxLayoutList::ContinueSelection(wxPoint cpos)
+wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos)
{
+ wxPoint cpos(cposOrig);
if(cpos.x == -1)
cpos = m_CursorPos;
+
wxASSERT(m_Selection.m_selecting == true);
wxASSERT(m_Selection.m_valid == false);
WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y));
- if(m_Selection.m_CursorB <= cpos)
+
+ if ( m_Selection.m_CursorB <= cpos )
+ {
+ m_Selection.m_ScreenB = spos;
m_Selection.m_CursorB = cpos;
+ }
else
+ {
+ m_Selection.m_ScreenA = spos;
m_Selection.m_CursorA = cpos;
- // We always want m_CursorA <= m_CursorB!
- if(! (m_Selection.m_CursorA <= m_Selection.m_CursorB))
+ }
+
+ // we always want m_CursorA <= m_CursorB!
+ if( m_Selection.m_CursorA > m_Selection.m_CursorB )
{
+ // exchange the start/end points
wxPoint help = m_Selection.m_CursorB;
m_Selection.m_CursorB = m_Selection.m_CursorA;
m_Selection.m_CursorA = help;
+
+ help = m_Selection.m_ScreenB;
+ m_Selection.m_ScreenB = m_Selection.m_ScreenA;
+ m_Selection.m_ScreenA = help;
}
}
void
-wxLayoutList::EndSelection(wxPoint cpos)
+wxLayoutList::EndSelection(const wxPoint& cposOrig, const wxPoint& spos)
{
+ wxPoint cpos(cposOrig);
if(cpos.x == -1)
cpos = m_CursorPos;
ContinueSelection(cpos);
m_Selection.m_valid = true;
}
+void
+wxLayoutList::DiscardSelection()
+{
+ if ( !HasSelection() )
+ return;
+
+ m_Selection.m_valid =
+ m_Selection.m_selecting = false;
+
+ // invalidate the area which was previousle selected - and which is not
+ // selected any more
+ if ( m_Selection.HasValidScreenCoords() )
+ {
+ SetUpdateRect(m_Selection.m_ScreenA);
+ SetUpdateRect(m_Selection.m_ScreenB);
+ }
+ else
+ {
+ // TODO
+ }
+}
bool
wxLayoutList::IsSelecting(void)
bool
wxLayoutList::IsSelected(const wxPoint &cursor)
{
- if(! m_Selection.m_valid && ! m_Selection.m_selecting)
+ if ( !HasSelection() )
return false;
- return m_Selection.m_CursorA <= cursor
- && cursor <= m_Selection.m_CursorB;
+
+ return m_Selection.m_CursorA <= cursor && cursor <= m_Selection.m_CursorB;
}
}
//@}
- /// Begin selecting text.
- void StartSelection(wxPoint cpos = wxPoint(-1,-1));
+ /// Begin selecting text
+ void StartSelection(const wxPoint& cpos = wxPoint(-1,-1),
+ const wxPoint& spos = wxPoint(-1,-1));
// Continue selecting text
- void ContinueSelection(wxPoint cpos = wxPoint(-1,-1));
+ void ContinueSelection(const wxPoint& cpos = wxPoint(-1,-1),
+ const wxPoint& spos = wxPoint(-1,-1));
/// End selecting text.
- void EndSelection(wxPoint cpos = wxPoint(-1,-1));
+ void EndSelection(const wxPoint& cpos = wxPoint(-1,-1),
+ const wxPoint& spos = wxPoint(-1,-1));
+ /// Discard the current selection
+ void DiscardSelection();
/// Are we still selecting text?
bool IsSelecting(void);
+ /// Is the given point (text coords) selected?
bool IsSelected(const wxPoint &cursor);
+ /// Do we have a non null selection?
+ bool HasSelection() const
+ { return m_Selection.m_valid || m_Selection.m_selecting; }
/** Return the selection as a wxLayoutList.
@param invalidate if true, the selection will be invalidated after this and can no longer be used.
#ifdef WXLAYOUT_DEBUG
void Debug(void);
#endif
+
private:
/// Clear the list.
void InternalClear(void);
#endif // WXLAYOUT_USE_CARET
//@}
- /// A structure for the selection.
+ /// selection.state and begin/end coordinates
struct Selection
{
Selection() { m_valid = false; m_selecting = false; }
bool m_valid;
bool m_selecting;
+
+ // returns true if we already have the screen coordinates of the
+ // selection start and end
+ bool HasValidScreenCoords() const
+ { return m_ScreenA.x != -1 && m_ScreenB.x != -1; }
+
+ // the start and end of the selection coordinates in pixels
+ wxPoint m_ScreenA, m_ScreenB;
+
+ // these coordinates are in text positions, not in pixels
wxPoint m_CursorA, m_CursorB;
} m_Selection;
/** @name Font parameters. */
// ===========================================================================
/* LEAVE IT HERE UNTIL WXGTK WORKS AGAIN!!! */
+#ifdef __WXGTK__
/// allows me to compare to wxPoints
static bool operator != (wxPoint const &p1, wxPoint const &p2)
{
return p1.x != p2.x || p1.y != p2.y;
}
+#endif // __WXGTK__
+
+#ifndef wxWANTS_CHARS
+ #define wxWANTS_CHARS 0
+#endif
// ----------------------------------------------------------------------------
// wxLayoutWindow
: wxScrolledWindow(parent, -1,
wxDefaultPosition, wxDefaultSize,
wxHSCROLL | wxVSCROLL |
- wxBORDER
- //FIXME |wxWANTS_CHARS
- )
+ wxBORDER |
+ wxWANTS_CHARS)
{
SetStatusBar(NULL); // don't use statusbar
m_Editable = false;
{
if(! m_Selecting)
{
- m_llist->StartSelection();
+ m_llist->StartSelection(wxPoint(-1, -1), m_ClickPosition);
m_Selecting = true;
- DoPaint(FALSE);
+ DoPaint(); // TODO: we don't have to redraw everything!
}
else
{
- m_llist->ContinueSelection(cursorPos);
- DoPaint(FALSE);
+ m_llist->ContinueSelection(cursorPos, m_ClickPosition);
+ DoPaint(); // TODO: we don't have to redraw everything!
}
}
if(m_Selecting && ! event.LeftIsDown())
{
- m_llist->EndSelection(cursorPos);
+ m_llist->EndSelection(cursorPos, m_ClickPosition);
m_Selecting = false;
- DoPaint(FALSE);
+ DoPaint(); // TODO: we don't have to redraw everything!
}
- if(u) u->DecRef();
- return;
- }
- // always move cursor to mouse click:
- if(eventId == WXLOWIN_MENU_LCLICK)
+ if ( u )
+ {
+ u->DecRef();
+ u = NULL;
+ }
+ }
+ else if(eventId == WXLOWIN_MENU_LCLICK)
{
+ // always move cursor to mouse click:
m_llist->MoveCursorTo(cursorPos);
+ // clicking a mouse removes the selection
+ if ( m_llist->HasSelection() )
+ {
+ m_llist->DiscardSelection();
+ DoPaint(); // TODO: we don't have to redraw everything!
+ }
+
// Calculate where the top of the visible area is:
int x0, y0;
ViewStart(&x0,&y0);
#endif // 0
#ifdef __WXGTK__
- DoPaint(FALSE); // DoPaint suppresses flicker under GTK
+ DoPaint(); // DoPaint suppresses flicker under GTK
#endif // wxGTK
}
- if(!m_doSendEvents) // nothing to do
+ // notify about mouse events?
+ if( m_doSendEvents )
{
- if(u) u->DecRef();
- return;
- }
+ // only do the menu if activated, editable and not on a clickable object
+ if(eventId == WXLOWIN_MENU_RCLICK
+ && IsEditable()
+ && (! obj || u == NULL))
+ {
+ PopupMenu(m_PopupMenu, m_ClickPosition.x, m_ClickPosition.y);
+ if(u) u->DecRef();
+ return;
+ }
- // only do the menu if activated, editable and not on a clickable object
- if(eventId == WXLOWIN_MENU_RCLICK
- && IsEditable()
- && (! obj || u == NULL))
- {
- PopupMenu(m_PopupMenu, m_ClickPosition.x, m_ClickPosition.y);
- if(u) u->DecRef();
- return;
+ // find the object at this position
+ if(obj)
+ {
+ wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, eventId);
+ commandEvent.SetEventObject( this );
+ commandEvent.SetClientData((char *)obj);
+ GetEventHandler()->ProcessEvent(commandEvent);
+ }
}
- if(u) u->DecRef();
- // find the object at this position
- if(obj)
- {
- wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, eventId);
- commandEvent.SetEventObject( this );
- commandEvent.SetClientData((char *)obj);
- GetEventHandler()->ProcessEvent(commandEvent);
- }
+ if( u )
+ u->DecRef();
}
/*
m_memDC->SetPen(wxPen(m_llist->GetDefaultStyleInfo().GetBGColour(),
0,wxTRANSPARENT));
m_memDC->SetLogicalFunction(wxCOPY);
+ m_memDC->Clear();
- /* Either fill the background with the background bitmap, or clear
- it. */
+ // fill the background with the background bitmap
if(m_BGbitmap)
{
CoordType
m_memDC->DrawBitmap(*m_BGbitmap, x, y);
m_memDC->SetBackgroundMode(wxTRANSPARENT);
}
- else
- {
- // clear the background: (must not be done if we use the update rectangle!)
- m_memDC->SetBackgroundMode(wxSOLID);
- m_memDC->DrawRectangle(0,0,x1, y1);
- }
- m_memDC->Clear();
- /* This is the important bit: we tell the list to draw itself: */
+ // This is the important bit: we tell the list to draw itself
#if WXLO_DEBUG_URECT
if(updateRect)
{
inline int SetCursorVisibility(int visibility = -1)
{ int v =m_CursorVisibility;
m_CursorVisibility = visibility; return v;}
-
+
/// Pastes text from clipboard.
void Paste(void);
/** Copies selection to clipboard.
bool Find(const wxString &needle,
wxPoint * fromWhere = NULL);
-
+
void EnablePopup(bool enable = true) { m_DoPopupMenu = enable; }
/** Sets the wrap margin.
@param margin set this to 0 to disable it
*/
void SetWrapMargin(CoordType margin) { m_WrapMargin = margin; }
-
+
/** Redraws the window.
Internally, this stores the parameter and calls a refresh on
wxMSW, draws directly on wxGTK.
m_StatusBar = bar; m_StatusFieldLabel = labelfield;
m_StatusFieldCursor = cursorfield;
}
-protected:
+
+protected:
/// generic function for mouse events processing
void OnMouse(int eventId, wxMouseEvent& event);
/// as the name says