[california] Create "Toolkit" namespace for widgetry
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california] Create "Toolkit" namespace for widgetry
- Date: Fri, 4 Apr 2014 01:29:18 +0000 (UTC)
commit 8e8a7e8391151dda115850dd85736e65d2247cf3
Author: Jim Nelson <jim yorba org>
Date: Thu Apr 3 18:27:30 2014 -0700
Create "Toolkit" namespace for widgetry
This also abolishes the old clunky Host.Interaction and makes all
UI panes Toolkit.Cards hosted in Toolkit.Decks. This is a more
flexible system and allows for these cards to be strung together
in single-window dialogs as well as GtkPopovers.
Finally, the old color chooser popup was removed in favor of using
GtkColorButton in the Calendar Manager.
src/Makefile.am | 17 +-
src/activator/activator-instance-list.vala | 10 +-
src/activator/activator-instance.vala | 2 +-
src/activator/activator-window.vala | 8 +-
src/activator/activator.vala | 2 +
.../activator-google-authenticating-pane.vala | 4 +-
.../activator-google-calendar-list-pane.vala | 12 +-
.../google/activator-google-login-pane.vala | 4 +-
src/activator/google/activator-google.vala | 4 +-
src/activator/webcal/activator-webcal-pane.vala | 4 +-
src/activator/webcal/activator-webcal.vala | 4 +-
src/collection/collection-iterable.vala | 203 ++++++++++++++++++++
src/host/host-color-chooser-popup.vala | 36 ----
src/host/host-create-update-event.vala | 15 ++-
src/host/host-interaction.vala | 52 -----
src/host/host-main-window.vala | 19 +-
src/host/host-modal-window.vala | 79 --------
src/host/host-show-event.vala | 13 ++-
src/host/host.vala | 2 +
src/manager/manager-calendar-list-item.vala | 22 +--
src/manager/manager-calendar-list.vala | 13 ++-
src/manager/manager-window.vala | 4 +-
src/manager/manager.vala | 2 +
src/rc/calendar-manager-list-item.ui | 8 +-
.../toolkit-calendar-popup.vala} | 2 +-
src/toolkit/toolkit-card.vala | 119 ++++++++++++
src/toolkit/toolkit-deck-window.vala | 50 +++++
.../util-deck.vala => toolkit/toolkit-deck.vala} | 131 ++-----------
.../toolkit-listbox-model.vala} | 19 +--
.../host-popup.vala => toolkit/toolkit-popup.vala} | 2 +-
src/toolkit/toolkit.vala | 29 +++
src/util/util-interfaces.vala | 24 +++
32 files changed, 541 insertions(+), 374 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 071c509..074b53d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -65,6 +65,7 @@ california_VALASOURCES = \
calendar/calendar-week-span.vala \
calendar/calendar-year.vala \
\
+ collection/collection-iterable.vala \
collection/collection-simple-iterator.vala \
collection/collection-simple-iterable.vala \
\
@@ -77,13 +78,8 @@ california_VALASOURCES = \
component/component-vtype.vala \
\
host/host.vala \
- host/host-calendar-popup.vala \
- host/host-color-chooser-popup.vala \
host/host-create-update-event.vala \
- host/host-interaction.vala \
host/host-main-window.vala \
- host/host-modal-window.vala \
- host/host-popup.vala \
host/host-show-event.vala \
\
manager/manager.vala \
@@ -91,9 +87,16 @@ california_VALASOURCES = \
manager/manager-calendar-list-item.vala \
manager/manager-window.vala \
\
- util/util-deck.vala \
+ toolkit/toolkit.vala \
+ toolkit/toolkit-calendar-popup.vala \
+ toolkit/toolkit-card.vala \
+ toolkit/toolkit-deck.vala \
+ toolkit/toolkit-listbox-model.vala \
+ toolkit/toolkit-deck-window.vala \
+ toolkit/toolkit-popup.vala \
+ \
util/util-gfx.vala \
- util/util-listbox-model.vala \
+ util/util-interfaces.vala \
util/util-memory.vala \
util/util-string.vala \
util/util-uri.vala \
diff --git a/src/activator/activator-instance-list.vala b/src/activator/activator-instance-list.vala
index f7c3bcb..e8583e1 100644
--- a/src/activator/activator-instance-list.vala
+++ b/src/activator/activator-instance-list.vala
@@ -7,7 +7,7 @@
namespace California.Activator {
[GtkTemplate (ui = "/org/yorba/california/rc/activator-list.ui")]
-public class InstanceList : Gtk.Grid, Card {
+public class InstanceList : Gtk.Grid, Toolkit.Card {
public const string ID = "ActivatorInstanceList";
public string card_id { get { return ID; } }
@@ -24,14 +24,14 @@ public class InstanceList : Gtk.Grid, Card {
[GtkChild]
private Gtk.Button add_button;
- private ListBoxModel<Instance> model;
+ private Toolkit.ListBoxModel<Instance> model;
public InstanceList() {
- model = new ListBoxModel<Instance>(listbox, model_presentation, activator_comparator);
+ model = new Toolkit.ListBoxModel<Instance>(listbox, model_presentation, activator_comparator);
model.add_many(activators);
model.activated.connect(on_item_activated);
- model.bind_property(ListBoxModel.PROP_SELECTED, add_button, "sensitive", BindingFlags.SYNC_CREATE,
+ model.bind_property(Toolkit.ListBoxModel.PROP_SELECTED, add_button, "sensitive",
BindingFlags.SYNC_CREATE,
selected_to_sensitive);
show_all();
@@ -43,7 +43,7 @@ public class InstanceList : Gtk.Grid, Card {
return true;
}
- public void jumped_to(Card? from, Value? message) {
+ public void jumped_to(Toolkit.Card? from, Value? message) {
}
private void on_item_activated(Instance activator) {
diff --git a/src/activator/activator-instance.vala b/src/activator/activator-instance.vala
index ae9393b..5926d25 100644
--- a/src/activator/activator-instance.vala
+++ b/src/activator/activator-instance.vala
@@ -49,7 +49,7 @@ public abstract class Instance : BaseObject {
*
* The first Card will be jumped to initially.
*/
- public abstract Gee.List<Card> create_cards(Soup.URI? supplied_uri);
+ public abstract Gee.List<Toolkit.Card> create_cards(Soup.URI? supplied_uri);
public override string to_string() {
return title;
diff --git a/src/activator/activator-window.vala b/src/activator/activator-window.vala
index ed14006..7df1c2b 100644
--- a/src/activator/activator-window.vala
+++ b/src/activator/activator-window.vala
@@ -10,24 +10,20 @@ namespace California.Activator {
* A modal window for selecting and managing { link Activator.Instance} workflows.
*/
-public class Window : Host.ModalWindow {
+public class Window : Toolkit.DeckWindow {
private static Activator.Window? instance = null;
- private Deck deck = new Deck();
-
private Window(Gtk.Window? parent) {
base (parent);
// The Deck is pre-populated with each of their Cards, with the InstanceList jumping to
// the right set when asked to (and acting as home)
- Gee.List<Card> cards = new Gee.ArrayList<Card>();
+ Gee.List<Toolkit.Card> cards = new Gee.ArrayList<Toolkit.Card>();
cards.add(new InstanceList());
foreach (Instance activator in activators)
cards.add_all(activator.create_cards(null));
deck.add_cards(cards);
-
- content_area.add(deck);
}
public static void display(Gtk.Window? parent) {
diff --git a/src/activator/activator.vala b/src/activator/activator.vala
index 27bddf7..e32d619 100644
--- a/src/activator/activator.vala
+++ b/src/activator/activator.vala
@@ -25,6 +25,7 @@ public void init() throws Error {
return;
Backing.init();
+ Toolkit.init();
activators = new Gee.ArrayList<Instance>();
@@ -43,6 +44,7 @@ public void terminate() {
activators = null;
Backing.terminate();
+ Toolkit.terminate();
}
}
diff --git a/src/activator/google/activator-google-authenticating-pane.vala
b/src/activator/google/activator-google-authenticating-pane.vala
index ca9800f..5914081 100644
--- a/src/activator/google/activator-google-authenticating-pane.vala
+++ b/src/activator/google/activator-google-authenticating-pane.vala
@@ -7,7 +7,7 @@
namespace California.Activator {
[GtkTemplate (ui = "/org/yorba/california/rc/google-authenticating.ui")]
-public class GoogleAuthenticatingPane : Gtk.Grid, Card {
+public class GoogleAuthenticatingPane : Gtk.Grid, Toolkit.Card {
public const string ID = "GoogleAuthenticatingPane";
private const int SUCCESS_DELAY_MSEC = 1500;
@@ -55,7 +55,7 @@ public class GoogleAuthenticatingPane : Gtk.Grid, Card {
app_id = "yorba-california-%s".printf(Application.VERSION);
}
- public void jumped_to(Card? from, Value? message) {
+ public void jumped_to(Toolkit.Card? from, Value? message) {
Message? credentials = message as Message;
assert(credentials != null);
diff --git a/src/activator/google/activator-google-calendar-list-pane.vala
b/src/activator/google/activator-google-calendar-list-pane.vala
index f50afa7..31643e4 100644
--- a/src/activator/google/activator-google-calendar-list-pane.vala
+++ b/src/activator/google/activator-google-calendar-list-pane.vala
@@ -7,7 +7,7 @@
namespace California.Activator {
[GtkTemplate (ui = "/org/yorba/california/rc/google-calendar-list.ui")]
-public class GoogleCalendarListPane : Gtk.Grid, Card {
+public class GoogleCalendarListPane : Gtk.Grid, Toolkit.Card {
public const string ID = "GoogleCalendarListPane";
public class Message : BaseObject {
@@ -45,8 +45,8 @@ public class GoogleCalendarListPane : Gtk.Grid, Card {
private Backing.CalDAVSubscribable store;
private string? username = null;
- private ListBoxModel<GData.CalendarCalendar> own_calendars_model;
- private ListBoxModel<GData.CalendarCalendar> unowned_calendars_model;
+ private Toolkit.ListBoxModel<GData.CalendarCalendar> own_calendars_model;
+ private Toolkit.ListBoxModel<GData.CalendarCalendar> unowned_calendars_model;
public GoogleCalendarListPane(Backing.CalDAVSubscribable store) {
this.store = store;
@@ -54,9 +54,9 @@ public class GoogleCalendarListPane : Gtk.Grid, Card {
own_calendars_listbox.set_placeholder(create_placeholder());
unowned_calendars_listbox.set_placeholder(create_placeholder());
- own_calendars_model = new ListBoxModel<GData.CalendarCalendar>(own_calendars_listbox,
+ own_calendars_model = new Toolkit.ListBoxModel<GData.CalendarCalendar>(own_calendars_listbox,
entry_to_widget, entry_comparator);
- unowned_calendars_model = new ListBoxModel<GData.CalendarCalendar>(unowned_calendars_listbox,
+ unowned_calendars_model = new Toolkit.ListBoxModel<GData.CalendarCalendar>(unowned_calendars_listbox,
entry_to_widget, entry_comparator);
}
@@ -67,7 +67,7 @@ public class GoogleCalendarListPane : Gtk.Grid, Card {
return label;
}
- public void jumped_to(Card? from, Value? message) {
+ public void jumped_to(Toolkit.Card? from, Value? message) {
Message? feeds = message as Message;
assert(feeds != null);
diff --git a/src/activator/google/activator-google-login-pane.vala
b/src/activator/google/activator-google-login-pane.vala
index 438af3e..856db52 100644
--- a/src/activator/google/activator-google-login-pane.vala
+++ b/src/activator/google/activator-google-login-pane.vala
@@ -7,7 +7,7 @@
namespace California.Activator {
[GtkTemplate (ui = "/org/yorba/california/rc/google-login.ui")]
-internal class GoogleLoginPane : Gtk.Grid, Card {
+internal class GoogleLoginPane : Gtk.Grid, Toolkit.Card {
public const string ID = "GoogleLoginPane";
public string card_id { get { return ID; } }
@@ -34,7 +34,7 @@ internal class GoogleLoginPane : Gtk.Grid, Card {
BindingFlags.SYNC_CREATE, on_entry_changed);
}
- public void jumped_to(Card? from, Value? msg) {
+ public void jumped_to(Toolkit.Card? from, Value? msg) {
password_entry.text = "";
}
diff --git a/src/activator/google/activator-google.vala b/src/activator/google/activator-google.vala
index 973c3aa..e667e49 100644
--- a/src/activator/google/activator-google.vala
+++ b/src/activator/google/activator-google.vala
@@ -17,8 +17,8 @@ internal class GoogleActivator : Instance {
caldav_store = store;
}
- public override Gee.List<Card> create_cards(Soup.URI? supplied_uri) {
- Gee.List<Card> cards = new Gee.ArrayList<Card>();
+ public override Gee.List<Toolkit.Card> create_cards(Soup.URI? supplied_uri) {
+ Gee.List<Toolkit.Card> cards = new Gee.ArrayList<Toolkit.Card>();
cards.add(new GoogleLoginPane());
cards.add(new GoogleAuthenticatingPane());
cards.add(new GoogleCalendarListPane(caldav_store));
diff --git a/src/activator/webcal/activator-webcal-pane.vala b/src/activator/webcal/activator-webcal-pane.vala
index b1cb10e..20d4d83 100644
--- a/src/activator/webcal/activator-webcal-pane.vala
+++ b/src/activator/webcal/activator-webcal-pane.vala
@@ -7,7 +7,7 @@
namespace California.Activator {
[GtkTemplate (ui = "/org/yorba/california/rc/webcal-subscribe.ui")]
-internal class WebCalActivatorPane : Gtk.Grid, Card {
+internal class WebCalActivatorPane : Gtk.Grid, Toolkit.Card {
public const string ID = "WebCalActivatorPane";
public string card_id { get { return ID; } }
@@ -46,7 +46,7 @@ internal class WebCalActivatorPane : Gtk.Grid, Card {
BindingFlags.SYNC_CREATE, on_entry_changed);
}
- public void jumped_to(Card? from, Value? message) {
+ public void jumped_to(Toolkit.Card? from, Value? message) {
}
private bool on_entry_changed(Binding binding, Value source_value, ref Value target_value) {
diff --git a/src/activator/webcal/activator-webcal.vala b/src/activator/webcal/activator-webcal.vala
index 9d91dda..a74b301 100644
--- a/src/activator/webcal/activator-webcal.vala
+++ b/src/activator/webcal/activator-webcal.vala
@@ -17,8 +17,8 @@ internal class WebCalActivator : Instance {
webcal_store = store;
}
- public override Gee.List<Card> create_cards(Soup.URI? supplied_uri) {
- Gee.List<Card> cards = new Gee.ArrayList<Card>();
+ public override Gee.List<Toolkit.Card> create_cards(Soup.URI? supplied_uri) {
+ Gee.List<Toolkit.Card> cards = new Gee.ArrayList<Toolkit.Card>();
cards.add(new WebCalActivatorPane(webcal_store, supplied_uri));
return cards;
diff --git a/src/collection/collection-iterable.vala b/src/collection/collection-iterable.vala
new file mode 100644
index 0000000..1bd9cbf
--- /dev/null
+++ b/src/collection/collection-iterable.vala
@@ -0,0 +1,203 @@
+/* Copyright 2013-2014 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.
+ */
+
+namespace California {
+
+/**
+ * Take a Gee object and return a California.Iterable for convenience.
+ */
+public California.Iterable<G> traverse<G>(Gee.Iterable<G> i) {
+ return new California.Iterable<G>(i.iterator());
+}
+
+/**
+ * Take some non-null items (all must be of type G) and return a
+ * California.Iterable for convenience.
+ */
+public California.Iterable<G> iterate<G>(G g, ...) {
+ va_list args = va_list();
+ G arg = g;
+
+ Gee.ArrayList<G> list = new Gee.ArrayList<G>();
+ do {
+ list.add(arg);
+ } while((arg = args.arg()) != null);
+
+ return California.traverse<G>(list);
+}
+
+/**
+ * An Iterable that simply wraps an existing Iterator. You get one iteration,
+ * and only one iteration. Basically every method triggers one iteration and
+ * returns a new object.
+ *
+ * Note that this can't inherit from Gee.Iterable because its interface
+ * requires that map/filter/etc. return Iterators, not Iterables. It still
+ * works in foreach.
+ */
+
+public class Iterable<G> : BaseObject {
+ /**
+ * A private class that lets us take a California.Iterable and convert it back
+ * into a Gee.Iterable.
+ */
+ private class GeeIterable<G> : Gee.Traversable<G>, Gee.Iterable<G>, BaseObject {
+ private Gee.Iterator<G> i;
+
+ public GeeIterable(Gee.Iterator<G> iterator) {
+ i = iterator;
+ }
+
+ public Gee.Iterator<G> iterator() {
+ return i;
+ }
+
+ // Unfortunately necessary for Gee.Traversable.
+ public virtual bool @foreach(Gee.ForallFunc<G> f) {
+ foreach (G g in this) {
+ if (!f(g))
+ return false;
+ }
+ return true;
+ }
+
+ public override string to_string() {
+ return "GeeIterable";
+ }
+ }
+
+ private Gee.Iterator<G> i;
+
+ public Iterable(Gee.Iterator<G> iterator) {
+ i = iterator;
+ }
+
+ public virtual Gee.Iterator<G> iterator() {
+ return i;
+ }
+
+ public Iterable<A> map<A>(Gee.MapFunc<A, G> f) {
+ return new Iterable<A>(i.map<A>(f));
+ }
+
+ public Iterable<A> scan<A>(Gee.FoldFunc<A, G> f, owned A seed) {
+ return new Iterable<A>(i.scan<A>(f, seed));
+ }
+
+ public Iterable<G> filter(owned Gee.Predicate<G> f) {
+ return new Iterable<G>(i.filter((owned) f));
+ }
+
+ public Iterable<G> chop(int offset, int length = -1) {
+ return new Iterable<G>(i.chop(offset, length));
+ }
+
+ public Iterable<A> map_nonnull<A>(Gee.MapFunc<A, G> f) {
+ return new Iterable<A>(i.map<A>(f).filter(g => g != null));
+ }
+
+ /**
+ * Return only objects of the destination type, as the destination type.
+ * Only works on types derived from Object.
+ */
+ public Iterable<A> cast_object<A>() {
+ return new Iterable<G>(
+ // This would be a lot simpler if valac didn't barf on the shorter,
+ // more obvious syntax for each of these delegates here.
+ i.filter(g => ((Object) g).get_type().is_a(typeof(A)))
+ .map<A>(g => { return (A) g; }));
+ }
+
+ public G? first() {
+ return (i.next() ? i get() : null);
+ }
+
+ public G? first_matching(owned Gee.Predicate<G> f) {
+ foreach (G g in this) {
+ if (f(g))
+ return g;
+ }
+ return null;
+ }
+
+ public bool any(owned Gee.Predicate<G> f) {
+ foreach (G g in this) {
+ if (f(g))
+ return true;
+ }
+ return false;
+ }
+
+ public bool all(owned Gee.Predicate<G> f) {
+ foreach (G g in this) {
+ if (!f(g))
+ return false;
+ }
+ return true;
+ }
+
+ public int count_matching(owned Gee.Predicate<G> f) {
+ int count = 0;
+ foreach (G g in this) {
+ if (f(g))
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * The resulting Gee.Iterable comes with the same caveat that you may only
+ * iterate over it once.
+ */
+ public Gee.Iterable<G> to_gee_iterable() {
+ return new GeeIterable<G>(i);
+ }
+
+ public Gee.Collection<G> add_all_to(Gee.Collection<G> c) {
+ while (i.next())
+ c.add(i get());
+ return c;
+ }
+
+ public Gee.ArrayList<G> to_array_list(owned Gee.EqualDataFunc<G>? equal_func = null) {
+ return (Gee.ArrayList<G>) add_all_to(new Gee.ArrayList<G>((owned) equal_func));
+ }
+
+ public Gee.LinkedList<G> to_linked_list(owned Gee.EqualDataFunc<G>? equal_func = null) {
+ return (Gee.LinkedList<G>) add_all_to(new Gee.LinkedList<G>((owned) equal_func));
+ }
+
+ public Gee.HashSet<G> to_hash_set(owned Gee.HashDataFunc<G>? hash_func = null,
+ owned Gee.EqualDataFunc<G>? equal_func = null) {
+ return (Gee.HashSet<G>) add_all_to(new Gee.HashSet<G>((owned) hash_func, (owned) equal_func));
+ }
+
+ public Gee.TreeSet<G> to_tree_set(owned CompareDataFunc<G>? compare_func = null) {
+ return (Gee.TreeSet<G>) add_all_to(new Gee.TreeSet<G>((owned) compare_func));
+ }
+
+ public Gee.Map<K, G> add_all_to_map<K>(Gee.Map<K, G> c, Gee.MapFunc<K, G> key_func) {
+ while (i.next()) {
+ G g = i get();
+ c set(key_func(g), g);
+ }
+ return c;
+ }
+
+ public Gee.HashMap<K, G> to_hash_map<K>(Gee.MapFunc<K, G> key_func,
+ owned Gee.HashDataFunc<K>? key_hash_func = null,
+ owned Gee.EqualDataFunc<K>? key_equal_func = null,
+ owned Gee.EqualDataFunc<G>? value_equal_func = null) {
+ return (Gee.HashMap<K, G>) add_all_to_map<K>(new Gee.HashMap<K, G>(
+ (owned) key_hash_func, (owned) key_equal_func, (owned) value_equal_func), key_func);
+ }
+
+ public override string to_string() {
+ return "Iterable";
+ }
+}
+
+}
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index 17ed8c4..7e8530a 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -11,15 +11,23 @@ namespace California.Host {
*/
[GtkTemplate (ui = "/org/yorba/california/rc/create-update-event.ui")]
-public class CreateUpdateEvent : Gtk.Grid, Interaction {
+public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
+ public const string ID = "CreateUpdateEvent";
+
public const string PROP_SELECTED_DATE_SPAN = "selected-date-span";
private const int START_HOUR = 0;
private const int END_HOUR = 23;
private const int MIN_DIVISIONS = 15;
+ public string card_id { get { return ID; } }
+
+ public string? title { get { return null; } }
+
public Gtk.Widget? default_widget { get { return accept_button; } }
+ public Gtk.Widget? initial_focus { get { return summary_entry; } }
+
[GtkChild]
private Gtk.Entry summary_entry;
@@ -198,6 +206,9 @@ public class CreateUpdateEvent : Gtk.Grid, Interaction {
BindingFlags.SYNC_CREATE);
}
+ public void jumped_to(Toolkit.Card? from, Value? message) {
+ }
+
[GtkCallback]
private void on_date_button_clicked(Gtk.Button button) {
bool is_dtstart = (button == dtstart_date_button);
@@ -208,7 +219,7 @@ public class CreateUpdateEvent : Gtk.Grid, Interaction {
both_date_buttons_touched
|| (last_date_button_touched != null && last_date_button_touched != button);
- CalendarPopup popup = new CalendarPopup(button,
+ Toolkit.CalendarPopup popup = new Toolkit.CalendarPopup(button,
is_dtstart ? selected_date_span.start_date : selected_date_span.end_date);
popup.date_selected.connect((date) => {
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index 96b072d..1706122 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -124,18 +124,17 @@ public class MainWindow : Gtk.ApplicationWindow {
add(layout);
}
- private void show_interaction(Gtk.Widget relative_to, Gdk.Point? for_location,
- Interaction child) {
- ModalWindow modal_window = new ModalWindow(this);
- modal_window.content_area.add(child);
+ private void show_deck(Gtk.Widget relative_to, Gdk.Point? for_location, Gee.List<Toolkit.Card> cards) {
+ Toolkit.DeckWindow deck_window = new Toolkit.DeckWindow(this);
+ deck_window.deck.add_cards(cards);
// when the dialog closes, reset View.Controllable state (selection is maintained while
// use is viewing/editing Interaction) and destroy widgets
- child.dismissed.connect(() => current_view.unselect_all());
+ deck_window.deck.dismissed.connect(() => current_view.unselect_all());
- modal_window.show_all();
- modal_window.run();
- modal_window.destroy();
+ deck_window.show_all();
+ deck_window.run();
+ deck_window.destroy();
}
private void on_new_event() {
@@ -189,7 +188,7 @@ public class MainWindow : Gtk.ApplicationWindow {
update_event_async.begin(event, null);
});
- show_interaction(relative_to, for_location, create_update_event);
+ show_deck(relative_to, for_location, iterate<Toolkit.Card>(create_update_event).to_array_list());
}
private async void create_event_async(Component.Event event, Cancellable? cancellable) {
@@ -226,7 +225,7 @@ public class MainWindow : Gtk.ApplicationWindow {
create_event(null, null, event, relative_to, for_location);
});
- show_interaction(relative_to, for_location, show_event);
+ show_deck(relative_to, for_location, iterate<Toolkit.Card>(show_event).to_array_list());
}
private async void remove_event_async(Component.Event event, Cancellable? cancellable) {
diff --git a/src/host/host-show-event.vala b/src/host/host-show-event.vala
index af612c1..169d8c7 100644
--- a/src/host/host-show-event.vala
+++ b/src/host/host-show-event.vala
@@ -7,9 +7,17 @@
namespace California.Host {
[GtkTemplate (ui = "/org/yorba/california/rc/show-event.ui")]
-public class ShowEvent : Gtk.Grid, Interaction {
+public class ShowEvent : Gtk.Grid, Toolkit.Card {
+ public const string ID = "ShowEvent";
+
+ public string card_id { get { return ID; } }
+
+ public string? title { get { return null; } }
+
public Gtk.Widget? default_widget { get { return close_button; } }
+ public Gtk.Widget? initial_focus { get { return close_button; } }
+
[GtkChild]
private Gtk.Label text_label;
@@ -41,6 +49,9 @@ public class ShowEvent : Gtk.Grid, Interaction {
Calendar.System.instance.today_changed.disconnect(build_display);
}
+ public void jumped_to(Toolkit.Card? from, Value? message) {
+ }
+
private void build_display() {
// Each string should end without whitespace; add_lf_lf will ensure each section is
// separated as long as there's preceding text
diff --git a/src/host/host.vala b/src/host/host.vala
index 82a8dcb..c11f7ba 100644
--- a/src/host/host.vala
+++ b/src/host/host.vala
@@ -22,6 +22,7 @@ public void init() throws Error {
View.init();
Backing.init();
Calendar.init();
+ Toolkit.init();
}
public void terminate() {
@@ -31,6 +32,7 @@ public void terminate() {
View.terminate();
Backing.terminate();
Calendar.terminate();
+ Toolkit.terminate();
}
}
diff --git a/src/manager/manager-calendar-list-item.vala b/src/manager/manager-calendar-list-item.vala
index 11a3bb2..14983d5 100644
--- a/src/manager/manager-calendar-list-item.vala
+++ b/src/manager/manager-calendar-list-item.vala
@@ -23,7 +23,7 @@ public class CalendarListItem : Gtk.Grid {
private Gtk.Label title_label;
[GtkChild]
- private Gtk.Button color_button;
+ private Gtk.ColorButton color_button;
public CalendarListItem(Backing.CalendarSource source) {
this.source = source;
@@ -38,25 +38,7 @@ public class CalendarListItem : Gtk.Grid {
}
private void on_color_changed() {
- Gdk.Pixbuf pixbuf = new Gdk.Pixbuf(Gdk.Colorspace.RGB, false, 8, COLOR_DIM, COLOR_DIM);
- pixbuf.fill(Gfx.rgba_to_pixel(source.color_as_rgba()));
-
- color_button.set_image(new Gtk.Image.from_pixbuf(pixbuf));
- }
-
- [GtkCallback]
- private void on_color_button_clicked() {
- Host.ColorChooserPopup popup = new Host.ColorChooserPopup(color_button, source.color_as_rgba());
-
- popup.selected.connect((rgba) => {
- source.set_color_to_rgba(rgba);
- });
-
- popup.dismissed.connect(() => {
- popup.destroy();
- });
-
- popup.show_all();
+ color_button.set_color(source.color_as_rgb());
}
}
diff --git a/src/manager/manager-calendar-list.vala b/src/manager/manager-calendar-list.vala
index 4f396a9..5d1ce98 100644
--- a/src/manager/manager-calendar-list.vala
+++ b/src/manager/manager-calendar-list.vala
@@ -11,9 +11,17 @@ namespace California.Manager {
*/
[GtkTemplate (ui = "/org/yorba/california/rc/calendar-manager-list.ui")]
-public class CalendarList : Gtk.Grid, Host.Interaction {
+public class CalendarList : Gtk.Grid, Toolkit.Card {
+ public const string ID = "CalendarList";
+
+ public string card_id { get { return ID; } }
+
+ public string? title { get { return null; } }
+
public Gtk.Widget? default_widget { get { return null; } }
+ public Gtk.Widget? initial_focus { get { return calendar_list_box; } }
+
[GtkChild]
private Gtk.ListBox calendar_list_box;
@@ -30,6 +38,9 @@ public class CalendarList : Gtk.Grid, Host.Interaction {
Backing.Manager.instance.notify[Backing.Manager.PROP_IS_OPEN].disconnect(on_manager_opened_closed);
}
+ public void jumped_to(Toolkit.Card? from, Value? message) {
+ }
+
private void on_manager_opened_closed() {
if (Backing.Manager.instance.is_open)
init();
diff --git a/src/manager/manager-window.vala b/src/manager/manager-window.vala
index a910c6f..57b3855 100644
--- a/src/manager/manager-window.vala
+++ b/src/manager/manager-window.vala
@@ -10,13 +10,13 @@ namespace California.Manager {
* The Calendar Manager main window.
*/
-public class Window : Host.ModalWindow {
+public class Window : Toolkit.DeckWindow {
private static Manager.Window? instance = null;
private Window(Gtk.Window? parent) {
base (parent);
- content_area.add(new CalendarList());
+ deck.add_cards(iterate<Toolkit.Card>(new CalendarList()).to_array_list());
}
public static void display(Gtk.Window? parent) {
diff --git a/src/manager/manager.vala b/src/manager/manager.vala
index daf174d..bdac485 100644
--- a/src/manager/manager.vala
+++ b/src/manager/manager.vala
@@ -18,6 +18,7 @@ public void init() throws Error {
return;
Backing.init();
+ Toolkit.init();
}
public void terminate() {
@@ -25,6 +26,7 @@ public void terminate() {
return;
Backing.terminate();
+ Toolkit.terminate();
}
}
diff --git a/src/rc/calendar-manager-list-item.ui b/src/rc/calendar-manager-list-item.ui
index 0a8647e..a636784 100644
--- a/src/rc/calendar-manager-list-item.ui
+++ b/src/rc/calendar-manager-list-item.ui
@@ -47,17 +47,13 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="color_button">
+ <object class="GtkColorButton" id="color_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Calendar color</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <signal name="clicked" handler="on_color_button_clicked" object="CaliforniaManagerCalendarListItem"
swapped="no"/>
- <child>
- <placeholder/>
- </child>
+ <property name="title" translatable="yes">Calendar color</property>
</object>
<packing>
<property name="left_attach">1</property>
diff --git a/src/host/host-calendar-popup.vala b/src/toolkit/toolkit-calendar-popup.vala
similarity index 98%
rename from src/host/host-calendar-popup.vala
rename to src/toolkit/toolkit-calendar-popup.vala
index 4cd47d9..391dab0 100644
--- a/src/host/host-calendar-popup.vala
+++ b/src/toolkit/toolkit-calendar-popup.vala
@@ -4,7 +4,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
-namespace California.Host {
+namespace California.Toolkit {
/**
* A simple { link Popup} window featuring only a GtkCalendar.
diff --git a/src/toolkit/toolkit-card.vala b/src/toolkit/toolkit-card.vala
new file mode 100644
index 0000000..fb20277
--- /dev/null
+++ b/src/toolkit/toolkit-card.vala
@@ -0,0 +1,119 @@
+/* Copyright 2014 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.
+ */
+
+namespace California.Toolkit {
+
+/**
+ * A Card is a single pane of widget(s) in a { link Deck}.
+ *
+ * The navigation of Cards is tracked within their Deck, and Cards can request navigation via their
+ * various signals. They're also notified when nevigation which affects them is made.
+ */
+
+public interface Card : Gtk.Widget {
+ /**
+ * Each { link Card} has its own identifier that should be unique within the { link Deck}.
+ *
+ * In the Gtk.Stack, this is its name.
+ */
+ public abstract string card_id { get; }
+
+ /**
+ * A user-visible string that may be used elsewhere in the application.
+ *
+ * Gtk.StackSwitcher uses this title. { link Deck} does not use the title in any way.
+ */
+ public abstract string? title { get; }
+
+ /**
+ * The widget the { link Card} wants to be default when navigated to.
+ *
+ * The widget must have can-default set to true.
+ */
+ public abstract Gtk.Widget? default_widget { get; }
+
+ /**
+ * The widget the { link Card} wants to have initial focus when navigated to.
+ *
+ * Focus is set after { link default_widget} is handled, so if this widget has receives-default
+ * set to true, it will get the default as well.
+ *
+ * The widget must have can-focus set to true.
+ */
+ public abstract Gtk.Widget? initial_focus { get; }
+
+ /**
+ * Returns the { link Deck} this { link Card} is registered to, if any.
+ */
+ public Deck? deck { get { return parent as Deck; } }
+
+ /**
+ * Fired when the { link Card} wishes to jump to another Card in the same { link Deck.}
+ *
+ * Each Card can accept a message which parameterizes its activation. It's up to Cards
+ * navigating to the new one to construct and pass an appropriate message.
+ *
+ * @see jump_to_card_by_name
+ */
+ public signal void jump_to_card(Card next, Value? message);
+
+ /**
+ * Fired when the { link Card} wishes to jump to another Card by its name.
+ *
+ * @see jump_to_card
+ */
+ public signal void jump_to_card_by_name(string name, Value? message);
+
+ /**
+ * Fired when the { link Card} wishes to jump to the previous Card in the { link Deck}.
+ *
+ * Note that this Card's position in the navigation stack is lost; there is no "jump forward".
+ */
+ public signal void jump_back();
+
+ /**
+ * Fired when the { link Card} wishes to jump to the first Card in the { link Deck}.
+ *
+ * This clears the Deck's navigation stack, meaning { link jump_back} will not return to
+ * this Card.
+ */
+ public signal void jump_home();
+
+ /**
+ * Fired when the { link Deck}'s work is cancelled, closed, or dismissed, whether due to
+ * programmatic reasons or by user request.
+ *
+ * Implementing classes should fire this after firing the { link completed signal} so
+ * subscribers can maintain their cleanup in a single handler.
+ */
+ public signal void dismissed(bool user_request);
+
+ /**
+ * Fired when the { link Deck}'s work has completed successfully.
+ *
+ * This should only be fired if the Deck requires valid input from the user to perform
+ * some intensive operation. Merely displaying information and closing the Deck
+ * should simply fire { link dismissed}.
+ *
+ * "completed" implies that dismissed will be called shortly thereafter, meaning all
+ * cleanup can be handled there.
+ */
+ public signal void completed();
+
+ /**
+ * Called by { link Deck} when the { link Card} has been activated, i.e. put to the "top" of
+ * the Deck.
+ *
+ * message may be null even if the Card expects one; generally this means { link jump_back}
+ * or { link jump_home} was invoked, resulting in this Card being activated.
+ *
+ * This is called before dealing with { link default_widget} and { link initial_focus}, so
+ * changes to those properties in this call, if need be.
+ */
+ public abstract void jumped_to(Card? from, Value? message);
+}
+
+}
diff --git a/src/toolkit/toolkit-deck-window.vala b/src/toolkit/toolkit-deck-window.vala
new file mode 100644
index 0000000..333f709
--- /dev/null
+++ b/src/toolkit/toolkit-deck-window.vala
@@ -0,0 +1,50 @@
+/* Copyright 2014 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.
+ */
+
+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.
+ */
+
+public class DeckWindow : Gtk.Dialog {
+ public Deck deck { get; private set; default = new Deck(); }
+
+ private Gtk.ResponseType response_type = Gtk.ResponseType.CLOSE;
+
+ public DeckWindow(Gtk.Window? parent) {
+ transient_for = parent;
+ modal = true;
+ resizable = false;
+
+ deck.dismissed.connect(on_deck_dismissed);
+ deck.completed.connect(on_deck_completed);
+
+ Gtk.Box content_area = (Gtk.Box) get_content_area();
+ content_area.margin = 8;
+ content_area.add(deck);
+
+ get_action_area().visible = false;
+ get_action_area().no_show_all = true;
+ }
+
+ private void on_deck_completed() {
+ response_type = Gtk.ResponseType.OK;
+ }
+
+ private void on_deck_dismissed() {
+ response(response_type);
+ }
+}
+
+}
+
diff --git a/src/util/util-deck.vala b/src/toolkit/toolkit-deck.vala
similarity index 70%
rename from src/util/util-deck.vala
rename to src/toolkit/toolkit-deck.vala
index c564152..20c587d 100644
--- a/src/util/util-deck.vala
+++ b/src/toolkit/toolkit-deck.vala
@@ -4,97 +4,58 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
-namespace California {
+namespace California.Toolkit {
/**
- * A Card is a single pane of widget(s) in a { link Deck}.
+ * A Deck is a collection of { link Card}s maintained within a Gtk.Stack.
*
- * The navigation of Cards is tracked within their Deck, and Cards can request navigation via their
- * various signals. They're also notified when nevigation which affects them is made.
+ * Cards control navigation through their various signals, which Deck monitors and acts upon.
+ * It also notifies Cards of nagivation changes which affect them via their abstract methods.
*/
-public interface Card : Gtk.Widget {
- /**
- * Each { link Card} has its own identifier that should be unique within the { link Deck}.
- *
- * In the Gtk.Stack, this is its name.
- */
- public abstract string card_id { get; }
-
- /**
- * A user-visible string that may be used elsewhere in the application.
- *
- * Gtk.StackSwitcher uses this title. { link Deck} does not use the title in any way.
- */
- public abstract string? title { get; }
-
- /**
- * The widget the { link Card} wants to be default when navigated to.
- *
- * The widget must have can-default set to true.
- */
- public abstract Gtk.Widget? default_widget { get; }
-
+public class Deck : Gtk.Stack {
/**
- * The widget the { link Card} wants to have initial focus when navigated to.
- *
- * Focus is set after { link default_widget} is handled, so if this widget has receives-default
- * set to true, it will get the default as well.
- *
- * The widget must have can-focus set to true.
+ * @inheritedDoc
*/
- public abstract Gtk.Widget? initial_focus { get; }
+ public Gtk.Widget? default_widget { get { return null; } }
/**
- * Returns the { link Deck} this { link Card} is registered to, if any.
+ * The number of { link Card}s registered to the { link Deck}.
*/
- public Deck? deck { get { return parent as Deck; } }
+ public int size { get { return list.size; } }
/**
- * Fired when the { link Card} wishes to jump to another Card in the same { link Deck.}
- *
- * Each Card can accept a message which parameterizes its activation. It's up to Cards
- * navigating to the new one to construct and pass an appropriate message.
- *
- * @see jump_to_card_by_name
+ * All registered { link Card}s returned as a read-only List.
*/
- public signal void jump_to_card(Card next, Value? message);
+ public Gee.List<Card> cards { owned get { return list.read_only_view; } }
/**
- * Fired when the { link Card} wishes to jump to another Card by its name.
- *
- * @see jump_to_card
+ * The home { link Card}.
*/
- public signal void jump_to_card_by_name(string name, Value? message);
+ public Card? home { owned get { return (list.size > 0) ? list[0] : null; } }
/**
- * Fired when the { link Card} wishes to jump to the previous Card in the { link Deck}.
- *
- * Note that this Card's position in the navigation stack is lost; there is no "jump forward".
+ * The current displayed { link Card}.
*/
- public signal void jump_back();
+ public Card? top { get; private set; default = null; }
- /**
- * Fired when the { link Card} wishes to jump to the first Card in the { link Deck}.
- *
- * This clears the Deck's navigation stack, meaning { link jump_back} will not return to
- * this Card.
- */
- public signal void jump_home();
+ private Gee.List<Card> list = new Gee.LinkedList<Card>();
+ private Gee.Deque<Card> navigation_stack = new Gee.LinkedList<Card>();
+ private Gee.HashMap<string, Card> names = new Gee.HashMap<string, Card>();
/**
* Fired when the { link Deck}'s work is cancelled, closed, or dismissed, whether due to
* programmatic reasons or by user request.
*
- * Implementing classes should fire this after firing the { link completed signal} so
- * subscribers can maintain their cleanup in a single handler.
+ * This will be fired after firing the { link completed signal} so subscribers can maintain
+ * their cleanup in a single handler.
*/
public signal void dismissed(bool user_request);
/**
* Fired when the { link Deck}'s work has completed successfully.
*
- * This should only be fired if the Deck requires valid input from the user to perform
+ * This will only be fired if the Deck requires valid input from the user to perform
* some intensive operation. Merely displaying information and closing the Deck
* should simply fire { link dismissed}.
*
@@ -104,56 +65,6 @@ public interface Card : Gtk.Widget {
public signal void completed();
/**
- * Called by { link Deck} when the { link Card} has been activated, i.e. put to the "top" of
- * the Deck.
- *
- * message may be null even if the Card expects one; generally this means { link jump_back}
- * or { link jump_home} was invoked, resulting in this Card being activated.
- *
- * This is called before dealing with { link default_widget} and { link initial_focus}, so
- * changes to those properties in this call, if need be.
- */
- public abstract void jumped_to(Card? from, Value? message);
-}
-
-/**
- * A Deck is a collection of { link Card}s maintained within a Gtk.Stack.
- *
- * Cards control navigation through their various signals, which Deck monitors and acts upon.
- * It also notifies Cards of nagivation changes which affect them via their abstract methods.
- */
-
-public class Deck : Gtk.Stack, Host.Interaction {
- /**
- * @inheritedDoc
- */
- public Gtk.Widget? default_widget { get { return null; } }
-
- /**
- * The number of { link Card}s registered to the { link Deck}.
- */
- public int size { get { return list.size; } }
-
- /**
- * All registered { link Card}s returned as a read-only List.
- */
- public Gee.List<Card> cards { owned get { return list.read_only_view; } }
-
- /**
- * The home { link Card}.
- */
- public Card? home { owned get { return (list.size > 0) ? list[0] : null; } }
-
- /**
- * The current displayed { link Card}.
- */
- public Card? top { get; private set; default = null; }
-
- private Gee.List<Card> list = new Gee.LinkedList<Card>();
- private Gee.Deque<Card> navigation_stack = new Gee.LinkedList<Card>();
- private Gee.HashMap<string, Card> names = new Gee.HashMap<string, Card>();
-
- /**
* Create a new { link Deck}.
*
* By default the Deck configures the underlying Gtk.Stack to slide left and right, depending
diff --git a/src/util/util-listbox-model.vala b/src/toolkit/toolkit-listbox-model.vala
similarity index 93%
rename from src/util/util-listbox-model.vala
rename to src/toolkit/toolkit-listbox-model.vala
index fb8f0d5..ebbd947 100644
--- a/src/util/util-listbox-model.vala
+++ b/src/toolkit/toolkit-listbox-model.vala
@@ -4,24 +4,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
-namespace California {
-
-/**
- * A { link Mutable} is an Object which can internally change state (i.e. is no immutable).
- *
- * { link ListBoxModel} recognizes when an Object supports this interface and will monitor its
- * { link mutated} signal.
- */
-
-public interface Mutable : Object {
- /**
- * Fired when important internal state has changed.
- *
- * This can be used by collections and other containers to update their own state, such as
- * re-sorting or re-applying filters.
- */
- public signal void mutated();
-}
+namespace California.Toolkit {
/**
* A simple model for Gtk.ListBox.
diff --git a/src/host/host-popup.vala b/src/toolkit/toolkit-popup.vala
similarity index 99%
rename from src/host/host-popup.vala
rename to src/toolkit/toolkit-popup.vala
index 5219753..beb76b8 100644
--- a/src/host/host-popup.vala
+++ b/src/toolkit/toolkit-popup.vala
@@ -4,7 +4,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
-namespace California.Host {
+namespace California.Toolkit {
/**
* A Popup is a single GtkWindow that grabs the application focus and dismisses itself if it
diff --git a/src/toolkit/toolkit.vala b/src/toolkit/toolkit.vala
new file mode 100644
index 0000000..7349b94
--- /dev/null
+++ b/src/toolkit/toolkit.vala
@@ -0,0 +1,29 @@
+/* Copyright 2014 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.
+ */
+
+/**
+ * A grab bag of utility classes for working with GTK.
+ */
+
+namespace California.Toolkit {
+
+private int init_count = 0;
+
+public void init() throws Error {
+ if (!Unit.do_init(ref init_count))
+ return;
+
+ Calendar.init();
+}
+
+public void terminate() {
+ if (!Unit.do_terminate(ref init_count))
+ return;
+
+ Calendar.terminate();
+}
+
+}
diff --git a/src/util/util-interfaces.vala b/src/util/util-interfaces.vala
new file mode 100644
index 0000000..9c98230
--- /dev/null
+++ b/src/util/util-interfaces.vala
@@ -0,0 +1,24 @@
+/* Copyright 2014 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.
+ */
+
+namespace California {
+
+/**
+ * A { link Mutable} is an Object which can internally change state (i.e. is no immutable).
+ */
+
+public interface Mutable : Object {
+ /**
+ * Fired when important internal state has changed.
+ *
+ * This can be used by collections and other containers to update their own state, such as
+ * re-sorting or re-applying filters.
+ */
+ public signal void mutated();
+}
+
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]