[california] Unify Show Event and Create/Update Event dialogs
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california] Unify Show Event and Create/Update Event dialogs
- Date: Thu, 24 Apr 2014 00:29:11 +0000 (UTC)
commit 09e678137541b65beb9c38dd37401f2cd49f8a51
Author: Jim Nelson <jim yorba org>
Date: Wed Apr 23 17:08:29 2014 -0700
Unify Show Event and Create/Update Event dialogs
src/component/component-instance.vala | 2 +-
src/host/host-create-update-event.vala | 177 +++++++++++++++-----------------
src/host/host-main-window.vala | 61 ++++--------
src/host/host-show-event.vala | 17 ++--
src/rc/create-update-event.ui | 47 ++++-----
src/toolkit/toolkit-card.vala | 10 ++
src/toolkit/toolkit-deck.vala | 33 ++++++
7 files changed, 179 insertions(+), 168 deletions(-)
---
diff --git a/src/component/component-instance.vala b/src/component/component-instance.vala
index 8c56076..f5c62ba 100644
--- a/src/component/component-instance.vala
+++ b/src/component/component-instance.vala
@@ -168,7 +168,7 @@ public abstract class Instance : BaseObject, Gee.Hashable<Instance> {
}
/**
- * Updates the { link Instance} with information from the E.CalComponent.
+ * Updates the { link Instance} with information from the iCal component.
*
* The Instance will update whatever changes it discovers from this new component and fire
* signals to update subscribers.
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index b77aacf..fa43c28 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -54,61 +54,67 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
public Calendar.DateSpan selected_date_span { get; set; }
- private new Component.Event event;
+ public bool is_update { get; set; default = false; }
+
+ private new Component.Event event = new Component.Event.blank();
private Gee.HashMap<string, Calendar.WallTime> time_map = new Gee.HashMap<string, Calendar.WallTime>();
- private Gee.List<Backing.CalendarSource> calendar_sources;
private Backing.CalendarSource? original_calendar_source;
- private Backing.CalendarSource? selected_calendar_source;
- private bool is_update = false;
+ private Toolkit.ComboBoxTextModel<Backing.CalendarSource> calendar_model;
private Gtk.Button? last_date_button_touched = null;
private bool both_date_buttons_touched = false;
- public signal void create_event(Component.Event event);
-
- public signal void update_event(Backing.CalendarSource? original_source, Component.Event event);
-
- public CreateUpdateEvent(Calendar.ExactTimeSpan initial) {
- event = new Component.Event.blank();
- event.set_event_exact_time_span(initial);
- original_calendar_source = null;
+ public CreateUpdateEvent() {
+ // when selected_date_span updates, update date buttons as well
+ notify[PROP_SELECTED_DATE_SPAN].connect(() => {
+ dtstart_date_button.label = selected_date_span.start_date.to_standard_string();
+ dtend_date_button.label = selected_date_span.end_date.to_standard_string();
+ });
- init();
- }
-
- public CreateUpdateEvent.all_day(Calendar.DateSpan initial) {
- event = new Component.Event.blank();
- event.set_event_date_span(initial);
- original_calendar_source = null;
+ // create button is active only if summary is filled out; all other fields (so far)
+ // guarantee valid values at all times
+ summary_entry.bind_property("text-length", accept_button, "sensitive",
+ BindingFlags.SYNC_CREATE);
- init();
- }
-
- public CreateUpdateEvent.update(Component.Event event) {
- this.event = event;
- original_calendar_source = event.calendar_source;
+ // hide start/end time widgets if an all-day event ..."no-show-all" needed to avoid the
+ // merciless effects of show_all()
+ all_day_toggle.bind_property("active", dtstart_time_combo, "visible",
+ BindingFlags.INVERT_BOOLEAN | BindingFlags.SYNC_CREATE);
+ dtstart_time_combo.no_show_all = true;
+ all_day_toggle.bind_property("active", dtend_time_combo, "visible",
+ BindingFlags.INVERT_BOOLEAN | BindingFlags.SYNC_CREATE);
+ dtend_time_combo.no_show_all = true;
- accept_button.label = _("_Update");
- is_update = true;
+ // use model to control calendars combo box
+ calendar_model = new Toolkit.ComboBoxTextModel<Backing.CalendarSource>(calendar_combo,
+ (cal) => cal.title);
+ foreach (Backing.CalendarSource calendar_source in
+ Backing.Manager.instance.get_sources_of_type<Backing.CalendarSource>()) {
+ if (!calendar_source.visible)
+ continue;
+
+ calendar_model.add(calendar_source);
+ }
- init();
+ update_controls();
}
- public CreateUpdateEvent.finish(Component.Event event) {
- this.event = event;
+ public void jumped_to(Toolkit.Card? from, Value? message) {
+ if (message != null) {
+ event = message as Component.Event;
+ assert(event != null);
+ } else {
+ event = new Component.Event.blank();
+ }
- init();
+ update_controls();
}
- private void init() {
+ private void update_controls() {
if (event.summary != null)
summary_entry.text = event.summary;
+ else
+ summary_entry.text = "";
- notify[PROP_SELECTED_DATE_SPAN].connect(() => {
- dtstart_date_button.label = selected_date_span.start_date.to_standard_string();
- dtend_date_button.label = selected_date_span.end_date.to_standard_string();
- });
-
- // date/date-time must be set in the Event prior to this call
Calendar.WallTime initial_start_time, initial_end_time;
if (event.exact_time_span != null) {
all_day_toggle.active = false;
@@ -131,7 +137,7 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
Calendar.System.now.adjust_time(1, Calendar.TimeUnit.HOUR));
}
- // initialize start and end time (as in, wall clock time)
+ // initialize start and end time controls (as in, wall clock time)
Calendar.WallTime current = new Calendar.WallTime(START_HOUR, Calendar.WallTime.MIN_MINUTE, 0);
Calendar.WallTime end = new Calendar.WallTime(END_HOUR, Calendar.WallTime.MAX_MINUTE, 0);
int index = 0;
@@ -168,57 +174,16 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
dtstart_time_combo.set_active(dtstart_active_index.clamp(0, index - 1));
dtend_time_combo.set_active(dtend_active_index.clamp(0, index - 1));
- // hide start/end time widgets if an all-day event ..."no-show-all" needed to avoid the
- // merciless effects of show_all()
- all_day_toggle.bind_property("active", dtstart_time_combo, "visible",
- BindingFlags.INVERT_BOOLEAN | BindingFlags.SYNC_CREATE);
- dtstart_time_combo.no_show_all = true;
- all_day_toggle.bind_property("active", dtend_time_combo, "visible",
- BindingFlags.INVERT_BOOLEAN | BindingFlags.SYNC_CREATE);
- dtend_time_combo.no_show_all = true;
-
- // initialize available calendars
- calendar_sources = Backing.Manager.instance.get_sources_of_type<Backing.CalendarSource>();
- calendar_sources.sort();
-
- index = 0;
- int calendar_source_index = 0;
- Gee.Iterator<Backing.Source> iter = calendar_sources.iterator();
- while (iter.next()) {
- Backing.Source source = iter.get();
-
- // drop from List to ensure ComboBox indices match array indices
- if (!source.visible) {
- iter.remove();
-
- continue;
- }
-
- calendar_combo.append_text(source.title);
- if (source == event.calendar_source)
- calendar_source_index = index;
-
- index++;
+ // set combo to event's calendar
+ if (event.calendar_source != null) {
+ calendar_model.set_item_active(event.calendar_source);
+ } else {
+ calendar_combo.active = 0;
+ is_update = false;
}
- // keep attribute up-to-date
- calendar_combo.notify["active"].connect(() => {
- if (calendar_combo.active >= 0 && calendar_combo.active < calendar_sources.size)
- selected_calendar_source = calendar_sources[calendar_combo.active];
- else
- selected_calendar_source = null;
- });
-
- // set now that handlers are in place
- calendar_combo.set_active(calendar_source_index);
-
- // create button is active only if summary is filled out; all other fields (so far)
- // guarantee valid values at all times
- summary_entry.bind_property("text-length", accept_button, "sensitive",
- BindingFlags.SYNC_CREATE);
- }
-
- public void jumped_to(Toolkit.Card? from, Value? message) {
+ accept_button.label = is_update ? _("_Update") : _("C_reate");
+ original_calendar_source = event.calendar_source;
}
[GtkCallback]
@@ -260,10 +225,10 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
[GtkCallback]
private void on_accept_clicked() {
- if (selected_calendar_source == null)
+ if (calendar_model.active == null)
return;
- event.calendar_source = selected_calendar_source;
+ event.calendar_source = calendar_model.active;
event.summary = summary_entry.text;
if (all_day_toggle.active) {
@@ -284,17 +249,43 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
}
if (is_update)
- update_event(original_calendar_source, event);
+ update_event_async.begin(null);
else
- create_event(event);
+ create_event_async.begin(null);
notify_success();
}
[GtkCallback]
private void on_cancel_button_clicked() {
- notify_user_closed();
+ jump_home_or_user_closed();
+ }
+
+ private async void create_event_async(Cancellable? cancellable) {
+ if (event.calendar_source == null)
+ return;
+
+ try {
+ yield event.calendar_source.create_component_async(event, cancellable);
+ notify_success();
+ } catch (Error err) {
+ notify_failure(_("Unable to create event: %s").printf(err.message));
+ }
}
+
+ // TODO: Delete from original source if not the same as the new source
+ private async void update_event_async(Cancellable? cancellable) {
+ if (event.calendar_source == null)
+ return;
+
+ try {
+ yield event.calendar_source.update_component_async(event, cancellable);
+ notify_success();
+ } catch (Error err) {
+ notify_failure(_("Unable to update event: %s").printf(err.message));
+ }
+ }
+
}
}
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index a4eec0d..1d2922e 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -153,7 +153,7 @@ public class MainWindow : Gtk.ApplicationWindow {
if (quick_create.parsed_event.is_valid())
create_event_async.begin(quick_create.parsed_event, null);
else
- create_event(null, null, quick_create.parsed_event, true, quick_add_button, null);
+ create_event(quick_create.parsed_event, quick_add_button, null);
});
Toolkit.Deck deck = new Toolkit.Deck();
@@ -176,39 +176,27 @@ public class MainWindow : Gtk.ApplicationWindow {
private void on_request_create_timed_event(Calendar.ExactTimeSpan initial, Gtk.Widget relative_to,
Gdk.Point? for_location) {
- create_event(initial, null, null, false, relative_to, for_location);
+ Component.Event event = new Component.Event.blank();
+ event.set_event_exact_time_span(initial);
+
+ create_event(event, relative_to, for_location);
}
private void on_request_create_all_day_event(Calendar.DateSpan initial, Gtk.Widget relative_to,
Gdk.Point? for_location) {
- create_event(null, initial, null, false, relative_to, for_location);
+ Component.Event event = new Component.Event.blank();
+ event.set_event_date_span(initial);
+
+ create_event(event, relative_to, for_location);
}
- private void create_event(Calendar.ExactTimeSpan? time_span, Calendar.DateSpan? date_span,
- Component.Event? existing, bool create_existing, Gtk.Widget relative_to, Gdk.Point? for_location) {
- assert(time_span != null || date_span != null || existing != null);
-
- CreateUpdateEvent create_update_event;
- if (time_span != null)
- create_update_event = new CreateUpdateEvent(time_span);
- else if (date_span != null)
- create_update_event = new CreateUpdateEvent.all_day(date_span);
- else if (create_existing)
- create_update_event = new CreateUpdateEvent.finish(existing);
- else
- create_update_event = new CreateUpdateEvent.update(existing);
-
- create_update_event.create_event.connect((event) => {
- create_event_async.begin(event, null);
- });
-
- create_update_event.update_event.connect((original_source, event) => {
- // TODO: Delete from original source if not the same as the new source
- update_event_async.begin(event, null);
- });
+ private void create_event(Component.Event event, Gtk.Widget relative_to, Gdk.Point? for_location) {
+ CreateUpdateEvent create_update_event = new CreateUpdateEvent();
+ create_update_event.is_update = false;
Toolkit.Deck deck = new Toolkit.Deck();
deck.add_cards(iterate<Toolkit.Card>(create_update_event).to_array_list());
+ deck.go_home(event);
show_deck(relative_to, for_location, deck);
}
@@ -224,31 +212,20 @@ public class MainWindow : Gtk.ApplicationWindow {
}
}
- private async void update_event_async(Component.Event event, Cancellable? cancellable) {
- if (event.calendar_source == null)
- return;
-
- try {
- yield event.calendar_source.update_component_async(event, cancellable);
- } catch (Error err) {
- debug("Unable to update event: %s", err.message);
- }
- }
-
private void on_request_display_event(Component.Event event, Gtk.Widget relative_to,
Gdk.Point? for_location) {
- ShowEvent show_event = new ShowEvent(event);
-
+ ShowEvent show_event = new ShowEvent();
show_event.remove_event.connect(() => {
remove_event_async.begin(event, null);
});
- show_event.update_event.connect(() => {
- create_event(null, null, event, false, relative_to, for_location);
- });
+ CreateUpdateEvent create_update_event = new CreateUpdateEvent();
+ create_update_event.is_update = true;
Toolkit.Deck deck = new Toolkit.Deck();
- deck.add_cards(iterate<Toolkit.Card>(show_event).to_array_list());
+ deck.add_card(show_event);
+ deck.add_card(create_update_event);
+ deck.go_home(event);
show_deck(relative_to, for_location, deck);
}
diff --git a/src/host/host-show-event.vala b/src/host/host-show-event.vala
index 9091e98..963149e 100644
--- a/src/host/host-show-event.vala
+++ b/src/host/host-show-event.vala
@@ -34,12 +34,7 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
public signal void remove_event(Component.Event event);
- public signal void update_event(Component.Event event);
-
- public ShowEvent(Component.Event event) {
- this.event = event;
-
- build_display();
+ public ShowEvent() {
Calendar.System.instance.is_24hr_changed.connect(build_display);
Calendar.System.instance.today_changed.connect(build_display);
}
@@ -50,6 +45,13 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
}
public void jumped_to(Toolkit.Card? from, Value? message) {
+ if (message == null)
+ return;
+
+ event = message as Component.Event;
+ assert(event != null);
+
+ build_display();
}
private void build_display() {
@@ -143,8 +145,7 @@ public class ShowEvent : Gtk.Grid, Toolkit.Card {
[GtkCallback]
private void on_update_button_clicked() {
- update_event(event);
- notify_success();
+ jump_to_card_by_name(CreateUpdateEvent.ID, event);
}
[GtkCallback]
diff --git a/src/rc/create-update-event.ui b/src/rc/create-update-event.ui
index d785f96..c1890ff 100644
--- a/src/rc/create-update-event.ui
+++ b/src/rc/create-update-event.ui
@@ -18,9 +18,9 @@
<property name="can_focus">True</property>
<property name="has_focus">True</property>
<property name="is_focus">True</property>
- <property name="max_length">64</property>
+ <property name="max_length">128</property>
<property name="activates_default">True</property>
- <property name="width_chars">24</property>
+ <property name="width_chars">48</property>
<property name="caps_lock_warning">False</property>
<property name="placeholder_text" translatable="yes">Untitled event</property>
</object>
@@ -121,25 +121,6 @@
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="all_day_toggle">
- <property name="label" translatable="yes">_All-day event</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">end</property>
- <property name="use_underline">True</property>
- <property name="xalign">0</property>
- <property name="image_position">right</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
<object class="GtkBox" id="calendar_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -180,12 +161,11 @@
<object class="GtkButtonBox" id="button_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">baseline</property>
- <property name="valign">baseline</property>
+ <property name="valign">end</property>
<property name="margin_top">8</property>
+ <property name="vexpand">True</property>
<property name="spacing">8</property>
<property name="homogeneous">True</property>
- <property name="baseline_position">bottom</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="cancel_button">
@@ -235,6 +215,25 @@
</packing>
</child>
<child>
+ <object class="GtkCheckButton" id="all_day_toggle">
+ <property name="label" translatable="yes">_All-day event</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="image_position">right</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
<placeholder/>
</child>
</template>
diff --git a/src/toolkit/toolkit-card.vala b/src/toolkit/toolkit-card.vala
index e192943..158a8a3 100644
--- a/src/toolkit/toolkit-card.vala
+++ b/src/toolkit/toolkit-card.vala
@@ -160,6 +160,16 @@ public interface Card : Gtk.Widget {
dismiss(true, false);
failure(user_message);
}
+
+ /**
+ * Jump home or, if this { link Card} is the home card, dismiss { link Deck}.
+ */
+ protected void jump_home_or_user_closed() {
+ if (deck.home == this)
+ notify_user_closed();
+ else
+ jump_home();
+ }
}
}
diff --git a/src/toolkit/toolkit-deck.vala b/src/toolkit/toolkit-deck.vala
index 306ba85..c8b6803 100644
--- a/src/toolkit/toolkit-deck.vala
+++ b/src/toolkit/toolkit-deck.vala
@@ -15,6 +15,11 @@ namespace California.Toolkit {
public class Deck : Gtk.Stack {
/**
+ * A slightly slower transition duration than default.
+ */
+ public const int DEFAULT_TRANSITION_MSEC = 300;
+
+ /**
* @inheritedDoc
*/
public Gtk.Widget? default_widget { get { return null; } }
@@ -67,6 +72,8 @@ public class Deck : Gtk.Stack {
*/
public Deck() {
transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT;
+ transition_duration = DEFAULT_TRANSITION_MSEC;
+
notify["visible-child"].connect(on_child_to_top);
}
@@ -104,6 +111,13 @@ public class Deck : Gtk.Stack {
}
/**
+ * A helper method for { link add_cards}.
+ */
+ public void add_card(Card card) {
+ add_cards(iterate<Card>(card).to_array_list());
+ }
+
+ /**
* Add { link Card}s to the { link Deck}.
*
* Cards can be added in multiple batches, but the ordering is important as it dictates how
@@ -182,6 +196,25 @@ public class Deck : Gtk.Stack {
}
}
+ /**
+ * Force the { link Deck} to jump to the { link home} { link Card}.
+ *
+ * In general, Deck avoids jumping to a Card if it's already displayed (on top). However, for
+ * this call it will call the Card's { link Card.jumped_to} method and pass the supplied
+ * message every time, even if already on top. This allows for this call to be used for Deck
+ * initialization.
+ */
+ public void go_home(Value? message) {
+ if (home == null)
+ return;
+
+ // clear navigation stack, this acts as a kind of reset
+ navigation_stack.clear();
+
+ set_visible_child(home);
+ home.jumped_to(null, message);
+ }
+
private void on_jump_to_card(Card card, Card next, Value? message) {
// do nothing if already visible
if (get_visible_child() == next) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]