[gnome-todo/gnome-3-22] task-row: rework focus management
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-todo/gnome-3-22] task-row: rework focus management
- Date: Thu, 1 Dec 2016 03:59:56 +0000 (UTC)
commit c2a022dacf179f305d6e33df711e5e93062be848
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Dec 1 01:37:40 2016 -0200
task-row: rework focus management
Instead of relying on these shady focus-in and focus-out
events, lets just manually handle them.
https://bugzilla.gnome.org/show_bug.cgi?id=762852
data/ui/list-view.ui | 1 +
data/ui/task-row.ui | 2 -
src/gtd-task-list-view.c | 55 +++++++++++++++++++
src/gtd-task-row.c | 131 +++++++++++++++++++++-------------------------
src/gtd-task-row.h | 5 ++
5 files changed, 120 insertions(+), 74 deletions(-)
---
diff --git a/data/ui/list-view.ui b/data/ui/list-view.ui
index 719b77a..30bc6aa 100644
--- a/data/ui/list-view.ui
+++ b/data/ui/list-view.ui
@@ -41,6 +41,7 @@
<signal name="drag-drop" handler="listbox_drag_drop" object="GtdTaskListView"
swapped="no" />
<signal name="drag-leave" handler="listbox_drag_leave" object="GtdTaskListView"
swapped="no" />
<signal name="drag-motion" handler="listbox_drag_motion" object="GtdTaskListView"
swapped="no" />
+ <signal name="row-activated" handler="listbox_row_activated"
object="GtdTaskListView" swapped="no" />
<child>
<object class="GtdTaskRow" id="new_task_row">
<property name="visible">True</property>
diff --git a/data/ui/task-row.ui b/data/ui/task-row.ui
index 29b899f..89b32f7 100644
--- a/data/ui/task-row.ui
+++ b/data/ui/task-row.ui
@@ -98,7 +98,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
- <signal name="focus_out_event" handler="gtd_task_row__entry_focus_out"
object="GtdTaskRow" swapped="no" />
</object>
<packing>
<property name="name">title</property>
@@ -220,7 +219,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="activate" handler="gtd_task_row__entry_activated" object="GtdTaskRow"
swapped="no" />
- <signal name="focus_out_event" handler="gtd_task_row__entry_focus_out"
object="GtdTaskRow" swapped="no" />
</object>
<packing>
<property name="name">entry</property>
diff --git a/src/gtd-task-list-view.c b/src/gtd-task-list-view.c
index eadb807..d90997a 100644
--- a/src/gtd-task-list-view.c
+++ b/src/gtd-task-list-view.c
@@ -104,6 +104,8 @@ typedef struct
/* Custom sorting function data */
GtdTaskListViewSortFunc sort_func;
gpointer sort_user_data;
+
+ GtkWidget *active_row;
} GtdTaskListViewPrivate;
struct _GtdTaskListView
@@ -164,6 +166,27 @@ typedef gboolean (*IterateSubtaskFunc) (GtdTaskListVie
GtdTask *task);
/*
+ * Active row management
+ */
+static void
+set_active_row (GtdTaskListView *self,
+ GtkWidget *row)
+{
+ GtdTaskListViewPrivate *priv = gtd_task_list_view_get_instance_private (self);
+
+ if (priv->active_row == row)
+ return;
+
+ if (priv->active_row)
+ gtd_task_row_set_active (GTD_TASK_ROW (priv->active_row), FALSE);
+
+ priv->active_row = row;
+
+ if (row)
+ gtd_task_row_set_active (GTD_TASK_ROW (row), TRUE);
+}
+
+/*
* Auxiliary function to iterate through a list of subtasks
*/
static void
@@ -660,6 +683,9 @@ gtd_task_list_view__remove_task_cb (GtdEditPane *pane,
gtd_window_notify (window, notification);
+ /* Clear the active row */
+ set_active_row (user_data, NULL);
+
g_clear_pointer (&text, g_free);
out:
@@ -679,6 +705,8 @@ gtd_task_list_view__edit_task_finished (GtdEditPane *pane,
priv = GTD_TASK_LIST_VIEW (user_data)->priv;
+ set_active_row (user_data, NULL);
+
gtk_revealer_set_reveal_child (priv->edit_revealer, FALSE);
gtd_task_save (task);
@@ -800,6 +828,8 @@ task_row_entered_cb (GtdTaskListView *self,
gtk_revealer_set_reveal_child (priv->edit_revealer, TRUE);
gtd_arrow_frame_set_row (priv->arrow_frame, row);
+
+ set_active_row (self, GTK_WIDGET (row));
}
static void
@@ -822,6 +852,23 @@ task_row_exited_cb (GtdTaskListView *self,
gtk_revealer_set_reveal_child (priv->edit_revealer, FALSE);
gtd_arrow_frame_set_row (priv->arrow_frame, NULL);
+
+ if (GTK_WIDGET (row) == priv->active_row &&
+ priv->active_row != GTK_WIDGET (priv->new_task_row))
+ {
+ set_active_row (self, NULL);
+ }
+}
+
+static void
+listbox_row_activated (GtkListBox *listbox,
+ GtkListBox *row,
+ GtdTaskListView *self)
+{
+ if (!GTD_IS_TASK_ROW (row))
+ return;
+
+ set_active_row (self, GTK_WIDGET (row));
}
static void
@@ -864,6 +911,9 @@ destroy_task_row (GtdTaskListView *self,
g_signal_handlers_disconnect_by_func (row, task_row_entered_cb, self);
g_signal_handlers_disconnect_by_func (row, task_row_exited_cb, self);
+ if (GTK_WIDGET (row) == self->priv->active_row)
+ set_active_row (self, NULL);
+
gtd_task_row_destroy (row);
}
@@ -1576,6 +1626,7 @@ gtd_task_list_view_class_init (GtdTaskListViewClass *klass)
gtk_widget_class_bind_template_callback (widget_class, listbox_drag_drop);
gtk_widget_class_bind_template_callback (widget_class, listbox_drag_leave);
gtk_widget_class_bind_template_callback (widget_class, listbox_drag_motion);
+ gtk_widget_class_bind_template_callback (widget_class, listbox_row_activated);
gtk_widget_class_bind_template_callback (widget_class, task_row_exited_cb);
gtk_widget_class_set_css_name (widget_class, "task-list-view");
@@ -1590,6 +1641,8 @@ gtd_task_list_view_init (GtdTaskListView *self)
gtk_widget_init_template (GTK_WIDGET (self));
+ self->priv->active_row = GTK_WIDGET (self->priv->new_task_row);
+
gtk_drag_dest_set (GTK_WIDGET (self->priv->listbox),
0,
NULL,
@@ -1828,6 +1881,8 @@ gtd_task_list_view_set_task_list (GtdTaskListView *view,
"task-updated",
G_CALLBACK (gtk_list_box_invalidate_sort),
priv->listbox);
+
+ set_active_row (view, GTK_WIDGET (priv->new_task_row));
}
/**
diff --git a/src/gtd-task-row.c b/src/gtd-task-row.c
index 456f356..1b21cb1 100644
--- a/src/gtd-task-row.c
+++ b/src/gtd-task-row.c
@@ -59,6 +59,8 @@ struct _GtdTaskRow
GtdTask *task;
gint destroy_row_timeout_id;
+
+ gboolean active;
};
#define PRIORITY_ICON_SIZE 8
@@ -69,7 +71,6 @@ G_DEFINE_TYPE (GtdTaskRow, gtd_task_row, GTK_TYPE_LIST_BOX_ROW)
enum {
ENTER,
EXIT,
- ACTIVATED,
CREATE_TASK,
NUM_SIGNALS
};
@@ -363,49 +364,6 @@ gtd_task_row_new (GtdTask *task)
}
static gboolean
-gtd_task_row__entry_focus_out (GtkWidget *widget,
- GdkEventFocus *event,
- gpointer user_data)
-{
- GtdTaskRow *self = GTD_TASK_ROW (user_data);
-
- g_return_val_if_fail (GTD_IS_TASK_ROW (user_data), FALSE);
-
- if (self->new_task_mode)
- gtk_stack_set_visible_child_name (self->new_task_stack, "label");
- else
- gtk_stack_set_visible_child_name (self->task_stack, "label");
-
- return FALSE;
-}
-
-static gboolean
-gtd_task_row__focus_in (GtkWidget *widget,
- GdkEventFocus *event)
-{
- GtdTaskRow *self = GTD_TASK_ROW (widget);
-
- g_return_val_if_fail (GTD_IS_TASK_ROW (widget), FALSE);
-
- if (self->new_task_mode)
- {
- gtk_stack_set_visible_child_name (self->new_task_stack, "entry");
- gtk_widget_grab_focus (GTK_WIDGET (self->new_task_entry));
-
- g_signal_emit (self, signals[EXIT], 0);
- }
- else
- {
- gtk_stack_set_visible_child_name (self->task_stack, "title");
- gtk_widget_grab_focus (GTK_WIDGET (self->title_entry));
-
- g_signal_emit (self, signals[ENTER], 0);
- }
-
- return FALSE;
-}
-
-static gboolean
gtd_task_row__key_press_event (GtkWidget *row,
GdkEventKey *event)
{
@@ -414,6 +372,8 @@ gtd_task_row__key_press_event (GtkWidget *row,
if (event->keyval == GDK_KEY_Escape && // Esc is pressed
!(event->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) // No modifiers together
{
+ self->active = FALSE;
+
if (self->new_task_mode)
{
gtk_stack_set_visible_child_name (self->new_task_stack, "label");
@@ -429,6 +389,15 @@ gtd_task_row__key_press_event (GtkWidget *row,
return FALSE;
}
+static gboolean
+gtd_task_row_focus_in_event (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ gtd_task_row_set_active (GTD_TASK_ROW (widget), TRUE);
+
+ return GDK_EVENT_PROPAGATE;
+}
+
static void
gtd_task_row__entry_activated (GtkEntry *entry,
gpointer user_data)
@@ -546,30 +515,19 @@ gtd_task_row_set_property (GObject *object,
}
static void
-gtd_task_row_activate (GtkListBoxRow *row)
-{
- GTK_LIST_BOX_ROW_CLASS (gtd_task_row_parent_class)->activate (row);
-
- g_signal_emit (row, signals[ENTER], 0);
-}
-
-static void
gtd_task_row_class_init (GtdTaskRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkListBoxRowClass *row_class = GTK_LIST_BOX_ROW_CLASS (klass);
object_class->dispose = gtd_task_row_dispose;
object_class->finalize = gtd_task_row_finalize;
object_class->get_property = gtd_task_row_get_property;
object_class->set_property = gtd_task_row_set_property;
- widget_class->focus_in_event = gtd_task_row__focus_in;
+ widget_class->focus_in_event = gtd_task_row_focus_in_event;
widget_class->key_press_event = gtd_task_row__key_press_event;
- row_class->activate = gtd_task_row_activate;
-
/**
* GtdTaskRow::handle-subtasks:
*
@@ -643,21 +601,6 @@ gtd_task_row_class_init (GtdTaskRowClass *klass)
0);
/**
- * GtdTaskRow::activate:
- *
- * Emitted when the row wants to apply the changes.
- */
- signals[ACTIVATED] = g_signal_new ("activated",
- GTD_TYPE_TASK_ROW,
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 0);
-
- /**
* GtdTaskRow::create-task:
*
* Emitted when the row wants the parent widget to create a new task.
@@ -695,7 +638,6 @@ gtd_task_row_class_init (GtdTaskRowClass *klass)
gtk_widget_class_bind_template_callback (widget_class, mouse_out_event);
gtk_widget_class_bind_template_callback (widget_class, mouse_over_event);
gtk_widget_class_bind_template_callback (widget_class, gtd_task_row__entry_activated);
- gtk_widget_class_bind_template_callback (widget_class, gtd_task_row__entry_focus_out);
gtk_widget_class_set_css_name (widget_class, "taskrow");
}
@@ -943,3 +885,48 @@ gtd_task_row_set_handle_subtasks (GtdTaskRow *self,
g_object_notify (G_OBJECT (self), "handle-subtasks");
}
+
+gboolean
+gtd_task_row_get_active (GtdTaskRow *self)
+{
+ g_return_val_if_fail (GTD_IS_TASK_ROW (self), FALSE);
+
+ return self->active;
+}
+
+void
+gtd_task_row_set_active (GtdTaskRow *self,
+ gboolean active)
+{
+ g_return_if_fail (GTD_IS_TASK_ROW (self));
+
+ if (self->active == active)
+ return;
+
+ self->active = active;
+
+ if (active)
+ {
+ if (self->new_task_mode)
+ {
+ gtk_stack_set_visible_child_name (self->new_task_stack, "entry");
+ gtk_widget_grab_focus (GTK_WIDGET (self->new_task_entry));
+
+ g_signal_emit (self, signals[EXIT], 0);
+ }
+ else
+ {
+ gtk_stack_set_visible_child_name (self->task_stack, "title");
+ gtk_widget_grab_focus (GTK_WIDGET (self->title_entry));
+
+ g_signal_emit (self, signals[ENTER], 0);
+ }
+ }
+ else
+ {
+ if (self->new_task_mode)
+ gtk_stack_set_visible_child_name (self->new_task_stack, "label");
+ else
+ gtk_stack_set_visible_child_name (self->task_stack, "label");
+ }
+}
diff --git a/src/gtd-task-row.h b/src/gtd-task-row.h
index 0394995..d934670 100644
--- a/src/gtd-task-row.h
+++ b/src/gtd-task-row.h
@@ -54,6 +54,11 @@ gboolean gtd_task_row_get_handle_subtasks (GtdTaskRow
void gtd_task_row_set_handle_subtasks (GtdTaskRow *self,
gboolean handle_subtasks);
+gboolean gtd_task_row_get_active (GtdTaskRow *self);
+
+void gtd_task_row_set_active (GtdTaskRow *self,
+ gboolean active);
+
G_END_DECLS
#endif /* GTD_TASK_ROW_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]