[california/wip/732029-gtk-312: 2/3] Final touches and some basic fixes for Gtk.Popover use
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/732029-gtk-312: 2/3] Final touches and some basic fixes for Gtk.Popover use
- Date: Fri, 18 Jul 2014 23:04:03 +0000 (UTC)
commit e152c08286172c3ac704e62f320ec79260320f37
Author: Jim Nelson <jim yorba org>
Date: Fri Jul 18 16:02:27 2014 -0700
Final touches and some basic fixes for Gtk.Popover use
src/activator/activator-window.vala | 5 ++++
src/collection/collection-iterable.vala | 4 ++-
src/host/host-main-window.vala | 6 +----
src/host/host-show-event.vala | 4 +-
src/manager/manager-window.vala | 5 ++++
src/toolkit/toolkit-deck-window.vala | 22 +++++++------------
src/toolkit/toolkit-rotating-button-box.vala | 23 ++++++++++++++++++++
src/toolkit/toolkit.vala | 29 ++++++++++++++++++++++++++
8 files changed, 76 insertions(+), 22 deletions(-)
---
diff --git a/src/activator/activator-window.vala b/src/activator/activator-window.vala
index 25158b6..95ff428 100644
--- a/src/activator/activator-window.vala
+++ b/src/activator/activator-window.vala
@@ -26,6 +26,11 @@ public class Window : Toolkit.DeckWindow {
public static void display(Gtk.Widget relative_to, Gdk.Point? for_location) {
Activator.Window instance = new Activator.Window(relative_to, for_location);
+
+ instance.dismiss.connect(() => {
+ Toolkit.destroy_later(instance);
+ });
+
instance.show_all();
}
}
diff --git a/src/collection/collection-iterable.vala b/src/collection/collection-iterable.vala
index 5648456..cc20101 100644
--- a/src/collection/collection-iterable.vala
+++ b/src/collection/collection-iterable.vala
@@ -22,7 +22,9 @@ public California.Iterable<G> traverse<G>(Gee.Iterable<G>? gee_iterable) {
* it.
*
* "Safe iteration" means later operations that remove elements while iterating do not cause an
- * assertion.
+ * assertion. This involves creating a copy of the supplied Gee.Iterable, meaning that any changes
+ * made in subsequence operations (i.e. { link California.Iterable.filter} are not reflected in
+ * the passed-in collection.
*
* An empty Gee.Iterable is created and used if null is passed in.
*/
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index f96f325..fd55705 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -339,12 +339,8 @@ public class MainWindow : Gtk.ApplicationWindow {
// when the dialog closes, reset View.Controllable state (selection is maintained while
// use is viewing/editing interaction) and destroy widgets
deck_window.dismiss.connect(() => {
- debug("dismissed");
current_controller.unselect_all();
- deck_window.hide();
- // give the dialog a change to hide before allowing other signals to fire, which may
- // invoke another dialog (prevents multiple dialogs on screen at same time)
- Toolkit.spin_event_loop();
+ Toolkit.destroy_later(deck_window);
});
deck_window.deck.failure.connect((msg) => {
diff --git a/src/host/host-show-event.vala b/src/host/host-show-event.vala
index ebd1bc1..e406dd5 100644
--- a/src/host/host-show-event.vala
+++ b/src/host/host-show-event.vala
@@ -131,10 +131,10 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
bool read_only = event.calendar_source != null && event.calendar_source.read_only;
update_button.visible = !read_only;
- update_button.no_show_all = !read_only;
+ update_button.no_show_all = read_only;
remove_button.visible = !read_only;
- remove_button.no_show_all = !read_only;
+ remove_button.no_show_all = read_only;
}
private string? escape(string? plain) {
diff --git a/src/manager/manager-window.vala b/src/manager/manager-window.vala
index 4c1a440..a798243 100644
--- a/src/manager/manager-window.vala
+++ b/src/manager/manager-window.vala
@@ -21,6 +21,11 @@ public class Window : Toolkit.DeckWindow {
public static void display(Gtk.Widget relative_to, Gdk.Point? for_location) {
Manager.Window instance = new Manager.Window(relative_to, for_location);
+
+ instance.dismiss.connect(() => {
+ Toolkit.destroy_later(instance);
+ });
+
instance.show_all();
}
diff --git a/src/toolkit/toolkit-deck-window.vala b/src/toolkit/toolkit-deck-window.vala
index f1d9d8f..80b2d41 100644
--- a/src/toolkit/toolkit-deck-window.vala
+++ b/src/toolkit/toolkit-deck-window.vala
@@ -7,26 +7,24 @@
namespace California.Toolkit {
/**
- * A GtkDialog with no visible action area.
- *
- * This is designed for UI panes that want to control their own interaction with the user (in
- * particular, button placement) but need all the benefits interaction-wise of GtkDialog.
- *
- * It's expected this will go away when we move to GTK+ 3.12 and can use GtkPopovers for these
- * interactions.
+ * A GtkPopover with special support for { link Deck}s.
*/
public class DeckWindow : Gtk.Popover {
public Deck deck { get; private set; }
+ /**
+ * See { link Card.dismiss}
+ */
public signal void dismiss(bool user_request, bool final);
public DeckWindow(Gtk.Widget rel_to, Gdk.Point? for_location, Deck? starter_deck) {
Object (relative_to: rel_to);
- // Toolkit.RotatingButtonBox requires DeckWindow not be modal because when rotating the
- // buttons something occurs (probably a focus switch) that causes it to dismiss
- modal = false;
+ // treat "closed" signal as dismissal by user request
+ closed.connect(() => {
+ dismiss(true, true);
+ });
this.deck = starter_deck ?? new Deck();
@@ -48,14 +46,10 @@ public class DeckWindow : Gtk.Popover {
~DeckWindow() {
deck.dismiss.disconnect(on_deck_dismissed);
- debug("CTOR");
}
private void on_deck_dismissed(bool user_request, bool final) {
- debug("deck dismissed");
dismiss(user_request, final);
- if (final)
- destroy();
}
}
diff --git a/src/toolkit/toolkit-rotating-button-box.vala b/src/toolkit/toolkit-rotating-button-box.vala
index 13778f7..716463d 100644
--- a/src/toolkit/toolkit-rotating-button-box.vala
+++ b/src/toolkit/toolkit-rotating-button-box.vala
@@ -33,16 +33,39 @@ public class RotatingButtonBox : Gtk.Stack {
public string? family { get; set; }
private Gee.HashMap<string, Gtk.ButtonBox> button_boxes = new Gee.HashMap<string, Gtk.ButtonBox>();
+ private Gtk.Popover? parent_popover = null;
+ private bool parent_popover_modal = false;
public RotatingButtonBox() {
homogeneous = true;
transition_duration = SLOW_STACK_TRANSITION_DURATION_MSEC;
transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT;
+ notify["transition-running"].connect(on_transition_running);
+
bind_property("visible-child-name", this, PROP_FAMILY,
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
}
+ // unfortunately, RotatingButtonBox can cause modal Popovers to close because the focus
+ // changes from one button box to another, triggering a situation in GtkWidget where the
+ // Popover thinks it has lost focus ... this hacks around the problem by setting the popover
+ // to modeless until the transition is complete
+ private void on_transition_running() {
+ if (transition_running && parent_popover == null) {
+ // set to modeless to hack around problem
+ parent_popover = get_ancestor(typeof (Gtk.Popover)) as Gtk.Popover;
+ if (parent_popover != null) {
+ parent_popover_modal = parent_popover.modal;
+ parent_popover.modal = false;
+ }
+ } else if (!transition_running && parent_popover != null) {
+ // reset to original mode
+ parent_popover.modal = parent_popover_modal;
+ parent_popover = null;
+ }
+ }
+
/**
* Pack a Gtk.Button at the start of a particular family, creating the family if necessary.
*
diff --git a/src/toolkit/toolkit.vala b/src/toolkit/toolkit.vala
index 2630ed5..ca38290 100644
--- a/src/toolkit/toolkit.vala
+++ b/src/toolkit/toolkit.vala
@@ -33,19 +33,28 @@ public const bool STOP = true;
public const bool PROPAGATE = false;
private int init_count = 0;
+private Gee.Set<Gtk.Widget>? dead_pool = null;
+private Scheduled? dead_pool_gc = null;
public void init() throws Error {
if (!Unit.do_init(ref init_count))
return;
+ dead_pool = new Gee.HashSet<Gtk.Widget>();
+
Calendar.init();
+ Collection.init();
}
public void terminate() {
if (!Unit.do_terminate(ref init_count))
return;
+ Collection.terminate();
Calendar.terminate();
+
+ dead_pool = null;
+ dead_pool_gc = null;
}
/**
@@ -94,4 +103,24 @@ public void set_unbusy(Gtk.Widget widget, Gdk.Cursor? unbusy_cursor) {
toplevel.get_window().set_cursor(unbusy_cursor);
}
+/**
+ * Destroy a Gtk.Widget when the event loop is idle.
+ */
+public void destroy_later(Gtk.Widget widget) {
+ if (!dead_pool.add(widget))
+ return;
+
+ // always reschedule
+ dead_pool_gc = new Scheduled.once_at_idle(() => {
+ // traverse_safely makes a copy of the dead_pool, so filter() won't work to remove destroyed
+ // elements, but that also means we can safely remove elements from it in the iterate()
+ // handler ... need to jump through these hoops because the widget.destroy() signal handlers
+ // may turn around and add more widgets to the dead pool during traversal
+ traverse_safely<Gtk.Widget>(dead_pool).iterate((widget) => {
+ widget.destroy();
+ dead_pool.remove(widget);
+ });
+ }, Priority.LOW);
+}
+
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]