mirror of
https://github.com/oleid/gnome-shell-teatime.git
synced 2022-04-29 18:53:50 +00:00
combatiblity for gnome-shell 3.32 (maybe break for earlier versions)
This commit is contained in:
parent
e5a5e61398
commit
e94ef7f5bc
481
src/extension.js
481
src/extension.js
@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop; // timer
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
@ -29,10 +28,8 @@ const N_ = function (e) {
|
||||
|
||||
|
||||
|
||||
const TeaTimeFullscreenNotification = new Lang.Class({
|
||||
Name: 'TeaTimeFullscreenNotification',
|
||||
|
||||
_init: function () {
|
||||
class TeaTimeFullscreenNotification {
|
||||
constructor() {
|
||||
// this spans the whole monitor and contains
|
||||
// the actual layout, which it displays in
|
||||
// the center of itself
|
||||
@ -80,7 +77,7 @@ const TeaTimeFullscreenNotification = new Lang.Class({
|
||||
reactive: true,
|
||||
keep_aspect_ratio: true
|
||||
});
|
||||
this._texture.connect("button-release-event", Lang.bind(this, this.hide));
|
||||
this._texture.connect("button-release-event", this.hide.bind(this));
|
||||
this._layout.add_child(this._texture);
|
||||
|
||||
this._timeline = new Clutter.Timeline({
|
||||
@ -88,7 +85,7 @@ const TeaTimeFullscreenNotification = new Lang.Class({
|
||||
repeat_count: -1,
|
||||
progress_mode: Clutter.AnimationMode.LINEAR
|
||||
});
|
||||
this._timeline.connect("new-frame", Lang.bind(this, this._newFrame));
|
||||
this._timeline.connect("new-frame", this._newFrame.bind(this));
|
||||
|
||||
this._label = new St.Label({
|
||||
text: _("Your tea is ready!"),
|
||||
@ -98,19 +95,19 @@ const TeaTimeFullscreenNotification = new Lang.Class({
|
||||
|
||||
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);
|
||||
},
|
||||
destroy: function () {
|
||||
}
|
||||
destroy() {
|
||||
this.hide();
|
||||
Main.popModal(this._bin);
|
||||
this._bin.destroy();
|
||||
this._lightbox.hide();
|
||||
},
|
||||
_newFrame: function (timeline, msecs, user) {
|
||||
}
|
||||
_newFrame(timeline, msecs, user) {
|
||||
let progress = timeline.get_progress();
|
||||
let idx = Math.round(progress * this._textureFiles.length) % this._textureFiles.length;
|
||||
this._texture.set_from_file(this._textureFiles[idx]);
|
||||
},
|
||||
show: function () {
|
||||
}
|
||||
show() {
|
||||
if (typeof Layout.MonitorConstraint != 'undefined') {
|
||||
this._monitorConstraint.index = global.screen.get_current_monitor()
|
||||
}
|
||||
@ -118,22 +115,19 @@ const TeaTimeFullscreenNotification = new Lang.Class({
|
||||
this._timeline.start();
|
||||
this._lightbox.show();
|
||||
this._bin.show_all();
|
||||
},
|
||||
hide: function () {
|
||||
}
|
||||
hide() {
|
||||
Main.popModal(this._bin);
|
||||
this._bin.hide();
|
||||
this._lightbox.hide();
|
||||
this._timeline.stop();
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
const PopupTeaMenuItem = new Lang.Class({
|
||||
Name: 'PopupTeaMenuItem',
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function (sTeaname, nBrewtime, params) {
|
||||
this.parent(params);
|
||||
class PopupTeaMenuItem extends PopupMenu.PopupBaseMenuItem {
|
||||
constructor(sTeaname, nBrewtime, params) {
|
||||
super(params);
|
||||
|
||||
this.tealabel = new St.Label({
|
||||
text: sTeaname
|
||||
@ -163,259 +157,270 @@ const PopupTeaMenuItem = new Lang.Class({
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var TeaTime = class extends PanelMenu.Button {
|
||||
|
||||
const TeaTime = new Lang.Class({
|
||||
Name: 'TeaTime',
|
||||
Extends: PanelMenu.Button,
|
||||
constructor() {
|
||||
super(null, "TeaTime");
|
||||
|
||||
_init: function () {
|
||||
this.parent(null, "TeaTime");
|
||||
this.myinit = function () {
|
||||
|
||||
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
|
||||
this._textualTimer = new St.Label({
|
||||
text: "",
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.CENTER
|
||||
});
|
||||
this._graphicalTimer = new Icon.TwoColorIcon(24, Icon.Pie);
|
||||
// set timer widget
|
||||
this._textualTimer = new St.Label({
|
||||
text: "",
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.CENTER
|
||||
});
|
||||
this._graphicalTimer = new Icon.TwoColorIcon(24, Icon.Pie);
|
||||
|
||||
this.actor.add_actor(this._logo);
|
||||
this.actor.add_style_class_name('panel-status-button');
|
||||
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
|
||||
this.actor.add_actor(this._logo);
|
||||
this.actor.add_style_class_name('panel-status-button');
|
||||
this.actor.connect('style-changed', this._onStyleChanged.bind(this));
|
||||
|
||||
this._idleTimeout = null;
|
||||
this._idleTimeout = null;
|
||||
|
||||
this._createMenu();
|
||||
},
|
||||
_createMenu: function () {
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this._settings.connect("changed::" + this.config_keys.steep_times,
|
||||
Lang.bind(this, this._updateTeaList));
|
||||
this._settings.connect("changed::" + this.config_keys.graphical_countdown,
|
||||
Lang.bind(this, this._updateCountdownType));
|
||||
this._createMenu();
|
||||
};
|
||||
|
||||
this.teaItemCont = new PopupMenu.PopupMenuSection();
|
||||
this._createMenu = function () {
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this._settings.connect("changed::" + this.config_keys.steep_times,
|
||||
this._updateTeaList.bind(this));
|
||||
this._settings.connect("changed::" + this.config_keys.graphical_countdown,
|
||||
this._updateCountdownType.bind(this));
|
||||
|
||||
/*******************/
|
||||
// maybe one day the PopupImageMenuItem works^^
|
||||
let head = new PopupMenu.PopupMenuSection();
|
||||
let item = new PopupMenu.PopupMenuItem(_("Show settings")); //, 'gtk-preferences');
|
||||
// item._icon.icon_size = 15;
|
||||
item.connect('activate', Lang.bind(this, this._showPreferences));
|
||||
head.addMenuItem(item);
|
||||
this.teaItemCont = new PopupMenu.PopupMenuSection();
|
||||
|
||||
/*******************/
|
||||
let bottom = new PopupMenu.PopupMenuSection();
|
||||
this._customEntry = new St.Entry({
|
||||
style_class: 'teatime-custom-entry',
|
||||
track_hover: true,
|
||||
hint_text: _("min:sec")
|
||||
});
|
||||
this._customEntry.get_clutter_text().set_max_length(10);
|
||||
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;")
|
||||
/*******************/
|
||||
// maybe one day the PopupImageMenuItem works^^
|
||||
let head = new PopupMenu.PopupMenuSection();
|
||||
let item = new PopupMenu.PopupMenuItem(_("Show settings")); //, 'gtk-preferences');
|
||||
// item._icon.icon_size = 15;
|
||||
item.connect('activate', this._showPreferences.bind(this));
|
||||
head.addMenuItem(item);
|
||||
|
||||
/*******************/
|
||||
/*******************/
|
||||
let bottom = new PopupMenu.PopupMenuSection();
|
||||
this._customEntry = new St.Entry({
|
||||
style_class: 'teatime-custom-entry',
|
||||
track_hover: true,
|
||||
hint_text: _("min:sec")
|
||||
});
|
||||
this._customEntry.get_clutter_text().set_max_length(10);
|
||||
this._customEntry.get_clutter_text().connect("key-press-event", this._createCustomTimer.bind(this));
|
||||
bottom.box.add(this._customEntry);
|
||||
bottom.actor.set_style("padding: 0px 18px;")
|
||||
|
||||
this.menu.addMenuItem(head);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addMenuItem(this.teaItemCont);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addMenuItem(bottom);
|
||||
/*******************/
|
||||
|
||||
this._updateTeaList();
|
||||
},
|
||||
_updateTeaList: function (config, output) {
|
||||
// make sure the menu is empty
|
||||
this.teaItemCont.removeAll();
|
||||
this.menu.addMenuItem(head);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addMenuItem(this.teaItemCont);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addMenuItem(bottom);
|
||||
|
||||
// fill with new teas
|
||||
let list = this._settings.get_value(this.config_keys.steep_times).unpack();
|
||||
let menuItem = new PopupTeaMenuItem("Stop Timer", 0);
|
||||
menuItem.connect('activate', Lang.bind(this, function () {
|
||||
this._stopCountdown();
|
||||
}));
|
||||
this.teaItemCont.addMenuItem(menuItem);
|
||||
for (let teaname in list) {
|
||||
let time = list[teaname].get_uint32();
|
||||
this._updateTeaList();
|
||||
};
|
||||
this._updateTeaList = function (config, output) {
|
||||
// make sure the menu is empty
|
||||
this.teaItemCont.removeAll();
|
||||
|
||||
let menuItem = new PopupTeaMenuItem(_(teaname), time);
|
||||
menuItem.connect('activate', Lang.bind(this, function () {
|
||||
this._initCountdown(time);
|
||||
}));
|
||||
// fill with new teas
|
||||
let list = this._settings.get_value(this.config_keys.steep_times).unpack();
|
||||
let menuItem = new PopupTeaMenuItem("Stop Timer", 0);
|
||||
menuItem.connect('activate', function () {
|
||||
this._stopCountdown();
|
||||
}.bind(this));
|
||||
this.teaItemCont.addMenuItem(menuItem);
|
||||
}
|
||||
},
|
||||
_updateCountdownType: function (config, output) {
|
||||
let bWantGraphicalCountdown = this._settings.get_boolean(this.config_keys.graphical_countdown);
|
||||
for (let teaname in list) {
|
||||
let time = list[teaname].get_uint32();
|
||||
|
||||
if (bWantGraphicalCountdown != this._bGraphicalCountdown) {
|
||||
if (this._idleTimeout != null) {
|
||||
// we have a running countdown, replace the display
|
||||
this.actor.remove_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
this._bGraphicalCountdown = bWantGraphicalCountdown;
|
||||
this.actor.add_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
|
||||
this._updateTimerDisplay(this._getRemainingSec());
|
||||
} // if timeout active
|
||||
} // value changed
|
||||
},
|
||||
_createCustomTimer: function (text, event) {
|
||||
if (event.get_key_symbol() == Clutter.KEY_Enter ||
|
||||
event.get_key_symbol() == Clutter.KEY_Return) {
|
||||
|
||||
let customTime = text.get_text();
|
||||
let seconds = 0;
|
||||
let match = customTime.match(/^(?:(\d+)(?::(\d{0,2}))?|:(\d+))$/)
|
||||
if (match) {
|
||||
let factor = 1;
|
||||
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
|
||||
seconds += factor * parseInt(s);
|
||||
factor *= 60;
|
||||
}
|
||||
if (seconds > 0) {
|
||||
this._initCountdown(seconds);
|
||||
this.menu.close();
|
||||
}
|
||||
let menuItem = new PopupTeaMenuItem(_(teaname), time);
|
||||
menuItem.connect('activate', function () {
|
||||
this._initCountdown(time);
|
||||
}.bind(this));
|
||||
this.teaItemCont.addMenuItem(menuItem);
|
||||
}
|
||||
this._customEntry.set_text("");
|
||||
}
|
||||
},
|
||||
_showNotification: function (subject, text) {
|
||||
let source = (Utils.isGnome34()) ?
|
||||
new MessageTray.Source(_("TeaTime applet")) :
|
||||
new MessageTray.Source(_("TeaTime applet"), 'utilities-teatime');
|
||||
};
|
||||
this._updateCountdownType = function (config, output) {
|
||||
let bWantGraphicalCountdown = this._settings.get_boolean(this.config_keys.graphical_countdown);
|
||||
|
||||
if (Utils.isGnome34()) {
|
||||
source.createNotificationIcon =
|
||||
function () {
|
||||
let iconBox = new St.Bin();
|
||||
iconBox._size = this.ICON_SIZE;
|
||||
iconBox.child = new St.Icon({
|
||||
icon_name: 'utilities-teatime',
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: iconBox._size
|
||||
});
|
||||
return iconBox;
|
||||
} // createNotificationIcon
|
||||
}
|
||||
if (bWantGraphicalCountdown != this._bGraphicalCountdown) {
|
||||
if (this._idleTimeout != null) {
|
||||
// we have a running countdown, replace the display
|
||||
this.actor.remove_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
this._bGraphicalCountdown = bWantGraphicalCountdown;
|
||||
this.actor.add_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
|
||||
Main.messageTray.add(source);
|
||||
this._updateTimerDisplay(this._getRemainingSec());
|
||||
} // if timeout active
|
||||
} // value changed
|
||||
};
|
||||
this._createCustomTimer = function (text, event) {
|
||||
if (event.get_key_symbol() == Clutter.KEY_Enter ||
|
||||
event.get_key_symbol() == Clutter.KEY_Return ||
|
||||
event.get_key_symbol() == Clutter.KEY_KP_Enter) {
|
||||
|
||||
let notification = new MessageTray.Notification(source, subject, text);
|
||||
notification.setTransient(true);
|
||||
source.notify(notification);
|
||||
},
|
||||
_initCountdown: function (time) {
|
||||
this._startTime = new Date();
|
||||
this._stopTime = new Date();
|
||||
this._cntdownStart = time;
|
||||
let customTime = text.get_text();
|
||||
let seconds = 0;
|
||||
let match = customTime.match(/^(?:(\d+)(?::(\d{0,2}))?|:(\d+))$/)
|
||||
if (match) {
|
||||
let factor = 1;
|
||||
if (match[3] === undefined) { // minutes and seconds?
|
||||
for (var i = match.length - 2; i > 0; i--) {
|
||||
let s = match[i] === undefined ? "" : match[i].replace(/^0/, ''); // fix for elder GNOME <= 3.10 which don't like leading zeros
|
||||
if (s.match(/^\d+$/)) { // only if something left
|
||||
seconds += factor * parseInt(s);
|
||||
}
|
||||
factor *= 60;
|
||||
}
|
||||
} else { // only seconds?
|
||||
let s = match[3].replace(/^0/, '');
|
||||
seconds = parseInt(s);
|
||||
}
|
||||
if (seconds > 0) {
|
||||
this._initCountdown(seconds);
|
||||
this.menu.close();
|
||||
}
|
||||
}
|
||||
this._customEntry.set_text("");
|
||||
}
|
||||
};
|
||||
this._showNotification = function (subject, text) {
|
||||
let source = (Utils.isGnome34()) ?
|
||||
new MessageTray.Source(_("TeaTime applet")) :
|
||||
new MessageTray.Source(_("TeaTime applet"), 'utilities-teatime');
|
||||
|
||||
this._bGraphicalCountdown = this._settings.get_boolean(this.config_keys.graphical_countdown);
|
||||
if (Utils.isGnome34()) {
|
||||
source.createNotificationIcon =
|
||||
function () {
|
||||
let iconBox = new St.Bin();
|
||||
iconBox._size = this.ICON_SIZE;
|
||||
iconBox.child = new St.Icon({
|
||||
icon_name: 'utilities-teatime',
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: iconBox._size
|
||||
});
|
||||
return iconBox;
|
||||
} // createNotificationIcon
|
||||
}
|
||||
|
||||
let dt = this._bGraphicalCountdown ?
|
||||
Math.max(1.0, time / 90) // set time step to fit animation
|
||||
:
|
||||
1.0; // show every second for the textual countdown
|
||||
Main.messageTray.add(source);
|
||||
|
||||
this._stopTime.setTime(this._startTime.getTime() + time * 1000); // in msec
|
||||
let notification = new MessageTray.Notification(source, subject, text);
|
||||
notification.setTransient(true);
|
||||
source.notify(notification);
|
||||
};
|
||||
this._initCountdown = function (time) {
|
||||
this._startTime = new Date();
|
||||
this._stopTime = new Date();
|
||||
this._cntdownStart = time;
|
||||
|
||||
this.actor.remove_actor(this._logo); // show timer instead of default icon
|
||||
this._bGraphicalCountdown = this._settings.get_boolean(this.config_keys.graphical_countdown);
|
||||
|
||||
this._updateTimerDisplay(time);
|
||||
let dt = this._bGraphicalCountdown ?
|
||||
Math.max(1.0, time / 90) // set time step to fit animation
|
||||
:
|
||||
1.0; // show every second for the textual countdown
|
||||
|
||||
this.actor.add_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
this._stopTime.setTime(this._startTime.getTime() + time * 1000); // in msec
|
||||
|
||||
if (this._idleTimeout != null) Mainloop.source_remove(this._idleTimeout);
|
||||
this._idleTimeout = Mainloop.timeout_add_seconds(dt, Lang.bind(this, this._doCountdown));
|
||||
},
|
||||
_stopCountdown: function () {
|
||||
if (this._idleTimeout != null) Mainloop.source_remove(this._idleTimeout);
|
||||
this.actor.remove_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
this.actor.add_actor(this._logo);
|
||||
this._idleTimeout = null;
|
||||
},
|
||||
_getRemainingSec: function () {
|
||||
let a = new Date();
|
||||
return (this._stopTime.getTime() - a.getTime()) * 1e-3;
|
||||
},
|
||||
_updateTimerDisplay: function (remainingTime) {
|
||||
if (this._bGraphicalCountdown) {
|
||||
this._graphicalTimer.setStatus((this._cntdownStart - remainingTime) / this._cntdownStart);
|
||||
} else {
|
||||
this._textualTimer.text = Utils.formatTime(remainingTime);
|
||||
}
|
||||
},
|
||||
_doCountdown: function () {
|
||||
let remainingTime = this._getRemainingSec();
|
||||
this.actor.remove_actor(this._logo); // show timer instead of default icon
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
// count down finished, switch display again
|
||||
this._stopCountdown();
|
||||
this._playSound();
|
||||
this._updateTimerDisplay(time);
|
||||
|
||||
if (!Utils.isGnome34() && this._settings.get_boolean(this.config_keys.fullscreen_notification)) {
|
||||
this.dialog = new TeaTimeFullscreenNotification();
|
||||
this.dialog.show();
|
||||
this.actor.add_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
|
||||
if (this._idleTimeout != null) Mainloop.source_remove(this._idleTimeout);
|
||||
this._idleTimeout = Mainloop.timeout_add_seconds(dt, this._doCountdown.bind(this));
|
||||
};
|
||||
this._stopCountdown = function () {
|
||||
if (this._idleTimeout != null) Mainloop.source_remove(this._idleTimeout);
|
||||
this.actor.remove_actor(this._bGraphicalCountdown ?
|
||||
this._graphicalTimer : this._textualTimer);
|
||||
this.actor.add_actor(this._logo);
|
||||
this._idleTimeout = null;
|
||||
};
|
||||
this._getRemainingSec = function () {
|
||||
let a = new Date();
|
||||
return (this._stopTime.getTime() - a.getTime()) * 1e-3;
|
||||
};
|
||||
this._updateTimerDisplay = function (remainingTime) {
|
||||
if (this._bGraphicalCountdown) {
|
||||
this._graphicalTimer.setStatus((this._cntdownStart - remainingTime) / this._cntdownStart);
|
||||
} else {
|
||||
this._showNotification(_("Your tea is ready!"),
|
||||
_("Drink it, while it is hot!"));
|
||||
this._textualTimer.text = Utils.formatTime(remainingTime);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
this._updateTimerDisplay(remainingTime);
|
||||
return true; // continue timer
|
||||
}
|
||||
},
|
||||
_playSound: function () {
|
||||
let bPlayAlarmSound = this._settings.get_boolean(this.config_keys.use_alarm_sound);
|
||||
if (bPlayAlarmSound) {
|
||||
Utils.playSound(this._settings.get_string(this.config_keys.alarm_sound));
|
||||
}
|
||||
},
|
||||
_showPreferences: function () {
|
||||
imports.misc.util.spawn(["gnome-shell-extension-prefs", ExtensionUtils.getCurrentExtension().metadata['uuid']]);
|
||||
return 0;
|
||||
},
|
||||
_onStyleChanged: function (actor) {
|
||||
let themeNode = actor.get_theme_node();
|
||||
let color = themeNode.get_foreground_color()
|
||||
let [bHasPadding, padding] = themeNode.lookup_length("-natural-hpadding", false);
|
||||
};
|
||||
this._doCountdown = function () {
|
||||
let remainingTime = this._getRemainingSec();
|
||||
|
||||
this._primaryColor = color;
|
||||
this._secondaryColor = new Clutter.Color({
|
||||
red: color.red,
|
||||
green: color.green,
|
||||
blue: color.blue,
|
||||
alpha: color.alpha * 0.3
|
||||
});
|
||||
this._logo.setPadding(bHasPadding * padding);
|
||||
this._graphicalTimer.setPadding(bHasPadding * padding);
|
||||
this._textualTimer.margin_right = bHasPadding * padding;
|
||||
this._textualTimer.margin_left = bHasPadding * padding;
|
||||
if (remainingTime <= 0) {
|
||||
// count down finished, switch display again
|
||||
this._stopCountdown();
|
||||
this._playSound();
|
||||
|
||||
this._logo.setColor(this._primaryColor, this._secondaryColor);
|
||||
this._graphicalTimer.setColor(this._primaryColor, this._secondaryColor);
|
||||
if (!Utils.isGnome34() && this._settings.get_boolean(this.config_keys.fullscreen_notification)) {
|
||||
this.dialog = new TeaTimeFullscreenNotification();
|
||||
this.dialog.show();
|
||||
} else {
|
||||
this._showNotification(_("Your tea is ready!"),
|
||||
_("Drink it, while it is hot!"));
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
this._updateTimerDisplay(remainingTime);
|
||||
return true; // continue timer
|
||||
}
|
||||
};
|
||||
this._playSound = function () {
|
||||
let bPlayAlarmSound = this._settings.get_boolean(this.config_keys.use_alarm_sound);
|
||||
if (bPlayAlarmSound) {
|
||||
Utils.playSound(this._settings.get_string(this.config_keys.alarm_sound));
|
||||
}
|
||||
};
|
||||
this._showPreferences = function () {
|
||||
const currExt = ExtensionUtils.getCurrentExtension();
|
||||
imports.misc.util.spawn(["gnome-shell-extension-prefs", currExt.metadata['uuid']]);
|
||||
return 0;
|
||||
};
|
||||
this._onStyleChanged = function (actor) {
|
||||
let themeNode = actor.get_theme_node();
|
||||
let color = themeNode.get_foreground_color()
|
||||
let [bHasPadding, padding] = themeNode.lookup_length("-natural-hpadding", false);
|
||||
|
||||
// forward (possible) scaling style change to child
|
||||
let scaling = Utils.getGlobalDisplayScaleFactor();
|
||||
this._logo.setScaling(scaling);
|
||||
this._graphicalTimer.setScaling(scaling);
|
||||
},
|
||||
config_keys: Utils.GetConfigKeys()
|
||||
});
|
||||
this._primaryColor = color;
|
||||
this._secondaryColor = new Clutter.Color({
|
||||
red: color.red,
|
||||
green: color.green,
|
||||
blue: color.blue,
|
||||
alpha: color.alpha * 0.3
|
||||
});
|
||||
this._logo.setPadding(bHasPadding * padding);
|
||||
this._graphicalTimer.setPadding(bHasPadding * padding);
|
||||
this._textualTimer.margin_right = bHasPadding * padding;
|
||||
this._textualTimer.margin_left = bHasPadding * padding;
|
||||
|
||||
this._logo.setColor(this._primaryColor, this._secondaryColor);
|
||||
this._graphicalTimer.setColor(this._primaryColor, this._secondaryColor);
|
||||
|
||||
// forward (possible) scaling style change to child
|
||||
let scaling = Utils.getGlobalDisplayScaleFactor();
|
||||
this._logo.setScaling(scaling);
|
||||
this._graphicalTimer.setScaling(scaling);
|
||||
};
|
||||
this.config_keys = Utils.GetConfigKeys();
|
||||
this.myinit();
|
||||
}
|
||||
};
|
||||
|
||||
function init(metadata) {
|
||||
let theme = imports.gi.Gtk.IconTheme.get_default();
|
||||
|
122
src/icon.js
122
src/icon.js
@ -10,86 +10,90 @@
|
||||
* If there is a better way for that stuff, please let me know ;)
|
||||
********************************************************************/
|
||||
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const ExUt = imports.misc.extensionUtils;
|
||||
const Me = ExUt.getCurrentExtension();
|
||||
const Utils = Me.imports.utils;
|
||||
|
||||
var TwoColorIcon = new Lang.Class({
|
||||
Name: 'TwoColorIcon',
|
||||
Extends: St.DrawingArea,
|
||||
|
||||
_init: function (size, drawingObject) {
|
||||
this.parent({
|
||||
var TwoColorIcon = class extends St.DrawingArea {
|
||||
constructor(size, drawingObject) {
|
||||
super({
|
||||
reactive: true,
|
||||
style: 'padding: 0px 2px'
|
||||
});
|
||||
this._base_size = size;
|
||||
this.setScaling(Utils.getGlobalDisplayScaleFactor());
|
||||
this.myinit = function () {
|
||||
this._base_size = size;
|
||||
//this.setScaling(Utils.getGlobalDisplayScaleFactor());
|
||||
|
||||
this._drawingObject = drawingObject;
|
||||
this._drawingObject = drawingObject;
|
||||
|
||||
this.connect('repaint', Lang.bind(this, this._drawIcon));
|
||||
this.connect('repaint', function () {
|
||||
this._drawIcon();
|
||||
}.bind(this));
|
||||
|
||||
// some fallback color
|
||||
this._primaryColor = new Clutter.Color({
|
||||
red: 150,
|
||||
green: 150,
|
||||
blue: 150,
|
||||
alpha: 255
|
||||
});
|
||||
this._secundaryColor = this._primaryColor;
|
||||
this._customStatus = null;
|
||||
},
|
||||
setPadding: function (padding) {
|
||||
this.margin_left = padding;
|
||||
this.margin_right = padding;
|
||||
},
|
||||
setColor: function (primary, secundary) {
|
||||
this._primaryColor = primary;
|
||||
this._secundaryColor = secundary;
|
||||
this.queue_repaint();
|
||||
},
|
||||
setScaling: function (newScale) {
|
||||
this._default_scale = newScale;
|
||||
this.set_width(this._base_size * this._default_scale);
|
||||
this.set_height(this._base_size * this._default_scale);
|
||||
this.queue_repaint();
|
||||
},
|
||||
setStatus: function (newStatus) {
|
||||
this._customStatus = newStatus;
|
||||
this.queue_repaint();
|
||||
},
|
||||
_drawIcon: function () {
|
||||
let cr = this.get_context();
|
||||
let orWdt = this._drawingObject.width;
|
||||
let orHgt = this._drawingObject.height;
|
||||
let [width, height] = this.get_surface_size();
|
||||
// some fallback color
|
||||
this._primaryColor = new Clutter.Color({
|
||||
red: 150,
|
||||
green: 150,
|
||||
blue: 150,
|
||||
alpha: 255
|
||||
});
|
||||
this._secundaryColor = this._primaryColor;
|
||||
this._customStatus = null;
|
||||
};
|
||||
this.setPadding = function (padding) {
|
||||
this.margin_left = padding;
|
||||
this.margin_right = padding;
|
||||
};
|
||||
this.setColor = function (primary, secundary) {
|
||||
this._primaryColor = primary;
|
||||
this._secundaryColor = secundary;
|
||||
this.queue_repaint();
|
||||
};
|
||||
this.setScaling = function (newScale) {
|
||||
this._default_scale = newScale;
|
||||
this.set_width(this._base_size * this._default_scale);
|
||||
this.set_height(this._base_size * this._default_scale);
|
||||
this.queue_repaint();
|
||||
};
|
||||
this.setStatus = function (newStatus) {
|
||||
this._customStatus = newStatus;
|
||||
this.queue_repaint();
|
||||
};
|
||||
this._drawIcon = function () {
|
||||
let cr = this.get_context();
|
||||
let orWdt = this._drawingObject.width;
|
||||
let orHgt = this._drawingObject.height;
|
||||
let [width, height] = this.get_surface_size();
|
||||
|
||||
cr.save();
|
||||
cr.save();
|
||||
|
||||
let object_longest_edge = Math.max(orWdt, orHgt);
|
||||
let surface_shortest_edge = Math.min(width, height);
|
||||
let scaling = surface_shortest_edge / object_longest_edge;
|
||||
let padding_x = (width - orWdt * scaling) * 0.5;
|
||||
let padding_y = (height - orHgt * scaling) * 0.5;
|
||||
let object_longest_edge = Math.max(orWdt, orHgt);
|
||||
let surface_shortest_edge = Math.min(width, height);
|
||||
let scaling = surface_shortest_edge / object_longest_edge;
|
||||
let padding_x = (width - orWdt * scaling) * 0.5;
|
||||
let padding_y = (height - orHgt * scaling) * 0.5;
|
||||
|
||||
cr.translate(padding_x, padding_y);
|
||||
cr.scale(scaling, scaling);
|
||||
cr.translate(padding_x, padding_y);
|
||||
try {
|
||||
cr.scale(scaling, scaling);
|
||||
|
||||
this._drawingObject.draw(cr, this._customStatus, this._primaryColor, this._secundaryColor);
|
||||
this._drawingObject.draw(cr, this._customStatus, this._primaryColor, this._secundaryColor);
|
||||
|
||||
cr.restore();
|
||||
cr.restore();
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
this.myinit();
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
var TeaPot = {
|
||||
width: 484,
|
||||
height: 295,
|
||||
draw: function (cr, stat, primary, secundary) {
|
||||
draw(cr, stat, primary, secundary) {
|
||||
// draw TeaPot
|
||||
// cairo commands generated from svg2cairo
|
||||
// https://github.com/akrinke/svg2cairo
|
||||
@ -133,7 +137,7 @@ var TeaPot = {
|
||||
var Pie = {
|
||||
width: 1,
|
||||
height: 1,
|
||||
draw: function (cr, stat, primary, secundary) {
|
||||
draw(cr, stat, primary, secundary) {
|
||||
const pi = Math.PI;
|
||||
const r = 0.5;
|
||||
|
||||
|
@ -1 +1 @@
|
||||
{"shell-version": ["3.4", "3.6", "3.8", "3.10", "3.12", "3.14", "3.16", "3.18", "3.20", "3.22", "3.24", "3.26"], "uuid": "TeaTime@oleid.mescharet.de", "name": "TeaTime", "settings-schema": "org.gnome.shell.extensions.teatime", "gettext-domain": "TeaTime", "description": "A tea steeping timer"}
|
||||
{"shell-version": ["3.32"], "uuid": "TeaTime@oleid.mescharet.de", "name": "TeaTime", "settings-schema": "org.gnome.shell.extensions.teatime", "gettext-domain": "TeaTime", "description": "A tea steeping timer"}
|
||||
|
487
src/prefs.js
487
src/prefs.js
@ -3,7 +3,6 @@
|
||||
Thomas Liebetraut <thomas@tommie-lie.de>
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
@ -23,12 +22,9 @@ const Columns = {
|
||||
ADJUSTMENT: 2
|
||||
}
|
||||
|
||||
const TeaTimePrefsWidget = new Lang.Class({
|
||||
Name: 'TeaTimePrefsWidget',
|
||||
Extends: Gtk.Grid,
|
||||
|
||||
_init: function () {
|
||||
this.parent({
|
||||
var TeaTimePrefsWidget = class extends Gtk.Grid {
|
||||
constructor() {
|
||||
super({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
column_homogeneous: false,
|
||||
vexpand: true,
|
||||
@ -36,278 +32,281 @@ const TeaTimePrefsWidget = new Lang.Class({
|
||||
row_spacing: 5
|
||||
});
|
||||
|
||||
this._tealist = new Gtk.ListStore();
|
||||
this._tealist.set_column_types([
|
||||
GObject.TYPE_STRING,
|
||||
GObject.TYPE_INT,
|
||||
Gtk.Adjustment
|
||||
]);
|
||||
this.myinit = function () {
|
||||
this._tealist = new Gtk.ListStore();
|
||||
this._tealist.set_column_types([
|
||||
GObject.TYPE_STRING,
|
||||
GObject.TYPE_INT,
|
||||
Gtk.Adjustment
|
||||
]);
|
||||
|
||||
this.set_column_spacing(3);
|
||||
this.set_column_spacing(3);
|
||||
|
||||
this._settings = Utils.getSettings();
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.connect("changed", Lang.bind(this, this._refresh));
|
||||
this._settings = Utils.getSettings();
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.connect("changed", this._refresh.bind(this));
|
||||
|
||||
this._initWindow();
|
||||
this._inhibitUpdate = false;
|
||||
this._refresh();
|
||||
this._tealist.connect("row-changed", Lang.bind(this, this._save));
|
||||
this._tealist.connect("row-deleted", Lang.bind(this, this._save));
|
||||
},
|
||||
_initWindow: function () {
|
||||
let curRow = 0;
|
||||
let labelFN = new Gtk.Label({
|
||||
label: _("Fullscreen Notifications"),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START
|
||||
});
|
||||
let labelGC = new Gtk.Label({
|
||||
label: _("Graphical Countdown"),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START
|
||||
});
|
||||
this._initWindow();
|
||||
this._inhibitUpdate = false;
|
||||
this._refresh();
|
||||
this._tealist.connect("row-changed", this._save.bind(this));
|
||||
this._tealist.connect("row-deleted", this._save.bind(this));
|
||||
};
|
||||
this._initWindow = function () {
|
||||
let curRow = 0;
|
||||
let labelFN = new Gtk.Label({
|
||||
label: _("Fullscreen Notifications"),
|
||||
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"),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START
|
||||
});
|
||||
let labelAS = new Gtk.Label({
|
||||
label: _("Alarm sound"),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START
|
||||
});
|
||||
|
||||
this.fullscreenNotificationSwitch = new Gtk.Switch();
|
||||
this.fullscreenNotificationSwitch.connect("notify::active", Lang.bind(this, this._saveFullscreenNotifications));
|
||||
this.fullscreenNotificationSwitch = new Gtk.Switch();
|
||||
this.fullscreenNotificationSwitch.connect("notify::active", this._saveFullscreenNotifications.bind(this));
|
||||
|
||||
this.graphicalCountdownSwitch = new Gtk.Switch();
|
||||
this.graphicalCountdownSwitch.connect("notify::active", Lang.bind(this, this._saveGraphicalCountdown));
|
||||
this.graphicalCountdownSwitch = new Gtk.Switch();
|
||||
this.graphicalCountdownSwitch.connect("notify::active", this._saveGraphicalCountdown.bind(this));
|
||||
|
||||
// alarm sound file chooser
|
||||
this.alarmSoundSwitch = new Gtk.Switch();
|
||||
this.alarmSoundSwitch.connect("notify::active", Lang.bind(this, this._saveUseAlarm));
|
||||
// alarm sound file chooser
|
||||
this.alarmSoundSwitch = new Gtk.Switch();
|
||||
this.alarmSoundSwitch.connect("notify::active", this._saveUseAlarm.bind(this));
|
||||
|
||||
|
||||
this.alarmSoundFile = new Gtk.FileChooserButton({
|
||||
title: _("Select alarm sound file"),
|
||||
action: Gtk.FileChooserAction.OPEN
|
||||
});
|
||||
this.alarmSoundFileFilter = new Gtk.FileFilter();
|
||||
this.alarmSoundFile.set_filter(this.alarmSoundFileFilter);
|
||||
this.alarmSoundFileFilter.add_mime_type("audio/*");
|
||||
this.alarmSoundFile.connect("selection_changed", Lang.bind(this, this._saveSoundFile));
|
||||
this.alarmSoundFile = new Gtk.FileChooserButton({
|
||||
title: _("Select alarm sound file"),
|
||||
action: Gtk.FileChooserAction.OPEN
|
||||
});
|
||||
this.alarmSoundFileFilter = new Gtk.FileFilter();
|
||||
this.alarmSoundFile.set_filter(this.alarmSoundFileFilter);
|
||||
this.alarmSoundFileFilter.add_mime_type("audio/*");
|
||||
this.alarmSoundFile.connect("selection_changed", this._saveSoundFile.bind(this));
|
||||
|
||||
|
||||
if (!Utils.isGnome34()) {
|
||||
// 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(this.fullscreenNotificationSwitch, 2, curRow, 1, 1);
|
||||
if (!Utils.isGnome34()) {
|
||||
// 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(this.fullscreenNotificationSwitch, 2, curRow, 1, 1);
|
||||
curRow += 1;
|
||||
}
|
||||
|
||||
this.attach(labelGC, 0 /*col*/ , curRow /*row*/ , 2 /*col span*/ , 1 /*row span*/ );
|
||||
this.attach(this.graphicalCountdownSwitch, 2, curRow, 1, 1);
|
||||
curRow += 1;
|
||||
}
|
||||
|
||||
this.attach(labelGC, 0 /*col*/ , curRow /*row*/ , 2 /*col span*/ , 1 /*row span*/ );
|
||||
this.attach(this.graphicalCountdownSwitch, 2, curRow, 1, 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.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.treeview.set_reorderable(true);
|
||||
this.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE);
|
||||
this.attach(this.treeview, 0, curRow, 3, 1);
|
||||
curRow += 1;
|
||||
|
||||
this.treeview = new Gtk.TreeView({
|
||||
model: this._tealist,
|
||||
expand: true
|
||||
});
|
||||
this.treeview.set_reorderable(true);
|
||||
this.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE);
|
||||
this.attach(this.treeview, 0, curRow, 3, 1);
|
||||
curRow += 1;
|
||||
let teaname = new Gtk.TreeViewColumn({
|
||||
title: _("Tea"),
|
||||
expand: true
|
||||
});
|
||||
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", 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]);
|
||||
}.bind(this));
|
||||
teaname.pack_start(renderer, true);
|
||||
teaname.add_attribute(renderer, "text", Columns.TEA_NAME);
|
||||
this.treeview.append_column(teaname);
|
||||
|
||||
let teaname = new Gtk.TreeViewColumn({
|
||||
title: _("Tea"),
|
||||
expand: true
|
||||
});
|
||||
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", 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)]);
|
||||
}.bind(this));
|
||||
|
||||
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);
|
||||
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.get_style_context().add_class("inline-toolbar");
|
||||
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.addButton.connect("clicked", Lang.bind(this, this._addTea));
|
||||
this.toolbar.insert(this.addButton, -1);
|
||||
this.removeButton = new Gtk.ToolButton({
|
||||
icon_name: "list-remove-symbolic",
|
||||
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.toolbar = new Gtk.Toolbar({
|
||||
icon_size: 1
|
||||
});
|
||||
this.toolbar.get_style_context().add_class("inline-toolbar");
|
||||
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.addButton.connect("clicked", this._addTea.bind(this));
|
||||
this.toolbar.insert(this.addButton, -1);
|
||||
this.removeButton = new Gtk.ToolButton({
|
||||
icon_name: "list-remove-symbolic",
|
||||
use_action_appearance: false
|
||||
});
|
||||
this.removeButton.connect("clicked", this._removeSelectedTea.bind(this));
|
||||
this.toolbar.insert(this.removeButton, -1);
|
||||
};
|
||||
this._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(this.config_keys.fullscreen_notification)
|
||||
this.fullscreenNotificationSwitch.active = this._settings.get_boolean(this.config_keys.fullscreen_notification)
|
||||
|
||||
this.graphicalCountdownSwitch.active = this._settings.get_boolean(this.config_keys.graphical_countdown)
|
||||
this.alarmSoundSwitch.active = this._settings.get_boolean(this.config_keys.use_alarm_sound)
|
||||
let list = this._settings.get_value(this.config_keys.steep_times).unpack();
|
||||
let file_name = this._settings.get_string(this.config_keys.alarm_sound);
|
||||
this.alarmSoundFile.set_uri(file_name);
|
||||
this.graphicalCountdownSwitch.active = this._settings.get_boolean(this.config_keys.graphical_countdown)
|
||||
this.alarmSoundSwitch.active = this._settings.get_boolean(this.config_keys.use_alarm_sound)
|
||||
let list = this._settings.get_value(this.config_keys.steep_times).unpack();
|
||||
let file_name = this._settings.get_string(this.config_keys.alarm_sound);
|
||||
this.alarmSoundFile.set_uri(file_name);
|
||||
|
||||
// stop everyone from reacting to the changes we are about to produce
|
||||
// in the model
|
||||
this._inhibitUpdate = true;
|
||||
// stop everyone from reacting to the changes we are about to produce
|
||||
// in the model
|
||||
this._inhibitUpdate = true;
|
||||
|
||||
this._tealist.clear();
|
||||
for (let teaname in list) {
|
||||
let time = list[teaname].get_uint32();
|
||||
this._tealist.clear();
|
||||
for (let teaname in list) {
|
||||
let time = list[teaname].get_uint32();
|
||||
|
||||
let adj = new Gtk.Adjustment({
|
||||
lower: 1,
|
||||
step_increment: 1,
|
||||
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._addTea = function () {
|
||||
let adj = new Gtk.Adjustment({
|
||||
lower: 1,
|
||||
step_increment: 1,
|
||||
upper: 65535,
|
||||
value: time
|
||||
value: 1
|
||||
});
|
||||
this._tealist.set(this._tealist.append(), [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], [teaname, time, adj]);
|
||||
}
|
||||
|
||||
this._inhibitUpdate = false;
|
||||
},
|
||||
_addTea: function () {
|
||||
let adj = new Gtk.Adjustment({
|
||||
lower: 1,
|
||||
step_increment: 1,
|
||||
upper: 65535,
|
||||
value: 1
|
||||
});
|
||||
let item = this._tealist.append();
|
||||
this._tealist.set(item, [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], ["", 1, adj]);
|
||||
this.treeview.set_cursor(this._tealist.get_path(item),
|
||||
this.treeview.get_column(Columns.TEA_NAME),
|
||||
true);
|
||||
},
|
||||
_removeSelectedTea: function () {
|
||||
let [selection, store] = this.treeview.get_selection().get_selected_rows();
|
||||
let iters = [];
|
||||
for (let i = 0; i < selection.length; ++i) {
|
||||
let [isSet, iter] = store.get_iter(selection[i]);
|
||||
if (isSet) {
|
||||
iters.push(iter);
|
||||
let item = this._tealist.append();
|
||||
this._tealist.set(item, [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], ["", 1, adj]);
|
||||
this.treeview.set_cursor(this._tealist.get_path(item),
|
||||
this.treeview.get_column(Columns.TEA_NAME),
|
||||
true);
|
||||
};
|
||||
this._removeSelectedTea = function () {
|
||||
let [selection, store] = this.treeview.get_selection().get_selected_rows();
|
||||
let iters = [];
|
||||
for (let i = 0; i < selection.length; ++i) {
|
||||
let [isSet, iter] = store.get_iter(selection[i]);
|
||||
if (isSet) {
|
||||
iters.push(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
// it's ok not to inhibit updates here as remove != change
|
||||
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();
|
||||
},
|
||||
_saveFullscreenNotifications: function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.set_boolean(this.config_keys.fullscreen_notification,
|
||||
sw.active);
|
||||
this._inhibitUpdate = false;
|
||||
},
|
||||
_saveGraphicalCountdown: function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.set_boolean(this.config_keys.graphical_countdown,
|
||||
sw.active);
|
||||
this._inhibitUpdate = false;
|
||||
},
|
||||
_saveUseAlarm: function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.set_boolean(this.config_keys.use_alarm_sound,
|
||||
sw.active);
|
||||
this._inhibitUpdate = false;
|
||||
},
|
||||
_saveSoundFile: function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
let alarm_sound = this.alarmSoundFile.get_uri();
|
||||
Utils.debug(this._settings.get_string(this.config_keys.alarm_sound) + "-->" + alarm_sound);
|
||||
this.treeview.get_selection().unselect_all();
|
||||
};
|
||||
this._saveFullscreenNotifications = function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.set_boolean(this.config_keys.fullscreen_notification,
|
||||
sw.active);
|
||||
this._inhibitUpdate = false;
|
||||
};
|
||||
this._saveGraphicalCountdown = function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.set_boolean(this.config_keys.graphical_countdown,
|
||||
sw.active);
|
||||
this._inhibitUpdate = false;
|
||||
};
|
||||
this._saveUseAlarm = function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
this._inhibitUpdate = true;
|
||||
this._settings.set_boolean(this.config_keys.use_alarm_sound,
|
||||
sw.active);
|
||||
this._inhibitUpdate = false;
|
||||
};
|
||||
this._saveSoundFile = function (sw, data) {
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
let alarm_sound = this.alarmSoundFile.get_uri();
|
||||
Utils.debug(this._settings.get_string(this.config_keys.alarm_sound) + "-->" + alarm_sound);
|
||||
|
||||
let have_value = Utils.isType(alarm_sound, "string");
|
||||
let setting_is_different =
|
||||
this._settings.get_string(this.config_keys.alarm_sound) != alarm_sound;
|
||||
if (have_value && setting_is_different) {
|
||||
let have_value = Utils.isType(alarm_sound, "string");
|
||||
let setting_is_different =
|
||||
this._settings.get_string(this.config_keys.alarm_sound) != alarm_sound;
|
||||
if (have_value && setting_is_different) {
|
||||
this._inhibitUpdate = true;
|
||||
|
||||
Utils.playSound(alarm_sound);
|
||||
this._settings.set_string(this.config_keys.alarm_sound, alarm_sound);
|
||||
this._inhibitUpdate = false;
|
||||
}
|
||||
};
|
||||
this._save = function (store, path_, iter_) {
|
||||
const GLib = imports.gi.GLib;
|
||||
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
|
||||
let values = [];
|
||||
this._tealist.foreach(function (store, path, iter) {
|
||||
values.push(GLib.Variant.new_dict_entry(
|
||||
GLib.Variant.new_string(store.get_value(iter, Columns.TEA_NAME)),
|
||||
GLib.Variant.new_uint32(store.get_value(iter, Columns.STEEP_TIME))))
|
||||
});
|
||||
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;
|
||||
|
||||
Utils.playSound(alarm_sound);
|
||||
this._settings.set_string(this.config_keys.alarm_sound, alarm_sound);
|
||||
this._settings.set_value(this.config_keys.steep_times, settingsValue);
|
||||
|
||||
this._inhibitUpdate = false;
|
||||
}
|
||||
},
|
||||
_save: function (store, path_, iter_) {
|
||||
const GLib = imports.gi.GLib;
|
||||
|
||||
// don't update the backend if someone else is messing with the model
|
||||
if (this._inhibitUpdate)
|
||||
return;
|
||||
|
||||
let values = [];
|
||||
this._tealist.foreach(function (store, path, iter) {
|
||||
values.push(GLib.Variant.new_dict_entry(
|
||||
GLib.Variant.new_string(store.get_value(iter, Columns.TEA_NAME)),
|
||||
GLib.Variant.new_uint32(store.get_value(iter, Columns.STEEP_TIME))))
|
||||
});
|
||||
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(this.config_keys.steep_times, settingsValue);
|
||||
|
||||
this._inhibitUpdate = false;
|
||||
},
|
||||
config_keys: Utils.GetConfigKeys()
|
||||
});
|
||||
};
|
||||
this.config_keys = Utils.GetConfigKeys();
|
||||
this.myinit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function init() {}
|
||||
|
@ -116,7 +116,6 @@ function formatTime(sec_num) {
|
||||
|
||||
function playSound(uri) {
|
||||
const Gst = imports.gi.Gst;
|
||||
const Lang = imports.lang;
|
||||
|
||||
debug("Playing " + uri);
|
||||
|
||||
@ -125,7 +124,7 @@ function playSound(uri) {
|
||||
this.player = Gst.ElementFactory.make("playbin", "player");
|
||||
this.playBus = this.player.get_bus();
|
||||
this.playBus.add_signal_watch();
|
||||
this.playBus.connect("message", Lang.bind(this,
|
||||
this.playBus.connect("message",
|
||||
function (playBus, message) {
|
||||
if (message != null) {
|
||||
// IMPORTANT: to reuse the player, set state to READY
|
||||
@ -134,7 +133,7 @@ function playSound(uri) {
|
||||
this.player.set_state(Gst.State.READY);
|
||||
}
|
||||
} // message handler
|
||||
}));
|
||||
}.bind(this));
|
||||
} // if undefined
|
||||
this.player.set_property('uri', uri);
|
||||
this.player.set_state(Gst.State.PLAYING);
|
||||
|
Loading…
Reference in New Issue
Block a user