added selecting-while-dragging
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@20922 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -41,9 +41,9 @@ public:
|
||||
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; }
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
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 &&
|
||||
@@ -65,7 +66,7 @@ public:
|
||||
private:
|
||||
wxPoint m_fromPos, m_toPos;
|
||||
wxPoint m_fromPrivPos, m_toPrivPos;
|
||||
wxHtmlCell *m_fromCell, *m_toCell;
|
||||
const wxHtmlCell *m_fromCell, *m_toCell;
|
||||
};
|
||||
|
||||
|
||||
@@ -144,7 +145,7 @@ enum
|
||||
{
|
||||
wxHTML_FIND_EXACT = 1,
|
||||
wxHTML_FIND_NEAREST_BEFORE = 2,
|
||||
wxHTML_FIND_NEAREST_AFTER = 4,
|
||||
wxHTML_FIND_NEAREST_AFTER = 4
|
||||
};
|
||||
|
||||
|
||||
@@ -283,10 +284,7 @@ public:
|
||||
// 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
|
||||
@@ -332,9 +330,9 @@ public:
|
||||
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;
|
||||
|
@@ -32,6 +32,7 @@ class wxHtmlProcessor;
|
||||
class wxHtmlWinModule;
|
||||
class wxHtmlHistoryArray;
|
||||
class wxHtmlProcessorList;
|
||||
class WXDLLEXPORT wxHtmlWinAutoScrollTimer;
|
||||
|
||||
|
||||
// wxHtmlWindow flags:
|
||||
@@ -207,7 +208,8 @@ protected:
|
||||
// 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);
|
||||
@@ -216,6 +218,8 @@ protected:
|
||||
#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)
|
||||
@@ -228,6 +232,7 @@ protected:
|
||||
// and wxHW_NO_SELECTION not used)
|
||||
bool IsSelectionEnabled() const;
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
// Convert selection to text:
|
||||
wxString SelectionToText();
|
||||
|
||||
@@ -239,10 +244,12 @@ protected:
|
||||
|
||||
// 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
|
||||
@@ -275,7 +282,14 @@ protected:
|
||||
// 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;
|
||||
|
@@ -36,8 +36,8 @@
|
||||
// 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;
|
||||
@@ -45,7 +45,7 @@ void wxHtmlSelection::Set(const wxPoint& fromPos, wxHtmlCell *fromCell,
|
||||
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;
|
||||
@@ -249,7 +249,7 @@ wxHtmlWordCell::wxHtmlWordCell(const wxString& word, wxDC& dc) : wxHtmlCell()
|
||||
// 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
|
||||
{
|
||||
@@ -356,6 +356,19 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -33,10 +33,86 @@
|
||||
#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
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -95,6 +171,10 @@ void wxHtmlWindow::Init()
|
||||
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,
|
||||
@@ -113,6 +193,9 @@ bool wxHtmlWindow::Create(wxWindow *parent, wxWindowID id,
|
||||
|
||||
wxHtmlWindow::~wxHtmlWindow()
|
||||
{
|
||||
#if wxUSE_CLIPBOARD
|
||||
StopAutoScrolling();
|
||||
#endif
|
||||
HistoryClear();
|
||||
|
||||
if (m_Cell) delete m_Cell;
|
||||
@@ -121,6 +204,7 @@ wxHtmlWindow::~wxHtmlWindow()
|
||||
delete m_FS;
|
||||
delete m_History;
|
||||
delete m_Processors;
|
||||
delete m_backBuffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -637,6 +721,7 @@ bool wxHtmlWindow::IsSelectionEnabled() const
|
||||
}
|
||||
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
wxString wxHtmlWindow::SelectionToText()
|
||||
{
|
||||
if ( !m_selection )
|
||||
@@ -666,7 +751,6 @@ wxString wxHtmlWindow::SelectionToText()
|
||||
|
||||
void wxHtmlWindow::CopySelection(ClipboardType t)
|
||||
{
|
||||
#if wxUSE_CLIPBOARD
|
||||
if ( m_selection )
|
||||
{
|
||||
wxTheClipboard->UsePrimarySelection(t == Primary);
|
||||
@@ -679,8 +763,8 @@ void wxHtmlWindow::CopySelection(ClipboardType t)
|
||||
_("Copied to clipboard:\"%s\""), txt.c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
|
||||
@@ -705,25 +789,45 @@ void wxHtmlWindow::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell),
|
||||
// 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -731,8 +835,19 @@ void wxHtmlWindow::OnDraw(wxDC& dc)
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -762,6 +877,7 @@ void wxHtmlWindow::OnMouseDown(wxMouseEvent& event)
|
||||
|
||||
void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
|
||||
{
|
||||
#if wxUSE_CLIPBOARD
|
||||
if ( m_makingSelection )
|
||||
{
|
||||
ReleaseMouse();
|
||||
@@ -778,6 +894,7 @@ void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SetFocus();
|
||||
if ( m_Cell )
|
||||
@@ -884,14 +1001,8 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -931,6 +1042,85 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
|
||||
}
|
||||
|
||||
#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() )
|
||||
@@ -962,7 +1152,11 @@ BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
|
||||
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
|
||||
|
Reference in New Issue
Block a user