[Goodies-commits] r6881 - in xfce4-notes-plugin/trunk: . panel-plugin
Mike Massonnet
mmassonnet at xfce.org
Wed Mar 11 04:31:09 CET 2009
Author: mmassonnet
Date: 2009-03-11 03:31:09 +0000 (Wed, 11 Mar 2009)
New Revision: 6881
Added:
xfce4-notes-plugin/trunk/panel-plugin/hypertextview.vala
Modified:
xfce4-notes-plugin/trunk/ChangeLog
xfce4-notes-plugin/trunk/configure.in.in
xfce4-notes-plugin/trunk/panel-plugin/Makefile.am
xfce4-notes-plugin/trunk/panel-plugin/notes.c
xfce4-notes-plugin/trunk/panel-plugin/notes.h
Log:
Include first Vala prototype of Xfce.HypertextView
Modified: xfce4-notes-plugin/trunk/ChangeLog
===================================================================
--- xfce4-notes-plugin/trunk/ChangeLog 2009-03-11 02:31:30 UTC (rev 6880)
+++ xfce4-notes-plugin/trunk/ChangeLog 2009-03-11 03:31:09 UTC (rev 6881)
@@ -1,3 +1,18 @@
+2009-03-11 Mike Massonnet <mmassonnet at xfce.org>
+
+Include first Vala prototype of Xfce.HypertextView
+ * configure.in.in:
+ - Check for the program valac
+ * panel-plugin/Makefile.am:
+ - When in maintainer mode, build the hypertextview C source files
+ with the valac compiler
+ * panel-plugin/hypertextview.vala:
+ - A new object on top of GtkTextView that displays links and makes
+ them clickable + it manages a simple undo/redo history
+ * panel-plugin/notes.c:
+ - Replace gtk_text_view_new against xfce_hypertext_view_new
+ - Remove undo/redo code
+
2009-03-07 Mike Massonnet <mmassonnet at xfce.org>
No rm -rf on the window path
Modified: xfce4-notes-plugin/trunk/configure.in.in
===================================================================
--- xfce4-notes-plugin/trunk/configure.in.in 2009-03-11 02:31:30 UTC (rev 6880)
+++ xfce4-notes-plugin/trunk/configure.in.in 2009-03-11 03:31:09 UTC (rev 6881)
@@ -83,6 +83,17 @@
enable_thunar_vfs=no
fi
+dnl check for valac
+if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
+ AC_CHECK_PROG([has_valac], [valac], [yes], [no])
+ if test "x$has_valac" != "xyes" ; then
+ echo "***"
+ echo "*** You need the valac compiler in order to compile parts of the project"
+ echo "***"
+ echo
+ fi
+fi
+
dnl Translations
XDT_I18N([@LINGUAS@])
@@ -107,6 +118,11 @@
echo
echo "Build Configuration:"
echo
+echo "* Maintainer Mode: $USE_MAINTAINER_MODE"
+if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
+echo " * Vala: $has_valac"
+echo
+fi
echo "* Settings Dialog: $enable_xfconf"
echo "* Thunar-vfs Support: $enable_thunar_vfs"
echo "* Debug Support: $enable_debug"
Modified: xfce4-notes-plugin/trunk/panel-plugin/Makefile.am
===================================================================
--- xfce4-notes-plugin/trunk/panel-plugin/Makefile.am 2009-03-11 02:31:30 UTC (rev 6880)
+++ xfce4-notes-plugin/trunk/panel-plugin/Makefile.am 2009-03-11 03:31:09 UTC (rev 6881)
@@ -13,6 +13,15 @@
@LIBX11_LIBS@ \
@GTK_LIBS@
+if MAINTAINER_MODE
+BUILT_SOURCES = \
+ hypertextview.c \
+ hypertextview.h
+
+hypertextview.c: hypertextview.vala Makefile
+ valac --pkg=gtk+-2.0 hypertextview.vala -C
+endif
+
plugindir = $(libexecdir)/xfce4/panel-plugins
plugin_PROGRAMS = xfce4-notes-plugin
@@ -22,6 +31,8 @@
xfce-arrow-button.h \
color.c \
color.h \
+ hypertextview.c \
+ hypertextview.h \
panel-plugin.c \
settings-dialog.c \
settings-dialog.h \
@@ -52,10 +63,10 @@
@INTLTOOL_DESKTOP_RULE@
EXTRA_DIST = \
- $(desktop_in_in_files)
+ $(desktop_in_in_files) hypertextview.vala
DISTCLEANFILES = \
- $(desktop_DATA) $(desktop_in_files)
+ $(desktop_DATA) $(desktop_in_files) $(BUILT_SOURCES)
# get full path into .desktop file
%.desktop.in: %.desktop.in.in
Added: xfce4-notes-plugin/trunk/panel-plugin/hypertextview.vala
===================================================================
--- xfce4-notes-plugin/trunk/panel-plugin/hypertextview.vala (rev 0)
+++ xfce4-notes-plugin/trunk/panel-plugin/hypertextview.vala 2009-03-11 03:31:09 UTC (rev 6881)
@@ -0,0 +1,389 @@
+/*
+ * Notes - panel plugin for Xfce Desktop Environment
+ * Copyright (c) 2009 Mike Massonnet <mmassonnet at xfce.org>
+ *
+ * TODO: on set_buffer initialize the undo/redo texts
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+using Gtk;
+using Pango;
+
+namespace Xfce {
+
+ public class HypertextView : Gtk.TextView {
+
+ private Gdk.Cursor hand_cursor;
+ private Gdk.Cursor regular_cursor;
+ private bool cursor_over_link = false;
+
+ private uint undo_timeout = 0;
+ private int undo_cursor_pos;
+ private string undo_text = "";
+ private string redo_text = "";
+
+ private uint tag_timeout = 0;
+ private Gtk.TextTag tag_link;
+
+ construct {
+ Gtk.TextIter iter;
+
+ this.hand_cursor = new Gdk.Cursor (Gdk.CursorType.HAND2);
+ this.regular_cursor = new Gdk.Cursor (Gdk.CursorType.XTERM);
+
+ this.button_release_event += button_release_event_cb;
+ this.motion_notify_event += motion_notify_event_cb;
+ this.move_cursor += move_cursor_cb;
+ this.buffer.changed += buffer_changed_cb;
+ this.buffer.insert_text += insert_text_cb;
+ this.buffer.delete_range += delete_range_cb;
+
+ this.buffer.get_iter_at_offset (out iter, 0);
+ this.buffer.create_mark ("undo-pos", iter, false);
+
+ this.tag_link = this.buffer.create_tag ("link",
+ "foreground", "blue", // TODO use __gdk_color_constrast function
+ "underline", Pango.Underline.SINGLE,
+ null);
+ }
+
+ /*
+ * Signal callbacks
+ */
+
+ /**
+ * button_release_event_cb:
+ *
+ * Event to open links.
+ */
+ private bool button_release_event_cb (Xfce.HypertextView hypertextview, Gdk.EventButton event) {
+ Gtk.TextIter start, end, iter;
+ string link;
+ int x, y;
+
+ if (event.button != 1)
+ return false;
+
+ this.buffer.get_selection_bounds (out start, out end);
+ if (start.get_offset () != end.get_offset ())
+ return false;
+
+ window_to_buffer_coords (Gtk.TextWindowType.WIDGET, (int)event.x, (int)event.y, out x, out y);
+ get_iter_at_location (out iter, x, y);
+
+ if (iter.has_tag (this.tag_link)) {
+ start = end = iter;
+
+ if (!start.begins_tag (this.tag_link)) {
+ start.backward_to_tag_toggle (this.tag_link);
+ }
+
+ end.forward_to_tag_toggle (this.tag_link);
+
+ link = start.get_text (end);
+
+ try {
+ GLib.AppInfo.launch_default_for_uri (link, null);
+ } catch (Error ex) {
+ warning ("Unable to open link `%s': %s", link, ex.message);
+
+ if (Gdk.spawn_command_line_on_screen (Gdk.Screen.get_default (), "xdg-open "+link)) {
+ return false;
+ }
+
+ if (Gdk.spawn_command_line_on_screen (Gdk.Screen.get_default (), "firefox "+link)) {
+ return false;
+ }
+
+ critical ("Impossible to find an appropriate fallback to open the link");
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * motion_notify_event_cb:
+ *
+ * Event to update the cursor of the pointer.
+ */
+ private bool motion_notify_event_cb (Xfce.HypertextView hypertextview, Gdk.EventMotion event) {
+ Gtk.TextIter iter;
+ Gdk.Window win;
+ bool over_link;
+ int x, y;
+
+ window_to_buffer_coords (Gtk.TextWindowType.WIDGET, (int)event.x, (int)event.y, out x, out y);
+ get_iter_at_location (out iter, x, y);
+ over_link = iter.has_tag (this.tag_link);
+
+ if (over_link != this.cursor_over_link) {
+ this.cursor_over_link = over_link;
+ win = get_window (Gtk.TextWindowType.TEXT);
+ win.set_cursor (over_link ? this.hand_cursor : this.regular_cursor);
+ }
+
+ return false;
+ }
+
+ /**
+ * move_cursor_cb:
+ *
+ * Destroys existing timeouts and executes the actions immediately.
+ */
+ private void move_cursor_cb (Xfce.HypertextView hypertextview, Gtk.MovementStep step, int count, bool extend_selection) {
+ if (this.undo_timeout > 0) {
+ /* Make an undo snapshot and save cursor_position before it really moves */
+ Source.remove (this.undo_timeout);
+ undo_snapshot ();
+ this.undo_cursor_pos = this.buffer.cursor_position;
+ }
+
+ if (this.tag_timeout > 0) {
+ Source.remove (this.tag_timeout);
+ update_tags ();
+ }
+ }
+
+ /**
+ * buffer_changed_cb:
+ *
+ * Initializes timeouts to postpone actions.
+ */
+ private void buffer_changed_cb () {
+ /* Initialize undo_timeout */
+ if (this.undo_timeout > 0) {
+ Source.remove (this.undo_timeout);
+ }
+ this.undo_timeout = Timeout.add_seconds_full (Priority.DEFAULT, 2,
+ undo_snapshot, undo_timeout_destroy);
+
+ /* Reinit tag_timeout as long as the buffer is under constant changes */
+ if (this.tag_timeout > 0) {
+ Source.remove (this.tag_timeout);
+ this.tag_timeout = Timeout.add_seconds_full (Priority.DEFAULT, 2,
+ tag_timeout_cb, tag_timeout_destroy);
+ }
+ }
+
+ /**
+ * insert_text_cb:
+ *
+ * Event to create and update existing tags within the buffer.
+ */
+ private void insert_text_cb (Gtk.TextBuffer buffer, Gtk.TextIter location, string text, int len) {
+ Gtk.TextIter start, end;
+
+ /* Text is inserted inside a tag */
+ if (location.has_tag (this.tag_link) && !location.begins_tag (this.tag_link)) {
+ start = location;
+ start.backward_to_tag_toggle (this.tag_link);
+
+ if (location.get_offset () - start.get_offset () < 7) {
+ end = start;
+ end.forward_to_tag_toggle (this.tag_link);
+
+ this.buffer.remove_tag (this.tag_link, start, end);
+
+ if (len > 1 && (text.contains (" ") || text.contains ("\n"))) {
+ /* We are here because there is a chance in a million that the
+ * user pasted a text that ends with " ht" in front of "tp://"
+ */
+ tag_timeout_init ();
+ }
+ }
+ else if (text.contains (" ") || text.contains ("\n")) {
+ end = location;
+ end.forward_to_tag_toggle (this.tag_link);
+
+ this.buffer.remove_tag (this.tag_link, start, end);
+
+ tag_timeout_init ();
+ }
+ }
+
+ /* Text is inserted at the end of a tag */
+ else if (location.ends_tag (this.tag_link)) {
+ start = location;
+ start.backward_to_tag_toggle (this.tag_link);
+
+ this.buffer.remove_tag (this.tag_link, start, location);
+
+ tag_timeout_init ();
+ }
+
+ /* Check if the word being typed is "http://" */
+ else if (len == 1 && text[0] == '/') {
+ start = location;
+
+ if (!start.backward_chars (6) || start.get_text(location).down () != "http:/")
+ return;
+
+ tag_timeout_init ();
+ }
+
+ /* Text contains links */
+ else if (len > 1 && text.contains ("http://")) {
+ tag_timeout_init ();
+ }
+ }
+
+ /**
+ * delete_range_cb:
+ *
+ * Event to delete and update existing tags within the buffer.
+ */
+ private void delete_range_cb (Gtk.TextBuffer buffer, Gtk.TextIter start, Gtk.TextIter end) {
+ Gtk.TextIter iter;
+
+ if (!start.has_tag (this.tag_link) && !end.has_tag (this.tag_link))
+ return;
+
+ if (start.has_tag (this.tag_link)) {
+ iter = start;
+ iter.backward_to_tag_toggle (this.tag_link);
+ this.buffer.remove_tag (this.tag_link, iter, start);
+ }
+
+ if (end.has_tag (this.tag_link)) {
+ iter = end;
+ iter.forward_to_tag_toggle (this.tag_link);
+ this.buffer.remove_tag (this.tag_link, end, iter);
+ }
+
+ tag_timeout_init ();
+ }
+
+ /*
+ * Undo
+ */
+
+ /**
+ * undo_snapshot:
+ *
+ * Makes a snapshot of the current buffer and swaps undo/redo texts.
+ */
+ private bool undo_snapshot () {
+ Gtk.TextIter start, end;
+
+ this.undo_cursor_pos = this.buffer.cursor_position;
+
+ this.buffer.get_iter_at_offset (out start, 0);
+ this.buffer.get_iter_at_offset (out end, -1);
+
+ this.undo_text = this.redo_text;
+ this.redo_text = this.buffer.get_text (start, end, false);
+
+ return false;
+ }
+
+ private void undo_timeout_destroy () {
+ this.undo_timeout = 0;
+ }
+
+ /**
+ * undo:
+ *
+ * Revert the buffer to the undo text and swaps undo/redo texts.
+ */
+ public void undo () {
+ Gtk.TextIter iter;
+ Gtk.TextMark mark;
+ string tmp;
+
+ if (this.undo_timeout > 0) {
+ /* Make an undo snaphot */
+ Source.remove (this.undo_timeout);
+ undo_snapshot ();
+ }
+
+ this.buffer.set_text (this.undo_text, -1);
+ this.buffer.get_iter_at_offset (out iter, this.undo_cursor_pos);
+ this.buffer.place_cursor (iter);
+
+ /* Scroll to the cursor position */
+ mark = this.buffer.get_mark ("undo-pos");
+ this.buffer.move_mark (mark, iter);
+ this.scroll_to_mark (mark, 0.0, false, 0.5, 0.5);
+
+ tmp = this.undo_text;
+ this.undo_text = this.redo_text;
+ this.redo_text = tmp;
+
+ Source.remove (this.undo_timeout);
+ }
+
+ /*
+ * Tags
+ */
+
+ private bool tag_timeout_cb () {
+ update_tags ();
+ return false;
+ }
+
+ private void tag_timeout_init () {
+ if (this.tag_timeout > 0) {
+ Source.remove (this.tag_timeout);
+ }
+
+ this.tag_timeout = Timeout.add_seconds_full (Priority.DEFAULT, 2,
+ tag_timeout_cb, tag_timeout_destroy);
+ }
+
+ private void tag_timeout_destroy () {
+ this.tag_timeout = 0;
+ }
+
+ /**
+ * update_tags:
+ *
+ * Goes through the entire document to search for untagged HTTP links and tag them.
+ */
+ public void update_tags () {
+ Gtk.TextIter iter, start, end, tmp;
+
+ if (this.tag_timeout > 0)
+ Source.remove (this.tag_timeout);
+
+ this.buffer.get_iter_at_offset (out iter, 0);
+
+ while (iter.forward_search ("http://", Gtk.TextSearchFlags.TEXT_ONLY, out start, out end, null)) {
+ iter = end;
+
+ if (start.begins_tag (this.tag_link))
+ continue;
+
+ if (!iter.forward_search (" ", Gtk.TextSearchFlags.TEXT_ONLY, out end, null, null)) {
+ if (!iter.forward_search ("\n", Gtk.TextSearchFlags.TEXT_ONLY, out end, null, null)) {
+ this.buffer.get_iter_at_offset (out end, -1);
+ }
+ }
+ else if (iter.forward_search ("\n", Gtk.TextSearchFlags.TEXT_ONLY, out tmp, null, null)) {
+ if (tmp.get_offset () < end.get_offset ()) {
+ end = tmp;
+ }
+ }
+
+ if (end.get_offset () - start.get_offset () >= 7)
+ this.buffer.apply_tag (this.tag_link, start, end);
+ }
+ }
+
+ }
+
+}
+
Modified: xfce4-notes-plugin/trunk/panel-plugin/notes.c
===================================================================
--- xfce4-notes-plugin/trunk/panel-plugin/notes.c 2009-03-11 02:31:30 UTC (rev 6880)
+++ xfce4-notes-plugin/trunk/panel-plugin/notes.c 2009-03-11 03:31:09 UTC (rev 6881)
@@ -36,6 +36,7 @@
#include "defines.h"
#include "notes.h"
#include "xfce-arrow-button.h"
+#include "hypertextview.h"
#define PLUGIN_NAME "xfce4-notes-plugin"
#define OPAQUE 0xffffffff
@@ -126,14 +127,8 @@
GdkEventKey *event);
static void notes_note_buffer_changed (NotesNote *notes_note);
-static void notes_note_destroy_undo_timeout (NotesNote *notes_note);
-static gboolean notes_note_undo_snapshot (NotesNote *notes_note);
-static void notes_note_undo (NotesNote *notes_note);
-
-
-
/**
* NotesWindow
*/
@@ -1654,7 +1649,7 @@
notes_window_undo (NotesWindow *notes_window)
{
NotesNote *current_note = notes_window_get_current_note (notes_window);
- notes_note_undo (current_note);
+ xfce_hypertext_view_undo (XFCE_HYPERTEXT_VIEW (current_note->text_view));
}
@@ -1732,7 +1727,7 @@
GTK_POLICY_AUTOMATIC);
/* Text view */
- notes_note->text_view = gtk_text_view_new ();
+ notes_note->text_view = (GtkWidget *)xfce_hypertext_view_new ();
g_object_set (notes_note->text_view,
"wrap-mode", GTK_WRAP_WORD,
"left-margin", 2,
@@ -1741,8 +1736,6 @@
"pixels-below-lines", 1,
NULL);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (notes_note->text_view));
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &iter, 0);
- gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), "undo-pos", &iter, FALSE);
if (NULL != notes_note->notes_window->font)
notes_note_set_font (notes_note, notes_note->notes_window->font);
gtk_container_add (GTK_CONTAINER (notes_note->scrolled_window),
@@ -1793,12 +1786,6 @@
if (notes_note->timeout != 0)
g_source_remove (notes_note->timeout);
- /* Remove undo/redo data */
- if (notes_note->undo_timeout != 0)
- g_source_remove (notes_note->undo_timeout);
- g_free (notes_note->undo_text);
- g_free (notes_note->redo_text);
-
/* Remove notebook page */
id = g_slist_index (notes_window->notes, notes_note);
gtk_notebook_remove_page (GTK_NOTEBOOK (notes_window->notebook), id);
@@ -1865,10 +1852,6 @@
TRACE ("Load data for notes `%s':\n%s", notes_note->name, contents);
gtk_text_buffer_set_text (buffer, contents, -1);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (notes_note->text_view), buffer);
-
- /* Set initial undo/redo text */
- notes_note->undo_text = g_strdup (contents);
- notes_note->redo_text = g_strdup (contents);
}
g_free (contents);
@@ -2108,70 +2091,5 @@
notes_note->timeout = 0;
}
notes_note->timeout = g_timeout_add (60000, (GSourceFunc)notes_note_save_data, notes_note);
-
- /* Undo timeout */
- if (notes_note->undo_timeout > 0)
- g_source_remove (notes_note->undo_timeout);
- notes_note->undo_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, 1230,
- (GSourceFunc)notes_note_undo_snapshot, notes_note,
- (GDestroyNotify)notes_note_destroy_undo_timeout);
}
-static void
-notes_note_destroy_undo_timeout (NotesNote *notes_note)
-{
- notes_note->undo_timeout = 0;
-}
-
-static gboolean
-notes_note_undo_snapshot (NotesNote *notes_note)
-{
- GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (notes_note->text_view));
- GtkTextIter start, end;
-
- g_object_get (buffer, "cursor-position", ¬es_note->cursor_pos, NULL);
-
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &start, 0);
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &end, -1);
-
- g_free (notes_note->undo_text);
- notes_note->undo_text = notes_note->redo_text;
- notes_note->redo_text = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (buffer),
- &start, &end, FALSE);
-
- return FALSE;
-}
-
-static void
-notes_note_undo (NotesNote *notes_note)
-{
- GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (notes_note->text_view));
- gchar *tmp;
- GtkTextIter iter;
- GtkTextMark *mark;
-
- if (notes_note->undo_timeout > 0)
- {
- /* Take the snapshot by hand */
- g_source_remove (notes_note->undo_timeout);
- notes_note_undo_snapshot (notes_note);
- }
-
- if (notes_note->undo_text == NULL)
- notes_note->undo_text = g_strdup ("");
-
- gtk_text_buffer_set_text (GTK_TEXT_BUFFER (buffer), notes_note->undo_text, -1);
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &iter, notes_note->cursor_pos);
- gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (buffer), &iter);
-
- mark = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (buffer), "undo-pos");
- gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (buffer), mark, &iter);
- gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (notes_note->text_view), mark, 0.0, FALSE, 0.5, 0.5);
-
- tmp = notes_note->undo_text;
- notes_note->undo_text = notes_note->redo_text;
- notes_note->redo_text = tmp;
-
- g_source_remove (notes_note->undo_timeout);
-}
-
Modified: xfce4-notes-plugin/trunk/panel-plugin/notes.h
===================================================================
--- xfce4-notes-plugin/trunk/panel-plugin/notes.h 2009-03-11 02:31:30 UTC (rev 6880)
+++ xfce4-notes-plugin/trunk/panel-plugin/notes.h 2009-03-11 03:31:09 UTC (rev 6881)
@@ -121,11 +121,6 @@
GtkWidget *scrolled_window;
GtkWidget *text_view;
- gint cursor_pos;
- guint undo_timeout;
- gchar *undo_text;
- gchar *redo_text;
-
#ifdef HAVE_THUNAR_VFS
gboolean delete;
#endif
More information about the Goodies-commits
mailing list