From caee0fbd542912eb26cdfbdb62aa6ab5bd62e65c Mon Sep 17 00:00:00 2001
From: Renaud Le Gac <legac@cppm.in2p3.fr>
Date: Wed, 10 Oct 2012 16:27:27 +0200
Subject: [PATCH] Redesign the FilterBox as LinkedComboBox.

---
 models/widgets_fields.py                    |  11 +-
 static/plugin_dbui/CHANGELOG                |   1 +
 static/plugin_dbui/src/appfilterbox.js      |  32 -----
 static/plugin_dbui/src/applinkedcombobox.js | 123 ++++++++++++++++++++
 4 files changed, 129 insertions(+), 38 deletions(-)
 delete mode 100644 static/plugin_dbui/src/appfilterbox.js
 create mode 100644 static/plugin_dbui/src/applinkedcombobox.js

diff --git a/models/widgets_fields.py b/models/widgets_fields.py
index 87c03bb3..af93efa9 100755
--- a/models/widgets_fields.py
+++ b/models/widgets_fields.py
@@ -28,15 +28,14 @@ fieldsModifier.merge_fields('conference_start',
 #
 fieldsModifier = dbui.FieldsModifier('foo1')
 fieldsModifier.configure_field('my_axis',
-                               displayField='axis',
-                               mode='local',
-                               store='axesStore',
-                               valueField='axis', 
-                               xtype='xfilterbox')
+                               master=True,
+                               masterField='axis',
+                               masterStore='axesStore',
+                               xtype='xlinkedcombobox')
 
 fieldsModifier.configure_field('my_granularity',
                                displayField='granularity',
                                mode='local',
                                store='axesStore',
                                valueField='granularity', 
-                               xtype='xfilterbox')
+                               xtype='xlinkedcombobox')
diff --git a/static/plugin_dbui/CHANGELOG b/static/plugin_dbui/CHANGELOG
index 49d22d41..6a876243 100644
--- a/static/plugin_dbui/CHANGELOG
+++ b/static/plugin_dbui/CHANGELOG
@@ -5,6 +5,7 @@ HEAD
   - Improve the files organization defining the model.
   - Enable tab scrolling in viewport.
   - Add the possibility to define static store (Ext.data.ArrayStore) in the model.
+  - Add a new widget LinkedComboBox.
   
 0.4.8.2 (Jul 2012)
   - Consolidation version
diff --git a/static/plugin_dbui/src/appfilterbox.js b/static/plugin_dbui/src/appfilterbox.js
deleted file mode 100644
index b484d07b..00000000
--- a/static/plugin_dbui/src/appfilterbox.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * combobox setup to filter the content of its local store
- * 
- * @extends Ext.form.ComboBox 
- *
- */
-Ext.namespace('App.form');
-
-App.form.FilterBox = Ext.extend(App.form.ComboBox, {
-    
-    /**
-     * private method require by the ExtJS component model
-     */	
-    initComponent: function () {
-
-        // construct the underlying class. DON'T MOVE
-        App.form.FilterBox.superclass.initComponent.call(this);
-
-        //logic to filter the content of the store to the combobox value
-        this.on('select', this.onChange, this);
-        
-    },
-
-    /**
-     * Handler to catch a change in field value anf to filter the store
-     */    
-    onChange: function (combo, record, index) {
-        this.store.filter(this.displayField, combo.getValue());
-    }
-});
-
-Ext.reg('xfilterbox', App.form.FilterBox);
diff --git a/static/plugin_dbui/src/applinkedcombobox.js b/static/plugin_dbui/src/applinkedcombobox.js
new file mode 100644
index 00000000..a56d6c5c
--- /dev/null
+++ b/static/plugin_dbui/src/applinkedcombobox.js
@@ -0,0 +1,123 @@
+/**
+ * Linked combobox has been designed to solve the case with two comboboxes
+ * where the values of the second one depend on the select value of the 
+ * first one.
+ * 
+ * The design is based on a master and a slave combobox which are 
+ * linked to a common store.
+ * 
+ * The master shows the values which are used to filter the common store.
+ * Values are unique and sorted in alphabetic order. It is enough to define 
+ * the properties master, masterField and masterStore to setup a master.
+ * 
+ * A slave is a standard combobox. The store identifier should be the same
+ * than the masterStore.
+ * 
+ * Several masters and slaves can be attached to a single store.
+ * 
+ * @extends Ext.form.ComboBox 
+ *
+ */
+Ext.namespace('App.form');
+
+App.form.LinkedComboBox = Ext.extend(Ext.form.ComboBox, {
+   
+    /**
+     * @cfg {Boolean] master true for a master combobox. default is false.
+     */ 
+    master: false,
+    
+    /**
+     * @cfg {String] masterField field of the common store display in the combobox
+     */ 
+    masterField: null,
+ 
+    /**
+     * @cfg {String] masterStore identifier of the store used by masters and slave
+     */ 
+    masterStore: null,
+    
+    /**
+     * private method require by the ExtJS component model
+     */	
+    initComponent: function () {
+
+
+        // configure a master combobox.
+        // create a local store containing the values which can be used 
+        // to filter the master store
+        if (this.master) {
+            
+            this.mode = 'local';
+            this.store = [];
+            this.masterStore = App.getStore(this.masterStore);
+            this.masterStore.each(this.fillData, this);
+            this.store.sort();
+            this.triggerAction = 'all';
+
+        // configure a slave combobox
+        } else {
+            
+            this.store = App.getStore(this.store);
+            this.triggerAction = 'all';
+        }
+
+        // construct the underlying class. DON'T MOVE
+        App.form.LinkedComboBox.superclass.initComponent.call(this);
+
+        // logic to filter the content of the master store
+        if (this.master) {
+            this.on('select', this.filterMasterStore, this);
+                
+        // logic to update the content of a slave
+        } else {
+            this.store.on('datachanged', this.onDataChanged, this);
+        }
+    },
+
+    /**
+     * Helper method to extract the master values to filter the common store.
+     * 
+     * @param {Ext.data.Record} record
+     */
+    fillData: function (record) {
+        var i,
+            value = record.get(this.masterField);
+
+        // initialise the list        
+        if (this.store.length === 0) {
+            this.store.push(value);
+            return;
+        } 
+        
+        // avoid duplicate entries
+        for (i = 0; i < this.store.length; i += 1) {
+            if (value === this.store[i]) {
+                return;
+            }
+        }
+        this.store.push(value);
+    },
+    
+    /**
+     * Helper method to filter the master store
+     * 
+     * @param {Ext.form.combobox} combo
+     * @param {Ext.data.Record} record
+     * @param {Integer} index
+     */
+    filterMasterStore: function (combo, record, index) {
+        this.masterStore.filter(this.masterField, combo.getValue());
+    },
+    
+    /**
+     * Helper method to update the combo box content and to select
+     * the first value of the filtered store
+     */
+    onDataChanged: function () {
+        var value = this.store.getAt(0).get(this.displayField);
+        this.setValue(value);
+    } 
+});
+
+Ext.reg('xlinkedcombobox', App.form.LinkedComboBox);
-- 
GitLab