]> git.llucax.com Git - z.facultad/75.42/plaqui.git/commitdiff
Se agrega ejemplo de DND con icono.
authorLeandro Lucarella <llucax@gmail.com>
Fri, 10 Oct 2003 14:56:43 +0000 (14:56 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Fri, 10 Oct 2003 14:56:43 +0000 (14:56 +0000)
tests/gtkmm/dnd_pixmap/cone.xpm [new file with mode: 0644]
tests/gtkmm/dnd_pixmap/cube.xpm [new file with mode: 0644]
tests/gtkmm/dnd_pixmap/dnd.c [new file with mode: 0644]
tests/gtkmm/dnd_pixmap/sphere.xpm [new file with mode: 0644]

diff --git a/tests/gtkmm/dnd_pixmap/cone.xpm b/tests/gtkmm/dnd_pixmap/cone.xpm
new file mode 100644 (file)
index 0000000..f3b0663
--- /dev/null
@@ -0,0 +1,171 @@
+/* XPM */
+static char * cone_xpm[] = {
+"20 20 148 2",
+"      c None",
+".     c #1F9715",
+"+     c #1E9614",
+"@     c #80D579",
+"#     c #64C75B",
+"$     c #1B9310",
+"%     c #42C835",
+"&     c #A6E99F",
+"*     c #79E06E",
+"=     c #39BD2E",
+"-     c #239B17",
+";     c #72E468",
+">     c #BBF0B6",
+",     c #78E66E",
+"'     c #4AD23D",
+")     c #138909",
+"!     c #239D18",
+"~     c #3EBE32",
+"{     c #8FE888",
+"]     c #B3EEAD",
+"^     c #68E75C",
+"/     c #4DD440",
+"(     c #1E9914",
+"_     c #0D7F03",
+":     c #32B226",
+"<     c #54D749",
+"[     c #A9EBA3",
+"}     c #A7ECA0",
+"|     c #5EE152",
+"1     c #4ACE3E",
+"2     c #31B126",
+"3     c #1B9110",
+"4     c #1C9212",
+"5     c #32B128",
+"6     c #6DDF62",
+"7     c #B4EEAF",
+"8     c #91EA88",
+"9     c #59DC4D",
+"0     c #48CC3C",
+"a     c #3CBE31",
+"b     c #28A61D",
+"c     c #2FAD24",
+"d     c #54D849",
+"e     c #8BE882",
+"f     c #AFEEA9",
+"g     c #7BE871",
+"h     c #56DA4A",
+"i     c #44C738",
+"j     c #3EC033",
+"k     c #2EAC22",
+"l     c #18910D",
+"m     c #39B92E",
+"n     c #66E15A",
+"o     c #A1ED9C",
+"p     c #A9EEA3",
+"q     c #6EE563",
+"r     c #52D546",
+"s     c #43C637",
+"t     c #42C537",
+"u     c #35B62A",
+"v     c #25A119",
+"w     c #108406",
+"x     c #2FAF24",
+"y     c #52D745",
+"z     c #80E877",
+"A     c #A5ED9D",
+"B     c #99EC92",
+"C     c #67E45B",
+"D     c #4ED242",
+"E     c #47C93B",
+"F     c #3CBD30",
+"G     c #1B9410",
+"H     c #7F7F7F",
+"I     c #35B629",
+"J     c #5DDC51",
+"K     c #8BE983",
+"L     c #A7EDA1",
+"M     c #8EEA86",
+"N     c #5FE153",
+"O     c #48CB3C",
+"P     c #49CC3D",
+"Q     c #3CBE30",
+"R     c #2AA91F",
+"S     c #219E16",
+"T     c #118607",
+"U     c #27A31C",
+"V     c #41C835",
+"W     c #6FDD64",
+"X     c #89E681",
+"Y     c #A1EC9A",
+"Z     c #84E87A",
+"`     c #5ADC4E",
+" .    c #3EC133",
+"..    c #2AAA1F",
+"+.    c #23A018",
+"@.    c #1A930F",
+"#.    c #2AA61E",
+"$.    c #3EC333",
+"%.    c #69DB5E",
+"&.    c #8EE786",
+"*.    c #98EA90",
+"=.    c #7EE674",
+"-.    c #58DB4C",
+";.    c #45CA39",
+">.    c #47CA3B",
+",.    c #3FC033",
+"'.    c #2FB024",
+").    c #28A61C",
+"!.    c #1F9B15",
+"~.    c #0B7C01",
+"{.    c #29A51E",
+"].    c #3CC030",
+"^.    c #50D544",
+"/.    c #7AE271",
+"(.    c #82E677",
+"_.    c #71E367",
+":.    c #53D647",
+"<.    c #47CB3B",
+"[.    c #44C739",
+"}.    c #39BA2E",
+"|.    c #2DAC22",
+"1.    c #29A81E",
+"2.    c #1D9913",
+"3.    c #1B9111",
+"4.    c #229C18",
+"5.    c #39B92D",
+"6.    c #42C336",
+"7.    c #4FD143",
+"8.    c #57D64C",
+"9.    c #45C739",
+"0.    c #44C638",
+"a.    c #3BBC2F",
+"b.    c #2AA81F",
+"c.    c #209A15",
+"d.    c #1A9210",
+"e.    c #2FAB25",
+"f.    c #30AD26",
+"g.    c #2CA720",
+"h.    c #32B026",
+"i.    c #35B429",
+"j.    c #37B62C",
+"k.    c #38B82C",
+"l.    c #24A019",
+"m.    c #128607",
+"n.    c #0C7E02",
+"o.    c #198E0D",
+"p.    c #178B0D",
+"q.    c #128507",
+"                                        ",
+"                  . .                   ",
+"                + @ # $                 ",
+"                % & * =                 ",
+"              - ; > , ' )               ",
+"              - ; > , ' )               ",
+"            ! ~ { ] ^ / ( _             ",
+"            : < [ } | 1 2 3             ",
+"          4 5 6 7 8 9 0 a b _           ",
+"          c d e f g h i j k l           ",
+"        4 m n o p q r s t u v w         ",
+"        x y z A B C D E E F b G H       ",
+"      4 I J K L M N D O P Q R S T H     ",
+"      U V W X Y Z ` 0 O 0  ...+.@.H H   ",
+"    4 #.$.%.&.*.=.-.;.O >.,.'.).!.~.H H ",
+"    4 {.].^./.(._.:.<.>.[.}.|.1.2.~.H   ",
+"      3.4.5.6.7.8.0 9.0.a.b.c.d.T H     ",
+"          e.f.g.h.i.j.k.l.m.n.H         ",
+"                3.o.p.q.                ",
+"                                        "};
diff --git a/tests/gtkmm/dnd_pixmap/cube.xpm b/tests/gtkmm/dnd_pixmap/cube.xpm
new file mode 100644 (file)
index 0000000..e82fc1d
--- /dev/null
@@ -0,0 +1,197 @@
+/* XPM */
+static char * cube_xpm[] = {
+"20 20 174 2",
+"      c None",
+".     c #3C3CAD",
+"+     c #6161D1",
+"@     c #5757CA",
+"#     c #4E4EC7",
+"$     c #4C4CC8",
+"%     c #5454CB",
+"&     c #5959CD",
+"*     c #5858CD",
+"=     c #4747C4",
+"-     c #3838BA",
+";     c #3A3ABD",
+">     c #3737B9",
+",     c #22229D",
+"'     c #3434A5",
+")     c #8181E6",
+"!     c #9393ED",
+"~     c #9D9DEF",
+"{     c #8B8BED",
+"]     c #8080EC",
+"^     c #7474EB",
+"/     c #7171EB",
+"(     c #7070EB",
+"_     c #6565E9",
+":     c #5E5EE5",
+"<     c #4F4FDA",
+"[     c #2D2DB1",
+"}     c #0B0B7E",
+"|     c #4B4BA4",
+"1     c #8F8FEB",
+"2     c #9B9BEE",
+"3     c #A2A2EF",
+"4     c #A5A5F0",
+"5     c #9696EF",
+"6     c #8C8CED",
+"7     c #7B7BEC",
+"8     c #7575EC",
+"9     c #6262E7",
+"0     c #5D5DE2",
+"a     c #1F1FA6",
+"b     c #0B0B90",
+"c     c #04047B",
+"d     c #5151A1",
+"e     c #8484E4",
+"f     c #9C9CED",
+"g     c #A1A1EF",
+"h     c #A4A4F1",
+"i     c #A4A4EF",
+"j     c #9A9AEC",
+"k     c #8989E7",
+"l     c #8484E6",
+"m     c #7878E6",
+"n     c #6868E3",
+"o     c #5C5CE1",
+"p     c #2424AA",
+"q     c #0E0E98",
+"r     c #09098A",
+"s     c #7171C5",
+"t     c #9F9FEC",
+"u     c #A4A4EE",
+"v     c #A4A4ED",
+"w     c #A3A3ED",
+"x     c #A1A1ED",
+"y     c #A0A0ED",
+"z     c #9C9CEC",
+"A     c #9A9AEA",
+"B     c #9898E9",
+"C     c #8888E8",
+"D     c #8080E4",
+"E     c #0B0B8E",
+"F     c #0A0A84",
+"G     c #5858CF",
+"H     c #6A6AD5",
+"I     c #6969D4",
+"J     c #6767D3",
+"K     c #6969D5",
+"L     c #5D5DD1",
+"M     c #5050D2",
+"N     c #4E4ED2",
+"O     c #5353CD",
+"P     c #4C4CC7",
+"Q     c #3A3AC8",
+"R     c #090984",
+"S     c #5B5BD0",
+"T     c #6565D4",
+"U     c #6262D1",
+"V     c #5C5CCC",
+"W     c #5D5DD5",
+"X     c #4C4CD0",
+"Y     c #4D4DCB",
+"Z     c #4F4FCC",
+"`     c #4B4BCA",
+" .    c #3939C6",
+"..    c #5656D0",
+"+.    c #5959D0",
+"@.    c #5D5DCD",
+"#.    c #6060D2",
+"$.    c #5D5DD8",
+"%.    c #6060D7",
+"&.    c #5151CE",
+"*.    c #4343C9",
+"=.    c #3C3CC5",
+"-.    c #2C2CC2",
+";.    c #0A0A8C",
+">.    c #4F4FCF",
+",.    c #5B5BCD",
+"'.    c #5656CB",
+").    c #4E4EC8",
+"!.    c #5252CE",
+"~.    c #5151D4",
+"{.    c #4949CB",
+"].    c #4747C9",
+"^.    c #4343CB",
+"/.    c #3232C1",
+"(.    c #2525C1",
+"_.    c #0F0F9A",
+":.    c #060682",
+"<.    c #7F7F7F",
+"[.    c #4A4ACD",
+"}.    c #5050C6",
+"|.    c #5858D0",
+"1.    c #5151CF",
+"2.    c #4949C6",
+"3.    c #4747C8",
+"4.    c #4040C7",
+"5.    c #3E3ECA",
+"6.    c #2727BE",
+"7.    c #2424BF",
+"8.    c #1313A2",
+"9.    c #020275",
+"0.    c #0F0F87",
+"a.    c #3C3CC9",
+"b.    c #4B4BC4",
+"c.    c #5454C8",
+"d.    c #4A4AC9",
+"e.    c #4545C5",
+"f.    c #4141C9",
+"g.    c #3D3DCA",
+"h.    c #2D2DBE",
+"i.    c #2525C0",
+"j.    c #2323BE",
+"k.    c #1313A1",
+"l.    c #0C0C91",
+"m.    c #000070",
+"n.    c #3434C7",
+"o.    c #3E3EC6",
+"p.    c #4242CA",
+"q.    c #4444C2",
+"r.    c #4646C9",
+"s.    c #4040C9",
+"t.    c #2828C4",
+"u.    c #2727C4",
+"v.    c #1313A0",
+"w.    c #04047D",
+"x.    c #2E2EC6",
+"y.    c #3232BC",
+"z.    c #3737BC",
+"A.    c #3838BF",
+"B.    c #3333C3",
+"C.    c #2828BE",
+"D.    c #2323BD",
+"E.    c #2222BB",
+"F.    c #2222BC",
+"G.    c #13139F",
+"H.    c #050580",
+"I.    c #2626C2",
+"J.    c #2424BD",
+"K.    c #2424BE",
+"L.    c #2626C3",
+"M.    c #0B0B8C",
+"N.    c #07077F",
+"O.    c #090983",
+"P.    c #0E0E8E",
+"Q.    c #04047A",
+"                                        ",
+"                                        ",
+"                                        ",
+"          . + @ # $ % & * = - ; > ,     ",
+"        ' ) ! ~ { ] ^ / ( _ : < [ }     ",
+"      | 1 2 3 4 5 6 7 8 ( 9 0 a b c     ",
+"    d e f g h i j k l m n o p q q r     ",
+"    s t u v w x y z A B C D q q q E     ",
+"    F G H I J K L M N O P Q q q q E     ",
+"    R S T U V L W X Y Z `  .q q q E     ",
+"    R ..+.@.#.$.%.M &.*.=.-.q q q ;.    ",
+"    R >.,.'.).!.~.{.].^./.(._.q q :.<.  ",
+"    F [.}.|.1.>.2.3.4.5.6.7.8.q q 9.<.<.",
+"    0.a.b.c.1.d.e.f.g.h.i.j.k.q l.m.<.<.",
+"    0.n.o.p.q.r.s.n.t.u.i.7.v.b w.m.<.<.",
+"    F x.y.z.A.B.C.D.u.E.F.7.G.H.m.<.<.  ",
+"    m.I.J.J.K.K.K.J.J.I.L.(.M.9.<.<.    ",
+"    m.N.O.O.O.O.O.O.O.O.P.Q.m.<.        ",
+"                                        ",
+"                                        "};
diff --git a/tests/gtkmm/dnd_pixmap/dnd.c b/tests/gtkmm/dnd_pixmap/dnd.c
new file mode 100644 (file)
index 0000000..63df3ca
--- /dev/null
@@ -0,0 +1,899 @@
+/*
+       GTK Drag & Drop Tutorial - Example Source Code
+
+       Copyright (C) 2000-2002 WolfPack Entertainment
+       http://wolfpack.twu.net/
+
+
+       To compile:
+
+               cc `gtk-config --cflags --libs` dnd.c -o dnd
+
+
+       Important: DND does not appear to work properly with GTK+ 1.2.9
+       or older!!  Please try to obtain GTK+ 1.2.10 or newer before
+       attempting to run this demo.
+
+
+       Order of GTK DND events are as follows (for one complete drag
+       and drop operation):
+
+       1. "drag_begin_event"   notifies source that drag started
+       2. "drag_motion"        notifies target about drag pointer motion
+       3. "drag_data_get"      request for drag data from source
+       4. "drag_data_received" source has sent target the requested data
+       5. "drag_data_delete"   source should/can delete data
+       6. "drag_end_event"     notifies source that drag is done
+
+       Sequences 1, 3, 5, and 6 are sent to the source widget, while
+       sequences 2 and 4 are sent to the target widget.
+
+ */
+
+#include <gdk/gdkx.h>  /* Needed for pixmap loading. */
+#include <gtk/gtk.h>
+
+/* Data for the pixmaps that we will be using in the GtkCList cells
+ * and DND icons.
+ */
+#include "sphere.xpm"
+#include "cube.xpm"
+#include "cone.xpm"
+
+
+/*
+ *     DND data format type idenficaition, it identifies what format
+ *     the drag data is in for internal parsing by this program.
+ *     Remember that this is the data format type (not to be confused
+ *     with data type, like string, binary, etc).
+ *
+ *     These values are passed to gtk_drag_dest_set() and
+ *     gtk_drag_source_set() and will be given as inputs in DND signal
+ *     callbacks.
+ *
+ *     In each callback, we have the choice of using either the name 
+ *     (a string) or the info (an int).  In this example we will use
+ *     the info (an int) since it is easier and more commonly practiced.
+ *
+ *     Below we define the name and info pairs that are commonly used
+ *     in most GTK+ and GNOME applications:
+ */
+#define DRAG_TAR_NAME_0                "text/plain"
+#define DRAG_TAR_INFO_0                0
+
+#define DRAG_TAR_NAME_1                "text/uri-list"         /* not url-list */
+#define DRAG_TAR_INFO_1                1
+
+#define DRAG_TAR_NAME_2                "STRING"
+#define DRAG_TAR_INFO_2                2
+
+
+/*
+ *     Our window structure, it's just a toplevel GtkWindow and a
+ *     GtkCList.  The GtkCList will not be set reorderable, so that
+ *     we can demostrate the (more advanced) DND abilities of this
+ *     program.
+ */
+typedef struct {
+
+       GtkWidget *toplevel;
+       GtkWidget *clist;
+
+} my_prog_window_struct;
+
+
+/* General event/signal callbacks. */
+static gint HandleCloseCB(
+       GtkWidget *widget, gpointer *event, gpointer data
+);
+static void CListSelectRowCB(
+        GtkWidget *widget,
+        gint row, gint column,
+        GdkEventButton *event, gpointer data
+);
+static void CListUnselectRowCB(
+        GtkWidget *widget,
+        gint row, gint column,
+        GdkEventButton *event, gpointer data
+);
+
+/* DND specific event/signal callbacks. */
+static void DNDBeginCB(
+       GtkWidget *widget, GdkDragContext *dc, gpointer data
+);
+static void DNDEndCB(
+       GtkWidget *widget, GdkDragContext *dc, gpointer data
+);
+static gboolean DNDDragMotionCB(
+        GtkWidget *widget, GdkDragContext *dc,
+        gint x, gint y, guint t,
+        gpointer data
+);
+static void DNDDataRequestCB(
+        GtkWidget *widget, GdkDragContext *dc,
+        GtkSelectionData *selection_data, guint info, guint t,
+        gpointer data
+);
+static void DNDDataRecievedCB(
+        GtkWidget *widget, GdkDragContext *dc,
+        gint x, gint y, GtkSelectionData *selection_data,  
+        guint info, guint t, gpointer data
+);
+static void DNDDataDeleteCB(
+       GtkWidget *widget, GdkDragContext *dc, gpointer data
+);
+
+/* Some convience functions for our example. */
+static my_prog_window_struct *WindowNew(const gchar *title);
+static void WindowDelete(my_prog_window_struct *win);
+
+
+/* Pixmap and mask pairs used for GtkCList cell pixmaps and
+ * DND icons.
+ */
+static GdkPixmap       *sphere_pixmap,
+                       *cube_pixmap,
+                       *cone_pixmap;
+static GdkBitmap       *sphere_mask,
+                       *cube_mask,
+                       *cone_mask;
+
+
+/*
+ *     "delete_event" signal callback.
+ *
+ *     Called when a GtkWindow closes.
+ */
+static gint HandleCloseCB(
+       GtkWidget *widget, gpointer *event, gpointer data
+)
+{
+       /* Make it simple, when one window closes we just effectively
+        * close them all by breaking out of the last GTK+ main loop
+        * so that they will all be destroyed.
+        */
+       gtk_main_quit();
+
+        return(TRUE);
+}
+
+/*
+ *     "select_row" signal callback.
+ *
+ *     Called when a row is selected on a GtkCList.
+ */
+static void CListSelectRowCB(
+       GtkWidget *widget,
+       gint row, gint column,
+        GdkEventButton *event, gpointer data
+)
+{
+       GtkCList *clist;
+       my_prog_window_struct *win = (my_prog_window_struct *)data;
+       if((widget == NULL) || (win == NULL))
+               return;
+
+       clist = GTK_CLIST(widget);
+
+       /* Selected row in bounds? */
+       if((row >= 0) && (row < clist->rows))
+       {
+               gint cell_type;
+               guint8 spacing = 0;
+               gchar *text = NULL;
+               GdkPixmap *pixmap = NULL;
+               GdkBitmap *mask = NULL;
+
+
+               /* Obtain the pixmap and mask pair of the icon of the
+                * selected row and update the DND icon.
+                */
+               cell_type = gtk_clist_get_cell_type(clist, row, 0);
+               switch(cell_type)
+               {
+                 case GTK_CELL_PIXMAP:
+                   gtk_clist_get_pixmap(
+                       clist, row, 0, &pixmap, &mask
+                   );
+                  case GTK_CELL_PIXTEXT:
+                    gtk_clist_get_pixtext(
+                       clist, row, 0,
+                       &text, &spacing, &pixmap, &mask
+                    );
+               }
+               /* Selected row has pixmap? */
+               if(pixmap != NULL)
+               {
+                       gint w = 15, h = 15;
+
+                       /* Get size of pixmap. */
+                       gdk_window_get_size(
+                               (GdkWindow *)pixmap, &w, &h
+                       );
+                       /* Update the DND icon to be used on the next
+                        * drag based on this pixmap. Set the hot spot
+                        * to be at the center of this pixmap.
+                        */
+                       gtk_drag_set_default_icon(
+                               gdk_colormap_get_system(),
+                               pixmap, mask,
+                               w / 2, h / 2
+                       );
+               }
+
+               /* If the selected row is not fully visible, attempt to
+                * scroll and make it visible in the center of the
+                * list.
+                */
+               if(gtk_clist_row_is_visible(clist, row) !=
+                       GTK_VISIBILITY_FULL
+               )
+                       gtk_clist_moveto(
+                               clist,
+                               row, 0,         /* Row, column. */
+                               0.5, 0.0        /* Row, column. */
+                       );
+       }
+}
+
+/*
+ *     "unselect_row" signal callback.
+ *
+ *     Called when a row is selected on a GtkCList.
+ */
+static void CListUnselectRowCB(
+        GtkWidget *widget,
+        gint row, gint column,
+        GdkEventButton *event, gpointer data
+)
+{
+       /* Ignore this. */
+} 
+
+
+/*
+ *     DND "drag_begin" handler, this is called whenever a drag starts.
+ */
+static void DNDBeginCB(
+       GtkWidget *widget, GdkDragContext *dc, gpointer data
+)
+{
+        my_prog_window_struct *win = (my_prog_window_struct *)data;
+        if((widget == NULL) || (win == NULL) || (dc == NULL))
+               return;
+
+       /* Put any needed drag begin setup code here. */
+}
+
+/*
+ *      DND "drag_end" handler, this is called when a drag and drop has
+ *     completed. So this function is the last one to be called in
+ *     any given DND operation.
+ */
+static void DNDEndCB(
+       GtkWidget *widget, GdkDragContext *dc, gpointer data
+)
+{
+        my_prog_window_struct *win = (my_prog_window_struct *)data;
+        if((win == NULL) || (dc == NULL))
+                return;
+
+       /* Put any needed drag end cleanup code here. */
+}
+
+/*
+ *     DND "drag_motion" handler, this is called whenever the 
+ *     pointer is dragging over the target widget.
+ */
+static gboolean DNDDragMotionCB(
+        GtkWidget *widget, GdkDragContext *dc,
+        gint x, gint y, guint t,
+        gpointer data
+)
+{
+       gboolean same_widget;
+       GdkDragAction suggested_action;
+       GtkWidget *src_widget, *tar_widget;
+       my_prog_window_struct *win = (my_prog_window_struct *)data;
+        if((win == NULL) || (dc == NULL))
+                return(FALSE);
+
+       /* Get source widget and target widget. */
+       src_widget = gtk_drag_get_source_widget(dc);
+       tar_widget = widget;
+
+       /* Note if source widget is the same as the target. */
+       same_widget = (src_widget == tar_widget) ? TRUE : FALSE;
+
+
+       /* If this is the same widget, our suggested action should be
+        * move.  For all other case we assume copy.
+        */
+       if(same_widget)
+               suggested_action = GDK_ACTION_MOVE;
+       else
+               suggested_action = GDK_ACTION_COPY;
+
+       /* Respond with default drag action (status). First we check
+        * the dc's list of actions. If the list only contains
+        * move, copy, or link then we select just that, otherwise we
+        * return with our default suggested action.
+        * If no valid actions are listed then we respond with 0.
+        */
+
+        /* Only move? */
+        if(dc->actions == GDK_ACTION_MOVE)
+            gdk_drag_status(dc, GDK_ACTION_MOVE, t);
+        /* Only copy? */
+        else if(dc->actions == GDK_ACTION_COPY)
+            gdk_drag_status(dc, GDK_ACTION_COPY, t);
+        /* Only link? */
+        else if(dc->actions == GDK_ACTION_LINK)
+            gdk_drag_status(dc, GDK_ACTION_LINK, t);
+        /* Other action, check if listed in our actions list? */
+        else if(dc->actions & suggested_action)
+            gdk_drag_status(dc, suggested_action, t);
+        /* All else respond with 0. */
+        else
+            gdk_drag_status(dc, 0, t);
+
+       return(FALSE);
+}
+
+/*
+ *     DND "drag_data_get" handler, for handling requests for DND
+ *     data on the specified widget. This function is called when
+ *     there is need for DND data on the source, so this function is
+ *     responsable for setting up the dynamic data exchange buffer
+ *     (DDE as sometimes it is called) and sending it out.
+ */
+static void DNDDataRequestCB(
+       GtkWidget *widget, GdkDragContext *dc,
+       GtkSelectionData *selection_data, guint info, guint t,
+       gpointer data
+)
+{
+       gboolean data_sent = FALSE;
+       gint row;
+       GList *glist;
+       GtkCList *clist;
+       my_prog_window_struct *win = (my_prog_window_struct *)data;
+        if((widget == NULL) || (win == NULL) || (dc == NULL))
+                return;
+
+       clist = GTK_CLIST(widget);
+
+       /* Get last selected row on the clist. */
+       glist = clist->selection_end;
+       row = (glist != NULL) ? (gint)glist->data : -1;
+
+       /* Selected row in bounds? */
+       if((row >= 0) && (row < clist->rows))
+       {
+               gint cell_type;
+                guint8 spacing = 0;
+                gchar *text = NULL;
+                GdkPixmap *pixmap = NULL;
+                GdkBitmap *mask = NULL;
+
+
+                /* Obtain the text of the first cell of the selected
+                * row, then use this text and send it out to the DDE.
+                 */
+                cell_type = gtk_clist_get_cell_type(clist, row, 0);
+                switch(cell_type)
+                {
+                  case GTK_CELL_TEXT:
+                    gtk_clist_get_text(
+                        clist, row, 0, &text
+                    );
+                  case GTK_CELL_PIXTEXT:
+                    gtk_clist_get_pixtext(
+                        clist, row, 0,
+                        &text, &spacing, &pixmap, &mask
+                    );
+                }
+                /* Selected row has text? */
+               if(text != NULL)
+               {
+                       /* Send out the data using the selection system,
+                        * this is also used for cut and paste but
+                        * GTK uses it for drag and drop as well. When
+                        * sending a string, GTK will ensure that a null
+                        * terminating byte is added to the end so we
+                        * do not need to add it. GTK also coppies the
+                        * data so the original will never be modified.
+                        */
+                       gtk_selection_data_set(
+                               selection_data,
+                               GDK_SELECTION_TYPE_STRING,
+                               8,      /* 8 bits per character. */
+                               text, strlen(text)
+                       );
+                       data_sent = TRUE;
+               }
+       }
+
+       /* If we did not send out any data (for whatever reason),
+        * then send out an error response since this function
+        * needs to gaurantee a response when reasonably possible.
+        */
+       if(!data_sent)
+       {
+               const gchar *cstrptr = "Error";
+
+               gtk_selection_data_set(
+                       selection_data,
+                       GDK_SELECTION_TYPE_STRING,
+                       8,      /* 8 bits per character. */
+                       cstrptr, strlen(cstrptr)
+               );
+               data_sent = TRUE;
+       }
+}
+
+/*
+ *      DND "drag_data_received" handler. When DNDDataRequestCB()
+ *     calls gtk_selection_data_set() to send out the data, this function
+ *     recieves it and is responsible for handling it.
+ *
+ *     This is also the only DND callback function where the given
+ *     inputs may reflect those of the drop target so we need to check
+ *     if this is the same structure or not.
+ */
+static void DNDDataRecievedCB(
+       GtkWidget *widget, GdkDragContext *dc,
+       gint x, gint y, GtkSelectionData *selection_data,
+       guint info, guint t, gpointer data
+)
+{
+       gboolean same;
+       gint row, column;
+       GtkWidget *source_widget;
+       GtkCList *clist;
+        my_prog_window_struct *win = (my_prog_window_struct *)data;
+        if((widget == NULL) || (win == NULL) || (dc == NULL))
+                return;
+
+       /* Important, check if we actually got data.  Sometimes errors
+        * occure and selection_data will be NULL.
+        */
+       if(selection_data == NULL)
+               return;
+        if(selection_data->length < 0)
+                return;
+
+        /* Source and target widgets are the same? */
+       source_widget = gtk_drag_get_source_widget(dc);
+        same = (source_widget == widget) ? TRUE : FALSE;
+
+        clist = GTK_CLIST(widget);
+
+       /* Calculate the row and column at which the drop has occured
+        * over on the clist based on the given x and y coordinates.
+        */
+       if(!gtk_clist_get_selection_info(
+               clist,
+               x,
+               y - ((clist->flags & GTK_CLIST_SHOW_TITLES) ?
+                       clist->column_title_area.height +
+                       clist->column_title_area.y : 0),
+               &row, &column
+       ))
+       {
+               row = -1;
+               column = 0;
+       }
+
+       /* Now check if the data format type is one that we support
+        * (remember, data format type, not data type).
+        *
+        * We check this by testing if info matches one of the info
+        * values that we have defined.
+        *
+        * Note that we can also iterate through the atoms in:
+        *      GList *glist = dc->targets;
+        *
+        *      while(glist != NULL)
+        *      {
+        *          gchar *name = gdk_atom_name((GdkAtom)glist->data);
+        *           * strcmp the name to see if it matches
+        *           * one that we support
+        *           *
+        *          glist = glist->next;
+        *      }
+        */
+       if((info == DRAG_TAR_INFO_0) ||
+           (info == DRAG_TAR_INFO_1) ||
+           (info == DRAG_TAR_INFO_2)
+       )
+       {
+               gint new_row;
+               gchar *new_text = selection_data->data;
+               gchar *text[1];
+               GdkPixmap *pixmap = NULL;
+               GdkBitmap *mask = NULL;
+
+
+               /* Reset cells text array for adding a new row, we'll
+                * set the actual text after the row has been created.
+                */
+               text[0] = "";
+
+               /* Append or insert the new row? */
+               if((row >= 0) && (row < clist->rows))
+                        new_row = gtk_clist_insert(clist, row, text);
+               else
+                       new_row = gtk_clist_append(clist, text);
+
+               /* Check the name of the cell obtained from the received
+                * data and decipher which pixmap and mask pair to
+                * use for the new cell (if any).
+                */
+               if(!strcmp(new_text, "Sphere"))
+               {
+                       pixmap = sphere_pixmap;
+                       mask = sphere_mask;
+               }
+               else if(!strcmp(new_text, "Cube"))
+               {
+                        pixmap = cube_pixmap;
+                        mask = cube_mask;
+                }
+                else if(!strcmp(new_text, "Cone"))
+                {
+                        pixmap = cone_pixmap;
+                        mask = cone_mask;
+                }
+               /* Update the new row's cell with the pixmap (if
+                * available) and the received data as the text.
+                */
+               if(pixmap != NULL)
+                       gtk_clist_set_pixtext(
+                               clist, new_row, 0,
+                               new_text, 2, pixmap, mask
+                       );
+               else
+                       gtk_clist_set_text(
+                               clist, new_row, 0,
+                               new_text
+                       );
+       }
+}
+
+/*
+ *     DND "drag_data_delete" handler, this function is called when
+ *     the data on the source `should' be deleted (ie if the DND was
+ *     a move).
+ */
+static void DNDDataDeleteCB(
+       GtkWidget *widget, GdkDragContext *dc, gpointer data
+)
+{
+       gint row;
+       GList *glist;
+       GtkCList *clist;
+        my_prog_window_struct *win = (my_prog_window_struct *)data;
+        if((widget == NULL) || (win == NULL) || (dc == NULL))
+                return;
+
+        clist = GTK_CLIST(widget);
+
+        /* Get last selected row on the clist. */
+        glist = clist->selection_end;
+        row = (glist != NULL) ? (gint)glist->data : -1;
+
+       /* Remove the last selected row. */
+       gtk_clist_remove(clist, row);
+}  
+
+
+/*
+ *     Creates a new window with everything set up.
+ */
+static my_prog_window_struct *WindowNew(const gchar *title)
+{
+       gchar *heading[1];
+       GtkWidget *w, *parent, *scrolled_window;
+       GtkCList *clist;
+       GtkTargetEntry target_entry[3];
+       my_prog_window_struct *win = (my_prog_window_struct *)g_malloc0(
+               sizeof(my_prog_window_struct)
+       );
+       if(win == NULL)
+           return(NULL);
+
+       /* Create toplevel. */
+        w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       win->toplevel = w;
+        gtk_signal_connect(
+            GTK_OBJECT(w), "delete_event",
+            GTK_SIGNAL_FUNC(HandleCloseCB), win
+        );
+       gtk_widget_set_usize(w, 200, 150);
+        gtk_window_set_title(
+           GTK_WINDOW(w),
+           (title == NULL) ? "Untitled" : title
+       );
+       /* Do not show the toplevel just yet. */
+       parent = w;
+
+        /* Main vbox to hold clist. */
+        w = gtk_vbox_new(FALSE, 0);
+        gtk_container_add(GTK_CONTAINER(parent), w);
+        gtk_widget_show(w);
+        parent = w;
+
+       /* Create the scrolled window for the clist and the clist
+        * itself.
+        */
+       scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+       gtk_box_pack_start(GTK_BOX(parent), scrolled_window, TRUE, TRUE, 0);
+       gtk_scrolled_window_set_policy(
+               GTK_SCROLLED_WINDOW (scrolled_window),
+               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC
+       );
+       gtk_widget_show(scrolled_window);
+
+       heading[0] = "Name";
+       w = gtk_clist_new_with_titles(1, heading);
+       clist = GTK_CLIST(w);
+       win->clist = w;
+       gtk_clist_set_selection_mode(clist, GTK_SELECTION_SINGLE);
+       gtk_clist_set_shadow_type(clist, GTK_SHADOW_IN);
+       gtk_clist_column_titles_passive(clist);
+        gtk_clist_set_column_justification(
+            clist, 0, GTK_JUSTIFY_LEFT
+        );
+        gtk_clist_set_row_height(clist, 20);
+       gtk_signal_connect(
+               GTK_OBJECT(w), "select_row",
+               GTK_SIGNAL_FUNC(CListSelectRowCB), win
+       );
+        gtk_signal_connect(
+                GTK_OBJECT(w), "unselect_row",
+                GTK_SIGNAL_FUNC(CListUnselectRowCB), win
+        );
+       gtk_container_add(GTK_CONTAINER(scrolled_window), w);
+
+       /* Realize the clist widget and make sure it has a window,
+        * this will be for DND setup.
+        */
+       gtk_widget_realize(w);
+        if(!GTK_WIDGET_NO_WINDOW(w))
+       {
+               /* DND: Set up the clist as a potential DND destination.
+                * First we set up target_entry which is a sequence of of
+                * structure which specify the kinds (which we define) of
+                * drops accepted on this widget.
+                */
+
+               /* Set up the list of data format types that our DND
+                * callbacks will accept.
+                */
+               target_entry[0].target = DRAG_TAR_NAME_0;
+               target_entry[0].flags = 0;
+               target_entry[0].info = DRAG_TAR_INFO_0;
+                target_entry[1].target = DRAG_TAR_NAME_1;
+                target_entry[1].flags = 0;
+                target_entry[1].info = DRAG_TAR_INFO_1;
+                target_entry[2].target = DRAG_TAR_NAME_2;
+                target_entry[2].flags = 0;
+                target_entry[2].info = DRAG_TAR_INFO_2;
+
+               /* Set the drag destination for this widget, using the
+                * above target entry types, accept move's and coppies'.
+                */
+               gtk_drag_dest_set(
+                       w,
+                       GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT |
+                       GTK_DEST_DEFAULT_DROP,
+                       target_entry,
+                       sizeof(target_entry) / sizeof(GtkTargetEntry),
+                       GDK_ACTION_MOVE | GDK_ACTION_COPY
+               );
+               gtk_signal_connect(
+                       GTK_OBJECT(w), "drag_motion",
+                       GTK_SIGNAL_FUNC(DNDDragMotionCB),
+                       win
+               );
+
+               /* Set the drag source for this widget, allowing the user
+                * to drag items off of this clist.
+                */
+               gtk_drag_source_set(
+                       w,
+                       GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+                        target_entry,
+                        sizeof(target_entry) / sizeof(GtkTargetEntry),
+                       GDK_ACTION_MOVE | GDK_ACTION_COPY
+               );
+               /* Set DND signals on clist. */
+               gtk_signal_connect(
+                       GTK_OBJECT(w), "drag_begin",
+                       GTK_SIGNAL_FUNC(DNDBeginCB), win
+               );
+                gtk_signal_connect(
+                        GTK_OBJECT(w), "drag_end",
+                        GTK_SIGNAL_FUNC(DNDEndCB), win
+                );
+                gtk_signal_connect(
+                        GTK_OBJECT(w), "drag_data_get",
+                        GTK_SIGNAL_FUNC(DNDDataRequestCB), win
+                );
+                gtk_signal_connect(
+                        GTK_OBJECT(w), "drag_data_received",
+                        GTK_SIGNAL_FUNC(DNDDataRecievedCB), win
+                );
+                gtk_signal_connect(
+                        GTK_OBJECT(w), "drag_data_delete",
+                        GTK_SIGNAL_FUNC(DNDDataDeleteCB), win
+                );
+       }
+
+
+       gtk_widget_show(w);
+
+
+       /* Now show the toplevel. */
+       gtk_widget_show(win->toplevel);
+
+       return(win);
+}
+
+/*
+ *     Dealloactes the given window and all its resources.
+ */
+static void WindowDelete(my_prog_window_struct *win)
+{
+       GtkWidget *w;
+
+
+       if(win == NULL)
+               return;
+
+       /* Destroy the GtkCList, first remove the DND settings on it
+        * and then destroy it.
+        */
+       w = win->clist;
+       if(w != NULL)
+       {
+               /* Remove DND settings on this widget. */
+               gtk_drag_dest_unset(w);
+               gtk_drag_source_unset(w);
+
+               win->clist = NULL;
+               gtk_widget_destroy(w);
+       }
+
+       /* Destroy toplevel GtkWindow, thus destroying all of its
+        * child widgets.
+        */
+       w = win->toplevel;
+       if(w != NULL)
+       {
+               win->toplevel = NULL;
+               gtk_widget_destroy(w);
+       }
+
+       /* Deallocate the structure itself. */
+       g_free(win);
+}
+
+
+int main(int argc, char **argv)
+{
+       GtkStyle *style;
+       GdkWindow *window;
+       GdkPixmap **pixmap;
+       GdkBitmap **mask;
+       gchar **pixmap_data;
+       my_prog_window_struct *win[2];
+
+
+       gtk_init(&argc, &argv);
+
+
+       /* Load the pixmaps that we will be using as GtkCList cell
+        * pixmaps and DND icons.
+        *
+        * This requires that we use the root window for loading of
+        * the pixmaps (hence the need to include gdk/gdkx.h).
+        */
+       style = gtk_widget_get_default_style();
+       window = (GdkWindow *)GDK_ROOT_PARENT();
+
+       pixmap = &sphere_pixmap;
+       mask = &sphere_mask;
+       pixmap_data = sphere_xpm;
+        *pixmap = gdk_pixmap_create_from_xpm_d(
+            window, mask,
+            &style->bg[GTK_STATE_NORMAL],
+            pixmap_data
+        );
+
+        pixmap = &cube_pixmap;
+        mask = &cube_mask;
+        pixmap_data = cube_xpm;
+        *pixmap = gdk_pixmap_create_from_xpm_d(
+            window, mask,
+            &style->bg[GTK_STATE_NORMAL],
+            pixmap_data
+        );
+
+        pixmap = &cone_pixmap;
+        mask = &cone_mask;
+        pixmap_data = cone_xpm;
+        *pixmap = gdk_pixmap_create_from_xpm_d(
+            window, mask,
+            &style->bg[GTK_STATE_NORMAL],
+            pixmap_data
+        );
+
+
+       /* Create two windows. */
+       win[0] = WindowNew("List 1");
+       win[1] = WindowNew("List 2");
+
+       /* Add some items to the first list. */
+       if(win[0] != NULL)
+       {
+               GtkCList *clist = (GtkCList *)win[0]->clist;
+               if(clist != NULL)
+               {
+                       gint new_row;
+                       gchar *text[1];
+
+
+                       /* Reset cells text array for adding a new row,
+                        * we'll set the actual text after the row has
+                        * been created.
+                        */
+                       text[0] = "";
+
+                       /* Begin creating new rows. */
+
+                       new_row = gtk_clist_append(clist, text);
+                        gtk_clist_set_pixtext(
+                                clist, new_row, 0,
+                                "Sphere", 2,
+                               sphere_pixmap, sphere_mask
+                        );
+
+                        new_row = gtk_clist_append(clist, text);
+                        gtk_clist_set_pixtext(
+                                clist, new_row, 0,
+                                "Cube", 2,
+                                cube_pixmap, cube_mask
+                        );
+
+                        new_row = gtk_clist_append(clist, text);
+                        gtk_clist_set_pixtext(
+                                clist, new_row, 0,
+                                "Cone", 2,
+                                cone_pixmap, cone_mask
+                        );
+               }
+       }
+
+
+       /* Enter main gtk loop. */
+       gtk_main();
+
+
+       /* Application now shutting down, begin deallocating
+        * resources.
+        */
+       WindowDelete(win[0]);
+       WindowDelete(win[1]);
+
+       gdk_pixmap_unref(sphere_pixmap);
+       gdk_bitmap_unref(sphere_mask);
+       gdk_pixmap_unref(cube_pixmap);
+        gdk_bitmap_unref(cube_mask);
+       gdk_pixmap_unref(cone_pixmap);
+        gdk_bitmap_unref(cone_mask);
+
+
+       return(0);
+}
diff --git a/tests/gtkmm/dnd_pixmap/sphere.xpm b/tests/gtkmm/dnd_pixmap/sphere.xpm
new file mode 100644 (file)
index 0000000..3c93587
--- /dev/null
@@ -0,0 +1,196 @@
+/* XPM */
+static char * sphere_xpm[] = {
+"20 20 173 2",
+"      c None",
+".     c #770F0F",
+"+     c #8E1414",
+"@     c #901212",
+"#     c #841010",
+"$     c #6E0B0B",
+"%     c #801515",
+"&     c #952222",
+"*     c #D23F3F",
+"=     c #D53939",
+"-     c #D02C2C",
+";     c #C32424",
+">     c #B71E1E",
+",     c #7D0D0D",
+"'     c #730A0A",
+")     c #8D1A1A",
+"!     c #DA5555",
+"~     c #E47878",
+"{     c #E68080",
+"]     c #E36868",
+"^     c #DB4343",
+"/     c #D22D2D",
+"(     c #C82323",
+"_     c #BB1D1D",
+":     c #A91919",
+"<     c #760B0B",
+"[     c #7F1111",
+"}     c #D64A4A",
+"|     c #EB8787",
+"1     c #F2AFAF",
+"2     c #EA8C8C",
+"3     c #E05C5C",
+"4     c #DB3535",
+"5     c #D22828",
+"6     c #C22020",
+"7     c #AE1B1B",
+"8     c #991212",
+"9     c #650505",
+"0     c #951A1A",
+"a     c #E15B5B",
+"b     c #EE9A9A",
+"c     c #F5BBBB",
+"d     c #F6B8B8",
+"e     c #ED9292",
+"f     c #E25F5F",
+"g     c #DE3838",
+"h     c #D52A2A",
+"i     c #C32121",
+"j     c #AC1919",
+"k     c #991414",
+"l     c #750909",
+"m     c #6E0C0C",
+"n     c #D02F2F",
+"o     c #E05757",
+"p     c #EC8B8B",
+"q     c #F0A3A3",
+"r     c #F29E9E",
+"s     c #E87A7A",
+"t     c #E14D4D",
+"u     c #DA3131",
+"v     c #CF2626",
+"w     c #BD1F1F",
+"x     c #AA1919",
+"y     c #9B1313",
+"z     c #8F1010",
+"A     c #5E0101",
+"B     c #7E1010",
+"C     c #CE2E2E",
+"D     c #DC4A4A",
+"E     c #E66969",
+"F     c #E77575",
+"G     c #E56969",
+"H     c #E04F4F",
+"I     c #DD3434",
+"J     c #D32929",
+"K     c #C72323",
+"L     c #B51D1D",
+"M     c #A41818",
+"N     c #971515",
+"O     c #8B1010",
+"P     c #640404",
+"Q     c #7F1010",
+"R     c #CB2B2B",
+"S     c #D64040",
+"T     c #DE4E4E",
+"U     c #E04D4D",
+"V     c #DD4141",
+"W     c #DA3434",
+"X     c #D52929",
+"Y     c #CB2424",
+"Z     c #C02020",
+"`     c #B11A1A",
+" .    c #A11616",
+"..    c #941313",
+"+.    c #891010",
+"@.    c #650707",
+"#.    c #750D0D",
+"$.    c #C02525",
+"%.    c #CB3232",
+"&.    c #D13B3B",
+"*.    c #D53A3A",
+"=.    c #D33232",
+"-.    c #D02929",
+";.    c #CB2525",
+">.    c #C32222",
+",.    c #B91D1D",
+"'.    c #AD1919",
+").    c #9E1414",
+"!.    c #8E1111",
+"~.    c #820C0C",
+"{.    c #600505",
+"].    c #5F0707",
+"^.    c #B41D1D",
+"/.    c #BD2424",
+"(.    c #C22828",
+"_.    c #C32626",
+":.    c #C62424",
+"<.    c #C52323",
+"[.    c #C12121",
+"}.    c #BD2020",
+"|.    c #B21B1B",
+"1.    c #A51818",
+"2.    c #961414",
+"3.    c #870E0E",
+"4.    c #780A0A",
+"5.    c #540000",
+"6.    c #810F0F",
+"7.    c #AD1B1B",
+"8.    c #B31D1D",
+"9.    c #B61E1E",
+"0.    c #B91F1F",
+"a.    c #B91E1E",
+"b.    c #B81E1E",
+"c.    c #B51C1C",
+"d.    c #AB1A1A",
+"e.    c #9A1414",
+"f.    c #870F0F",
+"g.    c #790A0A",
+"h.    c #6B0707",
+"i.    c #490000",
+"j.    c #5B0505",
+"k.    c #9E1616",
+"l.    c #A41717",
+"m.    c #A81818",
+"n.    c #AB1919",
+"o.    c #A41616",
+"p.    c #8C0F0F",
+"q.    c #790B0B",
+"r.    c #6F0909",
+"s.    c #7F7F7F",
+"t.    c #610606",
+"u.    c #981414",
+"v.    c #991313",
+"w.    c #961313",
+"x.    c #901010",
+"y.    c #7B0C0C",
+"z.    c #700909",
+"A.    c #590202",
+"B.    c #440000",
+"C.    c #560202",
+"D.    c #700A0A",
+"E.    c #850F0F",
+"F.    c #840D0D",
+"G.    c #800D0D",
+"H.    c #7D0C0C",
+"I.    c #770A0A",
+"J.    c #6C0505",
+"K.    c #540101",
+"L.    c #500000",
+"M.    c #560303",
+"N.    c #5A0404",
+"O.    c #580303",
+"P.    c #520202",
+"                                        ",
+"                                        ",
+"              . + @ # $                 ",
+"          % & * = - ; > , '             ",
+"        ) ! ~ { ] ^ / ( _ : <           ",
+"      [ } | 1 1 2 3 4 5 6 7 8 9         ",
+"      0 a b c d e f g h i j k l         ",
+"    m n o p q r s t u v w x y z A       ",
+"    B C D E F G H I J K L M N O P       ",
+"    Q R S T U V W X Y Z `  ...+.@.      ",
+"    #.$.%.&.*.=.-.;.>.,.'.).!.~.{.      ",
+"    ].^./.(._.:.<.[.}.|.1.2.3.4.5.      ",
+"      6.7.8.9.0.a.b.c.d.e.f.g.h.i.      ",
+"      j.k.l.m.n.j n.o.y p.q.r.5.s.s.    ",
+"        t.u.v.k k w.x.3.y.z.A.B.s.s.    ",
+"          C.D.E.F.G.H.I.J.K.B.s.s.      ",
+"              L.M.N.O.P.s.s.            ",
+"                                        ",
+"                                        ",
+"                                        "};