Committed by
Gerrit Code Review
GUI -- Continued porting topology behavior over to the new codebase. WIP.
- added FnService.windowSize() function. - added MastService and mastHeight() function. - implemented SvgUtilService.createDragBehavior(). Change-Id: I5dae35244ab8220e1b95ddfd55b180e6adcb7a00
Showing
8 changed files
with
177 additions
and
19 deletions
... | @@ -20,8 +20,12 @@ | ... | @@ -20,8 +20,12 @@ |
20 | (function () { | 20 | (function () { |
21 | 'use strict'; | 21 | 'use strict'; |
22 | 22 | ||
23 | + // injected services | ||
23 | var $log; | 24 | var $log; |
24 | 25 | ||
26 | + // configuration | ||
27 | + var mastHeight = 36; | ||
28 | + | ||
25 | angular.module('onosMast', ['onosNav']) | 29 | angular.module('onosMast', ['onosNav']) |
26 | .controller('MastCtrl', ['$log', 'NavService', function (_$log_, ns) { | 30 | .controller('MastCtrl', ['$log', 'NavService', function (_$log_, ns) { |
27 | var self = this; | 31 | var self = this; |
... | @@ -37,6 +41,13 @@ | ... | @@ -37,6 +41,13 @@ |
37 | }; | 41 | }; |
38 | 42 | ||
39 | $log.log('MastCtrl has been created'); | 43 | $log.log('MastCtrl has been created'); |
44 | + }]) | ||
45 | + | ||
46 | + // also define a service to allow lookup of mast height. | ||
47 | + .factory('MastService', [function () { | ||
48 | + return { | ||
49 | + mastHeight: function () { return mastHeight; } | ||
50 | + } | ||
40 | }]); | 51 | }]); |
41 | 52 | ||
42 | }()); | 53 | }()); | ... | ... |
... | @@ -34,9 +34,99 @@ | ... | @@ -34,9 +34,99 @@ |
34 | $log = _$log_; | 34 | $log = _$log_; |
35 | fs = _fs_; | 35 | fs = _fs_; |
36 | 36 | ||
37 | - function createDragBehavior() { | 37 | + function createDragBehavior(force, selectCb, atDragEnd, |
38 | - $log.warn('SvgUtilService: createDragBehavior -- To Be Implemented'); | 38 | + dragEnabled, clickEnabled) { |
39 | - } | 39 | + var draggedThreshold = d3.scale.linear() |
40 | + .domain([0, 0.1]) | ||
41 | + .range([5, 20]) | ||
42 | + .clamp(true), | ||
43 | + drag, | ||
44 | + fSel = fs.isF(selectCb), | ||
45 | + fEnd = fs.isF(atDragEnd), | ||
46 | + fDEn = fs.isF(dragEnabled), | ||
47 | + fCEn = fs.isF(clickEnabled), | ||
48 | + bad = []; | ||
49 | + | ||
50 | + function naf(what) { | ||
51 | + return 'SvgUtilService: createDragBehavior(): ' + what + | ||
52 | + ' is not a function'; | ||
53 | + } | ||
54 | + | ||
55 | + if (!fSel) { | ||
56 | + bad.push(naf('selectCb')); | ||
57 | + } | ||
58 | + if (!fEnd) { | ||
59 | + bad.push(naf('atDragEnd')); | ||
60 | + } | ||
61 | + if (!fDEn) { | ||
62 | + bad.push(naf('dragEnabled')); | ||
63 | + } | ||
64 | + if (!fCEn) { | ||
65 | + bad.push(naf('clickEnabled')); | ||
66 | + } | ||
67 | + | ||
68 | + if (bad.length) { | ||
69 | + $log.error(bad.join('\n')); | ||
70 | + return null; | ||
71 | + } | ||
72 | + | ||
73 | + | ||
74 | + function dragged(d) { | ||
75 | + var threshold = draggedThreshold(force.alpha()), | ||
76 | + dx = d.oldX - d.px, | ||
77 | + dy = d.oldY - d.py; | ||
78 | + if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) { | ||
79 | + d.dragged = true; | ||
80 | + } | ||
81 | + return d.dragged; | ||
82 | + } | ||
83 | + | ||
84 | + drag = d3.behavior.drag() | ||
85 | + .origin(function(d) { return d; }) | ||
86 | + .on('dragstart', function(d) { | ||
87 | + if (clickEnabled() || dragEnabled()) { | ||
88 | + d3.event.sourceEvent.stopPropagation(); | ||
89 | + | ||
90 | + d.oldX = d.x; | ||
91 | + d.oldY = d.y; | ||
92 | + d.dragged = false; | ||
93 | + d.fixed |= 2; | ||
94 | + d.dragStarted = true; | ||
95 | + } | ||
96 | + }) | ||
97 | + .on('drag', function(d) { | ||
98 | + if (dragEnabled()) { | ||
99 | + d.px = d3.event.x; | ||
100 | + d.py = d3.event.y; | ||
101 | + if (dragged(d)) { | ||
102 | + if (!force.alpha()) { | ||
103 | + force.alpha(.025); | ||
104 | + } | ||
105 | + } | ||
106 | + } | ||
107 | + }) | ||
108 | + .on('dragend', function(d) { | ||
109 | + if (d.dragStarted) { | ||
110 | + d.dragStarted = false; | ||
111 | + if (!dragged(d)) { | ||
112 | + // consider this the same as a 'click' | ||
113 | + // (selection of a node) | ||
114 | + if (clickEnabled()) { | ||
115 | + selectCb(d, this); | ||
116 | + // TODO: set 'this' context instead of param | ||
117 | + } | ||
118 | + } | ||
119 | + d.fixed &= ~6; | ||
120 | + | ||
121 | + // hook at the end of a drag gesture | ||
122 | + if (dragEnabled()) { | ||
123 | + atDragEnd(d, this); | ||
124 | + // TODO: set 'this' context instead of param | ||
125 | + } | ||
126 | + } | ||
127 | + }); | ||
128 | + | ||
129 | + return drag; } | ||
40 | 130 | ||
41 | function loadGlow() { | 131 | function loadGlow() { |
42 | $log.warn('SvgUtilService: loadGlow -- To Be Implemented'); | 132 | $log.warn('SvgUtilService: loadGlow -- To Be Implemented'); | ... | ... |
... | @@ -20,6 +20,8 @@ | ... | @@ -20,6 +20,8 @@ |
20 | (function () { | 20 | (function () { |
21 | 'use strict'; | 21 | 'use strict'; |
22 | 22 | ||
23 | + var $window; | ||
24 | + | ||
23 | function isF(f) { | 25 | function isF(f) { |
24 | return typeof f === 'function' ? f : null; | 26 | return typeof f === 'function' ? f : null; |
25 | } | 27 | } |
... | @@ -58,15 +60,29 @@ | ... | @@ -58,15 +60,29 @@ |
58 | return true; | 60 | return true; |
59 | } | 61 | } |
60 | 62 | ||
63 | + // Returns width and height of window inner dimensions. | ||
64 | + // offH, offW : offset width/height are subtracted, if present | ||
65 | + function windowSize(offH, offW) { | ||
66 | + var oh = offH || 0, | ||
67 | + ow = offW || 0; | ||
68 | + return { | ||
69 | + height: $window.innerHeight - oh, | ||
70 | + width: $window.innerWidth - ow | ||
71 | + }; | ||
72 | + } | ||
73 | + | ||
61 | angular.module('onosUtil') | 74 | angular.module('onosUtil') |
62 | - .factory('FnService', [function () { | 75 | + .factory('FnService', ['$window', function (_$window_) { |
76 | + $window = _$window_; | ||
77 | + | ||
63 | return { | 78 | return { |
64 | isF: isF, | 79 | isF: isF, |
65 | isA: isA, | 80 | isA: isA, |
66 | isS: isS, | 81 | isS: isS, |
67 | isO: isO, | 82 | isO: isO, |
68 | contains: contains, | 83 | contains: contains, |
69 | - areFunctions: areFunctions | 84 | + areFunctions: areFunctions, |
85 | + windowSize: windowSize | ||
70 | }; | 86 | }; |
71 | }]); | 87 | }]); |
72 | 88 | ... | ... |
... | @@ -28,7 +28,7 @@ | ... | @@ -28,7 +28,7 @@ |
28 | ]; | 28 | ]; |
29 | 29 | ||
30 | // references to injected services etc. | 30 | // references to injected services etc. |
31 | - var $log, ks, zs, gs, ms, ps, tes, tfs; | 31 | + var $log, fs, ks, zs, gs, ms, ps, tes, tfs; |
32 | 32 | ||
33 | // DOM elements | 33 | // DOM elements |
34 | var ovtopo, svg, defs, zoomLayer, mapG, forceG; | 34 | var ovtopo, svg, defs, zoomLayer, mapG, forceG; |
... | @@ -102,7 +102,8 @@ | ... | @@ -102,7 +102,8 @@ |
102 | 102 | ||
103 | // callback invoked when the SVG view has been resized.. | 103 | // callback invoked when the SVG view has been resized.. |
104 | function svgResized(w, h) { | 104 | function svgResized(w, h) { |
105 | - // not used now, but may be required later... | 105 | + $log.debug('TopoView just resized... ' + w + 'x' + h); |
106 | + tfs.resize(w, h); | ||
106 | } | 107 | } |
107 | 108 | ||
108 | // --- Background Map ------------------------------------------------ | 109 | // --- Background Map ------------------------------------------------ |
... | @@ -133,7 +134,7 @@ | ... | @@ -133,7 +134,7 @@ |
133 | 134 | ||
134 | function setUpForce() { | 135 | function setUpForce() { |
135 | forceG = zoomLayer.append('g').attr('id', 'topo-force'); | 136 | forceG = zoomLayer.append('g').attr('id', 'topo-force'); |
136 | - tfs.initForce(forceG); | 137 | + tfs.initForce(forceG, svg.attr('width'), svg.attr('height')); |
137 | } | 138 | } |
138 | 139 | ||
139 | 140 | ||
... | @@ -143,13 +144,15 @@ | ... | @@ -143,13 +144,15 @@ |
143 | 144 | ||
144 | .controller('OvTopoCtrl', [ | 145 | .controller('OvTopoCtrl', [ |
145 | '$scope', '$log', '$location', '$timeout', | 146 | '$scope', '$log', '$location', '$timeout', |
147 | + 'FnService', 'MastService', | ||
146 | 'KeyService', 'ZoomService', 'GlyphService', 'MapService', | 148 | 'KeyService', 'ZoomService', 'GlyphService', 'MapService', |
147 | 'PanelService', 'TopoEventService', 'TopoForceService', | 149 | 'PanelService', 'TopoEventService', 'TopoForceService', |
148 | 150 | ||
149 | - function ($scope, _$log_, $loc, $timeout, | 151 | + function ($scope, _$log_, $loc, $timeout, _fs_, mast, |
150 | _ks_, _zs_, _gs_, _ms_, _ps_, _tes_, _tfs_) { | 152 | _ks_, _zs_, _gs_, _ms_, _ps_, _tes_, _tfs_) { |
151 | var self = this; | 153 | var self = this; |
152 | $log = _$log_; | 154 | $log = _$log_; |
155 | + fs = _fs_; | ||
153 | ks = _ks_; | 156 | ks = _ks_; |
154 | zs = _zs_; | 157 | zs = _zs_; |
155 | gs = _gs_; | 158 | gs = _gs_; |
... | @@ -159,7 +162,7 @@ | ... | @@ -159,7 +162,7 @@ |
159 | tfs = _tfs_; | 162 | tfs = _tfs_; |
160 | 163 | ||
161 | self.notifyResize = function () { | 164 | self.notifyResize = function () { |
162 | - svgResized(svg.style('width'), svg.style('height')); | 165 | + svgResized(svg.attr('width'), svg.attr('height')); |
163 | }; | 166 | }; |
164 | 167 | ||
165 | // Cleanup on destroyed scope.. | 168 | // Cleanup on destroyed scope.. |
... | @@ -172,6 +175,8 @@ | ... | @@ -172,6 +175,8 @@ |
172 | // svg layer and initialization of components | 175 | // svg layer and initialization of components |
173 | ovtopo = d3.select('#ov-topo'); | 176 | ovtopo = d3.select('#ov-topo'); |
174 | svg = ovtopo.select('svg'); | 177 | svg = ovtopo.select('svg'); |
178 | + // set the svg size to match that of the window, less the masthead | ||
179 | + svg.attr(fs.windowSize(mast.mastHeight())); | ||
175 | 180 | ||
176 | // bind to topo event dispatcher.. | 181 | // bind to topo event dispatcher.. |
177 | evDispatcher = tes.bindDispatcher('TODO: topo-DOM-elements-here'); | 182 | evDispatcher = tes.bindDispatcher('TODO: topo-DOM-elements-here'); | ... | ... |
... | @@ -96,8 +96,9 @@ | ... | @@ -96,8 +96,9 @@ |
96 | // forceG is the SVG group to display the force layout in | 96 | // forceG is the SVG group to display the force layout in |
97 | // w, h are the initial dimensions of the SVG | 97 | // w, h are the initial dimensions of the SVG |
98 | // opts are, well, optional :) | 98 | // opts are, well, optional :) |
99 | - function initForce (forceG, w, h, opts) { | 99 | + function initForce(forceG, w, h, opts) { |
100 | - // TODO: create the force layout and initialize | 100 | + $log.debug('initForce().. WxH = ' + w + 'x' + h); |
101 | + | ||
101 | settings = angular.extend({}, defaultSettings, opts); | 102 | settings = angular.extend({}, defaultSettings, opts); |
102 | 103 | ||
103 | linkG = forceG.append('g').attr('id', 'topo-links'); | 104 | linkG = forceG.append('g').attr('id', 'topo-links'); |
... | @@ -109,7 +110,7 @@ | ... | @@ -109,7 +110,7 @@ |
109 | node = nodeG.selectAll('.node'); | 110 | node = nodeG.selectAll('.node'); |
110 | 111 | ||
111 | force = d3.layout.force() | 112 | force = d3.layout.force() |
112 | - .size(w, h) | 113 | + .size([w, h]) |
113 | .nodes(network.nodes) | 114 | .nodes(network.nodes) |
114 | .links(network.links) | 115 | .links(network.links) |
115 | .gravity(settings.gravity) | 116 | .gravity(settings.gravity) |
... | @@ -124,8 +125,9 @@ | ... | @@ -124,8 +125,9 @@ |
124 | } | 125 | } |
125 | 126 | ||
126 | function resize(w, h) { | 127 | function resize(w, h) { |
127 | - force.size(w, h); | 128 | + force.size([w, h]); |
128 | // Review -- do we need to nudge the layout ? | 129 | // Review -- do we need to nudge the layout ? |
130 | + | ||
129 | } | 131 | } |
130 | 132 | ||
131 | return { | 133 | return { | ... | ... |
... | @@ -21,15 +21,20 @@ describe('Controller: MastCtrl', function () { | ... | @@ -21,15 +21,20 @@ describe('Controller: MastCtrl', function () { |
21 | // instantiate the masthead module | 21 | // instantiate the masthead module |
22 | beforeEach(module('onosMast')); | 22 | beforeEach(module('onosMast')); |
23 | 23 | ||
24 | - var $log, ctrl; | 24 | + var $log, ctrl, ms; |
25 | 25 | ||
26 | // we need an instance of the controller | 26 | // we need an instance of the controller |
27 | - beforeEach(inject(function(_$log_, $controller) { | 27 | + beforeEach(inject(function(_$log_, $controller, MastService) { |
28 | $log = _$log_; | 28 | $log = _$log_; |
29 | ctrl = $controller('MastCtrl'); | 29 | ctrl = $controller('MastCtrl'); |
30 | + ms = MastService; | ||
30 | })); | 31 | })); |
31 | 32 | ||
32 | it('should start with no radio buttons', function () { | 33 | it('should start with no radio buttons', function () { |
33 | expect(ctrl.radio).toBeNull(); | 34 | expect(ctrl.radio).toBeNull(); |
34 | }); | 35 | }); |
36 | + | ||
37 | + it('should declare height to be 36', function () { | ||
38 | + expect(ms.mastHeight()).toBe(36); | ||
39 | + }) | ||
35 | }); | 40 | }); | ... | ... |
... | @@ -18,7 +18,8 @@ | ... | @@ -18,7 +18,8 @@ |
18 | ONOS GUI -- Util -- General Purpose Functions - Unit Tests | 18 | ONOS GUI -- Util -- General Purpose Functions - Unit Tests |
19 | */ | 19 | */ |
20 | describe('factory: fw/util/fn.js', function() { | 20 | describe('factory: fw/util/fn.js', function() { |
21 | - var fs, | 21 | + var $window, |
22 | + fs, | ||
22 | someFunction = function () {}, | 23 | someFunction = function () {}, |
23 | someArray = [1, 2, 3], | 24 | someArray = [1, 2, 3], |
24 | someObject = { foo: 'bar'}, | 25 | someObject = { foo: 'bar'}, |
... | @@ -29,8 +30,12 @@ describe('factory: fw/util/fn.js', function() { | ... | @@ -29,8 +30,12 @@ describe('factory: fw/util/fn.js', function() { |
29 | 30 | ||
30 | beforeEach(module('onosUtil')); | 31 | beforeEach(module('onosUtil')); |
31 | 32 | ||
32 | - beforeEach(inject(function (FnService) { | 33 | + beforeEach(inject(function (_$window_, FnService) { |
34 | + $window = _$window_; | ||
33 | fs = FnService; | 35 | fs = FnService; |
36 | + | ||
37 | + $window.innerWidth = 400; | ||
38 | + $window.innerHeight = 200; | ||
34 | })); | 39 | })); |
35 | 40 | ||
36 | 41 | ||
... | @@ -186,4 +191,28 @@ describe('factory: fw/util/fn.js', function() { | ... | @@ -186,4 +191,28 @@ describe('factory: fw/util/fn.js', function() { |
186 | }); | 191 | }); |
187 | 192 | ||
188 | 193 | ||
194 | + // === Tests for windowSize() | ||
195 | + it('windowSize(): noargs', function () { | ||
196 | + var dim = fs.windowSize(); | ||
197 | + expect(dim.width).toEqual(400); | ||
198 | + expect(dim.height).toEqual(200); | ||
199 | + }); | ||
200 | + | ||
201 | + it('windowSize(): adjust height', function () { | ||
202 | + var dim = fs.windowSize(50); | ||
203 | + expect(dim.width).toEqual(400); | ||
204 | + expect(dim.height).toEqual(150); | ||
205 | + }); | ||
206 | + | ||
207 | + it('windowSize(): adjust width', function () { | ||
208 | + var dim = fs.windowSize(0, 50); | ||
209 | + expect(dim.width).toEqual(350); | ||
210 | + expect(dim.height).toEqual(200); | ||
211 | + }); | ||
212 | + | ||
213 | + it('windowSize(): adjust width and height', function () { | ||
214 | + var dim = fs.windowSize(101, 201); | ||
215 | + expect(dim.width).toEqual(199); | ||
216 | + expect(dim.height).toEqual(99); | ||
217 | + }); | ||
189 | }); | 218 | }); | ... | ... |
... | @@ -34,7 +34,7 @@ describe('factory: view/topo/topoForce.js', function() { | ... | @@ -34,7 +34,7 @@ describe('factory: view/topo/topoForce.js', function() { |
34 | 34 | ||
35 | it('should define api functions', function () { | 35 | it('should define api functions', function () { |
36 | expect(fs.areFunctions(tfs, [ | 36 | expect(fs.areFunctions(tfs, [ |
37 | - 'initForce' | 37 | + 'initForce', 'resize' |
38 | ])).toBeTruthy(); | 38 | ])).toBeTruthy(); |
39 | }); | 39 | }); |
40 | 40 | ... | ... |
-
Please register or login to post a comment