Commit 0a119add authored by Dylan McCall's avatar Dylan McCall

Added a central list of enabled breaks, instead of keeping track of state in...

Added a central list of enabled breaks, instead of keeping track of state in each break's own settings.
Tweaked break settings dialog to use a combo box to choose the configuration, instead of an on/off switch beside each break. (Fixes multiple ways to disable all breaks).
Added a message in the main window if the break helper application is not running when it should be. (This currently appears more often than it should because the settings application is not autostarting the helper application).
parent d2724d62
...@@ -5,20 +5,25 @@ ...@@ -5,20 +5,25 @@
<schema id="org.brainbreak.breaks" path="/org/brainbreak/breaks/" gettext-domain="brainbreak"> <schema id="org.brainbreak.breaks" path="/org/brainbreak/breaks/" gettext-domain="brainbreak">
<key name="master-enabled" type="b"> <key name="master-enabled" type="b">
<default>true</default>
<_summary>True to enable Brain Break</_summary> <_summary>True to enable Brain Break</_summary>
<default>true</default>
</key>
<key name="selected-breaks" type="as">
<_summary>The list of breaks that are currently enabled</_summary>
<default>[]</default>
</key> </key>
<key name="quiet-mode" type="b"> <key name="quiet-mode" type="b">
<default>false</default>
<_summary>True to enable quiet mode</_summary> <_summary>True to enable quiet mode</_summary>
<_description>Hides breaks until quiet-mode-expire-time.</_description> <_description>Hides breaks until quiet-mode-expire-time.</_description>
<default>false</default>
</key> </key>
<key name="quiet-mode-expire-time" type="x"> <key name="quiet-mode-expire-time" type="x">
<default>0</default>
<_summary>Time to end quiet mode.</_summary> <_summary>Time to end quiet mode.</_summary>
<_description>The time to automatically disable quiet mode, in unix time.</_description> <_description>The time to automatically disable quiet mode, in unix time.</_description>
<default>0</default>
</key> </key>
<child schema="org.brainbreak.breaks.restbreak" name="restbreak"/> <child schema="org.brainbreak.breaks.restbreak" name="restbreak"/>
...@@ -26,34 +31,24 @@ ...@@ -26,34 +31,24 @@
</schema> </schema>
<schema id="org.brainbreak.breaks.restbreak" path="/org/brainbreak/breaks/restbreak/" gettext-domain="brainbreak"> <schema id="org.brainbreak.breaks.restbreak" path="/org/brainbreak/breaks/restbreak/" gettext-domain="brainbreak">
<key name="enabled" type="b">
<default>true</default>
<_summary>True to enable break type</_summary>
</key>
<key name="interval-seconds" type="i"> <key name="interval-seconds" type="i">
<default>2400</default>
<_summary>Time between breaks</_summary> <_summary>Time between breaks</_summary>
<_description>The time between rest breaks, in seconds.</_description> <_description>The time between rest breaks, in seconds.</_description>
<default>2400</default>
</key> </key>
<key name="duration-seconds" type="i"> <key name="duration-seconds" type="i">
<default>360</default>
<_summary>Duration of each break</_summary> <_summary>Duration of each break</_summary>
<_description>The duration of each rest break, in seconds.</_description> <_description>The duration of each rest break, in seconds.</_description>
<default>360</default>
</key> </key>
</schema> </schema>
<schema id="org.brainbreak.breaks.microbreak" path="/org/brainbreak/breaks/microbreak/" gettext-domain="brainbreak"> <schema id="org.brainbreak.breaks.microbreak" path="/org/brainbreak/breaks/microbreak/" gettext-domain="brainbreak">
<key name="enabled" type="b">
<default>true</default>
<_summary>True to enable break type</_summary>
</key>
<key name="interval-seconds" type="i"> <key name="interval-seconds" type="i">
<default>360</default>
<_summary>Time between breaks</_summary> <_summary>Time between breaks</_summary>
<_description>The preferred time between micro breaks, in seconds.</_description> <_description>The preferred time between micro breaks, in seconds.</_description>
<default>360</default>
</key> </key>
<key name="duration-seconds" type="i"> <key name="duration-seconds" type="i">
......
...@@ -19,14 +19,24 @@ public class BreakManager : Object { ...@@ -19,14 +19,24 @@ public class BreakManager : Object {
private Application application; private Application application;
private UIManager ui_manager; private UIManager ui_manager;
private Gee.Map<string, BreakType> breaks;
private BreakHelperServer break_helper_server; private BreakHelperServer break_helper_server;
private Gee.Map<string, BreakType> breaks; private Settings settings;
public bool master_enabled {get; set;}
public string[] selected_break_ids {get; set;}
public BreakManager(Application application, UIManager ui_manager) { public BreakManager(Application application, UIManager ui_manager) {
this.application = application; this.application = application;
this.ui_manager = ui_manager; this.ui_manager = ui_manager;
this.breaks = new Gee.HashMap<string, BreakType>(); this.breaks = new Gee.HashMap<string, BreakType>();
this.settings = new Settings("org.brainbreak.breaks");
this.settings.bind("master-enabled", this, "master-enabled", SettingsBindFlags.DEFAULT);
this.settings.bind("selected-breaks", this, "selected-break-ids", SettingsBindFlags.DEFAULT);
this.notify["master-enabled"].connect(this.update_enabled_breaks);
this.notify["selected-break-ids"].connect(this.update_enabled_breaks);
this.break_helper_server = new BreakHelperServer(this); this.break_helper_server = new BreakHelperServer(this);
try { try {
...@@ -54,6 +64,8 @@ public class BreakManager : Object { ...@@ -54,6 +64,8 @@ public class BreakManager : Object {
this.add_break(new MicroBreakType(activity_monitor)); this.add_break(new MicroBreakType(activity_monitor));
this.add_break(new RestBreakType(activity_monitor)); this.add_break(new RestBreakType(activity_monitor));
} }
this.update_enabled_breaks();
} }
public Gee.Set<string> all_break_ids() { public Gee.Set<string> all_break_ids() {
...@@ -71,10 +83,13 @@ public class BreakManager : Object { ...@@ -71,10 +83,13 @@ public class BreakManager : Object {
private void add_break(BreakType break_type) { private void add_break(BreakType break_type) {
this.breaks.set(break_type.id, break_type); this.breaks.set(break_type.id, break_type);
break_type.initialize(this.ui_manager); break_type.initialize(this.ui_manager);
}
// At the moment, we expect breaks to enable and disable themselves
// using settings keys under their own namespaces. In the future, we private void update_enabled_breaks() {
// might want a global list of enabled break types, instead. foreach (BreakType break_type in this.all_breaks()) {
bool is_enabled = this.master_enabled && break_type.id in this.selected_break_ids;
break_type.break_controller.set_enabled(is_enabled);
}
} }
} }
......
...@@ -83,10 +83,10 @@ public abstract class BreakController : Object { ...@@ -83,10 +83,10 @@ public abstract class BreakController : Object {
* @param enable True to enable the break, false to disable it * @param enable True to enable the break, false to disable it
*/ */
public void set_enabled(bool enable) { public void set_enabled(bool enable) {
if (enable && ! this.is_enabled()) { if (enable && !this.is_enabled()) {
this.state = State.WAITING; this.state = State.WAITING;
this.enabled(); this.enabled();
} else if (this.is_enabled()) { } else if (!enable && this.is_enabled()) {
this.state = State.DISABLED; this.state = State.DISABLED;
this.finished(BreakController.FinishedReason.DISABLED); this.finished(BreakController.FinishedReason.DISABLED);
this.disabled(); this.disabled();
......
...@@ -21,27 +21,15 @@ public abstract class BreakType : Object { ...@@ -21,27 +21,15 @@ public abstract class BreakType : Object {
public BreakView break_view; public BreakView break_view;
protected Settings settings; protected Settings settings;
protected Settings global_settings;
public BreakType(string id, Settings settings) { public BreakType(string id, Settings settings) {
this.id = id; this.id = id;
this.settings = settings; this.settings = settings;
this.global_settings = new Settings("org.brainbreak.breaks");
} }
public virtual void initialize(UIManager ui_manager) { public virtual void initialize(UIManager ui_manager) {
this.break_controller = this.get_break_controller(this.settings); this.break_controller = this.get_break_controller(this.settings);
this.break_view = this.get_break_view(this.break_controller, ui_manager); this.break_view = this.get_break_view(this.break_controller, ui_manager);
this.global_settings.changed["master-enabled"].connect(this.update_enabled);
this.settings.changed["enabled"].connect(this.update_enabled);
this.update_enabled();
}
private void update_enabled() {
bool is_enabled = this.global_settings.get_boolean("master-enabled") &&
this.settings.get_boolean("enabled");
this.break_controller.set_enabled(is_enabled);
} }
protected abstract BreakController get_break_controller(Settings settings); protected abstract BreakController get_break_controller(Settings settings);
......
...@@ -95,8 +95,10 @@ public abstract class TimerBreakController : BreakController { ...@@ -95,8 +95,10 @@ public abstract class TimerBreakController : BreakController {
} }
private void finished_cb(BreakController.FinishedReason reason) { private void finished_cb(BreakController.FinishedReason reason) {
this.interval_countdown.reset(); if (reason > BreakController.FinishedReason.DISABLED) {
this.duration_countdown.reset(); this.interval_countdown.reset();
this.duration_countdown.reset();
}
} }
bool is_warned; bool is_warned;
......
...@@ -26,10 +26,18 @@ public class BreakManager : Object { ...@@ -26,10 +26,18 @@ public class BreakManager : Object {
private Gee.Map<string, BreakType> breaks; private Gee.Map<string, BreakType> breaks;
private List<BreakType> breaks_ordered; private List<BreakType> breaks_ordered;
private Settings settings;
public bool master_enabled {get; set;}
public string[] selected_break_ids {get; set;}
public BreakManager(Application application) { public BreakManager(Application application) {
this.application = application; this.application = application;
this.breaks = new Gee.HashMap<string, BreakType>(); this.breaks = new Gee.HashMap<string, BreakType>();
this.breaks_ordered = new List<BreakType>(); this.breaks_ordered = new List<BreakType>();
this.settings = new Settings("org.brainbreak.breaks");
this.settings.bind("master-enabled", this, "master-enabled", SettingsBindFlags.DEFAULT);
this.settings.bind("selected-breaks", this, "selected-break-ids", SettingsBindFlags.DEFAULT);
} }
public signal void break_added(BreakType break_type); public signal void break_added(BreakType break_type);
...@@ -71,8 +79,8 @@ public class BreakManager : Object { ...@@ -71,8 +79,8 @@ public class BreakManager : Object {
} }
} }
private void break_status_changed(BreakType break_type, BreakStatus break_status) { private void break_status_changed(BreakType break_type, BreakStatus? break_status) {
if (break_status.is_focused && break_status.is_active) { if (break_status != null && break_status.is_focused && break_status.is_active) {
this.set_foreground_break(break_type); this.set_foreground_break(break_type);
} else if (this.foreground_break == break_type) { } else if (this.foreground_break == break_type) {
this.set_foreground_break(null); this.set_foreground_break(null);
......
/*
* This file is part of Brain Break.
*
* Brain Break is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Brain Break is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Brain Break. If not, see <http://www.gnu.org/licenses/>.
*/
public class BreakSettingsDialog : Gtk.Dialog {
private BreakManager break_manager;
private ApplicationPanel application_panel;
private BreakConfigurationChooser configuration_chooser;
private Gtk.Grid breaks_grid;
private static const int ABOUT_BUTTON_RESPONSE = 5;
public BreakSettingsDialog(BreakManager break_manager) {
Object();
this.break_manager = break_manager;
Settings settings = new Settings("org.brainbreak.breaks");
this.set_title(_("Choose Your Break Schedule"));
this.set_resizable(false);
this.delete_event.connect(this.hide_on_delete);
Gtk.Widget close_button = this.add_button(Gtk.Stock.CLOSE, Gtk.ResponseType.CLOSE);
this.response.connect(this.response_cb);
Gtk.Container content_area = (Gtk.Container)this.get_content_area();
Gtk.Grid content = new Gtk.Grid();
content_area.add(content);
content.set_orientation(Gtk.Orientation.VERTICAL);
content.set_margin_left(10);
content.set_margin_right(10);
this.configuration_chooser = new BreakConfigurationChooser();
content.add(this.configuration_chooser);
this.configuration_chooser.add_configuration(
{"microbreak", "restbreak"},
_("A mix of short breaks and long breaks")
);
this.configuration_chooser.add_configuration(
{"restbreak"},
_("Occasional long breaks")
);
this.configuration_chooser.add_configuration(
{"microbreak"},
_("Frequent short breaks")
);
settings.bind("selected-breaks", this.configuration_chooser, "selected-break-ids", SettingsBindFlags.DEFAULT);
this.breaks_grid = new Gtk.Grid();
content.add(this.breaks_grid);
this.breaks_grid.set_orientation(Gtk.Orientation.VERTICAL);
content.show_all();
break_manager.break_added.connect(this.break_added_cb);
this.configuration_chooser.notify["selected-break-ids"].connect(this.update_break_configuration);
}
private void update_break_configuration() {
foreach (BreakType break_type in this.break_manager.all_breaks()) {
if (break_type.id in this.configuration_chooser.selected_break_ids) {
break_type.settings_panel.show();
} else {
break_type.settings_panel.hide();
}
}
}
private void break_added_cb(BreakType break_type) {
var settings_panel = break_type.settings_panel;
breaks_grid.add(settings_panel);
settings_panel.set_margin_top(10);
settings_panel.set_margin_bottom(10);
this.update_break_configuration();
}
private void response_cb(int response_id) {
if (response_id == Gtk.ResponseType.CLOSE) {
this.hide();
}
}
}
class BreakConfigurationChooser : Gtk.ComboBox {
public class Configuration : Object {
public Gtk.TreeIter iter;
public string[] break_ids;
public string label;
public Configuration(string[] break_ids, string label) {
this.break_ids = break_ids;
this.label = label;
}
public bool matches_breaks(string[] test_break_ids) {
if (test_break_ids.length == this.break_ids.length) {
foreach (string test_break_id in test_break_ids) {
if (! (test_break_id in this.break_ids)) return false;
}
return true;
} else {
return false;
}
}
}
private Gtk.ListStore list_store;
private List<Configuration> configurations;
public string[] selected_break_ids {public get; public set;}
public BreakConfigurationChooser() {
Object();
this.configurations = new List<Configuration>();
this.list_store = new Gtk.ListStore(2, typeof(Configuration), typeof(string));
this.set_model(this.list_store);
var label_renderer = new Gtk.CellRendererText();
this.pack_start(label_renderer, true);
this.add_attribute(label_renderer, "text", 1);
this.notify["active"].connect(this.send_selected_break);
this.notify["selected-break-ids"].connect(this.receive_selected_break);
}
public void add_configuration(string[] break_ids, string label) {
var configuration = new Configuration(break_ids, label);
this.configurations.append(configuration);
Gtk.TreeIter iter;
this.list_store.append(out iter);
this.list_store.set(iter, 0, configuration, 1, configuration.label);
configuration.iter = iter;
}
private void send_selected_break() {
Gtk.TreeIter iter;
if (this.get_active_iter(out iter)) {
Value value;
this.list_store.get_value(iter, 0, out value);
Configuration configuration = (Configuration)value;
this.selected_break_ids = configuration.break_ids;
}
}
private void receive_selected_break() {
var configuration = this.get_configuration_for_break_ids(this.selected_break_ids);
if (configuration != null) {
this.set_active_iter(configuration.iter);
} else {
this.set_active(-1);
}
}
private Configuration? get_configuration_for_break_ids(string[] selected_breaks) {
foreach (Configuration configuration in this.configurations) {
if (configuration.matches_breaks(selected_breaks)) {
return configuration;
}
}
return null;
}
}
...@@ -17,8 +17,7 @@ ...@@ -17,8 +17,7 @@
public abstract class BreakType : Object { public abstract class BreakType : Object {
public string id {get; private set;} public string id {get; private set;}
public bool enabled {get; protected set;} public BreakStatus? status;
public BreakStatus status;
public BreakInfoPanel info_panel; public BreakInfoPanel info_panel;
public BreakStatusPanel status_panel; public BreakStatusPanel status_panel;
...@@ -29,11 +28,9 @@ public abstract class BreakType : Object { ...@@ -29,11 +28,9 @@ public abstract class BreakType : Object {
public BreakType(string id, Settings settings) { public BreakType(string id, Settings settings) {
this.id = id; this.id = id;
this.settings = settings; this.settings = settings;
settings.bind("enabled", this, "enabled", SettingsBindFlags.DEFAULT);
} }
public signal void status_changed(BreakStatus status); public signal void status_changed(BreakStatus? status);
public virtual void initialize() { public virtual void initialize() {
this.info_panel = this.get_info_panel(); this.info_panel = this.get_info_panel();
...@@ -41,7 +38,7 @@ public abstract class BreakType : Object { ...@@ -41,7 +38,7 @@ public abstract class BreakType : Object {
this.settings_panel = this.get_settings_panel(); this.settings_panel = this.get_settings_panel();
} }
protected void update_status(BreakStatus status) { protected void update_status(BreakStatus? status) {
this.status = status; this.status = status;
this.status_changed(status); this.status_changed(status);
} }
...@@ -102,9 +99,19 @@ public abstract class BreakStatusPanel : Gtk.Grid { ...@@ -102,9 +99,19 @@ public abstract class BreakStatusPanel : Gtk.Grid {
} }
} }
public abstract class BreakSettingsPanel : SettingsPanel { public abstract class BreakSettingsPanel : Gtk.Grid {
private Gtk.Grid header;
private Gtk.Grid details;
public BreakSettingsPanel(BreakType break_type, string title, string? description) { public BreakSettingsPanel(BreakType break_type, string title, string? description) {
base(); Object();
this.set_orientation(Gtk.Orientation.VERTICAL);
this.set_row_spacing(10);
this.header = new Gtk.Grid();
this.add(this.header);
this.header.set_column_spacing(12);
var title_grid = new Gtk.Grid(); var title_grid = new Gtk.Grid();
this.set_header(title_grid); this.set_header(title_grid);
...@@ -112,28 +119,40 @@ public abstract class BreakSettingsPanel : SettingsPanel { ...@@ -112,28 +119,40 @@ public abstract class BreakSettingsPanel : SettingsPanel {
title_grid.set_row_spacing(4); title_grid.set_row_spacing(4);
var title_label = new Gtk.Label(title); var title_label = new Gtk.Label(title);
title_label.set_halign(Gtk.Align.START);
title_label.get_style_context().add_class("_settings-title");
title_grid.add(title_label); title_grid.add(title_label);
title_label.get_style_context().add_class("_settings-title");
title_label.set_halign(Gtk.Align.FILL);
title_label.set_hexpand(true);
title_label.set_justify(Gtk.Justification.CENTER);
var description_label = new Gtk.Label("<small>%s</small>".printf(description)); // var description_label = new Gtk.Label("<small>%s</small>".printf(description));
description_label.set_use_markup(true); // title_grid.add(description_label);
description_label.set_halign(Gtk.Align.START); // description_label.get_style_context().add_class("_settings-description");
description_label.get_style_context().add_class("_settings-description"); // description_label.set_use_markup(true);
title_grid.add(description_label); // description_label.set_halign(Gtk.Align.FILL);
// description_label.set_hexpand(true);
var toggle_switch = new Gtk.Switch(); // description_label.set_justify(Gtk.Justification.CENTER);
this.set_header_action(toggle_switch);
toggle_switch.set_hexpand(true); this.details = new Gtk.Grid();
toggle_switch.set_halign(Gtk.Align.END); this.add(this.details);
toggle_switch.set_valign(Gtk.Align.CENTER); this.details.set_margin_left(12);
break_type.settings.bind("enabled", toggle_switch, "active", SettingsBindFlags.DEFAULT); this.details.set_halign(Gtk.Align.CENTER);
this.details.set_hexpand(true);
this.show_all(); this.show_all();
}
toggle_switch.notify["active"].connect((s, p) => {
bool enabled = toggle_switch.active; protected void set_header(Gtk.Widget content) {
this.set_editable(enabled); this.header.attach(content, 0, 0, 1, 1);
}); }
protected void set_header_action(Gtk.Widget content) {
this.header.attach(content, 1, 0, 1, 1);
content.set_halign(Gtk.Align.END);
content.set_valign(Gtk.Align.CENTER);
}
protected void set_details(Gtk.Widget content) {
this.details.add(content);
} }
} }
...@@ -21,7 +21,7 @@ public class MainWindow : Gtk.ApplicationWindow { ...@@ -21,7 +21,7 @@ public class MainWindow : Gtk.ApplicationWindow {
private IBreakHelper? break_helper_server; private IBreakHelper? break_helper_server;
private Gd.HeaderBar header; private Gd.HeaderBar header;
private SettingsDialog settings_dialog; private BreakSettingsDialog break_settings_dialog;
private Gd.Stack main_stack; private Gd.Stack main_stack;
private StatusPanel status_panel; private StatusPanel status_panel;
...@@ -34,9 +34,9 @@ public class MainWindow : Gtk.ApplicationWindow { ...@@ -34,9 +34,9 @@ public class MainWindow : Gtk.ApplicationWindow {
this.set_title(_("Break Timer")); this.set_title(_("Break Timer"));
this.set_hide_titlebar_when_maximized(true); this.set_hide_titlebar_when_maximized(true);
this.settings_dialog = new SettingsDialog(break_manager); this.break_settings_dialog = new BreakSettingsDialog(break_manager);
this.settings_dialog.set_modal(true); this.break_settings_dialog.set_modal(true);
this.settings_dialog.set_transient_for(this); this.break_settings_dialog.set_transient_for(this);
Gtk.Grid content = new Gtk.Grid(); Gtk.Grid content = new Gtk.Grid();
this.add(content); this.add(content);
...@@ -104,7 +104,7 @@ public class MainWindow : Gtk.ApplicationWindow { ...@@ -104,7 +104,7 @@ public class MainWindow : Gtk.ApplicationWindow {
} }
private void settings_clicked_cb() { private void settings_clicked_cb() {
this.settings_dialog.show(); this.break_settings_dialog.show();
} }
private void launch_helper() { private void launch_helper() {
...@@ -119,11 +119,16 @@ public class MainWindow : Gtk.ApplicationWindow { ...@@ -119,11 +119,16 @@ public class MainWindow : Gtk.ApplicationWindow {
} }
} }
private class WelcomePanel : Gd.Stack {
}
private class StatusPanel : Gd.Stack { private class StatusPanel : Gd.Stack {
private BreakManager break_manager; private BreakManager break_manager;
private Gtk.Grid breaks_list; private Gtk.Grid breaks_list;
private Gtk.Grid no_breaks_message; private Gtk.Grid no_breaks_message;
private Gtk.Grid error_message;
public StatusPanel(BreakManager break_manager) { public StatusPanel(BreakManager break_manager) {
// TODO: Once we port to Gtk.Stack, set property "homogenous: false" // TODO: Once we port to Gtk.Stack, set property "homogenous: false"
...@@ -141,6 +146,9 @@ private class StatusPanel : Gd.Stack { ...@@ -141,6 +146,9 @@ private class StatusPanel : Gd.Stack {
this.no_breaks_message = this.build_no_breaks_message(); this.no_breaks_message = this.build_no_breaks_message();
this.add(this.no_breaks_message); this.add(this.no_breaks_message);
this.error_message = this.build_error_message();
this.add(this.error_message);
break_manager.break_added.connect(this.break_added_cb); break_manager.break_added.connect(this.break_added_cb);
} }
...@@ -153,27 +161,45 @@ private class StatusPanel : Gd.Stack { ...@@ -153,27 +161,45 @@ private class StatusPanel : Gd.Stack {
return breaks_list; return breaks_list;
} }
private Gtk.Grid build_message(string icon_name, string heading, string detail) {
var message = new Gtk.Grid();
message.set_orientation(Gtk.Orientation.VERTICAL);
message.set_halign(Gtk.Align.CENTER);
message.set_valign(Gtk.Align.CENTER);
message.set_row_spacing(12);
var image = new Gtk.Image.from_icon_name(icon_name, Gtk.IconSize.DIALOG);
message.add(image);
image.set_pixel_size(120);
image.get_style_context().add_class("_break-status-icon");
var heading_label = new Gtk.Label(heading);
message.add(heading_label);
heading_label.get_style_context().add_class("_break-status-heading");
var detail_label = new Gtk.Label(null);
message.add(detail_label);
detail_label.set_markup(detail);
detail_label.get_style_context().add_class("_break-status-hint");
detail_label.set_max_width_chars(60);
return message;
}
private Gtk.Grid build_no_breaks_message() { private Gtk.Grid build_no_breaks_message() {
var no_breaks_message = new Gtk.Grid(); return this.build_message(
no_breaks_message.set_orientation(Gtk.Orientation.VERTICAL); "face-sad-symbolic",
no_breaks_message.set_halign(Gtk.Align.CENTER); _("Break Timer is taking a break"),
no_breaks_message.set_valign(Gtk.Align.CENTER); _("Turn me on to get those breaks going")
no_breaks_message.set_row_spacing(12);