/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.tabfolder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.IPageChangeProvider;
import org.eclipse.jface.dialogs.IPageChangedListener;
import org.eclipse.jface.dialogs.PageChangedEvent;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.SubActionBars;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.Page;
import org.eclipse.ui.part.PageBook;
/**
* @author Frank Shaka
*
*/
public abstract class PageBookPage extends Page implements
IPageChangedListener, IPageClosedListener {
private IPageChangeProvider provider;
private PageBook pageBook;
private Object activeSourcePage;
private Control defaultPage;
private Map<Object, Page> pageMap = new HashMap<Object, Page>();
private DelegatedSelectionProvider selectionProvider = new DelegatedSelectionProvider();
private IPropertyChangeListener actionBarPropListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(SubActionBars.P_ACTION_HANDLERS)) {
Page page = getActivePage();
if (page != null
&& event.getSource() == page.getSite().getActionBars()) {
refreshGlobalActionHandlers();
}
}
}
};
/**
*
*/
public PageBookPage(IPageChangeProvider sourcePageProvider) {
this.provider = sourcePageProvider;
}
/**
* @return the provider
*/
public IPageChangeProvider getSourcePageProvider() {
return provider;
}
@Override
public void init(IPageSite pageSite) {
super.init(pageSite);
pageSite.setSelectionProvider(selectionProvider);
}
protected Object getActiveSourcePage() {
return activeSourcePage;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.part.Page#createControl(org.eclipse.swt.widgets.Composite
* )
*/
@Override
public void createControl(Composite parent) {
pageBook = new PageBook(parent, SWT.NONE);
provider.addPageChangedListener(this);
Object page = provider.getSelectedPage();
if (page != null) {
setActivePage(page);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#getControl()
*/
@Override
public Control getControl() {
return pageBook;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#setFocus()
*/
@Override
public void setFocus() {
pageBook.setFocus();
}
@Override
public void dispose() {
provider.removePageChangedListener(this);
Object[] pages = pageMap.entrySet().toArray();
for (int i = 0; i < pages.length; i++) {
Entry entry = (Entry) pages[i];
Object sourcePage = entry.getKey();
Page nestedPge = (Page) entry.getValue();
disposeNestedPage(nestedPge, sourcePage);
}
super.dispose();
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.ui.tabfolder.IPageClosedListener#pageClosed(java.lang.Object )
*/
public void pageClosed(Object page) {
Page nestedPage = pageMap.remove(page);
if (nestedPage == null)
return;
disposeNestedPage(nestedPage, page);
}
protected void disposeNestedPage(Page nestedPage, Object sourcePage) {
IPageSite site = nestedPage.getSite();
Control control = nestedPage.getControl();
if (control != null && !control.isDisposed()) {
control.dispose();
}
nestedPage.dispose();
((SubActionBars) site.getActionBars())
.removePropertyChangeListener(actionBarPropListener);
((NestedPageSite) site).dispose();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.dialogs.IPageChangedListener#pageChanged(org.eclipse
* .jface.dialogs.PageChangedEvent)
*/
public void pageChanged(PageChangedEvent event) {
setActivePage(event.getSelectedPage());
}
private void setActivePage(Object sourcePage) {
if (pageBook == null || pageBook.isDisposed())
return;
this.activeSourcePage = sourcePage;
if (sourcePage != null) {
showNestedPage(sourcePage);
} else {
showDefaultPage();
}
refreshGlobalActionHandlers();
/*
* The first update is for parent PageBookView to collect global action
* handlers.
*/
getSite().getActionBars().updateActionBars();
/* The seconds update is for RetargetActions to refresh their handlers. */
getSite().getActionBars().updateActionBars();
}
protected void showNestedPage(Object sourcePage) {
Page activePage = pageMap.get(sourcePage);
if (activePage == null) {
activePage = createNestedPage(sourcePage);
pageMap.put(sourcePage, activePage);
}
Control pageControl = activePage.getControl();
if (pageControl != null && !pageControl.isDisposed()) {
pageBook.showPage(pageControl);
selectionProvider.setDelegate(activePage.getSite()
.getSelectionProvider());
}
}
private void showDefaultPage() {
if (defaultPage == null || defaultPage.isDisposed()) {
defaultPage = createDefaultPage(pageBook);
}
pageBook.showPage(defaultPage);
}
protected abstract Control createDefaultPage(Composite parent);
protected Page createNestedPage(Object sourcePage) {
Page page = doCreateNestedPage(sourcePage);
NestedPageSite site = new NestedPageSite(getSite());
page.init(site);
if (pageBook != null && !pageBook.isDisposed()) {
page.createControl(pageBook);
}
((SubActionBars) site.getActionBars())
.addPropertyChangeListener(actionBarPropListener);
return page;
}
protected abstract Page doCreateNestedPage(Object sourcePage);
protected Page getActivePage() {
return activeSourcePage == null ? null : pageMap.get(activeSourcePage);
}
protected void refreshGlobalActionHandlers() {
// Clear old actions.
IActionBars bars = getSite().getActionBars();
bars.clearGlobalActionHandlers();
// Set new actions from active nested page.
Page page = getActivePage();
if (page != null) {
Map newActionHandlers = ((SubActionBars) page.getSite()
.getActionBars()).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());
}
}
}
}
}