Mercurial > dive4elements > river
view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ThemePanel.java @ 9416:05405292a7ca
Navigationtheme panel now shows themes of dWt and WQ charts grayed out, if the current station is outside the valid range of the theme.
author | gernotbelger |
---|---|
date | Thu, 16 Aug 2018 16:28:03 +0200 |
parents | 5e38e2924c07 |
children | cff7636035ce |
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde * Software engineering by Intevation GmbH * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.client.client.ui; import java.util.ArrayList; import java.util.List; import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.FLYSConstants; import org.dive4elements.river.client.client.event.HasOutputParameterChangeHandlers; import org.dive4elements.river.client.client.event.HasRedrawRequestHandlers; import org.dive4elements.river.client.client.event.OnMoveEvent; import org.dive4elements.river.client.client.event.OnMoveHandler; import org.dive4elements.river.client.client.event.OutputParameterChangeEvent; import org.dive4elements.river.client.client.event.OutputParameterChangeHandler; import org.dive4elements.river.client.client.event.RedrawRequestEvent; import org.dive4elements.river.client.client.event.RedrawRequestEvent.Type; import org.dive4elements.river.client.client.event.RedrawRequestHandler; import org.dive4elements.river.client.client.services.CollectionAttributeService; import org.dive4elements.river.client.client.services.CollectionAttributeServiceAsync; import org.dive4elements.river.client.client.services.CollectionItemAttributeService; import org.dive4elements.river.client.client.services.CollectionItemAttributeServiceAsync; import org.dive4elements.river.client.shared.model.Collection; import org.dive4elements.river.client.shared.model.CollectionItemAttribute; import org.dive4elements.river.client.shared.model.FacetRecord; import org.dive4elements.river.client.shared.model.OutputMode; import org.dive4elements.river.client.shared.model.Theme; import org.dive4elements.river.client.shared.model.ThemeList; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.util.BooleanCallback; import com.smartgwt.client.util.SC; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.grid.ListGrid; import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.grid.events.EditCompleteEvent; import com.smartgwt.client.widgets.grid.events.EditCompleteHandler; import com.smartgwt.client.widgets.grid.events.RowContextClickEvent; import com.smartgwt.client.widgets.grid.events.RowContextClickHandler; import com.smartgwt.client.widgets.menu.Menu; import com.smartgwt.client.widgets.menu.MenuItem; import com.smartgwt.client.widgets.menu.events.ClickHandler; import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent; /** * ThemePanel on the left in CollectionView. * Contains control widgets for "themes", which are plotted in * a diagram (chart). * * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public abstract class ThemePanel extends Canvas implements OnMoveHandler, EditCompleteHandler, HasOutputParameterChangeHandlers, HasRedrawRequestHandlers { private final CollectionAttributeServiceAsync updater = GWT.create(CollectionAttributeService.class); /** The service used to get collection item attributes. */ private final CollectionItemAttributeServiceAsync itemAttributeService = GWT.create(CollectionItemAttributeService.class); /** i18ner. */ protected final FLYSConstants MSG = GWT.create(FLYSConstants.class); /** List of OutParameterChangedHandler. */ private final List<OutputParameterChangeHandler> outHandlers; /** List of ChartShallRedrawHandler. */ protected final List<RedrawRequestHandler> redrawRequestHandlers; protected final OutputMode mode; protected final ThemeNavigationPanel navigation; protected final ListGrid list; /** The collection view */ protected CollectionView view; private final IThemeRecordHandler recordHandler; /** * Setup Grid, navigation bar. * * @param collection * Collection for which to show themes. */ public ThemePanel(final OutputMode mode, final CollectionView view, final IThemeRecordHandler recordHandler) { this.mode = mode; this.recordHandler = recordHandler; this.list = createGrid(); this.view = view; this.list.addRowContextClickHandler(new RowContextClickHandler() { @Override public void onRowContextClick(final RowContextClickEvent event) { final ListGridRecord[] records = ThemePanel.this.list.getSelectedRecords(); Menu menu = null; if (records == null || records.length == 0) { return; } else if (records.length == 1) { menu = getSingleContextMenu(records); } else if (records.length > 1) { menu = getMultiContextMenu(records); } if (menu != null) { ThemePanel.this.list.setContextMenu(menu); menu.showContextMenu(); event.cancel(); } } }); this.redrawRequestHandlers = new ArrayList<RedrawRequestHandler>(); this.outHandlers = new ArrayList<OutputParameterChangeHandler>(); this.navigation = new ThemeNavigationPanel(); this.navigation.addOnMoveHandler(this); this.setShowResizeBar(true); } public abstract void activateTheme(Theme theme, boolean active); /** * Replace the current collection with a new one. <b>NOTE: this operation * triggers updateGrid() which modifies the themes in the grid.</b> * * @param collection * The new collection object. */ protected void setCollection(final Collection collection) { // Set collection of view, but do not trigger event shooting. this.view.setCollection(collection, true); updateGrid(); } /** Get Collection. */ public Collection getCollection() { return this.view.getCollection(); } /** * Returns the ThemeList of the current collection and output mode. * * @return the current ThemeList. */ public ThemeList getThemeList() { return getCollection().getThemeList(this.mode.getName()); } public ListGridRecord[] getSelectedRecords() { return this.list.getSelectedRecords(); } /** * Registers a new OutputParameterChangeHandler. * * @param h * The new handler. */ @Override public void addOutputParameterChangeHandler(final OutputParameterChangeHandler h) { if (h != null) { this.outHandlers.add(h); } } /** * Registers a RedrawRequestHandler. * * @param h * The new handler. */ @Override public void addRedrawRequestHandler(final RedrawRequestHandler h) { if (h != null) { this.redrawRequestHandlers.add(h); } } /** * Request a redraw of e.g. a Chart. */ final public void requestRedraw() { for (final RedrawRequestHandler handler : this.redrawRequestHandlers) { handler.onRedrawRequest(new RedrawRequestEvent(Type.DEFAULT)); } } /** * Called when the attribution of an output changed. It informs the * registered handlers about the changes. */ protected void fireOutputParameterChanged() { final OutputParameterChangeEvent evt = new OutputParameterChangeEvent(); for (final OutputParameterChangeHandler handler : this.outHandlers) { handler.onOutputParameterChanged(evt); } } /** Registers the CollectionView associated to this ThemePanel. */ public void setCollectionView(final CollectionView view) { this.view = view; } /** * This method is used to clear the current theme grid and add new updated * data. */ protected void updateGrid() { GWT.log("ThemePanel.updateGrid"); final ListGridRecord[] selected = this.list.getSelectedRecords(); clearGrid(); final ThemeList themeList = getThemeList(); if (themeList == null) { GWT.log("ERROR: No theme list."); return; } final int count = themeList.getThemeCount(); for (int i = 1; i <= count; i++) { final Theme theme = themeList.getThemeAt(i); if (theme == null) { continue; } if (theme.getFacet().equals("empty.facet")) { theme.setVisible(0); } if (theme.getVisible() == 0) { continue; } final FacetRecord newRecord = createRecord(theme); addFacetRecord(newRecord); final String newArtifact = theme.getArtifact(); final String newFacet = theme.getFacet(); final int newIndex = theme.getIndex(); for (final ListGridRecord r : selected) { final FacetRecord sel = (FacetRecord) r; final Theme oldTheme = sel.getTheme(); if (oldTheme.getArtifact().equals(newArtifact) && oldTheme.getFacet().equals(newFacet) && oldTheme.getIndex() == newIndex) { this.list.selectRecord(newRecord); } } } updateThemes(); fireOutputParameterChanged(); } /** Adds given Record to the list (table). */ protected void addFacetRecord(final FacetRecord rec) { this.list.addData(rec); } /** Create a FacetRecord that wraps given theme. */ protected final FacetRecord createRecord(final Theme theme) { return new FacetRecord(theme); } /** * This method triggers the CollectionAttributeService. Based on the current * collectin settings, the attribute of the collection is modified or not. * But in every case, we will get a new collection object - which might be * the same as the current one. */ public void updateCollection() { final Config config = Config.getInstance(); final String loc = config.getLocale(); GWT.log("ThemePanel.updateCollection via RPC now"); // Don't forget to enable the panel after the request has finished! disable(); this.updater.update(getCollection(), loc, new AsyncCallback<Collection>() { @Override public void onFailure(final Throwable caught) { GWT.log("Could not update collection attributes."); SC.warn(ThemePanel.this.MSG.getString(caught.getMessage())); enable(); } @Override public void onSuccess(final Collection collection) { setCollection(collection); enable(); } }); } /** * Create and configure the Grid to display. */ protected ListGrid createGrid() { final ListGrid grid = new ListGrid(); grid.setLeaveScrollbarGap(false); return grid; } /** * A method that removes all records from theme grid. */ protected void clearGrid() { final ListGridRecord[] records = this.list.getRecords(); if (records == null || records.length == 0) { return; } for (final ListGridRecord record : records) { this.list.removeData(record); } } /** Return 'separator'- menu-item. */ protected MenuItem createSeparator() { final MenuItem separator = new MenuItem(); separator.setIsSeparator(true); return separator; } /** * Get the context menu for a (right mouse button)click on a single item. */ protected Menu getSingleContextMenu(final ListGridRecord[] records) { final Menu menu = new Menu(); menu.addItem(createActivateItem(records)); menu.addItem(createDeactivateItem(records)); menu.addItem(createRemoveItem(records)); menu.addItem(createSeparator()); menu.addItem(createPropertiesItem(records)); return menu; } protected Menu getMultiContextMenu(final ListGridRecord[] records) { final Menu menu = new Menu(); menu.addItem(createActivateItem(records)); menu.addItem(createDeactivateItem(records)); menu.addItem(createRemoveItem(records)); return menu; } /** The properties menu item (opens style editor on click). */ protected MenuItem createPropertiesItem(final ListGridRecord[] records) { final MenuItem properties = new MenuItem(this.MSG.properties()); properties.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { GWT.log("clicked properties"); for (final ListGridRecord record : records) { openStyleEditor((FacetRecord) record); } } }); return properties; } protected MenuItem createActivateItem(final ListGridRecord[] records) { final MenuItem activate = new MenuItem(this.MSG.activateTheme()); activate.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { for (final ListGridRecord record : records) { final FacetRecord facet = (FacetRecord) record; activateTheme(facet.getTheme(), true); } updateCollection(); } }); return activate; } protected MenuItem createDeactivateItem(final ListGridRecord[] records) { final MenuItem deactivate = new MenuItem(this.MSG.deactivateTheme()); deactivate.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { for (final ListGridRecord record : records) { final FacetRecord facet = (FacetRecord) record; activateTheme(facet.getTheme(), false); } updateCollection(); } }); return deactivate; } /** Remove given themes (not asking for confirmation). */ protected void removeThemes(final ListGridRecord[] records) { for (final ListGridRecord record : records) { final FacetRecord facet = (FacetRecord) record; final Theme theme = facet.getTheme(); theme.setVisible(0); theme.setActive(0); updateCollection(); } } /** Create menu item for removing theme(s). Will ask for confirmation. */ protected MenuItem createRemoveItem(final ListGridRecord[] records) { final MenuItem remove = new MenuItem(this.MSG.removeTheme()); remove.addClickHandler(new ClickHandler() { @Override public void onClick(final MenuItemClickEvent evt) { SC.ask(ThemePanel.this.MSG.askThemeRemove(), new BooleanCallback() { @Override public void execute(final Boolean value) { if (value) { removeThemes(records); } } }); } }); return remove; } /** * This method is called after a cell in the theme grid has been modified. * * @param event * The event that stores information about the modified record. */ @Override public void onEditComplete(final EditCompleteEvent event) { GWT.log("Edited record."); final int row = event.getRowNum(); final FacetRecord rec = (FacetRecord) this.list.getRecord(row); final Theme theme = rec.getTheme(); theme.setDescription(rec.getName()); activateTheme(theme, rec.getActive()); updateCollection(); } /** * This method should be defined in subclasses that wants to listen to this * event. * * @param theme * The theme that is moved. * @param oldIdx * The index of the theme before it was moved. * @param newIdx * The index of the theme after it was moved. */ protected void fireThemeMoved(final Theme theme, final int oldIdx, final int newIdx) { // Do nothing } @Override public void onMove(final OnMoveEvent event) { final int type = event.getType(); GWT.log("ThemePanel.onMove: " + type); final ListGridRecord[] records = this.list.getSelectedRecords(); if (records == null || records.length == 0) { GWT.log("ThemePanel.onMove: No records selected."); return; } switch (type) { case 0: moveRecordsTop(records); break; case 1: moveRecordsUp(records); break; case 2: moveRecordsDown(records); break; case 3: moveRecordsBottom(records); break; } updateCollection(); } /** * Moves the selected grid records (themes) to the top of the grid. * * @param records * The selected themes in the list. Null not permitted. */ protected void moveRecordsTop(final ListGridRecord[] records) { final ThemeList themeList = getThemeList(); int idx = 1; for (final ListGridRecord record : records) { final Theme theme = ((FacetRecord) record).getTheme(); fireThemeMoved(theme, theme.getPosition(), idx); themeList.setThemePosition(theme, idx++); } updateGrid(); } /** * Moves the selected grid records (themes) one step up. * * @param records * The selected themes in the list. Null not permitted. */ protected void moveRecordsUp(final ListGridRecord[] records) { final ThemeList themeList = getThemeList(); final int[] newPos = new int[records.length]; for (int i = 0; i < records.length; i++) { final Theme theme = ((FacetRecord) records[i]).getTheme(); newPos[i] = theme.getPosition() - 1; } for (int i = 0; i < records.length; i++) { final Theme theme = ((FacetRecord) records[i]).getTheme(); fireThemeMoved(theme, theme.getPosition(), newPos[i]); themeList.setThemePosition(theme, newPos[i]); } updateGrid(); } /** * Moves the selected grid records (themes) one step down. * * @param records * The selected themes in the list. Null not permitted. */ protected void moveRecordsDown(final ListGridRecord[] records) { final ThemeList themeList = getThemeList(); final int[] newPos = new int[records.length]; for (int i = records.length - 1; i >= 0; i--) { final Theme theme = ((FacetRecord) records[i]).getTheme(); newPos[i] = theme.getPosition() + 1; } for (int i = records.length - 1; i >= 0; i--) { final Theme theme = ((FacetRecord) records[i]).getTheme(); fireThemeMoved(theme, theme.getPosition(), newPos[i]); themeList.setThemePosition(theme, newPos[i]); } updateGrid(); } /** * Moves the selected grid records (themes) to the bottom of the grid. * * @param records * The selected themes in the list. Null not permitted. */ protected void moveRecordsBottom(final ListGridRecord[] records) { final ThemeList themeList = getThemeList(); int idx = themeList.getThemeCount(); for (int i = records.length - 1; i >= 0; i--) { final Theme theme = ((FacetRecord) records[i]).getTheme(); fireThemeMoved(theme, theme.getPosition(), idx); themeList.setThemePosition(theme, idx--); } updateGrid(); } protected void openStyleEditor(final FacetRecord record) { final Config config = Config.getInstance(); final String locale = config.getLocale(); final String artifact = record.getTheme().getArtifact(); this.itemAttributeService.getCollectionItemAttribute(this.getCollection(), artifact, locale, new AsyncCallback<CollectionItemAttribute>() { @Override public void onFailure(final Throwable caught) { SC.warn(ThemePanel.this.MSG.getString(caught.getMessage())); } @Override public void onSuccess(final CollectionItemAttribute cia) { GWT.log("Successfully loaded collectionitem attributes."); showStyleEditor(cia, record); } }); } protected void showStyleEditor(final CollectionItemAttribute cia, final FacetRecord record) { final StyleEditorWindow win = new StyleEditorWindow(getCollection(), cia, record); win.setThemePanel(this); win.centerInPage(); win.show(); } /** Get OutputMode of this Panel. */ public OutputMode getMode() { return this.mode; } public void updateThemes() { final ListGridRecord[] records = this.list.getRecords(); for (final ListGridRecord record : records) { final FacetRecord facetRecord = (FacetRecord) record; this.recordHandler.handle(facetRecord); } this.list.markForRedraw(); } }