diff --git a/gitg/Makefile.am b/gitg/Makefile.am index 336062b7..dfd441af 100644 --- a/gitg/Makefile.am +++ b/gitg/Makefile.am @@ -55,6 +55,7 @@ gitg_gitg_VALASOURCES = \ gitg/gitg-author-details-dialog.vala \ gitg/gitg-info-bar.vala \ gitg/gitg-resource.vala \ + gitg/gitg-dash-view.vala \ gitg/gitg-application.vala \ gitg/gitg-plugins-engine.vala \ gitg/gitg-popup-menu.vala \ diff --git a/gitg/gitg-dash-view.vala b/gitg/gitg-dash-view.vala new file mode 100644 index 00000000..d58cc53b --- /dev/null +++ b/gitg/gitg-dash-view.vala @@ -0,0 +1,179 @@ +/* + * This file is part of gitg + * + * Copyright (C) 2014 - Jesse van den Kieboom + * + * gitg 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 2 of the License, or + * (at your option) any later version. + * + * gitg 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 gitg. If not, see . + */ + +namespace Gitg +{ + +class DashView : RepositoryListBox, GitgExt.UIElement, GitgExt.Activity, GitgExt.Selectable, GitgExt.Searchable +{ + private const string version = Config.VERSION; + + public GitgExt.Application? application { owned get; construct set; } + + private bool d_search_enabled; + private bool d_setting_mode; + + [Notify] + public GitgExt.SelectionMode selectable_mode + { + get + { + switch (mode) + { + case Gitg.SelectionMode.NORMAL: + return GitgExt.SelectionMode.NORMAL; + case Gitg.SelectionMode.SELECTION: + return GitgExt.SelectionMode.SELECTION; + } + + return GitgExt.SelectionMode.NORMAL; + } + + set + { + if (selectable_mode == value) + { + return; + } + + d_setting_mode = true; + + switch (value) + { + case GitgExt.SelectionMode.NORMAL: + mode = Gitg.SelectionMode.NORMAL; + break; + case GitgExt.SelectionMode.SELECTION: + mode = Gitg.SelectionMode.SELECTION; + break; + } + + d_setting_mode = false; + } + } + + public string display_name + { + owned get { return "Dash"; } + } + + public string description + { + owned get { return "Dash view"; } + } + + public string id + { + owned get { return "/org/gnome/gitg/dash"; } + } + + public Gtk.Widget? widget + { + owned get { return this; } + } + + public string? icon + { + owned get { return null; } + } + + private string d_search_text; + + public string search_text + { + owned get { return d_search_text; } + + set + { + if (d_search_text != value) + { + d_search_text = value; + filter_text(d_search_text); + } + } + } + + public bool search_visible { get; set; } + + public bool search_enabled + { + get { return d_search_enabled; } + set + { + if (d_search_enabled != value) + { + d_search_enabled = value; + + if (d_search_enabled) + { + filter_text(d_search_text); + } + else + { + filter_text(null); + } + } + } + } + + public Gtk.Widget? action_widget + { + owned get + { + var ab = new Gtk.ActionBar(); + + var del = new Gtk.Button.with_mnemonic(_("_Delete")); + + del.sensitive = false; + del.show(); + + del.clicked.connect(() => { + foreach (var sel in selection) + { + sel.request_remove(); + } + + selectable_mode = GitgExt.SelectionMode.NORMAL; + }); + + bind_property("has-selection", del, "sensitive"); + + ab.pack_end(del); + + return ab; + + } + } + + construct + { + d_search_text = ""; + + notify["mode"].connect(() => { + if (!d_setting_mode) + { + notify_property("selectable-mode"); + } + }); + } +} + +} + +// ex:ts=4 noet diff --git a/gitg/gitg-window.vala b/gitg/gitg-window.vala index 0ea9dbc6..71201185 100644 --- a/gitg/gitg-window.vala +++ b/gitg/gitg-window.vala @@ -33,6 +33,9 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable private Gtk.Dialog? d_dialog; private Gtk.Widget? d_select_actions; + private Binding? d_selectable_mode_binding; + private GitgExt.SelectionMode d_selectable_mode; + private UIElements d_activities; // Widgets @@ -71,7 +74,7 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable [GtkChild] private Gtk.ScrolledWindow d_dash_scrolled_window; [GtkChild] - private Gitg.RepositoryListBox d_dash_view; + private DashView d_dash_view; [GtkChild] private Gtk.Stack d_stack_activities; @@ -145,22 +148,30 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable [GtkCallback] private void search_button_toggled(Gtk.ToggleButton button) { + var searchable = current_activity as GitgExt.Searchable; + if (button.get_active()) { d_search_entry.grab_focus(); + + d_search_entry.text = searchable.search_text; + searchable.search_visible = true; } else { - d_search_entry.set_text(""); + searchable.search_visible = false; } } [GtkCallback] private void search_entry_changed(Gtk.Editable entry) { - if (d_mode == Mode.DASH) + var searchable = current_activity as GitgExt.Searchable; + var ntext = (entry as Gtk.Entry).text; + + if (ntext != searchable.search_text) { - d_dash_view.filter_text((entry as Gtk.Entry).text); + searchable.search_text = ntext; } } @@ -180,6 +191,21 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable { add_action_entries(win_entries, this); + var selact = lookup_action("select"); + + selact.notify["state"].connect(() => { + var st = selact.get_state().get_boolean(); + + if (st) + { + selectable_mode = GitgExt.SelectionMode.SELECTION; + } + else + { + selectable_mode = GitgExt.SelectionMode.NORMAL; + } + }); + d_interface_settings = new Settings("org.gnome.gitg.preferences.interface"); string menuname; @@ -275,7 +301,17 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable public GitgExt.Activity? current_activity { - owned get { return d_activities.current; } + owned get + { + if (d_mode == Mode.ACTIVITY) + { + return d_activities.current; + } + else + { + return d_dash_view; + } + } } public GitgExt.MessageBus message_bus @@ -353,8 +389,6 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable d_activities_switcher.hide(); d_dash_button.hide(); d_gear_menu.menu_model = d_dash_model; - d_search_button.visible = true; - d_select_button.visible = true; } d_activities.update(); @@ -363,6 +397,11 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable { activate_default_activity(); } + + if (d_mode == Mode.DASH) + { + on_current_activity_changed(); + } } protected override bool window_state_event(Gdk.EventWindowState event) @@ -471,19 +510,44 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable author_details.show(); } - private void on_current_activity_changed(Object obj, ParamSpec pspec) + private void on_current_activity_changed() { notify_property("current_activity"); - d_search_button.visible = (d_activities.current is GitgExt.Searchable); - d_select_button.visible = (d_activities.current is GitgExt.Selectable); + var current = current_activity; - if (!d_search_button.visible) + var searchable = current as GitgExt.Searchable; + + if (searchable != null) { + d_search_button.visible = true; + d_search_entry.text = searchable.search_text; + d_search_button.active = searchable.search_visible; + } + else + { + d_search_button.visible = false; d_search_button.active = false; + d_search_entry.text = ""; } - if (!d_select_button.visible) + var selectable = (current as GitgExt.Selectable); + d_select_button.visible = (selectable != null); + + if (d_selectable_mode_binding != null) + { + d_selectable_mode_binding.unbind(); + d_selectable_mode_binding = null; + } + + if (selectable != null) + { + d_selectable_mode_binding = selectable.bind_property("selectable-mode", + this, + "selectable-mode", + BindingFlags.DEFAULT); + } + else { d_select_button.active = false; } @@ -742,122 +806,60 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable } } - private void remove_selected_repositories() - { - foreach (var sel in d_dash_view.selection) - { - sel.request_remove(); - } - } - - [GtkCallback] - private bool dash_view_button_press(Gdk.EventButton event) - { - Gdk.Event *ev = (Gdk.Event *)event; - - if (ev->triggers_context_menu() && !d_dash_view.is_selection) - { - d_select_button.active = true; - return true; - } - - return false; - } - - private Gtk.Widget make_dash_select_actions() - { - var ab = new Gtk.ActionBar(); - - var del = new Gtk.Button.with_mnemonic(_("_Delete")); - del.sensitive = false; - del.show(); - - del.clicked.connect(() => { - remove_selected_repositories(); - d_select_button.active = false; - }); - - d_dash_view.bind_property("has-selection", - del, - "sensitive"); - - ab.pack_end(del); - - return ab; - } - private void on_select_activated(SimpleAction action) { - if (d_mode != Mode.DASH && !(d_activities.current is GitgExt.Selectable)) + var st = action.get_state().get_boolean(); + action.set_state(new Variant.boolean(!st)); + } + + public GitgExt.SelectionMode selectable_mode + { + get { return d_selectable_mode; } + set { - return; - } - - var state = action.get_state().get_boolean(); - var nstate = !state; - - Gtk.Widget? select_actions = null; - - if (d_mode == Mode.ACTIVITY) - { - var selectable = d_activities.current as GitgExt.Selectable; + var selectable = current_activity as GitgExt.Selectable; if (selectable == null) { return; } - if (nstate) + d_selectable_mode = value; + selectable.selectable_mode = value; + + var ctx = d_header_bar.get_style_context(); + + if (d_selectable_mode == GitgExt.SelectionMode.SELECTION) { - selectable.mode = GitgExt.SelectionMode.SELECT; + ctx.add_class("selection-mode"); + + d_select_actions = selectable.action_widget; + + if (d_select_actions != null) + { + d_grid_main.attach(d_select_actions, 0, 3, 1, 1); + d_select_actions.show(); + } } else { - selectable.mode = GitgExt.SelectionMode.NORMAL; + ctx.remove_class("selection-mode"); + + if (d_select_actions != null) + { + d_select_actions.destroy(); + d_select_actions = null; + } } + + var issel = (d_selectable_mode == GitgExt.SelectionMode.SELECTION); + + d_header_bar.show_close_button = !issel; + d_search_button.visible = !issel; + d_gear_menu.visible = !issel; + d_select_button.visible = !issel; + d_select_cancel_button.visible = issel; } - else - { - d_dash_view.is_selection = nstate; - - if (nstate) - { - select_actions = make_dash_select_actions(); - } - } - - var ctx = d_header_bar.get_style_context(); - - if (nstate) - { - ctx.add_class("selection-mode"); - - d_select_actions = select_actions; - - if (d_select_actions != null) - { - d_grid_main.attach(d_select_actions, 0, 3, 1, 1); - d_select_actions.show(); - } - } - else - { - ctx.remove_class("selection-mode"); - - if (d_select_actions != null) - { - d_select_actions.destroy(); - d_select_actions = null; - } - } - - d_header_bar.show_close_button = !nstate; - d_search_button.visible = !nstate; - d_gear_menu.visible = !nstate; - d_select_button.visible = !nstate; - d_select_cancel_button.visible = nstate; - - action.set_state(new Variant.boolean(nstate)); } [GtkCallback] diff --git a/gitg/resources/ui/gitg-window.ui b/gitg/resources/ui/gitg-window.ui index d2199ce6..cd96c3e5 100644 --- a/gitg/resources/ui/gitg-window.ui +++ b/gitg/resources/ui/gitg-window.ui @@ -235,12 +235,11 @@ - + True True - diff --git a/libgitg-ext/gitg-ext-searchable.vala b/libgitg-ext/gitg-ext-searchable.vala index 23a8852e..ec3c761b 100644 --- a/libgitg-ext/gitg-ext-searchable.vala +++ b/libgitg-ext/gitg-ext-searchable.vala @@ -28,6 +28,9 @@ namespace GitgExt */ public interface Searchable : Object, Activity { + public abstract string search_text { owned get; set; } + public abstract bool search_visible { get; set; } + public abstract bool search_enabled { get; set; } } } diff --git a/libgitg-ext/gitg-ext-selectable.vala b/libgitg-ext/gitg-ext-selectable.vala index ef82b994..99c5f16a 100644 --- a/libgitg-ext/gitg-ext-selectable.vala +++ b/libgitg-ext/gitg-ext-selectable.vala @@ -23,7 +23,7 @@ namespace GitgExt public enum SelectionMode { NORMAL, - SELECT + SELECTION } /** @@ -34,7 +34,10 @@ public enum SelectionMode */ public interface Selectable : Object, Activity { - public abstract SelectionMode mode { set; } + [Notify] + public abstract SelectionMode selectable_mode { get; set; } + + public abstract Gtk.Widget? action_widget { owned get; } } diff --git a/libgitg/gitg-repository-list-box.vala b/libgitg/gitg-repository-list-box.vala index 824e9e1b..af618623 100644 --- a/libgitg/gitg-repository-list-box.vala +++ b/libgitg/gitg-repository-list-box.vala @@ -19,11 +19,19 @@ namespace Gitg { + public enum SelectionMode + { + NORMAL, + SELECTION + } + public class RepositoryListBox : Gtk.ListBox { - private static Gtk.IconSize d_icon_size; private string? d_filter_text; + public signal void repository_activated(Repository repository); + public signal void show_error(string primary_message, string secondary_message); + [GtkTemplate (ui = "/org/gnome/gitg/gtk/gitg-repository-list-box-row.ui")] public class Row : Gtk.ListBoxRow { @@ -50,22 +58,26 @@ namespace Gitg public signal void request_remove(); - private bool d_is_selection; + private SelectionMode d_mode; - public bool is_selection + private static Gtk.IconSize s_icon_size; + + static construct { - get - { - return d_is_selection; - } + s_icon_size = Gtk.icon_size_register("gitg", 64, 64); + } + + public SelectionMode mode + { + get { return d_mode; } set { - if (d_is_selection != value) + if (d_mode != value) { - d_is_selection = value; + d_mode = value; - d_remove_revealer.reveal_child = d_is_selection; + d_remove_revealer.reveal_child = (d_mode == SelectionMode.SELECTION); d_remove_check_button.active = false; } @@ -73,7 +85,7 @@ namespace Gitg } [Notify] - public new bool is_selected + public new bool selected { get; set; } @@ -82,7 +94,7 @@ namespace Gitg { d_remove_check_button.bind_property("active", this, - "is-selected", + "selected", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); } @@ -95,6 +107,7 @@ namespace Gitg d_repository = value; branch_name = ""; + if (d_repository != null) { try @@ -168,7 +181,7 @@ namespace Gitg d_has_remote = value; var folder_icon_name = d_has_remote ? "folder-remote" : "folder"; - d_image.set_from_icon_name(folder_icon_name, d_icon_size); + d_image.set_from_icon_name(folder_icon_name, s_icon_size); } } @@ -178,27 +191,32 @@ namespace Gitg } } - public signal void repository_activated(Repository repository); - public signal void show_error(string primary_message, string secondary_message); + [Notify] + public SelectionMode mode { get; set; } - public bool is_selection { get; set; } + protected override bool button_press_event(Gdk.EventButton event) + { + Gdk.Event *ev = (Gdk.Event *)event; + + if (ev->triggers_context_menu() && mode == SelectionMode.NORMAL) + { + mode = SelectionMode.SELECTION; + return true; + } + + return false; + } protected override void row_activated(Gtk.ListBoxRow row) { - if (is_selection) + var r = (Row)row; + + if (mode == SelectionMode.SELECTION) { - var r = row as Row; - - if (r != null && r.is_selection) - { - r.is_selected = !r.is_selected; - } - + r.selected = !r.selected; return; } - var r = (Row)row; - if (r.repository != null) { repository_activated(r.repository); @@ -207,14 +225,12 @@ namespace Gitg construct { - d_icon_size = Gtk.icon_size_register ("gitg", 64, 64); - set_header_func(update_header); set_filter_func(filter); set_sort_func(compare_widgets); show(); - set_selection_mode (Gtk.SelectionMode.NONE); + set_selection_mode(Gtk.SelectionMode.NONE); add_recent_info(); } @@ -289,6 +305,7 @@ namespace Gitg foreach (var child in get_children()) { var d = (Row)child; + if (d.repository.get_location().equal(repository.get_location())) { row = d; @@ -339,14 +356,14 @@ namespace Gitg if (f != null) { - bind_property("is-selection", + bind_property("mode", row, - "is-selection"); + "mode"); } if (f != null) { - row.notify["is-selected"].connect(() => { + row.notify["selected"].connect(() => { notify_property("has-selection"); }); @@ -390,9 +407,9 @@ namespace Gitg foreach (var row in get_children()) { - var r = row as Row; + var r = (Row)row; - if (r != null && r.can_remove && r.is_selected) + if (r.selected) { ret += r; } @@ -408,9 +425,9 @@ namespace Gitg { foreach (var row in get_children()) { - var r = row as Row; + var r = (Row)row; - if (r != null && r.can_remove && r.is_selected) + if (r.selected) { return true; } @@ -504,7 +521,7 @@ namespace Gitg } // Clone - Row row = new Row(subfolder_name, "Cloning...", true); + var row = new Row(subfolder_name, "Cloning...", true); row.loading = true; row.show(); add(row);