Mercurial > dive4elements > river
comparison flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ManualPointsEditor.java @ 1545:2f0150f21e77
Added basic UI to enter manual points.
flys-client/trunk@3773 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Thu, 26 Jan 2012 13:27:19 +0000 |
parents | |
children | 76377fe3f0c7 |
comparison
equal
deleted
inserted
replaced
1544:2b3d02626823 | 1545:2f0150f21e77 |
---|---|
1 package de.intevation.flys.client.client.ui.chart; | |
2 | |
3 import java.util.ArrayList; | |
4 import java.util.List; | |
5 import java.util.Map; | |
6 | |
7 import com.google.gwt.json.client.JSONArray; | |
8 import com.google.gwt.json.client.JSONNumber; | |
9 import com.google.gwt.json.client.JSONParser; | |
10 import com.google.gwt.core.client.GWT; | |
11 import com.google.gwt.user.client.rpc.AsyncCallback; | |
12 | |
13 import com.smartgwt.client.util.SC; | |
14 import com.smartgwt.client.widgets.Window; | |
15 import com.smartgwt.client.widgets.tab.TabSet; | |
16 import com.smartgwt.client.widgets.tab.Tab; | |
17 import com.smartgwt.client.widgets.layout.VLayout; | |
18 import com.smartgwt.client.widgets.layout.HLayout; | |
19 import com.smartgwt.client.widgets.IButton; | |
20 import com.smartgwt.client.widgets.Button; | |
21 import com.smartgwt.client.widgets.Label; | |
22 import com.smartgwt.client.widgets.Canvas; | |
23 import com.smartgwt.client.widgets.grid.ListGrid; | |
24 import com.smartgwt.client.widgets.grid.ListGridField; | |
25 import com.smartgwt.client.widgets.grid.ListGridRecord; | |
26 | |
27 import com.smartgwt.client.widgets.form.DynamicForm; | |
28 import com.smartgwt.client.widgets.form.fields.FormItem; | |
29 import com.smartgwt.client.widgets.form.fields.CheckboxItem; | |
30 import com.smartgwt.client.widgets.form.fields.TextItem; | |
31 | |
32 import com.smartgwt.client.widgets.events.ClickEvent; | |
33 import com.smartgwt.client.widgets.events.ClickHandler; | |
34 import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; | |
35 import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; | |
36 import com.smartgwt.client.widgets.form.fields.events.BlurHandler; | |
37 import com.smartgwt.client.widgets.form.fields.events.BlurEvent; | |
38 | |
39 import com.smartgwt.client.types.Alignment; | |
40 | |
41 import de.intevation.flys.client.shared.model.Artifact; | |
42 | |
43 import de.intevation.flys.client.client.Config; | |
44 import de.intevation.flys.client.client.FLYSConstants; | |
45 import de.intevation.flys.client.shared.model.Property; | |
46 import de.intevation.flys.client.shared.model.PropertyGroup; | |
47 import de.intevation.flys.client.shared.model.PropertySetting; | |
48 import de.intevation.flys.client.shared.model.BooleanProperty; | |
49 import de.intevation.flys.client.shared.model.DoubleProperty; | |
50 import de.intevation.flys.client.shared.model.IntegerProperty; | |
51 import de.intevation.flys.client.shared.model.StringProperty; | |
52 import de.intevation.flys.client.shared.model.Settings; | |
53 import de.intevation.flys.client.shared.model.OutputSettings; | |
54 import de.intevation.flys.client.shared.model.Collection; | |
55 import de.intevation.flys.client.shared.model.CollectionItem; | |
56 import de.intevation.flys.client.client.utils.IntegerValidator; | |
57 import de.intevation.flys.client.client.utils.DoubleValidator; | |
58 | |
59 import de.intevation.flys.client.client.services.CollectionAttributeService; | |
60 import de.intevation.flys.client.client.services.CollectionAttributeServiceAsync; | |
61 import de.intevation.flys.client.client.services.LoadArtifactService; | |
62 import de.intevation.flys.client.client.services.LoadArtifactServiceAsync; | |
63 import de.intevation.flys.client.client.services.FeedService; | |
64 import de.intevation.flys.client.client.services.FeedServiceAsync; | |
65 | |
66 import de.intevation.flys.client.shared.model.Data; | |
67 import de.intevation.flys.client.shared.model.DefaultArtifact; | |
68 import de.intevation.flys.client.shared.model.DefaultData; | |
69 import de.intevation.flys.client.shared.model.Recommendation; | |
70 import de.intevation.flys.client.shared.model.Recommendation.Facet; | |
71 import de.intevation.flys.client.shared.model.Recommendation.Filter; | |
72 | |
73 | |
74 /** | |
75 * UI to enter point data and save it to an PointArtifact. | |
76 */ | |
77 public class ManualPointsEditor | |
78 extends Window | |
79 implements ClickHandler | |
80 { | |
81 /** The interface that provides i18n messages. */ | |
82 protected FLYSConstants MSG = GWT.create(FLYSConstants.class); | |
83 | |
84 /** Name of the main data item to be fed. */ | |
85 public static final String POINT_DATA = "manualpoints.data"; | |
86 // TODO with separate point sets in multiple diagrams, we might need | |
87 // different POINT_DATA-names (e.g. one per diagram). | |
88 | |
89 protected CollectionAttributeServiceAsync updater = | |
90 GWT.create(CollectionAttributeService.class); | |
91 | |
92 /** The collection */ | |
93 protected Collection collection; | |
94 | |
95 /** The listGrid showing point entries. */ | |
96 protected ListGrid listGrid; | |
97 | |
98 /** Service handle to clone and add artifacts to collection. */ | |
99 LoadArtifactServiceAsync loadArtifactService = GWT.create( | |
100 de.intevation.flys.client.client.services.LoadArtifactService.class); | |
101 | |
102 /** Service to feed the artifact with new point-data. */ | |
103 FeedServiceAsync feedService = GWT.create( | |
104 de.intevation.flys.client.client.services.FeedService.class); | |
105 | |
106 /** UUID of artifact to feed. */ | |
107 protected String uuid; | |
108 | |
109 | |
110 /** | |
111 * Setup editor dialog. | |
112 * @param collection The collection to use. | |
113 */ | |
114 public ManualPointsEditor(Collection collection) { | |
115 this.collection = collection; | |
116 init(); | |
117 } | |
118 | |
119 | |
120 /** Searches collection for first artifact to serve (manual) point data. */ | |
121 public String findManualPointsUUID() { | |
122 // TODO Need to be more picky (different points in different diagrams) | |
123 int size = collection.getItemLength(); | |
124 | |
125 for (int i = 0; i < size; i++) { | |
126 CollectionItem item = collection.getItem(i); | |
127 String dataValue = (String) item.getData().get(POINT_DATA); | |
128 if (dataValue != null) { | |
129 // Found it. | |
130 uuid = item.identifier(); | |
131 return uuid; | |
132 } | |
133 } | |
134 | |
135 return null; | |
136 } | |
137 | |
138 | |
139 /** | |
140 * Initialize the editor window and its components. | |
141 */ | |
142 protected void init() { | |
143 setTitle("Add Points"); | |
144 //TODO MSG.properties()); | |
145 setCanDragReposition(true); | |
146 setCanDragResize(true); | |
147 | |
148 // If no manualpoints artifact found, create it now. | |
149 if(findManualPointsUUID() == null) { | |
150 addArtifactCreateUI(); | |
151 } | |
152 else { | |
153 createUI(); | |
154 } | |
155 } | |
156 | |
157 /** Create and setup/add the ui. */ | |
158 public void createUI() { | |
159 Config config = Config.getInstance(); | |
160 | |
161 Button accept = new Button(MSG.label_ok()); | |
162 Button cancel = new Button(MSG.label_cancel()); | |
163 cancel.addClickHandler(this); | |
164 accept.addClickHandler(new ClickHandler() { | |
165 public void onClick(ClickEvent e) { | |
166 if(isDialogValid()) { | |
167 // Feed JSON-encoded content of listgrid. | |
168 String jsonString = ""; | |
169 int idx = 0; | |
170 JSONArray list = new JSONArray(); | |
171 | |
172 // TODO also need name attribute | |
173 for(ListGridRecord record : listGrid.getRecords()) { | |
174 if (record instanceof PointRecord) { | |
175 JSONArray data = new JSONArray(); | |
176 | |
177 PointRecord point = (PointRecord) record; | |
178 data.set(0, new JSONNumber(point.getX())); | |
179 data.set(1, new JSONNumber(point.getY())); | |
180 | |
181 list.set(idx, data); | |
182 idx++; | |
183 } | |
184 else { | |
185 JSONArray data = new JSONArray(); | |
186 | |
187 // TODO better get double directly (via cell-formatter etc) | |
188 String xString = record.getAttributeAsString("X"); | |
189 String yString = record.getAttributeAsString("Y"); | |
190 | |
191 data.set(0, new JSONNumber(Double.valueOf(xString))); | |
192 data.set(1, new JSONNumber(Double.valueOf(yString))); | |
193 | |
194 list.set(idx, data); | |
195 idx++; | |
196 } | |
197 } | |
198 | |
199 // TODO lock UI until feed succeeded/failed. | |
200 | |
201 // Feed list.toString to respective artifact. | |
202 Data[] feedData = new Data[] { | |
203 DefaultData.createSimpleStringData(POINT_DATA, | |
204 list.toString()) | |
205 }; | |
206 feedService.feed( | |
207 Config.getInstance().getLocale(), | |
208 new DefaultArtifact(uuid, "TODO:hash"), | |
209 feedData, | |
210 new AsyncCallback<Artifact>() { | |
211 public void onFailure(Throwable caught) { | |
212 GWT.log("Could not feed artifact with points."); | |
213 SC.warn(MSG.getString(caught.getMessage())); | |
214 enable(); | |
215 } | |
216 public void onSuccess(Artifact fartifact) { | |
217 GWT.log("Successfully set points "); | |
218 // TODO refresh view | |
219 //requestRedraw(); | |
220 //updateCollection(); | |
221 //updateGrid(); | |
222 //enable(); | |
223 destroy(); | |
224 } | |
225 }); | |
226 } | |
227 else { | |
228 GWT.log("Dialog not valid"); | |
229 SC.warn(MSG.error_dialog_not_valid()); | |
230 } | |
231 } | |
232 }); | |
233 | |
234 HLayout buttons = new HLayout(); | |
235 buttons.addMember(accept); | |
236 buttons.addMember(cancel); | |
237 buttons.setAlign(Alignment.CENTER); | |
238 buttons.setHeight(30); | |
239 | |
240 HLayout newPointLayout = new HLayout(); | |
241 DynamicForm newPointForm = createNewPointForm(); | |
242 newPointLayout.addMember(newPointForm); | |
243 | |
244 VLayout layout = new VLayout(); | |
245 listGrid = new ListGrid(); | |
246 listGrid.setWidth100(); | |
247 listGrid.setHeight(200); | |
248 final ListGridField xField = new ListGridField("X", "X"); | |
249 final ListGridField yField = new ListGridField("Y", "Y"); | |
250 final ListGridField nameField = new ListGridField("name", "name"); | |
251 final ListGridField removeField = new ListGridField("remove", "remove"); | |
252 listGrid.setFields(new ListGridField[] {xField, yField, removeField}); | |
253 | |
254 // Find the artifacts uuid. | |
255 findManualPointsUUID(); | |
256 CollectionItem item = collection.getItem(uuid); | |
257 | |
258 // Add points to grid. | |
259 if (item != null) { | |
260 String jsonData = item.getData().get(POINT_DATA); | |
261 JSONArray jsonArray = (JSONArray) JSONParser.parse(jsonData); | |
262 for (int i = 0; i < jsonArray.size(); i++) { | |
263 JSONArray point = (JSONArray) jsonArray.get(i); | |
264 listGrid.addData(pointRecordFromJSON(point)); | |
265 } | |
266 } | |
267 else { | |
268 System.out.println("No item found for " + uuid); | |
269 } | |
270 | |
271 layout.addMember(listGrid); | |
272 | |
273 addItem(layout); | |
274 IButton button = new IButton("Edit New"); | |
275 button.setTop(250); | |
276 button.addClickHandler(new ClickHandler() { | |
277 public void onClick(ClickEvent event) { | |
278 listGrid.startEditingNew(); | |
279 } | |
280 }); | |
281 addItem(button); | |
282 addItem(buttons); | |
283 setWidth(380); | |
284 setHeight(470); | |
285 centerInPage(); | |
286 } | |
287 | |
288 | |
289 /** From a JSON-encoded point, create a PointRecord. */ | |
290 public PointRecord pointRecordFromJSON(JSONArray jsonArray) { | |
291 JSONNumber x = (JSONNumber) jsonArray.get(0); | |
292 JSONNumber y = (JSONNumber) jsonArray.get(1); | |
293 return new PointRecord(x.doubleValue(), y.doubleValue()); | |
294 } | |
295 | |
296 | |
297 /** Add a ManualPointArtifact to Collection. */ | |
298 public void addArtifactCreateUI() { | |
299 // TODO MSG:/i18n | |
300 final Label standByLabel = new Label("Creating artifact, these are not the droids"); | |
301 addItem(standByLabel); | |
302 | |
303 setWidth(380); | |
304 setHeight(470); | |
305 centerInPage(); | |
306 | |
307 Config config = Config.getInstance(); | |
308 String locale = config.getLocale(); | |
309 | |
310 loadArtifactService.load( | |
311 this.collection, | |
312 new Recommendation("manualpoints", ""), | |
313 "manualpoints", | |
314 locale, | |
315 new AsyncCallback<Artifact>() { | |
316 public void onFailure(Throwable caught) { | |
317 GWT.log("Creating manualpoint artifact failed!"); | |
318 } | |
319 public void onSuccess(Artifact artifact) { | |
320 GWT.log("Successfully created artifact."); | |
321 removeItem(standByLabel); | |
322 uuid = artifact.getUuid(); | |
323 createUI(); | |
324 } | |
325 }); | |
326 } | |
327 | |
328 | |
329 /** | |
330 * This method is called when the user aborts point editing. | |
331 * @param event The event. | |
332 */ | |
333 public void onClick(ClickEvent event) { | |
334 this.destroy(); | |
335 } | |
336 | |
337 | |
338 /** Simple record to store points. */ | |
339 public class PointRecord extends ListGridRecord { | |
340 protected static final String ATTRIBUTE_X = "X"; | |
341 protected static final String ATTRIBUTE_Y = "Y"; | |
342 | |
343 double x; | |
344 double y; | |
345 | |
346 private PointRecord() {;} | |
347 | |
348 public PointRecord(double x, double y) { | |
349 setX(x); | |
350 setY(y); | |
351 } | |
352 | |
353 public void setX(double x) { | |
354 this.x = x; | |
355 setAttribute(ATTRIBUTE_X, getX()); | |
356 } | |
357 | |
358 public void setY(double y) { | |
359 this.y = y; | |
360 setAttribute(ATTRIBUTE_Y, getY()); | |
361 } | |
362 | |
363 public double getX() { | |
364 return this.x; | |
365 } | |
366 | |
367 public double getY() { | |
368 return this.y; | |
369 } | |
370 } | |
371 | |
372 | |
373 // TODO cleanup. We need code similar to the following. | |
374 | |
375 /* | |
376 protected void updateCollection() { | |
377 final Config config = Config.getInstance(); | |
378 final String loc = config.getLocale(); | |
379 | |
380 GWT.log("PropertiesEditor.updateCollection via RPC now"); | |
381 | |
382 Settings s = settings; | |
383 collection.addSettings(this.tab.getOutputName(), s); | |
384 updater.update(collection, loc, new AsyncCallback<Collection>() { | |
385 public void onFailure(Throwable caught) { | |
386 GWT.log("Could not update collection attributes."); | |
387 SC.warn(MSG.getString(caught.getMessage())); | |
388 } | |
389 public void onSuccess(Collection collection) { | |
390 updateChartTab(); | |
391 } | |
392 }); | |
393 } | |
394 | |
395 /* | |
396 protected void updateChartTab() { | |
397 this.tab.updateChartInfo(); | |
398 this.tab.updateChartPanel(); | |
399 this.destroy(); | |
400 } | |
401 */ | |
402 | |
403 protected boolean isDialogValid() { | |
404 boolean valid = true; | |
405 /* | |
406 for (int i = 0; i < tabs.getNumTabs(); i++) { | |
407 Tab t = tabs.getTab(i); | |
408 Canvas container = t.getPane(); | |
409 Canvas[] children = container.getChildren(); | |
410 for (Canvas c: children) { | |
411 valid = validateCanvas(c); | |
412 if(!valid) { | |
413 return valid; | |
414 } | |
415 } | |
416 } | |
417 */ | |
418 return valid; | |
419 } | |
420 | |
421 | |
422 protected boolean validateCanvas(Canvas c) { | |
423 boolean valid = true; | |
424 if(c instanceof DynamicForm) { | |
425 DynamicForm f = (DynamicForm) c; | |
426 return !f.hasErrors(); | |
427 } | |
428 else if(c.getChildren().length > 0) { | |
429 for (Canvas child: c.getChildren()) { | |
430 valid = validateCanvas(child); | |
431 if(!valid) { | |
432 return valid; | |
433 } | |
434 } | |
435 } | |
436 return valid; | |
437 } | |
438 } | |
439 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |