001: /*******************************************************************************
002: * Copyright (c) 2003, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.examples.rcp.browser;
011:
012: import org.eclipse.core.commands.IHandler;
013: import org.eclipse.core.runtime.Assert;
014: import org.eclipse.core.runtime.IProgressMonitor;
015: import org.eclipse.jface.action.Action;
016: import org.eclipse.jface.action.IStatusLineManager;
017: import org.eclipse.jface.commands.ActionHandler;
018: import org.eclipse.swt.SWT;
019: import org.eclipse.swt.browser.Browser;
020: import org.eclipse.swt.browser.CloseWindowListener;
021: import org.eclipse.swt.browser.LocationAdapter;
022: import org.eclipse.swt.browser.LocationEvent;
023: import org.eclipse.swt.browser.OpenWindowListener;
024: import org.eclipse.swt.browser.ProgressAdapter;
025: import org.eclipse.swt.browser.ProgressEvent;
026: import org.eclipse.swt.browser.StatusTextEvent;
027: import org.eclipse.swt.browser.StatusTextListener;
028: import org.eclipse.swt.browser.TitleEvent;
029: import org.eclipse.swt.browser.TitleListener;
030: import org.eclipse.swt.browser.WindowEvent;
031: import org.eclipse.swt.events.SelectionAdapter;
032: import org.eclipse.swt.events.SelectionEvent;
033: import org.eclipse.swt.layout.GridData;
034: import org.eclipse.swt.layout.GridLayout;
035: import org.eclipse.swt.widgets.Composite;
036: import org.eclipse.swt.widgets.Label;
037: import org.eclipse.swt.widgets.Shell;
038: import org.eclipse.swt.widgets.Text;
039: import org.eclipse.ui.IActionBars;
040: import org.eclipse.ui.IMemento;
041: import org.eclipse.ui.IViewPart;
042: import org.eclipse.ui.IViewReference;
043: import org.eclipse.ui.IViewSite;
044: import org.eclipse.ui.IWorkbench;
045: import org.eclipse.ui.IWorkbenchPage;
046: import org.eclipse.ui.IWorkbenchWindow;
047: import org.eclipse.ui.PartInitException;
048: import org.eclipse.ui.WorkbenchException;
049: import org.eclipse.ui.handlers.IHandlerService;
050: import org.eclipse.ui.part.ViewPart;
051:
052: /**
053: * The Browser view. This consists of a <code>Browser</code> control, and an
054: * address bar consisting of a <code>Label</code> and a <code>Text</code>
055: * control. This registers handling actions for the retargetable actions added
056: * by <code>BrowserActionBuilder</code> (Back, Forward, Stop, Refresh).
057: * This also hooks listeners on the Browser control for status and progress
058: * messages, and redirects these to the status line.
059: *
060: * @since 3.0
061: */
062: public class BrowserView extends ViewPart {
063:
064: /**
065: * Debug flag. When true, status and progress messages are sent to the
066: * console in addition to the status line.
067: */
068: private static final boolean DEBUG = false;
069:
070: private Browser browser;
071: private Text location;
072: private String initialUrl;
073:
074: private Action backAction = new Action("Back") {
075: public void run() {
076: browser.back();
077: }
078: };
079:
080: private Action forwardAction = new Action("Forward") {
081: public void run() {
082: browser.forward();
083: }
084: };
085:
086: private Action stopAction = new Action("Stop") {
087: public void run() {
088: browser.stop();
089: // cancel any partial progress.
090: getViewSite().getActionBars().getStatusLineManager()
091: .getProgressMonitor().done();
092: }
093: };
094:
095: private Action refreshAction = new Action("Refresh") {
096: public void run() {
097: browser.refresh();
098: }
099: };
100:
101: /**
102: * The easter egg action.
103: * See the corresponding command and key binding in the plugin.xml,
104: * and how it's registered in createBrowser.
105: */
106: private Action easterEggAction = new Action() {
107: {
108: setActionDefinitionId(IBrowserConstants.COMMAND_PREFIX
109: + "easterEgg");} //$NON-NLS-1$
110:
111: public void run() {
112: browser
113: .execute("window.confirm('You found the easter egg!')");
114: }
115: };
116:
117: /**
118: * Finds the first browser view in the given window.
119: *
120: * @param window the window
121: * @return the first found browser view, or <code>null</code> if none found
122: */
123: private static BrowserView findBrowser(IWorkbenchWindow window) {
124: IWorkbenchPage page = window.getActivePage();
125: IViewPart view = page
126: .findView(IBrowserConstants.BROWSER_VIEW_ID);
127: if (view != null) {
128: return (BrowserView) view;
129: }
130: IViewReference[] refs = page.getViewReferences();
131: for (int i = 0; i < refs.length; i++) {
132: if (IBrowserConstants.BROWSER_VIEW_ID.equals(refs[i]
133: .getId())) {
134: return (BrowserView) refs[i].getPart(true);
135: }
136: }
137: return null;
138: }
139:
140: /**
141: * Constructs a new <code>BrowserView</code>.
142: */
143: public BrowserView() {
144: initialUrl = BrowserPlugin.getDefault().getPluginPreferences()
145: .getString(IBrowserConstants.PREF_HOME_PAGE);
146: }
147:
148: public void init(IViewSite site, IMemento memento)
149: throws PartInitException {
150: super .init(site);
151: if (memento != null) {
152: String u = memento.getString(IBrowserConstants.MEMENTO_URL);
153: if (u != null) {
154: initialUrl = u;
155: }
156: }
157: }
158:
159: public void saveState(IMemento memento) {
160: memento.putString(IBrowserConstants.MEMENTO_URL, browser
161: .getUrl());
162: }
163:
164: public void createPartControl(Composite parent) {
165: browser = createBrowser(parent, getViewSite().getActionBars());
166: browser.setUrl(initialUrl);
167: }
168:
169: public void setFocus() {
170: if (browser != null && !browser.isDisposed()) {
171: browser.setFocus();
172: }
173: }
174:
175: private Browser createBrowser(Composite parent,
176: final IActionBars actionBars) {
177:
178: GridLayout gridLayout = new GridLayout();
179: gridLayout.numColumns = 2;
180: parent.setLayout(gridLayout);
181:
182: Label labelAddress = new Label(parent, SWT.NONE);
183: labelAddress.setText("A&ddress");
184:
185: location = new Text(parent, SWT.BORDER);
186: GridData data = new GridData();
187: data = new GridData();
188: data.horizontalAlignment = GridData.FILL;
189: data.grabExcessHorizontalSpace = true;
190: location.setLayoutData(data);
191:
192: browser = new Browser(parent, SWT.NONE);
193: data = new GridData();
194: data.horizontalAlignment = GridData.FILL;
195: data.verticalAlignment = GridData.FILL;
196: data.horizontalSpan = 2;
197: data.grabExcessHorizontalSpace = true;
198: data.grabExcessVerticalSpace = true;
199: browser.setLayoutData(data);
200:
201: browser.addProgressListener(new ProgressAdapter() {
202: IProgressMonitor monitor = actionBars
203: .getStatusLineManager().getProgressMonitor();
204: boolean working = false;
205: int workedSoFar;
206:
207: public void changed(ProgressEvent event) {
208: if (DEBUG) {
209: System.out.println("changed: " + event.current
210: + "/" + event.total);
211: }
212: if (event.total == 0)
213: return;
214: if (!working) {
215: if (event.current == event.total)
216: return;
217: monitor.beginTask("", event.total); //$NON-NLS-1$
218: workedSoFar = 0;
219: working = true;
220: }
221: monitor.worked(event.current - workedSoFar);
222: workedSoFar = event.current;
223: }
224:
225: public void completed(ProgressEvent event) {
226: if (DEBUG) {
227: System.out.println("completed: " + event.current
228: + "/" + event.total);
229: }
230: monitor.done();
231: working = false;
232: }
233: });
234: browser.addStatusTextListener(new StatusTextListener() {
235: IStatusLineManager status = actionBars
236: .getStatusLineManager();
237:
238: public void changed(StatusTextEvent event) {
239: if (DEBUG) {
240: System.out.println("status: " + event.text);
241: }
242: status.setMessage(event.text);
243: }
244: });
245: browser.addLocationListener(new LocationAdapter() {
246: public void changed(LocationEvent event) {
247: if (event.top)
248: location.setText(event.location);
249: }
250: });
251: browser.addTitleListener(new TitleListener() {
252: public void changed(TitleEvent event) {
253: setPartName(event.title);
254: }
255: });
256: browser.addOpenWindowListener(new OpenWindowListener() {
257: public void open(WindowEvent event) {
258: BrowserView.this .openWindow(event);
259: }
260: });
261: // TODO: should handle VisibilityWindowListener.show and .hide events
262: browser.addCloseWindowListener(new CloseWindowListener() {
263: public void close(WindowEvent event) {
264: BrowserView.this .close();
265: }
266: });
267: location.addSelectionListener(new SelectionAdapter() {
268: public void widgetDefaultSelected(SelectionEvent e) {
269: browser.setUrl(location.getText());
270: }
271: });
272:
273: // Hook the navigation actons as handlers for the retargetable actions
274: // defined in BrowserActionBuilder.
275: actionBars.setGlobalActionHandler("back", backAction); //$NON-NLS-1$
276: actionBars.setGlobalActionHandler("forward", forwardAction); //$NON-NLS-1$
277: actionBars.setGlobalActionHandler("stop", stopAction); //$NON-NLS-1$
278: actionBars.setGlobalActionHandler("refresh", refreshAction); //$NON-NLS-1$
279:
280: // Register the easter egg action with the key binding service,
281: // allowing it to be invoked directly via keypress,
282: // without requiring the action to be visible in the UI.
283: // Note that the address field needs to have focus for this to work,
284: // or any control other than the browser widget, due to
285: // <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=69919">bug 69919</a>.
286: IHandlerService hs = (IHandlerService) getSite().getService(
287: IHandlerService.class);
288: IHandler easterHandler = new ActionHandler(easterEggAction);
289: hs.activateHandler(easterEggAction.getActionDefinitionId(),
290: easterHandler);
291: return browser;
292: }
293:
294: /**
295: * Opens a new browser window.
296: *
297: * @param event the open window event
298: */
299: private void openWindow(WindowEvent event) {
300: try {
301: IWorkbench workbench = getSite().getWorkbenchWindow()
302: .getWorkbench();
303: IWorkbenchWindow window = workbench.openWorkbenchWindow(
304: IBrowserConstants.BROWSER_PERSPECTIVE_ID, null);
305: Shell shell = window.getShell();
306: if (event.location != null)
307: shell.setLocation(event.location);
308: if (event.size != null)
309: shell.setLocation(event.size);
310: BrowserView view = findBrowser(window);
311: Assert.isNotNull(view);
312: event.browser = view.browser;
313: } catch (WorkbenchException e) {
314: BrowserPlugin.getDefault().log(e);
315: }
316: }
317:
318: /**
319: * Closes this browser view. Closes the window too if there
320: * are no non-secondary parts open.
321: */
322: private void close() {
323: IWorkbenchPage page = getSite().getPage();
324: IWorkbenchWindow window = page.getWorkbenchWindow();
325: page.hideView(this );
326: if (BrowserPlugin.getNonSecondaryParts(page).size() == 0) {
327: page.closePerspective(page.getPerspective(), true, true);
328: }
329: if (window.getActivePage() == null) {
330: window.close();
331: }
332: }
333:
334: }
|