[california] Use calendar colors: Closes bgo#725768
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california] Use calendar colors: Closes bgo#725768
- Date: Thu, 20 Mar 2014 22:12:34 +0000 (UTC)
commit 3c945c11d93ef688d1cedea890a3f7722907c5c4
Author: Jim Nelson <jim yorba org>
Date: Thu Mar 20 15:11:50 2014 -0700
Use calendar colors: Closes bgo#725768
Colors are used to display events and can be changed from the
Calendar Manager.
src/Makefile.am | 6 +
src/backing/backing-source.vala | 33 ++++++
src/backing/eds/backing-eds-calendar-source.vala | 11 ++
src/host/host-color-chooser-popup.vala | 36 +++++++
src/manager/manager-calendar-list-item.vala | 30 ++++++
src/rc/calendar-manager-list-item.ui | 20 ++++
src/util/util-gfx.vala | 114 ++++++++++++++++++++++
src/view/month/month-cell.vala | 13 ++-
8 files changed, 257 insertions(+), 6 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 4c6ac3b..f523b5a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,6 +62,7 @@ california_VALASOURCES = \
\
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 \
@@ -74,6 +75,7 @@ california_VALASOURCES = \
manager/manager-calendar-list-item.vala \
manager/manager-window.vala \
\
+ util/util-gfx.vala \
util/util-memory.vala \
util/util-string.vala \
\
@@ -123,6 +125,10 @@ california_CFLAGS = \
-DPREFIX=\"$(prefix)\" \
$(NULL)
+LIBS = \
+ -lm \
+ $(NULL)
+
california-resources.c: $(california_RC) california-resources.xml
$(GLIB_COMPILE_RESOURCES) --target="$@" --generate-source california-resources.xml
diff --git a/src/backing/backing-source.vala b/src/backing/backing-source.vala
index 022c9c6..d985b93 100644
--- a/src/backing/backing-source.vala
+++ b/src/backing/backing-source.vala
@@ -20,6 +20,7 @@ public abstract class Source : BaseObject {
public const string PROP_IS_AVAILABLE = "is-available";
public const string PROP_TITLE = "title";
public const string PROP_VISIBLE = "visible";
+ public const string PROP_COLOR = "color";
/**
* True if the { link Source} is unavailable for use due to being removed from it's
@@ -49,6 +50,12 @@ public abstract class Source : BaseObject {
*/
public bool visible { get; set; }
+ /**
+ * The suggested color to use when displaying the { link Source} or information about or from
+ * it.
+ */
+ public string color { get; set; }
+
protected Source(string title) {
this.title = title;
}
@@ -65,6 +72,32 @@ public abstract class Source : BaseObject {
is_available = false;
}
+ /**
+ * Returns the current { link color} setting as a Gdk.Color.
+ *
+ * If the color string is unparseable, returns a Gdk.Color that corresponds to "dressy-black".
+ */
+ public Gdk.Color color_as_rgb() {
+ return Gfx.rgb_string_to_rgb(color, Gdk.Color() { red = 0, green = 0, blue = 0 }, null);
+ }
+
+ /**
+ * Returns the current { link color} setting as a Gdk.RGBA.
+ *
+ * If the color string is unparseable, returns a Gdk.RGBA that corresponds to "dressy-black".
+ */
+ public Gdk.RGBA color_as_rgba() {
+ return Gfx.rgb_string_to_rgba(color,
+ Gdk.RGBA() { red = 0.0, green = 0.0, blue = 0.0, alpha = 1.0 }, null);
+ }
+
+ /**
+ * Set the { link color} property to the string representation of the Gdk.RGBA structure.
+ */
+ public void set_color_to_rgba(Gdk.RGBA rgba) {
+ color = Gfx.rgb_to_uint8_rgb_string(Gfx.rgba_to_rgb(rgba));
+ }
+
public override string to_string() {
return title;
}
diff --git a/src/backing/eds/backing-eds-calendar-source.vala
b/src/backing/eds/backing-eds-calendar-source.vala
index 8b31f90..0c9f9bb 100644
--- a/src/backing/eds/backing-eds-calendar-source.vala
+++ b/src/backing/eds/backing-eds-calendar-source.vala
@@ -28,9 +28,11 @@ internal class EdsCalendarSource : CalendarSource {
// use unidirectional bindings so source updates (writing) only occurs when changed from
// within the app
eds_calendar.bind_property("selected", this, PROP_VISIBLE, BindingFlags.SYNC_CREATE);
+ eds_calendar.bind_property("color", this, PROP_COLOR, BindingFlags.SYNC_CREATE);
// when changed within the app, need to write it back out
notify[PROP_VISIBLE].connect(on_visible_changed);
+ notify[PROP_COLOR].connect(on_color_changed);
}
~EdsCalendarSource() {
@@ -46,6 +48,15 @@ internal class EdsCalendarSource : CalendarSource {
schedule_source_write("visible=%s".printf(visible.to_string()));
}
+ private void on_color_changed() {
+ // only schedule writes if something changed
+ if (eds_calendar.color == color)
+ return;
+
+ eds_calendar.color = color;
+ schedule_source_write("color=%s".printf(color));
+ }
+
private void schedule_source_write(string reason) {
cancel_source_write();
diff --git a/src/host/host-color-chooser-popup.vala b/src/host/host-color-chooser-popup.vala
new file mode 100644
index 0000000..dc76f85
--- /dev/null
+++ b/src/host/host-color-chooser-popup.vala
@@ -0,0 +1,36 @@
+/* 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.Host {
+
+/**
+ * A simple { link Popup} window featuring only a GtkColorChooser.
+ */
+
+public class ColorChooserPopup : Popup {
+ private Gtk.ColorChooserWidget color_chooser = new Gtk.ColorChooserWidget();
+
+ public signal void selected(Gdk.RGBA rgba);
+
+ public ColorChooserPopup(Gtk.Widget relative_to, Gdk.RGBA initial_rgba) {
+ base (relative_to);
+
+ color_chooser.rgba = initial_rgba;
+ color_chooser.use_alpha = false;
+ color_chooser.show_editor = false;
+ color_chooser.margin = 8;
+
+ color_chooser.color_activated.connect((rgba) => {
+ selected(rgba);
+ dismissed();
+ });
+
+ add(color_chooser);
+ }
+}
+
+}
+
diff --git a/src/manager/manager-calendar-list-item.vala b/src/manager/manager-calendar-list-item.vala
index 87c1e6c..11a3bb2 100644
--- a/src/manager/manager-calendar-list-item.vala
+++ b/src/manager/manager-calendar-list-item.vala
@@ -12,6 +12,8 @@ namespace California.Manager {
[GtkTemplate (ui = "/org/yorba/california/rc/calendar-manager-list-item.ui")]
public class CalendarListItem : Gtk.Grid {
+ private const int COLOR_DIM = 16;
+
public Backing.CalendarSource source { get; private set; }
[GtkChild]
@@ -20,6 +22,9 @@ public class CalendarListItem : Gtk.Grid {
[GtkChild]
private Gtk.Label title_label;
+ [GtkChild]
+ private Gtk.Button color_button;
+
public CalendarListItem(Backing.CalendarSource source) {
this.source = source;
@@ -27,6 +32,31 @@ public class CalendarListItem : Gtk.Grid {
BindingFlags.SYNC_CREATE);
source.bind_property(Backing.Source.PROP_VISIBLE, visible_check_button, "active",
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
+
+ on_color_changed();
+ source.notify[Backing.Source.PROP_COLOR].connect(on_color_changed);
+ }
+
+ 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();
}
}
diff --git a/src/rc/calendar-manager-list-item.ui b/src/rc/calendar-manager-list-item.ui
index b081b42..0a8647e 100644
--- a/src/rc/calendar-manager-list-item.ui
+++ b/src/rc/calendar-manager-list-item.ui
@@ -40,6 +40,26 @@
<property name="single_line_mode">True</property>
</object>
<packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" 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>
+ </object>
+ <packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
diff --git a/src/util/util-gfx.vala b/src/util/util-gfx.vala
new file mode 100644
index 0000000..2225df4
--- /dev/null
+++ b/src/util/util-gfx.vala
@@ -0,0 +1,114 @@
+/* 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.Gfx {
+
+/**
+ * Convert an RGB string into an RGB structure.
+ *
+ * The string can be in any of the forms that Gdk.Color.parse accepts. If unable to parse the
+ * string, the { link default_rgb} is returned and { link used_default} is set to true.
+ */
+public Gdk.Color rgb_string_to_rgb(string rgb_string, Gdk.Color default_rgb, out bool used_default) {
+ Gdk.Color rgb;
+ if (!Gdk.Color.parse(rgb_string, out rgb)) {
+ debug("Unable to parse RGB color \"%s\"", rgb_string);
+
+ used_default = true;
+
+ return default_rgb;
+ }
+
+ used_default = false;
+
+ return rgb;
+}
+
+/**
+ * Convert an RGB string into an RGBA structure.
+ *
+ * The string can be in any of the forms that Gdk.Color.parse accepts. If unable to parse the
+ * string, the { link default_rgba} is returned and { link used_default} is set to true.
+ */
+public Gdk.RGBA rgb_string_to_rgba(string rgb_string, Gdk.RGBA default_rgba, out bool used_default) {
+ Gdk.Color rgb;
+ if (!Gdk.Color.parse(rgb_string, out rgb)) {
+ debug("Unable to parse RGB color \"%s\"", rgb_string);
+
+ used_default = true;
+
+ return default_rgba;
+ }
+
+ Gdk.RGBA rgba = Gdk.RGBA();
+ rgba.red = uint16_to_fp(rgb.red);
+ rgba.green = uint16_to_fp(rgb.green);
+ rgba.blue = uint16_to_fp(rgb.blue);
+ rgba.alpha = 1.0;
+
+ used_default = false;
+
+ return rgba;
+}
+
+// compiler error if this calculation is done inline when initializing struct
+private inline double uint16_to_fp(uint16 value) {
+ return (double) value / (double) uint16.MAX;
+}
+
+/**
+ * Converts the Gdk.RGBA into a 32-bit pixel representation.
+ */
+public uint32 rgba_to_pixel(Gdk.RGBA rgba) {
+ return (uint32) fp_to_uint8(rgba.red) << 24
+ | (uint32) fp_to_uint8(rgba.green) << 16
+ | (uint32) fp_to_uint8(rgba.blue) << 8
+ | (uint32) fp_to_uint8(rgba.alpha);
+}
+
+private inline uint8 fp_to_uint8(double value) {
+ return (uint8) Math.round(value * (double) uint8.MAX);
+}
+
+/**
+ * Converts a Gdk.RGBA structure into an RGB (Gdk.Color) structure.
+ *
+ * The alpha channel is necessarily stripped in this conversion.
+ */
+public Gdk.Color rgba_to_rgb(Gdk.RGBA rgba) {
+ Gdk.Color rgb = Gdk.Color();
+ rgb.red = fp_to_uint16(rgba.red);
+ rgb.green = fp_to_uint16(rgba.green);
+ rgb.blue = fp_to_uint16(rgba.blue);
+
+ return rgb;
+}
+
+private inline uint16 fp_to_uint16(double value) {
+ return (uint16) Math.round(value * (double) uint16.MAX);
+}
+
+public string rgb_to_uint8_rgb_string(Gdk.Color rgb) {
+ return "#%02x%02x%02x".printf(
+ uint16_to_uint8(rgb.red),
+ uint16_to_uint8(rgb.green),
+ uint16_to_uint8(rgb.blue)
+ );
+}
+
+private inline uint8 uint16_to_uint8(uint16 value) {
+ return (uint8) (value / (uint8.MAX + 1));
+}
+
+public string rgb_to_string(Gdk.Color rgb) {
+ return "(%d,%d,%d)".printf(rgb.red, rgb.green, rgb.blue);
+}
+
+public string rgba_to_string(Gdk.RGBA rgba) {
+ return "(%lf,%lf,%lf,%lf)".printf(rgba.red, rgba.green, rgba.blue, rgba.alpha);
+}
+
+}
diff --git a/src/view/month/month-cell.vala b/src/view/month/month-cell.vala
index 80e01de..2aa450f 100644
--- a/src/view/month/month-cell.vala
+++ b/src/view/month/month-cell.vala
@@ -255,7 +255,8 @@ public class Cell : Gtk.EventBox {
text = "%s %s".printf(local_start.to_pretty_time_string(PRETTY_TIME_FLAGS), event.summary);
}
- Pango.Layout layout = draw_line_of_text(ctx, line_number, RGBA_DAY_OF_MONTH, text);
+ Pango.Layout layout = draw_line_of_text(ctx, line_number, event.calendar_source.color_as_rgba(),
+ text);
line_to_event.set(line_number++, event);
event.set_data<string?>(KEY_TOOLTIP, layout.is_ellipsized() ? text : null);
}
@@ -314,12 +315,12 @@ public class Cell : Gtk.EventBox {
* The Gdk.Point must be relative to the widget's coordinate system.
*/
public Component.Event? get_event_at(Gdk.Point point) {
- int line_number = 0;
- foreach (Component.Event event in days_events) {
- int y = get_line_top_y(line_number++);
-
+ for (int line_number = 0; line_number < line_to_event.size; line_number++) {
+ int y = get_line_top_y(line_number);
if (point.y >= y && point.y < (y + line_height_px))
- return event;
+ return line_to_event.get(line_number);
+
+ line_number++;
}
return null;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]