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:
Václav Slavík
2003-06-04 18:17:04 +00:00
parent 8ca3dfcdfa
commit 1338c59a02
4 changed files with 252 additions and 33 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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