blob: d9110dd3ec4d16693485b81edbafbfafdd877c06 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.facesconfig.ui;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jst.jsf.common.ui.internal.logging.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.SubActionBars;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.IPage;
import org.eclipse.ui.part.IPageBookViewPage;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.MessagePage;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.part.Page;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
/**
* @author Xiao-guang Zhang
*
* The outline page class for mulitPage Editorpart.
*/
public class MultiPageEditorOutlinePage extends Page implements
IContentOutlinePage, SelectionListener {
/** log instance */
private static final Logger log = EditorPlugin
.getLogger(MultiPageEditorOutlinePage.class);
/**
* Selection change listeners.
*/
private ListenerList selectionChangedListeners = new ListenerList(ListenerList.IDENTITY);
/** the pagebook */
private PageBook pageBook = null;
/**
* Selection change listener to listen for page selection changes
*/
private ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
pageSelectionChanged(event);
}
};
/**
* A data structure used to store the information about a single page within
* a MultiPageEditorOutlinePage
*/
protected static class PageRec {
/**
* The part including editorpart, or Control
*/
public IWorkbenchPart part;
/**
* The page.
*/
public IPage page;
/**
* The page's action bars
*/
public SubActionBars subActionBars;
/**
* Creates a new page record initialized to the given part and page.
*
* @param part
* @param page
*/
public PageRec(IWorkbenchPart part, IPage page) {
this.part = part;
this.page = page;
}
/**
* Disposes of this page record by <code>null</code>ing its fields.
*/
public void dispose() {
part = null;
page = null;
}
}
/**
* The page record for the default page.
*/
private PageRec defaultPageRec;
/**
* Map from parts to part records (key type: <code>IWorkbenchPart</code>;
* value type: <code>PartRec</code>).
*/
private Map mapPartToRec = new HashMap();
/**
* Map from pages to view sites Note that view sites were not added to page
* recs to avoid breaking binary compatibility with previous builds
*/
private Map mapPageToSite = new HashMap();
/**
* The page rec which provided the current page or <code>null</code>
*/
private PageRec activeRec;
/**
* the container composite control of MutliPageEditorPart
*/
private CTabFolder tabFolder;
/**
* Creates a new MultiPageEditorOutlinePage instance.
*
*
*/
public MultiPageEditorOutlinePage() {
super();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
// pagebook
pageBook = new PageBook(parent, SWT.NONE);
// Create the default page rec.
IPage defaultPage = createDefaultPage(pageBook);
defaultPageRec = new PageRec(null, defaultPage);
preparePage(defaultPageRec);
// Show the default page
showPageRec(defaultPageRec);
// get the tab control and add the page selection listener.
if (getContainerForMultiPageEditorPart() != null) {
getContainerForMultiPageEditorPart().addSelectionListener(this);
}
// show the activate part page.
showBootstrapPart();
}
/*
* (non-Javadoc)
*
* @see Page#dispose()
*/
public void dispose() {
// Deref all of the pages.
activeRec = null;
if (defaultPageRec != null) {
// check for null since the default page may not have
// been created (ex. perspective never visible)
defaultPageRec.page.dispose();
defaultPageRec = null;
}
Map clone = (Map) ((HashMap) mapPartToRec).clone();
Iterator iterator = clone.values().iterator();
while (iterator.hasNext()) {
PageRec rec = (PageRec) iterator.next();
removePage(rec);
}
// important: always call super implementation of dispose
super.dispose();
}
/**
* Creates and returns the default page for this view.
*
* @param book -
* the pagebook control
* @return - the default page
*/
protected IPage createDefaultPage(PageBook book) {
// Message to show on the default page
String defaultText = EditorMessages.MultiPageEditorOutlinePage_noOutline;
MessagePage page = new MessagePage();
initPage(page);
page.createControl(book);
page.setMessage(defaultText);
return page;
}
/**
* Prepares the page in the given page rec for use in this view.
*
* @param rec -
* the page rec
*/
private void preparePage(PageRec rec) {
IPageSite site = null;
if (!doesPageExist(rec.page)) {
if (rec.page instanceof IPageBookViewPage) {
site = ((IPageBookViewPage) rec.page).getSite();
}
if (site == null) {
// We will create a site for our use
site = new SubPageSite(getSite());
}
mapPageToSite.put(rec.page, site);
rec.subActionBars = (SubActionBars) site.getActionBars();
// rec.subActionBars.addPropertyChangeListener(actionBarPropListener);
// for backward compability with IPage
rec.page.setActionBars(rec.subActionBars);
} else {
site = (IPageSite) mapPageToSite.get(rec.page);
rec.subActionBars = (SubActionBars) site.getActionBars();
}
}
/**
* Returns the currently visible page for this view or <code>null</code>
* if no page is currently visible.
*
* @return the currently visible page
*/
public IPage getCurrentPage() {
if (activeRec == null)
return null;
return activeRec.page;
}
/**
* Returns the view site for the given page of this view.
*
* @param page
* the page
* @return the corresponding site, or <code>null</code> if not found
*/
protected SubPageSite getPageSite(IPage page) {
return (SubPageSite) mapPageToSite.get(page);
}
/**
* Shows page contained in the given page record in this view. The page
* record must be one from this pagebook view.
* <p>
* The <code>PageBookView</code> implementation of this method asks the
* pagebook control to show the given page's control, and records that the
* given page is now current. Subclasses may extend.
* </p>
*
* @param pageRec
* the page record containing the page to show
*/
protected void showPageRec(PageRec pageRec) {
IPageSite pageSite = getPageSite(pageRec.page);
ISelectionProvider provider = pageSite.getSelectionProvider();
if (provider == null && (pageRec.page instanceof IContentOutlinePage)) {
// This means that the page did not set a provider during its
// initialization
// so for backward compatibility we will set the page itself as the
// provider.
pageSite.setSelectionProvider((IContentOutlinePage) pageRec.page);
}
// If already showing do nothing
if (activeRec == pageRec) {
return;
}
// If the page is the same, just set activeRec to pageRec
if (activeRec != null && pageRec != null
&& activeRec.page == pageRec.page) {
activeRec = pageRec;
return;
}
// Hide old page.
if (activeRec != null) {
activeRec.subActionBars.deactivate();
// remove our selection listener
provider = ((SubPageSite) mapPageToSite.get(activeRec.page))
.getSelectionProvider();
if (provider != null) {
provider
.removeSelectionChangedListener(selectionChangedListener);
}
}
// Show new page.
activeRec = pageRec;
Control pageControl = activeRec.page.getControl();
if (pageControl != null && !pageControl.isDisposed()) {
// Verify that the page control is not disposed
// If we are closing, it may have already been disposed
pageBook.showPage(pageControl);
activeRec.subActionBars.activate();
refreshGlobalActionHandlers();
// add our selection listener
provider = ((SubPageSite) mapPageToSite.get(activeRec.page))
.getSelectionProvider();
if (provider != null) {
provider.addSelectionChangedListener(selectionChangedListener);
}
// Update action bars.
getSite().getActionBars().updateActionBars();
}
}
/**
* Refreshes the global actions for the active page.
*/
private void refreshGlobalActionHandlers() {
// Clear old actions.
IActionBars bars = getSite().getActionBars();
bars.clearGlobalActionHandlers();
// Set new actions.
Map newActionHandlers = activeRec.subActionBars
.getGlobalActionHandlers();
if (newActionHandlers != null) {
Set keys = newActionHandlers.entrySet();
Iterator iter = keys.iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
bars.setGlobalActionHandler((String) entry.getKey(),
(IAction) entry.getValue());
}
}
}
/**
* Creates a page for a given part. Adds it to the pagebook but does not
* show it.
*
* @param part
* The part we are making a page for.
* @return IWorkbenchPart
*/
private PageRec createPage(IWorkbenchPart part) {
PageRec rec = doCreatePage(part);
if (rec != null) {
mapPartToRec.put(part, rec);
preparePage(rec);
}
return rec;
}
/*
* (non-Javadoc) Method declared on PageBookView.
*/
private PageRec doCreatePage(IWorkbenchPart part) {
// Try to get an outline page.
Object obj = part.getAdapter(IContentOutlinePage.class);
if (obj instanceof IContentOutlinePage) {
IContentOutlinePage page = (IContentOutlinePage) obj;
if (page instanceof IPageBookViewPage) {
initPage((IPageBookViewPage) page);
}
page.createControl(getPageBook());
return new PageRec(part, page);
}
// There is no content outline
return null;
}
/**
* Returns the pagebook control for this view.
*
* @return the pagebook control, or <code>null</code> if not initialized
*/
protected PageBook getPageBook() {
return pageBook;
}
/**
* Returns the page record for the given part.
*
* @param part
* the part
* @return the corresponding page record, or <code>null</code> if not
* found
*/
protected PageRec getPageRec(Object part) {
return (PageRec) mapPartToRec.get(part);
}
/**
* Initializes the given page with a page site.
* <p>
* Subclasses should call this method after the page is created but before
* creating its controls.
* </p>
* <p>
* Subclasses may override
* </p>
*
* @param page
* The page to initialize
*/
protected void initPage(IPageBookViewPage page) {
try {
page.init(new SubPageSite(getSite()));
} catch (PartInitException e) {
log.error(e.getMessage());
}
}
/**
* Shows a page for the active workbench part.
*/
private void showBootstrapPart() {
IWorkbenchPart part = getBootstrapPart();
if (part != null) {
partActivated(part);
}
}
/**
* Returns the active, important workbench part for this view.
*
* @return the active important part, or <code>null</code> if none
*/
private IWorkbenchPart getBootstrapPart() {
IWorkbenchPage page = getSite().getPage();
if (page != null
&& page.getActiveEditor() instanceof MultiPageEditorPart) {
// get active editor of mutli-page editor.
return (IWorkbenchPart) page.getActiveEditor().getAdapter(
IEditorPart.class);
}
return null;
}
/**
* This method shows the page when the given part is activated. Subclasses
* may extend.
*/
private void partActivated(IWorkbenchPart part) {
// Is this an important part? If not just return.
if (!isImportant(part)) {
return;
}
// Create a page for the part.
PageRec rec = getPageRec(part);
if (rec == null) {
rec = createPage(part);
}
// Show the page.
if (rec != null) {
showPageRec(rec);
} else {
showPageRec(defaultPageRec);
}
}
/**
* Returns true if the page has already been created.
*
* @param page
* the page to test
* @return true if this page has already been created.
*/
private boolean doesPageExist(IPage page) {
return mapPageToSite.containsKey(page);
}
/**
* Returns whether the given part should be added to this view.
*
* @param part
* the input part
* @return <code>true</code> if the part is relevant, and
* <code>false</code> otherwise
*/
protected boolean isImportant(IWorkbenchPart part) {
// We only care about editors
return (part instanceof IEditorPart);
}
/**
* get the composite control (Container) of source MultiPageEditorPart
*
* @return - the composite control (Container)
*/
private CTabFolder getContainerForMultiPageEditorPart() {
if (null == tabFolder) {
tabFolder = ((CTabFolder) (getSite().getPage().getActiveEditor()
.getAdapter(CTabFolder.class)));
}
return tabFolder;
}
/**
* Removes a page record. If it is the last reference to the page dispose of
* it - otherwise just decrement the reference count.
*
* @param rec
*/
private void removePage(PageRec rec) {
mapPartToRec.remove(rec.part);
IPageSite site = (IPageSite) mapPageToSite.remove(rec.page);
if (rec.subActionBars != null) {
rec.subActionBars.dispose();
}
Control control = rec.page.getControl();
if (control != null && !control.isDisposed()) {
// Dispose the page's control so pages don't have to do this in
// their
// dispose method.
// The page's control is a child of this view's control so if this
// view
// is closed, the page's control will already be disposed.
control.dispose();
}
if (site instanceof SubPageSite) {
((SubPageSite) site).dispose();
}
// free the page
doDestroyPage(rec.part, rec);
}
/**
* Destroys a page in the pagebook for a particular part.
*
* @param part
* the input part
* @param rec
* a page record for the part
*/
protected void doDestroyPage(IWorkbenchPart part, PageRec rec) {
IContentOutlinePage page = (IContentOutlinePage) rec.page;
page.dispose();
rec.dispose();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#getControl()
*/
public Control getControl() {
return pageBook;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#setFocus()
*/
public void setFocus() {
if (getControl() != null) {
getControl().setFocus();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void addSelectionChangedListener(ISelectionChangedListener listener) {
selectionChangedListeners.add(listener);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
*/
public ISelection getSelection() {
// get the selection provider from the current page
IPage currentPage = getCurrentPage();
// during workbench startup we may be in a state when
// there is no current page
if (currentPage == null) {
return StructuredSelection.EMPTY;
}
IPageSite site = getPageSite(currentPage);
if (site == null) {
return StructuredSelection.EMPTY;
}
ISelectionProvider selProvider = site.getSelectionProvider();
if (selProvider != null) {
return selProvider.getSelection();
}
return StructuredSelection.EMPTY;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void removeSelectionChangedListener(
ISelectionChangedListener listener) {
selectionChangedListeners.remove(listener);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
*/
public void setSelection(ISelection selection) {
// get the selection provider from the current page
IPage currentPage = getCurrentPage();
// during workbench startup we may be in a state when
// there is no current page
if (currentPage == null) {
return;
}
IPageSite site = getPageSite(currentPage);
if (site == null) {
return;
}
ISelectionProvider selProvider = site.getSelectionProvider();
// and set its selection
if (selProvider != null) {
selProvider.setSelection(selection);
}
}
/**
* The selection has changed. Process the event.
*
* @param event
*/
public void pageSelectionChanged(final SelectionChangedEvent event) {
// pass on the notification to listeners
Object[] listeners = selectionChangedListeners.getListeners();
for (int i = 0; i < listeners.length; ++i) {
final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
SafeRunner.run(new SafeRunnable() {
public void run() {
l.selectionChanged(event);
}
});
}
}
/*
* (non-Javadoc)
*
* @see SelectionListener#widgetSelected(SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
EditorPart part = (EditorPart) ((CTabItem) e.item).getData();
if (part != null) {
partActivated(part);
}
}
/*
* (non-Javadoc)
*
* @see SelectionListener#widgetDefaultSelected(SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
// do nothing: no handling of default selected event
}
}