talkatu/talkatu

Parents 94800fbdd529
Children 9794852de957
Add an optional send button. This fixes #48. I added a bunch of accessors and other clean ups to the editor those this pr got a little bit bigger than I anticipated..
--- a/demo/data/demo.ui Thu Jul 11 23:00:56 2019 -0500
+++ b/demo/data/demo.ui Sat Jul 13 04:47:52 2019 -0500
@@ -138,6 +138,7 @@
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Insert HTML from a file</property>
<property name="label" translatable="yes">Insert HTML</property>
<property name="use_underline">True</property>
<property name="icon_name">text-html</property>
@@ -152,6 +153,7 @@
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Insert Markdown from a file</property>
<property name="label" translatable="yes">Insert Markdown</property>
<property name="use_underline">True</property>
<property name="icon_name">text-x-generic</property>
@@ -162,6 +164,42 @@
<property name="homogeneous">True</property>
</packing>
</child>
+ <child>
+ <object class="GtkSeparatorToolItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="toggle_toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Toogle toolbar visibility</property>
+ <property name="label" translatable="yes">Toolbar</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="toggle_send_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Toggle send button visibility</property>
+ <property name="label" translatable="yes">Send Button</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
--- a/demo/talkatudemowindow.c Thu Jul 11 23:00:56 2019 -0500
+++ b/demo/talkatudemowindow.c Sat Jul 13 04:47:52 2019 -0500
@@ -32,6 +32,9 @@
GtkRadioToolButton *toggle_html;
GtkRadioToolButton *toggle_markdown;
+ GtkToggleToolButton *toggle_toolbar;
+ GtkToggleToolButton *toggle_send_button;
+
GtkTextBuffer *buffer_plain;
GtkTextBuffer *buffer_whole;
GtkTextBuffer *buffer_html;
@@ -224,6 +227,18 @@
gtk_widget_init_template(GTK_WIDGET(window));
gtk_text_view_set_buffer(GTK_TEXT_VIEW(window->view_history), window->buffer_history);
+
+ g_object_bind_property(
+ window->editor, "show-toolbar",
+ window->toggle_toolbar, "active",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL
+ );
+
+ g_object_bind_property(
+ window->editor, "show-send-button",
+ window->toggle_send_button, "active",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL
+ );
}
static void
@@ -249,6 +264,9 @@
gtk_widget_class_bind_template_child(widget_class, TalkatuDemoWindow, toggle_html);
gtk_widget_class_bind_template_child(widget_class, TalkatuDemoWindow, toggle_markdown);
+ gtk_widget_class_bind_template_child(widget_class, TalkatuDemoWindow, toggle_toolbar);
+ gtk_widget_class_bind_template_child(widget_class, TalkatuDemoWindow, toggle_send_button);
+
gtk_widget_class_bind_template_callback(widget_class, talkatu_demo_window_closed_cb);
gtk_widget_class_bind_template_callback(widget_class, talkatu_demo_window_buffer_changed_cb);
gtk_widget_class_bind_template_callback(widget_class, talkatu_demo_window_view_open_url_cb);
--- a/talkatu/data/editor.ui Thu Jul 11 23:00:56 2019 -0500
+++ b/talkatu/data/editor.ui Sat Jul 13 04:47:52 2019 -0500
@@ -23,20 +23,45 @@
</packing>
</child>
<child>
- <object class="GtkScrolledWindow">
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">in</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">4</property>
<child>
- <object class="TalkatuView" id="view">
+ <object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="wrap_mode">word</property>
- <property name="buffer">buffer</property>
- <signal name="notify::buffer" handler="talkatu_editor_view_buffer_changed_handler" object="TalkatuEditor" swapped="no"/>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="TalkatuView" id="view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="wrap_mode">word</property>
+ <property name="buffer">buffer</property>
+ <signal name="notify::buffer" handler="talkatu_editor_view_buffer_changed_handler" object="TalkatuEditor" swapped="no"/>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="send_button">
+ <property name="label" translatable="yes">Send</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="talkatu_editor_send_button_clicked_cb" object="TalkatuEditor" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
--- a/talkatu/talkatueditor.c Thu Jul 11 23:00:56 2019 -0500
+++ b/talkatu/talkatueditor.c Sat Jul 13 04:47:52 2019 -0500
@@ -36,8 +36,21 @@
GtkWidget *view;
GtkWidget *toolbar;
+ GtkWidget *send_button;
};
+enum {
+ PROP_0,
+ PROP_TOOLBAR,
+ PROP_SHOW_TOOLBAR,
+ PROP_VIEW,
+ PROP_BUFFER,
+ PROP_SHOW_SEND_BUTTON,
+ N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = {NULL, };
+
G_DEFINE_TYPE(TalkatuEditor, talkatu_editor, GTK_TYPE_BOX)
/******************************************************************************
@@ -63,18 +76,125 @@
talkatu_editor_buffer_changed(TALKATU_EDITOR(data));
}
+static void
+talkatu_editor_send_button_clicked_cb(GtkButton *button, gpointer data) {
+ TalkatuEditor *editor = TALKATU_EDITOR(data);
+
+ talkatu_view_send_message(TALKATU_VIEW(editor->view));
+
+ gtk_widget_grab_focus(editor->view);
+}
+
/******************************************************************************
* GObject Stuff
*****************************************************************************/
static void
+talkatu_editor_get_property(GObject *obj, guint param_id, GValue *value, GParamSpec *pspec) {
+ TalkatuEditor *editor = TALKATU_EDITOR(obj);
+
+ switch(param_id) {
+ case PROP_TOOLBAR:
+ g_value_set_object(value, talkatu_editor_get_toolbar(editor));
+ break;
+ case PROP_SHOW_TOOLBAR:
+ g_value_set_boolean(value, talkatu_editor_get_toolbar_visible(editor));
+ break;
+ case PROP_VIEW:
+ g_value_set_object(value, talkatu_editor_get_view(editor));
+ break;
+ case PROP_SHOW_SEND_BUTTON:
+ g_value_set_boolean(value, talkatu_editor_get_send_button_visible(editor));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
+talkatu_editor_set_property(GObject *obj, guint param_id, const GValue *value, GParamSpec *pspec) {
+ TalkatuEditor *editor = TALKATU_EDITOR(obj);
+
+ switch(param_id) {
+ case PROP_SHOW_TOOLBAR:
+ talkatu_editor_set_toolbar_visible(editor, g_value_get_boolean(value));
+ break;
+ case PROP_BUFFER:
+ talkatu_editor_set_buffer(editor, g_value_get_object(value));
+ break;
+ case PROP_SHOW_SEND_BUTTON:
+ talkatu_editor_set_send_button_visible(editor, g_value_get_boolean(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+ break;
+ }
+}
+
+static void
talkatu_editor_init(TalkatuEditor *editor) {
gtk_widget_init_template(GTK_WIDGET(editor));
+
+ /* bind the visibility of the toolbar to the editor property */
+ g_object_bind_property(
+ editor, "show-toolbar",
+ editor->toolbar, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL
+ );
+
+ /* bind the visibility of the send button to the editor property */
+ g_object_bind_property(
+ editor, "show-send-button",
+ editor->send_button, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL
+ );
}
static void
talkatu_editor_class_init(TalkatuEditorClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ obj_class->get_property = talkatu_editor_get_property;
+ obj_class->set_property = talkatu_editor_set_property;
+
+ properties[PROP_TOOLBAR] = g_param_spec_object(
+ "toolbar", "toolbar",
+ "The toolbar widget",
+ TALKATU_TYPE_TOOLBAR,
+ G_PARAM_READABLE
+ );
+
+ properties[PROP_SHOW_TOOLBAR] = g_param_spec_boolean(
+ "show-toolbar", "show-toolbar",
+ "Whether or not to show the toolbar",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT
+ );
+
+ properties[PROP_VIEW] = g_param_spec_object(
+ "view", "view",
+ "The view widget",
+ TALKATU_TYPE_VIEW,
+ G_PARAM_READABLE
+ );
+
+ properties[PROP_BUFFER] = g_param_spec_object(
+ "buffer", "buffer",
+ "The GtkTextBuffer for the view",
+ GTK_TYPE_TEXT_BUFFER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT
+ );
+
+ properties[PROP_SHOW_SEND_BUTTON] = g_param_spec_boolean(
+ "show-send-button", "show-send-button",
+ "Whether or not to show the send button",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT
+ );
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+
/* load our template */
gtk_widget_class_set_template_from_resource(
GTK_WIDGET_CLASS(klass),
@@ -83,8 +203,11 @@
gtk_widget_class_bind_template_child_internal(widget_class, TalkatuEditor, view);
gtk_widget_class_bind_template_child_internal(widget_class, TalkatuEditor, toolbar);
+ gtk_widget_class_bind_template_child_internal(widget_class, TalkatuEditor, send_button);
gtk_widget_class_bind_template_callback(widget_class, talkatu_editor_view_buffer_changed_handler);
+
+ gtk_widget_class_bind_template_callback(widget_class, talkatu_editor_send_button_clicked_cb);
}
/******************************************************************************
@@ -104,6 +227,80 @@
}
/**
+ * talkatu_editor_get_toolbar:
+ * @editor: The #TalkatuEditor instance.
+ *
+ * Gets the #TalkatuToolbar that @editor is using.
+ *
+ * Returns: (transfer none): The #TalkatuToolbar that @editor is using.
+ */
+GtkWidget *
+talkatu_editor_get_toolbar(TalkatuEditor *editor) {
+ g_return_val_if_fail(TALKATU_IS_EDITOR(editor), NULL);
+
+ return editor->toolbar;
+}
+
+/**
+ * talkatu_editor_set_toolbar_visible:
+ * @editor: The #TalkatuEditor instance.
+ * @visible: Whether or not the toolbar should be visible.
+ *
+ * Makes the toolbar visible if @visible is %TRUE otherwise hides it.
+ */
+void
+talkatu_editor_set_toolbar_visible(TalkatuEditor *editor, gboolean visible) {
+ g_return_if_fail(TALKATU_IS_EDITOR(editor));
+
+ gtk_widget_set_visible(editor->toolbar, visible);
+}
+
+/**
+ * talkatu_editor_get_toolbar_visible:
+ * @editor: The #TalkatuEditor instance.
+ *
+ * Returns whether or not the toolbar is visible.
+ *
+ * Returns: %TRUE if the toolbar is visible, %FALSE otherwise.
+ */
+gboolean
+talkatu_editor_get_toolbar_visible(TalkatuEditor *editor) {
+ g_return_val_if_fail(TALKATU_IS_EDITOR(editor), FALSE);
+
+ return gtk_widget_get_visible(editor->toolbar);
+}
+
+/**
+ * talkatu_editor_show_toolbar:
+ * @editor: The #TalkatuEditor instance.
+ *
+ * Shows the toolbar inside of @editor if it was previously hidden.
+ *
+ * Deprecated: use #talkatu_editor_set_toolbar_visible instead.
+ */
+void
+talkatu_editor_show_toolbar(TalkatuEditor *editor) {
+ g_return_if_fail(TALKATU_IS_EDITOR(editor));
+
+ gtk_widget_show(editor->toolbar);
+}
+
+/**
+ * talkatu_editor_hide_toolbar:
+ * @editor: The #TalkatuEditor instance.
+ *
+ * Hides the toolbar inside of @editor if it is currently visible.
+ *
+ * Deprecated: use #talkatu_editor_set_toolbar_visible instead.
+ */
+void
+talkatu_editor_hide_toolbar(TalkatuEditor *editor) {
+ g_return_if_fail(TALKATU_IS_EDITOR(editor));
+
+ gtk_widget_hide(editor->toolbar);
+}
+
+/**
* talkatu_editor_get_view:
* @editor: The #TalkatuEditor instance.
*
@@ -119,42 +316,59 @@
}
/**
- * talkatu_editor_get_toolbar:
+ * talkatu_editor_get_buffer:
* @editor: The #TalkatuEditor instance.
*
- * Gets the #TalkatuToolbar that @editor is using.
+ * Gets the #GtkTextBuffer for the internal view.
*
- * Returns: (transfer none): The #TalkatuToolbar that @editor is using.
+ * Returns: (transfer none): The #GtkTextBuffer for the internal view.
*/
-GtkWidget *
-talkatu_editor_get_toolbar(TalkatuEditor *editor) {
+GtkTextBuffer *
+talkatu_editor_get_buffer(TalkatuEditor *editor) {
g_return_val_if_fail(TALKATU_IS_EDITOR(editor), NULL);
- return editor->toolbar;
+ return gtk_text_view_get_buffer(GTK_TEXT_VIEW(editor->view));
}
/**
- * talkatu_editor_show_toolbar:
+ * talkatu_editor_set_buffer:
* @editor: The #TalkatuEditor instance.
+ * @buffer: A new #GtkTextBuffer to use.
*
- * Shows the toolbar inside of @editor if it was previously hidden.
+ * Sets the #GtkTextBuffer for the internal view to @buffer.
*/
void
-talkatu_editor_show_toolbar(TalkatuEditor *editor) {
+talkatu_editor_set_buffer(TalkatuEditor *editor, GtkTextBuffer *buffer) {
g_return_if_fail(TALKATU_IS_EDITOR(editor));
- gtk_widget_show(editor->toolbar);
+ gtk_text_view_set_buffer(GTK_TEXT_VIEW(editor->view), buffer);
}
/**
- * talkatu_editor_hide_toolbar:
+ * talkatu_editor_get_send_button_visible:
* @editor: The #TalkatuEditor instance.
*
- * Hides the toolbar inside of @editor if it is currently visible.
+ * Returns whether or not the send button is visible.
+ *
+ * Returns: %TRUE if the send button is visible, %FALSE otherwise.
+ */
+gboolean
+talkatu_editor_get_send_button_visible(TalkatuEditor *editor) {
+ g_return_val_if_fail(TALKATU_IS_EDITOR(editor), FALSE);
+
+ return gtk_widget_get_visible(editor->send_button);
+}
+
+/**
+ * talkatu_editor_set_send_button_visible:
+ * @editor: The #TalkatuEditor instance.
+ * @visible: Whether or not the send button should be visible.
+ *
+ * Sets the visibility of the send button depending on @visible.
*/
void
-talkatu_editor_hide_toolbar(TalkatuEditor *editor) {
+talkatu_editor_set_send_button_visible(TalkatuEditor *editor, gboolean visible) {
g_return_if_fail(TALKATU_IS_EDITOR(editor));
- gtk_widget_hide(editor->toolbar);
+ gtk_widget_set_visible(editor->send_button, visible);
}
--- a/talkatu/talkatueditor.h Thu Jul 11 23:00:56 2019 -0500
+++ b/talkatu/talkatueditor.h Sat Jul 13 04:47:52 2019 -0500
@@ -30,18 +30,25 @@
G_BEGIN_DECLS
-#define TALKATU_TYPE_EDITOR (talkatu_editor_get_type())
-
+#define TALKATU_TYPE_EDITOR (talkatu_editor_get_type())
G_DECLARE_FINAL_TYPE(TalkatuEditor, talkatu_editor, TALKATU, EDITOR, GtkBox)
GtkWidget *talkatu_editor_new(void);
-GtkWidget *talkatu_editor_get_view(TalkatuEditor *editor);
GtkWidget *talkatu_editor_get_toolbar(TalkatuEditor *editor);
-
+void talkatu_editor_set_toolbar_visible(TalkatuEditor *editor, gboolean visible);
+gboolean talkatu_editor_get_toolbar_visible(TalkatuEditor *editor);
void talkatu_editor_show_toolbar(TalkatuEditor *editor);
void talkatu_editor_hide_toolbar(TalkatuEditor *editor);
+GtkWidget *talkatu_editor_get_view(TalkatuEditor *editor);
+
+GtkTextBuffer *talkatu_editor_get_buffer(TalkatuEditor *editor);
+void talkatu_editor_set_buffer(TalkatuEditor *editor, GtkTextBuffer *buffer);
+
+gboolean talkatu_editor_get_send_button_visible(TalkatuEditor *editor);
+void talkatu_editor_set_send_button_visible(TalkatuEditor *editor, gboolean visible);
+
G_END_DECLS
#endif /* TALKATU_EDITOR_H */
--- a/talkatu/talkatuview.c Thu Jul 11 23:00:56 2019 -0500
+++ b/talkatu/talkatuview.c Sat Jul 13 04:47:52 2019 -0500
@@ -156,7 +156,7 @@
TalkatuViewPrivate *priv = talkatu_view_get_instance_private(view);
if((priv->send_binding & binding) != 0) {
- g_signal_emit(view, signals[SIG_SEND_MESSAGE], 0);
+ talkatu_view_send_message(view);
} else if(gtk_text_view_get_editable(GTK_TEXT_VIEW(view))) {
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
@@ -184,10 +184,10 @@
}
static void
-talkatu_view_emit_send_message_cb(GtkMenuItem *item, gpointer data) {
- TalkatuView *view = TALKATU_VIEW(data);
+talkatu_view_send_message_cb(GtkMenuItem *item, gpointer data) {
+ talkatu_view_send_message(TALKATU_VIEW(data));
- g_signal_emit(view, signals[SIG_SEND_MESSAGE], 0);
+ gtk_widget_grab_focus(GTK_WIDGET(data));
}
static void
@@ -239,7 +239,7 @@
g_signal_connect_after(
G_OBJECT(item),
"activate",
- G_CALLBACK(talkatu_view_emit_send_message_cb),
+ G_CALLBACK(talkatu_view_send_message_cb),
view
);
gtk_menu_shell_insert(GTK_MENU_SHELL(popup), item, pos++);
@@ -516,3 +516,18 @@
return priv->send_binding;
}
+
+/**
+ * talkatu_view_send_message:
+ * @view: The #TalkatuView instance.
+ *
+ * Emits the signal that @view is trying to send a message. This is used for
+ * cases like the optional send button in #TalkatuEditor and other instances
+ * where the user has performed an actions to send a message.
+ */
+void
+talkatu_view_send_message(TalkatuView *view) {
+ g_return_if_fail(TALKATU_IS_VIEW(view));
+
+ g_signal_emit(view, signals[SIG_SEND_MESSAGE], 0);
+}
\ No newline at end of file
--- a/talkatu/talkatuview.h Thu Jul 11 23:00:56 2019 -0500
+++ b/talkatu/talkatuview.h Sat Jul 13 04:47:52 2019 -0500
@@ -61,6 +61,8 @@
void talkatu_view_set_send_binding(TalkatuView *view, TalkatuViewSendBinding bindings);
TalkatuViewSendBinding talkatu_view_get_send_binding(TalkatuView *view);
+void talkatu_view_send_message(TalkatuView *view);
+
G_END_DECLS
#endif /* TALKATU_VIEW_H */