Related to issue 18227: Closing a tab doesn't release all objects
authorMartin Taal <martin.taal@openbravo.com>
Thu, 01 Sep 2011 12:00:38 +0200
changeset 13644 ddf08e2b22d9
parent 13643 d9a96d401f20
child 13645 b21bbf743e3f
Related to issue 18227: Closing a tab doesn't release all objects
Prevent recompute of fields when datasource is set in form
Create/initialize datasources in the init method and not as part of properties (results in too early initialization)
Destroy datasources which are not shared when destroying a field
Explicitly remove old tab pane when a new tab pane gets set
modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-form.js.ftl
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quick-launch.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-view-manager.js
modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/ob-myopenbravo.js
modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/ob-widget.js
modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/templates/datasource.ftl
modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/templates/selector-as-link.ftl
modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/templates/selector.ftl
modules/org.openbravo.userinterface.selector/web/org.openbravo.userinterface.selector/js/ob-selector-item.js
modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-form.js.ftl	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/templates/ob-view-form.js.ftl	Thu Sep 01 12:00:38 2011 +0200
@@ -19,7 +19,14 @@
 */
 -->
 {
-    fields: [
+    // use theFields instead of fields, when the form
+    // gets created, initialized, the datasource is
+    // set (ob-standard-view.js buildStructure) 
+    // causing re-initialization of the fields,
+    // removing the current ones and recreating new ones
+    // by using theFields, the form initially does not
+    // have fields, which prevents this initial destroy step
+    theFields: [
     <#list data.fields as field>
       <@createField field/><#if field_has_next>,</#if>
     </#list>    
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Thu Sep 01 12:00:38 2011 +0200
@@ -90,7 +90,8 @@
 
     // is used to keep track of the original simple objects
     // used to create fields
-    this._originalFields = isc.shallowClone(this.fields);
+    // note fields can be in fields or theFields
+    this._originalFields = isc.shallowClone(this.fields || this.theFields);
     
     this.Super('initWidget', arguments);
 
@@ -1562,7 +1563,7 @@
     // caching reference to all DS of Items
     for (i = 0; i < len; i++) {
       item = items[i];
-      ds = items && (item.dataSource || item.optionDataSource);
+      ds = item ? item.dataSource || item.optionDataSource : null;
 
       if(ds) {
         dataSources.push(ds);
@@ -1570,7 +1571,6 @@
     }
 
     this.Super('destroy', arguments);
-
     len = dataSources.length;
 
     // Destroying DS not managed by DynamicForm.destroy
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Thu Sep 01 12:00:38 2011 +0200
@@ -258,7 +258,14 @@
       // setDataSource executes setFields which replaces the current fields
       // We don't want to destroy the associated DataSource objects
       this.viewForm.destroyItemObjects = false;
-      this.viewForm.setDataSource(this.dataSource, this.viewForm.fields);
+      
+      // initially the viewForm.fields is not set, the fields are
+      // in this.viewForm.theFields, this to prevent too early creation of fields
+      // i.e. they are recreated when setting the datasource, as is done
+      // here.
+      // make sure the fields are set now
+      this.viewForm.fields = this.viewForm.theFields;
+      this.viewForm.setDataSource(this.dataSource, this.viewForm.theFields);
       this.viewForm.isViewForm = true;
       this.viewForm.destroyItemObjects = true;
     }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quick-launch.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/navbar/ob-quick-launch.js	Thu Sep 01 12:00:38 2011 +0200
@@ -88,7 +88,9 @@
           index++;
         }
       }
+
       this.members[0].setMembers(newFields);
+
       this.layout.showMember(this.members[0]);
     }
     this.members[1].getField('value').setValue(null);
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/personalization/ob-personalize-form.js	Thu Sep 01 12:00:38 2011 +0200
@@ -728,7 +728,7 @@
   
   // creates the preview form and displays it
   buildPreviewForm: function() {
-    var statusBar, i, fld, itemClick, me = this;
+    var statusBar, currentPane, i, fld, itemClick, me = this;
     
     this.formLayout = isc.VLayout.create({ height: '100%', width: '100%'}, OB.Styles.Personalization.Preview);
     
@@ -820,7 +820,13 @@
     
     this.formLayout.addMember(this.previewForm);
     
+    if (this.previewTabSet.getTab(0).pane) {
+      currentPane = this.previewTabSet.getTab(0).pane;
+    }    
     this.previewTabSet.updateTab(this.previewTabSet.getTab(0), this.formLayout);
+    if (currentPane) {
+      currentPane.destroy();
+    }
   },
   
   buildFormAndTree: function() {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-view-manager.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-view-manager.js	Thu Sep 01 12:00:38 2011 +0200
@@ -265,7 +265,8 @@
           // 1) view is not open and class not loaded (open view and show loading bar)
           // 2) view is not open but class was loaded (open view and show loading bar)
           // 3) view is open and class is loaded (show loading bar in open view)          
-          var viewTabId, tabTitle, loadingTab = vmgr.findLoadingTab(params), loadingPane,
+          var viewTabId, tabTitle, loadingTab = vmgr.findLoadingTab(params), 
+              loadingPane, currentPane,
               tabSet = OB.MainView.TabSet;
 
           params = params || {};
@@ -286,7 +287,15 @@
               loadingPane.isLoadingTab = true;
 
               // refresh the existing tab
+              // explicitly destroy as the old tab is not destroyed
+              if (tabSet.getTabObject(viewTabId)) {
+                currentPane = tabSet.getTabObject(viewTabId).pane;  
+              }
               tabSet.updateTab(viewTabId, loadingPane);
+              if (currentPane) {
+                currentPane.destroy();
+              }
+              
               // and show it
               tabSet.selectTab(viewTabId);
             } else {
@@ -296,12 +305,14 @@
               params = vmgr.createLoadingTab(viewName, params, viewTabId);
             }
             // use a canvas to make use of the fireOnPause possibilities
+            // but don't forget to destroy it afterwards...
             var cnv = isc.Canvas.create({
               openView: function() {
                 vmgr.openView(viewName, params);
                 // delete so that at the next opening a new loading layout
                 // is created
                 delete params.loadingTabId;
+                this.destroy();
               }
             });
             cnv.fireOnPause('openView', cnv.openView, null, cnv);
@@ -332,7 +343,16 @@
           if (viewTabId !== null) {
 
             // refresh the view
+
+            // refresh the existing tab
+            // explicitly destroy as the old tab is not destroyed
+            if (tabSet.getTabObject(viewTabId)) {
+              currentPane = tabSet.getTabObject(viewTabId).pane;  
+            }
             tabSet.updateTab(viewTabId, viewInstance);
+            if (currentPane) {
+              currentPane.destroy();
+            }
 
             // and show it
             tabSet.selectTab(viewTabId);
--- a/modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/ob-myopenbravo.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/ob-myopenbravo.js	Thu Sep 01 12:00:38 2011 +0200
@@ -355,7 +355,9 @@
   },
 
   setRecentList: function(layout){
-    var recentList, newRecent, recentIndex = 0, recent, lbl, newIcon, entryLayout, icon;
+    var recentList, newRecent,  
+      recentIndex = 0, recent, lbl, newIcon, entryLayout, icon;
+    
     // start with a fresh content
     layout.removeMembers(layout.members);
     
@@ -447,10 +449,12 @@
   },
   
   setRecentDocumentsList: function(layout){
-    var recentList, newRecent, recentIndex = 0, recent, lbl, newIcon, entryLayout, icon;
+    var recentList, newRecent, recentIndex = 0, recent, 
+      lbl, newIcon, entryLayout, icon;
+    
     // start with a fresh content
     layout.removeMembers(layout.members);
-    
+
     // reads the list of recents and displays them
     recentList = OB.Layout.ViewManager.recentManager.getRecentValue('OBUIAPP_RecentDocumentsList');
     if (recentList && recentList.length > 0) {
--- a/modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/ob-widget.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.client.myob/web/org.openbravo.client.myob/js/ob-widget.js	Thu Sep 01 12:00:38 2011 +0200
@@ -166,6 +166,7 @@
   showMinimizeButton: false,
   showCloseButton: false,
   closeConfirmationMessage: OB.I18N.getLabel('OBKMO_DeleteThisWidgetConfirmation'),
+  destroyOnClose: true,
   
   canDelete: true,
   dbInstanceId: '',
--- a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/templates/datasource.ftl	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/templates/datasource.ftl	Thu Sep 01 12:00:38 2011 +0200
@@ -38,6 +38,7 @@
         createClassName: '${data.dataSourceClassName?js_string}',
 <#if data.getParameter("_onlyGenerateCreateStatement") == "" || data.getParameter("_create") != "">
         ID:'${data.id}',
+        potentiallyShared: true,
 </#if>
 <#if data.getParameter("_new") != "">
         _new: true,
--- a/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/templates/selector-as-link.ftl	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/templates/selector-as-link.ftl	Thu Sep 01 12:00:38 2011 +0200
@@ -48,7 +48,13 @@
     </#list>
     },
     extraSearchFields: [${data.extraSearchFields}],
-    dataSource: ${data.dataSourceJavascript},
+    // create the datasource in the init method, this
+    // prevents too early creation, it is created when the
+    // fields on the form are actually created
+    init: function() {    
+        this.dataSource = ${data.dataSourceJavascript};
+        this.Super('init', arguments);
+    },
     whereClause : '${data.whereClause?js_string}'
 <#else>
 /* jslint */
--- a/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/templates/selector.ftl	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.userinterface.selector/src/org/openbravo/userinterface/selector/templates/selector.ftl	Thu Sep 01 12:00:38 2011 +0200
@@ -49,7 +49,13 @@
     </#list>
     },
     extraSearchFields: [${data.extraSearchFields}],
-    optionDataSource: ${data.dataSourceJavascript},
+    // create the datasource in the init method, this
+    // prevents too early creation, it is created when the
+    // fields on the form are actually created
+    init: function() {
+        this.optionDataSource = ${data.dataSourceJavascript};
+        this.Super('init', arguments);
+    },
     whereClause : '${data.whereClause?js_string}',
     outHiddenInputPrefix: '${data.outHiddenInputPrefix}'
 <#else>
--- a/modules/org.openbravo.userinterface.selector/web/org.openbravo.userinterface.selector/js/ob-selector-item.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.userinterface.selector/web/org.openbravo.userinterface.selector/js/ob-selector-item.js	Thu Sep 01 12:00:38 2011 +0200
@@ -383,7 +383,7 @@
       this.icons = null;
     }
     
-    if (this.showSelectorGrid) {
+    if (this.showSelectorGrid && !this.form.isPreviewForm) {
       this.selectorWindow = isc.OBSelectorPopupWindow.create({
         // solves issue: https://issues.openbravo.com/view.php?id=17268
         title: (this.form && this.form.grid ? this.form.grid.getField(this.name).title : this.title),
@@ -762,15 +762,17 @@
       this.icons = null;
     }
     
-    this.selectorWindow = isc.OBSelectorPopupWindow.create({
-      // solves issue: https://issues.openbravo.com/view.php?id=17268
-      title: (this.form && this.form.grid ? this.form.grid.getField(this.name).title : this.title),
-      dataSource: this.dataSource,
-      selector: this,
-      valueField: this.gridValueField,
-      displayField: this.gridDisplayField,
-      selectorGridFields: isc.shallowClone(this.selectorGridFields)
-    });
+    if (!this.form.isPreviewForm) {
+      this.selectorWindow = isc.OBSelectorPopupWindow.create({
+        // solves issue: https://issues.openbravo.com/view.php?id=17268
+        title: (this.form && this.form.grid ? this.form.grid.getField(this.name).title : this.title),
+        dataSource: this.dataSource,
+        selector: this,
+        valueField: this.gridValueField,
+        displayField: this.gridDisplayField,
+        selectorGridFields: isc.shallowClone(this.selectorGridFields)
+      });
+    }
     
     return this.Super('init', arguments);
   },
--- a/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js	Thu Sep 01 11:08:07 2011 +0200
+++ b/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js	Thu Sep 01 12:00:38 2011 +0200
@@ -79,6 +79,20 @@
     this._original_init();
   },
   
+  // make sure that the datasources are also destroyed
+  _original_destroy: isc.FormItem.getPrototype().destroy,
+  destroy: function() {
+    if (this.optionDataSource && !this.optionDataSource.potentiallyShared) {
+      this.optionDataSource.destroy();
+      this.optionDataSource = null;
+    }
+    if (this.dataSource && !this.dataSource.potentiallyShared) {
+      this.dataSource.destroy();
+      this.dataSource = null;
+    }
+    this._original_destroy();
+  },
+  
   // overridden to not show if hiddenInForm is set
   _show: isc.FormItem.getPrototype().show,
   show: function (arg1) {