m_fromPrivPos(wxDefaultPosition), m_toPrivPos(wxDefaultPosition),
m_fromCell(NULL), m_toCell(NULL) {}
- void Set(const wxPoint& fromPos, wxHtmlCell *fromCell,
- const wxPoint& toPos, wxHtmlCell *toCell);
- void Set(wxHtmlCell *fromCell, wxHtmlCell *toCell);
+ void Set(const wxPoint& fromPos, const wxHtmlCell *fromCell,
+ const wxPoint& toPos, const wxHtmlCell *toCell);
+ void Set(const wxHtmlCell *fromCell, const wxHtmlCell *toCell);
const wxHtmlCell *GetFromCell() const { return m_fromCell; }
const wxHtmlCell *GetToCell() const { return m_toCell; }
const wxPoint& GetToPrivPos() const { return m_toPrivPos; }
void SetFromPrivPos(const wxPoint& pos) { m_fromPrivPos = pos; }
void SetToPrivPos(const wxPoint& pos) { m_toPrivPos = pos; }
+ void ClearPrivPos() { m_toPrivPos = m_fromPrivPos = wxDefaultPosition; }
const bool IsEmpty() const
{ return m_fromPos == wxDefaultPosition &&
private:
wxPoint m_fromPos, m_toPos;
wxPoint m_fromPrivPos, m_toPrivPos;
- wxHtmlCell *m_fromCell, *m_toCell;
+ const wxHtmlCell *m_fromCell, *m_toCell;
};
{
wxHTML_FIND_EXACT = 1,
wxHTML_FIND_NEAREST_BEFORE = 2,
- wxHTML_FIND_NEAREST_AFTER = 4,
+ wxHTML_FIND_NEAREST_AFTER = 4
};
// cells (= as they are read). If cell A is (grand)parent of cell B,
// then both A.IsBefore(B) and B.IsBefore(A) always return true.
bool IsBefore(wxHtmlCell *cell) const;
-
- // Sets cell's private position values in wxHtmlSelection
- virtual void SetSelectionPrivPos(wxDC& dc, wxHtmlSelection *s) const {}
-
+
// Converts the cell into text representation. If sel != NULL then
// only part of the cell inside the selection is converted.
virtual wxString ConvertToText(wxHtmlSelection *WXUNUSED(sel)) const
void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
wxHtmlRenderingInfo& info);
wxString ConvertToText(wxHtmlSelection *sel) const;
- void SetSelectionPrivPos(wxDC& dc, wxHtmlSelection *s) const;
protected:
+ void SetSelectionPrivPos(wxDC& dc, wxHtmlSelection *s) const;
void Split(wxDC& dc,
const wxPoint& selFrom, const wxPoint& selTo,
unsigned& pos1, unsigned& pos2) const;
class wxHtmlWinModule;
class wxHtmlHistoryArray;
class wxHtmlProcessorList;
+class WXDLLEXPORT wxHtmlWinAutoScrollTimer;
// wxHtmlWindow flags:
// actual size of window. This method also setup scrollbars
void CreateLayout();
- void OnDraw(wxDC& dc);
+ void OnEraseBackground(wxEraseEvent& event);
+ void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
void OnMouseMove(wxMouseEvent& event);
void OnMouseDown(wxMouseEvent& event);
#if wxUSE_CLIPBOARD
void OnKeyUp(wxKeyEvent& event);
void OnCopy(wxCommandEvent& event);
+ void OnMouseEnter(wxMouseEvent& event);
+ void OnMouseLeave(wxMouseEvent& event);
#endif
// Returns new filter (will be stored into m_DefaultFilter variable)
// and wxHW_NO_SELECTION not used)
bool IsSelectionEnabled() const;
+#if wxUSE_CLIPBOARD
// Convert selection to text:
wxString SelectionToText();
// Copies selection to clipboard:
void CopySelection(ClipboardType t = Secondary);
+ void StopAutoScrolling();
+#endif
protected:
- // This is pointer to the first cell in parsed data.
- // (Note: the first cell is usually top one = all other cells are sub-cells of this one)
+ // This is pointer to the first cell in parsed data. (Note: the first cell
+ // is usually top one = all other cells are sub-cells of this one)
wxHtmlContainerCell *m_Cell;
// parser which is used to parse HTML input.
// Each wxHtmlWindow has it's own parser because sharing one global
// true if the user is dragging mouse to select text
bool m_makingSelection;
+#if wxUSE_CLIPBOARD
+ wxHtmlWinAutoScrollTimer *m_timerAutoScroll;
+#endif
+
private:
+ // window content for double buffered rendering:
+ wxBitmap *m_backBuffer;
+
// variables used when user is selecting text
wxPoint m_tmpSelFromPos;
wxHtmlCell *m_tmpSelFromCell;
// Helper classes
//-----------------------------------------------------------------------------
-void wxHtmlSelection::Set(const wxPoint& fromPos, wxHtmlCell *fromCell,
- const wxPoint& toPos, wxHtmlCell *toCell)
+void wxHtmlSelection::Set(const wxPoint& fromPos, const wxHtmlCell *fromCell,
+ const wxPoint& toPos, const wxHtmlCell *toCell)
{
m_fromCell = fromCell;
m_toCell = toCell;
m_toPos = toPos;
}
-void wxHtmlSelection::Set(wxHtmlCell *fromCell, wxHtmlCell *toCell)
+void wxHtmlSelection::Set(const wxHtmlCell *fromCell, const wxHtmlCell *toCell)
{
wxPoint p1 = fromCell ? fromCell->GetAbsPos() : wxDefaultPosition;
wxPoint p2 = toCell ? toCell->GetAbsPos() : wxDefaultPosition;
// Splits m_Word into up to three parts according to selection, returns
// substring before, in and after selection and the points (in relative coords)
// where s2 and s3 start:
-void wxHtmlWordCell::Split(wxDC& dc,
+void wxHtmlWordCell::Split(wxDC& dc,
const wxPoint& selFrom, const wxPoint& selTo,
unsigned& pos1, unsigned& pos2) const
{
wxPoint priv = (this == s->GetFromCell()) ?
s->GetFromPrivPos() : s->GetToPrivPos();
+
+ // NB: this is quite a hack: in order to compute selection boundaries
+ // (in word's characters) we must know current font, which is only
+ // possible inside rendering code. Therefore we update the
+ // information here and store it in wxHtmlSelection so that
+ // ConvertToText can use it later:
+ if ( priv == wxDefaultPosition )
+ {
+ SetSelectionPrivPos(dc, s);
+ priv = (this == s->GetFromCell()) ?
+ s->GetFromPrivPos() : s->GetToPrivPos();
+ }
+
int part1 = priv.x;
int part2 = priv.y;
#include "wx/html/htmlproc.h"
#include "wx/list.h"
#include "wx/clipbrd.h"
+#include "wx/timer.h"
+#include "wx/dcmemory.h"
#include "wx/arrimpl.cpp"
#include "wx/listimpl.cpp"
+
+
+#if wxUSE_CLIPBOARD
+// ----------------------------------------------------------------------------
+// wxHtmlWinAutoScrollTimer: the timer used to generate a stream of scroll
+// events when a captured mouse is held outside the window
+// ----------------------------------------------------------------------------
+
+class wxHtmlWinAutoScrollTimer : public wxTimer
+{
+public:
+ wxHtmlWinAutoScrollTimer(wxScrolledWindow *win,
+ wxEventType eventTypeToSend,
+ int pos, int orient)
+ {
+ m_win = win;
+ m_eventType = eventTypeToSend;
+ m_pos = pos;
+ m_orient = orient;
+ }
+
+ virtual void Notify();
+
+private:
+ wxScrolledWindow *m_win;
+ wxEventType m_eventType;
+ int m_pos,
+ m_orient;
+
+ DECLARE_NO_COPY_CLASS(wxHtmlWinAutoScrollTimer)
+};
+
+void wxHtmlWinAutoScrollTimer::Notify()
+{
+ // only do all this as long as the window is capturing the mouse
+ if ( wxWindow::GetCapture() != m_win )
+ {
+ Stop();
+ }
+ else // we still capture the mouse, continue generating events
+ {
+ // first scroll the window if we are allowed to do it
+ wxScrollWinEvent event1(m_eventType, m_pos, m_orient);
+ event1.SetEventObject(m_win);
+ if ( m_win->GetEventHandler()->ProcessEvent(event1) )
+ {
+ // and then send a pseudo mouse-move event to refresh the selection
+ wxMouseEvent event2(wxEVT_MOTION);
+ wxGetMousePosition(&event2.m_x, &event2.m_y);
+
+ // the mouse event coordinates should be client, not screen as
+ // returned by wxGetMousePosition
+ wxWindow *parentTop = m_win;
+ while ( parentTop->GetParent() )
+ parentTop = parentTop->GetParent();
+ wxPoint ptOrig = parentTop->GetPosition();
+ event2.m_x -= ptOrig.x;
+ event2.m_y -= ptOrig.y;
+
+ event2.SetEventObject(m_win);
+
+ // FIXME: we don't fill in the other members - ok?
+ m_win->GetEventHandler()->ProcessEvent(event2);
+ }
+ else // can't scroll further, stop
+ {
+ Stop();
+ }
+ }
+}
+#endif
+
+
+
//-----------------------------------------------------------------------------
// wxHtmlHistoryItem
//-----------------------------------------------------------------------------
SetBorders(10);
m_selection = NULL;
m_makingSelection = false;
+#if wxUSE_CLIPBOARD
+ m_timerAutoScroll = NULL;
+#endif
+ m_backBuffer = NULL;
}
bool wxHtmlWindow::Create(wxWindow *parent, wxWindowID id,
wxHtmlWindow::~wxHtmlWindow()
{
+#if wxUSE_CLIPBOARD
+ StopAutoScrolling();
+#endif
HistoryClear();
if (m_Cell) delete m_Cell;
delete m_FS;
delete m_History;
delete m_Processors;
+ delete m_backBuffer;
}
}
+#if wxUSE_CLIPBOARD
wxString wxHtmlWindow::SelectionToText()
{
if ( !m_selection )
void wxHtmlWindow::CopySelection(ClipboardType t)
{
-#if wxUSE_CLIPBOARD
if ( m_selection )
{
wxTheClipboard->UsePrimarySelection(t == Primary);
_("Copied to clipboard:\"%s\""), txt.c_str());
}
}
-#endif
}
+#endif
void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
// do nothing here
}
-void wxHtmlWindow::OnDraw(wxDC& dc)
+void wxHtmlWindow::OnEraseBackground(wxEraseEvent& event)
+{
+}
+
+void wxHtmlWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
{
+ wxPaintDC dc(this);
+
if (m_tmpCanDrawLocks > 0 || m_Cell == NULL) return;
int x, y;
- wxRect rect = GetUpdateRegion().GetBox();
-
- dc.SetMapMode(wxMM_TEXT);
- dc.SetBackgroundMode(wxTRANSPARENT);
GetViewStart(&x, &y);
-
+ wxRect rect = GetUpdateRegion().GetBox();
+ wxSize sz = GetSize();
+
+ wxMemoryDC dcm;
+ if ( !m_backBuffer )
+ m_backBuffer = new wxBitmap(sz.x, sz.y);
+ dcm.SelectObject(*m_backBuffer);
+ dcm.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
+ dcm.Clear();
+ PrepareDC(dcm);
+ dcm.SetMapMode(wxMM_TEXT);
+ dcm.SetBackgroundMode(wxTRANSPARENT);
+
wxHtmlRenderingInfo rinfo;
wxDefaultHtmlRenderingStyle rstyle;
rinfo.SetSelection(m_selection);
rinfo.SetStyle(&rstyle);
- m_Cell->Draw(dc, 0, 0,
+ m_Cell->Draw(dcm, 0, 0,
y * wxHTML_SCROLL_STEP + rect.GetTop(),
y * wxHTML_SCROLL_STEP + rect.GetBottom(),
rinfo);
+
+ dcm.SetDeviceOrigin(0,0);
+ dc.Blit(0, rect.GetTop(),
+ sz.x, rect.GetBottom() - rect.GetTop() + 1,
+ &dcm,
+ 0, rect.GetTop());
}
void wxHtmlWindow::OnSize(wxSizeEvent& event)
{
+ wxDELETE(m_backBuffer);
+
wxScrolledWindow::OnSize(event);
CreateLayout();
+
+ // Recompute selection if necessary:
+ if ( m_selection )
+ {
+ m_selection->Set(m_selection->GetFromCell(),
+ m_selection->GetToCell());
+ m_selection->ClearPrivPos();
+ }
+
Refresh();
}
void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
{
+#if wxUSE_CLIPBOARD
if ( m_makingSelection )
{
ReleaseMouse();
return;
}
}
+#endif
SetFocus();
if ( m_Cell )
m_selection->Set(wxPoint(x,y), selcell,
m_tmpSelFromPos, m_tmpSelFromCell);
}
- {
- wxClientDC dc(this);
- m_selection->GetFromCell()->SetSelectionPrivPos(
- dc, m_selection);
- m_selection->GetToCell()->SetSelectionPrivPos(
- dc, m_selection);
- }
- Refresh(); // FIXME - optimize!
+ m_selection->ClearPrivPos();
+ Refresh();
}
}
}
}
#if wxUSE_CLIPBOARD
+void wxHtmlWindow::StopAutoScrolling()
+{
+ if ( m_timerAutoScroll )
+ {
+ wxDELETE(m_timerAutoScroll);
+ }
+}
+
+void wxHtmlWindow::OnMouseEnter(wxMouseEvent& event)
+{
+ StopAutoScrolling();
+ event.Skip();
+}
+
+void wxHtmlWindow::OnMouseLeave(wxMouseEvent& event)
+{
+ // don't prevent the usual processing of the event from taking place
+ event.Skip();
+
+ // when a captured mouse leave a scrolled window we start generate
+ // scrolling events to allow, for example, extending selection beyond the
+ // visible area in some controls
+ if ( wxWindow::GetCapture() == this )
+ {
+ // where is the mouse leaving?
+ int pos, orient;
+ wxPoint pt = event.GetPosition();
+ if ( pt.x < 0 )
+ {
+ orient = wxHORIZONTAL;
+ pos = 0;
+ }
+ else if ( pt.y < 0 )
+ {
+ orient = wxVERTICAL;
+ pos = 0;
+ }
+ else // we're lower or to the right of the window
+ {
+ wxSize size = GetClientSize();
+ if ( pt.x > size.x )
+ {
+ orient = wxHORIZONTAL;
+ pos = GetVirtualSize().x / wxHTML_SCROLL_STEP;
+ }
+ else if ( pt.y > size.y )
+ {
+ orient = wxVERTICAL;
+ pos = GetVirtualSize().y / wxHTML_SCROLL_STEP;
+ }
+ else // this should be impossible
+ {
+ // but seems to happen sometimes under wxMSW - maybe it's a bug
+ // there but for now just ignore it
+
+ //wxFAIL_MSG( _T("can't understand where has mouse gone") );
+
+ return;
+ }
+ }
+
+ // only start the auto scroll timer if the window can be scrolled in
+ // this direction
+ if ( !HasScrollbar(orient) )
+ return;
+
+ delete m_timerAutoScroll;
+ m_timerAutoScroll = new wxHtmlWinAutoScrollTimer
+ (
+ this,
+ pos == 0 ? wxEVT_SCROLLWIN_LINEUP
+ : wxEVT_SCROLLWIN_LINEDOWN,
+ pos,
+ orient
+ );
+ m_timerAutoScroll->Start(50); // FIXME: make configurable
+ }
+}
+
void wxHtmlWindow::OnKeyUp(wxKeyEvent& event)
{
if ( event.GetKeyCode() == 'C' && event.ControlDown() )
EVT_RIGHT_UP(wxHtmlWindow::OnMouseUp)
EVT_MOTION(wxHtmlWindow::OnMouseMove)
EVT_IDLE(wxHtmlWindow::OnIdle)
+ EVT_ERASE_BACKGROUND(wxHtmlWindow::OnEraseBackground)
+ EVT_PAINT(wxHtmlWindow::OnPaint)
#if wxUSE_CLIPBOARD
+ EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
+ EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
#endif