changeset 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 9744ce3c3853
children 46e3e23cca0b
files gwt-client/src/main/java/org/dive4elements/river/client/client/ui/IThemeRecordHandler.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/NoopThemeRecordHandler.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ThemePanel.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartOutputTab.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartThemePanel.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartToolbar.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/CrossSectionChartThemePanel.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartRecordHandler.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/OverviewOutputTab.java gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapThemePanel.java gwt-client/src/main/java/org/dive4elements/river/client/shared/model/AttributedTheme.java gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ChartMode.java gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FacetRecord.java gwt-client/src/main/webapp/FLYS.css
diffstat 15 files changed, 706 insertions(+), 605 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/IThemeRecordHandler.java	Thu Aug 16 16:28:03 2018 +0200
@@ -0,0 +1,21 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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 org.dive4elements.river.client.shared.model.FacetRecord;
+
+/**
+ * Implementors of this interface are allowed to manipulate the records of the theme panel.
+ *
+ * @author Gernot Belger
+ */
+public interface IThemeRecordHandler {
+    void handle(FacetRecord facetRecord);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/NoopThemeRecordHandler.java	Thu Aug 16 16:28:03 2018 +0200
@@ -0,0 +1,25 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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 org.dive4elements.river.client.shared.model.FacetRecord;
+
+/**
+ * Default implementation of {@link IThemeRecordHandler} that does nothing.
+ *
+ * @author Gernot Belger
+ */
+public final class NoopThemeRecordHandler implements IThemeRecordHandler {
+
+    @Override
+    public void handle(final FacetRecord facetRecord) {
+        /* we do nothing */
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ThemePanel.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ThemePanel.java	Thu Aug 16 16:28:03 2018 +0200
@@ -8,22 +8,8 @@
 
 package org.dive4elements.river.client.client.ui;
 
-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;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.dive4elements.river.client.client.Config;
 import org.dive4elements.river.client.client.FLYSConstants;
@@ -47,8 +33,21 @@
 import org.dive4elements.river.client.shared.model.Theme;
 import org.dive4elements.river.client.shared.model.ThemeList;
 
-import java.util.ArrayList;
-import java.util.List;
+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.
@@ -57,67 +56,62 @@
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public abstract class ThemePanel
-extends               Canvas
-implements            OnMoveHandler,
-                      EditCompleteHandler,
-                      HasOutputParameterChangeHandlers,
-                      HasRedrawRequestHandlers
-{
-    protected CollectionAttributeServiceAsync updater =
-        GWT.create(CollectionAttributeService.class);
+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. */
-    protected CollectionItemAttributeServiceAsync itemAttributeService =
-        GWT.create(CollectionItemAttributeService.class);
+    private final CollectionItemAttributeServiceAsync itemAttributeService = GWT.create(CollectionItemAttributeService.class);
 
     /** i18ner. */
-    protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
+    protected final FLYSConstants MSG = GWT.create(FLYSConstants.class);
 
     /** List of OutParameterChangedHandler. */
-    protected List<OutputParameterChangeHandler> outHandlers;
+    private final List<OutputParameterChangeHandler> outHandlers;
 
     /** List of ChartShallRedrawHandler. */
-    protected List<RedrawRequestHandler> redrawRequestHandlers;
-
-    protected OutputMode mode;
+    protected final List<RedrawRequestHandler> redrawRequestHandlers;
 
-    protected ThemeNavigationPanel navigation;
-    protected ListGrid list;
+    protected final OutputMode mode;
 
-    /** The collection view*/
+    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.
+     *
+     * @param collection
+     *            Collection for which to show themes.
      */
-    public ThemePanel(
-        OutputMode mode,
-        CollectionView view
-    ) {
-        this.mode       = mode;
-        this.list       = createGrid();
-        this.view       = view;
-        list.addRowContextClickHandler(new RowContextClickHandler() {
+    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(RowContextClickEvent event) {
-                ListGridRecord[] records = list.getSelectedRecords();
+            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) {
+                } else if (records.length == 1) {
                     menu = getSingleContextMenu(records);
-                }
-                else if (records.length > 1) {
+                } else if (records.length > 1) {
                     menu = getMultiContextMenu(records);
                 }
 
                 if (menu != null) {
-                    list.setContextMenu(menu);
+                    ThemePanel.this.list.setContextMenu(menu);
                     menu.showContextMenu();
 
                     event.cancel();
@@ -127,104 +121,98 @@
 
         this.redrawRequestHandlers = new ArrayList<RedrawRequestHandler>();
         this.outHandlers = new ArrayList<OutputParameterChangeHandler>();
-        this.navigation  = new ThemeNavigationPanel();
+        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.
+     * @param collection
+     *            The new collection object.
      */
-    protected void setCollection(Collection collection) {
+    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 view.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(mode.getName());
+        return getCollection().getThemeList(this.mode.getName());
     }
 
     public ListGridRecord[] getSelectedRecords() {
-        return list.getSelectedRecords();
+        return this.list.getSelectedRecords();
     }
 
     /**
      * Registers a new OutputParameterChangeHandler.
      *
-     * @param h The new handler.
+     * @param h
+     *            The new handler.
      */
     @Override
-    public void addOutputParameterChangeHandler(OutputParameterChangeHandler h){
+    public void addOutputParameterChangeHandler(final OutputParameterChangeHandler h) {
         if (h != null) {
-            outHandlers.add(h);
+            this.outHandlers.add(h);
         }
     }
 
-
     /**
      * Registers a RedrawRequestHandler.
      *
-     * @param h The new handler.
+     * @param h
+     *            The new handler.
      */
     @Override
-    public void addRedrawRequestHandler(RedrawRequestHandler h){
+    public void addRedrawRequestHandler(final RedrawRequestHandler h) {
         if (h != null) {
-            redrawRequestHandlers.add(h);
+            this.redrawRequestHandlers.add(h);
         }
     }
 
-
     /**
      * Request a redraw of e.g. a Chart.
      */
     final public void requestRedraw() {
-        for (RedrawRequestHandler handler: redrawRequestHandlers) {
+        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() {
-        OutputParameterChangeEvent evt = new OutputParameterChangeEvent();
+        final OutputParameterChangeEvent evt = new OutputParameterChangeEvent();
 
-        for (OutputParameterChangeHandler handler: outHandlers) {
+        for (final OutputParameterChangeHandler handler : this.outHandlers) {
             handler.onOutputParameterChanged(evt);
         }
     }
 
-
     /** Registers the CollectionView associated to this ThemePanel. */
-    public void setCollectionView(CollectionView view) {
+    public void setCollectionView(final CollectionView view) {
         this.view = view;
     }
 
-
     /**
      * This method is used to clear the current theme grid and add new updated
      * data.
@@ -232,21 +220,21 @@
     protected void updateGrid() {
         GWT.log("ThemePanel.updateGrid");
 
-        ListGridRecord[] selected = list.getSelectedRecords();
+        final ListGridRecord[] selected = this.list.getSelectedRecords();
 
         clearGrid();
 
-        ThemeList themeList = getThemeList();
+        final ThemeList themeList = getThemeList();
 
         if (themeList == null) {
             GWT.log("ERROR: No theme list.");
             return;
         }
 
-        int count = themeList.getThemeCount();
+        final int count = themeList.getThemeCount();
 
         for (int i = 1; i <= count; i++) {
-            Theme theme = themeList.getThemeAt(i);
+            final Theme theme = themeList.getThemeAt(i);
 
             if (theme == null) {
                 continue;
@@ -260,41 +248,38 @@
                 continue;
             }
 
-            FacetRecord newRecord = createRecord(theme);
+            final FacetRecord newRecord = createRecord(theme);
             addFacetRecord(newRecord);
 
-            String newArtifact = theme.getArtifact();
-            String newFacet    = theme.getFacet();
-            int    newIndex    = theme.getIndex();
+            final String newArtifact = theme.getArtifact();
+            final String newFacet = theme.getFacet();
+            final int newIndex = theme.getIndex();
 
-            for (ListGridRecord r: selected) {
-                FacetRecord sel = (FacetRecord) r;
-                Theme oldTheme  = sel.getTheme();
+            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) {
-                    list.selectRecord(newRecord);
+                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(FacetRecord rec) {
-        list.addData(rec);
+    protected void addFacetRecord(final FacetRecord rec) {
+        this.list.addData(rec);
     }
 
-
     /** Create a FacetRecord that wraps given theme. */
-    protected FacetRecord createRecord(Theme 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.
@@ -303,25 +288,24 @@
      */
     public void updateCollection() {
         final Config config = Config.getInstance();
-        final String loc    = config.getLocale();
+        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();
 
-        updater.update(getCollection(), loc, new AsyncCallback<Collection>() {
+        this.updater.update(getCollection(), loc, new AsyncCallback<Collection>() {
             @Override
-            public void onFailure(Throwable caught) {
+            public void onFailure(final Throwable caught) {
                 GWT.log("Could not update collection attributes.");
-                SC.warn(MSG.getString(caught.getMessage()));
+                SC.warn(ThemePanel.this.MSG.getString(caught.getMessage()));
 
                 enable();
             }
 
-
             @Override
-            public void onSuccess(Collection collection) {
+            public void onSuccess(final Collection collection) {
                 setCollection(collection);
 
                 enable();
@@ -329,51 +313,43 @@
         });
     }
 
-
     /**
      * Create and configure the Grid to display.
      */
     protected ListGrid createGrid() {
-        ListGrid grid = createNewGrid();
+        final ListGrid grid = new ListGrid();
         grid.setLeaveScrollbarGap(false);
 
         return grid;
     }
 
-
-    protected ListGrid createNewGrid() {
-        return new ListGrid();
-    }
-
-
     /**
      * A method that removes all records from theme grid.
      */
     protected void clearGrid() {
-        ListGridRecord[] records = list.getRecords();
+        final ListGridRecord[] records = this.list.getRecords();
 
         if (records == null || records.length == 0) {
             return;
         }
 
-        for (ListGridRecord record: records) {
-            list.removeData(record);
+        for (final ListGridRecord record : records) {
+            this.list.removeData(record);
         }
     }
 
     /** Return 'separator'- menu-item. */
     protected MenuItem createSeparator() {
-        MenuItem separator = new MenuItem();
+        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) {
-        Menu menu = new Menu();
+        final Menu menu = new Menu();
 
         menu.addItem(createActivateItem(records));
         menu.addItem(createDeactivateItem(records));
@@ -384,9 +360,8 @@
         return menu;
     }
 
-
     protected Menu getMultiContextMenu(final ListGridRecord[] records) {
-        Menu menu = new Menu();
+        final Menu menu = new Menu();
 
         menu.addItem(createActivateItem(records));
         menu.addItem(createDeactivateItem(records));
@@ -395,16 +370,15 @@
         return menu;
     }
 
-
     /** The properties menu item (opens style editor on click). */
     protected MenuItem createPropertiesItem(final ListGridRecord[] records) {
-        MenuItem properties = new MenuItem(MSG.properties());
+        final MenuItem properties = new MenuItem(this.MSG.properties());
 
         properties.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(MenuItemClickEvent evt) {
+            public void onClick(final MenuItemClickEvent evt) {
                 GWT.log("clicked properties");
-                for (ListGridRecord record: records) {
+                for (final ListGridRecord record : records) {
                     openStyleEditor((FacetRecord) record);
                 }
             }
@@ -413,15 +387,14 @@
         return properties;
     }
 
-
     protected MenuItem createActivateItem(final ListGridRecord[] records) {
-        MenuItem activate = new MenuItem(MSG.activateTheme());
+        final MenuItem activate = new MenuItem(this.MSG.activateTheme());
 
         activate.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(MenuItemClickEvent evt) {
-                for (ListGridRecord record: records) {
-                    FacetRecord facet = (FacetRecord) record;
+            public void onClick(final MenuItemClickEvent evt) {
+                for (final ListGridRecord record : records) {
+                    final FacetRecord facet = (FacetRecord) record;
                     activateTheme(facet.getTheme(), true);
                 }
 
@@ -432,15 +405,14 @@
         return activate;
     }
 
-
     protected MenuItem createDeactivateItem(final ListGridRecord[] records) {
-        MenuItem deactivate = new MenuItem(MSG.deactivateTheme());
+        final MenuItem deactivate = new MenuItem(this.MSG.deactivateTheme());
 
         deactivate.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(MenuItemClickEvent evt) {
-                for (ListGridRecord record: records) {
-                    FacetRecord facet = (FacetRecord) record;
+            public void onClick(final MenuItemClickEvent evt) {
+                for (final ListGridRecord record : records) {
+                    final FacetRecord facet = (FacetRecord) record;
                     activateTheme(facet.getTheme(), false);
                 }
 
@@ -451,29 +423,27 @@
         return deactivate;
     }
 
-
     /** Remove given themes (not asking for confirmation). */
     protected void removeThemes(final ListGridRecord[] records) {
-        for (ListGridRecord record: records) {
-            FacetRecord facet = (FacetRecord) record;
-            Theme theme = facet.getTheme();
+        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) {
-        MenuItem remove = new MenuItem(MSG.removeTheme());
+        final MenuItem remove = new MenuItem(this.MSG.removeTheme());
 
         remove.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(MenuItemClickEvent evt) {
-                SC.ask(MSG.askThemeRemove(), new BooleanCallback() {
+            public void onClick(final MenuItemClickEvent evt) {
+                SC.ask(ThemePanel.this.MSG.askThemeRemove(), new BooleanCallback() {
                     @Override
-                    public void execute(Boolean value) {
+                    public void execute(final Boolean value) {
                         if (value) {
                             removeThemes(records);
                         }
@@ -485,20 +455,20 @@
         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.
+     * @param event
+     *            The event that stores information about the modified record.
      */
     @Override
-    public void onEditComplete(EditCompleteEvent event) {
+    public void onEditComplete(final EditCompleteEvent event) {
         GWT.log("Edited record.");
 
-        int         row = event.getRowNum();
-        FacetRecord rec = (FacetRecord) list.getRecord(row);
+        final int row = event.getRowNum();
+        final FacetRecord rec = (FacetRecord) this.list.getRecord(row);
 
-        Theme theme = rec.getTheme();
+        final Theme theme = rec.getTheme();
 
         theme.setDescription(rec.getName());
         activateTheme(theme, rec.getActive());
@@ -506,27 +476,28 @@
         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.
+     * @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(Theme theme, int oldIdx, int newIdx) {
+    protected void fireThemeMoved(final Theme theme, final int oldIdx, final int newIdx) {
         // Do nothing
     }
 
-
     @Override
-    public void onMove(OnMoveEvent event) {
-        int type = event.getType();
+    public void onMove(final OnMoveEvent event) {
+        final int type = event.getType();
 
         GWT.log("ThemePanel.onMove: " + type);
 
-        ListGridRecord[] records = list.getSelectedRecords();
+        final ListGridRecord[] records = this.list.getSelectedRecords();
 
         if (records == null || records.length == 0) {
             GWT.log("ThemePanel.onMove: No records selected.");
@@ -534,28 +505,36 @@
         }
 
         switch (type) {
-            case 0: moveRecordsTop(records); break;
-            case 1: moveRecordsUp(records); break;
-            case 2: moveRecordsDown(records); break;
-            case 3: moveRecordsBottom(records); break;
+        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.
+     * @param records
+     *            The selected themes in the list. Null not permitted.
      */
-    protected void moveRecordsTop(ListGridRecord[] records) {
-        ThemeList themeList = getThemeList();
+    protected void moveRecordsTop(final ListGridRecord[] records) {
+        final ThemeList themeList = getThemeList();
 
         int idx = 1;
 
-        for (ListGridRecord record: records) {
-            Theme theme = ((FacetRecord) record).getTheme();
+        for (final ListGridRecord record : records) {
+            final Theme theme = ((FacetRecord) record).getTheme();
             fireThemeMoved(theme, theme.getPosition(), idx);
             themeList.setThemePosition(theme, idx++);
         }
@@ -563,49 +542,24 @@
         updateGrid();
     }
 
-
     /**
      * Moves the selected grid records (themes) one step up.
      *
-     * @param records The selected themes in the list. Null not permitted.
+     * @param records
+     *            The selected themes in the list. Null not permitted.
      */
-    protected void moveRecordsUp(ListGridRecord[] records) {
-        ThemeList themeList = getThemeList();
-
-        int[] newPos = new int[records.length];
+    protected void moveRecordsUp(final ListGridRecord[] records) {
+        final ThemeList themeList = getThemeList();
 
-        for (int i = 0; i < records.length ; i++) {
-            Theme theme = ((FacetRecord) records[i]).getTheme();
-            newPos[i]   = theme.getPosition() - 1;
-        }
+        final int[] newPos = new int[records.length];
 
-        for (int i = 0; i < records.length ; i++) {
-            Theme theme = ((FacetRecord) records[i]).getTheme();
-            fireThemeMoved(theme, theme.getPosition(), newPos[i]);
-            themeList.setThemePosition(theme, newPos[i]);
+        for (int i = 0; i < records.length; i++) {
+            final Theme theme = ((FacetRecord) records[i]).getTheme();
+            newPos[i] = theme.getPosition() - 1;
         }
 
-        updateGrid();
-    }
-
-
-    /**
-     * Moves the selected grid records (themes) one step down.
-     *
-     * @param records The selected themes in the list. Null not permitted.
-     */
-    protected void moveRecordsDown(ListGridRecord[] records) {
-        ThemeList themeList = getThemeList();
-
-        int[] newPos = new int[records.length];
-
-        for (int i = records.length-1; i >= 0; i--) {
-            Theme theme = ((FacetRecord) records[i]).getTheme();
-            newPos[i] = theme.getPosition()+1;
-        }
-
-        for (int i = records.length-1; i >= 0; i--) {
-            Theme theme = ((FacetRecord) records[i]).getTheme();
+        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]);
         }
@@ -613,19 +567,44 @@
         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.
+     * @param records
+     *            The selected themes in the list. Null not permitted.
      */
-    protected void moveRecordsBottom(ListGridRecord[] records) {
-        ThemeList themeList = getThemeList();
+    protected void moveRecordsBottom(final ListGridRecord[] records) {
+        final ThemeList themeList = getThemeList();
 
         int idx = themeList.getThemeCount();
 
-        for (int i = records.length-1; i >= 0; i--) {
-            Theme theme = ((FacetRecord) records[i]).getTheme();
+        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--);
         }
@@ -633,48 +612,47 @@
         updateGrid();
     }
 
-
     protected void openStyleEditor(final FacetRecord record) {
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
-
-        String artifact = record.getTheme().getArtifact();
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        itemAttributeService.getCollectionItemAttribute(
-            this.getCollection(),
-            artifact,
-            locale,
-            new AsyncCallback<CollectionItemAttribute>() {
-                @Override
-                public void onFailure (Throwable caught) {
-                    SC.warn(MSG.getString(caught.getMessage()));
-                }
-                @Override
-                public void onSuccess(CollectionItemAttribute cia) {
-                    GWT.log("Successfully loaded collectionitem attributes.");
-                    showStyleEditor(cia, record);
-                }
-            });
+        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(
-        CollectionItemAttribute cia,
-        FacetRecord record)
-    {
-        StyleEditorWindow win = new StyleEditorWindow(
-            getCollection(),
-            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;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+    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();
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartOutputTab.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartOutputTab.java	Thu Aug 16 16:28:03 2018 +0200
@@ -31,6 +31,8 @@
 import org.dive4elements.river.client.client.services.ChartInfoService;
 import org.dive4elements.river.client.client.services.ChartInfoServiceAsync;
 import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.IThemeRecordHandler;
+import org.dive4elements.river.client.client.ui.NoopThemeRecordHandler;
 import org.dive4elements.river.client.client.ui.OutputTab;
 import org.dive4elements.river.client.shared.Transform2D;
 import org.dive4elements.river.client.shared.model.Axis;
@@ -74,9 +76,6 @@
      * coordinates. */
     protected Transform2D[] transformer;
 
-    /** The collection view.*/
-    protected CollectionView view;
-
     /** The ThemePanel to expose control over themes (facettes). */
     protected ChartThemePanel ctp;
 
@@ -107,16 +106,17 @@
      * @param collection The Collection which this chart belongs to.
      * @param mode The OutputMode.
      * @param collectionView The shown collection.
+     * @param recordHandler 
      */
     public ChartOutputTab(
         String         title,
         Collection     collection,
         OutputMode     mode,
-        CollectionView collectionView
+        CollectionView collectionView, 
+        IThemeRecordHandler recordHandler
     ){
         super(title, collection, collectionView, mode);
 
-        view      = collectionView;
         left      = new Canvas();
         right     = new Canvas();
         xrange    = new int[2];
@@ -143,7 +143,7 @@
         hLayout.addMember(left);
         hLayout.addMember(right);
 
-        ctp = createThemePanel(mode, collectionView);
+        ctp = createThemePanel(mode, collectionView, recordHandler);
         if (ctp != null) {
             ctp.addRedrawRequestHandler(this);
             ctp.addOutputParameterChangeHandler(this);
@@ -170,17 +170,13 @@
     }
 
 
-    public ChartThemePanel createThemePanel(
-        OutputMode mode, CollectionView view
-    ) {
+    public ChartThemePanel createThemePanel( OutputMode mode, CollectionView view, IThemeRecordHandler recordHandler ) {
         // Output "cross_section" needs slightly modified ThemePanel
         // (with action buttons).
-        if (mode.getName().equals("cross_section")) {
-            return new CrossSectionChartThemePanel(mode, view);
-        }
-        else {
-            return new ChartThemePanel(mode, view);
-        }
+        if (mode.getName().equals("cross_section"))
+            return new CrossSectionChartThemePanel(mode, view, recordHandler);
+
+        return new ChartThemePanel(mode, view, recordHandler);
     }
 
 
@@ -482,7 +478,7 @@
         String locale = config.getLocale();
 
         info.getChartInfo(
-            view.getCollection(),
+            getCollectionView().getCollection(),
             locale,
             mode.getName(),
             getChartAttributes(),
@@ -506,8 +502,11 @@
 
         chart.setSrc(getImgUrl(w, h));
     }
-
-
+    
+    protected final void updateThemePanel() {
+        ctp.updateThemes();
+    }
+    
     /**
      * Returns the existing chart panel.
      *
@@ -709,13 +708,6 @@
         return zoom;
     }
 
-
-    /** Return the 'parent' CollectionView. */
-    public CollectionView getView() {
-        return this.view;
-    }
-
-
     public static Number subtract(Number left, Number right) {
         if (left instanceof Double) {
             return new Double(left.doubleValue() - right.doubleValue());
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartThemePanel.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartThemePanel.java	Thu Aug 16 16:28:03 2018 +0200
@@ -8,25 +8,12 @@
 
 package org.dive4elements.river.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.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 org.dive4elements.river.client.client.Config;
-import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.client.services.FeedServiceAsync;
 import org.dive4elements.river.client.client.services.LoadArtifactService;
 import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
 import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.IThemeRecordHandler;
 import org.dive4elements.river.client.client.ui.ThemePanel;
 import org.dive4elements.river.client.shared.model.Artifact;
 import org.dive4elements.river.client.shared.model.Data;
@@ -38,6 +25,18 @@
 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.types.ListGridFieldType;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+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;
 
 /**
  * ThemePanel on the left in CollectionView.
@@ -48,348 +47,272 @@
  */
 public class ChartThemePanel extends ThemePanel {
     /** Artifact Clone/Creation service. */
-    protected LoadArtifactServiceAsync loadService =
-                GWT.create(LoadArtifactService.class);
-
-    /** The interface that provides i18n messages. */
-    protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
-
-    public static final String GRID_FIELD_ACTIVE  = "active";
-    public static final String GRID_FIELD_NAME    = "name";
-    public static final String GRID_FIELD_ACTIONS = "actions";
+    private final LoadArtifactServiceAsync loadService = GWT.create(LoadArtifactService.class);
 
-    FeedServiceAsync feedService = GWT.create(
-        org.dive4elements.river.client.client.services.FeedService.class);
-
+    protected static final String GRID_FIELD_ACTIVE = "active";
+    protected static final String GRID_FIELD_NAME = "name";
+    protected static final String GRID_FIELD_ACTIONS = "actions";
 
-    /** Constructor for a ChartThemePanel. */
-    public ChartThemePanel(
-        OutputMode mode,
-        CollectionView view
-    ) {
-        super(mode, view);
+    protected final FeedServiceAsync feedService = GWT.create(org.dive4elements.river.client.client.services.FeedService.class);
 
-        initGrid();
+    /** Constructor for a ChartThemePanel.
+     * @param recordHandler */
+    public ChartThemePanel(final OutputMode mode, final CollectionView view, final IThemeRecordHandler recordHandler) {
+        super(mode, view, recordHandler);
+
+        initGrid(recordHandler);
         initLayout();
 
         updateGrid();
     }
 
-
     /** Creates Layout with theme list and navigation bar inside. */
     protected VLayout createLayout() {
-        VLayout layout = new VLayout();
+        final VLayout layout = new VLayout();
         layout.setWidth100();
         layout.setHeight100();
 
-        layout.addMember(list);
-        layout.addMember(navigation);
+        layout.addMember(this.list);
+        layout.addMember(this.navigation);
 
         return layout;
     }
 
-
     /**
      * Initializes the layout of this panel.
      */
-    protected void initLayout() {
+    private void initLayout() {
         setWidth100();
         setHeight100();
 
         addChild(createLayout());
     }
 
-
     /**
      * Initializes the components (columns) of the theme grid.
+     * @param recordHandler
      */
-    protected void initGrid() {
-        list.setCanEdit(true);
-        list.setCanSort(false);
-        list.setShowRecordComponents(false);
-        list.setShowRecordComponentsByCell(true);
-        list.setShowHeader(true);
-        list.setShowHeaderContextMenu(false);
-        list.setWidth100();
-        list.setHeight100();
+    protected void initGrid( final IThemeRecordHandler recordHandler ) {
+        this.list.setCanEdit(true);
+        this.list.setCanSort(false);
+        this.list.setShowRecordComponents(false);
+        this.list.setShowRecordComponentsByCell(true);
+        this.list.setShowHeader(true);
+        this.list.setShowHeaderContextMenu(false);
+        this.list.setWidth100();
+        this.list.setHeight100();
 
-        list.addEditCompleteHandler(this);
+        this.list.addEditCompleteHandler(this);
 
-        ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20);
+        final ListGridField active = new ListGridField(GRID_FIELD_ACTIVE, " ", 20);
         active.setType(ListGridFieldType.BOOLEAN);
 
-        ListGridField name = new ListGridField(
-            GRID_FIELD_NAME, MSG.chart_themepanel_header_themes());
+        final ListGridField name = new ListGridField(GRID_FIELD_NAME, this.MSG.chart_themepanel_header_themes());
         name.setType(ListGridFieldType.TEXT);
 
-        list.setFields(active, name);
+        if( recordHandler instanceof CellFormatter)
+            name.setCellFormatter((CellFormatter) recordHandler);
+
+        this.list.setFields(active, name);
     }
 
-
     /** Set theme active/inactive. */
     @Override
-    public void activateTheme(Theme theme, boolean active) {
+    public void activateTheme(final Theme theme, final boolean active) {
         theme.setActive(active ? 1 : 0);
     }
 
-
     /** Returns name of longitudinal section area facets. */
     protected String getAreaFacetName() {
         return "longitudinal_section.area";
     }
 
-
     /** Create the DataProvider ('Blackboard') key for a theme. */
-    public static String areaKey(Theme theme) {
-        return theme.getArtifact() + ":" + theme.getFacet() + ":"
-            + theme.getIndex();
+    public static String areaKey(final Theme theme) {
+        return theme.getArtifact() + ":" + theme.getFacet() + ":" + theme.getIndex();
     }
 
-
     /**
      * Tell an area artifact where to get the upper and lower curve from.
-     * @param artifact UUID of area-artifact.
+     *
+     * @param artifact
+     *            UUID of area-artifact.
      */
-    public void feedTellArea(
-        final String artifact,
-        Theme under,
-        Theme over,
-        boolean between
-    ) {
+    public void feedTellArea(final String artifact, final Theme under, final Theme over, final boolean between) {
         Data[] feedData;
 
         if (over != null && under != null) {
-            feedData = new Data[] {
-                DefaultData.createSimpleStringData("area.curve_under",
-                    areaKey(under)),
-                DefaultData.createSimpleStringData("area.curve_over",
-                    areaKey(over)),
-                DefaultData.createSimpleStringData("area.name",
-                    over.getDescription() + " / " + under.getDescription()),
-                DefaultData.createSimpleStringData("area.facet",
-                    getAreaFacetName()),
-                DefaultData.createSimpleStringData("area.between",
-                    (between)? "true" : "false")
-            };
+            feedData = new Data[] { DefaultData.createSimpleStringData("area.curve_under", areaKey(under)),
+                    DefaultData.createSimpleStringData("area.curve_over", areaKey(over)),
+                    DefaultData.createSimpleStringData("area.name", over.getDescription() + " / " + under.getDescription()),
+                    DefaultData.createSimpleStringData("area.facet", getAreaFacetName()),
+                    DefaultData.createSimpleStringData("area.between", (between) ? "true" : "false") };
             GWT.log("Have 'over' and 'under' curve");
-        }
-        else if (over == null && under != null) {
-            feedData = new Data[] {
-                DefaultData.createSimpleStringData("area.curve_under",
-                    areaKey(under)),
-                DefaultData.createSimpleStringData("area.name",
-                    under.getDescription() + " / " + MSG.getString("x_axis")),
-                DefaultData.createSimpleStringData("area.facet",
-                    getAreaFacetName()),
-                DefaultData.createSimpleStringData("area.between",
-                    (between)? "true" : "false")
-            };
+        } else if (over == null && under != null) {
+            feedData = new Data[] { DefaultData.createSimpleStringData("area.curve_under", areaKey(under)),
+                    DefaultData.createSimpleStringData("area.name", under.getDescription() + " / " + this.MSG.getString("x_axis")),
+                    DefaultData.createSimpleStringData("area.facet", getAreaFacetName()),
+                    DefaultData.createSimpleStringData("area.between", (between) ? "true" : "false") };
             GWT.log("Have 'under' curve only");
-        }
-        else if (over != null && under == null) {
-            feedData = new Data[] {
-                DefaultData.createSimpleStringData("area.curve_over",
-                    areaKey(over)),
-                DefaultData.createSimpleStringData("area.name",
-                    MSG.getString("x_axis") + " / " + over.getDescription()),
-                DefaultData.createSimpleStringData("area.facet",
-                    getAreaFacetName()),
-                DefaultData.createSimpleStringData("area.between",
-                    (between)? "true" : "false")
-            };
+        } else if (over != null && under == null) {
+            feedData = new Data[] { DefaultData.createSimpleStringData("area.curve_over", areaKey(over)),
+                    DefaultData.createSimpleStringData("area.name", this.MSG.getString("x_axis") + " / " + over.getDescription()),
+                    DefaultData.createSimpleStringData("area.facet", getAreaFacetName()),
+                    DefaultData.createSimpleStringData("area.between", (between) ? "true" : "false") };
             GWT.log("Have 'over' curve only");
-        }
-        else {
+        } else {
             GWT.log("Missing Data for area painting.");
             return;
         }
 
-        feedService.feed(
-            Config.getInstance().getLocale(),
-            new DefaultArtifact(artifact, "TODO:hash"),
-            feedData,
-            new AsyncCallback<Artifact>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Could not feed artifact (" + artifact
-                            + ") with area info: " + caught.getMessage());
-                    SC.warn(MSG.getString(caught.getMessage()));
-                    enable();
-                }
-                @Override
-                public void onSuccess(Artifact fartifact) {
-                    GWT.log("Successfully set area params to " + artifact);
-                    requestRedraw();
-                    updateCollection();
-                    updateGrid();
-                    enable();
-                }
-            });
+        this.feedService.feed(Config.getInstance().getLocale(), new DefaultArtifact(artifact, "TODO:hash"), feedData, new AsyncCallback<Artifact>() {
+            @Override
+            public void onFailure(final Throwable caught) {
+                GWT.log("Could not feed artifact (" + artifact + ") with area info: " + caught.getMessage());
+                SC.warn(ChartThemePanel.this.MSG.getString(caught.getMessage()));
+                enable();
+            }
+
+            @Override
+            public void onSuccess(final Artifact fartifact) {
+                GWT.log("Successfully set area params to " + artifact);
+                requestRedraw();
+                updateCollection();
+                updateGrid();
+                enable();
+            }
+        });
     }
 
-
     /**
      * Create and parameterize a new area artifact.
+     *
      * @param under
-     * @param over if null, against axis.
-     * @param between if true, ignore under/over order.
+     * @param over
+     *            if null, against axis.
+     * @param between
+     *            if true, ignore under/over order.
      */
-    public void createAreaArtifact(
-        final Theme   over,
-        final Theme   under,
-        final boolean between
-    ) {
-        Config config = Config.getInstance();
-        String locale = config.getLocale();
+    public void createAreaArtifact(final Theme over, final Theme under, final boolean between) {
+        final Config config = Config.getInstance();
+        final String locale = config.getLocale();
 
-        Recommendation area = new Recommendation(
-            "area",
-            "",
-            "",
-            null);
+        final Recommendation area = new Recommendation("area", "", "", null);
 
         // Set target out dynamically.
         area.setTargetOut(getMode().getName());
 
-        Recommendation[] recommendations = new Recommendation[] {area};
+        final Recommendation[] recommendations = new Recommendation[] { area };
 
-        loadService.loadMany(
-            this.getCollection(),
-            recommendations,
-            null, //use individual factories.
-            locale,
-            new AsyncCallback<Artifact[]>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    GWT.log("Failed, no area artifact: " + caught.getMessage());
-                    enable();
-                    // TODO i18n
-                    SC.warn("Failed, no area artifact: " + caught.getMessage());
-                }
-                @Override
-                public void onSuccess(Artifact[] artifacts) {
-                    GWT.log("Success, created area artifact: "
-                        + artifacts[0].getUuid());
-                    // Now, feed the artifact with the relevant data.
-                    feedTellArea(artifacts[0].getUuid(), under, over, between);
-                }
-            }
-        );
+        this.loadService.loadMany(this.getCollection(), recommendations, null, // use individual factories.
+                locale, new AsyncCallback<Artifact[]>() {
+                    @Override
+                    public void onFailure(final Throwable caught) {
+                        GWT.log("Failed, no area artifact: " + caught.getMessage());
+                        enable();
+                        // TODO i18n
+                        SC.warn("Failed, no area artifact: " + caught.getMessage());
+                    }
+
+                    @Override
+                    public void onSuccess(final Artifact[] artifacts) {
+                        GWT.log("Success, created area artifact: " + artifacts[0].getUuid());
+                        // Now, feed the artifact with the relevant data.
+                        feedTellArea(artifacts[0].getUuid(), under, over, between);
+                    }
+                });
     }
 
-
     /**
      * 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.
+     * in subclasses.
      */
-    protected boolean areAreaCompatible(Theme a, Theme b) {
+    protected boolean areAreaCompatible(final Theme a, final Theme b) {
         if (a.equals(b)) {
             return false;
         }
-        if (a.getFacet().equals("w_differences") &&
-            b.getFacet().equals("w_differences")) {
+        if (a.getFacet().equals("w_differences") && b.getFacet().equals("w_differences")) {
             return true;
         }
-        if (a.getFacet().equals("longitudinal_section.w") ||
-            a.getFacet().equals("other.wqkms.w") ||
-            a.getFacet().equals("other.wqkms") ||
-            a.getFacet().equals("discharge_longitudinal_section.w") ||
-            a.getFacet().equals("discharge_longitudinal_section.c") ||
-            a.getFacet().equals("other.wkms")) {
-            return b.getFacet().equals("longitudinal_section.w")
-                || b.getFacet().equals("other.wqkms")
-                || b.getFacet().equals("other.wqkms.w")
-                || b.getFacet().equals("discharge_longitudinal_section.w")
-                || b.getFacet().equals("discharge_longitudinal_section.c")
-                || b.getFacet().equals("other.wkms");
-        }
-        else if (a.getFacet().equals("longitudinal_section.q") ||
-                 a.getFacet().equals("discharge_longitudinal_section.q") ||
-                 a.getFacet().equals("other.wqkms.q")) {
-            return b.getFacet().equals("longitudinal_section.q")
-                    || b.getFacet().equals("discharge_longitudinal_section.q")
+        if (a.getFacet().equals("longitudinal_section.w") || a.getFacet().equals("other.wqkms.w") || a.getFacet().equals("other.wqkms")
+                || a.getFacet().equals("discharge_longitudinal_section.w") || a.getFacet().equals("discharge_longitudinal_section.c")
+                || a.getFacet().equals("other.wkms")) {
+            return b.getFacet().equals("longitudinal_section.w") || b.getFacet().equals("other.wqkms") || b.getFacet().equals("other.wqkms.w")
+                    || b.getFacet().equals("discharge_longitudinal_section.w") || b.getFacet().equals("discharge_longitudinal_section.c")
+                    || b.getFacet().equals("other.wkms");
+        } else if (a.getFacet().equals("longitudinal_section.q") || a.getFacet().equals("discharge_longitudinal_section.q")
+                || a.getFacet().equals("other.wqkms.q")) {
+            return b.getFacet().equals("longitudinal_section.q") || b.getFacet().equals("discharge_longitudinal_section.q")
                     || b.getFacet().equals("other.wqkms.q");
         }
         return false;
     }
 
-
     /**
      * True if context menu should contain 'create area' submenu on
      * this theme.
      */
-    protected boolean canArea(Theme a) {
-        return a.getFacet().equals("longitudinal_section.q")
-            || a.getFacet().equals("longitudinal_section.w")
-            || a.getFacet().equals("discharge_longitudinal_section.w")
-            || a.getFacet().equals("discharge_longitudinal_section.q")
-            || a.getFacet().equals("discharge_longitudinal_section.c")
-            || a.getFacet().startsWith("other.wqkms")
-            || a.getFacet().equals("other.wkms")
-            || a.getFacet().equals("w_differences");
+    protected boolean canArea(final Theme a) {
+        return a.getFacet().equals("longitudinal_section.q") || a.getFacet().equals("longitudinal_section.w")
+                || a.getFacet().equals("discharge_longitudinal_section.w") || a.getFacet().equals("discharge_longitudinal_section.q")
+                || a.getFacet().equals("discharge_longitudinal_section.c") || a.getFacet().startsWith("other.wqkms") || a.getFacet().equals("other.wkms")
+                || a.getFacet().equals("w_differences");
     }
 
-
     /** Attach menu/item to open editor for Manual Points. */
-    protected void attachManualPointsMenu(Menu menu) {
+    protected void attachManualPointsMenu(final Menu menu) {
         menu.addItem(createSeparator());
-        MenuItem editManualPoints = new MenuItem(MSG.editpoints());
+        final MenuItem editManualPoints = new MenuItem(this.MSG.editpoints());
 
         editManualPoints.addClickHandler(new ClickHandler() {
-                @Override
-                public void onClick(MenuItemClickEvent evt) {
-                    if(mode.getName().equals("historical_discharge")) {
-                        new ManualDatePointsEditor(view.getCollection(),
-                            redrawRequestHandlers.get(0),
-                            mode.getName()).show();
-                    }
-                    else {
-                        new ManualPointsEditor(view.getCollection(),
-                            redrawRequestHandlers.get(0),
-                            mode.getName()).show();
-                    }
+            @Override
+            public void onClick(final MenuItemClickEvent evt) {
+                if (ChartThemePanel.this.mode.getName().equals("historical_discharge")) {
+                    new ManualDatePointsEditor(ChartThemePanel.this.view.getCollection(), ChartThemePanel.this.redrawRequestHandlers.get(0),
+                            ChartThemePanel.this.mode.getName()).show();
+                } else {
+                    new ManualPointsEditor(ChartThemePanel.this.view.getCollection(), ChartThemePanel.this.redrawRequestHandlers.get(0),
+                            ChartThemePanel.this.mode.getName()).show();
                 }
-            });
+            }
+        });
         menu.addItem(editManualPoints);
     }
 
-
     /**
      * Include area specific menu items and manual point editor, depending
      * on facet.
      */
     @Override
     protected Menu getSingleContextMenu(final ListGridRecord[] records) {
-        Menu menu = super.getSingleContextMenu(records);
+        final Menu menu = super.getSingleContextMenu(records);
 
-        final Theme facetTheme = ((FacetRecord)records[0]).getTheme();
+        final Theme facetTheme = ((FacetRecord) records[0]).getTheme();
 
         if (!canArea(facetTheme)) {
             if (facetTheme.getFacet().endsWith("manualpoints")) {
                 attachManualPointsMenu(menu);
                 return menu;
-            }
-            else {
+            } else {
                 return menu;
             }
         }
 
         menu.addItem(createSeparator());
 
-        MenuItem areaMenuItem = new MenuItem(MSG.chart_themepanel_new_area());
-        Menu areaMenu         = new Menu();
+        final MenuItem areaMenuItem = new MenuItem(this.MSG.chart_themepanel_new_area());
+        final Menu areaMenu = new Menu();
 
-        ThemeList themes = getThemeList();
-        int nThemes      = themes.getThemeCount();
+        final ThemeList themes = getThemeList();
+        final int nThemes = themes.getThemeCount();
 
         // Create the "under..." submenu.
-        MenuItem underMenuItem = new MenuItem(
-            MSG.chart_themepanel_area_under());
-        Menu underMenu = new Menu();
-        for (int i = 0; i < nThemes; i++)  {
-            final Theme theme = themes.getThemeAt(i+1);
+        final MenuItem underMenuItem = new MenuItem(this.MSG.chart_themepanel_area_under());
+        final Menu underMenu = new Menu();
+        for (int i = 0; i < nThemes; i++) {
+            final Theme theme = themes.getThemeAt(i + 1);
 
             if (theme.getVisible() == 0) {
                 continue;
@@ -399,12 +322,12 @@
                 continue;
             }
 
-            MenuItem againster = new MenuItem(theme.getDescription());
+            final MenuItem againster = new MenuItem(theme.getDescription());
             underMenu.addItem(againster);
 
             againster.addClickHandler(new ClickHandler() {
                 @Override
-                public void onClick(MenuItemClickEvent evt) {
+                public void onClick(final MenuItemClickEvent evt) {
                     disable();
                     createAreaArtifact(theme, facetTheme, false);
                 }
@@ -412,32 +335,32 @@
         }
 
         // Create the "over..." submenu.
-        MenuItem overMenuItem = new MenuItem(MSG.chart_themepanel_area_over());
-        Menu overMenu = new Menu();
-        for (int i = 0; i < nThemes; i++)  {
-            final Theme theme = themes.getThemeAt(i+1);
+        final MenuItem overMenuItem = new MenuItem(this.MSG.chart_themepanel_area_over());
+        final Menu overMenu = new Menu();
+        for (int i = 0; i < nThemes; i++) {
+            final Theme theme = themes.getThemeAt(i + 1);
             if (theme.getVisible() == 0) {
                 continue;
             }
             if (!areAreaCompatible(facetTheme, theme)) {
                 continue;
             }
-            MenuItem againster = new MenuItem(theme.getDescription());
+            final MenuItem againster = new MenuItem(theme.getDescription());
             overMenu.addItem(againster);
 
             againster.addClickHandler(new ClickHandler() {
                 @Override
-                public void onClick(MenuItemClickEvent evt) {
+                public void onClick(final MenuItemClickEvent evt) {
                     disable();
                     createAreaArtifact(facetTheme, theme, false);
                 }
             });
         }
         overMenu.addItem(createSeparator());
-        MenuItem againstAxis = new MenuItem(MSG.getString("x_axis"));
+        final MenuItem againstAxis = new MenuItem(this.MSG.getString("x_axis"));
         againstAxis.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(MenuItemClickEvent evt) {
+            public void onClick(final MenuItemClickEvent evt) {
                 disable();
                 createAreaArtifact(null, facetTheme, false);
             }
@@ -445,23 +368,22 @@
         overMenu.addItem(againstAxis);
 
         // Create the "between..." submenu.
-        MenuItem betweenMenuItem = new MenuItem(
-            MSG.chart_themepanel_area_between());
-        Menu betweenMenu = new Menu();
-        for (int i = 0; i < nThemes; i++)  {
-            final Theme theme = themes.getThemeAt(i+1);
+        final MenuItem betweenMenuItem = new MenuItem(this.MSG.chart_themepanel_area_between());
+        final Menu betweenMenu = new Menu();
+        for (int i = 0; i < nThemes; i++) {
+            final Theme theme = themes.getThemeAt(i + 1);
             if (theme.getVisible() == 0) {
                 continue;
             }
             if (!areAreaCompatible(facetTheme, theme)) {
                 continue;
             }
-            MenuItem againster = new MenuItem(theme.getDescription());
+            final MenuItem againster = new MenuItem(theme.getDescription());
             betweenMenu.addItem(againster);
 
             againster.addClickHandler(new ClickHandler() {
                 @Override
-                public void onClick(MenuItemClickEvent evt) {
+                public void onClick(final MenuItemClickEvent evt) {
                     disable();
                     createAreaArtifact(facetTheme, theme, true);
                 }
@@ -478,11 +400,10 @@
         areaMenu.addItem(overMenuItem);
         areaMenu.addItem(underMenuItem);
         areaMenu.addItem(createSeparator());
-        MenuItem standAloneAgainstAxis = new MenuItem(
-            MSG.getString("against_x_axis"));
+        final MenuItem standAloneAgainstAxis = new MenuItem(this.MSG.getString("against_x_axis"));
         standAloneAgainstAxis.addClickHandler(new ClickHandler() {
             @Override
-            public void onClick(MenuItemClickEvent evt) {
+            public void onClick(final MenuItemClickEvent evt) {
                 disable();
                 createAreaArtifact(null, facetTheme, false);
             }
@@ -494,5 +415,4 @@
 
         return menu;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartToolbar.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartToolbar.java	Thu Aug 16 16:28:03 2018 +0200
@@ -83,7 +83,7 @@
                 @Override
                 public void onClick(ClickEvent ce) {
                     new ManualWSPEditor(
-                        finalChartTab.getView().getCollection(),
+                        finalChartTab.getCollectionView().getCollection(),
                         finalChartTab,
                         finalChartTab.getMode().getName()).show();
                     }});
@@ -300,11 +300,11 @@
     protected void openPointWindow() {
         ChartOutputTab chartTab = getChartOutputTab();
         if (chartTab.getMode().getName().equals("historical_discharge")) {
-            new ManualDatePointsEditor(chartTab.getView().getCollection(),
+            new ManualDatePointsEditor(chartTab.getCollectionView().getCollection(),
                 chartTab, chartTab.getMode().getName()).show();
         }
         else {
-            new ManualPointsEditor(chartTab.getView().getCollection(),
+            new ManualPointsEditor(chartTab.getCollectionView().getCollection(),
                 chartTab, chartTab.getMode().getName()).show();
         }
     }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/CrossSectionChartThemePanel.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/CrossSectionChartThemePanel.java	Thu Aug 16 16:28:03 2018 +0200
@@ -32,6 +32,7 @@
 import org.dive4elements.river.client.client.services.LoadArtifactService;
 import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync;
 import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.IThemeRecordHandler;
 import org.dive4elements.river.client.client.widgets.KMSpinner;
 import org.dive4elements.river.client.client.widgets.KMSpinnerChangeListener;
 import org.dive4elements.river.client.shared.model.Artifact;
@@ -97,12 +98,11 @@
 
     /**
      * Trivial constructor.
+     * @param noopThemeRecordHandler 
      */
-    public CrossSectionChartThemePanel(
-        OutputMode mode,
-        CollectionView view)
+    public CrossSectionChartThemePanel( OutputMode mode, CollectionView view, IThemeRecordHandler recordHandler)
     {
-        super(mode, view);
+        super(mode, view, recordHandler);
     }
 
 
@@ -550,7 +550,7 @@
      * Initializes the components (columns) of the theme grid.
      */
     @Override
-    protected void initGrid() {
+    protected void initGrid(IThemeRecordHandler recordHandler) {
         list.setCanEdit(true);
         list.setCanSort(false);
         list.setShowRecordComponents(true);
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartOutputTab.java	Thu Aug 16 16:28:03 2018 +0200
@@ -53,7 +53,7 @@
     private INaviChartStepper stepper;
 
     public NaviChartOutputTab(final String title, final Collection collection, final OutputMode mode, final CollectionView collectionView) {
-        super(title, collection, mode, collectionView);
+        super(title, collection, mode, collectionView, new NaviChartRecordHandler(collectionView));
 
         this.stepper = new NilNaviChartStepper();
 
@@ -230,6 +230,7 @@
         this.currentkm.setValue(this.kmFormat.format(currentKm));
         this.tbarPanel.onZoom(null);
 
+        updateThemePanel();
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/NaviChartRecordHandler.java	Thu Aug 16 16:28:03 2018 +0200
@@ -0,0 +1,85 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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.chart;
+
+import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.IThemeRecordHandler;
+import org.dive4elements.river.client.shared.model.AttributedTheme;
+import org.dive4elements.river.client.shared.model.FacetRecord;
+import org.dive4elements.river.client.shared.model.Theme;
+
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
+/**
+ * @author Gernot Belger
+ */
+final class NaviChartRecordHandler implements IThemeRecordHandler, CellFormatter {
+
+    private static final String STYLE_CLASS_NAVI_CHART_GRAYED = "naviChartGrayed";
+    private final CollectionView collectionView;
+
+    public NaviChartRecordHandler(final CollectionView collectionView) {
+        this.collectionView = collectionView;
+    }
+
+    private boolean checkOutsideRange(final FacetRecord facetRecord) {
+
+        final Theme theme = facetRecord.getTheme();
+        if (!(theme instanceof AttributedTheme))
+            return false;
+
+        final double currentKm = this.collectionView.getCurrentKm();
+
+        final AttributedTheme aTheme = (AttributedTheme) theme;
+
+        final Double startKm = aTheme.getAttrAsDouble("startKm");
+        final Double endKm = aTheme.getAttrAsDouble("endKm");
+        if (startKm == null || endKm == null)
+            return false;
+
+        final double fromKm = startKm < endKm ? startKm : endKm;
+        final double toKm = startKm < endKm ? endKm : startKm;
+
+        return currentKm < fromKm || currentKm > toKm;
+    }
+
+    @Override
+    public void handle(final FacetRecord facetRecord) {
+
+        final boolean isOutsideRange = checkOutsideRange(facetRecord);
+        if (isOutsideRange)
+            facetRecord.set_baseStyle(STYLE_CLASS_NAVI_CHART_GRAYED);
+        else
+            facetRecord.set_baseStyle(null);
+    }
+
+    @Override
+    public String format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) {
+
+        if (!(record instanceof FacetRecord))
+            return null;
+
+        final FacetRecord facetRecord = (FacetRecord) record;
+        final String description = facetRecord.getName();
+
+        final boolean isOutsideRange = checkOutsideRange(facetRecord);
+        if (isOutsideRange) {
+            return new StringBuilder(description) //
+                    .append(" (") //
+                    // FIXME: i10n
+                    .append("auß. Gültigkeitsbereich") //
+                    .append(")") //
+                    .toString();
+        }
+
+        return description;
+    }
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/OverviewOutputTab.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/OverviewOutputTab.java	Thu Aug 16 16:28:03 2018 +0200
@@ -13,7 +13,9 @@
 import org.dive4elements.river.client.client.event.OutputParameterChangeHandler;
 import org.dive4elements.river.client.client.event.RedrawRequestHandler;
 import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.IThemeRecordHandler;
 import org.dive4elements.river.client.client.ui.ImgLink;
+import org.dive4elements.river.client.client.ui.NoopThemeRecordHandler;
 import org.dive4elements.river.client.shared.model.Collection;
 import org.dive4elements.river.client.shared.model.OutputMode;
 import org.dive4elements.river.client.shared.model.Theme;
@@ -24,7 +26,7 @@
     private class NoChartThemePanel extends ChartThemePanel {
 
         public NoChartThemePanel(OutputMode mode, CollectionView view) {
-            super(mode, view);
+            super(mode, view, new NoopThemeRecordHandler());
         }
 
         @Override
@@ -99,15 +101,13 @@
         OutputMode     mode,
         CollectionView collectionView
         ){
-        super(title, collection, mode, collectionView);
+        super(title, collection, mode, collectionView, new NoopThemeRecordHandler());
         left.setVisible(false);
     }
 
 
     @Override
-    public ChartThemePanel createThemePanel(
-        OutputMode mode, CollectionView view
-        ) {
+    public ChartThemePanel createThemePanel(OutputMode mode, CollectionView view, IThemeRecordHandler recordHandler) {
         return new NoChartThemePanel(mode, view);
     }
 
@@ -115,4 +115,4 @@
     public ChartToolbar createChartToolbar(ChartOutputTab tab) {
         return new MinimumChartToolbar(tab);
     }
-}
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapThemePanel.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapThemePanel.java	Thu Aug 16 16:28:03 2018 +0200
@@ -25,6 +25,7 @@
 
 import org.dive4elements.river.client.client.FLYSConstants;
 import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.NoopThemeRecordHandler;
 import org.dive4elements.river.client.client.ui.ThemePanel;
 import org.dive4elements.river.client.shared.model.AttributedTheme;
 import org.dive4elements.river.client.shared.model.FacetRecord;
@@ -80,7 +81,7 @@
         ThemeMovedCallback themeMovedCallback,
         LayerZoomCallback  layerZoomCallback
     ) {
-        super(mode, view);
+        super(mode, view, new NoopThemeRecordHandler());
 
         this.mapOut             = mapOut;
         this.activateCallback   = activateCallback;
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/AttributedTheme.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/AttributedTheme.java	Thu Aug 16 16:28:03 2018 +0200
@@ -18,58 +18,77 @@
  */
 public class AttributedTheme implements Theme {
 
-    protected Map<String, String> attributes;
+    private static final long serialVersionUID = 1L;
+
+    private Map<String, String> attributes;
 
     /** CollectionItem associated with this facet/themes artifact. */
-    protected CollectionItem collectionItem;
+    private CollectionItem collectionItem;
 
     public AttributedTheme() {
         this.attributes = new HashMap<String, String>();
     }
 
+    /** Remark: only here so attributes is not final and serialization is happy */
+    public void setAttributes(final Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
 
     public Set<String> getKeys() {
-        return attributes.keySet();
+        return this.attributes.keySet();
     }
 
-
-    public void addAttr(String name, String value) {
+    public void addAttr(final String name, final String value) {
         if (name != null && value != null) {
-            attributes.put(name, value);
+            this.attributes.put(name, value);
         }
     }
 
-
-    public String getAttr(String name) {
-        return attributes.get(name);
+    public String getAttr(final String name) {
+        return this.attributes.get(name);
     }
 
-
-    public Integer getAttrAsInt(String name) {
-        String attr = getAttr(name);
+    public Integer getAttrAsInt(final String name) {
+        final String attr = getAttr(name);
 
         if (attr != null && attr.length() > 0) {
             try {
                 return Integer.parseInt(attr);
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
+                nfe.printStackTrace();
             }
         }
 
         return null;
     }
 
+    public Double getAttrAsDouble(final String name) {
 
-    public boolean getAttrAsBoolean(String name) {
-        String attr = getAttr(name);
+        final String attr = getAttr(name);
+        if (attr == null || attr.isEmpty())
+            return null;
+
+        try {
+            return Double.parseDouble(attr);
+        }
+        catch (final NumberFormatException nfe) {
+            nfe.printStackTrace();
+            return null;
+        }
+    }
+
+    public boolean getAttrAsBoolean(final String name) {
+        final String attr = getAttr(name);
 
         if (attr != null) {
             try {
-                int num = Integer.valueOf(attr);
+                final int num = Integer.valueOf(attr);
                 return num > 0;
             }
-            catch (NumberFormatException nfe) {
+            catch (final NumberFormatException nfe) {
                 // do nothing
+                nfe.printStackTrace();
             }
         }
 
@@ -79,21 +98,21 @@
 
     @Override
     public int getPosition() {
-        Integer pos = getAttrAsInt("pos");
+        final Integer pos = getAttrAsInt("pos");
 
         return pos != null ? pos.intValue() : -1;
     }
 
 
     @Override
-    public void setPosition(int pos) {
+    public void setPosition(final int pos) {
         addAttr("pos", String.valueOf(pos));
     }
 
 
     @Override
     public int getIndex() {
-        Integer idx = getAttrAsInt("index");
+        final Integer idx = getAttrAsInt("index");
 
         return idx != null ? idx.intValue() : -1;
     }
@@ -106,7 +125,7 @@
 
 
     @Override
-    public void setActive(int active) {
+    public void setActive(final int active) {
         addAttr("active", String.valueOf(active));
     }
 
@@ -130,7 +149,7 @@
 
 
     @Override
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         if (description != null && description.length() > 0) {
             addAttr("description", description);
         }
@@ -144,18 +163,18 @@
 
 
     @Override
-    public void setVisible(int visible) {
+    public void setVisible(final int visible) {
         addAttr("visible", String.valueOf(visible));
     }
 
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (!(o instanceof AttributedTheme)) {
             return false;
         }
 
-        AttributedTheme other = (AttributedTheme) o;
+        final AttributedTheme other = (AttributedTheme) o;
 
         if (other.getPosition() != getPosition()) {
             return false;
@@ -188,18 +207,15 @@
         return true;
     }
 
-
     /** Get the CollectionItem representing the facets artifact. */
     @Override
     public CollectionItem getCollectionItem() {
-        return collectionItem;
+        return this.collectionItem;
     }
 
-
     /** Set the CollectionItem representing the facets artifact. */
     @Override
-    public void setCollectionItem(CollectionItem ci) {
+    public void setCollectionItem(final CollectionItem ci) {
         this.collectionItem = ci;
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ChartMode.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ChartMode.java	Thu Aug 16 16:28:03 2018 +0200
@@ -11,49 +11,42 @@
 import java.util.List;
 
 import org.dive4elements.river.client.client.ui.CollectionView;
+import org.dive4elements.river.client.client.ui.NoopThemeRecordHandler;
 import org.dive4elements.river.client.client.ui.OutputTab;
 import org.dive4elements.river.client.client.ui.chart.ChartOutputTab;
 import org.dive4elements.river.client.client.ui.chart.NaviChartOutputTab;
 
-
 /**
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
 public class ChartMode extends DefaultOutputMode {
 
+    private static final long serialVersionUID = 1L;
+
     public ChartMode() {
     }
 
-
-    public ChartMode(String name, String desc, String mimeType) {
-        super(name, desc, mimeType);
-    }
-
+    public ChartMode(final String name, final String descrition, final String mimeType, final List<Facet> facets, final String type) {
+        super(name, descrition, mimeType, facets);
 
-    public ChartMode(
-        String name,
-        String descrition,
-        String mimeType,
-        List<Facet> facets,
-        String type)
-    {
-        super(name, descrition, mimeType, facets);
         this.type = type;
     }
 
-
     /** Create output tab. Some outs feel better inside a specialized one. */
     @Override
-    public OutputTab createOutputTab(String t, Collection c, CollectionView p) {
-        if (this.getName().equals("fix_wq_curve") ||
-            this.getName().equals("extreme_wq_curve") ||
-            this.getName().equals("fix_deltawt_curve") ||
-            this.getName().equals("fix_derivate_curve") ||
-            this.getName().equals("fix_vollmer_wq_curve") ||
-            this.getName().equals("sinfo_floodduration_curve")){
+    public OutputTab createOutputTab(final String t, final Collection c, final CollectionView p) {
+        final String modeName = this.getName();
+
+        if (modeName.equals("fix_wq_curve") || //
+                modeName.equals("extreme_wq_curve") || //
+                modeName.equals("fix_deltawt_curve") || //
+                modeName.equals("fix_derivate_curve") || //
+                modeName.equals("fix_vollmer_wq_curve") || //
+                modeName.equals("sinfo_floodduration_curve")) {
+
             return new NaviChartOutputTab(t, c, this, p);
         }
-        return new ChartOutputTab(t, c, this, p);
+
+        return new ChartOutputTab(t, c, this, p, new NoopThemeRecordHandler());
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FacetRecord.java	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FacetRecord.java	Thu Aug 16 16:28:03 2018 +0200
@@ -12,46 +12,38 @@
 
 /**
  * ListGridRecord for Facets.
+ *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class FacetRecord extends ListGridRecord {
+public final class FacetRecord extends ListGridRecord {
 
     /** Underlying theme. */
-    protected Theme theme;
+    private final Theme theme;
 
-
-    public FacetRecord(Theme theme) {
+    public FacetRecord(final Theme theme) {
         this.theme = theme;
 
         setActive(theme.getActive() == 1);
         setName(theme.getDescription());
     }
 
-
     public Theme getTheme() {
-        return theme;
+        return this.theme;
     }
 
-
-    public void setName(String description) {
-        // TODO Add a setter method setName() to Facet
-        // facet.setName(name);
+    public void setName(final String description) {
         setAttribute("name", description);
     }
 
-
     public String getName() {
         return getAttribute("name");
     }
 
-
     public boolean getActive() {
         return getAttributeAsBoolean("active");
     }
 
-
-    public void setActive(boolean active) {
+    public void setActive(final boolean active) {
         setAttribute("active", active);
     }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/gwt-client/src/main/webapp/FLYS.css	Thu Aug 16 16:27:53 2018 +0200
+++ b/gwt-client/src/main/webapp/FLYS.css	Thu Aug 16 16:28:03 2018 +0200
@@ -244,3 +244,80 @@
 .riverLinkHighlight {
     background: #B7D431;
 }
+
+.naviChartGrayed,
+.naviChartGrayedDark,
+.naviChartGrayedOver,
+.naviChartGrayedOverDark,
+.naviChartGrayedSelected,
+.naviChartGrayedSelectedDark,
+.naviChartGrayedSelectedOver,
+.naviChartGrayedSelectedOverDark,
+.naviChartGrayedDisabled,
+.naviChartGrayedDisabledDark  {
+	
+  border-top: 1px solid #fafafa;
+  border-bottom: 1px solid #f0f0f0;
+  font-family: Arial, Verdana, sans-serif;
+  font-size: 11px;
+  text-overflow: ellipsis;	
+	
+  color: #CCCCCC;
+  font-style: italic;
+}
+
+.naviChartGrayedDark {
+  background-color: #fafafa;
+}
+
+.naviChartGrayedOver,
+.naviChartGrayedOverDark {
+  background-color: #c4ddfd;
+  background-image: url(./images/ListGrid/row_Over.png);
+  background-repeat: repeat-x;
+  background-position: bottom left;
+  background-attachment: scroll;
+  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2M0ZGRmZCIvPjxzdG9wIG9mZnNldD0iOSUiIHN0b3AtY29sb3I9IiNmMGY4ZmYiLz48c3RvcCBvZmZzZXQ9IjE0JSIgc3RvcC1jb2xvcj0iI2U1ZjNmZiIvPjxzdG9wIG9mZnNldD0iODYlIiBzdG9wLWNvbG9yPSIjY2NlNWZmIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjYzRkZGZkIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
+  background-size: 100%;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c4ddfd), color-stop(9%, #f0f8ff), color-stop(14%, #e5f3ff), color-stop(86%, #cce5ff), color-stop(100%, #c4ddfd));
+  background-image: -webkit-linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  background-image: -moz-linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  background-image: -o-linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  background-image: linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  border-bottom: 1px solid #c4ddfd;
+  border-top: 1px solid #c4ddfd;
+  -webkit-box-shadow: inset #e5f0ff 0 1px 0, inset #e5f0ff 0 -1px 0;
+  -moz-box-shadow: inset #e5f0ff 0 1px 0, inset #e5f0ff 0 -1px 0;
+  box-shadow: inset #e5f0ff 0 1px 0, inset #e5f0ff 0 -1px 0;
+}
+
+.naviChartGrayedSelected,
+.naviChartGrayedSelectedDark {
+  background: #d6e8ff;
+  border-bottom: 1px dotted #9fb7e9;
+  border-top: 1px dotted #9fb7e9;
+}
+
+.naviChartGrayedSelectedOver,
+.naviChartGrayedSelectedOverDark {
+  border-bottom: 1px solid #ababab;
+  border-top: 1px solid #b8cfef;
+  background-color: #c4ddfd;
+  background-image: url(./images/ListGrid/row_Selected_Over.png);
+  background-repeat: repeat-x;
+  background-attachment: scroll;
+  background-position: bottom left;
+  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2M0ZGRmZCIvPjxzdG9wIG9mZnNldD0iOSUiIHN0b3AtY29sb3I9IiNmMGY4ZmYiLz48c3RvcCBvZmZzZXQ9IjE0JSIgc3RvcC1jb2xvcj0iI2U1ZjNmZiIvPjxzdG9wIG9mZnNldD0iODYlIiBzdG9wLWNvbG9yPSIjY2NlNWZmIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjYzRkZGZkIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
+  background-size: 100%;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c4ddfd), color-stop(9%, #f0f8ff), color-stop(14%, #e5f3ff), color-stop(86%, #cce5ff), color-stop(100%, #c4ddfd));
+  background-image: -webkit-linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  background-image: -moz-linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  background-image: -o-linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+  background-image: linear-gradient(top, #c4ddfd 0%, #f0f8ff 9%, #e5f3ff 14%, #cce5ff 86%, #c4ddfd 100%);
+}
+
+.naviChartGrayedDisabled,
+.naviChartGrayedDisabledDark {
+  background-color: white;
+  color: #ababab;
+}
\ No newline at end of file

http://dive4elements.wald.intevation.org