]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ui/src/org/argeo/cms/forms/EditableMultiStringProperty.java
Next developemt cycle
[lgpl/argeo-commons.git] / org.argeo.cms.ui / src / org / argeo / cms / forms / EditableMultiStringProperty.java
1 package org.argeo.cms.forms;
2
3 import java.util.List;
4
5 import javax.jcr.Node;
6 import javax.jcr.RepositoryException;
7
8 import org.argeo.cms.util.CmsUtils;
9 import org.argeo.cms.viewers.EditablePart;
10 import org.argeo.cms.widgets.StyledControl;
11 import org.argeo.eclipse.ui.EclipseUiUtils;
12 import org.eclipse.jface.dialogs.MessageDialog;
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.events.SelectionListener;
15 import org.eclipse.swt.events.TraverseEvent;
16 import org.eclipse.swt.events.TraverseListener;
17 import org.eclipse.swt.layout.GridData;
18 import org.eclipse.swt.layout.GridLayout;
19 import org.eclipse.swt.layout.RowLayout;
20 import org.eclipse.swt.widgets.Button;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Label;
24 import org.eclipse.swt.widgets.Text;
25
26 /** Display, add or remove values from a list in a CMS context */
27 public class EditableMultiStringProperty extends StyledControl implements
28 EditablePart {
29 private static final long serialVersionUID = -7044614381252178595L;
30
31 private String propertyName;
32 private String message;
33 // TODO implement the ability to provide a list of legal values
34 // private String[] possibleValues;
35 private boolean canEdit;
36 private SelectionListener removeValueSL;
37 private List<String> values;
38
39 // TODO manage within the CSS
40 private int rowSpacing = 5;
41 private int rowMarging = 0;
42 private int oneValueMargingRight = 5;
43 private int btnWidth = 16;
44 private int btnHeight = 16;
45 private int btnHorizontalIndent = 3;
46
47 public EditableMultiStringProperty(Composite parent, int style, Node node,
48 String propertyName, List<String> values, String[] possibleValues,
49 String addValueMsg, SelectionListener removeValueSelectionListener)
50 throws RepositoryException {
51 super(parent, style, node, true);
52
53 this.propertyName = propertyName;
54 this.values = values;
55 // this.possibleValues = possibleValues;
56 this.message = addValueMsg;
57 this.canEdit = removeValueSelectionListener != null;
58 this.removeValueSL = removeValueSelectionListener;
59 }
60
61 public List<String> getValues() {
62 return values;
63 }
64
65 public void setValues(List<String> values) {
66 this.values = values;
67 }
68
69 // Row layout items do not need explicit layout data
70 protected void setControlLayoutData(Control control) {
71 }
72
73 /** To be overridden */
74 protected void setContainerLayoutData(Composite composite) {
75 composite.setLayoutData(CmsUtils.fillWidth());
76 }
77
78 @Override
79 public Control getControl() {
80 return super.getControl();
81 }
82
83 @Override
84 protected Control createControl(Composite box, String style) {
85 Composite row = new Composite(box, SWT.NO_FOCUS);
86 row.setLayoutData(EclipseUiUtils.fillAll());
87
88 RowLayout rl = new RowLayout(SWT.HORIZONTAL);
89 rl.wrap = true;
90 rl.spacing = rowSpacing;
91 rl.marginRight = rl.marginLeft = rl.marginBottom = rl.marginTop = rowMarging;
92 row.setLayout(rl);
93
94 if (values != null) {
95 for (final String value : values) {
96 if (canEdit)
97 createRemovableValue(row, SWT.SINGLE, value);
98 else
99 createValueLabel(row, SWT.SINGLE, value);
100 }
101 }
102
103 if (!canEdit)
104 return row;
105 else if (isEditing())
106 return createText(row, style);
107 else
108 return createLabel(row, style);
109 }
110
111 /**
112 * Override to provide specific layout for the existing values, typically
113 * adding a pound (#) char for tags or anchor info for browsable links. We
114 * assume the parent composite already has a layout and it is the caller
115 * responsibility to apply corresponding layout data
116 */
117 protected Label createValueLabel(Composite parent, int style, String value) {
118 Label label = new Label(parent, style);
119 label.setText("#" + value);
120 CmsUtils.markup(label);
121 CmsUtils.style(label, FormStyle.propertyText.style());
122 return label;
123 }
124
125 private Composite createRemovableValue(Composite parent, int style,
126 String value) {
127 Composite valCmp = new Composite(parent, SWT.NO_FOCUS);
128 GridLayout gl = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2,
129 false));
130 gl.marginRight = oneValueMargingRight;
131 valCmp.setLayout(gl);
132
133 createValueLabel(valCmp, SWT.WRAP, value);
134
135 Button deleteBtn = new Button(valCmp, SWT.FLAT);
136 deleteBtn.setData(FormConstants.LINKED_VALUE, value);
137 deleteBtn.addSelectionListener(removeValueSL);
138 CmsUtils.style(deleteBtn, FormStyle.delete.style()
139 + FormStyle.BUTTON_SUFFIX);
140 GridData gd = new GridData();
141 gd.heightHint = btnHeight;
142 gd.widthHint = btnWidth;
143 gd.horizontalIndent = btnHorizontalIndent;
144 deleteBtn.setLayoutData(gd);
145
146 return valCmp;
147 }
148
149 protected Text createText(Composite box, String style) {
150 final Text text = new Text(box, getStyle());
151 // The "add new value" text is not meant to change, so we can set it on
152 // creation
153 text.setMessage(message);
154 CmsUtils.style(text, style);
155 text.setFocus();
156
157 text.addTraverseListener(new TraverseListener() {
158 private static final long serialVersionUID = 1L;
159
160 public void keyTraversed(TraverseEvent e) {
161 if (e.keyCode == SWT.CR) {
162 addValue(text);
163 e.doit = false;
164 }
165 }
166 });
167
168 // The OK button does not work with the focusOut listener
169 // because focus out is called before the OK button is pressed
170
171 // // we must call layout() now so that the row data can compute the
172 // height
173 // // of the other controls.
174 // text.getParent().layout();
175 // int height = text.getSize().y;
176 //
177 // Button okBtn = new Button(box, SWT.BORDER | SWT.PUSH | SWT.BOTTOM);
178 // okBtn.setText("OK");
179 // RowData rd = new RowData(SWT.DEFAULT, height - 2);
180 // okBtn.setLayoutData(rd);
181 //
182 // okBtn.addSelectionListener(new SelectionAdapter() {
183 // private static final long serialVersionUID = 2780819012423622369L;
184 //
185 // @Override
186 // public void widgetSelected(SelectionEvent e) {
187 // addValue(text);
188 // }
189 // });
190
191 return text;
192 }
193
194 /** Performs the real addition, overwrite to make further sanity checks */
195 protected void addValue(Text text) {
196 String value = text.getText();
197 String errMsg = null;
198
199 if (EclipseUiUtils.isEmpty(value))
200 return;
201
202 if (values.contains(value))
203 errMsg = "Dupplicated value: " + value
204 + ", please correct and try again";
205 if (errMsg != null)
206 MessageDialog.openError(this.getShell(), "Addition not allowed",
207 errMsg);
208 else {
209 values.add(value);
210 Composite newCmp = createRemovableValue(text.getParent(),
211 SWT.SINGLE, value);
212 newCmp.moveAbove(text);
213 text.setText("");
214 newCmp.getParent().layout();
215 }
216 }
217
218 protected Label createLabel(Composite box, String style) {
219 if (canEdit) {
220 Label lbl = new Label(box, getStyle());
221 lbl.setText(message);
222 CmsUtils.style(lbl, style);
223 CmsUtils.markup(lbl);
224 if (mouseListener != null)
225 lbl.addMouseListener(mouseListener);
226 return lbl;
227 }
228 return null;
229 }
230
231 protected void clear(boolean deep) {
232 Control child = getControl();
233 if (deep)
234 super.clear(deep);
235 else {
236 child.getParent().dispose();
237 }
238 }
239
240 public void setText(String text) {
241 Control child = getControl();
242 if (child instanceof Label) {
243 Label lbl = (Label) child;
244 if (canEdit)
245 lbl.setText(text);
246 else
247 lbl.setText("");
248 } else if (child instanceof Text) {
249 Text txt = (Text) child;
250 txt.setText(text);
251 }
252 }
253
254 public synchronized void startEditing() {
255 getControl().setData(STYLE, FormStyle.propertyText.style());
256 super.startEditing();
257 }
258
259 public synchronized void stopEditing() {
260 getControl().setData(STYLE, FormStyle.propertyMessage.style());
261 super.stopEditing();
262 }
263
264 public String getPropertyName() {
265 return propertyName;
266 }
267 }