<commit_before>/* Copyright 2011-2015 Yorba Foundation
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

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.
    public signal void on_shift_key(bool pressed);
    
    public FolderList.Tree folder_list { get; private set; default = new FolderList.Tree(); }
    public ConversationListStore conversation_list_store { get; private set; default = new ConversationListStore(); }
    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; }
    public ConversationViewer conversation_viewer { get; private set; default = new ConversationViewer(); }
    public StatusBar status_bar { get; private set; default = new StatusBar(); }
    
    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;
    private MonitoredSpinner spinner = new MonitoredSpinner();
    private Gtk.Box folder_box;
    private Gtk.Box conversation_box;
    private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
    private Geary.ProgressMonitor? conversation_monitor_progress = null;
    private Geary.ProgressMonitor? folder_progress = null;
    private Geary.Folder? current_folder = null;
    
    public MainWindow(GearyApplication application) {
        Object(application: application);
        
        title = GearyApplication.NAME;
        
        conversation_list_view = new ConversationListView(conversation_list_store);
        
        add_events(Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK
            | Gdk.EventMask.FOCUS_CHANGE_MASK);
        
        // 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.
        Configuration config = GearyApplication.instance.config;
        config.bind(Configuration.MESSAGES_PANE_POSITION_KEY, 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");
        // Update to layout
        if (config.folder_list_pane_position_horizontal == -1) {
            config.folder_list_pane_position_horizontal = config.folder_list_pane_position_old;
            config.messages_pane_position += config.folder_list_pane_position_old;
        }
        
        add_accel_group(GearyApplication.instance.ui_manager.get_accel_group());
        
        spinner.set_progress_monitor(progress_monitor);
        progress_monitor.add(conversation_list_store.preview_monitor);
        
        GLib.List<Gdk.Pixbuf> pixbuf_list = new GLib.List<Gdk.Pixbuf>();
        pixbuf_list.append(IconFactory.instance.application_icon);
        // Use copy() because set_default_icon_list() actually accepts an owned reference
        // If we didn't hold the pixbufs in memory, would need to use copy_deep()
        // See https://mail.gnome.org/archives/vala-list/2014-August/msg00022.html
        set_default_icon_list(pixbuf_list.copy());
        
        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();
        main_toolbar.bind_property("search-open", search_bar, "search-mode-enabled",
            BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
        if (!GearyApplication.instance.is_running_unity) {
            main_toolbar.show_close_button = true;
            set_titlebar(main_toolbar);
        }
        
        set_styling();
        create_layout();
        on_change_orientation();
    }
    
    public override void show_all() {
        set_default_size(GearyApplication.instance.config.window_width,
            GearyApplication.instance.config.window_height);
        if (GearyApplication.instance.config.window_maximize)
            maximize();
        
        base.show_all();
    }
    
    private bool on_delete_event() {
        if (Args.hidden_startup || GearyApplication.instance.config.startup_notifications)
            return hide_on_delete();
        
        GearyApplication.instance.exit();
        
        return true;
    }

    // Fired on window resize, window move and possibly other events
    // We want to save the window size for the next start
    public override bool configure_event(Gdk.EventConfigure event) {

        // Writing the window_* variables triggers a dconf database update.
        // Only write if the value has changed.
        if(window_width != event.width)
            window_width = event.width;
        if(window_height != event.height)
            window_height = event.height;

        return base.configure_event(event);
    }

    // Fired on [un]maximize and possibly other events
    // We want to save the maximized state for the next start
    public override bool window_state_event(Gdk.EventWindowState event) {
        bool maximized = ((event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0);

        // Writing the window_* variables triggers a dconf database update.
        // Only write if the value has changed.
        if(window_maximized != maximized)
            window_maximized = maximized;

        return base.window_state_event(event);
    }
    
    private void set_styling() {
        Gtk.CssProvider provider = new Gtk.CssProvider();
        Gtk.StyleContext.add_provider_for_screen(Gdk.Display.get_default().get_default_screen(),
            provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
        // Gtk < 3.14: No borders along top or left side of window
        string css = """
            .folder-frame {
                border-left-width: 0px;
                border-top-width: 0px;
            }
            .sidebar-pane-separator.horizontal .conversation-frame {
                border-top-width: 0px;
                border-bottom-width: 0px;
            }
            .sidebar-pane-separator.vertical .conversation-frame {
                border-left-width: 0px;
            }
            ComposerBox {
                border-left-width: 0px;
                border-right-width: 0px;
                border-bottom-width: 0px;
            }
            ComposerBox.full-pane {
                border-top-width: 0px;
            }
            ComposerEmbed GtkHeaderBar,
            ComposerBox GtkHeaderBar {
                border-radius: 0px;
            }
            .geary-titlebar-left:dir(ltr),
            .geary-titlebar-right:dir(rtl) {
                border-top-right-radius: 0px;
            }
            .geary-titlebar-right:dir(ltr),
            .geary-titlebar-left:dir(rtl) {
                border-top-left-radius: 0px;
            }
        """;
        
        if(Gtk.MAJOR_VERSION > 3 || Gtk.MAJOR_VERSION == 3 && Gtk.MINOR_VERSION >= 14) {
            // Gtk >= 3.14: Borders only along status bar
            css += """
                  .folder-frame {
                      border-right-width: 0px;
                  }
                  .sidebar-pane-separator.vertical .folder-frame {
                      border-bottom-width: 0px;
                  }
                  .conversation-frame {
                      border-top-width: 0px;
                      border-left-width: 0px;
                      border-right-width: 0px;
                  }<commit_msg>Don't allow border-radius in headerbars when using server-side decorations<commit_after>/* Copyright 2011-2015 Yorba Foundation
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

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.
    public signal void on_shift_key(bool pressed);
    
    public FolderList.Tree folder_list { get; private set; default = new FolderList.Tree(); }
    public ConversationListStore conversation_list_store { get; private set; default = new ConversationListStore(); }
    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; }
    public ConversationViewer conversation_viewer { get; private set; default = new ConversationViewer(); }
    public StatusBar status_bar { get; private set; default = new StatusBar(); }
    
    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;
    private MonitoredSpinner spinner = new MonitoredSpinner();
    private Gtk.Box folder_box;
    private Gtk.Box conversation_box;
    private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
    private Geary.ProgressMonitor? conversation_monitor_progress = null;
    private Geary.ProgressMonitor? folder_progress = null;
    private Geary.Folder? current_folder = null;
    
    public MainWindow(GearyApplication application) {
        Object(application: application);
        
        title = GearyApplication.NAME;
        
        conversation_list_view = new ConversationListView(conversation_list_store);
        
        add_events(Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK
            | Gdk.EventMask.FOCUS_CHANGE_MASK);
        
        // 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.
        Configuration config = GearyApplication.instance.config;
        config.bind(Configuration.MESSAGES_PANE_POSITION_KEY, 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");
        // Update to layout
        if (config.folder_list_pane_position_horizontal == -1) {
            config.folder_list_pane_position_horizontal = config.folder_list_pane_position_old;
            config.messages_pane_position += config.folder_list_pane_position_old;
        }
        
        add_accel_group(GearyApplication.instance.ui_manager.get_accel_group());
        
        spinner.set_progress_monitor(progress_monitor);
        progress_monitor.add(conversation_list_store.preview_monitor);
        
        GLib.List<Gdk.Pixbuf> pixbuf_list = new GLib.List<Gdk.Pixbuf>();
        pixbuf_list.append(IconFactory.instance.application_icon);
        // Use copy() because set_default_icon_list() actually accepts an owned reference
        // If we didn't hold the pixbufs in memory, would need to use copy_deep()
        // See https://mail.gnome.org/archives/vala-list/2014-August/msg00022.html
        set_default_icon_list(pixbuf_list.copy());
        
        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();
        main_toolbar.bind_property("search-open", search_bar, "search-mode-enabled",
            BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
        if (!GearyApplication.instance.is_running_unity) {
            main_toolbar.show_close_button = true;
            set_titlebar(main_toolbar);
        }
        
        set_styling();
        create_layout();
        on_change_orientation();
    }
    
    public override void show_all() {
        set_default_size(GearyApplication.instance.config.window_width,
            GearyApplication.instance.config.window_height);
        if (GearyApplication.instance.config.window_maximize)
            maximize();
        
        base.show_all();
    }
    
    private bool on_delete_event() {
        if (Args.hidden_startup || GearyApplication.instance.config.startup_notifications)
            return hide_on_delete();
        
        GearyApplication.instance.exit();
        
        return true;
    }

    // Fired on window resize, window move and possibly other events
    // We want to save the window size for the next start
    public override bool configure_event(Gdk.EventConfigure event) {

        // Writing the window_* variables triggers a dconf database update.
        // Only write if the value has changed.
        if(window_width != event.width)
            window_width = event.width;
        if(window_height != event.height)
            window_height = event.height;

        return base.configure_event(event);
    }

    // Fired on [un]maximize and possibly other events
    // We want to save the maximized state for the next start
    public override bool window_state_event(Gdk.EventWindowState event) {
        bool maximized = ((event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0);

        // Writing the window_* variables triggers a dconf database update.
        // Only write if the value has changed.
        if(window_maximized != maximized)
            window_maximized = maximized;

        return base.window_state_event(event);
    }
    
    private void set_styling() {
        Gtk.CssProvider provider = new Gtk.CssProvider();
        Gtk.StyleContext.add_provider_for_screen(Gdk.Display.get_default().get_default_screen(),
            provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
        // Gtk < 3.14: No borders along top or left side of window
        string css = """
            .folder-frame {
                border-left-width: 0px;
                border-top-width: 0px;
            }
            .sidebar-pane-separator.horizontal .conversation-frame {
                border-top-width: 0px;
                border-bottom-width: 0px;
            }
            .sidebar-pane-separator.vertical .conversation-frame {
                border-left-width: 0px;
            }
            ComposerBox {
                border-left-width: 0px;
                border-right-width: 0px;
                border-bottom-width: 0px;
            }
            ComposerBox.full-pane {
                border-top-width: 0px;
            }
            ComposerEmbed GtkHeaderBar,
            ComposerBox GtkHeaderBar,
            GtkBox.vertical GtkHeaderBar {
                border-radius: 0px;
            }
            .geary-titlebar-left:dir(ltr),
            .geary-titlebar-right:dir(rtl) {
                border-top-right-radius: 0px;
            }
            .geary-titlebar-right:dir(ltr),
            .geary-titlebar-left:dir(rtl) {
                border-top-left-radius: 0px;
            }
        """;
        
        if(Gtk.MAJOR_VERSION > 3 || Gtk.MAJOR_VERSION == 3 && Gtk.MINOR_VERSION >= 14) {
            // Gtk >= 3.14: Borders only along status bar
            css += """
                  .folder-frame {
                      border-right-width: 0px;
                  }
                  .sidebar-pane-separator.vertical .folder-frame {
                      border-bottom-width: 0px;
                  }
                  .conversation-frame {
                      border-top-width: 0px;
                      border-left-width: 0px;
                      border-right-width: 0px;
                  }
{'fraction_non_alphanumeric': 0.08344088434992425, 'fraction_numerical': 0.006284720273834241, 'mean_word_length': 2.3843524496771744, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6631581', 'n_tokens_mistral': 5117, 'n_tokens_neox': 4893, 'n_words': 1048}