1<!DOCTYPE html> 2<!-- 3Copyright 2015 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/ui/base/deep_utils.html"> 9<link rel="import" href="/tracing/ui/base/polymer_utils.html"> 10<link rel="import" href="/tracing/value/numeric.html"> 11<link rel="import" href="/tracing/value/unit.html"> 12 13<script> 14'use strict'; 15tr.exportTo('tr.v.ui', function() { 16 function createScalarSpan(value, opt_config) { 17 if (value === undefined) 18 return ''; 19 20 var config = opt_config || {}; 21 var ownerDocument = config.ownerDocument || document; 22 23 var span = ownerDocument.createElement('tr-v-ui-scalar-span'); 24 25 var numericValue; 26 if (value instanceof tr.v.ScalarNumeric) { 27 span.value = value; 28 numericValue = value.value; 29 } else { 30 var unit = config.unit; 31 if (unit === undefined) { 32 throw new Error( 33 'Unit must be provided in config when value is a number'); 34 } 35 span.setValueAndUnit(value, unit); 36 numericValue = value; 37 } 38 39 if (config.total) 40 span.percentage = numericValue / config.total; 41 42 if (config.rightAlign) 43 span.rightAlign = true; 44 45 return span; 46 } 47 48 tr.v.Unit.addEventListener('display-mode-changed', function(e) { 49 var scalarSpanTagName = 'tr-v-ui-scalar-span'; 50 var subclassNames = tr.ui.b.getPolymerElementsThatSubclass( 51 scalarSpanTagName); 52 subclassNames.push(scalarSpanTagName); 53 var isSubclass = {}; 54 subclassNames.forEach(function(n) { 55 isSubclass[n.toUpperCase()] = true; 56 }); 57 58 var m = tr.b.findDeepElementsMatchingPredicate( 59 document.body, 60 function(el) { 61 return isSubclass[el.tagName]; 62 }); 63 m.forEach(function(el) { 64 el.updateContent_(); 65 }); 66 }); 67 68 return { 69 createScalarSpan: createScalarSpan 70 }; 71}); 72</script> 73 74<polymer-element name="tr-v-ui-scalar-span"> 75 <template> 76 <style> 77 :host { 78 display: block; 79 position: relative; 80 } 81 #content.right-align { 82 text-align: right; 83 position: relative; 84 display: block; 85 } 86 #sparkline { 87 width: 0%; 88 position: absolute; 89 bottom: 0; 90 right: 0; 91 display: none; 92 height: 100%; 93 background-color: hsla(216, 100%, 94.5%, .75); 94 border-left: 1px solid hsl(216, 100%, 89%); 95 box-sizing: border-box; 96 } 97 #warning { 98 margin-left: 4px; 99 font-size: 66%; 100 } 101 </style> 102 <span id="sparkline"></span> 103 <span id="content"></span> 104 <span id="warning" style="display:none">⚠</span> 105 </template> 106 <script> 107 'use strict'; 108 109 Polymer({ 110 ready: function() { 111 this.value_ = undefined; 112 this.unit_ = undefined; 113 114 this.warning_ = undefined; 115 this.percentage_ = undefined; 116 }, 117 118 set contentTextDecoration(deco) { 119 this.$.content.style.textDecoration = deco; 120 }, 121 122 get value() { 123 return this.value_; 124 }, 125 126 set value(value) { 127 if (value instanceof tr.v.ScalarNumeric) { 128 this.value_ = value.value; 129 this.unit_ = value.unit; 130 } else { 131 this.value_ = value; 132 } 133 this.updateContent_(); 134 }, 135 136 get unit() { 137 return this.unit_; 138 }, 139 140 set unit(unit) { 141 this.unit_ = unit; 142 this.updateContent_(); 143 }, 144 145 setValueAndUnit: function(value, unit) { 146 this.value_ = value; 147 this.unit_ = unit; 148 this.updateContent_(); 149 }, 150 151 get percentage() { 152 return this.percentage_; 153 }, 154 155 set percentage(percentage) { 156 this.percentage_ = percentage; 157 this.updateSparkline_(); 158 }, 159 160 get rightAlign() { 161 return this.$.content.classList.contains('right-align'); 162 }, 163 164 set rightAlign(rightAlign) { 165 if (rightAlign) 166 this.$.content.classList.add('right-align'); 167 else 168 this.$.content.classList.remove('right-align'); 169 }, 170 171 updateSparkline_: function() { 172 if (this.percentage_ === undefined) { 173 this.$.sparkline.style.display = 'none'; 174 this.$.sparkline.style.width = '0'; 175 } else { 176 this.$.sparkline.style.display = 'block'; 177 this.$.sparkline.style.width = (this.percentage_ * 100) + '%'; 178 } 179 }, 180 181 updateContent_: function() { 182 if (this.unit_ === undefined) { 183 this.$.content.textContent = ''; 184 this.$.content.style.color = ''; 185 return; 186 } 187 188 this.$.content.textContent = this.unit_.format(this.value); 189 190 var BIGGER_IS_BETTER = tr.v.ImprovementDirection.BIGGER_IS_BETTER; 191 var SMALLER_IS_BETTER = tr.v.ImprovementDirection.SMALLER_IS_BETTER; 192 var color = ''; 193 if (this.unit_.isDelta) { 194 var improvementDirection = this.unit_.improvementDirection; 195 if (this.value > 0) { 196 // Positive delta. 197 switch (improvementDirection) { 198 case BIGGER_IS_BETTER: 199 color = 'green'; 200 break; 201 case SMALLER_IS_BETTER: 202 color = 'red'; 203 break; 204 } 205 } else if (this.value < 0) { 206 // Negative delta. 207 switch (improvementDirection) { 208 case BIGGER_IS_BETTER: 209 color = 'red'; 210 break; 211 case SMALLER_IS_BETTER: 212 color = 'green'; 213 break; 214 } 215 } 216 } 217 this.$.content.style.color = color; 218 }, 219 220 get warning() { 221 return this.warning_; 222 }, 223 224 set warning(warning) { 225 this.warning_ = warning; 226 var warningEl = this.$.warning; 227 if (this.warning_) { 228 warningEl.title = warning; 229 warningEl.style.display = ''; 230 } else { 231 warningEl.title = ''; 232 warningEl.style.display = 'none'; 233 } 234 } 235 }); 236 </script> 237</polymer-element> 238