GtkSharp/sample/GtkDemo/DemoHyperText.cs
Dan Winship 62258ca7c3 * generator/CallbackGen.cs:
* generator/CodeGenerator.cs: 
        * generator/ManagedCallString.cs:
        * generator/Property.cs: Remove unused vars

        * generator/Method.cs (GetHashCode): have to implement this since
        we're overriding Equals.

        * generator/CallbackGen.cs: print a message when generating a
        broken struct-returning callback. (Currently affects
        GtkSharp.TextSegSplitFuncNative and
        GtkSharp.TextSegCleanupFuncNative)

        * gdk/glue/device.c: 
        * gdk/glue/dragcontext.c: Add missing prototypes

        * gtk/Gtk.metadata: Mark SeparatorToolItem.Draw "new". Re-rename
        CheckMenuItem.Toggled to EmitToggled rather than Toggle, since
        that's a better description of what it does.

        * gtk/CheckMenuItem.custom: implement a "Toggle" method that does
        what the documentation claims it does.

        * gtk/NodeStore.cs: remove unused var

        * gnome/Gnome.metadata: mark DateEdit.Flags, Dialog.Default, and
        PropertyBox.State "new". Hide GnomePixmapEntry.GnomeEntry and
        GnomePixmapEntry.GtkEntry since they do exactly the same thing as
        the methods of the same names inherited from GnomeFileEntry.

        * gnome/glue/canvas-proxy.c:
        * gnome/glue/canvas-proxy.h:
        * gnome/glue/canvas-proxy-marshal.c:
        * gnome/glue/canvas-proxy-marshal.h:
        * gnome/glue/canvas-proxy-marshal.list: Remove unused code

        * gnome/glue/Makefile.am (libgnomesharpglue_2_la_SOURCES): update

        * panelapplet/PanelApplet.metadata: mark PanelApplet.Flags "new"

        * sample/CanvasExample.cs: 
        * sample/CustomCellRenderer.cs: 
        * sample/CustomNotebook.cs: 
        * sample/DrawingSample.cs:
        * sample/Fifteen.cs: 
        * sample/GladeTest.cs: 
        * sample/GtkDemo/DemoHyperText.cs: 
        * sample/GtkDemo/DemoPixbuf.cs: 
        * sample/ScribbleXInput.cs: remove unused vars, use
        GLib.Timeout.Add rather than the deprecated Gtk.Timeout.Add

svn path=/trunk/gtk-sharp/; revision=38043
2004-12-21 18:46:42 +00:00

214 lines
6 KiB
C#

//
// Author: John Luke <john.luke@gmail.com>
// ported from gtk-demo in GTK+
// Demostrates HyperLinks in the TextView
//
using System;
using Gtk;
namespace GtkDemo
{
[Demo ("Hyper Text", "DemoHyperText.cs", "Text Widget")]
public class DemoHyperText : Gtk.Window
{
bool hoveringOverLink = false;
Gdk.Cursor handCursor, regularCursor;
public DemoHyperText () : base ("HyperText")
{
this.DeleteEvent += new DeleteEventHandler (OnWindowDelete);
this.SetDefaultSize (450, 450);
CreateCursors ();
this.Add (CreateScrolledWindow ());
this.ShowAll ();
}
void CreateCursors ()
{
handCursor = new Gdk.Cursor (Gdk.CursorType.Hand2);
regularCursor = new Gdk.Cursor (Gdk.CursorType.Xterm);
}
ScrolledWindow CreateScrolledWindow ()
{
ScrolledWindow sw = new ScrolledWindow ();
sw.Add (CreateTextView ());
return sw;
}
TextView CreateTextView ()
{
TextView view = new TextView ();
view.WrapMode = WrapMode.Word;
view.KeyPressEvent += new KeyPressEventHandler (OnKeyPress);
view.MotionNotifyEvent += new MotionNotifyEventHandler (OnMotionNotify);
view.VisibilityNotifyEvent += new VisibilityNotifyEventHandler (OnVisibilityNotify);
view.ButtonReleaseEvent += new ButtonReleaseEventHandler (OnButtonRelease);
ShowPage (view.Buffer, 1);
return view;
}
// Inserts a piece of text into the buffer, giving it the usual
// appearance of a hyperlink in a web browser: blue and underlined.
// Additionally, attaches some data on the tag, to make it recognizable
// as a link.
void InsertLink (TextBuffer buffer, ref TextIter iter, string text, int page)
{
TextTag tag = new TextTag ("link");
tag.Foreground = "blue";
tag.Underline = Pango.Underline.Single;
tag.Data.Add ("page", page);
buffer.TagTable.Add (tag);
buffer.InsertWithTags (ref iter, text, tag);
}
// Fills the buffer with text and interspersed links. In any real
// hypertext app, this method would parse a file to identify the links.
void ShowPage (TextBuffer buffer, int page)
{
buffer.Text = "";
TextIter iter = buffer.GetIterAtOffset (0);
if (page == 1)
{
buffer.Insert (ref iter, "Some text to show that simple ");
InsertLink (buffer, ref iter, "hypertext", 3);
buffer.Insert (ref iter, " can easily be realized with ");
InsertLink (buffer, ref iter, "tags", 2);
buffer.Insert (ref iter, ".");
}
else if (page == 2)
{
buffer.Insert (ref iter,
"A tag is an attribute that can be applied to some range of text. " +
"For example, a tag might be called \"bold\" and make the text inside " +
"the tag bold. However, the tag concept is more general than that; " +
"tags don't have to affect appearance. They can instead affect the " +
"behavior of mouse and key presses, \"lock\" a range of text so the " +
"user can't edit it, or countless other things.\n");
InsertLink (buffer, ref iter, "Go back", 1);
}
else if (page == 3)
{
TextTag tag = new TextTag ("bold");
tag.Weight = Pango.Weight.Bold;
buffer.InsertWithTags (ref iter, "hypertext:\n", tag);
buffer.Insert (ref iter,
"machine-readable text that is not sequential but is organized" +
"so that related items of information are connected.\n");
InsertLink (buffer, ref iter, "Go back", 1);
}
}
// Looks at all tags covering the position of iter in the text view,
// and if one of them is a link, follow it by showing the page identified
// by the data attached to it.
void FollowIfLink (TextView view, TextIter iter)
{
foreach (TextTag tag in iter.Tags)
{
int page = (int) tag.Data ["page"];
if (page != 0)
ShowPage (view.Buffer, page);
}
}
// Looks at all tags covering the position (x, y) in the text view,
// and if one of them is a link, change the cursor to the "hands" cursor
// typically used by web browsers.
void SetCursorIfAppropriate (TextView view, int x, int y)
{
bool hovering = false;
TextIter iter = view.GetIterAtLocation (x, y);
foreach (TextTag tag in iter.Tags)
{
int page = (int) tag.Data ["page"];
if (page != 0) {
hovering = true;
break;
}
}
if (hovering != hoveringOverLink)
{
hoveringOverLink = hovering;
if (hoveringOverLink)
view.GdkWindow.Cursor = handCursor;
else
view.GdkWindow.Cursor = regularCursor;
}
}
void OnButtonRelease (object sender, ButtonReleaseEventArgs a)
{
if (a.Event.Button != 1)
return;
TextView view = sender as TextView;
TextIter start, end, iter;
int x, y;
view.Buffer.GetSelectionBounds (out start, out end);
if (start.Offset != end.Offset)
return;
view.WindowToBufferCoords (TextWindowType.Widget, (int) a.Event.X, (int) a.Event.Y, out x, out y);
iter = view.GetIterAtLocation (x, y);
FollowIfLink (view, iter);
}
// Links can be activated by pressing Enter.
void OnKeyPress (object sender, KeyPressEventArgs a)
{
TextView view = sender as TextView;
switch ((Gdk.Key) a.Event.KeyValue) {
case Gdk.Key.Return:
case Gdk.Key.KP_Enter:
TextIter iter = view.Buffer.GetIterAtMark (view.Buffer.InsertMark);
FollowIfLink (view, iter);
break;
default:
break;
}
}
//Update the cursor image if the pointer moved.
void OnMotionNotify (object sender, MotionNotifyEventArgs a)
{
TextView view = sender as TextView;
int x, y;
view.WindowToBufferCoords (TextWindowType.Widget, (int) a.Event.X, (int) a.Event.Y, out x, out y);
SetCursorIfAppropriate (view, x, y);
}
// Also update the cursor image if the window becomes visible
// (e.g. when a window covering it got iconified).
void OnVisibilityNotify (object sender, VisibilityNotifyEventArgs a)
{
TextView view = sender as TextView;
int wx, wy, bx, by;
view.GetPointer (out wx, out wy);
view.WindowToBufferCoords (TextWindowType.Widget, wx, wy, out bx, out by);
SetCursorIfAppropriate (view, bx, by);
}
void OnWindowDelete (object sender, DeleteEventArgs a)
{
this.Hide ();
this.Destroy ();
a.RetVal = true;
}
}
}