commit 19fc4473fd06f46a77b9ca922d75f15994c14a10
Author: Patrick Plitzner <p.plitzner@bgbm.org>
Date:   Mon Feb 5 09:24:43 2018 +0100

    ref #7095 Freeze/stick supplemental info columns
    
     - Add button for unfreezing

diff --git a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/CharacterMatrix.java b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/CharacterMatrix.java
index f07223b87..39569a063 100644
--- a/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/CharacterMatrix.java
+++ b/eu.etaxonomy.taxeditor.editor/src/main/java/eu/etaxonomy/taxeditor/editor/workingSet/matrix/CharacterMatrix.java
@@ -8,6 +8,13 @@
  */
 package eu.etaxonomy.taxeditor.editor.workingSet.matrix;
 
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.DisplayMode;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.Window;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -26,6 +33,7 @@ import java.util.UUID;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
+import javax.annotation.Resources;
 import javax.inject.Inject;
 
 import org.apache.commons.collections4.map.LinkedMap;
@@ -40,7 +48,6 @@ import org.eclipse.jface.viewers.ArrayContentProvider;
 import org.eclipse.jface.viewers.ComboViewer;
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.window.Window;
 import org.eclipse.nebula.widgets.nattable.NatTable;
 import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
 import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
@@ -57,6 +64,8 @@ import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEven
 import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsSortModel;
 import org.eclipse.nebula.widgets.nattable.extension.glazedlists.tree.GlazedListTreeData;
 import org.eclipse.nebula.widgets.nattable.extension.glazedlists.tree.GlazedListTreeRowModel;
+import org.eclipse.nebula.widgets.nattable.freeze.FreezeHelper;
+import org.eclipse.nebula.widgets.nattable.freeze.config.DefaultFreezeGridBindings;
 import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
 import org.eclipse.nebula.widgets.nattable.grid.command.ClientAreaResizeCommand;
 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
@@ -68,8 +77,7 @@ import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
 import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
 import org.eclipse.nebula.widgets.nattable.grid.layer.config.DefaultRowStyleConfiguration;
-import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
-import org.eclipse.nebula.widgets.nattable.hideshow.RowHideShowLayer;
+import org.eclipse.nebula.widgets.nattable.layer.AbstractLayer;
 import org.eclipse.nebula.widgets.nattable.layer.CompositeLayer;
 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
@@ -85,17 +93,13 @@ import org.eclipse.nebula.widgets.nattable.persistence.command.DisplayPersistenc
 import org.eclipse.nebula.widgets.nattable.persistence.command.IStateChangedListener;
 import org.eclipse.nebula.widgets.nattable.persistence.command.StateChangeEvent;
 import org.eclipse.nebula.widgets.nattable.persistence.gui.PersistenceDialog;
-import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
-import org.eclipse.nebula.widgets.nattable.reorder.RowReorderLayer;
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
 import org.eclipse.nebula.widgets.nattable.selection.config.DefaultSelectionStyleConfiguration;
 import org.eclipse.nebula.widgets.nattable.selection.event.CellSelectionEvent;
 import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
 import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
 import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
-import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
 import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum;
-import org.eclipse.nebula.widgets.nattable.style.Style;
 import org.eclipse.nebula.widgets.nattable.style.VerticalAlignmentEnum;
 import org.eclipse.nebula.widgets.nattable.summaryrow.FixedSummaryRowLayer;
 import org.eclipse.nebula.widgets.nattable.summaryrow.SummaryRowLayer;
@@ -106,18 +110,12 @@ import org.eclipse.nebula.widgets.nattable.tree.command.TreeExpandAllCommand;
 import org.eclipse.nebula.widgets.nattable.ui.menu.AbstractHeaderMenuConfiguration;
 import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
 import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
-import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.FontData;
 import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.layout.RowLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
 
 import ca.odell.glazedlists.EventList;
 import ca.odell.glazedlists.GlazedLists;
@@ -132,8 +130,6 @@ import eu.etaxonomy.cdm.model.description.Feature;
 import eu.etaxonomy.cdm.model.description.FeatureTree;
 import eu.etaxonomy.cdm.model.description.MeasurementUnit;
 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
-import eu.etaxonomy.cdm.model.description.State;
-import eu.etaxonomy.cdm.model.description.WorkingSet;
 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
 import eu.etaxonomy.taxeditor.editor.workingSet.matrix.categorical.CategoricalDataCellEditor;
@@ -147,7 +143,6 @@ import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
 import eu.etaxonomy.taxeditor.model.ImageResources;
 import eu.etaxonomy.taxeditor.model.MessagingUtils;
-import eu.etaxonomy.taxeditor.preference.Resources;
 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
 import eu.etaxonomy.taxeditor.store.CdmStore;
@@ -155,6 +150,7 @@ import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
 
 /**
+ * Character matrix editor for editing specimen/taxon descriptions in a table
  * @author pplitzner
  * @since Nov 26, 2017
  *
@@ -209,6 +205,10 @@ ICdmEntitySessionEnabled{
 
     private ListDataProvider<Object> bodyDataProvider;
 
+    private FreezeLayer freezeLayer;
+
+    private ViewportLayer viewportLayer;
+
     private Label wsLabel;
 
     private Composite parent;
@@ -233,7 +233,7 @@ ICdmEntitySessionEnabled{
 
         Composite toolbarComposite = new Composite(parent, SWT.NONE);
         toolbarComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
-        toolbarComposite.setLayout(new GridLayout(8, false));
+        toolbarComposite.setLayout(new GridLayout(9, false));
         natTable = new NatTable(parent, false);
 
         wsLabel = new Label(toolbarComposite, SWT.NONE);
@@ -242,6 +242,7 @@ ICdmEntitySessionEnabled{
         Button btnToggleFlat = new Button(toolbarComposite, SWT.PUSH);
         Button btnCollapseAll = new Button(toolbarComposite, SWT.PUSH);
         Button btnExpandAll = new Button(toolbarComposite, SWT.PUSH);
+        Button btnFreezeSuppInfo = new Button(toolbarComposite, SWT.TOGGLE);
         ComboViewer comboStates = new ComboViewer(toolbarComposite, SWT.DROP_DOWN);
         Button btnManageState = new Button(toolbarComposite, SWT.PUSH);
         Button btnExcelExport = new Button(toolbarComposite, SWT.PUSH);
@@ -297,6 +298,20 @@ ICdmEntitySessionEnabled{
             }
         });
 
+        /**
+         * Freeze supplemental info button
+         */
+        btnFreezeSuppInfo.setImage(ImageResources.getImage(ImageResources.LOCK_ICON));
+        btnFreezeSuppInfo.setToolTipText("Lock specimen columns");
+        btnFreezeSuppInfo.setSelection(true);
+        btnFreezeSuppInfo.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+              FreezeHelper.unfreeze(freezeLayer, viewportLayer);
+
+            }
+        });
+
         /**
          * Table state persistence
          */
@@ -558,35 +573,49 @@ ICdmEntitySessionEnabled{
         GlazedListTreeData treeData = new GlazedListTreeData<>(treeList);
         ITreeRowModel treeRowModel = new GlazedListTreeRowModel<>(treeData);
 
-        ColumnReorderLayer columnReorderLayer;
-        ColumnHideShowLayer columnHideShowLayer;
-        SelectionLayer selectionLayer;
-        TreeLayer treeLayer;
-        ViewportLayer viewportLayer;
-        if(treeView){
-            columnReorderLayer = new ColumnReorderLayer(eventLayer);
-            columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
-            selectionLayer = new SelectionLayer(columnHideShowLayer);
-            treeLayer = new TreeLayer(selectionLayer, treeRowModel);
-            viewportLayer = treeView?new ViewportLayer(treeLayer):new ViewportLayer(selectionLayer);
-        }
-        else{
-            RowReorderLayer rowReorderLayer = new RowReorderLayer(eventLayer);
-            columnReorderLayer = new ColumnReorderLayer(rowReorderLayer);
-            columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
-            RowHideShowLayer rowHideShowLayer = new RowHideShowLayer(columnHideShowLayer);
-            selectionLayer = new SelectionLayer(rowHideShowLayer);
-            treeLayer = new TreeLayer(selectionLayer, treeRowModel);
-            viewportLayer = treeView?new ViewportLayer(treeLayer):new ViewportLayer(selectionLayer);
-        }
+//        ColumnReorderLayer columnReorderLayer;
+//        ColumnHideShowLayer columnHideShowLayer;
+//        SelectionLayer selectionLayer;
+//        TreeLayer treeLayer;
+//        ViewportLayer viewportLayer;
+//        if(treeView){
+//            columnReorderLayer = new ColumnReorderLayer(eventLayer);
+//            columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
+//            selectionLayer = new SelectionLayer(columnHideShowLayer);
+//            treeLayer = new TreeLayer(selectionLayer, treeRowModel);
+//            viewportLayer = treeView?new ViewportLayer(treeLayer):new ViewportLayer(selectionLayer);
+//        }
+//        else{
+//            RowReorderLayer rowReorderLayer = new RowReorderLayer(eventLayer);
+//            columnReorderLayer = new ColumnReorderLayer(rowReorderLayer);
+//            columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
+//            RowHideShowLayer rowHideShowLayer = new RowHideShowLayer(columnHideShowLayer);
+//            selectionLayer = new SelectionLayer(rowHideShowLayer);
+//            treeLayer = new TreeLayer(selectionLayer, treeRowModel);
+//            viewportLayer = treeView?new ViewportLayer(treeLayer):new ViewportLayer(selectionLayer);
+//        }
+        final DefaultBodyLayerStack bodyLayer = new DefaultBodyLayerStack(
+                bodyDataLayer);
+        viewportLayer = bodyLayer.getViewportLayer();
+        final SelectionLayer selectionLayer = bodyLayer.getSelectionLayer();
+        freezeLayer = new FreezeLayer(selectionLayer);
+        final CompositeFreezeLayer compositeFreezeLayer = new CompositeFreezeLayer(
+                freezeLayer, bodyLayer.getViewportLayer(), selectionLayer);
+        TreeLayer treeLayer = new TreeLayer(compositeFreezeLayer, treeRowModel);
+//        ViewportLayer viewportLayer = new ViewportLayer(treeLayer);
+//        FreezeLayer freezeLayer = new FreezeLayer(viewportLayer);
+//        CompositeFreezeLayer compositeFreezeLayer = new CompositeFreezeLayer(freezeLayer, viewportLayer, selectionLayer);
+
+
+        AbstractLayer topMostLayer = treeView?treeLayer:compositeFreezeLayer;
 
         // create a standalone FixedSummaryRowLayer
         // since the summary row should be fixed at the top of the body
         // region the horizontal dependency of the FixedSummaryRowLayer
         // is the ViewportLayer
         FixedSummaryRowLayer summaryRowLayer =
-                new FixedSummaryRowLayer(bodyDataLayer, viewportLayer, configRegistry, false);
-        //register labels with summary prefix for summary layer
+                new FixedSummaryRowLayer(bodyDataLayer, topMostLayer, configRegistry, false);
+        //regoster labels with summary prefix for summary layer
         ColumnOverrideLabelAccumulator summaryColumnLabelAccumulator =new ColumnOverrideLabelAccumulator(bodyDataLayer);
         summaryRowLayer.setConfigLabelAccumulator(summaryColumnLabelAccumulator);
         for(int i=0;i<features.size();i++){
@@ -601,7 +630,7 @@ ICdmEntitySessionEnabled{
 
         CompositeLayer composite = new CompositeLayer(1, 2);
         composite.setChildLayer("SUMMARY", summaryRowLayer, 0, 0);
-        composite.setChildLayer(GridRegion.BODY, viewportLayer, 0, 1);
+        composite.setChildLayer(GridRegion.BODY, topMostLayer, 0, 1);
 
 
         /**
@@ -610,7 +639,7 @@ ICdmEntitySessionEnabled{
         IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(
                 propertyToLabelMap.values().toArray(new String[] {}), propertyToLabelMap);
         DataLayer columnHeaderDataLayer = new DataLayer(columnHeaderDataProvider);
-        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);
+        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, topMostLayer, selectionLayer);
 
         // add the SortHeaderLayer to the column header layer stack
         // as we use GlazedLists, we use the GlazedListsSortModel which
@@ -683,7 +712,7 @@ ICdmEntitySessionEnabled{
         cellStyle.setAttributeValue(CellStyleAttributes.HORIZONTAL_ALIGNMENT, HorizontalAlignmentEnum.LEFT);
 
         // add custom configuration for data conversion and add column labels to viewport layer
-        viewportLayer.addConfiguration(new AbstractRegistryConfiguration() {
+        topMostLayer.addConfiguration(new AbstractRegistryConfiguration() {
             @Override
             public void configureRegistry(IConfigRegistry configRegistry) {
                 //add display converter for string representation
@@ -737,7 +766,7 @@ ICdmEntitySessionEnabled{
 
         // add the ExportCommandHandler to the ViewportLayer in order to make
         // exporting work
-        viewportLayer.registerCommandHandler(new ExportCommandHandler(viewportLayer));
+        topMostLayer.registerCommandHandler(new ExportCommandHandler(topMostLayer));
 
         //propagate single cell selection
         natTable.addLayerListener(new ILayerListener() {
@@ -774,6 +803,15 @@ ICdmEntitySessionEnabled{
         wsLabel.getParent().layout();
 
         parent.layout();
+
+        natTable.addConfiguration(new DefaultFreezeGridBindings());
+
+        //freeze supplemental info columns
+        //TODO: calculate row count for freeze position
+        FreezeHelper.freeze(freezeLayer, viewportLayer,
+                new PositionCoordinate(viewportLayer, 0, 0),
+                new PositionCoordinate(viewportLayer, LEADING_COLUMN_COUNT-1, Integer.MAX_VALUE));
+
     }
 
     private void selectStateItem(ComboViewer comboStates, String stateName){
