js-beautified source code

This commit is contained in:
Olaf Leidinger 2017-11-03 20:52:04 +01:00
parent b99cf2f204
commit 2d2fc839fa
4 changed files with 720 additions and 637 deletions

View File

@ -14,374 +14,410 @@ const Clutter = imports.gi.Clutter;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const FileUtils = imports.misc.fileUtils; const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Panel = imports.ui.panel; const Panel = imports.ui.panel;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension(); const Me = ExtensionUtils.getCurrentExtension();
const Utils = Me.imports.utils; const Utils = Me.imports.utils;
const Icon = Me.imports.icon; const Icon = Me.imports.icon;
const bUseGnome34Workarounds = imports.misc.extensionUtils.versionCheck( ["3.4"], imports.misc.config.PACKAGE_VERSION); const bUseGnome34Workarounds = imports.misc.extensionUtils.versionCheck(["3.4"], imports.misc.config.PACKAGE_VERSION);
Utils.initTranslations(); Utils.initTranslations();
const _ = Gettext.gettext; const _ = Gettext.gettext;
const N_ = function(e) { return e; }; const N_ = function (e) {
return e;
};
const TeaTimeFullscreenNotification = new Lang.Class({ const TeaTimeFullscreenNotification = new Lang.Class({
Name: 'TeaTimeFullscreenNotification', Name: 'TeaTimeFullscreenNotification',
_init: function() { _init: function () {
// this spans the whole monitor and contains // this spans the whole monitor and contains
// the actual layout, which it displays in // the actual layout, which it displays in
// the center of itself // the center of itself
this._bin = new St.Bin({ x_align: St.Align.MIDDLE, y_align: St.Align.MIDDLE}); this._bin = new St.Bin({
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE
});
if (typeof Layout.MonitorConstraint != 'undefined') { if (typeof Layout.MonitorConstraint != 'undefined') {
// MonitorConstraint was introduced in gnome-3.6 // MonitorConstraint was introduced in gnome-3.6
this._monitorConstraint = new Layout.MonitorConstraint(); this._monitorConstraint = new Layout.MonitorConstraint();
this._bin.add_constraint(this._monitorConstraint); this._bin.add_constraint(this._monitorConstraint);
} }
Main.uiGroup.add_actor(this._bin); Main.uiGroup.add_actor(this._bin);
// a table imitating a vertical box layout to hold the texture and // a table imitating a vertical box layout to hold the texture and
// a label underneath it // a label underneath it
this._layout = new St.BoxLayout({ vertical: true, y_align: Clutter.ActorAlign.CENTER }); this._layout = new St.BoxLayout({
this._bin.set_child(this._layout); vertical: true,
y_align: Clutter.ActorAlign.CENTER
});
this._bin.set_child(this._layout);
// find all the textures // find all the textures
let datadir = Me.dir.get_child("data"); let datadir = Me.dir.get_child("data");
this._textureFiles = []; this._textureFiles = [];
if (datadir.query_exists(null)) { if (datadir.query_exists(null)) {
let enumerator = datadir.enumerate_children(Gio.FILE_ATTRIBUTE_STANDARD_NAME, let enumerator = datadir.enumerate_children(Gio.FILE_ATTRIBUTE_STANDARD_NAME,
Gio.FileQueryInfoFlags.NONE, Gio.FileQueryInfoFlags.NONE,
null); null);
let info; let info;
info = enumerator.next_file(null); info = enumerator.next_file(null);
while ( info != null ) { while (info != null) {
let filename = info.get_name(); let filename = info.get_name();
if (filename.match(/^cup.*/)) { if (filename.match(/^cup.*/)) {
this._textureFiles.push(datadir.get_child(filename).get_path()); this._textureFiles.push(datadir.get_child(filename).get_path());
} }
info = enumerator.next_file(null); info = enumerator.next_file(null);
} }
} }
this._textureFiles.sort(); this._textureFiles.sort();
this._texture = new Clutter.Texture({ reactive: true, keep_aspect_ratio: true }); this._texture = new Clutter.Texture({
this._texture.connect("button-release-event", Lang.bind(this, this.hide)); reactive: true,
this._layout.add_child(this._texture); keep_aspect_ratio: true
});
this._texture.connect("button-release-event", Lang.bind(this, this.hide));
this._layout.add_child(this._texture);
this._timeline = new Clutter.Timeline({ duration: 2000, repeat_count: -1, progress_mode: Clutter.AnimationMode.LINEAR }); this._timeline = new Clutter.Timeline({
this._timeline.connect("new-frame", Lang.bind(this, this._newFrame)); duration: 2000,
repeat_count: -1,
progress_mode: Clutter.AnimationMode.LINEAR
});
this._timeline.connect("new-frame", Lang.bind(this, this._newFrame));
this._label = new St.Label({ text: _("Your tea is ready!"), style_class: "dash-label" }); this._label = new St.Label({
this._layout.add_child(this._label); text: _("Your tea is ready!"),
style_class: "dash-label"
});
this._layout.add_child(this._label);
this._lightbox = new imports.ui.lightbox.Lightbox(Main.uiGroup); // Seems not to work on Gnome 3.10 { fadeInTime: 0.5, fadeOutTime: 0.5 } this._lightbox = new imports.ui.lightbox.Lightbox(Main.uiGroup); // Seems not to work on Gnome 3.10 { fadeInTime: 0.5, fadeOutTime: 0.5 }
this._lightbox.highlight(this._bin); this._lightbox.highlight(this._bin);
}, },
destroy: function() { destroy: function () {
this.hide(); this.hide();
Main.popModal(this._bin); Main.popModal(this._bin);
this._bin.destroy(); this._bin.destroy();
this._lightbox.hide(); this._lightbox.hide();
}, },
_newFrame: function(timeline, msecs, user) { _newFrame: function (timeline, msecs, user) {
let progress = timeline.get_progress(); let progress = timeline.get_progress();
let idx = Math.round(progress * this._textureFiles.length) % this._textureFiles.length; let idx = Math.round(progress * this._textureFiles.length) % this._textureFiles.length;
this._texture.set_from_file(this._textureFiles[idx]); this._texture.set_from_file(this._textureFiles[idx]);
}, },
show: function() { show: function () {
if (typeof Layout.MonitorConstraint != 'undefined') { if (typeof Layout.MonitorConstraint != 'undefined') {
this._monitorConstraint.index = global.screen.get_current_monitor() this._monitorConstraint.index = global.screen.get_current_monitor()
} }
Main.pushModal(this._bin); Main.pushModal(this._bin);
this._timeline.start(); this._timeline.start();
this._lightbox.show(); this._lightbox.show();
this._bin.show_all(); this._bin.show_all();
}, },
hide: function() { hide: function () {
Main.popModal(this._bin); Main.popModal(this._bin);
this._bin.hide(); this._bin.hide();
this._lightbox.hide(); this._lightbox.hide();
this._timeline.stop(); this._timeline.stop();
} }
}) })
const PopupTeaMenuItem = new Lang.Class({ const PopupTeaMenuItem = new Lang.Class({
Name: 'PopupTeaMenuItem', Name: 'PopupTeaMenuItem',
Extends: PopupMenu.PopupBaseMenuItem, Extends: PopupMenu.PopupBaseMenuItem,
_init: function (sTeaname, nBrewtime, params) { _init: function (sTeaname, nBrewtime, params) {
this.parent(params); this.parent(params);
this.tealabel = new St.Label({ text: sTeaname }); this.tealabel = new St.Label({
this.timelabel = new St.Label({ text: Utils.formatTime(nBrewtime) }); text: sTeaname
});
this.timelabel = new St.Label({
text: Utils.formatTime(nBrewtime)
});
if (this.actor instanceof St.BoxLayout) { if (this.actor instanceof St.BoxLayout) {
// will be used for gnome-shell 3.10 and possibly above where this.actor is BoxLayout // will be used for gnome-shell 3.10 and possibly above where this.actor is BoxLayout
this.actor.add(this.tealabel, { expand: true }); this.actor.add(this.tealabel, {
this.actor.add(this.timelabel); expand: true
} else { });
this.addActor(this.tealabel, {expand: true }); this.actor.add(this.timelabel);
this.addActor(this.timelabel, {expand: false }); } else {
} this.addActor(this.tealabel, {
} expand: true
});
this.addActor(this.timelabel, {
expand: false
});
}
}
}); });
const TeaTime = new Lang.Class({ const TeaTime = new Lang.Class({
Name : 'TeaTime', Name: 'TeaTime',
Extends : PanelMenu.Button, Extends: PanelMenu.Button,
_init : function() { _init: function () {
this.parent(null, "TeaTime"); this.parent(null, "TeaTime");
this._settings = Utils.getSettings(); this._settings = Utils.getSettings();
this._logo = new Icon.TwoColorIcon(24, Icon.TeaPot); this._logo = new Icon.TwoColorIcon(24, Icon.TeaPot);
// set timer widget // set timer widget
this._textualTimer = new St.Label({ text: "", this._textualTimer = new St.Label({
x_align: Clutter.ActorAlign.END, text: "",
y_align: Clutter.ActorAlign.CENTER }); x_align: Clutter.ActorAlign.END,
this._graphicalTimer = new Icon.TwoColorIcon(24, Icon.Pie); y_align: Clutter.ActorAlign.CENTER
});
this._graphicalTimer = new Icon.TwoColorIcon(24, Icon.Pie);
this.actor.add_actor(this._logo); this.actor.add_actor(this._logo);
this.actor.add_style_class_name('panel-status-button'); this.actor.add_style_class_name('panel-status-button');
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged)); this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
this._idleTimeout = null; this._idleTimeout = null;
this._createMenu(); this._createMenu();
}, },
_createMenu : function() { _createMenu: function () {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._settings.connect("changed::" + Utils.TEATIME_STEEP_TIMES_KEY, this._settings.connect("changed::" + Utils.TEATIME_STEEP_TIMES_KEY,
Lang.bind(this, this._updateTeaList)); Lang.bind(this, this._updateTeaList));
this._settings.connect("changed::" + Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY, this._settings.connect("changed::" + Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY,
Lang.bind(this, this._updateCountdownType)); Lang.bind(this, this._updateCountdownType));
this.teaItemCont = new PopupMenu.PopupMenuSection(); this.teaItemCont = new PopupMenu.PopupMenuSection();
/*******************/ /*******************/
// maybe one day the PopupImageMenuItem works^^ // maybe one day the PopupImageMenuItem works^^
let head = new PopupMenu.PopupMenuSection(); let head = new PopupMenu.PopupMenuSection();
let item = new PopupMenu.PopupMenuItem(_("Show settings")); //, 'gtk-preferences'); let item = new PopupMenu.PopupMenuItem(_("Show settings")); //, 'gtk-preferences');
// item._icon.icon_size = 15; // item._icon.icon_size = 15;
item.connect('activate', Lang.bind(this, this._showPreferences)); item.connect('activate', Lang.bind(this, this._showPreferences));
head.addMenuItem(item); head.addMenuItem(item);
/*******************/ /*******************/
let bottom = new PopupMenu.PopupMenuSection(); let bottom = new PopupMenu.PopupMenuSection();
this._customEntry = new St.Entry({ style_class: 'teatime-custom-entry', this._customEntry = new St.Entry({
track_hover: true, style_class: 'teatime-custom-entry',
hint_text: _("min:sec") }); track_hover: true,
this._customEntry.get_clutter_text().set_max_length(10); hint_text: _("min:sec")
this._customEntry.get_clutter_text().connect("key-press-event", Lang.bind(this, this._createCustomTimer)); });
bottom.box.add(this._customEntry); this._customEntry.get_clutter_text().set_max_length(10);
bottom.actor.set_style("padding: 0px 18px;") this._customEntry.get_clutter_text().connect("key-press-event", Lang.bind(this, this._createCustomTimer));
bottom.box.add(this._customEntry);
bottom.actor.set_style("padding: 0px 18px;")
/*******************/ /*******************/
this.menu.addMenuItem(head); this.menu.addMenuItem(head);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(this.teaItemCont); this.menu.addMenuItem(this.teaItemCont);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(bottom); this.menu.addMenuItem(bottom);
this._updateTeaList(); this._updateTeaList();
}, },
_updateTeaList : function(config, output) { _updateTeaList: function (config, output) {
// make sure the menu is empty // make sure the menu is empty
this.teaItemCont.removeAll(); this.teaItemCont.removeAll();
// fill with new teas // fill with new teas
let list = this._settings.get_value(Utils.TEATIME_STEEP_TIMES_KEY).unpack(); let list = this._settings.get_value(Utils.TEATIME_STEEP_TIMES_KEY).unpack();
for (let teaname in list) { for (let teaname in list) {
let time = list[teaname].get_uint32(); let time = list[teaname].get_uint32();
let menuItem = new PopupTeaMenuItem(_(teaname), time); let menuItem = new PopupTeaMenuItem(_(teaname), time);
menuItem.connect('activate', Lang.bind(this, function() { menuItem.connect('activate', Lang.bind(this, function () {
this._initCountdown(time); this._initCountdown(time);
})); }));
this.teaItemCont.addMenuItem(menuItem); this.teaItemCont.addMenuItem(menuItem);
} }
}, },
_updateCountdownType : function(config, output) { _updateCountdownType: function (config, output) {
let bWantGraphicalCountdown = this._settings.get_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY); let bWantGraphicalCountdown = this._settings.get_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY);
if ( bWantGraphicalCountdown != this._bGraphicalCountdown) { if (bWantGraphicalCountdown != this._bGraphicalCountdown) {
if (this._idleTimeout != null) { if (this._idleTimeout != null) {
// we have a running countdown, replace the display // we have a running countdown, replace the display
this.actor.remove_actor( this._bGraphicalCountdown this.actor.remove_actor(this._bGraphicalCountdown ?
? this._graphicalTimer : this._textualTimer); this._graphicalTimer : this._textualTimer);
this._bGraphicalCountdown = bWantGraphicalCountdown; this._bGraphicalCountdown = bWantGraphicalCountdown;
this.actor.add_actor( this._bGraphicalCountdown this.actor.add_actor(this._bGraphicalCountdown ?
? this._graphicalTimer : this._textualTimer); this._graphicalTimer : this._textualTimer);
this._updateTimerDisplay( this._getRemainingSec() ); this._updateTimerDisplay(this._getRemainingSec());
} // if timeout active } // if timeout active
} // value changed } // value changed
}, },
_createCustomTimer: function(text, event) { _createCustomTimer: function (text, event) {
if (event.get_key_symbol() == Clutter.KEY_Enter || if (event.get_key_symbol() == Clutter.KEY_Enter ||
event.get_key_symbol() == Clutter.KEY_Return) { event.get_key_symbol() == Clutter.KEY_Return) {
let customTime = text.get_text(); let customTime = text.get_text();
let seconds = 0; let seconds = 0;
let match = customTime.match(/^(?:(\d+)(?::(\d{0,2}))?|:(\d+))$/) let match = customTime.match(/^(?:(\d+)(?::(\d{0,2}))?|:(\d+))$/)
if (match) { if (match) {
let factor = 1; let factor = 1;
for (var i = match.length-2; i > 0; i--) { for (var i = match.length - 2; i > 0; i--) {
let s = match[i].replace(/^0/,''); // fix for elder GNOME <= 3.10 which don't like leading zeros let s = match[i].replace(/^0/, ''); // fix for elder GNOME <= 3.10 which don't like leading zeros
seconds += factor * parseInt(s); seconds += factor * parseInt(s);
factor *= 60; factor *= 60;
} }
if (seconds > 0) { if (seconds > 0) {
this._initCountdown(seconds); this._initCountdown(seconds);
this.menu.close(); this.menu.close();
} }
} }
this._customEntry.set_text(""); this._customEntry.set_text("");
} }
}, },
_showNotification : function(subject, text) { _showNotification: function (subject, text) {
let source = ( bUseGnome34Workarounds ) let source = (bUseGnome34Workarounds) ?
? new MessageTray.Source(_("TeaTime applet")) new MessageTray.Source(_("TeaTime applet")) :
: new MessageTray.Source(_("TeaTime applet"), 'utilities-teatime'); new MessageTray.Source(_("TeaTime applet"), 'utilities-teatime');
if (bUseGnome34Workarounds) { source.createNotificationIcon = if (bUseGnome34Workarounds) {
function() { source.createNotificationIcon =
let iconBox = new St.Bin(); function () {
iconBox._size = this.ICON_SIZE; let iconBox = new St.Bin();
iconBox.child = new St.Icon({ icon_name: 'utilities-teatime', iconBox._size = this.ICON_SIZE;
icon_type: St.IconType.FULLCOLOR, iconBox.child = new St.Icon({
icon_size: iconBox._size }); icon_name: 'utilities-teatime',
return iconBox; icon_type: St.IconType.FULLCOLOR,
} // createNotificationIcon icon_size: iconBox._size
} });
return iconBox;
} // createNotificationIcon
}
Main.messageTray.add(source); Main.messageTray.add(source);
let notification = new MessageTray.Notification(source, subject, text); let notification = new MessageTray.Notification(source, subject, text);
notification.setTransient(true); notification.setTransient(true);
source.notify(notification); source.notify(notification);
}, },
_initCountdown : function(time) { _initCountdown: function (time) {
this._startTime = new Date(); this._startTime = new Date();
this._stopTime = new Date(); this._stopTime = new Date();
this._cntdownStart = time; this._cntdownStart = time;
this._bGraphicalCountdown = this._settings.get_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY); this._bGraphicalCountdown = this._settings.get_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY);
let dt = this._bGraphicalCountdown let dt = this._bGraphicalCountdown ?
? Math.max(1.0, time / 90) // set time step to fit animation Math.max(1.0, time / 90) // set time step to fit animation
: 1.0; // show every second for the textual countdown :
1.0; // show every second for the textual countdown
this._stopTime.setTime(this._startTime.getTime() + time*1000); // in msec this._stopTime.setTime(this._startTime.getTime() + time * 1000); // in msec
this.actor.remove_actor(this._logo); // show timer instead of default icon this.actor.remove_actor(this._logo); // show timer instead of default icon
this._updateTimerDisplay(time); this._updateTimerDisplay(time);
this.actor.add_actor( this._bGraphicalCountdown this.actor.add_actor(this._bGraphicalCountdown ?
? this._graphicalTimer : this._textualTimer); this._graphicalTimer : this._textualTimer);
if (this._idleTimeout != null) Mainloop.source_remove(this._idleTimeout); if (this._idleTimeout != null) Mainloop.source_remove(this._idleTimeout);
this._idleTimeout = Mainloop.timeout_add_seconds(dt, Lang.bind(this, this._doCountdown)); this._idleTimeout = Mainloop.timeout_add_seconds(dt, Lang.bind(this, this._doCountdown));
}, },
_getRemainingSec: function() { _getRemainingSec: function () {
let a = new Date(); let a = new Date();
return (this._stopTime.getTime() - a.getTime()) * 1e-3; return (this._stopTime.getTime() - a.getTime()) * 1e-3;
}, },
_updateTimerDisplay: function(remainingTime) { _updateTimerDisplay: function (remainingTime) {
if ( this._bGraphicalCountdown ) { if (this._bGraphicalCountdown) {
this._graphicalTimer.setStatus((this._cntdownStart - remainingTime) / this._cntdownStart); this._graphicalTimer.setStatus((this._cntdownStart - remainingTime) / this._cntdownStart);
} else { } else {
this._textualTimer.text = Utils.formatTime(remainingTime); this._textualTimer.text = Utils.formatTime(remainingTime);
} }
}, },
_doCountdown : function() { _doCountdown: function () {
let remainingTime = this._getRemainingSec(); let remainingTime = this._getRemainingSec();
if (remainingTime <= 0) { if (remainingTime <= 0) {
// count down finished, switch display again // count down finished, switch display again
this.actor.remove_actor( this._bGraphicalCountdown this.actor.remove_actor(this._bGraphicalCountdown ?
? this._graphicalTimer : this._textualTimer); this._graphicalTimer : this._textualTimer);
this.actor.add_actor(this._logo); this.actor.add_actor(this._logo);
this._playSound(); this._playSound();
if ( !bUseGnome34Workarounds && this._settings.get_boolean(Utils.TEATIME_FULLSCREEN_NOTIFICATION_KEY)) { if (!bUseGnome34Workarounds && this._settings.get_boolean(Utils.TEATIME_FULLSCREEN_NOTIFICATION_KEY)) {
this.dialog = new TeaTimeFullscreenNotification(); this.dialog = new TeaTimeFullscreenNotification();
this.dialog.show(); this.dialog.show();
} else { } else {
this._showNotification(_("Your tea is ready!"), this._showNotification(_("Your tea is ready!"),
_("Drink it, while it is hot!")); _("Drink it, while it is hot!"));
} }
this._idleTimeout = null; this._idleTimeout = null;
return false; return false;
} else { } else {
this._updateTimerDisplay(remainingTime); this._updateTimerDisplay(remainingTime);
return true; // continue timer return true; // continue timer
} }
}, },
_playSound : function() { _playSound: function () {
let bPlayAlarmSound = this._settings.get_boolean(Utils.TEATIME_USE_ALARM_SOUND_KEY); let bPlayAlarmSound = this._settings.get_boolean(Utils.TEATIME_USE_ALARM_SOUND_KEY);
if (bPlayAlarmSound) { if (bPlayAlarmSound) {
Utils.playSound(this._settings.get_string(Utils.TEATIME_ALARM_SOUND_KEY)); Utils.playSound(this._settings.get_string(Utils.TEATIME_ALARM_SOUND_KEY));
} }
}, },
_showPreferences : function() { _showPreferences: function () {
imports.misc.util.spawn(["gnome-shell-extension-prefs", ExtensionUtils.getCurrentExtension().metadata['uuid']]); imports.misc.util.spawn(["gnome-shell-extension-prefs", ExtensionUtils.getCurrentExtension().metadata['uuid']]);
return 0; return 0;
}, },
_onStyleChanged: function(actor) { _onStyleChanged: function (actor) {
let themeNode = actor.get_theme_node(); let themeNode = actor.get_theme_node();
let color = themeNode.get_foreground_color() let color = themeNode.get_foreground_color()
let [bHasPadding, padding] = themeNode.lookup_length("-natural-hpadding", false); let [bHasPadding, padding] = themeNode.lookup_length("-natural-hpadding", false);
this._primaryColor = color; this._primaryColor = color;
this._secondaryColor = new Clutter.Color({ this._secondaryColor = new Clutter.Color({
red: color.red, red: color.red,
green: color.green, green: color.green,
blue: color.blue, blue: color.blue,
alpha: color.alpha*0.3 alpha: color.alpha * 0.3
}); });
this._logo.setPadding(bHasPadding*padding); this._logo.setPadding(bHasPadding * padding);
this._graphicalTimer.setPadding(bHasPadding*padding); this._graphicalTimer.setPadding(bHasPadding * padding);
this._textualTimer.margin_right = bHasPadding*padding; this._textualTimer.margin_right = bHasPadding * padding;
this._textualTimer.margin_left = bHasPadding*padding; this._textualTimer.margin_left = bHasPadding * padding;
this._logo.setColor(this._primaryColor, this._secondaryColor); this._logo.setColor(this._primaryColor, this._secondaryColor);
this._graphicalTimer.setColor(this._primaryColor, this._secondaryColor); this._graphicalTimer.setColor(this._primaryColor, this._secondaryColor);
} }
}); });
function init(metadata) { function init(metadata) {
let theme = imports.gi.Gtk.IconTheme.get_default(); let theme = imports.gi.Gtk.IconTheme.get_default();
theme.append_search_path(metadata.path); theme.append_search_path(metadata.path);
} }
let _TeaTime; let _TeaTime;
function enable() { function enable() {
_TeaTime = new TeaTime(); _TeaTime = new TeaTime();
Main.panel.addToStatusArea('teatime', _TeaTime); Main.panel.addToStatusArea('teatime', _TeaTime);
} }
function disable() { function disable() {
if (_TeaTime._idleTimeout != null) Mainloop.source_remove(_TeaTime._idleTimeout); if (_TeaTime._idleTimeout != null) Mainloop.source_remove(_TeaTime._idleTimeout);
_TeaTime.destroy(); _TeaTime.destroy();
}; };

View File

@ -10,61 +10,64 @@
* If there is a better way for that stuff, please let me know ;) * If there is a better way for that stuff, please let me know ;)
********************************************************************/ ********************************************************************/
const Lang = imports.lang; const Lang = imports.lang;
const St = imports.gi.St; const St = imports.gi.St;
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const ExUt = imports.misc.extensionUtils; const ExUt = imports.misc.extensionUtils;
const Me = ExUt.getCurrentExtension(); const Me = ExUt.getCurrentExtension();
const Utils = Me.imports.utils; const Utils = Me.imports.utils;
const TwoColorIcon = new Lang.Class({ const TwoColorIcon = new Lang.Class({
Name: 'TwoColorIcon', Name: 'TwoColorIcon',
Extends: St.DrawingArea, Extends: St.DrawingArea,
_init : function(size, drawingObject) { _init: function (size, drawingObject) {
this.parent({ reactive : true, style: 'padding: 0px 2px' }); this.parent({
this.set_width(size); reactive: true,
this.set_height(size); style: 'padding: 0px 2px'
});
this.set_width(size);
this.set_height(size);
this._drawingObject = drawingObject; this._drawingObject = drawingObject;
this.connect('repaint', Lang.bind(this, this._drawIcon)); this.connect('repaint', Lang.bind(this, this._drawIcon));
// some fallback color // some fallback color
this._primaryColor = new Clutter.Color({ this._primaryColor = new Clutter.Color({
red: 150, red: 150,
green: 150, green: 150,
blue: 150, blue: 150,
alpha: 255 alpha: 255
}); });
this._secundaryColor = this._primaryColor; this._secundaryColor = this._primaryColor;
this._currentStatus = null; this._currentStatus = null;
}, },
setPadding: function(padding) { setPadding: function (padding) {
this.margin_left = padding; this.margin_left = padding;
this.margin_right = padding; this.margin_right = padding;
}, },
setColor: function(primary, secundary) { setColor: function (primary, secundary) {
this._primaryColor = primary; this._primaryColor = primary;
this._secundaryColor = secundary; this._secundaryColor = secundary;
this.queue_repaint(); this.queue_repaint();
}, },
setStatus: function(newStatus) { setStatus: function (newStatus) {
this._customStatus = newStatus; this._customStatus = newStatus;
this.queue_repaint(); this.queue_repaint();
}, },
_drawIcon: function() { _drawIcon: function () {
let cr = this.get_context(); let cr = this.get_context();
let orWdt = this._drawingObject.width; let orWdt = this._drawingObject.width;
let orHgt = this._drawingObject.height; let orHgt = this._drawingObject.height;
let[width, height] = this.get_surface_size(); let [width, height] = this.get_surface_size();
cr.save(); cr.save();
let object_longest_edge = Math.max(orWdt, orHgt); let object_longest_edge = Math.max(orWdt, orHgt);
let surface_shortest_edge = Math.min(width, height); let surface_shortest_edge = Math.min(width, height);
let scaling = surface_shortest_edge / object_longest_edge; let scaling = surface_shortest_edge / object_longest_edge;
let padding_x = (width - orWdt * scaling)*0.5; let padding_x = (width - orWdt * scaling) * 0.5;
let padding_y = (height - orHgt * scaling)*0.5; let padding_y = (height - orHgt * scaling) * 0.5;
cr.translate(padding_x, padding_y); cr.translate(padding_x, padding_y);
cr.scale(scaling, scaling); cr.scale(scaling, scaling);
@ -77,10 +80,10 @@ const TwoColorIcon = new Lang.Class({
}); });
const TeaPot = { const TeaPot = {
width : 484, width: 484,
height : 295, height: 295,
draw : function(cr, stat, primary, secundary) { draw: function (cr, stat, primary, secundary) {
// draw TeaPot // draw TeaPot
// cairo commands generated from svg2cairo // cairo commands generated from svg2cairo
// https://github.com/akrinke/svg2cairo // https://github.com/akrinke/svg2cairo
@ -121,27 +124,27 @@ const TeaPot = {
const Pie = { const Pie = {
width : 1, width: 1,
height: 1, height: 1,
draw : function(cr, stat, primary, secundary) { draw: function (cr, stat, primary, secundary) {
const pi = Math.PI; const pi = Math.PI;
const r = 0.5; const r = 0.5;
if(stat == null) stat = 0; if (stat == null) stat = 0;
cr.translate(0.5, 0.5); cr.translate(0.5, 0.5);
cr.save(); cr.save();
Utils.setCairoColorFromClutter(cr, secundary); Utils.setCairoColorFromClutter(cr, secundary);
cr.moveTo(0, 0); cr.moveTo(0, 0);
cr.arc(0, 0, r, 3 / 2 * pi + 2 * pi * stat, 3 / 2 * pi + 2 cr.arc(0, 0, r, 3 / 2 * pi + 2 * pi * stat, 3 / 2 * pi + 2 *
* pi); pi);
cr.fill(); cr.fill();
Utils.setCairoColorFromClutter(cr, primary); Utils.setCairoColorFromClutter(cr, primary);
cr.moveTo(0, 0); cr.moveTo(0, 0);
cr.arc(0, 0, r, 3 / 2 * pi, 3 / 2 * pi + 2 * pi * stat); cr.arc(0, 0, r, 3 / 2 * pi, 3 / 2 * pi + 2 * pi * stat);
cr.fill(); cr.fill();
cr.restore(); cr.restore();
} // draw } // draw
}; // Pie }; // Pie

View File

@ -13,275 +13,311 @@ const Lang = imports.lang;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const GObject = imports.gi.GObject; const GObject = imports.gi.GObject;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension(); const Me = ExtensionUtils.getCurrentExtension();
const Utils = Me.imports.utils; const Utils = Me.imports.utils;
const bUseGnome34Workarounds = imports.misc.extensionUtils.versionCheck( ["3.4"], imports.misc.config.PACKAGE_VERSION); const bUseGnome34Workarounds = imports.misc.extensionUtils.versionCheck(["3.4"], imports.misc.config.PACKAGE_VERSION);
Utils.initTranslations(); Utils.initTranslations();
const _ = Gettext.gettext; const _ = Gettext.gettext;
const N_ = function(e) { return e; }; const N_ = function (e) {
return e;
};
const Columns = { const Columns = {
TEA_NAME: 0, TEA_NAME: 0,
STEEP_TIME: 1, STEEP_TIME: 1,
ADJUSTMENT: 2 ADJUSTMENT: 2
} }
const TeaTimePrefsWidget = new Lang.Class({ const TeaTimePrefsWidget = new Lang.Class({
Name : 'TeaTimePrefsWidget', Name: 'TeaTimePrefsWidget',
Extends : Gtk.Grid, Extends: Gtk.Grid,
_init: function() {
this.parent({ orientation: Gtk.Orientation.VERTICAL,
column_homogeneous: false,
vexpand: true,
margin: 5,
row_spacing: 5 });
this._tealist = new Gtk.ListStore(); _init: function () {
this._tealist.set_column_types([ this.parent({
orientation: Gtk.Orientation.VERTICAL,
column_homogeneous: false,
vexpand: true,
margin: 5,
row_spacing: 5
});
this._tealist = new Gtk.ListStore();
this._tealist.set_column_types([
GObject.TYPE_STRING, GObject.TYPE_STRING,
GObject.TYPE_INT, GObject.TYPE_INT,
Gtk.Adjustment Gtk.Adjustment
]); ]);
this.set_column_spacing(3); this.set_column_spacing(3);
this._settings = Utils.getSettings(); this._settings = Utils.getSettings();
this._inhibitUpdate = true; this._inhibitUpdate = true;
this._settings.connect("changed", Lang.bind(this, this._refresh)); this._settings.connect("changed", Lang.bind(this, this._refresh));
this._initWindow(); this._initWindow();
this._inhibitUpdate = false; this._inhibitUpdate = false;
this._refresh(); this._refresh();
this._tealist.connect("row-changed", Lang.bind(this, this._save)); this._tealist.connect("row-changed", Lang.bind(this, this._save));
this._tealist.connect("row-deleted", Lang.bind(this, this._save)); this._tealist.connect("row-deleted", Lang.bind(this, this._save));
}, },
_initWindow: function() { _initWindow: function () {
let curRow = 0; let curRow = 0;
let labelFN = new Gtk.Label({ label: _("Fullscreen Notifications"), let labelFN = new Gtk.Label({
hexpand: true, label: _("Fullscreen Notifications"),
halign: Gtk.Align.START }); hexpand: true,
let labelGC = new Gtk.Label({ label: _("Graphical Countdown"), halign: Gtk.Align.START
hexpand: true, });
halign: Gtk.Align.START }); let labelGC = new Gtk.Label({
label: _("Graphical Countdown"),
hexpand: true,
halign: Gtk.Align.START
});
let labelAS = new Gtk.Label({ label: _("Alarm sound"), let labelAS = new Gtk.Label({
hexpand: true, label: _("Alarm sound"),
halign: Gtk.Align.START }); hexpand: true,
halign: Gtk.Align.START
});
this.fullscreenNotificationSwitch = new Gtk.Switch(); this.fullscreenNotificationSwitch = new Gtk.Switch();
this.fullscreenNotificationSwitch.connect("notify::active", Lang.bind(this, this._saveFullscreenNotifications)); this.fullscreenNotificationSwitch.connect("notify::active", Lang.bind(this, this._saveFullscreenNotifications));
this.graphicalCountdownSwitch = new Gtk.Switch(); this.graphicalCountdownSwitch = new Gtk.Switch();
this.graphicalCountdownSwitch.connect("notify::active", Lang.bind(this, this._saveGraphicalCountdown)); this.graphicalCountdownSwitch.connect("notify::active", Lang.bind(this, this._saveGraphicalCountdown));
// alarm sound file chooser // alarm sound file chooser
this.alarmSoundSwitch = new Gtk.Switch(); this.alarmSoundSwitch = new Gtk.Switch();
this.alarmSoundSwitch.connect("notify::active", Lang.bind(this, this._saveUseAlarm)); this.alarmSoundSwitch.connect("notify::active", Lang.bind(this, this._saveUseAlarm));
this.alarmSoundFile = new Gtk.FileChooserButton ({ this.alarmSoundFile = new Gtk.FileChooserButton({
title: _("Select alarm sound file"), title: _("Select alarm sound file"),
action: Gtk.FileChooserAction.OPEN}); action: Gtk.FileChooserAction.OPEN
this.alarmSoundFileFilter = new Gtk.FileFilter(); });
this.alarmSoundFile.set_filter (this.alarmSoundFileFilter); this.alarmSoundFileFilter = new Gtk.FileFilter();
this.alarmSoundFileFilter.add_mime_type ("audio/*"); this.alarmSoundFile.set_filter(this.alarmSoundFileFilter);
this.alarmSoundFile.connect("selection_changed", Lang.bind(this, this._saveSoundFile)); this.alarmSoundFileFilter.add_mime_type("audio/*");
this.alarmSoundFile.connect("selection_changed", Lang.bind(this, this._saveSoundFile));
if ( !bUseGnome34Workarounds) { if (!bUseGnome34Workarounds) {
// Full screen notifications currently not working on GNOME 3.4, thus don't show the switch // Full screen notifications currently not working on GNOME 3.4, thus don't show the switch
this.attach(labelFN, 0 /*col*/, curRow /*row*/, 2 /*col span*/, 1 /*row span*/); this.attach(labelFN, 0 /*col*/ , curRow /*row*/ , 2 /*col span*/ , 1 /*row span*/ );
this.attach(this.fullscreenNotificationSwitch, 2, curRow, 1, 1); this.attach(this.fullscreenNotificationSwitch, 2, curRow, 1, 1);
curRow += 1; curRow += 1;
} }
this.attach(labelGC, 0 /*col*/, curRow /*row*/, 2 /*col span*/, 1 /*row span*/); this.attach(labelGC, 0 /*col*/ , curRow /*row*/ , 2 /*col span*/ , 1 /*row span*/ );
this.attach(this.graphicalCountdownSwitch, 2, curRow, 1, 1); this.attach(this.graphicalCountdownSwitch, 2, curRow, 1, 1);
curRow += 1; curRow += 1;
this.attach(labelAS, 0 /*col*/, curRow /*row*/, 1 /*col span*/, 1 /*row span*/);
this.attach(this.alarmSoundFile, 1, curRow, 1, 1);
this.attach(this.alarmSoundSwitch, 2, curRow, 1, 1);
curRow += 1;
this.treeview = new Gtk.TreeView({model: this._tealist, expand: true}); this.attach(labelAS, 0 /*col*/ , curRow /*row*/ , 1 /*col span*/ , 1 /*row span*/ );
this.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE); this.attach(this.alarmSoundFile, 1, curRow, 1, 1);
this.attach(this.treeview, 0, curRow, 3, 1); this.attach(this.alarmSoundSwitch, 2, curRow, 1, 1);
curRow += 1; curRow += 1;
let teaname = new Gtk.TreeViewColumn({ title: _("Tea"), expand: true }); this.treeview = new Gtk.TreeView({
let renderer = new Gtk.CellRendererText({ editable: true }); model: this._tealist,
// When the renderer is done editing it's value, we first write expand: true
// the new value to the view's model, i.e. this._tealist. });
// This makes life a little harder due to chaining of callbacks this.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE);
// and the need for this._inhibitUpdate, but it feels a lot cleaner this.attach(this.treeview, 0, curRow, 3, 1);
// when the UI does not know about the config storage backend. curRow += 1;
renderer.connect("edited", Lang.bind(this, function(renderer, pathString, newValue) {
let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString));
this._tealist.set(iter, [Columns.TEA_NAME], [newValue]);
}));
teaname.pack_start(renderer, true);
teaname.add_attribute(renderer, "text", Columns.TEA_NAME);
this.treeview.append_column(teaname);
let steeptime = new Gtk.TreeViewColumn({ title: _("Steep time"), min_width: 150 });
let spinrenderer = new Gtk.CellRendererSpin({ editable: true });
// See comment above.
spinrenderer.connect("edited", Lang.bind(this, function(renderer, pathString, newValue) {
let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString));
this._tealist.set(iter, [Columns.STEEP_TIME], [parseInt(newValue)]);
}));
steeptime.pack_start(spinrenderer, true); let teaname = new Gtk.TreeViewColumn({
steeptime.add_attribute(spinrenderer, "adjustment", Columns.ADJUSTMENT); title: _("Tea"),
steeptime.add_attribute(spinrenderer, "text", Columns.STEEP_TIME); expand: true
this.treeview.append_column(steeptime); });
let renderer = new Gtk.CellRendererText({
editable: true
});
// When the renderer is done editing it's value, we first write
// the new value to the view's model, i.e. this._tealist.
// This makes life a little harder due to chaining of callbacks
// and the need for this._inhibitUpdate, but it feels a lot cleaner
// when the UI does not know about the config storage backend.
renderer.connect("edited", Lang.bind(this, function (renderer, pathString, newValue) {
let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString));
this._tealist.set(iter, [Columns.TEA_NAME], [newValue]);
}));
teaname.pack_start(renderer, true);
teaname.add_attribute(renderer, "text", Columns.TEA_NAME);
this.treeview.append_column(teaname);
let steeptime = new Gtk.TreeViewColumn({
title: _("Steep time"),
min_width: 150
});
let spinrenderer = new Gtk.CellRendererSpin({
editable: true
});
// See comment above.
spinrenderer.connect("edited", Lang.bind(this, function (renderer, pathString, newValue) {
let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString));
this._tealist.set(iter, [Columns.STEEP_TIME], [parseInt(newValue)]);
}));
steeptime.pack_start(spinrenderer, true);
steeptime.add_attribute(spinrenderer, "adjustment", Columns.ADJUSTMENT);
steeptime.add_attribute(spinrenderer, "text", Columns.STEEP_TIME);
this.treeview.append_column(steeptime);
this.toolbar = new Gtk.Toolbar({ icon_size: 1 }); this.toolbar = new Gtk.Toolbar({
this.toolbar.get_style_context().add_class("inline-toolbar"); icon_size: 1
this.attach(this.toolbar, 0 /*col*/, curRow /*row*/, 3 /*col span*/, 1 /*row span*/); });
this.addButton = new Gtk.ToolButton({ icon_name: "list-add-symbolic", use_action_appearance: false }); this.toolbar.get_style_context().add_class("inline-toolbar");
this.addButton.connect("clicked", Lang.bind(this, this._addTea)); this.attach(this.toolbar, 0 /*col*/ , curRow /*row*/ , 3 /*col span*/ , 1 /*row span*/ );
this.toolbar.insert(this.addButton, -1); this.addButton = new Gtk.ToolButton({
this.removeButton = new Gtk.ToolButton({ icon_name: "list-remove-symbolic", use_action_appearance: false }); icon_name: "list-add-symbolic",
this.removeButton.connect("clicked", Lang.bind(this, this._removeSelectedTea)); use_action_appearance: false
this.toolbar.insert(this.removeButton, -1); });
}, this.addButton.connect("clicked", Lang.bind(this, this._addTea));
_refresh: function() { this.toolbar.insert(this.addButton, -1);
// don't update the model if someone else is messing with the backend this.removeButton = new Gtk.ToolButton({
if (this._inhibitUpdate) icon_name: "list-remove-symbolic",
return; use_action_appearance: false
});
this.removeButton.connect("clicked", Lang.bind(this, this._removeSelectedTea));
this.toolbar.insert(this.removeButton, -1);
},
_refresh: function () {
// don't update the model if someone else is messing with the backend
if (this._inhibitUpdate)
return;
this.fullscreenNotificationSwitch.active = this._settings.get_boolean(Utils.TEATIME_FULLSCREEN_NOTIFICATION_KEY) this.fullscreenNotificationSwitch.active = this._settings.get_boolean(Utils.TEATIME_FULLSCREEN_NOTIFICATION_KEY)
this.graphicalCountdownSwitch.active = this._settings.get_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY) this.graphicalCountdownSwitch.active = this._settings.get_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY)
this.alarmSoundSwitch.active = this._settings.get_boolean(Utils.TEATIME_USE_ALARM_SOUND_KEY) this.alarmSoundSwitch.active = this._settings.get_boolean(Utils.TEATIME_USE_ALARM_SOUND_KEY)
let list = this._settings.get_value(Utils.TEATIME_STEEP_TIMES_KEY).unpack(); let list = this._settings.get_value(Utils.TEATIME_STEEP_TIMES_KEY).unpack();
this.alarmSoundFile.set_uri(this._settings.get_string(Utils.TEATIME_ALARM_SOUND_KEY)); this.alarmSoundFile.set_uri(this._settings.get_string(Utils.TEATIME_ALARM_SOUND_KEY));
// stop everyone from reacting to the changes we are about to produce // stop everyone from reacting to the changes we are about to produce
// in the model // in the model
this._inhibitUpdate = true; this._inhibitUpdate = true;
this._tealist.clear(); this._tealist.clear();
for (let teaname in list) { for (let teaname in list) {
let time = list[teaname].get_uint32(); let time = list[teaname].get_uint32();
let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: time }); let adj = new Gtk.Adjustment({
this._tealist.set(this._tealist.append(), lower: 1,
[Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], step_increment: 1,
[teaname, time, adj]); upper: 65535,
} value: time
});
this._tealist.set(this._tealist.append(), [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], [teaname, time, adj]);
}
this._inhibitUpdate = false; this._inhibitUpdate = false;
}, },
_addTea: function() { _addTea: function () {
let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: 1 }); let adj = new Gtk.Adjustment({
let item = this._tealist.append(); lower: 1,
this._tealist.set(item, step_increment: 1,
[Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], upper: 65535,
["", 1, adj]); value: 1
this.treeview.set_cursor(this._tealist.get_path(item), });
this.treeview.get_column(Columns.TEA_NAME), let item = this._tealist.append();
true); this._tealist.set(item, [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], ["", 1, adj]);
}, this.treeview.set_cursor(this._tealist.get_path(item),
_removeSelectedTea: function() { this.treeview.get_column(Columns.TEA_NAME),
let [selection, store] = this.treeview.get_selection().get_selected_rows(); true);
let iters = []; },
for (let i = 0; i < selection.length; ++i) { _removeSelectedTea: function () {
let [isSet, iter] = store.get_iter(selection[i]); let [selection, store] = this.treeview.get_selection().get_selected_rows();
if (isSet) { let iters = [];
iters.push(iter); for (let i = 0; i < selection.length; ++i) {
} let [isSet, iter] = store.get_iter(selection[i]);
} if (isSet) {
// it's ok not to inhibit updates here as remove != change iters.push(iter);
iters.forEach(function(value, index, array) { }
store.remove(value) } }
); // it's ok not to inhibit updates here as remove != change
iters.forEach(function (value, index, array) {
store.remove(value)
});
this.treeview.get_selection().unselect_all(); this.treeview.get_selection().unselect_all();
}, },
_saveFullscreenNotifications: function(sw, data) { _saveFullscreenNotifications: function (sw, data) {
// don't update the backend if someone else is messing with the model // don't update the backend if someone else is messing with the model
if (this._inhibitUpdate) if (this._inhibitUpdate)
return; return;
this._inhibitUpdate = true; this._inhibitUpdate = true;
this._settings.set_boolean(Utils.TEATIME_FULLSCREEN_NOTIFICATION_KEY, this._settings.set_boolean(Utils.TEATIME_FULLSCREEN_NOTIFICATION_KEY,
sw.active); sw.active);
this._inhibitUpdate = false; this._inhibitUpdate = false;
}, },
_saveGraphicalCountdown: function(sw, data) { _saveGraphicalCountdown: function (sw, data) {
// don't update the backend if someone else is messing with the model // don't update the backend if someone else is messing with the model
if (this._inhibitUpdate) if (this._inhibitUpdate)
return; return;
this._inhibitUpdate = true; this._inhibitUpdate = true;
this._settings.set_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY, this._settings.set_boolean(Utils.TEATIME_GRAPHICAL_COUNTDOWN_KEY,
sw.active); sw.active);
this._inhibitUpdate = false; this._inhibitUpdate = false;
}, },
_saveUseAlarm: function(sw, data) { _saveUseAlarm: function (sw, data) {
// don't update the backend if someone else is messing with the model // don't update the backend if someone else is messing with the model
if (this._inhibitUpdate) if (this._inhibitUpdate)
return; return;
this._inhibitUpdate = true; this._inhibitUpdate = true;
this._settings.set_boolean(Utils.TEATIME_USE_ALARM_SOUND_KEY, this._settings.set_boolean(Utils.TEATIME_USE_ALARM_SOUND_KEY,
sw.active); sw.active);
this._inhibitUpdate = false; this._inhibitUpdate = false;
}, },
_saveSoundFile: function(sw, data) { _saveSoundFile: function (sw, data) {
// don't update the backend if someone else is messing with the model // don't update the backend if someone else is messing with the model
if (this._inhibitUpdate) if (this._inhibitUpdate)
return; return;
if (this._settings.get_string(Utils.TEATIME_ALARM_SOUND_KEY) != this.alarmSoundFile.get_uri()) { if (this._settings.get_string(Utils.TEATIME_ALARM_SOUND_KEY) != this.alarmSoundFile.get_uri()) {
this._inhibitUpdate = true; this._inhibitUpdate = true;
let uri=this.alarmSoundFile.get_uri(); let uri = this.alarmSoundFile.get_uri();
Utils.playSound(uri); Utils.playSound(uri);
this._settings.set_string(Utils.TEATIME_ALARM_SOUND_KEY, uri); this._settings.set_string(Utils.TEATIME_ALARM_SOUND_KEY, uri);
this._inhibitUpdate = false; this._inhibitUpdate = false;
} }
}, },
_save: function(store, path_, iter_) { _save: function (store, path_, iter_) {
// don't update the backend if someone else is messing with the model // don't update the backend if someone else is messing with the model
if (this._inhibitUpdate) if (this._inhibitUpdate)
return; return;
let values = []; let values = [];
this._tealist.foreach(function(store, path, iter) { this._tealist.foreach(function (store, path, iter) {
values.push(GLib.Variant.new_dict_entry( values.push(GLib.Variant.new_dict_entry(
GLib.Variant.new_string(store.get_value(iter, Columns.TEA_NAME)), GLib.Variant.new_string(store.get_value(iter, Columns.TEA_NAME)),
GLib.Variant.new_uint32(store.get_value(iter, Columns.STEEP_TIME)))) GLib.Variant.new_uint32(store.get_value(iter, Columns.STEEP_TIME))))
}); });
let settingsValue = GLib.Variant.new_array(GLib.VariantType.new("{su}"), values); let settingsValue = GLib.Variant.new_array(GLib.VariantType.new("{su}"), values);
// all changes have happened through the UI, we can safely
// disable updating it here to avoid an infinite loop
this._inhibitUpdate = true;
this._settings.set_value(Utils.TEATIME_STEEP_TIMES_KEY, settingsValue); // all changes have happened through the UI, we can safely
// disable updating it here to avoid an infinite loop
this._inhibitUpdate = false; this._inhibitUpdate = true;
}
this._settings.set_value(Utils.TEATIME_STEEP_TIMES_KEY, settingsValue);
this._inhibitUpdate = false;
}
}); });
function init() { function init() {}
}
function buildPrefsWidget() { function buildPrefsWidget() {
let widget = new TeaTimePrefsWidget(); let widget = new TeaTimePrefsWidget();
widget.show_all();
return widget;
}
widget.show_all();
return widget;
}

View File

@ -3,13 +3,13 @@
Thomas Liebetraut <thomas@tommie-lie.de> Thomas Liebetraut <thomas@tommie-lie.de>
*/ */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension(); const Me = ExtensionUtils.getCurrentExtension();
const Config = imports.misc.config; const Config = imports.misc.config;
const Gst = imports.gi.Gst; const Gst = imports.gi.Gst;
const TEATIME_STEEP_TIMES_KEY = 'steep-times'; const TEATIME_STEEP_TIMES_KEY = 'steep-times';
const TEATIME_FULLSCREEN_NOTIFICATION_KEY = 'fullscreen-notification'; const TEATIME_FULLSCREEN_NOTIFICATION_KEY = 'fullscreen-notification';
@ -20,105 +20,113 @@ const TEATIME_ALARM_SOUND_KEY = 'alarm-sound-file';
const ENABLE_LOGGING = false; const ENABLE_LOGGING = false;
function debug(text) { function debug(text) {
if (ENABLE_LOGGING) if (ENABLE_LOGGING)
log("**TeaTime >: " + text); log("**TeaTime >: " + text);
} }
function getExtensionLocaleDir() { function getExtensionLocaleDir() {
// check if this extension was built with "make zip-file", and thus // check if this extension was built with "make zip-file", and thus
// has the locale files in a subfolder // has the locale files in a subfolder
// otherwise assume that extension has been installed in the // otherwise assume that extension has been installed in the
// same prefix as gnome-shell // same prefix as gnome-shell
let localLocaleDir = ExtensionUtils.getCurrentExtension().dir.get_child('locale'); let localLocaleDir = ExtensionUtils.getCurrentExtension().dir.get_child('locale');
let selectedDir = (localLocaleDir.query_exists(null)) let selectedDir = (localLocaleDir.query_exists(null)) ?
? localLocaleDir.get_path() localLocaleDir.get_path() :
: Config.LOCALEDIR; Config.LOCALEDIR;
debug("Using locale dir: " + selectedDir); debug("Using locale dir: " + selectedDir);
return selectedDir; return selectedDir;
} }
function initTranslations(domain) { function initTranslations(domain) {
let extension = ExtensionUtils.getCurrentExtension(); let extension = ExtensionUtils.getCurrentExtension();
domain = domain || extension.metadata['gettext-domain']; domain = domain || extension.metadata['gettext-domain'];
Gettext.textdomain(domain); Gettext.textdomain(domain);
Gettext.bindtextdomain(domain, getExtensionLocaleDir()); Gettext.bindtextdomain(domain, getExtensionLocaleDir());
} }
function getSettings(schema) { function getSettings(schema) {
let extension = ExtensionUtils.getCurrentExtension(); let extension = ExtensionUtils.getCurrentExtension();
schema = schema || extension.metadata['settings-schema']; schema = schema || extension.metadata['settings-schema'];
const GioSSS = Gio.SettingsSchemaSource; const GioSSS = Gio.SettingsSchemaSource;
// check if this extension was built with "make zip-file", and thus // check if this extension was built with "make zip-file", and thus
// has the schema files in a subfolder // has the schema files in a subfolder
// otherwise assume that extension has been installed in the // otherwise assume that extension has been installed in the
// same prefix as gnome-shell (and therefore schemas are available // same prefix as gnome-shell (and therefore schemas are available
// in the standard folders) // in the standard folders)
let schemaDir = extension.dir.get_child('schemas'); let schemaDir = extension.dir.get_child('schemas');
let schemaSource; let schemaSource;
if (schemaDir.query_exists(null)) { if (schemaDir.query_exists(null)) {
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(), GioSSS.get_default(),
false); false);
} else { } else {
schemaSource = GioSSS.get_default(); schemaSource = GioSSS.get_default();
} }
let schemaObj = schemaSource.lookup(schema, true); let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj) if (!schemaObj)
throw new Error('Schema ' + schema + ' could not be found for extension ' throw new Error('Schema ' + schema + ' could not be found for extension ' +
+ extension.metadata.uuid + '. Please check your installation.'); extension.metadata.uuid + '. Please check your installation.');
return new Gio.Settings({ settings_schema: schemaObj }); return new Gio.Settings({
settings_schema: schemaObj
});
} }
function formatTime(sec_num) { function formatTime(sec_num) {
/* toLocaleFormat would be nicer, however it doesn't work with /* toLocaleFormat would be nicer, however it doesn't work with
Debian Wheezy and some later gnome versions */ Debian Wheezy and some later gnome versions */
// based on code from // based on code from
// http://stackoverflow.com/questions/6312993/javascript-seconds-to-time-with-format-hhmmss // http://stackoverflow.com/questions/6312993/javascript-seconds-to-time-with-format-hhmmss
let hours = Math.floor(sec_num / 3600); let hours = Math.floor(sec_num / 3600);
let minutes = Math.floor((sec_num - (hours * 3600)) / 60); let minutes = Math.floor((sec_num - (hours * 3600)) / 60);
let seconds = Math.round(sec_num - (hours * 3600) - (minutes * 60)); let seconds = Math.round(sec_num - (hours * 3600) - (minutes * 60));
if (hours < 10) {hours = "0"+hours;} if (hours < 10) {
if (minutes < 10) {minutes = "0"+minutes;} hours = "0" + hours;
if (seconds < 10) {seconds = "0"+seconds;} }
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
return (( hours == "00") ? "" : hours+':') + minutes + ':' + seconds; return ((hours == "00") ? "" : hours + ':') + minutes + ':' + seconds;
} }
function playSound(uri) { function playSound(uri) {
if ( typeof this.player == 'undefined' ) { if (typeof this.player == 'undefined') {
Gst.init(null, 0); Gst.init(null, 0);
this.player = Gst.ElementFactory.make("playbin","player"); this.player = Gst.ElementFactory.make("playbin", "player");
this.playBus = this.player.get_bus(); this.playBus = this.player.get_bus();
this.playBus.add_signal_watch(); this.playBus.add_signal_watch();
this.playBus.connect("message", Lang.bind(this, this.playBus.connect("message", Lang.bind(this,
function(playBus, message) { function (playBus, message) {
if (message != null) { if (message != null) {
// IMPORTANT: to reuse the player, set state to READY // IMPORTANT: to reuse the player, set state to READY
let t = message.type; let t = message.type;
if ( t == Gst.MessageType.EOS || t == Gst.MessageType.ERROR) { if (t == Gst.MessageType.EOS || t == Gst.MessageType.ERROR) {
this.player.set_state(Gst.State.READY); this.player.set_state(Gst.State.READY);
} }
} // message handler } // message handler
})); }));
} // if undefined } // if undefined
this.player.set_property('uri', uri); this.player.set_property('uri', uri);
this.player.set_state(Gst.State.PLAYING); this.player.set_state(Gst.State.PLAYING);
} }
function setCairoColorFromClutter(cr, c) { function setCairoColorFromClutter(cr, c) {
let s=1.0/255; let s = 1.0 / 255;
cr.setSourceRGBA(s*c.red, s*c.green, s*c.blue, s*c.alpha); cr.setSourceRGBA(s * c.red, s * c.green, s * c.blue, s * c.alpha);
} }