| 1 | package de.uka.ipd.sdq.pcmbench.tabs; |
| 2 | |
| 3 | import org.eclipse.emf.common.notify.Notification; |
| 4 | import org.eclipse.emf.ecore.EObject; |
| 5 | import org.eclipse.emf.ecore.EStructuralFeature; |
| 6 | import org.eclipse.emf.ecore.util.EContentAdapter; |
| 7 | import org.eclipse.emf.transaction.RecordingCommand; |
| 8 | import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| 9 | import org.eclipse.emf.transaction.util.TransactionUtil; |
| 10 | import org.eclipse.swt.SWT; |
| 11 | import org.eclipse.swt.custom.CLabel; |
| 12 | import org.eclipse.swt.layout.FormAttachment; |
| 13 | import org.eclipse.swt.layout.FormData; |
| 14 | import org.eclipse.swt.widgets.Composite; |
| 15 | import org.eclipse.swt.widgets.Control; |
| 16 | import org.eclipse.swt.widgets.Event; |
| 17 | import org.eclipse.swt.widgets.Listener; |
| 18 | import org.eclipse.swt.widgets.Text; |
| 19 | import org.eclipse.ui.services.IDisposable; |
| 20 | import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection; |
| 21 | import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants; |
| 22 | import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory; |
| 23 | |
| 24 | /** |
| 25 | * @author Snowball |
| 26 | * This class provides a fully generic edit field which can be used to edit |
| 27 | * EMF features of type string. Any given feature of any EMF meta-model can |
| 28 | * be specified and will be displayed using a label and a text edit field. |
| 29 | */ |
| 30 | public class EMFPropertyTextEdit implements IDisposable { |
| 31 | |
| 32 | |
| 33 | private TabbedPropertySheetWidgetFactory factory; |
| 34 | |
| 35 | private Text valueText; |
| 36 | |
| 37 | private Listener listener; |
| 38 | |
| 39 | private String labelText; |
| 40 | |
| 41 | /** |
| 42 | * The transactional editing domain which is used to get the commands and alter the model |
| 43 | */ |
| 44 | protected TransactionalEditingDomain editingDomain = null; |
| 45 | |
| 46 | private EObject element; |
| 47 | private EStructuralFeature attribute; |
| 48 | |
| 49 | private EMFPropertyTextEdit predecessor; |
| 50 | |
| 51 | private EContentAdapter listeningAdapter; |
| 52 | |
| 53 | private Composite composite; |
| 54 | |
| 55 | |
| 56 | /** |
| 57 | * Constructor of the generic EMF edit field |
| 58 | * @param parentForm The SWT parent form on which this edit field will be shown |
| 59 | * @param labelText The text which is displayed in front of the edit field |
| 60 | * @param attribute The EMF feature which is being edited in the edit field |
| 61 | * @param factory The widged factory used to create the UI parts |
| 62 | * @param predecessor The preceeding edit field - |
| 63 | * this is used to layout the edit fields on the property tab sheets. |
| 64 | * Pass in null for the first field |
| 65 | */ |
| 66 | public EMFPropertyTextEdit(Composite parentForm, |
| 67 | String labelText, |
| 68 | EStructuralFeature attribute, |
| 69 | TabbedPropertySheetWidgetFactory factory, |
| 70 | EMFPropertyTextEdit predecessor) { |
| 71 | |
| 72 | this.factory = factory; |
| 73 | this.labelText = labelText; |
| 74 | this.attribute = attribute; |
| 75 | this.predecessor = predecessor; |
| 76 | this.composite = parentForm; |
| 77 | |
| 78 | init(); |
| 79 | } |
| 80 | |
| 81 | private void init() { |
| 82 | createTextField(); |
| 83 | createDisplayLabel(); |
| 84 | addChangeListener(); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | /** |
| 89 | * This listener reacts on Focus Out and On Enter, in both cases we store the current value in the model via a command |
| 90 | */ |
| 91 | private void addChangeListener() { |
| 92 | listener = new Listener() { |
| 93 | |
| 94 | public void handleEvent(Event event) { |
| 95 | switch (event.type) { |
| 96 | case SWT.KeyDown: |
| 97 | if (event.character == SWT.CR) |
| 98 | textChanged((Control) event.widget); |
| 99 | break; |
| 100 | case SWT.FocusOut: |
| 101 | textChanged((Control) event.widget); |
| 102 | break; |
| 103 | } |
| 104 | } |
| 105 | }; |
| 106 | valueText.addListener(SWT.KeyDown, listener); |
| 107 | valueText.addListener(SWT.FocusOut, listener); |
| 108 | valueText.addListener(SWT.Modify, listener); |
| 109 | } |
| 110 | |
| 111 | private void createDisplayLabel() { |
| 112 | FormData data; |
| 113 | CLabel valueLabel = factory.createCLabel(composite, labelText+":"); //$NON-NLS-1$ |
| 114 | data = new FormData(); |
| 115 | data.left = new FormAttachment(0, 0); |
| 116 | data.right = new FormAttachment(valueText, |
| 117 | -ITabbedPropertyConstants.HSPACE); |
| 118 | data.top = new FormAttachment(valueText, 0, SWT.CENTER); |
| 119 | valueLabel.setLayoutData(data); |
| 120 | } |
| 121 | |
| 122 | private void createTextField() { |
| 123 | FormData data; |
| 124 | valueText = factory.createText(composite, ""); //$NON-NLS-1$ |
| 125 | data = new FormData(); |
| 126 | if (predecessor == null){ |
| 127 | data.top = new FormAttachment(0, 0); |
| 128 | data.left = new FormAttachment(0, |
| 129 | AbstractPropertySection.STANDARD_LABEL_WIDTH); |
| 130 | data.right = new FormAttachment(100, 0); |
| 131 | } else { |
| 132 | data.top = |
| 133 | new FormAttachment( |
| 134 | predecessor.getValueText(), |
| 135 | ITabbedPropertyConstants.VSPACE, |
| 136 | SWT.BOTTOM); |
| 137 | data.left = new FormAttachment(predecessor.getValueText(), 0, SWT.LEFT); |
| 138 | data.right = new FormAttachment(predecessor.getValueText(), 0, SWT.RIGHT); |
| 139 | } |
| 140 | valueText.setLayoutData(data); |
| 141 | } |
| 142 | |
| 143 | private Text getValueText() { |
| 144 | return valueText; |
| 145 | } |
| 146 | |
| 147 | /** |
| 148 | * Initialise this edit field with its model object which is displayed and |
| 149 | * edited in this text field |
| 150 | * @param object Model object which is edited in this text field |
| 151 | */ |
| 152 | public void setEObject(EObject object) |
| 153 | { |
| 154 | this.editingDomain = TransactionUtil.getEditingDomain(object); |
| 155 | this.element = object; |
| 156 | this.listeningAdapter = new EContentAdapter(){ |
| 157 | |
| 158 | /* (non-Javadoc) |
| 159 | * @see org.eclipse.emf.ecore.util.EContentAdapter#notifyChanged(org.eclipse.emf.common.notify.Notification) |
| 160 | */ |
| 161 | @Override |
| 162 | public void notifyChanged(Notification notification) { |
| 163 | super.notifyChanged(notification); |
| 164 | if (notification.getEventType() == Notification.SET && notification.getFeature().equals(attribute)) |
| 165 | { |
| 166 | if (!valueText.getText().equals(element.eGet(attribute))) |
| 167 | valueText.setText((String)element.eGet(attribute)); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | }; |
| 172 | object.eAdapters().add(listeningAdapter); |
| 173 | String newValue = element.eGet(attribute) == null ? "" : (String)element.eGet(attribute); |
| 174 | valueText.setText(newValue); |
| 175 | } |
| 176 | |
| 177 | /** |
| 178 | * Listener which issues edit commands whenever the edit field content |
| 179 | * is changed |
| 180 | * @param control The control sending the event |
| 181 | */ |
| 182 | private void textChanged(Control control) { |
| 183 | RecordingCommand recCommand = new RecordingCommand(editingDomain) { |
| 184 | |
| 185 | @Override |
| 186 | protected void doExecute() { |
| 187 | element.eSet(attribute, valueText.getText()); |
| 188 | } |
| 189 | |
| 190 | }; |
| 191 | if (!valueText.getText().equals(element.eGet(attribute))) |
| 192 | { |
| 193 | recCommand.setDescription("Edit Component Property"); |
| 194 | recCommand.setLabel("Set "+attribute.getName()); |
| 195 | editingDomain.getCommandStack().execute(recCommand); |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | /* (non-Javadoc) |
| 200 | * @see org.eclipse.ui.services.IDisposable#dispose() |
| 201 | */ |
| 202 | public void dispose() { |
| 203 | this.element.eAdapters().remove(listeningAdapter); |
| 204 | valueText.removeListener(SWT.KeyDown, listener); |
| 205 | valueText.removeListener(SWT.FocusOut, listener); |
| 206 | valueText.removeListener(SWT.Modify, listener); |
| 207 | } |
| 208 | |
| 209 | } |