From 0d5b59a3e6892e66acc8f5e708896fc2dc7d9c7d Mon Sep 17 00:00:00 2001 From: Sergey Linev <S.Linev@gsi.de> Date: Tue, 30 Apr 2019 14:17:42 +0200 Subject: [PATCH] geom viewer: use BrowserModel from RBrowser Eliminate duplictaed model from geom viewer itself --- ui5/browser/model/BrowserModel.js | 82 ++- ui5/eve7/controller/GeomViewer.controller.js | 2 +- ui5/eve7/model/BrowserListBinding.js | 91 ---- ui5/eve7/model/BrowserModel.js | 499 ------------------- 4 files changed, 82 insertions(+), 592 deletions(-) delete mode 100644 ui5/eve7/model/BrowserListBinding.js delete mode 100644 ui5/eve7/model/BrowserModel.js diff --git a/ui5/browser/model/BrowserModel.js b/ui5/browser/model/BrowserModel.js index f0f7b35680e..806b25e0e39 100644 --- a/ui5/browser/model/BrowserModel.js +++ b/ui5/browser/model/BrowserModel.js @@ -45,6 +45,7 @@ sap.ui.define([ topnode.expanded = true; this.reset_nodes = true; delete this.noData; + this.scanShifts(); if (this.oBinding) this.oBinding.checkUpdate(true); }, @@ -140,6 +141,7 @@ sap.ui.define([ currpath += curr.name + "/"; } + return this.scanShifts(curr); }, sendFirstRequest: function(websocket) { @@ -156,6 +158,7 @@ sap.ui.define([ this.reset_nodes = true; this.fullModel = this.mainFullModel; delete this.noData; + this.scanShifts(); if (this.oBinding) this.oBinding.checkUpdate(true); } else if (!this.fullModel) { @@ -228,9 +231,11 @@ sap.ui.define([ // remember main model if ((reply.path === "/") && !this.mainModel) { this.mainModel = elem.childs; - this.mainFullModel = true; + this.mainFullModel = false; } + this.scanShifts(); + // reset existing nodes if reply does not match with expectation if (!smart_merge) this.reset_nodes = true; @@ -246,6 +251,7 @@ sap.ui.define([ if ((index > 0) && this.treeTable) this.treeTable.setFirstVisibleRow(Math.max(0, index - Math.round(this.treeTable.getVisibleRowCount()/2))); } + }, getNodeByIndex: function(indx) { @@ -259,6 +265,55 @@ sap.ui.define([ return node ? node._elem : null; }, + // function used to calculate all ids shifts and total number of elements + // if element specified - returns index of that element + scanShifts: function(for_elem) { + + var id = 0, full = this.fullModel, res = -1; + + function scan(lvl, elem) { + + if (elem === for_elem) res = id; + + if (lvl >= 0) id++; + + var before_id = id; + + if (elem.expanded) { + if (elem.childs === undefined) { + // do nothing, childs are not visible as long as we do not have any list + + // id += 0; + } else { + + // gap at the begin + if (!full && elem.first) + id += elem.first; + + // jump over all childs + for (var k=0;k<elem.childs.length;++k) + scan(lvl+1, elem.childs[k]); + + // gap at the end + if (!full) { + var _last = (elem.first || 0) + elem.childs.length; + var _remains = elem.nchilds - _last; + if (_remains > 0) id += _remains; + } + } + } + + // this shift can be later applied to jump over all elements + elem._shift = id - before_id; + } + + scan(-1, this.h); + + this.setProperty("/length", id); + + return for_elem ? res : id; + }, + // main method to create flat list of nodes - only whose which are specified in selection // following arguments: // args.begin - first visisble element from flat list @@ -396,6 +451,7 @@ sap.ui.define([ // close folder - reassign shifts this.reset_nodes = true; + this.scanShifts(); return true; @@ -406,12 +462,36 @@ sap.ui.define([ if (this.fullModel) { this.reset_nodes = true; + this.scanShifts(); } return true; } }, + // change sorting method, for now server supports default, "direct" and "reverse" + changeSortOrder: function(newValue) { + if (newValue === undefined) + newValue = this.getProperty("/sortOrder") || ""; + + if ((newValue !== "") && (newValue !=="direct") && (newValue !== "reverse")) { + console.error('WRONG sorting order ', newValue, 'use default'); + newValue = ""; + } + + // ignore same value + if (newValue === this.sortOrder) + return; + + + this.sortOrder = newValue; + + // now we should request values once again + + this.submitRequest(this.h, "/"); + + } + }); return hRootModel; diff --git a/ui5/eve7/controller/GeomViewer.controller.js b/ui5/eve7/controller/GeomViewer.controller.js index 4dfa2f5f5c8..4cbffbebd54 100644 --- a/ui5/eve7/controller/GeomViewer.controller.js +++ b/ui5/eve7/controller/GeomViewer.controller.js @@ -7,7 +7,7 @@ sap.ui.define(['sap/ui/core/Component', "sap/ui/core/ResizeHandler", "sap/ui/layout/HorizontalLayout", "sap/ui/table/Column", - "rootui5/eve7/model/BrowserModel" + "rootui5/browser/model/BrowserModel" ],function(Component, Controller, CoreControl, mText, mCheckBox, Splitter, ResizeHandler, HorizontalLayout, tableColumn, BrowserModel) { diff --git a/ui5/eve7/model/BrowserListBinding.js b/ui5/eve7/model/BrowserListBinding.js deleted file mode 100644 index b4079cc68fb..00000000000 --- a/ui5/eve7/model/BrowserListBinding.js +++ /dev/null @@ -1,91 +0,0 @@ -sap.ui.define([ - "sap/base/Log", - "sap/ui/model/json/JSONListBinding" -], function(Log, JSONListBinding) { - "use strict"; - - var hRootListBinding = JSONListBinding.extend("rootui5.eve7.model.BrowserListBinding", { - - // called by the TreeTable to know the amount of entries - getLength: function() { - // Log.warning("root.model.hListBinding#getLength()"); - return this.getModel().getLength(); - }, - - // function is called by the TreeTable when requesting the data to display - getNodes: function(iStartIndex, iLength, iThreshold) { - - var args = { begin: iStartIndex, end: iStartIndex + iLength, threshold: iThreshold }, - nodes = this.getModel().buildFlatNodes(args); - - var aNodes = []; - - for (var i = args.begin; i < args.end; i++) - aNodes.push(nodes && nodes[i] ? nodes[i] : null); - - console.log("root.model.hListBinding#getNodes(" + iStartIndex + ", " + iLength + ", " + iThreshold + ") res = " + aNodes.length); - - return aNodes; - }, - - getContextByIndex: function(iIndex) { - Log.warning("root.model.hListBinding#getContextByIndex(" + iIndex + ")"); - return this.getModel().getContext(this.getPath() + "/" + iIndex); - }, - - findNode: function() { - Log.warning("root.model.hListBinding#findNode()"); - }, - - nodeHasChildren: function(oNode) { - // Log.warning("root.model.hListBinding#nodeHasChildren(" + oNode.type + ")"); - return oNode.type === "folder"; - }, - - isExpanded: function(iIndex) { - var elem = this.getModel().getElementByIndex(iIndex); - var res = elem ? !!elem.expanded : false; - - Log.warning("root.model.hListBinding#isExpanded(" + iIndex + ") res = " + res + " iselem = " + (elem ? elem._name : "---")); - - return res; - }, - - expand: function(iIndex) { - Log.warning("root.model.hListBinding#expand(" + iIndex + ")"); - }, - - collapse: function(iIndex) { - Log.warning("root.model.hListBinding#collapse(" + iIndex + ")"); - }, - - collapseToLevel: function(lvl) { - console.log('root.model.hListBinding#collapseToLevel', lvl); - }, - - expandToLevel: function(lvl) { - console.log('root.model.hListBinding#expandToLevel', lvl); - }, - - // called by the TreeTable when a node is expanded/collapsed - toggleIndex: function(iIndex) { - console.log("root.model.hListBinding#toggleIndex(" + iIndex + ")"); - if (this.getModel().toggleNode(iIndex)) - this.checkUpdate(true); - - // QUESTION: why one should call checkUpdate?, should it be done automatically always? - }, - - getSelectedIndex: function() { - Log.warning("root.model.hListBinding#getSelectedIndex(" + JSON.stringify(arguments) + ")"); - }, - - isIndexSelectable: function() { - Log.warning("root.model.hListBinding#isIndexSelectable(" + JSON.stringify(arguments) + ")"); - } - - }); - - return hRootListBinding; - -}); \ No newline at end of file diff --git a/ui5/eve7/model/BrowserModel.js b/ui5/eve7/model/BrowserModel.js deleted file mode 100644 index 41bc9551bec..00000000000 --- a/ui5/eve7/model/BrowserModel.js +++ /dev/null @@ -1,499 +0,0 @@ -sap.ui.define([ - "sap/ui/model/json/JSONModel", - "rootui5/eve7/model/BrowserListBinding", - "sap/base/Log" -], function(JSONModel, BrowserListBinding, Log) { - "use strict"; - - var hRootModel = JSONModel.extend("rootui5.eve7.model.BrowserModel", { - - constructor: function() { - JSONModel.apply(this); - this.setProperty("/", { - nodes: {}, // nodes shown in the TreeTable, should be flat list - length: 0 // total number of elements - }); - - // this is true hierarchy, created on the client side and used for creation of flat list - this.h = { - name: "__Holder__", - expanded: true - }; - - this.loadDataCounter = 0; // counter of number of nodes - - this.sortOrder = ""; - - this.threshold = 100; // default threshold to prefetch items - }, - - assignTreeTable: function(t) { - this.treeTable = t; - }, - - /* Method can be used when complete hierarchy is ready and can be used directly */ - setFullModel: function(topnode) { - this.fullModel = true; - this.h.nchilds = 1; - this.h.childs = [ topnode ]; - - if (!this.mainModel) { - this.mainModel = this.h.childs; - this.mainFullModel = true; - } - - topnode.expanded = true; - this.reset_nodes = true; - delete this.noData; - this.scanShifts(); - if (this.oBinding) - this.oBinding.checkUpdate(true); - }, - - clearFullModel: function() { - delete this.h.childs; - delete this.h.nchilds; - delete this.fullModel; - delete this.noData; - this.reset_nodes = true; - if (this.oBinding) - this.oBinding.checkUpdate(true); - }, - - setNoData: function(on) { - this.noData = on; - if (this.oBinding) - this.oBinding.checkUpdate(true); - }, - - bindTree: function(sPath, oContext, aFilters, mParameters, aSorters) { - Log.warning("root.model.hModel#bindTree() " + sPath); - - console.log('BINDING TREE!!!!!!!!!!!!! ' + sPath); - - this.oBinding = new BrowserListBinding(this, sPath, oContext, aFilters, mParameters, aSorters); - return this.oBinding; - }, - - getLength: function() { - if (this.noData) return 0; - return this.getProperty("/length"); - }, - - getNodeByPath: function(path) { - var curr = this.h; - if (!path || (typeof path !== "string") || (path == "/")) return curr; - - var names = path.split("/"); - - while (names.length > 0) { - var name = names.shift(), find = false; - if (!name) continue; // ignore start or stop slash - - for (var k=0;k<curr.childs.length;++k) { - if (curr.childs[k].name == name) { - curr = curr.childs[k]; - find = true; - break; - } - } - - if (!find) return null; - } - return curr; - }, - - /** expand node by given path, when path not exists - try to send request */ - expandNodeByPath: function(path) { - if (!path || (typeof path !== "string") || (path == "/")) return -1; - - var names = path.split("/"), curr = this.h, currpath = "/"; - - while (names.length > 0) { - var name = names.shift(), find = false; - if (!name) continue; // ignore start or stop slash - - if (!curr.childs) { - // request childs for current element - // TODO: we do not know child index, but simply can suply search child as argument - if (!this.fullModel && curr.nchilds) { - curr.expanded = true; - this.reset_nodes = true; - this._expanding_path = path; - this.submitRequest(curr, currpath, "expanding"); - break; - } - return -1; - } - - for (var k=0;k<curr.childs.length;++k) { - if (curr.childs[k].name == name) { - this.reset_nodes = true; - curr.expanded = true; - curr = curr.childs[k]; - find = true; - break; - } - } - - if (!find) return -1; - - currpath += curr.name + "/"; - } - - return this.scanShifts(curr); - }, - - sendFirstRequest: function(websocket) { - this._websocket = websocket; - // submit top-level request already when construct model - this.submitRequest(this.h, "/"); - }, - - reloadMainModel: function(force) { - if (this.mainModel && !force) { - this.h.nchilds = this.mainModel.length; - this.h.childs = this.mainModel; - this.h.expanded = true; - this.reset_nodes = true; - this.fullModel = this.mainFullModel; - delete this.noData; - this.scanShifts(); - if (this.oBinding) - this.oBinding.checkUpdate(true); - } else if (!this.fullModel) { - // send request, content will be reassigned - this.submitRequest(this.h, "/"); - } - - }, - - // submit next request to the server - // directly use web socket, later can be dedicated channel - submitRequest: function(elem, path, first, number) { - - if (first === "expanding") { - first = 0; - } else { - delete this._expanding_path; - } - - if (!this._websocket || elem._requested || this.fullModel) return; - elem._requested = true; - - this.loadDataCounter++; - - var request = { - _typename: "ROOT::Experimental::RBrowserRequest", - path: path, - first: first || 0, - number: number || this.threshold || 100, - sort: this.sortOrder || "" - }; - - this._websocket.Send("BRREQ:" + JSON.stringify(request)); - }, - - // process reply from server - // In the future reply will be received via websocket channel - processResponse: function(reply) { - - this.loadDataCounter--; - - // console.log('PROCESS BR RESPONSE', reply.path, reply); - - var elem = this.getNodeByPath(reply.path); - - if (!elem) { console.error('DID NOT FOUND ' + reply.path); return; } - - if (!elem._requested) console.error('ELEMENT WAS NOT REQUESTED!!!!', reply.path); - delete elem._requested; - - var smart_merge = false; - - if ((elem.nchilds === reply.nchilds) && elem.childs && reply.nodes) { - if (elem.first + elem.childs.length == reply.first) { - elem.childs = elem.childs.concat(reply.nodes); - smart_merge = true; - } else if (reply.first + reply.nodes.length == elem.first) { - elem.first = reply.first; - elem.childs = reply.nodes.concat(elem.childs); - smart_merge = true; - } - } - - if (!smart_merge) { - elem.nchilds = reply.nchilds; - elem.childs = reply.nodes; - elem.first = reply.first || 0; - } - - // remember main model - if ((reply.path === "/") && !this.mainModel) { - this.mainModel = elem.childs; - this.mainFullModel = false; - } - - this.scanShifts(); - - // reset existing nodes if reply does not match with expectation - if (!smart_merge) - this.reset_nodes = true; - - if (this.loadDataCounter == 0) - if (this.oBinding) - this.oBinding.checkUpdate(true); - - if (this._expanding_path) { - var d = this._expanding_path; - delete this._expanding_path; - var index = this.expandNodeByPath(d); - if ((index > 0) && this.treeTable) - this.treeTable.setFirstVisibleRow(Math.max(0, index - Math.round(this.treeTable.getVisibleRowCount()/2))); - } - - }, - - getNodeByIndex: function(indx) { - var nodes = this.getProperty("/nodes"); - return nodes ? nodes[indx] : null; - }, - - // return element of hierarchical structure by TreeTable index - getElementByIndex: function(indx) { - var node = this.getNodeByIndex(indx); - return node ? node._elem : null; - }, - - // function used to calculate all ids shifts and total number of elements - // if element specified - returns index of that element - scanShifts: function(for_elem) { - - var id = 0, full = this.fullModel, res = -1; - - function scan(lvl, elem) { - - if (elem === for_elem) res = id; - - if (lvl >= 0) id++; - - var before_id = id; - - if (elem.expanded) { - if (elem.childs === undefined) { - // do nothing, childs are not visible as long as we do not have any list - - // id += 0; - } else { - - // gap at the begin - if (!full && elem.first) - id += elem.first; - - // jump over all childs - for (var k=0;k<elem.childs.length;++k) - scan(lvl+1, elem.childs[k]); - - // gap at the end - if (!full) { - var _last = (elem.first || 0) + elem.childs.length; - var _remains = elem.nchilds - _last; - if (_remains > 0) id += _remains; - } - } - } - - // this shift can be later applied to jump over all elements - elem._shift = id - before_id; - } - - scan(-1, this.h); - - this.setProperty("/length", id); - - return for_elem ? res : id; - }, - - // main method to create flat list of nodes - only whose which are specified in selection - // following arguments: - // args.begin - first visisble element from flat list - // args.end - first not-visisble element - // args.threshold - extra elements (before/after) which probably should be prefetched - // returns holder object with all existing nodes - buildFlatNodes: function(args) { - - if (this.noData) return null; - - var pthis = this, - id = 0, // current id, at the same time number of items - threshold = args.threshold || this.threshold || 100, - threshold2 = Math.round(threshold/2), - nodes = this.reset_nodes ? {} : this.getProperty("/nodes"); - - // main method to scan through all existing sub-folders - function scan(lvl, elem, path) { - - // create elements with safety margin - if ((lvl >= 0) && (nodes !== null) && !nodes[id] && (id >= args.begin - threshold2) && (id < args.end + threshold2)) { - nodes[id] = { - name: elem.name, - fullpath: path, - index: id, - _elem: elem, - // these are required by list binding, should be eliminated in the future - type: elem.nchilds ? "folder" : "file", - isLeaf: !elem.nchilds, - level: lvl, - context: pthis.getContext("/nodes/" + id), - nodeState: { - expanded: !!elem.expanded, - selected: !!elem.selected, - sum: false // ???? - } - }; - if (typeof pthis.addNodeAttributes == 'function') - pthis.addNodeAttributes(nodes[id], elem); - } - - if (lvl >= 0) id++; - - if (!elem.expanded) return; - - if (elem.childs === undefined) { - // add new request - can we check if only special part of childs is required? - - // TODO: probably one could guess more precise request - pthis.submitRequest(elem, path); - - return; - } - - // check if scan is required - if (((id + elem._shift) < args.begin - threshold2) || (id >= args.end + threshold2)) { - id += elem._shift; - return; - } - - // when not all childs from very beginning is loaded, but may be required - if (elem.first && !pthis.fullModel) { - - // check if requests are needed to load part in the begin of the list - if (args.begin - id - threshold2 < elem.first) { - - var first = Math.max(args.begin - id - threshold2, 0), - number = Math.min(elem.first - first, threshold); - - pthis.submitRequest(elem, path, first, number); - } - - id += elem.first; - } - - - for (var k=0;k<elem.childs.length;++k) - scan(lvl+1, elem.childs[k], path + elem.childs[k].name + "/"); - - // check if more elements are required - - if (!pthis.fullModel) { - var _last = (elem.first || 0) + elem.childs.length; - var _remains = elem.nchilds - _last; - - if (_remains > 0) { - if (args.end + threshold2 > id) { - - var first = _last, number = args.end + threshold2 - id; - if (number < threshold) number = threshold; // always request much - if (number > _remains) number = _remains; // but not too much - if (number > threshold) { - first += (number - threshold); - number = threshold; - } - - console.log('submit request for last', path, first,number) - - pthis.submitRequest(elem, path, first, number); - } - - id += _remains; - } - } - } - - // start scan from very top - scan(-1, this.h, "/"); - - if (this.getProperty("/length") != id) { - // console.error('LENGTH MISMATCH', this.getProperty("/length"), id); - this.setProperty("/length", id); // update length property - } - - if (this.reset_nodes) { - this.setProperty("/nodes", nodes); - delete this.reset_nodes; - } - - return nodes; - }, - - // toggle expand state of specified node - toggleNode: function(index) { - - var node = this.getNodeByIndex(index), - elem = node ? node._elem : null; - - if (!node || !elem) return; - - if (elem.expanded) { - delete elem.expanded; - if (!this.fullModel) - delete elem.childs; // TODO: for the future keep childs but make request if expand once again - - // close folder - reassign shifts - this.reset_nodes = true; - this.scanShifts(); - - return true; - - } else if (elem.nchilds || !elem.index) { - - elem.expanded = true; - // structure is changing but not immediately - - if (this.fullModel) { - this.reset_nodes = true; - this.scanShifts(); - } - - return true; - } - }, - - // change sorting method, for now server supports default, "direct" and "reverse" - changeSortOrder: function(newValue) { - if (newValue === undefined) - newValue = this.getProperty("/sortOrder") || ""; - - if ((newValue !== "") && (newValue !=="direct") && (newValue !== "reverse")) { - console.error('WRONG sorting order ', newValue, 'use default'); - newValue = ""; - } - - // ignore same value - if (newValue === this.sortOrder) - return; - - - this.sortOrder = newValue; - - // now we should request values once again - - this.submitRequest(this.h, "/"); - - } - - }); - - return hRootModel; - -}); -- GitLab