X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/36c4ff4d6501712cbc718a6569599f2725db0d2c..4760fa91097407e9967efd21f90ef04d69e5bb9c:/src/html/htmlwin.cpp?ds=inline diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp index 43da986f29..bf886c6bd4 100644 --- a/src/html/htmlwin.cpp +++ b/src/html/htmlwin.cpp @@ -32,6 +32,7 @@ #include "wx/html/htmlwin.h" #include "wx/html/htmlproc.h" #include "wx/list.h" +#include "wx/clipbrd.h" #include "wx/arrimpl.cpp" #include "wx/listimpl.cpp" @@ -92,6 +93,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 +156,8 @@ bool wxHtmlWindow::SetPage(const wxString& source) { wxString newsrc(source); + wxDELETE(m_selection); + // pass HTML through registered processors: if (m_Processors || m_GlobalProcessors) { @@ -630,11 +635,57 @@ bool wxHtmlWindow::IsSelectionEnabled() const return false; #endif } + + +wxString wxHtmlWindow::SelectionToText() +{ + if ( !m_selection ) + return wxEmptyString; + + const wxHtmlCell *end = m_selection->GetToCell(); + wxString text; + wxHtmlTerminalCellsInterator i(m_selection->GetFromCell(), end); + if ( i ) + { + text << i->ConvertToText(m_selection); + ++i; + } + const wxHtmlCell *prev = *i; + while ( i ) + { + if ( prev->GetParent() != i->GetParent() ) + text << _T('\n'); + text << i->ConvertToText(*i == end ? m_selection : NULL); + prev = *i; + ++i; + } + return text; +} + +void wxHtmlWindow::CopySelection(ClipboardType t) +{ +#if wxUSE_CLIPBOARD + if ( m_selection ) + { + wxTheClipboard->UsePrimarySelection(t == Primary); + wxString txt(SelectionToText()); + if ( wxTheClipboard->Open() ) + { + wxTheClipboard->SetData(new wxTextDataObject(txt)); + wxTheClipboard->Close(); + wxLogTrace(_T("wxhtmlselection"), + _("Copied to clipboard:\"%s\""), txt.c_str()); + } + } +#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, @@ -663,12 +714,7 @@ void wxHtmlWindow::OnDraw(wxDC& dc) dc.SetBackgroundMode(wxTRANSPARENT); GetViewStart(&x, &y); - wxHtmlSelection sel; - sel.Set(wxPoint(20,80), - m_Cell->FindCellByPos(20,80,wxHTML_FIND_TERMINAL|wxHTML_FIND_NONTERMINAL), - wxPoint(200,300), - m_Cell->FindCellByPos(200,300,wxHTML_FIND_TERMINAL|wxHTML_FIND_NONTERMINAL)); - wxHtmlRenderingState rstate(IsSelectionEnabled() ? &sel : NULL); + wxHtmlRenderingState rstate(m_selection); m_Cell->Draw(dc, 0, 0, y * wxHTML_SCROLL_STEP + rect.GetTop(), y * wxHTML_SCROLL_STEP + rect.GetBottom(), @@ -686,33 +732,57 @@ void wxHtmlWindow::OnSize(wxSizeEvent& event) } -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); + } } @@ -727,18 +797,93 @@ 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_AFTER); + if (!m_tmpSelFromCell) + m_tmpSelFromCell = m_Cell->GetFirstTerminal(); + } + else + { + m_tmpSelFromCell = m_Cell->FindCellByPos(x, y, + wxHTML_FIND_NEAREST_BEFORE); + 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 ( m_tmpSelFromCell->IsBefore(selcell) ) + { + 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! +#ifdef __UNIX__ + CopySelection(Primary); +#endif + } + } + } + + // handle cursor and status bar text changes: if ( cell != m_tmpLastCell ) { wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL; @@ -772,6 +917,26 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event)) } } +#if wxUSE_CLIPBOARD +void wxHtmlWindow::OnKeyUp(wxKeyEvent& event) +{ + if ( event.GetKeyCode() == 'C' && event.ControlDown() ) + { + if ( m_selection ) + CopySelection(); + } + else + event.Skip(); +} + +void wxHtmlWindow::OnCopy(wxCommandEvent& event) +{ + if ( m_selection ) + CopySelection(); +} +#endif + + IMPLEMENT_ABSTRACT_CLASS(wxHtmlProcessor,wxObject) @@ -779,10 +944,15 @@ IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow) 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) +#if wxUSE_CLIPBOARD + EVT_KEY_UP(wxHtmlWindow::OnKeyUp) + EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy) +#endif END_EVENT_TABLE()