[Commits] r2814 - in sandbox/gxm/geoext/gxm: lib/GXM/widgets tests/lib/widgets

commits at geoext.org commits at geoext.org
Wed Aug 17 15:39:17 CEST 2011


Author: marcjansen
Date: 2011-08-17 15:39:17 +0200 (Wed, 17 Aug 2011)
New Revision: 2814

Modified:
   sandbox/gxm/geoext/gxm/lib/GXM/widgets/Button.js
   sandbox/gxm/geoext/gxm/tests/lib/widgets/Button.test.html
Log:
[gxm]
  * GXM.Button: make autoactivation of controls according to 'pressed' configuration happen even if the control was already added to a map
  * GXM.Button: implement cleanup on butoon.destroy() calls

Modified: sandbox/gxm/geoext/gxm/lib/GXM/widgets/Button.js
===================================================================
--- sandbox/gxm/geoext/gxm/lib/GXM/widgets/Button.js	2011-08-17 13:36:22 UTC (rev 2813)
+++ sandbox/gxm/geoext/gxm/lib/GXM/widgets/Button.js	2011-08-17 13:39:17 UTC (rev 2814)
@@ -127,6 +127,19 @@
      */
     control:null,
     
+    /** private: property[autoadded]
+     * 
+     *  ``Boolean`` When a button instance is created with a control that did 
+     *  not belong to a map already we add it to the configured map. That also 
+     *  means that we are responsible for removing said control from the map in 
+     *  the case that this button is destroyed. This property tracks whether we 
+     *  added the control to a map.
+     *  
+     *  Defaults to `null` but will be set to the correct value on
+     *  button instanciation. 
+     */
+    autoadded: null,
+    
     /** private: method[initComponent]
      * 
      *  Initializes the button.
@@ -152,19 +165,29 @@
         
         if (this.control) {
             if (this.map  && !this.control.map ) {
+                // add the control to the configured map
                 this.map.addControl(this.control);
-                if(this.pressed && this.control.map) {
-                    this.addCls(this.pressedCls);
-                    this.control.activate();
-                }
+                // add internal flag to remove the control 
+                // from the map when this button is destroyed
+                this.autoadded = true;
+            } else {
+                this.autoadded = false;
             }
+            // if we were configured with pressed:true,
+            // we need to activate the control and add 
+            // the appropriate css class 
+            if(this.pressed && this.control.map) {
+                this.addCls(this.pressedCls);
+                this.control.activate();
+            }
+            // register the handlers that sync the visual pressed
+            // state with the controls active-state
             this.control.events.on({
                 activate: this.onCtrlActivate,
                 deactivate: this.onCtrlDeactivate,
                 scope: this
             });
         }
-        
     },
     
     /** private: method[pHandler]
@@ -250,6 +273,33 @@
         if(!this._isDeactivating) {
             this.removeCls(this.pressedCls);
         }
+    },
+    
+    /** private method[beforeDestroy]
+     * 
+     *  Called prior to destroying the button. We remove all our registered 
+     *  handlers and nullify relevant properties.
+     */
+    beforeDestroy: function() {
+        // unregister button for de/activating in exclusiveGroups
+        GXM.Button.manager.unregister(this);
+
+        // unregister the handlers that synced the visual pressed
+        // state with the controls active-state
+        if (this.control && this.control.events) {
+            this.control.events.un({
+                activate: this.onCtrlActivate,
+                deactivate: this.onCtrlDeactivate,
+                scope: this
+            });
+            // remove the control from the map if we added it
+            if (this.autoadded) {
+                this.map.removeControl(this.control);
+            } 
+        }
+        
+        delete this.control;
+        GXM.Button.superclass.beforeDestroy.call(this);
     }
 });
 

Modified: sandbox/gxm/geoext/gxm/tests/lib/widgets/Button.test.html
===================================================================
--- sandbox/gxm/geoext/gxm/tests/lib/widgets/Button.test.html	2011-08-17 13:36:22 UTC (rev 2813)
+++ sandbox/gxm/geoext/gxm/tests/lib/widgets/Button.test.html	2011-08-17 13:39:17 UTC (rev 2814)
@@ -220,6 +220,9 @@
         cmp = Ext.ComponentMgr.create( minimumConf, xtype );
  
         t.ok(cmp instanceof clazz, 'The xtype "' + xtype + '" points to the class "' + className + '".');
+        
+        // teardown
+        cmp.destroy();
     } else {
         t.ok(false, "Since the xtype is not registered, we cannot check whether it points to the right class");
     }
@@ -328,6 +331,9 @@
         t.delay_call(1, function(){
             t.eq(triggerCnt, 1, 'The controls trigger method has been called once (triggerCnt incremented)');
             t.eq(handlerCnt, 1, 'The buttons handler method has been called once (handlerCnt incremented)');
+            
+            // teardown
+            btn.destroy();
         });
     });
 }
@@ -396,6 +402,9 @@
             t.eq(activateCnt, 1, 'ctrl.activate() was called.');
             t.eq(deactivateCnt, 0, 'ctrl.deactivateCnt() was not called.');
             t.eq(handlerCnt, 1, 'btn.handler-meth0d was called.');
+            
+            // teardown
+            btn.destroy();
         });
     });
 }
@@ -446,6 +455,9 @@
         t.eq(passedArguments.gxmBtn.length, 3,  'GXM.Button instances pass exactly three arguments');
         t.ok(Ext.isBoolean(passedArguments.gxmBtn[2]), 'Third argument is a boolean...');
         t.eq(passedArguments.gxmBtn[2], ctrl.active,  '... that represents the controls active-state.');
+        
+        // teardown
+        gxmBtn.destroy();
     });
 }
 
@@ -490,12 +502,147 @@
                 ctrl.deactivate(); 
                 t.delay_call(1, function(){
                     t.eq(gxmBtn.getEl().hasCls(gxmBtn.pressedCls), gxmBtn.control.active, 'states and pressedCls are in sync (triggered via ctrl), class present? ' + gxmBtn.getEl().hasCls(gxmBtn.pressedCls) + ', control active? ' + gxmBtn.control.active);
+                    gxmBtn.destroy();
                 });
             });
         });
     });
 }
+
+function test_destroy(t) {
+    var funcToStringSupported = !!(Function.prototype.toString);
+    
+    if (funcToStringSupported) {
+        t.plan(6);
+    } else {
+        t.plan(4);
+    }
+    
+    // setup   
+    var ctrl = new OpenLayers.Control({});
+    var map = new OpenLayers.Map({controls:[]});
+    var onCtrlDeactivateFunc = function(){return 'deactivate';};
+    var onCtrlActivateFunc = function(){return 'activate';};
+    
+    var btn = new GXM.Button({
+        control: ctrl,
+        map: map,
+        onCtrlDeactivate: onCtrlDeactivateFunc,
+        onCtrlActivate: onCtrlActivateFunc
+    });
         
+    // 4 tests
+    // have the events been registered?    
+    t.eq(ctrl.events.listeners.activate.length, 1,
+        'A activate eventlistener was added to the control');
+    t.eq(ctrl.events.listeners.deactivate.length, 1,
+        'A deactivate eventlistener was added to the control');
+    
+    if (funcToStringSupported) {
+        t.eq(ctrl.events.listeners.activate[0].func.toString(), 
+            onCtrlActivateFunc.toString(), 
+            'The correct activate eventlistener was added to the control');
+        t.eq(ctrl.events.listeners.deactivate[0].func.toString(), 
+            onCtrlDeactivateFunc.toString(), 
+            'The correct deactivate eventlistener was added to the control');
+    }
+    btn.destroy();
+    
+    // 2 tests
+    // destroy the button... our eventlisteners should be gone
+    t.eq(ctrl.events.listeners.activate.length, 0,
+        'The activate eventlistener was removed from the control');
+    t.eq(ctrl.events.listeners.deactivate.length, 0,
+        'The deactivate eventlistener was removed from the control');
+}
+
+function test_controlRemovalOnButtonDestroy(t){
+    t.plan(4);
+    
+    // setup   
+    var ctrl = new OpenLayers.Control({});
+    var map = new OpenLayers.Map({controls:[]});
+    map.addControl(ctrl);
+    
+    var btn = new GXM.Button({
+        control: ctrl
+    });
+    
+    // 1 test
+    // autoadded should be false, since the control already belonged to a map
+    t.eq(btn.autoadded, false, 
+        'btn.autoadded property is set to false ' +
+        'when the control already belonged to the map.');
+    
+    btn.destroy();
+    
+    // 1 test
+    // leave the control in the map on destroy
+    t.eq(map.controls.length, 1, 
+        'map contains one control that was once managed by a button ' +
+        'even if that button is destroyed.');
+    
+    
+    // setup
+    ctrl = new OpenLayers.Control({});
+    map = new OpenLayers.Map({controls:[]});
+        
+    btn = new GXM.Button({
+        control: ctrl,
+        map: map
+    });
+    
+    // 1 test
+    // autoadded should be true, since the control did not belong to a map
+    t.eq(btn.autoadded, true, 
+        'btn.autoadded property is set to true ' +
+        'when the control was added to amap by GXM.Button-constructor.');
+        
+    btn.destroy();
+    
+    // 1 test
+    // remve the control in the map on destroy
+    t.eq(map.controls.length, 0, 
+        'map does not contain a control that was once managed by a button ' +
+        'because that button is destroyed and we added it to the map.');
+}
+
+function test_ButtonManager(t){
+    t.plan(5);
+    
+    // 2 tests
+    // we always have a ButtonManager instance.
+    t.ok(GXM.Button.manager && Ext.isDefined(GXM.Button.manager), 
+        'GXM.Button.manager is truthy and defined');
+    t.ok(GXM.Button.manager instanceof Ext.AbstractManager, 
+        'GXM.Button.manager is an instance of Ext.AbstractManager');
+    
+    var ctrl = new OpenLayers.Control({});
+    var map = new OpenLayers.Map();
+        
+    var btn = new GXM.Button({
+        control: ctrl,
+        map: map
+    });
+    var btnId = btn.id;
+    
+    // 2 tests
+    // a button is added to the manager on instanciation
+    t.eq(GXM.Button.manager.getCount(), 1,
+        'GXM.Button.manager manages exactly one button.');
+    t.eq(GXM.Button.manager.get(btnId).id, btn.id,
+        'GXM.Button.manager manages the right button.');
+    
+    // a button is removed from the manager when it is being destroyed
+    btn.destroy();
+    
+    // 1 test
+    // a button is added to the manager on instanciation
+    t.eq(GXM.Button.manager.getCount(), 0,
+        'GXM.Button.manager manages exactly zero buttons.');
+
+}
+
         </script>
     </head>
     <body>



More information about the Commits mailing list