teichmann@5835: package org.dive4elements.river.client.client.ui.chart; ingo@523: ingo@523: import com.google.gwt.core.client.GWT; felix@1456: import com.google.gwt.user.client.rpc.AsyncCallback; ingo@523: felix@1456: import com.smartgwt.client.types.ListGridFieldType; christian@4568: import com.smartgwt.client.util.SC; felix@1456: import com.smartgwt.client.widgets.grid.ListGridField; felix@1456: import com.smartgwt.client.widgets.grid.ListGridRecord; felix@1456: import com.smartgwt.client.widgets.layout.VLayout; felix@1456: import com.smartgwt.client.widgets.menu.Menu; felix@1456: import com.smartgwt.client.widgets.menu.MenuItem; christian@4568: import com.smartgwt.client.widgets.menu.events.ClickHandler; felix@1456: import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent; felix@1456: teichmann@5835: import org.dive4elements.river.client.client.Config; teichmann@5835: import org.dive4elements.river.client.client.FLYSConstants; teichmann@5835: import org.dive4elements.river.client.client.services.FeedServiceAsync; teichmann@5835: import org.dive4elements.river.client.client.services.LoadArtifactService; teichmann@5835: import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync; teichmann@5835: import org.dive4elements.river.client.client.ui.CollectionView; teichmann@5835: import org.dive4elements.river.client.client.ui.ThemePanel; teichmann@5835: import org.dive4elements.river.client.shared.model.Artifact; teichmann@5835: import org.dive4elements.river.client.shared.model.Data; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultArtifact; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultData; teichmann@5835: import org.dive4elements.river.client.shared.model.FacetRecord; teichmann@5835: import org.dive4elements.river.client.shared.model.OutputMode; teichmann@5835: import org.dive4elements.river.client.shared.model.Recommendation; teichmann@5835: import org.dive4elements.river.client.shared.model.Theme; teichmann@5835: import org.dive4elements.river.client.shared.model.ThemeList; ingo@523: felix@1456: ingo@523: /** felix@1430: * ThemePanel on the left in CollectionView. felix@1430: * Contains control widgets for "themes", which are plotted in a diagram (chart). felix@1430: * ingo@523: * @author Ingo Weinzierl ingo@523: */ ingo@805: public class ChartThemePanel extends ThemePanel { felix@1456: /** Artifact Clone/Creation service. */ felix@1456: protected LoadArtifactServiceAsync loadService = felix@1456: GWT.create(LoadArtifactService.class); ingo@805: ingo@523: /** The interface that provides i18n messages. */ felix@858: protected FLYSConstants MSG = GWT.create(FLYSConstants.class); ingo@526: felix@854: public static final String GRID_FIELD_ACTIVE = "active"; felix@854: public static final String GRID_FIELD_NAME = "name"; felix@854: public static final String GRID_FIELD_ACTIONS = "actions"; ingo@523: felix@854: FeedServiceAsync feedService = GWT.create( teichmann@5835: org.dive4elements.river.client.client.services.FeedService.class); ingo@523: felix@1456: felix@1517: /** Constructor for a ChartThemePanel. */ felix@1474: public ChartThemePanel( felix@1474: OutputMode mode, felix@1474: CollectionView view felix@1474: ) { felix@1555: super(mode, view); ingo@523: ingo@523: initGrid(); ingo@523: initLayout(); ingo@523: ingo@523: updateGrid(); ingo@523: } ingo@523: ingo@523: felix@1514: /** Creates Layout with theme list and navigation bar inside. */ felix@1430: protected VLayout createLayout() { felix@1430: VLayout layout = new VLayout(); felix@1430: layout.setWidth100(); felix@1430: layout.setHeight100(); felix@1430: felix@1430: layout.addMember(list); felix@1430: layout.addMember(navigation); felix@1430: felix@1430: return layout; felix@1430: } felix@1430: felix@1456: ingo@523: /** ingo@523: * Initializes the layout of this panel. ingo@523: */ ingo@523: protected void initLayout() { ingo@523: setWidth100(); ingo@523: setHeight100(); ingo@523: felix@1430: addChild(createLayout()); ingo@523: } ingo@523: ingo@523: ingo@523: /** ingo@523: * Initializes the components (columns) of the theme grid. ingo@523: */ ingo@523: protected void initGrid() { ingo@523: list.setCanEdit(true); ingo@523: list.setCanSort(false); felix@858: list.setShowRecordComponents(false); ingo@523: list.setShowRecordComponentsByCell(true); ingo@523: list.setShowHeader(true); ingo@523: list.setShowHeaderContextMenu(false); ingo@523: list.setWidth100(); ingo@523: list.setHeight100(); ingo@523: ingo@523: list.addEditCompleteHandler(this); ingo@523: ingo@1288: ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20); ingo@523: active.setType(ListGridFieldType.BOOLEAN); ingo@523: ingo@523: ListGridField name = new ListGridField( ingo@523: GRID_FIELD_NAME, MSG.chart_themepanel_header_themes()); ingo@523: name.setType(ListGridFieldType.TEXT); ingo@523: felix@858: list.setFields(active, name); ingo@523: } ingo@523: ingo@523: felix@1460: /** Set theme active/inactive. */ ingo@805: @Override ingo@805: public void activateTheme(Theme theme, boolean active) { ingo@805: theme.setActive(active ? 1 : 0); ingo@527: } felix@1456: felix@1456: felix@1457: /** Returns name of longitudinal section area facets. */ felix@1457: protected String getAreaFacetName() { felix@1457: return "longitudinal_section.area"; felix@1457: } felix@1457: felix@1517: felix@1517: /** Create the DataProvider ('Blackboard') key for a theme. */ felix@1514: public static String areaKey(Theme theme) { felix@1514: return theme.getArtifact() + ":" + theme.getFacet() + ":" felix@1514: + theme.getIndex(); felix@1514: } felix@1514: felix@1457: felix@1456: /** felix@1456: * Tell an area artifact where to get the upper and lower curve from. felix@1462: * @param artifact UUID of area-artifact. felix@1456: */ felix@1462: public void feedTellArea( felix@1462: final String artifact, felix@1462: Theme under, felix@1462: Theme over, felix@1462: boolean between felix@1462: ) { felix@1456: Data[] feedData; felix@1456: felix@1456: if (over != null && under != null) { felix@1456: feedData = new Data[] { felix@1456: DefaultData.createSimpleStringData("area.curve_under", felix@1514: areaKey(under)), felix@1456: DefaultData.createSimpleStringData("area.curve_over", felix@1514: areaKey(over)), felix@1456: DefaultData.createSimpleStringData("area.name", felix@1456: over.getDescription() + " / " + under.getDescription()), felix@1456: DefaultData.createSimpleStringData("area.facet", felix@1462: getAreaFacetName()), felix@1462: DefaultData.createSimpleStringData("area.between", felix@1462: (between)? "true" : "false") felix@1456: }; felix@1517: GWT.log("Have 'over' and 'under' curve"); felix@1456: } felix@1456: else if (over == null && under != null) { felix@1456: feedData = new Data[] { felix@1456: DefaultData.createSimpleStringData("area.curve_under", felix@1514: areaKey(under)), felix@1456: DefaultData.createSimpleStringData("area.name", felix@1456: under.getDescription() + " / " + MSG.getString("x_axis")), felix@1456: DefaultData.createSimpleStringData("area.facet", felix@1462: getAreaFacetName()), felix@1462: DefaultData.createSimpleStringData("area.between", felix@1462: (between)? "true" : "false") felix@1456: }; felix@1517: GWT.log("Have 'under' curve only"); felix@1456: } felix@1456: else if (over != null && under == null) { felix@1456: feedData = new Data[] { felix@1456: DefaultData.createSimpleStringData("area.curve_over", felix@1514: areaKey(over)), felix@1456: DefaultData.createSimpleStringData("area.name", felix@1456: MSG.getString("x_axis") + " / " + over.getDescription()), felix@1456: DefaultData.createSimpleStringData("area.facet", felix@1462: getAreaFacetName()), felix@1462: DefaultData.createSimpleStringData("area.between", felix@1462: (between)? "true" : "false") felix@1456: }; felix@1517: GWT.log("Have 'over' curve only"); felix@1456: } felix@1456: else { felix@1456: GWT.log("Missing Data for area painting."); felix@1456: return; felix@1456: } felix@1456: felix@1456: feedService.feed( felix@1456: Config.getInstance().getLocale(), felix@1456: new DefaultArtifact(artifact, "TODO:hash"), felix@1456: feedData, felix@1456: new AsyncCallback() { christian@4568: @Override felix@1456: public void onFailure(Throwable caught) { felix@1456: GWT.log("Could not feed artifact (" + artifact felix@1456: + ") with area info: " + caught.getMessage()); felix@1456: SC.warn(MSG.getString(caught.getMessage())); felix@1456: enable(); felix@1456: } christian@4568: @Override felix@1514: public void onSuccess(Artifact fartifact) { felix@1456: GWT.log("Successfully set area params to " + artifact); felix@1456: requestRedraw(); felix@1456: updateCollection(); felix@1456: updateGrid(); felix@1456: enable(); felix@1456: } felix@1456: }); felix@1456: } felix@1456: felix@1456: felix@1456: /** felix@1456: * Create and parameterize a new area artifact. felix@1456: * @param under felix@1462: * @param over if null, against axis. felix@1462: * @param between if true, ignore under/over order. felix@1456: */ felix@1456: public void createAreaArtifact( felix@1462: final Theme over, felix@1462: final Theme under, felix@1462: final boolean between felix@1456: ) { felix@1456: Config config = Config.getInstance(); felix@1456: String locale = config.getLocale(); felix@1456: felix@1456: Recommendation area = new Recommendation( felix@1456: "area", felix@1456: "", felix@1456: "", felix@1456: null); felix@1456: Recommendation[] recommendations = new Recommendation[] {area}; felix@1456: felix@1456: loadService.loadMany( felix@1555: this.getCollection(), felix@1456: recommendations, felix@1456: null, //use individual factories. felix@1456: locale, felix@1456: new AsyncCallback() { christian@4568: @Override felix@1456: public void onFailure(Throwable caught) { felix@1456: GWT.log("Failed, no area artifact: " + caught.getMessage()); felix@1456: enable(); christian@4568: // TODO i18n christian@4568: SC.warn("Failed, no area artifact: " + caught.getMessage()); felix@1456: } christian@4568: @Override felix@1456: public void onSuccess(Artifact[] artifacts) { felix@1456: GWT.log("Success, created area artifact: " felix@1456: + artifacts[0].getUuid()); felix@1456: // Now, feed the artifact with the relevant data. felix@1462: feedTellArea(artifacts[0].getUuid(), under, over, between); felix@1456: } felix@1456: } felix@1517: ); felix@1456: } felix@1456: sascha@2905: felix@1456: /** felix@1456: * Return true if two themes are canditates for an area being felix@1456: * rendered between them. felix@1456: * TODO join with canArea, generalize to allow easier modification felix@1456: * in subclasses. felix@1456: */ felix@1456: protected boolean areAreaCompatible(Theme a, Theme b) { felix@1456: if (a.equals(b)) { felix@1456: return false; felix@1456: } felix@1460: if (a.getFacet().equals("longitudinal_section.w") || felix@1460: a.getFacet().equals("other.wkms")) { felix@1460: return b.getFacet().equals("longitudinal_section.w") felix@1460: || b.getFacet().equals("other.wkms"); felix@1456: } felix@1456: else if (a.getFacet().equals("longitudinal_section.q")) { felix@1456: return b.getFacet().equals("longitudinal_section.q"); felix@1456: } felix@1456: return false; felix@1456: } felix@1456: felix@1456: felix@1456: /** felix@1456: * True if context menu should contain 'create area' submenu on felix@1456: * this theme. felix@1456: */ felix@1456: protected boolean canArea(Theme a) { felix@1456: return a.getFacet().equals("longitudinal_section.q") felix@1460: || a.getFacet().equals("longitudinal_section.w") felix@1460: || a.getFacet().equals("other.wkms"); felix@1456: } felix@1456: felix@1456: felix@1559: /** Attach menu/item to open editor for Manual Points. */ felix@1559: protected void attachManualPointsMenu(Menu menu) { felix@1559: menu.addItem(createSeparator()); felix@1559: MenuItem editManualPoints = new MenuItem(MSG.editpoints()); sascha@2905: felix@1559: editManualPoints.addClickHandler(new ClickHandler() { christian@4568: @Override felix@1559: public void onClick(MenuItemClickEvent evt) { raimund@2483: if(mode.getName().equals("historical_discharge")) { raimund@2483: new ManualDatePointsEditor(view.getCollection(), raimund@2483: redrawRequestHandlers.get(0), raimund@2483: mode.getName()).show(); raimund@2483: } raimund@2483: else { raimund@2483: new ManualPointsEditor(view.getCollection(), raimund@2483: redrawRequestHandlers.get(0), raimund@2483: mode.getName()).show(); raimund@2483: } felix@1559: } felix@1559: }); felix@1559: menu.addItem(editManualPoints); felix@1559: } felix@1559: felix@1559: felix@1456: /** felix@1559: * Include area specific menu items and manual point editor, depending felix@1559: * on facet. felix@1456: */ christian@4568: @Override felix@1456: protected Menu getSingleContextMenu(final ListGridRecord[] records) { felix@1456: Menu menu = super.getSingleContextMenu(records); felix@1456: felix@1456: final Theme facetTheme = ((FacetRecord)records[0]).getTheme(); christian@4568: felix@1456: if (!canArea(facetTheme)) { felix@1607: if (facetTheme.getFacet().endsWith("manualpoints")) { felix@1559: attachManualPointsMenu(menu); felix@1559: return menu; felix@1559: } felix@1559: else { felix@1559: return menu; felix@1559: } felix@1456: } sascha@2905: felix@1456: menu.addItem(createSeparator()); felix@1456: felix@1456: MenuItem areaMenuItem = new MenuItem(MSG.chart_themepanel_new_area()); felix@1456: Menu areaMenu = new Menu(); felix@1456: felix@1456: ThemeList themes = getThemeList(); felix@1456: int nThemes = themes.getThemeCount(); felix@1456: felix@1517: // Create the "under..." submenu. felix@1456: MenuItem underMenuItem = new MenuItem(MSG.chart_themepanel_area_under()); felix@1456: Menu underMenu = new Menu(); felix@1456: for (int i = 0; i < nThemes; i++) { felix@1456: final Theme theme = themes.getThemeAt(i+1); felix@2442: felix@2442: if (theme.getVisible() == 0) { felix@2442: continue; felix@2442: } felix@2442: felix@1456: if (!areAreaCompatible(facetTheme, theme)) { felix@1456: continue; felix@1456: } felix@2442: felix@1456: MenuItem againster = new MenuItem(theme.getDescription()); felix@1456: underMenu.addItem(againster); felix@1456: felix@1456: againster.addClickHandler(new ClickHandler() { christian@4568: @Override felix@1456: public void onClick(MenuItemClickEvent evt) { felix@1456: disable(); felix@1456: createAreaArtifact(theme, facetTheme, false); felix@1456: } felix@1456: }); felix@1456: } felix@1456: felix@1517: // Create the "over..." submenu. felix@1456: MenuItem overMenuItem = new MenuItem(MSG.chart_themepanel_area_over()); felix@1456: Menu overMenu = new Menu(); felix@1456: for (int i = 0; i < nThemes; i++) { felix@1456: final Theme theme = themes.getThemeAt(i+1); felix@2442: if (theme.getVisible() == 0) { felix@2442: continue; felix@2442: } felix@1456: if (!areAreaCompatible(facetTheme, theme)) { felix@1456: continue; felix@1456: } felix@1456: MenuItem againster = new MenuItem(theme.getDescription()); felix@1456: overMenu.addItem(againster); felix@1456: felix@1456: againster.addClickHandler(new ClickHandler() { christian@4568: @Override felix@1456: public void onClick(MenuItemClickEvent evt) { felix@1456: disable(); felix@1456: createAreaArtifact(facetTheme, theme, false); felix@1456: } felix@1456: }); felix@1456: } felix@1456: overMenu.addItem(createSeparator()); felix@1456: MenuItem againstAxis = new MenuItem(MSG.getString("x_axis")); felix@1456: againstAxis.addClickHandler(new ClickHandler() { christian@4568: @Override felix@1456: public void onClick(MenuItemClickEvent evt) { felix@1456: disable(); felix@1469: createAreaArtifact(null, facetTheme, false); felix@1456: } felix@1456: }); felix@1456: overMenu.addItem(againstAxis); felix@1456: felix@1517: // Create the "between..." submenu. felix@1456: MenuItem betweenMenuItem = new MenuItem(MSG.chart_themepanel_area_between()); felix@1456: Menu betweenMenu = new Menu(); felix@1456: for (int i = 0; i < nThemes; i++) { felix@1456: final Theme theme = themes.getThemeAt(i+1); felix@2442: if (theme.getVisible() == 0) { felix@2442: continue; felix@2442: } felix@1456: if (!areAreaCompatible(facetTheme, theme)) { felix@1456: continue; felix@1456: } felix@1456: MenuItem againster = new MenuItem(theme.getDescription()); felix@1456: betweenMenu.addItem(againster); felix@1456: felix@1456: againster.addClickHandler(new ClickHandler() { christian@4568: @Override felix@1456: public void onClick(MenuItemClickEvent evt) { felix@1456: disable(); felix@1456: createAreaArtifact(facetTheme, theme, true); felix@1456: } felix@1456: }); felix@1456: } felix@1456: betweenMenu.addItem(createSeparator()); felix@1456: betweenMenu.addItem(againstAxis); felix@1456: felix@1456: overMenuItem.setSubmenu(overMenu); felix@1456: underMenuItem.setSubmenu(underMenu); felix@1456: betweenMenuItem.setSubmenu(betweenMenu); felix@1456: felix@1469: areaMenu.addItem(betweenMenuItem); felix@1456: areaMenu.addItem(overMenuItem); felix@1456: areaMenu.addItem(underMenuItem); felix@1469: areaMenu.addItem(createSeparator()); felix@1469: MenuItem standAloneAgainstAxis = new MenuItem(MSG.getString("against_x_axis")); felix@1469: standAloneAgainstAxis.addClickHandler(new ClickHandler() { christian@4568: @Override felix@1469: public void onClick(MenuItemClickEvent evt) { felix@1469: disable(); felix@1469: createAreaArtifact(null, facetTheme, false); felix@1469: } felix@1469: }); felix@1469: areaMenu.addItem(standAloneAgainstAxis); felix@1456: felix@1456: areaMenuItem.setSubmenu(areaMenu); felix@1456: menu.addItem(areaMenuItem); felix@1456: felix@1456: return menu; felix@1456: } ingo@523: } ingo@523: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :