diff options
Diffstat (limited to 'iup/src/gtk')
-rwxr-xr-x | iup/src/gtk/iupgtk_button.c | 10 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_canvas.c | 17 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_common.c | 59 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_dialog.c | 65 | ||||
-rw-r--r-- | iup/src/gtk/iupgtk_draw.c | 161 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_drv.h | 4 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_filedlg.c | 63 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_font.c | 4 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_fontdlg.c | 7 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_frame.c | 22 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_key.c | 26 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_label.c | 4 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_list.c | 29 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_loop.c | 7 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_menu.c | 21 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_open.c | 47 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_tabs.c | 50 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_text.c | 40 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_toggle.c | 4 | ||||
-rwxr-xr-x | iup/src/gtk/iupgtk_tree.c | 1533 | ||||
-rw-r--r-- | iup/src/gtk/iupmac_help.c | 46 | ||||
-rw-r--r-- | iup/src/gtk/iupmac_info.c | 358 |
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; +} |