Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 1 | /* |
Brian O'Connor | 5ab426f | 2016-04-09 01:19:45 -0700 | [diff] [blame] | 2 | * Copyright 2015-present Open Networking Laboratory |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 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 | eef67ae | 2015-07-01 16:26:59 -0700 | [diff] [blame] | 24 | var $log, fs, is, tts; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 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 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 52 | // === BUTTON ================================================= |
| 53 | |
| 54 | // div is where to put the button (d3.selection of a DIV element) |
| 55 | // id should be globally unique |
| 56 | // gid is glyph ID (from Glyph Service) |
| 57 | // cb is callback function on click |
| 58 | // tooltip is text for tooltip |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 59 | function button(div, id, gid, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 60 | if (!divExists(div, 'button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 61 | |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 62 | var btnDiv = createDiv(div, 'button', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 63 | cbFnc = fs.isF(cb) || noop; |
| 64 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 65 | is.loadIcon(btnDiv, gid, btnSize, true); |
Bri Prebilic Cole | eef67ae | 2015-07-01 16:26:59 -0700 | [diff] [blame] | 66 | if (tooltip) { tts.addTooltip(btnDiv, tooltip); } |
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 | eef67ae | 2015-07-01 16:26:59 -0700 | [diff] [blame] | 94 | if (tooltip) { tts.addTooltip(togDiv, tooltip); } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 95 | |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 96 | function _toggle(b, nocb) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 97 | sel = (b === undefined) ? !sel : !!b; |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 98 | togDiv.classed('selected', sel); |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 99 | nocb || cbFnc(sel); |
| 100 | } |
| 101 | |
| 102 | // toggle the button state without invoking the callback |
| 103 | function toggleNoCb() { |
| 104 | _toggle(undefined, true); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | togDiv.on('click', _toggle); |
| 108 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 109 | return { |
| 110 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 111 | width: buttonWidth, |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 112 | selected: function () { return sel; }, |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 113 | toggle: _toggle, |
| 114 | toggleNoCb: toggleNoCb |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 115 | } |
| 116 | } |
| 117 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 118 | |
| 119 | // === RADIO BUTTON SET ======================================= |
| 120 | |
| 121 | |
| 122 | // div is where to put the button (d3.selection of a DIV element) |
| 123 | // id should be globally unique |
| 124 | // rset is an array of button descriptors of the following form: |
| 125 | // { |
| 126 | // gid: glyphId, |
| 127 | // tooltip: tooltipText, |
| 128 | // cb: callbackFunction |
| 129 | // } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 130 | function radioSet(div, id, rset) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 131 | if (!divExists(div, 'radio button set')) return null; |
| 132 | |
| 133 | if (!fs.isA(rset) || !rset.length) { |
| 134 | $log.warn('invalid array (radio button set)'); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 135 | return null; |
| 136 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 137 | |
| 138 | var rDiv = createDiv(div, 'radioSet', id), |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 139 | rads = [], |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 140 | idxByKey = {}, |
| 141 | currIdx = 0; |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 142 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 143 | function rsetWidth() { |
| 144 | return ((btnSize + btnPadding) * rads.length) + btnPadding; |
| 145 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 146 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 147 | function rbclick() { |
| 148 | var id = d3.select(this).attr('id'), |
| 149 | m = /^.*-(\d+)$/.exec(id), |
| 150 | idx = Number(m[1]); |
| 151 | |
| 152 | if (idx !== currIdx) { |
| 153 | rads[currIdx].el.classed('selected', false); |
| 154 | currIdx = idx; |
| 155 | rads[currIdx].el.classed('selected', true); |
| 156 | invokeCurrent(); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 157 | } |
| 158 | } |
| 159 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 160 | // { |
| 161 | // gid: gid, |
| 162 | // tooltip: ..., (optional) |
| 163 | // key: ..., (optional) |
| 164 | // cb: cb |
| 165 | // id: ... (added by us) |
| 166 | // index: ... (added by us) |
| 167 | // } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 168 | |
| 169 | rset.forEach(function (btn, index) { |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 170 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 171 | if (!fs.isO(btn)) { |
| 172 | $log.warn('radio button descriptor at index ' + index + |
| 173 | ' not an object'); |
| 174 | return; |
| 175 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 176 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 177 | var rid = id + '-' + index, |
| 178 | initSel = (index === 0), |
| 179 | rbdiv = createDiv(rDiv, 'radioButton', rid); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 180 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 181 | rbdiv.classed('selected', initSel); |
| 182 | rbdiv.on('click', rbclick); |
| 183 | is.loadIcon(rbdiv, btn.gid, btnSize, true); |
Bri Prebilic Cole | eef67ae | 2015-07-01 16:26:59 -0700 | [diff] [blame] | 184 | if (btn.tooltip) { tts.addTooltip(rbdiv, btn.tooltip); } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 185 | angular.extend(btn, { |
| 186 | el: rbdiv, |
| 187 | id: rid, |
| 188 | cb: fs.isF(btn.cb) || noop, |
| 189 | index: index |
| 190 | }); |
| 191 | |
| 192 | if (btn.key) { |
| 193 | idxByKey[btn.key] = index; |
| 194 | } |
| 195 | |
| 196 | rads.push(btn); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 197 | }); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 198 | |
| 199 | |
| 200 | function invokeCurrent() { |
| 201 | var curr = rads[currIdx]; |
| 202 | curr.cb(curr.index, curr.key); |
| 203 | } |
| 204 | |
| 205 | function selected(x) { |
| 206 | var curr = rads[currIdx], |
| 207 | idx; |
| 208 | |
| 209 | if (x === undefined) { |
| 210 | return curr.key || curr.index; |
| 211 | } else { |
| 212 | idx = idxByKey[x]; |
| 213 | if (idx === undefined) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 214 | $log.warn('no radio button with key:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 215 | } else { |
| 216 | selectedIndex(idx); |
| 217 | } |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | function selectedIndex(x) { |
| 222 | if (x === undefined) { |
| 223 | return currIdx; |
| 224 | } else { |
| 225 | if (x >= 0 && x < rads.length) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 226 | if (currIdx !== x) { |
Simon Hunt | a5b53af | 2015-10-12 15:56:40 -0700 | [diff] [blame] | 227 | rads[currIdx].el.classed('selected', false); |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 228 | currIdx = x; |
Simon Hunt | a5b53af | 2015-10-12 15:56:40 -0700 | [diff] [blame] | 229 | rads[currIdx].el.classed('selected', true); |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 230 | invokeCurrent(); |
| 231 | } else { |
| 232 | $log.warn('current index already selected:', x); |
| 233 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 234 | } else { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 235 | $log.warn('invalid radio button index:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 236 | } |
| 237 | } |
| 238 | } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 239 | |
| 240 | return { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 241 | width: rsetWidth, |
| 242 | selected: selected, |
Simon Hunt | 5b024d7 | 2016-01-29 11:02:43 -0800 | [diff] [blame] | 243 | selectedIndex: selectedIndex, |
| 244 | size: function () { return rads.length; } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 245 | } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 246 | } |
| 247 | |
Bri Prebilic Cole | 258f046 | 2015-02-25 14:48:50 -0800 | [diff] [blame] | 248 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 249 | angular.module('onosWidget') |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 250 | .factory('ButtonService', |
Bri Prebilic Cole | eef67ae | 2015-07-01 16:26:59 -0700 | [diff] [blame] | 251 | ['$log', 'FnService', 'IconService', 'TooltipService', |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 252 | |
Bri Prebilic Cole | eef67ae | 2015-07-01 16:26:59 -0700 | [diff] [blame] | 253 | function (_$log_, _fs_, _is_, _tts_) { |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 254 | $log = _$log_; |
| 255 | fs = _fs_; |
| 256 | is = _is_; |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 257 | tts = _tts_; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 258 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 259 | return { |
| 260 | button: button, |
| 261 | toggle: toggle, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 262 | radioSet: radioSet |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 263 | }; |
| 264 | }]); |
| 265 | |
| 266 | }()); |