ViewSystem.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. import React from 'react';
  2. import {TreeNode, Tree} from '../helpers/tree'
  3. import Row from '../../modules/Row';
  4. import Col from '../../modules/Col';
  5. import BaseHolder from '../../modules/BaseHolder';
  6. import {View as Div, StyleSheet} from 'react-native';
  7. function log(...m) {
  8. console.log(...m);
  9. }
  10. export class ViewNode extends TreeNode {
  11. constructor(id,value, props, namespace = "default"){
  12. super(id);
  13. this.value = value; // constructor Component
  14. this.namespace = namespace;
  15. this.props = props || {};
  16. }
  17. }
  18. export class Node extends TreeNode {
  19. constructor(id, props, content) {
  20. super(id);
  21. this.ctor = BaseHolder;
  22. this.props = props || {};
  23. if(content){
  24. this.content = content; // this is a viewNode
  25. }
  26. }
  27. }
  28. export default class ViewSystem {
  29. constructor(CS) {
  30. this.views = {};
  31. this.CoreSystem = CS;
  32. this.ModuleSystem = CS.ModuleSystem;
  33. this.EventSystem = CS.EventSystem;
  34. this.ghosts = {};
  35. }
  36. getNode(ViewId, NodeId) {
  37. return this.views[ViewId].getNode(NodeId);
  38. }
  39. getView(name) {
  40. return this.views[name];
  41. }
  42. addView(name, view) {
  43. this.views[name] = view;
  44. return view;
  45. }
  46. removeView(name) {
  47. let view = this.views[name];
  48. delete this.views[name];
  49. return view;
  50. }
  51. render(name) {
  52. return this.views[name].render(this.CoreSystem);
  53. }
  54. renderModule(mod, id) {
  55. let selfView = this.CoreSystem.getCurrentView();
  56. let nodeId = "___"+id+"Node";
  57. let {
  58. value,
  59. props,
  60. namespace
  61. } = mod;
  62. if(!selfView.ghosts[nodeId]) {
  63. let viewNode = new ViewNode(id, value, props, namespace);
  64. let node = new Node(nodeId, {}, viewNode);
  65. selfView.ghosts[nodeId] = node;
  66. }
  67. let vn = selfView.ghosts[nodeId].content;
  68. vn.value = value;
  69. vn.namespace = namespace;
  70. let ViewNodeReact = renderContent(selfView.ghosts[nodeId], this.CoreSystem, selfView);
  71. return renderNode(selfView.ghosts[nodeId], this.CoreSystem, ViewNodeReact);
  72. }
  73. export() {
  74. let views = {};
  75. for(var i in this.views) {
  76. views[i] = this.views[i].export();
  77. }
  78. return {
  79. views
  80. }
  81. }
  82. import(data) {
  83. let { views } = data;
  84. for(var i in views) {
  85. this.views[i] = new View().import(views[i]);
  86. }
  87. return this;
  88. }
  89. ray(viewId, x, y, id) {
  90. let tree = this.views[viewId].ViewTree;
  91. }
  92. }
  93. export class View {
  94. constructor(){
  95. this.ViewTree = new Tree();
  96. let rootNode = new Node(Math.random(), {stretchContainer: false, selected: true}); // row
  97. this.addViewNode(rootNode);
  98. this.defaultContainer = rootNode;
  99. this.ghosts = {};
  100. }
  101. getDefaultContainer() {
  102. return this.defaultContainer;
  103. }
  104. getRoot() {
  105. return this.ViewTree.root;
  106. }
  107. getNode(id) {
  108. return this.ghosts[id] || this.ViewTree.getNode(id);
  109. }
  110. has(node) {
  111. if (typeof node !== "object") return this.getNode(node);
  112. return this.getNode(node.id);
  113. }
  114. render(CS) {
  115. let node = this.ViewTree.root;
  116. return (<Renderer CoreSystem={CS} node={node} tree={this.ViewTree} selfView={this}/>);
  117. }
  118. addViewNode(node,parentNode = null){
  119. this.ViewTree.insert(node,parentNode);
  120. return this;
  121. }
  122. setContent(content, container) {
  123. container.content = content;
  124. return this;
  125. }
  126. getParent(node) {
  127. if(!this.has(node)) return false;
  128. return this.getNode(this.ViewTree.getParent(node));
  129. }
  130. getRows(column) {
  131. log("Deprecated for now")
  132. return true;
  133. if(!column.isCol) {
  134. throw new Error("You must pass a ColNode to this function");
  135. }
  136. return this.getChildren(column);
  137. }
  138. setRows(column, rows = 1) {
  139. log("Deprecated for now")
  140. return true;
  141. if(!column.isCol) throw new Error("You must pass a ColNode to this function");
  142. if(rows < 1) throw new Error("Only positive rows");
  143. let colChildren = this.getChildren(column);
  144. if (colChildren.length > rows) {
  145. for(var i = rows; i < colChildren.length; i++) {
  146. let row = colChildren[i];
  147. if(row.content) {
  148. if(confirm("Are you sure you want to remove this row it has content?"))
  149. this.remove(row);
  150. } else {
  151. this.remove(row); }
  152. }
  153. } else {
  154. for(var i = colChildren.length; i < rows; i++)
  155. this.addViewNode(new Node(Math.random(), true), column); // row
  156. }
  157. return this.getRows(column);
  158. }
  159. getColumns(row) {
  160. log("Deprecated for now")
  161. return true;
  162. if(!row.isRow) {
  163. throw new Error("You must pass a RowNode to this function");
  164. }
  165. return this.getChildren(row);
  166. }
  167. setColumns(row, columns = 1) {
  168. log("Deprecated for now")
  169. return true;
  170. if(!row.isRow) throw new Error("You must pass a RowNode to this function");
  171. if(columns < 1) throw new Error("Only positive cols");
  172. let rowChildren = this.getChildren(row);
  173. if (rowChildren.length > columns) {
  174. for(var i = columns; i < rowChildren.length; i++) {
  175. let col = rowChildren[i];
  176. if(col.content) {
  177. if(confirm("Are you sure you want to remove this col it has content?"))
  178. this.remove(col);
  179. } else {
  180. this.remove(col);
  181. }
  182. }
  183. } else {
  184. for(var i = rowChildren.length; i < columns; i++) {
  185. this.addViewNode(new Node(Math.random()), row);
  186. }
  187. }
  188. return this.getColumns(row);
  189. }
  190. addGrid(column, rowSize, columnSize) {
  191. log("Deprecated for now")
  192. return true;
  193. this.setRows(column, rowSize)
  194. .forEach(row => this.setColumns(row, columnSize)
  195. .forEach(col => col.content = new ViewNode(
  196. Math.random(),
  197. "BaseContainer",
  198. {}
  199. )));
  200. }
  201. remove(node) {
  202. if(node === root) {
  203. console.log("Cannot remove Root node", node);
  204. return this;
  205. }
  206. this.ViewTree.remove(node);
  207. return this;
  208. }
  209. replace(oldNode,newNode){
  210. this.ViewTree.replaceNode(oldNode,newNode);
  211. return this;
  212. }
  213. getChildren(node) {
  214. return this.ViewTree.getChildren(node);
  215. }
  216. import(data, parentNode) {
  217. let { tree, ghosts } = data;
  218. if(!parentNode)
  219. this.ViewTree = new Tree();
  220. try {
  221. this.ViewTree.import(tree, Node, parentNode);
  222. this.defaultContainer = this.ViewTree.root;
  223. for(var i in ghosts) {
  224. this.ghosts[i] = new Node().import(ghosts[i]);
  225. }
  226. } catch(e) {
  227. log(e);
  228. throw new Error("ViewSystem import error : ", e);
  229. }
  230. return this;
  231. }
  232. export(node) {
  233. let tree = this.ViewTree.export(node);
  234. let ghostsExported = {};
  235. for(var i in this.ghosts) {
  236. ghostsExported[i] = this.ghosts[i].export();
  237. }
  238. return {
  239. tree,
  240. ghosts: ghostsExported
  241. };
  242. }
  243. }
  244. /// Node = Container -> Everywhere Containers
  245. // Content is Node.content Container property.
  246. // When Content is present, Container for Containers is stretchedToContent
  247. // IF NOT -> just be placed there.
  248. //
  249. let Renderer = (props) => {
  250. let { node , tree, CoreSystem, selfView } = props;
  251. let childrens = tree.getChildren(node);
  252. let childrenReact = childrens.map(child => {
  253. return(
  254. <Renderer node = {child}
  255. tree={tree}
  256. key={child.id}
  257. CoreSystem={CoreSystem}
  258. selfView={selfView} />)
  259. });
  260. let ModuleSystem = CoreSystem.ModuleSystem;
  261. let EventSystem = CoreSystem.EventSystem;
  262. let viewNode = node.content;
  263. let ViewNodeReact;
  264. // IF CONTENT
  265. if(viewNode) {
  266. ViewNodeReact = renderContent(node, CoreSystem, selfView);
  267. }
  268. return renderNode(node, CoreSystem, ViewNodeReact, childrenReact);
  269. }
  270. let renderNode = (node, CoreSystem, ViewNodeReact, childrenReact) => {
  271. CoreSystem.ModuleSystem.createRef(node.id);
  272. return CoreSystem.ModuleSystem.createElementCtor(
  273. node.ctor,
  274. {
  275. ...node.props,
  276. depth: node.depth,
  277. content: ViewNodeReact,
  278. ID: node.id,
  279. CoreSystem: CoreSystem
  280. },
  281. childrenReact,
  282. node.id
  283. );
  284. }
  285. let renderContent = (node, CoreSystem, selfView) => {
  286. let viewNode = node.content;
  287. // Create ref
  288. CoreSystem.ModuleSystem.createRef(viewNode.id);
  289. // Crete element
  290. return CoreSystem.ModuleSystem.createElement(
  291. viewNode.value,
  292. {
  293. ...viewNode.props,
  294. ModuleID: viewNode.id,
  295. NodeID: node.id,
  296. EventSystem: CoreSystem.EventSystem,
  297. CoreSystem: CoreSystem,
  298. View: selfView
  299. },
  300. null, // children
  301. viewNode.namespace,
  302. viewNode.id
  303. );
  304. }
  305. const styles = StyleSheet.create({
  306. colWrapper: {
  307. "position": "absolute",
  308. "left": 0,
  309. "bottom": 0,
  310. "right": 0,
  311. "top": 0
  312. }
  313. })