diff options
author | cbateman | 2008-04-16 00:13:06 +0000 |
---|---|---|
committer | cbateman | 2008-04-16 00:13:06 +0000 |
commit | d89fcfbd467e1c68a9aa1e2cd4f883ecbf8bbde1 (patch) | |
tree | 82749a94c6a61787075d1a309f2df855994a96b3 /jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst | |
parent | 83dc590e354ba7a2a0d957d3f6fa7ece46a54f71 (diff) | |
download | webtools.jsf-d89fcfbd467e1c68a9aa1e2cd4f883ecbf8bbde1.tar.gz webtools.jsf-d89fcfbd467e1c68a9aa1e2cd4f883ecbf8bbde1.tar.xz webtools.jsf-d89fcfbd467e1c68a9aa1e2cd4f883ecbf8bbde1.zip |
Part of:
NEW - bug 224998: [exception] UI in new tag registry and component tree views needs finalizing.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=224998
Diffstat (limited to 'jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst')
6 files changed, 723 insertions, 0 deletions
diff --git a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractDetailsForm.java b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractDetailsForm.java new file mode 100644 index 000000000..c75290cea --- /dev/null +++ b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractDetailsForm.java @@ -0,0 +1,137 @@ +package org.eclipse.jst.jsf.common.ui.internal.form; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * The parent of all detail forms. + * + * @author cbateman + * + */ +public abstract class AbstractDetailsForm +{ + private FormToolkit _toolkit; + + /** + * + */ + protected AbstractDetailsForm() + { + super(); + } + + /** + * Called to refresh model if stale + */ + public void refresh() + { + // do nothing by default + } + + /** + * Called before createContents. + * + * @param toolkit + */ + public final void initialize(final FormToolkit toolkit) + { + _toolkit = toolkit; + doInitialize(); + } + + /** + * Override to customize initialization. getToolkit() is safe to call + * from this method. You should not make other state assumptions. + */ + protected void doInitialize() + { + // do nothing by default; + } + + /** + * Callled by MasterDetailBlock during it's dispose + */ + public abstract void dispose(); + + /** + * @param onSave + */ + public abstract void commit(boolean onSave); + + /** + * Called on this details form before it is shown, when it becomes active + * due to a matching selection change in the master form. Implementer + * should use newSelection as the new instance of their model and + * reinitialize UI as appropriate. + * @param newSelection + */ + protected abstract void doUpdateSelection(final Object newSelection); + + /** + * @return the contents control. Must not be called before createContents. + */ + public abstract Control getControl(); + + /** + * Fired to indicate that this detail form is now selected based on the + * master form selected. + * + * @param selection + */ + public void selectionChanged(final ISelection selection) + { + // by default, get the first element of the selection if there is + // one and call doUpdateSelection on it. Sub-classes may change + // this behaviour + if (selection instanceof IStructuredSelection) + { + final Object selectionObj = ((IStructuredSelection) selection) + .getFirstElement(); + doUpdateSelection(selectionObj); + } + } + + /** + * Create the contents of the detail form using 'parent'. Should not be + * called before initialize. + * + * @param parent + */ + public abstract void createContents(Composite parent); + + /** + * @return the form toolkit in use. Should not be called before + * initialize. + */ + protected final FormToolkit getToolkit() + { + return _toolkit; + } + + /** + * @return true if the form is dirty + */ + public boolean isDirty() + { + // never dirty by default + return false; + } + + /** + * @return true if form is stale + */ + public boolean isStale() + { + // always stale by default + return true; + } + + /** + * Called to set focus on the detail form's control + */ + public abstract void setFocus(); +}
\ No newline at end of file diff --git a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractMasterDetailBlock.java b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractMasterDetailBlock.java new file mode 100644 index 000000000..6674b9495 --- /dev/null +++ b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractMasterDetailBlock.java @@ -0,0 +1,196 @@ +package org.eclipse.jst.jsf.common.ui.internal.form; + +import java.util.List; + +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.widgets.Form; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * An alternative to MasterDetailBlock that doesn't use the ScrolledForm + * that causes problems as described here: + * + * http://dev.eclipse.org/newslists/news.eclipse.platform/msg73145.html + + * @author cbateman + * + */ +public abstract class AbstractMasterDetailBlock implements + ISelectionChangedListener +{ + private AbstractMasterForm _masterForm; + private Composite _detailsPanel; + private AbstractDetailsForm _curPage; + private FormToolkit _toolkit; + private StackLayout _detailLayout; + private List<AbstractDetailsForm> _detailForms; + private BlankDetailsForm _blankDetails; + + /** + * + */ + protected AbstractMasterDetailBlock() + { + super(); + } + + /** + * Disposes the master detail form + */ + public final void dispose() + { + _masterForm.dispose(); + + for (final AbstractDetailsForm detailsForm : _detailForms) + { + detailsForm.dispose(); + } + + doDispose(); + } + + /** + * Override to get custom dispose logic. Do not use this to dispose of + * master or details forms. This is done automatically for you before + * doDispose is called. + */ + protected void doDispose() + { + // do nothing by default + } + + /** + * @param toolkit + * @param form + */ + public final void createContent(final FormToolkit toolkit, final Form form) + { + _toolkit = toolkit; + + final GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + form.getBody().setLayout(layout); + final SashForm sashForm = new SashForm(form.getBody(), SWT.NULL); + // sashForm.setData("form", managedForm); //$NON-NLS-1$ + _toolkit.adapt(sashForm, false, false); + sashForm.setMenu(form.getBody().getMenu()); + sashForm.setLayoutData(new GridData(GridData.FILL_BOTH)); + initializeMasterPart(_toolkit, sashForm); + createDetailsPart(sashForm); + + _masterForm.createHead(form); + createToolBarActions(form); + form.updateToolBar(); + } + + /** + * @param toolkit + * @return the master form. + */ + protected abstract AbstractMasterForm createMasterPart( + final FormToolkit toolkit); + + private void initializeMasterPart(final FormToolkit toolkit, + final Composite parent) + { + _masterForm = createMasterPart(toolkit); + _masterForm.initialize(this); + _masterForm.createClientArea(parent); + } + + private void createToolBarActions(final Form form) + { + _masterForm.contributeActions(form.getToolBarManager()); + } + + private void createDetailsPart(final Composite parent) + { + _detailsPanel = new Composite(parent, SWT.NONE); + _detailLayout = new StackLayout(); + _detailsPanel.setLayout(_detailLayout); + + _detailForms = createDetailPages(); + + for (final AbstractDetailsForm detailForm : _detailForms) + { + detailForm.initialize(_toolkit); + detailForm.createContents(_detailsPanel); + } + + // create default blank page + _blankDetails = new BlankDetailsForm(); + _blankDetails.initialize(_toolkit); + _blankDetails.createContents(_detailsPanel); + + _curPage = _blankDetails; + _detailLayout.topControl = _curPage.getControl(); + _detailsPanel.layout(); + } + + public final void selectionChanged(final SelectionChangedEvent event) + { + final Object selectedObj = ((IStructuredSelection) event.getSelection()) + .getFirstElement(); + final AbstractDetailsForm page = selectPage(selectedObj); + if (page != null) + { + final AbstractDetailsForm fpage = page; + BusyIndicator.showWhile(_detailsPanel.getDisplay(), new Runnable() + { + public void run() + { + final AbstractDetailsForm oldPage = _curPage; + _curPage = fpage; + // commit the current page + if (oldPage != null && oldPage.isDirty()) + { + oldPage.commit(false); + } + // refresh the new page + if (fpage.isStale()) + { + fpage.refresh(); + } + _curPage.selectionChanged(event.getSelection()); + // _pageBook.showPage(_curPage.getTextSection().getControl()); + _detailLayout.topControl = _curPage.getControl(); + _detailsPanel.layout(); + } + }); + } + } + + /** + * @return a list of detail forms + */ + protected abstract List<AbstractDetailsForm> createDetailPages(); + + /** + * @param forModel + * @return the details form for 'forModel'. If implementer returns null, + * then a blank page will be provided + */ + protected abstract AbstractDetailsForm doSelectPage(final Object forModel); + + private AbstractDetailsForm selectPage(final Object forModel) + { + final AbstractDetailsForm clientForm = doSelectPage(forModel); + + if (clientForm != null) + { + return clientForm; + } + return _blankDetails; + } + +}
\ No newline at end of file diff --git a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractMasterForm.java b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractMasterForm.java new file mode 100644 index 000000000..a41adb2b5 --- /dev/null +++ b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractMasterForm.java @@ -0,0 +1,155 @@ +package org.eclipse.jst.jsf.common.ui.internal.form; + +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.ui.forms.widgets.Form; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * + * @author cbateman + * + */ +public abstract class AbstractMasterForm +{ + + private final FormToolkit _toolkit; + private ISelectionChangedListener _listener; + private ToolBarManager _toolBarManager; + + /** + * @param toolkit + */ + protected AbstractMasterForm(FormToolkit toolkit) + { + super(); + _toolkit = toolkit; + } + + /** + * @param listener + * the selection listener that is signalled to indicate the + * selection in the master has changed and the detail should be + * updated. + */ + public final void initialize(final ISelectionChangedListener listener) + { + _listener = listener; + doInitialize(); + } + + /** + * It is safe to call getListener() and get getToolkit() in this method. All + * other methods should be considered unavailable. + */ + protected void doInitialize() + { + // do nothing by default; override to do customize init + } + + /** + * @param parent + * @return the client area for the master form, using parent is the parent + * control. + */ + public abstract Control createClientArea(final Composite parent); + + /** + * @param form + */ + public final void createHead(final Form form) + { + final Composite head = form.getHead(); + final Composite container = getToolkit().createComposite(head); + container.setLayout(new RowLayout()); + + // sub-class contribution + contributeToHeadArea(getToolkit(), container); + + _toolBarManager = new ToolBarManager(SWT.FLAT); + ToolBar toolbar = _toolBarManager.createControl(container); + // _toolkit.adapt(toolbar, false, false); + + toolbar.setBackground(form.getHead().getBackground()); + toolbar.setForeground(form.getHead().getForeground()); + //toolbar.setCursor(FormsResources.getHandCursor()); + container.addDisposeListener(new DisposeListener() + { + public void widgetDisposed(DisposeEvent e) + { + if (_toolBarManager != null) + { + _toolBarManager.dispose(); + _toolBarManager = null; + } + } + }); + + form.setHeadClient(container); + + } + + /** + * Override to add client area before the toolbar. + * + * @param toolkit + * @param container + */ + protected void contributeToHeadArea(FormToolkit toolkit, Composite container) + { + // do nothing by default + } + + /** + * @param formManager + */ + public final void contributeActions(final IToolBarManager formManager) + { + contributeActions(formManager, _toolBarManager); + } + + /** + * @param formManager + * adds to the toolkit's toolbar + * @param localManager + * adds to AbstractMasterForm's toolbar. + */ + protected void contributeActions(final IToolBarManager formManager, + final IToolBarManager localManager) + { + // do nothing by default. Override to add actions. + } + + /** + * Should be called at any time after initialize and createContents when the + * owner is finished with the master-detail form block. + */ + public void dispose() + { + // do nothing by default; + } + + /** + * @return the tool kit in use. + */ + protected final FormToolkit getToolkit() + { + return _toolkit; + } + + /** + * @return the selection listener + */ + protected final ISelectionChangedListener getListener() + { + return _listener; + } +}
\ No newline at end of file diff --git a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractXMLSectionsDetailsForm.java b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractXMLSectionsDetailsForm.java new file mode 100644 index 000000000..ebacecff1 --- /dev/null +++ b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/AbstractXMLSectionsDetailsForm.java @@ -0,0 +1,176 @@ +package org.eclipse.jst.jsf.common.ui.internal.form; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.RowData; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.forms.widgets.ExpandableComposite; +import org.eclipse.ui.forms.widgets.FormText; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; + +/** + * A detail form that uses XML text sections. + * + * @author cbateman + * + */ +public abstract class AbstractXMLSectionsDetailsForm extends + AbstractDetailsForm +{ + private Map<Object, XMLTextSection> _textSections; + private Composite _detailFormComposite; + + /** + * @param parent + */ + @Override + public final void createContents(final Composite parent) + { + _detailFormComposite = getToolkit().createComposite(parent, SWT.NONE); + final RowLayout rowLayout = new RowLayout(SWT.VERTICAL); + rowLayout.fill = true; + _detailFormComposite.setLayout(rowLayout); + // take a copy of what's returned so the sub-class can't control + // the map reference + _textSections = Collections + .unmodifiableMap(new HashMap<Object, XMLTextSection>( + createXMLTextSections(_detailFormComposite))); + + final Set<XMLTextSection> expandedSections = getInitiallyExpanded(_textSections); + for (final Map.Entry<? extends Object, XMLTextSection> entry : _textSections + .entrySet()) + { + final XMLTextSection section = entry.getValue(); + if (expandedSections.contains(section)) + { + section._section.setExpanded(true); + } + } + } + + /** + * @param parent + * the parent that should be used for all XMLTextSections + * @return a map keyed by an object type understood by the sub-class + * containing as values the XMLTextSections + */ + protected abstract Map<? extends Object, XMLTextSection> createXMLTextSections( + final Composite parent); + + /** + * @param sections + * @return the subset of XMLTextSections in the provided map that are to be + * expanded. NOTE: all elements in the returned set must be in + * sections.getValues. + */ + protected abstract Set<XMLTextSection> getInitiallyExpanded( + final Map<Object, XMLTextSection> sections); + + /** + * @return the control for this form + */ + @Override + public Control getControl() + { + return _detailFormComposite; + } + + /** + * @param selection + */ + public final void selectionChanged(final ISelection selection) + { + if (selection instanceof IStructuredSelection) + { + final Object selectionObj = ((IStructuredSelection) selection) + .getFirstElement(); + doUpdateSelection(selectionObj); + } + } + + @Override + public void commit(final boolean onSave) + { + // do nothing + } + + @Override + public void dispose() + { + // do nothing + } + + @Override + public void setFocus() + { + // do nothing; sub-classes should override to pick an XMLTextSection + // where they want focus. + } + + /** + * An XML text section + * + */ + protected final static class XMLTextSection + { + private final Section _section; + private FormText _formText; + + /** + * @param toolkit + * @param parent + * @param title + */ + public XMLTextSection(final FormToolkit toolkit, + final Composite parent, final String title) + { + _section = toolkit.createSection(parent, + ExpandableComposite.TREE_NODE + | ExpandableComposite.CLIENT_INDENT); + _section.setLayoutData(new RowData()); + _section.setText(title); + + _formText = toolkit.createFormText(_section, true); + _formText.setText("", false, false); + + _section.setClient(_formText); + } + + /** + * @param text + * @param parseTags + * @param expandURLs + */ + public void setText(final String text, final boolean parseTags, + final boolean expandURLs) + { + _formText.setText(text, parseTags, expandURLs); + } + + /** + * @return the parent control. + */ + public Control getControl() + { + return _section; + } + + /** + * Force a visual relayout and update. + */ + public void refresh() + { + _section.getParent().layout(true, true); + } + } + +} diff --git a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/BlankDetailsForm.java b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/BlankDetailsForm.java new file mode 100644 index 000000000..e4635b599 --- /dev/null +++ b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/form/BlankDetailsForm.java @@ -0,0 +1,51 @@ +package org.eclipse.jst.jsf.common.ui.internal.form; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** + * A blank details form. + * + * @author cbateman + * + */ +public final class BlankDetailsForm extends AbstractDetailsForm +{ + private Composite _emptyPanel; + + @Override + public void createContents(Composite parent) + { + _emptyPanel = getToolkit().createComposite(parent); + } + + @Override + public Control getControl() + { + return _emptyPanel; + } + + @Override + protected void doUpdateSelection(Object newSelection) + { + // do nothing + } + + @Override + public void commit(boolean onSave) + { + // nothing to commit + } + + @Override + public void dispose() + { + // nothing to dispose + } + + @Override + public void setFocus() + { + // don't bother changing focus + } +} diff --git a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/utils/JSFSharedImages.java b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/utils/JSFSharedImages.java index 298241b34..3790e904f 100644 --- a/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/utils/JSFSharedImages.java +++ b/jsf/plugins/org.eclipse.jst.jsf.common.ui/src/org/eclipse/jst/jsf/common/ui/internal/utils/JSFSharedImages.java @@ -41,4 +41,12 @@ public interface JSFSharedImages */ public final static String GENERIC_CONVERTER_IMG = "jsf_converter.gif"; + /** + * A generic image suitable for representing a view root. Same as the + * default image generally associated with f:view. + * + * Size: 16x16. + */ + public static final String GENERIC_VIEWROOT_IMG = "jsf_view.gif"; + } |