Simon Hunt
Committed by Gerrit Code Review

GUI -- Refactored Button Service.

Change-Id: I194af8f44aae4d6905bbe564d3aaae6599d20e92
...@@ -27,7 +27,15 @@ ...@@ -27,7 +27,15 @@
27 var btnSize = 25, 27 var btnSize = 25,
28 btnPadding = 4; 28 btnPadding = 4;
29 29
30 - function noop() {} 30 +
31 + // === Helper Functions
32 +
33 + function divExists(div, msg) {
34 + if (!div) {
35 + $log.warn('div undefined (' + msg + ')');
36 + }
37 + return !!div;
38 + }
31 39
32 function createDiv(div, cls, id) { 40 function createDiv(div, cls, id) {
33 return div.append('div') 41 return div.append('div')
...@@ -35,11 +43,22 @@ ...@@ -35,11 +43,22 @@
35 .attr('id', id); 43 .attr('id', id);
36 } 44 }
37 45
46 + function noop() {}
47 +
48 + function buttonWidth() {
49 + return btnSize + 2 * btnPadding;
50 + }
51 +
52 +
53 + // === BUTTON =================================================
54 +
55 + // div is where to put the button (d3.selection of a DIV element)
56 + // id should be globally unique
57 + // gid is glyph ID (from Glyph Service)
58 + // cb is callback function on click
59 + // tooltip is text for tooltip
38 function button(div, id, gid, cb, tooltip) { 60 function button(div, id, gid, cb, tooltip) {
39 - if (!div) { 61 + if (!divExists(div, 'button')) return null;
40 - $log.warn('Button cannot append to div');
41 - return null;
42 - }
43 62
44 var btnDiv = createDiv(div, 'button', id), 63 var btnDiv = createDiv(div, 'button', id),
45 cbFnc = fs.isF(cb) || noop; 64 cbFnc = fs.isF(cb) || noop;
...@@ -50,16 +69,21 @@ ...@@ -50,16 +69,21 @@
50 69
51 return { 70 return {
52 id: id, 71 id: id,
53 - click: cbFnc, 72 + width: buttonWidth
54 - el: btnDiv
55 } 73 }
56 } 74 }
57 75
76 +
77 + // === TOGGLE BUTTON ==========================================
78 +
79 + // div is where to put the button (d3.selection of a DIV element)
80 + // id should be globally unique
81 + // gid is glyph ID (from Glyph Service)
82 + // initState is whether the toggle is on or not to begin
83 + // cb is callback function on click
84 + // tooltip is text for tooltip
58 function toggle(div, id, gid, initState, cb, tooltip) { 85 function toggle(div, id, gid, initState, cb, tooltip) {
59 - if (!div) { 86 + if (!divExists(div, 'toggle button')) return null;
60 - $log.warn('Toggle cannot append to div');
61 - return null;
62 - }
63 87
64 var sel = !!initState, 88 var sel = !!initState,
65 togDiv = createDiv(div, 'toggleButton', id), 89 togDiv = createDiv(div, 'toggleButton', id),
...@@ -69,116 +93,144 @@ ...@@ -69,116 +93,144 @@
69 togDiv.classed('selected', sel); 93 togDiv.classed('selected', sel);
70 94
71 function _toggle(b) { 95 function _toggle(b) {
72 - if (b === undefined) { 96 + sel = (b === undefined) ? !sel : !!b;
73 - sel = !sel;
74 - } else {
75 - sel = !!b;
76 - }
77 - cbFnc(sel);
78 togDiv.classed('selected', sel); 97 togDiv.classed('selected', sel);
98 + cbFnc(sel);
79 } 99 }
80 100
81 togDiv.on('click', _toggle); 101 togDiv.on('click', _toggle);
82 102
83 return { 103 return {
84 id: id, 104 id: id,
85 - el: togDiv, 105 + width: buttonWidth,
86 selected: function () { return sel; }, 106 selected: function () { return sel; },
87 toggle: _toggle 107 toggle: _toggle
88 } 108 }
89 } 109 }
90 110
111 +
112 + // === RADIO BUTTON SET =======================================
113 +
114 +
115 + // div is where to put the button (d3.selection of a DIV element)
116 + // id should be globally unique
117 + // rset is an array of button descriptors of the following form:
118 + // {
119 + // gid: glyphId,
120 + // tooltip: tooltipText,
121 + // cb: callbackFunction
122 + // }
91 function radioSet(div, id, rset) { 123 function radioSet(div, id, rset) {
92 - if (!div) { 124 + if (!divExists(div, 'radio button set')) return null;
93 - $log.warn('Radio buttons cannot append to div'); 125 +
94 - return null; 126 + if (!fs.isA(rset) || !rset.length) {
95 - } 127 + $log.warn('invalid array (radio button set)');
96 - if (!fs.isA(rset)) {
97 - $log.warn('Radio button set is not an array');
98 - return null;
99 - }
100 - if (rset.length === 0) {
101 - $log.warn('Cannot create radio button set from empty array');
102 return null; 128 return null;
103 } 129 }
104 - var rDiv = div.append('div').classed('radioSet', true), 130 +
131 + var rDiv = createDiv(div, 'radioSet', id),
105 rads = [], 132 rads = [],
106 - sel; 133 + idxByKey = {},
107 - 134 + currIdx = 0;
108 - function _selected(s) { 135 +
109 - var curr = d3.select(this), 136 + function rsetWidth() {
110 - currId = curr.attr('id'), 137 + return ((btnSize + btnPadding) * rads.length) + btnPadding;
111 - selIndex = _getIndex(),
112 - currIndex = _getIndex(currId);
113 -
114 - // I have it going by id's because I couldn't think of a way
115 - // to get the radio button's index from the div element
116 - // We could look at the end of the radio button id for its number
117 - // but I didn't know how to get the end of the string's number
118 - if (!s) {
119 - if (sel !== currId) {
120 - rads[selIndex].el.classed('selected', false);
121 - curr.classed('selected', true);
122 - rads[currIndex].cb();
123 - sel = currId;
124 - }
125 - } else {
126 - if (!rads[s].el.classed('selected')) {
127 - rads[selIndex].el.classed('selected', false);
128 - rads[s].el.classed('selected', true);
129 - rads[s].cb();
130 - sel = rads[s].id;
131 - }
132 - }
133 } 138 }
134 139
135 - // given the id, will get the index of element 140 + function rbclick() {
136 - // without the id, will get the index of sel 141 + var id = d3.select(this).attr('id'),
137 - function _getIndex(id) { 142 + m = /^.*-(\d+)$/.exec(id),
138 - if (!id) { 143 + idx = Number(m[1]);
139 - for (var i = 0; i < rads.length; i++) { 144 +
140 - if (rads[i].id === sel) { return i; } 145 + if (idx !== currIdx) {
141 - } 146 + rads[currIdx].el.classed('selected', false);
142 - } else { 147 + currIdx = idx;
143 - for (var j = 0; j < rads.length; j++) { 148 + rads[currIdx].el.classed('selected', true);
144 - if (rads[j].id === id) { return j; } 149 + invokeCurrent();
145 - }
146 } 150 }
147 } 151 }
148 152
153 + // {
154 + // gid: gid,
155 + // tooltip: ..., (optional)
156 + // key: ..., (optional)
157 + // cb: cb
158 + // id: ... (added by us)
159 + // index: ... (added by us)
160 + // }
161 +
149 rset.forEach(function (btn, index) { 162 rset.forEach(function (btn, index) {
150 - var rid = {id: id + '-' + index},
151 - rbtn = angular.extend({}, btn, rid),
152 - istate = (index === 0),
153 - rBtnDiv = createDiv(rDiv, 'radioButton', rbtn.id);
154 163
155 - if (istate) { rBtnDiv.classed('selected', true); } 164 + if (!fs.isO(btn)) {
156 - is.loadIcon(rBtnDiv, rbtn.gid, btnSize, true); 165 + $log.warn('radio button descriptor at index ' + index +
157 - rbtn.el = rBtnDiv; 166 + ' not an object');
158 - rbtn.cb = fs.isF(rbtn.cb) || noop; 167 + return;
168 + }
159 169
160 - rBtnDiv.on('click', _selected); 170 + var rid = id + '-' + index,
171 + initSel = (index === 0),
172 + rbdiv = createDiv(rDiv, 'radioButton', rid);
173 +
174 + rbdiv.classed('selected', initSel);
175 + rbdiv.on('click', rbclick);
176 + is.loadIcon(rbdiv, btn.gid, btnSize, true);
177 + angular.extend(btn, {
178 + el: rbdiv,
179 + id: rid,
180 + cb: fs.isF(btn.cb) || noop,
181 + index: index
182 + });
183 +
184 + if (btn.key) {
185 + idxByKey[btn.key] = index;
186 + }
161 187
162 - rads.push(rbtn); 188 + rads.push(btn);
163 }); 189 });
164 - sel = rads[0].id;
165 - rads[0].cb();
166 190
167 - return { 191 +
168 - rads: rads, 192 + function invokeCurrent() {
169 - width: (((btnSize + btnPadding) * rads.length) + btnPadding), 193 + var curr = rads[currIdx];
170 - selected: function (i) { 194 + curr.cb(curr.index, curr.key);
171 - if (i === undefined) { _getIndex(); } 195 + }
172 - else { _selected(i); } 196 +
197 + function selected(x) {
198 + var curr = rads[currIdx],
199 + idx;
200 +
201 + if (x === undefined) {
202 + return curr.key || curr.index;
203 + } else {
204 + idx = idxByKey[x];
205 + if (idx === undefined) {
206 + $log.warn('no radio button with key "' + x + '"');
207 + } else {
208 + selectedIndex(idx);
209 + }
173 } 210 }
174 } 211 }
175 - }
176 212
177 - function width(s) { 213 + function selectedIndex(x) {
178 - if (s) { btnSize = s; } 214 + if (x === undefined) {
179 - return btnSize; 215 + return currIdx;
216 + } else {
217 + if (x >= 0 && x < rads.length) {
218 + currIdx = x;
219 + invokeCurrent();
220 + } else {
221 + $log.warn('invalid radio button index', x);
222 + }
223 + }
224 + }
225 +
226 + return {
227 + width: rsetWidth,
228 + selected: selected,
229 + selectedIndex: selectedIndex
230 + }
180 } 231 }
181 232
233 +
182 angular.module('onosWidget') 234 angular.module('onosWidget')
183 .factory('ButtonService', 235 .factory('ButtonService',
184 ['$log', 'FnService', 'IconService', 236 ['$log', 'FnService', 'IconService',
...@@ -191,8 +243,7 @@ ...@@ -191,8 +243,7 @@
191 return { 243 return {
192 button: button, 244 button: button,
193 toggle: toggle, 245 toggle: toggle,
194 - radioSet: radioSet, 246 + radioSet: radioSet
195 - width: width
196 }; 247 };
197 }]); 248 }]);
198 249
......
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
88 if (!validId(btnId, 'addButton')) { return null; } 88 if (!validId(btnId, 'addButton')) { return null; }
89 ids.push(btnId); 89 ids.push(btnId);
90 button = bns.button(tbarDiv, btnId, gid, cb, tooltip); 90 button = bns.button(tbarDiv, btnId, gid, cb, tooltip);
91 - if (button) { addToWidth(bns.width()); } 91 + if (button) { addToWidth(button.width()); }
92 displayTools(); 92 displayTools();
93 return button; 93 return button;
94 } 94 }
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
99 if (!validId(togId, 'addToggle')) { return null; } 99 if (!validId(togId, 'addToggle')) { return null; }
100 ids.push(togId); 100 ids.push(togId);
101 toggle = bns.toggle(tbarDiv, togId, gid, initState, cb, tooltip); 101 toggle = bns.toggle(tbarDiv, togId, gid, initState, cb, tooltip);
102 - if (toggle) { addToWidth(bns.width()); } 102 + if (toggle) { addToWidth(toggle.width()); }
103 displayTools(); 103 displayTools();
104 return toggle; 104 return toggle;
105 } 105 }
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
110 if (!validId(radId, 'addRadioSet')) { return null; } 110 if (!validId(radId, 'addRadioSet')) { return null; }
111 ids.push(radId); 111 ids.push(radId);
112 radios = bns.radioSet(tbarDiv, radId, rset); 112 radios = bns.radioSet(tbarDiv, radId, rset);
113 - if (radios) { addToWidth(radios.width); } 113 + if (radios) { addToWidth(radios.width()); }
114 displayTools(); 114 displayTools();
115 return radios; 115 return radios;
116 } 116 }
......