/******************************************************************************* * Copyright (c) 2008, 2011 Obeo. * 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: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.emf.eef.runtime.ui.viewers; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.Assert; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.eef.runtime.api.notify.IPropertiesEditionEvent; import org.eclipse.emf.eef.runtime.api.notify.IPropertiesEditionListener; import org.eclipse.emf.eef.runtime.api.parts.IFormPropertiesEditionPart; import org.eclipse.emf.eef.runtime.api.parts.IPropertiesEditionPart; import org.eclipse.emf.eef.runtime.api.parts.ISWTPropertiesEditionPart; import org.eclipse.emf.eef.runtime.context.ExtendedPropertiesEditingContext; import org.eclipse.emf.eef.runtime.context.PropertiesEditingContext; import org.eclipse.emf.eef.runtime.impl.parts.CompositePropertiesEditionPart; import org.eclipse.emf.eef.runtime.ui.parts.impl.BindingViewHelper; import org.eclipse.emf.eef.runtime.ui.utils.EEFRuntimeUIMessages; import org.eclipse.emf.eef.runtime.ui.viewers.filters.PropertiesEditionPartFilter; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.widgets.FormToolkit; /** * @author <a href="mailto:goulwen.lefur@obeo.fr">Goulwen Le Fur</a> */ public class PropertiesEditionViewer extends StructuredViewer { /** * Graphical purpose fields */ private FormToolkit toolkit; /** * TODO: sets this private */ protected CTabFolder folder = null; /** * TODO: sets this private */ protected Composite control; protected boolean dynamicTabHeader = true; /** * The expected kind for the part. */ private int kind; private List<ViewerFilter> filters; private boolean initState = false; protected ResourceSet allResources; private ItemListener listener; /** * TODO: sets this private */ protected ScrolledComposite scroll; /** * Create an Viewer for EEF properties editing in the given parent composite. * * @param parent * the parent control * @param style * the SWT style bits * @param kind * the kind of the part */ public PropertiesEditionViewer(Composite container, ResourceSet allResources, int style, int kind) { control = new Composite(container, SWT.NONE); control.setLayout(new FillLayout()); control.setLayoutData(new GridData(GridData.FILL_BOTH)); scroll = new ScrolledComposite(control, SWT.V_SCROLL | SWT.H_SCROLL); folder = new CTabFolder(scroll, style); folder.setSimple(false); this.allResources = allResources; this.kind = kind; scroll.setContent(folder); scroll.setExpandHorizontal(true); scroll.setExpandVertical(true); listener = new ItemListener(); folder.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ public void widgetSelected(SelectionEvent e) { listener.updateControlListener(); } }); control.addControlListener(listener); } /** * Create an Viewer for EEF properties editing in the given parent composite * * @param parent * the parent control * @param kind * the kind of the part */ public PropertiesEditionViewer(Composite container, ResourceSet allResources, int kind) { this(container, allResources, SWT.BORDER, kind); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.Viewer#getControl() */ public Control getControl() { return control; } /** * @return the toolkit */ public FormToolkit getToolkit() { return toolkit; } /** * @param toolkit * the toolkit to set */ public void setToolkit(FormToolkit toolkit) { this.toolkit = toolkit; toolkit.adapt(control); toolkit.adapt(scroll); toolkit.adapt(folder); } /** * @return <code>true</code> if the viewer is initializing */ public boolean isInitializing() { return initState; } /** * Defines if the tab headers are visible when there is more than 1 tab. * * @param dynamic * the dynamic tab header */ public void setDynamicTabHeader(boolean dynamic) { dynamicTabHeader = dynamic; } /** * @param listener * the properties listener to add */ public void addPropertiesListener(IPropertiesEditionListener listener) { if (getContentProvider() != null) ((PropertiesEditionContentProvider)getContentProvider()).addPropertiesListener(listener); } /** * Returns the root element. * <p> * The default implementation of this framework method forwards to <code>getInput</code>. Override if the * root element is different from the viewer's input element. * </p> * * @return the root element, or <code>null</code> if none */ protected Object getRoot() { return getEObjectFromInput(); } /** * @return */ public EObject getEObjectFromInput() { EObject result = null; if (getInput() instanceof EObject) { result = (EObject)getInput(); } else if (getInput() instanceof PropertiesEditingContext) { result = ((PropertiesEditingContext)getInput()).getEObject(); } return result; } /* * =============================== Filters management =============================== */ /** * Returns this viewer's filters. * * @return an array of viewer filters * @see StructuredViewer#setFilters(ViewerFilter[]) */ public ViewerFilter[] getFilters() { if (filters == null) { return new ViewerFilter[0]; } ViewerFilter[] result = new ViewerFilter[filters.size()]; filters.toArray(result); return result; } /** * Adds the given filter to this viewer, and triggers refiltering and resorting of the elements. If you * want to add more than one filter consider using {@link StructuredViewer#setFilters(ViewerFilter[])}. * * @param filter * a viewer filter * @see StructuredViewer#setFilters(ViewerFilter[]) */ public void addFilter(ViewerFilter filter) { if (filters == null) { filters = new ArrayList<ViewerFilter>(); } filters.add(filter); refresh(); } /** * Removes the given filter from this viewer, and triggers refiltering and resorting of the elements if * required. Has no effect if the identical filter is not registered. If you want to remove more than one * filter consider using {@link StructuredViewer#setFilters(ViewerFilter[])}. * * @param filter * a viewer filter * @see StructuredViewer#setFilters(ViewerFilter[]) */ public void removeFilter(ViewerFilter filter) { Assert.isNotNull(filter); if (filters != null) { // Note: can't use List.remove(Object). Use identity comparison // instead. for (Iterator<ViewerFilter> i = filters.iterator(); i.hasNext();) { Object o = i.next(); if (o == filter) { i.remove(); refresh(); if (filters.size() == 0) { filters = null; } return; } } } } /** * Sets the filters, replacing any previous filters, and triggers refiltering and resorting of the * elements. * * @param filters * an array of viewer filters * @since 3.3 */ public void setFilters(ViewerFilter[] filters) { if (filters.length == 0) { resetFilters(); } else { this.filters = new ArrayList<ViewerFilter>(Arrays.asList(filters)); refresh(); } } /** * Discards this viewer's filters and triggers refiltering and resorting of the elements. */ public void resetFilters() { if (filters != null) { filters = null; refresh(); } } /** * Returns the result of running the given elements through the filters. * * @param elements * the elements to filter * @return only the elements which all filters accept */ private boolean selectPart(String key, IPropertiesEditionPart propertiesEditionPart) { boolean result = true; if (filters != null) { boolean select = true; for (int j = 0; j < filters.size(); j++) { ViewerFilter viewerFilter = filters.get(j); if (viewerFilter instanceof PropertiesEditionPartFilter) { select = viewerFilter.select(this, key, propertiesEditionPart); if (!select) { result = false; break; } } } } return result; } /** * Validate the model and return the resulting Diagnostic * * @param event * the event triggering the validation * @return the resulting value */ public Diagnostic validateValue(IPropertiesEditionEvent event) { if (getContentProvider() != null) return ((PropertiesEditionContentProvider)getContentProvider()).validateValue(event); return null; } /* * ============================== Selection management ============================== */ /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.Viewer#getSelection() */ public ISelection getSelection() { Object root = getRoot(); if (root != null) return new StructuredSelection(root); return new StructuredSelection(); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean) */ public void setSelection(ISelection selection, boolean reveal) { // TODO Auto-generated method stub } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List, boolean) */ protected void setSelectionToWidget(List l, boolean reveal) { // TODO Auto-generated method stub } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget() */ protected List getSelectionFromWidget() { // TODO Auto-generated method stub return null; } /* * ============================== Graphical management ============================== */ /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object) */ protected void internalRefresh(Object element) { } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object) */ protected void inputChanged(Object input, Object oldInput) { super.inputChanged(input, oldInput); initControl(); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object) */ public void reveal(Object element) { // Nothing to do } /** * @param propertiesEditionContentProvider * @return */ public CompositePropertiesEditionPart getSelectedPart() { PropertiesEditionContentProvider propertiesEditionContentProvider = (PropertiesEditionContentProvider)getContentProvider(); String selectedPartTitle = folder.getSelection().getText(); return (CompositePropertiesEditionPart)propertiesEditionContentProvider.getPropertiesEditionPart(kind, selectedPartTitle); } /** * Create the control content */ protected void initControl() { if (getContentProvider() != null) { PropertiesEditionContentProvider propertiesEditionProvider = (PropertiesEditionContentProvider)getContentProvider(); // first set initState to true to not handle changes yet initState = true; String[] partsList = propertiesEditionProvider.partsList(); initTabbedControl(propertiesEditionProvider, partsList); initState = false; } } /** * Initialize the control of the viewer in "Tabbed case". Defines one tab for each PropertiesEditionPart * of the component. * * @param propertiesEditionProvider * @param partsList */ protected void initTabbedControl(PropertiesEditionContentProvider propertiesEditionProvider, String[] partsList) { resetTab(); List<String> selectedParts = new ArrayList<String>(); if (kind == 1) { if (propertiesEditionProvider.getPropertiesEditingComponent().getEditingContext() instanceof ExtendedPropertiesEditingContext) { ExtendedPropertiesEditingContext editingContext = (ExtendedPropertiesEditingContext) propertiesEditionProvider.getPropertiesEditingComponent().getEditingContext(); editingContext.setHelper(new BindingViewHelper(editingContext, toolkit)); } toolkit.adapt(folder, true, true); toolkit.getColors().initializeSectionToolBarColors(); folder.setSelectionBackground( new Color[] {toolkit.getColors().getColor(IFormColors.H_GRADIENT_START), toolkit.getColors().getColor(IFormColors.H_GRADIENT_END)}, new int[] {50}, true); folder.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); folder.setSelectionForeground(toolkit.getColors().getColor(IFormColors.TITLE)); } for (int i = 0; i < partsList.length; i++) { String nextComponentKey = partsList[i]; IPropertiesEditionPart part = propertiesEditionProvider.getPropertiesEditionPart(kind, nextComponentKey); if (selectPart(nextComponentKey, part)) { selectedParts.add(nextComponentKey); addPartTab(propertiesEditionProvider, part, nextComponentKey); } else { part.setVisible(false); } } if (dynamicTabHeader) { if (selectedParts.size() > 1) folder.setTabHeight(SWT.DEFAULT); else folder.setTabHeight(0); } folder.setSelection(0); } /** * Create a new tab in the folder for a given PropertiesEditionPart. * * @param propertiesEditionProvider * the EEF properties provider * @param key * the key of the part * @param tabText * the title of the tab */ private void addPartTab(PropertiesEditionContentProvider propertiesEditionProvider, IPropertiesEditionPart part, String key) { Composite editComposite = null; if (part instanceof ISWTPropertiesEditionPart) editComposite = ((ISWTPropertiesEditionPart)part).createFigure(folder); if (part instanceof IFormPropertiesEditionPart) { Assert.isNotNull(toolkit, EEFRuntimeUIMessages.PropertiesEditionViewer_widget_factory_not_defined); editComposite = ((IFormPropertiesEditionPart)part).createFigure(folder, toolkit); } if (editComposite != null) { if (allResources == null && getEObjectFromInput() != null) propertiesEditionProvider.initPart(propertiesEditionProvider.translatePart(key), kind, ((EObject)getEObjectFromInput())); else propertiesEditionProvider.initPart(propertiesEditionProvider.translatePart(key), kind, ((EObject)getEObjectFromInput()), allResources); } else editComposite = new Composite(folder, SWT.NONE); CTabItem tab = new CTabItem(folder, SWT.NONE); tab.setControl(editComposite); tab.setText(part.getTitle()); } /** * Reset all the tabs of the folder. */ private void resetTab() { if (folder.getItemCount() > 0) { CTabItem[] items = folder.getItems(); for (int i = 0; i < items.length; i++) { CTabItem cTabItem = items[i]; if (!cTabItem.getControl().isDisposed()) cTabItem.getControl().dispose(); //adding this line solves my problem. if (!cTabItem.isDisposed()) cTabItem.dispose(); } } } /** * Refresh the active tab. */ public void refreshTab() { getSelectedPart().refresh(); PropertiesEditionContentProvider propertiesEditionContentProvider = (PropertiesEditionContentProvider)getContentProvider(); propertiesEditionContentProvider.initPart(propertiesEditionContentProvider.translatePart(folder.getSelection().getText()), kind, ((EObject)getEObjectFromInput())); } /* * ================================= Search methods ================================= */ /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object) */ protected Widget doFindInputItem(Object element) { // TODO Auto-generated method stub return null; } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object) */ protected Widget doFindItem(Object element) { // TODO Auto-generated method stub return null; } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget, * java.lang.Object, boolean) */ protected void doUpdateItem(Widget item, Object element, boolean fullMap) { // TODO Auto-generated method stub } /* * ================================= Scroll management ================================= */ /** * update the scroll composite size */ private void updateScrollSize() { if (folder.getSelection() != null && folder.getSelection().getControl() != null) { scroll.setMinSize(folder.getSelection().getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT)); } } private class ItemListener implements ControlListener { Control listenedControl = null; /** * {@inheritDoc} * * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent) */ public void controlMoved(ControlEvent e) { // Nothing to do } /** * {@inheritDoc} * * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent) */ public void controlResized(ControlEvent e) { updateScrollSize(); } /** * update listeners managing scroll composite size */ public void updateControlListener() { removeControlListener(); Control control2 = folder.getSelection().getControl(); if (control2 != null) { listener.listenedControl = control2; control2.addControlListener(listener); } } public void removeControlListener() { if (listener.listenedControl != null && !listener.listenedControl.isDisposed()) { listener.listenedControl.removeControlListener(listener); } } } }