View Javadoc
1   package org.argeo.cms.ui.forms;
2   
3   import java.text.DateFormat;
4   import java.util.Calendar;
5   import java.util.GregorianCalendar;
6   
7   import javax.jcr.Node;
8   import javax.jcr.RepositoryException;
9   
10  import org.argeo.cms.ui.util.CmsUiUtils;
11  import org.argeo.cms.ui.viewers.EditablePart;
12  import org.argeo.cms.ui.widgets.StyledControl;
13  import org.argeo.eclipse.ui.EclipseUiUtils;
14  import org.eclipse.swt.SWT;
15  import org.eclipse.swt.events.MouseEvent;
16  import org.eclipse.swt.events.MouseListener;
17  import org.eclipse.swt.events.SelectionAdapter;
18  import org.eclipse.swt.events.SelectionEvent;
19  import org.eclipse.swt.events.ShellAdapter;
20  import org.eclipse.swt.events.ShellEvent;
21  import org.eclipse.swt.layout.GridData;
22  import org.eclipse.swt.layout.GridLayout;
23  import org.eclipse.swt.widgets.Button;
24  import org.eclipse.swt.widgets.Composite;
25  import org.eclipse.swt.widgets.Control;
26  import org.eclipse.swt.widgets.DateTime;
27  import org.eclipse.swt.widgets.Label;
28  import org.eclipse.swt.widgets.Shell;
29  import org.eclipse.swt.widgets.Text;
30  
31  /** CMS form part to display and edit a date */
32  public class EditablePropertyDate extends StyledControl implements EditablePart {
33  	private static final long serialVersionUID = 2500215515778162468L;
34  
35  	// Context
36  	private String propertyName;
37  	private String message;
38  	private DateFormat dateFormat;
39  
40  	// UI Objects
41  	private Text dateTxt;
42  	private Button openCalBtn;
43  
44  	// TODO manage within the CSS
45  	private int fieldBtnSpacing = 5;
46  
47  	/**
48  	 * 
49  	 * @param parent
50  	 * @param style
51  	 * @param node
52  	 * @param propertyName
53  	 * @param message
54  	 * @param dateFormat
55  	 *            provide a {@link DateFormat} as contract to be able to
56  	 *            read/write dates as strings
57  	 * @throws RepositoryException
58  	 */
59  	public EditablePropertyDate(Composite parent, int style, Node node,
60  			String propertyName, String message, DateFormat dateFormat)
61  			throws RepositoryException {
62  		super(parent, style, node, false);
63  
64  		this.propertyName = propertyName;
65  		this.message = message;
66  		this.dateFormat = dateFormat;
67  
68  		if (node.hasProperty(propertyName)) {
69  			this.setStyle(FormStyle.propertyText.style());
70  			this.setText(dateFormat.format(node.getProperty(propertyName)
71  					.getDate().getTime()));
72  		} else {
73  			this.setStyle(FormStyle.propertyMessage.style());
74  			this.setText(message);
75  		}
76  	}
77  
78  	public void setText(String text) {
79  		Control child = getControl();
80  		if (child instanceof Label) {
81  			Label lbl = (Label) child;
82  			if (EclipseUiUtils.isEmpty(text))
83  				lbl.setText(message);
84  			else
85  				lbl.setText(text);
86  		} else if (child instanceof Text) {
87  			Text txt = (Text) child;
88  			if (EclipseUiUtils.isEmpty(text)) {
89  				txt.setText("");
90  			} else
91  				txt.setText(text);
92  		}
93  	}
94  
95  	public synchronized void startEditing() {
96  		// if (dateTxt != null && !dateTxt.isDisposed())
97  		getControl().setData(STYLE, FormStyle.propertyText.style());
98  		super.startEditing();
99  	}
100 
101 	public synchronized void stopEditing() {
102 		if (EclipseUiUtils.isEmpty(dateTxt.getText()))
103 			getControl().setData(STYLE, FormStyle.propertyMessage.style());
104 		else
105 			getControl().setData(STYLE, FormStyle.propertyText.style());
106 		super.stopEditing();
107 	}
108 
109 	public String getPropertyName() {
110 		return propertyName;
111 	}
112 
113 	@Override
114 	protected Control createControl(Composite box, String style) {
115 		if (isEditing()) {
116 			return createCustomEditableControl(box, style);
117 		} else
118 			return createLabel(box, style);
119 	}
120 
121 	protected Label createLabel(Composite box, String style) {
122 		Label lbl = new Label(box, getStyle() | SWT.WRAP);
123 		lbl.setLayoutData(CmsUiUtils.fillWidth());
124 		CmsUiUtils.style(lbl, style);
125 		CmsUiUtils.markup(lbl);
126 		if (mouseListener != null)
127 			lbl.addMouseListener(mouseListener);
128 		return lbl;
129 	}
130 
131 	private Control createCustomEditableControl(Composite box, String style) {
132 		box.setLayoutData(CmsUiUtils.fillWidth());
133 		Composite dateComposite = new Composite(box, SWT.NONE);
134 		GridLayout gl = EclipseUiUtils.noSpaceGridLayout(new GridLayout(2,
135 				false));
136 		gl.horizontalSpacing = fieldBtnSpacing;
137 		dateComposite.setLayout(gl);
138 		dateTxt = new Text(dateComposite, SWT.BORDER);
139 		CmsUiUtils.style(dateTxt, style);
140 		dateTxt.setLayoutData(new GridData(120, SWT.DEFAULT));
141 		dateTxt.setToolTipText("Enter a date with form \""
142 				+ FormUtils.DEFAULT_SHORT_DATE_FORMAT
143 				+ "\" or use the calendar");
144 		openCalBtn = new Button(dateComposite, SWT.FLAT);
145 		CmsUiUtils.style(openCalBtn, FormStyle.calendar.style()
146 				+ FormStyle.BUTTON_SUFFIX);
147 		GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false);
148 		gd.heightHint = 17;
149 		openCalBtn.setLayoutData(gd);
150 		// openCalBtn.setImage(PeopleRapImages.CALENDAR_BTN);
151 
152 		openCalBtn.addSelectionListener(new SelectionAdapter() {
153 			private static final long serialVersionUID = 1L;
154 
155 			public void widgetSelected(SelectionEvent event) {
156 				CalendarPopup popup = new CalendarPopup(dateTxt);
157 				popup.open();
158 			}
159 		});
160 
161 		// dateTxt.addFocusListener(new FocusListener() {
162 		// private static final long serialVersionUID = 1L;
163 		//
164 		// @Override
165 		// public void focusLost(FocusEvent event) {
166 		// String newVal = dateTxt.getText();
167 		// // Enable reset of the field
168 		// if (FormUtils.notNull(newVal))
169 		// calendar = null;
170 		// else {
171 		// try {
172 		// Calendar newCal = parseDate(newVal);
173 		// // DateText.this.setText(newCal);
174 		// calendar = newCal;
175 		// } catch (ParseException pe) {
176 		// // Silent. Manage error popup?
177 		// if (calendar != null)
178 		// EditablePropertyDate.this.setText(calendar);
179 		// }
180 		// }
181 		// }
182 		//
183 		// @Override
184 		// public void focusGained(FocusEvent event) {
185 		// }
186 		// });
187 		return dateTxt;
188 	}
189 
190 	protected void clear(boolean deep) {
191 		Control child = getControl();
192 		if (deep || child instanceof Label)
193 			super.clear(deep);
194 		else {
195 			child.getParent().dispose();
196 		}
197 	}
198 
199 	/** Enable setting a custom tooltip on the underlying text */
200 	@Deprecated
201 	public void setToolTipText(String toolTipText) {
202 		dateTxt.setToolTipText(toolTipText);
203 	}
204 
205 	@Deprecated
206 	/** Enable setting a custom message on the underlying text */
207 	public void setMessage(String message) {
208 		dateTxt.setMessage(message);
209 	}
210 
211 	@Deprecated
212 	public void setText(Calendar cal) {
213 		String newValueStr = "";
214 		if (cal != null)
215 			newValueStr = dateFormat.format(cal.getTime());
216 		if (!newValueStr.equals(dateTxt.getText()))
217 			dateTxt.setText(newValueStr);
218 	}
219 
220 	// UTILITIES TO MANAGE THE CALENDAR POPUP
221 	// TODO manage the popup shell in a cleaner way
222 	private class CalendarPopup extends Shell {
223 		private static final long serialVersionUID = 1L;
224 		private DateTime dateTimeCtl;
225 
226 		public CalendarPopup(Control source) {
227 			super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP);
228 			populate();
229 			// Add border and shadow style
230 			CmsUiUtils.markup(CalendarPopup.this);
231 			CmsUiUtils.style(CalendarPopup.this, FormStyle.popupCalendar.style());
232 			pack();
233 			layout();
234 			setLocation(source.toDisplay((source.getLocation().x - 2),
235 					(source.getSize().y) + 3));
236 
237 			addShellListener(new ShellAdapter() {
238 				private static final long serialVersionUID = 5178980294808435833L;
239 
240 				@Override
241 				public void shellDeactivated(ShellEvent e) {
242 					close();
243 					dispose();
244 				}
245 			});
246 			open();
247 		}
248 
249 		private void setProperty() {
250 			// Direct set does not seems to work. investigate
251 			// cal.set(dateTimeCtl.getYear(), dateTimeCtl.getMonth(),
252 			// dateTimeCtl.getDay(), 12, 0);
253 			Calendar cal = new GregorianCalendar();
254 			cal.set(Calendar.YEAR, dateTimeCtl.getYear());
255 			cal.set(Calendar.MONTH, dateTimeCtl.getMonth());
256 			cal.set(Calendar.DAY_OF_MONTH, dateTimeCtl.getDay());
257 			String dateStr = dateFormat.format(cal.getTime());
258 			dateTxt.setText(dateStr);
259 		}
260 
261 		protected void populate() {
262 			setLayout(EclipseUiUtils.noSpaceGridLayout());
263 
264 			dateTimeCtl = new DateTime(this, SWT.CALENDAR);
265 			dateTimeCtl.setLayoutData(EclipseUiUtils.fillAll());
266 
267 			Calendar calendar = FormUtils.parseDate(dateFormat,
268 					dateTxt.getText());
269 
270 			if (calendar != null)
271 				dateTimeCtl.setDate(calendar.get(Calendar.YEAR),
272 						calendar.get(Calendar.MONTH),
273 						calendar.get(Calendar.DAY_OF_MONTH));
274 
275 			dateTimeCtl.addSelectionListener(new SelectionAdapter() {
276 				private static final long serialVersionUID = -8414377364434281112L;
277 
278 				@Override
279 				public void widgetSelected(SelectionEvent e) {
280 					setProperty();
281 				}
282 			});
283 
284 			dateTimeCtl.addMouseListener(new MouseListener() {
285 				private static final long serialVersionUID = 1L;
286 
287 				@Override
288 				public void mouseUp(MouseEvent e) {
289 				}
290 
291 				@Override
292 				public void mouseDown(MouseEvent e) {
293 				}
294 
295 				@Override
296 				public void mouseDoubleClick(MouseEvent e) {
297 					setProperty();
298 					close();
299 					dispose();
300 				}
301 			});
302 		}
303 	}
304 }