Mercurial > dive4elements > river
view flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/CrossSectionChartThemePanel.java @ 4215:c179cd02177d
Logout the current user
Add code to the logout button to remove the current user from the session and to
redirect the browser window to the login page.
Part of flys/issue916 (Logout: "Abmelden" Knopf mit Funktion belegen)
author | Björn Ricks <bjoern.ricks@intevation.de> |
---|---|
date | Tue, 23 Oct 2012 09:59:16 +0200 |
parents | 3b4cef59836a |
children | bbd82bd8e541 |
line wrap: on
line source
package de.intevation.flys.client.client.ui.chart; 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.Canvas; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.SelectItem; import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; import com.smartgwt.client.widgets.grid.ListGrid; 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; import de.intevation.flys.client.client.Config; import de.intevation.flys.client.client.services.CrossSectionKMServiceAsync; import de.intevation.flys.client.client.services.LoadArtifactService; import de.intevation.flys.client.client.services.LoadArtifactServiceAsync; import de.intevation.flys.client.client.ui.CollectionView; import de.intevation.flys.client.client.widgets.KMSpinner; import de.intevation.flys.client.client.widgets.KMSpinnerChangeListener; import de.intevation.flys.client.shared.model.Artifact; import de.intevation.flys.client.shared.model.Data; import de.intevation.flys.client.shared.model.DefaultArtifact; import de.intevation.flys.client.shared.model.DefaultData; import de.intevation.flys.client.shared.model.FacetRecord; import de.intevation.flys.client.shared.model.OutputMode; import de.intevation.flys.client.shared.model.Theme; import de.intevation.flys.client.shared.model.ThemeList; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * ThemePanel much like ChartThemePanel, but shows an "Actions" column, * needed for interaction in the CrossSection Charts and a selector to * declare which cross section profile is "master" (waterlevels refer to the * chosen kilometer of that cross section profile). * Also can show 'area creation' context menus. */ public class CrossSectionChartThemePanel extends ChartThemePanel implements KMSpinnerChangeListener { /** Artifact Clone/Creation service. */ protected LoadArtifactServiceAsync loadService = GWT.create(LoadArtifactService.class); /** Service to query measurement points of cross sections. */ CrossSectionKMServiceAsync kmService = GWT.create( de.intevation.flys.client.client.services.CrossSectionKMService.class); /** UUID of the current "master" cross section. */ protected String currentCSMasterUUID; /** The layout (used for visual active/inactive feedback). */ protected VLayout layout; /** Data item name for CrossSections selected km. */ protected static String CS_KM = "cross_section.km"; /** Data item name for CrossSections selected km. */ protected static String CS_IS_MASTER = "cross_section.master?"; /** List of cross-section themes through which is moved through synchronously. */ protected HashSet synchronCrossSectionThemes = new HashSet(); /** Data for master artifact combobox.*/ protected LinkedHashMap<String, String> masters; /** Combobox for master artifacts.*/ protected SelectItem masterCb; /** * Trivial constructor. */ public CrossSectionChartThemePanel( OutputMode mode, CollectionView view) { super(mode, view); } /** Create DefaultArtifact. */ public static DefaultArtifact artifactReference(String uuid) { return new DefaultArtifact(uuid, "TODO:hash"); } /** Access data of collection item of theme. */ public static String dataOf(Theme theme, String dataItemName) { if (theme != null && theme.getCollectionItem() != null && theme.getCollectionItem().getData() != null ) { return theme.getCollectionItem().getData().get(dataItemName); } return null; } /** * Feed an artifact to let it know that it is master wrt cross-sections. * @param artifact uuid of an artifact. */ public void feedTellMaster(final String artifact) { Data[] feedData = DefaultData.createSimpleStringDataArray( CS_IS_MASTER, "1"); feedService.feed( Config.getInstance().getLocale(), artifactReference(artifact), feedData, new AsyncCallback<Artifact>() { public void onFailure(Throwable caught) { GWT.log("Could not feed artifact (" + artifact + ") with master marker: " + caught.getMessage()); SC.warn(MSG.getString(caught.getMessage())); enable(); } public void onSuccess(Artifact artifact) { GWT.log("Successfully injected master mark to " + artifact); setCurrentCSMaster(artifact.getUuid()); requestRedraw(); enable(); } }); } /** * Sets currentCSMasterUUID. */ public String findCurrentCSMaster() { ThemeList themeList = getThemeList(); int count = getThemeList().getThemeCount(); String firstCSUuid = null; Theme firstCS = null; for (int i = 1; i <= count; i++) { Theme theme = themeList.getThemeAt(i); String value = dataOf(theme, CS_IS_MASTER); if (value != null) { if (firstCSUuid == null) { firstCSUuid = theme.getArtifact(); firstCS = theme; } if (!value.equals("0")) { setCurrentCSMaster(theme.getArtifact()); GWT.log("found a master: " + currentCSMasterUUID + "/" + theme.getDescription()); return theme.getDescription(); } } } // There is none selected. Take the first one. if (firstCSUuid != null) { setCurrentCSMaster(firstCSUuid); feedTellMaster(firstCSUuid); } return null; } /** * Create Layout, add a master selection box beneath. */ @Override protected VLayout createLayout() { layout = super.createLayout(); // Create "set master" combobox. masterCb = new SelectItem(); masterCb.setTitle(MSG.chart_themepanel_set_master()); masterCb.setType("comboBox"); masters = getThemeList().toMapArtifactUUIDDescription("cross_section"); masterCb.setValueMap(masters); final DynamicForm form = new DynamicForm(); form.setWidth(200); form.setFields(masterCb); layout.addMember(form, 0); Config config = Config.getInstance(); final String locale = config.getLocale(); findCurrentCSMaster(); masterCb.setValue(getCurrentCSMaster()); // Add Change Handler to first unset the old master and then set the // new master. masterCb.addChangeHandler(new ChangeHandler() { public void onChange(ChangeEvent event) { String selectedItem = (String) event.getValue(); final String artifact = selectedItem; disable(); // Tell current master that he is not master anymore. if (getCurrentCSMaster() != null) { Data[] feedData = DefaultData.createSimpleStringDataArray( CS_IS_MASTER, "0"); feedService.feed( locale, artifactReference(getCurrentCSMaster()), feedData, new AsyncCallback<Artifact>() { public void onFailure(Throwable caught) { GWT.log("Could not un-master artifact (" + getCurrentCSMaster() + "): " + caught.getMessage()); SC.warn(MSG.getString(caught.getMessage())); enable(); } public void onSuccess(Artifact oldMaster) { GWT.log("Successfully un-mastered artifact."); feedTellMaster(artifact); } }); } else { feedTellMaster(artifact); } } }); return layout; } /** Disable the UI (becomes gray, inresponsive to user input). */ @Override public void disable() { this.layout.setDisabled(true); } /** DisDisable the UI (becomes ungray, responsive to user input). */ @Override public void enable() { this.layout.setDisabled(false); } /** * Returns a double from the list that has the smallest distance to the * given to value. In case of multiple values with the same difference, * the last one is taken. * @param in possible return values. * @param to the value to be as close to as possible. * @param up if true, prefer numerically higher values in case of two * values with equal distance to \param to. * @return value from in that is closest to to, -1 if none. */ public static double closest(Double[] in, double to, boolean up) { if (in == null || in.length == 0) { return -1; } if (in[0] == to) { return to; } for (int i = 0; i < in.length; i++) { GWT.log ("Close? " + in[i]); } double minDiff = Math.abs(to - in[0]); double bestMatch = in[0]; for (int i = 1; i < in.length; i++) { if (in[i] == to) { return to; } if ((in[i] < to && up) || (in[i] > to && !up)) { continue; } double diff = Math.abs(to - in[i]); if (diff <= minDiff) { minDiff = diff; bestMatch = in[i]; } } return bestMatch; } /** * Feed a single artifact with the km of the crosssection to display. * If its the selected master, also feed the collectionmaster. * * @param artifacts List of artifacts to feed. * @param kmD The km to set. */ public void sendFeed(final List<Artifact> artifacts, final double kmD) { Config config = Config.getInstance(); final String locale = config.getLocale(); Data[] feedData = DefaultData.createSimpleStringDataArray(CS_KM, Double.valueOf(kmD).toString()); disable(); // TODO // The ones who do not have data for this km should not show line! feedService.feedMany( locale, artifacts, feedData, new AsyncCallback<List<Artifact>>() { @Override public void onFailure(Throwable caught) { GWT.log("Could not feed many artifacts " + caught.getMessage()); SC.warn(MSG.getString(caught.getMessage())); enable(); } @Override public void onSuccess(List<Artifact> artifact) { GWT.log("Successfully fed many with km"); requestRedraw(); enable(); } }); } /** * Feed a single artifact with the km of the crosssection to display. * If its the selected master, also feed the collectionmaster. * @param artUUID The UUID of the artifact to feed. * @param kmD The km to set. */ public void sendFeed(final String artUUID, final double kmD) { Config config = Config.getInstance(); final String locale = config.getLocale(); Data[] feedData = DefaultData.createSimpleStringDataArray(CS_KM, Double.valueOf(kmD).toString()); disable(); feedService.feed( locale, artifactReference(artUUID), feedData, new AsyncCallback<Artifact>() { @Override public void onFailure(Throwable caught) { GWT.log("Could not feed artifact " + caught.getMessage()); SC.warn(MSG.getString(caught.getMessage())); enable(); } @Override public void onSuccess(Artifact artifact) { GWT.log("Successfully fed with km"); requestRedraw(); enable(); } }); } /** Remove the themes, also from the master (reference) select box. */ @Override protected void removeThemes(final ListGridRecord[] records) { // TODO take care of what happens if that was the last // cross section and/or the cross section currently selected as master. for (ListGridRecord record: records) { FacetRecord facet = (FacetRecord) record; Theme theme = facet.getTheme(); masters.remove(theme.getArtifact()); } masterCb.setValueMap(masters); super.removeThemes(records); } /** * Callback for when a value has been accepted in the km-spinner * of a Cross-Section Profile theme. * @param item The SpinnerItem which was manipulated. * @param enteredKm The double-parsed value that has been entered. * @param facetRecord The underlying datastores record. * @param up If true, numerically higher values are preferred if * two values in \param in are in the same distance to * \param to. */ public void spinnerValueEntered(KMSpinner spinner, final double enteredKm, final FacetRecord facetRecord, final boolean up) { disable(); Config config = Config.getInstance(); final String locale = config.getLocale(); Map<Integer, Double> map = new HashMap<Integer,Double>(); int _dbid = -1; try { _dbid = Integer.valueOf(facetRecord.getTheme() .getCollectionItem() .getData().get("cross_section.dbid")); } catch (NumberFormatException nfe) { GWT.log("Could not extract cross-section db id from data."); } final int dbid = _dbid; map.put(dbid, enteredKm); // Query the available cross section measurements. kmService.getCrossSectionKMs(locale, map, 2, new AsyncCallback<Map<Integer, Double[]>>() { @Override public void onFailure(Throwable caught) { GWT.log("Could not get single km for " + dbid + ": "+ caught.getMessage()); SC.warn(MSG.getString(caught.getMessage())); updateCollection(); //updateGrid(); enable(); } @Override public void onSuccess(Map<Integer, Double[]> obj) { Double[] kms = obj.get(dbid); double closest = CrossSectionChartThemePanel.closest(kms, enteredKm, up); GWT.log("Got single km close to " + enteredKm + " for " + dbid + ", it is " + closest); // Do not set value, as it will trigger strange // "javascript" bugs. /*item.setValue(closest);*/ if (synchronCrossSectionThemes.contains (themeHash (facetRecord.getTheme()))) { // Move all other synchrons ThemeList themes = getThemeList(); int nThemes = themes.getThemeCount(); List<Artifact> artifacts = new ArrayList<Artifact>(); for (int i = 0; i < nThemes; i++) { final Theme theme = themes.getThemeAt(i+1); if (theme.getFacet().equals("cross_section") && theme.getActive() == 1 && synchronCrossSectionThemes.contains(themeHash(theme)) ) { artifacts.add(artifactReference(theme.getArtifact())); } } sendFeed(artifacts, closest); } else { sendFeed(facetRecord.getTheme().getArtifact(), closest); } } }); } /** * Create and configure the Grid to display. * @return ListGrid with Themes and related controls inside. */ @Override protected ListGrid createGrid() { final CrossSectionChartThemePanel parent = this; ListGrid list = new ListGrid() { @Override protected Canvas createRecordComponent( final ListGridRecord record, Integer colNum) { // Only cross_section Facets display an action widget. final FacetRecord facetRecord = (FacetRecord) record; if (!facetRecord.getTheme().getFacet().equals( "cross_section")) { return null; } String fieldName = this.getFieldName(colNum); if (fieldName.equals(GRID_FIELD_ACTIONS)) { double currentValue = Double.valueOf(facetRecord.getTheme().getCollectionItem().getData().get(CS_KM)); KMSpinner kmSpinner = new KMSpinner(currentValue, facetRecord); kmSpinner.addChangeListener(parent); return kmSpinner; } else { return null; } } }; list.setCanResizeFields(true); list.setShowRecordComponents(true); list.setShowRecordComponentsByCell(true); list.setShowAllRecords(true); list.setShowHeaderContextMenu(false); list.setLeaveScrollbarGap(false); return list; } /** * Initializes the components (columns) of the theme grid. */ @Override protected void initGrid() { list.setCanEdit(true); list.setCanSort(false); list.setShowRecordComponents(true); list.setShowRecordComponentsByCell(true); list.setShowHeader(true); list.setWidth100(); list.setHeight100(); list.addEditCompleteHandler(this); ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20); active.setType(ListGridFieldType.BOOLEAN); ListGridField name = new ListGridField( GRID_FIELD_NAME, MSG.chart_themepanel_header_themes()); name.setType(ListGridFieldType.TEXT); ListGridField actions = new ListGridField(GRID_FIELD_ACTIONS, MSG.chart_themepanel_header_actions(), 100); list.setFields(active, name, actions); } /** Get Current Cross-section Masters uuid. */ public String getCurrentCSMaster() { return currentCSMasterUUID; } /** Set Current Cross-section Masters uuid. */ public void setCurrentCSMaster(String currentMasterUuid) { this.currentCSMasterUUID = currentMasterUuid; } /** Returns name of cross section area facets. */ @Override protected String getAreaFacetName() { return "cross_section.area"; } /** * 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. */ @Override protected boolean areAreaCompatible(Theme a, Theme b) { if (a.equals(b)) { return false; } return (a.getFacet().equals("cross_section") || a.getFacet().endsWith("line")) && (b.getFacet().equals("cross_section") || b.getFacet().endsWith("line")); } /** * True if context menu should contain 'create area' submenu on * this theme. */ @Override protected boolean canArea(Theme a) { return a.getFacet().equals("cross_section") || a.getFacet().equals("cross_section_water_line") || a.getFacet().endsWith("line"); } protected String themeHash(Theme theme) { return theme.getArtifact() + theme.getFacet() + theme.getIndex(); } /** * Include synchron navigation item. */ @Override protected Menu getSingleContextMenu(final ListGridRecord[] records) { Menu contextMenu = super.getSingleContextMenu(records); Theme facetTheme = ((FacetRecord)records[0]).getTheme(); String item = facetTheme.getFacet(); if (item.equals("cross_section")) { // Synchron checking. MenuItem synchronNavigationMenuItem = new MenuItem(); final String themeHash = themeHash(facetTheme); if (synchronCrossSectionThemes.contains(themeHash)) { synchronNavigationMenuItem.setTitle(MSG.chart_themepanel_asynchron()); synchronNavigationMenuItem.addClickHandler(new ClickHandler() { public void onClick(MenuItemClickEvent evt) { synchronCrossSectionThemes.remove (themeHash); } }); } else { synchronNavigationMenuItem.setTitle(MSG.chart_themepanel_synchron()); synchronNavigationMenuItem.addClickHandler(new ClickHandler() { public void onClick(MenuItemClickEvent evt) { synchronCrossSectionThemes.add (themeHash); } }); } contextMenu.addItem(synchronNavigationMenuItem); } return contextMenu; } /** * This method is used to clear the current theme grid and add new updated * data. */ @Override protected void updateGrid() { GWT.log("CrossSectionChartThemePanel.updateGrid"); ListGridRecord[] selected = list.getSelectedRecords(); clearGrid(); ThemeList themeList = getThemeList(); if (themeList == null) { GWT.log("ERROR: No theme list."); return; } int count = themeList.getThemeCount(); for (int i = 1; i <= count; i++) { Theme theme = themeList.getThemeAt(i); if (theme == null) { continue; } if (theme.getFacet().equals("empty.facet")) { theme.setVisible(0); } if (theme.getVisible() == 0) { continue; } if (theme.getFacet().equals("cross_section")) { addToReferences(theme); } FacetRecord newRecord = createRecord(theme); addFacetRecord(newRecord); String newArtifact = theme.getArtifact(); String newFacet = theme.getFacet(); int newIndex = theme.getIndex(); for (ListGridRecord r: selected) { FacetRecord sel = (FacetRecord) r; Theme oldTheme = sel.getTheme(); if (oldTheme.getArtifact().equals(newArtifact) && oldTheme.getFacet().equals(newFacet) && oldTheme.getIndex() == newIndex) { list.selectRecord(newRecord); } } } fireOutputParameterChanged(); } /** * Adds a cross section theme to the master artifacts combobox and finds * a new master if necessary. * * @param theme The cross section theme. */ protected void addToReferences(Theme theme) { if (theme.getVisible() != 0) { masters.put(theme.getArtifact(), theme.getDescription()); masterCb.setValueMap(masters); } findCurrentCSMaster(); if (masterCb.getSelectedRecord() == null) { masterCb.setValue(getCurrentCSMaster()); } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :