m_Processors = NULL;
m_Style = 0;
SetBorders(10);
+ m_selection = NULL;
+ m_makingSelection = false;
}
bool wxHtmlWindow::Create(wxWindow *parent, wxWindowID id,
{
wxString newsrc(source);
+ wxDELETE(m_selection);
+
// pass HTML through registered processors:
if (m_Processors || m_GlobalProcessors)
{
f = m_Parser->OpenURL(wxHTML_URL_PAGE, location);
+ // try to interpret 'location' as filename instead of URL:
+ if (f == NULL)
+ {
+ wxFileName fn(location);
+ wxString location2 = wxFileSystem::FileNameToURL(fn);
+ f = m_Parser->OpenURL(wxHTML_URL_PAGE, location2);
+ }
+
if (f == NULL)
{
wxLogError(_("Unable to open requested HTML document: %s"), location.c_str());
}
+bool wxHtmlWindow::LoadFile(const wxFileName& filename)
+{
+ wxString url = wxFileSystem::FileNameToURL(filename);
+ return LoadPage(url);
+}
+
bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor)
{
void wxHtmlWindow::CleanUpStatics()
{
- delete m_DefaultFilter;
- m_DefaultFilter = NULL;
+ wxDELETE(m_DefaultFilter);
m_Filters.DeleteContents(TRUE);
m_Filters.Clear();
- delete m_GlobalProcessors;
- m_GlobalProcessors = NULL;
- delete s_cur_hand;
- delete s_cur_arrow;
+ wxDELETE(m_GlobalProcessors);
+ wxDELETE(s_cur_hand);
+ wxDELETE(s_cur_arrow);
}
}
+bool wxHtmlWindow::IsSelectionEnabled() const
+{
+#if wxUSE_CLIPBOARD
+ return !(m_Style & wxHW_NO_SELECTION);
+#else
+ return false;
+#endif
+}
void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
{
- LoadPage(link.GetHref());
+ const wxMouseEvent *e = link.GetEvent();
+ if (e == NULL || e->LeftUp())
+ LoadPage(link.GetHref());
}
void wxHtmlWindow::OnCellClicked(wxHtmlCell *cell,
dc.SetBackgroundMode(wxTRANSPARENT);
GetViewStart(&x, &y);
+ wxHtmlRenderingState rstate(m_selection);
m_Cell->Draw(dc, 0, 0,
y * wxHTML_SCROLL_STEP + rect.GetTop(),
- y * wxHTML_SCROLL_STEP + rect.GetBottom());
+ y * wxHTML_SCROLL_STEP + rect.GetBottom(),
+ rstate);
}
}
-void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event)
+void wxHtmlWindow::OnMouseMove(wxMouseEvent& event)
{
- m_tmpMouseMoved = TRUE;
+ m_tmpMouseMoved = true;
+}
- if (event.ButtonDown())
+void wxHtmlWindow::OnMouseDown(wxMouseEvent& event)
+{
+ if ( event.LeftDown() && IsSelectionEnabled() )
{
- SetFocus();
- if ( m_Cell )
+ m_makingSelection = true;
+
+ if ( m_selection )
{
- int sx, sy;
- GetViewStart(&sx, &sy);
- sx *= wxHTML_SCROLL_STEP;
- sy *= wxHTML_SCROLL_STEP;
+ wxDELETE(m_selection);
+ Refresh();
+ }
+ m_tmpSelFromPos = CalcUnscrolledPosition(event.GetPosition());
+ m_tmpSelFromCell = NULL;
- wxPoint pos = event.GetPosition();
- pos.x += sx;
- pos.y += sy;
+ CaptureMouse();
+ }
+}
- wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
+void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
+{
+ if ( m_makingSelection )
+ {
+ ReleaseMouse();
+ m_makingSelection = false;
- // VZ: is it possible that we don't find anything at all?
- // VS: yes. FindCellByPos returns terminal cell and
- // containers may have empty borders
- if ( cell )
- OnCellClicked(cell, pos.x, pos.y, event);
+ // 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 )
+ {
+ 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?
+ // VS: yes. FindCellByPos returns terminal cell and
+ // containers may have empty borders
+ if ( cell )
+ OnCellClicked(cell, pos.x, pos.y, 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;
BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
EVT_SIZE(wxHtmlWindow::OnSize)
- EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent)
- EVT_RIGHT_DOWN(wxHtmlWindow::OnMouseEvent)
- EVT_MOTION(wxHtmlWindow::OnMouseEvent)
+ 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()