From e37741247336250f4460714baa43b8136cee3b96 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Mon, 2 Jun 2003 21:21:23 +0000 Subject: [PATCH] added copying selection to clipboard; fixes to selection making git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@20861 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/html/htmlcell.cpp | 150 +++++++++++++++++++++++++++++++++++++++--- src/html/htmlwin.cpp | 80 ++++++++++++++++++++-- src/html/m_dflist.cpp | 4 +- src/html/m_fonts.cpp | 2 +- src/html/m_layout.cpp | 10 +-- src/html/m_list.cpp | 2 +- 6 files changed, 225 insertions(+), 23 deletions(-) diff --git a/src/html/htmlcell.cpp b/src/html/htmlcell.cpp index ad79eb042f..c867b38366 100644 --- a/src/html/htmlcell.cpp +++ b/src/html/htmlcell.cpp @@ -32,6 +32,30 @@ #include "wx/settings.h" #include +//----------------------------------------------------------------------------- +// Helper classes +//----------------------------------------------------------------------------- + +void wxHtmlSelection::Set(const wxPoint& fromPos, wxHtmlCell *fromCell, + const wxPoint& toPos, wxHtmlCell *toCell) +{ + m_fromCell = fromCell; + m_toCell = toCell; + m_fromPos = fromPos; + m_toPos = toPos; +} + +void wxHtmlSelection::Set(wxHtmlCell *fromCell, wxHtmlCell *toCell) +{ + wxPoint p1 = fromCell ? fromCell->GetAbsPos() : wxDefaultPosition; + wxPoint p2 = toCell ? toCell->GetAbsPos() : wxDefaultPosition; + if ( toCell ) + { + p2.x += toCell->GetWidth()-1; + p2.y += toCell->GetHeight()-1; + } + Set(p1, fromCell, p2, toCell); +} //----------------------------------------------------------------------------- // wxHtmlCell @@ -147,6 +171,54 @@ wxPoint wxHtmlCell::GetAbsPos() const } return p; } + +unsigned wxHtmlCell::GetDepth() const +{ + unsigned d = 0; + for (wxHtmlCell *p = m_Parent; p; p = p->m_Parent) + d++; + return d; +} + +bool wxHtmlCell::IsBefore(wxHtmlCell *cell) const +{ + const wxHtmlCell *c1 = this; + const wxHtmlCell *c2 = cell; + unsigned d1 = GetDepth(); + unsigned d2 = cell->GetDepth(); + + if ( d1 > d2 ) + for (; d1 != d2; d1-- ) + c1 = c1->m_Parent; + else if ( d1 < d2 ) + for (; d1 != d2; d2-- ) + c2 = c2->m_Parent; + + if ( cell == this ) + return true; + + while ( c1 && c2 ) + { + if ( c1->m_Parent == c2->m_Parent ) + { + while ( c1 ) + { + if ( c1 == c2 ) + return true; + c1 = c1->GetNext(); + } + return false; + } + else + { + c1 = c1->m_Parent; + c2 = c2->m_Parent; + } + } + + wxFAIL_MSG(_T("Cells are in different trees")); + return false; +} //----------------------------------------------------------------------------- @@ -183,8 +255,16 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y, dc.SetTextBackground(state.GetBgColour()); } + // FIXME - use selection dc.DrawText(m_Word, x + m_PosX, y + m_PosY); } + + +wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *sel) const +{ + // FIXME - use selection + return m_Word; +} @@ -266,7 +346,7 @@ bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak, int* known_pagebreaks, else { - wxHtmlCell *c = GetFirstCell(); + wxHtmlCell *c = GetFirstChild(); bool rt = FALSE; int pbrk = *pagebreak - m_PosY; @@ -718,19 +798,31 @@ void wxHtmlContainerCell::GetHorizontalConstraints(int *left, int *right) const wxHtmlCell *wxHtmlContainerCell::GetFirstTerminal() const { - if (m_Cells) - return m_Cells->GetFirstTerminal(); - else - return NULL; + if ( m_Cells ) + { + wxHtmlCell *c2; + for (wxHtmlCell *c = m_Cells; c; c = c->GetNext()) + { + c2 = c->GetFirstTerminal(); + if ( c2 ) + return c2; + } + } + return NULL; } wxHtmlCell *wxHtmlContainerCell::GetLastTerminal() const { - if (m_Cells) + if ( m_Cells ) { - wxHtmlCell *c; - for (c = m_Cells; c->GetNext(); c = c->GetNext()) {} - return c; + wxHtmlCell *c, *c2 = NULL; + // most common case first: + c = m_LastCell->GetLastTerminal(); + if ( c ) + return c; + for (wxHtmlCell *c = m_Cells; c; c = c->GetNext()) + c2 = c->GetLastTerminal(); + return c2; } else return NULL; @@ -864,4 +956,44 @@ void wxHtmlWidgetCell::Layout(int w) wxHtmlCell::Layout(w); } + + +// ---------------------------------------------------------------------------- +// wxHtmlTerminalCellsInterator +// ---------------------------------------------------------------------------- + +const wxHtmlCell* wxHtmlTerminalCellsInterator::operator++() +{ + if ( !m_pos ) + return NULL; + + do + { + if ( m_pos == m_to ) + { + m_pos = NULL; + return NULL; + } + + if ( m_pos->GetNext() ) + m_pos = m_pos->GetNext(); + else + { + // we must go up the hierarchy until we reach container where this + // is not the last child, and then go down to first terminal cell: + while ( m_pos->GetNext() == NULL ) + { + m_pos = m_pos->GetParent(); + if ( !m_pos ) + return NULL; + } + m_pos = m_pos->GetNext(); + } + while ( m_pos->GetFirstChild() != NULL ) + m_pos = m_pos->GetFirstChild(); + } while ( !m_pos->IsTerminalCell() ); + + return m_pos; +} + #endif diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp index 5986277c0a..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" @@ -634,6 +635,50 @@ 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) @@ -770,16 +815,14 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event)) if (goingDown) { m_tmpSelFromCell = m_Cell->FindCellByPos(x, y, - wxHTML_FIND_NEAREST_BEFORE); -#if 0 // FIXME -- needed or not? + wxHTML_FIND_NEAREST_AFTER); if (!m_tmpSelFromCell) m_tmpSelFromCell = m_Cell->GetFirstTerminal(); -#endif } else { m_tmpSelFromCell = m_Cell->FindCellByPos(x, y, - wxHTML_FIND_NEAREST_AFTER); + wxHTML_FIND_NEAREST_BEFORE); if (!m_tmpSelFromCell) m_tmpSelFromCell = m_Cell->GetLastTerminal(); } @@ -822,7 +865,7 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event)) } if ( m_selection ) { - if (goingDown) + if ( m_tmpSelFromCell->IsBefore(selcell) ) { m_selection->Set(m_tmpSelFromPos, m_tmpSelFromCell, wxPoint(x,y), selcell); @@ -833,6 +876,9 @@ void wxHtmlWindow::OnIdle(wxIdleEvent& WXUNUSED(event)) m_tmpSelFromPos, m_tmpSelFromCell); } Refresh(); // FIXME - optimize! +#ifdef __UNIX__ + CopySelection(Primary); +#endif } } } @@ -871,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) @@ -883,6 +949,10 @@ BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow) 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() diff --git a/src/html/m_dflist.cpp b/src/html/m_dflist.cpp index e113412e7a..6c767aed91 100644 --- a/src/html/m_dflist.cpp +++ b/src/html/m_dflist.cpp @@ -43,7 +43,7 @@ TAG_HANDLER_BEGIN(DEFLIST, "DL,DT,DD" ) if (tag.GetName() == wxT("DL")) { - if (m_WParser->GetContainer()->GetFirstCell() != NULL) + if (m_WParser->GetContainer()->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); @@ -52,7 +52,7 @@ TAG_HANDLER_BEGIN(DEFLIST, "DL,DT,DD" ) ParseInner(tag); - if (m_WParser->GetContainer()->GetFirstCell() != NULL) + if (m_WParser->GetContainer()->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); diff --git a/src/html/m_fonts.cpp b/src/html/m_fonts.cpp index 8582927cf7..7ec96a0b50 100644 --- a/src/html/m_fonts.cpp +++ b/src/html/m_fonts.cpp @@ -246,7 +246,7 @@ TAG_HANDLER_BEGIN(Hx, "H1,H2,H3,H4,H5,H6") } c = m_WParser->GetContainer(); - if (c->GetFirstCell()) + if (c->GetFirstChild()) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); diff --git a/src/html/m_layout.cpp b/src/html/m_layout.cpp index f99e547ca1..abd44132e9 100644 --- a/src/html/m_layout.cpp +++ b/src/html/m_layout.cpp @@ -136,7 +136,7 @@ TAG_HANDLER_BEGIN(P, "P") TAG_HANDLER_PROC(tag) { - if (m_WParser->GetContainer()->GetFirstCell() != NULL) + if (m_WParser->GetContainer()->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); @@ -177,7 +177,7 @@ TAG_HANDLER_BEGIN(CENTER, "CENTER") wxHtmlContainerCell *c = m_WParser->GetContainer(); m_WParser->SetAlign(wxHTML_ALIGN_CENTER); - if (c->GetFirstCell() != NULL) + if (c->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); @@ -190,7 +190,7 @@ TAG_HANDLER_BEGIN(CENTER, "CENTER") ParseInner(tag); m_WParser->SetAlign(old); - if (c->GetFirstCell() != NULL) + if (c->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); @@ -231,7 +231,7 @@ TAG_HANDLER_BEGIN(DIV, "DIV") { int old = m_WParser->GetAlign(); wxHtmlContainerCell *c = m_WParser->GetContainer(); - if (c->GetFirstCell() != NULL) + if (c->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); @@ -248,7 +248,7 @@ TAG_HANDLER_BEGIN(DIV, "DIV") ParseInner(tag); m_WParser->SetAlign(old); - if (c->GetFirstCell() != NULL) + if (c->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); diff --git a/src/html/m_list.cpp b/src/html/m_list.cpp index 144268218a..935f1c0299 100644 --- a/src/html/m_list.cpp +++ b/src/html/m_list.cpp @@ -133,7 +133,7 @@ TAG_HANDLER_BEGIN(OLULLI, "OL,UL,LI") else m_Numbering = 1; c = m_WParser->GetContainer(); - if (c->GetFirstCell() != NULL) + if (c->GetFirstChild() != NULL) { m_WParser->CloseContainer(); m_WParser->OpenContainer(); -- 2.45.2