[california/wip/725767-week] Flesh out week view, fix layout issues, hours down left-side
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/725767-week] Flesh out week view, fix layout issues, hours down left-side
- Date: Thu, 8 May 2014 02:58:02 +0000 (UTC)
commit 6242ef174c18de3e5a8ae7ba05d71f9eb07fe5ac
Author: Jim Nelson <jim yorba org>
Date: Wed May 7 19:57:25 2014 -0700
Flesh out week view, fix layout issues, hours down left-side
src/Makefile.am | 2 +
src/calendar/calendar-wall-time.vala | 5 +-
src/calendar/calendar.vala | 4 +-
src/host/host-main-window.vala | 3 +-
src/toolkit/toolkit-stack-model.vala | 2 -
src/view/month/month-cell.vala | 4 +-
src/view/month/month-controller.vala | 2 -
src/view/view-palette.vala | 5 +-
src/view/week/week-controller.vala | 6 --
src/view/week/week-day-pane.vala | 57 ++++++++++++++++++++++
src/view/week/week-grid.vala | 86 +++++++++++++++++++++------------
src/view/week/week-hour-runner.vala | 56 ++++++++++++++++++++++
src/view/week/week-pane.vala | 68 ++++++++++++---------------
13 files changed, 212 insertions(+), 88 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index a5b5de4..8bf8f9c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -136,7 +136,9 @@ california_VALASOURCES = \
\
view/week/week.vala \
view/week/week-controller.vala \
+ view/week/week-day-pane.vala \
view/week/week-grid.vala \
+ view/week/week-hour-runner.vala \
view/week/week-pane.vala \
\
$(NULL)
diff --git a/src/calendar/calendar-wall-time.vala b/src/calendar/calendar-wall-time.vala
index 495fafb..b8806be 100644
--- a/src/calendar/calendar-wall-time.vala
+++ b/src/calendar/calendar-wall-time.vala
@@ -361,8 +361,9 @@ public class WallTime : BaseObject, Gee.Comparable<WallTime>, Gee.Hashable<WallT
// Not marked for translation on thw assumption that a 12-hour hour followed by the meridiem
// isn't something that varies between locales, on the assumption that the user has
- // specified 12-hour time to begin with
- if (optional_min && minute == 0)
+ // specified 12-hour time to begin with ... don't allow for 24-hour time because it doesn't
+ // look right (especially early hours, i.e. "0", "2")
+ if (optional_min && minute == 0 && !is_24hr)
return "%d%s".printf(is_24hr ? hour : 12hour, meridiem);
if (!include_sec) {
diff --git a/src/calendar/calendar.vala b/src/calendar/calendar.vala
index db3cc06..4d6d705 100644
--- a/src/calendar/calendar.vala
+++ b/src/calendar/calendar.vala
@@ -156,10 +156,10 @@ public void init() throws Error {
FMT_12HOUR_MIN_SEC_MERIDIEM = _("%d:%02d:%02d%s");
/// The 24-hour time with minutes, i.e. "17:06"
- FMT_24HOUR_MIN = _("%d:%02d");
+ FMT_24HOUR_MIN = _("%02d:%02d");
/// The 24-hour time with minutes and seconds, i.e. "17:06:31"
- FMT_24HOUR_MIN_SEC = _("%d:%02d:%02d");
+ FMT_24HOUR_MIN_SEC = _("%02d:%02d:%02d");
// Used by quick-add to convert a user's day unit into an internal value. Common abbreviations
// (without punctuation) should be included. Each word must be separated by semi-colons.
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index 64c61b6..f629565 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -69,8 +69,9 @@ public class MainWindow : Gtk.ApplicationWindow {
view_stack.notify["visible-child"].connect(on_view_changed);
// add views to view stack, first added is first shown
- add_controller(month_view);
+ // TODO: Switch back to month_view first
add_controller(week_view);
+ add_controller(month_view);
// if not on Unity, use headerbar as the titlebar (removes window chrome) and provide close
// button for users who might have trouble finding it otherwise
diff --git a/src/toolkit/toolkit-stack-model.vala b/src/toolkit/toolkit-stack-model.vala
index c63f615..cbd72be 100644
--- a/src/toolkit/toolkit-stack-model.vala
+++ b/src/toolkit/toolkit-stack-model.vala
@@ -293,7 +293,6 @@ public class StackModel<G> : BaseObject {
if (stack_destroyed || in_balance_cache)
return;
- debug("%s: balance cache: %s", to_string(), why);
in_balance_cache = true;
// trim existing widgets from cache
@@ -319,7 +318,6 @@ public class StackModel<G> : BaseObject {
}
}
- debug("%s: cache balanced: %s", to_string(), why);
in_balance_cache = false;
}
diff --git a/src/view/month/month-cell.vala b/src/view/month/month-cell.vala
index cc3d773..7518af4 100644
--- a/src/view/month/month-cell.vala
+++ b/src/view/month/month-cell.vala
@@ -470,10 +470,10 @@ private class Cell : Gtk.EventBox {
y = Palette.TEXT_MARGIN_PX;
} else {
// starting y of "regular" lines
- y = Palette.TEXT_MARGIN_PX + Palette.instance.normal_font_height_px + Palette.LINE_SPACING_PX;
+ y = Palette.TEXT_MARGIN_PX + Palette.instance.normal_font_height_px + Palette.LINE_PADDING_PX;
// add additional lines
- y += line_number * (Palette.instance.small_font_height_px + Palette.LINE_SPACING_PX);
+ y += line_number * (Palette.instance.small_font_height_px + Palette.LINE_PADDING_PX);
}
return y;
diff --git a/src/view/month/month-controller.vala b/src/view/month/month-controller.vala
index c01c24c..b40a2df 100644
--- a/src/view/month/month-controller.vala
+++ b/src/view/month/month-controller.vala
@@ -121,8 +121,6 @@ public class Controller : BaseObject, View.Controllable {
}
private Gtk.Widget model_presentation(Calendar.MonthOfYear moy, out string? id) {
- debug("Creating month grid for %s", moy.to_string());
-
Grid grid = new Grid(this, moy);
id = grid.id;
diff --git a/src/view/view-palette.vala b/src/view/view-palette.vala
index a3dc4ee..ebdbf6e 100644
--- a/src/view/view-palette.vala
+++ b/src/view/view-palette.vala
@@ -20,9 +20,9 @@ public class Palette : BaseObject {
public const int TEXT_MARGIN_PX = 2;
/**
- * Line spacing when painting text (in pixels).
+ * Line padding when painting text (in pixels).
*/
- public const int LINE_SPACING_PX = 4;
+ public const int LINE_PADDING_PX = 4;
/**
* Hairline line width.
@@ -174,6 +174,7 @@ public class Palette : BaseObject {
public static Cairo.Context prepare_hairline_border(Cairo.Context ctx) {
Gdk.cairo_set_source_rgba(ctx, instance.border);
ctx.set_line_width(HAIRLINE_WIDTH);
+ ctx.set_dash(null, 0);
return ctx;
}
diff --git a/src/view/week/week-controller.vala b/src/view/week/week-controller.vala
index 0be5d54..e76f559 100644
--- a/src/view/week/week-controller.vala
+++ b/src/view/week/week-controller.vala
@@ -111,8 +111,6 @@ public class Controller : BaseObject, View.Controllable {
}
private Gtk.Widget model_presentation(Calendar.Week week, out string? id) {
- debug("Creating Grid for %s", week.to_string());
-
Grid week_grid = new Grid(week);
id = week_grid.id;
@@ -124,8 +122,6 @@ public class Controller : BaseObject, View.Controllable {
if (week.equal_to(Calendar.System.today.week_of(first_of_week)))
return false;
- debug("Trim %s: %s", week.to_string(), (!cache_span.has(week)).to_string());
-
// otherwise only keep weeks that are in the current cache span
return !cache_span.has(week);
}
@@ -137,8 +133,6 @@ public class Controller : BaseObject, View.Controllable {
// add today's week to the mix
weeks.add(Calendar.System.today.week_of(first_of_week));
- debug("ensuring %d weeks", weeks.size);
-
return weeks;
}
diff --git a/src/view/week/week-day-pane.vala b/src/view/week/week-day-pane.vala
new file mode 100644
index 0000000..714def6
--- /dev/null
+++ b/src/view/week/week-day-pane.vala
@@ -0,0 +1,57 @@
+/* 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.View.Week {
+
+internal class DayPane : Pane {
+ public const string PROP_OWNER = "owner";
+ public const string PROP_DATE = "date";
+ public const string PROP_SELECTED = "selected";
+
+ public Calendar.Date date { get; set; }
+
+ public bool selected { get; set; default = false; }
+
+ public DayPane(Grid owner, Calendar.Date date) {
+ base (owner, -1);
+
+ this.date = date;
+
+ notify[PROP_DATE].connect(queue_draw);
+ notify[PROP_SELECTED].connect(queue_draw);
+ Calendar.System.instance.is_24hr_changed.connect(queue_draw);
+ Calendar.System.instance.today_changed.connect(on_today_changed);
+ }
+
+ ~DayPane() {
+ Calendar.System.instance.is_24hr_changed.disconnect(queue_draw);
+ Calendar.System.instance.today_changed.disconnect(on_today_changed);
+ }
+
+ private void on_today_changed(Calendar.Date old_today, Calendar.Date new_today) {
+ // need to know re: redrawing background color to indicate current day
+ if (date.equal_to(old_today) || date.equal_to(new_today))
+ queue_draw();
+ }
+
+ // note that a painter's algorithm should be used here: background should be painted before
+ // calling base method, and foreground afterward
+ protected override bool on_draw(Cairo.Context ctx) {
+ // shade background color if this is current day or selected
+ if (selected) {
+ Gdk.cairo_set_source_rgba(ctx, Palette.instance.selection);
+ ctx.paint();
+ } else if (date.equal_to(Calendar.System.today)) {
+ Gdk.cairo_set_source_rgba(ctx, Palette.instance.current_day);
+ ctx.paint();
+ }
+
+ return base.on_draw(ctx);
+ }
+}
+
+}
+
diff --git a/src/view/week/week-grid.vala b/src/view/week/week-grid.vala
index a4a2eec..a68c24d 100644
--- a/src/view/week/week-grid.vala
+++ b/src/view/week/week-grid.vala
@@ -7,10 +7,22 @@
namespace California.View.Week {
/**
- * A Gtk.Grid that holds the various { link Pane}s for each day of thw week.
+ * A GTK container that holds the various { link Pane}s for each day of thw week.
+ *
+ * Although this looks to be the perfect use of Gtk.Grid, some serious limitations with that widget
+ * forced this implementation to fall back on the old "boxes within boxes" of GTK 2.0.
+ * Specifically, the top-left cell in this widget must be a fixed width (the same as
+ * { link HourRunner}'s) and Gtk.Grid wouldn't let that occur, always giving it more space than it
+ * needed (although, strangely, always honoring the requested width for HourRunner). This ruined
+ * the effect of an "empty" box in the top left corner where the date labels met the hour runner.
+ *
+ * The basic layout is a top row of date labels (with a spacer at the beginning, as mentioned)
+ * with a scrollable box of { link DayPane}s with an HourRunner on the left side which scrolls
+ * as well. This layout ensures the date labels are always visible as the user scrolls down the
+ * time of day for all the panes.
*/
-internal class Grid : Gtk.Grid {
+internal class Grid : Gtk.Box {
public const string PROP_WEEK = "week";
/**
@@ -25,56 +37,68 @@ internal class Grid : Gtk.Grid {
*/
public string id { owned get { return week.to_string(); } }
- private Gtk.Grid pane_grid = new Gtk.Grid();
- private Gtk.ScrolledWindow scrolled_panes = new Gtk.ScrolledWindow(null, null);
-
public Grid(Calendar.Week week) {
+ Object(orientation: Gtk.Orientation.VERTICAL, spacing: 0);
+
this.week = week;
- column_homogeneous = true;
- column_spacing = 0;
- row_homogeneous = false;
- row_spacing = 0;
+ // hold date labels in a horizontal box
+ Gtk.Box label_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
+ pack_start(label_box, false, true, 0);
- pane_grid.column_homogeneous = true;
+ // fixed size space in top left corner of "grid"
+ Gtk.DrawingArea spacer = new Gtk.DrawingArea();
+ spacer.set_size_request(HourRunner.REQUESTED_WIDTH, -1);
+ spacer.draw.connect(on_draw_bottom_line);
+ label_box.pack_start(spacer, false, false, 0);
+
+ // hold Panes (DayPanes and HourRunner) in a scrolling Gtk.Grid
+ Gtk.Grid pane_grid = new Gtk.Grid();
+ pane_grid.column_homogeneous = false;
pane_grid.column_spacing = 0;
- pane_grid.row_homogeneous = true;
+ pane_grid.row_homogeneous = false;
pane_grid.row_spacing = 0;
- scrolled_panes.hscrollbar_policy = Gtk.PolicyType.NEVER;
- scrolled_panes.vscrollbar_policy = Gtk.PolicyType.ALWAYS;
- scrolled_panes.add(pane_grid);
+ // attach an HourRunner to the left side of the Panes grid
+ pane_grid.attach(new HourRunner(this), 0, 0, 1, 1);
- // date labels across the top, week panes extending across the bottom, all stored inside
- // a scrolled window
- int col = 0;
+ // date labels across the top, week panes extending across the bottom ... start col at one
+ // to account for spacer/HourRunner
+ int col = 1;
foreach (Calendar.Date date in week) {
Gtk.Label date_label = new Gtk.Label("%s %d/%d".printf(date.day_of_week.abbrev_name,
date.month_of_year().month.value, date.day_of_month.value));
// draw a line along the bottom of the label
- date_label.draw.connect((ctx) => {
- int width = date_label.get_allocated_width();
- int height = date_label.get_allocated_height();
-
- Palette.prepare_hairline_border(ctx);
- ctx.move_to(0, height);
- ctx.line_to(width, height);
- ctx.stroke();
-
- return false;
- });
+ date_label.draw.connect(on_draw_bottom_line);
- attach(date_label, col, 0, 1, 1);
+ label_box.pack_start(date_label, true, true, 0);
- Pane pane = new Pane(this, date);
+ DayPane pane = new DayPane(this, date);
pane.expand = true;
pane_grid.attach(pane, col, 0, 1, 1);
col++;
}
- attach(scrolled_panes, 0, 1, col, 1);
+ // place Panes grid into a GtkScrolledWindow
+ Gtk.ScrolledWindow scrolled_panes = new Gtk.ScrolledWindow(null, null);
+ scrolled_panes.hscrollbar_policy = Gtk.PolicyType.NEVER;
+ scrolled_panes.vscrollbar_policy = Gtk.PolicyType.ALWAYS;
+ scrolled_panes.add(pane_grid);
+ pack_end(scrolled_panes, true, true, 0);
+ }
+
+ private bool on_draw_bottom_line(Gtk.Widget widget, Cairo.Context ctx) {
+ int width = widget.get_allocated_width();
+ int height = widget.get_allocated_height();
+
+ Palette.prepare_hairline_border(ctx);
+ ctx.move_to(0, height);
+ ctx.line_to(width, height);
+ ctx.stroke();
+
+ return false;
}
}
diff --git a/src/view/week/week-hour-runner.vala b/src/view/week/week-hour-runner.vala
new file mode 100644
index 0000000..1bcbcf1
--- /dev/null
+++ b/src/view/week/week-hour-runner.vala
@@ -0,0 +1,56 @@
+/* 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.View.Week {
+
+internal class HourRunner : Pane {
+ public const int REQUESTED_WIDTH = 50;
+
+ private const Calendar.WallTime.PrettyFlag TIME_FLAGS =
+ Calendar.WallTime.PrettyFlag.OPTIONAL_MINUTES;
+
+ public HourRunner(Grid owner) {
+ base (owner, REQUESTED_WIDTH);
+
+ Calendar.System.instance.is_24hr_changed.connect(queue_draw);
+ }
+
+ ~HourRunner() {
+ Calendar.System.instance.is_24hr_changed.disconnect(queue_draw);
+ }
+
+ // note that a painter's algorithm should be used here: background should be painted before
+ // calling base method, and foreground afterward
+ protected override bool on_draw(Cairo.Context ctx) {
+ if (!base.on_draw(ctx))
+ return false;
+
+ int right_justify_px = get_allocated_width() - Palette.TEXT_MARGIN_PX;
+
+ // draw time-of-day down right-hand side of HourRunner pane, which acts as tick marks for
+ // the rest of the week view
+ Calendar.WallTime wall_time = Calendar.WallTime.earliest;
+ for (;;) {
+ Pango.Layout layout = create_pango_layout(wall_time.to_pretty_string(TIME_FLAGS));
+ layout.set_font_description(Palette.instance.small_font);
+ layout.set_width(right_justify_px);
+ layout.set_alignment(Pango.Alignment.RIGHT);
+
+ ctx.move_to(right_justify_px, get_text_y(wall_time));
+ Pango.cairo_show_layout(ctx, layout);
+
+ bool rollover;
+ wall_time = wall_time.adjust(1, Calendar.TimeUnit.HOUR, out rollover);
+ if (rollover)
+ break;
+ }
+
+ return true;
+ }
+}
+
+}
+
diff --git a/src/view/week/week-pane.vala b/src/view/week/week-pane.vala
index b52f05a..5dc53a1 100644
--- a/src/view/week/week-pane.vala
+++ b/src/view/week/week-pane.vala
@@ -6,70 +6,48 @@
namespace California.View.Week {
-internal class Pane : Gtk.EventBox {
- public const string PROP_OWNER = "owner";
- public const string PROP_DATE = "date";
- public const string PROP_SELECTED = "selected";
-
+internal abstract class Pane : Gtk.EventBox {
public weak Grid owner { get; private set; }
- public Calendar.Date date { get; set; }
-
- public bool selected { get; set; default = false; }
+ // The height of each "line" of text, including top and bottom padding
+ protected int line_height_px { get; private set; default = 0; }
+ private int requested_width;
private Gtk.DrawingArea canvas = new Gtk.DrawingArea();
- private int line_height_px = 0;
- public Pane(Grid owner, Calendar.Date initial_date) {
+ public Pane(Grid owner, int requested_width) {
this.owner = owner;
- date = initial_date;
+ this.requested_width = requested_width;
margin = 0;
add(canvas);
- notify[PROP_DATE].connect(queue_draw);
- notify[PROP_SELECTED].connect(queue_draw);
+ update_palette_metrics();
Palette.instance.palette_changed.connect(on_palette_changed);
- Calendar.System.instance.is_24hr_changed.connect(queue_draw);
- Calendar.System.instance.today_changed.connect(on_today_changed);
canvas.draw.connect(on_draw);
}
~Pane() {
Palette.instance.palette_changed.disconnect(on_palette_changed);
- Calendar.System.instance.is_24hr_changed.disconnect(queue_draw);
- Calendar.System.instance.today_changed.disconnect(on_today_changed);
}
- private void on_palette_changed() {
- // calculcate the amount of space each "line" gets when drawing (normal font height plus
+ private void update_palette_metrics() {
+ // calculate the amount of space each "line" gets when drawing (normal font height plus
// padding on top and bottom)
- line_height_px = Palette.instance.normal_font_height_px + (Palette.LINE_SPACING_PX * 2);
+ line_height_px = Palette.instance.normal_font_height_px + (Palette.LINE_PADDING_PX * 2);
// update the height request based on the number of lines needed to show the entire day
- canvas.set_size_request(-1, get_line_y(Calendar.WallTime.latest) + line_height_px);
-
- queue_draw();
+ canvas.set_size_request(requested_width, get_line_y(Calendar.WallTime.latest));
}
- private void on_today_changed(Calendar.Date old_today, Calendar.Date new_today) {
- // need to know re: redrawing background color to indicate current day
- if (date.equal_to(old_today) || date.equal_to(new_today))
- queue_draw();
+ private void on_palette_changed() {
+ update_palette_metrics();
+ queue_draw();
}
- private bool on_draw(Cairo.Context ctx) {
- // shade background color if this is current day or selected
- if (selected) {
- Gdk.cairo_set_source_rgba(ctx, Palette.instance.selection);
- ctx.paint();
- } else if (date.equal_to(Calendar.System.today)) {
- Gdk.cairo_set_source_rgba(ctx, Palette.instance.current_day);
- ctx.paint();
- }
-
+ protected virtual bool on_draw(Cairo.Context ctx) {
int width = get_allocated_width();
int height = get_allocated_height();
@@ -104,7 +82,12 @@ internal class Pane : Gtk.EventBox {
return true;
}
- private int get_line_y(Calendar.WallTime wall_time) {
+ /**
+ * Returns the y (in pixels) for a particular line of text for the { link Calendar.WallTime}.
+ *
+ * If displaying text, use { link get_text_y}, as that will deduct padding.
+ */
+ protected int get_line_y(Calendar.WallTime wall_time) {
// every hour gets two "lines" of text
int line_y = line_height_px * 2 * wall_time.hour;
@@ -118,6 +101,15 @@ internal class Pane : Gtk.EventBox {
return line_y;
}
+
+ /**
+ * Returns the y (in pixels) for the top of a line of text at { link Calendar.WallTime}.
+ *
+ * Use this when displaying text. Drawing lines, borders, etc. should use { link get_line_y}.
+ */
+ protected int get_text_y(Calendar.WallTime wall_time) {
+ return get_line_y(wall_time) + Palette.LINE_PADDING_PX;
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]