teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5861: * Software engineering by Intevation GmbH teichmann@5861: * teichmann@5993: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5993: * documentation coming with Dive4Elements River for details. teichmann@5861: */ teichmann@5861: teichmann@5835: package org.dive4elements.river.client.client.ui.chart; felix@858: felix@858: import com.google.gwt.core.client.GWT; felix@1436: import com.google.gwt.user.client.rpc.AsyncCallback; christian@4568: felix@1436: import com.smartgwt.client.types.ListGridFieldType; sascha@2939: import com.smartgwt.client.util.SC; felix@858: import com.smartgwt.client.widgets.Canvas; felix@858: import com.smartgwt.client.widgets.form.DynamicForm; felix@1436: import com.smartgwt.client.widgets.form.fields.SelectItem; felix@1436: import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; felix@1436: import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; sascha@2939: import com.smartgwt.client.widgets.grid.ListGrid; sascha@2939: import com.smartgwt.client.widgets.grid.ListGridField; sascha@2939: import com.smartgwt.client.widgets.grid.ListGridRecord; sascha@2939: import com.smartgwt.client.widgets.layout.VLayout; felix@1519: import com.smartgwt.client.widgets.menu.Menu; felix@1519: import com.smartgwt.client.widgets.menu.MenuItem; felix@1519: import com.smartgwt.client.widgets.menu.events.ClickHandler; felix@1519: import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent; felix@1519: teichmann@5835: import org.dive4elements.river.client.client.Config; teichmann@5835: import org.dive4elements.river.client.client.services.CrossSectionKMServiceAsync; 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.widgets.KMSpinner; teichmann@5835: import org.dive4elements.river.client.client.widgets.KMSpinnerChangeListener; 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.Theme; teichmann@5835: import org.dive4elements.river.client.shared.model.ThemeList; felix@858: sascha@2939: import java.util.ArrayList; andre@8465: import java.util.Arrays; sascha@2939: import java.util.HashMap; sascha@2939: import java.util.HashSet; sascha@2939: import java.util.LinkedHashMap; sascha@2939: import java.util.List; sascha@2939: import java.util.Map; felix@1472: felix@1444: felix@858: /** felix@858: * ThemePanel much like ChartThemePanel, but shows an "Actions" column, felix@1457: * needed for interaction in the CrossSection Charts and a selector to felix@2481: * declare which cross section profile is "master" (waterlevels refer to the felix@2481: * chosen kilometer of that cross section profile). felix@1457: * Also can show 'area creation' context menus. felix@858: */ felix@858: public class CrossSectionChartThemePanel christian@3717: extends ChartThemePanel christian@3717: implements KMSpinnerChangeListener christian@3717: { felix@1444: /** Artifact Clone/Creation service. */ felix@1444: protected LoadArtifactServiceAsync loadService = felix@1444: GWT.create(LoadArtifactService.class); felix@858: felix@1436: /** Service to query measurement points of cross sections. */ felix@1436: CrossSectionKMServiceAsync kmService = GWT.create( tom@8856: org.dive4elements.river.client.client.services tom@8856: .CrossSectionKMService.class); felix@1436: felix@1436: /** UUID of the current "master" cross section. */ felix@1470: protected String currentCSMasterUUID; felix@1436: felix@1436: /** The layout (used for visual active/inactive feedback). */ felix@1436: protected VLayout layout; felix@1436: felix@1475: /** Data item name for CrossSections selected km. */ felix@1476: protected static String CS_KM = "cross_section.km"; felix@1476: felix@6195: /** Data item name for CrossSections reference ('master') flag. */ felix@1476: protected static String CS_IS_MASTER = "cross_section.master?"; felix@1475: tom@8856: /** List of cross-section themes through which is moved tom@8856: * through synchronously. */ felix@2463: protected HashSet synchronCrossSectionThemes = new HashSet(); felix@1519: raimund@1533: /** Data for master artifact combobox.*/ raimund@1533: protected LinkedHashMap masters; raimund@1533: raimund@1533: /** Combobox for master artifacts.*/ raimund@1533: protected SelectItem masterCb; felix@1475: felix@1573: felix@858: /** felix@858: * Trivial constructor. felix@858: */ felix@858: public CrossSectionChartThemePanel( felix@1475: OutputMode mode, felix@1475: CollectionView view) felix@858: { felix@1555: super(mode, view); felix@1475: } felix@1475: felix@1475: felix@1475: /** Create DefaultArtifact. */ felix@1475: public static DefaultArtifact artifactReference(String uuid) { felix@1475: return new DefaultArtifact(uuid, "TODO:hash"); felix@1475: } felix@1475: felix@1475: felix@1475: /** Access data of collection item of theme. */ felix@1475: public static String dataOf(Theme theme, String dataItemName) { felix@1578: if (theme != null && theme.getCollectionItem() != null felix@1578: && theme.getCollectionItem().getData() != null felix@1578: ) { felix@1578: return theme.getCollectionItem().getData().get(dataItemName); felix@1578: } felix@1578: felix@1578: return null; felix@858: } felix@858: felix@858: felix@858: /** felix@1436: * Feed an artifact to let it know that it is master wrt cross-sections. felix@1436: * @param artifact uuid of an artifact. felix@1436: */ felix@1436: public void feedTellMaster(final String artifact) { felix@1436: Data[] feedData = DefaultData.createSimpleStringDataArray( felix@1476: CS_IS_MASTER, "1"); felix@1436: felix@1436: feedService.feed( felix@1436: Config.getInstance().getLocale(), felix@1475: artifactReference(artifact), felix@1436: feedData, felix@1436: new AsyncCallback() { christian@4568: @Override felix@1436: public void onFailure(Throwable caught) { felix@1436: GWT.log("Could not feed artifact (" + artifact felix@1436: + ") with master marker: " + caught.getMessage()); felix@1436: SC.warn(MSG.getString(caught.getMessage())); felix@1436: enable(); felix@1436: } christian@4568: @Override felix@1436: public void onSuccess(Artifact artifact) { felix@1436: GWT.log("Successfully injected master mark to " + artifact); felix@1470: setCurrentCSMaster(artifact.getUuid()); felix@1436: requestRedraw(); felix@1436: enable(); felix@1436: } felix@1436: }); felix@1436: } felix@1436: felix@1436: felix@1444: /** felix@1470: * Sets currentCSMasterUUID. felix@1438: */ felix@1470: public String findCurrentCSMaster() { felix@1438: ThemeList themeList = getThemeList(); felix@1438: int count = getThemeList().getThemeCount(); felix@1445: String firstCSUuid = null; christian@4568: felix@1438: for (int i = 1; i <= count; i++) { felix@1438: Theme theme = themeList.getThemeAt(i); felix@1476: String value = dataOf(theme, CS_IS_MASTER); felix@1438: felix@1445: if (value != null) { felix@1445: if (firstCSUuid == null) { felix@1445: firstCSUuid = theme.getArtifact(); felix@1445: } felix@1445: if (!value.equals("0")) { felix@1470: setCurrentCSMaster(theme.getArtifact()); felix@1472: GWT.log("found a master: " + currentCSMasterUUID felix@1472: + "/" + theme.getDescription()); felix@1445: return theme.getDescription(); felix@1445: } felix@1438: } felix@1438: } felix@1445: // There is none selected. Take the first one. felix@1445: if (firstCSUuid != null) { felix@6195: // TODO better take the one closest to first km! felix@6195: // issue1157, query next/prev kms, select the one which is closest. felix@1470: setCurrentCSMaster(firstCSUuid); felix@1445: feedTellMaster(firstCSUuid); felix@1445: } felix@1438: return null; felix@1438: } felix@1438: felix@1444: felix@1438: /** felix@1436: * Create Layout, add a master selection box beneath. felix@1436: */ felix@1436: @Override felix@1436: protected VLayout createLayout() { felix@1438: layout = super.createLayout(); felix@1436: felix@1436: // Create "set master" combobox. raimund@1533: masterCb = new SelectItem(); felix@1436: raimund@1533: masterCb.setTitle(MSG.chart_themepanel_set_master()); raimund@1533: masterCb.setType("comboBox"); raimund@1533: masters = getThemeList().toMapArtifactUUIDDescription("cross_section"); raimund@1533: masterCb.setValueMap(masters); felix@1436: felix@1436: final DynamicForm form = new DynamicForm(); felix@1436: form.setWidth(200); raimund@1533: form.setFields(masterCb); felix@2462: layout.addMember(form, 0); felix@1436: felix@1438: Config config = Config.getInstance(); felix@1438: final String locale = config.getLocale(); felix@1470: findCurrentCSMaster(); raimund@1533: masterCb.setValue(getCurrentCSMaster()); felix@1436: felix@1436: // Add Change Handler to first unset the old master and then set the felix@1436: // new master. raimund@1533: masterCb.addChangeHandler(new ChangeHandler() { christian@4568: @Override sascha@2905: public void onChange(ChangeEvent event) { felix@1436: String selectedItem = (String) event.getValue(); felix@1436: final String artifact = selectedItem; felix@1436: felix@1436: disable(); felix@1436: felix@1436: // Tell current master that he is not master anymore. felix@1470: if (getCurrentCSMaster() != null) { felix@1436: Data[] feedData = DefaultData.createSimpleStringDataArray( felix@1476: CS_IS_MASTER, "0"); felix@1436: feedService.feed( felix@1436: locale, felix@1475: artifactReference(getCurrentCSMaster()), felix@1436: feedData, felix@1436: new AsyncCallback() { christian@4568: @Override felix@1436: public void onFailure(Throwable caught) { felix@1573: GWT.log("Could not un-master artifact (" felix@1573: + getCurrentCSMaster() + "): " + felix@1436: caught.getMessage()); felix@1436: SC.warn(MSG.getString(caught.getMessage())); felix@1436: enable(); felix@1436: } christian@4568: @Override felix@1436: public void onSuccess(Artifact oldMaster) { felix@1436: GWT.log("Successfully un-mastered artifact."); felix@1436: feedTellMaster(artifact); felix@1436: } felix@1436: }); felix@1436: } felix@1436: else { felix@1436: feedTellMaster(artifact); felix@1436: } sascha@2905: } felix@1436: }); felix@1436: felix@1436: return layout; felix@1436: } felix@1436: felix@1436: felix@1436: /** Disable the UI (becomes gray, inresponsive to user input). */ christian@3717: @Override felix@1436: public void disable() { felix@1436: this.layout.setDisabled(true); felix@1436: } felix@1436: felix@1436: felix@1436: /** DisDisable the UI (becomes ungray, responsive to user input). */ christian@3717: @Override felix@1436: public void enable() { felix@1436: this.layout.setDisabled(false); felix@1436: } felix@1436: felix@1436: felix@1436: /** felix@1436: * Returns a double from the list that has the smallest distance to the felix@1436: * given to value. In case of multiple values with the same difference, felix@1436: * the last one is taken. felix@1436: * @param in possible return values. felix@1436: * @param to the value to be as close to as possible. felix@2934: * @param up if true, prefer numerically higher values in case of two felix@2934: * values with equal distance to \param to. tom@8468: * @return value from in that is closest to to, NaN if none. felix@1436: */ andre@8467: public static Double closest(Double[] in, double to, boolean up) { felix@1436: if (in == null || in.length == 0) { andre@8467: return Double.NaN; felix@1436: } andre@8465: Arrays.sort(in); tom@8856: GWT.log ("Closest match for " + (up ? "next" : "previous") tom@8856: + " value to: " + to + " candidates: " + Arrays.toString(in)); andre@8465: if (up) { tom@8468: double max = in[in.length - 1]; andre@8465: for (int i = 0; i < in.length; i++) { tom@8468: if (in[i] >= to || in[i] == max) { andre@8465: return in[i]; andre@8465: } felix@1436: } andre@8465: } else { tom@8468: double min = in[0]; andre@8465: for (int i = in.length - 1; i >= 0; i--) { tom@8468: if (in[i] <= to || in[i] == min) { andre@8465: return in[i]; andre@8465: } felix@1436: } felix@1436: } andre@8465: GWT.log("Failed to find closest match"); andre@8467: return Double.NaN; felix@1436: } felix@1436: felix@1573: felix@1573: /** felix@6535: * Feed artifacts with the km of the crosssection to display. felix@1573: * If its the selected master, also feed the collectionmaster. felix@1573: * felix@1573: * @param artifacts List of artifacts to feed. felix@1573: * @param kmD The km to set. felix@1573: */ felix@1519: public void sendFeed(final List artifacts, final double kmD) { felix@1519: Config config = Config.getInstance(); felix@1519: final String locale = config.getLocale(); felix@1519: felix@1519: Data[] feedData = felix@1519: DefaultData.createSimpleStringDataArray(CS_KM, felix@1519: Double.valueOf(kmD).toString()); felix@1519: felix@1519: disable(); felix@2518: // TODO felix@2518: // The ones who do not have data for this km should not show line! felix@1519: feedService.feedMany( felix@1519: locale, felix@1519: artifacts, felix@1519: feedData, felix@1519: new AsyncCallback>() { felix@1519: @Override felix@1519: public void onFailure(Throwable caught) { tom@8856: GWT.log("Could not feed many artifacts " tom@8856: + caught.getMessage()); felix@1519: SC.warn(MSG.getString(caught.getMessage())); felix@1519: enable(); felix@1519: } felix@1519: @Override felix@1519: public void onSuccess(List artifact) { felix@1519: GWT.log("Successfully fed many with km"); felix@1519: requestRedraw(); felix@1519: enable(); felix@1519: } felix@1519: }); felix@1519: } felix@1436: felix@1573: felix@1573: /** felix@1573: * Feed a single artifact with the km of the crosssection to display. felix@1573: * If its the selected master, also feed the collectionmaster. felix@1573: * @param artUUID The UUID of the artifact to feed. felix@1573: * @param kmD The km to set. felix@1573: */ felix@1472: public void sendFeed(final String artUUID, final double kmD) { felix@1472: Config config = Config.getInstance(); felix@1472: final String locale = config.getLocale(); felix@1436: felix@1436: Data[] feedData = felix@1476: DefaultData.createSimpleStringDataArray(CS_KM, felix@1436: Double.valueOf(kmD).toString()); felix@1436: felix@1436: disable(); felix@1436: feedService.feed( felix@1436: locale, felix@1475: artifactReference(artUUID), felix@1436: feedData, felix@1436: new AsyncCallback() { felix@1436: @Override felix@1436: public void onFailure(Throwable caught) { felix@1436: GWT.log("Could not feed artifact " + caught.getMessage()); felix@1436: SC.warn(MSG.getString(caught.getMessage())); felix@1436: enable(); felix@1436: } felix@1436: @Override felix@1436: public void onSuccess(Artifact artifact) { felix@1472: GWT.log("Successfully fed with km"); felix@1436: requestRedraw(); felix@1496: enable(); felix@1436: } felix@1436: }); felix@1436: } felix@1436: felix@1573: felix@2443: /** Remove the themes, also from the master (reference) select box. */ felix@2443: @Override felix@2443: protected void removeThemes(final ListGridRecord[] records) { felix@2443: // TODO take care of what happens if that was the last felix@2443: // cross section and/or the cross section currently selected as master. felix@2443: for (ListGridRecord record: records) { felix@2443: FacetRecord facet = (FacetRecord) record; felix@2443: Theme theme = facet.getTheme(); felix@2443: masters.remove(theme.getArtifact()); felix@2443: } felix@2443: masterCb.setValueMap(masters); felix@2443: super.removeThemes(records); felix@2443: } felix@2443: felix@2443: felix@2482: /** felix@2482: * Callback for when a value has been accepted in the km-spinner felix@2482: * of a Cross-Section Profile theme. felix@2482: * @param item The SpinnerItem which was manipulated. felix@2482: * @param enteredKm The double-parsed value that has been entered. felix@2482: * @param facetRecord The underlying datastores record. felix@2934: * @param up If true, numerically higher values are preferred if felix@2934: * two values in \param in are in the same distance to felix@2934: * \param to. felix@2482: */ christian@4568: @Override felix@6195: public void spinnerValueEntered(KMSpinner spinner, felix@6195: final double enteredKm, felix@6195: final FacetRecord facetRecord, felix@6195: final boolean up felix@6195: ) { felix@1573: disable(); felix@1572: Config config = Config.getInstance(); felix@1572: final String locale = config.getLocale(); felix@1572: felix@1572: Map map = new HashMap(); felix@1572: int _dbid = -1; felix@1572: try { felix@1572: _dbid = Integer.valueOf(facetRecord.getTheme() felix@1572: .getCollectionItem() felix@1572: .getData().get("cross_section.dbid")); felix@1572: } felix@1572: catch (NumberFormatException nfe) { felix@1572: GWT.log("Could not extract cross-section db id from data."); felix@1572: } felix@1572: final int dbid = _dbid; felix@1572: felix@1572: map.put(dbid, enteredKm); felix@1572: felix@2482: // Query the available cross section measurements. felix@1572: kmService.getCrossSectionKMs(locale, map, 2, felix@1572: new AsyncCallback>() { felix@1572: @Override felix@1572: public void onFailure(Throwable caught) { felix@1572: GWT.log("Could not get single km for " felix@1572: + dbid + ": "+ caught.getMessage()); felix@1572: SC.warn(MSG.getString(caught.getMessage())); felix@1572: updateCollection(); felix@1573: //updateGrid(); felix@1572: enable(); felix@1572: } christian@3717: felix@1572: @Override felix@1572: public void onSuccess(Map obj) { felix@1572: Double[] kms = obj.get(dbid); andre@8467: Double closest = felix@2934: CrossSectionChartThemePanel.closest(kms, enteredKm, up); andre@8467: if (Double.isNaN(closest)) { tom@8856: GWT.log("Failed to find a closest km. " tom@8856: + "Staying on current km."); andre@8467: updateCollection(); andre@8467: enable(); andre@8467: return; andre@8467: } andre@8467: tom@8856: GWT.log("Got single km close to " tom@8856: + enteredKm + " for " + dbid + ", it is " felix@1572: + closest); felix@1574: felix@1574: // Do not set value, as it will trigger strange felix@2463: // "javascript" bugs. /*item.setValue(closest);*/ felix@2463: if (synchronCrossSectionThemes.contains (themeHash felix@2463: (facetRecord.getTheme()))) { felix@2463: // Move all other synchrons felix@1572: ThemeList themes = getThemeList(); felix@1572: int nThemes = themes.getThemeCount(); felix@1572: List artifacts = new ArrayList(); felix@1572: for (int i = 0; i < nThemes; i++) { felix@1572: final Theme theme = themes.getThemeAt(i+1); felix@1572: if (theme.getFacet().equals("cross_section") && felix@2463: theme.getActive() == 1 && tom@8856: synchronCrossSectionThemes.contains( tom@8856: themeHash(theme)) felix@2463: ) { tom@8856: artifacts.add( tom@8856: artifactReference(theme.getArtifact())); felix@1572: } felix@1572: } felix@1574: sendFeed(artifacts, closest); felix@1572: } felix@1572: else { felix@1572: sendFeed(facetRecord.getTheme().getArtifact(), felix@1572: closest); felix@1572: } felix@1572: } felix@1572: }); felix@1572: } felix@1572: felix@1436: felix@1436: /** felix@858: * Create and configure the Grid to display. felix@1438: * @return ListGrid with Themes and related controls inside. felix@858: */ felix@858: @Override felix@858: protected ListGrid createGrid() { christian@3717: final CrossSectionChartThemePanel parent = this; christian@3717: felix@858: ListGrid list = new ListGrid() { felix@858: @Override felix@1379: protected Canvas createRecordComponent( felix@1379: final ListGridRecord record, felix@1379: Integer colNum) felix@1379: { felix@861: // Only cross_section Facets display an action widget. felix@861: final FacetRecord facetRecord = (FacetRecord) record; felix@861: if (!facetRecord.getTheme().getFacet().equals( felix@1379: "cross_section")) felix@1379: { felix@861: return null; felix@861: } felix@858: felix@858: String fieldName = this.getFieldName(colNum); felix@858: felix@6195: // Place KMSpinner in Grid with currently chosen km value. felix@888: if (fieldName.equals(GRID_FIELD_ACTIONS)) { christian@3717: double currentValue = tom@8856: Double.valueOf( tom@8856: facetRecord.getTheme().getCollectionItem() tom@8856: .getData().get(CS_KM)); tom@8856: KMSpinner kmSpinner = new KMSpinner( tom@8856: currentValue, facetRecord); christian@3717: kmSpinner.addChangeListener(parent); christian@3717: return kmSpinner; felix@858: } felix@858: else { felix@858: return null; felix@858: } felix@858: } felix@858: }; felix@858: list.setCanResizeFields(true); felix@858: list.setShowRecordComponents(true); felix@858: list.setShowRecordComponentsByCell(true); felix@858: list.setShowAllRecords(true); felix@1378: list.setShowHeaderContextMenu(false); ingo@2445: list.setLeaveScrollbarGap(false); felix@6195: felix@858: return list; felix@858: } felix@858: felix@858: felix@858: /** felix@858: * Initializes the components (columns) of the theme grid. felix@858: */ felix@858: @Override felix@858: protected void initGrid() { felix@858: list.setCanEdit(true); felix@858: list.setCanSort(false); felix@858: list.setShowRecordComponents(true); felix@858: list.setShowRecordComponentsByCell(true); felix@858: list.setShowHeader(true); felix@858: list.setWidth100(); felix@858: list.setHeight100(); felix@858: felix@858: list.addEditCompleteHandler(this); felix@858: felix@858: ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20); felix@858: active.setType(ListGridFieldType.BOOLEAN); felix@858: felix@858: ListGridField name = new ListGridField( felix@858: GRID_FIELD_NAME, MSG.chart_themepanel_header_themes()); felix@858: name.setType(ListGridFieldType.TEXT); felix@858: felix@858: ListGridField actions = new ListGridField(GRID_FIELD_ACTIONS, christian@3717: MSG.chart_themepanel_header_actions(), 100); felix@858: felix@858: list.setFields(active, name, actions); felix@858: } felix@1436: felix@1436: felix@1436: /** Get Current Cross-section Masters uuid. */ felix@1470: public String getCurrentCSMaster() { felix@1470: return currentCSMasterUUID; felix@1436: } felix@1436: felix@1436: felix@1436: /** Set Current Cross-section Masters uuid. */ felix@1470: public void setCurrentCSMaster(String currentMasterUuid) { felix@1470: this.currentCSMasterUUID = currentMasterUuid; felix@1436: } felix@1444: felix@1444: felix@1457: /** Returns name of cross section area facets. */ christian@3717: @Override felix@1457: protected String getAreaFacetName() { felix@1457: return "cross_section.area"; felix@1457: } felix@1444: felix@1444: felix@1444: /** felix@1457: * Return true if two themes are canditates for an area being felix@1457: * rendered between them. felix@1457: * TODO join with canArea, generalize to allow easier modification felix@1457: * in subclasses. felix@1444: */ christian@3717: @Override felix@1457: protected boolean areAreaCompatible(Theme a, Theme b) { felix@1457: if (a.equals(b)) { felix@1457: return false; felix@1444: } felix@1457: return (a.getFacet().equals("cross_section") felix@2930: || a.getFacet().endsWith("line")) felix@1457: && (b.getFacet().equals("cross_section") felix@2930: || b.getFacet().endsWith("line")); felix@1457: } felix@1444: felix@1452: felix@1457: /** felix@1457: * True if context menu should contain 'create area' submenu on felix@1457: * this theme. felix@1457: */ christian@3717: @Override felix@1457: protected boolean canArea(Theme a) { felix@1457: return a.getFacet().equals("cross_section") felix@2930: || a.getFacet().equals("cross_section_water_line") felix@2930: || a.getFacet().endsWith("line"); felix@1444: } felix@1519: felix@1519: felix@2463: protected String themeHash(Theme theme) { felix@2463: return theme.getArtifact() + theme.getFacet() + theme.getIndex(); felix@2463: } felix@2463: felix@2463: felix@1519: /** felix@1519: * Include synchron navigation item. felix@1519: */ felix@1519: @Override felix@1519: protected Menu getSingleContextMenu(final ListGridRecord[] records) { felix@1519: Menu contextMenu = super.getSingleContextMenu(records); felix@1519: raimund@2453: Theme facetTheme = ((FacetRecord)records[0]).getTheme(); raimund@2453: String item = facetTheme.getFacet(); raimund@2453: felix@2482: if (item.equals("cross_section")) { raimund@2453: // Synchron checking. raimund@2453: MenuItem synchronNavigationMenuItem = new MenuItem(); felix@2463: final String themeHash = themeHash(facetTheme); felix@2463: if (synchronCrossSectionThemes.contains(themeHash)) { tom@8856: synchronNavigationMenuItem.setTitle( tom@8856: MSG.chart_themepanel_asynchron()); felix@2463: synchronNavigationMenuItem.addClickHandler(new ClickHandler() { christian@4568: @Override felix@2463: public void onClick(MenuItemClickEvent evt) { felix@2463: synchronCrossSectionThemes.remove (themeHash); felix@2463: } felix@2463: }); raimund@2453: } raimund@2453: else { tom@8856: synchronNavigationMenuItem.setTitle( tom@8856: MSG.chart_themepanel_synchron()); felix@2463: synchronNavigationMenuItem.addClickHandler(new ClickHandler() { christian@4568: @Override felix@2463: public void onClick(MenuItemClickEvent evt) { felix@2463: synchronCrossSectionThemes.add (themeHash); felix@2463: } felix@2463: }); raimund@2453: } raimund@2453: contextMenu.addItem(synchronNavigationMenuItem); felix@1519: } felix@1519: felix@1519: return contextMenu; felix@1519: } raimund@1533: raimund@1533: raimund@1533: /** raimund@1533: * This method is used to clear the current theme grid and add new updated raimund@1533: * data. raimund@1533: */ raimund@1533: @Override raimund@1533: protected void updateGrid() { raimund@1533: GWT.log("CrossSectionChartThemePanel.updateGrid"); raimund@1533: raimund@1533: ListGridRecord[] selected = list.getSelectedRecords(); raimund@1533: raimund@1533: clearGrid(); raimund@1533: raimund@1533: ThemeList themeList = getThemeList(); raimund@1533: raimund@1533: if (themeList == null) { raimund@1533: GWT.log("ERROR: No theme list."); raimund@1533: return; raimund@1533: } raimund@1533: raimund@1533: int count = themeList.getThemeCount(); raimund@1533: raimund@1533: for (int i = 1; i <= count; i++) { raimund@1533: Theme theme = themeList.getThemeAt(i); raimund@1533: felix@1578: if (theme == null) { felix@1578: continue; felix@1578: } felix@1578: felix@1578: if (theme.getFacet().equals("empty.facet")) { raimund@1533: theme.setVisible(0); raimund@1533: } raimund@1533: felix@1578: if (theme.getVisible() == 0) { raimund@1533: continue; raimund@1533: } raimund@1533: raimund@1533: if (theme.getFacet().equals("cross_section")) { raimund@1533: addToReferences(theme); raimund@1533: } raimund@1533: raimund@1533: FacetRecord newRecord = createRecord(theme); raimund@1533: addFacetRecord(newRecord); raimund@1533: raimund@1533: String newArtifact = theme.getArtifact(); raimund@1533: String newFacet = theme.getFacet(); raimund@1533: int newIndex = theme.getIndex(); raimund@1533: raimund@1533: for (ListGridRecord r: selected) { raimund@1533: FacetRecord sel = (FacetRecord) r; raimund@1533: Theme oldTheme = sel.getTheme(); raimund@1533: raimund@1533: if (oldTheme.getArtifact().equals(newArtifact) raimund@1533: && oldTheme.getFacet().equals(newFacet) raimund@1533: && oldTheme.getIndex() == newIndex) { raimund@1533: list.selectRecord(newRecord); raimund@1533: } raimund@1533: } raimund@1533: } raimund@1533: raimund@1533: fireOutputParameterChanged(); raimund@1533: raimund@1533: } raimund@1533: raimund@1533: raimund@1533: /** raimund@1533: * Adds a cross section theme to the master artifacts combobox and finds raimund@1533: * a new master if necessary. raimund@1533: * raimund@1533: * @param theme The cross section theme. raimund@1533: */ raimund@1533: protected void addToReferences(Theme theme) { felix@2443: if (theme.getVisible() != 0) { felix@2443: masters.put(theme.getArtifact(), theme.getDescription()); felix@2443: masterCb.setValueMap(masters); felix@2443: } raimund@1533: findCurrentCSMaster(); raimund@1533: if (masterCb.getSelectedRecord() == null) { raimund@1533: masterCb.setValue(getCurrentCSMaster()); raimund@1533: } raimund@1533: } felix@858: } felix@858: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :