diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js index db7fe591..39801ab9 100644 --- a/extensions/systemMonitor/extension.js +++ b/extensions/systemMonitor/extension.js @@ -9,6 +9,9 @@ const Shell = imports.gi.Shell; const Main = imports.ui.main; +const INDICATOR_UPDATE_INTERVAL = 500; +const INDICATOR_NUM_GRID_LINES = 3; + let _cpuIndicator; let _memIndicator; let _box; @@ -19,29 +22,24 @@ function Indicator() { Indicator.prototype = { _init: function() { - this._initValues(); - this.actor = new St.DrawingArea({ style_class: "extension-systemMonitor-indicator-area", - reactive: true}); - this.actor.connect('repaint', Lang.bind(this, this._draw)); - this.actor.connect('button-press-event', function() { + this._initValues(); + this.drawing_area = new St.DrawingArea({ reactive: true }); + this.drawing_area.width = 100; this.drawing_area.height = 100; + this.drawing_area.connect('repaint', Lang.bind(this, this._draw)); + this.drawing_area.connect('button-press-event', function() { let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop'); app.open_new_window(-1); }); - this._timeoutId = Mainloop.timeout_add(250, Lang.bind(this, function () { - this._updateValues(); - this.actor.queue_repaint(); + this.actor = new St.Bin({ style_class: "extension-systemMonitor-indicator-area", + reactive: true}); + this.actor.add_actor(this.drawing_area); + + Mainloop.timeout_add(INDICATOR_UPDATE_INTERVAL, Lang.bind(this, function () { + this._updateValues(); + this.drawing_area.queue_repaint(); return true; - })); - }, - - destroy: function() { - if (this._timeoutId) { - Mainloop.source_remove(this._timeoutId); - this._timeoutId = 0; - } - - this.actor.destroy(); + })); }, _initValues: function() { @@ -54,23 +52,83 @@ Indicator.prototype = { let [width, height] = area.get_surface_size(); let themeNode = this.actor.get_theme_node(); let cr = area.get_context(); - for (let i = this.values.length - 1; i >= 0; i--) { - let color = themeNode.get_color(this.values[i].color); - cr.moveTo(0, height); - let k; - for (k = 0; k < this.values[i].values.length; k++) { - cr.lineTo(k, (1 - this.values[i].values[k]) * height); - } - if (k > width) - this.values[i].values.shift(); - cr.lineTo(k, height); - cr.lineTo(0, height); - cr.closePath(); - Clutter.cairo_set_source_color(cr, color); - cr.fill(); + //draw the background grid + let color = themeNode.get_color(this.gridColor); + let gridOffset = Math.floor(height / (INDICATOR_NUM_GRID_LINES + 1)); + for (let i = 1; i <= INDICATOR_NUM_GRID_LINES; ++i) { + cr.moveTo(0, i * gridOffset + .5); + cr.lineTo(width, i * gridOffset + .5); } + Clutter.cairo_set_source_color(cr, color); + cr.setLineWidth(1); + cr.setDash([4,1], 0); + cr.stroke(); + + //draw the foreground + + function makePath(values, reverse, nudge) { + if (nudge == null) { + nudge = 0; + } + //if we are going in reverse, we are completing the bottom of a chart, so use lineTo + if (reverse) { + cr.lineTo(values.length - 1, (1 - values[values.length - 1]) * height + nudge); + for (let k = values.length - 2; k >= 0; --k) { + cr.lineTo(k, (1 - values[k]) * height + nudge); + } + } else { + cr.moveTo(0, (1 - values[0]) * height + nudge); + for (let k = 1; k < values.length; ++k) { + cr.lineTo(k, (1 - values[k]) * height + nudge); + } + + } + } + + let renderStats = this.renderStats; + + // Make sure we don't have more sample points than pixels + renderStats.map(Lang.bind(this, function(k){ + let stat = this.stats[k]; + if (stat.values.length > width) { + stat.values = stat.values.slice(stat.values.length - width, stat.values.length); + } + })); + + for (let i = 0; i < renderStats.length; ++i) { + let stat = this.stats[renderStats[i]]; + // We outline at full opacity and fill with 40% opacity + let outlineColor = themeNode.get_color(stat.color); + let color = new Clutter.Color(outlineColor); + color.alpha = color.alpha * .4; + + // Render the background between us and the next level + makePath(stat.values, false); + // If there is a process below us, render the cpu between us and it, otherwise, + // render to the bottom of the chart + if (i == renderStats.length - 1) { + cr.lineTo(stat.values.length - 1, height); + cr.lineTo(0, height); + cr.closePath(); + } else { + let nextStat = this.stats[renderStats[i+1]]; + makePath(nextStat.values, true); + } + cr.closePath() + Clutter.cairo_set_source_color(cr, color); + cr.fill(); + + // Render the outline of this level + makePath(stat.values, false, .5); + Clutter.cairo_set_source_color(cr, outlineColor); + cr.setLineWidth(1.0); + cr.setDash([], 0); + cr.stroke(); + } + } + }; function CpuIndicator() { @@ -80,14 +138,28 @@ function CpuIndicator() { CpuIndicator.prototype = { __proto__: Indicator.prototype, + _init: function() { + Indicator.prototype._init.call(this); + this.gridColor = '-grid-color'; + this.renderStats = [ 'cpu-user', 'cpu-sys', 'cpu-iowait' ]; + + // Make sure renderStats is sorted as necessary for rendering + let renderStatOrder = {'cpu-total': 0, 'cpu-user': 1, 'cpu-sys': 2, 'cpu-iowait': 3}; + this.renderStats = this.renderStats.sort(function(a,b) { + return renderStatOrder[a] - renderStatOrder[b]; + }); + }, + _initValues: function() { this._prev = new GTop.glibtop_cpu; GTop.glibtop_get_cpu(this._prev); - this.values = []; - this.values.push({color: "-cpu-user-color", values: []}); - this.values.push({color: "-cpu-sys-color", values: []}); - this.values.push({color: "-cpu-iowait-color", values: []}); + this.stats = { + 'cpu-user': {color: '-cpu-user-color', values: []}, + 'cpu-sys': {color: '-cpu-sys-color', values: []}, + 'cpu-iowait': {color: '-cpu-iowait-color', values: []}, + 'cpu-total': {color: '-cpu-total-color', values: []} + }; }, _updateValues: function() { @@ -98,15 +170,16 @@ CpuIndicator.prototype = { let user = cpu.user - this._prev.user; let sys = cpu.sys - this._prev.sys; let iowait = cpu.iowait - this._prev.iowait; + let idle = cpu.idle - this._prev.idle; - t = user / total; - this.values[0].values.push(t); - - t += sys / total; - this.values[1].values.push(t); t += iowait / total; - this.values[2].values.push(t); - + this.stats['cpu-iowait'].values.push(t); + t += sys / total; + this.stats['cpu-sys'].values.push(t); + t += user / total; + this.stats['cpu-user'].values.push(t); + this.stats['cpu-total'].values.push(1 - idle / total); + this._prev = cpu; } }; @@ -117,24 +190,37 @@ function MemoryIndicator() { MemoryIndicator.prototype = { __proto__: Indicator.prototype, + + _init: function() { + Indicator.prototype._init.call(this); + this.gridColor = '-grid-color'; + this.renderStats = [ 'mem-user', 'mem-other', 'mem-cached' ]; + + // Make sure renderStats is sorted as necessary for rendering + let renderStatOrder = { 'mem-cached': 0, 'mem-other': 1, 'mem-user': 2 }; + this.renderStats = this.renderStats.sort(function(a,b) { + return renderStatOrder[a] - renderStatOrder[b]; + }); + }, _initValues: function() { this.mem = new GTop.glibtop_mem; - this.values = []; - this.values.push({ color: "-mem-user-color", values: [] }); - this.values.push({ color: "-mem-other-color", values: [] }); - this.values.push({ color: "-mem-cached-color", values: [] }); + this.stats = { + 'mem-user': { color: "-mem-user-color", values: [] }, + 'mem-other': { color: "-mem-other-color", values: [] }, + 'mem-cached': { color: "-mem-cached-color", values: [] } + }; }, _updateValues: function() { GTop.glibtop_get_mem(this.mem); let t = this.mem.user / this.mem.total; - this.values[0].values.push(t); + this.stats['mem-user'].values.push(t); t += (this.mem.used - this.mem.user - this.mem.cached) / this.mem.total; - this.values[1].values.push(t); + this.stats['mem-other'].values.push(t); t += this.mem.cached / this.mem.total; - this.values[2].values.push(t); + this.stats['mem-cached'].values.push(t); } }; @@ -143,7 +229,7 @@ function init() { } function enable() { - _cpuIndicator = new CpuIndicator(); + _cpuIndicator = new CpuIndicator(); _memIndicator = new MemoryIndicator(); _box = new St.BoxLayout({ style_class: 'extension-systemMonitor-container' }); _box.add(_cpuIndicator.actor); diff --git a/extensions/systemMonitor/stylesheet.css b/extensions/systemMonitor/stylesheet.css index 26aad6b3..daad48d1 100644 --- a/extensions/systemMonitor/stylesheet.css +++ b/extensions/systemMonitor/stylesheet.css @@ -1,16 +1,23 @@ .extension-systemMonitor-container { spacing: 5px; + padding-left: 5px; + padding-right: 5px; + padding-bottom: 1px; + padding-top: 0px; } .extension-systemMonitor-indicator-area { - border: 1px solid #000; + border: 1px solid #8d8d8d; + border-radius: 3px; width: 100px; - height: 34px; - -cpu-user-color: #f00; - -cpu-sys-color: #0f0; - -cpu-iowait-color: #00f; - -mem-user-color: #ff0; - -mem-cached-color: #0ff; - -mem-other-color: #111; - background-color: #fff; + height: 30px; + -grid-color: #575757; + -cpu-total-color: rgb(0,154,62); + -cpu-user-color: rgb(69,154,0); + -cpu-sys-color: rgb(255,253,81); + -cpu-iowait-color: rgb(210,148,0); + -mem-user-color: rgb(210,148,0); + -mem-cached-color: rgb(90,90,90); + -mem-other-color: rgb(205,203,41); + background-color: #1e1e1e; }