1
/******************************************************************************
2
* Copyright (C) 2011 Michael Hofmann <mh21@piware.de> *
4
* This program is free software; you can redistribute it and/or modify *
5
* it under the terms of the GNU General Public License as published by *
6
* the Free Software Foundation; either version 3 of the License, or *
7
* (at your option) any later version. *
9
* This program is distributed in the hope that it will be useful, *
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12
* GNU General Public License for more details. *
14
* You should have received a copy of the GNU General Public License along *
15
* with this program; if not, write to the Free Software Foundation, Inc., *
16
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
17
******************************************************************************/
19
public class MultiLoadIndicator : Object {
23
private string directory;
24
private TimeoutSource timeout;
25
private FixedAppIndicator.Indicator indicator;
29
private IconData[] _icon_datas;
30
private Gtk.Menu _menu;
38
foreach (unowned IconData icon_data in this._icon_datas)
39
icon_data.trace_length = value;
49
if (this.timeout != null)
50
this.timeout.destroy();
51
if (this.speed % 1000 == 0)
52
this.timeout = new TimeoutSource.seconds(this.speed / 1000);
54
this.timeout = new TimeoutSource(this.speed);
55
this.timeout.attach(null);
56
this.timeout.set_callback(() => {
57
foreach (unowned IconData icon_data in this._icon_datas) {
58
icon_data.update_traces();
59
icon_data.update_factor();
61
if (indicator != null)
62
indicator.set_icon(this.write());
68
public IconData[] icon_datas {
70
return this._icon_datas;
74
public Gtk.Menu menu {
81
this.indicator = null;
82
if (value != null && this.indicator == null) {
83
this.indicator = new FixedAppIndicator.Indicator.with_path("multiload", this.write(),
84
AppIndicator.IndicatorCategory.SYSTEM_SERVICES, this.directory);
85
this.indicator.set_status(AppIndicator.IndicatorStatus.ACTIVE);
88
this.indicator.set_menu(value);
92
// Needs to be called before destruction to break the reference cycle from the timeout source
93
public void destroy() {
94
if (this.timeout == null)
96
this.timeout.destroy();
100
~MultiLoadIndicator() {
101
for (uint i = 0, icount = this.count; i < icount; ++i)
102
FileUtils.remove(this.filename(i));
103
DirUtils.remove(this.directory);
106
public MultiLoadIndicator() {
107
var template = "/var/lock/multiload-icons-XXXXXX".dup();
108
this.directory = DirUtils.mkdtemp(template);
117
public void add_icon_data(IconData data) {
118
data.trace_length = this._size;
119
this._icon_datas += data;
122
private string filename(uint index) {
123
return @"$(this.directory)/$index.png";
126
private string write() {
128
foreach (unowned IconData icon_data in this._icon_datas)
129
if (icon_data.enabled)
131
var surface = new Cairo.ImageSurface(Cairo.Format.ARGB32,
132
(int)(count * (this._size + 2)) - 2, (int)this.height);
133
var ctx = new Cairo.Context(surface);
134
ctx.set_antialias(Cairo.Antialias.NONE);
135
ctx.set_line_width(1);
137
foreach (unowned IconData icon_data in this._icon_datas) {
138
if (!icon_data.enabled)
140
icon_data.set_source_color(ctx);
141
ctx.rectangle(offset, 0, this._size, this.height);
143
var values = new double[icon_data.length, this._size];
144
var scale = icon_data.factor;
145
for (uint j = 0, jsize = values.length[0]; j < jsize; ++j) {
146
unowned double[] trace_data = icon_data.trace(j).values;
147
for (uint i = 0, isize = values.length[1]; i < isize; ++i)
148
values[j, i] = (j > 0 ? values[j - 1, i] : 0) + trace_data[i] / scale;
151
for (int j = values.length[0] - 1; j >= 0; --j) {
152
Gdk.cairo_set_source_color(ctx, icon_data.trace(j).color);
153
for (uint i = 0, isize = values.length[1]; i < isize; ++i) {
154
// the baseline is outside the canvas
155
ctx.move_to(0.5 + offset + i, this.height + 0.5);
156
ctx.line_to(0.5 + offset + i,
157
this.height + 0.5 - this.height * values[j, i]);
161
offset += this._size + 2;
163
string name = this.filename(this.index);
164
surface.write_to_png(name);
165
this.index = (this.index + 1) % this.count;