[california] Indicate with cursor when hovering over hot spot: Bug #731635
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california] Indicate with cursor when hovering over hot spot: Bug #731635
- Date: Fri, 19 Sep 2014 23:16:47 +0000 (UTC)
commit 5d437d691b8524aa8ff7638a89a5a07cab7fa28b
Author: Jim Nelson <jim yorba org>
Date: Fri Sep 19 16:15:50 2014 -0700
Indicate with cursor when hovering over hot spot: Bug #731635
This moves Month.Grid entirely onto the Toolkit.EventConnectors
by using MotionConnector for both hot spot detection as well as
selection dragging.
src/toolkit/toolkit.vala | 37 +++++++++++++++++++++++-----------
src/view/month/month-grid.vala | 42 ++++++++++++++++++++++++++++++++-------
src/view/week/week-grid.vala | 34 ++++++++++++++++++++++++++++---
3 files changed, 89 insertions(+), 24 deletions(-)
---
diff --git a/src/toolkit/toolkit.vala b/src/toolkit/toolkit.vala
index ca38290..f407356 100644
--- a/src/toolkit/toolkit.vala
+++ b/src/toolkit/toolkit.vala
@@ -72,18 +72,7 @@ public void spin_event_loop() {
* { link set_window_unbusy}.
*/
public Gdk.Cursor? set_busy(Gtk.Widget widget) {
- Gtk.Widget toplevel = widget.get_toplevel();
- if (!toplevel.is_toplevel()) {
- debug("Unable to set busy: widget has no toplevel window");
-
- return null;
- }
-
- Gdk.Window gdk_window = toplevel.get_window();
- Gdk.Cursor? unbusy_cursor = gdk_window.get_cursor();
- gdk_window.set_cursor(new Gdk.Cursor.for_display(toplevel.get_display(), Gdk.CursorType.WATCH));
-
- return unbusy_cursor;
+ return set_toplevel_cursor(widget, Gdk.CursorType.WATCH);
}
/**
@@ -104,6 +93,30 @@ public void set_unbusy(Gtk.Widget widget, Gdk.Cursor? unbusy_cursor) {
}
/**
+ * Sets the Gtk.Widget's toplevel's cursor.
+ *
+ * @returns The toplevel's current cursor. This can be saved to restore later or simply dropped.
+ */
+public Gdk.Cursor? set_toplevel_cursor(Gtk.Widget widget, Gdk.CursorType? cursor_type) {
+ Gtk.Widget toplevel = widget.get_toplevel();
+ if (!toplevel.is_toplevel()) {
+ debug("Unable to set cursor: widget has no toplevel window");
+
+ return null;
+ }
+
+ Gdk.Window gdk_window = toplevel.get_window();
+ Gdk.Cursor? old_cursor = gdk_window.get_cursor();
+
+ if (cursor_type != null)
+ gdk_window.set_cursor(new Gdk.Cursor.for_display(toplevel.get_display(), cursor_type));
+ else
+ gdk_window.set_cursor(null);
+
+ return old_cursor;
+}
+
+/**
* Destroy a Gtk.Widget when the event loop is idle.
*/
public void destroy_later(Gtk.Widget widget) {
diff --git a/src/view/month/month-grid.vala b/src/view/month/month-grid.vala
index f124f94..47444d2 100644
--- a/src/view/month/month-grid.vala
+++ b/src/view/month/month-grid.vala
@@ -52,6 +52,7 @@ private class Grid : Gtk.Grid {
private Gee.HashMap<Calendar.Date, Cell> date_to_cell = new Gee.HashMap<Calendar.Date, Cell>();
private Backing.CalendarSubscriptionManager? subscriptions = null;
private Toolkit.ButtonConnector cell_button_connector = new Toolkit.ButtonConnector();
+ private Toolkit.MotionConnector cell_motion_connector = new Toolkit.MotionConnector();
private Scheduled? scheduled_subscription_update = null;
public Grid(Controller owner, Calendar.MonthOfYear month_of_year) {
@@ -65,6 +66,10 @@ private class Grid : Gtk.Grid {
cell_button_connector.clicked.connect(on_cell_single_click);
cell_button_connector.double_clicked.connect(on_cell_double_click);
+ cell_motion_connector.entered.connect(on_cell_entered_exited);
+ cell_motion_connector.exited.connect(on_cell_entered_exited);
+ cell_motion_connector.motion.connect(on_cell_motion);
+ cell_motion_connector.button_motion.connect(on_cell_button_motion);
// create a WeekSpan for the first week of the month to the last week of the month
Calendar.WeekSpan span = new Calendar.WeekSpan.from_span(month_of_year,
Calendar.System.first_of_week);
@@ -87,7 +92,7 @@ private class Grid : Gtk.Grid {
Cell cell = new Cell(this, date, rows, col);
cell.expand = true;
cell_button_connector.connect_to(cell);
- cell.motion_notify_event.connect(on_cell_motion_event);
+ cell_motion_connector.connect_to(cell);
attach(cell, col, rows, 1, 1);
@@ -300,6 +305,8 @@ private class Grid : Gtk.Grid {
Cell press_cell = (Cell) details.widget;
+ Toolkit.set_toplevel_cursor(this, null);
+
// if pressed and released on the same cell, display the event at the released location
if (press_cell == release_cell) {
Component.Event? event = release_cell.get_event_at(details.release_point);
@@ -343,27 +350,48 @@ private class Grid : Gtk.Grid {
if (release_cell.get_event_at(release_cell_point) != null)
return Toolkit.STOP;
+ Toolkit.set_toplevel_cursor(this, null);
+
owner.request_create_all_day_event(new Calendar.DateSpan(press_cell.date, release_cell.date),
release_cell, release_cell_point);
return Toolkit.STOP;
}
- private bool on_cell_motion_event(Gtk.Widget widget, Gdk.EventMotion event) {
+ private void on_cell_entered_exited(Toolkit.MotionEvent details) {
+ // when entering or leaving cell, reset the cursor
+ Toolkit.set_toplevel_cursor(details.widget, null);
+ }
+
+ private void on_cell_motion(Toolkit.MotionEvent details) {
+ Cell cell = (Cell) details.widget;
+
+ // if hovering over an event, show the "hyperlink" cursor
+ Gdk.CursorType? cursor_type = null;
+ if (cell.get_event_at(details.point) != null)
+ cursor_type = Gdk.CursorType.HAND1;
+
+ Toolkit.set_toplevel_cursor(cell, cursor_type);
+ }
+
+ private void on_cell_button_motion(Toolkit.MotionEvent event) {
+ if (!event.is_button_pressed(Toolkit.Button.PRIMARY))
+ return;
+
// Because using button 1 motion mask, widget is always the original cell the button-pressed
// event originated at
- Cell press_cell = (Cell) widget;
+ Cell press_cell = (Cell) event.widget;
// turn Cell coordinates into GtkGrid coordinates
int grid_x, grid_y;
- if (!press_cell.translate_coordinates(this, (int) event.x, (int) event.y, out grid_x, out grid_y))
- return false;
+ if (!press_cell.translate_coordinates(this, event.point.x, event.point.y, out grid_x, out grid_y))
+ return;
// get the cell the pointer is currently over ... if not found or the same as the original,
// do nothing
Cell? hover_cell = translate_to_cell(grid_x, grid_y);
if (hover_cell == null || hover_cell == press_cell)
- return false;
+ return;
// mark two cells and all in-between as selected, being sure to mark any previous selected
// as unselected
@@ -373,8 +401,6 @@ private class Grid : Gtk.Grid {
return true;
});
-
- return true;
}
}
diff --git a/src/view/week/week-grid.vala b/src/view/week/week-grid.vala
index e79af4e..9ee6a7a 100644
--- a/src/view/week/week-grid.vala
+++ b/src/view/week/week-grid.vala
@@ -49,8 +49,8 @@ internal class Grid : Gtk.Box {
private Toolkit.ButtonConnector instance_container_button_connector = new Toolkit.ButtonConnector();
private Toolkit.ButtonConnector all_day_button_connector = new Toolkit.ButtonConnector();
private Toolkit.ButtonConnector day_pane_button_connector = new Toolkit.ButtonConnector();
- private Toolkit.MotionConnector day_pane_motion_connector = new Toolkit.MotionConnector.button_only();
- private Toolkit.MotionConnector all_day_cell_motion_connector = new
Toolkit.MotionConnector.button_only();
+ private Toolkit.MotionConnector day_pane_motion_connector = new Toolkit.MotionConnector();
+ private Toolkit.MotionConnector all_day_cell_motion_connector = new Toolkit.MotionConnector();
private Gtk.ScrolledWindow scrolled_panes;
private Gtk.Widget right_spacer;
private bool vadj_init = false;
@@ -150,8 +150,15 @@ internal class Grid : Gtk.Box {
instance_container_button_connector.double_clicked.connect(on_instance_container_double_clicked);
// connect to individual motion event handlers for different types of instance containers
+ all_day_cell_motion_connector.entered.connect(on_instance_container_entered_exited);
+ all_day_cell_motion_connector.exited.connect(on_instance_container_entered_exited);
+ all_day_cell_motion_connector.motion.connect(on_instance_container_motion);
all_day_cell_motion_connector.button_motion.connect(on_all_day_cell_button_motion);
- day_pane_motion_connector.button_motion.connect(on_day_pane_motion);
+
+ day_pane_motion_connector.entered.connect(on_instance_container_entered_exited);
+ day_pane_motion_connector.exited.connect(on_instance_container_entered_exited);
+ day_pane_motion_connector.motion.connect(on_instance_container_motion);
+ day_pane_motion_connector.button_motion.connect(on_day_pane_button_motion);
// connect to individual button released handlers for different types of instance containers
all_day_button_connector.released.connect(on_all_day_cell_button_released);
@@ -336,6 +343,8 @@ internal class Grid : Gtk.Box {
if (details.button != Toolkit.Button.PRIMARY)
return Toolkit.PROPAGATE;
+ Toolkit.set_toplevel_cursor(this, null);
+
Common.InstanceContainer instance_container = (Common.InstanceContainer) details.widget;
Component.Event? event = instance_container.get_event_at(details.press_point);
@@ -345,6 +354,21 @@ internal class Grid : Gtk.Box {
return Toolkit.STOP;
}
+ private void on_instance_container_motion(Toolkit.MotionEvent details) {
+ Common.InstanceContainer instance_container = (Common.InstanceContainer) details.widget;
+
+ Gdk.CursorType? cursor_type = null;
+ if (instance_container.get_event_at(details.point) != null)
+ cursor_type = Gdk.CursorType.HAND1;
+
+ Toolkit.set_toplevel_cursor(instance_container, cursor_type);
+ }
+
+ private void on_instance_container_entered_exited(Toolkit.MotionEvent details) {
+ // when entering or leaving instance container (all day cell or day pane), reset the cursor
+ Toolkit.set_toplevel_cursor(details.widget, null);
+ }
+
private bool on_instance_container_double_clicked(Toolkit.ButtonEvent details) {
if (details.button != Toolkit.Button.PRIMARY)
return Toolkit.PROPAGATE;
@@ -355,6 +379,8 @@ internal class Grid : Gtk.Box {
if (instance_container.get_event_at(details.press_point) != null)
return Toolkit.PROPAGATE;
+ Toolkit.set_toplevel_cursor(instance_container, null);
+
// if a DayPane, use double-click to determine rounded time of the event's start
DayPane? day_pane = instance_container as DayPane;
if (day_pane != null) {
@@ -379,7 +405,7 @@ internal class Grid : Gtk.Box {
return Toolkit.STOP;
}
- private void on_day_pane_motion(Toolkit.MotionEvent details) {
+ private void on_day_pane_button_motion(Toolkit.MotionEvent details) {
DayPane day_pane = (DayPane) details.widget;
// only update selection as long as button is depressed
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]