KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > forms > editor > FormEditor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.forms.editor;
12
13 import java.util.Vector JavaDoc;
14
15 import org.eclipse.core.runtime.ListenerList;
16 import org.eclipse.jface.dialogs.IPageChangeProvider;
17 import org.eclipse.jface.dialogs.IPageChangedListener;
18 import org.eclipse.jface.dialogs.PageChangedEvent;
19 import org.eclipse.jface.util.SafeRunnable;
20 import org.eclipse.jface.viewers.ISelection;
21 import org.eclipse.jface.viewers.ISelectionProvider;
22 import org.eclipse.jface.viewers.SelectionChangedEvent;
23 import org.eclipse.jface.viewers.StructuredSelection;
24 import org.eclipse.swt.widgets.Composite;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.Display;
27 import org.eclipse.ui.IEditorActionBarContributor;
28 import org.eclipse.ui.IEditorInput;
29 import org.eclipse.ui.IEditorPart;
30 import org.eclipse.ui.IEditorSite;
31 import org.eclipse.ui.PartInitException;
32 import org.eclipse.ui.forms.IManagedForm;
33 import org.eclipse.ui.forms.widgets.FormToolkit;
34 import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
35 import org.eclipse.ui.part.MultiPageEditorPart;
36 import org.eclipse.ui.part.MultiPageSelectionProvider;
37
38 /**
39  * This class forms a base of multi-page form editors that typically use one or
40  * more pages with forms and one page for raw source of the editor input.
41  * <p>
42  * Pages are added 'lazily' i.e. adding a page reserves a tab for it but does
43  * not cause the page control to be created. Page control is created when an
44  * attempt is made to select the page in question. This allows editors with
45  * several tabs and complex pages to open quickly.
46  * <p>
47  * Subclasses should extend this class and implement <code>addPages</code>
48  * method. One of the two <code>addPage</code> methods should be called to
49  * contribute pages to the editor. One adds complete (standalone) editors as
50  * nested tabs. These editors will be created right away and will be hooked so
51  * that key bindings, selection service etc. is compatible with the one for the
52  * standalone case. The other method adds classes that implement
53  * <code>IFormPage</code> interface. These pages will be created lazily and
54  * they will share the common key binding and selection service. Since 3.1,
55  * FormEditor is a page change provider. It allows listeners to attach to it and
56  * get notified when pages are changed. This new API in JFace allows dynamic
57  * help to update on page changes.
58  *
59  * @since 3.0
60  */

61 public abstract class FormEditor extends MultiPageEditorPart implements
62         IPageChangeProvider {
63
64     /**
65      * An array of pages currently in the editor. Page objects are not limited
66      * to those that implement <code>IFormPage</code>, hence the size of this
67      * array matches the number of pages as viewed by the user.
68      * <p>
69      * Subclasses can access this field but should not modify it.
70      */

71     protected Vector JavaDoc pages = new Vector JavaDoc();
72
73     private FormToolkit toolkit;
74
75     private int currentPage = -1;
76
77     private ListenerList pageListeners = new ListenerList();
78
79     private static class FormEditorSelectionProvider extends
80             MultiPageSelectionProvider {
81         private ISelection globalSelection;
82
83         /**
84          * @param formEditor the editor
85          */

86         public FormEditorSelectionProvider(FormEditor formEditor) {
87             super(formEditor);
88         }
89
90         public ISelection getSelection() {
91             IEditorPart activeEditor = ((FormEditor) getMultiPageEditor())
92                     .getActiveEditor();
93             if (activeEditor != null) {
94                 ISelectionProvider selectionProvider = activeEditor.getSite()
95                         .getSelectionProvider();
96                 if (selectionProvider != null)
97                     return selectionProvider.getSelection();
98             }
99             if (globalSelection != null) {
100                 return globalSelection;
101             }
102             return StructuredSelection.EMPTY;
103         }
104
105         /*
106          * (non-Javadoc) Method declared on <code> ISelectionProvider </code> .
107          */

108         public void setSelection(ISelection selection) {
109             IEditorPart activeEditor = ((FormEditor) getMultiPageEditor())
110                     .getActiveEditor();
111             if (activeEditor != null) {
112                 ISelectionProvider selectionProvider = activeEditor.getSite()
113                         .getSelectionProvider();
114                 if (selectionProvider != null)
115                     selectionProvider.setSelection(selection);
116             } else {
117                 this.globalSelection = selection;
118                 fireSelectionChanged(new SelectionChangedEvent(this,
119                         globalSelection));
120             }
121         }
122     }
123
124     /**
125      * The constructor.
126      */

127     public FormEditor() {
128     }
129
130     /**
131      * Overrides super to plug in a different selection provider.
132      */

133     public void init(IEditorSite site, IEditorInput input)
134             throws PartInitException {
135         setSite(site);
136         setInput(input);
137         site.setSelectionProvider(new FormEditorSelectionProvider(this));
138     }
139
140     /**
141      * Creates the common toolkit for this editor and adds pages to the editor.
142      *
143      * @see #addPages
144      */

145     protected void createPages() {
146         addPages();
147     }
148
149     /*
150      * @see org.eclipse.ui.part.MultiPageEditorPart#createPageContainer(org.eclipse.swt.widgets.Composite)
151      */

152     protected Composite createPageContainer(Composite parent) {
153         parent = super.createPageContainer(parent);
154         toolkit = createToolkit(parent.getDisplay());
155         return parent;
156     }
157
158     /**
159      * Creates the form toolkit. The method can be implemented to substitute a
160      * subclass of the toolkit that should be used for this editor. A typical
161      * use of this method would be to create the form toolkit using one shared
162      * <code>FormColors</code> object to share resources across the multiple
163      * editor instances.
164      *
165      * @param display
166      * the display to use when creating the toolkit
167      * @return the newly created toolkit instance
168      */

169     protected FormToolkit createToolkit(Display display) {
170         return new FormToolkit(display);
171     }
172
173     /**
174      * Subclass should implement this method to add pages to the editor using
175      * 'addPage(IFormPage)' method.
176      */

177     protected abstract void addPages();
178
179     /*
180      * (non-Javadoc)
181      *
182      * @see org.eclipse.jface.dialogs.IPageChangeProvider#addPageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener)
183      */

184     public void addPageChangedListener(IPageChangedListener listener) {
185         pageListeners.add(listener);
186     }
187
188     /*
189      * (non-Javadoc)
190      *
191      * @see org.eclipse.jface.dialogs.IPageChangeProvider#removePageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener)
192      */

193     public void removePageChangedListener(IPageChangedListener listener) {
194         pageListeners.remove(listener);
195     }
196
197     /*
198      * (non-Javadoc)
199      *
200      * @see org.eclipse.jface.dialogs.IPageChangeProvider#getSelectedPage()
201      */

202     public Object JavaDoc getSelectedPage() {
203         return getActivePageInstance();
204     }
205
206     /**
207      * Adds the form page to this editor. Form page will be loaded lazily. Its
208      * part control will not be created until it is activated for the first
209      * time.
210      *
211      * @param page
212      * the form page to add
213      */

214     public int addPage(IFormPage page) throws PartInitException {
215         int i = super.addPage(page.getPartControl());
216         configurePage(i, page);
217         return i;
218     }
219
220     /**
221      * Adds the form page to this editor at the specified index (0-based). Form
222      * page will be loaded lazily. Its part control will not be created until it
223      * is activated for the first time.
224      *
225      * @param index
226      * the position to add the page at (0-based)
227      * @param page
228      * the form page to add
229      * @since 3.1
230      */

231     public void addPage(int index, IFormPage page) throws PartInitException {
232         super.addPage(index, page.getPartControl());
233         configurePage(index, page);
234     }
235
236     /**
237      * Adds a simple SWT control as a page. Overrides superclass implementation
238      * to keep track of pages.
239      *
240      * @param control
241      * the page control to add
242      * @return the 0-based index of the newly added page
243      */

244     public int addPage(Control control) {
245         int i = super.addPage(control);
246         try {
247             registerPage(-1, control);
248         } catch (PartInitException e) {
249             // cannot happen for controls
250
}
251         return i;
252     }
253
254     /**
255      * Adds a simple SWT control as a page. Overrides superclass implementation
256      * to keep track of pages.
257      *
258      * @param control
259      * the page control to add
260      * @param index
261      * the index at which to add the page (0-based)
262      * @since 3.1
263      */

264     public void addPage(int index, Control control) {
265         super.addPage(index, control);
266         try {
267             registerPage(index, control);
268         } catch (PartInitException e) {
269             // cannot happen for controls
270
}
271     }
272
273     /**
274      * Tests whether the editor is dirty by checking all the pages that
275      * implement <code>IFormPage</code>. If none of them is dirty, the method
276      * delegates further processing to <code>super.isDirty()</code>.
277      *
278      * @return <code>true</code> if any of the pages in the editor are dirty,
279      * <code>false</code> otherwise.
280      * @since 3.1
281      */

282
283     public boolean isDirty() {
284         if (pages != null) {
285             for (int i = 0; i < pages.size(); i++) {
286                 Object JavaDoc page = pages.get(i);
287                 if (page instanceof IFormPage) {
288                     IFormPage fpage = (IFormPage) page;
289                     if (fpage.isDirty())
290                         return true;
291                 }
292             }
293         }
294         return super.isDirty();
295     }
296     
297     /**
298      * Commits all dirty pages in the editor. This method should
299      * be called as a first step of a 'save' operation.
300      * @param onSave <code>true</code> if commit is performed as part
301      * of the 'save' operation, <code>false</code> otherwise.
302      * @since 3.3
303      */

304
305     protected void commitPages(boolean onSave) {
306         if (pages != null) {
307             for (int i = 0; i < pages.size(); i++) {
308                 Object JavaDoc page = (IFormPage)pages.get(i);
309                 if (page instanceof IFormPage) {
310                     IFormPage fpage = (IFormPage)page;
311                     IManagedForm mform = fpage.getManagedForm();
312                     if (mform != null && mform.isDirty())
313                         mform.commit(onSave);
314                 }
315             }
316         }
317     }
318
319     /**
320      * Adds a complete editor part to the multi-page editor.
321      *
322      * @see MultiPageEditorPart#addPage(IEditorPart, IEditorInput)
323      */

324     public int addPage(IEditorPart editor, IEditorInput input)
325             throws PartInitException {
326         int index = super.addPage(editor, input);
327         if (editor instanceof IFormPage)
328             configurePage(index, (IFormPage) editor);
329         else
330             registerPage(-1, editor);
331         return index;
332     }
333
334     /**
335      * Adds a complete editor part to the multi-page editor at the specified
336      * position.
337      *
338      * @see MultiPageEditorPart#addPage(int, IEditorPart, IEditorInput)
339      * @since 3.1
340      */

341     public void addPage(int index, IEditorPart editor, IEditorInput input)
342             throws PartInitException {
343         super.addPage(index, editor, input);
344         if (editor instanceof IFormPage)
345             configurePage(index, (IFormPage) editor);
346         else
347             registerPage(index, editor);
348     }
349
350     /**
351      * Configures the form page.
352      *
353      * @param index
354      * the page index
355      * @param page
356      * the page to configure
357      * @throws PartInitException
358      * if there are problems in configuring the page
359      */

360     protected void configurePage(int index, IFormPage page)
361             throws PartInitException {
362         setPageText(index, page.getTitle());
363         // setPageImage(index, page.getTitleImage());
364
page.setIndex(index);
365         registerPage(index, page);
366     }
367
368     /**
369      * Overrides the superclass to remove the page from the page table.
370      *
371      * @param pageIndex
372      * the 0-based index of the page in the editor
373      */

374     public void removePage(int pageIndex) {
375         if (pageIndex >= 0 && pageIndex < pages.size()) {
376             Object JavaDoc page = pages.get(pageIndex);
377             pages.remove(page);
378             if (page instanceof IFormPage) {
379                 IFormPage fpage = (IFormPage) page;
380                 if (!fpage.isEditor())
381                     fpage.dispose();
382                 updatePageIndices();
383             }
384         }
385         super.removePage(pageIndex);
386     }
387
388     // fix the page indices after the removal
389
private void updatePageIndices() {
390         for (int i = 0; i < pages.size(); i++) {
391             Object JavaDoc page = pages.get(i);
392             if (page instanceof IFormPage) {
393                 IFormPage fpage = (IFormPage) page;
394                 fpage.setIndex(i);
395             }
396         }
397     }
398
399     /**
400      * Called to indicate that the editor has been made dirty or the changes
401      * have been saved.
402      */

403     public void editorDirtyStateChanged() {
404         firePropertyChange(PROP_DIRTY);
405     }
406
407     /**
408      * Disposes the pages and the toolkit after disposing the editor itself.
409      * Subclasses must call 'super' when reimplementing the method.
410      */

411     public void dispose() {
412         super.dispose();
413         for (int i = 0; i < pages.size(); i++) {
414             Object JavaDoc page = pages.get(i);
415             if (page instanceof IFormPage) {
416                 IFormPage fpage = (IFormPage) page;
417                 // don't dispose source pages because they will
418
// be disposed as nested editors by the superclass
419
if (!fpage.isEditor())
420                     fpage.dispose();
421             }
422         }
423         pages = null;
424         // toolkit may be null if editor has been instantiated
425
// but never created - see defect #62190
426
if (toolkit != null) {
427             toolkit.dispose();
428             toolkit = null;
429         }
430     }
431
432     /**
433      * Returns the toolkit owned by this editor.
434      *
435      * @return the toolkit object
436      */

437     public FormToolkit getToolkit() {
438         return toolkit;
439     }
440
441     /**
442      * Widens the visibility of the method in the superclass.
443      *
444      * @return the active nested editor
445      */

446     public IEditorPart getActiveEditor() {
447         return super.getActiveEditor();
448     }
449
450     /**
451      * Returns the current page index. The value is identical to the value of
452      * 'getActivePage()' except during the page switch, when this method still
453      * has the old active page index.
454      * <p>
455      * Another important difference is during the editor closing. When the tab
456      * folder is disposed, 'getActivePage()' will return -1, while this method
457      * will still return the last active page.
458      *
459      * @see #getActivePage
460      * @return the currently selected page or -1 if no page is currently
461      * selected
462      */

463     protected int getCurrentPage() {
464         return currentPage;
465     }
466
467     /**
468      * @see MultiPageEditorPart#pageChange(int)
469      */

470     protected void pageChange(int newPageIndex) {
471         // fix for windows handles
472
int oldPageIndex = getCurrentPage();
473         if (oldPageIndex != -1 && pages.size() > oldPageIndex
474                 && pages.get(oldPageIndex) instanceof IFormPage
475                 && oldPageIndex != newPageIndex) {
476             // Check the old page
477
IFormPage oldFormPage = (IFormPage) pages.get(oldPageIndex);
478             if (oldFormPage.canLeaveThePage() == false) {
479                 setActivePage(oldPageIndex);
480                 return;
481             }
482         }
483         // Now is the absolute last moment to create the page control.
484
Object JavaDoc page = pages.get(newPageIndex);
485         if (page instanceof IFormPage) {
486             IFormPage fpage = (IFormPage) page;
487             if (fpage.getPartControl() == null) {
488                 fpage.createPartControl(getContainer());
489                 setControl(newPageIndex, fpage.getPartControl());
490                 fpage.getPartControl().setMenu(getContainer().getMenu());
491             }
492         }
493         if (oldPageIndex != -1 && pages.size() > oldPageIndex
494                 && pages.get(oldPageIndex) instanceof IFormPage) {
495             // Commit old page before activating the new one
496
IFormPage oldFormPage = (IFormPage) pages.get(oldPageIndex);
497             IManagedForm mform = oldFormPage.getManagedForm();
498             if (mform != null)
499                 mform.commit(false);
500         }
501         if (pages.size() > newPageIndex
502                 && pages.get(newPageIndex) instanceof IFormPage)
503             ((IFormPage) pages.get(newPageIndex)).setActive(true);
504         if (oldPageIndex != -1 && pages.size() > oldPageIndex
505                 && newPageIndex != oldPageIndex &&
506                 pages.get(oldPageIndex) instanceof IFormPage)
507             ((IFormPage) pages.get(oldPageIndex)).setActive(false);
508         // Call super - this will cause pages to switch
509
super.pageChange(newPageIndex);
510         this.currentPage = newPageIndex;
511         IFormPage newPage = getActivePageInstance();
512         if (newPage != null)
513             firePageChanged(new PageChangedEvent(this, newPage));
514     }
515
516     /**
517      * Sets the active page using the unique page identifier.
518      *
519      * @param pageId
520      * the id of the page to switch to
521      * @return page that was set active or <samp>null </samp> if not found.
522      */

523     public IFormPage setActivePage(String JavaDoc pageId) {
524         for (int i = 0; i < pages.size(); i++) {
525             Object JavaDoc page = pages.get(i);
526             if (page instanceof IFormPage) {
527                 IFormPage fpage = (IFormPage) page;
528                 if (fpage.getId().equals(pageId)) {
529                     setActivePage(i);
530                     return fpage;
531                 }
532             }
533         }
534         return null;
535     }
536
537     /**
538      * Finds the page instance that has the provided id.
539      *
540      * @param pageId
541      * the id of the page to find
542      * @return page with the matching id or <code>null</code> if not found.
543      */

544     public IFormPage findPage(String JavaDoc pageId) {
545         for (int i = 0; i < pages.size(); i++) {
546             Object JavaDoc page = pages.get(i);
547             if (page instanceof IFormPage) {
548                 IFormPage fpage = (IFormPage) pages.get(i);
549                 if (fpage.getId().equals(pageId))
550                     return fpage;
551             }
552         }
553         return null;
554     }
555
556     /**
557      * Sets the active page using the unique page identifier and sets its input
558      * to the provided object.
559      *
560      * @param pageId
561      * the id of the page to switch to
562      * @param pageInput
563      * the page input
564      * @return page that was set active or <samp>null </samp> if not found.
565      */

566     public IFormPage setActivePage(String JavaDoc pageId, Object JavaDoc pageInput) {
567         IFormPage page = setActivePage(pageId);
568         if (page != null) {
569             IManagedForm mform = page.getManagedForm();
570             if (mform != null)
571                 mform.setInput(pageInput);
572         }
573         return page;
574     }
575
576     /**
577      * Iterates through the pages calling similar method until a page is found
578      * that contains the desired page input.
579      *
580      * @param pageInput
581      * the object to select and reveal
582      * @return the page that accepted the request or <code>null</code> if no
583      * page has the desired object.
584      * @see #setActivePage(String, Object)
585      */

586     public IFormPage selectReveal(Object JavaDoc pageInput) {
587         for (int i = 0; i < pages.size(); i++) {
588             Object JavaDoc page = pages.get(i);
589             if (page instanceof IFormPage) {
590                 IFormPage fpage = (IFormPage) page;
591                 if (fpage.selectReveal(pageInput))
592                     return fpage;
593             }
594         }
595         return null;
596     }
597
598     /**
599      * Returns active page instance if the currently selected page index is not
600      * -1, or <code>null</code> if it is.
601      *
602      * @return active page instance if selected, or <code>null</code> if no
603      * page is currently active.
604      */

605     public IFormPage getActivePageInstance() {
606         int index = getActivePage();
607         if (index != -1) {
608             Object JavaDoc page = pages.get(index);
609             if (page instanceof IFormPage)
610                 return (IFormPage) page;
611         }
612         return null;
613     }
614
615     /**
616      * @see MultiPageEditorPart#setActivePage(int)
617      */

618     protected void setActivePage(int pageIndex) {
619         // fix for window handles problem
620
// this should be called only when the editor is first opened
621
if (pages.size() > pageIndex
622                 && pages.get(pageIndex) instanceof IFormPage) {
623             pageChange(pageIndex);
624             IFormPage activePage = (IFormPage) pages.get(pageIndex);
625             activePage.setActive(true);
626             super.setActivePage(pageIndex);
627         } else
628             super.setActivePage(pageIndex);
629         updateActionBarContributor(pageIndex);
630     }
631
632     /**
633      * Notifies action bar contributor about page change.
634      *
635      * @param pageIndex
636      * the index of the new page
637      */

638     protected void updateActionBarContributor(int pageIndex) {
639         // this is to enable the undo/redo actions before a page change has
640
// occurred
641
IEditorActionBarContributor contributor = getEditorSite()
642                 .getActionBarContributor();
643         if (contributor != null
644                 && contributor instanceof MultiPageEditorActionBarContributor) {
645             ((MultiPageEditorActionBarContributor) contributor)
646                     .setActivePage(getEditor(pageIndex));
647         }
648     }
649
650     /**
651      * Closes the editor programmatically.
652      *
653      * @param save
654      * if <code>true</code>, the content should be saved before
655      * closing.
656      */

657     public void close(final boolean save) {
658         Display display = getSite().getShell().getDisplay();
659         display.asyncExec(new Runnable JavaDoc() {
660             public void run() {
661                 if (toolkit != null) {
662                     getSite().getPage().closeEditor(FormEditor.this, save);
663                 }
664             }
665         });
666     }
667
668     private void registerPage(int index, Object JavaDoc page) throws PartInitException {
669         if (!pages.contains(page)) {
670             if (index == -1)
671                 pages.add(page);
672             else
673                 pages.add(index, page);
674         }
675         if (page instanceof IFormPage) {
676             IFormPage fpage = (IFormPage) page;
677             if (fpage.isEditor() == false)
678                 fpage.init(getEditorSite(), getEditorInput());
679         }
680     }
681
682     private void firePageChanged(final PageChangedEvent event) {
683         Object JavaDoc[] listeners = pageListeners.getListeners();
684         for (int i = 0; i < listeners.length; ++i) {
685             final IPageChangedListener l = (IPageChangedListener) listeners[i];
686             SafeRunnable.run(new SafeRunnable() {
687                 public void run() {
688                     l.pageChanged(event);
689                 }
690             });
691         }
692     }
693 }
694
Popular Tags