Index: tracing/tracing/value/ui/scalar_span.html |
diff --git a/tracing/tracing/value/ui/scalar_span.html b/tracing/tracing/value/ui/scalar_span.html |
index 56797585daf6eaee2a1ad4361d1f08a6cccb90bc..134eac5f39d767d70b4529b8a44134417ee3f205 100644 |
--- a/tracing/tracing/value/ui/scalar_span.html |
+++ b/tracing/tracing/value/ui/scalar_span.html |
@@ -8,10 +8,27 @@ found in the LICENSE file. |
<link rel="import" href="/tracing/ui/base/deep_utils.html"> |
<link rel="import" href="/tracing/value/numeric.html"> |
<link rel="import" href="/tracing/value/unit.html"> |
+<link rel="import" href="/tracing/value/value.html"> |
<script> |
'use strict'; |
tr.exportTo('tr.v.ui', function() { |
+ var emojiPrefix = String.fromCharCode(55357); |
+ var Emoji = { |
+ GRINNING_FACE: emojiPrefix + String.fromCharCode(56835), |
+ NEUTRAL_FACE: emojiPrefix + String.fromCharCode(56848), |
+ CONFOUNDED_FACE: emojiPrefix + String.fromCharCode(56854) |
+ }; |
+ |
+ /** |
+ * @param {undefined|tr.v.NumericValue|tr.v.Numeric} value |
+ * @param {Object=} opt_config |
+ * @param {number=} opt_config.total |
+ * @param {boolean=} opt_config.rightAlign |
+ * @param {!tr.v.Unit=} opt_config.unit |
+ * @param {tr.v.Significance=} opt_config.significance |
+ * @return {string|Element} |
+ */ |
function createScalarSpan(value, opt_config) { |
if (value === undefined) |
return ''; |
@@ -21,10 +38,20 @@ tr.exportTo('tr.v.ui', function() { |
var span = ownerDocument.createElement('tr-v-ui-scalar-span'); |
+ if (value instanceof tr.v.NumericValue) { |
+ value = value.numeric; |
+ config.unit = value.unit; |
+ } |
+ |
var numericValue; |
if (value instanceof tr.v.ScalarNumeric) { |
span.value = value; |
numericValue = value.value; |
+ } else if (value instanceof tr.v.Numeric) { |
+ numericValue = value.average; |
+ if (numericValue === undefined) |
+ return ''; |
+ span.setValueAndUnit(numericValue, value.unit); |
} else { |
var unit = config.unit; |
if (unit === undefined) { |
@@ -44,10 +71,14 @@ tr.exportTo('tr.v.ui', function() { |
if (config.rightAlign) |
span.rightAlign = true; |
+ if (config.significance !== undefined) |
+ span.significance = config.significance; |
+ |
return span; |
} |
return { |
+ Emoji: Emoji, |
createScalarSpan: createScalarSpan |
}; |
}); |
@@ -65,6 +96,12 @@ tr.exportTo('tr.v.ui', function() { |
position: relative; |
display: block; |
} |
+ #significance.better, #content.better { |
+ color: green; |
+ } |
+ #significance.worse, #content.worse { |
+ color: red; |
+ } |
#sparkline { |
width: 0%; |
position: absolute; |
@@ -80,8 +117,13 @@ tr.exportTo('tr.v.ui', function() { |
margin-left: 4px; |
font-size: 66%; |
} |
+ #significance { |
+ font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; |
+ font-size: 13pt; |
+ } |
</style> |
<span id="sparkline"></span> |
+ <span id="significance"></span> |
<span id="content"></span> |
<span id="warning" style="display:none">⚠</span> |
</template> |
@@ -92,12 +134,41 @@ tr.exportTo('tr.v.ui', function() { |
Polymer({ |
is: 'tr-v-ui-scalar-span', |
- ready: function() { |
+ created: function() { |
this.value_ = undefined; |
this.unit_ = undefined; |
+ this.context_ = undefined; |
this.warning_ = undefined; |
this.percentage_ = undefined; |
+ this.significance_ = tr.v.Significance.DONT_CARE; |
+ }, |
+ |
+ get significance() { |
+ return this.significance_; |
+ }, |
+ |
+ set significance(s) { |
+ this.significance_ = s; |
+ this.updateContent_(); |
+ }, |
+ |
+ set contentTextDecoration(deco) { |
+ this.$.content.style.textDecoration = deco; |
+ }, |
+ |
+ get value() { |
+ return this.value_; |
+ }, |
+ |
+ set value(value) { |
+ if (value instanceof tr.v.ScalarNumeric) { |
+ this.value_ = value.value; |
+ this.unit_ = value.unit; |
+ } else { |
+ this.value_ = value; |
+ } |
+ this.updateContent_(); |
}, |
attached: function() { |
@@ -128,14 +199,14 @@ Polymer({ |
this.updateContent_(); |
}, |
- get context() { |
- return this.context_; |
- }, |
+ get context() { |
+ return this.context_; |
+ }, |
- set context(context) { |
- this.context_ = context; |
- this.updateContent_(); |
- }, |
+ set context(context) { |
+ this.context_ = context; |
+ this.updateContent_(); |
+ }, |
get unit() { |
return this.unit_; |
@@ -183,41 +254,108 @@ Polymer({ |
}, |
updateContent_: function() { |
- if (this.unit_ === undefined) { |
- Polymer.dom(this.$.content).textContent = ''; |
- this.$.content.style.color = ''; |
+ Polymer.dom(this.$.significance).textContent = ''; |
+ Polymer.dom(this.$.content).textContent = ''; |
+ Polymer.dom(this.$.content).classList.remove('better'); |
+ Polymer.dom(this.$.content).classList.remove('worse'); |
+ Polymer.dom(this.$.significance).classList.remove('better'); |
+ Polymer.dom(this.$.significance).classList.remove('worse'); |
+ |
+ if (this.unit_ === undefined) |
return; |
- } |
+ this.$.content.title = ''; |
Polymer.dom(this.$.content).textContent = |
this.unit_.format(this.value, this.context); |
+ this.updateDelta_(); |
+ }, |
- var BIGGER_IS_BETTER = tr.v.ImprovementDirection.BIGGER_IS_BETTER; |
- var SMALLER_IS_BETTER = tr.v.ImprovementDirection.SMALLER_IS_BETTER; |
- var color = ''; |
- if (this.unit_.isDelta) { |
- var improvementDirection = this.unit_.improvementDirection; |
- if (this.value > 0) { |
- // Positive delta. |
- switch (improvementDirection) { |
- case BIGGER_IS_BETTER: |
- color = 'green'; |
- break; |
- case SMALLER_IS_BETTER: |
- color = 'red'; |
- break; |
- } |
- } else if (this.value < 0) { |
- // Negative delta. |
- switch (improvementDirection) { |
- case BIGGER_IS_BETTER: |
- color = 'red'; |
- break; |
- case SMALLER_IS_BETTER: |
- color = 'green'; |
- break; |
- } |
- } |
+ updateDelta_: function() { |
+ if (!this.unit_.isDelta) |
+ return; |
+ |
+ var biggerIsBetter = false; |
+ var smallerIsBetter = false; |
+ switch (this.unit_.improvementDirection) { |
+ case tr.v.ImprovementDirection.DONT_CARE: |
+ return; |
+ |
+ case tr.v.ImprovementDirection.BIGGER_IS_BETTER: |
+ biggerIsBetter = true; |
+ break; |
+ |
+ case tr.v.ImprovementDirection.SMALLER_IS_BETTER: |
+ smallerIsBetter = true; |
+ break; |
+ } |
+ |
+ var better = ((biggerIsBetter && this.value > 0) || |
+ (smallerIsBetter && this.value < 0)); |
+ var worse = ((biggerIsBetter && this.value < 0) || |
+ (smallerIsBetter && this.value > 0)); |
+ |
+ var changeClass = ''; |
+ var emoji = tr.v.ui.Emoji.NEUTRAL_FACE; |
+ var title = ''; |
+ |
+ if (better) { |
+ changeClass = 'better'; |
+ emoji = tr.v.ui.Emoji.GRINNING_FACE; |
+ title = 'improvement'; |
+ } else if (worse) { |
+ changeClass = 'worse'; |
+ emoji = tr.v.ui.Emoji.CONFOUNDED_FACE; |
+ title = 'regression'; |
+ } else { |
+ title = 'no change'; |
+ } |
+ |
+ // Set the content class separately from the significance class so that |
+ // NEUTRAL_FACE is always a neutral color. |
+ if (changeClass) |
+ Polymer.dom(this.$.content).classList.add(changeClass); |
+ |
+ switch (this.significance) { |
+ case tr.v.Significance.DONT_CARE: |
+ emoji = ''; |
+ changeClass = ''; |
+ break; |
+ |
+ case tr.v.Significance.INSIGNIFICANT: |
+ changeClass = ''; |
+ emoji = tr.v.ui.Emoji.NEUTRAL_FACE; |
+ if (better || worse) |
+ title = 'insignificant ' + title; |
+ break; |
+ |
+ case tr.v.Significance.SIGNIFICANT: |
+ if (!better && !worse) |
+ throw new Error('How can no change be significant?'); |
+ |
+ title = 'significant ' + title; |
+ break; |
+ } |
+ |
+ Polymer.dom(this.$.significance).textContent = emoji; |
+ this.$.significance.title = title; |
+ this.$.content.title = title; |
+ if (changeClass) |
+ Polymer.dom(this.$.significance).classList.add(changeClass); |
+ }, |
+ |
+ get warning() { |
+ return this.warning_; |
+ }, |
+ |
+ set warning(warning) { |
+ this.warning_ = warning; |
+ var warningEl = this.$.warning; |
+ if (this.warning_) { |
+ warningEl.title = warning; |
+ warningEl.style.display = ''; |
+ } else { |
+ warningEl.title = ''; |
+ warningEl.style.display = 'none'; |
} |
this.$.content.style.color = color; |
}, |