From: Václav Slavík Date: Thu, 13 Apr 2006 22:08:28 +0000 (+0000) Subject: 1. added abstract interface to wxHtmlWindow for use by wxHtmlWinParser and implemente... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/bc55e31bdc7fbf6f1006f298ed8310e7972984e9 1. added abstract interface to wxHtmlWindow for use by wxHtmlWinParser and implemented it for wxHtmlListBox 2. used the above to implement clickable links support in wxHtmlListBox git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38701 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index f21436a893..1a34097829 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -13,6 +13,11 @@ INCOMPATIBLE CHANGES SINCE 2.6.x - wxCHECK family of macros now must be followed by a semicolon - wxMBConv::cMB2WC() and cWC2MB() take size of the input buffer and return length of the converted string in all cases now. +- wxHtmlWindow::OnCellClicked() now returns bool. +- wxHtmlCell::OnMouseClick() was deprecated and replaced with + wxHtmlCell::ProcessMouseClick(); old code overriding OnMouseClick() will + continue to work with WXWIN_COMPATIBILITY_2_6, but should be rewritten to + use ProcessMouseClick(). Deprecated methods since 2.6.x and their replacements @@ -111,6 +116,8 @@ All (GUI): - Added wxListBox::HitTest(). - Added wxDisplay::GetClientArea(). - Indices and counts in wxControlWithItems derived API are unsigned. +- Added support for links to wxHtmlListBox; use code has to override + wxHtmlListBox::OnLinkClicked() to take advantage of it. wxMSW: diff --git a/docs/latex/wx/htcell.tex b/docs/latex/wx/htcell.tex index 71ade362ee..a627e84ec0 100644 --- a/docs/latex/wx/htcell.tex +++ b/docs/latex/wx/htcell.tex @@ -223,13 +223,14 @@ It must be called before displaying cells structure because m\_PosX and m\_PosY are undefined (or invalid) before calling Layout. -\membersection{wxHtmlCell::OnMouseClick}\label{wxhtmlcellonmouseclick} +\membersection{wxHtmlCell::ProcessMouseClick}\label{wxhtmlcellprocessmouseclick} -\func{virtual void}{OnMouseClick}{\param{wxWindow* }{parent}, \param{int}{x}, \param{int }{y}, \param{const wxMouseEvent\& }{event}} +\func{virtual bool}{ProcessMouseClick}{\param{wxHtmlWindowInterface* }{window}, \param{const wxPoint\& }{pos}, \param{const wxMouseEvent\& }{event}} -This function is simple event handler. Each time the user clicks mouse button over a cell -within \helpref{wxHtmlWindow}{wxhtmlwindow} this method of that cell is called. Default behavior is -that it calls \helpref{wxHtmlWindow::LoadPage}{wxhtmlwindowloadpage}. +This function is simple event handler. Each time the user clicks mouse button +over a cell within \helpref{wxHtmlWindow}{wxhtmlwindow} this method of that +cell is called. Default behavior is to call +\helpref{wxHtmlWindow::LoadPage}{wxhtmlwindowloadpage}. \wxheading{Note} @@ -238,12 +239,15 @@ you should use wxHtmlBinderCell instead. \wxheading{Parameters} -\docparam{parent}{parent window (always wxHtmlWindow!)} +\docparam{window}{interface to the parent HTML window} -\docparam{x, y}{coordinates of mouse click (this is relative to cell's origin} +\docparam{pos}{coordinates of mouse click (this is relative to cell's origin} -\docparam{left, middle, right}{boolean flags for mouse buttons. true if the left/middle/right -button is pressed, false otherwise} +\docparam{event}{mouse event that triggered the call} + +\wxheading{Return value} + +\true if a link was clicked, \false otherwise. \membersection{wxHtmlCell::SetId}\label{wxhtmlcellsetid} diff --git a/docs/latex/wx/htmllbox.tex b/docs/latex/wx/htmllbox.tex index e56d1b6d1a..257611d039 100644 --- a/docs/latex/wx/htmllbox.tex +++ b/docs/latex/wx/htmllbox.tex @@ -127,3 +127,18 @@ for the given item. This function may be overridden to decorate HTML returned by \helpref{OnGetItem()}{wxhtmllistboxongetitem}. +\membersection{wxHtmlListBox::OnLinkClicked}\label{wxhtmlistboxonlinkclicked} + +\func{virtual void}{OnLinkClicked}{\param{size\_t }{n}, \param{const wxHtmlLinkInfo\& }{link}} + +Called when the user clicks on hypertext link. Does nothing by default. + +\wxheading{Parameters} + +\docparam{n}{Index of the item containing the link.} + +\docparam{link}{Description of the link.} + +\wxheading{See also} + +See also \helpref{wxHtmlLinkInfo}{wxhtmllinkinfo}. diff --git a/docs/latex/wx/htwindow.tex b/docs/latex/wx/htwindow.tex index 01c50a9223..190551eee7 100644 --- a/docs/latex/wx/htwindow.tex +++ b/docs/latex/wx/htwindow.tex @@ -197,7 +197,7 @@ false if an error occurred, true otherwise \membersection{wxHtmlWindow::OnCellClicked}\label{wxhtmlwindowoncellclicked} -\func{virtual void}{OnCellClicked}{\param{wxHtmlCell }{*cell}, \param{wxCoord }{x}, \param{wxCoord }{y}, \param{const wxMouseEvent\& }{event}} +\func{virtual bool}{OnCellClicked}{\param{wxHtmlCell }{*cell}, \param{wxCoord }{x}, \param{wxCoord }{y}, \param{const wxMouseEvent\& }{event}} This method is called when a mouse button is clicked inside wxHtmlWindow. The default behaviour is to call @@ -213,6 +213,10 @@ hypertext link. \docparam{event}{The mouse event containing other information about the click} +\wxheading{Return value} + +\true if a link was clicked, \false otherwise. + \membersection{wxHtmlWindow::OnCellMouseHover}\label{wxhtmlwindowoncellmousehover} \func{virtual void}{OnCellMouseHover}{\param{wxHtmlCell }{*cell}, \param{wxCoord }{x}, \param{wxCoord }{y}} diff --git a/docs/latex/wx/htwinprs.tex b/docs/latex/wx/htwinprs.tex index 5a24cf285b..930306a5af 100644 --- a/docs/latex/wx/htwinprs.tex +++ b/docs/latex/wx/htwinprs.tex @@ -32,10 +32,12 @@ The product of parsing is a wxHtmlCell (resp. wxHtmlContainer) object. \func{}{wxHtmlWinParser}{\void} -\func{}{wxHtmlWinParser}{\param{wxHtmlWindow }{*wnd}} +\func{}{wxHtmlWinParser}{\param{wxHtmlWindowInterface }{*wndIface}} Constructor. Don't use the default one, use constructor with -{\it wnd} parameter ({\it wnd} is pointer to associated \helpref{wxHtmlWindow}{wxhtmlwindow}) +{\it wndIface} parameter ({\it wndIface} is a pointer to interface object for +the associated \helpref{wxHtmlWindow}{wxhtmlwindow} or other HTML rendering +window such as \helpref{wxHtmlListBox}{wxhtmllistbox}). \membersection{wxHtmlWinParser::AddModule}\label{wxhtmlwinparseraddmodule} diff --git a/include/wx/html/htmlcell.h b/include/wx/html/htmlcell.h index 62afdebae4..0b32fe4fb2 100644 --- a/include/wx/html/htmlcell.h +++ b/include/wx/html/htmlcell.h @@ -20,6 +20,7 @@ #include "wx/window.h" +class WXDLLIMPEXP_HTML wxHtmlWindowInterface; class WXDLLIMPEXP_HTML wxHtmlLinkInfo; class WXDLLIMPEXP_HTML wxHtmlCell; class WXDLLIMPEXP_HTML wxHtmlContainerCell; @@ -244,12 +245,23 @@ public: // returns pointer to anchor news virtual const wxHtmlCell* Find(int condition, const void* param) const; + // This function is called when mouse button is clicked over the cell. + // Returns true if a link is clicked, false otherwise. // - // Parent is pointer to wxHtmlWindow that generated the event + // 'window' is pointer to wxHtmlWindowInterface of the window which + // generated the event. // HINT: if this handling is not enough for you you should use // wxHtmlWidgetCell - virtual void OnMouseClick(wxWindow *parent, int x, int y, const wxMouseEvent& event); + virtual bool ProcessMouseClick(wxHtmlWindowInterface *window, + const wxPoint& pos, + const wxMouseEvent& event); + +#if WXWIN_COMPATIBILITY_2_6 + // this was replaced by ProcessMouseClick, don't use in new code! + virtual void OnMouseClick(wxWindow *window, + int x, int y, const wxMouseEvent& event); +#endif // This method used to adjust pagebreak position. The parameter is variable // that contains y-coordinate of page break (= horizontal line that should @@ -283,8 +295,14 @@ public: virtual wxHtmlCell *FindCellByPos(wxCoord x, wxCoord y, unsigned flags = wxHTML_FIND_EXACT) const; - // Returns absolute position of the cell on HTML canvas - wxPoint GetAbsPos() const; + // Returns absolute position of the cell on HTML canvas. + // If rootCell is provided, then it's considered to be the root of the + // hierarchy and the returned value is relative to it. + wxPoint GetAbsPos(wxHtmlCell *rootCell = NULL) const; + + // Returns root cell of the hierarchy (i.e. grand-grand-...-parent that + // doesn't have a parent itself) + wxHtmlCell *GetRootCell() 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. @@ -424,7 +442,15 @@ public: void SetBorder(const wxColour& clr1, const wxColour& clr2) {m_UseBorder = true; m_BorderColour1 = clr1, m_BorderColour2 = clr2;} virtual wxHtmlLinkInfo* GetLink(int x = 0, int y = 0) const; virtual const wxHtmlCell* Find(int condition, const void* param) const; - virtual void OnMouseClick(wxWindow *parent, int x, int y, const wxMouseEvent& event); + +#if WXWIN_COMPATIBILITY_2_6 + // this was replaced by ProcessMouseClick, don't use in new code! + virtual void OnMouseClick(wxWindow *window, + int x, int y, const wxMouseEvent& event); +#endif + virtual bool ProcessMouseClick(wxHtmlWindowInterface *window, + const wxPoint& pos, + const wxMouseEvent& event); virtual wxHtmlCell* GetFirstChild() const { return m_Cells; } #if WXWIN_COMPATIBILITY_2_4 diff --git a/include/wx/html/htmlwin.h b/include/wx/html/htmlwin.h index 719173bedb..ea22e30601 100644 --- a/include/wx/html/htmlwin.h +++ b/include/wx/html/htmlwin.h @@ -38,15 +38,163 @@ class WXDLLIMPEXP_HTML wxHtmlWinAutoScrollTimer; #define wxHW_DEFAULT_STYLE wxHW_SCROLLBAR_AUTO - -// enums for wxHtmlWindow::OnOpeningURL +/// Enum for wxHtmlWindow::OnOpeningURL and wxHtmlWindowInterface::OnOpeningURL enum wxHtmlOpeningStatus { + /// Open the requested URL wxHTML_OPEN, + /// Do not open the URL wxHTML_BLOCK, + /// Redirect to another URL (returned from OnOpeningURL) wxHTML_REDIRECT }; +/** + Abstract interface to a HTML rendering window (such as wxHtmlWindow or + wxHtmlListBox) that is passed to wxHtmlWinParser. It encapsulates all + communication from the parser to the window. + */ +class WXDLLIMPEXP_HTML wxHtmlWindowInterface +{ +public: + /// Ctor + wxHtmlWindowInterface() {} + virtual ~wxHtmlWindowInterface() {} + + /** + Called by the parser to set window's title to given text. + */ + virtual void SetHTMLWindowTitle(const wxString& title) = 0; + + /** + Called when a link is clicked. + + @param link information about the clicked link + */ + virtual void OnHTMLLinkClicked(const wxHtmlLinkInfo& link) = 0; + + /** + Called when the parser needs to open another URL (e.g. an image). + + @param type Type of the URL request (e.g. image) + @param url URL the parser wants to open + @param redirect If the return value is wxHTML_REDIRECT, then the + URL to redirect to will be stored in this variable + (the pointer must never be NULL) + + @return indicator of how to treat the request + */ + virtual wxHtmlOpeningStatus OnHTMLOpeningURL(wxHtmlURLType type, + const wxString& url, + wxString *redirect) const = 0; + + /** + Converts coordinates @a pos relative to given @a cell to + physical coordinates in the window. + */ + virtual wxPoint HTMLCoordsToWindow(wxHtmlCell *cell, + const wxPoint& pos) const = 0; + + /// Returns the window used for rendering (may be NULL). + virtual wxWindow* GetHTMLWindow() = 0; + + /// Returns background colour to use by default. + virtual wxColour GetHTMLBackgroundColour() const = 0; + + /// Sets window's background to colour @a clr. + virtual void SetHTMLBackgroundColour(const wxColour& clr) = 0; + + /// Sets window's background to given bitmap. + virtual void SetHTMLBackgroundImage(const wxBitmap& bmpBg) = 0; + + /// Sets status bar text. + virtual void SetHTMLStatusText(const wxString& text) = 0; +}; + +/** + Helper class that implements part of mouse handling for wxHtmlWindow and + wxHtmlListBox. Cursor changes and clicking on links are handled, text + selection is not. + */ +class WXDLLIMPEXP_HTML wxHtmlWindowMouseHelper +{ +public: + /** + Ctor. + + @param iface Interface to the owner window. + */ + wxHtmlWindowMouseHelper(wxHtmlWindowInterface *iface); + + /// Returns true if the mouse moved since the last call to HandleIdle + bool DidMouseMove() const { return m_tmpMouseMoved; } + + /// Call this from EVT_MOTION event handler + void HandleMouseMoved(); + + /** + Call this from EVT_LEFT_UP handler (or, alternatively, EVT_LEFT_DOWN). + + @param rootCell HTML cell inside which the click occured. This doesn't + have to be the leaf cell, it can be e.g. toplevel + container, but the mouse must be inside the container's + area, otherwise the event would be ignored. + @param pos Mouse position in coordinates relative to @a cell + @param event The event that triggered the call + */ + bool HandleMouseClick(wxHtmlCell *rootCell, + const wxPoint& pos, const wxMouseEvent& event); + + /** + Call this from OnInternalIdle of the HTML displaying window. Handles + mouse movements and must be used together with HandleMouseMoved. + + @param rootCell HTML cell inside which the click occured. This doesn't + have to be the leaf cell, it can be e.g. toplevel + container, but the mouse must be inside the container's + area, otherwise the event would be ignored. + @param pos Current mouse position in coordinates relative to + @a cell + */ + void HandleIdle(wxHtmlCell *rootCell, const wxPoint& pos); + + /** + Called by HandleIdle when the mouse hovers over a cell. Default + behaviour is to do nothing. + + @param cell the cell the mouse is over + @param x, y coordinates of mouse relative to the cell + */ + virtual void OnCellMouseHover(wxHtmlCell *cell, wxCoord x, wxCoord y); + + /** + Called by HandleMouseClick when the user clicks on a cell. + Default behavior is to call wxHtmlWindowInterface::OnLinkClicked() + if this cell corresponds to a hypertext link. + + @param cell the cell the mouse is over + @param x, y coordinates of mouse relative to the cell + @param event The event that triggered the call + + + @return true if a link was clicked, false otherwise. + */ + virtual bool OnCellClicked(wxHtmlCell *cell, + wxCoord x, wxCoord y, + const wxMouseEvent& event); + +protected: + // this flag indicates if the mouse moved (used by HandleIdle) + bool m_tmpMouseMoved; + // contains last link name + wxHtmlLinkInfo *m_tmpLastLink; + // contains the last (terminal) cell which contained the mouse + wxHtmlCell *m_tmpLastCell; + +private: + wxHtmlWindowInterface *m_interface; +}; + // ---------------------------------------------------------------------------- // wxHtmlWindow // (This is probably the only class you will directly use.) @@ -58,18 +206,21 @@ enum wxHtmlOpeningStatus // SetPage(text) or LoadPage(filename). // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_HTML wxHtmlWindow : public wxScrolledWindow +class WXDLLIMPEXP_HTML wxHtmlWindow : public wxScrolledWindow, + public wxHtmlWindowInterface, + private wxHtmlWindowMouseHelper { DECLARE_DYNAMIC_CLASS(wxHtmlWindow) friend class wxHtmlWinModule; public: - wxHtmlWindow() { Init(); } + wxHtmlWindow() : wxHtmlWindowMouseHelper(this) { Init(); } wxHtmlWindow(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxHW_DEFAULT_STYLE, const wxString& name = wxT("htmlWindow")) + : wxHtmlWindowMouseHelper(this) { Init(); Create(parent, id, pos, size, style, name); @@ -178,16 +329,6 @@ public: // (depending on the information passed to SetRelatedFrame() method) virtual void OnSetTitle(const wxString& title); - // Called when the mouse hovers over a cell: (x, y) are logical coords - // Default behaviour is to do nothing at all - virtual void OnCellMouseHover(wxHtmlCell *cell, wxCoord x, wxCoord y); - - // Called when user clicks on a cell. Default behavior is to call - // OnLinkClicked() if this cell corresponds to a hypertext link - virtual void OnCellClicked(wxHtmlCell *cell, - wxCoord x, wxCoord y, - const wxMouseEvent& event); - // Called when user clicked on hypertext link. Default behavior is to // call LoadPage(loc) virtual void OnLinkClicked(const wxHtmlLinkInfo& link); @@ -216,6 +357,7 @@ public: virtual void OnInternalIdle(); + protected: void Init(); @@ -272,6 +414,20 @@ protected: wxString DoSelectionToText(wxHtmlSelection *sel); private: + // wxHtmlWindowInterface methods: + virtual void SetHTMLWindowTitle(const wxString& title); + virtual void OnHTMLLinkClicked(const wxHtmlLinkInfo& link); + virtual wxHtmlOpeningStatus OnHTMLOpeningURL(wxHtmlURLType type, + const wxString& url, + wxString *redirect) const; + virtual wxPoint HTMLCoordsToWindow(wxHtmlCell *cell, + const wxPoint& pos) const; + virtual wxWindow* GetHTMLWindow(); + virtual wxColour GetHTMLBackgroundColour() const; + virtual void SetHTMLBackgroundColour(const wxColour& clr); + virtual void SetHTMLBackgroundImage(const wxBitmap& bmpBg); + virtual void SetHTMLStatusText(const wxString& text); + // implementation of SetPage() bool DoSetPage(const wxString& source); @@ -333,10 +489,6 @@ private: wxPoint m_tmpSelFromPos; wxHtmlCell *m_tmpSelFromCell; - // contains last link name - wxHtmlLinkInfo *m_tmpLastLink; - // contains the last (terminal) cell which contained the mouse - wxHtmlCell *m_tmpLastCell; // if >0 contents of the window is not redrawn // (in order to avoid ugly blinking) int m_tmpCanDrawLocks; @@ -356,10 +508,6 @@ private: // if this FLAG is false, items are not added to history bool m_HistoryOn; - // a flag indicated if mouse moved - // (if true we will try to change cursor in last call to OnIdle) - bool m_tmpMouseMoved; - // a flag set if we need to erase background in OnPaint() (otherwise this // is supposed to have been done in OnEraseBackground()) bool m_eraseBgInOnPaint; diff --git a/include/wx/html/winpars.h b/include/wx/html/winpars.h index 12893b888b..965738d542 100644 --- a/include/wx/html/winpars.h +++ b/include/wx/html/winpars.h @@ -20,10 +20,12 @@ #include "wx/encconv.h" class WXDLLIMPEXP_HTML wxHtmlWindow; +class WXDLLIMPEXP_HTML wxHtmlWindowInterface; class WXDLLIMPEXP_HTML wxHtmlWinParser; class WXDLLIMPEXP_HTML wxHtmlWinTagHandler; class WXDLLIMPEXP_HTML wxHtmlTagsModule; + //-------------------------------------------------------------------------------- // wxHtmlWinParser // This class is derived from wxHtmlParser and its mail goal @@ -37,7 +39,8 @@ class WXDLLIMPEXP_HTML wxHtmlWinParser : public wxHtmlParser friend class wxHtmlWindow; public: - wxHtmlWinParser(wxHtmlWindow *wnd = NULL); + wxHtmlWinParser(wxHtmlWindowInterface *wndIface = NULL); + ~wxHtmlWinParser(); virtual void InitParser(const wxString& source); @@ -62,7 +65,10 @@ public: // GetDC()->GetChar...() // returns associated wxWindow - wxHtmlWindow *GetWindow() {return m_Window;} + wxHtmlWindowInterface *GetWindowInterface() {return m_windowInterface;} +#if WXWIN_COMPATIBILITY_2_6 + wxDEPRECATED( wxHtmlWindow *GetWindow() ); +#endif // Sets fonts to be used when displaying HTML page. (if size null then default sizes used). void SetFonts(const wxString& normal_face, const wxString& fixed_face, const int *sizes = NULL); @@ -148,7 +154,7 @@ private: wxChar *m_tmpStrBuf; size_t m_tmpStrBufSize; // temporary variables used by AddText - wxHtmlWindow *m_Window; + wxHtmlWindowInterface *m_windowInterface; // window we're parsing for double m_PixelScale; wxDC *m_DC; diff --git a/include/wx/htmllbox.h b/include/wx/htmllbox.h index bf0d295bde..6c37476ace 100644 --- a/include/wx/htmllbox.h +++ b/include/wx/htmllbox.h @@ -13,6 +13,7 @@ #define _WX_HTMLLBOX_H_ #include "wx/vlbox.h" // base class +#include "wx/html/htmlwin.h" #if wxUSE_FILESYSTEM #include "wx/filesys.h" @@ -27,7 +28,9 @@ class WXDLLIMPEXP_HTML wxHtmlListBoxStyle; // wxHtmlListBox // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_HTML wxHtmlListBox : public wxVListBox +class WXDLLIMPEXP_HTML wxHtmlListBox : public wxVListBox, + public wxHtmlWindowInterface, + private wxHtmlWindowMouseHelper { DECLARE_ABSTRACT_CLASS(wxHtmlListBox) public: @@ -35,7 +38,7 @@ public: // --------------------- // default constructor, you must call Create() later - wxHtmlListBox() { Init(); } + wxHtmlListBox(); // normal constructor which calls Create() internally wxHtmlListBox(wxWindow *parent, @@ -43,12 +46,7 @@ public: const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxVListBoxNameStr) - { - Init(); - - (void)Create(parent, id, pos, size, style, name); - } + const wxString& name = wxVListBoxNameStr); // really creates the control and sets the initial number of items in it // (which may be changed later with SetItemCount()) @@ -80,6 +78,8 @@ public: const wxFileSystem& GetFileSystem() const { return m_filesystem; } #endif // wxUSE_FILESYSTEM + virtual void OnInternalIdle(); + protected: // this method must be implemented in the derived class and should return // the body (i.e. without ) of the HTML for the given item @@ -108,9 +108,15 @@ protected: virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; virtual wxCoord OnMeasureItem(size_t n) const; + // This method may be overriden to handle clicking on a link in + // the listbox. By default, clicking links is ignored. + virtual void OnLinkClicked(size_t WXUNUSED(n), + const wxHtmlLinkInfo& WXUNUSED(link)) {} // event handlers void OnSize(wxSizeEvent& event); + void OnMouseMove(wxMouseEvent& event); + void OnLeftDown(wxMouseEvent& event); // common part of all ctors @@ -119,6 +125,38 @@ protected: // ensure that the given item is cached void CacheItem(size_t n) const; +private: + // wxHtmlWindowInterface methods: + virtual void SetHTMLWindowTitle(const wxString& title); + virtual void OnHTMLLinkClicked(const wxHtmlLinkInfo& link); + virtual wxHtmlOpeningStatus OnHTMLOpeningURL(wxHtmlURLType type, + const wxString& url, + wxString *redirect) const; + virtual wxPoint HTMLCoordsToWindow(wxHtmlCell *cell, + const wxPoint& pos) const; + virtual wxWindow* GetHTMLWindow(); + virtual wxColour GetHTMLBackgroundColour() const; + virtual void SetHTMLBackgroundColour(const wxColour& clr); + virtual void SetHTMLBackgroundImage(const wxBitmap& bmpBg); + virtual void SetHTMLStatusText(const wxString& text); + + // returns index of item that contains given HTML cell + size_t GetItemForCell(const wxHtmlCell *cell) const; + + // return physical coordinates of root wxHtmlCell of n-th item + wxPoint GetRootCellCoords(size_t n) const; + + // Converts physical coordinates stored in @a pos into coordinates + // relative to the root cell of the item under mouse cursor, if any. If no + // cell is found under the cursor, returns false. Otherwise stores the new + // coordinates back into @a pos and pointer to the cell under cursor into + // @a cell and returns true. + bool PhysicalCoordsToCell(wxPoint& pos, wxHtmlCell*& cell) const; + + // The opposite of PhysicalCoordsToCell: converts coordinates relative to + // given cell to physical coordinates in the window + wxPoint CellCoordsToPhysical(const wxPoint& pos, wxHtmlCell *cell) const; + private: // this class caches the pre-parsed HTML to speed up display wxHtmlListBoxCache *m_cache; @@ -137,6 +175,7 @@ private: // it calls our GetSelectedTextColour() and GetSelectedTextBgColour() friend class wxHtmlListBoxStyle; + friend class wxHtmlListBoxWinInterface; DECLARE_EVENT_TABLE() diff --git a/samples/htlbox/htlbox.cpp b/samples/htlbox/htlbox.cpp index 419def086c..0522932c5e 100644 --- a/samples/htlbox/htlbox.cpp +++ b/samples/htlbox/htlbox.cpp @@ -77,6 +77,8 @@ protected: virtual void OnDrawSeparator(wxDC& dc, wxRect& rect, size_t n) const; virtual wxColour GetSelectedTextColour(const wxColour& colFg) const; + // override this method to handle mouse clicks + virtual void OnLinkClicked(size_t n, const wxHtmlLinkInfo& link); // flag telling us whether we should use fg colour even for the selected // item @@ -85,6 +87,9 @@ protected: // flag which we toggle to update the first items text in OnGetItem() bool m_firstItemUpdated; + // flag which we toggle when the user clicks on the link in 2nd item + // to change 2nd item's text + bool m_linkClicked; #ifdef USE_HTML_FILE @@ -423,6 +428,7 @@ MyHtmlListBox::MyHtmlListBox(wxWindow *parent, bool multi) { m_change = true; m_firstItemUpdated = false; + m_linkClicked = false; SetMargins(5, 5); @@ -469,14 +475,23 @@ wxString MyHtmlListBox::OnGetItem(size_t n) const return s; #else int level = n % 6 + 1; - return wxString::Format(_T("") - _T("Item %lu") - _T(""), - level, - abs((int)n - 192) % 256, - abs((int)n - 256) % 256, - abs((int)n - 128) % 256, - (unsigned long)n, level); + wxString label = wxString::Format(_T("") + _T("Item %lu") + _T(""), + level, + abs((int)n - 192) % 256, + abs((int)n - 256) % 256, + abs((int)n - 128) % 256, + (unsigned long)n, level); + if ( n == 1 ) + { + if ( !m_linkClicked ) + label += _T("Click here..."); + else + label += _T("Clicked here..."); + } + + return label; #endif } @@ -492,3 +507,10 @@ void MyHtmlListBox::UpdateFirstItem() RefreshLine(0); } +void MyHtmlListBox::OnLinkClicked(size_t WXUNUSED(n), + const wxHtmlLinkInfo& WXUNUSED(link)) +{ + m_linkClicked = true; + + RefreshLine(1); +} diff --git a/src/generic/htmllbox.cpp b/src/generic/htmllbox.cpp index f6669cbfe9..c70d7b85f4 100644 --- a/src/generic/htmllbox.cpp +++ b/src/generic/htmllbox.cpp @@ -39,6 +39,13 @@ #include "wx/html/forcelnk.h" FORCE_WXHTML_MODULES() +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// small border always added to the cells: +static const wxCoord CELL_BORDER = 2; + // ============================================================================ // private classes // ============================================================================ @@ -169,13 +176,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() // ============================================================================ @@ -189,6 +197,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; @@ -259,7 +287,7 @@ 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); @@ -271,6 +299,10 @@ void wxHtmlListBox::CacheItem(size_t n) const 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("%u"), n)); + cell->Layout(GetClientSize().x - 2*GetMargins().x); m_cache->Store(n, cell); @@ -341,7 +373,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+2, rect.y+2, 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 @@ -354,5 +388,147 @@ wxCoord wxHtmlListBox::OnMeasureItem(size_t n) const return cell->GetHeight() + cell->GetDescent() + 4; } -#endif // wxUSE_HTML +// ---------------------------------------------------------------------------- +// 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); +} + +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 +} + +// ---------------------------------------------------------------------------- +// 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(); + } +} + +#endif // wxUSE_HTML diff --git a/src/html/htmlcell.cpp b/src/html/htmlcell.cpp index 114097e2fa..1b111b9aca 100644 --- a/src/html/htmlcell.cpp +++ b/src/html/htmlcell.cpp @@ -117,19 +117,85 @@ void wxHtmlCell::SetScriptMode(wxHtmlScriptMode mode, long previousBase) m_Descent += m_ScriptBaseline; } -void wxHtmlCell::OnMouseClick(wxWindow *parent, int x, int y, - const wxMouseEvent& event) +#if WXWIN_COMPATIBILITY_2_6 + +struct wxHtmlCellOnMouseClickCompatHelper; + +static wxHtmlCellOnMouseClickCompatHelper *gs_helperOnMouseClick = NULL; + +// helper for routing calls to new ProcessMouseClick() method to deprecated +// OnMouseClick() method +struct wxHtmlCellOnMouseClickCompatHelper +{ + wxHtmlCellOnMouseClickCompatHelper(wxHtmlWindowInterface *window_, + const wxPoint& pos_, + const wxMouseEvent& event_) + : window(window_), pos(pos_), event(event_), retval(false) + { + } + + bool CallOnMouseClick(wxHtmlCell *cell) + { + wxHtmlCellOnMouseClickCompatHelper *oldHelper = gs_helperOnMouseClick; + gs_helperOnMouseClick = this; + cell->OnMouseClick + ( + window ? window->GetHTMLWindow() : NULL, + pos.x, pos.y, + event + ); + gs_helperOnMouseClick = oldHelper; + return retval; + } + + wxHtmlWindowInterface *window; + const wxPoint& pos; + const wxMouseEvent& event; + bool retval; +}; +#endif // WXWIN_COMPATIBILITY_2_6 + +bool wxHtmlCell::ProcessMouseClick(wxHtmlWindowInterface *window, + const wxPoint& pos, + const wxMouseEvent& event) +{ + wxCHECK_MSG( window, false, _T("window interface must be provided") ); + +#if WXWIN_COMPATIBILITY_2_6 + // NB: this hack puts the body of ProcessMouseClick() into OnMouseClick() + // (for which it has to pass the arguments and return value via a + // helper variable because these two methods have different + // signatures), so that old code overriding OnMouseClick will continue + // to work + wxHtmlCellOnMouseClickCompatHelper compat(window, pos, event); + return compat.CallOnMouseClick(this); +} + +void wxHtmlCell::OnMouseClick(wxWindow *, int, int, const wxMouseEvent& event) { - wxHtmlLinkInfo *lnk = GetLink(x, y); - if (lnk != NULL) + wxCHECK_RET( gs_helperOnMouseClick, _T("unexpected call to OnMouseClick") ); + wxHtmlWindowInterface *window = gs_helperOnMouseClick->window; + const wxPoint& pos = gs_helperOnMouseClick->pos; +#endif // WXWIN_COMPATIBILITY_2_6 + + wxHtmlLinkInfo *lnk = GetLink(pos.x, pos.y); + bool retval = false; + + if (lnk) { wxHtmlLinkInfo lnk2(*lnk); lnk2.SetEvent(&event); lnk2.SetHtmlCell(this); - // note : this cast is legal because parent is *always* wxHtmlWindow - wxStaticCast(parent, wxHtmlWindow)->OnLinkClicked(lnk2); + window->OnHTMLLinkClicked(lnk2); + retval = true; } + +#if WXWIN_COMPATIBILITY_2_6 + gs_helperOnMouseClick->retval = retval; +#else + return retval; +#endif // WXWIN_COMPATIBILITY_2_6 } @@ -203,10 +269,11 @@ wxHtmlCell *wxHtmlCell::FindCellByPos(wxCoord x, wxCoord y, } -wxPoint wxHtmlCell::GetAbsPos() const +wxPoint wxHtmlCell::GetAbsPos(wxHtmlCell *rootCell) const { wxPoint p(m_PosX, m_PosY); - for (wxHtmlCell *parent = m_Parent; parent; parent = parent->m_Parent) + for (wxHtmlCell *parent = m_Parent; parent && parent != rootCell; + parent = parent->m_Parent) { p.x += parent->m_PosX; p.y += parent->m_PosY; @@ -214,6 +281,14 @@ wxPoint wxHtmlCell::GetAbsPos() const return p; } +wxHtmlCell *wxHtmlCell::GetRootCell() const +{ + wxHtmlCell *c = wxConstCast(this, wxHtmlCell); + while ( c->m_Parent ) + c = c->m_Parent; + return c; +} + unsigned wxHtmlCell::GetDepth() const { unsigned d = 0; @@ -1150,13 +1225,34 @@ wxHtmlCell *wxHtmlContainerCell::FindCellByPos(wxCoord x, wxCoord y, } -void wxHtmlContainerCell::OnMouseClick(wxWindow *parent, int x, int y, const wxMouseEvent& event) +bool wxHtmlContainerCell::ProcessMouseClick(wxHtmlWindowInterface *window, + const wxPoint& pos, + const wxMouseEvent& event) { - wxHtmlCell *cell = FindCellByPos(x, y); - if ( cell ) - cell->OnMouseClick(parent, x, y, event); +#if WXWIN_COMPATIBILITY_2_6 + wxHtmlCellOnMouseClickCompatHelper compat(window, pos, event); + return compat.CallOnMouseClick(this); } +void wxHtmlContainerCell::OnMouseClick(wxWindow*, + int, int, const wxMouseEvent& event) +{ + wxCHECK_RET( gs_helperOnMouseClick, _T("unexpected call to OnMouseClick") ); + wxHtmlWindowInterface *window = gs_helperOnMouseClick->window; + const wxPoint& pos = gs_helperOnMouseClick->pos; +#endif // WXWIN_COMPATIBILITY_2_6 + + bool retval = false; + wxHtmlCell *cell = FindCellByPos(pos.x, pos.y); + if ( cell ) + retval = cell->ProcessMouseClick(window, pos, event); + +#if WXWIN_COMPATIBILITY_2_6 + gs_helperOnMouseClick->retval = retval; +#else + return retval; +#endif // WXWIN_COMPATIBILITY_2_6 +} wxHtmlCell *wxHtmlContainerCell::GetFirstTerminal() const diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp index 7d71dd82d7..741e10fb62 100644 --- a/src/html/htmlwin.cpp +++ b/src/html/htmlwin.cpp @@ -140,6 +140,104 @@ WX_DEFINE_OBJARRAY(wxHtmlHistoryArray) WX_DECLARE_LIST(wxHtmlProcessor, wxHtmlProcessorList); WX_DEFINE_LIST(wxHtmlProcessorList) +//----------------------------------------------------------------------------- +// wxHtmlWindowMouseHelper +//----------------------------------------------------------------------------- + +wxHtmlWindowMouseHelper::wxHtmlWindowMouseHelper(wxHtmlWindowInterface *iface) + : m_tmpMouseMoved(false), + m_tmpLastLink(NULL), + m_tmpLastCell(NULL), + m_interface(iface) +{ +} + +void wxHtmlWindowMouseHelper::HandleMouseMoved() +{ + m_tmpMouseMoved = true; +} + +bool wxHtmlWindowMouseHelper::HandleMouseClick(wxHtmlCell *rootCell, + const wxPoint& pos, + const wxMouseEvent& event) +{ + if (!rootCell) + return false; + + wxHtmlCell *cell = rootCell->FindCellByPos(pos.x, pos.y); + // this check is needed because FindCellByPos returns terminal cell and + // containers may have empty borders -- in this case NULL will be + // returned + if (!cell) + return false; + + // adjust the coordinates to be relative to this cell: + wxPoint relpos = pos - cell->GetAbsPos(rootCell); + + return OnCellClicked(cell, relpos.x, relpos.y, event); +} + +void wxHtmlWindowMouseHelper::HandleIdle(wxHtmlCell *rootCell, + const wxPoint& pos) +{ + wxHtmlCell *cell = rootCell ? rootCell->FindCellByPos(pos.x, pos.y) : NULL; + + if (cell != m_tmpLastCell) + { + wxHtmlLinkInfo *lnk = NULL; + if (cell) + { + // adjust the coordinates to be relative to this cell: + wxPoint relpos = pos - cell->GetAbsPos(rootCell); + lnk = cell->GetLink(relpos.x, relpos.y); + } + + wxCursor cur; + if (cell) + cur = cell->GetCursor(); + else + cur = *wxSTANDARD_CURSOR; + m_interface->GetHTMLWindow()->SetCursor(cur); + + if (lnk != m_tmpLastLink) + { + if (lnk) + m_interface->SetHTMLStatusText(lnk->GetHref()); + else + m_interface->SetHTMLStatusText(wxEmptyString); + + m_tmpLastLink = lnk; + } + + m_tmpLastCell = cell; + } + else // mouse moved but stayed in the same cell + { + if ( cell ) + { + OnCellMouseHover(cell, pos.x, pos.y); + } + } + + m_tmpMouseMoved = false; +} + +bool wxHtmlWindowMouseHelper::OnCellClicked(wxHtmlCell *cell, + wxCoord x, wxCoord y, + const wxMouseEvent& event) +{ + wxCHECK_MSG( cell, false, _T("can't be called with NULL cell") ); + + return cell->ProcessMouseClick(m_interface, wxPoint(x, y), event); +} + +void wxHtmlWindowMouseHelper::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell), + wxCoord WXUNUSED(x), + wxCoord WXUNUSED(y)) +{ + // do nothing here +} + //----------------------------------------------------------------------------- // wxHtmlWindow //----------------------------------------------------------------------------- @@ -147,9 +245,6 @@ WX_DEFINE_LIST(wxHtmlProcessorList) void wxHtmlWindow::Init() { - m_tmpMouseMoved = false; - m_tmpLastLink = NULL; - m_tmpLastCell = NULL; m_tmpCanDrawLocks = 0; m_FS = new wxFileSystem(); #if wxUSE_STATUSBAR @@ -836,21 +931,6 @@ void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link) LoadPage(link.GetHref()); } -void wxHtmlWindow::OnCellClicked(wxHtmlCell *cell, - wxCoord x, wxCoord y, - const wxMouseEvent& event) -{ - wxCHECK_RET( cell, _T("can't be called with NULL cell") ); - - cell->OnMouseClick(this, x, y, event); -} - -void wxHtmlWindow::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell), - wxCoord WXUNUSED(x), wxCoord WXUNUSED(y)) -{ - // do nothing here -} - void wxHtmlWindow::OnEraseBackground(wxEraseEvent& event) { if ( !m_bmpBg.Ok() ) @@ -994,7 +1074,7 @@ void wxHtmlWindow::OnSize(wxSizeEvent& event) void wxHtmlWindow::OnMouseMove(wxMouseEvent& WXUNUSED(event)) { - m_tmpMouseMoved = true; + wxHtmlWindowMouseHelper::HandleMouseMoved(); } void wxHtmlWindow::OnMouseDown(wxMouseEvent& event) @@ -1048,17 +1128,9 @@ void wxHtmlWindow::OnMouseUp(wxMouseEvent& event) #endif // wxUSE_CLIPBOARD SetFocus(); - if ( m_Cell ) - { - wxPoint pos = CalcUnscrolledPosition(event.GetPosition()); - wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y); - // check is needed because FindCellByPos returns terminal cell and - // containers may have empty borders -- in this case NULL will be - // returned - if ( cell ) - OnCellClicked(cell, pos.x, pos.y, event); - } + wxPoint pos = CalcUnscrolledPosition(event.GetPosition()); + wxHtmlWindowMouseHelper::HandleMouseClick(m_Cell, pos, event); } @@ -1067,7 +1139,7 @@ void wxHtmlWindow::OnInternalIdle() { wxWindow::OnInternalIdle(); - if (m_tmpMouseMoved && (m_Cell != NULL)) + if (m_Cell != NULL && DidMouseMove()) { #ifdef DEBUG_HTML_SELECTION Refresh(); @@ -1184,44 +1256,14 @@ void wxHtmlWindow::OnInternalIdle() } // handle cursor and status bar text changes: - if ( cell != m_tmpLastCell ) - { - wxHtmlLinkInfo *lnk = cell ? cell->GetLink(x, y) : NULL; - wxCursor cur; - if (cell) - cur = cell->GetCursor(); - else - cur = *wxSTANDARD_CURSOR; - SetCursor(cur); - - if (lnk != m_tmpLastLink) - { -#if wxUSE_STATUSBAR - if (lnk == NULL) - { - if (m_RelatedStatusBar != -1) - m_RelatedFrame->SetStatusText(wxEmptyString, - m_RelatedStatusBar); - } - else - { - if (m_RelatedStatusBar != -1) - m_RelatedFrame->SetStatusText(lnk->GetHref(), - m_RelatedStatusBar); - } -#endif // wxUSE_STATUSBAR - m_tmpLastLink = lnk; - } - - m_tmpLastCell = cell; - } - else // mouse moved but stayed in the same cell - { - if ( cell ) - OnCellMouseHover(cell, x, y); - } - m_tmpMouseMoved = false; + // NB: because we're passing in 'cell' and not 'm_Cell' (so that the + // leaf cell lookup isn't done twice), we need to adjust the + // position for the new root: + wxPoint posInCell(x, y); + if (cell) + posInCell -= cell->GetAbsPos(); + wxHtmlWindowMouseHelper::HandleIdle(cell, posInCell); } } @@ -1460,9 +1502,65 @@ BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow) #endif // wxUSE_CLIPBOARD END_EVENT_TABLE() +//----------------------------------------------------------------------------- +// wxHtmlWindowInterface implementation in wxHtmlWindow +//----------------------------------------------------------------------------- + +void wxHtmlWindow::SetHTMLWindowTitle(const wxString& title) +{ + OnSetTitle(title); +} + +void wxHtmlWindow::OnHTMLLinkClicked(const wxHtmlLinkInfo& link) +{ + OnLinkClicked(link); +} + +wxHtmlOpeningStatus wxHtmlWindow::OnHTMLOpeningURL(wxHtmlURLType type, + const wxString& url, + wxString *redirect) const +{ + return OnOpeningURL(type, url, redirect); +} + +wxPoint wxHtmlWindow::HTMLCoordsToWindow(wxHtmlCell *WXUNUSED(cell), + const wxPoint& pos) const +{ + return CalcScrolledPosition(pos); +} + +wxWindow* wxHtmlWindow::GetHTMLWindow() +{ + return this; +} + +wxColour wxHtmlWindow::GetHTMLBackgroundColour() const +{ + return GetBackgroundColour(); +} + +void wxHtmlWindow::SetHTMLBackgroundColour(const wxColour& clr) +{ + SetBackgroundColour(clr); +} + +void wxHtmlWindow::SetHTMLBackgroundImage(const wxBitmap& bmpBg) +{ + SetBackgroundImage(bmpBg); +} +void wxHtmlWindow::SetHTMLStatusText(const wxString& text) +{ +#if wxUSE_STATUSBAR + if (m_RelatedStatusBar != -1) + m_RelatedFrame->SetStatusText(text, m_RelatedStatusBar); +#endif // wxUSE_STATUSBAR +} +//----------------------------------------------------------------------------- +// wxHtmlWinModule +//----------------------------------------------------------------------------- // A module to allow initialization/cleanup // without calling these functions from app.cpp or from diff --git a/src/html/htmprint.cpp b/src/html/htmprint.cpp index b6a1bc636d..63054b2544 100644 --- a/src/html/htmprint.cpp +++ b/src/html/htmprint.cpp @@ -45,7 +45,7 @@ wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject() m_DC = NULL; m_Width = m_Height = 0; m_Cells = NULL; - m_Parser = new wxHtmlWinParser(NULL); + m_Parser = new wxHtmlWinParser(); m_FS = new wxFileSystem(); m_Parser->SetFS(m_FS); } diff --git a/src/html/m_image.cpp b/src/html/m_image.cpp index 9574b94d41..3182825232 100644 --- a/src/html/m_image.cpp +++ b/src/html/m_image.cpp @@ -286,7 +286,7 @@ const wxHtmlCell *wxHtmlImageMapCell::Find( int cond, const void *param ) const class wxHtmlImageCell : public wxHtmlCell { public: - wxHtmlImageCell(wxWindow *window, + wxHtmlImageCell(wxHtmlWindowInterface *windowIface, wxFSFile *input, int w = wxDefaultCoord, int h = wxDefaultCoord, double scale = 1.0, int align = wxHTML_ALIGN_BOTTOM, const wxString& mapname = wxEmptyString); @@ -305,7 +305,7 @@ private: wxBitmap *m_bitmap; int m_bmpW, m_bmpH; bool m_showFrame:1; - wxScrolledWindow *m_window; + wxHtmlWindowInterface *m_windowIface; #if wxUSE_GIF && wxUSE_TIMER wxGIFDecoder *m_gifDecoder; wxTimer *m_gifTimer; @@ -341,11 +341,12 @@ class wxGIFTimer : public wxTimer //---------------------------------------------------------------------------- -wxHtmlImageCell::wxHtmlImageCell(wxWindow *window, wxFSFile *input, +wxHtmlImageCell::wxHtmlImageCell(wxHtmlWindowInterface *windowIface, + wxFSFile *input, int w, int h, double scale, int align, const wxString& mapname) : wxHtmlCell() { - m_window = window ? wxStaticCast(window, wxScrolledWindow) : NULL; + m_windowIface = windowIface; m_scale = scale; m_showFrame = false; m_bitmap = NULL; @@ -370,8 +371,9 @@ wxHtmlImageCell::wxHtmlImageCell(wxWindow *window, wxFSFile *input, { #if wxUSE_GIF && wxUSE_TIMER bool readImg = true; - if ( (input->GetLocation().Matches(wxT("*.gif")) || - input->GetLocation().Matches(wxT("*.GIF"))) && m_window ) + if ( m_windowIface && + (input->GetLocation().Matches(wxT("*.gif")) || + input->GetLocation().Matches(wxT("*.GIF"))) ) { m_gifDecoder = new wxGIFDecoder(s, true); if ( m_gifDecoder->ReadGIF() == wxGIF_OK ) @@ -492,11 +494,12 @@ void wxHtmlImageCell::AdvanceAnimation(wxTimer *timer) } } - int x, y; - m_window->CalcScrolledPosition(m_physX, m_physY, &x, &y); - wxRect rect(x, y, m_Width, m_Height); + wxWindow *win = m_windowIface->GetHTMLWindow(); + wxPoint pos = + m_windowIface->HTMLCoordsToWindow(this, wxPoint(m_physX, m_physY)); + wxRect rect(pos, wxSize(m_Width, m_Height)); - if ( m_window->GetClientRect().Intersects(rect) && + if ( win->GetClientRect().Intersects(rect) && m_gifDecoder->ConvertToImage(&img) ) { #if !defined(__WXMSW__) || wxUSE_WXDIB @@ -511,9 +514,9 @@ void wxHtmlImageCell::AdvanceAnimation(wxTimer *timer) true /* use mask */); } else -#endif +#endif SetImage(img); - m_window->Refresh(img.HasMask(), &rect); + win->Refresh(img.HasMask(), &rect); } timer->Start(m_gifDecoder->GetDelay(), true); @@ -645,7 +648,7 @@ TAG_HANDLER_BEGIN(IMG, "IMG,MAP,AREA") } } wxHtmlImageCell *cel = new wxHtmlImageCell( - m_WParser->GetWindow(), + m_WParser->GetWindowInterface(), str, w, h, m_WParser->GetPixelScale(), al, mn); diff --git a/src/html/m_layout.cpp b/src/html/m_layout.cpp index d9d76f6f6f..0bc14503f7 100644 --- a/src/html/m_layout.cpp +++ b/src/html/m_layout.cpp @@ -289,21 +289,19 @@ TAG_HANDLER_BEGIN(TITLE, "TITLE") TAG_HANDLER_PROC(tag) { - if (m_WParser->GetWindow()) + wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface(); + if (winIface) { - wxHtmlWindow *wfr = (wxHtmlWindow*)(m_WParser->GetWindow()); - if (wfr) - { - wxString title = m_WParser->GetSource()->Mid( - tag.GetBeginPos(), - tag.GetEndPos1()-tag.GetBeginPos()); + wxString title = m_WParser->GetSource()->Mid( + tag.GetBeginPos(), + tag.GetEndPos1()-tag.GetBeginPos()); #if !wxUSE_UNICODE && wxUSE_WCHAR_T - wxCSConv conv(m_WParser->GetInputEncoding()); - title = wxString(title.wc_str(conv), wxConvLocal); + wxCSConv conv(m_WParser->GetInputEncoding()); + title = wxString(title.wc_str(conv), wxConvLocal); #endif - title = m_WParser->GetEntitiesParser()->Parse(title); - wfr->OnSetTitle(title); - } + title = m_WParser->GetEntitiesParser()->Parse(title); + + winIface->SetHTMLWindowTitle(title); } return true; } @@ -329,6 +327,11 @@ TAG_HANDLER_BEGIN(BODY, "BODY") if (tag.GetParamAsColour(wxT("LINK"), &clr)) m_WParser->SetLinkColor(clr); + wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface(); + // the rest of this function requires a window: + if ( !winIface ) + return false; + if (tag.HasParam(wxT("BACKGROUND"))) { wxFSFile *fileBgImage = m_WParser->OpenURL @@ -344,8 +347,8 @@ TAG_HANDLER_BEGIN(BODY, "BODY") #if !defined(__WXMSW__) || wxUSE_WXDIB wxImage image(*is); if ( image.Ok() ) - m_WParser->GetWindow()->SetBackgroundImage(image); -#endif + winIface->SetHTMLBackgroundImage(image); +#endif } } } @@ -354,8 +357,7 @@ TAG_HANDLER_BEGIN(BODY, "BODY") { m_WParser->GetContainer()->InsertCell( new wxHtmlColourCell(clr, wxHTML_CLR_BACKGROUND)); - if (m_WParser->GetWindow() != NULL) - m_WParser->GetWindow()->SetBackgroundColour(clr); + winIface->SetHTMLBackgroundColour(clr); } return false; diff --git a/src/html/winpars.cpp b/src/html/winpars.cpp index 265572a844..352ba3e0cc 100644 --- a/src/html/winpars.cpp +++ b/src/html/winpars.cpp @@ -38,11 +38,11 @@ IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser, wxHtmlParser) wxList wxHtmlWinParser::m_Modules; -wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindow *wnd) : wxHtmlParser() +wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindowInterface *wndIface) { m_tmpStrBuf = NULL; m_tmpStrBufSize = 0; - m_Window = wnd; + m_windowInterface = wndIface; m_Container = NULL; m_DC = NULL; m_CharHeight = m_CharWidth = 0; @@ -212,11 +212,18 @@ void wxHtmlWinParser::InitParser(const wxString& source) m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor)); wxColour windowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) ; - m_Container->InsertCell( - new wxHtmlColourCell(GetWindow() ? - GetWindow()->GetBackgroundColour() : - windowColour, - wxHTML_CLR_BACKGROUND)); + + m_Container->InsertCell + ( + new wxHtmlColourCell + ( + m_windowInterface + ? m_windowInterface->GetHTMLBackgroundColour() + : windowColour, + wxHTML_CLR_BACKGROUND + ) + ); + m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont())); } @@ -229,6 +236,15 @@ void wxHtmlWinParser::DoneParser() wxHtmlParser::DoneParser(); } +#if WXWIN_COMPATIBILITY_2_6 +wxHtmlWindow *wxHtmlWinParser::GetWindow() +{ + if (!m_windowInterface) + return NULL; + return wxDynamicCast(m_windowInterface->GetHTMLWindow(), wxHtmlWindow); +} +#endif + wxObject* wxHtmlWinParser::GetProduct() { wxHtmlContainerCell *top; @@ -246,58 +262,56 @@ wxObject* wxHtmlWinParser::GetProduct() wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type, const wxString& url) const { - if ( m_Window ) + if ( !m_windowInterface ) + return wxHtmlParser::OpenURL(type, url); + + wxString myurl(url); + wxHtmlOpeningStatus status; + for (;;) { - wxString myurl(url); - wxHtmlOpeningStatus status; - for (;;) - { - wxString myfullurl(myurl); + wxString myfullurl(myurl); - // consider url as absolute path first - wxURI current(myurl); - myfullurl = current.BuildUnescapedURI(); + // consider url as absolute path first + wxURI current(myurl); + myfullurl = current.BuildUnescapedURI(); - // if not absolute then ... - if( current.IsReference() ) - { - wxString basepath = GetFS()->GetPath(); - wxURI base(basepath); + // if not absolute then ... + if( current.IsReference() ) + { + wxString basepath = GetFS()->GetPath(); + wxURI base(basepath); - // ... try to apply base path if valid ... - if( !base.IsReference() ) - { - wxURI path(myfullurl); - path.Resolve( base ); - myfullurl = path.BuildUnescapedURI(); - } - else + // ... try to apply base path if valid ... + if( !base.IsReference() ) + { + wxURI path(myfullurl); + path.Resolve( base ); + myfullurl = path.BuildUnescapedURI(); + } + else + { + // ... or force such addition if not included already + if( !current.GetPath().Contains(base.GetPath()) ) { - // ... or force such addition if not included already - if( !current.GetPath().Contains(base.GetPath()) ) - { - basepath += myurl; - wxURI connected( basepath ); - myfullurl = connected.BuildUnescapedURI(); - } + basepath += myurl; + wxURI connected( basepath ); + myfullurl = connected.BuildUnescapedURI(); } } - - wxString redirect; - status = m_Window->OnOpeningURL(type, myfullurl, &redirect); - if ( status != wxHTML_REDIRECT ) - break; - - myurl = redirect; } - if ( status == wxHTML_BLOCK ) - return NULL; + wxString redirect; + status = m_windowInterface->OnHTMLOpeningURL(type, myfullurl, &redirect); + if ( status != wxHTML_REDIRECT ) + break; - return GetFS()->OpenFile(myurl); + myurl = redirect; } - return wxHtmlParser::OpenURL(type, url); + if ( status == wxHTML_BLOCK ) + return NULL; + + return GetFS()->OpenFile(myurl); } void wxHtmlWinParser::AddText(const wxChar* txt)