X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0c8392cac2d36d0d211432e71d3b24d3d93c22db..032bc940fcde34cc649eaa111cd6aff1cda66104:/src/generic/htmllbox.cpp diff --git a/src/generic/htmllbox.cpp b/src/generic/htmllbox.cpp index 0970e8ef91..c034af5f20 100644 --- a/src/generic/htmllbox.cpp +++ b/src/generic/htmllbox.cpp @@ -28,6 +28,8 @@ #include "wx/dcclient.h" #endif //WX_PRECOMP +#if wxUSE_HTML + #include "wx/htmllbox.h" #include "wx/html/htmlcell.h" @@ -37,6 +39,16 @@ #include "wx/html/forcelnk.h" FORCE_WXHTML_MODULES() +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// small border always added to the cells: +static const wxCoord CELL_BORDER = 2; + +const wxChar wxHtmlListBoxNameStr[] = wxT("htmlListBox"); +const wxChar wxSimpleHtmlListBoxNameStr[] = wxT("simpleHtmlListBox"); + // ============================================================================ // private classes // ============================================================================ @@ -49,6 +61,15 @@ FORCE_WXHTML_MODULES() // the items to avoid doing it anew each time an item must be drawn class wxHtmlListBoxCache { +private: + // invalidate a single item, used by Clear() and InvalidateRange() + void InvalidateItem(size_t n) + { + m_items[n] = (size_t)-1; + delete m_cells[n]; + m_cells[n] = NULL; + } + public: wxHtmlListBoxCache() { @@ -74,9 +95,7 @@ public: { for ( size_t n = 0; n < SIZE; n++ ) { - m_items[n] = (size_t)-1; - delete m_cells[n]; - m_cells[n] = NULL; + InvalidateItem(n); } } @@ -107,6 +126,18 @@ public: m_next = 0; } + // forget the cached value of the item(s) between the given ones (inclusive) + void InvalidateRange(size_t from, size_t to) + { + for ( size_t n = 0; n < SIZE; n++ ) + { + if ( m_items[n] >= from && m_items[n] <= to ) + { + InvalidateItem(n); + } + } + } + private: // the max number of the items we cache enum { SIZE = 50 }; @@ -130,7 +161,7 @@ private: class wxHtmlListBoxStyle : public wxDefaultHtmlRenderingStyle { public: - wxHtmlListBoxStyle(wxHtmlListBox& hlbox) : m_hlbox(hlbox) { } + wxHtmlListBoxStyle(const wxHtmlListBox& hlbox) : m_hlbox(hlbox) { } virtual wxColour GetSelectedTextColour(const wxColour& colFg) { @@ -148,13 +179,14 @@ private: DECLARE_NO_COPY_CLASS(wxHtmlListBoxStyle) }; - // ---------------------------------------------------------------------------- // event tables // ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(wxHtmlListBox, wxVListBox) EVT_SIZE(wxHtmlListBox::OnSize) + EVT_MOTION(wxHtmlListBox::OnMouseMove) + EVT_LEFT_DOWN(wxHtmlListBox::OnLeftDown) END_EVENT_TABLE() // ============================================================================ @@ -168,6 +200,26 @@ IMPLEMENT_ABSTRACT_CLASS(wxHtmlListBox, wxVListBox) // wxHtmlListBox creation // ---------------------------------------------------------------------------- +wxHtmlListBox::wxHtmlListBox() + : wxHtmlWindowMouseHelper(this) +{ + Init(); +} + +// normal constructor which calls Create() internally +wxHtmlListBox::wxHtmlListBox(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) + : wxHtmlWindowMouseHelper(this) +{ + Init(); + + (void)Create(parent, id, pos, size, style, name); +} + void wxHtmlListBox::Init() { m_htmlParser = NULL; @@ -238,14 +290,22 @@ void wxHtmlListBox::CacheItem(size_t n) const { wxHtmlListBox *self = wxConstCast(this, wxHtmlListBox); - self->m_htmlParser = new wxHtmlWinParser; + self->m_htmlParser = new wxHtmlWinParser(self); m_htmlParser->SetDC(new wxClientDC(self)); + m_htmlParser->SetFS(&self->m_filesystem); + + // use system's default GUI font by default: + m_htmlParser->SetStandardFonts(); } wxHtmlContainerCell *cell = (wxHtmlContainerCell *)m_htmlParser-> Parse(OnGetItemMarkup(n)); wxCHECK_RET( cell, _T("wxHtmlParser::Parse() returned NULL?") ); + // set the cell's ID to item's index so that CellCoordsToPhysical() + // can quickly find the item: + cell->SetId(wxString::Format(_T("%lu"), (unsigned long)n)); + cell->Layout(GetClientSize().x - 2*GetMargins().x); m_cache->Store(n, cell); @@ -260,6 +320,20 @@ void wxHtmlListBox::OnSize(wxSizeEvent& event) event.Skip(); } +void wxHtmlListBox::RefreshLine(size_t line) +{ + m_cache->InvalidateRange(line, line); + + wxVListBox::RefreshLine(line); +} + +void wxHtmlListBox::RefreshLines(size_t from, size_t to) +{ + m_cache->InvalidateRange(from, to); + + wxVListBox::RefreshLines(from, to); +} + void wxHtmlListBox::RefreshAll() { m_cache->Clear(); @@ -292,7 +366,7 @@ void wxHtmlListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const if ( IsSelected(n) ) { wxHtmlSelection htmlSel; - htmlSel.Set(wxPoint(0, 0), cell, wxPoint(INT_MAX, INT_MAX), cell); + htmlSel.Set(wxPoint(0,0), cell, wxPoint(INT_MAX, INT_MAX), cell); htmlRendInfo.SetSelection(&htmlSel); if ( m_htmlRendStyle ) htmlRendInfo.SetStyle(m_htmlRendStyle); @@ -302,7 +376,9 @@ void wxHtmlListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const // note that we can't stop drawing exactly at the window boundary as then // even the visible cells part could be not drawn, so always draw the // entire cell - cell->Draw(dc, rect.x, rect.y, 0, INT_MAX, htmlRendInfo); + cell->Draw(dc, + rect.x + CELL_BORDER, rect.y + CELL_BORDER, + 0, INT_MAX, htmlRendInfo); } wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const @@ -312,6 +388,294 @@ wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const wxHtmlCell *cell = m_cache->Get(n); wxCHECK_MSG( cell, 0, _T("this cell should be cached!") ); - return cell->GetHeight() + cell->GetDescent(); + return cell->GetHeight() + cell->GetDescent() + 4; +} + +// ---------------------------------------------------------------------------- +// wxHtmlListBox implementation of wxHtmlListBoxWinInterface +// ---------------------------------------------------------------------------- + +void wxHtmlListBox::SetHTMLWindowTitle(const wxString& WXUNUSED(title)) +{ + // nothing to do +} + +void wxHtmlListBox::OnHTMLLinkClicked(const wxHtmlLinkInfo& link) +{ + OnLinkClicked(GetItemForCell(link.GetHtmlCell()), link); +} + +void wxHtmlListBox::OnLinkClicked(size_t WXUNUSED(n), + const wxHtmlLinkInfo& link) +{ + wxHtmlLinkEvent event(GetId(), link); + GetEventHandler()->ProcessEvent(event); +} + +wxHtmlOpeningStatus +wxHtmlListBox::OnHTMLOpeningURL(wxHtmlURLType WXUNUSED(type), + const wxString& WXUNUSED(url), + wxString *WXUNUSED(redirect)) const +{ + return wxHTML_OPEN; +} + +wxPoint wxHtmlListBox::HTMLCoordsToWindow(wxHtmlCell *cell, + const wxPoint& pos) const +{ + return CellCoordsToPhysical(pos, cell); +} + +wxWindow* wxHtmlListBox::GetHTMLWindow() { return this; } + +wxColour wxHtmlListBox::GetHTMLBackgroundColour() const +{ + return GetBackgroundColour(); +} + +void wxHtmlListBox::SetHTMLBackgroundColour(const wxColour& WXUNUSED(clr)) +{ + // nothing to do +} + +void wxHtmlListBox::SetHTMLBackgroundImage(const wxBitmap& WXUNUSED(bmpBg)) +{ + // nothing to do +} + +void wxHtmlListBox::SetHTMLStatusText(const wxString& WXUNUSED(text)) +{ + // nothing to do +} + +wxCursor wxHtmlListBox::GetHTMLCursor(HTMLCursor type) const +{ + // we don't want to show text selection cursor in listboxes + if (type == HTMLCursor_Text) + return wxHtmlWindow::GetDefaultHTMLCursor(HTMLCursor_Default); + + // in all other cases, use the same cursor as wxHtmlWindow: + return wxHtmlWindow::GetDefaultHTMLCursor(type); +} + +// ---------------------------------------------------------------------------- +// wxHtmlListBox handling of HTML links +// ---------------------------------------------------------------------------- + +wxPoint wxHtmlListBox::GetRootCellCoords(size_t n) const +{ + wxPoint pos(CELL_BORDER, CELL_BORDER); + pos += GetMargins(); + pos.y += GetLinesHeight(GetFirstVisibleLine(), n); + return pos; +} + +bool wxHtmlListBox::PhysicalCoordsToCell(wxPoint& pos, wxHtmlCell*& cell) const +{ + int n = HitTest(pos); + if ( n == wxNOT_FOUND ) + return false; + + // convert mouse coordinates to coords relative to item's wxHtmlCell: + pos -= GetRootCellCoords(n); + + CacheItem(n); + cell = m_cache->Get(n); + + return true; +} + +size_t wxHtmlListBox::GetItemForCell(const wxHtmlCell *cell) const +{ + wxCHECK_MSG( cell, 0, _T("no cell") ); + + cell = cell->GetRootCell(); + + wxCHECK_MSG( cell, 0, _T("no root cell") ); + + // the cell's ID contains item index, see CacheItem(): + unsigned long n; + if ( !cell->GetId().ToULong(&n) ) + { + wxFAIL_MSG( _T("unexpected root cell's ID") ); + return 0; + } + + return n; +} + +wxPoint +wxHtmlListBox::CellCoordsToPhysical(const wxPoint& pos, wxHtmlCell *cell) const +{ + return pos + GetRootCellCoords(GetItemForCell(cell)); +} + +void wxHtmlListBox::OnInternalIdle() +{ + wxVListBox::OnInternalIdle(); + + if ( wxHtmlWindowMouseHelper::DidMouseMove() ) + { + wxPoint pos = ScreenToClient(wxGetMousePosition()); + wxHtmlCell *cell; + + if ( !PhysicalCoordsToCell(pos, cell) ) + return; + + wxHtmlWindowMouseHelper::HandleIdle(cell, pos); + } +} + +void wxHtmlListBox::OnMouseMove(wxMouseEvent& event) +{ + wxHtmlWindowMouseHelper::HandleMouseMoved(); + event.Skip(); +} + +void wxHtmlListBox::OnLeftDown(wxMouseEvent& event) +{ + wxPoint pos = event.GetPosition(); + wxHtmlCell *cell; + + if ( !PhysicalCoordsToCell(pos, cell) ) + { + event.Skip(); + return; + } + + if ( !wxHtmlWindowMouseHelper::HandleMouseClick(cell, pos, event) ) + { + // no link was clicked, so let the listbox code handle the click (e.g. + // by selecting another item in the list): + event.Skip(); + } +} + + +// ---------------------------------------------------------------------------- +// wxSimpleHtmlListBox +// ---------------------------------------------------------------------------- + +bool wxSimpleHtmlListBox::Create(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) +{ + if (!wxHtmlListBox::Create(parent, id, pos, size, style, name)) + return false; + + SetValidator(validator); + for (int i=0; iIsFrozen()) + RefreshAll(); } +#endif // wxUSE_HTML