diff --git a/BinaryClock.png b/BinaryClock.png index ff38b80..72ce6e8 100644 Binary files a/BinaryClock.png and b/BinaryClock.png differ diff --git a/BinaryClock@zdyb.tk/extension.js b/BinaryClock@zdyb.tk/extension.js index cb8e742..142e351 100644 --- a/BinaryClock@zdyb.tk/extension.js +++ b/BinaryClock@zdyb.tk/extension.js @@ -5,98 +5,240 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +// show the time label (11:23) in the date menu: +const TimePosition = { + // * not at all? + NONE: 0, + // * above the date label ("Wednesday November 7, 2012")? + ABOVE_DATE: 1, + // * below the date label? + BELOW_DATE: 2 +}; + +////// CONFIGURE ////// +// show the time label (11:23) in the date menu: +// * above the date label ("Wednesday November 7, 2012")? +// * below the date label? +// * not at all? +let timePosition = TimePosition.BELOW_DATE; + +////// CODE ////// + +const Main = imports.ui.main; const Lang = imports.lang; const Mainloop = imports.mainloop; -const PanelMenu = imports.ui.panelMenu; +const Panel = imports.ui.panel; const St = imports.gi.St; -const Clutter = imports.gi.Clutter; +const Clutter = imports.gi.Clutter; +const Cairo = imports.cairo; +const Gio = imports.gi.Gio; -const UPDATE_INTERVAL = 500; +const UPDATE_INTERVAL = 1000; +// width of lines between the squares (px) const LINE_WIDTH = 2; +// marging around the entire clock top & bottom (px) const MARGIN = 1; +// padding square and the black centre +const PADDING = 2; +// compatibility GNOME 3.2, 3.4, 3.6 +function _getDateMenu() { + return Main.panel._dateMenu || Main.panel.statusArea.dateMenu; +} +function _getClockActor() { + let dm = _getDateMenu(); + return dm._clockDisplay || dm._clock; +} +function insert_child_above(container, child, sibling) { + if (container.insert_child_above) { + container.insert_child_above(child, sibling); + } else { // gnome 3.2 + container.add_actor(child); + container.raise_child(child, sibling); + } +} +function insert_child_below(container, child, sibling) { + if (container.insert_child_below) { + container.insert_child_below(child, sibling); + } else { // gnome 3.2 + container.insert_child_at_index(child); + container.lower_child(child, sibling); + } +} + +// ------------------------------- function BinaryClock() { this._init(); } BinaryClock.prototype = { - _init: function() { - let now = new Date(); - this.display_time = [now.getHours(), now.getMinutes()]; - - let date_menu = Main.panel._dateMenu; - this._clock = date_menu._clock; + _init: function () { + this.display_time = [-1, -1]; + //this.time_format = "%R:%S"; // Safe fallback + + this.date_menu = _getDateMenu(); + this.orig_clock = _getClockActor(); this.binary_clock = new St.DrawingArea(); - this.date = new St.Label({ style_class: "datemenu-date-label", text: this._clock.get_text() }); - - this.bs = Math.floor(Main.panel.button.height/2)-2*MARGIN; // Box size - - this.binary_clock.set_width(MARGIN*2 + (this.bs + MARGIN + LINE_WIDTH)*6); - this.binary_clock.set_height(Main.panel.button.height); - date_menu.actor.add_actor(this.binary_clock); - - this.binary_clock.connect("repaint", Lang.bind(this, this.paint_clock)); - this.binary_clock.queue_repaint(); - - let children = date_menu.menu.box.get_children(); - for each(let c in children) { - if(c.name == "calendarArea") { - c.get_children()[0].insert_actor(this.date, 0); - break; - } + + // Box size. Should be *even* and integer but still fit vertically. + this.bs = Math.floor((Panel.PANEL_ICON_SIZE - 2 * MARGIN - LINE_WIDTH) / 2); + if (this.bs % 2) { + this.bs -= 1; } + let height = 2 * this.bs + LINE_WIDTH; + this.binary_clock.set_width(6 * this.bs + 5 * LINE_WIDTH); + this.binary_clock.set_height(height); + + this.repaint = this.binary_clock.connect("repaint", + Lang.bind(this, this.paint_clock)); }, - - Run: function() { - Mainloop.timeout_add(UPDATE_INTERVAL, Lang.bind(this, this.on_timeout)); + + Run: function () { + this.run = true; + this.on_timeout(); + Mainloop.timeout_add(UPDATE_INTERVAL, Lang.bind(this, this.on_timeout)); }, - - on_timeout: function() { - this.date.set_text(this._clock.get_text()); - + + on_timeout: function () { let now = new Date(); + //this.time_label.set_text(now.toLocaleFormat(this.time_format)) let display_time = [now.getHours(), now.getMinutes()]; - - if ((this.display_time[0] != display_time[0]) || (this.display_time[1] != display_time[1])) { + + if ((this.display_time[0] !== display_time[0]) || + (this.display_time[1] !== display_time[1])) { this.display_time = display_time; this.binary_clock.queue_repaint(); } - + return true; }, - + + // to avoid fuzziness in cairo. If the line width is even you have to start + // drawing on integer coordinates, otherwise on integer + 0.5 coordinates. paint_clock: function (area) { let cr = area.get_context(); let theme_node = this.binary_clock.get_theme_node(); - + + let area_height = area.get_height(); + let area_width = area.get_width(); + + // Draw background Clutter.cairo_set_source_color(cr, theme_node.get_foreground_color()); - for (let p in cr) global.log(p); cr.setLineWidth(LINE_WIDTH); - - for (let p in this.display_time) { - for (let i=0; i<6; ++i) { - cr.rectangle(MARGIN + LINE_WIDTH/2 + (this.bs + MARGIN + LINE_WIDTH)*i, LINE_WIDTH/2 + (this.bs + MARGIN + LINE_WIDTH)*p, this.bs, this.bs); + cr.rectangle(0, 0, area_width, area_height); + cr.fill(); + + // Draw grid + cr.setSourceRGBA(0, 0, 0, 0); + cr.setOperator(Cairo.Operator.CLEAR); + // ensure no fuzziness + let halfHeight = Math.floor(area_height / 2) + (LINE_WIDTH % 2 ? 0.5 : 0); + cr.moveTo(0, halfHeight); + cr.lineTo(area_width, halfHeight); + cr.stroke(); + + // Draw dots (precache some stuff) + let dim = this.bs - 2 * LINE_WIDTH, // dimension of internal box + halfLineWidth = LINE_WIDTH / 2, + blockWidth = this.bs + LINE_WIDTH; + for (let p = 0; p < this.display_time.length; ++p) { + for (let i = 0; i < 6; ++i) { + let startx = i * blockWidth; + let borderx = startx + this.bs + halfLineWidth; // FOR SURE + + // draw the border + cr.moveTo(borderx, 0); + cr.lineTo(borderx, area_height); cr.stroke(); - if (!(this.display_time[p] & (1 << (5-i)))) { - cr.rectangle(MARGIN + LINE_WIDTH/2 + (this.bs + MARGIN + LINE_WIDTH)*i, + LINE_WIDTH/2 + (this.bs + MARGIN + LINE_WIDTH)*p, this.bs, this.bs); + + // draw the rectangle. + if ((this.display_time[p] & (1 << (5 - i)))) { + cr.rectangle( + startx + PADDING, + p * blockWidth + PADDING, + dim, + dim + ); cr.fill(); } } } + + }, + + getShowDate: function () { + if (this.date_menu._clock.time_only !== undefined) { + return !this.date_menu._clock.time_only; + } else { + return this.date_menu._clockSettings.get_boolean('show-date'); + } + }, + + toggleShowDate: function (state) { + if (this.getShowDate() === state) { + return; + } + if (this.date_menu._clock.time_only !== undefined) { + this.date_menu._clock.time_only = !state; + } else { + this.date_menu._clockSettings.set_boolean('show-date', state); + + } + }, + + enable: function () { + this.date_menu.actor.remove_actor(this.orig_clock); + this.date_menu.actor.add_actor(this.binary_clock); + this.date_menu.actor.add_style_class_name("binary-clock"); + + this.binary_clock.queue_repaint(); + + // show the time label in the date menu (or no at all) + this._originalShowDate = this.getShowDate(); + if (timePosition !== TimePosition.NONE) { + this.toggleShowDate(false); + this.orig_clock.add_style_class_name('datemenu-date-label'); + let children = this.date_menu.menu.box.get_children(); + for (let i = 0; i < children.length; ++i) { + let c = children[i]; + if (c.name === "calendarArea") { + let vbox = c.get_children()[0]; + if (timePosition === TimePosition.BELOW_DATE) { + // note - since the box layout packs vertically downwards + // to get the label visually below _date we insert_child_above. + insert_child_above(vbox, this.orig_clock, this.date_menu._date); + } else { + insert_child_below(vbox, this.orig_clock, this.date_menu._date); + } + vbox.child_set(this.orig_clock, {x_align: St.Align.MIDDLE, x_fill: false}); + break; + } + } + this.Run(); + } + }, + + disable: function () { + this.run = false; + this.date_menu.actor.remove_style_class_name("binary-clock"); + this.date_menu.actor.remove_actor(this.binary_clock); + + this.toggleShowDate(this._originalShowDate); + this.orig_clock.reparent(this.date_menu.actor); + this.orig_clock.remove_style_class_name('datemenu-date-label'); } -} +}; -function main() { - (new BinaryClock()).Run(); +function init() { + return new BinaryClock(); } diff --git a/BinaryClock@zdyb.tk/metadata.json b/BinaryClock@zdyb.tk/metadata.json index 1edf72a..fdf9e64 100644 --- a/BinaryClock@zdyb.tk/metadata.json +++ b/BinaryClock@zdyb.tk/metadata.json @@ -1,6 +1,12 @@ { - "shell-version": ["3.0.2"], + "shell-version": [ + "3.2", + "3.4", + "3.6" + ], "uuid": "BinaryClock@zdyb.tk", "name": "Binary Clock", - "description": "Shows a binary clock on panel instead of the default one" + "description": "Shows a binary clock on panel instead of the default one", + "url": "http://github.com/ojo/gnome-shell-extension-binaryclock", + "author": "Aleksander Zdyb" } diff --git a/BinaryClock@zdyb.tk/stylesheet.css b/BinaryClock@zdyb.tk/stylesheet.css new file mode 100644 index 0000000..b2d0531 --- /dev/null +++ b/BinaryClock@zdyb.tk/stylesheet.css @@ -0,0 +1,3 @@ +.binary-clock { + padding-top: 1px; +} diff --git a/BinaryClockMenu.png b/BinaryClockMenu.png index c47feaa..1adba27 100644 Binary files a/BinaryClockMenu.png and b/BinaryClockMenu.png differ diff --git a/README.rst b/README.rst index 8241a75..d491854 100644 --- a/README.rst +++ b/README.rst @@ -10,10 +10,10 @@ What it looks like? Everybody loves screenshots, right? -.. image:: http://img191.imageshack.us/img191/1846/binaryclock.png +.. image:: http://img687.imageshack.us/img687/1846/binaryclock.png :alt: BinaryClock -.. image:: http://img5.imageshack.us/img5/5193/binaryclockmenu.png +.. image:: http://img805.imageshack.us/img805/5193/binaryclockmenu.png :alt: BinaryClock (menu) @@ -40,6 +40,9 @@ or:: $ cp BinaryClock\@zdyb.tk ~/.local/share/gnome-shell/extensions/ +Please do not forget to enable the newly installed extension using for example gnome-tweak-tool_. + +.. _gnome-tweak-tool: http://live.gnome.org/GnomeTweakTool License ======= @@ -56,4 +59,4 @@ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program. If not, see http://www.gnu.org/licenses/. \ No newline at end of file +this program. If not, see http://www.gnu.org/licenses/.