/*******************************************************************************
* Copyright (c) 2000, 2009 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package net.enilink.commons.ui.editor;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.forms.IMessage;
import org.eclipse.ui.forms.IMessageManager;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.SharedScrolledComposite;
/**
* Managed form wraps a form widget and adds life cycle methods for form parts.
* A form part is a portion of the form that participates in form life cycle
* events.
* <p>
* There is requirement for 1/1 mapping between widgets and form parts. A widget
* like Section can be a part by itself, but a number of widgets can join around
* one form part.
* <p>
* Note to developers: this class is left public to allow its use beyond the
* original intention (inside a multi-page editor's page). You should limit the
* use of this class to make new instances inside a form container (wizard page,
* dialog etc.). Clients that need access to the class should not do it
* directly. Instead, they should do it through IManagedForm interface as much
* as possible.
*/
public class EditorForm implements IEditorForm {
private Object input;
private EditorWidgetFactory widgetFactory;
private boolean ownsWidgetFactory;
private boolean initialized;
private MessageManager messageManager;
private List<IEditorPart> parts = new ArrayList<IEditorPart>();
private Composite parent;
private List<IEditorStateListener> stateListeners = new ArrayList<IEditorStateListener>();
/**
* Creates a managed form in the provided parent. Form toolkit and widget
* will be created and owned by this object.
*
* @param parent
* the parent widget
*/
public EditorForm(Composite parent) {
this.parent = parent;
widgetFactory = new EditorWidgetFactory(parent.getDisplay());
ownsWidgetFactory = true;
}
/**
* Creates a managed form that will use the provided widget factory
*
* @param widgetFactory
*/
public EditorForm(Composite parent, EditorWidgetFactory widgetFactory) {
this.parent = parent;
this.widgetFactory = widgetFactory;
}
/**
* Creates a managed form that will use the provided widget factory
*
* @param widgetFactory
*/
public EditorForm(Composite parent, FormToolkit formToolkit) {
this(parent, new EditorWidgetFactory(formToolkit));
}
public void addPart(IEditorPart part) {
parts.add(part);
part.initialize(this);
}
public void removePart(IEditorPart part) {
parts.remove(part);
}
public IEditorPart[] getParts() {
return parts.toArray(new IEditorPart[parts.size()]);
}
public EditorWidgetFactory getWidgetFactory() {
return widgetFactory;
}
/**
* Initializes the form by looping through the managed parts and
* initializing them. Has no effect if already called once.
*/
public void initialize() {
if (initialized)
return;
for (int i = 0; i < parts.size(); i++) {
IEditorPart part = parts.get(i);
part.initialize(this);
}
initialized = true;
}
/**
* Disposes all the parts in this form.
*/
public void dispose() {
for (int i = 0; i < parts.size(); i++) {
IEditorPart part = parts.get(i);
part.dispose();
}
if (ownsWidgetFactory) {
widgetFactory.dispose();
}
}
/**
* Refreshes the form by refreshes all the stale parts. Since 3.1, this
* method is performed on a UI thread when called from another thread so it
* is not needed to wrap the call in <code>Display.syncExec</code> or
* <code>asyncExec</code>.
*/
public void refreshStale() {
Thread t = Thread.currentThread();
Thread dt = widgetFactory.getColors().getDisplay().getThread();
if (t.equals(dt))
doRefreshStale();
else {
widgetFactory.getColors().getDisplay().asyncExec(new Runnable() {
public void run() {
doRefreshStale();
}
});
}
}
private void doRefreshStale() {
int nrefreshed = 0;
for (int i = 0; i < parts.size(); i++) {
IEditorPart part = parts.get(i);
if (part.isStale()) {
part.refresh();
nrefreshed++;
}
}
if (nrefreshed > 0) {
reflow(true);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#commit(boolean)
*/
public void commit(boolean onSave) {
for (IEditorPart part : parts) {
if (part.isDirty()) {
part.commit(onSave);
}
}
}
public void reflow(boolean changed) {
if (parent instanceof SharedScrolledComposite) {
((SharedScrolledComposite) parent).reflow(changed);
} else if (parent.getParent() instanceof SharedScrolledComposite) {
((SharedScrolledComposite) parent.getParent()).reflow(changed);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#setInput(java.lang.Object)
*/
public boolean setInput(Object input) {
boolean partResult = false;
this.input = input;
for (IEditorPart part : parts) {
boolean result = part.setEditorInput(input);
if (result) {
partResult = true;
}
}
return partResult;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#getInput()
*/
public Object getInput() {
return input;
}
/**
* Transfers the focus to the first form part which wants to own it.
*/
public void setFocus() {
for (IEditorPart part : parts) {
if (part.setFocus()) {
return;
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#isDirty()
*/
public boolean isDirty() {
for (IEditorPart part : parts) {
if (part.isDirty()) {
return true;
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#isStale()
*/
public boolean isStale() {
for (IEditorPart part : parts) {
if (part.isStale()) {
return true;
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#dirtyStateChanged()
*/
public void dirtyStateChanged() {
fireDirtyStateChanged();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#staleStateChanged()
*/
public void staleStateChanged() {
fireStaleStateChanged();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.forms.IManagedForm#getMessageManager()
*/
public IMessageManager getMessageManager() {
if (messageManager == null) {
messageManager = new MessageManager(new IMessageContainer() {
@Override
public Composite getComposite() {
if (parent instanceof ScrolledForm) {
return ((ScrolledForm) parent).getBody();
}
return parent;
}
@Override
public void setMessage(String newMessage, int newType,
IMessage[] messages) {
if (parent instanceof ScrolledForm) {
((ScrolledForm) parent).setMessage(newMessage, newType,
messages);
} else if (parent.getParent() instanceof ScrolledForm) {
((ScrolledForm) parent.getParent()).setMessage(
newMessage, newType, messages);
}
}
@Override
public void setMessage(String newMessage, int newType) {
setMessage(newMessage, newType, null);
}
});
}
return messageManager;
}
public Shell getShell() {
return parent.getShell();
}
private void fireDirtyStateChanged() {
for (IEditorStateListener listener : new ArrayList<IEditorStateListener>(
stateListeners)) {
listener.dirtyStateChanged(this);
}
}
private void fireStaleStateChanged() {
for (IEditorStateListener listener : new ArrayList<IEditorStateListener>(
stateListeners)) {
listener.staleStateChanged(this);
}
}
/**
* A part can use this method to notify other parts that implement
* IPartSelectionListener about selection changes.
*
* @param firingPart
* the part that broadcasts the selection
* @param selection
* the selection in the part
* @see IPartSelectionListener
*/
public void fireSelectionChanged(IEditorPart firingPart,
ISelection selection) {
for (IEditorPart part : parts) {
if (firingPart.equals(part)) {
continue;
}
if (part instanceof IPartSelectionListener) {
((IPartSelectionListener) part).selectionChanged(firingPart,
selection);
}
}
}
@Override
public Composite getBody() {
if (parent instanceof ScrolledForm) {
return ((ScrolledForm) parent).getBody();
}
return parent;
}
public boolean addStateListener(IEditorStateListener stateListener) {
if (!stateListeners.contains(stateListener)) {
stateListeners.add(stateListener);
return true;
}
return false;
}
public boolean removeStateListener(IEditorStateListener stateListener) {
return stateListeners.remove(stateListener);
}
@SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class adapter) {
return null;
}
}