/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.attribute;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.jboss.tools.common.model.ui.attribute.adapter.AdapterFactory;
import org.jboss.tools.common.model.ui.attribute.adapter.DefaultValueAdapter;
import org.jboss.tools.common.model.ui.attribute.adapter.IModelPropertyEditorAdapter;
import org.jboss.tools.common.model.ui.attribute.editor.ExtendedFieldEditor;
import org.jboss.tools.common.model.ui.attribute.editor.IFieldEditor;
import org.jboss.tools.common.model.ui.attribute.editor.IPropertyEditor;
import org.jboss.tools.common.model.ui.attribute.editor.NoteEditor;
import org.jboss.tools.common.model.ui.attribute.editor.NoteFieldEditor;
import org.jboss.tools.common.model.ui.attribute.editor.PropertyEditor;
import org.jboss.tools.common.model.ui.attribute.editor.PropertyEditorFactory;
import org.jboss.tools.common.model.ui.attribute.editor.StringButtonFieldEditorEx;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.ui.actions.ActionFactory;
import org.jboss.tools.common.meta.XAttribute;
import org.jboss.tools.common.meta.XModelEntity;
import org.jboss.tools.common.meta.action.XAttributeData;
import org.jboss.tools.common.meta.action.XEntityData;
import org.jboss.tools.common.meta.key.WizardKeys;
import org.jboss.tools.common.model.XModelFactory;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
import org.jboss.tools.common.model.ui.widgets.DefaultSettings;
import org.jboss.tools.common.model.ui.widgets.IWidgetSettings;
import org.jboss.tools.common.model.util.ModelFeatureFactory;
/**
* @author eskimo
*/
public class XAttributeSupport {
public static interface IAttributeDependency extends java.beans.PropertyChangeListener {
public void setSupport(XAttributeSupport support);
}
boolean isDebugging = ModelUIPlugin.getDefault().isDebugging();
private ArrayList<IModelPropertyEditorAdapter> adapters = new ArrayList<IModelPropertyEditorAdapter>();
private ArrayList<PropertyEditor> editors = new ArrayList<PropertyEditor>();
private Map<String,FieldEditor> fieldEditors = new HashMap<String,FieldEditor>();
protected Set<String> alwaysGreedy = new HashSet<String>();
private XModelObject xmo;
private XEntityData data;
private Layout layout;
private IWidgetSettings settings = DefaultSettings.getDefault();
public XAttributeSupport() {
}
public XAttributeSupport(IWidgetSettings settings) {
this.settings = settings;
}
public XAttributeSupport(XModelObject xmo) {
if(xmo==null) throw new IllegalArgumentException("XModelObject cannot be null."); //$NON-NLS-1$
init(xmo);
}
public XAttributeSupport(XModelObject xmo, XEntityData data) {
this(xmo, data, false);
}
public XAttributeSupport(XModelObject xmo, XEntityData data, boolean useObject) {
if(data==null) throw new IllegalArgumentException("XEntityData cannot be null."); //$NON-NLS-1$
init(xmo, data, useObject);
}
public XEntityData getEntityData() {
return data;
}
public void init(XModelObject xmo, XEntityData data) {
init(xmo, data, false);
}
public void init(XModelObject xmo) {
this.xmo = xmo;
XAttribute[] attribute = xmo.getModelEntity().getAttributes();
adapters.clear();
editors.clear();
for (int i = 0; i < attribute.length; i++) {
if(!attribute[i].isVisible()) continue;
IModelPropertyEditorAdapter adapter = createAdapter(xmo, attribute[i]);
PropertyEditor editor = createEditor(adapter, xmo, attribute[i]);
adapters.add(adapter);
editors.add(editor);
if("always".equals(attribute[i].getProperty("greedy"))) { //$NON-NLS-1$ //$NON-NLS-2$
alwaysGreedy.add(attribute[i].getName());
}
}
initDependencies(xmo.getModelEntity());
}
public void init(XModelObject xmo, XEntityData data, boolean useObject) {
this.data = data;
this.xmo = xmo;
XAttributeData ads[] = data.getAttributeData();
adapters.clear();
editors.clear();
for (int i = 0; i < ads.length; i++) {
//if(!ads[i].getAttribute().isVisible()) continue;
XAttribute attr = ads[i].getAttribute();
IModelPropertyEditorAdapter adapter = (useObject) ? createAdapter(xmo, attr) : createAdapter(xmo, ads[i]);
PropertyEditor editor = (useObject) ? createEditor(adapter, xmo, attr) : createEditor(adapter, xmo, ads[i]);
if(editor.getLabelText() == null) {
String labelText = WizardKeys.getAttributeDisplayName(ads[i]);
if (labelText!=null) {
labelText = labelText + ((ads[i].getMandatoryFlag()) ? "*" : ""); //$NON-NLS-1$ //$NON-NLS-2$
editor.setLabelText(labelText);
}
}
adapters.add(adapter);
editors.add(editor);
if("always".equals(attr.getProperty("greedy"))) { //$NON-NLS-1$ //$NON-NLS-2$
alwaysGreedy.add(attr.getName());
}
}
initDependencies(data.getModelEntity());
}
void initDependencies(XModelEntity entity) {
String dependencies = entity.getProperty("formDependencies");
if(dependencies == null || dependencies.length() == 0) return;
IAttributeDependency d = (IAttributeDependency)ModelFeatureFactory.getInstance().createFeatureInstance(dependencies);
if(d == null) return;
d.setSupport(this);
addPropertyChangeListener(d);
}
public void dispose() {
if (editors!=null) {
Iterator i = editors.iterator();
Object object;
while (i.hasNext()) {
object = i.next();
if (object instanceof FieldEditor) ((FieldEditor)object).dispose();
}
editors.clear();
editors = null;
}
if (adapters!=null) {
Iterator i = adapters.iterator();
Object object;
while (i.hasNext()) {
object = i.next();
if (object instanceof DefaultValueAdapter) ((DefaultValueAdapter)object).dispose();
}
adapters.clear();
adapters = null;
}
if (fieldEditors!=null) {
fieldEditors.clear();
fieldEditors = null;
}
if (alwaysGreedy!=null) {
alwaysGreedy.clear();
alwaysGreedy = null;
}
xmo = null;
settings = null;
}
private IModelPropertyEditorAdapter createAdapter(XModelObject o, XAttribute a) {
return AdapterFactory.getAdapter(a, o, o.getModel());
}
private IModelPropertyEditorAdapter createAdapter(XModelObject o, XAttributeData a) {
return AdapterFactory.getAdapter(a.getAttribute(), o, a, o.getModel());
}
private PropertyEditor createEditor(Object adapter, XModelObject o, XAttribute a) {
return PropertyEditorFactory.createPropertyEditor(adapter, a, o, settings);
}
private PropertyEditor createEditor(Object adapter, XModelObject o, XAttributeData a) {
return PropertyEditorFactory.createPropertyEditor(adapter, a.getAttribute(), a, settings);
}
public void setAutoStore(boolean set) {
for (Iterator iter = adapters.iterator(); iter.hasNext();) {
IModelPropertyEditorAdapter element = (IModelPropertyEditorAdapter) iter.next();
element.setAutoStore(set);
}
}
// private static final int COLUMN_1_WIDTH = 100;
public Control[] fillComposite(Composite composite, PropertyEditor editor, StringButtonFieldEditorEx sb) {
composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
ExtendedFieldEditor fieldEditor = null;
boolean greedy = editor.isGreedyEditor();
if(!greedy) {
fieldEditor = editor.getFieldEditor(composite);
} else {
if(sb == null) sb = new StringButtonFieldEditorEx(settings);
sb.setLabelText(editor.getLabelText());
sb.setPropertyEditor(editor);
String changeButtonName = editor.getChangeButtonName();
if(changeButtonName != null) {
sb.setChangeButtonText(changeButtonName);
}
fieldEditor = sb;
greedy = false;
}
registerFieldEditor(editor.getAttributeName(), fieldEditor);
if (!enabled) {
fieldEditor.setEnabled(enabled);
}
Control[] controls = fillComposite(composite, fieldEditor, greedy);
if(fieldEditor instanceof StringButtonFieldEditorEx) {
((StringButtonFieldEditorEx)fieldEditor).setStringValue("" + editor.getValue()); //$NON-NLS-1$
}
return controls;
}
public Control[] fillComposite(Composite composite, FieldEditor fieldEditor, boolean greedy) {
composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
if (fieldEditor instanceof IFieldEditor) {
Control control;
GridData gd;
Control[] controls = ((IFieldEditor)fieldEditor).getControls(composite);
if (controls.length==2) {
// layout 2 element
control = controls[0];
gd = new GridData();
control.setLayoutData(gd);
control = controls[1];
if(greedy) {
gd.verticalAlignment = GridData.BEGINNING;
if(editors.size() == 1) gd.horizontalSpan = 2;
gd = new GridData(GridData.FILL_BOTH);
if(editors.size() == 1) gd.horizontalSpan = 2;
} else {
gd = new GridData(GridData.FILL_HORIZONTAL);
}
if(greedy) {
int h = control.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
if(h > 300) gd.heightHint = 300;
if (fieldEditor instanceof NoteFieldEditor) {
gd.heightHint = 100;
}
}
control.setLayoutData(gd);
} else if (controls.length==1) {
// layout 1st element
control = controls[0];
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
control.setLayoutData(gd);
}
return controls;
} else {
fieldEditor.fillIntoGrid(composite, 2);
return null;
}
}
public void fillComposite(Composite composite) {
composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
int greedyCount = 0;
sortEditors();
for (int i = 0; i < editors.size(); i++) {
PropertyEditor editor = (PropertyEditor)editors.get(i);
if(editor.isGreedyEditor()) ++greedyCount;
}
for (int i = 0; i < editors.size(); i++) {
PropertyEditor editor = (PropertyEditor)editors.get(i);
//editor.setLabelText(support.getAttributeMessage(id, ads[i].getAttribute().getName()));
ExtendedFieldEditor fieldEditor = null;
boolean greedy = editor.isGreedyEditor();
if(!greedy || keepGreedy(editor.getAttributeName(), i, greedyCount) || editor instanceof NoteEditor) {
fieldEditor = editor.getFieldEditor(composite);
} else {
StringButtonFieldEditorEx sb;
sb = new StringButtonFieldEditorEx(settings);
sb.setLabelText(editor.getLabelText());
sb.setPropertyEditor(editor);
String changeButtonName = editor.getChangeButtonName();
if(changeButtonName != null) {
sb.setChangeButtonText(changeButtonName);
}
fieldEditor = sb;
greedy = false;
}
registerFieldEditor(editor.getAttributeName(), fieldEditor);
if (!enabled) {
fieldEditor.setEnabled(enabled);
}
fillComposite(composite, fieldEditor, greedy);
if(fieldEditor instanceof StringButtonFieldEditorEx) {
((StringButtonFieldEditorEx)fieldEditor).setStringValue("" + editor.getValue()); //$NON-NLS-1$
}
}
}
private void sortEditors(){
PropertyEditor editor = null;
for (int i = 0; i < editors.size(); i++) {
editor = editors.get(i);
if ("description".equalsIgnoreCase(editor.getAttributeName())) {
editors.remove(editor);
editors.add(editor);
return;
}
}
}
public Composite createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
// composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
// composite.setBackground(parent.getBackground());
composite.setLayout(getLayout());
fillComposite(composite);
// int greedyCount = 0;
// sortEditors();
// for (int i = 0; i < editors.size(); i++) {
// PropertyEditor editor = (PropertyEditor)editors.get(i);
// if(editor.isGreedyEditor()) ++greedyCount;
// }
//
// for (int i = 0; i < editors.size(); i++) {
// PropertyEditor editor = (PropertyEditor)editors.get(i);
// //editor.setLabelText(support.getAttributeMessage(id, ads[i].getAttribute().getName()));
// ExtendedFieldEditor fieldEditor = null;
// boolean greedy = editor.isGreedyEditor();
// if(!greedy || keepGreedy(editor.getAttributeName(), i, greedyCount) || editor instanceof NoteEditor) {
// fieldEditor = editor.getFieldEditor(composite);
// } else {
// StringButtonFieldEditorEx sb = null;
//
// sb = new StringButtonFieldEditorEx(settings);
//
// sb.setLabelText(editor.getLabelText());
// String changeButtonName = editor.getChangeButtonName();
// if(changeButtonName != null) {
// sb.setChangeButtonText(changeButtonName);
// }
// sb.setPropertyEditor(editor);
// fieldEditor = sb;
// greedy = false;
// }
// registerFieldEditor(editor.getAttributeName(), fieldEditor);
// if (!enabled) {
// fieldEditor.setEnabled(enabled);
// }
// fillComposite(composite, fieldEditor, greedy);
// if(fieldEditor instanceof StringButtonFieldEditorEx) {
// ((StringButtonFieldEditorEx)fieldEditor).setStringValue("" + editor.getValue()); //$NON-NLS-1$
// }
// }
return composite;
}
protected boolean keepGreedy(String name, int index, int greedyCount) {
return greedyCount < 1 || (greedyCount == 1 && editors.size() < 2)
|| alwaysGreedy.contains(name);
}
public void store() {
for (int i = 0; i < editors.size(); i++)
((IModelPropertyEditorAdapter)adapters.get(i)).store();
}
public void load() {
if(xmo == null) throw new IllegalArgumentException("" + //$NON-NLS-1$
"Init support with XModelObject before saving"); //$NON-NLS-1$
for (int i = 0; i < editors.size(); i++)
((IModelPropertyEditorAdapter)adapters.get(i)).load();
}
public void save() {
if(xmo == null) throw new IllegalArgumentException("" + //$NON-NLS-1$
"Init support with XModelObject before saving"); //$NON-NLS-1$
if(xmo.getModel()==null) throw new IllegalArgumentException("Cannot store deleted or removed XModel object"); //$NON-NLS-1$
xmo.getModel().saveOptions();
}
public List getAdapterList() {
return Collections.unmodifiableList(adapters);
}
public List<FieldEditor> getVisibleFieldEditors() {
ArrayList<FieldEditor> visibleEditors = new ArrayList<FieldEditor>();
Set keySet = fieldEditors.keySet();
Iterator i = keySet.iterator();
while (i.hasNext()) visibleEditors.add(fieldEditors.get(i.next()));
return visibleEditors;
}
public List getEditorList() {
return Collections.unmodifiableList(editors);
}
public String getTitle() {
return xmo.getPresentationString();
}
public IPropertyEditor getPropertyEditorByName(String attributeName) {
IPropertyEditor result = null;
if (attributeName != null && !"".equals(attributeName)) { //$NON-NLS-1$
Iterator iterator = editors.iterator();
while (iterator.hasNext() && result == null) {
IPropertyEditor editor = (IPropertyEditor)iterator.next();
if (attributeName.equals(editor.getAttributeName()))
result = editor;
}
}
return result;
}
public FieldEditor getFieldEditorByName(String attributeName) {
return (FieldEditor)fieldEditors.get(attributeName);
}
public void registerFieldEditor(String attributeName, FieldEditor f) {
if(f != null) fieldEditors.put(attributeName, f);
}
public IModelPropertyEditorAdapter getPropertyEditorAdapterByName(String attributeName) {
IModelPropertyEditorAdapter result = null;
if (attributeName != null && !"".equals(attributeName)) { //$NON-NLS-1$
Iterator iterator = adapters.iterator();
while (iterator.hasNext() && result == null) {
IModelPropertyEditorAdapter adapter = (IModelPropertyEditorAdapter)iterator.next();
if (attributeName.equals(adapter.getAttribute().getName()))
result = adapter;
}
}
return result;
}
public Layout getLayout() {
if (layout == null) {
layout = getDefaultLayout();
}
return layout;
}
public void setLayout(Layout layout) {
this.layout = layout;
}
protected Layout getDefaultLayout() {
GridLayout gridLayout = new GridLayout(2, false);
return gridLayout;
}
public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {
for (int i = 0; i < adapters.size(); i++) {
IModelPropertyEditorAdapter a = (IModelPropertyEditorAdapter)adapters.get(i);
a.addValueChangeListener(listener);
}
}
public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {
for (int i = 0; i < adapters.size(); i++) {
IModelPropertyEditorAdapter a = (IModelPropertyEditorAdapter)adapters.get(i);
a.removeValueChangeListener(listener);
}
}
public Properties getValues() {
Properties p = new Properties();
if(data == null) return p;
XAttributeData ads[] = data.getAttributeData();
for (int i = 0; i < adapters.size(); i++) {
IModelPropertyEditorAdapter a = (IModelPropertyEditorAdapter)adapters.get(i);
Object v = a.getValue();
if(v == null) continue;
XAttribute att = ads[i].getAttribute();
String value = v.toString();
if(att.isTrimmable()) value = value.trim();
p.setProperty(att.getName(), value);
}
return p;
}
/**
* @return
*/
public IWidgetSettings getSettings() {
return settings;
}
/**
* @param settings
*/
public void setSettings(IWidgetSettings settings) {
this.settings = settings;
}
/*
* enabled
*/
private boolean enabled = Boolean.TRUE.booleanValue();
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean b) {
enabled = b;
doSetEnabled();
}
protected void doSetEnabled() {
if (this.fieldEditors!=null) {
Collection fieldEditros = this.fieldEditors.values();
Iterator i = fieldEditros.iterator();
while (i.hasNext()) {
((ExtendedFieldEditor)i.next()).setEnabled(enabled);
}
}
}
public void updateEnablementByModelObject() {
Iterator it = fieldEditors.keySet().iterator();
while(it.hasNext()) {
String n = it.next().toString();
ExtendedFieldEditor f = (ExtendedFieldEditor)fieldEditors.get(n);
f.setEnabled(xmo.isAttributeEditable(n));
}
}
public boolean doGlobalAction(String actionId) {
if (getVisibleFieldEditors()==null) return false;
Iterator i = getVisibleFieldEditors().iterator();
ExtendedFieldEditor fieldEditor;
while (i.hasNext()) {
fieldEditor = (ExtendedFieldEditor)i.next();
if (ActionFactory.CUT.getId().equals(actionId)) {
fieldEditor.cut();
} else if (ActionFactory.COPY.getId().equals(actionId)) {
fieldEditor.copy();
} else if (ActionFactory.PASTE.getId().equals(actionId)) {
fieldEditor.paste();
} else if (ActionFactory.DELETE.getId().equals(actionId)) {
fieldEditor.delete();
}
}
return false;
}
}