[geary] Clean up MainWindow. Bug 775006.



commit 776eebd48e13148726a309f44f0cd49ea6e33029
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Nov 23 00:58:05 2016 +0100

    Clean up MainWindow. Bug 775006.
    
    * Use GtkTemplate to simplify layout.
    * Prefix instance variables with this.
    * Extract helper methods for clarity.
    
    Signed-off-by: Niels De Graef <nielsdegraef gmail com>

 po/POTFILES.in                         |    1 +
 src/client/components/main-window.vala |  393 +++++++++++++++-----------------
 ui/CMakeLists.txt                      |    1 +
 ui/main-window.ui                      |  132 +++++++++++
 4 files changed, 314 insertions(+), 213 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e07a56a..8ecfb1a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -398,6 +398,7 @@ src/mailer/main.vala
 [type: gettext/glade]ui/gtk/menus.ui
 [type: gettext/glade]ui/login.glade
 [type: gettext/glade]ui/main-toolbar.ui
+[type: gettext/glade]ui/main-window.ui
 [type: gettext/glade]ui/password-dialog.glade
 [type: gettext/glade]ui/preferences.glade
 [type: gettext/glade]ui/remove_confirm.glade
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index cb072bc..6dbf84e 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -6,52 +6,70 @@
  * (version 2.1 or later). See the COPYING file in this distribution.
  */
 
+[GtkTemplate (ui = "/org/gnome/Geary/main-window.ui")]
 public class MainWindow : Gtk.ApplicationWindow {
-    private const int MESSAGE_LIST_WIDTH = 250;
-    private const int FOLDER_LIST_WIDTH = 100;
     private const int STATUS_BAR_HEIGHT = 18;
-    
-    /// Fired when the shift key is pressed or released.
+
+    /** Fired when the shift key is pressed or released. */
     public signal void on_shift_key(bool pressed);
-    
-    public FolderList.Tree folder_list { get; private set; default = new FolderList.Tree(); }
-    public MainToolbar main_toolbar { get; private set; }
-    public SearchBar search_bar { get; private set; default = new SearchBar(); }
-    public ConversationListView conversation_list_view  { get; private set; default = new 
ConversationListView(); }
-    public ConversationViewer conversation_viewer { get; private set; }
-    public StatusBar status_bar { get; private set; default = new StatusBar(); }
+
     public Geary.Folder? current_folder { get; private set; default = null; }
-    public Configuration config { get; private set; }
-    
+
+    private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
+    private Geary.ProgressMonitor? folder_progress = null;
+
+    // Used to save/load the window state between sessions.
     public int window_width { get; set; }
     public int window_height { get; set; }
     public bool window_maximized { get; set; }
 
-    private Gtk.Paned folder_paned = new Gtk.Paned(Gtk.Orientation.HORIZONTAL);
-    private Gtk.Paned conversations_paned = new Gtk.Paned(Gtk.Orientation.HORIZONTAL);
-    
-    private Gtk.ScrolledWindow conversation_list_scrolled;
+    // Widget descendants
+    public FolderList.Tree folder_list { get; private set; default = new FolderList.Tree(); }
+    public MainToolbar main_toolbar { get; private set; }
+    public SearchBar search_bar { get; private set; default = new SearchBar(); }
+    public ConversationListView conversation_list_view  { get; private set; default = new 
ConversationListView(); }
+    public ConversationViewer conversation_viewer { get; private set; default = new ConversationViewer(); }
+    public StatusBar status_bar { get; private set; default = new StatusBar(); }
     private MonitoredSpinner spinner = new MonitoredSpinner();
+    [GtkChild]
+    private Gtk.Box search_bar_box;
+    [GtkChild]
+    private Gtk.Paned folder_paned;
+    [GtkChild]
+    private Gtk.Paned conversations_paned;
+    [GtkChild]
     private Gtk.Box folder_box;
+    [GtkChild]
+    private Gtk.ScrolledWindow folder_list_scrolled;
+    [GtkChild]
     private Gtk.Box conversation_box;
-    private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
-    private Geary.ProgressMonitor? folder_progress = null;
-    
+    [GtkChild]
+    private Gtk.ScrolledWindow conversation_list_scrolled;
+
     public MainWindow(GearyApplication application) {
         Object(application: application);
-        set_show_menubar(false);
 
-        add_events(Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK
-            | Gdk.EventMask.FOCUS_CHANGE_MASK);
+        load_config(application.config);
+        restore_saved_window_state();
+
+        add_accel_group(application.ui_manager.get_accel_group());
 
-        config = application.config;
-        conversation_viewer = new ConversationViewer();
+        application.controller.notify[GearyController.PROP_CURRENT_CONVERSATION]
+            .connect(on_conversation_monitor_changed);
+        application.controller.folder_selected.connect(on_folder_selected);
+        Geary.Engine.instance.account_available.connect(on_account_available);
+        Geary.Engine.instance.account_unavailable.connect(on_account_unavailable);
+
+        set_styling();
+        setup_layout(application.config);
+        on_change_orientation();
+    }
 
-        // This code both loads AND saves the pane positions with live
-        // updating. This is more resilient against crashes because
-        // the value in dconf changes *immediately*, and stays saved
-        // in the event of a crash.
-        config.bind(Configuration.MESSAGES_PANE_POSITION_KEY, conversations_paned, "position");
+    private void load_config(Configuration config) {
+        // This code both loads AND saves the pane positions with live updating. This is more
+        // resilient against crashes because the value in dconf changes *immediately*, and
+        // stays saved in the event of a crash.
+        config.bind(Configuration.MESSAGES_PANE_POSITION_KEY, this.conversations_paned, "position");
         config.bind(Configuration.WINDOW_WIDTH_KEY, this, "window-width");
         config.bind(Configuration.WINDOW_HEIGHT_KEY, this, "window-height");
         config.bind(Configuration.WINDOW_MAXIMIZE_KEY, this, "window-maximized");
@@ -60,8 +78,11 @@ public class MainWindow : Gtk.ApplicationWindow {
             config.folder_list_pane_position_horizontal = config.folder_list_pane_position_old;
             config.messages_pane_position += config.folder_list_pane_position_old;
         }
+        config.settings.changed[Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY]
+            .connect(on_change_orientation);
+    }
 
-        // Restore saved window state
+    private void restore_saved_window_state() {
         Gdk.Screen? screen = get_screen();
         if (screen != null &&
             this.window_width <= screen.get_width() &&
@@ -71,61 +92,10 @@ public class MainWindow : Gtk.ApplicationWindow {
         if (this.window_maximized) {
             maximize();
         }
-        set_position(Gtk.WindowPosition.CENTER);
-
-        add_accel_group(GearyApplication.instance.ui_manager.get_accel_group());
-        
-        spinner.set_progress_monitor(progress_monitor);
-
-        delete_event.connect(on_delete_event);
-        key_press_event.connect(on_key_press_event);
-        key_release_event.connect(on_key_release_event);
-        focus_in_event.connect(on_focus_event);
-        GearyApplication.instance.config.settings.changed[
-            Configuration.FOLDER_LIST_PANE_HORIZONTAL_KEY].connect(on_change_orientation);
-        GearyApplication.instance.controller.notify[GearyController.PROP_CURRENT_CONVERSATION].
-            connect(on_conversation_monitor_changed);
-        GearyApplication.instance.controller.folder_selected.connect(on_folder_selected);
-        Geary.Engine.instance.account_available.connect(on_account_available);
-        Geary.Engine.instance.account_unavailable.connect(on_account_unavailable);
-
-        // Toolbar.
-        main_toolbar = new MainToolbar(config);
-        main_toolbar.bind_property("search-open", search_bar, "search-mode-enabled",
-            BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
-        main_toolbar.bind_property("find-open", conversation_viewer.conversation_find_bar, 
"search-mode-enabled",
-            BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
-        if (config.desktop_environment == Configuration.DesktopEnvironment.UNITY) {
-            BindingTransformFunc title_func = (binding, source, ref target) => {
-                string folder = current_folder != null ? current_folder.get_display_name() + " " : "";
-                string account = main_toolbar.account != null ? "(%s)".printf(main_toolbar.account) : "";
-
-                target = "%s%s - %s".printf(folder, account, GearyApplication.NAME);
-
-                return true;
-            };
-            bind_property("current-folder", this, "title", BindingFlags.SYNC_CREATE, title_func);
-            main_toolbar.bind_property("account", this, "title", BindingFlags.SYNC_CREATE, title_func);
-        } else {
-            main_toolbar.show_close_button = true;
-            set_titlebar(main_toolbar);
-        }
-
-        set_styling();
-        create_layout();
-        on_change_orientation();
-    }
-
-    private bool on_delete_event() {
-        if (Args.hidden_startup || GearyApplication.instance.config.startup_notifications)
-            return hide_on_delete();
-        
-        GearyApplication.instance.exit();
-        
-        return true;
+        this.window_position = Gtk.WindowPosition.CENTER;
     }
 
-    // Fired on [un]maximize and possibly others. Save maximized state
+    // Called on [un]maximize and possibly others. Save maximized state
     // for the next start.
     public override bool window_state_event(Gdk.EventWindowState event) {
         if ((event.new_window_state & Gdk.WindowState.WITHDRAWN) == 0) {
@@ -139,7 +109,7 @@ public class MainWindow : Gtk.ApplicationWindow {
         return base.window_state_event(event);
     }
 
-    // Fired on window resize. Save window size for the next start.
+    // Called on window resize. Save window size for the next start.
     public override void size_allocate(Gtk.Allocation allocation) {
         base.size_allocate(allocation);
 
@@ -177,96 +147,53 @@ public class MainWindow : Gtk.ApplicationWindow {
         });
         provider.load_from_resource(@"/org/gnome/Geary/geary.css");
     }
-    
-    private void create_layout() {
-        Gtk.Box main_layout = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
-        
-        // folder list
-        Gtk.ScrolledWindow folder_list_scrolled = new Gtk.ScrolledWindow(null, null);
-        folder_list_scrolled.set_size_request(FOLDER_LIST_WIDTH, -1);
-        folder_list_scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
-        folder_list_scrolled.add(folder_list);
-        Gtk.Frame folder_frame = new Gtk.Frame(null);
-        folder_frame.shadow_type = Gtk.ShadowType.IN;
-        folder_frame.get_style_context ().add_class("geary-folder-frame");
-        folder_frame.add(folder_list_scrolled);
-        folder_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
-        folder_box.pack_start(folder_frame, true, true);
-
-        // message list
-        conversation_list_scrolled = new Gtk.ScrolledWindow(null, null);
-        conversation_list_scrolled.set_size_request(MESSAGE_LIST_WIDTH, -1);
-        conversation_list_scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
-        conversation_list_scrolled.add(conversation_list_view);
-        Gtk.Frame conversation_frame = new Gtk.Frame(null);
-        conversation_frame.shadow_type = Gtk.ShadowType.IN;
-        conversation_frame.get_style_context ().add_class("geary-conversation-frame");
-        conversation_frame.add(conversation_list_scrolled);
-        conversation_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
-        conversation_box.pack_start(conversation_frame, true, true);
-        
-        // Three-pane display.
-        status_bar.set_size_request(-1, STATUS_BAR_HEIGHT);
-        status_bar.set_border_width(2);
-        spinner.set_size_request(STATUS_BAR_HEIGHT - 2, -1);
-        status_bar.add(spinner);
-        
-        folder_paned.get_style_context().add_class("geary-sidebar-pane-separator");
-
-        // Folder list to the left of everything.
-        folder_paned.pack1(folder_box, false, false);
-        folder_paned.pack2(conversation_box, true, false);
-        
-        Gtk.Box search_bar_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
-        search_bar_box.pack_start(search_bar, false, false, 0);
-        search_bar_box.pack_start(folder_paned);
-        search_bar_box.get_style_context().add_class(Gtk.STYLE_CLASS_SIDEBAR);
-        
-        // Message list left of message viewer.
-        conversations_paned.pack1(search_bar_box, false, false);
-        conversations_paned.pack2(conversation_viewer, true, true);
 
+    private void setup_layout(Configuration config) {
+        // Toolbar
+        this.main_toolbar = new MainToolbar(config);
+        this.main_toolbar.bind_property("search-open", this.search_bar, "search-mode-enabled",
+            BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
+        this.main_toolbar.bind_property("find-open", this.conversation_viewer.conversation_find_bar,
+                "search-mode-enabled", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
         if (config.desktop_environment == Configuration.DesktopEnvironment.UNITY) {
-            main_layout.pack_start(main_toolbar, false, true, 0);
+            BindingTransformFunc title_func = (binding, source, ref target) => {
+                string folder = current_folder != null ? current_folder.get_display_name() + " " : "";
+                string account = main_toolbar.account != null ? "(%s)".printf(main_toolbar.account) : "";
+
+                target = "%s%s - %s".printf(folder, account, GearyApplication.NAME);
+
+                return true;
+            };
+            bind_property("current-folder", this, "title", BindingFlags.SYNC_CREATE, title_func);
+            main_toolbar.bind_property("account", this, "title", BindingFlags.SYNC_CREATE, title_func);
+        } else {
+            main_toolbar.show_close_button = true;
+            set_titlebar(main_toolbar);
         }
 
-        main_layout.pack_end(conversations_paned, true, true, 0);
-        
-        add(main_layout);
+        // Search bar
+        this.search_bar_box.pack_start(this.search_bar, false, false, 0);
+        // Folder list
+        this.folder_list_scrolled.add(this.folder_list);
+        // Conversation list
+        this.conversation_list_scrolled.add(this.conversation_list_view);
+        // Conversation viewer
+        this.conversations_paned.pack2(this.conversation_viewer, true, true);
+
+        // Status bar
+        this.status_bar.set_size_request(-1, STATUS_BAR_HEIGHT);
+        this.status_bar.set_border_width(2);
+        this.spinner.set_size_request(STATUS_BAR_HEIGHT - 2, -1);
+        this.spinner.set_progress_monitor(progress_monitor);
+        this.status_bar.add(this.spinner);
     }
-    
+
     // Returns true when there's a conversation list scrollbar visible, i.e. the list is tall
     // enough to need one.  Otherwise returns false.
     public bool conversation_list_has_scrollbar() {
-        Gtk.Scrollbar? scrollbar = conversation_list_scrolled.get_vscrollbar() as Gtk.Scrollbar;
+        Gtk.Scrollbar? scrollbar = this.conversation_list_scrolled.get_vscrollbar() as Gtk.Scrollbar;
         return scrollbar != null && scrollbar.get_visible();
     }
-    
-    private bool on_key_press_event(Gdk.EventKey event) {
-        if ((event.keyval == Gdk.Key.Shift_L || event.keyval == Gdk.Key.Shift_R)
-            && (event.state & Gdk.ModifierType.SHIFT_MASK) == 0 && !search_bar.search_entry_has_focus)
-            on_shift_key(true);
-        
-        // Check whether the focused widget wants to handle it, if not let the accelerators kick in
-        // via the default handling
-        return propagate_key_event(event);
-    }
-    
-    private bool on_key_release_event(Gdk.EventKey event) {
-        // FIXME: it's possible the user will press two shift keys.  We want
-        // the shift key to report as released when they release ALL of them.
-        // There doesn't seem to be an easy way to do this in Gdk.
-        if ((event.keyval == Gdk.Key.Shift_L || event.keyval == Gdk.Key.Shift_R)
-            && !search_bar.search_entry_has_focus)
-            on_shift_key(false);
-        
-        return propagate_key_event(event);
-    }
-    
-    private bool on_focus_event() {
-        on_shift_key(false);
-        return false;
-    }
 
     private void on_conversation_monitor_changed() {
         ConversationListStore? old_model = this.conversation_list_view.get_model();
@@ -293,107 +220,147 @@ public class MainWindow : Gtk.ApplicationWindow {
     }
 
     private void on_folder_selected(Geary.Folder? folder) {
-        if (folder_progress != null) {
-            progress_monitor.remove(folder_progress);
-            folder_progress = null;
+        if (this.folder_progress != null) {
+            this.progress_monitor.remove(this.folder_progress);
+            this.folder_progress = null;
         }
-        
+
         if (folder != null) {
-            folder_progress = folder.opening_monitor;
-            progress_monitor.add(folder_progress);
+            this.folder_progress = folder.opening_monitor;
+            this.progress_monitor.add(this.folder_progress);
         }
-        
+
         // disconnect from old folder
-        if (current_folder != null)
-            current_folder.properties.notify.disconnect(update_headerbar);
-        
+        if (this.current_folder != null)
+            this.current_folder.properties.notify.disconnect(update_headerbar);
+
         // connect to new folder
         if (folder != null)
             folder.properties.notify.connect(update_headerbar);
-        
+
         // swap it in
-        current_folder = folder;
-        
+        this.current_folder = folder;
+
         update_headerbar();
     }
-    
+
     private void on_account_available(Geary.AccountInformation account) {
         try {
-            progress_monitor.add(Geary.Engine.instance.get_account_instance(account).opening_monitor);
-            progress_monitor.add(Geary.Engine.instance.get_account_instance(account).sending_monitor);
+            this.progress_monitor.add(Geary.Engine.instance.get_account_instance(account).opening_monitor);
+            this.progress_monitor.add(Geary.Engine.instance.get_account_instance(account).sending_monitor);
         } catch (Error e) {
             debug("Could not access account progress monitors: %s", e.message);
         }
     }
-    
+
     private void on_account_unavailable(Geary.AccountInformation account) {
         try {
-            progress_monitor.remove(Geary.Engine.instance.get_account_instance(account).opening_monitor);
-            progress_monitor.remove(Geary.Engine.instance.get_account_instance(account).sending_monitor);
+            
this.progress_monitor.remove(Geary.Engine.instance.get_account_instance(account).opening_monitor);
+            
this.progress_monitor.remove(Geary.Engine.instance.get_account_instance(account).sending_monitor);
         } catch (Error e) {
             debug("Could not access account progress monitors: %s", e.message);
         }
     }
-    
+
     private void on_change_orientation() {
         bool horizontal = GearyApplication.instance.config.folder_list_pane_horizontal;
         bool initial = true;
-        
-        if (status_bar.parent != null) {
-            status_bar.parent.remove(status_bar);
+
+        if (this.status_bar.parent != null) {
+            this.status_bar.parent.remove(status_bar);
             initial = false;
         }
-        
-        GLib.Settings.unbind(folder_paned, "position");
-        folder_paned.orientation = horizontal ? Gtk.Orientation.HORIZONTAL :
+
+        GLib.Settings.unbind(this.folder_paned, "position");
+        this.folder_paned.orientation = horizontal ? Gtk.Orientation.HORIZONTAL :
             Gtk.Orientation.VERTICAL;
-        
+
         int folder_list_width =
             GearyApplication.instance.config.folder_list_pane_position_horizontal;
         if (horizontal) {
             if (!initial)
-                conversations_paned.position += folder_list_width;
-            folder_box.pack_start(status_bar, false, false);
+                this.conversations_paned.position += folder_list_width;
+            this.folder_box.pack_start(status_bar, false, false);
         } else {
             if (!initial)
-                conversations_paned.position -= folder_list_width;
-            conversation_box.pack_start(status_bar, false, false);
+                this.conversations_paned.position -= folder_list_width;
+            this.conversation_box.pack_start(status_bar, false, false);
         }
-        
+
         GearyApplication.instance.config.bind(
             horizontal ? Configuration.FOLDER_LIST_PANE_POSITION_HORIZONTAL_KEY
             : Configuration.FOLDER_LIST_PANE_POSITION_VERTICAL_KEY,
-            folder_paned, "position");
+            this.folder_paned, "position");
     }
-    
+
     private void update_headerbar() {
-        if (current_folder == null) {
-            main_toolbar.account = null;
-            main_toolbar.folder = null;
-            
+        if (this.current_folder == null) {
+            this.main_toolbar.account = null;
+            this.main_toolbar.folder = null;
+
             return;
         }
-        
-        main_toolbar.account = current_folder.account.information.nickname;
-        
+
+        this.main_toolbar.account = this.current_folder.account.information.nickname;
+
         /// Current folder's name followed by its unread count, i.e. "Inbox (42)"
         // except for Drafts and Outbox, where we show total count
         int count;
-        switch (current_folder.special_folder_type) {
+        switch (this.current_folder.special_folder_type) {
             case Geary.SpecialFolderType.DRAFTS:
             case Geary.SpecialFolderType.OUTBOX:
-                count = current_folder.properties.email_total;
+                count = this.current_folder.properties.email_total;
             break;
-            
+
             default:
-                count = current_folder.properties.email_unread;
+                count = this.current_folder.properties.email_unread;
             break;
         }
-        
+
         if (count > 0)
-            main_toolbar.folder = _("%s (%d)").printf(current_folder.get_display_name(), count);
+            this.main_toolbar.folder = _("%s (%d)").printf(this.current_folder.get_display_name(), count);
         else
-            main_toolbar.folder = current_folder.get_display_name();
+            this.main_toolbar.folder = this.current_folder.get_display_name();
+    }
+
+    [GtkCallback]
+    private bool on_key_press_event(Gdk.EventKey event) {
+        if ((event.keyval == Gdk.Key.Shift_L || event.keyval == Gdk.Key.Shift_R)
+            && (event.state & Gdk.ModifierType.SHIFT_MASK) == 0
+            && !this.search_bar.search_entry_has_focus)
+            on_shift_key(true);
+
+        // Check whether the focused widget wants to handle it, if not let the accelerators kick in
+        // via the default handling
+        return propagate_key_event(event);
+    }
+
+    [GtkCallback]
+    private bool on_key_release_event(Gdk.EventKey event) {
+        // FIXME: it's possible the user will press two shift keys.  We want
+        // the shift key to report as released when they release ALL of them.
+        // There doesn't seem to be an easy way to do this in Gdk.
+        if ((event.keyval == Gdk.Key.Shift_L || event.keyval == Gdk.Key.Shift_R)
+            && !this.search_bar.search_entry_has_focus)
+            on_shift_key(false);
+
+        return propagate_key_event(event);
+    }
+
+    [GtkCallback]
+    private bool on_focus_event() {
+        on_shift_key(false);
+        return false;
+    }
+
+    [GtkCallback]
+    private bool on_delete_event() {
+        if (Args.hidden_startup || GearyApplication.instance.config.startup_notifications)
+            return hide_on_delete();
+
+        GearyApplication.instance.exit();
+
+        return true;
     }
 }
 
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index e2ac935..501ab7a 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -23,6 +23,7 @@ set(RESOURCE_LIST
   STRIPBLANKS "gtk/menus.ui"
   STRIPBLANKS "login.glade"
   STRIPBLANKS "main-toolbar.ui"
+  STRIPBLANKS "main-window.ui"
   STRIPBLANKS "password-dialog.glade"
   STRIPBLANKS "preferences.glade"
   STRIPBLANKS "remove_confirm.glade"
diff --git a/ui/main-window.ui b/ui/main-window.ui
new file mode 100644
index 0000000..f61c55a
--- /dev/null
+++ b/ui/main-window.ui
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.14"/>
+  <template class="MainWindow" parent="GtkApplicationWindow">
+    <property name="visible">False</property>
+    <property name="show_menubar">False</property>
+    <property name="events">GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | 
GDK_STRUCTURE_MASK</property>
+    <signal name="delete_event" handler="on_delete_event"/>
+    <signal name="key_press_event" handler="on_key_press_event"/>
+    <signal name="key_release_event" handler="on_key_release_event"/>
+    <signal name="focus_in_event" handler="on_focus_event"/>
+    <child>
+      <object class="GtkBox" id="main_layout">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">0</property>
+        <child>
+          <object class="GtkPaned" id="conversations_paned">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">horizontal</property>
+            <child>
+              <object class="GtkBox" id="search_bar_box">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">0</property>
+                <style>
+                  <class name="sidebar"/>
+                </style>
+                <child>
+                  <object class="GtkPaned" id="folder_paned">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">horizontal</property>
+                    <style>
+                      <class name="geary-sidebar-pane-separator"/>
+                    </style>
+                    <child>
+                      <object class="GtkBox" id="folder_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">0</property>
+                        <child>
+                          <object class="GtkFrame" id="folder_frame">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="shadow_type">in</property>
+                            <style>
+                              <class name="geary-folder-frame"/>
+                            </style>
+                            <child>
+                              <object class="GtkScrolledWindow" id="folder_list_scrolled">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="width_request">100</property>
+                                <property name="hscrollbar_policy">never</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="resize">False</property>
+                        <property name="shrink">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="conversation_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">0</property>
+                        <child>
+                          <object class="GtkFrame" id="conversation_frame">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="shadow_type">in</property>
+                            <style>
+                              <class name="geary-conversation-frame"/>
+                            </style>
+                            <child>
+                              <object class="GtkScrolledWindow" id="conversation_list_scrolled">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="width_request">250</property>
+                                <property name="hscrollbar_policy">automatic</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="resize">True</property>
+                        <property name="shrink">False</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack_type">end</property>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="resize">False</property>
+                <property name="shrink">False</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]