From f525061bab60ed9c5c9d629a36f92c65447ccdcd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Thu, 4 Jun 2020 19:06:14 +0200
Subject: [PATCH] [dome] table user settings

---
 ivette/src/dome/src/renderer/table/views.tsx | 75 ++++++++++++++++++--
 ivette/src/renderer/Properties.tsx           |  1 +
 2 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/ivette/src/dome/src/renderer/table/views.tsx b/ivette/src/dome/src/renderer/table/views.tsx
index 9c566b3ce0a..c1b078274bf 100644
--- a/ivette/src/dome/src/renderer/table/views.tsx
+++ b/ivette/src/dome/src/renderer/table/views.tsx
@@ -8,7 +8,7 @@
  */
 
 import React, { ReactNode } from 'react';
-import { debounce } from 'lodash';
+import { forEach, debounce } from 'lodash';
 import isEqual from 'react-fast-compare';
 import * as Dome from 'dome';
 import { DraggableCore } from 'react-draggable';
@@ -213,12 +213,24 @@ function makeDataRenderer(
   });
 }
 
+// --------------------------------------------------------------------------
+// --- Table Settings
+// --------------------------------------------------------------------------
+
+type ColSettings<A> = { [id: string]: undefined | null | A };
+
+type TableSettings = {
+  resize?: ColSettings<number>;
+  visible?: ColSettings<boolean>;
+}
+
 // --------------------------------------------------------------------------
 // --- Table State
 // --------------------------------------------------------------------------
 
 class TableState<Key, Row> {
 
+  settings?: string; // User settings
   signal?: Trigger; // Full reload
   width?: number; // Current table width
   offset?: number; // Current resizing offset
@@ -256,6 +268,7 @@ class TableState<Key, Row> {
     this.onRowRightClick = this.onRowRightClick.bind(this);
     this.onKeyDown = this.onKeyDown.bind(this);
     this.onSorting = this.onSorting.bind(this);
+    this.clearSettings = this.clearSettings.bind(this);
     this.rebuild = debounce(this.rebuild.bind(this), 5);
     this.rowGetter = makeRowGetter();
   }
@@ -312,7 +325,7 @@ class TableState<Key, Row> {
     this.resizing = undefined;
     this.offset = undefined;
     this.columnWith.clear();
-    this.forceUpdate();
+    this.updateSettings();
   }
 
   // Debounced
@@ -327,7 +340,55 @@ class TableState<Key, Row> {
       resize.set(lcol, wl);
       resize.set(rcol, wr);
       this.offset = offset;
-      this.forceUpdate();
+      this.forceUpdate(); // no settings yet, onStop only
+    }
+  }
+
+  // --- Table settings
+
+  clearSettings() {
+    this.resize.clear();
+    this.visible.clear();
+    this.forceUpdate();
+  }
+
+  updateSettings() {
+    const userSettings = this.settings;
+    if (userSettings) {
+      const cws: ColSettings<number> = {};
+      const cvs: ColSettings<boolean> = {};
+      const resize = this.resize;
+      const visible = this.visible;
+      this.columns.forEach(({ id }) => {
+        const cw = resize.get(id);
+        const cv = visible.get(id);
+        cws[id] = cw === undefined ? null : cw;
+        cvs[id] = cv === undefined ? null : cv;
+      });
+      const theSettings: TableSettings = { resize: cws, visible: cvs };
+      Dome.setWindowSetting(userSettings, theSettings);
+    }
+    this.forceUpdate();
+  }
+
+  importSettings(settings?: string) {
+    if (settings !== this.settings) {
+      this.settings = settings;
+      const resize = this.resize;
+      const visible = this.visible;
+      resize.clear();
+      visible.clear();
+      const theSettings: undefined | TableSettings =
+        Dome.getWindowSetting(settings);
+      if (theSettings) {
+        forEach(theSettings.resize, (cw, cid) => {
+          if (typeof cw === 'number') this.resize.set(cid, cw);
+        });
+        forEach(theSettings.visible, (cv, cid) => {
+          if (typeof cv === 'boolean') this.visible.set(cid, cv);
+        });
+        this.forceUpdate();
+      }
     }
   }
 
@@ -465,12 +526,12 @@ class TableState<Key, Row> {
     });
     const resetSizing = () => {
       this.resize.clear();
-      this.forceUpdate();
+      this.updateSettings();
     };
     const resetColumns = () => {
       this.visible.clear();
       this.resize.clear();
-      this.forceUpdate();
+      this.updateSettings();
     };
     const items: PopupMenu = [
       {
@@ -500,7 +561,7 @@ class TableState<Key, Row> {
           const checked = isVisible(visible, col);
           const onClick = () => {
             visible.set(id, !checked);
-            this.forceUpdate();
+            this.updateSettings();
           };
           items.push({ label: label || title || id, checked, onClick });
       }
@@ -903,6 +964,7 @@ export function Table<Key, Row>(props: TableProps<Key, Row>) {
   const [age, setAge] = React.useState(0);
   React.useEffect(() => {
     state.signal = () => setAge(age + 1);
+    state.importSettings(props.settings);
     state.setModel(props.model);
     state.setSorting(props.sorting);
     state.setRendering(props.rendering);
@@ -910,6 +972,7 @@ export function Table<Key, Row>(props: TableProps<Key, Row>) {
     state.onContextMenu = props.onContextMenu;
     return state.unwind;
   });
+  Dome.useEvent('dome.defaults', state.clearSettings);
 
   return (
     <div className='dome-xTable'>
diff --git a/ivette/src/renderer/Properties.tsx b/ivette/src/renderer/Properties.tsx
index 477361cb83b..3061204a39b 100644
--- a/ivette/src/renderer/Properties.tsx
+++ b/ivette/src/renderer/Properties.tsx
@@ -120,6 +120,7 @@ const RenderTable = () => {
       sorting={model}
       selection={selection}
       onSelection={onSelection}
+      settings="ivette.properties.table"
     >
       <ColumnCode id="function" label="Function" width={120} />
       <ColumnCode id="descr" label="Description" fill />
-- 
GitLab