Mercurial > dive4elements > river
view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartThemePanel.java @ 9580:839b2aa84dd0
minuend/subtrahend-UI-switch
author | gernotbelger |
---|---|
date | Tue, 08 Jan 2019 17:01:09 +0100 |
parents | 05405292a7ca |
children |
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde * Software engineering by Intevation GmbH * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.client.client.ui.chart; import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.services.FeedServiceAsync; import org.dive4elements.river.client.client.services.LoadArtifactService; import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync; import org.dive4elements.river.client.client.ui.CollectionView; import org.dive4elements.river.client.client.ui.IThemeRecordHandler; import org.dive4elements.river.client.client.ui.ThemePanel; import org.dive4elements.river.client.shared.model.Artifact; import org.dive4elements.river.client.shared.model.Data; import org.dive4elements.river.client.shared.model.DefaultArtifact; import org.dive4elements.river.client.shared.model.DefaultData; import org.dive4elements.river.client.shared.model.FacetRecord; import org.dive4elements.river.client.shared.model.OutputMode; import org.dive4elements.river.client.shared.model.Recommendation; import org.dive4elements.river.client.shared.model.Theme; import org.dive4elements.river.client.shared.model.ThemeList; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.types.ListGridFieldType; import com.smartgwt.client.util.SC; import com.smartgwt.client.widgets.grid.CellFormatter; import com.smartgwt.client.widgets.grid.ListGridField; import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.layout.VLayout; import com.smartgwt.client.widgets.menu.Menu; import com.smartgwt.client.widgets.menu.MenuItem; import com.smartgwt.client.widgets.menu.events.ClickHandler; import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent; /** * ThemePanel on the left in CollectionView. * Contains control widgets for "themes", which are plotted * in a diagram (chart). * * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class ChartThemePanel extends ThemePanel { /** Artifact Clone/Creation service. */ private final LoadArtifactServiceAsync loadService = GWT.create(LoadArtifactService.class); protected static final String GRID_FIELD_ACTIVE = "active"; protected static final String GRID_FIELD_NAME = "name"; protected static final String GRID_FIELD_ACTIONS = "actions"; protected final FeedServiceAsync feedService = GWT.create(org.dive4elements.river.client.client.services.FeedService.class); /** Constructor for a ChartThemePanel. * @param recordHandler */ public ChartThemePanel(final OutputMode mode, final CollectionView view, final IThemeRecordHandler recordHandler) { super(mode, view, recordHandler); initGrid(recordHandler); initLayout(); updateGrid(); } /** Creates Layout with theme list and navigation bar inside. */ protected VLayout createLayout() { final VLayout layout = new VLayout(); layout.setWidth100(); layout.setHeight100(); layout.addMember(this.list); layout.addMember(this.navigation); return layout; } /** * Initializes the layout of this panel. */ private void initLayout() { setWidth100(); setHeight100(); addChild(createLayout()); } /** * Initializes the components (columns) of the theme grid. * @param recordHandler */ protected void initGrid( final IThemeRecordHandler recordHandler ) { this.list.setCanEdit(true); this.list.setCanSort(false); this.list.setShowRecordComponents(false); this.list.setShowRecordComponentsByCell(true); this.list.setShowHeader(true); this.list.setShowHeaderContextMenu(false); this.list.setWidth100(); this.list.setHeight100(); this.list.addEditCompleteHandler(this); final ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20); active.setType(ListGridFieldType.BOOLEAN); final ListGridField name = new ListGridField(GRID_FIELD_NAME, this.MSG.chart_themepanel_header_themes()); name.setType(ListGridFieldType.TEXT); if( recordHandler instanceof CellFormatter) name.setCellFormatter((CellFormatter) recordHandler); this.list.setFields(active, name); } /** Set theme active/inactive. */ @Override public void activateTheme(final Theme theme, final boolean active) { theme.setActive(active ? 1 : 0); } /** Returns name of longitudinal section area facets. */ protected String getAreaFacetName() { return "longitudinal_section.area"; } /** Create the DataProvider ('Blackboard') key for a theme. */ public static String areaKey(final Theme theme) { return theme.getArtifact() + ":" + theme.getFacet() + ":" + theme.getIndex(); } /** * Tell an area artifact where to get the upper and lower curve from. * * @param artifact * UUID of area-artifact. */ public void feedTellArea(final String artifact, final Theme under, final Theme over, final boolean between) { Data[] feedData; if (over != null && under != null) { feedData = new Data[] { DefaultData.createSimpleStringData("area.curve_under", areaKey(under)), DefaultData.createSimpleStringData("area.curve_over", areaKey(over)), DefaultData.createSimpleStringData("area.name", over.getDescription() + " / " + under.getDescription()), DefaultData.createSimpleStringData("area.facet", getAreaFacetName()), DefaultData.createSimpleStringData("area.between", (between) ? "true" : "false") }; GWT.log("Have 'over' and 'under' curve"); } else if (over == null && under != null) { feedData = new Data[] { DefaultData.createSimpleStringData("area.curve_under", areaKey(under)), DefaultData.createSimpleStringData("area.name", under.getDescription() + " / " + this.MSG.getString("x_axis")), DefaultData.createSimpleStringData("area.facet", getAreaFacetName()), DefaultData.createSimpleStringData("area.between", (between) ? "true" : "false") }; GWT.log("Have 'under' curve only"); } else if (over != null && under == null) { feedData = new Data[] { DefaultData.createSimpleStringData("area.curve_over", areaKey(over)), DefaultData.createSimpleStringData("area.name", this.MSG.getString("x_axis") + " / " + over.getDescription()), DefaultData.createSimpleStringData("area.facet", getAreaFacetName()), DefaultData.createSimpleStringData("area.between", (between) ? "true" : "false") }; GWT.log("Have 'over' curve only"); } else { GWT.log("Missing Data for area painting."); return; } this.feedService.feed(Config.getInstance().getLocale(), new DefaultArtifact(artifact, "TODO:hash"), feedData, new AsyncCallback<Artifact>() { @Override public void onFailure(final Throwable caught) { GWT.log("Could not feed artifact (" + artifact + ") with area info: " + caught.getMessage()); SC.warn(ChartThemePanel.this.MSG.getString(caught.getMessage())); enable(); } @Override public void onSuccess(final Artifact fartifact) { GWT.log("Successfully set area params to " + artifact); requestRedraw(); updateCollection(); updateGrid(); enable(); } }); } /** * Create and parameterize a new area artifact. * * @param under * @param over * if null, against axis. * @param between * if true, ignore under/over order. */ public void createAreaArtifact(final Theme over, final Theme under, final boolean between) { final Config config = Config.getInstance(); final String locale = config.getLocale(); final Recommendation area = new Recommendation("area", "", "", null); // Set target out dynamically. area.setTargetOut(getMode().getName()); final Recommendation[] recommendations = new Recommendation[] { area }; this.loadService.loadMany(this.getCollection(), recommendations, null, // use individual factories. locale, new AsyncCallback<Artifact[]>() { @Override public void onFailure(final Throwable caught) { GWT.log("Failed, no area artifact: " + caught.getMessage()); enable(); // TODO i18n SC.warn("Failed, no area artifact: " + caught.getMessage()); } @Override public void onSuccess(final Artifact[] artifacts) { GWT.log("Success, created area artifact: " + artifacts[0].getUuid()); // Now, feed the artifact with the relevant data. feedTellArea(artifacts[0].getUuid(), under, over, between); } }); } /** * Return true if two themes are canditates for an area being * rendered between them. * TODO join with canArea, generalize to allow easier modification * in subclasses. */ protected boolean areAreaCompatible(final Theme a, final Theme b) { if (a.equals(b)) { return false; } if (a.getFacet().equals("w_differences") && b.getFacet().equals("w_differences")) { return true; } if (a.getFacet().equals("longitudinal_section.w") || a.getFacet().equals("other.wqkms.w") || a.getFacet().equals("other.wqkms") || a.getFacet().equals("discharge_longitudinal_section.w") || a.getFacet().equals("discharge_longitudinal_section.c") || a.getFacet().equals("other.wkms")) { return b.getFacet().equals("longitudinal_section.w") || b.getFacet().equals("other.wqkms") || b.getFacet().equals("other.wqkms.w") || b.getFacet().equals("discharge_longitudinal_section.w") || b.getFacet().equals("discharge_longitudinal_section.c") || b.getFacet().equals("other.wkms"); } else if (a.getFacet().equals("longitudinal_section.q") || a.getFacet().equals("discharge_longitudinal_section.q") || a.getFacet().equals("other.wqkms.q")) { return b.getFacet().equals("longitudinal_section.q") || b.getFacet().equals("discharge_longitudinal_section.q") || b.getFacet().equals("other.wqkms.q"); } return false; } /** * True if context menu should contain 'create area' submenu on * this theme. */ protected boolean canArea(final Theme a) { return a.getFacet().equals("longitudinal_section.q") || a.getFacet().equals("longitudinal_section.w") || a.getFacet().equals("discharge_longitudinal_section.w") || a.getFacet().equals("discharge_longitudinal_section.q") || a.getFacet().equals("discharge_longitudinal_section.c") || a.getFacet().startsWith("other.wqkms") || a.getFacet().equals("other.wkms") || a.getFacet().equals("w_differences"); } /** Attach menu/item to open editor for Manual Points. */ protected void attachManualPointsMenu(final Menu menu) { menu.addItem(createSeparator()); final MenuItem editManualPoints = new MenuItem(this.MSG.editpoints()); editManualPoints.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { if (ChartThemePanel.this.mode.getName().equals("historical_discharge")) { new ManualDatePointsEditor(ChartThemePanel.this.view.getCollection(), ChartThemePanel.this.redrawRequestHandlers.get(0), ChartThemePanel.this.mode.getName()).show(); } else { new ManualPointsEditor(ChartThemePanel.this.view.getCollection(), ChartThemePanel.this.redrawRequestHandlers.get(0), ChartThemePanel.this.mode.getName()).show(); } } }); menu.addItem(editManualPoints); } /** * Include area specific menu items and manual point editor, depending * on facet. */ @Override protected Menu getSingleContextMenu(final ListGridRecord[] records) { final Menu menu = super.getSingleContextMenu(records); final Theme facetTheme = ((FacetRecord) records[0]).getTheme(); if (!canArea(facetTheme)) { if (facetTheme.getFacet().endsWith("manualpoints")) { attachManualPointsMenu(menu); return menu; } else { return menu; } } menu.addItem(createSeparator()); final MenuItem areaMenuItem = new MenuItem(this.MSG.chart_themepanel_new_area()); final Menu areaMenu = new Menu(); final ThemeList themes = getThemeList(); final int nThemes = themes.getThemeCount(); // Create the "under..." submenu. final MenuItem underMenuItem = new MenuItem(this.MSG.chart_themepanel_area_under()); final Menu underMenu = new Menu(); for (int i = 0; i < nThemes; i++) { final Theme theme = themes.getThemeAt(i + 1); if (theme.getVisible() == 0) { continue; } if (!areAreaCompatible(facetTheme, theme)) { continue; } final MenuItem againster = new MenuItem(theme.getDescription()); underMenu.addItem(againster); againster.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { disable(); createAreaArtifact(theme, facetTheme, false); } }); } // Create the "over..." submenu. final MenuItem overMenuItem = new MenuItem(this.MSG.chart_themepanel_area_over()); final Menu overMenu = new Menu(); for (int i = 0; i < nThemes; i++) { final Theme theme = themes.getThemeAt(i + 1); if (theme.getVisible() == 0) { continue; } if (!areAreaCompatible(facetTheme, theme)) { continue; } final MenuItem againster = new MenuItem(theme.getDescription()); overMenu.addItem(againster); againster.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { disable(); createAreaArtifact(facetTheme, theme, false); } }); } overMenu.addItem(createSeparator()); final MenuItem againstAxis = new MenuItem(this.MSG.getString("x_axis")); againstAxis.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { disable(); createAreaArtifact(null, facetTheme, false); } }); overMenu.addItem(againstAxis); // Create the "between..." submenu. final MenuItem betweenMenuItem = new MenuItem(this.MSG.chart_themepanel_area_between()); final Menu betweenMenu = new Menu(); for (int i = 0; i < nThemes; i++) { final Theme theme = themes.getThemeAt(i + 1); if (theme.getVisible() == 0) { continue; } if (!areAreaCompatible(facetTheme, theme)) { continue; } final MenuItem againster = new MenuItem(theme.getDescription()); betweenMenu.addItem(againster); againster.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { disable(); createAreaArtifact(facetTheme, theme, true); } }); } betweenMenu.addItem(createSeparator()); betweenMenu.addItem(againstAxis); overMenuItem.setSubmenu(overMenu); underMenuItem.setSubmenu(underMenu); betweenMenuItem.setSubmenu(betweenMenu); areaMenu.addItem(betweenMenuItem); areaMenu.addItem(overMenuItem); areaMenu.addItem(underMenuItem); areaMenu.addItem(createSeparator()); final MenuItem standAloneAgainstAxis = new MenuItem(this.MSG.getString("against_x_axis")); standAloneAgainstAxis.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { disable(); createAreaArtifact(null, facetTheme, false); } }); areaMenu.addItem(standAloneAgainstAxis); areaMenuItem.setSubmenu(areaMenu); menu.addItem(areaMenuItem); return menu; } }