using Gtk; [GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/views/base.ui")] public class Tootle.Views.Base : Box { public static string STATUS_EMPTY = _("Nothing to see here"); public static string STATUS_LOADING = " "; public string? icon { get; set; default = null; } public string label { get; set; default = ""; } public bool needs_attention { get; set; default = false; } public bool current { get; set; default = false; } public SimpleActionGroup? actions { get; set; } public Container content { get; set; } [GtkChild] protected Hdy.HeaderBar header; [GtkChild] protected Button back_button; [GtkChild] protected ScrolledWindow scrolled; [GtkChild] protected Box view; [GtkChild] protected Hdy.Clamp clamp; [GtkChild] protected Box column_view; [GtkChild] protected Stack states; [GtkChild] protected Box content_box; [GtkChild] protected ListBox content_list; [GtkChild] protected Button status_button; [GtkChild] Stack status_stack; [GtkChild] Label status_message_label; public string state { get; set; default = "status"; } public string status_message { get; set; default = STATUS_EMPTY; } public bool empty { get { return content.get_children ().length () <= 0; } } construct { bind_property ("label", header, "title", BindingFlags.SYNC_CREATE); content = content_list; status_button.label = _("Reload"); bind_property ("state", states, "visible-child-name", BindingFlags.SYNC_CREATE); scrolled.edge_reached.connect (pos => { if (pos == PositionType.BOTTOM) on_bottom_reached (); }); content.remove.connect (() => on_content_changed ()); content_list.remove.connect (() => on_content_changed ()); content_list.row_activated.connect (on_content_item_activated); notify["status-message"].connect (() => { status_message_label.label = @"$status_message"; status_stack.visible_child_name = status_message == STATUS_LOADING ? "spinner" : "message"; }); notify["current"].connect (() => { if (current) on_shown (); else on_hidden (); }); scrolled.get_style_context ().add_class (Dialogs.MainWindow.ZOOM_CLASS); build_header (); } public virtual void build_header () {} public virtual void clear (){ content.forall (w => { w.destroy (); }); state = "status"; } public virtual void on_bottom_reached () {} public virtual void on_shown () { if (actions != null) window.insert_action_group ("view", actions); } public virtual void on_hidden () { if (actions != null) window.insert_action_group ("view", null); } public virtual void on_content_changed () { if (empty) { status_message = STATUS_EMPTY; state = "status"; } else { state = "content"; } check_resize (); } public virtual void on_error (int32 code, string reason) { status_message = reason; status_button.visible = true; status_button.sensitive = true; state = "status"; } [GtkCallback] protected void on_resized () { Allocation alloc; get_allocation (out alloc); var target_w = clamp.maximum_size; var view_w = alloc.width; var ctx = view.get_style_context (); if (view_w <= target_w && ctx.has_class ("padded")) ctx.remove_class ("padded"); if (view_w > target_w && !ctx.has_class ("padded")) ctx.add_class ("padded"); } public virtual void on_content_item_activated (ListBoxRow row) { Signal.emit_by_name (row, "open"); } [GtkCallback] void on_close () { window.back (); } }