/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ui.table;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.provider.INotifyChangedListener;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.core.designer.util.I18nUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelUtil;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.common.eventsupport.SelectionProvider;
import org.teiid.designer.ui.common.eventsupport.SelectionUtilities;
import org.teiid.designer.ui.common.print.IPrintable;
import org.teiid.designer.ui.common.print.Printable;
import org.teiid.designer.ui.common.table.DoubleClickTableViewer;
import org.teiid.designer.ui.common.table.TableColumnSelectionHelper;
import org.teiid.designer.ui.common.util.SystemClipboardUtilities;
import org.teiid.designer.ui.common.util.UiUtil;
import org.teiid.designer.ui.common.viewsupport.UiBusyIndicator;
import org.teiid.designer.ui.editors.AbstractModelEditorPageActionBarContributor;
import org.teiid.designer.ui.editors.IInlineRenameable;
import org.teiid.designer.ui.editors.INavigationSupported;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.editors.ModelEditorPage;
import org.teiid.designer.ui.editors.ModelEditorPageOutline;
import org.teiid.designer.ui.editors.NavigableEditor;
import org.teiid.designer.ui.editors.NavigationMarker;
import org.teiid.designer.ui.event.ModelResourceEvent;
import org.teiid.designer.ui.explorer.ModelExplorerLabelProvider;
import org.teiid.designer.ui.properties.udp.ExtensionPropertyDescriptor;
import org.teiid.designer.ui.util.NoOpDropTargetAdapter;
import org.teiid.designer.ui.viewsupport.ModelObjectUtilities;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
* ModelTableEditor is a tabbed panel of tables containing the content of the model, with the tab names corresponding to the
* different types of objects in the model.
*
* @since 8.0
*/
public class ModelTableEditor extends NavigableEditor
implements ModelEditorPage, IInlineRenameable, ITablePasteValidator, INavigationSupported, UiConstants {
private static final String PREFIX = I18nUtil.getPropertyPrefix(ModelTableEditor.class);
static final String UNDO_PREFIX = UiConstants.Util.getString("ModelTableEditor.undoPrefix") + ' '; //$NON-NLS-1$
private static final String UNDO_INSERT_ROWS = UiConstants.Util.getString("ModelTableEditor.undoInsertRows"); //$NON-NLS-1$
private static final String TOOLTIP = UiConstants.Util.getString("ModelTableEditor.tooltip"); //$NON-NLS-1$
/** A label provider for tab names and icons */
private ILabelProvider labelProvider;
/** A content provider for collecting up all the objects in the model */
private ITreeContentProvider contentProvider;
/** The container widget */
TabFolder tabFolder;
/** The SelectionProvider for selection in the tables to be hooked to the ModelEditor */
ModelObjectSelectionManager selectionMgr;
/** Key=tab name, Value=TableViewer */
Map viewers = new HashMap();
/** Responsible for contributing actions to menus, toolbars, etc. */
private ModelTableEditorActionContributor actionContributor;
/** Responsible for handling notification events on all TableViewers */
private TableNotificationHandler notificationHandler;
/** This Editor's ModelResource */
private ModelResource modelResource;
/** This Editor's Resource */
private Resource emfResource;
Map selectionHelperMap = new HashMap();
Map modelMap = new HashMap(); // key=viewer value=model
private String title;
private boolean lastReadOnly;
private IBaseLabelProvider tableLabelProvider = new ModelTableLabelProvider();
ModelEditor meParentEditor;
/**
* Construct an instance of ModelTableEditor.
*/
public ModelTableEditor() {
super();
}
/**
* Create this part's visual control. Responds by creating the CTabFolder, then filling the tabs from the model.
*
* @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPartControl( Composite parent ) {
this.selectionMgr = new ModelObjectSelectionManager();
this.tabFolder = createContainer(parent);
createTabs();
// set the active page (page 0 by default), unless it has already been done
int tabID = getActiveTab();
if (tabID == 1 || tabID == 0) {
setActiveTab(0);
// programmatically setting selection to tab 0 while constructing doesn't get
// handled by our handler created in createContainer(Composite) since it hasn't been
// called yet. So call pageChange method so that tab 0 can construct it's columns
pageChange(0);
}
}
/**
* Creates an empty CTabFolder with no style bits set, and hooks a selection listener which calls <code>pageChange()</code>
* whenever the selected tab changes.
*
* @return a new container
*/
private TabFolder createContainer( Composite parent ) {
final TabFolder container = new TabFolder(parent, SWT.TOP);
container.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent e ) {
int newPageIndex = container.indexOf((TabItem)e.item);
pageChange(newPageIndex);
}
});
return container;
}
/**
* Using the EditorInput supplied to this ModelEditorPage, create the tabs in the container for each EClass type found in the
* model.
*/
protected void createTabs() {
try {
labelProvider = new ModelExplorerLabelProvider();
contentProvider = ModelUtilities.getModelContentProvider();
HashMap objectTypeMap = new HashMap();
Collection types = buildObjectTypeMap(objectTypeMap);
int tabIndex = 0;
for (Iterator iter = types.iterator(); iter.hasNext(); tabIndex++) {
EClass tabClass = (EClass)iter.next();
ArrayList instanceList = (ArrayList)objectTypeMap.get(tabClass);
if (canAddTable(instanceList.get(0))) {
addTab(tabClass, instanceList, tabIndex);
} else {
--tabIndex;
}
}
} catch (Exception e) {
Util.log(IStatus.ERROR, e, PREFIX + "loadError"); //$NON-NLS-1$
}
}
public boolean canAddTable( Object instance ) {
IPropertySource propertySource = ModelUtilities.getEmfPropertySourceProvider().getPropertySource(instance);
IPropertyDescriptor[] properties = propertySource.getPropertyDescriptors();
return properties.length > 0;
}
protected int addTab( EClass tabClass,
ArrayList instanceList,
int tabIndex ) {
boolean supportsDescriptions = ModelUtilities.supportsModelDescription(this.modelResource.getResource());
ModelObjectTableModel model = ModelObjectTableModelFactory.createModelObjectTableModel(supportsDescriptions,
tabClass,
instanceList);
if (model.canView()) {
ModelTableEditorViewer tableViewer = new ModelTableEditorViewer(tabFolder, SWT.V_SCROLL | SWT.H_SCROLL
| SWT.FULL_SELECTION | SWT.MULTI);
tableViewer.addDropSupport(DND.DROP_COPY, new Transfer[] {}, NoOpDropTargetAdapter.getInstance());
selectionHelperMap.put(tableViewer, new TableColumnSelectionHelper(tableViewer));
modelMap.put(tableViewer, model);
tableViewer.getTable().setHeaderVisible(true);
tableViewer.getTable().setLinesVisible(true);
TableLayout layout = new TableLayout();
tableViewer.getTable().setLayout(layout);
model.setTableViewer(tableViewer);
tableViewer.setCellModifier(new TableCellModifier());
tableViewer.setContentProvider(new ModelTableContentProvider(model));
tableViewer.setLabelProvider(tableLabelProvider);
tableViewer.setSorter(new ModelObjectTableSorter(tableViewer));
// create a selection provider to listen to this TableViewer
ModelObjectTableSelectionManager tableSelectionMgr = new ModelObjectTableSelectionManager(tableViewer, model);
// broadcast selection change from the table out to the ModelEditor
tableSelectionMgr.addSelectionChangedListener(this.selectionMgr);
// hook each table selection provder to the workbench selection listener
this.selectionMgr.addSelectionChangedListener(tableSelectionMgr);
if (tabIndex >= 0) {
tabIndex = addTab(tableViewer.getControl(), tabIndex);
} else {
tabIndex = addTab(tableViewer.getControl());
}
TabItem item = tabFolder.getItems()[tabIndex];
item.setData(tabClass);
String tabName = tabClass.getName();
tabName = CoreStringUtil.computePluralForm(CoreStringUtil.computeDisplayableForm(tabName));
setTabText(tabIndex, tabName);
setTabToolTipText(tabIndex, tabName);
Object o = instanceList.get(0);
setTabImage(tabIndex, labelProvider.getImage(o));
tableSelectionMgr.setName(tabName);
viewers.put(tabName, tableViewer);
getNotificationHandler().addTable(tabClass, tableViewer, model);
// Added this listener to handle tab selection on table viewer. This will fire a selection based on
// the selected table rows in the applicable tabbed viewer.
tabFolder.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent event ) {
if (event.getSource() instanceof TabFolder) {
// event came from the table. convert selection to EObjects and fire out to listeners
if (getCurrentViewer() != null) {
StructuredSelection tableSel = (StructuredSelection)getCurrentViewer().getSelection();
final Iterator rowIter = tableSel.iterator();
final ArrayList objectList = new ArrayList(tableSel.size());
for (final Iterator iter = rowIter; iter.hasNext();) {
final ModelRowElement mre = (ModelRowElement)iter.next();
objectList.add(mre.getModelObject());
}
selectionMgr.selectionChanged(new SelectionChangedEvent(getCurrentViewer(),
new StructuredSelection(objectList)));
}
}
}
});
}
return tabIndex;
}
/**
* Build a HashMap of the content of the current EditorInput, where the keys are the unique EClass types of objects contained
* in the model, and the values are ArrayLists of EObjects of the key type.
*
* @return an ordered list of keys in the map
* @throws CoreException
*/
private Collection buildObjectTypeMap( HashMap objectTypeMap ) throws CoreException {
Collection modelContent = modelResource.getEObjects();
for (Iterator iter = modelContent.iterator(); iter.hasNext();) {
loadObjectTypeMap(iter.next(), objectTypeMap);
}
TreeSet orderedSet = new TreeSet(new EClassNameComparator());
orderedSet.addAll(objectTypeMap.keySet());
return orderedSet;
}
/**
* Recursively fill the model object HashMap beginning with the specified object.
*/
private void loadObjectTypeMap( Object o,
HashMap objectTypeMap ) {
if (o instanceof EObject) {
EObject eObj = (EObject)o;
if (ModelObjectUtilities.isPrimaryMetamodelObject(eObj)) {
ArrayList list = (ArrayList)objectTypeMap.get(eObj.eClass());
if (list == null) {
list = new ArrayList();
objectTypeMap.put(eObj.eClass(), list);
}
list.add(o);
// swj: amazingly, if you don't ask the EMF item provider hasChildren
// before getting children, you don't always get the correct
// array of children.
if (contentProvider.hasChildren(eObj)) {
Object[] children = contentProvider.getChildren(eObj);
for (int i = 0; i < children.length; ++i) {
loadObjectTypeMap(children[i], objectTypeMap);
}
}
}
}
}
/**
* Creates and adds a new tab containing the given control to this editor. The control may be <code>null</code>, allowing it
* to be created and set later using <code>setControl</code>.
*
* @param control the control, or <code>null</code>
* @return the index of the new tab
* @see #setControl
*/
protected int addTab( Control control ) {
createTab(control);
return getTabCount() - 1;
}
/**
* Creates and adds a new tab containing the given control to this editor. The control may be <code>null</code>, allowing it
* to be created and set later using <code>setControl</code>.
*
* @param control the control, or <code>null</code>
* @return the index of the new tab
* @see #setControl
*/
protected int addTab( Control control,
int index ) {
return tabFolder.indexOf(createTab(control, index));
}
/**
* Creates a tab item and places control in the new item. The item is a CTabItem with no style bits set.
*
* @param control is the control to be placed in an item
* @return a new item
*/
private TabItem createTab( Control control ) {
TabItem item = new TabItem(tabFolder, SWT.NONE);
item.setControl(control);
return item;
}
/**
* Creates a tab item and places control in the new item. The item is a CTabItem with no style bits set.
*
* @param control is the control to be placed in an item
* @return a new item
*/
private TabItem createTab( Control control,
int index ) {
TabItem item = new TabItem(tabFolder, SWT.NONE, index);
item.setControl(control);
return item;
}
/**
* Returns the control for the given tab index, or <code>null</code> if no control has been set for the tab. The index must be
* valid.
* <p>
* Subclasses should not override this method
* </p>
*
* @param tabIndex the index of the tab
* @return the control for the specified tab, or <code>null</code> if none has been set
*/
protected Control getControl( int tabIndex ) {
if (tabIndex >= 0 && tabIndex < tabFolder.getItemCount()) {
return getItem(tabIndex).getControl();
}
return null;
}
/**
* Returns the tab item for the given page index (page index is 0-based). The page index must be valid.
*
* @param pageIndex the index of the tab
* @return the CTabItem item for the given tab index
*/
private TabItem getItem( int tabIndex ) {
// May not have been created yet, or may have been disposed.
if (tabFolder != null && !tabFolder.isDisposed()) {
if (tabIndex > -1 && tabIndex < tabFolder.getItemCount()) {
return tabFolder.getItem(tabIndex);
}
}
return null;
}
/**
* Returns the number of tabs in this editor.
*
* @return the number of tabs
*/
protected int getTabCount() {
// May not have been created yet, or may have been disposed.
if (tabFolder != null && !tabFolder.isDisposed()) return tabFolder.getItemCount();
return 0;
}
/**
* Sets the image for the tab with the given index, or <code>null</code> to clear the image for the tab. The page index must
* be valid.
*
* @param tabIndex the index of the page
* @param image the image, or <code>null</code>
*/
protected void setTabImage( int tabIndex,
Image image ) {
getItem(tabIndex).setImage(image);
}
/**
* Sets the text label for the tab with the given index. The tab index must be valid. The text label must not be null.
*
* @param tabIndex the index of the page
* @param text the text label
*/
protected void setTabText( int tabIndex,
String text ) {
getItem(tabIndex).setText(text);
}
/**
* Sets the tooltip text for the tab with the given index. The tab index must be valid. The text must not be null.
*
* @param tabIndex the index of the page
* @param text the tool tip text
*/
protected void setTabToolTipText( int tabIndex,
String text ) {
getItem(tabIndex).setToolTipText(text);
}
/**
* Sets the currently active tab.
*
* @param tabIndex the index of the page to be activated; the index must be valid
*/
protected void setActiveTab( int tabIndex ) {
if (tabIndex >= 0 && tabIndex < getTabCount()) {
tabFolder.setSelection(tabIndex);
}
}
/**
* Sets focus on the active nested control if there is one.
* <p>
* Subclasses may extend or reimplement.
* </p>
*/
@Override
public void setFocus() {
int index = getActiveTab();
if (index != -1) {
setFocus(index);
if (meParentEditor != null) {
meParentEditor.setIgnoreInternalFocus(true);
}
}
}
/**
* Sets focus to the control for the given tab. This calls <code>setFocus</code> on the control for the tab.
*
* @tabIndex the index of the tab
*/
private void setFocus( int tabIndex ) {
if (tabIndex < 0 || tabIndex >= getTabCount()) return;
Control control = getControl(tabIndex);
if (control != null) {
control.setFocus();
// selectionMgr.setSelection(getS)
}
}
/**
* <p>
* Returns the index of the currently active tab, or -1 if there is no active tab.
* </p>
* <p>
* Subclasses should not override this method.
* </p>
*
* @return the index of the active tab, or -1 if there is no active tab
*/
protected int getActiveTab() {
if (tabFolder != null && !tabFolder.isDisposed()) {
return tabFolder.getSelectionIndex();
}
return -1;
}
/**
* Gets a <code>Map</code> of {@link TableViewer}s. There will be one for each tab within this editor page. The map is keyed
* by the tab name.
*
* @return the map
*/
public Map getTableViewerMap() {
return viewers;
}
protected void pageChange( int newPageIndex ) {
// each page's table columns are created only after their associated tab in the tabfolder
// has been selected. make sure the colums have been built.
UiBusyIndicator.showWhile(null, new Runnable() {
@Override
public void run() {
if (getCurrentModel() != null) {
getCurrentModel().buildColumns();
}
}
});
}
protected boolean isReadOnly() {
IFileEditorInput input = (IFileEditorInput)getEditorInput();
return ModelUtil.isIResourceReadOnly(input.getFile());
}
private TableNotificationHandler getNotificationHandler() {
if (notificationHandler == null) {
notificationHandler = new TableNotificationHandler(this);
}
return notificationHandler;
}
protected Resource getEmfResource() {
return emfResource;
}
/**
* Allows the TableNotifierHandler to add a Table to this editor if new object types show up
*
* @param eClass
* @param instanceList
*/
void addTable( EClass eClass,
ArrayList instanceList ) {
// figure out what the tab index should be for the new EClass type
String className = eClass.getName();
TreeSet orderedNames = new TreeSet();
orderedNames.addAll(viewers.keySet());
orderedNames.add(className);
int index = 0;
for (Iterator iter = orderedNames.iterator(); iter.hasNext(); index++) {
if (className.equals(iter.next())) {
break;
}
}
// create the tab at the appropriate index
index = addTab(eClass, instanceList, index);
// register the Table with the action contributor
this.actionContributor.addContextMenu(getControl(index), className);
}
/**
* @see org.teiid.designer.ui.editors.INavigationSupported
**/
@Override
public IMarker createMarker() {
// jhTODO: implement
// System.out.println("[ModelTableEditor.createMarker] TOP"); //$NON-NLS-1$
NavigationMarker nmMarker = new NavigationMarker();
return nmMarker;
}
/**
* @see org.eclipse.ui.IEditorPart#gotoMarker(org.eclipse.core.resources.IMarker)
*/
@Override
public void gotoMarker( IMarker marker ) {
EObject targetEObject = ModelObjectUtilities.getMarkedEObject(marker);
if (targetEObject != null) {
selectionMgr.setSelection(new StructuredSelection(targetEObject));
}
}
/**
* Receives the input information passed from the platform when this ModelEditorPart was created. Forwards to the baseclass.
*
* @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
*/
@Override
public void init( IEditorSite site,
IEditorInput input ) throws PartInitException {
setSite(site);
setInput(input);
try {
IFileEditorInput fileInput = (IFileEditorInput)input;
modelResource = ModelUtil.getModelResource(fileInput.getFile(), true);
if (modelResource != null) {
emfResource = modelResource.getEmfResource();
}
} catch (CoreException e) {
throw new PartInitException(Util.getString(PREFIX + "resourceError", input.getName()), e); //$NON-NLS-1$
}
}
/**
* @see org.eclipse.ui.ISaveablePart#isDirty()
*/
@Override
public boolean isDirty() {
// modTODO: implement
return false;
}
/**
* @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void doSave( IProgressMonitor monitor ) {
}
/**
* @see org.eclipse.ui.ISaveablePart#doSaveAs()
*/
@Override
public void doSaveAs() {
}
/**
* @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
*/
@Override
public boolean isSaveAsAllowed() {
return false;
}
/**
* @see org.eclipse.ui.IWorkbenchPart#getTitleImage()
*/
@Override
public Image getTitleImage() {
return UiPlugin.getDefault().getImage(PluginConstants.Images.TABLE_ICON);
}
/**
* @see org.eclipse.ui.IWorkbenchPart#dispose()
* @since 4.0
*/
@Override
public void dispose() {
this.labelProvider.dispose();
// Memory leak Defect 22290 - requires that we actually tell the actionContributor to dispose() so it can clean up all
// the references & listeners to menu managers, etc....
this.actionContributor.dispose();
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#preDispose()
* @since 4.2
*/
@Override
public void preDispose() {
// Default Implementation
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#canDisplay(org.eclipse.ui.IEditorInput)
*/
@Override
public boolean canDisplay( IEditorInput input ) {
return true;
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#canOpenContext(java.lang.Object)
*/
@Override
public boolean canOpenContext( Object input ) {
if (input instanceof EObject) {
return true;
}
return false;
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#openContext(java.lang.Object)
*/
@Override
public void openContext( Object input ) {
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#openContext(java.lang.Object)
*/
@Override
public void openContext( Object input,
boolean forceRefresh ) {
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#initializeEditorPage()
* @since 5.0.2
*/
@Override
public void initializeEditorPage() {
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#getControl()
*/
@Override
public Control getControl() {
return getControl(getActiveTab());
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#getModelObjectSelectionProvider()
*/
@Override
public ISelectionProvider getModelObjectSelectionProvider() {
return this.selectionMgr;
}
/**
* Return a selectionChangedListener that can receive ISelections from the workbench and send them into the table
*
* @see org.teiid.designer.ui.editors.ModelEditorPage#getModelObjectSelectionChangedListener()
*/
@Override
public ISelectionChangedListener getModelObjectSelectionChangedListener() {
return this.selectionMgr;
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#getActionBarContributor()
*/
@Override
public AbstractModelEditorPageActionBarContributor getActionBarContributor() {
if (actionContributor == null) {
actionContributor = new ModelTableEditorActionContributor(this);
}
return actionContributor;
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#setLabelProvider(org.eclipse.jface.viewers.ILabelProvider)
*/
@Override
public void setLabelProvider( ILabelProvider provider ) {
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#getNotifyChangedListener()
*/
@Override
public INotifyChangedListener getNotifyChangedListener() {
return getNotificationHandler();
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#getOutlineContribution()
*/
@Override
public ModelEditorPageOutline getOutlineContribution() {
return null;
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#setParent()
*/
@Override
public void setParent( ModelEditor meParentEditor ) {
this.meParentEditor = meParentEditor;
}
/** CellModifier to set property values onto the objects in the table */
class TableCellModifier implements ICellModifier {
Object lastGetValue = null;
@Override
public boolean canModify( Object element,
String property ) {
if (isReadOnly()) {
return false;
} else if (property.equals(UiConstants.LOCATION_KEY)) {
return false;
}
return true;
}
@Override
public Object getValue( Object element,
String property ) {
ModelRowElement row = (ModelRowElement)element;
lastGetValue = row.getValueObject(property);
return lastGetValue;
}
@Override
public void modify( Object element,
String property,
Object theValue ) {
boolean modifyValue = false;
Object value = theValue;
// check for EMPTY name property
if (property.equalsIgnoreCase("name")) { //$NON-NLS-1$
if (theValue != null && theValue instanceof String && ((String)theValue).length() == 0) {
value = lastGetValue;
}
}
if (lastGetValue == null && value != null) {
modifyValue = true;
} else if (value == null && lastGetValue != null) {
modifyValue = true;
} else if (value != null && lastGetValue != null) {
if (!lastGetValue.equals(value)) {
modifyValue = true;
}
}
if (modifyValue) {
boolean startedTxn = ModelerCore.startTxn(UNDO_PREFIX + ModelObjectTableModel.getPropertyLabel(property), this);
boolean succeeded = false;
try {
ModelRowElement row = (ModelRowElement)((TableItem)element).getData();
row.setValue(property, value);
succeeded = true;
} finally {
if (startedTxn) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
}
}
/** Comparator to order the tabs in this editor */
class EClassNameComparator implements Comparator {
@Override
public int compare( Object o1,
Object o2 ) {
// Order alphabetically by name (ascending)
EClass c1 = (EClass)o1;
EClass c2 = (EClass)o2;
return c1.getName().compareTo(c2.getName());
}
}
/**
* @since 4.0
*/
class ModelObjectSelectionManager extends SelectionProvider implements ISelectionChangedListener {
/**
* @since 4.0
*/
@Override
public void selectionChanged( final SelectionChangedEvent event ) {
getModelObjectSelectionProvider().setSelection(event.getSelection());
if (SelectionUtilities.isSingleSelection(event.getSelection())) {
Object obj = ((IStructuredSelection)event.getSelection()).getFirstElement();
if (obj instanceof EObject) {
Object activeEditor = meParentEditor.getActiveEditor();
if (activeEditor != null && activeEditor == ModelTableEditor.this) {
// ----------------------------
// Defect 22844 - setting ignoreInternalFocus
// This cleans up simple selection causing focus to OperationEditorPage way too often
// ----------------------------
meParentEditor.setIgnoreInternalFocus(true);
}
}
}
}
/**
* @see org.teiid.designer.ui.common.eventsupport.SelectionProvider#getListenerList()
* @since 4.2
*/
@Override
public List getListenerList() {
return super.getListenerList();
}
protected void removeTableSelectionListeners() {
List listeners = getListenerList();
List removeList = new ArrayList(listeners.size());
Object nextListener = null;
Iterator iter = listeners.iterator();
while (iter.hasNext()) {
nextListener = iter.next();
if (nextListener instanceof ModelObjectTableSelectionManager) {
removeList.add(nextListener);
}
}
iter = removeList.iterator();
while (iter.hasNext()) {
nextListener = iter.next();
super.removeSelectionChangedListener((ModelObjectTableSelectionManager)nextListener);
}
}
}
public boolean canInsertRows() {
boolean bResult = false;
TableViewer viewer = getCurrentViewer();
if (viewer != null) {
IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
if (selection != null && !selection.isEmpty() && SelectionUtilities.isSingleSelection(selection)) {
ModelRowElement mre = (ModelRowElement)selection.getFirstElement();
EObject eObj = mre.getModelObject();
bResult = (!ModelObjectUtilities.isReadOnly(eObj));
}
}
return bResult;
}
public void insertRows( int iRowCount ) {
TableViewer viewer = getCurrentViewer();
if (viewer != null) {
IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
if (!selection.isEmpty()) {
ModelRowElement mre = (ModelRowElement)selection.getFirstElement();
EObject eObj = mre.getModelObject();
boolean started = ModelerCore.startTxn(true, UNDO_INSERT_ROWS, this);
boolean succeeded = false;
try {
EClass eClass = eObj.eClass();
Collection commands = ModelerCore.getModelEditor().getNewSiblingCommands(eObj);
if ((commands != null) && !commands.isEmpty()) {
// find the right command to use. it will be the one with the same result object eClass
Iterator itr = commands.iterator();
Command cmd = null;
while (itr.hasNext()) {
Command tempCmd = (Command)itr.next();
Collection result = tempCmd.getResult();
if ((result != null) && !result.isEmpty()) {
EObject sibling = (EObject)result.iterator().next();
if (sibling.eClass().equals(eClass)) {
cmd = tempCmd;
break;
}
}
}
if (cmd == null) {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "msg.noSiblingCommandFound", //$NON-NLS-1$
new Object[] {eClass}));
} else if (cmd.canExecute()) {
String originalName = ModelerCore.getModelEditor().getName(eObj);
if (iRowCount > 1) {
Collection clonedChildren = ModelerCore.getModelEditor().cloneMultiple(eObj, iRowCount);
if (clonedChildren != null) {
EObject[] newChildArray = new EObject[clonedChildren.size()];
clonedChildren.toArray(newChildArray);
for (int i = newChildArray.length - 1; i >= 0; i--) {
// Get a unique name given the name of the original
renameToUniqueName(newChildArray[i], originalName);
}
}
} else {
EObject newChild = ModelerCore.getModelEditor().clone(eObj);
renameToUniqueName(newChild, originalName);
}
succeeded = true;
} else {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "msg.newSiblingCommandProblem", //$NON-NLS-1$
new Object[] {eClass}));
}
}
} catch (ModelerCoreException theException) {
Util.log(IStatus.ERROR, theException, Util.getString(PREFIX + "NewSiblingMenu.problem", //$NON-NLS-1$
new Object[] {eObj}));
} finally {
if (started) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
viewer.refresh();
}
}
/**
* Checks to see if the clipboard has text contents and if the table has a selection. If a table selection exists, the
* selected column must not be readonly.
*
* @return <code>true</code> if clipboard is not empty, the current viewer has a selection, and the selected column is not
* readonly; <code>false</code> otherwise.
*/
public boolean canPaste() {
boolean result = false;
if (!SystemClipboardUtilities.isEmpty()) {
TableViewer viewer = getCurrentViewer();
if (viewer != null) {
IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
if (!selection.isEmpty() && SelectionUtilities.isSingleSelection(selection)) {
TableColumnSelectionHelper helper = getCurrentSelectionHelper();
int selectedColumn = helper.getSelectedColumn();
if (selectedColumn != -1 && selectedColumn < viewer.getCellEditors().length) {
// if there is a CellEditor for this column, then the property is editable
result = viewer.getCellEditors()[selectedColumn] != null;
}
}
}
}
return result;
}
/**
* @see org.teiid.designer.ui.table.ITablePasteValidator#constructPasteStatusRecord(java.lang.String, int, int)
*/
@Override
public ClipboardPasteStatusRecord constructPasteStatusRecord( String theProposedValue,
int theRow,
int theColumn ) {
/* ----- DESIGN NOTE -----
* theRow and theColumn must be reference to the table not the paste data
*/
ClipboardPasteStatusRecord result = null;
Integer statusType = ClipboardPasteStatusRecord.VALID;
String columnName = null;
String errorMsg = null; // valid if null
if (!willPasteDataRowFit(theRow)) {
statusType = ClipboardPasteStatusRecord.ROW_TRUNCATED;
errorMsg = getErrorMsg(theProposedValue, theRow, theColumn);
} else if (!willPasteDataColumnFit(theColumn)) {
statusType = ClipboardPasteStatusRecord.COLUMN_TRUNCATED;
errorMsg = getErrorMsg(theProposedValue, theRow, theColumn);
columnName = ClipboardPasteProblemDialog.TRUNCATED_COLUMN_TITLE;
} else if (isProtected(theColumn)) {
statusType = ClipboardPasteStatusRecord.PROTECTED_COLUMN;
errorMsg = getErrorMsg(theProposedValue, theRow, theColumn);
} else {
errorMsg = getErrorMsg(theProposedValue, theRow, theColumn);
if (errorMsg != null) {
if (errorMsg.equals(ClipboardPasteStatusRecord.REFERENCE_COLUMN_MSG)) {
statusType = ClipboardPasteStatusRecord.PROTECTED_COLUMN;
} else {
statusType = ClipboardPasteStatusRecord.ERROR;
}
}
}
// if columnName is null and the column fits, get the column name
// otherwise the column will be truncated
// if the row is being truncated, the check to see if the column will fit has not been done
if (columnName == null) {
columnName = (willPasteDataColumnFit(theColumn)) ? getCurrentTable().getColumn(theColumn).getText() : ClipboardPasteProblemDialog.TRUNCATED_COLUMN_TITLE;
}
if (errorMsg == null) {
// valid value
result = new ClipboardPasteStatusRecord(columnName, theProposedValue);
} else {
result = new ClipboardPasteStatusRecord(statusType, columnName, theProposedValue, errorMsg);
}
return result;
}
private List constructClipboardPasteStatusRecords( List thePasteData,
int theSelectedRow,
int theSelectedColumn ) {
List result = new ArrayList(thePasteData.size());
for (int numRows = thePasteData.size(), i = 0; i < numRows; i++) {
List row = (List)thePasteData.get(i);
List resultRow = new ArrayList(row.size());
for (int numColumns = row.size(), j = 0; j < numColumns; j++) {
String data = (String)row.get(j);
resultRow.add(constructPasteStatusRecord(data, i + theSelectedRow, j + theSelectedColumn));
}
result.add(resultRow);
}
return result;
}
ModelObjectTableModel getCurrentModel() {
TableViewer viewer = getCurrentViewer();
return (viewer == null) ? null : (ModelObjectTableModel)modelMap.get(viewer);
}
private TableColumnSelectionHelper getCurrentSelectionHelper() {
TableViewer viewer = getCurrentViewer();
return (viewer == null) ? null : (TableColumnSelectionHelper)selectionHelperMap.get(viewer);
}
private Table getCurrentTable() {
TableViewer viewer = getCurrentViewer();
return (viewer == null) ? null : viewer.getTable();
}
public TableViewer getCurrentViewer() {
if (tabFolder != null && !tabFolder.isDisposed()) {
TabItem[] item = tabFolder.getSelection();
if (item == null || item.length == 0 || item[0] == null) {
return null;
}
return (item[0] == null) ? null : (TableViewer)viewers.get(item[0].getText());
}
return null;
}
/**
* @param theProposedValue
* @param theRow the table row where the proposed data will be pasted
* @param theColumn the table column where the proposed data will be pasted
* @return
*/
private String getErrorMsg( String theProposedValue,
int theRow,
int theColumn ) {
String result = null; // valid
if (!willPasteDataRowFit(theRow)) {
result = ClipboardPasteStatusRecord.ROW_TRUNCATED_MSG;
} else if (!willPasteDataColumnFit(theColumn)) {
result = ClipboardPasteStatusRecord.COLUMN_TRUNCATED_MSG;
} else if (isProtected(theColumn)) {
result = ClipboardPasteStatusRecord.PROTECTED_COLUMN_MSG;
} else {
// see if value validates
CellEditor editor = getCurrentViewer().getCellEditors()[theColumn];
if (editor != null) {
ICellEditorValidator validator = editor.getValidator();
if (validator != null) {
// if non-null, result is the error msg
result = validator.isValid(theProposedValue);
} else {
if (editor instanceof ComboBoxCellEditor) {
int iMatch = -1;
ComboBoxCellEditor cbceEditor = (ComboBoxCellEditor)editor;
String sNewVal = theProposedValue.trim();
String[] sItems = cbceEditor.getItems();
for (int i = 0; i < sItems.length; i++) {
if (sNewVal.equals(sItems[i])) {
iMatch = i;
}
}
if (iMatch == -1) {
ModelRowElement row = (ModelRowElement)getCurrentViewer().getElementAt(theRow);
String propertyID = (String)row.getPropertyIdForColumn(theColumn);
result = UiConstants.Util.getString("ModelRowElement.invalidValueError", sNewVal, propertyID); //$NON-NLS-1$
}
}
}
}
// jh Defect 19246: test for 'reference'
if (result == null) {
ModelRowElement row = (ModelRowElement)getCurrentViewer().getElementAt(theRow);
Object propID = row.getPropertyIdForColumn(theColumn);
if (propID instanceof String) {
result = row.getReferenceColumnMessage((String)propID, theProposedValue);
}
}
if (result == null) {
ModelRowElement row = (ModelRowElement)getCurrentViewer().getElementAt(theRow);
Object propID = row.getPropertyIdForColumn(theColumn);
if (propID instanceof String) {
result = row.getInvalidValueMessage((String)propID, theProposedValue);
} else if (propID instanceof ExtensionPropertyDescriptor) {
result = row.getInvalidValueMessage((ExtensionPropertyDescriptor)propID, theProposedValue);
}
}
}
return result;
}
/**
* @see org.teiid.designer.ui.table.ITablePasteValidator#getSelectedRowAndColumn()
*/
@Override
public int[] getSelectedRowAndColumn() {
TableViewer viewer = getCurrentViewer();
TableColumnSelectionHelper helper = (TableColumnSelectionHelper)selectionHelperMap.get(viewer);
return helper.getSelectedRowAndColumn();
}
/**
* Determines if the input is valid. The input can either be straight from the clipboard utilities parse content method or
* from this class's construct status records method.
*
* @param thePasteData the data can either be lists of lists containing strings or lists of lists containing
* ClipboardPasteStatusRecords
* @return
*/
private boolean isPasteDataValid( List thePasteData ) {
boolean result = true;
boolean rawData = true;
if ((thePasteData != null) && !thePasteData.isEmpty()) {
int[] rowCol = getSelectedRowAndColumn();
int selectedRow = rowCol[0];
int selectedColumn = rowCol[1];
for (int numRows = thePasteData.size(), i = 0; i < numRows; i++) {
List row = (List)thePasteData.get(i);
for (int numColumns = row.size(), j = 0; j < numColumns; j++) {
// determine if looking at row data or status records
if (j == 0) {
Object tempColumn = row.get(j);
if (tempColumn instanceof ClipboardPasteStatusRecord) {
rawData = false;
}
}
String columnData = null;
if (rawData) {
columnData = (String)row.get(j);
} else {
columnData = ((ClipboardPasteStatusRecord)row.get(j)).getPasteData();
}
if (getErrorMsg(columnData, i + selectedRow, j + selectedColumn) != null) {
// if rawData (right from clipboard) any error msg should be flagged as an error
// if status record then check if error
result = (rawData) ? false : !((ClipboardPasteStatusRecord)row.get(j)).isError();
if (!result) {
break;
}
}
}
}
}
return result;
}
private boolean isProtected( int theColumn ) {
boolean isProtected = false;
ModelObjectTableModel tableModel = getCurrentModel();
Object propID = tableModel.getPropertyIdAtIndex(theColumn);
if (propID instanceof String) {
if (isReadOnly()) {
isProtected = true;
} else if (propID.equals(UiConstants.LOCATION_KEY)) {
return true;
}
} else {
isProtected = isReadOnly();
}
return isProtected;
}
public void pasteClipboardContents() {
if (canPaste()) {
Table table = getCurrentTable();
ModelObjectTableModel model = getCurrentModel();
int[] rowCol = getSelectedRowAndColumn();
int selectedRow = rowCol[0];
int selectedColumn = rowCol[1];
String clipboardContents = SystemClipboardUtilities.getContents();
List pasteData = SystemClipboardUtilities.convertTableData(clipboardContents);
// make sure data is valid
if (willPasteDataFit(pasteData) && isPasteDataValid(pasteData)) {
int numRows = table.getItemCount();
int numCols = table.getColumnCount();
int numPasteDataRows = pasteData.size();
int numPasteDataColumns = ((List)pasteData.get(0)).size();
getCurrentViewer().cancelEditing();
boolean requiredStart = ModelerCore.startTxn(true,
true,
Util.getString(PREFIX + "tablePasteTransactionDescription.msg"), this); //$NON-NLS-1$
boolean succeeded = false;
try {
for (int i = 0; i < numPasteDataRows; i++) {
int modelRow = selectedRow + i;
// throw out row data that doesn't fit
if (modelRow == numRows) {
continue;
}
List pasteRow = (List)pasteData.get(i);
// Capture the ModelRowElement for this row
TableItem ti = getCurrentViewer().getTable().getItem(modelRow);
ModelRowElement mreRow = (ModelRowElement)ti.getData();
for (int j = 0; j < numPasteDataColumns; j++) {
int modelColumn = selectedColumn + j;
// throw out column data that doesn't fit
if (modelColumn == numCols) {
continue;
}
// to update the right row, we must call setValue on the ModelRowElement
// (This gets over any shuffling of rows the user may have done by column sorting.)
Object propID = model.getPropertyIdAtIndex(modelColumn);
if (propID instanceof String) {
mreRow.setValue((String)propID, pasteRow.get(j));
} else if (propID instanceof ExtensionPropertyDescriptor) {
mreRow.setValue((ExtensionPropertyDescriptor)propID, pasteRow.get(j));
}
}
}
succeeded = true;
} finally {
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
} else {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "tablePasteStartTransactionProblem.msg")); //$NON-NLS-1$
}
}
} else { // show dialog
List statusRecords = constructClipboardPasteStatusRecords(pasteData, selectedRow, selectedColumn);
Shell shell = UiUtil.getWorkbenchWindowOnlyIfUiThread().getShell();
ClipboardPasteProblemDialog dialog = new ClipboardPasteProblemDialog(shell, statusRecords, this);
int returnStatus = dialog.open();
if (returnStatus == Window.OK) {
statusRecords = dialog.getStatusRecords();
if ((statusRecords != null) && !statusRecords.isEmpty() && isPasteDataValid(statusRecords)) {
getCurrentViewer().cancelEditing();
boolean requiredStart = ModelerCore.startTxn(true,
true,
Util.getString(PREFIX
+ "tablePasteTransactionDescription.msg"), this); //$NON-NLS-1$
boolean succeeded = false;
try {
for (int numRows = statusRecords.size(), i = 0; i < numRows; i++) {
List pasteRow = (List)statusRecords.get(i);
int modelRow = selectedRow + i;
for (int numColumns = pasteRow.size(), j = 0; j < numColumns; j++) {
int modelColumn = selectedColumn + j;
ClipboardPasteStatusRecord statusRecord = (ClipboardPasteStatusRecord)pasteRow.get(j);
if (!statusRecord.isColumnTruncated() && !statusRecord.isRowTruncated()
&& !statusRecord.isProtectedColumn()) {
model.setValueAt(statusRecord.getPasteData(), modelRow, modelColumn);
}
}
}
succeeded = true;
} finally {
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
} else {
Util.log(IStatus.ERROR, Util.getString(PREFIX + "tablePasteStartTransactionProblem.msg")); //$NON-NLS-1$
}
}
}
}
}
}
}
private boolean willPasteDataColumnFit( int theColumn ) {
boolean result = false;
if (theColumn >= 0) {
Table table = getCurrentTable();
result = (theColumn < table.getColumnCount());
}
return result;
}
private boolean willPasteDataFit( List thePasteData ) {
boolean result = false;
if ((thePasteData != null) && !thePasteData.isEmpty()) {
TableViewer viewer = getCurrentViewer();
int[] rowCol = getSelectedRowAndColumn();
int selectedRow = rowCol[0];
int selectedColumn = rowCol[1];
// make sure something is selected
if ((selectedColumn != -1) && (selectedRow != -1)) {
Table table = viewer.getTable();
int tableColumnCount = table.getColumnCount();
int pasteDataRows = thePasteData.size();
int pasteDataColumns = ((List)thePasteData.get(0)).size();
if (((selectedColumn + pasteDataColumns - 1) <= tableColumnCount)
&& ((selectedRow + pasteDataRows - 1) < table.getItemCount())) {
result = true;
}
}
}
return result;
}
private boolean willPasteDataRowFit( int theRow ) {
boolean result = false;
if (theRow >= 0) {
Table table = getCurrentTable();
result = (theRow < table.getItemCount());
}
return result;
}
// jh Defect 19246: Added ability to copy selected rows to System Clipboard
public void copySelectedToSystemClipboard() {
Table table = getCurrentTable();
int[] iSelectedRows = table.getSelectionIndices();
int numCols = table.getColumnCount();
String sVal = ""; //$NON-NLS-1$
String sFullString = ""; //$NON-NLS-1$
for (int iRow = 0; iRow < iSelectedRows.length; iRow++) {
String sRowString = ""; //$NON-NLS-1$
int iThisRow = iSelectedRows[iRow];
// Capture the ModelRowElement for this row
TableItem ti = getCurrentViewer().getTable().getItem(iThisRow);
ModelRowElement mreRow = (ModelRowElement)ti.getData();
for (int iCol = 0; iCol < numCols; iCol++) {
// after the first col, prepend delimiter before adding column value string
if (iCol > 0) {
sRowString += SystemClipboardUtilities.COLUMN_DELIMITER;
}
sVal = (String)mreRow.getValue(iCol);
sRowString += sVal;
}
sFullString += sRowString + SystemClipboardUtilities.ROW_DELIMITER;
}
// apply the result to the system clipboard
SystemClipboardUtilities.setContents(sFullString);
}
/**
* @see org.eclipse.ui.IWorkbenchPart#getTitleToolTip()
*/
@Override
public String getTitleToolTip() {
return TOOLTIP;
}
/**
* @see org.eclipse.ui.IWorkbenchPart#getTitle()
*/
@Override
public String getTitle() {
if (title == null) {
return super.getTitle();
}
return title;
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#setTitleText(java.lang.String)
* @since 4.2
*/
@Override
public void setTitleText( String newTitle ) {
this.title = newTitle;
}
@Override
public Object getAdapter( Class type ) {
if (type == IPrintable.class) {
if (getTitleToolTip() != null) {
// return a Printable created from the table in the currently selected tab
return new Printable(getControl(tabFolder.getSelectionIndex()));
}
}
return super.getAdapter(type);
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#updateReadOnlyState(boolean)
*/
@Override
public void updateReadOnlyState( boolean isReadOnly ) {
// defect 16345 - table editor not working on checkout
if (lastReadOnly != isReadOnly) {
lastReadOnly = isReadOnly;
Iterator itor = modelMap.keySet().iterator();
// loop through all views:
while (itor.hasNext()) {
Object key = itor.next();
Object val = modelMap.get(key);
// refresh the editors for each table:
if (key instanceof TableViewer && val instanceof ModelObjectTableModel) {
TableViewer tv = (TableViewer)key;
ModelObjectTableModel model = (ModelObjectTableModel)val;
model.rebuildColumnEditors(tv.getTable());
} // endif -- correct object types
} // endwhile -- views
} // endif -- readonly state change
}
/**
* @see org.teiid.core.designer.event.EventObjectListener#processEvent(java.util.EventObject)
* @since 4.2
*/
@Override
public void processEvent( EventObject obj ) {
ModelResourceEvent event = (ModelResourceEvent)obj;
if (event.getType() == ModelResourceEvent.RELOADED) {
refresh();
}
}
private void refresh() {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (getControl() != null && !getControl().isDisposed()) {
// Remove Tab items.
TabItem[] tabs = tabFolder.getItems();
for (int i = tabs.length - 1; i >= 0; i--) {
tabs[i].dispose();
}
// Clear HashMap's and specific tables listeners.
modelMap.clear();
viewers.clear();
selectionHelperMap.clear();
selectionMgr.removeTableSelectionListeners();
// Recreate the tabs from the model
createTabs();
int tabID = getActiveTab();
if (tabID == 1 || tabID == 0) {
setActiveTab(0);
// programmatically setting selection to tab 0 while constructing doesn't get
// handled by our handler created in createContainer(Composite) since it hasn't been
// called yet. So call pageChange method so that tab 0 can construct it's columns
pageChange(0);
}
}
}
});
}
/**
* @see org.teiid.designer.ui.editors.ModelEditorPage#openComplete()
* @since 4.2
*/
@Override
public void openComplete() {
// Default Implementation
}
/**
* @see org.teiid.designer.ui.editors.IInlineRenameable#canRenameInline(org.eclipse.emf.ecore.EObject)
* @since 5.0
*/
@Override
public IInlineRenameable getInlineRenameable( EObject theObj ) {
return this;
}
/**
* @see org.teiid.designer.ui.editors.IInlineRenameable#renameInline(org.eclipse.emf.ecore.EObject)
* @since 5.0
*/
@Override
public void renameInline( final EObject targetEObject,
IInlineRenameable renameable ) {
if (renameable == this && targetEObject != null) {
// Set Selection
// Let's asynch this off
Display.getCurrent().asyncExec(new Runnable() {
@Override
public void run() {
selectionMgr.setSelection(new StructuredSelection(targetEObject));
DoubleClickTableViewer dctv = (DoubleClickTableViewer)getCurrentViewer();
// We need to get the column for the Name property (if it exists)
TableColumn[] columns = dctv.getTable().getColumns();
for (int i = 0; i < columns.length; i++) {
if (columns[i].getText().equalsIgnoreCase("name")) { //$NON-NLS-1$
// We found the column
dctv.renameInline(i);
break;
}
}
}
});
}
}
/**
* @see org.teiid.designer.core.ModelEditor#rename(org.eclipse.emf.ecore.resource.Resource, org.eclipse.emf.ecore.EObject,
* java.lang.String)
*/
protected boolean renameToUniqueName( final EObject eObject,
final String newName ) {
CoreArgCheck.isNotNull(eObject);
final EStructuralFeature nameFeature = ModelerCore.getModelEditor().getNameFeature(eObject);
if (nameFeature != null) {
generateUniqueInternalName(eObject.eContainer() == null ? eObject.eResource().getContents() : eObject.eContainer().eContents(),
eObject,
nameFeature,
newName);
return true;
}
return false;
}
private void generateUniqueInternalName( final EList siblings,
final EObject eObject,
final EStructuralFeature nameFeature,
final String name ) {
String newName = name;
if (siblings != null) {
final Set siblingNames = new HashSet();
for (Iterator it = siblings.iterator(); it.hasNext();) {
final EObject child = (EObject)it.next();
if (eObject.getClass().equals(child.getClass())) {
siblingNames.add(child.eGet(nameFeature));
}
}
boolean foundUniqueName = false;
int index = 1;
while (!foundUniqueName) {
if (siblingNames.contains(newName)) {
newName = name + String.valueOf(index++);
} else {
foundUniqueName = true;
}
}
}
eObject.eSet(nameFeature, newName);
}
/**
* @return False.
* @see org.teiid.designer.ui.editors.ModelEditorPage#isSelectedFirst(org.eclipse.ui.IEditorInput)
* @since 5.0.1
*/
@Override
public boolean isSelectedFirst( IEditorInput input ) {
return false;
}
}