felix@858: package de.intevation.flys.client.client.ui.chart; felix@858: felix@858: import com.google.gwt.core.client.GWT; felix@858: felix@2513: import com.google.gwt.i18n.client.NumberFormat; felix@2513: felix@1436: import com.google.gwt.user.client.rpc.AsyncCallback; felix@1436: sascha@2939: import com.smartgwt.client.data.Record; felix@1436: felix@1436: import com.smartgwt.client.types.ListGridFieldType; felix@1436: sascha@2939: import com.smartgwt.client.util.SC; sascha@2939: felix@2484: import com.smartgwt.client.widgets.Button; felix@858: import com.smartgwt.client.widgets.Canvas; felix@2484: import com.smartgwt.client.widgets.Label; sascha@2939: sascha@2939: import com.smartgwt.client.widgets.events.ClickEvent; sascha@2939: felix@858: import com.smartgwt.client.widgets.form.DynamicForm; felix@2513: import com.smartgwt.client.widgets.form.FormItemValueFormatter; felix@2513: import com.smartgwt.client.widgets.form.FormItemValueParser; felix@1436: sascha@2939: import com.smartgwt.client.widgets.form.fields.FormItem; felix@1436: import com.smartgwt.client.widgets.form.fields.SelectItem; sascha@2939: import com.smartgwt.client.widgets.form.fields.SpinnerItem; felix@2490: import com.smartgwt.client.widgets.form.fields.TextItem; sascha@2939: sascha@2939: import com.smartgwt.client.widgets.form.fields.events.BlurEvent; sascha@2939: import com.smartgwt.client.widgets.form.fields.events.BlurHandler; felix@1436: import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; felix@1436: import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; felix@2491: import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent; felix@2491: import com.smartgwt.client.widgets.form.fields.events.KeyPressHandler; felix@858: 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: sascha@2939: import com.smartgwt.client.widgets.layout.HLayout; sascha@2939: import com.smartgwt.client.widgets.layout.VLayout; sascha@2939: felix@1519: import com.smartgwt.client.widgets.menu.Menu; felix@1519: import com.smartgwt.client.widgets.menu.MenuItem; felix@2484: felix@1519: import com.smartgwt.client.widgets.menu.events.ClickHandler; felix@1519: import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent; felix@1519: felix@858: import de.intevation.flys.client.client.Config; sascha@2939: sascha@2939: import de.intevation.flys.client.client.services.CrossSectionKMServiceAsync; sascha@2939: import de.intevation.flys.client.client.services.LoadArtifactService; sascha@2939: import de.intevation.flys.client.client.services.LoadArtifactServiceAsync; sascha@2939: sascha@2939: import de.intevation.flys.client.client.ui.CollectionView; sascha@2939: felix@858: import de.intevation.flys.client.shared.model.Artifact; felix@858: import de.intevation.flys.client.shared.model.Data; felix@858: import de.intevation.flys.client.shared.model.DefaultArtifact; felix@858: import de.intevation.flys.client.shared.model.DefaultData; felix@858: import de.intevation.flys.client.shared.model.FacetRecord; felix@1436: import de.intevation.flys.client.shared.model.OutputMode; felix@1436: import de.intevation.flys.client.shared.model.Theme; felix@1436: import de.intevation.flys.client.shared.model.ThemeList; felix@858: sascha@2939: import java.util.ArrayList; 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 felix@858: extends ChartThemePanel { 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( felix@1436: de.intevation.flys.client.client.services.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@1476: /** Data item name for CrossSections selected km. */ felix@1476: protected static String CS_IS_MASTER = "cross_section.master?"; felix@1475: felix@2463: /** List of cross-section themes through which is moved 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() { 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: } 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; felix@1475: Theme firstCS = null; 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@1475: firstCS = theme; 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@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() { 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() { 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: } 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). */ 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). */ 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. felix@1436: * @return value from in that is closest to to, -1 if none. felix@1436: */ felix@2934: public static double closest(Double[] in, double to, boolean up) { felix@1436: if (in == null || in.length == 0) { felix@1436: return -1; felix@1436: } felix@1436: if (in[0] == to) { felix@1436: return to; felix@1436: } felix@2934: for (int i = 0; i < in.length; i++) { felix@2934: GWT.log ("Close? " + in[i]); felix@2934: } sascha@2937: felix@1436: double minDiff = Math.abs(to - in[0]); felix@1436: double bestMatch = in[0]; felix@1436: for (int i = 1; i < in.length; i++) { felix@1436: if (in[i] == to) { felix@1436: return to; felix@1436: } felix@2934: if ((in[i] < to && up) felix@2934: || (in[i] > to && !up)) { felix@2934: continue; felix@2934: } felix@2484: double diff = Math.abs(to - in[i]); felix@2934: if (diff <= minDiff) { felix@1436: minDiff = diff; felix@1436: bestMatch = in[i]; felix@1436: } felix@1436: } felix@1436: return bestMatch; felix@1436: } 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: * 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) { felix@1519: GWT.log("Could not feed many artifacts " + 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: */ felix@1572: public void spinnerValueEntered(final SpinnerItem item, felix@2934: final double enteredKm, final FacetRecord facetRecord, final boolean up felix@1572: ) { 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: } felix@1572: @Override felix@1572: public void onSuccess(Map obj) { felix@1572: Double[] kms = obj.get(dbid); felix@1572: double closest = felix@2934: CrossSectionChartThemePanel.closest(kms, enteredKm, up); felix@2484: GWT.log("Got single km close to " + 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 && felix@2463: synchronCrossSectionThemes.contains(themeHash(theme)) felix@2463: ) { felix@1572: artifacts.add(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@1438: * Create a "kilometer spinner" for CrossSection Facets. felix@1438: * @param facetRecord The respective Facet/Theme. felix@1438: * @return label, intialized SpinnerItem. felix@1438: */ felix@1438: public SpinnerItem createSpinnerItem(FacetRecord facetRecord) { felix@1438: SpinnerItem spinnerItem = new SpinnerItem(); felix@1438: spinnerItem.setShowTitle(false); felix@1438: spinnerItem.setTitle("Waterlevel-Spinner"); felix@1438: spinnerItem.setWidth(45); felix@1496: spinnerItem.setDefaultValue(Double.valueOf(facetRecord.getTheme() felix@1438: .getCollectionItem() felix@1496: .getData().get(CS_KM))); felix@1438: felix@1438: spinnerItem.setMin(0); felix@1475: spinnerItem.setMax(2000); felix@1572: spinnerItem.setStep(0.1d); felix@1438: spinnerItem.setChangeOnKeypress(true); felix@1438: return spinnerItem; felix@1438: } felix@1438: felix@1438: felix@1438: /** felix@2485: * SpinnerItem-like element with text label and up/down buttons. felix@2485: */ felix@2485: public class KmSpinner extends HLayout { felix@2485: protected Label label; felix@2485: felix@2485: protected FacetRecord facetRecord; felix@2485: felix@2485: protected double currentValue; felix@2485: felix@2485: public KmSpinner(FacetRecord facetRecord) { felix@2485: super(2); felix@2485: this.facetRecord = facetRecord; felix@2485: final FacetRecord _facetRecord = facetRecord; felix@2485: currentValue = Double.valueOf(facetRecord.getTheme() felix@2485: .getCollectionItem().getData().get(CS_KM)); felix@2485: // Buttons and labels. felix@2490: int height = 18; felix@2490: // minusButton shall ask service for previous available cs. felix@2485: Button minusButton = new Button("-"); felix@2485: minusButton.setWidth(10); felix@2485: minusButton.setHeight(height); felix@2485: minusButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() { felix@2485: public void onClick(ClickEvent evt) { felix@2934: spinnerValueEntered(null, currentValue - 0.1d, _facetRecord, false); felix@2485: } felix@2485: }); felix@2513: felix@2490: DynamicForm form = new DynamicForm(); felix@2490: final TextItem kmField = new TextItem(); felix@2490: kmField.setValue(currentValue); felix@2490: kmField.setWidth(35); felix@2490: kmField.setTitle(""); felix@2490: kmField.setHeight(height); felix@2513: felix@2513: FormItemValueFormatter doubleFormat = new FormItemValueFormatter() { felix@2513: public String formatValue(Object value, Record record, felix@2513: DynamicForm form, FormItem item) { felix@2513: if (value != null) { felix@2513: NumberFormat nf = NumberFormat.getDecimalFormat(); felix@2513: try { felix@2513: double d = Double.valueOf(value.toString()).doubleValue(); felix@2513: return nf.format(d); felix@2513: } catch (Exception e) { felix@2513: return value.toString(); felix@2513: } felix@2513: } felix@2513: else { felix@2513: return null; felix@2513: } felix@2513: } felix@2513: }; felix@2513: kmField.setEditorValueFormatter(doubleFormat); felix@2513: felix@2513: FormItemValueParser doubleParser = new FormItemValueParser() { felix@2513: public Object parseValue(String value, felix@2513: DynamicForm form, felix@2513: FormItem item) { felix@2513: if (value == null) felix@2513: return null; felix@2513: try { felix@2513: NumberFormat nf = NumberFormat.getDecimalFormat(); felix@2513: double d = nf.parse(value.toString()); felix@2513: return (new Double(d)).toString(); felix@2513: } felix@2513: catch(NumberFormatException nfe) { felix@2513: return value; felix@2513: } felix@2513: } felix@2513: }; felix@2513: kmField.setEditorValueParser(doubleParser); felix@2513: felix@2490: // Update on focus lost and enter-pressed. felix@2490: kmField.addBlurHandler(new BlurHandler() { felix@2490: @Override felix@2490: public void onBlur(BlurEvent be) { felix@2514: if (kmField.getValue() != null) { felix@2514: try { felix@2514: spinnerValueEntered(null, felix@2514: Double.parseDouble(kmField.getValue().toString()), felix@2934: _facetRecord, true); felix@2514: } felix@2514: catch(NumberFormatException nfe) { felix@2514: GWT.log("entered string cannot be parsed to double."); felix@2514: } felix@2514: } felix@2490: } felix@2490: }); felix@2490: kmField.addKeyPressHandler(new KeyPressHandler(){ felix@2490: @Override felix@2490: public void onKeyPress(KeyPressEvent kpe) { felix@2490: if (kpe.getKeyName().equals("Enter")) { felix@2490: kmField.blurItem(); felix@2490: } felix@2490: } felix@2490: }); felix@2490: // TODO: i18n Now add all the validators, formatters, editors/parsers etc. felix@2490: form.setFields(kmField); felix@2490: form.setTitle(""); felix@2490: form.setTitlePrefix(""); felix@2490: form.setTitleSuffix(""); felix@2490: form.setTitleWidth(0); felix@2490: form.setWidth(40); felix@2490: form.setHeight(height); felix@2485: // PlusButton shall ask service for next available cs. felix@2485: Button plusButton = new Button("+"); felix@2485: plusButton.setWidth(10); felix@2485: plusButton.setHeight(height); felix@2485: plusButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() { felix@2485: public void onClick(ClickEvent evt) { felix@2934: spinnerValueEntered(null, currentValue + 0.1d, _facetRecord, true); felix@2485: } felix@2485: }); felix@2485: this.addMember(minusButton); felix@2490: this.addMember(form); felix@2485: this.addMember(plusButton); felix@2485: felix@2485: this.setHeight(height*2); raimund@2544: this.setWidth(60); felix@2485: } felix@2485: } felix@2485: felix@2485: felix@2485: /** 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() { 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@888: if (fieldName.equals(GRID_FIELD_ACTIONS)) { felix@2485: /* felix@2490: TODO: felix@2464: if (facetRecord.getTheme().getActive() != 1) { felix@2464: spinnerItem.disable(); felix@2464: } felix@2485: */ sascha@2905: felix@2464: /* felix@2464: // To have visual representation of synchronous felix@2464: // navigation or not per theme, snip: felix@2464: if (synchronCrossSectionThemes.contains (themeHash felix@2464: (facetRecord.getTheme()))) { felix@2464: spinnerItem.setTextBoxStyle("bgBlueDark"); felix@2464: } felix@2464: */ felix@2464: felix@2485: return new KmSpinner(facetRecord); 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@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, raimund@2544: MSG.chart_themepanel_header_actions(), 65); 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. */ 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: */ 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: */ 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)) { felix@2462: synchronNavigationMenuItem.setTitle(MSG.chart_themepanel_asynchron()); felix@2463: synchronNavigationMenuItem.addClickHandler(new ClickHandler() { felix@2463: public void onClick(MenuItemClickEvent evt) { felix@2463: synchronCrossSectionThemes.remove (themeHash); felix@2463: } felix@2463: }); raimund@2453: } raimund@2453: else { felix@2462: synchronNavigationMenuItem.setTitle(MSG.chart_themepanel_synchron()); felix@2463: synchronNavigationMenuItem.addClickHandler(new ClickHandler() { 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 :