more work on text selection: selecting should work now, but there's no clipboard interaction yet
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@20849 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -101,8 +101,9 @@ private:
|
||||
// Flags for wxHtmlCell::FindCellByPos
|
||||
enum
|
||||
{
|
||||
wxHTML_FIND_TERMINAL = 0x0001,
|
||||
wxHTML_FIND_NONTERMINAL = 0x0002
|
||||
wxHTML_FIND_EXACT = 1,
|
||||
wxHTML_FIND_NEAREST_BEFORE = 2,
|
||||
wxHTML_FIND_NEAREST_AFTER = 4,
|
||||
};
|
||||
|
||||
|
||||
@@ -216,7 +217,17 @@ public:
|
||||
// nonterminal cells or both. In either case, returned cell is deepest
|
||||
// cell in cells tree that contains [x,y].
|
||||
virtual wxHtmlCell *FindCellByPos(wxCoord x, wxCoord y,
|
||||
unsigned flags = wxHTML_FIND_TERMINAL) const;
|
||||
unsigned flags = wxHTML_FIND_EXACT) const;
|
||||
|
||||
// Returns absolute position of the cell on HTML canvas
|
||||
wxPoint GetAbsPos() const;
|
||||
|
||||
// Returns first (last) terminal cell inside this cell. It may return NULL,
|
||||
// but it is rare -- only if there are no terminals in the tree.
|
||||
virtual wxHtmlCell *GetFirstTerminal() const
|
||||
{ return wxConstCast(this, wxHtmlCell); }
|
||||
virtual wxHtmlCell *GetLastTerminal() const
|
||||
{ return wxConstCast(this, wxHtmlCell); }
|
||||
|
||||
protected:
|
||||
wxHtmlCell *m_Next;
|
||||
@@ -325,7 +336,10 @@ public:
|
||||
virtual bool IsTerminalCell() const { return FALSE; }
|
||||
|
||||
virtual wxHtmlCell *FindCellByPos(wxCoord x, wxCoord y,
|
||||
unsigned flags = wxHTML_FIND_TERMINAL) const;
|
||||
unsigned flags = wxHTML_FIND_EXACT) const;
|
||||
|
||||
virtual wxHtmlCell *GetFirstTerminal() const;
|
||||
virtual wxHtmlCell *GetLastTerminal() const;
|
||||
|
||||
protected:
|
||||
void UpdateRenderingStatePre(wxHtmlRenderingState& state,
|
||||
|
@@ -210,7 +210,8 @@ protected:
|
||||
void OnDraw(wxDC& dc);
|
||||
void OnSize(wxSizeEvent& event);
|
||||
void OnMouseMove(wxMouseEvent& event);
|
||||
void OnMouseButton(wxMouseEvent& event);
|
||||
void OnMouseDown(wxMouseEvent& event);
|
||||
void OnMouseUp(wxMouseEvent& event);
|
||||
void OnIdle(wxIdleEvent& event);
|
||||
|
||||
// Returns new filter (will be stored into m_DefaultFilter variable)
|
||||
@@ -252,7 +253,17 @@ protected:
|
||||
|
||||
int m_Style;
|
||||
|
||||
// current text selection or NULL
|
||||
wxHtmlSelection *m_selection;
|
||||
|
||||
// true if the user is dragging mouse to select text
|
||||
bool m_makingSelection;
|
||||
|
||||
private:
|
||||
// variables used when user is selecting text
|
||||
wxPoint m_tmpSelFromPos;
|
||||
wxHtmlCell *m_tmpSelFromCell;
|
||||
|
||||
// a flag indicated if mouse moved
|
||||
// (if TRUE we will try to change cursor in last call to OnIdle)
|
||||
bool m_tmpMouseMoved;
|
||||
|
@@ -113,7 +113,9 @@ class wxHtmlHelpHtmlWindow : public wxHtmlWindow
|
||||
virtual void OnLinkClicked(const wxHtmlLinkInfo& link)
|
||||
{
|
||||
wxHtmlWindow::OnLinkClicked(link);
|
||||
m_Frame->NotifyPageChanged();
|
||||
const wxMouseEvent *e = link.GetEvent();
|
||||
if (e == NULL || e->LeftUp())
|
||||
m_Frame->NotifyPageChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -119,12 +119,33 @@ const wxHtmlCell* wxHtmlCell::Find(int WXUNUSED(condition), const void* WXUNUSED
|
||||
wxHtmlCell *wxHtmlCell::FindCellByPos(wxCoord x, wxCoord y,
|
||||
unsigned flags) const
|
||||
{
|
||||
if ( (flags & wxHTML_FIND_TERMINAL) &&
|
||||
x >= 0 && x < m_Width && y >= 0 && y < m_Height )
|
||||
if ( x >= 0 && x < m_Width && y >= 0 && y < m_Height )
|
||||
{
|
||||
return wxConstCast(this, wxHtmlCell);
|
||||
}
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
if ((flags & wxHTML_FIND_NEAREST_AFTER) &&
|
||||
(y < 0 || (y == 0 && x <= 0)))
|
||||
return wxConstCast(this, wxHtmlCell);
|
||||
else if ((flags & wxHTML_FIND_NEAREST_BEFORE) &&
|
||||
(y > m_Height-1 || (y == m_Height-1 && x >= m_Width)))
|
||||
return wxConstCast(this, wxHtmlCell);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxPoint wxHtmlCell::GetAbsPos() const
|
||||
{
|
||||
wxPoint p(m_PosX, m_PosY);
|
||||
for (wxHtmlCell *parent = m_Parent; parent; parent = parent->m_Parent)
|
||||
{
|
||||
p.x += parent->m_PosX;
|
||||
p.y += parent->m_PosY;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +166,7 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingState& state)
|
||||
{
|
||||
if (state.GetSelectionState() == wxHTML_SEL_IN &&
|
||||
if (state.GetSelectionState() != wxHTML_SEL_OUT &&
|
||||
dc.GetBackgroundMode() != wxSOLID)
|
||||
{
|
||||
dc.SetBackgroundMode(wxSOLID);
|
||||
@@ -440,10 +461,10 @@ void wxHtmlContainerCell::UpdateRenderingStatePost(wxHtmlRenderingState& state,
|
||||
{
|
||||
wxHtmlSelection *s = state.GetSelection();
|
||||
if (!s) return;
|
||||
if (s->GetFromCell() == cell)
|
||||
state.SetSelectionState(wxHTML_SEL_IN);
|
||||
else if (s->GetToCell() == cell)
|
||||
if (s->GetToCell() == cell)
|
||||
state.SetSelectionState(wxHTML_SEL_OUT);
|
||||
else if (s->GetFromCell() == cell)
|
||||
state.SetSelectionState(wxHTML_SEL_IN);
|
||||
}
|
||||
|
||||
#define mMin(a, b) (((a) < (b)) ? (a) : (b))
|
||||
@@ -616,24 +637,53 @@ const wxHtmlCell* wxHtmlContainerCell::Find(int condition, const void* param) co
|
||||
wxHtmlCell *wxHtmlContainerCell::FindCellByPos(wxCoord x, wxCoord y,
|
||||
unsigned flags) const
|
||||
{
|
||||
for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
|
||||
if (flags & wxHTML_FIND_EXACT)
|
||||
{
|
||||
int cx = cell->GetPosX(),
|
||||
cy = cell->GetPosY();
|
||||
|
||||
if ( (cx <= x) && (cx + cell->GetWidth() > x) &&
|
||||
(cy <= y) && (cy + cell->GetHeight() > y) )
|
||||
for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
|
||||
{
|
||||
wxHtmlCell *c = cell->FindCellByPos(x - cx, y - cy, flags);
|
||||
if (c == NULL && (flags & wxHTML_FIND_NONTERMINAL))
|
||||
return wxConstCast(this, wxHtmlContainerCell);
|
||||
else
|
||||
return c;
|
||||
int cx = cell->GetPosX(),
|
||||
cy = cell->GetPosY();
|
||||
|
||||
if ( (cx <= x) && (cx + cell->GetWidth() > x) &&
|
||||
(cy <= y) && (cy + cell->GetHeight() > y) )
|
||||
{
|
||||
return cell->FindCellByPos(x - cx, y - cy, flags);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (flags & wxHTML_FIND_NONTERMINAL) ?
|
||||
wxConstCast(this, wxHtmlContainerCell) : NULL;
|
||||
if ( flags & wxHTML_FIND_NEAREST_AFTER )
|
||||
{
|
||||
wxHtmlCell *c;
|
||||
int y2;
|
||||
for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
|
||||
{
|
||||
y2 = cell->GetPosY() + cell->GetHeight() - 1;
|
||||
if (y2 < y || (y2 == y && cell->GetPosX()+cell->GetWidth()-1 < x))
|
||||
continue;
|
||||
c = cell->FindCellByPos(x - cell->GetPosX(), y - cell->GetPosY(),
|
||||
flags);
|
||||
if (c) return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( flags & wxHTML_FIND_NEAREST_BEFORE )
|
||||
{
|
||||
wxHtmlCell *c = NULL;
|
||||
wxHtmlCell *cx;
|
||||
for ( const wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext() )
|
||||
{
|
||||
if (cell->GetPosY() > y ||
|
||||
(cell->GetPosY() == y && cell->GetPosX() > x))
|
||||
break;
|
||||
cx = cell->FindCellByPos(x - cell->GetPosX(), y - cell->GetPosY(),
|
||||
flags);
|
||||
if (cx) c = cx;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -669,6 +719,26 @@ void wxHtmlContainerCell::GetHorizontalConstraints(int *left, int *right) const
|
||||
*right = cright;
|
||||
}
|
||||
|
||||
|
||||
wxHtmlCell *wxHtmlContainerCell::GetFirstTerminal() const
|
||||
{
|
||||
if (m_Cells)
|
||||
return m_Cells->GetFirstTerminal();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wxHtmlCell *wxHtmlContainerCell::GetLastTerminal() const
|
||||
{
|
||||
if (m_Cells)
|
||||
{
|
||||
wxHtmlCell *c;
|
||||
for (c = m_Cells; c->GetNext(); c = c->GetNext()) {}
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -92,6 +92,8 @@ void wxHtmlWindow::Init()
|
||||
m_Processors = NULL;
|
||||
m_Style = 0;
|
||||
SetBorders(10);
|
||||
m_selection = NULL;
|
||||
m_makingSelection = false;
|
||||
}
|
||||
|
||||
bool wxHtmlWindow::Create(wxWindow *parent, wxWindowID id,
|
||||
@@ -153,6 +155,8 @@ bool wxHtmlWindow::SetPage(const wxString& source)
|
||||
{
|
||||
wxString newsrc(source);
|
||||
|
||||
wxDELETE(m_selection);
|
||||
|
||||
// pass HTML through registered processors:
|
||||
if (m_Processors || m_GlobalProcessors)
|
||||
{
|
||||
@@ -665,7 +669,7 @@ void wxHtmlWindow::OnDraw(wxDC& dc)
|
||||
dc.SetBackgroundMode(wxTRANSPARENT);
|
||||
GetViewStart(&x, &y);
|
||||
|
||||
wxHtmlRenderingState rstate(NULL);
|
||||
wxHtmlRenderingState rstate(m_selection);
|
||||
m_Cell->Draw(dc, 0, 0,
|
||||
y * wxHTML_SCROLL_STEP + rect.GetTop(),
|
||||
y * wxHTML_SCROLL_STEP + rect.GetBottom(),
|
||||
@@ -688,20 +692,44 @@ void wxHtmlWindow::OnMouseMove(wxMouseEvent& event)
|
||||
m_tmpMouseMoved = true;
|
||||
}
|
||||
|
||||
void wxHtmlWindow::OnMouseButton(wxMouseEvent& event)
|
||||
void wxHtmlWindow::OnMouseDown(wxMouseEvent& event)
|
||||
{
|
||||
if ( event.LeftDown() && IsSelectionEnabled() )
|
||||
{
|
||||
m_makingSelection = true;
|
||||
|
||||
if ( m_selection )
|
||||
{
|
||||
wxDELETE(m_selection);
|
||||
Refresh();
|
||||
}
|
||||
m_tmpSelFromPos = CalcUnscrolledPosition(event.GetPosition());
|
||||
m_tmpSelFromCell = NULL;
|
||||
|
||||
CaptureMouse();
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
|
||||
{
|
||||
if ( m_makingSelection )
|
||||
{
|
||||
ReleaseMouse();
|
||||
m_makingSelection = false;
|
||||
|
||||
// did the user move the mouse far enough from starting point?
|
||||
if ( m_selection )
|
||||
{
|
||||
// we don't want mouse up event that ended selecting to be
|
||||
// handled as mouse click and e.g. follow hyperlink:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetFocus();
|
||||
if ( m_Cell )
|
||||
{
|
||||
int sx, sy;
|
||||
GetViewStart(&sx, &sy);
|
||||
sx *= wxHTML_SCROLL_STEP;
|
||||
sy *= wxHTML_SCROLL_STEP;
|
||||
|
||||
wxPoint pos = event.GetPosition();
|
||||
pos.x += sx;
|
||||
pos.y += sy;
|
||||
|
||||
wxPoint pos = CalcUnscrolledPosition(event.GetPosition());
|
||||
wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
|
||||
|
||||
// VZ: is it possible that we don't find anything at all?
|
||||
@@ -724,18 +752,90 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event))
|
||||
|
||||
if (m_tmpMouseMoved && (m_Cell != NULL))
|
||||
{
|
||||
int sx, sy;
|
||||
GetViewStart(&sx, &sy);
|
||||
sx *= wxHTML_SCROLL_STEP;
|
||||
sy *= wxHTML_SCROLL_STEP;
|
||||
|
||||
int x, y;
|
||||
wxGetMousePosition(&x, &y);
|
||||
ScreenToClient(&x, &y);
|
||||
x += sx;
|
||||
y += sy;
|
||||
int xc, yc, x, y;
|
||||
wxGetMousePosition(&xc, &yc);
|
||||
ScreenToClient(&xc, &yc);
|
||||
CalcUnscrolledPosition(xc, yc, &x, &y);
|
||||
|
||||
wxHtmlCell *cell = m_Cell->FindCellByPos(x, y);
|
||||
|
||||
// handle selection update:
|
||||
if ( m_makingSelection )
|
||||
{
|
||||
bool goingDown = m_tmpSelFromPos.y < y ||
|
||||
m_tmpSelFromPos.y == y && m_tmpSelFromPos.x < x;
|
||||
|
||||
if ( !m_tmpSelFromCell )
|
||||
{
|
||||
if (goingDown)
|
||||
{
|
||||
m_tmpSelFromCell = m_Cell->FindCellByPos(x, y,
|
||||
wxHTML_FIND_NEAREST_BEFORE);
|
||||
if (!m_tmpSelFromCell)
|
||||
m_tmpSelFromCell = m_Cell->GetFirstTerminal();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tmpSelFromCell = m_Cell->FindCellByPos(x, y,
|
||||
wxHTML_FIND_NEAREST_AFTER);
|
||||
if (!m_tmpSelFromCell)
|
||||
m_tmpSelFromCell = m_Cell->GetLastTerminal();
|
||||
}
|
||||
}
|
||||
|
||||
wxHtmlCell *selcell = cell;
|
||||
if (!selcell)
|
||||
{
|
||||
if (goingDown)
|
||||
{
|
||||
selcell = m_Cell->FindCellByPos(x, y,
|
||||
wxHTML_FIND_NEAREST_AFTER);
|
||||
if (!selcell)
|
||||
selcell = m_Cell->GetLastTerminal();
|
||||
}
|
||||
else
|
||||
{
|
||||
selcell = m_Cell->FindCellByPos(x, y,
|
||||
wxHTML_FIND_NEAREST_BEFORE);
|
||||
if (!selcell)
|
||||
selcell = m_Cell->GetFirstTerminal();
|
||||
}
|
||||
}
|
||||
|
||||
// NB: it may *rarely* happen that the code above didn't find one
|
||||
// of the cells, e.g. if wxHtmlWindow doesn't contain any
|
||||
// visible cells.
|
||||
if ( selcell && m_tmpSelFromCell )
|
||||
{
|
||||
if ( !m_selection )
|
||||
{
|
||||
// start selecting only if mouse movement was big enough
|
||||
// (otherwise it was meant as mouse click, not selection):
|
||||
const int PRECISION = 2;
|
||||
wxPoint diff = m_tmpSelFromPos - wxPoint(x,y);
|
||||
if (abs(diff.x) > PRECISION || abs(diff.y) > PRECISION)
|
||||
{
|
||||
m_selection = new wxHtmlSelection();
|
||||
}
|
||||
}
|
||||
if ( m_selection )
|
||||
{
|
||||
if (goingDown)
|
||||
{
|
||||
m_selection->Set(m_tmpSelFromPos, m_tmpSelFromCell,
|
||||
wxPoint(x,y), selcell);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_selection->Set(wxPoint(x,y), selcell,
|
||||
m_tmpSelFromPos, m_tmpSelFromCell);
|
||||
}
|
||||
Refresh(); // FIXME - optimize!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle cursor and status bar text changes:
|
||||
if ( cell != m_tmpLastCell )
|
||||
{
|
||||
wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL;
|
||||
@@ -776,8 +876,9 @@ IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
|
||||
EVT_SIZE(wxHtmlWindow::OnSize)
|
||||
EVT_LEFT_UP(wxHtmlWindow::OnMouseButton)
|
||||
EVT_RIGHT_UP(wxHtmlWindow::OnMouseButton)
|
||||
EVT_LEFT_DOWN(wxHtmlWindow::OnMouseDown)
|
||||
EVT_LEFT_UP(wxHtmlWindow::OnMouseUp)
|
||||
EVT_RIGHT_UP(wxHtmlWindow::OnMouseUp)
|
||||
EVT_MOTION(wxHtmlWindow::OnMouseMove)
|
||||
EVT_IDLE(wxHtmlWindow::OnIdle)
|
||||
END_EVENT_TABLE()
|
||||
|
Reference in New Issue
Block a user