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 | } |