Skip to content

Commit 2fcdbbe

Browse files
authored
Merge pull request #500 from corecoding/develop
Develop
2 parents f183191 + 8500971 commit 2fcdbbe

12 files changed

Lines changed: 1504 additions & 65 deletions

File tree

extension.js

Lines changed: 282 additions & 45 deletions
Large diffs are not rendered by default.

history.js

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
Copyright (c) 2018, Chris Monahan <chris@corecoding.com>
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
* Redistributions of source code must retain the above copyright
7+
notice, this list of conditions and the following disclaimer.
8+
* Redistributions in binary form must reproduce the above copyright
9+
notice, this list of conditions and the following disclaimer in the
10+
documentation and/or other materials provided with the distribution.
11+
* Neither the name of the GNOME nor the names of its contributors may be
12+
used to endorse or promote products derived from this software without
13+
specific prior written permission.
14+
15+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
import GObject from 'gi://GObject';
28+
import St from 'gi://St';
29+
30+
const GRAPH_WIDTH = 208;
31+
const GRAPH_HEIGHT = 90;
32+
const PADDING = 4;
33+
const MIN_BAR_WIDTH = 1;
34+
35+
export const HistoryGraph = GObject.registerClass({
36+
GTypeName: 'HistoryGraph',
37+
}, class HistoryGraph extends St.Widget {
38+
39+
_init(params = {}) {
40+
super._init({
41+
width: GRAPH_WIDTH,
42+
height: GRAPH_HEIGHT,
43+
style_class: 'vitals-history-graph',
44+
...params
45+
});
46+
this._samples = [];
47+
this._label = '';
48+
this._unit = '';
49+
this._vMin = 0;
50+
this._vMax = 0;
51+
this._base = 1;
52+
this._dataOffset = 0;
53+
this.clip_to_allocation = true;
54+
this._barContainer = new St.Widget({
55+
x_expand: true,
56+
y_expand: true
57+
});
58+
this._barContainer.clip_to_allocation = true;
59+
this.add_child(this._barContainer);
60+
}
61+
62+
setData(samples, label, unit, base) {
63+
this._samples = Array.isArray(samples) ? samples : [];
64+
this._label = label || '';
65+
this._unit = unit || '';
66+
this._base = Math.max(1, base);
67+
this._rebuildBars();
68+
}
69+
70+
_rebuildBars() {
71+
try {
72+
const children = this._barContainer.get_children();
73+
if (children && children.length > 0) {
74+
for (let i = children.length - 1; i >= 0; i--)
75+
children[i].destroy();
76+
}
77+
} catch (e) {
78+
// ignore
79+
}
80+
const data = this._samples;
81+
if (data.length === 0) return;
82+
83+
const graphW = GRAPH_WIDTH - 2 * PADDING;
84+
const graphH = GRAPH_HEIGHT - PADDING;
85+
if (graphW <= 0 || graphH <= 0) return;
86+
87+
const base = this._base;
88+
const maxBars = Math.floor(graphW / MIN_BAR_WIDTH);
89+
const totalBars = Math.ceil(data.length / base);
90+
const numBars = Math.min(totalBars, maxBars);
91+
const dataOffset = (totalBars - numBars) * base;
92+
this._dataOffset = dataOffset;
93+
const barWidth = graphW / numBars;
94+
95+
let vMin = Infinity, vMax = -Infinity;
96+
for (let i = dataOffset; i < data.length; i++) {
97+
if (data[i].v === null) continue;
98+
if (data[i].v < vMin) vMin = data[i].v;
99+
if (data[i].v > vMax) vMax = data[i].v;
100+
}
101+
if (vMin === Infinity) {
102+
vMin = 0;
103+
vMax = 1;
104+
} else if (vMax <= vMin) {
105+
const v = vMin;
106+
if (v >= 0 && v <= 1) {
107+
const margin = 0.05;
108+
vMin = Math.max(0, v - margin);
109+
vMax = Math.min(1, v + margin);
110+
if (vMax <= vMin) vMax = vMin + margin;
111+
} else {
112+
vMin -= 1;
113+
vMax += 1;
114+
}
115+
}
116+
this._vMin = vMin;
117+
this._vMax = vMax;
118+
const vRange = vMax - vMin;
119+
120+
for (let b = 0; b < numBars; b++) {
121+
const iStart = dataOffset + b * base;
122+
const iEnd = Math.min(iStart + base, data.length);
123+
let sum = 0;
124+
let count = 0;
125+
for (let i = iStart; i < iEnd; i++) {
126+
if (data[i].v !== null) {
127+
sum += data[i].v;
128+
count++;
129+
}
130+
}
131+
if (count === 0) continue;
132+
const avg = sum / count;
133+
const norm = (avg - vMin) / vRange;
134+
const barH = Math.max(1, Math.round(norm * graphH));
135+
const x = Math.round(b * barWidth);
136+
const w = Math.round((b + 1) * barWidth) - x;
137+
const bar = new St.Bin({
138+
width: w,
139+
height: barH,
140+
style_class: 'vitals-history-graph-bar'
141+
});
142+
bar.set_position(x, graphH - barH);
143+
this._barContainer.add_child(bar);
144+
}
145+
}
146+
147+
getRawRange() {
148+
if (this._samples.length === 0) return null;
149+
return { min: this._vMin, max: this._vMax };
150+
}
151+
152+
getTimeSpan() {
153+
const start = this._dataOffset;
154+
if (this._samples.length - start < 2) return 0;
155+
return this._samples[this._samples.length - 1].t - this._samples[start].t;
156+
}
157+
});

locale/my_MM/LC_MESSAGES/vitals.mo

16.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)