diff --git a/data/io.elementary.code.gschema.xml b/data/io.elementary.code.gschema.xml index 0f78a64f7..58e76f580 100644 --- a/data/io.elementary.code.gschema.xml +++ b/data/io.elementary.code.gschema.xml @@ -58,6 +58,11 @@ Terminal visibility Whether or not the terminal pane is visible + + true + Sort open projects + Keep the open projects in alphabetical order + '' Last opened path diff --git a/plugins/fuzzy-search/fuzzy-search.vala b/plugins/fuzzy-search/fuzzy-search.vala index 41ebeec14..21fc73e54 100644 --- a/plugins/fuzzy-search/fuzzy-search.vala +++ b/plugins/fuzzy-search/fuzzy-search.vala @@ -10,11 +10,11 @@ public class Scratch.Plugins.FuzzySearch: Peas.ExtensionBase, Scratch.Services.A public Object object { owned get; set construct; } private const uint ACCEL_KEY = Gdk.Key.F; private const Gdk.ModifierType ACCEL_MODTYPE = Gdk.ModifierType.MOD1_MASK; + private const string FUZZY_FINDER_ID = "fuzzy-finder"; private Scratch.Services.FuzzySearchIndexer indexer; private MainWindow window = null; private Scratch.Services.Interface plugins; - private GLib.MenuItem fuzzy_menuitem; private GLib.Cancellable cancellable; private const string ACTION_GROUP = "fuzzysearch"; @@ -28,9 +28,11 @@ public class Scratch.Plugins.FuzzySearch: Peas.ExtensionBase, Scratch.Services.A private GLib.Settings folder_settings; private static Gee.MultiMap action_accelerators = new Gee.HashMultiMap (); + private static string accel_string; static construct { - action_accelerators.set (ACTION_SHOW, @"$(Gdk.keyval_name (ACCEL_KEY))"); + accel_string = @"$(Gdk.keyval_name (ACCEL_KEY))"; + action_accelerators.set (ACTION_SHOW, accel_string); } public void update_state () { @@ -88,25 +90,22 @@ public class Scratch.Plugins.FuzzySearch: Peas.ExtensionBase, Scratch.Services.A handle_opened_projects_change (); - fuzzy_menuitem = new GLib.MenuItem (_("Find Project Files"), ACTION_PREFIX + ACTION_SHOW ); - - var menu = window.sidebar.project_menu_model as GLib.Menu; - menu.append_item (fuzzy_menuitem); + var label = new Granite.AccelLabel (_("Find Project Files")) { + action_name = ACTION_PREFIX + ACTION_SHOW, + accel_string = accel_string + }; + var fuzzy_menuitem = new Gtk.Button () { // Cannot change child of ModelButton + action_name = ACTION_PREFIX + ACTION_SHOW, + child = label + }; + fuzzy_menuitem.get_style_context ().add_class ("flat"); + + window.sidebar.add_project_menu_widget (FUZZY_FINDER_ID, fuzzy_menuitem); } private void remove_actions () { - var sidebar_menu = window.sidebar.project_menu_model as GLib.Menu; - int length = sidebar_menu.get_n_items (); - for (var i = length - 1; i >= 0; i--) { - var action_name = sidebar_menu.get_item_attribute_value ( - i, - GLib.Menu.ATTRIBUTE_ACTION, - GLib.VariantType.STRING - ).get_string (); - if (action_name.has_prefix (ACTION_PREFIX)) { - sidebar_menu.remove (i); - } - } + var sidebar_menu = window.sidebar.project_menu; + window.sidebar.remove_project_menu_widget (FUZZY_FINDER_ID); var application = (Gtk.Application) GLib.Application.get_default (); var app = (Scratch.Application) application; diff --git a/src/FolderManager/FileView.vala b/src/FolderManager/FileView.vala index 2bb5035b3..eff964a15 100644 --- a/src/FolderManager/FileView.vala +++ b/src/FolderManager/FileView.vala @@ -63,6 +63,7 @@ public class Scratch.FolderManager.FileView : Code.Widgets.SourceList, Code.Pane public ActionGroup toplevel_action_group { get; private set; } public string icon_name { get; set; } public string title { get; set; } + public bool order_folders { get; set; default = true; } public FileView (Scratch.Services.PluginsManager plugins_manager) { plugins = plugins_manager; @@ -85,6 +86,12 @@ public class Scratch.FolderManager.FileView : Code.Widgets.SourceList, Code.Pane toplevel_action_group = get_action_group (MainWindow.ACTION_GROUP); assert_nonnull (toplevel_action_group); }); + + notify["order-folders"].connect (() => { + if (order_folders) { + reorder_folders (); + } + }); } private void action_close_folder (SimpleAction action, GLib.Variant? parameter) { @@ -168,9 +175,9 @@ public class Scratch.FolderManager.FileView : Code.Widgets.SourceList, Code.Pane } } - public void order_folders () { + private void reorder_folders () { + // This is not efficient but SourceList does not currently allow `insert_sorted` or setting a sort function var list = new Gee.ArrayList (); - foreach (var child in root.children) { root.remove (child as ProjectFolderItem); list.add (child as ProjectFolderItem); @@ -567,8 +574,12 @@ public class Scratch.FolderManager.FileView : Code.Widgets.SourceList, Code.Pane // Process any closed signals emitted before proceeding Idle.add (() => { var folder_root = new ProjectFolderItem (folder, this); // Constructor adds project to GitManager - this.root.add (folder_root); + this.root.add (folder_root); // TODO Implement add_sorted; rename_items_with_same_name (folder_root); + if (order_folders) { + reorder_folders (); + } + folder_root.expanded = expand; folder_root.closed.connect (() => { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index bcf37aeb6..ecf6d0e60 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -141,7 +141,7 @@ namespace Scratch { { ACTION_OPEN_FOLDER, action_open_folder, "s" }, { ACTION_OPEN_PROJECT, action_open_project }, { ACTION_COLLAPSE_ALL_FOLDERS, action_collapse_all_folders }, - { ACTION_ORDER_FOLDERS, action_order_folders }, + { ACTION_ORDER_FOLDERS, action_order_folders, null, "true" }, { ACTION_PREFERENCES, action_preferences }, { ACTION_REVERT, action_revert }, { ACTION_SAVE, action_save }, @@ -347,6 +347,9 @@ namespace Scratch { sidebar_action.set_state (saved_state.get_boolean ("sidebar-visible")); update_toolbar_button (ACTION_TOGGLE_SIDEBAR, saved_state.get_boolean ("sidebar-visible")); + var order_folders_action = Utils.action_from_group (ACTION_ORDER_FOLDERS, actions); + order_folders_action.set_state (saved_state.get_boolean ("order-folders")); + var outline_action = Utils.action_from_group (ACTION_TOGGLE_OUTLINE, actions); outline_action.set_state (saved_state.get_boolean ("outline-visible")); update_toolbar_button (ACTION_TOGGLE_OUTLINE, saved_state.get_boolean ("outline-visible")); @@ -567,6 +570,7 @@ namespace Scratch { Scratch.saved_state.bind ("sidebar-visible", sidebar, "visible", SettingsBindFlags.DEFAULT); Scratch.saved_state.bind ("outline-visible", document_view , "outline_visible", SettingsBindFlags.DEFAULT); Scratch.saved_state.bind ("terminal-visible", terminal, "visible", SettingsBindFlags.DEFAULT); + Scratch.saved_state.bind ("order-folders", folder_manager_view, "order-folders", SettingsBindFlags.DEFAULT); // Plugins hook HookFunc hook_func = () => { plugins.hook_window (this); @@ -1126,7 +1130,10 @@ namespace Scratch { } private void action_order_folders () { - folder_manager_view.order_folders (); + var action = Utils.action_from_group (ACTION_ORDER_FOLDERS, actions); + var to_show = !action.get_state ().get_boolean (); + action.set_state (to_show); + folder_manager_view.order_folders = to_show; } private void action_save () { diff --git a/src/Widgets/Sidebar.vala b/src/Widgets/Sidebar.vala index 2f95327ea..1af0be81c 100644 --- a/src/Widgets/Sidebar.vala +++ b/src/Widgets/Sidebar.vala @@ -25,7 +25,9 @@ public class Code.Sidebar : Gtk.Grid { public Gtk.Stack stack { get; private set; } public Code.ChooseProjectButton choose_project_button { get; private set; } public Hdy.HeaderBar headerbar { get; private set; } - public GLib.MenuModel project_menu_model { get; construct; } + public Gtk.Box project_menu { get; private set; } + private HashTable project_menu_map; + private Gtk.Separator project_menu_separator; // Divides plugin items from core items // May show progress in different way in future public bool cloning_in_progress { get { @@ -77,25 +79,28 @@ public class Code.Sidebar : Gtk.Grid { var actionbar = new Gtk.ActionBar (); actionbar.get_style_context ().add_class (Gtk.STYLE_CLASS_INLINE_TOOLBAR); - var collapse_all_menu_item = new GLib.MenuItem (_("Collapse All"), Scratch.MainWindow.ACTION_PREFIX - + Scratch.MainWindow.ACTION_COLLAPSE_ALL_FOLDERS); + var collapse_all_menu_item = new Gtk.ModelButton () { + text = _("Collapse All"), + action_name = Scratch.MainWindow.ACTION_PREFIX + Scratch.MainWindow.ACTION_COLLAPSE_ALL_FOLDERS + }; - var order_projects_menu_item = new GLib.MenuItem (_("Alphabetize"), Scratch.MainWindow.ACTION_PREFIX - + Scratch.MainWindow.ACTION_ORDER_FOLDERS); + var order_projects_menu_item = new Gtk.ModelButton () { + text = _("Alphabetize"), + action_name = Scratch.MainWindow.ACTION_PREFIX + Scratch.MainWindow.ACTION_ORDER_FOLDERS + }; - var project_menu = new GLib.Menu (); - project_menu.append_item (collapse_all_menu_item); - project_menu.append_item (order_projects_menu_item); - project_menu_model = project_menu; + project_menu = new Gtk.Box (VERTICAL, 0); + project_menu.add (collapse_all_menu_item); + project_menu.add (order_projects_menu_item); + project_menu.show_all (); + var project_menu_model = new Gtk.Popover (null); + project_menu_model.add (project_menu); - var label = new Gtk.Label ( _("Manage project folders…")) { - halign = START - }; var project_menu_button = new Gtk.MenuButton () { hexpand = true, - use_popover = false, - menu_model = project_menu_model, - child = label + halign = START, + popover = project_menu_model, + label = _("Manage project folders…") }; actionbar.pack_start (project_menu_button); @@ -131,6 +136,31 @@ public class Code.Sidebar : Gtk.Grid { Gtk.TargetEntry uris = {"text/uri-list", 0, TargetType.URI_LIST}; Gtk.drag_dest_set (this, Gtk.DestDefaults.ALL, {uris}, Gdk.DragAction.COPY); drag_data_received.connect (drag_received); + + project_menu_map = new HashTable (str_hash, str_equal); + } + + public void add_project_menu_widget (string id, Gtk.Widget widget) { + if (project_menu_map.size () == 0) { + project_menu_separator = new Gtk.Separator (HORIZONTAL); + project_menu.add (project_menu_separator); + } + + project_menu.add (widget); + project_menu_map.@set (id, widget); + project_menu.show_all (); + } + + public void remove_project_menu_widget (string id) { + var item = project_menu_map.take (id); + if (item != null) { + item.destroy (); + } + + if (project_menu_map.size () == 0) { + project_menu_separator.destroy (); + } + } private void drag_received (Gtk.Widget w,