Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 Open Networking Laboratory |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | /* |
| 18 | ONOS GUI -- Widget -- Button Service |
| 19 | */ |
| 20 | (function () { |
| 21 | 'use strict'; |
| 22 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 23 | // injected refs |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 24 | var $log, fs, is; |
| 25 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 26 | // configuration |
Bri Prebilic Cole | 258f046 | 2015-02-25 14:48:50 -0800 | [diff] [blame] | 27 | var btnSize = 25, |
| 28 | btnPadding = 4; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 29 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 30 | |
| 31 | // === Helper Functions |
| 32 | |
| 33 | function divExists(div, msg) { |
| 34 | if (!div) { |
| 35 | $log.warn('div undefined (' + msg + ')'); |
| 36 | } |
| 37 | return !!div; |
| 38 | } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 39 | |
| 40 | function createDiv(div, cls, id) { |
| 41 | return div.append('div') |
| 42 | .classed(cls, true) |
| 43 | .attr('id', id); |
| 44 | } |
| 45 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 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 |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 60 | function button(div, id, gid, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 61 | if (!divExists(div, 'button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 62 | |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 63 | var btnDiv = createDiv(div, 'button', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 64 | cbFnc = fs.isF(cb) || noop; |
| 65 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 66 | is.loadIcon(btnDiv, gid, btnSize, true); |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 67 | |
| 68 | btnDiv.on('click', cbFnc); |
| 69 | |
| 70 | return { |
| 71 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 72 | width: buttonWidth |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 73 | } |
| 74 | } |
| 75 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 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 |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 85 | function toggle(div, id, gid, initState, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 86 | if (!divExists(div, 'toggle button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 87 | |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 88 | var sel = !!initState, |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 89 | togDiv = createDiv(div, 'toggleButton', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 90 | cbFnc = fs.isF(cb) || noop; |
| 91 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 92 | is.loadIcon(togDiv, gid, btnSize, true); |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 93 | togDiv.classed('selected', sel); |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 94 | |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 95 | function _toggle(b, nocb) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 96 | sel = (b === undefined) ? !sel : !!b; |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 97 | togDiv.classed('selected', sel); |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 98 | nocb || cbFnc(sel); |
| 99 | } |
| 100 | |
| 101 | // toggle the button state without invoking the callback |
| 102 | function toggleNoCb() { |
| 103 | _toggle(undefined, true); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | togDiv.on('click', _toggle); |
| 107 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 108 | return { |
| 109 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 110 | width: buttonWidth, |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 111 | selected: function () { return sel; }, |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 112 | toggle: _toggle, |
| 113 | toggleNoCb: toggleNoCb |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 114 | } |
| 115 | } |
| 116 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 117 | |
| 118 | // === RADIO BUTTON SET ======================================= |
| 119 | |
| 120 | |
| 121 | // div is where to put the button (d3.selection of a DIV element) |
| 122 | // id should be globally unique |
| 123 | // rset is an array of button descriptors of the following form: |
| 124 | // { |
| 125 | // gid: glyphId, |
| 126 | // tooltip: tooltipText, |
| 127 | // cb: callbackFunction |
| 128 | // } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 129 | function radioSet(div, id, rset) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 130 | if (!divExists(div, 'radio button set')) return null; |
| 131 | |
| 132 | if (!fs.isA(rset) || !rset.length) { |
| 133 | $log.warn('invalid array (radio button set)'); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 134 | return null; |
| 135 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 136 | |
| 137 | var rDiv = createDiv(div, 'radioSet', id), |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 138 | rads = [], |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 139 | idxByKey = {}, |
| 140 | currIdx = 0; |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 141 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 142 | function rsetWidth() { |
| 143 | return ((btnSize + btnPadding) * rads.length) + btnPadding; |
| 144 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 145 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 146 | function rbclick() { |
| 147 | var id = d3.select(this).attr('id'), |
| 148 | m = /^.*-(\d+)$/.exec(id), |
| 149 | idx = Number(m[1]); |
| 150 | |
| 151 | if (idx !== currIdx) { |
| 152 | rads[currIdx].el.classed('selected', false); |
| 153 | currIdx = idx; |
| 154 | rads[currIdx].el.classed('selected', true); |
| 155 | invokeCurrent(); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 156 | } |
| 157 | } |
| 158 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 159 | // { |
| 160 | // gid: gid, |
| 161 | // tooltip: ..., (optional) |
| 162 | // key: ..., (optional) |
| 163 | // cb: cb |
| 164 | // id: ... (added by us) |
| 165 | // index: ... (added by us) |
| 166 | // } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 167 | |
| 168 | rset.forEach(function (btn, index) { |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 169 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 170 | if (!fs.isO(btn)) { |
| 171 | $log.warn('radio button descriptor at index ' + index + |
| 172 | ' not an object'); |
| 173 | return; |
| 174 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 175 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 176 | var rid = id + '-' + index, |
| 177 | initSel = (index === 0), |
| 178 | rbdiv = createDiv(rDiv, 'radioButton', rid); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 179 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 180 | rbdiv.classed('selected', initSel); |
| 181 | rbdiv.on('click', rbclick); |
| 182 | is.loadIcon(rbdiv, btn.gid, btnSize, true); |
| 183 | angular.extend(btn, { |
| 184 | el: rbdiv, |
| 185 | id: rid, |
| 186 | cb: fs.isF(btn.cb) || noop, |
| 187 | index: index |
| 188 | }); |
| 189 | |
| 190 | if (btn.key) { |
| 191 | idxByKey[btn.key] = index; |
| 192 | } |
| 193 | |
| 194 | rads.push(btn); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 195 | }); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 196 | |
| 197 | |
| 198 | function invokeCurrent() { |
| 199 | var curr = rads[currIdx]; |
| 200 | curr.cb(curr.index, curr.key); |
| 201 | } |
| 202 | |
| 203 | function selected(x) { |
| 204 | var curr = rads[currIdx], |
| 205 | idx; |
| 206 | |
| 207 | if (x === undefined) { |
| 208 | return curr.key || curr.index; |
| 209 | } else { |
| 210 | idx = idxByKey[x]; |
| 211 | if (idx === undefined) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 212 | $log.warn('no radio button with key:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 213 | } else { |
| 214 | selectedIndex(idx); |
| 215 | } |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | function selectedIndex(x) { |
| 220 | if (x === undefined) { |
| 221 | return currIdx; |
| 222 | } else { |
| 223 | if (x >= 0 && x < rads.length) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 224 | if (currIdx !== x) { |
| 225 | currIdx = x; |
| 226 | invokeCurrent(); |
| 227 | } else { |
| 228 | $log.warn('current index already selected:', x); |
| 229 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 230 | } else { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 231 | $log.warn('invalid radio button index:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 232 | } |
| 233 | } |
| 234 | } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 235 | |
| 236 | return { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 237 | width: rsetWidth, |
| 238 | selected: selected, |
| 239 | selectedIndex: selectedIndex |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 240 | } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 241 | } |
| 242 | |
Bri Prebilic Cole | 258f046 | 2015-02-25 14:48:50 -0800 | [diff] [blame] | 243 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 244 | angular.module('onosWidget') |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 245 | .factory('ButtonService', |
| 246 | ['$log', 'FnService', 'IconService', |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 247 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 248 | function (_$log_, _fs_, _is_) { |
| 249 | $log = _$log_; |
| 250 | fs = _fs_; |
| 251 | is = _is_; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 252 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 253 | return { |
| 254 | button: button, |
| 255 | toggle: toggle, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 256 | radioSet: radioSet |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 257 | }; |
| 258 | }]); |
| 259 | |
| 260 | }()); |