comparison gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartThemePanel.java @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartThemePanel.java@821a02bbfb4e
children 172338b1407f
comparison
equal deleted inserted replaced
5837:d9901a08d0a6 5838:5aa05a7a34b7
1 package org.dive4elements.river.client.client.ui.chart;
2
3 import com.google.gwt.core.client.GWT;
4 import com.google.gwt.user.client.rpc.AsyncCallback;
5
6 import com.smartgwt.client.types.ListGridFieldType;
7 import com.smartgwt.client.util.SC;
8 import com.smartgwt.client.widgets.grid.ListGridField;
9 import com.smartgwt.client.widgets.grid.ListGridRecord;
10 import com.smartgwt.client.widgets.layout.VLayout;
11 import com.smartgwt.client.widgets.menu.Menu;
12 import com.smartgwt.client.widgets.menu.MenuItem;
13 import com.smartgwt.client.widgets.menu.events.ClickHandler;
14 import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;
15
16 import org.dive4elements.river.client.client.Config;
17 import org.dive4elements.river.client.client.FLYSConstants;
18 import org.dive4elements.river.client.client.services.FeedServiceAsync;
19 import org.dive4elements.river.client.client.services.LoadArtifactService;
20 import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
21 import org.dive4elements.river.client.client.ui.CollectionView;
22 import org.dive4elements.river.client.client.ui.ThemePanel;
23 import org.dive4elements.river.client.shared.model.Artifact;
24 import org.dive4elements.river.client.shared.model.Data;
25 import org.dive4elements.river.client.shared.model.DefaultArtifact;
26 import org.dive4elements.river.client.shared.model.DefaultData;
27 import org.dive4elements.river.client.shared.model.FacetRecord;
28 import org.dive4elements.river.client.shared.model.OutputMode;
29 import org.dive4elements.river.client.shared.model.Recommendation;
30 import org.dive4elements.river.client.shared.model.Theme;
31 import org.dive4elements.river.client.shared.model.ThemeList;
32
33
34 /**
35 * ThemePanel on the left in CollectionView.
36 * Contains control widgets for "themes", which are plotted in a diagram (chart).
37 *
38 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
39 */
40 public class ChartThemePanel extends ThemePanel {
41 /** Artifact Clone/Creation service. */
42 protected LoadArtifactServiceAsync loadService =
43 GWT.create(LoadArtifactService.class);
44
45 /** The interface that provides i18n messages. */
46 protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
47
48 public static final String GRID_FIELD_ACTIVE = "active";
49 public static final String GRID_FIELD_NAME = "name";
50 public static final String GRID_FIELD_ACTIONS = "actions";
51
52 FeedServiceAsync feedService = GWT.create(
53 org.dive4elements.river.client.client.services.FeedService.class);
54
55
56 /** Constructor for a ChartThemePanel. */
57 public ChartThemePanel(
58 OutputMode mode,
59 CollectionView view
60 ) {
61 super(mode, view);
62
63 initGrid();
64 initLayout();
65
66 updateGrid();
67 }
68
69
70 /** Creates Layout with theme list and navigation bar inside. */
71 protected VLayout createLayout() {
72 VLayout layout = new VLayout();
73 layout.setWidth100();
74 layout.setHeight100();
75
76 layout.addMember(list);
77 layout.addMember(navigation);
78
79 return layout;
80 }
81
82
83 /**
84 * Initializes the layout of this panel.
85 */
86 protected void initLayout() {
87 setWidth100();
88 setHeight100();
89
90 addChild(createLayout());
91 }
92
93
94 /**
95 * Initializes the components (columns) of the theme grid.
96 */
97 protected void initGrid() {
98 list.setCanEdit(true);
99 list.setCanSort(false);
100 list.setShowRecordComponents(false);
101 list.setShowRecordComponentsByCell(true);
102 list.setShowHeader(true);
103 list.setShowHeaderContextMenu(false);
104 list.setWidth100();
105 list.setHeight100();
106
107 list.addEditCompleteHandler(this);
108
109 ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20);
110 active.setType(ListGridFieldType.BOOLEAN);
111
112 ListGridField name = new ListGridField(
113 GRID_FIELD_NAME, MSG.chart_themepanel_header_themes());
114 name.setType(ListGridFieldType.TEXT);
115
116 list.setFields(active, name);
117 }
118
119
120 /** Set theme active/inactive. */
121 @Override
122 public void activateTheme(Theme theme, boolean active) {
123 theme.setActive(active ? 1 : 0);
124 }
125
126
127 /** Returns name of longitudinal section area facets. */
128 protected String getAreaFacetName() {
129 return "longitudinal_section.area";
130 }
131
132
133 /** Create the DataProvider ('Blackboard') key for a theme. */
134 public static String areaKey(Theme theme) {
135 return theme.getArtifact() + ":" + theme.getFacet() + ":"
136 + theme.getIndex();
137 }
138
139
140 /**
141 * Tell an area artifact where to get the upper and lower curve from.
142 * @param artifact UUID of area-artifact.
143 */
144 public void feedTellArea(
145 final String artifact,
146 Theme under,
147 Theme over,
148 boolean between
149 ) {
150 Data[] feedData;
151
152 if (over != null && under != null) {
153 feedData = new Data[] {
154 DefaultData.createSimpleStringData("area.curve_under",
155 areaKey(under)),
156 DefaultData.createSimpleStringData("area.curve_over",
157 areaKey(over)),
158 DefaultData.createSimpleStringData("area.name",
159 over.getDescription() + " / " + under.getDescription()),
160 DefaultData.createSimpleStringData("area.facet",
161 getAreaFacetName()),
162 DefaultData.createSimpleStringData("area.between",
163 (between)? "true" : "false")
164 };
165 GWT.log("Have 'over' and 'under' curve");
166 }
167 else if (over == null && under != null) {
168 feedData = new Data[] {
169 DefaultData.createSimpleStringData("area.curve_under",
170 areaKey(under)),
171 DefaultData.createSimpleStringData("area.name",
172 under.getDescription() + " / " + MSG.getString("x_axis")),
173 DefaultData.createSimpleStringData("area.facet",
174 getAreaFacetName()),
175 DefaultData.createSimpleStringData("area.between",
176 (between)? "true" : "false")
177 };
178 GWT.log("Have 'under' curve only");
179 }
180 else if (over != null && under == null) {
181 feedData = new Data[] {
182 DefaultData.createSimpleStringData("area.curve_over",
183 areaKey(over)),
184 DefaultData.createSimpleStringData("area.name",
185 MSG.getString("x_axis") + " / " + over.getDescription()),
186 DefaultData.createSimpleStringData("area.facet",
187 getAreaFacetName()),
188 DefaultData.createSimpleStringData("area.between",
189 (between)? "true" : "false")
190 };
191 GWT.log("Have 'over' curve only");
192 }
193 else {
194 GWT.log("Missing Data for area painting.");
195 return;
196 }
197
198 feedService.feed(
199 Config.getInstance().getLocale(),
200 new DefaultArtifact(artifact, "TODO:hash"),
201 feedData,
202 new AsyncCallback<Artifact>() {
203 @Override
204 public void onFailure(Throwable caught) {
205 GWT.log("Could not feed artifact (" + artifact
206 + ") with area info: " + caught.getMessage());
207 SC.warn(MSG.getString(caught.getMessage()));
208 enable();
209 }
210 @Override
211 public void onSuccess(Artifact fartifact) {
212 GWT.log("Successfully set area params to " + artifact);
213 requestRedraw();
214 updateCollection();
215 updateGrid();
216 enable();
217 }
218 });
219 }
220
221
222 /**
223 * Create and parameterize a new area artifact.
224 * @param under
225 * @param over if null, against axis.
226 * @param between if true, ignore under/over order.
227 */
228 public void createAreaArtifact(
229 final Theme over,
230 final Theme under,
231 final boolean between
232 ) {
233 Config config = Config.getInstance();
234 String locale = config.getLocale();
235
236 Recommendation area = new Recommendation(
237 "area",
238 "",
239 "",
240 null);
241 Recommendation[] recommendations = new Recommendation[] {area};
242
243 loadService.loadMany(
244 this.getCollection(),
245 recommendations,
246 null, //use individual factories.
247 locale,
248 new AsyncCallback<Artifact[]>() {
249 @Override
250 public void onFailure(Throwable caught) {
251 GWT.log("Failed, no area artifact: " + caught.getMessage());
252 enable();
253 // TODO i18n
254 SC.warn("Failed, no area artifact: " + caught.getMessage());
255 }
256 @Override
257 public void onSuccess(Artifact[] artifacts) {
258 GWT.log("Success, created area artifact: "
259 + artifacts[0].getUuid());
260 // Now, feed the artifact with the relevant data.
261 feedTellArea(artifacts[0].getUuid(), under, over, between);
262 }
263 }
264 );
265 }
266
267
268 /**
269 * Return true if two themes are canditates for an area being
270 * rendered between them.
271 * TODO join with canArea, generalize to allow easier modification
272 * in subclasses.
273 */
274 protected boolean areAreaCompatible(Theme a, Theme b) {
275 if (a.equals(b)) {
276 return false;
277 }
278 if (a.getFacet().equals("longitudinal_section.w") ||
279 a.getFacet().equals("other.wkms")) {
280 return b.getFacet().equals("longitudinal_section.w")
281 || b.getFacet().equals("other.wkms");
282 }
283 else if (a.getFacet().equals("longitudinal_section.q")) {
284 return b.getFacet().equals("longitudinal_section.q");
285 }
286 return false;
287 }
288
289
290 /**
291 * True if context menu should contain 'create area' submenu on
292 * this theme.
293 */
294 protected boolean canArea(Theme a) {
295 return a.getFacet().equals("longitudinal_section.q")
296 || a.getFacet().equals("longitudinal_section.w")
297 || a.getFacet().equals("other.wkms");
298 }
299
300
301 /** Attach menu/item to open editor for Manual Points. */
302 protected void attachManualPointsMenu(Menu menu) {
303 menu.addItem(createSeparator());
304 MenuItem editManualPoints = new MenuItem(MSG.editpoints());
305
306 editManualPoints.addClickHandler(new ClickHandler() {
307 @Override
308 public void onClick(MenuItemClickEvent evt) {
309 if(mode.getName().equals("historical_discharge")) {
310 new ManualDatePointsEditor(view.getCollection(),
311 redrawRequestHandlers.get(0),
312 mode.getName()).show();
313 }
314 else {
315 new ManualPointsEditor(view.getCollection(),
316 redrawRequestHandlers.get(0),
317 mode.getName()).show();
318 }
319 }
320 });
321 menu.addItem(editManualPoints);
322 }
323
324
325 /**
326 * Include area specific menu items and manual point editor, depending
327 * on facet.
328 */
329 @Override
330 protected Menu getSingleContextMenu(final ListGridRecord[] records) {
331 Menu menu = super.getSingleContextMenu(records);
332
333 final Theme facetTheme = ((FacetRecord)records[0]).getTheme();
334
335 if (!canArea(facetTheme)) {
336 if (facetTheme.getFacet().endsWith("manualpoints")) {
337 attachManualPointsMenu(menu);
338 return menu;
339 }
340 else {
341 return menu;
342 }
343 }
344
345 menu.addItem(createSeparator());
346
347 MenuItem areaMenuItem = new MenuItem(MSG.chart_themepanel_new_area());
348 Menu areaMenu = new Menu();
349
350 ThemeList themes = getThemeList();
351 int nThemes = themes.getThemeCount();
352
353 // Create the "under..." submenu.
354 MenuItem underMenuItem = new MenuItem(MSG.chart_themepanel_area_under());
355 Menu underMenu = new Menu();
356 for (int i = 0; i < nThemes; i++) {
357 final Theme theme = themes.getThemeAt(i+1);
358
359 if (theme.getVisible() == 0) {
360 continue;
361 }
362
363 if (!areAreaCompatible(facetTheme, theme)) {
364 continue;
365 }
366
367 MenuItem againster = new MenuItem(theme.getDescription());
368 underMenu.addItem(againster);
369
370 againster.addClickHandler(new ClickHandler() {
371 @Override
372 public void onClick(MenuItemClickEvent evt) {
373 disable();
374 createAreaArtifact(theme, facetTheme, false);
375 }
376 });
377 }
378
379 // Create the "over..." submenu.
380 MenuItem overMenuItem = new MenuItem(MSG.chart_themepanel_area_over());
381 Menu overMenu = new Menu();
382 for (int i = 0; i < nThemes; i++) {
383 final Theme theme = themes.getThemeAt(i+1);
384 if (theme.getVisible() == 0) {
385 continue;
386 }
387 if (!areAreaCompatible(facetTheme, theme)) {
388 continue;
389 }
390 MenuItem againster = new MenuItem(theme.getDescription());
391 overMenu.addItem(againster);
392
393 againster.addClickHandler(new ClickHandler() {
394 @Override
395 public void onClick(MenuItemClickEvent evt) {
396 disable();
397 createAreaArtifact(facetTheme, theme, false);
398 }
399 });
400 }
401 overMenu.addItem(createSeparator());
402 MenuItem againstAxis = new MenuItem(MSG.getString("x_axis"));
403 againstAxis.addClickHandler(new ClickHandler() {
404 @Override
405 public void onClick(MenuItemClickEvent evt) {
406 disable();
407 createAreaArtifact(null, facetTheme, false);
408 }
409 });
410 overMenu.addItem(againstAxis);
411
412 // Create the "between..." submenu.
413 MenuItem betweenMenuItem = new MenuItem(MSG.chart_themepanel_area_between());
414 Menu betweenMenu = new Menu();
415 for (int i = 0; i < nThemes; i++) {
416 final Theme theme = themes.getThemeAt(i+1);
417 if (theme.getVisible() == 0) {
418 continue;
419 }
420 if (!areAreaCompatible(facetTheme, theme)) {
421 continue;
422 }
423 MenuItem againster = new MenuItem(theme.getDescription());
424 betweenMenu.addItem(againster);
425
426 againster.addClickHandler(new ClickHandler() {
427 @Override
428 public void onClick(MenuItemClickEvent evt) {
429 disable();
430 createAreaArtifact(facetTheme, theme, true);
431 }
432 });
433 }
434 betweenMenu.addItem(createSeparator());
435 betweenMenu.addItem(againstAxis);
436
437 overMenuItem.setSubmenu(overMenu);
438 underMenuItem.setSubmenu(underMenu);
439 betweenMenuItem.setSubmenu(betweenMenu);
440
441 areaMenu.addItem(betweenMenuItem);
442 areaMenu.addItem(overMenuItem);
443 areaMenu.addItem(underMenuItem);
444 areaMenu.addItem(createSeparator());
445 MenuItem standAloneAgainstAxis = new MenuItem(MSG.getString("against_x_axis"));
446 standAloneAgainstAxis.addClickHandler(new ClickHandler() {
447 @Override
448 public void onClick(MenuItemClickEvent evt) {
449 disable();
450 createAreaArtifact(null, facetTheme, false);
451 }
452 });
453 areaMenu.addItem(standAloneAgainstAxis);
454
455 areaMenuItem.setSubmenu(areaMenu);
456 menu.addItem(areaMenuItem);
457
458 return menu;
459 }
460 }
461 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org