Added word wrap option (problem: conflicts with folding)
[phpeclipse.git] / net.sourceforge.phpeclipse.webbrowser / src / net / sourceforge / phpeclipse / webbrowser / internal / WebBrowser.java
1 /**
2  * Copyright (c) 2003 IBM Corporation and others.
3  * All rights reserved.   This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  *    IBM - Initial API and implementation
10  */
11
12 //TODO 1. Handle the sizing of a popup running in shelled out secondary window.
13 //TODO 2. Support printing: waiting on eclipse bug 47937/44823.
14
15 package net.sourceforge.phpeclipse.webbrowser.internal;
16
17 import java.util.*;
18
19 import net.sourceforge.phpeclipse.webbrowser.IURLMap;
20
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.widgets.*;
23 import org.eclipse.swt.layout.FillLayout;
24 import org.eclipse.swt.layout.GridData;
25 import org.eclipse.swt.layout.GridLayout;
26 import org.eclipse.swt.dnd.Clipboard;
27 import org.eclipse.swt.events.*;
28 import org.eclipse.swt.graphics.Point;
29 import org.eclipse.swt.graphics.Rectangle;
30 import org.eclipse.ui.help.WorkbenchHelp;
31 import org.eclipse.swt.browser.*;
32
33 public class WebBrowser extends Composite {
34         protected Composite toolbarComp;
35         protected Composite statusComp;
36         protected Combo combo;
37         protected Clipboard clipboard;
38         protected boolean showToolbar;
39         protected ToolItem back;
40         protected ToolItem forward;
41         protected ToolItem stop;
42         protected ToolItem favorites;
43         protected ToolItem refresh;
44         protected BusyIndicator busy;
45         protected boolean showStatusbar;
46         protected ProgressBar progress;
47         protected Label status;
48         private static int MAX_HISTORY = 50;
49         protected static java.util.List history;
50         protected Browser browser; 
51         protected Shell shell;
52         protected WebBrowserEditor editor;
53         protected String title;
54         
55         public WebBrowser(Composite parent, final boolean showToolbar, final boolean showStatusbar) {
56                 super(parent, SWT.NONE);
57
58                 this.showToolbar = showToolbar;
59                 this.showStatusbar = showStatusbar;     
60
61                 GridLayout layout = new GridLayout();
62                 layout.marginHeight = 3;
63                 layout.marginWidth = 3;
64                 layout.horizontalSpacing = 3;
65                 layout.verticalSpacing = 3;
66                 layout.numColumns = 1;
67                 setLayout(layout);
68                 setLayoutData(new GridData(GridData.FILL_BOTH));
69                 clipboard = new Clipboard(parent.getDisplay());
70                 WorkbenchHelp.setHelp(this, ContextIds.WEB_BROWSER);
71                 
72                 if (showToolbar) {
73                         toolbarComp = new Composite(this, SWT.NONE);
74                         GridLayout outerLayout = new GridLayout();
75                         outerLayout.numColumns = 2;
76                         outerLayout.marginWidth = 0;
77                         outerLayout.marginHeight = 0;
78                         toolbarComp.setLayout(outerLayout);
79                         toolbarComp.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL));
80                         
81                         // create the top line, with a combo box for history and a "go" button
82                         Composite top = new Composite(toolbarComp, SWT.NONE);
83                         GridLayout topLayout = new GridLayout();
84                         topLayout.numColumns = 2;
85                         topLayout.marginWidth = 0;
86                         topLayout.marginHeight = 0;
87                         top.setLayout(topLayout);
88                         top.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL));
89                         
90                         combo = new Combo(top, SWT.DROP_DOWN);
91                         
92                         updateHistory();
93                         
94                         combo.addSelectionListener(new SelectionAdapter() {
95                                 public void widgetSelected(SelectionEvent we) {
96                                         try {
97                                                 if (combo.getSelectionIndex() != -1)
98                                                         setURL(combo.getItem(combo.getSelectionIndex()));
99                                         } catch (Exception e) { }
100                                 }
101                         });
102                         combo.addListener(SWT.DefaultSelection, new Listener() {
103                                 public void handleEvent(Event e) {
104                                         setURL(combo.getText());
105                                 }
106                         });
107                         combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
108                         WorkbenchHelp.setHelp(combo, ContextIds.WEB_BROWSER_URL);
109                         
110                         ToolBar toolbar = new ToolBar(top, SWT.FLAT);
111                         fillToolBar(toolbar);
112                         
113                         new ToolItem(toolbar, SWT.SEPARATOR);
114                         
115                         busy = new BusyIndicator(toolbarComp, SWT.NONE);
116                         busy.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
117                 }
118
119                 // create a new SWT Web browser widget, checking once again to make sure we can use it in this environment
120                 if (WebBrowserUtil.canUseInternalWebBrowser() & WebBrowserUtil.isInternalBrowserOperational())
121                         this.browser = new Browser(this, SWT.NONE);
122                 else {
123                         WebBrowserUtil.openError(WebBrowserUIPlugin.getResource("%errorCouldNotLaunchInternalWebBrowser"));
124                         return;
125                 }
126                 
127                 if (showToolbar) {
128                         back.setEnabled(browser.isBackEnabled());
129                         forward.setEnabled(browser.isForwardEnabled());
130                 }
131
132                 WorkbenchHelp.setHelp(browser, ContextIds.WEB_BROWSER_WEB);
133                 GridData data = new GridData();
134                 data.horizontalAlignment = GridData.FILL;
135                 data.verticalAlignment = GridData.FILL;
136                 data.horizontalSpan = 3;
137                 data.grabExcessHorizontalSpace = true;
138                 data.grabExcessVerticalSpace = true;
139                 browser.setLayoutData(data);
140                 
141                 if (showStatusbar)
142                         createStatusArea(this);
143                 
144                 addBrowserListeners();
145         }
146         /**
147          *
148          */
149         protected void addBrowserListeners() {  
150                 if (showStatusbar) {
151                         // respond to Browser StatusTextEvents events by updating the status Text label
152                         browser.addStatusTextListener(new StatusTextListener() {
153                                 public void changed(StatusTextEvent event) {
154                                         status.setText(event.text);     
155                                 }
156                         });
157                 }
158
159                 /** Add listener for new window creation so that we can instead of opening a separate
160                  *  new window in which the session is lost, we can instead open a new window in a new
161                  *  shell within the browser area thereby maintaining the session.
162                  */
163                 browser.addOpenWindowListener(new OpenWindowListener() {
164                         public void open(WindowEvent event) {
165                                 Shell shell2 = new Shell(getDisplay());
166                                 shell2.setLayout(new FillLayout());
167                                 shell2.setText(WebBrowserUIPlugin.getResource("%viewWebBrowserTitle"));
168                                 shell2.setImage(getShell().getImage());
169                                 WebBrowser browser2 = new WebBrowser(shell2, showToolbar, showStatusbar);
170                                 browser2.shell = shell2;
171                                 event.browser = browser2.browser;
172                                 shell2.open();
173                         }
174                 });
175                 
176                 browser.addCloseWindowListener(new CloseWindowListener(){
177                         public void close(WindowEvent event) {
178                                 // if shell is not null, it must be a secondary popup window, else its an editor window
179                                 if (shell != null)
180                                         shell.dispose();
181                                 else
182                                         editor.closeEditor();
183                         }
184                 });
185                 
186                 browser.addProgressListener(new ProgressListener() {
187                         public void changed(ProgressEvent event) {
188                                 if (event.total == 0)
189                                         return;
190                                 
191                                 boolean done = (event.current == event.total);
192
193                                 int percentProgress = event.current * 100 / event.total;
194                                 if (showStatusbar) {
195                                         if (done)
196                                                 progress.setSelection(0);
197                                         else
198                                                 progress.setSelection(percentProgress);
199                                 }
200                                 
201                                 if (showToolbar) {
202                                         if (!busy.isBusy() && (percentProgress > 0 && percentProgress < 100)) {
203                                                 busy.setBusy(true);
204                                         }
205                                         // Once the progress hits 100 percent, done, set busy to false
206                                         else if (busy.isBusy() && done) {
207                                                 busy.setBusy(false);
208                                         }
209                                 }
210                         }
211                         
212                         public void completed(ProgressEvent event) {
213                                 if (showStatusbar)
214                                         progress.setSelection(0);
215                                 if (showToolbar) {
216                                         busy.setBusy(false);
217                                         back.setEnabled(browser.isBackEnabled());
218                                         forward.setEnabled(browser.isForwardEnabled());
219                                 }
220                         }
221                 });
222
223                 if (showToolbar) {
224                         browser.addLocationListener(new LocationListener() {
225                                 public void changed(LocationEvent event) {
226                                         if (!event.top)
227                                                 return;
228                                         if (!isHome()) {
229                                                 combo.setText(event.location);
230                                                 addToHistory(event.location);
231                                                 updateHistory();
232                                         } else
233                                                 combo.setText("");
234                                 }
235                                 
236                                 public void changing(LocationEvent event) { }
237                         });
238                 }
239                 
240                 browser.addTitleListener(new TitleListener() {
241                         public void changed(TitleEvent event) {
242                                 title = event.title;
243                         }
244                 });
245         }
246
247         /**
248          * Return the underlying browser control.
249          * 
250          * @return org.eclipse.swt.browser.Browser
251          */
252         public Browser getBrowser() {
253                 return browser;
254         }
255
256         /**
257          * 
258          */
259         protected void forward() {
260                 browser.forward();
261         }
262
263         /**
264          * 
265          */
266         protected void back() {
267                 browser.back();
268         }
269         
270         /**
271          * 
272          */
273         protected void stop() {
274                 browser.stop();
275         }
276
277         /**
278          * 
279          */
280         protected void navigate(String url) {
281                 Trace.trace(Trace.FINER, "Navigate: " + url);
282                 if (url != null && url.equals(getURL())) {
283                         refresh();
284                         return;
285                 }
286                 browser.setUrl(url);
287         }
288
289         /**
290          * Refresh the currently viewed page.
291          */
292         public void refresh() {
293                 browser.refresh();
294         }
295
296         protected void setURL(String url, boolean browse) {
297                 Trace.trace(Trace.FINEST, "setURL: " + url + " " + browse);
298                 if (url == null) {
299                         home();
300                         return;
301                 }
302                 
303                 if (url.endsWith(WebBrowserPreference.getHomePageURL().substring(9)))
304                         return;
305
306                 // check URL maps
307                 Iterator iterator = WebBrowserUtil.getURLMaps().iterator();
308                 String newURL = null;
309                 while (iterator.hasNext() && newURL == null) {
310                         try {
311                                 IURLMap map = (IURLMap) iterator.next();
312                                 newURL = map.getMappedURL(url);
313                         } catch (Exception e) { }
314                 }
315                 if (newURL != null)
316                         url = newURL;
317                 
318                 if (browse)
319                         navigate(url);
320                 
321                 addToHistory(url);
322                 updateHistory();
323         }
324
325         protected void addToHistory(String url) {
326                 if (history == null)
327                         history = WebBrowserPreference.getInternalWebBrowserHistory();
328                 int found = -1;
329                 int size = history.size();
330                 for (int i = 0; i < size; i++){
331                         String s = (String) history.get(i);
332                         if (s.equals(url)) {
333                                 found = i;
334                                 break;
335                         }
336                 }
337                 
338                 if (found == -1) {
339                         if (size >= MAX_HISTORY)
340                                 history.remove(size - 1);
341                         history.add(0, url);
342                         WebBrowserPreference.setInternalWebBrowserHistory(history);
343                 } else if (found != 0) {
344                         history.remove(found);
345                         history.add(0, url);
346                         WebBrowserPreference.setInternalWebBrowserHistory(history);
347                 }
348         }
349
350         public void setURL(String url) {
351                 setURL(url, true);
352         }
353         
354         /**
355          * Creates the Web browser status area.
356          */
357         private void createStatusArea(Composite parent) {
358                 Composite composite = new Composite(parent, SWT.NONE);
359                 GridLayout layout = new GridLayout();
360                 layout.numColumns = 2;
361                 layout.marginHeight = 0;
362                 layout.marginWidth = 0;
363                 layout.horizontalSpacing = 4;
364                 layout.verticalSpacing = 0;
365                 composite.setLayout(layout);
366                 composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
367         
368                 // Add a label for displaying status messages as they are received from the control
369                 status = new Label(composite, SWT.SINGLE | SWT.READ_ONLY);
370                 GridData gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
371                 gridData.horizontalIndent = 2;
372                 status.setLayoutData(gridData);
373         
374                 // Add a progress bar to display downloading progress information
375                 progress = new ProgressBar(composite, SWT.BORDER);
376                 gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_FILL);
377                 gridData.widthHint = 100;
378                 gridData.heightHint = 10;
379                 progress.setLayoutData(gridData);
380         }
381         
382         /**
383          *
384          */
385         public void dispose() {
386                 super.dispose();
387
388                 showStatusbar = false;
389                 showToolbar = false;
390         
391                 if (busy != null)
392                         busy.dispose();
393                 busy = null;
394
395                 browser = null;
396         }
397         
398         /**
399          * Populate the toolbar.
400          * @param toolbar org.eclipse.swt.widgets.ToolBar
401          */
402         private void fillToolBar(final ToolBar toolbar) {
403                 ToolItem go = new ToolItem(toolbar, SWT.NONE);
404                 go.setImage(ImageResource.getImage(ImageResource.IMG_ELCL_NAV_GO));
405                 go.setHotImage(ImageResource.getImage(ImageResource.IMG_CLCL_NAV_GO));
406                 go.setDisabledImage(ImageResource.getImage(ImageResource.IMG_DLCL_NAV_GO));
407                 go.setToolTipText(WebBrowserUIPlugin.getResource("%actionWebBrowserGo"));
408                 go.addSelectionListener(new SelectionAdapter() {
409                         public void widgetSelected(SelectionEvent event) {
410                                 setURL(combo.getText());
411                         }
412                 });
413         
414                 new ToolItem(toolbar, SWT.SEPARATOR);
415                 
416                 favorites = new ToolItem(toolbar, SWT.DROP_DOWN);
417                 favorites.setImage(ImageResource.getImage(ImageResource.IMG_ELCL_NAV_FAVORITES));
418                 favorites.setHotImage(ImageResource.getImage(ImageResource.IMG_CLCL_NAV_FAVORITES));
419                 favorites.setDisabledImage(ImageResource.getImage(ImageResource.IMG_DLCL_NAV_FAVORITES));
420                 favorites.setToolTipText(WebBrowserUIPlugin.getResource("%actionWebBrowserFavorites"));
421                 
422                 favorites.addSelectionListener(new SelectionAdapter() {
423                         public void widgetSelected(SelectionEvent event) {
424                                 if (event.detail == SWT.ARROW) {
425                                         Rectangle r = favorites.getBounds();
426                                         showFavorites(toolbar, toolbar.toDisplay(r.x, r.y + r.height));
427                                 } else
428                                         addFavorite();
429                         }
430                 });
431         
432                 // create back and forward actions
433                 back = new ToolItem(toolbar, SWT.NONE);
434                 back.setImage(ImageResource.getImage(ImageResource.IMG_ELCL_NAV_BACKWARD));
435                 back.setHotImage(ImageResource.getImage(ImageResource.IMG_CLCL_NAV_BACKWARD));
436                 back.setDisabledImage(ImageResource.getImage(ImageResource.IMG_DLCL_NAV_BACKWARD));
437                 back.setToolTipText(WebBrowserUIPlugin.getResource("%actionWebBrowserBack"));
438                 back.addSelectionListener(new SelectionAdapter() {
439                         public void widgetSelected(SelectionEvent event) {
440                                 back();
441                         }
442                 });
443
444                 forward = new ToolItem(toolbar, SWT.NONE);
445                 forward.setImage(ImageResource.getImage(ImageResource.IMG_ELCL_NAV_FORWARD));
446                 forward.setHotImage(ImageResource.getImage(ImageResource.IMG_CLCL_NAV_FORWARD));
447                 forward.setDisabledImage(ImageResource.getImage(ImageResource.IMG_DLCL_NAV_FORWARD));
448                 forward.setToolTipText(WebBrowserUIPlugin.getResource("%actionWebBrowserForward"));
449                 forward.addSelectionListener(new SelectionAdapter() {
450                         public void widgetSelected(SelectionEvent event) {
451                                 forward();
452                         }
453                 });
454                 
455                 // create refresh, stop, and print actions
456                 stop = new ToolItem(toolbar, SWT.NONE);
457                 stop.setImage(ImageResource.getImage(ImageResource.IMG_ELCL_NAV_STOP));
458                 stop.setHotImage(ImageResource.getImage(ImageResource.IMG_CLCL_NAV_STOP));
459                 stop.setDisabledImage(ImageResource.getImage(ImageResource.IMG_DLCL_NAV_STOP));
460                 stop.setToolTipText(WebBrowserUIPlugin.getResource("%actionWebBrowserStop"));
461                 stop.addSelectionListener(new SelectionAdapter() {
462                         public void widgetSelected(SelectionEvent event) {
463                                 stop();
464                         }
465                 });
466         
467                 refresh = new ToolItem(toolbar, SWT.NONE);
468                 refresh.setImage(ImageResource.getImage(ImageResource.IMG_ELCL_NAV_REFRESH));
469                 refresh.setHotImage(ImageResource.getImage(ImageResource.IMG_CLCL_NAV_REFRESH));
470                 refresh.setDisabledImage(ImageResource.getImage(ImageResource.IMG_DLCL_NAV_REFRESH));
471                 refresh.setToolTipText(WebBrowserUIPlugin.getResource("%actionWebBrowserRefresh"));
472                 refresh.addSelectionListener(new SelectionAdapter() {
473                         public void widgetSelected(SelectionEvent event) {
474                                 refresh();
475                         }
476                 });
477         }
478         
479         protected void addFavorite() {
480                 java.util.List list = WebBrowserPreference.getInternalWebBrowserFavorites();
481                 Favorite f = new Favorite(title, browser.getUrl());
482                 if (!list.contains(f)) {
483                         list.add(f);
484                         WebBrowserPreference.setInternalWebBrowserFavorites(list);
485                 }
486         }
487         
488         protected void showFavorites(Control parent, Point p) {
489                 Menu perspectiveBarMenu = null;
490                 if (perspectiveBarMenu == null) {
491                         Menu menu = new Menu(parent);
492                         
493                         // locked favorites
494                         Iterator iterator = WebBrowserUtil.getLockedFavorites().iterator();
495                         if (iterator.hasNext()) {
496                                 while (iterator.hasNext()) {
497                                         final Favorite f = (Favorite) iterator.next();
498                                         MenuItem item = new MenuItem(menu, SWT.NONE);
499                                         item.setText(f.getName());
500                                         item.setImage(ImageResource.getImage(ImageResource.IMG_FAVORITE));
501                                         item.addSelectionListener(new SelectionAdapter() {
502                                                 public void widgetSelected(SelectionEvent event) {
503                                                         setURL(f.getURL());
504                                                 }
505                                         });
506                                 }
507                                 
508                                 new MenuItem(menu, SWT.SEPARATOR);
509                         }
510                         
511                         iterator = WebBrowserPreference.getInternalWebBrowserFavorites().iterator();
512                         if (!iterator.hasNext()) {
513                                 MenuItem item = new MenuItem(menu, SWT.NONE);
514                                 item.setText(WebBrowserUIPlugin.getResource("%actionWebBrowserNoFavorites"));
515                         }
516                         while (iterator.hasNext()) {
517                                 final Favorite f = (Favorite) iterator.next();
518                                 MenuItem item = new MenuItem(menu, SWT.NONE);
519                                 item.setText(f.getName());
520                                 item.setImage(ImageResource.getImage(ImageResource.IMG_FAVORITE));
521                                 item.addSelectionListener(new SelectionAdapter() {
522                                         public void widgetSelected(SelectionEvent event) {
523                                                 setURL(f.getURL());
524                                         }
525                                 });
526                         }
527                         
528                         new MenuItem(menu, SWT.SEPARATOR);
529         
530                         MenuItem item = new MenuItem(menu, SWT.NONE);
531                         item.setText(WebBrowserUIPlugin.getResource("%actionWebBrowserOrganizeFavorites"));
532                         item.addSelectionListener(new SelectionAdapter() {
533                                 public void widgetSelected(SelectionEvent event) {
534                                         OrganizeFavoritesDialog dialog = new OrganizeFavoritesDialog(shell);
535                                         dialog.open();
536                                 }
537                         });
538                         
539                         perspectiveBarMenu = menu;
540                 }
541                 
542                 if (perspectiveBarMenu != null) {
543                         perspectiveBarMenu.setLocation(p.x, p.y);
544                         perspectiveBarMenu.setVisible(true);
545                 }
546         }
547
548         public void home() {
549            navigate(WebBrowserPreference.getHomePageURL());
550         }
551
552         /**
553          * Returns true if the homepage is currently being displayed.
554          * @return boolean
555          */
556         protected boolean isHome() {
557                 return getURL() != null && getURL().endsWith(WebBrowserPreference.getHomePageURL().substring(9));
558         }
559
560         protected String getURL() {
561                 return browser.getUrl();
562         }
563
564         /**
565          * Update the history list to the global copy.
566          */
567         protected void updateHistory() {
568                 if (combo == null)
569                         return;
570         
571                 String temp = combo.getText();
572                 if (history == null)
573                         history = WebBrowserPreference.getInternalWebBrowserHistory();
574         
575                 String[] historyList = new String[history.size()];
576                 history.toArray(historyList);
577                 combo.setItems(historyList);
578         
579                 combo.setText(temp);
580         }
581 }