1/*
2 * Copyright (C) 2007 Kevin Ollivier  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * This class provides a default new window implementation for wxWebView clients
26 * who don't want/need to roll their own browser frame UI.
27 */
28
29#include "config.h"
30
31#include "wx/wxprec.h"
32#ifndef WX_PRECOMP
33    #include "wx/wx.h"
34#endif
35
36#include "wx/artprov.h"
37
38#include "WebBrowserShell.h"
39#include "WebFrame.h"
40#include "WebView.h"
41#include "WebViewPrivate.h"
42
43wxPageSourceViewFrame::wxPageSourceViewFrame(const wxString& source)
44        : wxFrame(NULL, wxID_ANY, _("Page Source View"), wxDefaultPosition, wxSize(600, 500))
45{
46    wxTextCtrl* control = new wxTextCtrl(this, -1, source, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
47}
48
49enum {
50    ID_LOADFILE = wxID_HIGHEST + 1,
51    ID_TEXTCTRL = wxID_HIGHEST + 2,
52    ID_BACK = wxID_HIGHEST + 3,
53    ID_FORWARD = wxID_HIGHEST + 4,
54    ID_TOGGLE_BEFORE_LOAD = wxID_HIGHEST + 5,
55    ID_MAKE_TEXT_LARGER = wxID_HIGHEST + 6,
56    ID_MAKE_TEXT_SMALLER = wxID_HIGHEST + 7,
57    ID_STOP = wxID_HIGHEST + 8,
58    ID_RELOAD = wxID_HIGHEST + 9,
59    ID_GET_SOURCE = wxID_HIGHEST + 10,
60    ID_SET_SOURCE = wxID_HIGHEST + 11,
61    ID_SEARCHCTRL = wxID_HIGHEST + 12,
62    ID_LOADURL = wxID_HIGHEST + 13,
63    ID_NEW_WINDOW = wxID_HIGHEST + 14,
64    ID_BROWSE = wxID_HIGHEST + 15,
65    ID_EDIT = wxID_HIGHEST + 16,
66    ID_RUN_SCRIPT = wxID_HIGHEST + 17,
67    ID_WEBVIEW = wxID_HIGHEST + 18,
68    ID_EDIT_COMMAND = wxID_HIGHEST + 19,
69    ID_GET_EDIT_COMMAND_STATE = wxID_HIGHEST + 20
70};
71
72BEGIN_EVENT_TABLE(wxWebBrowserShell, wxFrame)
73    EVT_MENU(wxID_CUT, wxWebBrowserShell::OnCut)
74    EVT_MENU(wxID_COPY, wxWebBrowserShell::OnCopy)
75    EVT_MENU(wxID_PASTE, wxWebBrowserShell::OnPaste)
76    EVT_MENU(wxID_EXIT,  wxWebBrowserShell::OnQuit)
77    EVT_MENU(wxID_ABOUT, wxWebBrowserShell::OnAbout)
78    EVT_MENU(ID_LOADFILE, wxWebBrowserShell::OnLoadFile)
79    EVT_TEXT_ENTER(ID_TEXTCTRL, wxWebBrowserShell::OnAddressBarEnter)
80    EVT_TEXT_ENTER(ID_SEARCHCTRL, wxWebBrowserShell::OnSearchCtrlEnter)
81    EVT_WEBVIEW_LOAD(ID_WEBVIEW, wxWebBrowserShell::OnLoadEvent)
82    EVT_WEBVIEW_BEFORE_LOAD(ID_WEBVIEW, wxWebBrowserShell::OnBeforeLoad)
83    EVT_MENU(ID_BACK, wxWebBrowserShell::OnBack)
84    EVT_MENU(ID_FORWARD, wxWebBrowserShell::OnForward)
85    EVT_MENU(ID_STOP, wxWebBrowserShell::OnStop)
86    EVT_MENU(ID_RELOAD, wxWebBrowserShell::OnReload)
87    EVT_MENU(ID_MAKE_TEXT_LARGER, wxWebBrowserShell::OnMakeTextLarger)
88    EVT_MENU(ID_MAKE_TEXT_SMALLER, wxWebBrowserShell::OnMakeTextSmaller)
89    EVT_MENU(ID_GET_SOURCE, wxWebBrowserShell::OnGetSource)
90    EVT_MENU(ID_SET_SOURCE, wxWebBrowserShell::OnSetSource)
91    EVT_MENU(ID_BROWSE, wxWebBrowserShell::OnBrowse)
92    EVT_MENU(ID_EDIT, wxWebBrowserShell::OnEdit)
93    EVT_MENU(ID_RUN_SCRIPT, wxWebBrowserShell::OnRunScript)
94    EVT_MENU(ID_EDIT_COMMAND, wxWebBrowserShell::OnEditCommand)
95    EVT_MENU(ID_GET_EDIT_COMMAND_STATE, wxWebBrowserShell::OnGetEditCommandState)
96END_EVENT_TABLE()
97
98
99wxWebBrowserShell::wxWebBrowserShell(const wxString& title) :
100        wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600, 500)),
101        m_checkBeforeLoad(false)
102{
103
104    // create a menu bar
105    wxMenu *fileMenu = new wxMenu;
106    fileMenu->Append(ID_NEW_WINDOW, _T("New Window\tCTRL+N"));
107    fileMenu->Append(ID_LOADFILE, _T("Open File...\tCTRL+O"));
108    fileMenu->Append(ID_LOADURL, _("Open Location...\tCTRL+L"));
109    fileMenu->Append(wxID_EXIT, _T("E&xit\tAlt-X"), _T("Quit this program"));
110
111    wxMenu *editMenu = new wxMenu;
112    editMenu->Append(wxID_CUT, _T("Cut\tCTRL+X"));
113    editMenu->Append(wxID_COPY, _T("Copy\tCTRL+C"));
114    editMenu->Append(wxID_PASTE, _T("Paste\tCTRL+V"));
115
116    wxMenu* viewMenu = new wxMenu;
117    viewMenu->AppendRadioItem(ID_BROWSE, _("Browse"));
118    viewMenu->AppendRadioItem(ID_EDIT, _("Edit"));
119    viewMenu->AppendSeparator();
120    viewMenu->Append(ID_STOP, _("Stop"));
121    viewMenu->Append(ID_RELOAD, _("Reload Page"));
122    viewMenu->Append(ID_MAKE_TEXT_SMALLER, _("Make Text Smaller\tCTRL+-"));
123    viewMenu->Append(ID_MAKE_TEXT_LARGER, _("Make Text Bigger\tCTRL++"));
124    viewMenu->AppendSeparator();
125    viewMenu->Append(ID_GET_SOURCE, _("View Page Source"));
126    viewMenu->AppendSeparator();
127
128    m_debugMenu = new wxMenu;
129    m_debugMenu->Append(ID_SET_SOURCE, _("Test SetPageSource"));
130    m_debugMenu->Append(ID_RUN_SCRIPT, _("Test RunScript"));
131    m_debugMenu->Append(ID_EDIT_COMMAND, _("Test EditCommand::Execute"));
132    m_debugMenu->Append(ID_GET_EDIT_COMMAND_STATE, _("Test EditCommand::GetState"));
133
134    // the "About" item should be in the help menu
135    wxMenu *helpMenu = new wxMenu;
136    helpMenu->Append(wxID_ABOUT, _T("&About...\tF1"), _T("Show about dialog"));
137
138    // now append the freshly created menu to the menu bar...
139    wxMenuBar *menuBar = new wxMenuBar();
140    menuBar->Append(fileMenu, _T("&File"));
141    menuBar->Append(editMenu, _T("&Edit"));
142    menuBar->Append(viewMenu, _T("&View"));
143    menuBar->Append(helpMenu, _T("&Help"));
144
145    // ... and attach this menu bar to the frame
146    SetMenuBar(menuBar);
147
148    wxToolBar* toolbar = CreateToolBar();
149    toolbar->SetToolBitmapSize(wxSize(32, 32));
150
151    wxBitmap back = wxArtProvider::GetBitmap(wxART_GO_BACK, wxART_TOOLBAR, wxSize(32,32));
152    toolbar->AddTool(ID_BACK, back, wxT("Back"));
153
154    wxBitmap forward = wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_TOOLBAR, wxSize(32,32));
155    toolbar->AddTool(ID_FORWARD, forward, wxT("Next"));
156
157    addressBar = new wxTextCtrl(toolbar, ID_TEXTCTRL, _T(""), wxDefaultPosition, wxSize(400, -1), wxTE_PROCESS_ENTER);
158    toolbar->AddControl(addressBar);
159
160    searchCtrl = new wxSearchCtrl(toolbar, ID_SEARCHCTRL, _("Search"), wxDefaultPosition, wxSize(200, -1), wxTE_PROCESS_ENTER);
161    toolbar->AddControl(searchCtrl);
162    toolbar->Realize();
163
164    SetToolBar(toolbar);
165
166    // Create the wxWebView Window
167    webview = new wxWebView((wxWindow*)this, ID_WEBVIEW, wxDefaultPosition, wxSize(200, 200));
168    webview->SetBackgroundColour(*wxWHITE);
169
170    // create a status bar just for fun (by default with 1 pane only)
171    CreateStatusBar(2);
172}
173
174wxWebBrowserShell::~wxWebBrowserShell()
175{
176    if (m_debugMenu && GetMenuBar()->FindMenu(_("&Debug")) == wxNOT_FOUND)
177        delete m_debugMenu;
178}
179
180void wxWebBrowserShell::ShowDebugMenu(bool show)
181{
182    int debugMenu = GetMenuBar()->FindMenu(_("&Debug"));
183    if (show && debugMenu == wxNOT_FOUND) {
184        int prevMenu = GetMenuBar()->FindMenu(_("&View"));
185        if (prevMenu != wxNOT_FOUND)
186            GetMenuBar()->Insert((size_t)prevMenu+1, m_debugMenu, _("&Debug"));
187    }
188    else if (!show && debugMenu != wxNOT_FOUND) {
189        GetMenuBar()->Remove(debugMenu);
190    }
191}
192
193// event handlers
194
195void wxWebBrowserShell::OnQuit(wxCommandEvent& WXUNUSED(event))
196{
197    // true is to force the frame to close
198    Close(true);
199}
200
201void wxWebBrowserShell::OnAbout(wxCommandEvent& WXUNUSED(event))
202{
203    wxString msg;
204    msg.Printf(_T("This is the About dialog of the wxWebKit sample.\n")
205               _T("Welcome to %s"), wxVERSION_STRING);
206
207    wxMessageBox(msg, _T("About wxWebKit Sample"), wxOK | wxICON_INFORMATION, this);
208
209}
210
211void wxWebBrowserShell::OnLoadFile(wxCommandEvent& WXUNUSED(event))
212{
213    wxFileDialog* dialog = new wxFileDialog(this, wxT("Choose a file"));
214    if (dialog->ShowModal() == wxID_OK) {
215        wxString path = dialog->GetPath().Prepend(wxT("file://"));
216
217        if (webview)
218            webview->LoadURL(path);
219    }
220}
221
222void wxWebBrowserShell::OnLoadEvent(wxWebViewLoadEvent& event)
223{
224    if (GetStatusBar() != NULL){
225        if (event.GetState() == wxWEBVIEW_LOAD_NEGOTIATING) {
226            GetStatusBar()->SetStatusText(_("Contacting ") + event.GetURL());
227        }
228        else if (event.GetState() == wxWEBVIEW_LOAD_TRANSFERRING) {
229            GetStatusBar()->SetStatusText(_("Loading ") + event.GetURL());
230        }
231        else if (event.GetState() == wxWEBVIEW_LOAD_ONLOAD_HANDLED) {
232            GetStatusBar()->SetStatusText(_("Load complete."));
233            addressBar->SetValue(event.GetURL());
234            SetTitle(webview->GetPageTitle());
235        }
236        else if (event.GetState() == wxWEBVIEW_LOAD_FAILED) {
237            GetStatusBar()->SetStatusText(_("Failed to load ") + event.GetURL());
238        }
239    }
240}
241
242void wxWebBrowserShell::OnBeforeLoad(wxWebViewBeforeLoadEvent& myEvent)
243{
244    if (m_checkBeforeLoad) {
245        int reply = wxMessageBox(_("Would you like to continue loading ") + myEvent.GetURL() + wxT("?"), _("Continue Loading?"), wxYES_NO);
246        if (reply == wxNO) {
247            myEvent.Cancel();
248        }
249    }
250}
251
252void wxWebBrowserShell::OnAddressBarEnter(wxCommandEvent& event)
253{
254    if (webview)
255        webview->LoadURL(addressBar->GetValue());
256}
257
258void wxWebBrowserShell::OnSearchCtrlEnter(wxCommandEvent& event)
259{
260    if (webview) {
261        webview->LoadURL(wxString::Format(wxT("http://www.google.com/search?rls=en&q=%s&ie=UTF-8&oe=UTF-8"), searchCtrl->GetValue().wc_str()));
262    }
263}
264
265void wxWebBrowserShell::OnCut(wxCommandEvent& event)
266{
267    if (webview && webview->CanCut())
268        webview->Cut();
269}
270
271void wxWebBrowserShell::OnCopy(wxCommandEvent& event)
272{
273    if (webview && webview->CanCopy())
274        webview->Copy();
275}
276
277void wxWebBrowserShell::OnPaste(wxCommandEvent& event)
278{
279    if (webview && webview->CanPaste())
280        webview->Paste();
281}
282
283void wxWebBrowserShell::OnBack(wxCommandEvent& event)
284{
285    if (webview)
286        webview->GoBack();
287}
288
289void wxWebBrowserShell::OnForward(wxCommandEvent& event)
290{
291    if (webview)
292        webview->GoForward();
293}
294
295void wxWebBrowserShell::OnStop(wxCommandEvent& myEvent)
296{
297    if (webview)
298        webview->Stop();
299}
300
301void wxWebBrowserShell::OnReload(wxCommandEvent& myEvent)
302{
303    if (webview)
304        webview->Reload();
305}
306
307void wxWebBrowserShell::OnMakeTextLarger(wxCommandEvent& myEvent)
308{
309    if (webview) {
310        if (webview->CanIncreaseTextSize())
311            webview->IncreaseTextSize();
312    }
313}
314
315void wxWebBrowserShell::OnMakeTextSmaller(wxCommandEvent& myEvent)
316{
317    if (webview) {
318        if (webview->CanDecreaseTextSize())
319            webview->DecreaseTextSize();
320    }
321}
322
323void wxWebBrowserShell::OnGetSource(wxCommandEvent& myEvent)
324{
325    if (webview) {
326        wxPageSourceViewFrame* pageSourceFrame = new wxPageSourceViewFrame(webview->GetPageSource());
327        pageSourceFrame->Show();
328    }
329}
330
331void wxWebBrowserShell::OnSetSource(wxCommandEvent& event)
332{
333    if (webview)
334        webview->SetPageSource(wxString(wxT("<p>Hello World!</p>")));
335}
336
337void wxWebBrowserShell::OnBrowse(wxCommandEvent& event)
338{
339    if (webview)
340        webview->MakeEditable(!event.IsChecked());
341}
342
343void wxWebBrowserShell::OnEdit(wxCommandEvent& event)
344{
345    if (webview)
346        webview->MakeEditable(event.IsChecked());
347}
348
349void wxWebBrowserShell::OnRunScript(wxCommandEvent& myEvent)
350{
351    if (webview) {
352        wxTextEntryDialog* dialog = new wxTextEntryDialog(this, _("Type in a JavaScript to exectute."));
353        if (dialog->ShowModal() == wxID_OK)
354            wxMessageBox(wxT("Result is: ") + webview->RunScript(dialog->GetValue()));
355
356        dialog->Destroy();
357    }
358}
359
360void wxWebBrowserShell::OnEditCommand(wxCommandEvent& myEvent)
361{
362    if (webview) {
363        if (!webview->IsEditable()) {
364            wxMessageBox(wxT("Please enable editing before running editing commands."));
365            return;
366        }
367
368        wxTextEntryDialog* dialog = new wxTextEntryDialog(this, _("Type in a editing command to exectute."));
369        if (dialog->ShowModal() == wxID_OK) {
370            bool result = webview->ExecuteEditCommand(dialog->GetValue());
371            if (!result)
372                wxMessageBox(wxT("Editing command failed."));
373        }
374        dialog->Destroy();
375    }
376}
377
378void wxWebBrowserShell::OnGetEditCommandState(wxCommandEvent& myEvent)
379{
380    if (webview) {
381        if (!webview->IsEditable()) {
382            wxMessageBox(wxT("Please enable editing before running editing commands."));
383            return;
384        }
385
386        wxTextEntryDialog* dialog = new wxTextEntryDialog(this, _("Type in a editing command whose state you want to get."));
387        if (dialog->ShowModal() == wxID_OK) {
388            EditState result = webview->GetEditCommandState(dialog->GetValue());
389            if (result == EditStateTrue)
390                wxMessageBox(wxT("State is true."));
391            else if (result == EditStateFalse)
392                wxMessageBox(wxT("State is false."));
393            else if (result == EditStateMixed)
394                wxMessageBox(wxT("State is mixed."));
395        }
396        dialog->Destroy();
397    }
398}
399