Add support for searching and highlighting a wxWebView.
Currently supports WebView on GTK and IE. Closes #14045. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72390 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
de3d7096fe
commit
66ac040060
@ -535,6 +535,7 @@ All:
|
||||
|
||||
All (GUI):
|
||||
|
||||
- Add support for searching in wxWebView for MSW and GTK (Allonii).
|
||||
- Respect window max size in wxBoxSizer (Nathan Ridge).
|
||||
- Add possibility to hide and show again wxRibbonBar pages (wxBen).
|
||||
- Add wxRibbonBar pages highlighting (wxBen).
|
||||
|
@ -96,6 +96,9 @@ public:
|
||||
virtual void Undo();
|
||||
virtual void Redo();
|
||||
|
||||
//Find function
|
||||
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT);
|
||||
|
||||
//Editing functions
|
||||
virtual void SetEditable(bool enable = true);
|
||||
virtual bool IsEditable() const;
|
||||
@ -142,6 +145,9 @@ private:
|
||||
void SetWebkitZoom(float level);
|
||||
float GetWebkitZoom() const;
|
||||
|
||||
//Find helper function
|
||||
void FindClear();
|
||||
|
||||
// focus event handler: calls GTKUpdateBitmap()
|
||||
void GTKOnFocus(wxFocusEvent& event);
|
||||
|
||||
@ -150,6 +156,12 @@ private:
|
||||
|
||||
wxVector<wxSharedPtr<wxWebViewHandler> > m_handlerList;
|
||||
|
||||
//variables used for Find()
|
||||
int m_findFlags;
|
||||
wxString m_findText;
|
||||
int m_findPosition;
|
||||
int m_findCount;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(wxWebViewWebKit);
|
||||
};
|
||||
|
||||
|
@ -244,10 +244,13 @@ public:
|
||||
/* END OF MSHTMHST.H implementation */
|
||||
|
||||
struct IHTMLDocument2;
|
||||
struct IHTMLElement;
|
||||
struct IMarkupPointer;
|
||||
class wxFSFile;
|
||||
class ClassFactory;
|
||||
class wxIEContainer;
|
||||
class DocHostUIHandler;
|
||||
class wxFindPointers;
|
||||
|
||||
class WXDLLIMPEXP_WEBVIEW wxWebViewIE : public wxWebView
|
||||
{
|
||||
@ -320,6 +323,9 @@ public:
|
||||
virtual void Undo();
|
||||
virtual void Redo();
|
||||
|
||||
//Find function
|
||||
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT);
|
||||
|
||||
//Editing functions
|
||||
virtual void SetEditable(bool enable = true);
|
||||
virtual bool IsEditable() const;
|
||||
@ -384,10 +390,21 @@ private:
|
||||
bool m_historyLoadingFromList;
|
||||
bool m_historyEnabled;
|
||||
|
||||
//Generic helper functions for IHtmlDocument commands
|
||||
//We store find flag, results and position.
|
||||
wxVector<wxFindPointers> m_findPointers;
|
||||
int m_findFlags;
|
||||
wxString m_findText;
|
||||
int m_findPosition;
|
||||
|
||||
//Generic helper functions
|
||||
bool CanExecCommand(wxString command) const;
|
||||
void ExecCommand(wxString command);
|
||||
wxCOMPtr<IHTMLDocument2> GetDocument() const;
|
||||
bool IsElementVisible(IHTMLElement* elm);
|
||||
//Find helper functions.
|
||||
void FindInternal(const wxString& text, int flags, int internal_flag);
|
||||
long FindNext(int direction = 1);
|
||||
void FindClear();
|
||||
//Toggles control features see INTERNETFEATURELIST for values.
|
||||
bool EnableControlFeature(long flag, bool enable = true);
|
||||
|
||||
@ -517,6 +534,18 @@ public:
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
};
|
||||
|
||||
class wxFindPointers
|
||||
{
|
||||
public:
|
||||
wxFindPointers(IMarkupPointer *ptrBegin, IMarkupPointer *ptrEnd)
|
||||
{
|
||||
begin = ptrBegin;
|
||||
end = ptrEnd;
|
||||
}
|
||||
//The two markup pointers.
|
||||
IMarkupPointer *begin, *end;
|
||||
};
|
||||
|
||||
#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE && defined(__WXMSW__)
|
||||
|
||||
#endif // wxWebViewIE_H
|
||||
|
@ -86,6 +86,9 @@ public:
|
||||
virtual void Undo();
|
||||
virtual void Redo();
|
||||
|
||||
//Find function
|
||||
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT) { return wxNOT_FOUND; };
|
||||
|
||||
//Clipboard functions
|
||||
virtual bool CanCut() const { return true; }
|
||||
virtual bool CanCopy() const { return true; }
|
||||
|
@ -68,6 +68,16 @@ enum wxWebViewReloadFlags
|
||||
wxWEB_VIEW_RELOAD_NO_CACHE
|
||||
};
|
||||
|
||||
enum wxWebViewFindFlags
|
||||
{
|
||||
wxWEB_VIEW_FIND_WRAP = 0x0001,
|
||||
wxWEB_VIEW_FIND_ENTIRE_WORD = 0x0002,
|
||||
wxWEB_VIEW_FIND_MATCH_CASE = 0x0004,
|
||||
wxWEB_VIEW_FIND_HIGHLIGHT_RESULT = 0x0008,
|
||||
wxWEB_VIEW_FIND_BACKWARDS = 0x0010,
|
||||
wxWEB_VIEW_FIND_DEFAULT = 0
|
||||
};
|
||||
|
||||
enum wxWebViewBackend
|
||||
{
|
||||
wxWEB_VIEW_BACKEND_DEFAULT,
|
||||
@ -181,6 +191,8 @@ public:
|
||||
|
||||
//Get the pointer to the underlying native engine.
|
||||
virtual void* GetNativeBackend() const = 0;
|
||||
//Find function
|
||||
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT) = 0;
|
||||
|
||||
protected:
|
||||
virtual void DoSetPage(const wxString& html, const wxString& baseUrl) = 0;
|
||||
|
@ -69,6 +69,30 @@ enum wxWebViewReloadFlags
|
||||
wxWEB_VIEW_RELOAD_NO_CACHE
|
||||
};
|
||||
|
||||
/**
|
||||
Find flags used when searching for text on page.
|
||||
*/
|
||||
enum wxWebViewFindFlags
|
||||
{
|
||||
/** Causes the search to restart when end or beginning reached */
|
||||
wxWEB_VIEW_FIND_WRAP = 0x0001,
|
||||
|
||||
/** Matches an entire word when searching */
|
||||
wxWEB_VIEW_FIND_ENTIRE_WORD = 0x0002,
|
||||
|
||||
/** Match case, i.e. case sensitive searching */
|
||||
wxWEB_VIEW_FIND_MATCH_CASE = 0x0004,
|
||||
|
||||
/** Highlights the search results */
|
||||
wxWEB_VIEW_FIND_HIGHLIGHT_RESULT = 0x0008,
|
||||
|
||||
/** Searches for phrase in backward direction */
|
||||
wxWEB_VIEW_FIND_BACKWARDS = 0x0010,
|
||||
|
||||
/** The default flag, which is simple searching */
|
||||
wxWEB_VIEW_FIND_DEFAULT = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* List of available backends for wxWebView
|
||||
*/
|
||||
@ -572,6 +596,30 @@ public:
|
||||
*/
|
||||
virtual void Undo() = 0;
|
||||
|
||||
/**
|
||||
@name Finding
|
||||
*/
|
||||
|
||||
/**
|
||||
Finds a phrase on the current page and if found, the control will
|
||||
scroll the phrase into view and select it.
|
||||
@param text The phrase to search for.
|
||||
@param flags The flags for the search.
|
||||
@return If search phrase was not found in combination with the flags
|
||||
then @c wxNOT_FOUND is returned. If called for the first time
|
||||
with search phrase then the total number of results will be
|
||||
returned. Then for every time its called with the same search
|
||||
phrase it will return the number of the current match.
|
||||
@note This function will restart the search if the flags
|
||||
@c wxWEB_VIEW_FIND_ENTIRE_WORD or @c wxWEB_VIEW_FIND_MATCH_CASE
|
||||
are changed, since this will require a new search. To reset the
|
||||
search, for example reseting the highlights call the function
|
||||
with an empty search phrase. This always returns @c wxNOT_FOUND
|
||||
on the OSX WebKit backend.
|
||||
@since 2.9.5
|
||||
*/
|
||||
virtual long Find(const wxString& text, wxWebViewFindFlags flags = wxWEB_VIEW_FIND_DEFAULT) = 0;
|
||||
|
||||
/**
|
||||
@name Zoom
|
||||
*/
|
||||
|
@ -136,6 +136,10 @@ public:
|
||||
void OnDeleteSelection(wxCommandEvent& evt);
|
||||
void OnSelectAll(wxCommandEvent& evt);
|
||||
void OnLoadScheme(wxCommandEvent& evt);
|
||||
void OnFind(wxCommandEvent& evt);
|
||||
void OnFindDone(wxCommandEvent& evt);
|
||||
void OnFindText(wxCommandEvent& evt);
|
||||
void OnFindOptions(wxCommandEvent& evt);
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_url;
|
||||
@ -148,6 +152,15 @@ private:
|
||||
wxToolBarToolBase* m_toolbar_reload;
|
||||
wxToolBarToolBase* m_toolbar_tools;
|
||||
|
||||
wxToolBarToolBase* m_find_toolbar_done;
|
||||
wxToolBarToolBase* m_find_toolbar_next;
|
||||
wxToolBarToolBase* m_find_toolbar_previous;
|
||||
wxToolBarToolBase* m_find_toolbar_options;
|
||||
wxMenuItem* m_find_toolbar_wrap;
|
||||
wxMenuItem* m_find_toolbar_highlight;
|
||||
wxMenuItem* m_find_toolbar_matchcase;
|
||||
wxMenuItem* m_find_toolbar_wholeword;
|
||||
|
||||
wxMenu* m_tools_menu;
|
||||
wxMenu* m_tools_history_menu;
|
||||
wxMenuItem* m_tools_layout;
|
||||
@ -171,11 +184,16 @@ private:
|
||||
wxMenuItem* m_scroll_page_down;
|
||||
wxMenuItem* m_selection_clear;
|
||||
wxMenuItem* m_selection_delete;
|
||||
wxMenuItem* m_find;
|
||||
|
||||
wxInfoBar *m_info;
|
||||
wxStaticText* m_info_text;
|
||||
wxTextCtrl* m_find_ctrl;
|
||||
wxToolBar* m_find_toolbar;
|
||||
|
||||
wxMenuHistoryMap m_histMenuItems;
|
||||
wxString m_findText;
|
||||
int m_findFlags, m_findCount;
|
||||
};
|
||||
|
||||
class SourceViewDialog : public wxDialog
|
||||
@ -240,6 +258,47 @@ WebFrame::WebFrame(const wxString& url) :
|
||||
|
||||
m_toolbar->Realize();
|
||||
|
||||
// Set find values.
|
||||
m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
|
||||
m_findText = wxEmptyString;
|
||||
m_findCount = 0;
|
||||
|
||||
// Create panel for find toolbar.
|
||||
wxPanel* panel = new wxPanel(this);
|
||||
topsizer->Add(panel, wxSizerFlags().Expand());
|
||||
|
||||
// Create sizer for panel.
|
||||
wxBoxSizer* panel_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
panel->SetSizer(panel_sizer);
|
||||
|
||||
// Create the find toolbar.
|
||||
m_find_toolbar = new wxToolBar(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL|wxTB_TEXT|wxTB_HORZ_LAYOUT);
|
||||
m_find_toolbar->Hide();
|
||||
panel_sizer->Add(m_find_toolbar, wxSizerFlags().Expand());
|
||||
|
||||
// Create find control.
|
||||
m_find_ctrl = new wxTextCtrl(m_find_toolbar, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(140,-1), wxTE_PROCESS_ENTER);
|
||||
|
||||
|
||||
//Find options menu
|
||||
wxMenu* findmenu = new wxMenu;
|
||||
m_find_toolbar_wrap = findmenu->AppendCheckItem(wxID_ANY,"Wrap");
|
||||
m_find_toolbar_matchcase = findmenu->AppendCheckItem(wxID_ANY,"Match Case");
|
||||
m_find_toolbar_wholeword = findmenu->AppendCheckItem(wxID_ANY,"Entire Word");
|
||||
m_find_toolbar_highlight = findmenu->AppendCheckItem(wxID_ANY,"Highlight");
|
||||
// Add find toolbar tools.
|
||||
m_find_toolbar->SetToolSeparation(7);
|
||||
m_find_toolbar_done = m_find_toolbar->AddTool(wxID_ANY, "Close", wxArtProvider::GetBitmap(wxART_CROSS_MARK));
|
||||
m_find_toolbar->AddSeparator();
|
||||
m_find_toolbar->AddControl(m_find_ctrl, "Find");
|
||||
m_find_toolbar->AddSeparator();
|
||||
m_find_toolbar_next = m_find_toolbar->AddTool(wxID_ANY, "Next", wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR, wxSize(16,16)));
|
||||
m_find_toolbar_previous = m_find_toolbar->AddTool(wxID_ANY, "Previous", wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR, wxSize(16,16)));
|
||||
m_find_toolbar->AddSeparator();
|
||||
m_find_toolbar_options = m_find_toolbar->AddTool(wxID_ANY, "Options", wxArtProvider::GetBitmap(wxART_PLUS, wxART_TOOLBAR, wxSize(16,16)), "", wxITEM_DROPDOWN);
|
||||
m_find_toolbar_options->SetDropdownMenu(findmenu);
|
||||
m_find_toolbar->Realize();
|
||||
|
||||
// Create the info panel
|
||||
m_info = new wxInfoBar(this);
|
||||
topsizer->Add(m_info, wxSizerFlags().Expand());
|
||||
@ -275,6 +334,10 @@ WebFrame::WebFrame(const wxString& url) :
|
||||
m_tools_handle_new_window = m_tools_menu->AppendCheckItem(wxID_ANY, _("Handle New Windows"));
|
||||
m_tools_menu->AppendSeparator();
|
||||
|
||||
//Find
|
||||
m_find = m_tools_menu->Append(wxID_ANY, _("Find"));
|
||||
m_tools_menu->AppendSeparator();
|
||||
|
||||
//History menu
|
||||
m_tools_history_menu = new wxMenu();
|
||||
wxMenuItem* clearhist = m_tools_history_menu->Append(wxID_ANY, _("Clear History"));
|
||||
@ -339,6 +402,20 @@ WebFrame::WebFrame(const wxString& url) :
|
||||
Connect(m_url->GetId(), wxEVT_COMMAND_TEXT_ENTER,
|
||||
wxCommandEventHandler(WebFrame::OnUrl), NULL, this );
|
||||
|
||||
// Connect find toolbar events.
|
||||
Connect(m_find_toolbar_done->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
|
||||
wxCommandEventHandler(WebFrame::OnFindDone), NULL, this );
|
||||
Connect(m_find_toolbar_next->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
|
||||
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
|
||||
Connect(m_find_toolbar_previous->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
|
||||
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
|
||||
|
||||
// Connect find control events.
|
||||
Connect(m_find_ctrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
|
||||
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
|
||||
Connect(m_find_ctrl->GetId(), wxEVT_COMMAND_TEXT_ENTER,
|
||||
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
|
||||
|
||||
// Connect the webview events
|
||||
Connect(m_browser->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
|
||||
wxWebViewEventHandler(WebFrame::OnNavigationRequest), NULL, this);
|
||||
@ -404,6 +481,8 @@ WebFrame::WebFrame(const wxString& url) :
|
||||
wxCommandEventHandler(WebFrame::OnSelectAll), NULL, this );
|
||||
Connect(loadscheme->GetId(), wxEVT_COMMAND_MENU_SELECTED,
|
||||
wxCommandEventHandler(WebFrame::OnLoadScheme), NULL, this );
|
||||
Connect(m_find->GetId(), wxEVT_COMMAND_MENU_SELECTED,
|
||||
wxCommandEventHandler(WebFrame::OnFind), NULL, this );
|
||||
|
||||
//Connect the idle events
|
||||
Connect(wxID_ANY, wxEVT_IDLE, wxIdleEventHandler(WebFrame::OnIdle), NULL, this);
|
||||
@ -549,6 +628,72 @@ void WebFrame::OnLoadScheme(wxCommandEvent& WXUNUSED(evt))
|
||||
m_browser->LoadURL(path);
|
||||
}
|
||||
|
||||
void WebFrame::OnFind(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
wxString value = m_browser->GetSelectedText();
|
||||
if(value.Len() > 150)
|
||||
{
|
||||
value.Truncate(150);
|
||||
}
|
||||
m_find_ctrl->SetValue(value);
|
||||
if(!m_find_toolbar->IsShown()){
|
||||
m_find_toolbar->Show(true);
|
||||
SendSizeEvent();
|
||||
}
|
||||
m_find_ctrl->SelectAll();
|
||||
}
|
||||
|
||||
void WebFrame::OnFindDone(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_browser->Find("");
|
||||
m_find_toolbar->Show(false);
|
||||
SendSizeEvent();
|
||||
}
|
||||
|
||||
void WebFrame::OnFindText(wxCommandEvent& evt)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if(m_find_toolbar_wrap->IsChecked())
|
||||
flags |= wxWEB_VIEW_FIND_WRAP;
|
||||
if(m_find_toolbar_wholeword->IsChecked())
|
||||
flags |= wxWEB_VIEW_FIND_ENTIRE_WORD;
|
||||
if(m_find_toolbar_matchcase->IsChecked())
|
||||
flags |= wxWEB_VIEW_FIND_MATCH_CASE;
|
||||
if(m_find_toolbar_highlight->IsChecked())
|
||||
flags |= wxWEB_VIEW_FIND_HIGHLIGHT_RESULT;
|
||||
|
||||
if(m_find_toolbar_previous->GetId() == evt.GetId())
|
||||
flags |= wxWEB_VIEW_FIND_BACKWARDS;
|
||||
|
||||
wxString find_text = m_find_ctrl->GetValue();
|
||||
long count = m_browser->Find(find_text, flags);
|
||||
|
||||
if(m_findText != find_text)
|
||||
{
|
||||
m_findCount = count;
|
||||
m_findText = find_text;
|
||||
}
|
||||
|
||||
if(count != wxNOT_FOUND || find_text.IsEmpty())
|
||||
{
|
||||
m_find_ctrl->SetBackgroundColour(*wxWHITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_find_ctrl->SetBackgroundColour(wxColour(255, 101, 101));
|
||||
}
|
||||
|
||||
m_find_ctrl->Refresh();
|
||||
|
||||
//Log the result, note that count is zero indexed.
|
||||
if(count != m_findCount)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
wxLogMessage("Searching for:%s current match:%i/%i", m_findText.c_str(), count, m_findCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when there is a request to load a new page (for instance
|
||||
* when the user clicks a link)
|
||||
|
@ -400,6 +400,7 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
|
||||
{
|
||||
m_busy = false;
|
||||
m_guard = false;
|
||||
FindClear();
|
||||
|
||||
// We currently unconditionally impose scrolling in both directions as it's
|
||||
// necessary to show arbitrary pages.
|
||||
@ -927,6 +928,80 @@ void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
||||
m_handlerList.push_back(handler);
|
||||
}
|
||||
|
||||
long wxWebViewWebKit::Find(const wxString& text, int flags)
|
||||
{
|
||||
bool newSearch = false;
|
||||
if(text != m_findText ||
|
||||
(flags & wxWEB_VIEW_FIND_MATCH_CASE) != (m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE))
|
||||
{
|
||||
newSearch = true;
|
||||
//If it is a new search we need to clear existing highlights
|
||||
webkit_web_view_unmark_text_matches(m_web_view);
|
||||
webkit_web_view_set_highlight_text_matches(m_web_view, false);
|
||||
}
|
||||
|
||||
m_findFlags = flags;
|
||||
m_findText = text;
|
||||
|
||||
//If the search string is empty then we clear any selection and highlight
|
||||
if(text == "")
|
||||
{
|
||||
webkit_web_view_unmark_text_matches(m_web_view);
|
||||
webkit_web_view_set_highlight_text_matches(m_web_view, false);
|
||||
ClearSelection();
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
|
||||
bool wrap = false, matchCase = false, forward = true;
|
||||
if(flags & wxWEB_VIEW_FIND_WRAP)
|
||||
wrap = true;
|
||||
if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
|
||||
matchCase = true;
|
||||
if(flags & wxWEB_VIEW_FIND_BACKWARDS)
|
||||
forward = false;
|
||||
|
||||
if(newSearch)
|
||||
{
|
||||
//Initially we mark the matches to know how many we have
|
||||
m_findCount = webkit_web_view_mark_text_matches(m_web_view, wxGTK_CONV(text), matchCase, 0);
|
||||
//In this case we return early to match IE behaviour
|
||||
m_findPosition = -1;
|
||||
return m_findCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(forward)
|
||||
m_findPosition++;
|
||||
else
|
||||
m_findPosition--;
|
||||
if(m_findPosition < 0)
|
||||
m_findPosition += m_findCount;
|
||||
if(m_findPosition > m_findCount)
|
||||
m_findPosition -= m_findCount;
|
||||
}
|
||||
|
||||
//Highlight them if needed
|
||||
bool highlight = flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT ? true : false;
|
||||
webkit_web_view_set_highlight_text_matches(m_web_view, highlight);
|
||||
|
||||
if(!webkit_web_view_search_text(m_web_view, wxGTK_CONV(text), matchCase, forward, wrap))
|
||||
{
|
||||
m_findPosition = -1;
|
||||
ClearSelection();
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
wxLogMessage(wxString::Format("Returning %d", m_findPosition));
|
||||
return newSearch ? m_findCount : m_findPosition;
|
||||
}
|
||||
|
||||
void wxWebViewWebKit::FindClear()
|
||||
{
|
||||
m_findCount = 0;
|
||||
m_findFlags = 0;
|
||||
m_findText = "";
|
||||
m_findPosition = -1;
|
||||
}
|
||||
|
||||
// static
|
||||
wxVisualAttributes
|
||||
wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
|
||||
|
@ -39,6 +39,12 @@ DEFINE_GUID(wxIID_IInternetProtocolRoot,0x79eac9e3,0xbaf9,0x11ce,0x8c,0x82,0,0xa
|
||||
DEFINE_GUID(wxIID_IInternetProtocol,0x79eac9e4,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
|
||||
DEFINE_GUID(wxIID_IDocHostUIHandler, 0xbd3f23c0, 0xd43e, 0x11cf, 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a);
|
||||
|
||||
enum //Internal find flags
|
||||
{
|
||||
wxWEB_VIEW_FIND_ADD_POINTERS = 0x0001,
|
||||
wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT = 0x0002
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView);
|
||||
@ -68,6 +74,7 @@ bool wxWebViewIE::Create(wxWindow* parent,
|
||||
m_historyEnabled = true;
|
||||
m_historyPosition = -1;
|
||||
m_zoomType = wxWEB_VIEW_ZOOM_TYPE_TEXT;
|
||||
FindClear();
|
||||
|
||||
if (::CoCreateInstance(CLSID_WebBrowser, NULL,
|
||||
CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
|
||||
@ -98,6 +105,7 @@ wxWebViewIE::~wxWebViewIE()
|
||||
{
|
||||
m_factories[i]->Release();
|
||||
}
|
||||
FindClear();
|
||||
}
|
||||
|
||||
void wxWebViewIE::LoadURL(const wxString& url)
|
||||
@ -591,6 +599,53 @@ void wxWebViewIE::Redo()
|
||||
ExecCommand("Redo");
|
||||
}
|
||||
|
||||
long wxWebViewIE::Find(const wxString& text, int flags)
|
||||
{
|
||||
//If the text is empty then we clear.
|
||||
if(text.IsEmpty())
|
||||
{
|
||||
ClearSelection();
|
||||
if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
|
||||
{
|
||||
FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
|
||||
}
|
||||
FindClear();
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
//Have we done this search before?
|
||||
if(m_findText == text)
|
||||
{
|
||||
//Just do a highlight?
|
||||
if((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) != (m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT))
|
||||
{
|
||||
m_findFlags = flags;
|
||||
if(!m_findPointers.empty())
|
||||
{
|
||||
FindInternal(m_findText, m_findFlags, ((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) == 0 ? wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT : 0));
|
||||
}
|
||||
return m_findPosition;
|
||||
}
|
||||
else if(((m_findFlags & wxWEB_VIEW_FIND_ENTIRE_WORD) == (flags & wxWEB_VIEW_FIND_ENTIRE_WORD)) && ((m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE) == (flags&wxWEB_VIEW_FIND_MATCH_CASE)))
|
||||
{
|
||||
m_findFlags = flags;
|
||||
return FindNext(((flags & wxWEB_VIEW_FIND_BACKWARDS) ? -1 : 1));
|
||||
}
|
||||
}
|
||||
//Remove old highlight if any.
|
||||
if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
|
||||
{
|
||||
FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
|
||||
}
|
||||
//Reset find variables.
|
||||
FindClear();
|
||||
ClearSelection();
|
||||
m_findText = text;
|
||||
m_findFlags = flags;
|
||||
//find the text and return count.
|
||||
FindInternal(text, flags, wxWEB_VIEW_FIND_ADD_POINTERS);
|
||||
return m_findPointers.empty() ? wxNOT_FOUND : m_findPointers.size();
|
||||
}
|
||||
|
||||
void wxWebViewIE::SetEditable(bool enable)
|
||||
{
|
||||
wxCOMPtr<IHTMLDocument2> document(GetDocument());
|
||||
@ -856,6 +911,232 @@ wxCOMPtr<IHTMLDocument2> wxWebViewIE::GetDocument() const
|
||||
return document;
|
||||
}
|
||||
|
||||
bool wxWebViewIE::IsElementVisible(IHTMLElement* elm)
|
||||
{
|
||||
IHTMLCurrentStyle* style;
|
||||
IHTMLElement *elm1 = elm;
|
||||
IHTMLElement2 *elm2;
|
||||
BSTR tmp_bstr;
|
||||
bool is_visible = true;
|
||||
//This method is not perfect but it does discover most of the hidden elements.
|
||||
//so if a better solution is found, then please do improve.
|
||||
while(elm1)
|
||||
{
|
||||
if(SUCCEEDED(elm1->QueryInterface(IID_IHTMLElement2, (void**) &elm2)))
|
||||
{
|
||||
if(SUCCEEDED(elm2->get_currentStyle(&style)))
|
||||
{
|
||||
//Check if the object has the style display:none.
|
||||
if((style->get_display(&tmp_bstr) != S_OK) ||
|
||||
(tmp_bstr != NULL && (_wcsicmp(tmp_bstr, L"none") == 0)))
|
||||
{
|
||||
is_visible = false;
|
||||
}
|
||||
//Check if the object has the style visibility:hidden.
|
||||
if(is_visible && (style->get_visibility(&tmp_bstr) != S_OK) ||
|
||||
(tmp_bstr != NULL && _wcsicmp(tmp_bstr, L"hidden") == 0))
|
||||
{
|
||||
is_visible = false;
|
||||
}
|
||||
style->Release();
|
||||
}
|
||||
elm2->Release();
|
||||
}
|
||||
|
||||
//Lets check the object's parent element.
|
||||
IHTMLElement* parent;
|
||||
if(is_visible && SUCCEEDED(elm1->get_parentElement(&parent)))
|
||||
{
|
||||
elm1->Release();
|
||||
elm1 = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
elm1->Release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return is_visible;
|
||||
}
|
||||
|
||||
void wxWebViewIE::FindInternal(const wxString& text, int flags, int internal_flag)
|
||||
{
|
||||
IMarkupServices *pIMS;
|
||||
IMarkupContainer *pIMC;
|
||||
IMarkupPointer *ptrBegin, *ptrEnd;
|
||||
IHTMLElement* elm;
|
||||
long find_flag = 0;
|
||||
IHTMLDocument2 *document = GetDocument();
|
||||
//This function does the acutal work.
|
||||
if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices, (void **)&pIMS)))
|
||||
{
|
||||
if(SUCCEEDED(document->QueryInterface(IID_IMarkupContainer, (void **)&pIMC)))
|
||||
{
|
||||
BSTR attr_bstr = SysAllocString(L"style=\"background-color:#ffff00\"");
|
||||
BSTR text_bstr = SysAllocString(text.wc_str());
|
||||
pIMS->CreateMarkupPointer(&ptrBegin);
|
||||
pIMS->CreateMarkupPointer(&ptrEnd);
|
||||
|
||||
ptrBegin->SetGravity(POINTER_GRAVITY_Right);
|
||||
ptrBegin->MoveToContainer(pIMC, TRUE);
|
||||
//Create the find flag from the wx one.
|
||||
if(flags & wxWEB_VIEW_FIND_ENTIRE_WORD)
|
||||
{
|
||||
find_flag |= FINDTEXT_WHOLEWORD;
|
||||
}
|
||||
if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
|
||||
{
|
||||
find_flag |= FINDTEXT_MATCHCASE;
|
||||
}
|
||||
|
||||
//A little speed-up to avoid to re-alloc in the positions vector.
|
||||
if(text.Len() < 3 && m_findPointers.capacity() < 500)
|
||||
{
|
||||
m_findPointers.reserve(text.Len() == 1 ? 1000 : 500);
|
||||
}
|
||||
|
||||
while(ptrBegin->FindText(text_bstr, find_flag, ptrEnd, NULL) == S_OK)
|
||||
{
|
||||
if(ptrBegin->CurrentScope(&elm) == S_OK)
|
||||
{
|
||||
if(IsElementVisible(elm))
|
||||
{
|
||||
//Highlight the word if the flag was set.
|
||||
if(flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
|
||||
{
|
||||
IHTMLElement* pFontEl;
|
||||
pIMS->CreateElement(TAGID_FONT, attr_bstr, &pFontEl);
|
||||
pIMS->InsertElement(pFontEl, ptrBegin, ptrEnd);
|
||||
}
|
||||
if(internal_flag & wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT)
|
||||
{
|
||||
IHTMLElement* pFontEl;
|
||||
ptrBegin->CurrentScope(&pFontEl);
|
||||
pIMS->RemoveElement(pFontEl);
|
||||
pFontEl->Release();
|
||||
}
|
||||
if(internal_flag & wxWEB_VIEW_FIND_ADD_POINTERS)
|
||||
{
|
||||
IMarkupPointer *cptrBegin, *cptrEnd;
|
||||
pIMS->CreateMarkupPointer(&cptrBegin);
|
||||
pIMS->CreateMarkupPointer(&cptrEnd);
|
||||
cptrBegin->MoveToPointer(ptrBegin);
|
||||
cptrEnd->MoveToPointer(ptrEnd);
|
||||
m_findPointers.push_back(wxFindPointers(cptrBegin,cptrEnd));
|
||||
}
|
||||
}
|
||||
elm->Release();
|
||||
}
|
||||
ptrBegin->MoveToPointer(ptrEnd);
|
||||
}
|
||||
//Clean up.
|
||||
SysFreeString(text_bstr);
|
||||
SysFreeString(attr_bstr);
|
||||
pIMC->Release();
|
||||
ptrBegin->Release();
|
||||
ptrEnd->Release();
|
||||
}
|
||||
pIMS->Release();
|
||||
}
|
||||
document->Release();
|
||||
}
|
||||
|
||||
long wxWebViewIE::FindNext(int direction)
|
||||
{
|
||||
//Don't bother if we have no pointers set.
|
||||
if(m_findPointers.empty())
|
||||
{
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
//Manage the find position and do some checks.
|
||||
if(direction > 0)
|
||||
{
|
||||
m_findPosition++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_findPosition--;
|
||||
}
|
||||
|
||||
if(m_findPosition >= (signed)m_findPointers.size())
|
||||
{
|
||||
if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
|
||||
{
|
||||
m_findPosition = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_findPosition--;
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
}
|
||||
else if(m_findPosition < 0)
|
||||
{
|
||||
if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
|
||||
{
|
||||
m_findPosition = m_findPointers.size()-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_findPosition++;
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
}
|
||||
//some variables to use later on.
|
||||
IHTMLElement *body_element;
|
||||
IHTMLBodyElement *body;
|
||||
IHTMLTxtRange *range = NULL;
|
||||
IMarkupServices *pIMS;
|
||||
IHTMLDocument2 *document = GetDocument();
|
||||
long ret = -1;
|
||||
//Now try to create a range from the body.
|
||||
if(SUCCEEDED(document->get_body(&body_element)))
|
||||
{
|
||||
if(SUCCEEDED(body_element->QueryInterface(IID_IHTMLBodyElement,(void**)&body)))
|
||||
{
|
||||
if(SUCCEEDED(body->createTextRange(&range)))
|
||||
{
|
||||
//So far so good, now we try to position our find pointers.
|
||||
if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices,(void **)&pIMS)))
|
||||
{
|
||||
IMarkupPointer *begin = m_findPointers[m_findPosition].begin, *end = m_findPointers[m_findPosition].end;
|
||||
if(pIMS->MoveRangeToPointers(begin,end,range) == S_OK && range->select() == S_OK)
|
||||
{
|
||||
ret = m_findPosition;
|
||||
}
|
||||
pIMS->Release();
|
||||
}
|
||||
range->Release();
|
||||
}
|
||||
body->Release();
|
||||
}
|
||||
body_element->Release();
|
||||
}
|
||||
document->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wxWebViewIE::FindClear()
|
||||
{
|
||||
//Reset find variables.
|
||||
m_findText.Empty();
|
||||
m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
|
||||
m_findPosition = -1;
|
||||
|
||||
//The m_findPointers contains pointers for the found text.
|
||||
//Since it uses ref counting we call release on the pointers first
|
||||
//before we remove them from the vector. In other words do not just
|
||||
//remove elements from m_findPointers without calling release first
|
||||
//or you will get a memory leak.
|
||||
size_t count = m_findPointers.size();
|
||||
for(size_t i = 0; i < count; i++)
|
||||
{
|
||||
m_findPointers[i].begin->Release();
|
||||
m_findPointers[i].end->Release();
|
||||
}
|
||||
m_findPointers.clear();
|
||||
}
|
||||
|
||||
bool wxWebViewIE::EnableControlFeature(long flag, bool enable)
|
||||
{
|
||||
#if wxUSE_DYNLIB_CLASS
|
||||
@ -989,6 +1270,8 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
|
||||
}
|
||||
//Reset as we are done now
|
||||
m_historyLoadingFromList = false;
|
||||
//Reset the find values.
|
||||
FindClear();
|
||||
// TODO: set target parameter if possible
|
||||
wxString target = wxEmptyString;
|
||||
wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),
|
||||
|
Loading…
Reference in New Issue
Block a user