Download - Autopsy Of A Widget

Transcript
  • 1. Autopsy ofa WidgetThe Internals of aqooxdoo Widget by Fabian Jakobs@fjakobs

2. Web Application 3. Browser as Render Engine 4. Primitives Image Text Rectangle 5. Tree of Primitives DOM tree Events CSS for styling JavaScript for behavior 6. The Body Widget 7. The WidgetSpinner Number input Composed widgetnew qx.ui.form.Spinner(20); 8. Static Structure: Composed Widgets 9. GoalCreate complex Widgets by composing WidgetsUse known GUI Concepts Abstraction over the Browser 10. GoalCreate complex Widgets by composing WidgetsUse known GUI Concepts Abstraction over the Browser 11. qx.Class.define("qx.ui.form.Spinner", { extend : qx.ui.core.Widget,construct : function(value) { this.base(arguments); } }); 12. qx.Class.define("qx.ui.form.Spinner", { extend : qx.ui.core.Widget,construct : function(value) { this.base(arguments);var layout = new qx.ui.layout.Grid(); layout.setRowFlex(0, 1); layout.setRowFlex(1, 1); layout.setColumnFlex(1, 1); this._setLayout(layout); } }); 13. qx.Class.define("qx.ui.form.Spinner", { extend : qx.ui.core.Widget,construct : function(value) { this.base(arguments);var layout = new qx.ui.layout.Grid(); layout.setRowFlex(0, 1); layout.setRowFlex(1, 1); layout.setColumnFlex(1, 1); this._setLayout(layout);this._input = new qx.ui.form.TextField(value.toString()); this._add(this._input, {row: 0, column: 0, rowSpan: 2});this._buttonUp = new qx.ui.form.Button(); this._buttonUp.setIcon("decoration/arrows/up-small.png"); this._add(this._buttonUp, {row: 0, column: 1});this._buttonDown = new qx.ui.form.Button(); this._buttonDown.setIcon("decoration/arrows/down-small.png"); this._add(this._buttonDown, {row: 1, column: 1}); } }); 14. Demo http://demo.qooxdoo.org/current/playground 15. DOM Structure 16. DOM Structure new qx.ui.form.TextField("Anatomy"); 17. DOM Structurenew qx.ui.form.TextField("Anatomy");

...

18. Container

...

19. Container Decorator

...

20. Container DecoratorContent

...

21. Summary 2-3 DOM elements Absolute positioning Fixed sizes No explicit padding

...

22. DOM StructureProCon Box Model Independence 2-3 DOM Elements Flexible StylingSize Computation in JS No Cross Browser Issues 23. Theming 24. The Guts: Working With The DOM 25. new qx.ui.form.TextField("Anatomy"); ???

...

26. The DOM is a Mess Many cross browser issues IEelement.style.filter ="alpha(opacity=" + (opacity * 100) + ");"; otherselement.style.opacity = opacity; 27. The DOM is a Mess Many cross browser issuesvar el = document.createElement("div"); document.body.appendChild(el);Small mistakes can degrade el.style.position = absolute; // more style changes performance 28. The DOM is a Mess Many cross browser issuesvar el = document.createElement("div"); document.body.appendChild(el);Small mistakes can degrade el.style.position = absolute; // more style changes performancevar el = document.createElement("div"); el.style.position = absolute; // more style changes document.body.appendChild(el); 29. The DOM is a Mess Many cross browser issues Small mistakes can degrade performance var width = parseInt(el.style.width); var height = parseInt(el.style.height);Reading styles/attributes is slow 30. The DOM is a Mess Many cross browser issues Small mistakes can degrade performance var width = parseInt(el.style.width); var height = parseInt(el.style.height);Reading styles/attributes is slow 31. DOM WrapperWrap DOM elements Lazy DOM element creation Batch DOM manipulations Cache styles/attributes 32. qx.Class.define("qx.ui.core.Widget", Container { extend : qx.core.Object,construct : function() { this.base(arguments); this._container = new qx.html.Element("div");this._content = new qx.html.Element("div").setStyles({ position: "absolute", zIndex: 10, overflow: "hidden" }); this._container.add(this._content);this._decorator = new qx.html.Element("div").setStyles({ position: "absolute", zIndex: 10 });this._container.add(this._decorator); } }); 33. qx.Class.define("qx.ui.core.Widget", Container { extend : qx.core.Object, Decorator construct : function() { this.base(arguments); this._container = new qx.html.Element("div");this._content = new qx.html.Element("div").setStyles({ position: "absolute", zIndex: 10, overflow: "hidden" }); this._container.add(this._content);this._decorator = new qx.html.Element("div").setStyles({ position: "absolute", zIndex: 10 });this._container.add(this._decorator); } }); 34. qx.Class.define("qx.ui.core.Widget", Container { extend : qx.core.Object, Decorator construct : function() Content { this.base(arguments); this._container = new qx.html.Element("div");this._content = new qx.html.Element("div").setStyles({ position: "absolute", zIndex: 10, overflow: "hidden" }); this._container.add(this._content);this._decorator = new qx.html.Element("div").setStyles({ position: "absolute", zIndex: 10 });this._container.add(this._decorator); } }); 35. DOM WrapperProCon Cross browser APIMemory overheadPerformanceAdditional complexity Keeps widget code clean 36. Dynamic Structure:Layouts 37. Initial Sizes 38. Initial Sizes 39. Initial Sizes 40. Dynamic Update 41. Layout Compute widgets sizes based onAvailable space Layout constraints Preferred widget sizes Widget size constraints 42. Algorithm 2 Passes 43. Algorithm2 Passes 1st Pass Compute Preferred Size 44. Algorithm2 Passes 1st Pass2nd Pass Compute Preferred SizeRender Size 45. 1st Pass Spinner Grid getSizeHint() getSizeHint() getLayout()getLayoutChildren()computeLayout(hints) TextField Button ButtongetSizeHint() getSizeHint()getSizeHint() measureTextHeight() getImageSize() getImageSize() 46. 1st Pass Spinner.getSizeHint = function() { Spinner Grid return this.getLayout().getSizeHint(); } getSizeHint()getSizeHint() getLayout() getLayoutChildren() computeLayout(hints) TextField Button ButtongetSizeHint() getSizeHint()getSizeHint() measureTextHeight() getImageSize() getImageSize() 47. 1st PassGrid.getSizeHint = function(){ Spinner Gridvar childrenHints = [];var children =getSizeHint() this.getLayoutChildren();getSizeHint()for (var i=0; i


Top Related