summaryrefslogtreecommitdiff
path: root/iup/src/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'iup/src/gtk')
-rwxr-xr-xiup/src/gtk/iupgtk_button.c10
-rwxr-xr-xiup/src/gtk/iupgtk_canvas.c17
-rwxr-xr-xiup/src/gtk/iupgtk_common.c59
-rwxr-xr-xiup/src/gtk/iupgtk_dialog.c65
-rw-r--r--iup/src/gtk/iupgtk_draw.c161
-rwxr-xr-xiup/src/gtk/iupgtk_drv.h4
-rwxr-xr-xiup/src/gtk/iupgtk_filedlg.c63
-rwxr-xr-xiup/src/gtk/iupgtk_font.c4
-rwxr-xr-xiup/src/gtk/iupgtk_fontdlg.c7
-rwxr-xr-xiup/src/gtk/iupgtk_frame.c22
-rwxr-xr-xiup/src/gtk/iupgtk_key.c26
-rwxr-xr-xiup/src/gtk/iupgtk_label.c4
-rwxr-xr-xiup/src/gtk/iupgtk_list.c29
-rwxr-xr-xiup/src/gtk/iupgtk_loop.c7
-rwxr-xr-xiup/src/gtk/iupgtk_menu.c21
-rwxr-xr-xiup/src/gtk/iupgtk_open.c47
-rwxr-xr-xiup/src/gtk/iupgtk_tabs.c50
-rwxr-xr-xiup/src/gtk/iupgtk_text.c40
-rwxr-xr-xiup/src/gtk/iupgtk_toggle.c4
-rwxr-xr-xiup/src/gtk/iupgtk_tree.c1533
-rw-r--r--iup/src/gtk/iupmac_help.c46
-rw-r--r--iup/src/gtk/iupmac_info.c358
22 files changed, 1717 insertions, 860 deletions
diff --git a/iup/src/gtk/iupgtk_button.c b/iup/src/gtk/iupgtk_button.c
index 18be87c..f8474ae 100755
--- a/iup/src/gtk/iupgtk_button.c
+++ b/iup/src/gtk/iupgtk_button.c
@@ -150,8 +150,10 @@ static int gtkButtonSetPaddingAttrib(Ihandle* ih, const char* value)
gtk_alignment_set_padding(alignment, ih->data->vert_padding, ih->data->vert_padding,
ih->data->horiz_padding, ih->data->horiz_padding);
}
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
#ifdef WIN32
@@ -366,12 +368,12 @@ static int gtkButtonMapMethod(Ihandle* ih)
ih->data->type = IUP_BUTTON_IMAGE;
value = iupAttribGet(ih, "TITLE");
- if (value)
+ if (value && *value!=0)
{
GtkSettings* settings = gtk_widget_get_settings(ih->handle);
g_object_set(settings, "gtk-button-images", (int)TRUE, NULL);
- gtk_button_set_label((GtkButton*)ih->handle, value);
+ gtk_button_set_label((GtkButton*)ih->handle, iupgtkStrConvertToUTF8(value));
ih->data->type |= IUP_BUTTON_TEXT;
#if GTK_CHECK_VERSION(2, 10, 0)
@@ -397,7 +399,7 @@ static int gtkButtonMapMethod(Ihandle* ih)
#endif
}
else
- gtk_button_set_label((GtkButton*)ih->handle, title);
+ gtk_button_set_label((GtkButton*)ih->handle, iupgtkStrConvertToUTF8(title));
ih->data->type = IUP_BUTTON_TEXT;
}
diff --git a/iup/src/gtk/iupgtk_canvas.c b/iup/src/gtk/iupgtk_canvas.c
index daae4ad..3af48a4 100755
--- a/iup/src/gtk/iupgtk_canvas.c
+++ b/iup/src/gtk/iupgtk_canvas.c
@@ -537,8 +537,8 @@ static int gtkCanvasMapMethod(Ihandle* ih)
/* To receive mouse events on a drawing area, you will need to enable them. */
gtk_widget_add_events(ih->handle, GDK_EXPOSURE_MASK|
- GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK|
- GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|
+ GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK|
+ GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_MOTION_MASK|
GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|
GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|
GDK_FOCUS_CHANGE_MASK|GDK_STRUCTURE_MASK);
@@ -611,14 +611,15 @@ void iupdrvCanvasInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "YAUTOHIDE", NULL, gtkCanvasSetYAutoHideAttrib, "YES", NULL, IUPAF_DEFAULT); /* force new default value */
iupClassRegisterAttribute(ic, "DRAWABLE", gtkCanvasGetDrawableAttrib, NULL, NULL, NULL, IUPAF_NO_STRING);
- //iupClassRegisterAttribute(ic, "CD_GDK", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
/* IupCanvas Windows or X only */
-#ifdef WIN32
- iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
-#else
- iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
- iupClassRegisterAttribute(ic, "XDISPLAY", (IattribGetFunc)iupdrvGetDisplay, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+#ifndef GTK_MAC
+ #ifdef WIN32
+ iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ #else
+ iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ iupClassRegisterAttribute(ic, "XDISPLAY", (IattribGetFunc)iupdrvGetDisplay, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ #endif
#endif
}
diff --git a/iup/src/gtk/iupgtk_common.c b/iup/src/gtk/iupgtk_common.c
index 40368f2..d84c1c8 100755
--- a/iup/src/gtk/iupgtk_common.c
+++ b/iup/src/gtk/iupgtk_common.c
@@ -91,13 +91,13 @@ void iupdrvBaseUnMapMethod(Ihandle* ih)
gtk_widget_destroy(widget); /* To match the call to gtk_*****_new */
}
-void iupdrvDisplayUpdate(Ihandle *ih)
+void iupdrvPostRedraw(Ihandle *ih)
{
/* Post a REDRAW */
gtk_widget_queue_draw(ih->handle);
}
-void iupdrvDisplayRedraw(Ihandle *ih)
+void iupdrvRedrawNow(Ihandle *ih)
{
GdkWindow* window = ih->handle->window;
/* Post a REDRAW */
@@ -202,7 +202,11 @@ void iupdrvSetVisible(Ihandle* ih, int visible)
int iupdrvIsVisible(Ihandle* ih)
{
+#if GTK_CHECK_VERSION(2, 18, 0)
+ if (gtk_widget_get_visible(ih->handle))
+#else
if (GTK_WIDGET_VISIBLE(ih->handle))
+#endif
{
/* if marked as visible, since we use gtk_widget_hide and NOT gtk_widget_hide_all
must check its parents. */
@@ -211,7 +215,11 @@ int iupdrvIsVisible(Ihandle* ih)
{
if (parent->iclass->nativetype != IUP_TYPEVOID)
{
+#if GTK_CHECK_VERSION(2, 18, 0)
+ if (!gtk_widget_get_visible(parent->handle))
+#else
if (!GTK_WIDGET_VISIBLE(parent->handle))
+#endif
return 0;
}
@@ -225,7 +233,11 @@ int iupdrvIsVisible(Ihandle* ih)
int iupdrvIsActive(Ihandle *ih)
{
- return (GTK_WIDGET_IS_SENSITIVE(ih->handle));
+#if GTK_CHECK_VERSION(2, 18, 0)
+ return gtk_widget_is_sensitive(ih->handle);
+#else
+ return GTK_WIDGET_IS_SENSITIVE(ih->handle);
+#endif
}
void iupdrvSetActive(Ihandle* ih, int enable)
@@ -424,9 +436,11 @@ static GdkCursor* gtkGetCursor(Ihandle* ih, const char* name)
{ "RESIZE_N", GDK_TOP_SIDE},
{ "RESIZE_S", GDK_BOTTOM_SIDE},
{ "RESIZE_NS", GDK_SB_V_DOUBLE_ARROW},
+ { "SPLITTER_HORIZ", GDK_SB_V_DOUBLE_ARROW},
{ "RESIZE_W", GDK_LEFT_SIDE},
{ "RESIZE_E", GDK_RIGHT_SIDE},
{ "RESIZE_WE", GDK_SB_H_DOUBLE_ARROW},
+ { "SPLITTER_VERT", GDK_SB_H_DOUBLE_ARROW},
{ "RESIZE_NE", GDK_TOP_RIGHT_CORNER},
{ "RESIZE_SE", GDK_BOTTOM_RIGHT_CORNER},
{ "RESIZE_NW", GDK_TOP_LEFT_CORNER},
@@ -571,18 +585,24 @@ void iupdrvDrawFocusRect(Ihandle* ih, void* _gc, int x, int y, int w, int h)
{
GdkWindow* window = ih->handle->window;
GtkStyle *style = gtk_widget_get_style(ih->handle);
+#if GTK_CHECK_VERSION(2, 18, 0)
+ GtkStateType state = gtk_widget_get_state(ih->handle);
+#else
+ GtkStateType state = GTK_WIDGET_STATE(ih->handle);
+#endif
+ gtk_paint_focus(style, window, state, NULL, ih->handle, NULL, x, y, w, h);
(void)_gc;
-
- gtk_paint_focus(style, window, GTK_WIDGET_STATE(ih->handle), NULL, ih->handle, NULL, x, y, w, h);
}
void iupdrvBaseRegisterCommonAttrib(Iclass* ic)
{
+#ifndef GTK_MAC
#ifdef WIN32
iupClassRegisterAttribute(ic, "HFONT", iupgtkGetFontIdAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
#else
iupClassRegisterAttribute(ic, "XFONTID", iupgtkGetFontIdAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
#endif
+#endif
iupClassRegisterAttribute(ic, "PANGOFONTDESC", iupgtkGetPangoFontDescAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
}
@@ -789,7 +809,17 @@ char* iupgtkStrConvertFromFilename(const char* str) /* From Filename to IUP */
gboolean iupgtkMotionNotifyEvent(GtkWidget *widget, GdkEventMotion *evt, Ihandle *ih)
{
- IFniis cb = (IFniis)IupGetCallback(ih,"MOTION_CB");
+ IFniis cb;
+
+ if (evt->is_hint)
+ {
+ int x, y;
+ gdk_window_get_pointer(widget->window, &x, &y, NULL);
+ evt->x = x;
+ evt->y = y;
+ }
+
+ cb = (IFniis)IupGetCallback(ih,"MOTION_CB");
if (cb)
{
char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
@@ -818,6 +848,23 @@ gboolean iupgtkButtonEvent(GtkWidget *widget, GdkEventButton *evt, Ihandle *ih)
iupgtkButtonKeySetStatus(evt->state, evt->button, status, doubleclick);
+ if (doubleclick)
+ {
+ /* Must compensate the fact that in GTK there is an extra button press event
+ when occours a double click, we compensate that completing the event
+ with a button release before the double click. */
+
+ status[5] = ' '; /* clear double click */
+
+ ret = cb(ih, b, 0, (int)evt->x, (int)evt->y, status); /* release */
+ if (ret==IUP_CLOSE)
+ IupExitLoop();
+ else if (ret==IUP_IGNORE)
+ return TRUE;
+
+ status[5] = 'D'; /* restore double click */
+ }
+
ret = cb(ih, b, press, (int)evt->x, (int)evt->y, status);
if (ret==IUP_CLOSE)
IupExitLoop();
diff --git a/iup/src/gtk/iupgtk_dialog.c b/iup/src/gtk/iupgtk_dialog.c
index 46c0ce1..ff0d8f2 100755
--- a/iup/src/gtk/iupgtk_dialog.c
+++ b/iup/src/gtk/iupgtk_dialog.c
@@ -120,12 +120,13 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
static int native_border = 0;
static int native_caption = 0;
- int has_caption = iupAttribGetBoolean(ih, "MAXBOX") ||
- iupAttribGetBoolean(ih, "MINBOX") ||
- iupAttribGetBoolean(ih, "MENUBOX") ||
- IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
+ int has_titlebar = iupAttribGetBoolean(ih, "RESIZE") || /* GTK and Motif only */
+ iupAttribGetBoolean(ih, "MAXBOX") ||
+ iupAttribGetBoolean(ih, "MINBOX") ||
+ iupAttribGetBoolean(ih, "MENUBOX") ||
+ IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
- int has_border = has_caption ||
+ int has_border = has_titlebar ||
iupAttribGetBoolean(ih, "RESIZE") ||
iupAttribGetBoolean(ih, "BORDER");
@@ -147,7 +148,7 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
*border = win_border;
*caption = 0;
- if (has_caption)
+ if (has_titlebar)
*caption = win_caption;
if (!native_border && *border)
@@ -171,7 +172,7 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
}
*caption = 0;
- if (has_caption)
+ if (has_titlebar)
{
if (native_caption)
*caption = native_caption;
@@ -429,6 +430,7 @@ static int gtkDialogMapMethod(Ihandle* ih)
int functions = 0;
InativeHandle* parent;
GtkWidget* fixed;
+ int has_titlebar = 0;
#ifdef HILDON
if (iupAttribGetBoolean(ih, "HILDONWINDOW"))
@@ -494,33 +496,41 @@ static int gtkDialogMapMethod(Ihandle* ih)
iupAttribSetStr(ih, "MINBOX", "NO");
}
- if (IupGetAttribute(ih, "TITLE")) { /* must use IupGetAttribute to check from the native implementation */
- functions |= GDK_FUNC_MOVE;
- decorations |= GDK_DECOR_TITLE;
- }
-
- if (iupAttribGetBoolean(ih, "MENUBOX")) {
+ if (iupAttribGet(ih, "TITLE"))
+ has_titlebar = 1;
+ if (iupAttribGetBoolean(ih, "MENUBOX"))
+ {
functions |= GDK_FUNC_CLOSE;
decorations |= GDK_DECOR_MENU;
+ has_titlebar = 1;
}
-
- if (iupAttribGetBoolean(ih, "MINBOX")) {
+ if (iupAttribGetBoolean(ih, "MINBOX"))
+ {
functions |= GDK_FUNC_MINIMIZE;
decorations |= GDK_DECOR_MINIMIZE;
+ has_titlebar = 1;
}
-
- if (iupAttribGetBoolean(ih, "MAXBOX")) {
+ if (iupAttribGetBoolean(ih, "MAXBOX"))
+ {
functions |= GDK_FUNC_MAXIMIZE;
decorations |= GDK_DECOR_MAXIMIZE;
+ has_titlebar = 1;
}
-
- if (iupAttribGetBoolean(ih, "RESIZE")) {
+ if (iupAttribGetBoolean(ih, "RESIZE"))
+ {
functions |= GDK_FUNC_RESIZE;
decorations |= GDK_DECOR_RESIZEH;
- }
- if (iupAttribGetBoolean(ih, "BORDER"))
- decorations |= GDK_DECOR_BORDER;
+ decorations |= GDK_DECOR_BORDER; /* has_border */
+ }
+ if (has_titlebar)
+ {
+ functions |= GDK_FUNC_MOVE;
+ decorations |= GDK_DECOR_TITLE;
+ gtk_window_set_title((GtkWindow*)ih->handle, "");
+ }
+ if (iupAttribGetBoolean(ih, "BORDER") || has_titlebar)
+ decorations |= GDK_DECOR_BORDER; /* has_border */
if (decorations == 0)
gtk_window_set_decorated((GtkWindow*)ih->handle, FALSE);
@@ -980,11 +990,12 @@ void iupdrvDialogInitClass(Iclass* ic)
iupClassRegisterCallback(ic, "TRAYCLICK_CB", "iii");
/* Driver Dependent Attribute functions */
-
-#ifdef WIN32
- iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
-#else
- iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+#ifndef GTK_MAC
+ #ifdef WIN32
+ iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ #else
+ iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ #endif
#endif
/* Visual */
diff --git a/iup/src/gtk/iupgtk_draw.c b/iup/src/gtk/iupgtk_draw.c
new file mode 100644
index 0000000..4390c66
--- /dev/null
+++ b/iup/src/gtk/iupgtk_draw.c
@@ -0,0 +1,161 @@
+/** \file
+ * \brief Draw Functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+
+#include <gtk/gtk.h>
+
+#include "iup.h"
+
+#include "iup_attrib.h"
+#include "iup_class.h"
+#include "iup_str.h"
+#include "iup_object.h"
+#include "iup_image.h"
+#include "iup_draw.h"
+
+#include "iupgtk_drv.h"
+
+
+struct _IdrawCanvas{
+ Ihandle* ih;
+ int w, h;
+
+ GdkDrawable* wnd;
+ GdkPixmap* pixmap;
+ GdkGC *gc, *pixmap_gc;
+};
+
+IdrawCanvas* iupDrawCreateCanvas(Ihandle* ih)
+{
+ IdrawCanvas* dc = calloc(1, sizeof(IdrawCanvas));
+
+ dc->wnd = ih->handle->window;
+ dc->gc = gdk_gc_new(dc->wnd);
+
+ gdk_drawable_get_size(dc->wnd, &dc->w, &dc->h);
+
+ dc->pixmap = gdk_pixmap_new(dc->wnd, dc->w, dc->h, gdk_drawable_get_depth(dc->wnd));
+ dc->pixmap_gc = gdk_gc_new(dc->pixmap);
+
+ return dc;
+}
+
+void iupDrawKillCanvas(IdrawCanvas* dc)
+{
+ g_object_unref(dc->pixmap_gc);
+ g_object_unref(dc->pixmap);
+ g_object_unref(dc->gc);
+
+ free(dc);
+}
+
+void iupDrawUpdateSize(IdrawCanvas* dc)
+{
+ int w, h;
+ gdk_drawable_get_size(dc->wnd, &w, &h);
+
+ if (w != dc->w || h != dc->h)
+ {
+ g_object_unref(dc->pixmap_gc);
+ g_object_unref(dc->pixmap);
+
+ dc->pixmap = gdk_pixmap_new(dc->wnd, dc->w, dc->h, gdk_drawable_get_depth(dc->wnd));
+ dc->pixmap_gc = gdk_gc_new(dc->pixmap);
+ }
+}
+
+void iupDrawFlush(IdrawCanvas* dc)
+{
+ gdk_draw_drawable(dc->wnd, dc->gc, dc->pixmap, 0, 0, 0, 0, dc->w, dc->h);
+}
+
+void iupDrawGetSize(IdrawCanvas* dc, int *w, int *h)
+{
+ if (w) *w = dc->w;
+ if (h) *h = dc->h;
+}
+
+void iupDrawParentBackground(IdrawCanvas* dc)
+{
+ unsigned char r=0, g=0, b=0;
+ char* color = iupBaseNativeParentGetBgColorAttrib(dc->ih);
+ iupStrToRGB(color, &r, &g, &b);
+ iupDrawRectangle(dc, 0, 0, dc->w-1, dc->h-1, r, g, b, 1);
+}
+
+void iupDrawRectangle(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b, int filled)
+{
+ GdkColor color;
+ iupgdkColorSet(&color, r, g, b);
+ gdk_gc_set_rgb_fg_color(dc->pixmap_gc, &color);
+ gdk_draw_rectangle(dc->pixmap, dc->pixmap_gc, filled, x1, y1, x2-x1+1, y2-y1+1);
+}
+
+void iupDrawLine(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b)
+{
+ GdkColor color;
+ iupgdkColorSet(&color, r, g, b);
+ gdk_gc_set_rgb_fg_color(dc->pixmap_gc, &color);
+ gdk_draw_line(dc->pixmap, dc->pixmap_gc, x1, y1, x2, y2);
+}
+
+void iupDrawArc(IdrawCanvas* dc, int x1, int y1, int x2, int y2, double a1, double a2, unsigned char r, unsigned char g, unsigned char b, int filled)
+{
+ GdkColor color;
+ iupgdkColorSet(&color, r, g, b);
+ gdk_gc_set_rgb_fg_color(dc->pixmap_gc, &color);
+ gdk_draw_arc(dc->pixmap, dc->pixmap_gc, filled, x1, y1, x2-x1+1, y2-y1+1, iupROUND(a1*64), iupROUND((a2 - a1)*64));
+}
+
+void iupDrawPolygon(IdrawCanvas* dc, int* points, int count, unsigned char r, unsigned char g, unsigned char b, int filled)
+{
+ GdkColor color;
+ iupgdkColorSet(&color, r, g, b);
+ gdk_gc_set_rgb_fg_color(dc->pixmap_gc, &color);
+ gdk_draw_polygon(dc->pixmap, dc->pixmap_gc, filled, (GdkPoint*)points, count);
+}
+
+void iupDrawSetClipRect(IdrawCanvas* dc, int x1, int y1, int x2, int y2)
+{
+ GdkRectangle rect;
+ rect.x = x1;
+ rect.y = y1;
+ rect.width = x2-x1+1;
+ rect.height = y2-y1+1;
+ gdk_gc_set_clip_rectangle(dc->pixmap_gc, &rect);
+}
+
+void iupDrawResetClip(IdrawCanvas* dc)
+{
+ gdk_gc_set_clip_region(dc->pixmap_gc, NULL);
+}
+
+void iupDrawText(IdrawCanvas* dc, const char* text, int len, int x, int y, unsigned char r, unsigned char g, unsigned char b)
+{
+ PangoLayout* fontlayout = (PangoLayout*)IupGetAttribute(dc->ih, "PANGOLAYOUT");
+ GdkColor color;
+ iupgdkColorSet(&color, r, g, b);
+ gdk_gc_set_rgb_fg_color(dc->pixmap_gc, &color);
+ pango_layout_set_text(fontlayout, iupgtkStrConvertToUTF8(text), len);
+ gdk_draw_layout(dc->pixmap, dc->pixmap_gc, x, y, fontlayout);
+}
+
+void iupDrawImage(IdrawCanvas* dc, const char* name, int make_inactive, int x, int y)
+{
+ int img_w, img_h, bpp;
+ GdkPixbuf* pixbuf = iupImageGetImage(name, dc->ih, make_inactive);
+ if (!pixbuf)
+ return;
+
+ /* must use this info, since image can be a driver image loaded from resources */
+ iupdrvImageGetInfo(pixbuf, &img_w, &img_h, &bpp);
+
+ gdk_draw_pixbuf(dc->pixmap, dc->pixmap_gc, pixbuf, 0, 0, x, y, img_w, img_h, GDK_RGB_DITHER_NORMAL, 0, 0);
+}
diff --git a/iup/src/gtk/iupgtk_drv.h b/iup/src/gtk/iupgtk_drv.h
index ade2a4a..bf567d6 100755
--- a/iup/src/gtk/iupgtk_drv.h
+++ b/iup/src/gtk/iupgtk_drv.h
@@ -59,8 +59,8 @@ void iupgtkFontUpdateObjectPangoLayout(Ihandle* ih, gpointer object);
/* There are PANGO_SCALE Pango units in one device unit.
For an output backend where a device unit is a pixel,
a size value of 10 * PANGO_SCALE gives 10 pixels. */
-#define IUPGTK_PANGOUNITS2PIXELS(_x) (((_x) + PANGO_SCALE/2) / PANGO_SCALE)
-#define IUPGTK_PIXELS2PANGOUNITS(_x) ((_x) * PANGO_SCALE)
+#define iupGTK_PANGOUNITS2PIXELS(_x) (((_x) + PANGO_SCALE/2) / PANGO_SCALE)
+#define iupGTK_PIXELS2PANGOUNITS(_x) ((_x) * PANGO_SCALE)
/* open */
diff --git a/iup/src/gtk/iupgtk_filedlg.c b/iup/src/gtk/iupgtk_filedlg.c
index 5426910..a326c72 100755
--- a/iup/src/gtk/iupgtk_filedlg.c
+++ b/iup/src/gtk/iupgtk_filedlg.c
@@ -77,6 +77,8 @@ static void gtkFileDlgGetMultipleFiles(Ihandle* ih, GSList* list)
cur_len = iupArrayCount(names_array);
all_names = iupArrayAdd(names_array, dir_len+1);
memcpy(all_names+cur_len, filename, dir_len);
+ all_names[cur_len+dir_len] = '0';
+ iupAttribStoreStr(ih, "DIRECTORY", all_names);
all_names[cur_len+dir_len] = '|';
dir_len++; /* skip separator */
@@ -101,10 +103,14 @@ static void gtkFileDlgGetMultipleFiles(Ihandle* ih, GSList* list)
iupArrayDestroy(names_array);
}
-#ifdef WIN32
-#include <gdk/gdkwin32.h>
+#ifdef GTK_MAC
+ #include <gdk/gdk.h>
#else
-#include <gdk/gdkx.h>
+ #ifdef WIN32
+ #include <gdk/gdkwin32.h>
+ #else
+ #include <gdk/gdkx.h>
+ #endif
#endif
static void gtkFileDlgUpdatePreviewGLCanvas(Ihandle* ih)
@@ -112,10 +118,12 @@ static void gtkFileDlgUpdatePreviewGLCanvas(Ihandle* ih)
Ihandle* glcanvas = IupGetAttributeHandle(ih, "PREVIEWGLCANVAS");
if (glcanvas)
{
-#ifdef WIN32
- iupAttribSetStr(glcanvas, "HWND", iupAttribGet(ih, "HWND"));
-#else
- iupAttribSetStr(glcanvas, "XWINDOW", iupAttribGet(ih, "XWINDOW"));
+#ifndef GTK_MAC
+ #ifdef WIN32
+ iupAttribSetStr(glcanvas, "HWND", iupAttribGet(ih, "HWND"));
+ #else
+ iupAttribSetStr(glcanvas, "XWINDOW", iupAttribGet(ih, "XWINDOW"));
+ #endif
#endif
glcanvas->iclass->Map(glcanvas);
}
@@ -126,12 +134,15 @@ static void gtkFileDlgPreviewRealize(GtkWidget *widget, Ihandle *ih)
iupAttribSetStr(ih, "PREVIEWDC", iupgtkGetNativeGraphicsContext(widget));
iupAttribSetStr(ih, "WID", (char*)widget);
-#ifdef WIN32
- iupAttribSetStr(ih, "HWND", (char*)GDK_WINDOW_HWND(widget->window));
-#else
- iupAttribSetStr(ih, "XWINDOW", (char*)GDK_WINDOW_XID(widget->window));
- iupAttribSetStr(ih, "XDISPLAY", (char*)iupdrvGetDisplay());
+#ifndef GTK_MAC
+ #ifdef WIN32
+ iupAttribSetStr(ih, "HWND", (char*)GDK_WINDOW_HWND(widget->window));
+ #else
+ iupAttribSetStr(ih, "XWINDOW", (char*)GDK_WINDOW_XID(widget->window));
+ iupAttribSetStr(ih, "XDISPLAY", (char*)iupdrvGetDisplay());
+ #endif
#endif
+
gtkFileDlgUpdatePreviewGLCanvas(ih);
}
@@ -174,11 +185,11 @@ static void gtkFileDlgUpdatePreview(GtkFileChooser *file_chooser, Ihandle* ih)
{
char *filename = gtk_file_chooser_get_preview_filename(file_chooser);
+ IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
if (iupdrvIsFile(filename))
- {
- IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
cb(ih, iupgtkStrConvertFromFilename(filename), "SELECT");
- }
+ else
+ cb(ih, iupgtkStrConvertFromFilename(filename), "OTHER");
g_free (filename);
@@ -469,6 +480,13 @@ static int gtkFileDlgPopup(Ihandle* ih, int x, int y)
char* filename = (char*)file_list->data;
iupAttribStoreStr(ih, "VALUE", iupgtkStrConvertFromFilename(filename));
g_free(filename);
+
+ /* store the DIRECTORY */
+ {
+ char* dir = iupStrFileGetPath(iupAttribGet(ih, "VALUE"));
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+ free(dir);
+ }
}
g_slist_free(file_list);
@@ -481,6 +499,14 @@ static int gtkFileDlgPopup(Ihandle* ih, int x, int y)
iupAttribStoreStr(ih, "VALUE", iupgtkStrConvertFromFilename(filename));
file_exist = iupdrvIsFile(filename);
dir_exist = iupdrvIsDirectory(filename);
+
+ if (file_exist)
+ {
+ char* dir = iupStrFileGetPath(filename);
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+ free(dir);
+ }
+
g_free(filename);
}
@@ -507,8 +533,11 @@ static int gtkFileDlgPopup(Ihandle* ih, int x, int y)
{
/* GtkFileChooser does not change the current directory */
char* dir = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
- if (dir) iupdrvSetCurrentDirectory(dir);
- g_free(dir);
+ if (dir)
+ {
+ iupdrvSetCurrentDirectory(dir);
+ g_free(dir);
+ }
}
}
else
diff --git a/iup/src/gtk/iupgtk_font.c b/iup/src/gtk/iupgtk_font.c
index f7ff348..1139f62 100755
--- a/iup/src/gtk/iupgtk_font.c
+++ b/iup/src/gtk/iupgtk_font.c
@@ -132,9 +132,9 @@ static IgtkFont* gtkFindFont(const char *standardfont)
metrics = pango_context_get_metrics(gtk_fonts_context, fontdesc, pango_context_get_language(gtk_fonts_context));
fonts[i].charheight = pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics);
- fonts[i].charheight = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charheight);
+ fonts[i].charheight = iupGTK_PANGOUNITS2PIXELS(fonts[i].charheight);
fonts[i].charwidth = pango_font_metrics_get_approximate_char_width(metrics);
- fonts[i].charwidth = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charwidth);
+ fonts[i].charwidth = iupGTK_PANGOUNITS2PIXELS(fonts[i].charwidth);
pango_font_metrics_unref(metrics);
gtkFontUpdate(&(fonts[i]));
diff --git a/iup/src/gtk/iupgtk_fontdlg.c b/iup/src/gtk/iupgtk_fontdlg.c
index 5769cbc..dca0232 100755
--- a/iup/src/gtk/iupgtk_fontdlg.c
+++ b/iup/src/gtk/iupgtk_fontdlg.c
@@ -24,7 +24,7 @@ static int gtkFontDlgPopup(Ihandle* ih, int x, int y)
InativeHandle* parent = iupDialogGetNativeParent(ih);
GtkFontSelectionDialog* dialog;
int response;
- char* preview_text;
+ char* preview_text, *standardfont;
iupAttribSetInt(ih, "_IUPDLG_X", x); /* used in iupDialogUpdatePosition */
iupAttribSetInt(ih, "_IUPDLG_Y", y);
@@ -36,7 +36,10 @@ static int gtkFontDlgPopup(Ihandle* ih, int x, int y)
if (parent)
gtk_window_set_transient_for((GtkWindow*)dialog, (GtkWindow*)parent);
- gtk_font_selection_dialog_set_font_name(dialog, iupAttribGet(ih, "VALUE"));
+ standardfont = iupAttribGet(ih, "VALUE");
+ if (!standardfont)
+ standardfont = IupGetGlobal("DEFAULTFONT");
+ gtk_font_selection_dialog_set_font_name(dialog, standardfont);
preview_text = iupAttribGet(ih, "PREVIEWTEXT");
if (preview_text)
diff --git a/iup/src/gtk/iupgtk_frame.c b/iup/src/gtk/iupgtk_frame.c
index 022c6c7..25595be 100755
--- a/iup/src/gtk/iupgtk_frame.c
+++ b/iup/src/gtk/iupgtk_frame.c
@@ -41,8 +41,11 @@ static char* gtkFrameGetTitleAttrib(Ihandle* ih)
static int gtkFrameSetTitleAttrib(Ihandle* ih, const char* value)
{
- GtkFrame* frame = (GtkFrame*)ih->handle;
- gtk_frame_set_label(frame, iupgtkStrConvertToUTF8(value));
+ if (iupAttribGetStr(ih, "_IUPFRAME_HAS_TITLE"))
+ {
+ GtkFrame* frame = (GtkFrame*)ih->handle;
+ gtk_frame_set_label(frame, iupgtkStrConvertToUTF8(value));
+ }
return 0;
}
@@ -57,7 +60,11 @@ static int gtkFrameSetBgColorAttrib(Ihandle* ih, const char* value)
if (label)
iupgtkBaseSetBgColor(label, r, g, b);
- iupgtkBaseSetBgColor(ih->handle, r, g, b);
+ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+ {
+ GtkWidget* fixed = gtk_bin_get_child((GtkBin*)ih->handle);
+ iupgtkBaseSetBgColor(fixed, r, g, b);
+ }
return 1;
}
@@ -120,10 +127,19 @@ static int gtkFrameMapMethod(Ihandle* ih)
gtk_frame_set_shadow_type((GtkFrame*)ih->handle, GTK_SHADOW_IN);
else
gtk_frame_set_shadow_type((GtkFrame*)ih->handle, GTK_SHADOW_ETCHED_IN);
+
+ if (iupAttribGet(ih, "BGCOLOR"))
+ iupAttribSetStr(ih, "_IUPFRAME_HAS_BGCOLOR", "1");
}
/* the container that will receive the child element. */
fixed = gtk_fixed_new();
+ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+#if GTK_CHECK_VERSION(2, 18, 0)
+ gtk_widget_set_has_window(fixed, TRUE);
+#else
+ gtk_fixed_set_has_window((GtkFixed*)fixed, TRUE);
+#endif
gtk_container_add((GtkContainer*)ih->handle, fixed);
gtk_widget_show(fixed);
diff --git a/iup/src/gtk/iupgtk_key.c b/iup/src/gtk/iupgtk_key.c
index 5aec919..ed485a7 100755
--- a/iup/src/gtk/iupgtk_key.c
+++ b/iup/src/gtk/iupgtk_key.c
@@ -316,9 +316,9 @@ gboolean iupgtkKeyPressEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih)
if (code == 0)
return FALSE;
- /* Avoid duplicate calls if a child of the dialog contains the focus.
- GTK will call the callback for the child and for the dialog */
- if (ih->iclass->nativetype == IUP_TYPEDIALOG && ih != IupGetFocus())
+ /* Avoid duplicate calls if a child of a native container contains the focus.
+ GTK will call the callback for the child and for the container. */
+ if (ih->iclass->childtype != IUP_CHILDNONE && ih != IupGetFocus())
return FALSE;
result = iupKeyCallKeyCb(ih, code);
@@ -390,33 +390,33 @@ gboolean iupgtkKeyReleaseEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih)
void iupgtkButtonKeySetStatus(guint state, unsigned int but, char* status, int doubleclick)
{
if (state & GDK_SHIFT_MASK)
- iupKEYSETSHIFT(status);
+ iupKEY_SETSHIFT(status);
if (state & GDK_CONTROL_MASK)
- iupKEYSETCONTROL(status);
+ iupKEY_SETCONTROL(status);
if ((state & GDK_BUTTON1_MASK) || but==1)
- iupKEYSETBUTTON1(status);
+ iupKEY_SETBUTTON1(status);
if ((state & GDK_BUTTON2_MASK) || but==2)
- iupKEYSETBUTTON2(status);
+ iupKEY_SETBUTTON2(status);
if ((state & GDK_BUTTON3_MASK) || but==3)
- iupKEYSETBUTTON3(status);
+ iupKEY_SETBUTTON3(status);
if ((state & GDK_BUTTON4_MASK) || but==4)
- iupKEYSETBUTTON4(status);
+ iupKEY_SETBUTTON4(status);
if ((state & GDK_BUTTON5_MASK) || but==5)
- iupKEYSETBUTTON5(status);
+ iupKEY_SETBUTTON5(status);
if (state & GDK_MOD1_MASK || state & GDK_MOD5_MASK) /* Alt */
- iupKEYSETALT(status);
+ iupKEY_SETALT(status);
if (state & GDK_MOD4_MASK) /* Apple/Win */
- iupKEYSETSYS(status);
+ iupKEY_SETSYS(status);
if (doubleclick)
- iupKEYSETDOUBLE(status);
+ iupKEY_SETDOUBLE(status);
}
diff --git a/iup/src/gtk/iupgtk_label.c b/iup/src/gtk/iupgtk_label.c
index 49d5c6d..f95f576 100755
--- a/iup/src/gtk/iupgtk_label.c
+++ b/iup/src/gtk/iupgtk_label.c
@@ -133,8 +133,10 @@ static int gtkLabelSetPaddingAttrib(Ihandle* ih, const char* value)
{
GtkMisc* misc = (GtkMisc*)ih->handle;
gtk_misc_set_padding(misc, ih->data->horiz_padding, ih->data->vert_padding);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static char* gtkLabelGetPangoLayoutAttrib(Ihandle* ih)
diff --git a/iup/src/gtk/iupgtk_list.c b/iup/src/gtk/iupgtk_list.c
index 80f6cce..48fa88e 100755
--- a/iup/src/gtk/iupgtk_list.c
+++ b/iup/src/gtk/iupgtk_list.c
@@ -113,6 +113,8 @@ void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
GtkTreeIter iter;
gtk_list_store_insert(GTK_LIST_STORE(model), &iter, pos);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, iupgtkStrConvertToUTF8(value), -1);
+
+ iupListUpdateOldValue(ih, pos, 0);
}
void iupdrvListRemoveItem(Ihandle* ih, int pos)
@@ -127,14 +129,24 @@ void iupdrvListRemoveItem(Ihandle* ih, int pos)
int curpos = gtk_combo_box_get_active((GtkComboBox*)ih->handle);
if (pos == curpos)
{
- if (curpos > 0) curpos--;
- else curpos++;
+ if (curpos > 0)
+ curpos--;
+ else
+ {
+ curpos=1;
+ if (iupdrvListGetCount(ih)==1)
+ curpos = -1; /* remove the selection */
+ }
+ g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkListComboBoxChanged), ih);
gtk_combo_box_set_active((GtkComboBox*)ih->handle, curpos);
+ g_signal_handlers_unblock_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkListComboBoxChanged), ih);
}
}
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+
+ iupListUpdateOldValue(ih, pos, 1);
}
}
@@ -177,7 +189,7 @@ static int gtkListSetStandardFontAttrib(Ihandle* ih, const char* value)
static char* gtkListGetIdValueAttrib(Ihandle* ih, const char* name_id)
{
int pos = iupListGetPos(ih, name_id);
- if (pos != -1)
+ if (pos >= 0)
{
GtkTreeIter iter;
GtkTreeModel* model = gtkListGetModel(ih);
@@ -349,7 +361,7 @@ static int gtkListSetValueAttrib(Ihandle* ih, const char* value)
GtkTreeModel *model = gtkListGetModel(ih);
g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkListComboBoxChanged), ih);
if (iupStrToInt(value, &pos)==1 &&
- (pos>0 && pos<gtk_tree_model_iter_n_children(model, NULL)))
+ (pos>0 && pos<=gtk_tree_model_iter_n_children(model, NULL)))
{
gtk_combo_box_set_active((GtkComboBox*)ih->handle, pos-1); /* IUP starts at 1 */
iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", pos);
@@ -788,9 +800,10 @@ static int gtkListSetNCAttrib(Ihandle* ih, const char* value)
{
GtkEntry* entry = (GtkEntry*)iupAttribGet(ih, "_IUPGTK_ENTRY");
gtk_entry_set_max_length(entry, ih->data->nc);
+ return 0;
}
-
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int gtkListSetClipboardAttrib(Ihandle *ih, const char *value)
@@ -1364,9 +1377,9 @@ static int gtkListMapMethod(Ihandle* ih)
if (!ih->data->has_editbox && ih->data->is_multiple)
{
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
-#if GTK_CHECK_VERSION(2, 10, 0)
+ #if GTK_CHECK_VERSION(2, 10, 0)
gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(ih->handle), TRUE);
-#endif
+ #endif
}
else
gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
diff --git a/iup/src/gtk/iupgtk_loop.c b/iup/src/gtk/iupgtk_loop.c
index e349a45..704923e 100755
--- a/iup/src/gtk/iupgtk_loop.c
+++ b/iup/src/gtk/iupgtk_loop.c
@@ -69,6 +69,13 @@ int IupMainLoop(void)
return IUP_NOERROR;
}
+int IupLoopStepWait(void)
+{
+ if (gtk_main_iteration_do(TRUE))
+ return IUP_CLOSE;
+ return IUP_DEFAULT;
+}
+
int IupLoopStep(void)
{
if (gtk_main_iteration_do(FALSE))
diff --git a/iup/src/gtk/iupgtk_menu.c b/iup/src/gtk/iupgtk_menu.c
index c12fbea..772f4cf 100755
--- a/iup/src/gtk/iupgtk_menu.c
+++ b/iup/src/gtk/iupgtk_menu.c
@@ -245,11 +245,19 @@ static int gtkMenuMapMethod(Ihandle* ih)
return IUP_NOERROR;
}
+static void gtkMenuUnMapMethod(Ihandle* ih)
+{
+ if (iupMenuIsMenuBar(ih))
+ ih->parent = NULL;
+
+ iupdrvBaseUnMapMethod(ih);
+}
+
void iupdrvMenuInitClass(Iclass* ic)
{
/* Driver Dependent Class functions */
ic->Map = gtkMenuMapMethod;
- ic->UnMap = iupdrvBaseUnMapMethod;
+ ic->UnMap = gtkMenuUnMapMethod;
/* Used by iupdrvMenuGetMenuBarSize */
iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, NULL, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_DEFAULT); /* use inheritance to retrieve standard fonts */
@@ -337,15 +345,10 @@ static int gtkItemSetValueAttrib(Ihandle* ih, const char* value)
static char* gtkItemGetValueAttrib(Ihandle* ih)
{
- if (GTK_IS_CHECK_MENU_ITEM(ih->handle))
- {
- if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)ih->handle))
- return "ON";
- else
- return "OFF";
- }
+ if (GTK_IS_CHECK_MENU_ITEM(ih->handle) && gtk_check_menu_item_get_active((GtkCheckMenuItem*)ih->handle))
+ return "ON";
else
- return NULL;
+ return "OFF";
}
static int gtkItemMapMethod(Ihandle* ih)
diff --git a/iup/src/gtk/iupgtk_open.c b/iup/src/gtk/iupgtk_open.c
index 66e46e8..962f760 100755
--- a/iup/src/gtk/iupgtk_open.c
+++ b/iup/src/gtk/iupgtk_open.c
@@ -20,7 +20,52 @@
#include "iupgtk_drv.h"
+#ifdef GTK_MAC
+#include <gdk/gdk.h>
+char* iupgtkGetNativeWindowHandle(Ihandle* ih)
+{
+ GdkWindow* window = ih->handle->window;
+ if (window)
+ return (char*)window;
+ else
+ return NULL;
+}
+
+void* iupgtkGetNativeGraphicsContext(GtkWidget* widget)
+{
+ return (void*)gdk_gc_new((GdkDrawable*)widget->window);
+}
+
+void iupgtkReleaseNativeGraphicsContext(GtkWidget* widget, void* gc)
+{
+ g_object_unref(gc);
+ (void)widget;
+}
+
+void* iupdrvGetDisplay(void)
+{
+ GdkDisplay* display = gdk_display_get_default();
+ return display;
+}
+
+void iupgtkPushVisualAndColormap(void* visual, void* colormap)
+{
+ GdkColormap* gdk_colormap;
+ GdkVisual *gdk_visual = gdk_visual_get_best();
+
+ gdk_colormap = gdk_colormap_new(gdk_visual, FALSE);
+
+ gtk_widget_push_colormap(gdk_colormap);
+
+ /* gtk_widget_push_visual is now deprecated */
+}
+
+static void gtkSetDrvGlobalAttrib(void)
+{
+}
+
+#else
#ifdef WIN32 /******************************** WIN32 ************************************/
#include <gdk/gdkwin32.h>
@@ -115,6 +160,8 @@ static void gtkSetDrvGlobalAttrib(void)
#endif
+#endif
+
static void gtkSetGlobalColorAttrib(const char* name, GdkColor *color)
{
iupGlobalSetDefaultColorAttrib(name, (int)iupCOLOR16TO8(color->red),
diff --git a/iup/src/gtk/iupgtk_tabs.c b/iup/src/gtk/iupgtk_tabs.c
index 8029826..6b5aa66 100755
--- a/iup/src/gtk/iupgtk_tabs.c
+++ b/iup/src/gtk/iupgtk_tabs.c
@@ -76,13 +76,13 @@ static void gtkTabsUpdatePageBgColor(Ihandle* ih, unsigned char r, unsigned char
for (child = ih->firstchild; child; child = child->brother)
{
- GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
- if (tab_page)
+ GtkWidget* tab_container = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ if (tab_container)
{
GtkWidget* tab_label = (GtkWidget*)iupAttribGet(child, "_IUPGTK_TABLABEL");
if (tab_label)
iupgtkBaseSetBgColor(tab_label, r, g, b);
- iupgtkBaseSetBgColor(tab_page, r, g, b);
+ iupgtkBaseSetBgColor(tab_container, r, g, b);
}
}
}
@@ -121,15 +121,18 @@ static int gtkTabsSetPaddingAttrib(Ihandle* ih, const char* value)
iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
if (ih->handle)
+ {
gtkTabsUpdatePagePadding(ih);
- return 0;
+ return 0;
+ }
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static void gtkTabsUpdateTabType(Ihandle* ih)
{
- GtkNotebook* tab_page = (GtkNotebook*)ih->handle;
int iup2gtk[4] = {GTK_POS_TOP, GTK_POS_BOTTOM, GTK_POS_LEFT, GTK_POS_RIGHT};
- gtk_notebook_set_tab_pos(tab_page, iup2gtk[ih->data->type]);
+ gtk_notebook_set_tab_pos((GtkNotebook*)ih->handle, iup2gtk[ih->data->type]);
}
static int gtkTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
@@ -144,7 +147,7 @@ static int gtkTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
ih->data->type = ITABS_TOP;
if (ih->handle)
- gtkTabsUpdateTabType(ih);
+ gtkTabsUpdateTabType(ih); /* for this to work must be updated in map */
return 0;
}
@@ -171,7 +174,7 @@ static int gtkTabsSetTabTitleAttrib(Ihandle* ih, const char* name_id, const char
GtkWidget* tab_label = (GtkWidget*)iupAttribGet(child, "_IUPGTK_TABLABEL");
if (tab_label)
{
- GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_PAGE");
gtk_label_set_text((GtkLabel*)tab_label, iupgtkStrConvertToUTF8(value));
gtk_notebook_set_menu_label_text((GtkNotebook*)ih->handle, tab_page, gtk_label_get_text((GtkLabel*)tab_label));
}
@@ -238,8 +241,10 @@ void gtkTabSwitchPage(GtkNotebook* notebook, GtkNotebookPage *page, int pos, Iha
IFnnn cb;
Ihandle* child = IupGetChild(ih, pos);
Ihandle* prev_child = IupGetChild(ih, iupdrvTabsGetCurrentTab(ih));
- IupSetAttribute(child, "VISIBLE", "YES");
- IupSetAttribute(prev_child, "VISIBLE", "NO");
+ GtkWidget* tab_container = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ GtkWidget* prev_tab_container = (GtkWidget*)iupAttribGet(prev_child, "_IUPTAB_CONTAINER");
+ if (tab_container) gtk_widget_show(tab_container);
+ if (prev_tab_container) gtk_widget_hide(prev_tab_container);
if (iupAttribGet(ih, "_IUPGTK_IGNORE_CHANGE"))
return;
@@ -263,7 +268,7 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
if (ih->handle)
{
- GtkWidget* tab_page;
+ GtkWidget *tab_page, *tab_container;
GtkWidget *tab_label = NULL, *tab_image = NULL;
char *tabtitle, *tabimage;
int pos;
@@ -271,9 +276,13 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
pos = IupGetChildPos(ih, child);
- tab_page = gtk_fixed_new();
+ tab_page = gtk_vbox_new(FALSE, 0);
gtk_widget_show(tab_page);
+ tab_container = gtk_fixed_new();
+ gtk_widget_show(tab_container);
+ gtk_container_add((GtkContainer*)tab_page, tab_container);
+
tabtitle = iupAttribGet(child, "TABTITLE");
if (!tabtitle) tabtitle = iupTabsAttribGetStrId(ih, "TABTITLE", pos);
tabimage = iupAttribGet(child, "TABIMAGE");
@@ -327,9 +336,10 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
iupAttribSetStr(child, "_IUPGTK_TABIMAGE", (char*)tab_image); /* store it even if its NULL */
iupAttribSetStr(child, "_IUPGTK_TABLABEL", (char*)tab_label);
- iupAttribSetStr(child, "_IUPTAB_CONTAINER", (char*)tab_page);
+ iupAttribSetStr(child, "_IUPTAB_CONTAINER", (char*)tab_container);
+ iupAttribSetStr(child, "_IUPTAB_PAGE", (char*)tab_page);
iupStrToRGB(IupGetAttribute(ih, "BGCOLOR"), &r, &g, &b);
- iupgtkBaseSetBgColor(tab_page, r, g, b);
+ iupgtkBaseSetBgColor(tab_container, r, g, b);
if (tabtitle)
{
@@ -354,10 +364,8 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
iupAttribSetStr(ih, "_IUPGTK_IGNORE_CHANGE", NULL);
- if (pos == iupdrvTabsGetCurrentTab(ih))
- IupSetAttribute(child, "VISIBLE", "YES");
- else
- IupSetAttribute(child, "VISIBLE", "NO");
+ if (pos != iupdrvTabsGetCurrentTab(ih))
+ gtk_widget_hide(tab_container);
}
}
@@ -365,10 +373,11 @@ static void gtkTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
{
if (ih->handle)
{
- GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_PAGE");
if (tab_page)
{
int pos = gtk_notebook_page_num((GtkNotebook*)ih->handle, tab_page);
+ iupTabsTestRemoveTab(ih, pos);
iupAttribSetStr(ih, "_IUPGTK_IGNORE_CHANGE", "1");
gtk_notebook_remove_page((GtkNotebook*)ih->handle, pos);
@@ -377,6 +386,7 @@ static void gtkTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
iupAttribSetStr(child, "_IUPGTK_TABIMAGE", NULL);
iupAttribSetStr(child, "_IUPGTK_TABLABEL", NULL);
iupAttribSetStr(child, "_IUPTAB_CONTAINER", NULL);
+ iupAttribSetStr(child, "_IUPTAB_PAGE", NULL);
}
}
}
@@ -440,5 +450,5 @@ void iupdrvTabsInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "TABORIENTATION", iupTabsGetTabOrientationAttrib, gtkTabsSetTabOrientationAttrib, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TABTITLE", NULL, gtkTabsSetTabTitleAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, gtkTabsSetTabImageAttrib, IUPAF_NO_INHERIT);
- iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, gtkTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, gtkTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
}
diff --git a/iup/src/gtk/iupgtk_text.c b/iup/src/gtk/iupgtk_text.c
index 4c2906a..d0909d7 100755
--- a/iup/src/gtk/iupgtk_text.c
+++ b/iup/src/gtk/iupgtk_text.c
@@ -101,7 +101,7 @@ static void gtkTextParseParagraphFormat(Ihandle* formattag, GtkTextTag* tag)
align = PANGO_TAB_LEFT;
free(str);
- pango_tab_array_set_tab(tabs, i, align, IUPGTK_PIXELS2PANGOUNITS(pos));
+ pango_tab_array_set_tab(tabs, i, align, iupGTK_PIXELS2PANGOUNITS(pos));
i++;
if (i == 32) break;
}
@@ -171,7 +171,7 @@ static void gtkTextParseCharacterFormat(Ihandle* formattag, GtkTextTag* tag)
else
iupStrToInt(format, &val);
- val = IUPGTK_PIXELS2PANGOUNITS(val);
+ val = iupGTK_PIXELS2PANGOUNITS(val);
g_object_set(G_OBJECT(tag), "rise", val, NULL);
}
@@ -214,7 +214,7 @@ static void gtkTextParseCharacterFormat(Ihandle* formattag, GtkTextTag* tag)
{
if (val < 0) /* in pixels */
{
- val = IUPGTK_PIXELS2PANGOUNITS(-val);
+ val = iupGTK_PIXELS2PANGOUNITS(-val);
g_object_set(G_OBJECT(tag), "size", val, NULL);
}
else /* in points */
@@ -387,8 +387,8 @@ static int gtkTextConvertXYToPos(Ihandle* ih, int x, int y)
/* transform to Layout coordinates */
gtk_entry_get_layout_offsets(GTK_ENTRY(ih->handle), &off_x, &off_y);
- x = IUPGTK_PIXELS2PANGOUNITS(x - off_x);
- y = IUPGTK_PIXELS2PANGOUNITS(y - off_y);
+ x = iupGTK_PIXELS2PANGOUNITS(x - off_x);
+ y = iupGTK_PIXELS2PANGOUNITS(y - off_y);
pango_layout_xy_to_index(gtk_entry_get_layout(GTK_ENTRY(ih->handle)), x, y, &pos, &trailing);
return pos;
@@ -851,7 +851,7 @@ static char* gtkTextGetValueAttrib(Ihandle* ih)
static int gtkTextSetInsertAttrib(Ihandle* ih, const char* value)
{
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
if (!value)
return 0;
@@ -875,7 +875,8 @@ static int gtkTextSetInsertAttrib(Ihandle* ih, const char* value)
static int gtkTextSetAppendAttrib(Ihandle* ih, const char* value)
{
- if (!ih->handle) /* do not store the action before map */
+ gint pos;
+ if (!ih->handle) /* do not do the action before map */
return 0;
/* disable callbacks */
iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1");
@@ -884,13 +885,18 @@ static int gtkTextSetAppendAttrib(Ihandle* ih, const char* value)
GtkTextIter iter;
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle));
gtk_text_buffer_get_end_iter(buffer, &iter);
- if (ih->data->append_newline)
+ pos = gtk_text_buffer_get_char_count(buffer);
+ if (ih->data->append_newline && pos!=0)
gtk_text_buffer_insert(buffer, &iter, "\n", 1);
gtk_text_buffer_insert(buffer, &iter, iupgtkStrConvertToUTF8(value), -1);
}
else
{
- gint pos = strlen(gtk_entry_get_text(GTK_ENTRY(ih->handle)))+1;
+#if GTK_CHECK_VERSION(2, 14, 0)
+ pos = gtk_entry_get_text_length(GTK_ENTRY(ih->handle))+1;
+#else
+ pos = strlen(gtk_entry_get_text(GTK_ENTRY(ih->handle)))+1;
+#endif
gtk_editable_insert_text(GTK_EDITABLE(ih->handle), iupgtkStrConvertToUTF8(value), -1, &pos);
}
iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL);
@@ -946,8 +952,10 @@ static int gtkTextSetPaddingAttrib(Ihandle* ih, const char* value)
gtk_entry_set_inner_border(GTK_ENTRY(ih->handle), &border);
#endif
}
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int gtkTextSetNCAttrib(Ihandle* ih, const char* value)
@@ -955,10 +963,14 @@ static int gtkTextSetNCAttrib(Ihandle* ih, const char* value)
if (!iupStrToInt(value, &ih->data->nc))
ih->data->nc = INT_MAX;
- if (!ih->data->is_multiline && ih->handle)
- gtk_entry_set_max_length(GTK_ENTRY(ih->handle), ih->data->nc);
-
- return 0;
+ if (ih->handle)
+ {
+ if (!ih->data->is_multiline)
+ gtk_entry_set_max_length(GTK_ENTRY(ih->handle), ih->data->nc);
+ return 0;
+ }
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int gtkTextSetClipboardAttrib(Ihandle *ih, const char *value)
diff --git a/iup/src/gtk/iupgtk_toggle.c b/iup/src/gtk/iupgtk_toggle.c
index 8ff7df5..040beda 100755
--- a/iup/src/gtk/iupgtk_toggle.c
+++ b/iup/src/gtk/iupgtk_toggle.c
@@ -213,8 +213,10 @@ static int gtkToggleSetPaddingAttrib(Ihandle* ih, const char* value)
GtkButton* button = (GtkButton*)ih->handle;
GtkMisc* misc = (GtkMisc*)gtk_button_get_image(button);
gtk_misc_set_padding(misc, ih->data->horiz_padding, ih->data->vert_padding);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int gtkToggleSetFgColorAttrib(Ihandle* ih, const char* value)
diff --git a/iup/src/gtk/iupgtk_tree.c b/iup/src/gtk/iupgtk_tree.c
index d408f27..9595ada 100755
--- a/iup/src/gtk/iupgtk_tree.c
+++ b/iup/src/gtk/iupgtk_tree.c
@@ -31,33 +31,50 @@
#include "iup_drvinfo.h"
#include "iupgtk_drv.h"
+
+/* IMPORTANT:
+
+ GtkTreeStore uses the "user_data" field of the GtkTreeIter
+ to store the node pointer that is position independent.
+ So we use it as a reference to the node in the cache, just like in Motif and Windows.
+
+ BUT if GTK change its implementation this must be changed also. See "gtk_tree_store.c".
+
+ ABOUT SELECTIONS:
+
+ From the GTK documentation on GtkTreeSelection
+
+ "Additionally, you cannot change the selection of a row on the model
+ that is not currently displayed by the view without expanding its parents first."
+*/
+
enum
{
- IUPGTK_TREE_IMAGE,
+ IUPGTK_TREE_IMAGE, /* "pixbuf", "pixbuf-expander-closed" */
IUPGTK_TREE_HAS_IMAGE,
- IUPGTK_TREE_IMAGE_EXPANDED,
+ IUPGTK_TREE_IMAGE_EXPANDED, /* "pixbuf-expander-open" */
IUPGTK_TREE_HAS_IMAGE_EXPANDED,
- IUPGTK_TREE_TITLE,
- IUPGTK_TREE_KIND,
- IUPGTK_TREE_COLOR,
- IUPGTK_TREE_FONT,
- IUPGTK_TREE_USERDATA
+ IUPGTK_TREE_TITLE, /* "text" */
+ IUPGTK_TREE_KIND, /* "is-expander" */
+ IUPGTK_TREE_COLOR, /* "foreground-gdk" */
+ IUPGTK_TREE_FONT, /* "font-desc" */
+ IUPGTK_TREE_SELECT,
+ IUPGTK_TREE_LAST_DATA /* used as a count */
};
-static GtkTreeIter gtkTreeInvalidIter = {0,0,0,0};
+static void gtkTreeRebuildNodeCache(Ihandle* ih, int id, GtkTreeIter iterItem);
/*****************************************************************************/
/* COPYING ITEMS (Branches and its children) */
/*****************************************************************************/
/* Insert the copied item in a new location. Returns the new item. */
-static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeIter* iterParent, int position, GtkTreeIter *iterNewItem, int full_copy)
+static void gtkTreeCopyItem(Ihandle* ih, GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeIter* iterParent, int position, GtkTreeIter *iterNewItem)
{
GtkTreeStore* store = GTK_TREE_STORE(model);
int kind;
char* title;
gboolean has_image, has_image_expanded;
PangoFontDescription* font;
- void* userdata;
GdkColor *color;
GdkPixbuf* image, *image_expanded;
@@ -69,9 +86,10 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI
IUPGTK_TREE_KIND, &kind,
IUPGTK_TREE_COLOR, &color,
IUPGTK_TREE_FONT, &font,
- IUPGTK_TREE_USERDATA, &userdata,
-1);
+ /* Add the new node */
+ ih->data->node_count++;
if (position == 2)
gtk_tree_store_append(store, iterNewItem, iterParent);
else if (position == 1) /* copy as first child of expanded branch */
@@ -79,9 +97,6 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI
else /* copy as next brother of item or collapsed branch */
gtk_tree_store_insert_after(store, iterNewItem, NULL, iterParent); /* iterParent is sibling of the new item */
- if (full_copy) /* during a full copy the userdata reference is not copied */
- userdata = NULL;
-
gtk_tree_store_set(store, iterNewItem, IUPGTK_TREE_IMAGE, image,
IUPGTK_TREE_HAS_IMAGE, has_image,
IUPGTK_TREE_IMAGE_EXPANDED, image_expanded,
@@ -90,21 +105,21 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI
IUPGTK_TREE_KIND, kind,
IUPGTK_TREE_COLOR, color,
IUPGTK_TREE_FONT, font,
- IUPGTK_TREE_USERDATA, userdata,
+ IUPGTK_TREE_SELECT, 0,
-1);
}
-static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, int full_copy)
+static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst)
{
GtkTreeIter iterChildSrc;
int hasItem = gtk_tree_model_iter_children(model, &iterChildSrc, iterItemSrc); /* get the firstchild */
while(hasItem)
{
GtkTreeIter iterNewItem;
- gtkTreeCopyItem(model, &iterChildSrc, iterItemDst, 2, &iterNewItem, full_copy); /* append always */
+ gtkTreeCopyItem(ih, model, &iterChildSrc, iterItemDst, 2, &iterNewItem); /* append always */
/* Recursively transfer all the items */
- gtkTreeCopyChildren(ih, model, &iterChildSrc, &iterNewItem, full_copy);
+ gtkTreeCopyChildren(ih, model, &iterChildSrc, &iterNewItem);
/* Go to next sibling item */
hasItem = gtk_tree_model_iter_next(model, &iterChildSrc);
@@ -112,9 +127,17 @@ static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *i
}
/* Copies all items in a branch to a new location. Returns the new branch node. */
-static void gtkTreeCopyNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, GtkTreeIter* iterNewItem, int full_copy)
+static void gtkTreeCopyMoveNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, GtkTreeIter* iterNewItem, int is_copy)
{
int kind, position = 0; /* insert after iterItemDst */
+ int id_new, count, id_src, id_dst;
+
+ int old_count = ih->data->node_count;
+
+ id_src = iupTreeFindNodeId(ih, iterItemSrc);
+ id_dst = iupTreeFindNodeId(ih, iterItemDst);
+ id_new = id_dst+1; /* contains the position for a copy operation */
+
gtk_tree_model_get(model, iterItemDst, IUPGTK_TREE_KIND, &kind, -1);
if (kind == ITREE_BRANCH)
@@ -122,346 +145,311 @@ static void gtkTreeCopyNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterI
GtkTreePath* path = gtk_tree_model_get_path(model, iterItemDst);
if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
position = 1; /* insert as first child of iterItemDst */
+ else
+ {
+ int child_count = iupdrvTreeTotalChildCount(ih, iterItemDst);
+ id_new += child_count;
+ }
gtk_tree_path_free(path);
}
- gtkTreeCopyItem(model, iterItemSrc, iterItemDst, position, iterNewItem, full_copy);
+ /* move to the same place does nothing */
+ if (!is_copy && id_new == id_src)
+ {
+ iterNewItem->stamp = 0;
+ return;
+ }
- gtkTreeCopyChildren(ih, model, iterItemSrc, iterNewItem, full_copy);
-}
+ gtkTreeCopyItem(ih, model, iterItemSrc, iterItemDst, position, iterNewItem);
-/*****************************************************************************/
-/* FINDING ITEMS */
-/*****************************************************************************/
+ gtkTreeCopyChildren(ih, model, iterItemSrc, iterNewItem);
-static void gtkTreeInvertAllNodeMarking(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter* iterItem)
-{
- GtkTreeIter iterChild;
- int hasItem = TRUE;
+ count = ih->data->node_count - old_count;
+ iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy);
- while(hasItem)
+ if (!is_copy)
{
- if(gtk_tree_selection_iter_is_selected(selection, iterItem))
- gtk_tree_selection_unselect_iter(selection, iterItem);
- else
- gtk_tree_selection_select_iter(selection, iterItem);
+ /* Deleting the node of its old position */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ gtk_tree_store_remove(GTK_TREE_STORE(model), iterItemSrc);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
- /* Check whether we have child items */
- if(gtk_tree_model_iter_has_child(model, iterItem))
- {
- gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
- gtkTreeInvertAllNodeMarking(ih, model, selection, &iterChild);
- }
+ /* restore count, because we remove src */
+ ih->data->node_count = old_count;
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, iterItem);
+ /* compensate position for a move */
+ if (id_new > id_src)
+ id_new -= count;
}
+
+ gtkTreeRebuildNodeCache(ih, id_new, *iterNewItem);
}
-static GtkTreeIter gtkTreeFindVisibleNodeId(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, GtkTreeIter iterNode)
+/*****************************************************************************/
+/* FINDING ITEMS */
+/*****************************************************************************/
+
+static void gtkTreeIterInit(Ihandle* ih, GtkTreeIter* iterItem, InodeHandle* node_handle)
{
- GtkTreeIter iterChild;
- GtkTreePath* path;
- int hasItem = TRUE;
+ iterItem->stamp = ih->data->stamp;
+ iterItem->user_data = node_handle;
+ iterItem->user_data2 = NULL;
+ iterItem->user_data3 = NULL;
+}
- while(hasItem)
- {
- /* ID control to traverse items */
- ih->data->id_control++; /* not the real id since it counts only the visible ones */
+static int gtkTreeIsNodeSelected(GtkTreeModel* model, GtkTreeIter *iterItem)
+{
+ gboolean selected = 0;
+ gtk_tree_model_get(model, iterItem, IUPGTK_TREE_SELECT, &selected, -1);
+ return selected;
+}
- /* StateID founded! */
- if(iterItem.user_data == iterNode.user_data)
- return iterItem;
+static void gtkTreeSelectNodeRaw(GtkTreeModel* model, GtkTreeIter *iterItem, int select)
+{
+ /* Cannot change the selection of a row on the model that is not currently displayed.
+ So we store the selection state here. And update the actual state when the node becames visible. */
+ gtk_tree_store_set(GTK_TREE_STORE(model), iterItem, IUPGTK_TREE_SELECT, select, -1);
+}
- path = gtk_tree_model_get_path(model, &iterItem);
+static void gtkTreeSelectNode(GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem, int select)
+{
+ if (select == -1)
+ select = !gtkTreeIsNodeSelected(model, iterItem); /* toggle */
- /* Check whether we have child items and it is expanded (visible) */
- if (gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
- {
- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
- iterChild = gtkTreeFindVisibleNodeId(ih, model, iterChild, iterNode);
+ gtkTreeSelectNodeRaw(model, iterItem, select);
- /* StateID founded! */
- if(iterChild.user_data)
- {
- gtk_tree_path_free(path);
- return iterChild;
- }
- }
+ if (select)
+ gtk_tree_selection_select_iter(selection, iterItem);
+ else
+ gtk_tree_selection_unselect_iter(selection, iterItem);
+}
- gtk_tree_path_free(path);
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterItem);
+static void gtkTreeSelectAll(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, int selected)
+{
+ int i;
+ GtkTreeIter iterItem;
+
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ gtkTreeSelectNodeRaw(model, &iterItem, selected);
}
- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
+ if (selected)
+ gtk_tree_selection_select_all(selection);
+ else
+ gtk_tree_selection_unselect_all(selection);
}
-static GtkTreeIter gtkTreeFindVisibleNodeFromId(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem)
+static void gtkTreeInvertAllNodeMarking(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection)
{
- GtkTreeIter iterChild;
- GtkTreePath* path;
- int hasItem = TRUE;
+ int i;
+ GtkTreeIter iterItem;
- while(hasItem)
+ for (i = 0; i < ih->data->node_count; i++)
{
- /* ID control to traverse items */
- ih->data->id_control--; /* not the real id since it counts only the visible ones */
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ gtkTreeSelectNode(model, selection, &iterItem, -1);
+ }
+}
- /* StateID founded! */
- if(ih->data->id_control < 0)
- return iterItem;
+static void gtkTreeSelectRange(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem1, GtkTreeIter *iterItem2, int clear)
+{
+ int i;
+ int id1 = iupTreeFindNodeId(ih, iterItem1->user_data);
+ int id2 = iupTreeFindNodeId(ih, iterItem2->user_data);
+ GtkTreeIter iterItem;
- path = gtk_tree_model_get_path(model, &iterItem);
+ if (id1 > id2)
+ {
+ int tmp = id1;
+ id1 = id2;
+ id2 = tmp;
+ }
- /* Check whether we have child items and it is expanded (visible) */
- if(gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ if (i < id1 || i > id2)
{
- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
- iterChild = gtkTreeFindVisibleNodeFromId(ih, model, iterChild);
-
- /* StateID founded! */
- if(ih->data->id_control < 0)
- {
- gtk_tree_path_free(path);
- return iterChild;
- }
+ if (clear)
+ gtkTreeSelectNode(model, selection, &iterItem, 0);
}
-
- gtk_tree_path_free(path);
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterItem);
+ else
+ gtkTreeSelectNode(model, selection, &iterItem, 1);
}
-
- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
}
-static GtkTreeIter gtkTreeGetLastVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem)
+static int gtkTreeIsNodeVisible(Ihandle* ih, GtkTreeModel* model, InodeHandle* node_handle, InodeHandle* *nodeLastParent)
{
- GtkTreeIter iterChild, iterPrev = gtkTreeInvalidIter;
- GtkTreePath* path = gtk_tree_model_get_path(model, &iterItem);
-
- /* Check whether we have child items and it is expanded (visible) */
- if(gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
- {
- int hasItem = TRUE;
- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
+ GtkTreeIter iterItem, iterParent;
+ GtkTreePath* path;
+ int is_visible;
- while(hasItem)
- {
- iterPrev = iterChild;
+ gtkTreeIterInit(ih, &iterItem, node_handle);
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterChild);
- }
+ if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem) ||
+ iterParent.user_data == *nodeLastParent)
+ return 1;
- iterItem = gtkTreeGetLastVisibleNode(ih, model, iterPrev);
- }
+ path = gtk_tree_model_get_path(model, &iterParent);
+ is_visible = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
gtk_tree_path_free(path);
- return iterItem;
+ if (!is_visible)
+ return 0;
+
+ /* save last parent */
+ *nodeLastParent = iterParent.user_data;
+ return 1;
}
-static GtkTreeIter gtkTreeFindNodeID(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, GtkTreeIter iterNode)
+static void gtkTreeGetLastVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem)
{
- GtkTreeIter iterChild;
- int hasItem = TRUE;
+ int i;
+ InodeHandle* nodeLastParent = NULL;
- while(hasItem)
+ for (i = ih->data->node_count-1; i >= 0; i--)
{
- /* ID control to traverse items */
- ih->data->id_control++;
-
- /* StateID founded! */
- if (iterItem.user_data == iterNode.user_data)
- return iterItem;
-
- /* Check whether we have child items */
- if (gtk_tree_model_iter_has_child(model, &iterItem))
+ if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent))
{
- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
- iterChild = gtkTreeFindNodeID(ih, model, iterChild, iterNode);
-
- /* StateID founded! */
- if(iterChild.user_data)
- return iterChild;
+ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle);
+ return;
}
-
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterItem);
}
- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
+ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[0].node_handle); /* root is always visible */
}
-static int gtkTreeGetNodeId(Ihandle* ih, GtkTreeIter iterItem)
+static void gtkTreeGetNextVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int count)
{
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterRoot;
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
- ih->data->id_control = -1;
- iterItem = gtkTreeFindNodeID(ih, model, iterRoot, iterItem);
- if (iterItem.user_data)
- return ih->data->id_control;
- else
- return -1;
-}
+ int i, id;
+ InodeHandle* nodeLastParent = NULL;
-static GtkTreeIter gtkTreeFindUserData(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, void* userdata)
-{
- GtkTreeIter iterChild;
- int hasItem = TRUE;
- void* node_userdata;
+ id = iupTreeFindNodeId(ih, iterItem->user_data);
+ id += count;
- while(hasItem)
+ for (i = id; i < ih->data->node_count; i++)
{
- /* ID control to traverse items */
- ih->data->id_control++;
+ if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent))
+ {
+ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle);
+ return;
+ }
+ }
- gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &node_userdata, -1);
+ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[0].node_handle); /* root is always visible */
+}
- /* userdata founded! */
- if (node_userdata == userdata)
- return iterItem;
+static void gtkTreeGetPreviousVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int count)
+{
+ int i, id;
+ InodeHandle* nodeLastParent = NULL;
- /* Check whether we have child items */
- if (gtk_tree_model_iter_has_child(model, &iterItem))
- {
- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
- iterChild = gtkTreeFindUserData(ih, model, iterChild, userdata);
+ id = iupTreeFindNodeId(ih, iterItem->user_data);
+ id -= count;
- /* userdata founded! */
- if (iterChild.user_data)
- return iterChild;
+ for (i = id; i >= 0; i--)
+ {
+ if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent))
+ {
+ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle);
+ return;
}
-
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterItem);
}
- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
+ gtkTreeGetLastVisibleNode(ih, model, iterItem);
}
-static int gtkTreeGetUserDataId(Ihandle* ih, GtkTreeModel* model, void* userdata)
+static int gtkTreeFindNodeId(Ihandle* ih, GtkTreeIter* iterItem)
{
- GtkTreeIter iterRoot, iterItem;
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
- ih->data->id_control = -1;
- iterItem = gtkTreeFindUserData(ih, model, iterRoot, userdata);
- if (iterItem.user_data)
- return ih->data->id_control;
- else
- return -1;
+ return iupTreeFindNodeId(ih, iterItem->user_data);
}
-static void gtkTreeCallNodeRemovedRec(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, IFnis cb)
+static void gtkTreeCallNodeRemovedRec(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, IFns cb, int *id)
{
GtkTreeIter iterChild;
- int hasItem = TRUE;
- void* node_userdata;
+ int hasItem;
+ int old_id = *id;
+ /* Check whether we have child items */
+ /* remove from children first */
+ hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
while(hasItem)
{
- /* ID control to traverse items */
- ih->data->id_control++;
-
- gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &node_userdata, -1);
-
- cb(ih, ih->data->id_control, (char*)node_userdata);
-
- /* Check whether we have child items */
- if (gtk_tree_model_iter_has_child(model, &iterItem))
- {
- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
- gtkTreeCallNodeRemovedRec(ih, model, iterChild, cb);
- }
+ /* go recursive to children */
+ gtkTreeCallNodeRemovedRec(ih, model, &iterChild, cb, id);
/* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterItem);
+ hasItem = gtk_tree_model_iter_next(model, &iterChild);
}
+
+ /* actually do it for the node */
+ ih->data->node_count--;
+ (*id)++;
+
+ cb(ih, (char*)ih->data->node_cache[old_id].userdata);
}
static void gtkTreeCallNodeRemoved(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem)
{
- IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
+ int old_count = ih->data->node_count;
+ int id = iupTreeFindNodeId(ih, iterItem->user_data);
+ int old_id = id;
+
+ IFns cb = (IFns)IupGetCallback(ih, "NODEREMOVED_CB");
if (cb)
+ gtkTreeCallNodeRemovedRec(ih, model, iterItem, cb, &id);
+ else
{
- ih->data->id_control = gtkTreeGetNodeId(ih, *iterItem)-1;
- gtkTreeCallNodeRemovedRec(ih, model, *iterItem, cb);
+ int removed_count = iupdrvTreeTotalChildCount(ih, iterItem->user_data)+1;
+ ih->data->node_count -= removed_count;
}
+
+ iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count);
}
-static gboolean gtkTreeFindNodeFromID(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int *id)
+static void gtkTreeCallNodeRemovedAll(Ihandle* ih)
{
- GtkTreeIter iterChild;
- int hasItem = TRUE;
+ IFns cb = (IFns)IupGetCallback(ih, "NODEREMOVED_CB");
+ int i, old_count = ih->data->node_count;
- while(hasItem)
+ if (cb)
{
- /* ID control to traverse items */
- (*id)--;
-
- /* StateID founded! */
- if (*id < 0)
- return TRUE;
-
- /* Check whether we have child items */
- if (gtk_tree_model_iter_has_child(model, iterItem))
+ for (i = 0; i < ih->data->node_count; i++)
{
- gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
-
- if (gtkTreeFindNodeFromID(ih, model, &iterChild, id))
- {
- *iterItem = iterChild;
- return TRUE;
- }
+ cb(ih, (char*)ih->data->node_cache[i].userdata);
}
-
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, iterItem);
}
- return FALSE;
+ ih->data->node_count = 0;
+
+ iupTreeDelFromCache(ih, 0, old_count);
}
-static gboolean gtkTreeFindNodeFromString(Ihandle* ih, GtkTreeModel* model, const char* name_id, GtkTreeIter *iterItem)
+static gboolean gtkTreeFindNodeFromString(Ihandle* ih, const char* name_id, GtkTreeIter *iterItem)
{
- if (name_id[0])
- {
- int id;
- if (iupStrToInt(name_id, &id))
- {
- gtk_tree_model_get_iter_first(model, iterItem);
- return gtkTreeFindNodeFromID(ih, model, iterItem, &id);
- }
- }
- else
- {
- GtkTreePath* path = NULL;
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL);
- if (path)
- {
- gtk_tree_model_get_iter(model, iterItem, path);
- gtk_tree_path_free(path);
- return TRUE;
- }
- }
- return FALSE;
+ InodeHandle* node_handle = iupTreeGetNodeFromString(ih, name_id);
+ if (!node_handle)
+ return FALSE;
+
+ gtkTreeIterInit(ih, iterItem, node_handle);
+ return TRUE;
}
/*****************************************************************************/
/* MANIPULATING IMAGES */
/*****************************************************************************/
-static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, int mode)
+static void gtkTreeUpdateImages(Ihandle* ih, int mode)
{
- GtkTreeIter iterChild;
- int hasItem = TRUE;
- int kind;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+ int i, kind;
- while(hasItem)
+ for (i=0; i<ih->data->node_count; i++)
{
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+
gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
if (kind == ITREE_BRANCH)
@@ -480,14 +468,6 @@ static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter it
if (!has_image)
gtk_tree_store_set(GTK_TREE_STORE(model), &iterItem, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed, -1);
}
-
- if (gtk_tree_model_iter_has_child(model, &iterItem))
- {
-
- /* Recursively traverse child items */
- gtk_tree_model_iter_children(model, &iterChild, &iterItem);
- gtkTreeUpdateImages(ih, model, iterChild, mode);
- }
}
else
{
@@ -499,9 +479,6 @@ static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter it
gtk_tree_store_set(GTK_TREE_STORE(model), &iterItem, IUPGTK_TREE_IMAGE, ih->data->def_image_leaf, -1);
}
}
-
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterItem);
}
}
@@ -536,26 +513,49 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
GtkTreeIter iterPrev, iterNewItem, iterParent;
GtkTreePath* path;
GdkColor color = {0L,0,0,0};
- int kindPrev;
-
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterPrev))
- return;
+ int kindPrev = -1;
- gtk_tree_model_get(GTK_TREE_MODEL(store), &iterPrev, IUPGTK_TREE_KIND, &kindPrev, -1);
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterPrev))
+ {
+ /* check if the root was really specified */
+ int id = 0;
+ if (!iupStrToInt(name_id, &id) || id != -1)
+ return;
+ }
+ else
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iterPrev, IUPGTK_TREE_KIND, &kindPrev, -1);
- if (kindPrev == ITREE_BRANCH && add)
- gtk_tree_store_insert(store, &iterNewItem, &iterPrev, 0); /* iterPrev is parent of the new item (firstchild of it) */
+ if (kindPrev != -1)
+ {
+ /* Add the new node */
+ if (kindPrev == ITREE_BRANCH && add)
+ gtk_tree_store_insert(store, &iterNewItem, &iterPrev, 0); /* iterPrev is parent of the new item (firstchild of it) */
+ else
+ gtk_tree_store_insert_after(store, &iterNewItem, NULL, &iterPrev); /* iterPrev is sibling of the new item */
+ iupTreeAddToCache(ih, add, kindPrev, iterPrev.user_data, iterNewItem.user_data);
+ }
else
- gtk_tree_store_insert_after(store, &iterNewItem, NULL, &iterPrev); /* iterPrev is sibling of the new item */
+ {
+ gtk_tree_store_append(store, &iterNewItem, NULL); /* root node */
+ iupTreeAddToCache(ih, 0, 0, NULL, iterNewItem.user_data);
+
+ /* store the stamp for the tree */
+ ih->data->stamp = iterNewItem.stamp;
+ }
iupgtkGetColor(iupAttribGetStr(ih, "FGCOLOR"), &color);
+ if (!title)
+ title = "";
+
/* set the attributes of the new node */
gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_HAS_IMAGE, FALSE,
IUPGTK_TREE_HAS_IMAGE_EXPANDED, FALSE,
IUPGTK_TREE_TITLE, iupgtkStrConvertToUTF8(title),
IUPGTK_TREE_KIND, kind,
- IUPGTK_TREE_COLOR, &color, -1);
+ IUPGTK_TREE_COLOR, &color,
+ IUPGTK_TREE_SELECT, 0,
+ -1);
if (kind == ITREE_LEAF)
gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_IMAGE, ih->data->def_image_leaf, -1);
@@ -563,56 +563,113 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed,
IUPGTK_TREE_IMAGE_EXPANDED, ih->data->def_image_expanded, -1);
- if (kindPrev == ITREE_BRANCH && add)
- iterParent = iterPrev;
- else
- gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &iterParent, &iterNewItem);
+ if (kindPrev != -1)
+ {
+ if (kindPrev == ITREE_BRANCH && add)
+ iterParent = iterPrev;
+ else if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &iterParent, &iterNewItem))
+ return;
- /* If this is the first child of the parent, then handle the ADDEXPANDED attribute */
- if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iterParent) == 1)
+ /* If this is the first child of the parent, then handle the ADDEXPANDED attribute */
+ if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iterParent) == 1)
+ {
+ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterParent);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
+ if (ih->data->add_expanded)
+ gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), path, FALSE);
+ else
+ gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL);
+ gtk_tree_path_free(path);
+ }
+ }
+ else
{
- int depth;
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterParent);
- depth = gtk_tree_path_get_depth(path)-1;
- if (ih->data->add_expanded || depth==0) /* if this is the first child of the root, expand always */
+ if (ih->data->node_count == 1)
{
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB", "1");
- gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), path, FALSE);
+ /* MarkStart node */
+ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)iterNewItem.user_data);
+
+ /* Set the default VALUE */
+ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterNewItem);
+ gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE);
+ gtk_tree_path_free(path);
}
- else
- gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
- gtk_tree_path_free(path);
}
}
-static void gtkTreeAddRootNode(Ihandle* ih)
+
+/*****************************************************************************/
+/* AUXILIAR FUNCTIONS */
+/*****************************************************************************/
+
+
+static void gtkTreeChildRebuildCacheRec(Ihandle* ih, GtkTreeModel *model, GtkTreeIter *iterItem, int *id)
{
- GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
- GtkTreePath* path;
- GtkTreeIter iterRoot;
- GdkColor color = {0L,0,0,0};
+ GtkTreeIter iterChild;
+ int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
+ while(hasItem)
+ {
+ (*id)++;
+ ih->data->node_cache[*id].node_handle = iterChild.user_data;
- iupgtkGetColor(iupAttribGetStr(ih, "FGCOLOR"), &color);
+ /* go recursive to children */
+ gtkTreeChildRebuildCacheRec(ih, model, &iterChild, id);
+
+ /* Go to next sibling item */
+ hasItem = gtk_tree_model_iter_next(model, &iterChild);
+ }
+}
- gtk_tree_store_append(store, &iterRoot, NULL); /* root node */
- gtk_tree_store_set(store, &iterRoot, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed,
- IUPGTK_TREE_HAS_IMAGE, FALSE,
- IUPGTK_TREE_IMAGE_EXPANDED, ih->data->def_image_expanded,
- IUPGTK_TREE_HAS_IMAGE_EXPANDED, FALSE,
- IUPGTK_TREE_KIND, ITREE_BRANCH,
- IUPGTK_TREE_COLOR, &color, -1);
+static void gtkTreeRebuildNodeCache(Ihandle* ih, int id, GtkTreeIter iterItem)
+{
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ ih->data->node_cache[id].node_handle = iterItem.user_data;
+ gtkTreeChildRebuildCacheRec(ih, model, &iterItem, &id);
+}
+
+static void gtkTreeChildCountRec(GtkTreeModel *model, GtkTreeIter *iterItem, int *count)
+{
+ GtkTreeIter iterChild;
+ int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
+ while(hasItem)
+ {
+ (*count)++;
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterRoot);
- /* MarkStart node */
- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)path);
+ /* go recursive to children */
+ gtkTreeChildCountRec(model, &iterChild, count);
- /* Set the default VALUE */
- gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE);
+ /* Go to next sibling item */
+ hasItem = gtk_tree_model_iter_next(model, &iterChild);
+ }
+}
+
+int iupdrvTreeTotalChildCount(Ihandle* ih, InodeHandle* node_handle)
+{
+ int count = 0;
+ GtkTreeIter iterItem;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ gtkTreeIterInit(ih, &iterItem, node_handle);
+ gtkTreeChildCountRec(model, &iterItem, &count);
+ return count;
+}
+
+InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih)
+{
+ GtkTreePath* path = NULL;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL);
+ if (path)
+ {
+ GtkTreeIter iterItem;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ gtk_tree_model_get_iter(model, &iterItem, path);
+ gtk_tree_path_free(path);
+ return iterItem.user_data;
+ }
+
+ return NULL;
}
-/*****************************************************************************/
-/* AUXILIAR FUNCTIONS */
-/*****************************************************************************/
static void gtkTreeOpenCloseEvent(Ihandle* ih)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
@@ -620,7 +677,7 @@ static void gtkTreeOpenCloseEvent(Ihandle* ih)
GtkTreePath* path;
int kind;
- if (!gtkTreeFindNodeFromString(ih, model, "", &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, "", &iterItem))
return;
path = gtk_tree_model_get_path(model, &iterItem);
@@ -637,27 +694,22 @@ static void gtkTreeOpenCloseEvent(Ihandle* ih)
}
}
-static gboolean gtkTreeSelected_Foreach_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list)
+typedef struct _gtkTreeSelectMinMax
{
- GtkTreeRowReference *rowref;
-
- rowref = gtk_tree_row_reference_new(model, path);
- *rowref_list = g_list_append(*rowref_list, rowref);
+ Ihandle* ih;
+ int id1, id2;
+} gtkTreeSelectMinMax;
- (void)iter;
- return FALSE; /* do not stop walking the store, call us with next row */
-}
-
-static gboolean gtkTreeSelected_Iter_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list)
+static gboolean gtkTreeSelected_Foreach_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iterItem, gtkTreeSelectMinMax *minmax)
{
- GtkTreeRowReference *rowref;
- GtkTreeIter iterParent;
- if (!gtk_tree_model_iter_parent(model, &iterParent, iter)) /* the root node can't be deleted */
- return FALSE; /* do not stop walking the store, call us with next row */
-
- rowref = gtk_tree_row_reference_new(model, path);
- *rowref_list = g_list_append(*rowref_list, rowref);
+ int id = iupTreeFindNodeId(minmax->ih, iterItem->user_data);
+ if (id < minmax->id1)
+ minmax->id1 = id;
+ if (id > minmax->id2)
+ minmax->id2 = id;
+ (void)model;
+ (void)path;
return FALSE; /* do not stop walking the store, call us with next row */
}
@@ -672,45 +724,48 @@ static void gtkTreeCallMultiSelectionCb(Ihandle* ih)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterRoot;
- GList *rr_list = NULL;
- GList *node;
- int* id_rowItem;
- int count_selected_rows, i = 0;
+ GtkTreeIter iterItem;
+ int i = 0, countItems;
+ gtkTreeSelectMinMax minmax;
- gtk_tree_model_get_iter_first(model, &iterRoot);
+ minmax.ih = ih;
+ minmax.id1 = ih->data->node_count;
+ minmax.id2 = -1;
- gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Foreach_Func, &rr_list);
- count_selected_rows = g_list_length(rr_list);
- id_rowItem = malloc(sizeof(int) * count_selected_rows);
+ gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Foreach_Func, &minmax);
+ if (minmax.id2 == -1)
+ return;
- for(node = rr_list; node != NULL; node = node->next)
+ /* interactive selection of several nodes will NOT select hidden nodes,
+ so make sure that they are selected. */
+ for(i = minmax.id1; i <= minmax.id2; i++)
{
- GtkTreePath* path = gtk_tree_row_reference_get_path(node->data);
- if (path)
- {
- GtkTreeIter iterItem;
- gtk_tree_model_get_iter(model, &iterItem, path);
-
- id_rowItem[i] = gtkTreeGetNodeId(ih, iterItem);
- i++;
-
- gtk_tree_path_free(path);
- }
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ if (!gtkTreeIsNodeSelected(model, &iterItem))
+ gtkTreeSelectNodeRaw(model, &iterItem, 1);
}
- g_list_foreach(rr_list, (GFunc) gtk_tree_row_reference_free, NULL);
- g_list_free(rr_list);
+ /* if last selected item is a branch, then select its children */
+ iupTreeSelectLastCollapsedBranch(ih, &(minmax.id2));
+
+ countItems = minmax.id2-minmax.id1+1;
if (cbMulti)
- cbMulti(ih, id_rowItem, count_selected_rows);
- else
{
- for (i=0; i<count_selected_rows; i++)
- cbSelec(ih, id_rowItem[i], 1);
- }
+ int* id_rowItem = malloc(sizeof(int) * countItems);
+
+ for(i = 0; i < countItems; i++)
+ id_rowItem[i] = minmax.id1+i;
- free(id_rowItem);
+ cbMulti(ih, id_rowItem, countItems);
+
+ free(id_rowItem);
+ }
+ else if (cbSelec)
+ {
+ for (i=0; i<countItems; i++)
+ cbSelec(ih, minmax.id1+i, 1);
+ }
}
}
@@ -747,14 +802,22 @@ static int gtkTreeSetTopItemAttrib(Ihandle* ih, const char* value)
GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
GtkTreeIter iterItem;
GtkTreePath* path;
+ int kind;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), value, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, value, &iterItem))
return 0;
path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterItem);
- if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iterItem, IUPGTK_TREE_KIND, &kind, -1);
+ if (kind == ITREE_LEAF)
+ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
+ else
+ {
+ int expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
+ if (!expanded) gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
+ }
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE, 0, 0); /* scroll to visible */
@@ -788,34 +851,23 @@ static int gtkTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
if (iupStrBoolean(value))
gtk_tree_view_expand_all(GTK_TREE_VIEW(ih->handle));
else
- {
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterRoot;
- GtkTreePath* pathRoot;
-
gtk_tree_view_collapse_all(GTK_TREE_VIEW(ih->handle));
- /* The root node is always expanded */
- gtk_tree_model_get_iter_first(model, &iterRoot);
- pathRoot = gtk_tree_model_get_path(model, &iterRoot);
- gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), pathRoot, FALSE);
- gtk_tree_path_free(pathRoot);
- }
-
return 0;
}
static char* gtkTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
{
- char* depth;
+ char* str;
GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
- depth = iupStrGetMemory(10);
- sprintf(depth, "%d", gtk_tree_store_iter_depth(store, &iterItem));
- return depth;
+ str = iupStrGetMemory(10);
+ sprintf(str, "%d", gtk_tree_store_iter_depth(store, &iterItem));
+ return str;
}
static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
@@ -824,14 +876,14 @@ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
GtkTreeIter iterItemSrc, iterItemDst, iterNewItem;
GtkTreeIter iterParent, iterNextParent;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItemSrc))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItemSrc))
return 0;
- if (!gtkTreeFindNodeFromString(ih, model, value, &iterItemDst))
+ if (!gtkTreeFindNodeFromString(ih, value, &iterItemDst))
return 0;
/* If Drag item is an ancestor of Drop item then return */
@@ -843,12 +895,8 @@ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
iterParent = iterNextParent;
}
- /* Copying the node and its children to the new position */
- gtkTreeCopyNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 0); /* not a full copy, preserve user data */
-
- /* Deleting the node of its old position */
- /* do not delete the user data, we copy the references in CopyNode */
- gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItemSrc);
+ /* Move the node and its children to the new position */
+ gtkTreeCopyMoveNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 0);
return 0;
}
@@ -859,14 +907,14 @@ static int gtkTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
GtkTreeIter iterItemSrc, iterItemDst, iterNewItem;
GtkTreeIter iterParent, iterNextParent;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItemSrc))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItemSrc))
return 0;
- if (!gtkTreeFindNodeFromString(ih, model, value, &iterItemDst))
+ if (!gtkTreeFindNodeFromString(ih, value, &iterItemDst))
return 0;
/* If Drag item is an ancestor of Drop item then return */
@@ -878,8 +926,8 @@ static int gtkTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
iterParent = iterNextParent;
}
- /* Copying the node and its children to the new position */
- gtkTreeCopyNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 1);
+ /* Copy the node and its children to the new position */
+ gtkTreeCopyMoveNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 1);
return 0;
}
@@ -891,7 +939,7 @@ static char* gtkTreeGetColorAttrib(Ihandle* ih, const char* name_id)
GtkTreeIter iterItem;
GdkColor *color;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_COLOR, &color, -1);
@@ -912,7 +960,7 @@ static int gtkTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
GdkColor color;
unsigned char r, g, b;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
if (!iupStrToRGB(value, &r, &g, &b))
@@ -931,14 +979,14 @@ static char* gtkTreeGetParentAttrib(Ihandle* ih, const char* name_id)
GtkTreeIter iterParent;
char* str;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem))
return NULL;
str = iupStrGetMemory(10);
- sprintf(str, "%d", gtkTreeGetNodeId(ih, iterParent));
+ sprintf(str, "%d", gtkTreeFindNodeId(ih, &iterParent));
return str;
}
@@ -948,7 +996,7 @@ static char* gtkTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
GtkTreeIter iterItem;
char* str;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
str = iupStrGetMemory(10);
@@ -956,40 +1004,13 @@ static char* gtkTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
return str;
}
-static int gtkTreeCount(GtkTreeModel* model, GtkTreeIter iterBranch)
-{
- GtkTreeIter iterChild;
- int count = 0;
- int hasItem = gtk_tree_model_iter_children(model, &iterChild, &iterBranch); /* get the firstchild */
- count++;
- while(hasItem)
- {
- count += gtkTreeCount(model, iterChild);
-
- /* Go to next sibling item */
- hasItem = gtk_tree_model_iter_next(model, &iterChild);
- }
-
- return count;
-}
-
-static char* gtkTreeGetCountAttrib(Ihandle* ih)
-{
- GtkTreeIter iterRoot;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- char* str = iupStrGetMemory(10);
- gtk_tree_model_get_iter_first(model, &iterRoot);
- sprintf(str, "%d", gtkTreeCount(model, iterRoot));
- return str;
-}
-
static char* gtkTreeGetKindAttrib(Ihandle* ih, const char* name_id)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
int kind;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
@@ -1005,7 +1026,7 @@ static char* gtkTreeGetStateAttrib(Ihandle* ih, const char* name_id)
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
if (gtk_tree_model_iter_has_child(model, &iterItem))
@@ -1028,13 +1049,20 @@ static int gtkTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* v
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
GtkTreePath* path;
+ int kind;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
- path = gtk_tree_model_get_path(model, &iterItem);
- gtkTreeExpandItem(ih, path, iupStrEqualNoCase(value, "EXPANDED"));
- gtk_tree_path_free(path);
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
+ if (kind == ITREE_BRANCH)
+ {
+ path = gtk_tree_model_get_path(model, &iterItem);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
+ gtkTreeExpandItem(ih, path, iupStrEqualNoCase(value, "EXPANDED"));
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL);
+ gtk_tree_path_free(path);
+ }
return 0;
}
@@ -1050,7 +1078,7 @@ static char* gtkTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
return gtkTreeGetTitle(model, iterItem);
}
@@ -1059,8 +1087,10 @@ static int gtkTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v
{
GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
+ if (!value)
+ value = "";
gtk_tree_store_set(store, &iterItem, IUPGTK_TREE_TITLE, iupgtkStrConvertToUTF8(value), -1);
return 0;
}
@@ -1070,7 +1100,7 @@ static int gtkTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
PangoFontDescription* fontdesc = NULL;
GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
if (value)
fontdesc = iupgtkGetPangoFontDesc(value);
@@ -1083,49 +1113,12 @@ static char* gtkTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
PangoFontDescription* fontdesc;
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return NULL;
gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_FONT, &fontdesc, -1);
return pango_font_description_to_string(fontdesc);
}
-static char* gtkTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
-{
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- int id;
- char* str = (char*)(name_id+1); /* skip ':' */
- void* userdata = NULL;
- if (sscanf(str, "%p", &userdata)!=1)
- return NULL;
- id = gtkTreeGetUserDataId(ih, model, userdata);
- if (id == -1)
- return NULL;
- str = iupStrGetMemory(16);
- sprintf(str, "%d", id);
- return str;
-}
-
-static char* gtkTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
-{
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterItem;
- char* userdata;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
- return NULL;
- gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &userdata, -1);
- return userdata;
-}
-
-static int gtkTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
-{
- GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
- GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
- return 0;
- gtk_tree_store_set(store, &iterItem, IUPGTK_TREE_USERDATA, value, -1);
- return 0;
-}
-
static char* gtkTreeGetValueAttrib(Ihandle* ih)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
@@ -1140,67 +1133,117 @@ static char* gtkTreeGetValueAttrib(Ihandle* ih)
gtk_tree_path_free(path);
str = iupStrGetMemory(16);
- sprintf(str, "%d", gtkTreeGetNodeId(ih, iterItem));
+ sprintf(str, "%d", gtkTreeFindNodeId(ih, &iterItem));
return str;
}
- return "0"; /* default VALUE is root */
+ if (ih->data->node_count)
+ return "0"; /* default VALUE is root */
+ else
+ return "-1";
+}
+
+static char* gtkTreeGetMarkedNodesAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(ih->data->node_count+1);
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+ int i;
+
+ for (i=0; i<ih->data->node_count; i++)
+ {
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ if (gtkTreeIsNodeSelected(model, &iterItem))
+ str[i] = '+';
+ else
+ str[i] = '-';
+ }
+
+ str[ih->data->node_count] = 0;
+ return str;
+}
+
+static int gtkTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value)
+{
+ int count, i;
+ GtkTreeModel* model;
+ GtkTreeIter iterItem;
+ GtkTreeSelection* selection;
+
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE || !value)
+ return 0;
+
+ count = strlen(value);
+ if (count > ih->data->node_count)
+ count = ih->data->node_count;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+
+ for (i=0; i<count; i++)
+ {
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ if (value[i] == '+')
+ gtkTreeSelectNode(model, selection, &iterItem, 1);
+ else
+ gtkTreeSelectNode(model, selection, &iterItem, 0);
+ }
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+
+ return 0;
}
static int gtkTreeSetMarkAttrib(Ihandle* ih, const char* value)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterRoot;
if (ih->data->mark_mode==ITREE_MARK_SINGLE)
return 0;
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
if(iupStrEqualNoCase(value, "BLOCK"))
{
+ GtkTreeIter iterItem1, iterItem2;
GtkTreePath* pathFocus;
gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
- gtk_tree_selection_select_range(selection, (GtkTreePath*)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"), pathFocus);
+ gtk_tree_model_get_iter(model, &iterItem1, pathFocus);
gtk_tree_path_free(pathFocus);
+
+ gtkTreeIterInit(ih, &iterItem2, iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"));
+
+ gtkTreeSelectRange(ih, model, selection, &iterItem1, &iterItem2, 0);
}
else if(iupStrEqualNoCase(value, "CLEARALL"))
- gtk_tree_selection_unselect_all(selection);
+ gtkTreeSelectAll(ih, model, selection, 0);
else if(iupStrEqualNoCase(value, "MARKALL"))
- gtk_tree_selection_select_all(selection);
+ gtkTreeSelectAll(ih, model, selection, 1);
else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */
- gtkTreeInvertAllNodeMarking(ih, model, selection, &iterRoot);
+ gtkTreeInvertAllNodeMarking(ih, model, selection);
else if(iupStrEqualPartial(value, "INVERT"))
{
/* iupStrEqualPartial allows the use of "INVERTid" form */
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, &value[strlen("INVERT")], &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, &value[strlen("INVERT")], &iterItem))
return 0;
- if(gtk_tree_selection_iter_is_selected(selection, &iterItem))
- gtk_tree_selection_unselect_iter(selection, &iterItem);
- else
- gtk_tree_selection_select_iter(selection, &iterItem);
+ gtkTreeSelectNode(model, selection, &iterItem, -1); /* toggle */
}
else
{
- GtkTreePath *path1, *path2;
GtkTreeIter iterItem1, iterItem2;
char str1[50], str2[50];
if (iupStrToStrStr(value, str1, str2, '-')!=2)
return 0;
- if (!gtkTreeFindNodeFromString(ih, model, str1, &iterItem1))
+ if (!gtkTreeFindNodeFromString(ih, str1, &iterItem1))
return 0;
- if (!gtkTreeFindNodeFromString(ih, model, str2, &iterItem2))
+ if (!gtkTreeFindNodeFromString(ih, str2, &iterItem2))
return 0;
- path1 = gtk_tree_model_get_path(model, &iterItem1);
- path2 = gtk_tree_model_get_path(model, &iterItem2);
- gtk_tree_selection_select_range(selection, path1, path2);
- gtk_tree_path_free(path1);
- gtk_tree_path_free(path2);
+ gtkTreeSelectRange(ih, model, selection, &iterItem1, &iterItem2, 0);
}
return 1;
@@ -1210,148 +1253,112 @@ static int gtkTreeSetValueAttrib(Ihandle* ih, const char* value)
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterRoot, iterItem;
+ GtkTreeIter iterItem;
GtkTreePath* path;
+ int kind;
if (gtkTreeSetMarkAttrib(ih, value))
return 0;
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
- if (iupStrEqualNoCase(value, "ROOT"))
- iterItem = iterRoot;
+ if (iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST"))
+ gtk_tree_model_get_iter_first(model, &iterItem);
else if(iupStrEqualNoCase(value, "LAST"))
- iterItem = gtkTreeGetLastVisibleNode(ih, model, iterRoot);
+ gtkTreeGetLastVisibleNode(ih, model, &iterItem);
else if(iupStrEqualNoCase(value, "PGUP"))
{
- GtkTreeIter iterPrev;
-
GtkTreePath* pathFocus;
gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
- gtk_tree_model_get_iter(model, &iterPrev, pathFocus);
+ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
gtk_tree_path_free(pathFocus);
- ih->data->id_control = -1;
- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterPrev);
- ih->data->id_control -= 10; /* less 10 visible nodes */
-
- if(ih->data->id_control < 0)
- ih->data->id_control = 0; /* Begin of tree = Root id */
-
- iterItem = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
+ gtkTreeGetPreviousVisibleNode(ih, model, &iterItem, 10);
}
else if(iupStrEqualNoCase(value, "PGDN"))
{
- GtkTreeIter iterNext;
-
GtkTreePath* pathFocus;
gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
- gtk_tree_model_get_iter(model, &iterNext, pathFocus);
+ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
gtk_tree_path_free(pathFocus);
- ih->data->id_control = -1;
- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterNext);
- ih->data->id_control += 10; /* more 10 visible nodes */
-
- iterNext = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
-
- if (ih->data->id_control >= 0)
- iterNext = gtkTreeGetLastVisibleNode(ih, model, iterRoot);
-
- iterItem = iterNext;
+ gtkTreeGetNextVisibleNode(ih, model, &iterItem, 10);
}
else if(iupStrEqualNoCase(value, "NEXT"))
{
- GtkTreeIter iterNext;
-
GtkTreePath* pathFocus;
gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
- gtk_tree_model_get_iter(model, &iterNext, pathFocus);
+ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
gtk_tree_path_free(pathFocus);
- ih->data->id_control = -1;
- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterNext);
- ih->data->id_control++; /* more 1 visible node */
-
- iterNext = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
-
- if (ih->data->id_control >= 0)
- iterNext = gtkTreeGetLastVisibleNode(ih, model, iterRoot);
-
- iterItem = iterNext;
+ gtkTreeGetNextVisibleNode(ih, model, &iterItem, 1);
}
else if(iupStrEqualNoCase(value, "PREVIOUS"))
{
- GtkTreeIter iterPrev;
-
GtkTreePath* pathFocus;
gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
- gtk_tree_model_get_iter(model, &iterPrev, pathFocus);
+ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
gtk_tree_path_free(pathFocus);
- ih->data->id_control = -1;
- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterPrev);
- ih->data->id_control--; /* less 1 visible node */
-
- if (ih->data->id_control < 0)
- ih->data->id_control = 0;
-
- iterItem = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
- if (!iterItem.user_data)
- return 0;
+ gtkTreeGetPreviousVisibleNode(ih, model, &iterItem, 1);
}
else
{
- if (!gtkTreeFindNodeFromString(ih, model, value, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, value, &iterItem))
return 0;
}
/* select */
if (ih->data->mark_mode==ITREE_MARK_SINGLE)
{
- iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", "1");
- gtk_tree_selection_select_iter(selection, &iterItem);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ gtkTreeSelectNode(model, selection, &iterItem, 1);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
}
path = gtk_tree_model_get_path(model, &iterItem);
+
+ /* make it visible */
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
+ if (kind == ITREE_LEAF)
+ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
+ else
+ {
+ int expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
+ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
+ if (!expanded) gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
+ }
+
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE, 0, 0); /* scroll to visible */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE); /* set focus */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+
gtk_tree_path_free(path);
- iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", gtkTreeGetNodeId(ih, iterItem));
+ iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", gtkTreeFindNodeId(ih, &iterItem));
return 0;
}
static int gtkTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
{
- GtkTreePath *pathMarkStart, *pathMarkStartPrev;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
- pathMarkStart = gtk_tree_model_get_path(model, &iterItem);
-
- pathMarkStartPrev = (GtkTreePath*)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE");
- if (pathMarkStartPrev)
- gtk_tree_path_free(pathMarkStartPrev);
-
- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)pathMarkStart);
+ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)iterItem.user_data);
return 1;
}
static char* gtkTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
{
- GtkTreeSelection* selection;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeModel* model;
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
- if (gtk_tree_selection_iter_is_selected(selection, &iterItem))
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ if (gtkTreeIsNodeSelected(model, &iterItem))
return "YES";
else
return "NO";
@@ -1359,87 +1366,99 @@ static char* gtkTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
static int gtkTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
{
+ GtkTreeModel* model;
GtkTreeSelection* selection;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
- iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", "1");
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
if (iupStrBoolean(value))
- gtk_tree_selection_select_iter(selection, &iterItem);
+ gtkTreeSelectNode(model, selection, &iterItem, 1);
else
- gtk_tree_selection_unselect_iter(selection, &iterItem);
+ gtkTreeSelectNode(model, selection, &iterItem, 0);
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
return 0;
}
static int gtkTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
{
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
- if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */
+ if (iupStrEqualNoCase(value, "ALL"))
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- GtkTreeIter iterItem;
- GtkTreeIter iterParent;
+ gtkTreeCallNodeRemovedAll(ih);
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
- return 0;
+ /* deleting the reference node (and it's children) */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ gtk_tree_store_clear(GTK_TREE_STORE(model));
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ return 0;
+ }
+ if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference node */
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
- if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem)) /* the root node can't be deleted */
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
gtkTreeCallNodeRemoved(ih, model, &iterItem);
- /* deleting the specified node (and it's children) */
+ /* deleting the reference node (and it's children) */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
}
- else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
+ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */
{
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
GtkTreeIter iterItem, iterChild;
int hasChildren;
- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
hasChildren = gtk_tree_model_iter_children(model, &iterChild, &iterItem);
- /* deleting the selected node's children */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+
+ /* deleting the reference node children */
while(hasChildren)
{
gtkTreeCallNodeRemoved(ih, model, &iterChild);
hasChildren = gtk_tree_store_remove(GTK_TREE_STORE(model), &iterChild);
}
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
}
else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */
{
+ int i;
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
- GList *rr_list = NULL;
- GList *node;
+ GtkTreeIter iterItem;
- gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Iter_Func, &rr_list);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
- for(node = rr_list; node != NULL; node = node->next)
+ for(i = 1; i < ih->data->node_count; /* increment only if not removed */)
{
- GtkTreePath* path = gtk_tree_row_reference_get_path(node->data);
- if (path)
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ if (gtkTreeIsNodeSelected(model, &iterItem))
{
- GtkTreeIter iterItem;
- if (gtk_tree_model_get_iter(model, &iterItem, path))
- {
- gtkTreeCallNodeRemoved(ih, model, &iterItem);
- gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem);
- }
- gtk_tree_path_free(path);
+ gtkTreeCallNodeRemoved(ih, model, &iterItem);
+ gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem);
}
- gtk_tree_row_reference_free(node->data);
+ else
+ i++;
}
- g_list_free(rr_list);
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
}
return 0;
@@ -1450,36 +1469,11 @@ static int gtkTreeSetRenameAttrib(Ihandle* ih, const char* value)
if (ih->data->show_rename)
{
GtkTreePath* path;
- IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
GtkTreeViewColumn *focus_column;
-
gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, &focus_column);
-
- if (cbShowRename)
- {
- GtkTreeIter iterItem;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- gtk_tree_model_get_iter(model, &iterItem, path);
- cbShowRename(ih, gtkTreeGetNodeId(ih, iterItem));
- }
-
gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, focus_column, TRUE);
gtk_tree_path_free(path);
}
- else
- {
- IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
- if (cbRenameNode)
- {
- GtkTreePath* path;
- GtkTreeIter iterItem;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL);
- gtk_tree_model_get_iter(model, &iterItem, path);
- gtk_tree_path_free(path);
- cbRenameNode(ih, gtkTreeGetNodeId(ih, iterItem), gtkTreeGetTitle(model, iterItem));
- }
- }
(void)value;
return 0;
@@ -1491,7 +1485,7 @@ static int gtkTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const
GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
GdkPixbuf* pixExpand = iupImageGetImage(value, ih, 0);
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
gtk_tree_model_get(GTK_TREE_MODEL(store), &iterItem, IUPGTK_TREE_KIND, &kind, -1);
@@ -1514,7 +1508,7 @@ static int gtkTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
GdkPixbuf* pixImage = iupImageGetImage(value, ih, 0);
GtkTreeIter iterItem;
- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
return 0;
if (pixImage)
@@ -1539,42 +1533,30 @@ static int gtkTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
static int gtkTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
{
- GtkTreeIter iterRoot;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
ih->data->def_image_expanded = iupImageGetImage(value, ih, 0);
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
- /* Update all images, starting at root node */
- gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_EXPANDED);
+ /* Update all images */
+ gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED);
return 1;
}
static int gtkTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
{
- GtkTreeIter iterRoot;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0);
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
- /* Update all images, starting at root node */
- gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_COLLAPSED);
+ /* Update all images */
+ gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED);
return 1;
}
static int gtkTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
{
- GtkTreeIter iterRoot;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
ih->data->def_image_leaf = iupImageGetImage(value, ih, 0);
- gtk_tree_model_get_iter_first(model, &iterRoot);
-
- /* Update all images, starting at root node */
- gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_LEAF);
+ /* Update all images */
+ gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF);
return 1;
}
@@ -1655,6 +1637,7 @@ void iupdrvTreeUpdateMarkMode(Ihandle *ih)
if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && !ih->data->show_dragdrop)
{
#if GTK_CHECK_VERSION(2, 10, 0)
+ if (iupAttribGetInt(ih, "RUBBERBAND"))
gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(ih->handle), TRUE);
#endif
}
@@ -1704,6 +1687,19 @@ static void gtkTreeCellTextEditingStarted(GtkCellRenderer *cell, GtkCellEditable
PangoFontDescription* fontdesc = NULL;
GdkColor *color = NULL;
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ IFni cbShowRename;
+
+ gtk_tree_model_get_iter_from_string(model, &iterItem, path_string);
+
+ cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+ if (cbShowRename && cbShowRename(ih, gtkTreeFindNodeId(ih, &iterItem))==IUP_IGNORE)
+ {
+ /* TODO: non of these worked:
+ gtk_cell_renderer_stop_editing(cell, TRUE);
+ gtk_cell_editable_editing_done(editable); */
+ gtk_editable_set_editable(GTK_EDITABLE(editable), FALSE);
+ return;
+ }
value = iupAttribGetStr(ih, "RENAMECARET");
if (value)
@@ -1713,7 +1709,6 @@ static void gtkTreeCellTextEditingStarted(GtkCellRenderer *cell, GtkCellEditable
if (value)
gtkTreeSetRenameSelectionPos(editable, value);
- gtk_tree_model_get_iter_from_string(model, &iterItem, path_string);
gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_FONT, &fontdesc, -1);
if (fontdesc)
gtk_widget_modify_font(GTK_WIDGET(editable), fontdesc);
@@ -1732,7 +1727,7 @@ static void gtkTreeCellTextEdited(GtkCellRendererText *cell, gchar *path_string,
IFnis cbRename;
if (!new_text)
- return;
+ new_text = "";
model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
if (!gtk_tree_model_get_iter_from_string(model, &iterItem, path_string))
@@ -1741,7 +1736,7 @@ static void gtkTreeCellTextEdited(GtkCellRendererText *cell, gchar *path_string,
cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
if (cbRename)
{
- if (cbRename(ih, gtkTreeGetNodeId(ih, iterItem), iupgtkStrConvertFromUTF8(new_text)) == IUP_IGNORE)
+ if (cbRename(ih, gtkTreeFindNodeId(ih, &iterItem), iupgtkStrConvertFromUTF8(new_text)) == IUP_IGNORE)
return;
}
@@ -1766,8 +1761,8 @@ static int gtkTreeCallDragDropCb(Ihandle* ih, GtkTreeIter *iterDrag, GtkTreeIter
if (cbDragDrop)
{
- int drag_id = gtkTreeGetNodeId(ih, *iterDrag);
- int drop_id = gtkTreeGetNodeId(ih, *iterDrop);
+ int drag_id = gtkTreeFindNodeId(ih, iterDrag);
+ int drop_id = gtkTreeFindNodeId(ih, iterDrop);
return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
}
@@ -1804,22 +1799,17 @@ static void gtkTreeDragDataReceived(GtkWidget *widget, GdkDragContext *context,
{
GtkTreeIter iterNewItem;
- /* Copy the dragged item to the new position. */
- gtkTreeCopyNode(ih, model, &iterDrag, &iterDrop, &iterNewItem, is_ctrl);
-
- if (!is_ctrl)
- {
- /* do not delete the user data, we copy the references in CopyNode */
- gtk_tree_store_remove(GTK_TREE_STORE(model), &iterDrag);
- }
+ /* Copy or move the dragged item to the new position. */
+ gtkTreeCopyMoveNode(ih, model, &iterDrag, &iterDrop, &iterNewItem, is_ctrl);
/* set focus and selection */
+ if (iterNewItem.stamp)
{
GtkTreePath *pathNew;
GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
pathNew = gtk_tree_model_get_path(model, &iterNewItem);
- gtk_tree_selection_select_path(selection, pathNew);
+ gtkTreeSelectNode(model, selection, &iterNewItem, 1);
gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), pathNew, NULL, FALSE, 0, 0);
gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), pathNew, NULL, FALSE);
@@ -1927,10 +1917,24 @@ static void gtkTreeDragBegin(GtkWidget *widget, GdkDragContext *context, Ihandle
(void)widget;
}
+static gboolean gtkTreeSelectionFunc(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean selected, Ihandle* ih)
+{
+ GtkTreeIter iterItem;
+ gtk_tree_model_get_iter(model, &iterItem, path);
+ gtkTreeSelectNodeRaw(model, &iterItem, !selected);
+ (void)ih;
+ (void)selection;
+ return TRUE;
+}
+
static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih)
{
IFnii cbSelec;
int is_ctrl = 0;
+ (void)selection;
+
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_SELECTION_CB"))
+ return;
if (ih->data->mark_mode == ITREE_MARK_MULTIPLE)
{
@@ -1953,25 +1957,17 @@ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih)
if (cbSelec)
{
int curpos = -1, is_selected = 0;
+ GtkTreeIter iterFocus;
+ GtkTreePath* pathFocus;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- if (iupAttribGet(ih, "_IUP_IGNORE_SELECTION"))
- {
- iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", NULL);
- return;
- }
-
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+ if (pathFocus)
{
- GtkTreeIter iterFocus;
- GtkTreePath* pathFocus;
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
- if (pathFocus)
- {
- gtk_tree_model_get_iter(model, &iterFocus, pathFocus);
- gtk_tree_path_free(pathFocus);
- curpos = gtkTreeGetNodeId(ih, iterFocus);
- is_selected = gtk_tree_selection_iter_is_selected(selection, &iterFocus);
- }
+ gtk_tree_model_get_iter(model, &iterFocus, pathFocus);
+ gtk_tree_path_free(pathFocus);
+ curpos = gtkTreeFindNodeId(ih, &iterFocus);
+ is_selected = gtkTreeIsNodeSelected(model, &iterFocus);
}
if (curpos == -1)
@@ -1993,18 +1989,52 @@ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih)
}
}
+static void gtkTreeUpdateSelectionChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem)
+{
+ int expanded;
+ GtkTreeIter iterChild;
+ int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
+ while(hasItem)
+ {
+ if (gtkTreeIsNodeSelected(model, &iterChild))
+ gtk_tree_selection_select_iter(selection, &iterChild);
+
+ expanded = 0;
+ if (gtk_tree_model_iter_has_child(model, &iterChild))
+ {
+ GtkTreePath* path = gtk_tree_model_get_path(model, &iterChild);
+ expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
+ gtk_tree_path_free(path);
+ }
+
+ /* Recursive only if expanded */
+ if (expanded)
+ gtkTreeUpdateSelectionChildren(ih, model, selection, &iterChild);
+
+ /* Go to next sibling item */
+ hasItem = gtk_tree_model_iter_next(model, &iterChild);
+ }
+}
+
+static void gtkTreeRowExpanded(GtkTreeView* tree_view, GtkTreeIter *iterItem, GtkTreePath *path, Ihandle* ih)
+{
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view);
+ GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ gtkTreeUpdateSelectionChildren(ih, model, selection, iterItem);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ (void)path;
+}
+
static gboolean gtkTreeTestExpandRow(GtkTreeView* tree_view, GtkTreeIter *iterItem, GtkTreePath *path, Ihandle* ih)
{
IFni cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
if (cbBranchOpen)
{
- if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB"))
- {
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB", NULL);
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB"))
return FALSE;
- }
- if (cbBranchOpen(ih, gtkTreeGetNodeId(ih, *iterItem)) == IUP_IGNORE)
+ if (cbBranchOpen(ih, gtkTreeFindNodeId(ih, iterItem)) == IUP_IGNORE)
return TRUE; /* prevent the change */
}
@@ -2018,7 +2048,10 @@ static gboolean gtkTreeTestCollapseRow(GtkTreeView* tree_view, GtkTreeIter *iter
IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
if (cbBranchClose)
{
- if (cbBranchClose(ih, gtkTreeGetNodeId(ih, *iterItem)) == IUP_IGNORE)
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB"))
+ return FALSE;
+
+ if (cbBranchClose(ih, gtkTreeFindNodeId(ih, iterItem)) == IUP_IGNORE)
return TRUE;
}
@@ -2042,7 +2075,7 @@ static void gtkTreeRowActived(GtkTreeView* tree_view, GtkTreePath *path, GtkTree
/* just to leaf nodes */
if(gtk_tree_model_iter_has_child(model, &iterItem) == 0 && kind == ITREE_LEAF)
- cbExecuteLeaf(ih, gtkTreeGetNodeId(ih, iterItem));
+ cbExecuteLeaf(ih, gtkTreeFindNodeId(ih, &iterItem));
(void)column;
(void)tree_view;
@@ -2057,11 +2090,57 @@ static int gtkTreeConvertXYToPos(Ihandle* ih, int x, int y)
GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
gtk_tree_model_get_iter(model, &iterItem, path);
gtk_tree_path_free (path);
- return gtkTreeGetNodeId(ih, iterItem);
+ return gtkTreeFindNodeId(ih, &iterItem);
}
return -1;
}
+static Iarray* gtkTreeGetSelectedArrayId(Ihandle* ih)
+{
+ Iarray* selarray = iupArrayCreate(1, sizeof(int));
+ int i;
+ GtkTreeIter iterItem;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
+ if (gtkTreeIsNodeSelected(model, &iterItem))
+ {
+ int* id_hitem = (int*)iupArrayInc(selarray);
+ int j = iupArrayCount(selarray);
+ id_hitem[j-1] = i;
+ }
+ }
+
+ return selarray;
+}
+
+static void gtkTreeCallMultiUnSelectionCb(Ihandle* ih)
+{
+ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB");
+ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ if (cbSelec || cbMulti)
+ {
+ Iarray* markedArray = gtkTreeGetSelectedArrayId(ih);
+ int* id_hitem = (int*)iupArrayGetData(markedArray);
+ int i, count = iupArrayCount(markedArray);
+
+ if (count > 1)
+ {
+ if (cbMulti)
+ cbMulti(ih, id_hitem, iupArrayCount(markedArray));
+ else
+ {
+ for (i=0; i<count; i++)
+ cbSelec(ih, id_hitem[i], 0);
+ }
+ }
+
+ iupArrayDestroy(markedArray);
+ }
+}
+
static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Ihandle* ih)
{
if (iupgtkButtonEvent(treeview, evt, ih) == TRUE)
@@ -2097,6 +2176,18 @@ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Iha
gtk_tree_path_free(path);
}
}
+ else if (evt->type == GDK_BUTTON_PRESS && evt->button == 1) /* left single press */
+ {
+ iupAttribSetInt(ih, "_IUPTREE_DRAG_X", (int)evt->x);
+ iupAttribSetInt(ih, "_IUPTREE_DRAG_Y", (int)evt->y);
+
+ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE &&
+ !(evt->state & GDK_SHIFT_MASK) && !(evt->state & GDK_CONTROL_MASK))
+ {
+ gtkTreeCallMultiUnSelectionCb(ih);
+ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1");
+ }
+ }
else if (evt->type == GDK_BUTTON_RELEASE && evt->button == 1) /* left single release */
{
if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & GDK_SHIFT_MASK))
@@ -2109,16 +2200,7 @@ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Iha
iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "2");
}
}
- else if (evt->type == GDK_BUTTON_PRESS && evt->button == 1) /* left single press */
- {
- iupAttribSetInt(ih, "_IUPTREE_DRAG_X", (int)evt->x);
- iupAttribSetInt(ih, "_IUPTREE_DRAG_Y", (int)evt->y);
- if (ih->data->mark_mode==ITREE_MARK_MULTIPLE &&
- !(evt->state & GDK_SHIFT_MASK) && !(evt->state & GDK_CONTROL_MASK))
- iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1");
- }
-
return FALSE;
}
@@ -2159,29 +2241,14 @@ static void gtkTreeEnableDragDrop(Ihandle* ih)
{ "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
};
- if (iupAttribGetBoolean(ih, "AUTODRAGDROP"))
- {
- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW(ih->handle),
- GDK_BUTTON1_MASK,
- row_targets,
- G_N_ELEMENTS(row_targets),
- GDK_ACTION_MOVE|GDK_ACTION_COPY);
- gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW(ih->handle),
- row_targets,
- G_N_ELEMENTS(row_targets),
- GDK_ACTION_MOVE|GDK_ACTION_COPY);
- }
- else
- {
- gtk_drag_source_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
- gtk_drag_dest_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
+ gtk_drag_source_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
+ gtk_drag_dest_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
- g_signal_connect(G_OBJECT(ih->handle), "drag-begin", G_CALLBACK(gtkTreeDragBegin), ih);
- g_signal_connect(G_OBJECT(ih->handle), "drag-motion", G_CALLBACK(gtkTreeDragMotion), ih);
- g_signal_connect(G_OBJECT(ih->handle), "drag-leave", G_CALLBACK(gtkTreeDragLeave), NULL);
- g_signal_connect(G_OBJECT(ih->handle), "drag-drop", G_CALLBACK(gtkTreeDragDrop), ih);
- g_signal_connect(G_OBJECT(ih->handle), "drag-data-received", G_CALLBACK(gtkTreeDragDataReceived), ih);
- }
+ g_signal_connect(G_OBJECT(ih->handle), "drag-begin", G_CALLBACK(gtkTreeDragBegin), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "drag-motion", G_CALLBACK(gtkTreeDragMotion), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "drag-leave", G_CALLBACK(gtkTreeDragLeave), NULL);
+ g_signal_connect(G_OBJECT(ih->handle), "drag-drop", G_CALLBACK(gtkTreeDragDrop), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "drag-data-received", G_CALLBACK(gtkTreeDragDataReceived), ih);
}
/*****************************************************************************/
@@ -2194,8 +2261,16 @@ static int gtkTreeMapMethod(Ihandle* ih)
GtkTreeSelection* selection;
GtkTreeViewColumn *column;
- store = gtk_tree_store_new(9, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN,
- G_TYPE_STRING, G_TYPE_INT, GDK_TYPE_COLOR, PANGO_TYPE_FONT_DESCRIPTION, G_TYPE_POINTER);
+ store = gtk_tree_store_new(IUPGTK_TREE_LAST_DATA,
+ GDK_TYPE_PIXBUF, /* IUPGTK_TREE_IMAGE */
+ G_TYPE_BOOLEAN, /* IUPGTK_TREE_HAS_IMAGE */
+ GDK_TYPE_PIXBUF, /* IUPGTK_TREE_IMAGE_EXPANDED */
+ G_TYPE_BOOLEAN, /* IUPGTK_TREE_HAS_IMAGE_EXPANDED */
+ G_TYPE_STRING, /* IUPGTK_TREE_TITLE */
+ G_TYPE_INT, /* IUPGTK_TREE_KIND */
+ GDK_TYPE_COLOR, /* IUPGTK_TREE_COLOR */
+ PANGO_TYPE_FONT_DESCRIPTION, /* IUPGTK_TREE_FONT */
+ G_TYPE_BOOLEAN); /* IUPGTK_TREE_SELECT */
ih->handle = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
@@ -2262,8 +2337,9 @@ static int gtkTreeMapMethod(Ihandle* ih)
gtk_scrolled_window_set_policy(scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
-
gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+ gtk_tree_selection_set_select_function(selection, (GtkTreeSelectionFunc)gtkTreeSelectionFunc, ih, NULL);
+
gtk_tree_view_set_reorderable(GTK_TREE_VIEW(ih->handle), FALSE);
/* callbacks */
@@ -2279,6 +2355,7 @@ static int gtkTreeMapMethod(Ihandle* ih)
g_signal_connect(G_OBJECT(ih->handle), "show-help", G_CALLBACK(iupgtkShowHelp), ih);
g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event",G_CALLBACK(iupgtkMotionNotifyEvent), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "row-expanded", G_CALLBACK(gtkTreeRowExpanded), ih);
g_signal_connect(G_OBJECT(ih->handle), "test-expand-row", G_CALLBACK(gtkTreeTestExpandRow), ih);
g_signal_connect(G_OBJECT(ih->handle), "test-collapse-row", G_CALLBACK(gtkTreeTestCollapseRow), ih);
g_signal_connect(G_OBJECT(ih->handle), "row-activated", G_CALLBACK(gtkTreeRowActived), ih);
@@ -2301,7 +2378,8 @@ static int gtkTreeMapMethod(Ihandle* ih)
ih->data->def_image_collapsed = iupImageGetImage("IMGCOLLAPSED", ih, 0);
ih->data->def_image_expanded = iupImageGetImage("IMGEXPANDED", ih, 0);
- gtkTreeAddRootNode(ih);
+ if (iupAttribGetInt(ih, "ADDROOT"))
+ iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0);
/* configure for DRAG&DROP of files */
if (IupGetCallback(ih, "DROPFILES_CB"))
@@ -2309,13 +2387,23 @@ static int gtkTreeMapMethod(Ihandle* ih)
IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)gtkTreeConvertXYToPos);
+ iupdrvTreeUpdateMarkMode(ih);
+
return IUP_NOERROR;
}
+static void gtkTreeUnMapMethod(Ihandle* ih)
+{
+ ih->data->node_count = 0;
+
+ iupdrvBaseUnMapMethod(ih);
+}
+
void iupdrvTreeInitClass(Iclass* ic)
{
/* Driver Dependent Class functions */
ic->Map = gtkTreeMapMethod;
+ ic->UnMap = gtkTreeUnMapMethod;
/* Visual */
iupClassRegisterAttribute(ic, "BGCOLOR", NULL, gtkTreeSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT);
@@ -2324,7 +2412,6 @@ void iupdrvTreeInitClass(Iclass* ic)
/* IupTree Attributes - GENERAL */
iupClassRegisterAttribute(ic, "EXPANDALL", NULL, gtkTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "INDENTATION", gtkTreeGetIndentationAttrib, gtkTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
- iupClassRegisterAttribute(ic, "COUNT", gtkTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "DRAGDROP", NULL, iupgtkSetDragDropAttrib, NULL, NULL, IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, gtkTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
iupClassRegisterAttribute(ic, "TOPITEM", NULL, gtkTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
@@ -2345,7 +2432,6 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttributeId(ic, "COLOR", gtkTreeGetColorAttrib, gtkTreeSetColorAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "NAME", gtkTreeGetTitleAttrib, gtkTreeSetTitleAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TITLE", gtkTreeGetTitleAttrib, gtkTreeSetTitleAttrib, IUPAF_NO_INHERIT);
- iupClassRegisterAttributeId(ic, "USERDATA", gtkTreeGetUserDataAttrib, gtkTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "CHILDCOUNT", gtkTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TITLEFONT", gtkTreeGetTitleFontAttrib, gtkTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
@@ -2355,6 +2441,7 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttribute (ic, "MARK", NULL, gtkTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "STARTING", NULL, gtkTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "MARKSTART", NULL, gtkTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKEDNODES", gtkTreeGetMarkedNodesAttrib, gtkTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "VALUE", gtkTreeGetValueAttrib, gtkTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
@@ -2363,7 +2450,7 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "RENAME", NULL, gtkTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "MOVENODE", NULL, gtkTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "COPYNODE", NULL, gtkTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
- iupClassRegisterAttributeId(ic, "FINDUSERDATA", gtkTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
- iupClassRegisterAttribute (ic, "AUTODRAGDROP", NULL, NULL, NULL, NULL, IUPAF_DEFAULT);
+ /* IupTree Attributes - GTK Only */
+ iupClassRegisterAttribute (ic, "RUBBERBAND", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
}
diff --git a/iup/src/gtk/iupmac_help.c b/iup/src/gtk/iupmac_help.c
new file mode 100644
index 0000000..fa8d0af
--- /dev/null
+++ b/iup/src/gtk/iupmac_help.c
@@ -0,0 +1,46 @@
+/** \file
+ * \brief MAC Driver IupHelp
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "iup.h"
+
+#include "iup_str.h"
+
+int IupHelp(const char *url)
+{
+ char *cmd;
+ int ret;
+ char *browser = getenv("IUP_HELPAPP");
+ if (!browser)
+ browser = IupGetGlobal("HELPAPP");
+
+ if (!browser)
+ {
+ char* system = IupGetGlobal("SYSTEM");
+ if (iupStrEqualNoCase(system, "Snow Leopard") ||
+ iupStrEqualNoCase(system, "Leopard") ||
+ iupStrEqualNoCase(system, "Tiger") ||
+ iupStrEqualNoCase(system, "Panther"))
+ browser = "safari";
+ else if (iupStrEqualNoCase(system, "Jaguar") ||
+ iupStrEqualNoCase(system, "Puma") ||
+ iupStrEqualNoCase(system, "Cheetah"))
+ browser = "iexplore";
+ else /* MacOS */
+ browser = "netscape";
+ }
+
+ cmd = (char*)malloc(sizeof(char)*(strlen(url)+strlen(browser)+3));
+ sprintf(cmd, "open -a %s %s &", browser, url);
+ ret = system(cmd);
+ free(cmd);
+ if (ret == -1)
+ return -1;
+ return 1;
+}
diff --git a/iup/src/gtk/iupmac_info.c b/iup/src/gtk/iupmac_info.c
new file mode 100644
index 0000000..a040bad
--- /dev/null
+++ b/iup/src/gtk/iupmac_info.c
@@ -0,0 +1,358 @@
+/** \file
+ * \brief MAC OS System Information
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* This module should depend only on IUP core headers and
+ Mac OS Carbon system headers. */
+
+#include <Carbon/Carbon.h>
+
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <gtk/gtk.h>
+
+#include "iup.h"
+
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_drvinfo.h"
+
+#define IUP_MAC_ERROR -1
+
+/******************************************
+ ** These are NOT working as expected. So we kept the posix versions. ***
+
+static void iupMacStrToUniChar(const char* buffer, UniChar* outBuf, long length, long* outLen)
+{
+ CFStringRef stringRef = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+
+ CFStringGetCharacters (stringRef, CFRangeMake(0, CFStringGetLength(stringRef)), outBuf);
+ *outLen = (long) CFStringGetLength (stringRef);
+
+ CFRelease(stringRef);
+}
+
+int iupdrvMakeDirectory(const char* name)
+{
+ FSRef refParent, refNew;
+ UniChar nameDir;
+ long lenDir;
+
+ if(FSFindFolder(kUserDomain, kCurrentUserFolderType, kDontCreateFolder, &refParent) != noErr)
+ return 0;
+
+ iupMacStrToUniChar(name, &nameDir, strlen(name), &lenDir);
+
+ if(FSMakeFSRefUnicode(&refParent, lenDir, &nameDir, kTextEncodingUnknown, &refNew) != fnfErr) // fnfErr => Directory does not exists
+ return 0;
+
+ if(FSCreateDirectoryUnicode(&refParent, lenDir, &nameDir, kFSCatInfoNone, NULL, &refNew, NULL, NULL) != noErr)
+ return 0;
+
+ return 1;
+}
+
+char* iupdrvGetCurrentDirectory(void)
+{
+ FSRef refDir;
+ FSVolumeRefNum vRefNum;
+ long dirID;
+ size_t size = 256;
+ char *buffer = (char *)malloc(size);
+
+ if(HGetVol(NULL, &vRefNum, &dirID) != noErr) // Deprecated in Mac OS X v10.4
+ return 0;
+
+ if(FSMakeFSRef(vRefNum, dirID, NULL, &refDir) != noErr) // Deprecated in Mac OS X v10.5
+ return 0;
+
+ FSRefMakePath (&refDir, (UInt8*)buffer, size);
+
+ return buffer;
+}
+
+int iupdrvSetCurrentDirectory(const char* dir)
+{
+ FSRef refDir;
+ FSCatalogInfo catalogInfo;
+ int isDirectory;
+
+ if(FSPathMakeRef((const UInt8*)dir, &refDir, &isDirectory) != noErr)
+ return 0;
+
+ if (!isDirectory)
+ return 0;
+
+ if(FSGetCatalogInfo(refDir, kFSCatInfoVolume + kFSCatInfoNodeID, &catalogInfo, NULL, NULL, NULL) != noErr)
+ return 0;
+
+ if(HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID) != noErr) // Deprecated in Mac OS X v10.4
+ return 0;
+
+ return 1;
+}
+
+char* iupdrvGetCurrentDirectory(void)
+{
+ char* path = iupStrGetMemory(256);
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef curDir = CFBundleCopyBundleURL(mainBundle);
+ CFStringRef cfStringRef = CFURLCopyFileSystemPath(curDir, kCFURLPOSIXPathStyle);
+
+ CFStringGetCString(cfStringRef, path, 256, kCFStringEncodingUTF8);
+
+ return path;
+}
+*********************************************/
+
+int iupdrvMakeDirectory(const char* name)
+{
+ mode_t oldmask = umask((mode_t)0);
+ int fail = mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+ S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ umask (oldmask);
+ if (fail)
+ return 0;
+ return 1;
+}
+
+static int iMacIsFolder(const char* name)
+{
+ FSRef refName;
+ Boolean isFolder;
+
+ if(FSPathMakeRef((const UInt8*)name, &refName, &isFolder) != noErr)
+ return IUP_MAC_ERROR;
+
+ return isFolder;
+}
+
+int iupdrvIsFile(const char* name)
+{
+ int isDir = iMacIsFolder(name);
+
+ if((isDir != IUP_MAC_ERROR) && !isDir)
+ return 1;
+
+ return 0;
+}
+
+int iupdrvIsDirectory(const char* name)
+{
+ int isDir = iMacIsFolder(name);
+
+ if((isDir != IUP_MAC_ERROR) && isDir)
+ return 1;
+
+ return 0;
+}
+
+char* iupdrvGetCurrentDirectory(void)
+{
+ size_t size = 256;
+ char *buffer = (char *)malloc(size);
+
+ for (;;)
+ {
+ if (getcwd(buffer, size) != NULL)
+ return buffer;
+
+ if (errno != ERANGE)
+ {
+ free(buffer);
+ return NULL;
+ }
+
+ size += size;
+ buffer = (char *)realloc(buffer, size);
+ }
+
+ return NULL;
+}
+
+int iupdrvSetCurrentDirectory(const char* dir)
+{
+ return chdir(dir) == 0? 1: 0;
+}
+
+int iupdrvGetWindowDecor(void* wnd, int *border, int *caption)
+{
+ Rect rect;
+ CGRect cg;
+ int minX, minY;
+
+ CGDirectDisplayID mainDisplayID = CGMainDisplayID();
+ GDHandle hGDev;
+ DMGetGDeviceByDisplayID((DisplayIDType)mainDisplayID, &hGDev, false);
+
+ GetAvailableWindowPositioningBounds(hGDev, &rect);
+
+ cg = CGRectMake(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+
+ minX = (int)CGRectGetMinX(cg);
+ minY = (int)CGRectGetMinY(cg);
+
+ if (minX >= 0 && minY >= 0 && (minY >= minX))
+ {
+ *border = minX;
+ *caption = minY - *border;
+
+ return 1;
+ }
+
+ *border = 0;
+ *caption = 0;
+
+ return 0;
+}
+
+void iupdrvGetScreenSize(int *width, int *height)
+{
+ int w_size = CGDisplayPixelsWide(kCGDirectMainDisplay);
+ int h_size = CGDisplayPixelsHigh(kCGDirectMainDisplay);
+
+ *width = w_size;
+ *height = h_size;
+}
+
+void iupdrvGetFullSize(int *width, int *height)
+{
+ CGRect rect;
+
+ rect = CGDisplayBounds(kCGDirectMainDisplay);
+
+ *width = (int)CGRectGetWidth(rect);
+ *height = (int)CGRectGetHeight(rect);
+}
+
+int iupdrvGetScreenDepth(void)
+{
+ return CGDisplayBitsPerPixel(kCGDirectMainDisplay); /* Deprecated in Mac OS X v10.6 */
+}
+
+void iupdrvGetCursorPos(int *x, int *y)
+{
+ Point pnt;
+ CGPoint point;
+
+ GetMouse(&pnt);
+ point = CGPointMake(pnt.h, pnt.v);
+
+ *x = (int)point.x;
+ *y = (int)point.y;
+}
+
+void iupdrvGetKeyState(char* key)
+{
+ if (GetCurrentEventKeyModifiers() & shiftKey)
+ key[0] = 'S';
+ else
+ key[0] = ' ';
+
+ if (GetCurrentEventKeyModifiers() & controlKey)
+ key[1] = 'C';
+ else
+ key[1] = ' ';
+
+ if (GetCurrentEventKeyModifiers() & optionKey)
+ key[2] = 'A';
+ else
+ key[2] = ' ';
+
+ if (GetCurrentEventKeyModifiers() & cmdKey)
+ key[3] = 'Y';
+ else
+ key[3] = ' ';
+
+ key[4] = 0;
+}
+
+char *iupdrvGetSystemName(void)
+{
+ long systemVersion;
+
+ if (Gestalt(gestaltSystemVersion, &systemVersion) == noErr)
+ {
+ if (systemVersion >= 0x1060)
+ return "Snow Leopard";
+ else if (systemVersion >= 0x1050)
+ return "Leopard";
+ else if (systemVersion >= 0x1040)
+ return "Tiger";
+ else if (systemVersion >= 0x1030)
+ return "Panther";
+ else if (systemVersion >= 0x1020)
+ return "Jaguar";
+ else if (systemVersion >= 0x1010)
+ return "Puma";
+ else if (systemVersion >= 0x1010)
+ return "Cheetah";
+ }
+
+ return "MacOS";
+}
+
+char *iupdrvGetSystemVersion(void)
+{
+ char* str = iupStrGetMemory(70);
+ long systemVersion, versionMajor, versionMinor, versionBugFix, systemArchitecture;
+
+ if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr)
+ {
+ printf("Unable to obtain system version\n");
+ return NULL;
+ }
+
+ if (systemVersion < 0x1040)
+ {
+ /* Major, Minor, Bug fix */
+ sprintf(str, "%ld.%ld.%ld", ((systemVersion & 0xF000) >> 12) * 10 + ((systemVersion & 0x0F00) >> 8),
+ ((systemVersion & 0x00F0) >> 4), (systemVersion & 0x000F));
+ }
+ else /* MAC_OS_X_VERSION_10_4 or later */
+ {
+ Gestalt(gestaltSystemVersionMajor, &versionMajor);
+ Gestalt(gestaltSystemVersionMinor, &versionMinor);
+ Gestalt(gestaltSystemVersionBugFix, &versionBugFix);
+
+ sprintf(str, "%ld.%ld.%ld", versionMajor, versionMinor, versionBugFix);
+ }
+
+ if(Gestalt(gestaltSysArchitecture, &systemArchitecture) == noErr)
+ {
+ if (systemArchitecture == gestalt68k)
+ sprintf(str, "%s %s", str, "(Motorola 68k)");
+ else if (systemArchitecture == gestaltPowerPC)
+ sprintf(str, "%s %s", str, "(Power PC)");
+ else /* gestaltIntel */
+ sprintf(str, "%s %s", str, "(Intel)");
+ }
+
+ return str;
+}
+
+char *iupdrvGetComputerName(void)
+{
+ char* str = iupStrGetMemory(50);
+ CFStringRef computerName = CSCopyMachineName();
+ CFStringGetCString(computerName, str, 50, kCFStringEncodingUTF8);
+ return str;
+}
+
+char *iupdrvGetUserName(void)
+{
+ char* str = iupStrGetMemory(50);
+ CFStringRef userName = CSCopyUserName(TRUE); /* TRUE = login name FALSE = user name */
+ CFStringGetCString(userName, str, 50, kCFStringEncodingUTF8);
+ return str;
+}