summaryrefslogtreecommitdiff
path: root/iup/src
diff options
context:
space:
mode:
Diffstat (limited to 'iup/src')
-rwxr-xr-xiup/src/Makefile11
-rwxr-xr-xiup/src/config.mak108
-rwxr-xr-xiup/src/gtk/iupgtk_button.c10
-rwxr-xr-xiup/src/gtk/iupgtk_canvas.c17
-rwxr-xr-xiup/src/gtk/iupgtk_common.c59
-rwxr-xr-xiup/src/gtk/iupgtk_dialog.c65
-rw-r--r--iup/src/gtk/iupgtk_draw.c161
-rwxr-xr-xiup/src/gtk/iupgtk_drv.h4
-rwxr-xr-xiup/src/gtk/iupgtk_filedlg.c63
-rwxr-xr-xiup/src/gtk/iupgtk_font.c4
-rwxr-xr-xiup/src/gtk/iupgtk_fontdlg.c7
-rwxr-xr-xiup/src/gtk/iupgtk_frame.c22
-rwxr-xr-xiup/src/gtk/iupgtk_key.c26
-rwxr-xr-xiup/src/gtk/iupgtk_label.c4
-rwxr-xr-xiup/src/gtk/iupgtk_list.c29
-rwxr-xr-xiup/src/gtk/iupgtk_loop.c7
-rwxr-xr-xiup/src/gtk/iupgtk_menu.c21
-rwxr-xr-xiup/src/gtk/iupgtk_open.c47
-rwxr-xr-xiup/src/gtk/iupgtk_tabs.c50
-rwxr-xr-xiup/src/gtk/iupgtk_text.c40
-rwxr-xr-xiup/src/gtk/iupgtk_toggle.c4
-rwxr-xr-xiup/src/gtk/iupgtk_tree.c1533
-rw-r--r--iup/src/gtk/iupmac_help.c46
-rw-r--r--iup/src/gtk/iupmac_info.c358
-rwxr-xr-xiup/src/iup.c8
-rwxr-xr-xiup/src/iup.def23
-rwxr-xr-xiup/src/iup_attrib.c73
-rwxr-xr-xiup/src/iup_attrib.h13
-rwxr-xr-xiup/src/iup_box.c8
-rwxr-xr-xiup/src/iup_button.c3
-rwxr-xr-xiup/src/iup_canvas.c4
-rwxr-xr-xiup/src/iup_classattrib.c11
-rwxr-xr-xiup/src/iup_classbase.c13
-rwxr-xr-xiup/src/iup_dialog.c17
-rw-r--r--iup/src/iup_draw.h98
-rwxr-xr-xiup/src/iup_drv.h4
-rwxr-xr-xiup/src/iup_focus.c27
-rwxr-xr-xiup/src/iup_focus.h1
-rwxr-xr-xiup/src/iup_getparam.c97
-rwxr-xr-xiup/src/iup_globalattrib.c6
-rwxr-xr-xiup/src/iup_hbox.c7
-rwxr-xr-xiup/src/iup_key.h20
-rwxr-xr-xiup/src/iup_layout.c23
-rwxr-xr-xiup/src/iup_layout.h2
-rwxr-xr-xiup/src/iup_ledlex.c15
-rwxr-xr-xiup/src/iup_list.c59
-rwxr-xr-xiup/src/iup_list.h1
-rwxr-xr-xiup/src/iup_names.c134
-rwxr-xr-xiup/src/iup_names.h2
-rwxr-xr-xiup/src/iup_object.c11
-rwxr-xr-xiup/src/iup_object.h1
-rwxr-xr-xiup/src/iup_open.c4
-rwxr-xr-xiup/src/iup_register.c1
-rwxr-xr-xiup/src/iup_sbox.c1
-rwxr-xr-xiup/src/iup_show.c46
-rwxr-xr-xiup/src/iup_spin.c9
-rw-r--r--iup/src/iup_split.c780
-rwxr-xr-xiup/src/iup_stdcontrols.h1
-rwxr-xr-xiup/src/iup_str.c24
-rwxr-xr-xiup/src/iup_table.c100
-rwxr-xr-xiup/src/iup_table.h18
-rwxr-xr-xiup/src/iup_tabs.c19
-rwxr-xr-xiup/src/iup_tabs.h1
-rwxr-xr-xiup/src/iup_tree.c397
-rwxr-xr-xiup/src/iup_tree.h36
-rwxr-xr-xiup/src/iup_vbox.c7
-rwxr-xr-xiup/src/iup_zbox.c6
-rwxr-xr-xiup/src/make_uname2
-rwxr-xr-xiup/src/mot/iupmot_button.c44
-rwxr-xr-xiup/src/mot/iupmot_canvas.c48
-rwxr-xr-xiup/src/mot/iupmot_common.c19
-rwxr-xr-xiup/src/mot/iupmot_dialog.c62
-rw-r--r--iup/src/mot/iupmot_draw.c188
-rwxr-xr-xiup/src/mot/iupmot_drv.h2
-rwxr-xr-xiup/src/mot/iupmot_filedlg.c104
-rwxr-xr-xiup/src/mot/iupmot_font.c14
-rwxr-xr-xiup/src/mot/iupmot_frame.c58
-rwxr-xr-xiup/src/mot/iupmot_key.c20
-rwxr-xr-xiup/src/mot/iupmot_label.c40
-rwxr-xr-xiup/src/mot/iupmot_list.c105
-rwxr-xr-xiup/src/mot/iupmot_loop.c15
-rwxr-xr-xiup/src/mot/iupmot_menu.c26
-rwxr-xr-xiup/src/mot/iupmot_progressbar.c30
-rwxr-xr-xiup/src/mot/iupmot_tabs.c73
-rwxr-xr-xiup/src/mot/iupmot_text.c108
-rwxr-xr-xiup/src/mot/iupmot_toggle.c72
-rwxr-xr-xiup/src/mot/iupmot_tree.c1636
-rwxr-xr-xiup/src/mot/iupmot_val.c42
-rwxr-xr-xiup/src/mot/iupunix_info.c2
-rwxr-xr-xiup/src/win/iupwin_button.c62
-rwxr-xr-xiup/src/win/iupwin_canvas.c54
-rwxr-xr-xiup/src/win/iupwin_common.c55
-rwxr-xr-xiup/src/win/iupwin_dialog.c26
-rwxr-xr-xiup/src/win/iupwin_draw.c374
-rwxr-xr-xiup/src/win/iupwin_drv.h5
-rwxr-xr-xiup/src/win/iupwin_filedlg.c72
-rwxr-xr-xiup/src/win/iupwin_focus.c17
-rwxr-xr-xiup/src/win/iupwin_font.c4
-rwxr-xr-xiup/src/win/iupwin_fontdlg.c6
-rwxr-xr-xiup/src/win/iupwin_frame.c43
-rwxr-xr-xiup/src/win/iupwin_globalattrib.c7
-rwxr-xr-xiup/src/win/iupwin_info.c2
-rwxr-xr-xiup/src/win/iupwin_info.h2
-rwxr-xr-xiup/src/win/iupwin_key.c20
-rwxr-xr-xiup/src/win/iupwin_label.c27
-rwxr-xr-xiup/src/win/iupwin_list.c55
-rwxr-xr-xiup/src/win/iupwin_loop.c12
-rwxr-xr-xiup/src/win/iupwin_menu.c3
-rwxr-xr-xiup/src/win/iupwin_open.c5
-rwxr-xr-xiup/src/win/iupwin_progressbar.c2
-rwxr-xr-xiup/src/win/iupwin_tabs.c56
-rwxr-xr-xiup/src/win/iupwin_text.c52
-rwxr-xr-xiup/src/win/iupwin_toggle.c32
-rwxr-xr-xiup/src/win/iupwin_tree.c1292
-rwxr-xr-xiup/src/win/iupwin_val.c37
115 files changed, 6496 insertions, 3363 deletions
diff --git a/iup/src/Makefile b/iup/src/Makefile
index 028047f..e666555 100755
--- a/iup/src/Makefile
+++ b/iup/src/Makefile
@@ -1,9 +1,12 @@
-.PHONY: do_all iup iupgtk
-do_all: iup iupgtk
+.PHONY: do_all iup iupgtk iupmot
+do_all: iup
iup:
- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak
+ @$(MAKE) --no-print-directory -f ../tecmake.mak
iupgtk:
- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak USE_GTK=Yes
+ @$(MAKE) --no-print-directory -f ../tecmake.mak USE_GTK=Yes
+
+iupmot:
+ @$(MAKE) --no-print-directory -f ../tecmake.mak USE_MOTIF=Yes
diff --git a/iup/src/config.mak b/iup/src/config.mak
index e857643..82b8452 100755
--- a/iup/src/config.mak
+++ b/iup/src/config.mak
@@ -2,9 +2,31 @@ PROJNAME = iup
LIBNAME = iup
OPT = YES
-#ifdef DBG
+ifdef GTK_DEFAULT
+ ifdef USE_MOTIF
+ # Build Motif version in Linux,Darwin,FreeBSD
+ LIBNAME = iupmot
+ else
+ ifeq ($(findstring Win, $(TEC_SYSNAME)), )
+ # Force definition if not in Windows
+ USE_GTK = Yes
+ endif
+ endif
+else
+ ifdef USE_GTK
+ # Build GTK version in IRIX,SunOS,AIX,Win32
+ LIBNAME = iupgtk
+ else
+ ifeq ($(findstring Win, $(TEC_SYSNAME)), )
+ # Force definition if not in Windows
+ USE_MOTIF = Yes
+ endif
+ endif
+endif
+
+ifdef DBG
DEFINES += IUP_ASSERT
-#endif
+endif
INCLUDES = ../include .
@@ -17,19 +39,14 @@ SRC = iup_array.c iup_callback.c iup_dlglist.c iup_attrib.c iup_focus.c iup_font
iup_user.c iup_button.c iup_radio.c iup_toggle.c iup_progressbar.c iup_text.c iup_val.c \
iup_box.c iup_hbox.c iup_vbox.c iup_cbox.c iup_class.c iup_classbase.c iup_maskmatch.c \
iup_mask.c iup_maskparse.c iup_tabs.c iup_spin.c iup_list.c iup_getparam.c \
- iup_sbox.c iup_normalizer.c iup_tree.c
+ iup_sbox.c iup_normalizer.c iup_tree.c iup_split.c
ifdef USE_GTK
- ifndef GTK_DEFAULT
- # Build GTK version in IRIX,SunOS,AIX,Win32
- LIBNAME := iupgtk
- endif
-
DEFINES += GTK_DISABLE_DEPRECATED
INCLUDES += gtk
SRC += gtk/iupgtk_common.c gtk/iupgtk_focus.c gtk/iupgtk_font.c gtk/iupgtk_clipboard.c \
gtk/iupgtk_globalattrib.c gtk/iupgtk_key.c gtk/iupgtk_tips.c \
- gtk/iupgtk_loop.c gtk/iupgtk_open.c gtk/iupgtk_messagedlg.c \
+ gtk/iupgtk_loop.c gtk/iupgtk_open.c gtk/iupgtk_messagedlg.c gtk/iupgtk_draw.c \
gtk/iupgtk_dialog.c gtk/iupgtk_timer.c gtk/iupgtk_image.c gtk/iupgtk_label.c \
gtk/iupgtk_colordlg.c gtk/iupgtk_fontdlg.c gtk/iupgtk_filedlg.c \
gtk/iupgtk_button.c gtk/iupgtk_toggle.c gtk/iupgtk_progressbar.c \
@@ -40,7 +57,11 @@ ifdef USE_GTK
DEFINES += _WIN32_WINNT=0x0500 _WIN32_IE=0x0500 WINVER=0x0500 NOTREEVIEW
SRC += win/iupwindows_main.c win/iupwindows_help.c win/iupwindows_info.c
else
- SRC += gtk/iupgtk_help.c mot/iupunix_info.c
+ ifdef GTK_MAC
+ SRC += gtk/iupmac_help.c gtk/iupmac_info.c
+ else
+ SRC += gtk/iupgtk_help.c mot/iupunix_info.c
+ endif
endif
ifdef USE_HILDON
@@ -49,42 +70,35 @@ ifdef USE_GTK
LIBS += hildon-1
endif
else
- ifneq ($(findstring Win, $(TEC_SYSNAME)), )
-
- SRC += win/iupwin_common.c win/iupwin_brush.c win/iupwin_focus.c win/iupwin_font.c \
- win/iupwin_globalattrib.c win/iupwin_handle.c win/iupwin_key.c \
- win/iupwin_loop.c win/iupwin_open.c win/iupwin_tips.c win/iupwin_info.c \
- win/iupwin_dialog.c win/iupwin_messagedlg.c win/iupwin_timer.c \
- win/iupwin_image.c win/iupwin_label.c win/iupwin_canvas.c win/iupwin_frame.c \
- win/iupwin_colordlg.c win/iupwin_fontdlg.c win/iupwin_filedlg.c \
- win/iupwin_button.c win/iupwin_draw.c win/iupwin_toggle.c win/iupwin_clipboard.c \
- win/iupwin_progressbar.c win/iupwin_text.c win/iupwin_val.c \
- win/iupwin_tabs.c win/iupwin_menu.c win/iupwin_list.c win/iupwin_tree.c
-
- SRC += win/iupwindows_main.c win/iupwindows_help.c win/iupwindows_info.c
-
- INCLUDES += win
- DEFINES += _WIN32_WINNT=0x0500 _WIN32_IE=0x0500 WINVER=0x0500 NOTREEVIEW
- else
- ifdef GTK_DEFAULT
- # Build Motif version in Linux,Darwin,FreeBSD
- LIBNAME := iupmot
- endif
-
- SRC += mot/iupmot_common.c mot/iupmot_color.c mot/iupmot_focus.c mot/iupmot_font.c \
- mot/iupmot_key.c mot/iupmot_loop.c mot/iupmot_open.c mot/iupmot_tips.c \
- mot/iupmot_globalattrib.c mot/iupmot_dialog.c mot/iupmot_messagedlg.c \
- mot/iupmot_timer.c mot/iupmot_image.c mot/iupmot_label.c mot/iupmot_canvas.c \
- mot/iupmot_colordlg.c mot/iupmot_fontdlg.c mot/iupmot_filedlg.c mot/iupmot_frame.c \
- mot/iupmot_button.c mot/iupmot_toggle.c mot/iupmot_progressbar.c mot/iupmot_clipboard.c \
- mot/iupmot_text.c mot/iupmot_val.c mot/iupmot_tabs.c mot/iupmot_menu.c \
- mot/iupmot_list.c mot/iupmot_tree.c
-
- SRC += mot/iupunix_help.c mot/iupunix_info.c
-
- INCLUDES += mot
- USE_MOTIF=Yes
- endif
+ifdef USE_MOTIF
+ SRC += mot/iupmot_common.c mot/iupmot_color.c mot/iupmot_focus.c mot/iupmot_font.c \
+ mot/iupmot_key.c mot/iupmot_loop.c mot/iupmot_open.c mot/iupmot_tips.c \
+ mot/iupmot_globalattrib.c mot/iupmot_dialog.c mot/iupmot_messagedlg.c mot/iupmot_draw.c \
+ mot/iupmot_timer.c mot/iupmot_image.c mot/iupmot_label.c mot/iupmot_canvas.c \
+ mot/iupmot_colordlg.c mot/iupmot_fontdlg.c mot/iupmot_filedlg.c mot/iupmot_frame.c \
+ mot/iupmot_button.c mot/iupmot_toggle.c mot/iupmot_progressbar.c mot/iupmot_clipboard.c \
+ mot/iupmot_text.c mot/iupmot_val.c mot/iupmot_tabs.c mot/iupmot_menu.c \
+ mot/iupmot_list.c mot/iupmot_tree.c
+
+ SRC += mot/iupunix_help.c mot/iupunix_info.c
+
+ INCLUDES += mot
+else
+ SRC += win/iupwin_common.c win/iupwin_brush.c win/iupwin_focus.c win/iupwin_font.c \
+ win/iupwin_globalattrib.c win/iupwin_handle.c win/iupwin_key.c \
+ win/iupwin_loop.c win/iupwin_open.c win/iupwin_tips.c win/iupwin_info.c \
+ win/iupwin_dialog.c win/iupwin_messagedlg.c win/iupwin_timer.c \
+ win/iupwin_image.c win/iupwin_label.c win/iupwin_canvas.c win/iupwin_frame.c \
+ win/iupwin_colordlg.c win/iupwin_fontdlg.c win/iupwin_filedlg.c \
+ win/iupwin_button.c win/iupwin_draw.c win/iupwin_toggle.c win/iupwin_clipboard.c \
+ win/iupwin_progressbar.c win/iupwin_text.c win/iupwin_val.c \
+ win/iupwin_tabs.c win/iupwin_menu.c win/iupwin_list.c win/iupwin_tree.c
+
+ SRC += win/iupwindows_main.c win/iupwindows_help.c win/iupwindows_info.c
+
+ INCLUDES += win
+ DEFINES += _WIN32_WINNT=0x0500 _WIN32_IE=0x0500 WINVER=0x0500 NOTREEVIEW
+endif
endif
ifeq "$(TEC_SYSNAME)" "SunOS"
@@ -113,6 +127,6 @@ ifeq "$(TEC_UNAME)" "dll"
endif
ifeq "$(TEC_UNAME)" "owc1"
- # Necessary or IUP will not work in Open Watcom
+ # Necessary or IUP 3 will not work in Open Watcom
DBG=Yes
endif
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;
+}
diff --git a/iup/src/iup.c b/iup/src/iup.c
index df4bf34..d103af5 100755
--- a/iup/src/iup.c
+++ b/iup/src/iup.c
@@ -36,8 +36,10 @@
* \subsection com File Comments (at start)
* - Check an existant file for example.
*
- * \subsection inc Include Defines
- * - __IUPXXX_H (same file name, upper case, "__" preffix and replace "." by "_")
+ * \subsection def Defines
+ * - __IUPXXX_H (for include file, same file name, upper case, "__" preffix and replace "." by "_")
+ * - IUP_XXX (for enumerations)
+ * - iupXXX (for macros, complement with Function Names rules)
*
* \subsection doc Documentation
* - In the header, using Doxygen commands.
@@ -58,7 +60,7 @@
#include "iup.h"
/* This appears only here to avoid changing the iup.h header fo bug fixes */
-#define IUP_VERSION_FIX " RC3"
+#define IUP_VERSION_FIX ""
#define IUP_VERSION_FIX_NUMBER 0
const char iup_ident[] =
diff --git a/iup/src/iup.def b/iup/src/iup.def
index d0dcfbd..56e7225 100755
--- a/iup/src/iup.def
+++ b/iup/src/iup.def
@@ -27,6 +27,8 @@ IupGetFunction
IupGetGlobal
IupGetHandle
IupGetInt
+IupGetInt2
+IupGetIntInt
IupGetLanguage
IupGetName
IupHbox
@@ -40,6 +42,7 @@ IupListDialog
IupLoad
IupLoadBuffer
IupLoopStep
+IupLoopStepWait
IupMainLoop
IupMap
IupMapFont
@@ -68,6 +71,7 @@ IupShowXY
IupStoreAttribute
IupStoreGlobal
IupSubmenu
+IupSplit
IupText
IupToggle
IupUnMapFont
@@ -135,6 +139,7 @@ IupTextConvertLinColToPos
IupTextConvertPosToLinCol
IupUpdateChildren
IupTreeSetAttribute
+IupTreeSetAttributeHandle
IupTreeStoreAttribute
IupTreeGetAttribute
IupTreeGetInt
@@ -175,8 +180,8 @@ iupdrvFontGetStringWidth
iupdrvFontGetMultiLineStringSize
iupdrvFontGetCharSize
iupdrvDrawFocusRect
-iupdrvDisplayUpdate
-iupdrvDisplayRedraw
+iupdrvPostRedraw
+iupdrvRedrawNow
iupdrvBaseUnMapMethod
iupdrvBaseSetZorderAttrib
iupdrvBaseSetTipVisibleAttrib
@@ -351,3 +356,17 @@ iupArrayCreate
iupArrayCount
iupArrayAdd
iupSaveImageAsText
+iupDrawCreateCanvas
+iupDrawKillCanvas
+iupDrawFlush
+iupDrawGetSize
+iupDrawParentBackground
+iupDrawRectangle
+iupDrawLine
+iupDrawArc
+iupDrawPolygon
+iupDrawResetClip
+iupDrawSetClipRect
+iupDrawText
+iupDrawUpdateSize
+iupDrawImage
diff --git a/iup/src/iup_attrib.c b/iup/src/iup_attrib.c
index 2bbb80a..bf9576e 100755
--- a/iup/src/iup_attrib.c
+++ b/iup/src/iup_attrib.c
@@ -63,7 +63,7 @@ char* IupGetAttributes(Ihandle *ih)
name = iupTableFirst(ih->attrib);
while (name)
{
- if (!iupAttribIsInternal(name))
+ if (!iupATTRIB_ISINTERNAL(name))
{
if (buffer[0] != 0)
strcat(buffer,",");
@@ -115,6 +115,14 @@ void iupAttribUpdateFromParent(Ihandle* ih)
}
}
+static int iAttribIsInherit(Ihandle* ih, const char* name)
+{
+ int inherit;
+ char *def_value;
+ iupClassObjectGetAttributeInfo(ih, name, &def_value, &inherit);
+ return inherit;
+}
+
static void iAttribNotifyChildren(Ihandle *ih, const char* name, const char *value)
{
int inherit;
@@ -123,17 +131,36 @@ static void iAttribNotifyChildren(Ihandle *ih, const char* name, const char *val
{
if (!iupTableGet(child->attrib, name))
{
- /* set on the class */
- iupClassObjectSetAttribute(child, name, value, &inherit);
+ /* set only if an inheritable attribute at the child */
+ if (iAttribIsInherit(child, name))
+ {
+ /* set on the class */
+ iupClassObjectSetAttribute(child, name, value, &inherit);
- if (inherit) /* inherit can be different for the child */
iAttribNotifyChildren(child, name, value);
+ }
}
child = child->brother;
}
}
+void iupAttribUpdateChildren(Ihandle* ih)
+{
+ char *name = iupTableFirst(ih->attrib);
+ while (name)
+ {
+ if (!iupATTRIB_ISINTERNAL(name) && iAttribIsInherit(ih, name))
+ {
+ /* retrieve from the table */
+ char* value = iupTableGet(ih->attrib, name);
+ iAttribNotifyChildren(ih, name, value);
+ }
+
+ name = iupTableNext(ih->attrib);
+ }
+}
+
void iupAttribUpdate(Ihandle* ih)
{
char** name_array;
@@ -159,7 +186,7 @@ void iupAttribUpdate(Ihandle* ih)
for (i = 0; i < count; i++)
{
name = name_array[i];
- if (!iupAttribIsInternal(name))
+ if (!iupATTRIB_ISINTERNAL(name))
{
/* retrieve from the table */
value = iupTableGet(ih->attrib, name);
@@ -196,7 +223,7 @@ void IupSetAttribute(Ihandle *ih, const char* name, const char *value)
if (!iupObjectCheck(ih))
return;
- if (iupAttribIsInternal(name))
+ if (iupATTRIB_ISINTERNAL(name))
iupAttribSetStr(ih, name, value);
else
{
@@ -225,7 +252,7 @@ void IupStoreAttribute(Ihandle *ih, const char* name, const char *value)
if (!iupObjectCheck(ih))
return;
- if (iupAttribIsInternal(name))
+ if (iupATTRIB_ISINTERNAL(name))
iupAttribStoreStr(ih, name, value);
else
{
@@ -257,7 +284,7 @@ char* IupGetAttribute(Ihandle *ih, const char* name)
if (!value)
value = iupAttribGet(ih, name);
- if (!value && !iupAttribIsInternal(name))
+ if (!value && !iupATTRIB_ISINTERNAL(name))
{
if (inherit)
{
@@ -346,6 +373,16 @@ void iupAttribSetHandleName(Ihandle *ih)
IupSetHandle(str_name, ih);
}
+char* iupAttribGetHandleName(Ihandle *ih)
+{
+ char str_name[100];
+ sprintf(str_name, "_IUP_NAME(%p)", ih);
+ if (IupGetHandle(str_name)==ih)
+ return iupStrGetMemoryCopy(str_name);
+ else
+ return NULL;
+}
+
void IupSetAttributeHandle(Ihandle *ih, const char* name, Ihandle *ih_named)
{
int inherit;
@@ -426,7 +463,7 @@ void iupAttribSetInt(Ihandle *ih, const char* name, int num)
void iupAttribSetFloat(Ihandle *ih, const char* name, float num)
{
- iupAttribSetStrf(ih, name, "%f", (double)num);
+ iupAttribSetStrf(ih, name, "%g", (double)num);
}
int iupAttribGetBoolean(Ihandle* ih, const char* name)
@@ -479,7 +516,7 @@ char* iupAttribGetStr(Ihandle* ih, const char* name)
value = iupTableGet(ih->attrib, name);
- if (!value && !iupAttribIsInternal(name))
+ if (!value && !iupATTRIB_ISINTERNAL(name))
{
int inherit;
char *def_value;
@@ -555,6 +592,15 @@ static void iAttribCapture(char* env_buffer, char* dlm)
env_buffer[i-1]='\0'; /* discard delimiter */
}
+static void iAttribSkipComment(void)
+{
+ int c;
+ do
+ {
+ c = *env_str; ++env_str;
+ } while ((c > 0) && (c != '\n'));
+}
+
static int iAttribToken(char* env_buffer)
{
for (;;)
@@ -565,6 +611,11 @@ static int iAttribToken(char* env_buffer)
case 0:
return IUPLEX_TK_END;
+ case '#': /* Skip comment */
+ case '%': /* Skip comment */
+ iAttribSkipComment();
+ continue;
+
case ' ': /* ignore whitespace */
case '\t':
case '\n':
@@ -609,7 +660,7 @@ static void iAttribParse(Ihandle *ih, const char* str)
{
switch (iAttribToken(env_buffer))
{
- case IUPLEX_TK_END: /* procedimento igual ao IUPLEX_TK_COMMA */
+ case IUPLEX_TK_END: /* same as IUPLEX_TK_COMMA */
end = 1;
case IUPLEX_TK_COMMA:
if (name)
diff --git a/iup/src/iup_attrib.h b/iup/src/iup_attrib.h
index 993dd3c..8593d6e 100755
--- a/iup/src/iup_attrib.h
+++ b/iup/src/iup_attrib.h
@@ -28,7 +28,7 @@ extern "C" {
/** Returns true if the attribute name if in the internal format "_IUP...".
* \ingroup attrib */
-#define iupAttribIsInternal(_name) ((_name[0] == '_' && _name[1] == 'I' && _name[2] == 'U' && _name[3] == 'P')? 1: 0)
+#define iupATTRIB_ISINTERNAL(_name) ((_name[0] == '_' && _name[1] == 'I' && _name[2] == 'U' && _name[3] == 'P')? 1: 0)
/** Returns true if the attribute name is a known pointer.
* \ingroup attrib */
@@ -102,16 +102,23 @@ float iupAttribGetFloat(Ihandle* ih, const char* name);
* \ingroup attrib */
void iupAttribSetHandleName(Ihandle *ih);
+/** Returns the internal name if set.
+ * \ingroup attrib */
+char* iupAttribGetHandleName(Ihandle *ih);
+
/* For all attributes in the evironment, call the class SetAttribute only.
- * Called only after the element is mapped. */
+ * Called only after the element is mapped, but before the children are mapped. */
void iupAttribUpdate(Ihandle* ih);
/* For all registered inherited attributes, checks the parent tree and
* call the class SetAttribute if the attribute is defined.
- * Called only after the element is mapped. */
+ * Called only after the element is mapped, but before the children are mapped. */
void iupAttribUpdateFromParent(Ihandle* ih);
+/* For all attributes in the evironment, call the class SetAttribute only for the children.
+ * Called only after the element is mapped, and after the children are mapped. */
+void iupAttribUpdateChildren(Ihandle* ih);
/* Other functions declared in <iup.h> and implemented here.
diff --git a/iup/src/iup_box.c b/iup/src/iup_box.c
index 54e56d9..111cab4 100755
--- a/iup/src/iup_box.c
+++ b/iup/src/iup_box.c
@@ -172,9 +172,9 @@ static int iBoxSetCMarginAttrib(Ihandle* ih, const char* value)
iupdrvFontGetCharSize(ih, &charwidth, &charheight);
iupStrToIntInt(value, &cmargin_x, &cmargin_y, 'x');
if (cmargin_x!=-1)
- ih->data->margin_x = iupHEIGHT2RASTER(cmargin_x, charheight);
+ ih->data->margin_x = iupWIDTH2RASTER(cmargin_x, charwidth);
if (cmargin_y!=-1)
- ih->data->margin_x = iupWIDTH2RASTER(cmargin_y, charwidth);
+ ih->data->margin_y = iupHEIGHT2RASTER(cmargin_y, charheight);
return 0;
}
@@ -227,8 +227,12 @@ Iclass* iupBoxClassBase(void)
/* boxes only */
iupClassRegisterAttribute(ic, "GAP", iBoxGetGapAttrib, iBoxSetGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
iupClassRegisterAttribute(ic, "CGAP", iBoxGetCGapAttrib, iBoxSetCGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "NGAP", iBoxGetGapAttrib, iBoxSetGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NCGAP", iBoxGetCGapAttrib, iBoxSetCGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "MARGIN", iBoxGetMarginAttrib, iBoxSetMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
iupClassRegisterAttribute(ic, "CMARGIN", iBoxGetCMarginAttrib, iBoxSetCMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "NMARGIN", iBoxGetMarginAttrib, iBoxSetMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NCMARGIN", iBoxGetCMarginAttrib, iBoxSetCMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "EXPANDCHILDREN", iBoxGetExpandChildrenAttrib, iBoxSetExpandChildrenAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "HOMOGENEOUS", iBoxGetHomogeneousAttrib, iBoxSetHomogeneousAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
diff --git a/iup/src/iup_button.c b/iup/src/iup_button.c
index 7719663..56befe2 100755
--- a/iup/src/iup_button.c
+++ b/iup/src/iup_button.c
@@ -100,8 +100,9 @@ static void iButtonComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *ex
char* value = iupAttribGet(ih, "IMAGE");
if (value)
{
+ char* title = iupAttribGet(ih, "TITLE");
type = IUP_BUTTON_IMAGE;
- if (iupAttribGet(ih, "TITLE"))
+ if (title && *title!=0)
type |= IUP_BUTTON_TEXT;
}
else
diff --git a/iup/src/iup_canvas.c b/iup/src/iup_canvas.c
index 5eda988..46fefd9 100755
--- a/iup/src/iup_canvas.c
+++ b/iup/src/iup_canvas.c
@@ -55,14 +55,14 @@ void iupCanvasCalcScrollRealPos(double min, double max, double *pos,
char* iupCanvasGetPosXAttrib(Ihandle* ih)
{
char* str = iupStrGetMemory(20);
- sprintf(str, "%f", ih->data->posx);
+ sprintf(str, "%g", ih->data->posx);
return str;
}
char* iupCanvasGetPosYAttrib(Ihandle* ih)
{
char* str = iupStrGetMemory(20);
- sprintf(str, "%f", ih->data->posy);
+ sprintf(str, "%g", ih->data->posy);
return str;
}
diff --git a/iup/src/iup_classattrib.c b/iup/src/iup_classattrib.c
index df8f873..3ac780c 100755
--- a/iup/src/iup_classattrib.c
+++ b/iup/src/iup_classattrib.c
@@ -55,7 +55,7 @@ static const char* iClassFindId(const char* name)
{
if (*name >= '0' && *name <= '9')
return name;
- if (*name == '*' || *name == ':')
+ if (*name == '*' || *name == ':' || *name == '-')
return name;
name++;
@@ -94,7 +94,6 @@ int iupClassObjectSetAttribute(Ihandle* ih, const char* name, const char * value
const char* name_id = iClassFindId(name);
if (name_id)
{
- IattribFunc* afunc;
const char* partial_name = iClassCutNameId(name, name_id);
if (!partial_name)
partial_name = "IDVALUE"; /* pure numbers are used as attributes in IupList and IupMatrix,
@@ -474,8 +473,12 @@ void iupClassObjectEnsureDefaultAttributes(Ihandle* ih)
(afunc->call_global_default && iupGlobalDefaultColorChanged(afunc->default_value)))
{
if ((!ih->handle && (afunc->flags & IUPAF_NOT_MAPPED)) ||
- (ih->handle && !(afunc->flags & IUPAF_NOT_MAPPED) && !iupAttribGet(ih, name)))
- afunc->set(ih, iClassGetDefaultValue(afunc));
+ (ih->handle && !(afunc->flags & IUPAF_NOT_MAPPED)))
+ {
+ char* value = iupAttribGet(ih, name);
+ if (!value) /* if set will be updated later */
+ afunc->set(ih, iClassGetDefaultValue(afunc));
+ }
}
}
diff --git a/iup/src/iup_classbase.c b/iup/src/iup_classbase.c
index 9cb9e63..03a98d1 100755
--- a/iup/src/iup_classbase.c
+++ b/iup/src/iup_classbase.c
@@ -164,8 +164,7 @@ static char* iBaseGetPositionAttrib(Ihandle* ih)
static int iBaseSetPositionAttrib(Ihandle* ih, const char* value)
{
- if (ih->is_floating)
- iupStrToIntInt(value, &ih->x, &ih->y, ',');
+ iupStrToIntInt(value, &ih->x, &ih->y, ',');
return 0;
}
@@ -211,7 +210,7 @@ char* iupBaseGetVisibleAttrib(Ihandle* ih)
int iupBaseSetVisibleAttrib(Ihandle* ih, const char* value)
{
iupdrvSetVisible(ih, iupStrBoolean(value));
- return 0;
+ return 1; /* must be 1 to mark when set at the element */
}
char* iupBaseNativeParentGetBgColorAttrib(Ihandle* ih)
@@ -410,15 +409,19 @@ void iupBaseRegisterCommonAttrib(Iclass* ic)
iupClassRegisterAttribute(ic, "FLOATING", iBaseGetFloatingAttrib, iBaseSetFloatingAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "EXPAND", iBaseGetExpandAttrib, iBaseSetExpandAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "NORMALIZERGROUP", NULL, iBaseSetNormalizerGroupAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EXPANDWEIGTH", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
/* make sure everyone has the correct default value */
- iupClassRegisterAttribute(ic, "VISIBLE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
iupClassRegisterAttribute(ic, "ACTIVE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
if (ic->is_interactive)
iupClassRegisterAttribute(ic, "CANFOCUS", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
else
iupClassRegisterAttribute(ic, "CANFOCUS", NULL, NULL, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NO_INHERIT);
+ /* if not native container, must set at children,
+ native container will automatically hide its children. */
+ iupClassRegisterAttribute(ic, "VISIBLE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT); /* let the attribute to be propagated to children */
+
iupClassRegisterAttribute(ic, "SIZE", iupBaseGetSizeAttrib, iupBaseSetSizeAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "RASTERSIZE", iupBaseGetRasterSizeAttrib, iupBaseSetRasterSizeAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "CHARSIZE", iupBaseGetCharSizeAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
@@ -439,7 +442,7 @@ void iupBaseRegisterCommonAttrib(Iclass* ic)
void iupBaseRegisterVisualAttrib(Iclass* ic)
{
- iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iupBaseSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT); /* VISIBLE inheritance comes from the native system */
+ iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iupBaseSetVisibleAttrib, "YES", "NO", IUPAF_DEFAULT);
iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iupBaseSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
iupClassRegisterAttribute(ic, "ZORDER", NULL, iupdrvBaseSetZorderAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
diff --git a/iup/src/iup_dialog.c b/iup/src/iup_dialog.c
index d70e12c..1aaf095 100755
--- a/iup/src/iup_dialog.c
+++ b/iup/src/iup_dialog.c
@@ -220,11 +220,19 @@ static void iDialogDestroyMethod(Ihandle* ih)
iupDlgListRemove(ih);
}
+static int iDialogSetMenuAttrib(Ihandle* ih, const char* value);
+
static void iDialogComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
{
int decorwidth, decorheight;
Ihandle* child = ih->firstchild;
+ /* if does not have a menu, but the attribute is defined,
+ try to update the menu before retrieving the decoration. */
+ char* value = iupAttribGet(ih, "MENU");
+ if (!ih->data->menu && value)
+ iDialogSetMenuAttrib(ih, value);
+
iupDialogGetDecorSize(ih, &decorwidth, &decorheight);
*w = decorwidth;
*h = decorheight;
@@ -278,20 +286,22 @@ static void iDialogAfterShow(Ihandle* ih)
{
Ihandle* old_focus;
IFni show_cb;
+ int show_state;
/* process all pending messages */
IupFlush();
old_focus = IupGetFocus();
+ show_state = ih->data->show_state;
show_cb = (IFni)IupGetCallback(ih, "SHOW_CB");
- if (show_cb && show_cb(ih, ih->data->show_state) == IUP_CLOSE)
+ if (show_cb && show_cb(ih, show_state) == IUP_CLOSE)
{
IupExitLoop();
return;
}
- if (ih->data->show_state == IUP_SHOW)
+ if (show_state == IUP_SHOW)
{
if (show_cb)
IupFlush(); /* again to update focus */
@@ -718,7 +728,8 @@ Iclass* iupDialogGetClass(void)
iupBaseRegisterVisualAttrib(ic);
/* Overwrite Visual */
- iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iDialogSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NO_INHERIT); /* the only case where VISIBLE default is NO */
+ /* the only case where VISIBLE default is NO, and must not be propagated to the dialog children */
+ iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iDialogSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NO_INHERIT);
/* IupDialog only */
iupClassRegisterAttribute(ic, "MENU", NULL, iDialogSetMenuAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
diff --git a/iup/src/iup_draw.h b/iup/src/iup_draw.h
new file mode 100644
index 0000000..b4d08e3
--- /dev/null
+++ b/iup/src/iup_draw.h
@@ -0,0 +1,98 @@
+/** \file
+ * \brief Simple Draw API.
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#ifndef __IUP_DRAW_H
+#define __IUP_DRAW_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** \defgroup draw Simple Draw API
+ * \par
+ * See \ref iup_draw.h
+ * \ingroup util */
+
+
+
+struct _IdrawCanvas;
+typedef struct _IdrawCanvas IdrawCanvas;
+
+
+/** Creates a draw canvas based on an IupCanvas.
+ * This will create an image for offscreen drawing.
+ * \ingroup draw */
+IdrawCanvas* iupDrawCreateCanvas(Ihandle* ih);
+
+/** Destroys the IdrawCanvas.
+ * \ingroup draw */
+void iupDrawKillCanvas(IdrawCanvas* dc);
+
+/** Draws the ofscreen image on the screen.
+ * \ingroup draw */
+void iupDrawFlush(IdrawCanvas* dc);
+
+/** Rebuild the offscreen image if the canvas size has changed.
+ * Automatically done in iupDrawCreateCanvas.
+ * \ingroup draw */
+void iupDrawUpdateSize(IdrawCanvas* dc);
+
+/** Returns the canvas size available for drawing.
+ * \ingroup draw */
+void iupDrawGetSize(IdrawCanvas* dc, int *w, int *h);
+
+/** Draws the parent background.
+ * \ingroup draw */
+void iupDrawParentBackground(IdrawCanvas* dc);
+
+/** Draws a line.
+ * \ingroup draw */
+void iupDrawLine(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b);
+
+/** Draws a filled/hollow rectangle.
+ * \ingroup draw */
+void iupDrawRectangle(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b, int filled);
+
+/** Draws a filled/hollow arc.
+ * \ingroup draw */
+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);
+
+/** Draws a filled/hollow polygon.
+ * points are arranged xyxyxy...
+ * \ingroup draw */
+void iupDrawPolygon(IdrawCanvas* dc, int* points, int count, unsigned char r, unsigned char g, unsigned char b, int filled);
+
+/** Draws a text.
+ * x,y is at left,top corner of the text.
+ * \ingroup draw */
+void iupDrawText(IdrawCanvas* dc, const char* text, int len, int x, int y, unsigned char r, unsigned char g, unsigned char b);
+
+/** Draws an image.
+ * x,y is at left,top corner of the image.
+ * \ingroup draw */
+void iupDrawImage(IdrawCanvas* dc, const char* name, int make_inactive, int x, int y);
+
+/** Sets a rectangle clipping area.
+ * \ingroup draw */
+void iupDrawSetClipRect(IdrawCanvas* dc, int x1, int y1, int x2, int y2);
+
+/** Removes clipping.
+ * \ingroup draw */
+void iupDrawResetClip(IdrawCanvas* dc);
+
+/*
+TO DO:
+- check position and size of primitives
+*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/iup/src/iup_drv.h b/iup/src/iup_drv.h
index 5cdb8e7..1071347 100755
--- a/iup/src/iup_drv.h
+++ b/iup/src/iup_drv.h
@@ -60,11 +60,11 @@ void iupdrvSetActive(Ihandle* ih, int enable);
/** Post a redraw of a control.
* \ingroup drv */
-void iupdrvDisplayUpdate(Ihandle *ih);
+void iupdrvPostRedraw(Ihandle *ih);
/** Force a redraw of a control.
* \ingroup drv */
-void iupdrvDisplayRedraw(Ihandle *ih);
+void iupdrvRedrawNow(Ihandle *ih);
/** Reparent the native control.
* \ingroup drv */
diff --git a/iup/src/iup_focus.c b/iup/src/iup_focus.c
index be54b75..fc0579c 100755
--- a/iup/src/iup_focus.c
+++ b/iup/src/iup_focus.c
@@ -220,15 +220,25 @@ void iupFocusPrevious(Ihandle *ih)
/* local variables */
static Ihandle* iup_current_focus = NULL;
+Ihandle* IupGetFocus(void)
+{
+ return iup_current_focus;
+}
+
+void iupSetCurrentFocus(Ihandle *ih)
+{
+ iup_current_focus = ih;
+}
+
Ihandle *IupSetFocus(Ihandle *ih)
{
- Ihandle* old_focus = iup_current_focus;
+ Ihandle* old_focus = IupGetFocus();
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return old_focus;
- /* iup_current_focus is NOT set here,
+ /* Current focus is NOT set here,
only in the iupCallGetFocusCb */
if (iupFocusCanAccept(ih))
@@ -237,16 +247,11 @@ Ihandle *IupSetFocus(Ihandle *ih)
return old_focus;
}
-Ihandle *IupGetFocus(void)
-{
- return iup_current_focus;
-}
-
void iupCallGetFocusCb(Ihandle *ih)
{
Icallback cb;
- if (ih == iup_current_focus) /* avoid duplicate messages */
+ if (ih == IupGetFocus()) /* avoid duplicate messages */
return;
cb = (Icallback)IupGetCallback(ih, "GETFOCUS_CB");
@@ -258,14 +263,14 @@ void iupCallGetFocusCb(Ihandle *ih)
if (cb2) cb2(ih, 1);
}
- iup_current_focus = ih;
+ iupSetCurrentFocus(ih);
}
void iupCallKillFocusCb(Ihandle *ih)
{
Icallback cb;
- if (ih != iup_current_focus) /* avoid duplicate messages */
+ if (ih != IupGetFocus()) /* avoid duplicate messages */
return;
cb = IupGetCallback(ih, "KILLFOCUS_CB");
@@ -277,5 +282,5 @@ void iupCallKillFocusCb(Ihandle *ih)
if (cb2) cb2(ih, 0);
}
- iup_current_focus = NULL;
+ iupSetCurrentFocus(NULL);
}
diff --git a/iup/src/iup_focus.h b/iup/src/iup_focus.h
index 239e233..9fb4e58 100755
--- a/iup/src/iup_focus.h
+++ b/iup/src/iup_focus.h
@@ -39,6 +39,7 @@ Ihandle* iupFocusNextInteractive(Ihandle *ih);
void iupFocusNext(Ihandle *ih);
void iupFocusPrevious(Ihandle *ih);
+void iupSetCurrentFocus(Ihandle *ih);
/* Other functions declared in <iup.h> and implemented here.
IupPreviousField
diff --git a/iup/src/iup_getparam.c b/iup/src/iup_getparam.c
index 1418aa5..7fd6a94 100755
--- a/iup/src/iup_getparam.c
+++ b/iup/src/iup_getparam.c
@@ -45,6 +45,14 @@ static int iParamButtonCancel_CB(Ihandle* self)
return IUP_CLOSE;
}
+static int iParamButtonHelp_CB(Ihandle* self)
+{
+ Ihandle* dlg = IupGetDialog(self);
+ Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB");
+ if (cb) cb(dlg, -4, (void*)iupAttribGet(dlg, "USER_DATA"));
+ return IUP_DEFAULT;
+}
+
static int iParamToggleAction_CB(Ihandle *self, int v)
{
Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM");
@@ -288,7 +296,7 @@ static int iParamColorButton_CB(Ihandle *self, int button, int pressed)
IupPopup(dlg, IUP_CENTER, IUP_CENTER);
- if (IupGetInt(dlg, "STATUS") != -1)
+ if (IupGetInt(dlg, "STATUS")==1)
{
char* value = IupGetAttribute(dlg, "VALUE");
IupSetAttribute(textbox, "VALUE", value);
@@ -381,11 +389,13 @@ static int iParamSpinInt_CB(Ihandle *self, int pos)
static Ihandle* iParamCreateBox(Ihandle* param)
{
Ihandle *box, *ctrl = NULL, *label;
- char *type;
+ char *type = iupAttribGet(param, "TYPE");
+
+ if (iupStrEqual(type, "BUTTONNAMES"))
+ return NULL;
label = IupLabel(iupAttribGet(param, "TITLE"));
- type = iupAttribGet(param, "TYPE");
if (iupStrEqual(type, "SEPARATOR"))
{
box = IupHbox(label, NULL);
@@ -563,7 +573,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
float step = iupAttribGetFloat(param, "STEP");
float val = iupAttribGetFloat(param, "VALUE");
if (step == 0) step = (max-min)/20.0f;
- IupSetfAttribute(ctrl, "MASKFLOAT", "%f:%f", (double)min, (double)max);
+ IupSetfAttribute(ctrl, "MASKFLOAT", "%g:%g", (double)min, (double)max);
/* here spin is always [0-spinmax] converted to [min-max] */
@@ -584,7 +594,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
if (min == 0)
IupSetAttribute(ctrl, "MASK", IUP_MASK_UFLOAT);
else
- IupSetfAttribute(ctrl, "MASKFLOAT", "%f:%f", (double)min, (double)1.0e10);
+ IupSetfAttribute(ctrl, "MASKFLOAT", "%g:%g", (double)min, (double)1.0e10);
IupAppend(box, ctrl);
}
else
@@ -620,6 +630,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
}
IupSetfAttribute(ctrl, "SPINMAX", "%d", max);
IupSetfAttribute(ctrl, "SPINMIN", "%d", min);
+ IupSetfAttribute(ctrl, "MASKINT", "%d:%d", min, max);
}
else if (iupAttribGetInt(param, "PARTIAL"))
{
@@ -696,7 +707,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
static Ihandle* IupParamDlgP(Ihandle** params)
{
- Ihandle *dlg, *button_ok, *button_cancel,
+ Ihandle *dlg, *button_ok, *button_cancel, *button_help=NULL,
*dlg_box, *button_box, *param_box;
int i, lbl_width, p, expand;
@@ -713,7 +724,23 @@ static Ihandle* IupParamDlgP(Ihandle** params)
i = 0; expand = 0;
while (params[i] != NULL)
{
- IupAppend(param_box, iParamCreateBox(params[i]));
+ Ihandle* box = iParamCreateBox(params[i]);
+ if (box)
+ IupAppend(param_box, box);
+ else /* buttonnames */
+ {
+ char* value = iupAttribGet(params[i], "_IUPGP_OK");
+ if (value && *value) IupSetAttribute(button_ok, "TITLE", value);
+ value = iupAttribGet(params[i], "_IUPGP_CANCEL");
+ if (value && *value) IupSetAttribute(button_cancel, "TITLE", value);
+ value = iupAttribGet(params[i], "_IUPGP_HELP");
+ if (value && *value)
+ {
+ button_help = IupButton(value, NULL);
+ IupSetAttribute(button_help, "PADDING", "20x0");
+ IupSetCallback(button_help, "ACTION", (Icallback)iParamButtonHelp_CB);
+ }
+ }
if (IupGetInt(params[i], "EXPAND"))
expand = 1;
@@ -725,6 +752,7 @@ static Ihandle* IupParamDlgP(Ihandle** params)
IupFill(),
button_ok,
button_cancel,
+ button_help,
NULL);
IupSetAttribute(button_box,"MARGIN","0x0");
IupSetAttribute(button_box, "NORMALIZESIZE", "HORIZONTAL");
@@ -926,6 +954,23 @@ static void iParamSetFileOptions(char* extra, Ihandle* param)
iupAttribStoreStr(param, "_IUPGP_NOOVERWRITEPROMPT", nooverwriteprompt);
}
+static void iParamSetButtonNames(char* extra, Ihandle* param)
+{
+ char *ok, *cancel, *help;
+ int count;
+
+ if (!extra)
+ return;
+
+ ok = iParamGetNextStrItem(extra, ',', &count); extra += count;
+ cancel = iParamGetNextStrItem(extra, ',', &count); extra += count;
+ help = iParamGetNextStrItem(extra, ',', &count); extra += count;
+
+ iupAttribStoreStr(param, "_IUPGP_OK", ok);
+ iupAttribStoreStr(param, "_IUPGP_CANCEL", cancel);
+ iupAttribStoreStr(param, "_IUPGP_HELP", help);
+}
+
static void iParamSetListItems(char* extra, Ihandle* param)
{
int d = 1, count;
@@ -1082,6 +1127,12 @@ static Ihandle *IupParamf(const char* format, int *line_size)
iupAttribSetStr(param, "TYPE", "SEPARATOR");
iupAttribSetStr(param, "DATA_TYPE", "-1"); /* NONE */
break;
+ case 'u':
+ iupAttribSetStr(param, "TYPE", "BUTTONNAMES");
+ iupAttribSetStr(param, "DATA_TYPE", "-1"); /* NONE */
+ extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count;
+ iParamSetButtonNames(extra, param);
+ break;
default:
return NULL;
}
@@ -1099,7 +1150,7 @@ static Ihandle *IupParamf(const char* format, int *line_size)
int iupGetParamCount(const char *format, int *param_extra)
{
- int param_count = 0, sep = 0;
+ int param_count = 0, extra = 0;
const char* s = format;
*param_extra = 0;
@@ -1107,14 +1158,20 @@ int iupGetParamCount(const char *format, int *param_extra)
{
if (*s == '%' && *(s+1) == 't') /* do not count separator lines */
{
- sep = 1;
+ extra = 1;
+ (*param_extra)++;
+ }
+
+ if (*s == '%' && *(s+1) == 'u') /* do not count button names lines */
+ {
+ extra = 1;
(*param_extra)++;
}
if (*s == '\n')
{
- if (sep)
- sep = 0;
+ if (extra)
+ extra = 0;
else
param_count++;
}
@@ -1154,21 +1211,21 @@ int IupGetParamv(const char* title, Iparamcb action, void* user_data, const char
return 0;
data_type = IupGetInt(params[i], "DATA_TYPE");
- if (data_type == 1)
- {
- int *data_int = (int*)(param_data[p]);
- if (!data_int) return 0;
- iupAttribSetStrf(params[i], "VALUE", "%d", *data_int);
- p++;
- }
- else if (data_type == 2)
+ if (data_type == 2) /* float */
{
float *data_float = (float*)(param_data[p]);
if (!data_float) return 0;
iupAttribSetStrf(params[i], "VALUE", "%g", *data_float);
p++;
}
- else if (data_type == 0)
+ else if (data_type == 1) /* integer */
+ {
+ int *data_int = (int*)(param_data[p]);
+ if (!data_int) return 0;
+ iupAttribSetStrf(params[i], "VALUE", "%d", *data_int);
+ p++;
+ }
+ else if (data_type == 0) /* string */
{
char *data_str = (char*)(param_data[p]);
if (!data_str) return 0;
diff --git a/iup/src/iup_globalattrib.c b/iup/src/iup_globalattrib.c
index 00586fb..d1a2584 100755
--- a/iup/src/iup_globalattrib.c
+++ b/iup/src/iup_globalattrib.c
@@ -129,12 +129,14 @@ int iupGlobalIsPointer(const char* name)
static struct {
const char *name;
} ptr_table[] = {
-#ifdef WIN32
+#ifndef GTK_MAC
+ #ifdef WIN32
{"HINSTANCE"},
-#else
+ #else
{"XDISPLAY"},
{"XSCREEN"},
{"APPSHELL"},
+ #endif
#endif
};
#define PTR_TABLE_SIZE ((sizeof ptr_table)/(sizeof ptr_table[0]))
diff --git a/iup/src/iup_hbox.c b/iup/src/iup_hbox.c
index e790636..a8a93a3 100755
--- a/iup/src/iup_hbox.c
+++ b/iup/src/iup_hbox.c
@@ -213,6 +213,13 @@ static void iHboxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
else
{
int empty = (child->expand & IUP_EXPAND_W1)? empty_w1: ((child->expand & IUP_EXPAND_W0)? empty_w0: 0);
+ char* weigth_str = iupAttribGet(child, "EXPANDWEIGTH");
+ if (weigth_str)
+ {
+ float weigth;
+ if (iupStrToFloat(weigth_str, &weigth))
+ empty = iupROUND(empty * weigth);
+ }
iupBaseSetCurrentSize(child, child->naturalwidth+empty, client_height, shrink);
}
diff --git a/iup/src/iup_key.h b/iup/src/iup_key.h
index 37d6c9d..9b30bc4 100755
--- a/iup/src/iup_key.h
+++ b/iup/src/iup_key.h
@@ -51,16 +51,16 @@ void iupKeyInit(void);
#define IUPKEY_STATUS_SIZE 11 /* 10 chars + null */
#define IUPKEY_STATUS_INIT " " /* 10 spaces */
-#define iupKEYSETSHIFT(_s) (_s[0]='S')
-#define iupKEYSETCONTROL(_s) (_s[1]='C')
-#define iupKEYSETBUTTON1(_s) (_s[2]='1')
-#define iupKEYSETBUTTON2(_s) (_s[3]='2')
-#define iupKEYSETBUTTON3(_s) (_s[4]='3')
-#define iupKEYSETDOUBLE(_s) (_s[5]='D')
-#define iupKEYSETALT(_s) (_s[6]='A')
-#define iupKEYSETSYS(_s) (_s[7]='Y')
-#define iupKEYSETBUTTON4(_s) (_s[8]='4')
-#define iupKEYSETBUTTON5(_s) (_s[9]='5')
+#define iupKEY_SETSHIFT(_s) (_s[0]='S')
+#define iupKEY_SETCONTROL(_s) (_s[1]='C')
+#define iupKEY_SETBUTTON1(_s) (_s[2]='1')
+#define iupKEY_SETBUTTON2(_s) (_s[3]='2')
+#define iupKEY_SETBUTTON3(_s) (_s[4]='3')
+#define iupKEY_SETDOUBLE(_s) (_s[5]='D')
+#define iupKEY_SETALT(_s) (_s[6]='A')
+#define iupKEY_SETSYS(_s) (_s[7]='Y')
+#define iupKEY_SETBUTTON4(_s) (_s[8]='4')
+#define iupKEY_SETBUTTON5(_s) (_s[9]='5')
#ifdef __cplusplus
diff --git a/iup/src/iup_layout.c b/iup/src/iup_layout.c
index b96293c..0ccd496 100755
--- a/iup/src/iup_layout.c
+++ b/iup/src/iup_layout.c
@@ -43,7 +43,7 @@ static void iLayoutDisplayUpdateChildren(Ihandle *ih)
iLayoutDisplayUpdateChildren(child);
if (child->handle && child->iclass->nativetype != IUP_TYPEVOID)
- iupdrvDisplayUpdate(child);
+ iupdrvPostRedraw(child);
}
}
@@ -54,7 +54,7 @@ void IupUpdate(Ihandle* ih)
return;
if (ih->handle && ih->iclass->nativetype != IUP_TYPEVOID)
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
}
void IupUpdateChildren(Ihandle* ih)
@@ -74,7 +74,7 @@ static void iLayoutDisplayRedrawChildren(Ihandle *ih)
iLayoutDisplayRedrawChildren(child);
if (child->handle && child->iclass->nativetype != IUP_TYPEVOID)
- iupdrvDisplayRedraw(child);
+ iupdrvRedrawNow(child);
}
}
@@ -85,7 +85,7 @@ void IupRedraw(Ihandle* ih, int children)
return;
if (ih->handle && ih->iclass->nativetype != IUP_TYPEVOID)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
if (children)
iLayoutDisplayRedrawChildren(ih);
@@ -136,7 +136,7 @@ void iupLayoutCompute(Ihandle* ih)
iupBaseSetPosition(ih, 0, 0);
}
-static void iLayoutSetMinMaxSize(Ihandle* ih, int *w, int *h)
+void iupLayoutSetMinMaxSize(Ihandle* ih, int *w, int *h)
{
if (ih->has_minsize)
{
@@ -163,7 +163,8 @@ void iupBaseComputeNaturalSize(Ihandle* ih)
ih->naturalwidth = ih->userwidth;
ih->naturalheight = ih->userheight;
- if (ih->iclass->childtype!=IUP_CHILDNONE || ih->iclass->nativetype == IUP_TYPEDIALOG)
+ if (ih->iclass->childtype!=IUP_CHILDNONE ||
+ ih->iclass->nativetype == IUP_TYPEDIALOG) /* pre-defined dialogs can restrict the number of children */
{
int w=0, h=0, children_expand;
@@ -190,7 +191,7 @@ void iupBaseComputeNaturalSize(Ihandle* ih)
ih->naturalheight = iupMAX(ih->naturalheight, h);
/* crop the natural size */
- iLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
+ iupLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
}
}
else
@@ -198,15 +199,15 @@ void iupBaseComputeNaturalSize(Ihandle* ih)
/* for non-container only compute if user size is not defined */
if (ih->naturalwidth <= 0 || ih->naturalheight <= 0)
{
- int w=0, h=0;
- iupClassObjectComputeNaturalSize(ih, &w, &h, NULL);
+ int w=0, h=0, children_expand;
+ iupClassObjectComputeNaturalSize(ih, &w, &h, &children_expand);
if (ih->naturalwidth <= 0) ih->naturalwidth = w;
if (ih->naturalheight <= 0) ih->naturalheight = h;
}
/* crop the natural size */
- iLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
+ iupLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
}
}
@@ -259,7 +260,7 @@ void iupBaseSetCurrentSize(Ihandle* ih, int w, int h, int shrink)
/* crop the current size if expanded */
if (ih->expand & IUP_EXPAND_WIDTH || ih->expand & IUP_EXPAND_HEIGHT)
- iLayoutSetMinMaxSize(ih, &(ih->currentwidth), &(ih->currentheight));
+ iupLayoutSetMinMaxSize(ih, &(ih->currentwidth), &(ih->currentheight));
}
}
diff --git a/iup/src/iup_layout.h b/iup/src/iup_layout.h
index a2a0c29..775e5a2 100755
--- a/iup/src/iup_layout.h
+++ b/iup/src/iup_layout.h
@@ -16,6 +16,8 @@ extern "C" {
void iupLayoutCompute(Ihandle* ih); /* can be called before map */
void iupLayoutUpdate(Ihandle* ih); /* called only after map */
+void iupLayoutSetMinMaxSize(Ihandle* ih, int *w, int *h);
+
/* Other functions declared in <iup.h> and implemented here.
IupRefresh
*/
diff --git a/iup/src/iup_ledlex.c b/iup/src/iup_ledlex.c
index 3283a43..5cf8640 100755
--- a/iup/src/iup_ledlex.c
+++ b/iup/src/iup_ledlex.c
@@ -35,7 +35,7 @@ static struct /* lexical variables */
static int iLexGetChar (void);
static int iLexToken(int *erro);
static int iLexCapture (char* dlm);
-static int iLexSkip (char* dlm);
+static void iLexSkipComment (void);
static int iLexCaptureAttr (void);
int iupLexStart(const char* filename, int is_file) /* initialize lexical analysis */
@@ -186,9 +186,9 @@ static int iLexToken(int *erro)
case ']':
return IUPLEX_TK_ENDATTR;
- case '#': /* iLexSkip comment */
- case '%': /* iLexSkip comment */
- iLexSkip ("\n\r");
+ case '#': /* Skip comment */
+ case '%': /* Skip comment */
+ iLexSkipComment();
continue;
case ' ': /* ignore whitespace */
@@ -276,14 +276,13 @@ static int iLexCaptureAttr (void)
return c; /* return delimiter */
}
-static int iLexSkip (char* dlm)
+static void iLexSkipComment (void)
{
int c;
do
{
- c = iLexGetChar ();
- } while ((c > 0) && !strchr (dlm,c));
- return c; /* return delimiter */
+ c = iLexGetChar();
+ } while ((c > 0) && (c != '\n'));
}
static int iLexGetChar (void)
diff --git a/iup/src/iup_list.c b/iup/src/iup_list.c
index 5965665..1077d98 100755
--- a/iup/src/iup_list.c
+++ b/iup/src/iup_list.c
@@ -53,6 +53,37 @@ static void iListCallActionCallback(Ihandle* ih, IFnsii cb, int pos, int state)
IupExitLoop();
}
+void iupListUpdateOldValue(Ihandle* ih, int pos, int removed)
+{
+ if (!ih->data->has_editbox)
+ {
+ char* old_value = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
+ if (old_value)
+ {
+ int old_pos = atoi(old_value)-1; /* was in IUP reference, starting at 1 */
+ if (ih->data->is_dropdown || !ih->data->is_multiple)
+ {
+ if (old_pos >= pos)
+ {
+ if (removed && old_pos == pos)
+ {
+ /* when the current item is removed nothing remains selected */
+ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
+ }
+ else
+ iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", removed? old_pos-1: old_pos+1);
+ }
+ }
+ else
+ {
+ /* multiple selection on a non drop-down list. */
+ char* value = IupGetAttribute(ih, "VALUE");
+ iupAttribStoreStr(ih, "_IUPLIST_OLDVALUE", value);
+ }
+ }
+ }
+}
+
void iupListSingleCallActionCallback(Ihandle* ih, IFnsii cb, int pos)
{
char* old_str = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
@@ -77,7 +108,7 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
char* old_str = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
int old_count = old_str? strlen(old_str): 0;
- char* str = iupStrGetMemory(count+1);
+ char* str = malloc(count+1);
memset(str, '-', count);
str[count]=0;
for (i=0; i<sel_count; i++)
@@ -92,6 +123,7 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
if (multi_cb)
{
int unchanged = 1;
+
for (i=0; i<count && old_str; i++)
{
if (str[i] == old_str[i])
@@ -101,7 +133,10 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
}
if (old_str && unchanged)
+ {
+ free(str);
return;
+ }
if (multi_cb(ih, str) == IUP_CLOSE)
IupExitLoop();
@@ -133,6 +168,7 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
}
iupAttribStoreStr(ih, "_IUPLIST_OLDVALUE", str);
+ free(str);
}
int iupListGetPos(Ihandle* ih, const char* name_id)
@@ -145,7 +181,8 @@ int iupListGetPos(Ihandle* ih, const char* name_id)
pos--; /* IUP items start at 1 */
if (pos < 0) return -1;
- if (pos > count-1) return -1;
+ if (pos == count) return -2;
+ if (pos > count) return -1;
return pos;
}
@@ -217,7 +254,10 @@ int iupListSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
if (pos >= 0 && pos <= count-1)
{
if (pos == 0)
+ {
iupdrvListRemoveAllItems(ih);
+ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
+ }
else
{
int i = pos;
@@ -245,7 +285,7 @@ int iupListSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
static int iListSetAppendItemAttrib(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)
iupdrvListAppendItem(ih, value);
@@ -254,27 +294,32 @@ static int iListSetAppendItemAttrib(Ihandle* ih, const char* value)
static int iListSetInsertItemAttrib(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 (value)
{
int pos = iupListGetPos(ih, name_id);
- if (pos!=-1)
+ if (pos >= 0)
iupdrvListInsertItem(ih, pos, value);
+ else if (pos == -2)
+ iupdrvListAppendItem(ih, value);
}
return 0;
}
static int iListSetRemoveItemAttrib(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)
+ {
iupdrvListRemoveAllItems(ih);
+ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
+ }
else
{
int pos = iupListGetPos(ih, value);
- if (pos!=-1)
+ if (pos >= 0)
iupdrvListRemoveItem(ih, pos);
}
return 0;
diff --git a/iup/src/iup_list.h b/iup/src/iup_list.h
index 045116b..05fe9f8 100755
--- a/iup/src/iup_list.h
+++ b/iup/src/iup_list.h
@@ -30,6 +30,7 @@ char* iupListGetNCAttrib(Ihandle* ih);
char* iupListGetPaddingAttrib(Ihandle* ih);
char* iupListGetSpacingAttrib(Ihandle* ih);
void iupListSingleCallDblClickCallback(Ihandle* ih, IFnis cb, int pos);
+void iupListUpdateOldValue(Ihandle* ih, int pos, int removed);
struct _IcontrolData
{
diff --git a/iup/src/iup_names.c b/iup/src/iup_names.c
index 9ec01a6..18ca3ef 100755
--- a/iup/src/iup_names.c
+++ b/iup/src/iup_names.c
@@ -14,11 +14,41 @@
#include "iup_object.h"
#include "iup_class.h"
#include "iup_assert.h"
+#include "iup_attrib.h"
#include "iup_str.h"
static Itable *inames_strtable = NULL; /* table indexed by name containing Ihandle* address */
-static Itable *inames_ihtable = NULL; /* table indexed by Ihandle* address containing names */
+
+void iupNamesInit(void)
+{
+ inames_strtable = iupTableCreate(IUPTABLE_STRINGINDEXED);
+}
+
+void iupNamesFinish(void)
+{
+ iupTableDestroy(inames_strtable);
+ inames_strtable = NULL;
+}
+
+static Ihandle* iNameGetTopParent(Ihandle* ih)
+{
+ Ihandle* parent = ih;
+ while (parent->parent)
+ parent = parent->parent;
+ return parent;
+}
+
+static int iNameCheckArray(Ihandle** ih_array, int count, Ihandle* ih)
+{
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ if (ih_array[i] == ih)
+ return 0;
+ }
+ return 1;
+}
void iupNamesDestroyHandles(void)
{
@@ -37,10 +67,14 @@ void iupNamesDestroyHandles(void)
while (name)
{
ih = (Ihandle*)iupTableGetCurr(inames_strtable);
- if (iupObjectCheck(ih))
+ if (iupObjectCheck(ih)) /* here must be a handle */
{
- ih_array[i] = ih;
- i++;
+ ih = iNameGetTopParent(ih);
+ if (iNameCheckArray(ih_array, i, ih))
+ {
+ ih_array[i] = ih;
+ i++;
+ }
}
name = iupTableNext(inames_strtable);
}
@@ -48,44 +82,28 @@ void iupNamesDestroyHandles(void)
count = i;
for (i = 0; i < count; i++)
{
- if (iupObjectCheck(ih_array[i]))
+ if (iupObjectCheck(ih_array[i])) /* here must be a handle */
IupDestroy(ih_array[i]);
}
free(ih_array);
}
-void iupNamesInit(void)
-{
- inames_strtable = iupTableCreate(IUPTABLE_STRINGINDEXED);
- inames_ihtable = iupTableCreate(IUPTABLE_POINTERINDEXED);
-}
-
-void iupNamesFinish(void)
-{
- iupTableDestroy(inames_strtable);
- inames_strtable = NULL;
-
- iupTableDestroy(inames_ihtable);
- inames_ihtable = NULL;
-}
-
-void iupRemoveAllNames(Ihandle* ih)
+void iupRemoveNames(Ihandle* ih)
{
char *name;
- Ihandle *cur_ih;
- name = iupTableFirst(inames_strtable);
- while (name)
- {
- cur_ih = (Ihandle*)iupTableGetCurr(inames_strtable);
- if (iupObjectCheck(cur_ih) && cur_ih == ih)
- iupTableRemoveCurr(inames_strtable);
+ /* clear the cache */
+ name = iupAttribGet(ih, "_IUP_LASTHANDLENAME");
+ if (name)
+ iupTableRemove(inames_strtable, name);
- name = iupTableNext(inames_strtable);
- }
+ /* check for an internal name */
+ name = iupAttribGetHandleName(ih);
+ if (name)
+ iupTableRemove(inames_strtable, name);
- iupTableRemove(inames_ihtable, (char*)ih);
+ /* Do NOT search for other names */
}
Ihandle *IupGetHandle(const char *name)
@@ -104,22 +122,24 @@ Ihandle* IupSetHandle(const char *name, Ihandle *ih)
return NULL;
old_ih = iupTableGet(inames_strtable, name);
+
if (ih != NULL)
{
iupTableSet(inames_strtable, name, ih, IUPTABLE_POINTER);
- iupTableSet(inames_ihtable, (char*)ih, (char*)name, IUPTABLE_STRING); /* keep only the last name set */
+
+ /* save the name in the cache if it is a valid handle */
+ if (iupObjectCheck(ih))
+ iupAttribStoreStr(ih, "_IUP_LASTHANDLENAME", name);
}
else
{
- ih = iupTableGet(inames_strtable, name);
iupTableRemove(inames_strtable, name);
- if (ih)
- {
- char* cur_name = iupTableGet(inames_ihtable, (char*)ih);
- if (iupStrEqualNoCase(cur_name, name))
- iupTableRemove(inames_ihtable, (char*)ih);
- }
+
+ /* clear the name from the cache if it is a valid handle */
+ if (iupObjectCheck(old_ih))
+ iupAttribSetStr(old_ih, "_IUP_LASTHANDLENAME", NULL);
}
+
return old_ih;
}
@@ -151,7 +171,8 @@ static int iNamesCountDialogs(void)
while (name)
{
Ihandle* dlg = (Ihandle*)iupTableGetCurr(inames_strtable);
- if (iupObjectCheck(dlg) && dlg->iclass->nativetype == IUP_TYPEDIALOG)
+ if (iupObjectCheck(dlg) && /* here must be a handle */
+ dlg->iclass->nativetype == IUP_TYPEDIALOG)
i++;
name = iupTableNext(inames_strtable);
@@ -171,7 +192,8 @@ int IupGetAllDialogs(char** names, int n)
while (name)
{
Ihandle* dlg = (Ihandle*)iupTableGetCurr(inames_strtable);
- if (iupObjectCheck(dlg) && dlg->iclass->nativetype == IUP_TYPEDIALOG)
+ if (iupObjectCheck(dlg) && /* here must be a handle */
+ dlg->iclass->nativetype == IUP_TYPEDIALOG)
{
names[i] = name;
i++;
@@ -186,8 +208,32 @@ int IupGetAllDialogs(char** names, int n)
char* IupGetName(Ihandle* ih)
{
- iupASSERT(iupObjectCheck(ih));
- if (!iupObjectCheck(ih))
+ char *name;
+ if (!ih) /* no iupASSERT needed here */
return NULL;
- return iupTableGet(inames_ihtable, (char*)ih);
+
+ if (iupObjectCheck(ih))
+ {
+ /* check the cache first, but must be a handle */
+ name = iupAttribGet(ih, "_IUP_LASTHANDLENAME");
+ if (name)
+ return name;
+ }
+
+ /* check for an internal name */
+ name = iupAttribGetHandleName(ih);
+ if (name)
+ return name;
+
+ /* search for the name */
+ name = iupTableFirst(inames_strtable);
+ while (name)
+ {
+ if ((Ihandle*)iupTableGetCurr(inames_strtable) == ih)
+ return name;
+
+ name = iupTableNext(inames_strtable);
+ }
+
+ return NULL;
}
diff --git a/iup/src/iup_names.h b/iup/src/iup_names.h
index 9d3adc7..d652594 100755
--- a/iup/src/iup_names.h
+++ b/iup/src/iup_names.h
@@ -17,7 +17,7 @@ void iupNamesFinish(void);
void iupNamesDestroyHandles(void);
/* called from IupDestroy */
-void iupRemoveAllNames(Ihandle* ih);
+void iupRemoveNames(Ihandle* ih);
/* Other functions declared in <iup.h> and implemented here.
IupGetName
diff --git a/iup/src/iup_object.c b/iup/src/iup_object.c
index 7f4ce23..f0d5dc9 100755
--- a/iup/src/iup_object.c
+++ b/iup/src/iup_object.c
@@ -148,6 +148,8 @@ Ihandle* IupCreate(const char *name)
void IupDestroy(Ihandle *ih)
{
+ Icallback cb;
+
iupASSERT(iupObjectCheck(ih));
if (!iupObjectCheck(ih))
return;
@@ -156,6 +158,9 @@ void IupDestroy(Ihandle *ih)
if (ih->iclass->nativetype == IUP_TYPEDIALOG)
IupHide(ih);
+ cb = IupGetCallback(ih, "DESTROY_CB");
+ if (cb) cb(ih);
+
/* Destroy all its children.
Just need to remove the first child,
IupDetach will update firstchild. */
@@ -165,6 +170,9 @@ void IupDestroy(Ihandle *ih)
/* unmap if mapped and remove from its parent child list */
IupDetach(ih);
+ /* removes names associated with the element */
+ iupRemoveNames(ih);
+
/* destroy the element */
iupClassObjectDestroy(ih);
@@ -172,9 +180,6 @@ void IupDestroy(Ihandle *ih)
if (ih->data)
free(ih->data);
- /* removes all the names associated with the element */
- iupRemoveAllNames(ih);
-
/* destroy the base handle structure */
iHandleDestroy(ih);
}
diff --git a/iup/src/iup_object.h b/iup/src/iup_object.h
index 6f6b668..a69edc0 100755
--- a/iup/src/iup_object.h
+++ b/iup/src/iup_object.h
@@ -113,6 +113,7 @@ Ihandle* iupObjectCreate(Iclass* ic, void** params);
void** iupObjectGetParamList(void* first, va_list arglist);
/** Checks if the handle is still valid based on the signature.
+ * But if the handle was destroyed still can access invalid memory.
* \ingroup object */
int iupObjectCheck(Ihandle* ih);
diff --git a/iup/src/iup_open.c b/iup/src/iup_open.c
index e02561e..bce5c5c 100755
--- a/iup/src/iup_open.c
+++ b/iup/src/iup_open.c
@@ -101,8 +101,8 @@ void IupClose(void)
iupdrvSetIdleFunction(NULL); /* stop any idle */
- iupDlgListDestroyAll(); /* destroy all dialogs */
- iupNamesDestroyHandles(); /* destroy everything else that have names */
+ iupDlgListDestroyAll(); /* destroy all dialogs and their children */
+ iupNamesDestroyHandles(); /* destroy everything that do not belong to a dialog */
iupImageStockFinish(); /* release stock images hash table and the images */
iupRegisterFinish(); /* release native classes */
diff --git a/iup/src/iup_register.c b/iup/src/iup_register.c
index 4c58038..2e9954a 100755
--- a/iup/src/iup_register.c
+++ b/iup/src/iup_register.c
@@ -99,6 +99,7 @@ void iupRegisterInternalClasses(void)
iupRegisterClass(iupCboxGetClass());
iupRegisterClass(iupSboxGetClass());
iupRegisterClass(iupNormalizerGetClass());
+ iupRegisterClass(iupSplitGetClass());
iupRegisterClass(iupMenuGetClass());
iupRegisterClass(iupItemGetClass());
diff --git a/iup/src/iup_sbox.c b/iup/src/iup_sbox.c
index 5a71d33..9998481 100755
--- a/iup/src/iup_sbox.c
+++ b/iup/src/iup_sbox.c
@@ -57,6 +57,7 @@ static void iSboxSaveDimension(Ihandle* ih, int w, int h)
{
ih->data->w = w;
ih->data->h = h;
+ iupLayoutSetMinMaxSize(ih, &(ih->data->w), &(ih->data->h));
}
static void iSboxAddDecorOffset(Ihandle* ih, int *x, int *y)
diff --git a/iup/src/iup_show.c b/iup/src/iup_show.c
index 9ea1408..b42975e 100755
--- a/iup/src/iup_show.c
+++ b/iup/src/iup_show.c
@@ -53,35 +53,6 @@ void IupUnmap(Ihandle *ih)
ih->handle = NULL;
}
-static char* iShowGetVisible(Ihandle* ih)
-{
- char* value = iupAttribGet(ih, "VISIBLE"); /* Check on the element first */
- while (!value)
- {
- ih = ih->parent; /* iheritance here independs on the attribute */
- if (!ih)
- return NULL;
-
- value = iupAttribGet(ih, "VISIBLE");
-
- /* only recursive up to the native parent */
- if (ih->iclass->nativetype != IUP_TYPEVOID)
- return value; /* can be NULL */
- }
-
- return value;
-}
-
-static void iShowUpdateVisible(Ihandle* ih)
-{
- int inherit;
- /* although default is VISIBLE=YES,
- when mapped the element is still hidden.
- So we must manually update the visible state. */
- char* value = iShowGetVisible(ih);
- iupClassObjectSetAttribute(ih, "VISIBLE", value, &inherit);
-}
-
int IupMap(Ihandle* ih)
{
iupASSERT(iupObjectCheck(ih));
@@ -108,7 +79,7 @@ int IupMap(Ihandle* ih)
return IUP_ERROR;
}
- /* update FONT, must be the before several others */
+ /* update FONT, must be the before several others, so we do it here */
if (ih->iclass->nativetype != IUP_TYPEVOID &&
ih->iclass->nativetype != IUP_TYPEIMAGE &&
ih->iclass->nativetype != IUP_TYPEMENU)
@@ -117,18 +88,13 @@ int IupMap(Ihandle* ih)
/* ensure attributes default values, at this time only the ones that need to be set after map */
iupClassObjectEnsureDefaultAttributes(ih);
- /* check visible state if not a dialog */
- if (ih->iclass->nativetype == IUP_TYPECANVAS ||
- ih->iclass->nativetype == IUP_TYPECONTROL)
- iShowUpdateVisible(ih);
-
- /* updates the defined attributes in the native system. */
+ /* updates the defined attributes from the hash table to the native system. */
iupAttribUpdate(ih);
- /* updates attributes defined in the parent tree */
+ /* updates inheritable attributes defined in the parent tree */
iupAttribUpdateFromParent(ih);
- /* map children */
+ /* map children independent from childtype */
{
Ihandle* child = ih->firstchild;
while (child)
@@ -140,6 +106,10 @@ int IupMap(Ihandle* ih)
}
}
+ /* updates the defined attributes from the hash table to the native system. */
+ if (ih->iclass->childtype!=IUP_CHILDNONE)
+ iupAttribUpdateChildren(ih);
+
/* moves and resizes the elements to reflect the layout computation */
/* if the dialog is visible will be reflected in the user interface */
if (ih->iclass->nativetype == IUP_TYPEDIALOG)
diff --git a/iup/src/iup_spin.c b/iup/src/iup_spin.c
index 6fadab4..514703f 100755
--- a/iup/src/iup_spin.c
+++ b/iup/src/iup_spin.c
@@ -175,7 +175,7 @@ static int iSpinCreateMethod(Ihandle* ih, void** params)
static int iSpinboxCreateMethod(Ihandle* ih, void** params)
{
- Ihandle *spin, *ctrl;
+ Ihandle *spin;
if (!params || !(params[0]))
return IUP_ERROR;
@@ -184,8 +184,7 @@ static int iSpinboxCreateMethod(Ihandle* ih, void** params)
IupSetAttribute(ih, "MARGIN", "0x0");
IupSetAttribute(ih, "ALIGNMENT", "ACENTER");
- ctrl = (Ihandle*)(params[0]);
- iupChildTreeAppend(ih, ctrl);
+ /* IupText is already a child of Spinbox because of the IupHbox Create method */
spin = IupSpin();
iupChildTreeAppend(ih, spin);
@@ -249,7 +248,7 @@ Iclass* iupSpinboxGetClass(void)
ic->name = "spinbox";
ic->format = "h"; /* one Ihandle */
ic->nativetype = IUP_TYPEVOID;
- ic->childtype = IUP_CHILDNONE;
+ ic->childtype = IUP_CHILD_ONE; /* fake value to define it as a container */
ic->is_interactive = 0;
iupClassRegisterCallback(ic, "SPIN_CB", "i");
@@ -267,7 +266,7 @@ Iclass* iupSpinGetClass(void)
ic->name = "spin";
ic->format = NULL; /* no parameters */
ic->nativetype = IUP_TYPEVOID;
- ic->childtype = IUP_CHILDNONE;
+ ic->childtype = IUP_CHILD_ONE; /* fake value to define it as a container */
ic->is_interactive = 0;
/* Class functions */
diff --git a/iup/src/iup_split.c b/iup/src/iup_split.c
new file mode 100644
index 0000000..1829142
--- /dev/null
+++ b/iup/src/iup_split.c
@@ -0,0 +1,780 @@
+/** \file
+ * \brief iupsplit control
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iupkey.h"
+
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_layout.h"
+#include "iup_childtree.h"
+#include "iup_draw.h"
+
+
+enum { ISPLIT_VERT, ISPLIT_HORIZ };
+
+struct _IcontrolData
+{
+ /* aux */
+ int is_holding;
+ int start_pos, start_bar, start_size;
+
+ /* attributes */
+ int layoutdrag, autohide, showgrip, barsize;
+ int direction; /* one of the types: ISPLIT_VERT, ISPLIT_HORIZ */
+ int val; /* split value: 0-1000, default 500 */
+};
+
+static int iSplitGetWidth1(Ihandle* ih)
+{
+ int width1 = ((ih->currentwidth-ih->data->barsize)*ih->data->val)/1000;
+ if (width1 < 0) width1 = 0;
+ return width1;
+}
+
+static int iSplitGetHeight1(Ihandle* ih)
+{
+ int height1 = ((ih->currentheight-ih->data->barsize)*ih->data->val)/1000;
+ if (height1 < 0) height1 = 0;
+ return height1;
+}
+
+static void iSplitSetBarPosition(Ihandle* ih, int cur_x, int cur_y, int update)
+{
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ ih->firstchild->x = ih->data->start_bar + (cur_x - ih->data->start_pos);
+ if (ih->firstchild->x < ih->x)
+ ih->firstchild->x = ih->x;
+ if (ih->firstchild->x > ih->x+ih->currentwidth)
+ ih->firstchild->x = ih->x+ih->currentwidth;
+ }
+ else /* ISPLIT_HORIZ */
+ {
+ ih->firstchild->y = ih->data->start_bar + (cur_y - ih->data->start_pos);
+ if (ih->firstchild->y < ih->y)
+ ih->firstchild->y = ih->y;
+ if (ih->firstchild->y > ih->y+ih->currentheight)
+ ih->firstchild->y = ih->y+ih->currentheight;
+ }
+
+ if (update)
+ {
+ IupSetAttribute(ih->firstchild, "ZORDER", "TOP");
+ iupClassObjectLayoutUpdate(ih->firstchild);
+ }
+}
+
+static void iSplitShowHide(Ihandle* child, int hide)
+{
+ if (hide)
+ {
+ IupSetAttribute(child, "FLOATING", "YES");
+ IupSetAttribute(child, "VISIBLE", "NO");
+ }
+ else if (!IupGetInt(child, "VISIBLE"))
+ {
+ IupSetAttribute(child, "FLOATING", "NO");
+ IupSetAttribute(child, "VISIBLE", "YES");
+ }
+}
+
+static void iSplitAutoHideXY(Ihandle* ih)
+{
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ Ihandle *child1 = ih->firstchild->brother;
+ if (child1)
+ {
+ Ihandle *child2 = child1->brother;
+
+ iSplitShowHide(child1, ih->firstchild->x < ih->x+ih->data->barsize);
+
+ if (child2)
+ iSplitShowHide(child2, ih->firstchild->x > ih->x+ih->currentwidth-ih->data->barsize);
+ }
+ }
+ else /* ISPLIT_HORIZ */
+ {
+ Ihandle *child1 = ih->firstchild->brother;
+ if (child1)
+ {
+ Ihandle *child2 = child1->brother;
+
+ iSplitShowHide(child1, ih->firstchild->y < ih->y+ih->data->barsize);
+
+ if (child2)
+ iSplitShowHide(child2, ih->firstchild->y > ih->y+ih->currentheight-ih->data->barsize);
+ }
+ }
+}
+
+static void iSplitAutoHideVal(Ihandle* ih)
+{
+ Ihandle *child1 = ih->firstchild->brother;
+ if (child1)
+ {
+ int tol;
+ Ihandle *child2 = child1->brother;
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ if (ih->currentwidth <= ih->data->barsize)
+ return;
+
+ tol = (1000*ih->data->barsize)/ih->currentwidth;
+ }
+ else
+ {
+ if (ih->currentheight <= ih->data->barsize)
+ return;
+
+ tol = (1000*ih->data->barsize)/ih->currentheight;
+ }
+
+ iSplitShowHide(child1, ih->data->val<tol);
+
+ if (child2)
+ iSplitShowHide(child2, ih->data->val > 1000-tol);
+ }
+}
+
+
+/*****************************************************************************\
+|* Callbacks of canvas bar *|
+\*****************************************************************************/
+
+
+static int iSplitAction_CB(Ihandle* bar)
+{
+ Ihandle* ih = bar->parent;
+ IdrawCanvas* dc = iupDrawCreateCanvas(bar);
+
+ iupDrawParentBackground(dc);
+
+ if (ih->data->showgrip)
+ {
+ int i, w, h, x, y, count;
+ unsigned char r = 160, g = 160, b = 160, bg_r, bg_g, bg_b;
+ iupDrawGetSize(dc, &w, &h);
+
+ iupStrToRGB(IupGetAttribute(ih, "COLOR"), &r, &g, &b);
+ if (r+g+b > 3*190)
+ { bg_r = 100; bg_g = 100; bg_b = 100; }
+ else
+ { bg_r = 255; bg_g = 255; bg_b = 255; }
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ x = ih->data->barsize/2-1;
+ y = 2;
+ count = (h-2)/5;
+ }
+ else
+ {
+ x = 2;
+ y = ih->data->barsize/2-1;
+ count = (w-2)/5;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ iupDrawRectangle(dc, x+1, y+1, x+2, y+2, bg_r, bg_g, bg_b, 1);
+ iupDrawRectangle(dc, x, y, x+1, y+1, r, g, b, 1);
+ if (ih->data->direction == ISPLIT_VERT)
+ y += 5;
+ else
+ x += 5;
+ }
+ }
+
+ iupDrawFlush(dc);
+
+ iupDrawKillCanvas(dc);
+
+ return IUP_DEFAULT;
+}
+
+static int iSplitMotion_CB(Ihandle* bar, int x, int y, char *status)
+{
+ Ihandle* ih = bar->parent;
+
+ if (ih->data->is_holding)
+ {
+ if (iup_isbutton1(status))
+ {
+ int cur_x, cur_y;
+
+ iupStrToIntInt(IupGetGlobal("CURSORPOS"), &cur_x, &cur_y, 'x');
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ int width1 = iSplitGetWidth1(ih);
+ width1 = ih->data->start_size + (cur_x - ih->data->start_pos);
+ ih->data->val = (width1*1000)/(ih->currentwidth-ih->data->barsize);
+ }
+ else
+ {
+ int height1 = iSplitGetHeight1(ih);
+ height1 = ih->data->start_size + (cur_y - ih->data->start_pos);
+ ih->data->val = (height1*1000)/(ih->currentheight-ih->data->barsize);
+ }
+
+ if (ih->data->val < 0) ih->data->val = 0;
+ if (ih->data->val > 1000) ih->data->val = 1000;
+
+ if (ih->data->layoutdrag)
+ {
+ if (ih->data->autohide)
+ {
+ iSplitSetBarPosition(ih, cur_x, cur_y, 0);
+ iSplitAutoHideXY(ih);
+ }
+
+ IupRefresh(ih); /* may affect all the elements in the dialog */
+ }
+ else
+ iSplitSetBarPosition(ih, cur_x, cur_y, 1);
+ }
+ else
+ ih->data->is_holding = 0;
+ }
+
+ (void)x;
+ (void)y;
+ return IUP_DEFAULT;
+}
+
+static int iSplitButton_CB(Ihandle* bar, int button, int pressed, int x, int y, char* status)
+{
+ Ihandle* ih = bar->parent;
+
+ if (button!=IUP_BUTTON1)
+ return IUP_DEFAULT;
+
+ if (!ih->data->is_holding && pressed)
+ {
+ int cur_x, cur_y;
+
+ ih->data->is_holding = 1;
+
+ iupStrToIntInt(IupGetGlobal("CURSORPOS"), &cur_x, &cur_y, 'x');
+
+ /* Save the cursor position and size */
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ ih->data->start_bar = ih->firstchild->x;
+ ih->data->start_pos = cur_x;
+ ih->data->start_size = iSplitGetWidth1(ih);
+ }
+ else
+ {
+ ih->data->start_bar = ih->firstchild->y;
+ ih->data->start_pos = cur_y;
+ ih->data->start_size = iSplitGetHeight1(ih);
+ }
+ }
+ else if (ih->data->is_holding && !pressed)
+ {
+ ih->data->is_holding = 0;
+
+ if (!ih->data->layoutdrag)
+ {
+ if (ih->data->autohide)
+ {
+ int cur_x, cur_y;
+ iupStrToIntInt(IupGetGlobal("CURSORPOS"), &cur_x, &cur_y, 'x');
+ iSplitSetBarPosition(ih, cur_x, cur_y, 0);
+ iSplitAutoHideXY(ih);
+ }
+
+ IupRefresh(ih); /* may affect all the elements in the dialog */
+ }
+ }
+
+ (void)x;
+ (void)y;
+ (void)status;
+ return IUP_DEFAULT;
+}
+
+static int iSplitFocus_CB(Ihandle* bar, int focus)
+{
+ Ihandle* ih = bar->parent;
+
+ if (!ih || focus) /* use only kill focus */
+ return IUP_DEFAULT;
+
+ if (ih->data->is_holding)
+ ih->data->is_holding = 0;
+
+ return IUP_DEFAULT;
+}
+
+
+/*****************************************************************************\
+|* Attributes *|
+\*****************************************************************************/
+
+
+static char* iSplitGetClientSize1Attrib(Ihandle* ih)
+{
+ int width, height;
+ char* str = iupStrGetMemory(20);
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ width = iSplitGetWidth1(ih);
+ height = ih->currentheight;
+ }
+ else /* ISPLIT_HORIZ */
+ {
+ height = iSplitGetHeight1(ih);
+ width = ih->currentwidth;
+ }
+
+ sprintf(str, "%dx%d", width, height);
+ return str;
+}
+
+static char* iSplitGetClientSize2Attrib(Ihandle* ih)
+{
+ int width, height;
+ char* str = iupStrGetMemory(20);
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ int width1 = iSplitGetWidth1(ih);
+
+ width = (ih->currentwidth-ih->data->barsize)-width1;
+ if (width < 0) width = 0;
+
+ height = ih->currentheight;
+ }
+ else /* ISPLIT_HORIZ */
+ {
+ int height1 = iSplitGetHeight1(ih);
+
+ height = (ih->currentheight-ih->data->barsize)-height1;
+ if (height < 0) height = 0;
+
+ width = ih->currentwidth;
+ }
+
+ sprintf(str, "%dx%d", width, height);
+ return str;
+}
+
+static int iSplitSetColorAttrib(Ihandle* ih, const char* value)
+{
+ (void)value;
+ iupdrvPostRedraw(ih);
+ return 1; /* store value in hash table */
+}
+
+static int iSplitSetDirectionAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->handle) /* only before map */
+ return 0;
+
+ if (iupStrEqual(value, "HORIZONTAL"))
+ ih->data->direction = ISPLIT_HORIZ;
+ else /* Default = VERTICAL */
+ ih->data->direction = ISPLIT_VERT;
+
+ if (ih->data->direction == ISPLIT_VERT)
+ IupSetAttribute(ih->firstchild, "CURSOR", "SPLITTER_VERT");
+ else
+ IupSetAttribute(ih->firstchild, "CURSOR", "SPLITTER_HORIZ");
+
+ return 0; /* do not store value in hash table */
+}
+
+static int iSplitSetValueAttrib(Ihandle* ih, const char* value)
+{
+ if (!value)
+ {
+ ih->data->val = -1;
+
+ if (ih->data->autohide)
+ iSplitAutoHideVal(ih);
+
+ if (ih->handle)
+ IupRefresh(ih); /* may affect all the elements in the dialog */
+ }
+ else
+ {
+ int val;
+ if (iupStrToInt(value, &val))
+ {
+ ih->data->val = val;
+
+ if (ih->data->autohide)
+ iSplitAutoHideVal(ih);
+
+ if (ih->handle)
+ IupRefresh(ih); /* may affect all the elements in the dialog */
+ }
+ }
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iSplitGetValueAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(30);
+ sprintf(str, "%d", ih->data->val);
+ return str;
+}
+
+static int iSplitSetBarSizeAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrToInt(value, &ih->data->barsize))
+ {
+ if (ih->data->autohide)
+ iSplitAutoHideVal(ih);
+
+ if (ih->handle)
+ IupRefresh(ih); /* may affect all the elements in the dialog */
+ }
+ return 0; /* do not store value in hash table */
+}
+
+static char* iSplitGetBarSizeAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(30);
+ sprintf(str, "%d", ih->data->barsize);
+ return str;
+}
+
+static int iSplitSetLayoutDragAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ ih->data->layoutdrag = 1;
+ else
+ ih->data->layoutdrag = 0;
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iSplitGetLayoutDragAttrib(Ihandle* ih)
+{
+ if (ih->data->layoutdrag)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iSplitSetShowGripAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ ih->data->showgrip = 1;
+ else
+ {
+ ih->data->showgrip = 0;
+
+ if (ih->data->barsize == 5)
+ iSplitSetBarSizeAttrib(ih, "3");
+ }
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iSplitGetShowGripAttrib(Ihandle* ih)
+{
+ if (ih->data->showgrip)
+ return "YES";
+ else
+ return "NO";
+}
+
+static int iSplitSetAutoHideAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ {
+ ih->data->autohide = 1;
+ iSplitAutoHideVal(ih);
+ }
+ else
+ {
+ Ihandle *child1 = ih->firstchild->brother;
+ if (child1)
+ {
+ Ihandle *child2 = child1->brother;
+ iSplitShowHide(child1, 0);
+ if (child2)
+ iSplitShowHide(child2, 0);
+ }
+
+ ih->data->autohide = 0;
+ }
+
+ return 0; /* do not store value in hash table */
+}
+
+static char* iSplitGetAutoHideAttrib(Ihandle* ih)
+{
+ if (ih->data->autohide)
+ return "YES";
+ else
+ return "NO";
+}
+
+
+/*****************************************************************************\
+|* Methods *|
+\*****************************************************************************/
+
+
+static void iSplitComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+{
+ int natural_w = 0,
+ natural_h = 0;
+ Ihandle *child1, *child2 = NULL;
+ child1 = ih->firstchild->brother;
+ if (child1)
+ child2 = child1->brother;
+
+ /* always has at least one child, the bar, not necessary to compute its natural size */
+ if (ih->data->direction == ISPLIT_VERT)
+ natural_w += ih->data->barsize;
+ else
+ natural_h += ih->data->barsize;
+
+ if (child1)
+ {
+ /* update child natural size first */
+ iupBaseComputeNaturalSize(child1);
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ natural_w += child1->naturalwidth;
+ natural_h = iupMAX(natural_h, child1->naturalheight);
+ }
+ else
+ {
+ natural_w = iupMAX(natural_w, child1->naturalwidth);
+ natural_h += child1->naturalheight;
+ }
+
+ *expand = child1->expand;
+
+ if (child2)
+ {
+ /* update child natural size first */
+ iupBaseComputeNaturalSize(child2);
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ natural_w += child2->naturalwidth;
+ natural_h = iupMAX(natural_h, child2->naturalheight);
+ }
+ else
+ {
+ natural_w = iupMAX(natural_w, child2->naturalwidth);
+ natural_h += child2->naturalheight;
+ }
+
+ *expand |= child2->expand;
+ }
+ }
+
+ if (ih->data->val == -1)
+ {
+ if (child1)
+ {
+ if (ih->data->direction == ISPLIT_VERT)
+ ih->data->val = (child1->naturalwidth*1000)/(natural_w-ih->data->barsize);
+ else
+ ih->data->val = (child1->naturalheight*1000)/(natural_h-ih->data->barsize);
+
+ if (ih->data->val < 0) ih->data->val = 0;
+ if (ih->data->val > 1000) ih->data->val = 1000;
+ }
+ else
+ ih->data->val = 0;
+ }
+
+ *w = natural_w;
+ *h = natural_h;
+}
+
+static void iSplitSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
+{
+ Ihandle *child1, *child2 = NULL;
+ child1 = ih->firstchild->brother;
+ if (child1)
+ child2 = child1->brother;
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ int width2 = 0;
+
+ if (child1)
+ {
+ int width1 = iSplitGetWidth1(ih);
+ iupBaseSetCurrentSize(child1, width1, ih->currentheight, shrink);
+
+ width2 = (ih->currentwidth-ih->data->barsize)-width1;
+ if (width2 < 0) width2 = 0;
+ }
+
+ /* bar */
+ ih->firstchild->currentwidth = ih->data->barsize;
+ ih->firstchild->currentheight = ih->currentheight;
+
+ if (child2)
+ iupBaseSetCurrentSize(child2, width2, ih->currentheight, shrink);
+ }
+ else /* ISPLIT_HORIZ */
+ {
+ int height2 = 0;
+
+ if (child1)
+ {
+ int height1 = iSplitGetHeight1(ih);
+ iupBaseSetCurrentSize(child1, ih->currentwidth, height1, shrink);
+
+ height2 = (ih->currentheight-ih->data->barsize)-height1;
+ if (height2 < 0) height2 = 0;
+ }
+
+ /* bar */
+ ih->firstchild->currentwidth = ih->currentwidth;
+ ih->firstchild->currentheight = ih->data->barsize;
+
+ if (child2)
+ iupBaseSetCurrentSize(child2, ih->currentwidth, height2, shrink);
+ }
+}
+
+static void iSplitSetChildrenPositionMethod(Ihandle* ih, int x, int y)
+{
+ Ihandle *child1, *child2 = NULL;
+ child1 = ih->firstchild->brother;
+ if (child1)
+ child2 = child1->brother;
+
+ if (ih->data->direction == ISPLIT_VERT)
+ {
+ if (child1)
+ iupBaseSetPosition(child1, x, y);
+ x += iSplitGetWidth1(ih);
+
+ /* bar */
+ iupBaseSetPosition(ih->firstchild, x, y);
+ x += ih->data->barsize;
+
+ if (child2)
+ iupBaseSetPosition(child2, x, y);
+ }
+ else /* ISPLIT_HORIZ */
+ {
+ if (child1)
+ iupBaseSetPosition(child1, x, y);
+ y += iSplitGetHeight1(ih);
+
+ /* bar */
+ iupBaseSetPosition(ih->firstchild, x, y);
+ y += ih->data->barsize;
+
+ if (child2)
+ iupBaseSetPosition(child2, x, y);
+ }
+}
+
+static int iSplitCreateMethod(Ihandle* ih, void** params)
+{
+ Ihandle* bar;
+
+ ih->data = iupALLOCCTRLDATA();
+
+ ih->data->direction = ISPLIT_VERT;
+ ih->data->val = -1;
+ ih->data->layoutdrag = 1;
+ ih->data->autohide = 0;
+ ih->data->barsize = 5;
+ ih->data->showgrip = 1;
+
+ bar = IupCanvas(NULL);
+ iupChildTreeAppend(ih, bar); /* bar will always be the firstchild */
+
+ IupSetAttribute(bar, "CANFOCUS", "NO");
+ IupSetAttribute(bar, "BORDER", "NO");
+ IupSetAttribute(bar, "EXPAND", "NO");
+ IupSetAttribute(bar, "CURSOR", "SPLITTER_VERT");
+
+ /* Setting callbacks */
+ IupSetCallback(bar, "BUTTON_CB", (Icallback) iSplitButton_CB);
+ IupSetCallback(bar, "FOCUS_CB", (Icallback) iSplitFocus_CB);
+ IupSetCallback(bar, "MOTION_CB", (Icallback) iSplitMotion_CB);
+ IupSetCallback(bar, "ACTION", (Icallback) iSplitAction_CB);
+
+ if (params)
+ {
+ Ihandle** iparams = (Ihandle**)params;
+ if (iparams[0]) IupAppend(ih, iparams[0]);
+ if (iparams[1]) IupAppend(ih, iparams[1]);
+ }
+
+ return IUP_NOERROR;
+}
+
+Iclass* iupSplitGetClass(void)
+{
+ Iclass* ic = iupClassNew(NULL);
+
+ ic->name = "split";
+ ic->format = "HH"; /* two optional ihandle */
+ ic->nativetype = IUP_TYPEVOID;
+ ic->childtype = IUP_CHILDMANY;
+ ic->is_interactive = 0;
+
+ /* Class functions */
+ ic->Create = iSplitCreateMethod;
+ ic->Map = iupBaseTypeVoidMapMethod;
+
+ ic->ComputeNaturalSize = iSplitComputeNaturalSizeMethod;
+ ic->SetChildrenCurrentSize = iSplitSetChildrenCurrentSizeMethod;
+ ic->SetChildrenPosition = iSplitSetChildrenPositionMethod;
+
+ /* Common */
+ iupBaseRegisterCommonAttrib(ic);
+
+ /* Base Container */
+ iupClassRegisterAttribute(ic, "CLIENTSIZE1", iSplitGetClientSize1Attrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CLIENTSIZE2", iSplitGetClientSize2Attrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EXPAND", iupBaseContainerGetExpandAttrib, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* IupSplit only */
+ iupClassRegisterAttribute(ic, "COLOR", NULL, iSplitSetColorAttrib, IUPAF_SAMEASSYSTEM, "160 160 160", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DIRECTION", NULL, iSplitSetDirectionAttrib, IUPAF_SAMEASSYSTEM, "VERTICAL", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE", iSplitGetValueAttrib, iSplitSetValueAttrib, IUPAF_SAMEASSYSTEM, "500", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "LAYOUTDRAG", iSplitGetLayoutDragAttrib, iSplitSetLayoutDragAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWGRIP", iSplitGetShowGripAttrib, iSplitSetShowGripAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AUTOHIDE", iSplitGetAutoHideAttrib, iSplitSetAutoHideAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "BARSIZE", iSplitGetBarSizeAttrib, iSplitSetBarSizeAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ return ic;
+}
+
+Ihandle* IupSplit(Ihandle* child1, Ihandle* child2)
+{
+ void *params[3];
+ params[0] = (void*)child1;
+ params[1] = (void*)child2;
+ params[2] = NULL;
+ return IupCreatev("split", params);
+}
diff --git a/iup/src/iup_stdcontrols.h b/iup/src/iup_stdcontrols.h
index 11499ae..0f3deb9 100755
--- a/iup/src/iup_stdcontrols.h
+++ b/iup/src/iup_stdcontrols.h
@@ -46,6 +46,7 @@ Iclass* iupZboxGetClass(void);
Iclass* iupCboxGetClass(void);
Iclass* iupSboxGetClass(void);
Iclass* iupNormalizerGetClass(void);
+Iclass* iupSplitGetClass(void);
Iclass* iupTimerGetClass(void);
Iclass* iupImageGetClass(void);
diff --git a/iup/src/iup_str.c b/iup/src/iup_str.c
index 68976f1..5f5b85d 100755
--- a/iup/src/iup_str.c
+++ b/iup/src/iup_str.c
@@ -147,8 +147,9 @@ char *iupStrCopyUntil(char **str, int c)
return NULL;
p_str=strchr(*str,c);
- if (!p_str) return NULL;
-
+ if (!p_str)
+ return NULL;
+ else
{
int i;
int sl=(int)(p_str - (*str));
@@ -160,10 +161,10 @@ char *iupStrCopyUntil(char **str, int c)
new_str[i] = (*str)[i];
new_str[sl] = 0;
- }
- *str = p_str+1;
- return new_str;
+ *str = p_str+1;
+ return new_str;
+ }
}
char *iupStrCopyUntilNoCase(char **str, int c)
@@ -174,11 +175,12 @@ char *iupStrCopyUntilNoCase(char **str, int c)
p_str=strchr(*str,c); /* usually the lower case is enough */
if (!p_str && isalpha(c))
- {
p_str=strchr(*str, toupper(c)); /* but check also for upper case */
- if (!p_str) return NULL;
- }
+ /* if both fail, then abort */
+ if (!p_str)
+ return NULL;
+ else
{
int i;
int sl=(int)(p_str - (*str));
@@ -190,10 +192,10 @@ char *iupStrCopyUntilNoCase(char **str, int c)
new_str[i] = (*str)[i];
new_str[sl] = 0;
- }
- *str = p_str+1;
- return new_str;
+ *str = p_str+1;
+ return new_str;
+ }
}
char *iupStrGetMemory(int size)
diff --git a/iup/src/iup_table.c b/iup/src/iup_table.c
index 9e97ff5..a873191 100755
--- a/iup/src/iup_table.c
+++ b/iup/src/iup_table.c
@@ -19,12 +19,12 @@
/* Adjust these parameters for optimal performance and memory usage */
static const unsigned int itable_maxTableSizeIndex = 8;
static const unsigned int itable_hashTableSize[] = { 31, 101, 401, 1601, 4001, 8009, 16001, 32003, 64007 };
-static const float itable_resizeLimit = 2;
+static const unsigned int itable_resizeLimit = 2;
static const unsigned int itable_itemGrow = 5;
/* Iteration context.
*/
-typedef struct ItableContext
+typedef struct _ItableContext
{
unsigned int entryIndex; /* index at the Itable::entries array */
unsigned int itemIndex; /* index at the ItableEntry::items array */
@@ -41,7 +41,7 @@ typedef struct ItableContext
* this is simply the pointer (in this case keyIndex
* and keyStr are equal).
*/
-typedef struct ItableKey
+typedef struct _ItableKey
{
unsigned long keyIndex; /* the secondary hash number */
const char *keyStr;
@@ -52,11 +52,11 @@ ItableKey;
* Such an item is stored in the item list of
* an entry.
*/
-typedef struct ItableItem
+typedef struct _ItableItem
{
Itable_Types itemType;
- ItableKey key;
- void *value;
+ ItableKey key;
+ void* value;
}
ItableItem;
@@ -67,29 +67,28 @@ ItableItem;
* in nextItemIndex.
* size is the current size of the items array.
*/
-typedef struct ItableEntry
+typedef struct _ItableEntry
{
unsigned int nextItemIndex;
- unsigned int size;
- ItableItem *items;
+ unsigned int itemsSize;
+ ItableItem* items;
}
ItableEntry;
/* A hash table.
- * indexType is the type of the index.
* entries is an array of entries. Select an
* entry by its index.
* size is the number of entries in the hash table...
*/
-struct Itable
+struct _Itable
{
- unsigned int size;
- unsigned int numberOfEntries;
- unsigned int tableSizeIndex; /* index into itable_hashTableSize array */
- Itable_IndexTypes indexType;
- ItableEntry *entries;
- ItableContext context;
+ unsigned int entriesSize;
+ unsigned int numberOfEntries;
+ unsigned int tableSizeIndex; /* index into itable_hashTableSize array */
+ Itable_IndexTypes indexType; /* type of the index: string or pointer. */
+ ItableEntry *entries;
+ ItableContext context;
};
@@ -121,8 +120,7 @@ Itable *iupTableCreate(Itable_IndexTypes indexType)
Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSizeIndex)
{
- Itable *it = (Itable *)malloc(sizeof(struct Itable));
-
+ Itable *it = (Itable *)malloc(sizeof(Itable));
iupASSERT(it!=NULL);
if (!it)
return 0;
@@ -130,12 +128,12 @@ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSiz
if (initialSizeIndex > itable_maxTableSizeIndex)
initialSizeIndex = itable_maxTableSizeIndex;
- it->size = itable_hashTableSize[initialSizeIndex];
+ it->entriesSize = itable_hashTableSize[initialSizeIndex];
it->tableSizeIndex = initialSizeIndex;
it->numberOfEntries = 0;
it->indexType = indexType;
- it->entries = (ItableEntry *)malloc(it->size * sizeof(ItableEntry));
+ it->entries = (ItableEntry *)malloc(it->entriesSize * sizeof(ItableEntry));
iupASSERT(it->entries!=NULL);
if (!it->entries)
{
@@ -143,7 +141,7 @@ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSiz
return 0;
}
- memset(it->entries, 0, it->size * sizeof(ItableEntry));
+ memset(it->entries, 0, it->entriesSize * sizeof(ItableEntry));
it->context.entryIndex = (unsigned int)-1;
it->context.itemIndex = (unsigned int)-1;
@@ -158,16 +156,19 @@ void iupTableClear(Itable *it)
if (!it)
return;
- for (i = 0; i < it->size; i++)
+ for (i = 0; i < it->entriesSize; i++)
{
ItableEntry *entry = &(it->entries[i]);
if (entry->items)
+ {
iTableFreeItemArray(it->indexType, entry->nextItemIndex, entry->items);
+ entry->items = NULL;
+ }
}
it->numberOfEntries = 0;
- memset(it->entries, 0, it->size * sizeof(ItableEntry));
+ memset(it->entries, 0, it->entriesSize * sizeof(ItableEntry));
it->context.entryIndex = (unsigned int)-1;
it->context.itemIndex = (unsigned int)-1;
@@ -185,7 +186,10 @@ void iupTableDestroy(Itable *it)
iupTableClear(it);
if (it->entries)
+ {
free(it->entries);
+ it->entries = NULL;
+ }
free(it);
}
@@ -288,17 +292,23 @@ static void iTableRemoveItem(Itable *it, ItableEntry *entry, unsigned int itemIn
item = &(entry->items[itemIndex]);
if (it->indexType == IUPTABLE_STRINGINDEXED)
+ {
free((void *)item->key.keyStr);
+ item->key.keyStr = NULL;
+ }
if (item->itemType == IUPTABLE_STRING)
+ {
free(item->value);
+ item->value = NULL;
+ }
- /* order the remaining items */
+ /* re-order the remaining items */
for (i = itemIndex; i < entry->nextItemIndex-1; i++)
entry->items[i] = entry->items[i+1];
- /* clear the non used item */
- memset(entry->items + entry->nextItemIndex, 0, sizeof (ItableItem));
+ /* clear the released item */
+ memset(entry->items + entry->nextItemIndex-1, 0, sizeof (ItableItem));
entry->nextItemIndex--;
it->numberOfEntries--;
@@ -398,7 +408,7 @@ char *iupTableFirst(Itable *it)
it->context.itemIndex = (unsigned int)-1;
/* find the first used entry */
- for (entryIndex = 0; entryIndex < it->size; entryIndex++)
+ for (entryIndex = 0; entryIndex < it->entriesSize; entryIndex++)
{
if (it->entries[entryIndex].nextItemIndex > 0)
{
@@ -430,7 +440,7 @@ char *iupTableNext(Itable *it)
else
{
/* find the next used entry */
- for (entryIndex = it->context.entryIndex+1; entryIndex < it->size; entryIndex++)
+ for (entryIndex = it->context.entryIndex+1; entryIndex < it->entriesSize; entryIndex++)
{
if (it->entries[entryIndex].nextItemIndex > 0)
{
@@ -471,7 +481,7 @@ char *iupTableRemoveCurr(Itable *it)
else
{
/* find the next used entry */
- for (entryIndex = it->context.entryIndex+1; entryIndex < it->size; entryIndex++)
+ for (entryIndex = it->context.entryIndex+1; entryIndex < it->entriesSize; entryIndex++)
{
if (it->entries[entryIndex].nextItemIndex > 0)
{
@@ -498,6 +508,8 @@ static void iTableFreeItemArray(Itable_IndexTypes indexType, unsigned int nextFr
{
unsigned int i;
+ /* Used only in iupTableClear */
+
iupASSERT(items!=NULL);
if (!items)
return;
@@ -505,13 +517,19 @@ static void iTableFreeItemArray(Itable_IndexTypes indexType, unsigned int nextFr
if (indexType == IUPTABLE_STRINGINDEXED)
{
for (i = 0; i < nextFreeIndex; i++)
+ {
free((void *)(items[i].key.keyStr));
+ items[i].key.keyStr = NULL;
+ }
}
for (i = 0; i < nextFreeIndex; i++)
{
if (items[i].itemType == IUPTABLE_STRING)
+ {
free(items[i].value);
+ items[i].value = NULL;
+ }
}
free(items);
@@ -545,7 +563,7 @@ static unsigned int iTableGetEntryIndex(Itable *it, const char *key, unsigned lo
*keyIndex = (unsigned long)key; /* this could NOT be dependent from table size */
}
- return (unsigned int)((*keyIndex) % it->size);
+ return (unsigned int)((*keyIndex) % it->entriesSize);
}
#ifdef DEBUGTABLE
@@ -603,25 +621,24 @@ static unsigned int iTableFindItem(Itable *it, const char *key, ItableEntry **en
static void iTableUpdateArraySize(ItableEntry *entry)
{
- if (entry->nextItemIndex >= entry->size)
+ if (entry->nextItemIndex >= entry->itemsSize)
{
/* we have to expand the item array */
unsigned int newSize;
- newSize = entry->size + itable_itemGrow;
+ newSize = entry->itemsSize + itable_itemGrow;
entry->items = (ItableItem *)realloc(entry->items, newSize * sizeof(ItableItem));
iupASSERT(entry->items!=NULL);
if (!entry->items)
return;
- memset(entry->items + entry->size, 0, itable_itemGrow * sizeof(ItableItem));
+ memset(entry->items + entry->itemsSize, 0, itable_itemGrow * sizeof(ItableItem));
- entry->size = newSize;
+ entry->itemsSize = newSize;
}
}
-
static void iTableAdd(Itable *it, ItableKey *key, void *value, Itable_Types itemType)
{
unsigned int entryIndex;
@@ -657,7 +674,7 @@ static unsigned int iTableResize(Itable *it)
/* check if we do not need to resize the hash table */
if (it->numberOfEntries == 0 ||
it->tableSizeIndex >= itable_maxTableSizeIndex ||
- it->size / it->numberOfEntries >= itable_resizeLimit)
+ it->entriesSize / it->numberOfEntries >= itable_resizeLimit)
return 0;
/* create a new hash table and copy the contents of
@@ -666,7 +683,7 @@ static unsigned int iTableResize(Itable *it)
newSizeIndex = it->tableSizeIndex + 1;
newTable = iupTableCreateSized(it->indexType, newSizeIndex);
- for (entryIndex = 0; entryIndex < it->size; entryIndex++)
+ for (entryIndex = 0; entryIndex < it->entriesSize; entryIndex++)
{
entry = &(it->entries[entryIndex]);
@@ -680,12 +697,13 @@ static unsigned int iTableResize(Itable *it)
}
free(entry->items);
+ entry->items = NULL;
}
}
free(it->entries);
- it->size = newTable->size;
+ it->entriesSize = newTable->entriesSize;
it->tableSizeIndex = newTable->tableSizeIndex;
it->numberOfEntries = newTable->numberOfEntries;
it->entries = newTable->entries;
@@ -712,11 +730,11 @@ static void iTableShowStatistics(Itable *it)
return;
}
- nofSlots = it->size;
+ nofSlots = it->entriesSize;
nofKeys = it->numberOfEntries;
optimalNofKeysPerSlot = (double)nofKeys / (double)nofSlots;
- for (entryIndex = 0; entryIndex < it->size; entryIndex++)
+ for (entryIndex = 0; entryIndex < it->entriesSize; entryIndex++)
{
ItableEntry *entry = &(it->entries[entryIndex]);
diff --git a/iup/src/iup_table.h b/iup/src/iup_table.h
index 5222160..f2ff2c7 100755
--- a/iup/src/iup_table.h
+++ b/iup/src/iup_table.h
@@ -42,8 +42,8 @@ typedef enum _Itable_Types
typedef void (*Ifunc)(void);
-struct Itable;
-typedef struct Itable Itable;
+struct _Itable;
+typedef struct _Itable Itable;
/** Creates a hash table with an initial default size.
@@ -63,7 +63,7 @@ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSiz
/** Destroys the Itable.
* Calls \ref iupTableClear.
* \ingroup table */
-void iupTableDestroy(Itable *n);
+void iupTableDestroy(Itable *it);
/** Removes all items in the table.
* This function does also free the memory of strings contained in the table!!!!
@@ -76,33 +76,33 @@ int iupTableCount(Itable *it);
/** Store an element in the table.
* \ingroup table */
-void iupTableSet(Itable *n, const char *key, void *value, Itable_Types itemType);
+void iupTableSet(Itable *it, const char *key, void *value, Itable_Types itemType);
/** Store a function pointer in the table.
* Type is set to IUPTABLE_FUNCPOINTER.
* \ingroup table */
-void iupTableSetFunc(Itable *n, const char *key, Ifunc func);
+void iupTableSetFunc(Itable *it, const char *key, Ifunc func);
/** Retrieves an element from the table.
* Returns NULL if not found.
* \ingroup table */
-void *iupTableGet(Itable *n, const char *key);
+void *iupTableGet(Itable *it, const char *key);
/** Retrieves a function pointer from the table.
* If not a function or not found returns NULL.
* value always contains the element pointer.
* \ingroup table */
-Ifunc iupTableGetFunc(Itable *n, const char *key, void **value);
+Ifunc iupTableGetFunc(Itable *it, const char *key, void **value);
/** Retrieves an element from the table and its type.
* \ingroup table */
-void *iupTableGetTyped(Itable *n, const char *key, Itable_Types *itemType);
+void *iupTableGetTyped(Itable *it, const char *key, Itable_Types *itemType);
/** Removes the entry at the specified key from the
* hash table and frees the memory used by it if
* it is a string...
* \ingroup table */
-void iupTableRemove(Itable *n, const char *key);
+void iupTableRemove(Itable *it, const char *key);
/** Key iteration function. Returns a key.
* To iterate over all keys call iupTableFirst at the first
diff --git a/iup/src/iup_tabs.c b/iup/src/iup_tabs.c
index 77b2cf5..2907371 100755
--- a/iup/src/iup_tabs.c
+++ b/iup/src/iup_tabs.c
@@ -307,6 +307,25 @@ static char* iTabsGetClientSizeAttrib(Ihandle* ih)
return str;
}
+void iupTabsTestRemoveTab(Ihandle* ih, int pos)
+{
+ int cur_pos = iupdrvTabsGetCurrentTab(ih);
+ if (cur_pos == pos)
+ {
+ if (cur_pos == 0)
+ {
+ Ihandle* child = IupGetChild(ih, 1);
+ if (!child) /* not found child, means only one child, do nothing */
+ return;
+
+ cur_pos = 1;
+ }
+ else
+ cur_pos--;
+
+ iupdrvTabsSetCurrentTab(ih, cur_pos);
+ }
+}
/* ------------------------------------------------------------------------- */
/* TABS - Methods */
diff --git a/iup/src/iup_tabs.h b/iup/src/iup_tabs.h
index 7f5df2e..fd0edf4 100755
--- a/iup/src/iup_tabs.h
+++ b/iup/src/iup_tabs.h
@@ -16,6 +16,7 @@ char* iupTabsGetTabOrientationAttrib(Ihandle* ih);
char* iupTabsGetTabTypeAttrib(Ihandle* ih);
char* iupTabsAttribGetStrId(Ihandle* ih, const char* name, int pos);
char* iupTabsGetPaddingAttrib(Ihandle* ih);
+void iupTabsTestRemoveTab(Ihandle* ih, int pos);
int iupdrvTabsExtraDecor(Ihandle* ih);
int iupdrvTabsGetLineCountAttrib(Ihandle* ih);
diff --git a/iup/src/iup_tree.c b/iup/src/iup_tree.c
index c06e573..b5344f5 100755
--- a/iup/src/iup_tree.c
+++ b/iup/src/iup_tree.c
@@ -200,6 +200,240 @@ void iupTreeUpdateImages(Ihandle *ih)
iupClassObjectSetAttribute(ih, "IMAGEBRANCHEXPANDED", value, &inherit);
}
+void iupTreeSelectLastCollapsedBranch(Ihandle* ih, int *last_id)
+{
+ /* if last selected item is a branch, then select its children */
+ if (iupStrEqual(IupTreeGetAttribute(ih, "KIND", *last_id), "BRANCH") &&
+ iupStrEqual(IupTreeGetAttribute(ih, "STATE", *last_id), "COLLAPSED"))
+ {
+ int childcount = IupTreeGetInt(ih, "CHILDCOUNT", *last_id);
+ if (childcount > 0)
+ {
+ int start = *last_id + 1;
+ int end = *last_id + childcount;
+ IupSetfAttribute(ih, "MARK", "%d-%d", start, end);
+ *last_id = *last_id + childcount;
+ }
+ }
+}
+
+int iupTreeForEach(Ihandle* ih, iupTreeNodeFunc func, void* userdata)
+{
+ int i;
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ if (!func(ih, ih->data->node_cache[i].node_handle, i, userdata))
+ return 0;
+ }
+
+ return 1;
+}
+
+int iupTreeFindNodeId(Ihandle* ih, InodeHandle* node_handle)
+{
+ /* Unoptimized version:
+ int i;
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ if (ih->data->node_cache[i].node_handle == node_handle)
+ return i;
+ }
+ */
+ InodeData *node_cache = ih->data->node_cache;
+ while(node_cache->node_handle != node_handle &&
+ node_cache->node_handle != NULL) /* the cache always have zeros at the end */
+ node_cache++;
+
+ if (node_cache->node_handle != NULL)
+ return node_cache - ih->data->node_cache;
+ else
+ return -1;
+}
+
+static int iTreeFindUserDataId(Ihandle* ih, void* userdata)
+{
+ /* Unoptimized version:
+ int i;
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ if (ih->data->node_cache[i].node_handle == node_handle)
+ return i;
+ }
+ */
+ InodeData *node_cache = ih->data->node_cache;
+ while(node_cache->userdata != userdata &&
+ node_cache->node_handle != NULL) /* the cache always have zeros at the end */
+ node_cache++;
+
+ if (node_cache->node_handle != NULL)
+ return node_cache - ih->data->node_cache;
+ else
+ return -1;
+}
+
+static int iTreeGetIdFromString(const char* name_id)
+{
+ if (name_id && name_id[0])
+ {
+ int id = -1;
+ iupStrToInt(name_id, &id);
+ return id;
+ }
+ else
+ return -2;
+}
+
+InodeHandle* iupTreeGetNode(Ihandle* ih, int id)
+{
+ if (id >= 0 && id < ih->data->node_count)
+ return ih->data->node_cache[id].node_handle;
+ else if (id == -2)
+ return iupdrvTreeGetFocusNode(ih);
+ else
+ return NULL;
+}
+
+InodeHandle* iupTreeGetNodeFromString(Ihandle* ih, const char* name_id)
+{
+ return iupTreeGetNode(ih, iTreeGetIdFromString(name_id));
+}
+
+static void iTreeAddToCache(Ihandle* ih, int id, InodeHandle* node_handle)
+{
+ iupASSERT(id >= 0 && id < ih->data->node_count);
+ if (id < 0 || id >= ih->data->node_count)
+ return;
+
+ /* node_count here already contains the final count */
+
+ if (id == ih->data->node_count-1)
+ ih->data->node_cache[id].node_handle = node_handle;
+ else
+ {
+ /* open space for the new id */
+ int remain_count = ih->data->node_count-id;
+ memmove(ih->data->node_cache+id+1, ih->data->node_cache+id, remain_count*sizeof(InodeData));
+ ih->data->node_cache[id].node_handle = node_handle;
+ }
+
+ ih->data->node_cache[id].userdata = NULL;
+}
+
+static void iTreeIncCacheMem(Ihandle* ih)
+{
+ /* node_count here already contains the final count */
+
+ if (ih->data->node_count+10 > ih->data->node_cache_max)
+ {
+ int old_node_cache_max = ih->data->node_cache_max;
+ ih->data->node_cache_max += 20;
+ ih->data->node_cache = realloc(ih->data->node_cache, ih->data->node_cache_max*sizeof(InodeData));
+ memset(ih->data->node_cache+old_node_cache_max, 0, 20*sizeof(InodeData));
+ }
+}
+
+void iupTreeAddToCache(Ihandle* ih, int add, int kindPrev, InodeHandle* prevNode, InodeHandle* node_handle)
+{
+ int new_id = 0;
+
+ ih->data->node_count++;
+
+ /* node_count here already contains the final count */
+ iTreeIncCacheMem(ih);
+
+ if (prevNode)
+ {
+ if (add || kindPrev == ITREE_LEAF)
+ {
+ /* ADD implies always that id=prev_id+1 */
+ /* INSERT after a leaf implies always that new_id=prev_id+1 */
+ int prev_id = iupTreeFindNodeId(ih, prevNode);
+ new_id = prev_id+1;
+ }
+ else
+ {
+ /* INSERT after a branch implies always that new_id=prev_id+1+child_count */
+ int prev_id = iupTreeFindNodeId(ih, prevNode);
+ int child_count = iupdrvTreeTotalChildCount(ih, prevNode);
+ new_id = prev_id+1+child_count;
+ }
+ }
+
+ iTreeAddToCache(ih, new_id, node_handle);
+ iupAttribSetInt(ih, "LASTADDNODE", new_id);
+}
+
+void iupTreeDelFromCache(Ihandle* ih, int id, int count)
+{
+ int remain_count;
+
+ /* id can be the last node, actually==node_count becase node_count is already updated */
+ iupASSERT(id >= 0 && id <= ih->data->node_count);
+ if (id < 0 || id > ih->data->node_count)
+ return;
+
+ /* node_count here already contains the final count */
+
+ /* remove id+count */
+ remain_count = ih->data->node_count-id;
+ memmove(ih->data->node_cache+id, ih->data->node_cache+id+count, remain_count*sizeof(InodeData));
+
+ /* clear the remaining space */
+ memset(ih->data->node_cache+ih->data->node_count, 0, count*sizeof(InodeData));
+}
+
+void iupTreeCopyMoveCache(Ihandle* ih, int id_src, int id_dst, int count, int is_copy)
+{
+ int remain_count;
+
+ iupASSERT(id_src >= 0 && id_src < ih->data->node_count);
+ if (id_src < 0 || id_src >= ih->data->node_count)
+ return;
+
+ iupASSERT(id_dst >= 0 && id_dst < ih->data->node_count);
+ if (id_dst < 0 || id_dst >= ih->data->node_count)
+ return;
+
+ iupASSERT(id_dst < id_src || id_dst > id_src+count);
+ if (id_dst >= id_src && id_dst <= id_src+count)
+ return;
+
+ /* id_dst here points to the final position for a copy operation */
+
+ /* node_count here contains the final count for a copy operation */
+ iTreeIncCacheMem(ih);
+
+ /* add space for new nodes */
+ remain_count = ih->data->node_count - (id_dst + count);
+ memmove(ih->data->node_cache+id_dst+count, ih->data->node_cache+id_dst, remain_count*sizeof(InodeData));
+
+ /* compensate because we add space for new nodes */
+ if (id_src > id_dst)
+ id_src += count;
+
+ if (is_copy)
+ {
+ /* during a copy, the userdata is not reused, so clear it */
+ memset(ih->data->node_cache+id_dst, 0, count*sizeof(InodeData));
+ }
+ else /* move = copy + delete */
+ {
+ /* copy userdata from src to dst */
+ memcpy(ih->data->node_cache+id_dst, ih->data->node_cache+id_src, count*sizeof(InodeData));
+
+ /* remove the src */
+ remain_count = ih->data->node_count - (id_src + count);
+ memmove(ih->data->node_cache+id_src, ih->data->node_cache+id_src+count, remain_count*sizeof(InodeData));
+
+ /* clear the remaining space */
+ memset(ih->data->node_cache+ih->data->node_count-count, 0, count*sizeof(InodeData));
+ }
+}
+
+
+/*************************************************************************/
+
+
char* iupTreeGetSpacingAttrib(Ihandle* ih)
{
char *str = iupStrGetMemory(50);
@@ -221,8 +455,10 @@ static int iTreeSetMarkModeAttrib(Ihandle* ih, const char* value)
ih->data->mark_mode = ITREE_MARK_MULTIPLE;
else
ih->data->mark_mode = ITREE_MARK_SINGLE;
+
if (ih->handle)
- iupdrvTreeUpdateMarkMode(ih);
+ iupdrvTreeUpdateMarkMode(ih); /* for this to work, must update during map */
+
return 0;
}
@@ -290,7 +526,7 @@ static int iTreeSetShowDragDropAttrib(Ihandle* ih, const char* value)
static int iTreeSetAddLeafAttrib(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;
iupdrvTreeAddNode(ih, name_id, ITREE_LEAF, value, 1);
return 0;
@@ -298,7 +534,7 @@ static int iTreeSetAddLeafAttrib(Ihandle* ih, const char* name_id, const char* v
static int iTreeSetAddBranchAttrib(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;
iupdrvTreeAddNode(ih, name_id, ITREE_BRANCH, value, 1);
return 0;
@@ -306,7 +542,7 @@ static int iTreeSetAddBranchAttrib(Ihandle* ih, const char* name_id, const char*
static int iTreeSetInsertLeafAttrib(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;
iupdrvTreeAddNode(ih, name_id, ITREE_LEAF, value, 0);
return 0;
@@ -314,7 +550,7 @@ static int iTreeSetInsertLeafAttrib(Ihandle* ih, const char* name_id, const char
static int iTreeSetInsertBranchAttrib(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;
iupdrvTreeAddNode(ih, name_id, ITREE_BRANCH, value, 0);
return 0;
@@ -338,6 +574,74 @@ static int iTreeSetAddExpandedAttrib(Ihandle* ih, const char* value)
return 0;
}
+static char* iTreeGetCountAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(10);
+ sprintf(str, "%d", ih->data->node_count);
+ return str;
+}
+
+static char* iTreeGetTotalChildCountAttrib(Ihandle* ih, const char* name_id)
+{
+ char* str;
+ InodeHandle* node_handle = iupTreeGetNodeFromString(ih, name_id);
+ if (!node_handle)
+ return NULL;
+
+ str = iupStrGetMemory(10);
+ sprintf(str, "%d", iupdrvTreeTotalChildCount(ih, node_handle));
+ return str;
+}
+
+
+static char* iTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
+{
+ int id;
+ char* str = (char*)(name_id+1); /* skip ':' */
+ void* userdata = NULL;
+ if (sscanf(str, "%p", &userdata)!=1)
+ return NULL;
+ id = iTreeFindUserDataId(ih, userdata);
+ if (id == -1)
+ return NULL;
+ str = iupStrGetMemory(16);
+ sprintf(str, "%d", id);
+ return str;
+}
+
+static char* iTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
+{
+ int id = iTreeGetIdFromString(name_id);
+ if (id >= 0 && id < ih->data->node_count)
+ return ih->data->node_cache[id].userdata;
+ else if (id == -2)
+ {
+ InodeHandle* node_handle = iupdrvTreeGetFocusNode(ih);
+ id = iupTreeFindNodeId(ih, node_handle);
+ if (id >= 0 && id < ih->data->node_count)
+ return ih->data->node_cache[id].userdata;
+ }
+ return NULL;
+}
+
+static int iTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
+{
+ int id = iTreeGetIdFromString(name_id);
+ if (id >= 0 && id < ih->data->node_count)
+ ih->data->node_cache[id].userdata = (void*)value;
+ else if (id == -2)
+ {
+ InodeHandle* node_handle = iupdrvTreeGetFocusNode(ih);
+ id = iupTreeFindNodeId(ih, node_handle);
+ if (id >= 0 && id < ih->data->node_count)
+ ih->data->node_cache[id].userdata = (void*)value;
+ }
+ return 0;
+}
+
+
+/*************************************************************************/
+
static int iTreeCreateMethod(Ihandle* ih, void **params)
{
(void)params;
@@ -348,10 +652,20 @@ static int iTreeCreateMethod(Ihandle* ih, void **params)
IupSetAttribute(ih, "EXPAND", "YES");
ih->data->add_expanded = 1;
+ ih->data->node_cache_max = 20;
+ ih->data->node_cache = calloc(ih->data->node_cache_max, sizeof(InodeData));
return IUP_NOERROR;
}
+static void iTreeDestroyMethod(Ihandle* ih)
+{
+ if (ih->data->node_cache)
+ free(ih->data->node_cache);
+}
+
+/*************************************************************************/
+
Ihandle* IupTree(void)
{
return IupCreate("tree");
@@ -371,15 +685,15 @@ Iclass* iupTreeGetClass(void)
/* Class functions */
ic->Create = iTreeCreateMethod;
ic->LayoutUpdate = iupdrvBaseLayoutUpdateMethod;
- ic->UnMap = iupdrvBaseUnMapMethod;
+ ic->Destroy = iTreeDestroyMethod;
/* Callbacks */
iupClassRegisterCallback(ic, "SELECTION_CB", "ii");
iupClassRegisterCallback(ic, "MULTISELECTION_CB", "Ii");
+ iupClassRegisterCallback(ic, "MULTIUNSELECTION_CB", "Ii");
iupClassRegisterCallback(ic, "BRANCHOPEN_CB", "i");
iupClassRegisterCallback(ic, "BRANCHCLOSE_CB", "i");
iupClassRegisterCallback(ic, "EXECUTELEAF_CB", "i");
- iupClassRegisterCallback(ic, "RENAMENODE_CB", "is");
iupClassRegisterCallback(ic, "SHOWRENAME_CB", "i");
iupClassRegisterCallback(ic, "RENAME_CB", "is");
iupClassRegisterCallback(ic, "DRAGDROP_CB", "iiii");
@@ -392,9 +706,12 @@ Iclass* iupTreeGetClass(void)
iupBaseRegisterVisualAttrib(ic);
/* IupTree Attributes - GENERAL */
- iupClassRegisterAttribute(ic, "SHOWDRAGDROP", iTreeGetShowDragDropAttrib, iTreeSetShowDragDropAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
- iupClassRegisterAttribute(ic, "SHOWRENAME", iTreeGetShowRenameAttrib, iTreeSetShowRenameAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
- iupClassRegisterAttribute(ic, "ADDEXPANDED", iTreeGetAddExpandedAttrib, iTreeSetAddExpandedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWDRAGDROP", iTreeGetShowDragDropAttrib, iTreeSetShowDragDropAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SHOWRENAME", iTreeGetShowRenameAttrib, iTreeSetShowRenameAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ADDEXPANDED", iTreeGetAddExpandedAttrib, iTreeSetAddExpandedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "COUNT", iTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "LASTADDNODE", NULL, NULL, IUPAF_SAMEASSYSTEM, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ADDROOT", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
/* IupTree Attributes - MARKS */
iupClassRegisterAttribute(ic, "CTRL", NULL, iTreeSetCtrlAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
@@ -406,6 +723,11 @@ Iclass* iupTreeGetClass(void)
iupClassRegisterAttributeId(ic, "ADDBRANCH", NULL, iTreeSetAddBranchAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "INSERTLEAF", NULL, iTreeSetInsertLeafAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "INSERTBRANCH", NULL, iTreeSetInsertBranchAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+
+ /* IupTree Attributes - NODES */
+ iupClassRegisterAttributeId(ic, "TOTALCHILDCOUNT", iTreeGetTotalChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "FINDUSERDATA", iTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "USERDATA", iTreeGetUserDataAttrib, iTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
/* Default node images */
iTreeInitializeImages();
@@ -415,18 +737,23 @@ Iclass* iupTreeGetClass(void)
return ic;
}
-
/********************************************************************************************/
-
-void IupTreeSetAttribute(Ihandle* ih, const char* a, int id, char* v)
+void IupTreeSetAttribute(Ihandle* ih, const char* a, int id, const char* v)
{
char* attr = iupStrGetMemory(50);
sprintf(attr, "%s%d", a, id);
IupSetAttribute(ih, attr, v);
}
-void IupTreeStoreAttribute(Ihandle* ih, const char* a, int id, char* v)
+void IupTreeSetAttributeHandle(Ihandle* ih, const char* a, int id, Ihandle* ih_named)
+{
+ char* attr = iupStrGetMemory(50);
+ sprintf(attr, "%s%d", a, id);
+ IupSetAttributeHandle(ih, attr, ih_named);
+}
+
+void IupTreeStoreAttribute(Ihandle* ih, const char* a, int id, const char* v)
{
char* attr = iupStrGetMemory(50);
sprintf(attr, "%s%d", a, id);
@@ -454,7 +781,7 @@ float IupTreeGetFloat(Ihandle* ih, const char* a, int id)
return IupGetFloat(ih, attr);
}
-void IupTreeSetfAttribute(Ihandle* ih, const char* a, int id, char* f, ...)
+void IupTreeSetfAttribute(Ihandle* ih, const char* a, int id, const char* f, ...)
{
static char v[SHRT_MAX];
char* attr = iupStrGetMemory(50);
@@ -466,34 +793,40 @@ void IupTreeSetfAttribute(Ihandle* ih, const char* a, int id, char* f, ...)
IupStoreAttribute(ih, attr, v);
}
-
/************************************************************************************/
-
int IupTreeSetUserId(Ihandle* ih, int id, void* userdata)
{
- char attr[30];
- sprintf(attr,"USERDATA%d",id);
- IupSetAttribute(ih, attr, userdata);
- return IupGetAttribute(ih, attr)? 1: 0;
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return 0;
+
+ if (id >= 0 && id < ih->data->node_count)
+ {
+ ih->data->node_cache[id].userdata = userdata;
+ return 1;
+ }
+
+ return 0;
}
int IupTreeGetId(Ihandle* ih, void *userdata)
{
- int id = -1;
- char* value;
- char attr[30];
- sprintf(attr,"FINDUSERDATA:%p",userdata);
- value = IupGetAttribute(ih, attr);
- if (!value) return -1;
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return -1;
- iupStrToInt(value, &id);
- return id;
+ return iTreeFindUserDataId(ih, userdata);
}
void* IupTreeGetUserId(Ihandle* ih, int id)
{
- char attr[30];
- sprintf(attr,"USERDATA%d",id);
- return IupGetAttribute(ih, attr);
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return NULL;
+
+ if (id >= 0 && id < ih->data->node_count)
+ return ih->data->node_cache[id].userdata;
+
+ return NULL;
}
diff --git a/iup/src/iup_tree.h b/iup/src/iup_tree.h
index f96a698..44acc83 100755
--- a/iup/src/iup_tree.h
+++ b/iup/src/iup_tree.h
@@ -29,6 +29,36 @@ void iupdrvTreeUpdateMarkMode(Ihandle *ih);
char* iupTreeGetSpacingAttrib(Ihandle* ih);
+#if defined(GTK_MAJOR_VERSION)
+typedef void InodeHandle;
+#elif defined(XmVERSION)
+typedef struct _WidgetRec InodeHandle;
+#elif defined(WINVER)
+typedef struct _TREEITEM InodeHandle;
+#else
+typedef struct _InodeData InodeHandle;
+#endif
+
+typedef struct _InodeData
+{
+ InodeHandle* node_handle;
+ void* userdata;
+} InodeData;
+
+typedef int (*iupTreeNodeFunc)(Ihandle* ih, InodeHandle* node_handle, int id, void* userdata);
+int iupTreeForEach(Ihandle* ih, iupTreeNodeFunc func, void* userdata);
+InodeHandle* iupTreeGetNode(Ihandle* ih, int id);
+InodeHandle* iupTreeGetNodeFromString(Ihandle* ih, const char* name_id);
+int iupTreeFindNodeId(Ihandle* ih, InodeHandle* node_handle);
+
+InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih);
+int iupdrvTreeTotalChildCount(Ihandle* ih, InodeHandle* node_handle);
+void iupTreeSelectLastCollapsedBranch(Ihandle* ih, int *last_id);
+
+void iupTreeDelFromCache(Ihandle* ih, int id, int count);
+void iupTreeAddToCache(Ihandle* ih, int add, int kindPrev, InodeHandle* prevNode, InodeHandle* node_handle);
+void iupTreeCopyMoveCache(Ihandle* ih, int id_src, int id_dst, int count, int is_copy);
+
/* Structure of the tree */
struct _IcontrolData
{
@@ -36,6 +66,7 @@ struct _IcontrolData
add_expanded,
show_dragdrop,
show_rename,
+ stamp, /* GTK only */
spacing;
void* def_image_leaf; /* Default image leaf */
@@ -44,9 +75,10 @@ struct _IcontrolData
void* def_image_leaf_mask; /* Motif Only */
void* def_image_collapsed_mask;
- void* def_image_expanded_mask;
+ void* def_image_expanded_mask;
- int id_control; /* auxiliary variable for computing or finding the id of a node */
+ InodeData *node_cache;
+ int node_cache_max, node_count;
};
diff --git a/iup/src/iup_vbox.c b/iup/src/iup_vbox.c
index f71aa51..23e8e3a 100755
--- a/iup/src/iup_vbox.c
+++ b/iup/src/iup_vbox.c
@@ -215,6 +215,13 @@ static void iVboxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
else
{
int empty = (child->expand & IUP_EXPAND_H1)? empty_h1: ((child->expand & IUP_EXPAND_H0)? empty_h0: 0);
+ char* weigth_str = iupAttribGet(child, "EXPANDWEIGTH");
+ if (weigth_str)
+ {
+ float weigth;
+ if (iupStrToFloat(weigth_str, &weigth))
+ empty = iupROUND(empty * weigth);
+ }
iupBaseSetCurrentSize(child, client_width, child->naturalheight+empty, shrink);
}
diff --git a/iup/src/iup_zbox.c b/iup/src/iup_zbox.c
index 3f79892..dd4a0e4 100755
--- a/iup/src/iup_zbox.c
+++ b/iup/src/iup_zbox.c
@@ -210,7 +210,7 @@ static int iZboxSetVisibleAttrib(Ihandle* ih, const char* value)
{
if (iupObjectCheck(ih->data->value_handle))
IupSetAttribute(ih->data->value_handle, "VISIBLE", (char*)value);
- return 0;
+ return 1; /* must be 1 to mark when set at the element */
}
static void iZboxComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
@@ -368,8 +368,8 @@ Iclass* iupZboxGetClass(void)
iupClassRegisterAttribute(ic, "VALUEPOS", iZboxGetValuePosAttrib, iZboxSetValuePosAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "VALUE_HANDLE", NULL, iZboxSetValueHandleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
- /* Intercept VISIBLE since ZBOX works showing and hidding its children */
- iupClassRegisterAttribute(ic, "VISIBLE", NULL, iZboxSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ /* Intercept VISIBLE since ZBOX works by showing and hidding its children */
+ iupClassRegisterAttribute(ic, "VISIBLE", NULL, iZboxSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
return ic;
}
diff --git a/iup/src/make_uname b/iup/src/make_uname
index 7fec9f8..6542234 100755
--- a/iup/src/make_uname
+++ b/iup/src/make_uname
@@ -1,4 +1,4 @@
#This builds all the libraries of the folder for 1 uname
-tecmake $1 $2 $3 $4 $5 $6 $7
+tecmake USE_MOTIF=Yes $1 $2 $3 $4 $5 $6 $7
tecmake USE_GTK=Yes $1 $2 $3 $4 $5 $6 $7
diff --git a/iup/src/mot/iupmot_button.c b/iup/src/mot/iupmot_button.c
index 2d93588..f6e383f 100755
--- a/iup/src/mot/iupmot_button.c
+++ b/iup/src/mot/iupmot_button.c
@@ -112,8 +112,10 @@ static int motButtonSetPaddingAttrib(Ihandle* ih, const char* value)
{
XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
XmNmarginWidth, ih->data->horiz_padding, NULL);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int motButtonSetBgColorAttrib(Ihandle* ih, const char* value)
@@ -189,43 +191,43 @@ static int motButtonMapMethod(Ihandle* ih)
if (value)
{
ih->data->type = IUP_BUTTON_IMAGE;
- iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmPIXMAP);
}
else
{
ih->data->type = IUP_BUTTON_TEXT;
- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING);
}
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Label */
- iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
- iupmotSetArg(args, num_args, XmNmarginLeft, 0);
- iupmotSetArg(args, num_args, XmNmarginBottom, 0);
- iupmotSetArg(args, num_args, XmNmarginRight, 0);
+ iupMOT_SETARG(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginTop, 0); /* no extra margins */
+ iupMOT_SETARG(args, num_args, XmNmarginLeft, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginBottom, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginRight, 0);
/* PushButton */
- iupmotSetArg(args, num_args, XmNfillOnArm, False);
+ iupMOT_SETARG(args, num_args, XmNfillOnArm, False);
/* Primitive */
if (iupAttribGetBoolean(ih, "FOCUSONCLICK"))
{
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
}
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
ih->handle = XtCreateManagedWidget(
iupDialogGetChildIdStr(ih), /* child identifier */
diff --git a/iup/src/mot/iupmot_canvas.c b/iup/src/mot/iupmot_canvas.c
index 7777cf3..299bbcd 100755
--- a/iup/src/mot/iupmot_canvas.c
+++ b/iup/src/mot/iupmot_canvas.c
@@ -434,6 +434,10 @@ static void motCanvasLayoutUpdateMethod(Ihandle *ih)
XtVaGetValues(sb_win, XmNborderWidth, &border, NULL);
+ /* avoid abort in X */
+ if (ih->currentwidth <= 2*border) ih->currentwidth = 2*border+1;
+ if (ih->currentheight <= 2*border) ih->currentheight = 2*border+1;
+
XtVaSetValues(sb_win,
XmNx, (XtArgVal)ih->x,
XmNy, (XtArgVal)ih->y,
@@ -458,19 +462,19 @@ static int motCanvasMapMethod(Ihandle* ih)
/* Create the scrolled window */
/******************************/
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and draw area */
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and draw area */
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
if (iupAttribGetBoolean(ih, "BORDER"))
{
- iupmotSetArg(args, num_args, XmNborderWidth, 1);
- iupmotSetArg(args, num_args, XmNborderColor, iupmotColorGetPixelStr("0 0 0"));
+ iupMOT_SETARG(args, num_args, XmNborderWidth, 1);
+ iupMOT_SETARG(args, num_args, XmNborderColor, iupmotColorGetPixelStr("0 0 0"));
}
else
- iupmotSetArg(args, num_args, XmNborderWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
sb_win = XtCreateManagedWidget(
iupDialogGetChildIdStr(ih), /* child identifier */
@@ -488,36 +492,36 @@ static int motCanvasMapMethod(Ihandle* ih)
/****************************/
num_args = 0;
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNresizePolicy, XmRESIZE_NONE); /* no automatic resize of children */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNresizePolicy, XmRESIZE_NONE); /* no automatic resize of children */
if (ih->iclass->is_interactive)
{
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); /* include in navigation */
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP); /* include in navigation */
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
}
else
{
- iupmotSetArg(args, num_args, XmNnavigationType, XmNONE);
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmNONE);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
}
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
visual = IupGetAttribute(ih, "VISUAL"); /* defined by the OpenGL Canvas or NULL */
if (visual)
{
Colormap colormap = (Colormap)iupAttribGet(ih, "COLORMAP");
if (colormap)
- iupmotSetArg(args, num_args, XmNcolormap,colormap);
+ iupMOT_SETARG(args, num_args, XmNcolormap,colormap);
iupmotDialogSetVisual(ih, visual);
}
diff --git a/iup/src/mot/iupmot_common.c b/iup/src/mot/iupmot_common.c
index 7b3f8b7..286e075 100755
--- a/iup/src/mot/iupmot_common.c
+++ b/iup/src/mot/iupmot_common.c
@@ -167,6 +167,10 @@ void iupdrvBaseLayoutUpdateMethod(Ihandle *ih)
Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
if (!widget) widget = ih->handle;
+ /* avoid abort in X */
+ if (ih->currentwidth == 0) ih->currentwidth = 1;
+ if (ih->currentheight == 0) ih->currentheight = 1;
+
XtVaSetValues(widget,
XmNx, (XtArgVal)ih->x,
XmNy, (XtArgVal)ih->y,
@@ -184,7 +188,7 @@ void iupdrvBaseUnMapMethod(Ihandle* ih)
XtDestroyWidget(widget); /* To match the call to XtCreateManagedWidget */
}
-void iupdrvDisplayUpdate(Ihandle *ih)
+void iupdrvPostRedraw(Ihandle *ih)
{
XExposeEvent evt;
Dimension w, h;
@@ -209,12 +213,12 @@ void iupdrvDisplayUpdate(Ihandle *ih)
XSendEvent(iupmot_display, XtWindow(ih->handle), False, ExposureMask, (XEvent*)&evt);
}
-void iupdrvDisplayRedraw(Ihandle *ih)
+void iupdrvRedrawNow(Ihandle *ih)
{
Widget w;
/* POST a Redraw */
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
/* if this element has an inner native parent (like IupTabs),
then redraw that native parent if different from the element. */
@@ -223,7 +227,7 @@ void iupdrvDisplayRedraw(Ihandle *ih)
{
Widget handle = ih->handle;
ih->handle = w;
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
ih->handle = handle;
}
@@ -276,10 +280,11 @@ int iupdrvBaseSetZorderAttrib(Ihandle* ih, const char* value)
{
if (iupdrvIsVisible(ih))
{
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
if (iupStrEqualNoCase(value, "TOP"))
- XRaiseWindow(iupmot_display, XtWindow(ih->handle));
+ XRaiseWindow(iupmot_display, XtWindow(widget));
else
- XLowerWindow(iupmot_display, XtWindow(ih->handle));
+ XLowerWindow(iupmot_display, XtWindow(widget));
}
return 0;
@@ -455,9 +460,11 @@ static Cursor motGetCursor(Ihandle* ih, const char* name)
{ "RESIZE_N", XC_top_side},
{ "RESIZE_S", XC_bottom_side},
{ "RESIZE_NS", XC_sb_v_double_arrow},
+ { "SPLITTER_HORIZ", XC_sb_v_double_arrow},
{ "RESIZE_W", XC_left_side},
{ "RESIZE_E", XC_right_side},
{ "RESIZE_WE", XC_sb_h_double_arrow},
+ { "SPLITTER_VERT", XC_sb_h_double_arrow},
{ "RESIZE_NE", XC_top_right_corner},
{ "RESIZE_SE", XC_bottom_right_corner},
{ "RESIZE_NW", XC_top_left_corner},
diff --git a/iup/src/mot/iupmot_dialog.c b/iup/src/mot/iupmot_dialog.c
index 4eeb834..7a27d74 100755
--- a/iup/src/mot/iupmot_dialog.c
+++ b/iup/src/mot/iupmot_dialog.c
@@ -134,12 +134,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");
@@ -155,7 +156,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)
@@ -181,7 +182,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;
@@ -853,6 +854,7 @@ static int motDialogMapMethod(Ihandle* ih)
InativeHandle* parent;
int mwm_decor = 0;
int num_args = 0;
+ int has_titlebar = 0;
Arg args[20];
if (iupAttribGetBoolean(ih, "DIALOGFRAME"))
@@ -867,32 +869,46 @@ static int motDialogMapMethod(Ihandle* ih)
/****************************/
if (iupAttribGet(ih, "TITLE"))
- mwm_decor |= MWM_DECOR_TITLE;
+ has_titlebar = 1;
if (iupAttribGetBoolean(ih, "MENUBOX"))
- mwm_decor |= MWM_DECOR_MENU;
+ {
+ mwm_decor |= MWM_DECOR_MENU;
+ has_titlebar = 1;
+ }
if (iupAttribGetBoolean(ih, "MINBOX"))
- mwm_decor |= MWM_DECOR_MINIMIZE;
+ {
+ mwm_decor |= MWM_DECOR_MINIMIZE;
+ has_titlebar = 1;
+ }
if (iupAttribGetBoolean(ih, "MAXBOX"))
- mwm_decor |= MWM_DECOR_MAXIMIZE;
+ {
+ mwm_decor |= MWM_DECOR_MAXIMIZE;
+ has_titlebar = 1;
+ }
if (iupAttribGetBoolean(ih, "RESIZE"))
- mwm_decor |= MWM_DECOR_RESIZEH;
- if (iupAttribGetBoolean(ih, "BORDER"))
- mwm_decor |= MWM_DECOR_BORDER;
-
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* so XtRealizeWidget will not show the dialog */
- iupmotSetArg(args, num_args, XmNdeleteResponse, XmDO_NOTHING);
- iupmotSetArg(args, num_args, XmNallowShellResize, True); /* Used so the BulletinBoard can control the shell size */
- iupmotSetArg(args, num_args, XmNtitle, "");
- iupmotSetArg(args, num_args, XmNvisual, iupmot_visual);
+ {
+ mwm_decor |= MWM_DECOR_RESIZEH;
+ mwm_decor |= MWM_DECOR_BORDER; /* has_border */
+ }
+ if (has_titlebar)
+ mwm_decor |= MWM_DECOR_TITLE;
+ if (iupAttribGetBoolean(ih, "BORDER") || has_titlebar)
+ mwm_decor |= MWM_DECOR_BORDER; /* has_border */
+
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* so XtRealizeWidget will not show the dialog */
+ iupMOT_SETARG(args, num_args, XmNdeleteResponse, XmDO_NOTHING);
+ iupMOT_SETARG(args, num_args, XmNallowShellResize, True); /* Used so the BulletinBoard can control the shell size */
+ iupMOT_SETARG(args, num_args, XmNtitle, "");
+ iupMOT_SETARG(args, num_args, XmNvisual, iupmot_visual);
if (iupmotColorMap())
- iupmotSetArg(args, num_args, XmNcolormap, iupmotColorMap());
+ iupMOT_SETARG(args, num_args, XmNcolormap, iupmotColorMap());
if (mwm_decor != 0x7E)
- iupmotSetArg(args, num_args, XmNmwmDecorations, mwm_decor);
+ iupMOT_SETARG(args, num_args, XmNmwmDecorations, mwm_decor);
if (iupAttribGetBoolean(ih, "SAVEUNDER"))
- iupmotSetArg(args, num_args, XmNsaveUnder, True);
+ iupMOT_SETARG(args, num_args, XmNsaveUnder, True);
parent = iupDialogGetNativeParent(ih);
if (parent)
diff --git a/iup/src/mot/iupmot_draw.c b/iup/src/mot/iupmot_draw.c
new file mode 100644
index 0000000..83a6d09
--- /dev/null
+++ b/iup/src/mot/iupmot_draw.c
@@ -0,0 +1,188 @@
+/** \file
+ * \brief Draw Functions
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+
+#include <Xm/Xm.h>
+#include <X11/Xlib.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 "iupmot_drv.h"
+#include "iupmot_color.h"
+
+
+struct _IdrawCanvas{
+ Ihandle* ih;
+ int w, h;
+
+ Window wnd;
+ Pixmap pixmap;
+ GC pixmap_gc, gc;
+};
+
+static void motDrawGetGeometry(Display *dpy, Drawable wnd, int *_w, int *_h, int *_d)
+{
+ Window root;
+ int x, y;
+ unsigned int w, h, b, d;
+ XGetGeometry(dpy, wnd, &root, &x, &y, &w, &h, &b, &d);
+ *_w = w;
+ *_h = h;
+ *_d = d;
+}
+
+IdrawCanvas* iupDrawCreateCanvas(Ihandle* ih)
+{
+ IdrawCanvas* dc = calloc(1, sizeof(IdrawCanvas));
+ int depth;
+
+ dc->wnd = XtWindow(ih->handle);
+ dc->gc = XCreateGC(iupmot_display, dc->wnd, 0, NULL);
+
+ motDrawGetGeometry(iupmot_display, dc->wnd, &dc->w, &dc->h, &depth);
+
+ dc->pixmap = XCreatePixmap(iupmot_display, dc->wnd, dc->w, dc->h, depth);
+ dc->pixmap_gc = XCreateGC(iupmot_display, dc->pixmap, 0, NULL);
+
+ return dc;
+}
+
+void iupDrawKillCanvas(IdrawCanvas* dc)
+{
+ XFreeGC(iupmot_display, dc->pixmap_gc);
+ XFreePixmap(iupmot_display, dc->pixmap);
+ XFreeGC(iupmot_display, dc->gc);
+
+ free(dc);
+}
+
+void iupDrawUpdateSize(IdrawCanvas* dc)
+{
+ int w, h, depth;
+ motDrawGetGeometry(iupmot_display, dc->wnd, &w, &h, &depth);
+
+ if (w != dc->w || h != dc->h)
+ {
+ XFreeGC(iupmot_display, dc->pixmap_gc);
+ XFreePixmap(iupmot_display, dc->pixmap);
+
+ dc->pixmap = XCreatePixmap(iupmot_display, dc->wnd, dc->w, dc->h, depth);
+ dc->pixmap_gc = XCreateGC(iupmot_display, dc->pixmap, 0, NULL);
+ }
+}
+
+void iupDrawFlush(IdrawCanvas* dc)
+{
+ XCopyArea(iupmot_display, dc->pixmap, dc->wnd, dc->gc, 0, 0, dc->w, dc->h, 0, 0);
+}
+
+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)
+{
+ XSetForeground(iupmot_display, dc->pixmap_gc, iupmotColorGetPixel(r, g, b));
+ if (filled)
+ XFillRectangle(iupmot_display, dc->pixmap, dc->pixmap_gc, x1, y1, x2-x1+1, y2-y1+1);
+ else
+ XDrawRectangle(iupmot_display, dc->pixmap, dc->pixmap_gc, 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)
+{
+ XSetForeground(iupmot_display, dc->pixmap_gc, iupmotColorGetPixel(r, g, b));
+ XDrawLine(iupmot_display, 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)
+{
+ XSetForeground(iupmot_display, dc->pixmap_gc, iupmotColorGetPixel(r, g, b));
+ if (filled)
+ {
+ XSetArcMode(iupmot_display, dc->pixmap_gc, ArcPieSlice);
+ XFillArc(iupmot_display, dc->pixmap, dc->pixmap_gc, x1, y1, x2-x1+1, y2-y1+1, iupROUND(a1*64), iupROUND((a2 - a1)*64));
+ }
+ else
+ XDrawArc(iupmot_display, dc->pixmap, dc->pixmap_gc, 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)
+{
+ int i;
+ XPoint* pnt = (XPoint*)malloc(count*sizeof(XPoint)); /* XPoint uses short for coordinates */
+
+ for (i = 0; i < count; i++)
+ {
+ pnt[i].x = (short)points[2*i];
+ pnt[i].y = (short)points[2*i+1];
+ }
+
+ XSetForeground(iupmot_display, dc->pixmap_gc, iupmotColorGetPixel(r, g, b));
+ if (filled)
+ XFillPolygon(iupmot_display, dc->pixmap, dc->pixmap_gc, pnt, count, Complex, CoordModeOrigin);
+ else
+ XDrawLines(iupmot_display, dc->pixmap, dc->pixmap_gc, pnt, count, CoordModeOrigin);
+
+ free(pnt);
+}
+
+void iupDrawSetClipRect(IdrawCanvas* dc, int x1, int y1, int x2, int y2)
+{
+ XRectangle rect;
+ rect.x = (short)x1;
+ rect.y = (short)y1;
+ rect.width = (unsigned short)(x2-x1+1);
+ rect.height = (unsigned short)(y2-y1+1);
+ XSetClipRectangles(iupmot_display, dc->pixmap_gc, 0, 0, &rect, 1, Unsorted);
+}
+
+void iupDrawResetClip(IdrawCanvas* dc)
+{
+ XSetClipMask(iupmot_display, dc->pixmap_gc, None);
+}
+
+void iupDrawText(IdrawCanvas* dc, const char* text, int len, int x, int y, unsigned char r, unsigned char g, unsigned char b)
+{
+ XFontStruct* xfont = (XFontStruct*)IupGetAttribute(dc->ih, "XFONTSTRUCT");
+ XSetForeground(iupmot_display, dc->pixmap_gc, iupmotColorGetPixel(r, g, b));
+ XSetFont(iupmot_display, dc->pixmap_gc, xfont->fid);
+ XDrawString(iupmot_display, dc->pixmap, dc->pixmap_gc, x, y-xfont->ascent, text, len);
+}
+
+void iupDrawImage(IdrawCanvas* dc, const char* name, int make_inactive, int x, int y)
+{
+ int img_w, img_h, bpp;
+ Pixmap pixmap = (Pixmap)iupImageGetImage(name, dc->ih, make_inactive);
+ if (!pixmap)
+ return;
+
+ /* must use this info, since image can be a driver image loaded from resources */
+ iupdrvImageGetInfo((void*)pixmap, &img_w, &img_h, &bpp);
+
+ XCopyArea(iupmot_display, pixmap, dc->pixmap, dc->pixmap_gc, 0, 0, img_w, img_h, x, y);
+}
diff --git a/iup/src/mot/iupmot_drv.h b/iup/src/mot/iupmot_drv.h
index 8a536ef..424ae9f 100755
--- a/iup/src/mot/iupmot_drv.h
+++ b/iup/src/mot/iupmot_drv.h
@@ -65,7 +65,7 @@ void iupmotGetWindowSize(Ihandle *ih, int *width, int *height);
char* iupmotGetXWindowAttrib(Ihandle *ih);
-#define iupmotSetArg(_a, _i, _n, _d) ((_a)[(_i)].name = (_n), (_a)[(_i)].value = (XtArgVal)(_d), (_i)++)
+#define iupMOT_SETARG(_a, _i, _n, _d) ((_a)[(_i)].name = (_n), (_a)[(_i)].value = (XtArgVal)(_d), (_i)++)
#ifdef __cplusplus
diff --git a/iup/src/mot/iupmot_filedlg.c b/iup/src/mot/iupmot_filedlg.c
index 768dd2b..0be6319 100755
--- a/iup/src/mot/iupmot_filedlg.c
+++ b/iup/src/mot/iupmot_filedlg.c
@@ -17,6 +17,7 @@
#include <Xm/DrawingA.h>
#include <Xm/PushB.h>
#include <Xm/Frame.h>
+#include <Xm/List.h>
#include "iup.h"
#include "iupcbs.h"
@@ -28,6 +29,7 @@
#include "iup_dialog.h"
#include "iup_strmessage.h"
#include "iup_drvinfo.h"
+#include "iup_array.h"
#include "iupmot_drv.h"
@@ -87,14 +89,14 @@ static int motFileDlgCheckValue(Ihandle* ih, Widget w)
return 0;
}
}
- else
+ else if (!iupAttribGetBoolean(ih, "MULTIPLEFILES"))
{
if (iupdrvIsDirectory(value)) /* selected a directory */
{
iupStrMessageShowError(ih, "IUP_INVALIDDIR");
return 0;
}
- else if (!iupdrvIsFile(value)) /* new file */
+ else if (!iupdrvIsFile(value)) /* not a file == new file */
{
value = iupAttribGet(ih, "ALLOWNEW");
if (!value)
@@ -132,6 +134,51 @@ static void motFileDlgCBclose(Widget w, XtPointer client_data, XtPointer call_da
iupAttribSetStr(ih, "_IUP_WM_DELETE", "1");
}
+static int motFileDlgGetMultipleFiles(Ihandle* ih, const char* dir, Widget wList)
+{
+ int *pos, sel_count, dir_len;
+ int i, len, cur_len;
+ char *filename, *all_names;
+ Iarray* names_array;
+ XmString* items;
+
+ if (!XmListGetSelectedPos(wList, &pos, &sel_count))
+ return 0;
+
+ names_array = iupArrayCreate(1024, 1); /* just set an initial size, but count is 0 */
+ XtVaGetValues(wList, XmNitems, &items, NULL);
+
+ cur_len = strlen(dir);
+
+ all_names = iupArrayAdd(names_array, cur_len+1);
+ memcpy(all_names, dir, cur_len);
+ all_names[cur_len] = '|';
+ dir_len = cur_len;
+ cur_len++; /* skip separator */
+
+ for (i = 0; i<sel_count; i++)
+ {
+ filename = iupmotConvertString(items[pos[i]-1]); /* XmListGetSelectedPos starts at 1 */
+ len = strlen(filename)-dir_len;
+
+ cur_len = iupArrayCount(names_array);
+ all_names = iupArrayAdd(names_array, len+1);
+ memcpy(all_names+cur_len, filename+dir_len, len);
+ all_names[cur_len+len] = '|';
+ }
+
+ XtFree((char*)pos);
+
+ cur_len = iupArrayCount(names_array);
+ all_names = iupArrayInc(names_array);
+ all_names[cur_len+1] = 0;
+
+ iupAttribStoreStr(ih, "VALUE", all_names);
+
+ iupArrayDestroy(names_array);
+ return 1;
+}
+
static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallbackStruct* call_data)
{
(void)w;
@@ -151,14 +198,38 @@ static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallback
iupAttribSetStr(ih, "STATUS", "0");
iupAttribSetStr(ih, "FILEEXIST", NULL);
}
+ else if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
+ {
+ Widget wList = XmFileSelectionBoxGetChild(w, XmDIALOG_LIST);
+
+ /* VALUE obtained above contains exactly the DIRECTORY */
+ char* dir = iupAttribGet(ih, "VALUE");
+ int len = strlen(dir);
+ if (dir[len-1]=='/') dir[len-1] = 0; /* remove last '/' */
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+
+ if (!motFileDlgGetMultipleFiles(ih, iupAttribGet(ih, "DIRECTORY"), wList))
+ {
+ iupStrMessageShowError(ih, "IUP_FILENOTEXIST");
+ return;
+ }
+
+ iupAttribSetStr(ih, "STATUS", "0");
+ iupAttribSetStr(ih, "FILEEXIST", "YES");
+ }
else
{
IFnss file_cb = (IFnss)IupGetCallback(ih, "FILE_CB");
- if (file_cb && file_cb(ih, iupAttribGet(ih, "VALUE"), "OK") == IUP_IGNORE)
+ filename = iupAttribGet(ih, "VALUE");
+ if (file_cb && file_cb(ih, filename, "OK") == IUP_IGNORE)
return;
- if (iupdrvIsFile(iupAttribGet(ih, "VALUE"))) /* check if file exists */
+ if (iupdrvIsFile(filename)) /* check if file exists */
{
+ char* dir = iupStrFileGetPath(filename);
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+ free(dir);
+
iupAttribSetStr(ih, "FILEEXIST", "YES");
iupAttribSetStr(ih, "STATUS", "0");
}
@@ -188,9 +259,8 @@ static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallback
}
}
-static void motFileDlgHelpCallback(Widget w, XtPointer client_data, XtPointer call_data)
+static void motFileDlgHelpCallback(Widget w, Ihandle *ih, XtPointer call_data)
{
- Ihandle *ih = (Ihandle*)client_data;
Icallback cb = IupGetCallback(ih, "HELP_CB");
if (cb && cb(ih) == IUP_CLOSE)
{
@@ -340,14 +410,15 @@ static void motFileDlgPreviewCanvasExposeCallback(Widget w, Ihandle *ih, XtPoint
static void motFileDlgBrowseSelectionCallback(Widget w, Ihandle* ih, XmListCallbackStruct* list_data)
{
char* filename;
+ IFnss cb;
XmStringGetLtoR(list_data->item, XmSTRING_DEFAULT_CHARSET, &filename);
+ cb = (IFnss)IupGetCallback(ih, "FILE_CB");
if (iupdrvIsFile(filename))
- {
- IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
cb(ih, filename, "SELECT");
- }
+ else
+ cb(ih, filename, "OTHER");
XtFree(filename);
(void)w;
@@ -417,6 +488,13 @@ static int motFileDlgPopup(Ihandle* ih, int x, int y)
if (dialogtype == IUP_DIALOGDIR)
XtVaSetValues(filebox, XmNfileTypeMask, XmFILE_DIRECTORY, NULL);
+ if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
+ {
+ Widget wList = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
+ XtVaSetValues(wList, XmNselectionPolicy, XmEXTENDED_SELECT, NULL);
+ XtAddCallback(wList, XmNextendedSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
+ }
+
/* just check for the path inside FILE */
value = iupAttribGet(ih, "FILE");
if (value && value[0] == '/')
@@ -501,8 +579,10 @@ static int motFileDlgPopup(Ihandle* ih, int x, int y)
file_cb = (IFnss)IupGetCallback(ih, "FILE_CB");
if (file_cb)
{
- Widget file_list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
- XtAddCallback(file_list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
+ Widget list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
+ XtAddCallback(list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
+ list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_DIR_LIST);
+ XtAddCallback(list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
if (iupAttribGetBoolean(ih, "SHOWPREVIEW"))
{
@@ -575,4 +655,6 @@ static int motFileDlgPopup(Ihandle* ih, int x, int y)
void iupdrvFileDlgInitClass(Iclass* ic)
{
ic->DlgPopup = motFileDlgPopup;
+
+ iupClassRegisterAttribute(ic, "MULTIPLEFILES", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT);
}
diff --git a/iup/src/mot/iupmot_font.c b/iup/src/mot/iupmot_font.c
index 8da06dd..42154b6 100755
--- a/iup/src/mot/iupmot_font.c
+++ b/iup/src/mot/iupmot_font.c
@@ -135,19 +135,19 @@ static XmFontList motFontCreateRenderTable(XFontStruct* fontstruct, int is_under
Arg args[10];
int num_args = 0;
- iupmotSetArg(args, num_args, XmNfontType, XmFONT_IS_FONT);
- iupmotSetArg(args, num_args, XmNfont, (XtPointer)fontstruct);
- iupmotSetArg(args, num_args, XmNloadModel, XmLOAD_IMMEDIATE);
+ iupMOT_SETARG(args, num_args, XmNfontType, XmFONT_IS_FONT);
+ iupMOT_SETARG(args, num_args, XmNfont, (XtPointer)fontstruct);
+ iupMOT_SETARG(args, num_args, XmNloadModel, XmLOAD_IMMEDIATE);
if (is_underline)
- iupmotSetArg(args, num_args, XmNunderlineType, XmSINGLE_LINE);
+ iupMOT_SETARG(args, num_args, XmNunderlineType, XmSINGLE_LINE);
else
- iupmotSetArg(args, num_args, XmNunderlineType, XmNO_LINE);
+ iupMOT_SETARG(args, num_args, XmNunderlineType, XmNO_LINE);
if (is_strikeout)
- iupmotSetArg(args, num_args, XmNstrikethruType, XmSINGLE_LINE);
+ iupMOT_SETARG(args, num_args, XmNstrikethruType, XmSINGLE_LINE);
else
- iupmotSetArg(args, num_args, XmNstrikethruType, XmNO_LINE);
+ iupMOT_SETARG(args, num_args, XmNstrikethruType, XmNO_LINE);
rendition = XmRenditionCreate(NULL, "", args, num_args);
diff --git a/iup/src/mot/iupmot_frame.c b/iup/src/mot/iupmot_frame.c
index 39de5d8..cfda44f 100755
--- a/iup/src/mot/iupmot_frame.c
+++ b/iup/src/mot/iupmot_frame.c
@@ -42,22 +42,33 @@ static int motFrameSetBgColorAttrib(Ihandle* ih, const char* value)
{
Pixel color;
- /* ignore given value, must use only from parent */
- value = iupBaseNativeParentGetBgColor(ih);
+ if (!iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+ {
+ /* ignore given value, must use only from parent */
+ value = iupBaseNativeParentGetBgColor(ih);
+ }
color = iupmotColorGetPixelStr(value);
if (color != (Pixel)-1)
{
Widget title_label, child_manager;
- iupmotSetBgColor(ih->handle, color);
+ if (!iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+ {
+ iupmotSetBgColor(ih->handle, color);
- child_manager = XtNameToWidget(ih->handle, "*child_manager");
- iupmotSetBgColor(child_manager, color);
+ child_manager = XtNameToWidget(ih->handle, "*child_manager");
+ iupmotSetBgColor(child_manager, color);
- title_label = XtNameToWidget(ih->handle, "*title_label");
- if (!title_label) return 1;
- iupmotSetBgColor(title_label, color);
+ title_label = XtNameToWidget(ih->handle, "*title_label");
+ if (!title_label) return 1;
+ iupmotSetBgColor(title_label, color);
+ }
+ else
+ {
+ child_manager = XtNameToWidget(ih->handle, "*child_manager");
+ iupmotSetBgColor(child_manager, color);
+ }
return 1;
}
@@ -171,22 +182,25 @@ static int motFrameMapMethod(Ihandle* ih)
{
char* value = iupAttribGetStr(ih, "SUNKEN");
if (iupStrBoolean(value))
- iupmotSetArg(args, num_args, XmNshadowType, XmSHADOW_IN);
+ iupMOT_SETARG(args, num_args, XmNshadowType, XmSHADOW_IN);
else
- iupmotSetArg(args, num_args, XmNshadowType, XmSHADOW_ETCHED_IN);
+ iupMOT_SETARG(args, num_args, XmNshadowType, XmSHADOW_ETCHED_IN);
+
+ if (iupAttribGet(ih, "BGCOLOR"))
+ iupAttribSetStr(ih, "_IUPFRAME_HAS_BGCOLOR", "1");
}
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Manager */
- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
/* Frame */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
ih->handle = XtCreateManagedWidget(
iupDialogGetChildIdStr(ih), /* child identifier */
@@ -204,11 +218,11 @@ static int motFrameMapMethod(Ihandle* ih)
Widget title_label;
num_args = 0;
/* Label */
- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
/* Frame Constraint */
- iupmotSetArg(args, num_args, XmNchildType, XmFRAME_TITLE_CHILD);
+ iupMOT_SETARG(args, num_args, XmNchildType, XmFRAME_TITLE_CHILD);
title_label = XtCreateManagedWidget("title_label", xmLabelWidgetClass, ih->handle, args, num_args);
iupmotSetString(title_label, XmNlabelString, title);
}
diff --git a/iup/src/mot/iupmot_key.c b/iup/src/mot/iupmot_key.c
index 835b5d7..9897741 100755
--- a/iup/src/mot/iupmot_key.c
+++ b/iup/src/mot/iupmot_key.c
@@ -393,33 +393,33 @@ void iupmotKeyPressEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
void iupmotButtonKeySetStatus(unsigned int state, unsigned int but, char* status, int doubleclick)
{
if (state & ShiftMask)
- iupKEYSETSHIFT(status);
+ iupKEY_SETSHIFT(status);
if (state & ControlMask)
- iupKEYSETCONTROL(status);
+ iupKEY_SETCONTROL(status);
if ((state & Button1Mask) || but==Button1)
- iupKEYSETBUTTON1(status);
+ iupKEY_SETBUTTON1(status);
if ((state & Button2Mask) || but==Button2)
- iupKEYSETBUTTON2(status);
+ iupKEY_SETBUTTON2(status);
if ((state & Button3Mask) || but==Button3)
- iupKEYSETBUTTON3(status);
+ iupKEY_SETBUTTON3(status);
if ((state & Button4Mask) || but==Button4)
- iupKEYSETBUTTON4(status);
+ iupKEY_SETBUTTON4(status);
if ((state & Button5Mask) || but==Button5)
- iupKEYSETBUTTON5(status);
+ iupKEY_SETBUTTON5(status);
if (state & Mod1Mask || state & Mod5Mask) /* Alt */
- iupKEYSETALT(status);
+ iupKEY_SETALT(status);
if (state & Mod4Mask) /* Apple/Win */
- iupKEYSETSYS(status);
+ iupKEY_SETSYS(status);
if (doubleclick)
- iupKEYSETDOUBLE(status);
+ iupKEY_SETDOUBLE(status);
}
diff --git a/iup/src/mot/iupmot_label.c b/iup/src/mot/iupmot_label.c
index 52dfc9a..afff3c3 100755
--- a/iup/src/mot/iupmot_label.c
+++ b/iup/src/mot/iupmot_label.c
@@ -147,8 +147,10 @@ static int motLabelSetPaddingAttrib(Ihandle* ih, const char* value)
{
XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
XmNmarginWidth, ih->data->horiz_padding, NULL);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int motLabelMapMethod(Ihandle* ih)
@@ -165,12 +167,12 @@ static int motLabelMapMethod(Ihandle* ih)
if (iupStrEqualNoCase(value, "HORIZONTAL"))
{
ih->data->type = IUP_LABEL_SEP_HORIZ;
- iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
+ iupMOT_SETARG(args, num_args, XmNorientation, XmHORIZONTAL);
}
else /* "VERTICAL" */
{
ih->data->type = IUP_LABEL_SEP_VERT;
- iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
+ iupMOT_SETARG(args, num_args, XmNorientation, XmVERTICAL);
}
}
else
@@ -180,32 +182,32 @@ static int motLabelMapMethod(Ihandle* ih)
if (value)
{
ih->data->type = IUP_LABEL_IMAGE;
- iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmPIXMAP);
}
else
{
ih->data->type = IUP_LABEL_TEXT;
- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING);
}
}
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Primitive */
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 0);
/* Label */
- iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
- iupmotSetArg(args, num_args, XmNmarginLeft, 0);
- iupmotSetArg(args, num_args, XmNmarginBottom, 0);
- iupmotSetArg(args, num_args, XmNmarginRight, 0);
+ iupMOT_SETARG(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginTop, 0); /* no extra margins */
+ iupMOT_SETARG(args, num_args, XmNmarginLeft, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginBottom, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginRight, 0);
ih->handle = XtCreateManagedWidget(
iupDialogGetChildIdStr(ih), /* child identifier */
diff --git a/iup/src/mot/iupmot_list.c b/iup/src/mot/iupmot_list.c
index f8e73ed..800e6e9 100755
--- a/iup/src/mot/iupmot_list.c
+++ b/iup/src/mot/iupmot_list.c
@@ -143,15 +143,36 @@ void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
motListAddSortedItem(ih, value);
else
motListAddItem(ih, pos, value);
+
+ iupListUpdateOldValue(ih, pos, 0);
}
void iupdrvListRemoveItem(Ihandle* ih, int pos)
{
/* The utility functions use 0=last 1=first */
if (ih->data->is_dropdown || ih->data->has_editbox)
+ {
+ if (ih->data->is_dropdown && !ih->data->has_editbox)
+ {
+ /* must check if removing the current item */
+ int curpos;
+ XtVaGetValues(ih->handle, XmNselectedPosition, &curpos, NULL);
+ if (pos == curpos && iupdrvListGetCount(ih)>1)
+ {
+ if (curpos > 0) curpos--;
+ else curpos++;
+
+ XtRemoveCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
+ XtVaSetValues(ih->handle, XmNselectedPosition, curpos, NULL);
+ XtAddCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
+ }
+ }
XmComboBoxDeletePos(ih->handle, pos+1);
+ }
else
XmListDeletePos(ih->handle, pos+1);
+
+ iupListUpdateOldValue(ih, pos, 1);
}
void iupdrvListRemoveAllItems(Ihandle* ih)
@@ -174,7 +195,7 @@ void iupdrvListRemoveAllItems(Ihandle* ih)
static char* motListGetIdValueAttrib(Ihandle* ih, const char* name_id)
{
int pos = iupListGetPos(ih, name_id);
- if (pos != -1)
+ if (pos >= 0)
{
XmString* items;
XtVaGetValues(ih->handle, XmNitems, &items, NULL);
@@ -852,8 +873,10 @@ static int motListSetNCAttrib(Ihandle* ih, const char* value)
Widget cbedit;
XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
XtVaSetValues(cbedit, XmNmaxLength, ih->data->nc, NULL);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int motListSetClipboardAttrib(Ihandle *ih, const char *value)
@@ -1181,32 +1204,32 @@ static int motListMapMethod(Ihandle* ih)
if (ih->data->is_dropdown || ih->data->has_editbox)
{
/* could not set XmNmappedWhenManaged to False because the list and the edit box where not displayed */
- /* iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0);
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ /* iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
if (ih->data->has_editbox)
{
if (ih->data->is_dropdown)
- iupmotSetArg(args, num_args, XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); /* hidden-list+edit */
+ iupMOT_SETARG(args, num_args, XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); /* hidden-list+edit */
else
- iupmotSetArg(args, num_args, XmNcomboBoxType, XmCOMBO_BOX); /* visible-list+edit */
+ iupMOT_SETARG(args, num_args, XmNcomboBoxType, XmCOMBO_BOX); /* visible-list+edit */
}
else
- iupmotSetArg(args, num_args, XmNcomboBoxType, XmDROP_DOWN_LIST); /* hidden-list */
+ iupMOT_SETARG(args, num_args, XmNcomboBoxType, XmDROP_DOWN_LIST); /* hidden-list */
ih->handle = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -1220,13 +1243,13 @@ static int motListMapMethod(Ihandle* ih)
/* Create the scrolled window */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
- iupmotSetArg(args, num_args, XmNborderWidth, 0);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
+ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
sb_win = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -1243,34 +1266,34 @@ static int motListMapMethod(Ihandle* ih)
/* Create the list */
num_args = 0;
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
- iupmotSetArg(args, num_args, XmNlistMarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNlistMarginWidth, 0);
- iupmotSetArg(args, num_args, XmNlistSpacing, 0);
- iupmotSetArg(args, num_args, XmNlistSizePolicy, XmCONSTANT); /* don't grow to fit, add scrollbar */
+ iupMOT_SETARG(args, num_args, XmNlistMarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNlistMarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNlistSpacing, 0);
+ iupMOT_SETARG(args, num_args, XmNlistSizePolicy, XmCONSTANT); /* don't grow to fit, add scrollbar */
if (ih->data->is_multiple)
- iupmotSetArg(args, num_args, XmNselectionPolicy, XmEXTENDED_SELECT);
+ iupMOT_SETARG(args, num_args, XmNselectionPolicy, XmEXTENDED_SELECT);
else
- iupmotSetArg(args, num_args, XmNselectionPolicy, XmBROWSE_SELECT);
+ iupMOT_SETARG(args, num_args, XmNselectionPolicy, XmBROWSE_SELECT);
if (iupAttribGetBoolean(ih, "AUTOHIDE"))
- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
+ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
else
- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC);
+ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC);
ih->handle = XtCreateManagedWidget(
child_id, /* child identifier */
diff --git a/iup/src/mot/iupmot_loop.c b/iup/src/mot/iupmot_loop.c
index 828ddcd..c1f92ec 100755
--- a/iup/src/mot/iupmot_loop.c
+++ b/iup/src/mot/iupmot_loop.c
@@ -56,7 +56,7 @@ void iupdrvSetIdleFunction(Icallback f)
mot_idle_id = XtAppAddWorkProc(iupmot_appcontext, motIdlecbWorkProc, NULL);
}
-static int motLoopStep(void)
+static int motLoopProcessEvent(void)
{
XtAppProcessEvent(iupmot_appcontext, XtIMAll);
return (mot_exitmainloop)? IUP_CLOSE : IUP_DEFAULT;
@@ -79,7 +79,7 @@ int IupMainLoop(void)
while (!mot_exitmainloop)
{
- if (motLoopStep() == IUP_CLOSE)
+ if (motLoopProcessEvent() == IUP_CLOSE)
break;
}
@@ -88,19 +88,26 @@ int IupMainLoop(void)
return IUP_NOERROR;
}
+int IupLoopStepWait(void)
+{
+ while(!XtAppPending(iupmot_appcontext));
+
+ return motLoopProcessEvent();
+}
+
int IupLoopStep(void)
{
if (!XtAppPending(iupmot_appcontext))
return IUP_DEFAULT;
- return motLoopStep();
+ return motLoopProcessEvent();
}
void IupFlush(void)
{
while (XPending(iupmot_display) != 0)
{
- if (motLoopStep() == IUP_CLOSE)
+ if (motLoopProcessEvent() == IUP_CLOSE)
break;
}
diff --git a/iup/src/mot/iupmot_menu.c b/iup/src/mot/iupmot_menu.c
index be9b953..8f51334 100755
--- a/iup/src/mot/iupmot_menu.c
+++ b/iup/src/mot/iupmot_menu.c
@@ -125,7 +125,10 @@ static void motPopupMenuUnmapCallback(Widget w, Ihandle* ih, XtPointer call_data
static void motMenuUnMapMethod(Ihandle* ih)
{
if (iupMenuIsMenuBar(ih))
+ {
XtDestroyWidget(ih->handle);
+ ih->parent = NULL;
+ }
else
XtDestroyWidget(XtParent(ih->handle)); /* in this case the RowColumn widget is a child of a MenuShell. */
}
@@ -146,7 +149,6 @@ static int motMenuMapMethod(Ihandle* ih)
XmNrowColumnType, XmMENU_BAR,
XmNmarginHeight, 0,
XmNmarginWidth, 0,
- XmNresizeWidth, False,
NULL);
if (!ih->handle)
return IUP_ERROR;
@@ -161,8 +163,8 @@ static int motMenuMapMethod(Ihandle* ih)
if (iupAttribGetBoolean(ih, "RADIO"))
{
- iupmotSetArg(args, num_args, XmNpacking, XmPACK_COLUMN);
- iupmotSetArg(args, num_args, XmNradioBehavior, TRUE);
+ iupMOT_SETARG(args, num_args, XmNpacking, XmPACK_COLUMN);
+ iupMOT_SETARG(args, num_args, XmNradioBehavior, TRUE);
}
ih->handle = XmCreatePulldownMenu(
@@ -183,7 +185,7 @@ static int motMenuMapMethod(Ihandle* ih)
{
/* top level menu used for IupPopup */
- iupmotSetArg(args, num_args, XmNpopupEnabled, XmPOPUP_AUTOMATIC);
+ iupMOT_SETARG(args, num_args, XmNpopupEnabled, XmPOPUP_AUTOMATIC);
ih->handle = XmCreatePopupMenu(
iupmot_appshell,
@@ -307,19 +309,19 @@ static int motItemMapMethod(Ihandle* ih)
if (iupAttribGetBoolean(ih->parent, "RADIO"))
{
- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
- iupmotSetArg(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
- iupmotSetArg(args, num_args, XmNindicatorSize, 13);
- iupmotSetArg(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
+ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+ iupMOT_SETARG(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
+ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
+ iupMOT_SETARG(args, num_args, XmNindicatorSize, 13);
+ iupMOT_SETARG(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
}
else
{
if (iupAttribGetBoolean(ih, "HIDEMARK"))
- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
+ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
else
- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK);
- iupmotSetArg(args, num_args, XmNlabelType, iupAttribGet(ih, "TITLEIMAGE")? XmPIXMAP: XmSTRING);
+ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK);
+ iupMOT_SETARG(args, num_args, XmNlabelType, iupAttribGet(ih, "TITLEIMAGE")? XmPIXMAP: XmSTRING);
}
ih->handle = XtCreateManagedWidget(
diff --git a/iup/src/mot/iupmot_progressbar.c b/iup/src/mot/iupmot_progressbar.c
index 7266d38..82fa178 100755
--- a/iup/src/mot/iupmot_progressbar.c
+++ b/iup/src/mot/iupmot_progressbar.c
@@ -98,25 +98,25 @@ static int motProgressBarMapMethod(Ihandle* ih)
Arg args[30];
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Primitive */
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 0);
/* Scale */
- iupmotSetArg(args, num_args, XmNminimum, 0);
- iupmotSetArg(args, num_args, XmNmaximum, SHRT_MAX);
- iupmotSetArg(args, num_args, XmNslidingMode, XmTHERMOMETER); /* thermometer effect */
- iupmotSetArg(args, num_args, XmNsliderMark, XmNONE);
- iupmotSetArg(args, num_args, XmNeditable, False);
- iupmotSetArg(args, num_args, XmNshowValue, XmNONE);
+ iupMOT_SETARG(args, num_args, XmNminimum, 0);
+ iupMOT_SETARG(args, num_args, XmNmaximum, SHRT_MAX);
+ iupMOT_SETARG(args, num_args, XmNslidingMode, XmTHERMOMETER); /* thermometer effect */
+ iupMOT_SETARG(args, num_args, XmNsliderMark, XmNONE);
+ iupMOT_SETARG(args, num_args, XmNeditable, False);
+ iupMOT_SETARG(args, num_args, XmNshowValue, XmNONE);
if (iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "VERTICAL"))
{
- iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
+ iupMOT_SETARG(args, num_args, XmNorientation, XmVERTICAL);
if (ih->currentheight < ih->currentwidth)
{
@@ -126,7 +126,7 @@ static int motProgressBarMapMethod(Ihandle* ih)
}
}
else
- iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
+ iupMOT_SETARG(args, num_args, XmNorientation, XmHORIZONTAL);
ih->handle = XtCreateManagedWidget(
iupDialogGetChildIdStr(ih), /* child identifier */
diff --git a/iup/src/mot/iupmot_tabs.c b/iup/src/mot/iupmot_tabs.c
index 7c8a6b5..cafc41d 100755
--- a/iup/src/mot/iupmot_tabs.c
+++ b/iup/src/mot/iupmot_tabs.c
@@ -52,8 +52,10 @@ void iupdrvTabsSetCurrentTab(Ihandle* ih, int pos)
{
Ihandle* child = IupGetChild(ih, pos);
Ihandle* prev_child = IupGetChild(ih, iupdrvTabsGetCurrentTab(ih));
- IupSetAttribute(child, "VISIBLE", "YES");
- IupSetAttribute(prev_child, "VISIBLE", "NO");
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ Widget prev_child_manager = (Widget)iupAttribGet(prev_child, "_IUPTAB_CONTAINER");
+ XtMapWidget(child_manager);
+ if (prev_child_manager) XtUnmapWidget(prev_child_manager);
XtVaSetValues(ih->handle, XmNcurrentPageNumber, pos, NULL);
}
@@ -200,7 +202,7 @@ static int motTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
ih->data->type = ITABS_TOP;
if (ih->handle)
- motTabsUpdateTabType(ih);
+ motTabsUpdateTabType(ih); /* for this to work must be updated in map */
return 0;
}
@@ -313,8 +315,10 @@ void motTabsPageChangedCallback(Widget w, Ihandle* ih, XmNotebookCallbackStruct
IFnnn cb;
Ihandle* child = IupGetChild(ih, nptr->page_number);
Ihandle* prev_child = IupGetChild(ih, nptr->prev_page_number);
- IupSetAttribute(child, "VISIBLE", "YES");
- IupSetAttribute(prev_child, "VISIBLE", "NO");
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ Widget prev_child_manager = (Widget)iupAttribGet(prev_child, "_IUPTAB_CONTAINER");
+ XtMapWidget(child_manager);
+ if (prev_child_manager) XtUnmapWidget(prev_child_manager);
cb = (IFnnn)IupGetCallback(ih, "TABCHANGE_CB");
if (cb)
@@ -397,12 +401,12 @@ static void motTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
/* Create tabs */
/* Label */
- iupmotSetArg(args, num_args, XmNlabelType, tabtitle? XmSTRING: XmPIXMAP);
- iupmotSetArg(args, num_args, XmNmarginHeight, 0);
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNlabelType, tabtitle? XmSTRING: XmPIXMAP);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
/* Notebook Constraint */
- iupmotSetArg(args, num_args, XmNnotebookChildType, XmMAJOR_TAB);
- iupmotSetArg(args, num_args, XmNpageNumber, pos);
+ iupMOT_SETARG(args, num_args, XmNnotebookChildType, XmMAJOR_TAB);
+ iupMOT_SETARG(args, num_args, XmNpageNumber, pos);
tab_button = XtCreateManagedWidget("tab_button", xmPushButtonWidgetClass, ih->handle, args, num_args);
/* Disable Drag Source */
@@ -450,10 +454,8 @@ static void motTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
iupAttribSetStr(child, "_IUPMOT_TABBUTTON", (char*)tab_button);
iupAttribSetInt(child, "_IUPMOT_TABNUMBER", pos);
- if (pos == iupdrvTabsGetCurrentTab(ih))
- IupSetAttribute(child, "VISIBLE", "YES");
- else
- IupSetAttribute(child, "VISIBLE", "NO");
+ if (pos != iupdrvTabsGetCurrentTab(ih))
+ XtUnmapWidget(child_manager);
}
}
@@ -464,20 +466,11 @@ static void motTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
if (child_manager)
{
- int cur_pos, pos;
+ int pos;
Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
- cur_pos = iupdrvTabsGetCurrentTab(ih);
pos = iupAttribGetInt(child, "_IUPMOT_TABNUMBER"); /* did not work when using XtVaGetValues(child_manager, XmNpageNumber) */
- if (cur_pos == pos)
- {
- if (cur_pos == 0)
- cur_pos = 1;
- else
- cur_pos--;
-
- iupdrvTabsSetCurrentTab(ih, cur_pos);
- }
+ iupTabsTestRemoveTab(ih, pos);
XtDestroyWidget(tab_button);
XtDestroyWidget(child_manager);
@@ -501,22 +494,22 @@ static int motTabsMapMethod(Ihandle* ih)
return IUP_ERROR;
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Manager */
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 0);
/* Notebook */
- iupmotSetArg(args, num_args, XmNbindingType, XmNONE);
- iupmotSetArg(args, num_args, XmNbindingWidth, 0);
- iupmotSetArg(args, num_args, XmNfirstPageNumber, 0); /* IupTabs index always starts with zero */
- iupmotSetArg(args, num_args, XmNbackPageSize, 0);
- iupmotSetArg(args, num_args, XmNbackPageNumber, 1);
- iupmotSetArg(args, num_args, XmNframeShadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNbindingType, XmNONE);
+ iupMOT_SETARG(args, num_args, XmNbindingWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNfirstPageNumber, 0); /* IupTabs index always starts with zero */
+ iupMOT_SETARG(args, num_args, XmNbackPageSize, 0);
+ iupMOT_SETARG(args, num_args, XmNbackPageNumber, 1);
+ iupMOT_SETARG(args, num_args, XmNframeShadowThickness, 2);
ih->handle = XtCreateManagedWidget(
iupDialogGetChildIdStr(ih), /* child identifier */
@@ -589,5 +582,5 @@ void iupdrvTabsInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "TABORIENTATION", iupTabsGetTabOrientationAttrib, NULL, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* can not be set, always HORIZONTAL in Motif */
iupClassRegisterAttributeId(ic, "TABTITLE", NULL, motTabsSetTabTitleAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, motTabsSetTabImageAttrib, IUPAF_NO_INHERIT);
- iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, motTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, motTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
}
diff --git a/iup/src/mot/iupmot_text.c b/iup/src/mot/iupmot_text.c
index 4a8f936..d9d2c74 100755
--- a/iup/src/mot/iupmot_text.c
+++ b/iup/src/mot/iupmot_text.c
@@ -142,8 +142,10 @@ static int motTextSetPaddingAttrib(Ihandle* ih, const char* value)
{
XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
XmNmarginWidth, ih->data->horiz_padding, NULL);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int motTextSetReadOnlyAttrib(Ihandle* ih, const char* value)
@@ -164,7 +166,7 @@ static char* motTextGetReadOnlyAttrib(Ihandle* ih)
static int motTextSetInsertAttrib(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;
@@ -207,12 +209,12 @@ static char* motTextGetSelectedTextAttrib(Ihandle* ih)
static int motTextSetAppendAttrib(Ihandle* ih, const char* value)
{
XmTextPosition pos;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
pos = XmTextGetLastPosition(ih->handle);
/* disable callbacks */
iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
- if (ih->data->is_multiline && ih->data->append_newline)
+ if (ih->data->is_multiline && ih->data->append_newline && pos!=0)
XmTextInsert(ih->handle, pos, "\n");
if (value)
XmTextInsert(ih->handle, pos+1, (char*)value);
@@ -482,8 +484,12 @@ static int motTextSetNCAttrib(Ihandle* ih, const char* value)
if (!iupStrToInt(value, &ih->data->nc))
ih->data->nc = INT_MAX;
if (ih->handle)
+ {
XtVaSetValues(ih->handle, XmNmaxLength, ih->data->nc, NULL);
- return 0;
+ return 0;
+ }
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int motTextSetClipboardAttrib(Ihandle *ih, const char *value)
@@ -911,6 +917,10 @@ static void motTextLayoutUpdateMethod(Ihandle* ih)
Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
if (spinbox && XmIsSpinBox(spinbox))
{
+ /* avoid abort in X */
+ if (ih->currentwidth == 0) ih->currentwidth = 1;
+ if (ih->currentheight == 0) ih->currentheight = 1;
+
XtVaSetValues(ih->handle,
XmNwidth, (XtArgVal)ih->currentwidth-ih->currentheight/2,
XmNheight, (XtArgVal)ih->currentheight,
@@ -952,13 +962,13 @@ static int motTextMapMethod(Ihandle* ih)
/* Create the scrolled window */
/******************************/
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
- iupmotSetArg(args, num_args, XmNborderWidth, 0);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
+ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
sb_win = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -973,9 +983,9 @@ static int motTextMapMethod(Ihandle* ih)
child_id = "text";
num_args = 0;
- iupmotSetArg(args, num_args, XmNeditMode, XmMULTI_LINE_EDIT);
+ iupMOT_SETARG(args, num_args, XmNeditMode, XmMULTI_LINE_EDIT);
if (wordwrap)
- iupmotSetArg(args, num_args, XmNwordWrap, True);
+ iupMOT_SETARG(args, num_args, XmNwordWrap, True);
}
else
{
@@ -986,18 +996,18 @@ static int motTextMapMethod(Ihandle* ih)
Widget spinbox;
num_args = 0;
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between spin and text */
- iupmotSetArg(args, num_args, XmNborderWidth, 0);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNmarginHeight, 0);
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNarrowSize, 8);
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between spin and text */
+ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNarrowSize, 8);
if (iupStrEqualNoCase(iupAttribGetStr(ih, "SPINALIGN"), "LEFT"))
- iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_BEGINNING);
+ iupMOT_SETARG(args, num_args, XmNarrowLayout, XmARROWS_BEGINNING);
else
- iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_END);
+ iupMOT_SETARG(args, num_args, XmNarrowLayout, XmARROWS_END);
spinbox = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -1019,61 +1029,61 @@ static int motTextMapMethod(Ihandle* ih)
}
num_args = 0;
- iupmotSetArg(args, num_args, XmNeditMode, XmSINGLE_LINE_EDIT);
+ iupMOT_SETARG(args, num_args, XmNeditMode, XmSINGLE_LINE_EDIT);
if (spin)
{
/* Spin Constraints */
- iupmotSetArg(args, num_args, XmNspinBoxChildType, XmNUMERIC);
- iupmotSetArg(args, num_args, XmNminimumValue, 0);
- iupmotSetArg(args, num_args, XmNmaximumValue, 100);
- iupmotSetArg(args, num_args, XmNposition, 0);
+ iupMOT_SETARG(args, num_args, XmNspinBoxChildType, XmNUMERIC);
+ iupMOT_SETARG(args, num_args, XmNminimumValue, 0);
+ iupMOT_SETARG(args, num_args, XmNmaximumValue, 100);
+ iupMOT_SETARG(args, num_args, XmNposition, 0);
if (iupAttribGetBoolean(ih, "SPINWRAP"))
- iupmotSetArg(args, num_args, XmNwrap, TRUE);
+ iupMOT_SETARG(args, num_args, XmNwrap, TRUE);
else
- iupmotSetArg(args, num_args, XmNwrap, FALSE);
+ iupMOT_SETARG(args, num_args, XmNwrap, FALSE);
}
else
{
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
}
}
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNverifyBell, False);
- iupmotSetArg(args, num_args, XmNspacing, 0);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNverifyBell, False);
+ iupMOT_SETARG(args, num_args, XmNspacing, 0);
if (iupAttribGetBoolean(ih, "BORDER"))
- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
else
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
if (ih->data->is_multiline)
{
if (ih->data->sb & IUP_SB_HORIZ)
- iupmotSetArg(args, num_args, XmNscrollHorizontal, True);
+ iupMOT_SETARG(args, num_args, XmNscrollHorizontal, True);
else
- iupmotSetArg(args, num_args, XmNscrollHorizontal, False);
+ iupMOT_SETARG(args, num_args, XmNscrollHorizontal, False);
if (ih->data->sb & IUP_SB_VERT)
- iupmotSetArg(args, num_args, XmNscrollVertical, True);
+ iupMOT_SETARG(args, num_args, XmNscrollVertical, True);
else
- iupmotSetArg(args, num_args, XmNscrollVertical, False);
+ iupMOT_SETARG(args, num_args, XmNscrollVertical, False);
}
ih->handle = XtCreateManagedWidget(
diff --git a/iup/src/mot/iupmot_toggle.c b/iup/src/mot/iupmot_toggle.c
index b18f24d..1fda258 100755
--- a/iup/src/mot/iupmot_toggle.c
+++ b/iup/src/mot/iupmot_toggle.c
@@ -236,8 +236,10 @@ static int motToggleSetPaddingAttrib(Ihandle* ih, const char* value)
{
XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
XmNmarginWidth, ih->data->horiz_padding, NULL);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static char* motToggleGetSelectColorAttrib(Ihandle* ih)
@@ -336,40 +338,40 @@ static int motToggleMapMethod(Ihandle* ih)
if (value)
{
ih->data->type = IUP_TOGGLE_IMAGE;
- iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmPIXMAP);
}
else
{
ih->data->type = IUP_TOGGLE_TEXT;
- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
+ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING);
}
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Primitive */
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
/* Label */
- iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
- iupmotSetArg(args, num_args, XmNmarginLeft, 0);
- iupmotSetArg(args, num_args, XmNmarginBottom, 0);
- iupmotSetArg(args, num_args, XmNmarginRight, 0);
+ iupMOT_SETARG(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginTop, 0); /* no extra margins */
+ iupMOT_SETARG(args, num_args, XmNmarginLeft, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginBottom, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginRight, 0);
if (radio)
{
- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
- iupmotSetArg(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
+ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+ iupMOT_SETARG(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
if (!iupAttribGet(radio, "_IUPMOT_LASTTOGGLE"))
{
@@ -380,33 +382,33 @@ static int motToggleMapMethod(Ihandle* ih)
else
{
if (ih->data->type == IUP_TOGGLE_TEXT && iupAttribGetBoolean(ih, "3STATE"))
- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_INDETERMINATE);
+ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_INDETERMINATE);
else
- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
- iupmotSetArg(args, num_args, XmNindicatorType, XmN_OF_MANY);
+ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+ iupMOT_SETARG(args, num_args, XmNindicatorType, XmN_OF_MANY);
}
if (ih->data->type == IUP_TOGGLE_IMAGE)
{
- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
- iupmotSetArg(args, num_args, XmNalignment, XmALIGNMENT_CENTER);
- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
+ iupMOT_SETARG(args, num_args, XmNalignment, XmALIGNMENT_CENTER);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
}
else
{
- iupmotSetArg(args, num_args, XmNspacing, 3);
- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
- iupmotSetArg(args, num_args, XmNalignment, XmALIGNMENT_BEGINNING);
+ iupMOT_SETARG(args, num_args, XmNspacing, 3);
+ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
+ iupMOT_SETARG(args, num_args, XmNalignment, XmALIGNMENT_BEGINNING);
if (radio)
{
- iupmotSetArg(args, num_args, XmNindicatorSize, 13);
- iupmotSetArg(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
+ iupMOT_SETARG(args, num_args, XmNindicatorSize, 13);
+ iupMOT_SETARG(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
}
else
- iupmotSetArg(args, num_args, XmNindicatorSize, 15);
+ iupMOT_SETARG(args, num_args, XmNindicatorSize, 15);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNdetailShadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNdetailShadowThickness, 2);
}
ih->handle = XtCreateManagedWidget(
diff --git a/iup/src/mot/iupmot_tree.c b/iup/src/mot/iupmot_tree.c
index eb230af..fa5ef09 100755
--- a/iup/src/mot/iupmot_tree.c
+++ b/iup/src/mot/iupmot_tree.c
@@ -46,48 +46,20 @@ typedef struct _motTreeItemData
Pixmap image, image_mask;
Pixmap image_expanded, image_expanded_mask;
unsigned char kind;
- void* userdata;
} motTreeItemData;
static void motTreeShowEditField(Ihandle* ih, Widget wItem);
-static int motTreeGetNodeId(Ihandle* ih, Widget wItem);
+static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_data, int call_cb);
-typedef int (*motTreeNodeFunc)(Ihandle* ih, Widget wItem, void* userdata);
-
-static int motTreeForEach(Ihandle* ih, Widget wItem, motTreeNodeFunc func, void* userdata)
-{
- WidgetList wItemChildList = NULL;
- int i, numChild;
-
- if (!wItem)
- wItem = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
- if (!func(ih, wItem, userdata))
- return 0;
-
- numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemChildList);
- for (i=0; i<numChild; i++)
- {
- /* Recursively traverse child items */
- if (!motTreeForEach(ih, wItemChildList[i], func, userdata))
- {
- XtFree((char*)wItemChildList);
- return 0;
- }
- }
- if (wItemChildList) XtFree((char*)wItemChildList);
-
- return 1;
-}
/*****************************************************************************/
/* COPYING ITEMS (Branches and its children) */
/*****************************************************************************/
/* Insert the copied item in a new location. Returns the new item. */
-static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos, int full_copy)
+static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos, int is_copy)
{
- Widget wNewItem;
+ Widget wItemNew;
XmString title;
motTreeItemData *itemData;
Pixel fgcolor, bgcolor;
@@ -96,13 +68,13 @@ static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos
Pixmap image = XmUNSPECIFIED_PIXMAP, mask = XmUNSPECIFIED_PIXMAP;
unsigned char state;
- iupmotSetArg(args, num_args, XmNentryParent, wParent);
- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNentryParent, wParent);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, ih->data->spacing);
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNviewType, XmSMALL_ICON);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
/* Get values to copy */
XtVaGetValues(wItem, XmNlabelString, &title,
@@ -113,49 +85,73 @@ static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos
XmNoutlineState, &state,
NULL);
- if (full_copy) /* during a full copy the userdata reference is not copied */
+ if (is_copy) /* during a copy the itemdata reference is not reused */
{
/* create a new one */
motTreeItemData* itemDataNew = malloc(sizeof(motTreeItemData));
memcpy(itemDataNew, itemData, sizeof(motTreeItemData));
- itemDataNew->userdata = NULL;
itemData = itemDataNew;
}
- iupmotSetArg(args, num_args, XmNlabelString, title);
- iupmotSetArg(args, num_args, XmNuserData, itemData);
- iupmotSetArg(args, num_args, XmNforeground, fgcolor);
- iupmotSetArg(args, num_args, XmNsmallIconPixmap, image);
- iupmotSetArg(args, num_args, XmNsmallIconMask, mask);
- iupmotSetArg(args, num_args, XmNoutlineState, state);
+ iupMOT_SETARG(args, num_args, XmNlabelString, title);
+ iupMOT_SETARG(args, num_args, XmNuserData, itemData);
+ iupMOT_SETARG(args, num_args, XmNforeground, fgcolor);
+ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, image);
+ iupMOT_SETARG(args, num_args, XmNsmallIconMask, mask);
+ iupMOT_SETARG(args, num_args, XmNoutlineState, state);
- iupmotSetArg(args, num_args, XmNentryParent, wParent);
- iupmotSetArg(args, num_args, XmNpositionIndex, pos);
+ iupMOT_SETARG(args, num_args, XmNentryParent, wParent);
+ iupMOT_SETARG(args, num_args, XmNpositionIndex, pos);
XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
- iupmotSetArg(args, num_args, XmNbackground, bgcolor);
+ iupMOT_SETARG(args, num_args, XmNbackground, bgcolor);
+
+ /* Add the new node */
+ wItemNew = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+ ih->data->node_count++;
+
+ XtRealizeWidget(wItemNew);
+
+ return wItemNew;
+}
+
+static void motTreeChildRebuildCacheRec(Ihandle* ih, Widget wItem, int *id)
+{
+ WidgetList itemChildList = NULL;
+ int i, numChild;
- wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+ /* Check whether we have child items */
+ numChild = XmContainerGetItemChildren(ih->handle, wItem, &itemChildList);
+
+ for (i = 0; i < numChild; i++)
+ {
+ (*id)++;
+ ih->data->node_cache[*id].node_handle = itemChildList[i];
- /* Root always expanded */
- XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
+ /* go recursive to children */
+ motTreeChildRebuildCacheRec(ih, itemChildList[i], id);
+ }
- XtRealizeWidget(wNewItem);
+ if (itemChildList) XtFree((char*)itemChildList);
+}
- return wNewItem;
+static void motTreeRebuildNodeCache(Ihandle* ih, int id, Widget wItem)
+{
+ ih->data->node_cache[id].node_handle = wItem;
+ motTreeChildRebuildCacheRec(ih, wItem, &id);
}
-static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy)
+static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int is_copy)
{
WidgetList wItemChildList = NULL;
int i = 0;
int numChild = XmContainerGetItemChildren(ih->handle, wItemSrc, &wItemChildList);
while(i != numChild)
{
- Widget wNewItem = motTreeCopyItem(ih, wItemChildList[i], wItemDst, i, full_copy); /* Use the same order they where enumerated */
+ Widget wItemNew = motTreeCopyItem(ih, wItemChildList[i], wItemDst, i, is_copy); /* Use the same order they where enumerated */
/* Recursively transfer all the items */
- motTreeCopyChildren(ih, wItemChildList[i], wNewItem, full_copy);
+ motTreeCopyChildren(ih, wItemChildList[i], wItemNew, is_copy);
/* Go to next sibling item */
i++;
@@ -165,12 +161,18 @@ static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, i
}
/* Copies all items in a branch to a new location. Returns the new branch node. */
-static Widget motTreeCopyNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy)
+static Widget motTreeCopyMoveNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int is_copy)
{
- Widget wNewItem, wParent;
+ Widget wItemNew, wParent;
motTreeItemData *itemDataDst;
unsigned char stateDst;
- int pos;
+ int pos, id_new, count, id_src, id_dst;
+
+ int old_count = ih->data->node_count;
+
+ id_src = iupTreeFindNodeId(ih, wItemSrc);
+ id_dst = iupTreeFindNodeId(ih, wItemDst);
+ id_new = id_dst+1; /* contains the position for a copy operation */
XtVaGetValues(wItemDst, XmNoutlineState, &stateDst,
XmNuserData, &itemDataDst,
@@ -184,17 +186,46 @@ static Widget motTreeCopyNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int
}
else
{
+ if (itemDataDst->kind == ITREE_BRANCH)
+ {
+ int child_count = iupdrvTreeTotalChildCount(ih, wItemDst);
+ id_new += child_count;
+ }
+
/* copy as next brother of item or collapsed branch */
XtVaGetValues(wItemDst, XmNentryParent, &wParent, NULL);
XtVaGetValues(wItemDst, XmNpositionIndex, &pos, NULL);
pos++;
}
- wNewItem = motTreeCopyItem(ih, wItemSrc, wParent, pos, full_copy);
+ /* move to the same place does nothing */
+ if (!is_copy && id_new == id_src)
+ return NULL;
+
+ wItemNew = motTreeCopyItem(ih, wItemSrc, wParent, pos, is_copy);
+
+ motTreeCopyChildren(ih, wItemSrc, wItemNew, is_copy);
+
+ count = ih->data->node_count - old_count;
+ iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy);
- motTreeCopyChildren(ih, wItemSrc, wNewItem, full_copy);
+ if (!is_copy)
+ {
+ /* Deleting the node (and its children) from the old position */
+ /* do not delete the itemdata, we reuse the references in CopyNode */
+ motTreeRemoveNode(ih, wItemSrc, 0, 0);
+
+ /* restore count, because we remove src */
+ ih->data->node_count = old_count;
+
+ /* compensate position for a move */
+ if (id_new > id_src)
+ id_new -= count;
+ }
- return wNewItem;
+ motTreeRebuildNodeCache(ih, id_new, wItemNew);
+
+ return wItemNew;
}
static void motTreeContainerDeselectAll(Ihandle *ih)
@@ -233,229 +264,181 @@ static void motTreeContainerSelectAll(Ihandle *ih)
XtCallActionProc(ih->handle, "ContainerSelectAll", (XEvent*)&ev, 0, 0);
}
-static Widget motTreeGetLastVisibleNode(Ihandle* ih, Widget wItem)
+static int motTreeIsNodeVisible(Widget wItem, Widget *wLastItemParent)
{
- unsigned char itemState;
-
- XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
-
- if (itemState == XmEXPANDED)
+ unsigned char itemParentState;
+ Widget wItemParent = NULL;
+ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
+ if (!wItemParent || wItemParent == *wLastItemParent)
+ return 1;
+ while(wItemParent)
{
- WidgetList wChildrenTree = NULL;
- int numChildren = XmContainerGetItemChildren(ih->handle, wItem, &wChildrenTree);
- if(numChildren)
- wItem = motTreeGetLastVisibleNode(ih, wChildrenTree[numChildren - 1]);
- if (wChildrenTree) XtFree((char*)wChildrenTree);
+ XtVaGetValues(wItemParent, XmNoutlineState, &itemParentState, NULL);
+ if (itemParentState != XmEXPANDED)
+ return 0;
+
+ XtVaGetValues(wItemParent, XmNentryParent, &wItemParent, NULL);
}
- return wItem;
+ /* save last parent */
+ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
+ *wLastItemParent = wItemParent;
+ return 1;
}
-static Widget motTreeFindVisibleNodeId(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode)
+static Widget motTreeGetLastVisibleNode(Ihandle* ih)
{
- Widget itemChild;
- WidgetList itemChildList;
- int i = 0;
- int numChild;
- unsigned char itemState;
+ int i;
+ Widget wLastItemParent = NULL;
- while(i != numItems)
+ for (i = ih->data->node_count-1; i >= 0; i--)
{
- /* ID control to traverse items */
- ih->data->id_control++; /* not the real id since it counts only the visible ones */
-
- /* StateID founded! */
- if(itemList[i] == itemNode)
- return itemList[i];
-
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
-
- /* The itemWidget has child and it is expanded (visible) */
- if (numChild && itemState == XmEXPANDED)
- {
- /* pass the list of children of this item */
- itemChild = motTreeFindVisibleNodeId(ih, itemChildList, numChild, itemNode);
-
- /* StateID founded! */
- if(itemChild)
- {
- XtFree((char*)itemChildList);
- return itemChild;
- }
- }
-
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
+ if (motTreeIsNodeVisible(ih->data->node_cache[i].node_handle, &wLastItemParent))
+ return ih->data->node_cache[i].node_handle;
}
- return NULL;
+ return ih->data->node_cache[0].node_handle; /* root is always visible */
}
-static Widget motTreeFindVisibleNodeFromId(Ihandle* ih, WidgetList itemList, int numItems)
+static Widget motTreeGetNextVisibleNode(Ihandle* ih, Widget wItem, int count)
{
- Widget itemChild;
- WidgetList itemChildList;
- int i = 0;
- int numChild;
- unsigned char itemState;
+ int i, id;
+ Widget wLastItemParent = NULL;
- while(i != numItems)
- {
- /* ID control to traverse items */
- ih->data->id_control--; /* not the real id since it counts only the visible ones */
+ id = iupTreeFindNodeId(ih, wItem);
+ id += count;
- /* StateID founded! */
- if(ih->data->id_control < 0)
- return itemList[i];
+ for (i = id; i < ih->data->node_count; i++)
+ {
+ if (motTreeIsNodeVisible(ih->data->node_cache[i].node_handle, &wLastItemParent))
+ return ih->data->node_cache[i].node_handle;
+ }
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
+ return ih->data->node_cache[0].node_handle; /* root is always visible */
+}
- /* The itemWidget has child and it is expanded (visible) */
- if (numChild && itemState == XmEXPANDED)
- {
- /* pass the list of children of this item */
- itemChild = motTreeFindVisibleNodeFromId(ih, itemChildList, numChild);
+static Widget motTreeGetPreviousVisibleNode(Ihandle* ih, Widget wItem, int count)
+{
+ int i, id;
+ Widget wLastItemParent = NULL;
- /* StateID founded! */
- if(ih->data->id_control < 0)
- {
- if (itemChildList) XtFree((char*)itemChildList);
- return itemChild;
- }
- }
+ id = iupTreeFindNodeId(ih, wItem);
+ id -= count;
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
+ for (i = id; i >= 0; i--)
+ {
+ if (motTreeIsNodeVisible(ih->data->node_cache[i].node_handle, &wLastItemParent))
+ return ih->data->node_cache[i].node_handle;
}
- return NULL;
+ return motTreeGetLastVisibleNode(ih);
}
-static Widget motTreeGetNextVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem)
+static void motTreeChildCountRec(Ihandle* ih, Widget wItem, int *count)
{
- Widget wNext;
+ WidgetList itemChildList = NULL;
+ int i, numChild;
- ih->data->id_control = -1;
- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem);
- ih->data->id_control++; /* more 1 visible node */
+ /* Check whether we have child items */
+ numChild = XmContainerGetItemChildren(ih->handle, wItem, &itemChildList);
- wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+ for (i = 0; i < numChild; i++)
+ {
+ (*count)++;
- if (ih->data->id_control >= 0)
- wNext = motTreeGetLastVisibleNode(ih, wRoot);
+ /* go recursive to children */
+ motTreeChildCountRec(ih, itemChildList[i], count);
+ }
- return wNext;
+ if (itemChildList) XtFree((char*)itemChildList);
}
-static Widget motTreeGetPreviousVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem)
+int iupdrvTreeTotalChildCount(Ihandle* ih, Widget wItem)
{
- ih->data->id_control = -1;
- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem);
- ih->data->id_control--; /* less 1 visible node */
-
- if (ih->data->id_control < 0)
- ih->data->id_control = 0; /* Begin of tree = Root id */
-
- return motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+ int count = 0;
+ motTreeChildCountRec(ih, wItem, &count);
+ return count;
}
-static void motTreeUpdateBgColor(Ihandle* ih, WidgetList itemList, int numItems, Pixel bgcolor)
+static void motTreeUpdateBgColor(Ihandle* ih, Pixel bgcolor)
{
- WidgetList itemChildList;
- int i = 0;
- int numChild;
-
- while(i != numItems)
+ int i;
+ for (i = 0; i < ih->data->node_count; i++)
{
- XtVaSetValues(itemList[i], XmNbackground, bgcolor, NULL);
-
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- if(numChild)
- motTreeUpdateBgColor(ih, itemChildList, numChild, bgcolor);
- if (itemChildList) XtFree((char*)itemChildList);
-
- /* Go to next sibling item */
- i++;
+ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNbackground, bgcolor, NULL);
}
}
-static void motTreeUpdateImages(Ihandle* ih, WidgetList itemList, int numItems, int mode)
+static void motTreeUpdateImages(Ihandle* ih, int mode)
{
- motTreeItemData *itemData;
- int i = 0;
-
+ int i;
/* called when one of the default images is changed */
-
- while(i != numItems)
+ for (i = 0; i < ih->data->node_count; i++)
{
- /* Get node attributes */
- XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL);
-
+ motTreeItemData *itemData;
+ Widget wItem = ih->data->node_cache[i].node_handle;
+
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+
if (itemData->kind == ITREE_BRANCH)
{
unsigned char itemState;
- XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
+ XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
if (itemState == XmEXPANDED)
{
if (mode == ITREE_UPDATEIMAGE_EXPANDED)
{
- XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL);
- XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL);
+ XtVaSetValues(wItem, XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL);
+ XtVaSetValues(wItem, XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL);
}
}
else
{
if (mode == ITREE_UPDATEIMAGE_COLLAPSED)
{
- XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL);
- XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL);
+ XtVaSetValues(wItem, XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL);
+ XtVaSetValues(wItem, XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL);
}
}
-
- /* Recursively traverse child items */
- {
- WidgetList itemChildList;
- int numChild;
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- motTreeUpdateImages(ih, itemChildList, numChild, mode);
- if (itemChildList) XtFree((char*)itemChildList);
- }
}
else
{
if (mode == ITREE_UPDATEIMAGE_LEAF)
{
- XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_leaf, NULL);
- XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_leaf_mask, NULL);
+ XtVaSetValues(wItem, XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_leaf, NULL);
+ XtVaSetValues(wItem, XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_leaf_mask, NULL);
}
}
-
- /* Go to next sibling node */
- i++;
}
}
-static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int *select)
+static int motTreeIsNodeSelected(Widget wItem)
+{
+ unsigned char isSelected;
+ XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+ if(isSelected == XmSELECTED)
+ return 1;
+ else
+ return 0;
+}
+
+static void motTreeSelectNode(Widget wItem, int select)
+{
+ if (select == -1)
+ select = !motTreeIsNodeSelected(wItem); /* toggle */
+
+ if (select)
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ else
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+}
+
+static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int id, int *select)
{
int do_select = *select;
if (do_select == -1)
- {
- unsigned char isSelected;
- XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
- do_select = (isSelected == XmSELECTED)? 0: 1; /* toggle */
- }
+ do_select = !motTreeIsNodeSelected(wItem); /* toggle */
if (do_select)
XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
@@ -463,272 +446,111 @@ static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int *select)
XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
(void)ih;
+ (void)id;
return 1;
}
static void motTreeInvertAllNodeMarking(Ihandle* ih)
{
int select = -1;
- motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectFunc, &select);
+ iupTreeForEach(ih, (iupTreeNodeFunc)motTreeSelectFunc, &select);
}
-typedef struct _motTreeRange{
- Widget wItem1, wItem2;
- char inside, clear;
-}motTreeRange;
-
-static int motTreeSelectRangeFunc(Ihandle* ih, Widget wItem, motTreeRange* range)
+static void motTreeSelectRange(Ihandle* ih, Widget wItem1, Widget wItem2, int clear)
{
- int end_range = 0;
-
- if (range->inside == 0) /* detect the range start */
- {
- if (range->wItem1 == wItem) range->inside=1;
- else if (range->wItem2 == wItem) range->inside=1;
- }
- else if (range->inside == 1) /* detect the range end */
+ int i;
+ int id1 = iupTreeFindNodeId(ih, wItem1);
+ int id2 = iupTreeFindNodeId(ih, wItem2);
+ if (id1 > id2)
{
- if (range->wItem1 == wItem) end_range=1;
- else if (range->wItem2 == wItem) end_range=1;
+ int tmp = id1;
+ id1 = id2;
+ id2 = tmp;
}
- if (range->inside == 1) /* if inside, select */
- XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
- else if (range->clear) /* if outside and clear, unselect */
- XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
-
- if (end_range || (range->inside && range->wItem1==range->wItem2))
- range->inside=-1; /* update after selecting the node */
-
- (void)ih;
- return 1;
-}
-
-static void motTreeSelectRange(Ihandle* ih, Widget wItem1, Widget wItem2, int clear)
-{
- motTreeRange range;
- range.wItem1 = wItem1;
- range.wItem2 = wItem2;
- range.inside = 0;
- range.clear = (char)clear;
- motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectRangeFunc, &range);
-}
-
-void motTreeExpandCollapseAllNodes(Ihandle* ih, WidgetList itemList, int numItems, unsigned char itemState)
-{
- WidgetList itemChildList;
- int numChild;
- int i = 0;
-
- while(i != numItems)
+ for (i = 0; i < ih->data->node_count; i++)
{
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
-
- if(numChild)
+ if (i < id1 || i > id2)
{
- XtVaSetValues(itemList[i], XmNoutlineState, itemState, NULL);
- motTreeExpandCollapseAllNodes(ih, itemChildList, numChild, itemState);
+ if (clear)
+ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
}
-
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
+ else
+ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmSELECTED, NULL);
}
}
-static void motTreeDestroyItemData(Ihandle* ih, Widget wItem)
+void motTreeExpandCollapseAllNodes(Ihandle* ih, unsigned char itemState)
{
- motTreeItemData *itemData = NULL;
- XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
- if (itemData)
+ int i;
+ /* called when one of the default images is changed */
+ for (i = 0; i < ih->data->node_count; i++)
{
- IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
- if (cb) cb(ih, motTreeGetNodeId(ih, wItem), (char*)itemData->userdata);
- free(itemData);
- XtVaSetValues(wItem, XmNuserData, NULL, NULL);
- }
-}
-
-static void motTreeRemoveChildren(Ihandle* ih, WidgetList itemList, int numItems, int del_userdata)
-{
- WidgetList itemChildList;
- int numChild;
- int i = 0;
+ motTreeItemData *itemData;
+ Widget wItem = ih->data->node_cache[i].node_handle;
- while(i != numItems)
- {
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+
/* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- if (numChild)
- motTreeRemoveChildren(ih, itemChildList, numChild, del_userdata);
-
- if (del_userdata)
- motTreeDestroyItemData(ih, itemList[i]);
-
- XtDestroyWidget(itemList[i]);
-
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
+ if (itemData->kind == ITREE_BRANCH)
+ XtVaSetValues(wItem, XmNoutlineState, itemState, NULL);
}
}
-static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_userdata)
+static void motTreeDestroyItemData(Ihandle* ih, Widget wItem, int del_data, IFns cb, int id)
{
- WidgetList wChildList = NULL;
- int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wChildList);
- if (numChild)
- motTreeRemoveChildren(ih, wChildList, numChild, del_userdata);
- if (del_userdata)
- motTreeDestroyItemData(ih, wItem);
- XtDestroyWidget(wItem);
- if (wChildList) XtFree((char*)wChildList);
-}
-
-static Widget motTreeFindNodeID(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode)
-{
- Widget itemChild;
- WidgetList itemChildList;
- int i = 0;
- int numChild;
-
- while(i != numItems)
+ motTreeItemData *itemData = NULL;
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+ if (itemData)
{
- /* ID control to traverse items */
- ih->data->id_control++;
+ if (cb)
+ cb(ih, (char*)ih->data->node_cache[id].userdata);
- /* StateID founded! */
- if(itemList[i] == itemNode)
- return itemList[i];
-
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- if(numChild)
+ if (del_data)
{
- /* pass the list of children of this item */
- itemChild = motTreeFindNodeID(ih, itemChildList, numChild, itemNode);
-
- /* StateID founded! */
- if(itemChild)
- {
- if (itemChildList) XtFree((char*)itemChildList);
- return itemChild;
- }
+ free(itemData);
+ XtVaSetValues(wItem, XmNuserData, NULL, NULL);
}
-
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
}
-
- return NULL;
}
-static Widget motTreeFindNodeFromID(Ihandle* ih, WidgetList itemList, int numItems)
+static void motTreeRemoveNodeRec(Ihandle* ih, Widget wItem, int del_data, IFns cb, int *id)
{
- Widget itemChild;
- WidgetList itemChildList;
- int i = 0;
- int numChild;
+ WidgetList itemChildList = NULL;
+ int i, numChild;
+ int old_id = *id;
- while(i != numItems)
+ /* Check whether we have child items */
+ /* remove from children first */
+ numChild = XmContainerGetItemChildren(ih->handle, wItem, &itemChildList);
+ for (i = 0; i < numChild; i++)
{
- /* ID control to traverse items */
- ih->data->id_control--;
-
- /* StateID founded! */
- if(ih->data->id_control < 0)
- return itemList[i];
-
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- if(numChild)
- {
- /* pass the list of children of this item */
- itemChild = motTreeFindNodeFromID(ih, itemChildList, numChild);
-
- /* StateID founded! */
- if(ih->data->id_control < 0)
- {
- if (itemChildList) XtFree((char*)itemChildList);
- return itemChild;
- }
- }
-
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
+ /* go recursive to children */
+ motTreeRemoveNodeRec(ih, itemChildList[i], del_data, cb, id);
}
+ if (itemChildList) XtFree((char*)itemChildList);
- return NULL;
-}
+ /* actually do it for the node */
+ ih->data->node_count--;
+ (*id)++;
-static int motTreeGetNodeId(Ihandle* ih, Widget wItem)
-{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
- ih->data->id_control = -1;
- if (motTreeFindNodeID(ih, &wRoot, 1, wItem))
- return ih->data->id_control;
- else
- return -1;
+ if (del_data || cb)
+ motTreeDestroyItemData(ih, wItem, del_data, cb, old_id);
+
+ XtDestroyWidget(wItem); /* must manually destroy each node, this is NOT recursive */
}
-static Widget motTreeFindUserDataID(Ihandle* ih, WidgetList itemList, int numItems, void* userdata)
+static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_data, int call_cb)
{
- Widget itemChild;
- WidgetList itemChildList;
- motTreeItemData *itemData;
- int i = 0;
- int numChild;
-
- while(i != numItems)
- {
- /* ID control to traverse items */
- ih->data->id_control++;
-
- XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL);
-
- /* StateID founded! */
- if(itemData->userdata == userdata)
- return itemList[i];
+ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
+ int old_count = ih->data->node_count;
+ int id = iupTreeFindNodeId(ih, wItem);
+ int old_id = id;
- /* Check whether we have child items */
- itemChildList = NULL;
- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
- if(numChild)
- {
- /* pass the list of children of this item */
- itemChild = motTreeFindUserDataID(ih, itemChildList, numChild, userdata);
-
- /* StateID founded! */
- if (itemChild)
- {
- if (itemChildList) XtFree((char*)itemChildList);
- return itemChild;
- }
- }
+ motTreeRemoveNodeRec(ih, wItem, del_data, cb, &id);
- if (itemChildList) XtFree((char*)itemChildList);
- /* Go to next sibling item */
- i++;
- }
-
- return NULL;
-}
-
-static int motTreeGetUserDataId(Ihandle* ih, void* userdata)
-{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
- ih->data->id_control = -1;
- if (motTreeFindUserDataID(ih, &wRoot, 1, userdata))
- return ih->data->id_control;
- else
- return -1;
+ if (call_cb)
+ iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count);
}
static void motTreeSetFocusNode(Ihandle* ih, Widget wItem)
@@ -737,7 +559,7 @@ static void motTreeSetFocusNode(Ihandle* ih, Widget wItem)
XmProcessTraversal(wItem, XmTRAVERSE_CURRENT);
}
-static Widget motTreeGetFocusNode(Ihandle* ih)
+Widget iupdrvTreeGetFocusNode(Ihandle* ih)
{
Widget wItem = XmGetFocusWidget(ih->handle); /* returns the focus in the dialog */
if (wItem && XtParent(wItem) == ih->handle) /* is a node */
@@ -746,18 +568,6 @@ static Widget motTreeGetFocusNode(Ihandle* ih)
return (Widget)iupAttribGet(ih, "_IUPTREE_LAST_FOCUS");
}
-static Widget motTreeFindNodeFromString(Ihandle* ih, const char* name_id)
-{
- if (name_id[0])
- {
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
- iupStrToInt(name_id, &ih->data->id_control);
- return motTreeFindNodeFromID(ih, &wRoot, 1);
- }
- else
- return motTreeGetFocusNode(ih);
-}
-
static void motTreeEnterLeaveWindowEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
{
if (iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
@@ -812,16 +622,24 @@ static void motTreeFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean
void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* title, int add)
{
- Widget wItemPrev = motTreeFindNodeFromString(ih, name_id);
- Widget wNewItem;
+ Widget wItemPrev = iupTreeGetNodeFromString(ih, name_id);
+ Widget wItemNew;
XmString itemTitle;
- motTreeItemData *itemData, *itemDataPrev;
+ motTreeItemData *itemData;
Pixel bgcolor, fgcolor;
- int kindPrev, num_args = 0;
+ int kindPrev = 0, num_args = 0;
Arg args[30];
if (!wItemPrev)
- return;
+ {
+ /* check if the root was really specified */
+ int id = 0;
+ if (!iupStrToInt(name_id, &id) || id != -1)
+ return;
+ }
+
+ if (!title)
+ title = "";
itemData = calloc(1, sizeof(motTreeItemData));
itemData->image = XmUNSPECIFIED_PIXMAP;
@@ -836,138 +654,103 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL);
XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
- /* Get the kind of previous item */
- XtVaGetValues(wItemPrev, XmNuserData, &itemDataPrev, NULL);
- kindPrev = itemDataPrev->kind;
-
- if (kindPrev == ITREE_BRANCH && add)
+ if (wItemPrev)
{
- /* wItemPrev is parent of the new item (firstchild of it) */
- iupmotSetArg(args, num_args, XmNentryParent, wItemPrev);
- iupmotSetArg(args, num_args, XmNpositionIndex, 0);
- }
- else
- {
- /* wItemPrev is sibling of the new item (set its parent to the new item) */
- Widget wItemParent;
- int pos;
+ motTreeItemData *itemDataPrev;
- XtVaGetValues(wItemPrev, XmNentryParent, &wItemParent, NULL);
- XtVaGetValues(wItemPrev, XmNpositionIndex, &pos, NULL);
+ /* Get the kind of previous item */
+ XtVaGetValues(wItemPrev, XmNuserData, &itemDataPrev, NULL);
+ kindPrev = itemDataPrev->kind;
+
+ if (kindPrev == ITREE_BRANCH && add)
+ {
+ /* wItemPrev is parent of the new item (firstchild of it) */
+ iupMOT_SETARG(args, num_args, XmNentryParent, wItemPrev);
+ iupMOT_SETARG(args, num_args, XmNpositionIndex, 0);
+ }
+ else
+ {
+ /* wItemPrev is sibling of the new item (set its parent to the new item) */
+ Widget wItemParent;
+ int pos;
- iupmotSetArg(args, num_args, XmNentryParent, wItemParent);
- iupmotSetArg(args, num_args, XmNpositionIndex, pos+1);
+ XtVaGetValues(wItemPrev, XmNentryParent, &wItemParent, NULL);
+ XtVaGetValues(wItemPrev, XmNpositionIndex, &pos, NULL);
+
+ iupMOT_SETARG(args, num_args, XmNentryParent, wItemParent);
+ iupMOT_SETARG(args, num_args, XmNpositionIndex, pos+1);
+ }
}
- iupmotSetArg(args, num_args, XmNuserData, itemData);
- iupmotSetArg(args, num_args, XmNforeground, fgcolor);
- iupmotSetArg(args, num_args, XmNbackground, bgcolor);
- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNlabelString, itemTitle);
+ iupMOT_SETARG(args, num_args, XmNuserData, itemData);
+ iupMOT_SETARG(args, num_args, XmNforeground, fgcolor);
+ iupMOT_SETARG(args, num_args, XmNbackground, bgcolor);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, ih->data->spacing);
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNviewType, XmSMALL_ICON);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNlabelString, itemTitle);
if (kind == ITREE_BRANCH)
{
if (ih->data->add_expanded)
{
- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
+ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
+ iupMOT_SETARG(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
}
else
{
- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_collapsed);
- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_collapsed_mask);
+ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, ih->data->def_image_collapsed);
+ iupMOT_SETARG(args, num_args, XmNsmallIconMask, ih->data->def_image_collapsed_mask);
}
}
else
{
- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_leaf);
- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_leaf_mask);
+ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, ih->data->def_image_leaf);
+ iupMOT_SETARG(args, num_args, XmNsmallIconMask, ih->data->def_image_leaf_mask);
}
+ /* Add the new node */
+ wItemNew = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+ if (wItemPrev)
+ iupTreeAddToCache(ih, add, kindPrev, wItemPrev, wItemNew);
+ else
+ {
+ iupTreeAddToCache(ih, 0, 0, NULL, wItemNew);
+
+ if (ih->data->node_count == 1)
+ {
+ /* MarkStart node */
+ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wItemNew);
- wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+ /* Set the default VALUE */
+ motTreeSetFocusNode(ih, wItemNew);
+ }
+ }
if (kind == ITREE_BRANCH)
{
+ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", "1");
if (ih->data->add_expanded)
- {
- iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", "1");
- XtVaSetValues(wNewItem, XmNoutlineState, XmEXPANDED, NULL);
- }
+ XtVaSetValues(wItemNew, XmNoutlineState, XmEXPANDED, NULL);
else
- XtVaSetValues(wNewItem, XmNoutlineState, XmCOLLAPSED, NULL);
+ XtVaSetValues(wItemNew, XmNoutlineState, XmCOLLAPSED, NULL);
+ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", NULL);
}
- /* Root always expanded */
- XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
-
- XtRealizeWidget(wNewItem);
+ XtRealizeWidget(wItemNew);
XmStringFree(itemTitle);
}
-static void motTreeAddRootNode(Ihandle* ih)
-{
- Widget wRootItem;
- motTreeItemData *itemData;
- Pixel bgcolor, fgcolor;
- int num_args = 0;
- Arg args[30];
-
- itemData = calloc(1, sizeof(motTreeItemData));
- itemData->image = XmUNSPECIFIED_PIXMAP;
- itemData->image_expanded = XmUNSPECIFIED_PIXMAP;
- itemData->image_mask = XmUNSPECIFIED_PIXMAP;
- itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP;
- itemData->kind = ITREE_BRANCH;
-
- /* Get default foreground color */
- XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL);
- XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
-
- iupmotSetArg(args, num_args, XmNentryParent, NULL);
- iupmotSetArg(args, num_args, XmNuserData, itemData);
- iupmotSetArg(args, num_args, XmNforeground, fgcolor);
- iupmotSetArg(args, num_args, XmNbackground, bgcolor);
- iupmotSetArg(args, num_args, XmNoutlineState, XmEXPANDED);
- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
-
- wRootItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
-
- /* Select the new item */
- XtVaSetValues(wRootItem, XmNvisualEmphasis, XmSELECTED, NULL);
-
- XtRealizeWidget(wRootItem);
-
- /* Save the root node for later use */
- iupAttribSetStr(ih, "_IUPTREE_ROOTITEM", (char*)wRootItem);
-
- /* MarkStart node */
- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wRootItem);
-
- /* Set the default VALUE */
- /* In Motif this will set also the current focus */
- motTreeSetFocusNode(ih, wRootItem);
-}
-
/*****************************************************************************/
static int motTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const char* value)
{
motTreeItemData *itemData;
unsigned char itemState;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1003,7 +786,7 @@ static int motTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const
static int motTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* value)
{
motTreeItemData *itemData;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1053,7 +836,6 @@ static int motTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
static int motTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
ih->data->def_image_expanded = iupImageGetImage(value, ih, 0);
if (!ih->data->def_image_expanded)
{
@@ -1067,14 +849,13 @@ static int motTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
}
/* Update all images, starting at root node */
- motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_EXPANDED);
+ motTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED);
return 1;
}
static int motTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0);
if (!ih->data->def_image_collapsed)
{
@@ -1088,14 +869,13 @@ static int motTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
}
/* Update all images, starting at root node */
- motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_COLLAPSED);
+ motTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED);
return 1;
}
static int motTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
ih->data->def_image_leaf = iupImageGetImage(value, ih, 0);
if (!ih->data->def_image_leaf)
{
@@ -1109,7 +889,7 @@ static int motTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
}
/* Update all images, starting at root node */
- motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_LEAF);
+ motTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF);
return 1;
}
@@ -1118,7 +898,7 @@ static char* motTreeGetStateAttrib(Ihandle* ih, const char* name_id)
{
int hasChildren;
unsigned char itemState;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1138,14 +918,21 @@ static char* motTreeGetStateAttrib(Ihandle* ih, const char* name_id)
static int motTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* value)
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
- if (!wItem)
+ motTreeItemData *itemData;
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem)
return 0;
- if (iupStrEqualNoCase(value, "EXPANDED"))
- XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL);
- else
- XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL);
+ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+ if (itemData->kind == ITREE_BRANCH)
+ {
+ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", "1");
+ if (iupStrEqualNoCase(value, "EXPANDED"))
+ XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL);
+ else
+ XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL);
+ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", NULL);
+ }
return 0;
}
@@ -1155,7 +942,7 @@ static char* motTreeGetColorAttrib(Ihandle* ih, const char* name_id)
unsigned char r, g, b;
Pixel color;
char* str;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
@@ -1170,7 +957,7 @@ static char* motTreeGetColorAttrib(Ihandle* ih, const char* name_id)
static int motTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* value)
{
Pixel color;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1182,36 +969,33 @@ static int motTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
static char* motTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
{
- Widget wRoot;
- int dep = 0;
- char* depth;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ int depth = -1;
+ char* str;
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
- while((wRoot != wItem) && (wItem != NULL))
+ while(wItem != NULL)
{
XtVaGetValues(wItem, XmNentryParent, &wItem, NULL);
- dep++;
+ depth++;
}
- depth = iupStrGetMemory(10);
- sprintf(depth, "%d", dep);
- return depth;
+ str = iupStrGetMemory(10);
+ sprintf(str, "%d", depth);
+ return str;
}
static int motTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
{
Widget wItemDst, wParent, wItemSrc;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
- wItemSrc = motTreeFindNodeFromString(ih, name_id);
+ wItemSrc = iupTreeGetNodeFromString(ih, name_id);
if (!wItemSrc)
return 0;
- wItemDst = motTreeFindNodeFromString(ih, value);
+ wItemDst = iupTreeGetNodeFromString(ih, value);
if (!wItemDst)
return 0;
@@ -1224,11 +1008,8 @@ static int motTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
return 0;
}
- /* Copying the node and its children to the new position */
- motTreeCopyNode(ih, wItemSrc, wItemDst, 0); /* not a full copy, preserve user data */
-
- /* Deleting the node (and its children) inserted into the old position */
- motTreeRemoveNode(ih, wItemSrc, 0); /* do not delete the user data, we copy the references in CopyNode */
+ /* Move the node and its children to the new position */
+ motTreeCopyMoveNode(ih, wItemSrc, wItemDst, 0);
return 0;
}
@@ -1237,12 +1018,12 @@ static int motTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
{
Widget wItemDst, wParent, wItemSrc;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
- wItemSrc = motTreeFindNodeFromString(ih, name_id);
+ wItemSrc = iupTreeGetNodeFromString(ih, name_id);
if (!wItemSrc)
return 0;
- wItemDst = motTreeFindNodeFromString(ih, value);
+ wItemDst = iupTreeGetNodeFromString(ih, value);
if (!wItemDst)
return 0;
@@ -1255,8 +1036,8 @@ static int motTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
return 0;
}
- /* Copying the node and its children to the new position */
- motTreeCopyNode(ih, wItemSrc, wItemDst, 1);
+ /* Copy the node and its children to the new position */
+ motTreeCopyMoveNode(ih, wItemSrc, wItemDst, 1);
return 0;
}
@@ -1265,7 +1046,7 @@ static char* motTreeGetParentAttrib(Ihandle* ih, const char* name_id)
{
Widget wItemParent;
char* str;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
@@ -1275,7 +1056,7 @@ static char* motTreeGetParentAttrib(Ihandle* ih, const char* name_id)
return NULL;
str = iupStrGetMemory(10);
- sprintf(str, "%d", motTreeGetNodeId(ih, wItemParent));
+ sprintf(str, "%d", iupTreeFindNodeId(ih, wItemParent));
return str;
}
@@ -1283,7 +1064,7 @@ static char* motTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
{
char* str;
WidgetList wList = NULL;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
@@ -1293,30 +1074,10 @@ static char* motTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
return str;
}
-static int motTreeCount(Ihandle* ih, Widget wItem)
-{
- WidgetList wList = NULL;
- int i, count = 0;
- int childCount = XmContainerGetItemChildren(ih->handle, wItem, &wList);
- count++;
- for (i=0; i<childCount; i++)
- count += motTreeCount(ih, wList[i]);
- if (wList) XtFree((char*)wList);
- return count;
-}
-
-static char* motTreeGetCountAttrib(Ihandle* ih)
-{
- char* str = iupStrGetMemory(10);
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
- sprintf(str, "%d", motTreeCount(ih, wRoot));
- return str;
-}
-
static char* motTreeGetKindAttrib(Ihandle* ih, const char* name_id)
{
motTreeItemData *itemData;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
@@ -1331,15 +1092,64 @@ static char* motTreeGetKindAttrib(Ihandle* ih, const char* name_id)
static char* motTreeGetValueAttrib(Ihandle* ih)
{
char* str;
- Widget wItem = motTreeGetFocusNode(ih);
+ Widget wItem = iupdrvTreeGetFocusNode(ih);
if (!wItem)
- return "0"; /* default VALUE is root */
+ {
+ if (ih->data->node_count)
+ return "0"; /* default VALUE is root */
+ else
+ return "-1";
+ }
str = iupStrGetMemory(10);
- sprintf(str, "%d", motTreeGetNodeId(ih, wItem));
+ sprintf(str, "%d", iupTreeFindNodeId(ih, wItem));
+ return str;
+}
+
+static char* motTreeGetMarkedNodesAttrib(Ihandle* ih)
+{
+ char* str;
+ int i;
+
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ return NULL;
+
+ str = iupStrGetMemory(ih->data->node_count+1);
+
+ for (i=0; i<ih->data->node_count; i++)
+ {
+ if (motTreeIsNodeSelected(ih->data->node_cache[i].node_handle))
+ str[i] = '+';
+ else
+ str[i] = '-';
+ }
+
+ str[ih->data->node_count] = 0;
return str;
}
+static int motTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value)
+{
+ int count, i;
+
+ 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;
+
+ for (i=0; i<count; i++)
+ {
+ if (value[i] == '+')
+ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmSELECTED, NULL);
+ else
+ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+ }
+
+ return 0;
+}
+
static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
{
if (ih->data->mark_mode==ITREE_MARK_SINGLE)
@@ -1353,21 +1163,16 @@ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
motTreeInvertAllNodeMarking(ih);
else if(iupStrEqualPartial(value, "INVERT"))
{
- unsigned char isSelected;
- Widget wItem = motTreeFindNodeFromString(ih, &value[strlen("INVERT")]);
+ Widget wItem = iupTreeGetNodeFromString(ih, &value[strlen("INVERT")]);
if (!wItem)
return 0;
- XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
- if (isSelected == XmSELECTED)
- XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
- else
- XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ motTreeSelectNode(wItem, -1);
}
else if(iupStrEqualNoCase(value, "BLOCK"))
{
Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE");
- Widget wFocusItem = motTreeGetFocusNode(ih);
+ Widget wFocusItem = iupdrvTreeGetFocusNode(ih);
if(!wFocusItem || !wItem)
return 0;
motTreeSelectRange(ih, wFocusItem, wItem, 0);
@@ -1379,10 +1184,10 @@ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
if (iupStrToStrStr(value, str1, str2, '-')!=2)
return 0;
- wItem1 = motTreeFindNodeFromString(ih, str1);
+ wItem1 = iupTreeGetNodeFromString(ih, str1);
if (!wItem1)
return 0;
- wItem2 = motTreeFindNodeFromString(ih, str2);
+ wItem2 = iupTreeGetNodeFromString(ih, str2);
if (!wItem2)
return 0;
@@ -1394,69 +1199,49 @@ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
static int motTreeSetValueAttrib(Ihandle* ih, const char* value)
{
- Widget wRoot, wItem;
+ Widget wItem, wItemParent;
if (motTreeSetMarkAttrib(ih, value))
return 0;
- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
- if (iupStrEqualNoCase(value, "ROOT"))
- wItem = wRoot;
+ if (iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST"))
+ wItem = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
else if(iupStrEqualNoCase(value, "LAST"))
- wItem = motTreeGetLastVisibleNode(ih, wRoot);
+ wItem = motTreeGetLastVisibleNode(ih);
else if(iupStrEqualNoCase(value, "PGUP"))
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
if(!wItemFocus)
return 0;
- ih->data->id_control = -1;
- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus);
- 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 */
-
- wItem = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+ wItem = motTreeGetPreviousVisibleNode(ih, wItemFocus, 10);
}
else if(iupStrEqualNoCase(value, "PGDN"))
{
- Widget wNext, wItemFocus;
-
- wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
if(!wItemFocus)
return 0;
- ih->data->id_control = -1;
- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus);
- ih->data->id_control += 10; /* more 10 visible nodes */
-
- wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
-
- if (ih->data->id_control >= 0)
- wNext = motTreeGetLastVisibleNode(ih, wRoot);
-
- wItem = wNext;
+ wItem = motTreeGetNextVisibleNode(ih, wItemFocus, 10);
}
else if(iupStrEqualNoCase(value, "NEXT"))
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
if (!wItemFocus)
return 0;
- wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus);
+ wItem = motTreeGetNextVisibleNode(ih, wItemFocus, 1);
}
else if(iupStrEqualNoCase(value, "PREVIOUS"))
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
if(!wItemFocus)
return 0;
- wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus);
+ wItem = motTreeGetPreviousVisibleNode(ih, wItemFocus, 1);
}
else
- wItem = motTreeFindNodeFromString(ih, value);
+ wItem = iupTreeGetNodeFromString(ih, value);
if (!wItem)
return 0;
@@ -1471,17 +1256,26 @@ static int motTreeSetValueAttrib(Ihandle* ih, const char* value)
XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
}
+
+ /* expand all parents */
+ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
+ while(wItemParent)
+ {
+ XtVaSetValues(wItemParent, XmNoutlineState, XmEXPANDED, NULL);
+ XtVaGetValues(wItemParent, XmNentryParent, &wItemParent, NULL);
+ }
+
/* set focus (will scroll to visible) */
motTreeSetFocusNode(ih, wItem);
- iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", motTreeGetNodeId(ih, wItem));
+ iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", iupTreeFindNodeId(ih, wItem));
return 0;
}
static int motTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1492,14 +1286,11 @@ static int motTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
static char* motTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
{
- unsigned char isSelected;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
- XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
-
- if(isSelected == XmSELECTED)
+ if (motTreeIsNodeSelected(wItem))
return "YES";
else
return "NO";
@@ -1507,7 +1298,7 @@ static char* motTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
static int motTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1531,7 +1322,7 @@ static char* motTreeGetTitle(Widget wItem)
static char* motTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
return motTreeGetTitle(wItem);
@@ -1539,10 +1330,13 @@ static char* motTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
static int motTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* value)
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
+ if (!value)
+ value = "";
+
iupmotSetString(wItem, XmNlabelString, value);
return 0;
@@ -1551,7 +1345,7 @@ static int motTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v
static int motTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const char* value)
{
XmFontList fontlist = NULL;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return 0;
@@ -1569,7 +1363,7 @@ static int motTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
static char* motTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
{
XmFontList fontlist;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if (!wItem)
return NULL;
@@ -1577,118 +1371,81 @@ static char* motTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
return iupmotFindFontList(fontlist);
}
-static char* motTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
-{
- int id;
- char* str = (char*)(name_id+1); /* skip ':' */
- void* userdata = NULL;
- if (sscanf(str, "%p", &userdata)!=1)
- return NULL;
- id = motTreeGetUserDataId(ih, userdata);
- if (id == -1)
- return NULL;
- str = iupStrGetMemory(16);
- sprintf(str, "%d", id);
- return str;
-}
-
-static char* motTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
-{
- motTreeItemData *itemData;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
- if (!wItem)
- return NULL;
-
- XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
-
- return itemData->userdata;
-}
-
-static int motTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
-{
- motTreeItemData *itemData;
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
- if (!wItem)
- return 0;
-
- XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
- itemData->userdata = (void*)value;
-
- return 0;
-}
-
static int motTreeSetRenameAttrib(Ihandle* ih, const char* value)
{
if (ih->data->show_rename)
{
- IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
- Widget wItemFocus = motTreeGetFocusNode(ih);
- if (cbShowRename)
- cbShowRename(ih, motTreeGetNodeId(ih, wItemFocus));
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
motTreeShowEditField(ih, wItemFocus);
}
- else
- {
- IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
- if (cbRenameNode)
- {
- Widget wItemFocus = motTreeGetFocusNode(ih);
- cbRenameNode(ih, motTreeGetNodeId(ih, wItemFocus), motTreeGetTitle(wItemFocus));
- }
- }
(void)value;
return 0;
}
+static void motTreeRemoveAllNodes(Ihandle* ih, int call_cb)
+{
+ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
+ int i, old_count = ih->data->node_count;
+ Widget wItem;
+
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ wItem = ih->data->node_cache[i].node_handle;
+
+ motTreeDestroyItemData(ih, wItem, 1, cb, i);
+
+ XtDestroyWidget(wItem); /* must manually destroy each node, this is NOT recursive */
+ }
+
+ ih->data->node_count = 0;
+
+ if (call_cb)
+ iupTreeDelFromCache(ih, 0, old_count);
+}
+
static int motTreeSetDelNodeAttrib(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"))
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
- /* the root node can't be deleted */
- if(!wItem || wItem == wRoot) /* root is the unique child */
+ motTreeRemoveAllNodes(ih, 1);
+ return 0;
+ }
+ if(iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference node */
+ {
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if(!wItem)
return 0;
- /* deleting the specified node (and it's children) */
- motTreeRemoveNode(ih, wItem, 1);
+ /* deleting the reference node (and it's children) */
+ motTreeRemoveNode(ih, wItem, 1, 1);
}
- else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
+ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */
{
- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+ int numChild, i;
+ WidgetList wItemList = NULL;
+ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
if(!wItem)
return 0;
- {
- /* deleting the selected node's children only */
- WidgetList wItemList = NULL;
- int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemList);
- if(numChild)
- motTreeRemoveChildren(ih, wItemList, numChild, 1);
- if (wItemList) XtFree((char*)wItemList);
- }
+ /* deleting the reference node children only */
+ numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemList);
+ for(i = 0; i < numChild; i++)
+ motTreeRemoveNode(ih, wItemList[i], 1, 1);
+ if (wItemList) XtFree((char*)wItemList);
}
else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */
{
- WidgetList wSelectedItemList = NULL;
- Widget wRoot;
- int countItems, i;
-
- XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
- XmNselectedObjectCount, &countItems, NULL);
-
- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
- for(i = 0; i < countItems; i++)
+ int i;
+ for(i = 1; i < ih->data->node_count; /* increment only if not removed */)
{
- int ok = XmIsIconGadget(wSelectedItemList[i]);
- if ((wSelectedItemList[i] != wRoot) && ok) /* the root node can't be deleted */
- motTreeRemoveNode(ih, wSelectedItemList[i], 1);
+ if (motTreeIsNodeSelected(ih->data->node_cache[i].node_handle))
+ motTreeRemoveNode(ih, ih->data->node_cache[i].node_handle, 1, 1);
+ else
+ i++;
}
}
@@ -1714,7 +1471,7 @@ static int motTreeSetIndentationAttrib(Ihandle* ih, const char* value)
static int motTreeSetTopItemAttrib(Ihandle* ih, const char* value)
{
- Widget wItem = motTreeFindNodeFromString(ih, value);
+ Widget wItem = iupTreeGetNodeFromString(ih, value);
Widget sb_win;
Widget wItemParent;
@@ -1735,10 +1492,11 @@ static int motTreeSetTopItemAttrib(Ihandle* ih, const char* value)
return 0;
}
-static int motTreeSpacingFunc(Ihandle* ih, Widget wItem, void *data)
+static int motTreeSpacingFunc(Ihandle* ih, Widget wItem, int id, void *data)
{
XtVaSetValues(wItem, XmNmarginHeight, ih->data->spacing, NULL);
(void)data;
+ (void)id;
return 1;
}
@@ -1752,7 +1510,7 @@ static int motTreeSetSpacingAttrib(Ihandle* ih, const char* value)
if (ih->handle)
{
- motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSpacingFunc, 0);
+ iupTreeForEach(ih, (iupTreeNodeFunc)motTreeSpacingFunc, 0);
return 0;
}
else
@@ -1761,17 +1519,10 @@ static int motTreeSetSpacingAttrib(Ihandle* ih, const char* value)
static int motTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
if (iupStrBoolean(value))
- motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmEXPANDED);
+ motTreeExpandCollapseAllNodes(ih, XmEXPANDED);
else
- {
- motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmCOLLAPSED);
-
- /* The root node is always expanded */
- XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
- }
+ motTreeExpandCollapseAllNodes(ih, XmCOLLAPSED);
return 0;
}
@@ -1801,16 +1552,13 @@ static int motTreeSetBgColorAttrib(Ihandle* ih, const char* value)
color = iupmotColorGetPixelStr(value);
if (color != (Pixel)-1)
{
- Widget wRoot;
Widget clipwin = NULL;
XtVaGetValues(sb_win, XmNclipWindow, &clipwin, NULL);
if (clipwin) iupmotSetBgColor(clipwin, color);
- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
-
/* Update all children, starting at root node */
- motTreeUpdateBgColor(ih, &wRoot, 1, color);
+ motTreeUpdateBgColor(ih, color);
}
iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */
@@ -1871,10 +1619,14 @@ static void motTreeSetRenameSelectionPos(Widget cbEdit, const char* value)
static int motTreeCallBranchCloseCb(Ihandle* ih, Widget wItem)
{
- IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
+ IFni cbBranchClose;
+
+ if (iupAttribGet(ih, "_IUP_IGNORE_BRANCH_CB"))
+ return IUP_DEFAULT;
- if(cbBranchClose)
- return cbBranchClose(ih, motTreeGetNodeId(ih, wItem));
+ cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
+ if (cbBranchClose)
+ return cbBranchClose(ih, iupTreeFindNodeId(ih, wItem));
return IUP_DEFAULT;
}
@@ -1883,59 +1635,136 @@ static int motTreeCallBranchOpenCb(Ihandle* ih, Widget wItem)
{
IFni cbBranchOpen;
- if (iupAttribGet(ih, "_IUP_IGNORE_BRANCHOPEN"))
- {
- iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", NULL);
+ if (iupAttribGet(ih, "_IUP_IGNORE_BRANCH_CB"))
return IUP_DEFAULT;
- }
cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
if (cbBranchOpen)
- return cbBranchOpen(ih, motTreeGetNodeId(ih, wItem));
+ return cbBranchOpen(ih, iupTreeFindNodeId(ih, wItem));
return IUP_DEFAULT;
}
+static void motTreeFindRange(Ihandle* ih, WidgetList wSelectedItemList, int countItems, int *id1, int *id2)
+{
+ int i = 0, id;
+
+ *id1 = ih->data->node_count;
+ *id2 = -1;
+
+ for(i = 0; i < countItems; i++)
+ {
+ int is_icon = XmIsIconGadget(wSelectedItemList[i]); /* this line generates a warning in some compilers */
+ if (is_icon)
+ {
+ id = iupTreeFindNodeId(ih, wSelectedItemList[i]);
+ if (id < *id1)
+ *id1 = id;
+ if (id > *id2)
+ *id2 = id;
+ }
+ }
+
+ /* interactive selection of several nodes will NOT select hidden nodes,
+ so make sure that they are selected. */
+ for(i = *id1; i <= *id2; i++)
+ {
+ if (!motTreeIsNodeSelected(ih->data->node_cache[i].node_handle))
+ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+
+ /* if last selected item is a branch, then select its children */
+ iupTreeSelectLastCollapsedBranch(ih, id2);
+}
+
+static Iarray* motTreeGetSelectedArrayId(Ihandle* ih, WidgetList wSelectedItemList, int countItems)
+{
+ Iarray* selarray = iupArrayCreate(1, sizeof(int));
+ int i;
+
+ for(i = 0; i < countItems; i++)
+ {
+ int is_icon = XmIsIconGadget(wSelectedItemList[i]); /* this line generates a warning in some compilers */
+ if (is_icon)
+ {
+ int* id_hitem = (int*)iupArrayInc(selarray);
+ int j = iupArrayCount(selarray);
+ id_hitem[j-1] = iupTreeFindNodeId(ih, wSelectedItemList[i]);
+ }
+ }
+
+ return selarray;
+}
+
+static void motTreeCallMultiUnSelectionCb(Ihandle* ih)
+{
+ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB");
+ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ if (cbSelec || cbMulti)
+ {
+ WidgetList wSelectedItemList = NULL;
+ int countItems = 0;
+
+ XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
+ XmNselectedObjectCount, &countItems, NULL);
+ if (countItems > 1)
+ {
+ Iarray* markedArray = motTreeGetSelectedArrayId(ih, wSelectedItemList, countItems);
+ int* id_hitem = (int*)iupArrayGetData(markedArray);
+ int i, count = iupArrayCount(markedArray);
+
+ if (cbMulti)
+ cbMulti(ih, id_hitem, iupArrayCount(markedArray));
+ else
+ {
+ for (i=0; i<count; i++)
+ cbSelec(ih, id_hitem[i], 0);
+ }
+
+ iupArrayDestroy(markedArray);
+ }
+ }
+}
+
static void motTreeCallMultiSelectionCb(Ihandle* ih)
{
IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTISELECTION_CB");
IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
WidgetList wSelectedItemList = NULL;
- Widget wRoot;
- int countItems;
-
- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ int countItems, id1, id2, i;
XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
XmNselectedObjectCount, &countItems, NULL);
if (countItems == 0)
return;
- if (cbMulti || cbSelec)
+ /* Must be a continuous range of selection ids */
+ motTreeFindRange(ih, wSelectedItemList, countItems, &id1, &id2);
+ countItems = id2-id1+1;
+
+ if (cbMulti)
{
int* id_rowItem = malloc(sizeof(int) * countItems);
- int i = 0;
for(i = 0; i < countItems; i++)
- id_rowItem[i] = motTreeGetNodeId(ih, wSelectedItemList[i]);
+ id_rowItem[i] = id1+i;
- if (cbMulti)
- cbMulti(ih, id_rowItem, countItems);
- else
- {
- for (i=0; i<countItems; i++)
- cbSelec(ih, id_rowItem[i], 1);
- }
+ cbMulti(ih, id_rowItem, countItems);
free(id_rowItem);
}
+ else if (cbSelec)
+ {
+ for (i=0; i<countItems; i++)
+ cbSelec(ih, id1+i, 1);
+ }
}
static int motTreeConvertXYToPos(Ihandle* ih, int x, int y)
{
Widget wItem = XmObjectAtPoint(ih->handle, (Position)x, (Position)y);
if (wItem)
- return motTreeGetNodeId(ih, wItem);
+ return iupTreeFindNodeId(ih, wItem);
return -1;
}
@@ -1965,7 +1794,7 @@ static void motTreeCallRenameCb(Ihandle* ih)
cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
if (cbRename)
{
- if (cbRename(ih, motTreeGetNodeId(ih, wItem), title) == IUP_IGNORE)
+ if (cbRename(ih, iupTreeFindNodeId(ih, wItem), title) == IUP_IGNORE)
ignore = 1;
}
@@ -1993,8 +1822,8 @@ static int motTreeCallDragDropCb(Ihandle* ih, Widget wItemDrag, Widget wItemDrop
if (cbDragDrop)
{
- int drag_id = motTreeGetNodeId(ih, wItemDrag);
- int drop_id = motTreeGetNodeId(ih, wItemDrop);
+ int drag_id = iupTreeFindNodeId(ih, wItemDrag);
+ int drop_id = iupTreeFindNodeId(ih, wItemDrop);
return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
}
@@ -2069,6 +1898,10 @@ static void motTreeShowEditField(Ihandle* ih, Widget wItem)
XmFontList fontlist;
Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+ if (cbShowRename && cbShowRename(ih, iupTreeFindNodeId(ih, wItem))==IUP_IGNORE)
+ return;
+
XtVaGetValues(wItem, XmNx, &x,
XmNy, &y,
XmNwidth, &w,
@@ -2083,16 +1916,16 @@ static void motTreeShowEditField(Ihandle* ih, Widget wItem)
iupdrvImageGetInfo((void*)image, &w_img, NULL, NULL);
w_img += 3; /* add some room for borders */
- iupmotSetArg(args, num_args, XmNx, x+w_img); /* x-position */
- iupmotSetArg(args, num_args, XmNy, y); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, w-w_img); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, h); /* default height to avoid 0 */
- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
- iupmotSetArg(args, num_args, XmNforeground, color);
- iupmotSetArg(args, num_args, XmNrenderTable, fontlist);
- iupmotSetArg(args, num_args, XmNvalue, iupmotConvertString(title));
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNx, x+w_img); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, y); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, w-w_img); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, h); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, ih->data->spacing); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNforeground, color);
+ iupMOT_SETARG(args, num_args, XmNrenderTable, fontlist);
+ iupMOT_SETARG(args, num_args, XmNvalue, iupmotConvertString(title));
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
cbEdit = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -2134,8 +1967,6 @@ static void motTreeSelectionCallback(Widget w, Ihandle* ih, XmContainerSelectCal
(void)w;
(void)nptr;
-printf("SelectionCallback(%d)\n", nptr->selected_item_count);
-
if (ih->data->mark_mode == ITREE_MARK_MULTIPLE)
{
char key[5];
@@ -2149,11 +1980,13 @@ printf("SelectionCallback(%d)\n", nptr->selected_item_count);
{
if (IupGetCallback(ih, "MULTISELECTION_CB"))
{
+ /* current selection same as the initial selection */
if (nptr->auto_selection_type==XmAUTO_NO_CHANGE)
motTreeCallMultiSelectionCb(ih);
}
else
{
+ /* current selection is caused by button drag */
if (nptr->auto_selection_type==XmAUTO_MOTION)
motTreeCallMultiSelectionCb(ih);
}
@@ -2164,14 +1997,10 @@ printf("SelectionCallback(%d)\n", nptr->selected_item_count);
cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
if (cbSelec)
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
- int curpos = motTreeGetNodeId(ih, wItemFocus);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ int curpos = iupTreeFindNodeId(ih, wItemFocus);
if (is_ctrl)
- {
- unsigned char isSelected;
- XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL);
- cbSelec(ih, curpos, isSelected == XmSELECTED? 1: 0);
- }
+ cbSelec(ih, curpos, motTreeIsNodeSelected(wItemFocus));
else
{
int oldpos = iupAttribGetInt(ih, "_IUPTREE_OLDVALUE");
@@ -2218,7 +2047,7 @@ static void motTreeDefaultActionCallback(Widget w, Ihandle* ih, XmContainerSelec
{
IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
if (cbExecuteLeaf)
- cbExecuteLeaf(ih, motTreeGetNodeId(ih, wItem));
+ cbExecuteLeaf(ih, iupTreeFindNodeId(ih, wItem));
}
}
@@ -2295,15 +2124,14 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
iupmotHelpCallback(w, ih, NULL);
else if ((motcode == XK_Down || motcode == XK_Up) && (evt->state & ControlMask))
{
- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
Widget wItem;
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
/* Ctrl+Arrows move only focus */
if (motcode == XK_Down)
- wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus);
+ wItem = motTreeGetNextVisibleNode(ih, wItemFocus, 1);
else
- wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus);
+ wItem = motTreeGetPreviousVisibleNode(ih, wItemFocus, 1);
motTreeSetFocusNode(ih, wItem);
*cont = False;
@@ -2317,8 +2145,8 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
if (motcode == XK_Home)
wItem = wRoot;
- else
- wItem = motTreeGetLastVisibleNode(ih, wRoot);
+ else /* motcode == XK_End */
+ wItem = motTreeGetLastVisibleNode(ih);
/* Ctrl+Arrows move only focus */
if (!(evt->state & ControlMask))
@@ -2326,7 +2154,7 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
/* Shift+Arrows select block */
if (evt->state & ShiftMask)
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
if (!wItemFocus)
return;
motTreeSelectRange(ih, wItemFocus, wItem, 1);
@@ -2346,16 +2174,9 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
}
else if(motcode == XK_space && (evt->state & ControlMask))
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
if (wItemFocus)
- {
- unsigned char isSelected;
- XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL);
- if (isSelected == XmSELECTED)
- XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
- else
- XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmSELECTED, NULL);
- }
+ motTreeSelectNode(wItemFocus, -1);
}
}
@@ -2378,7 +2199,7 @@ static void motTreeButtonEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean
if (evt->button==Button1)
{
- Widget wItemFocus = motTreeGetFocusNode(ih);
+ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
static Widget wLastItem = NULL;
static Time last = 0;
int clicktwice = 0, doubleclicktime = XtGetMultiClickTime(iupmot_display);
@@ -2395,6 +2216,11 @@ static void motTreeButtonEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean
*cont = False;
}
wLastItem = wItemFocus;
+
+ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE &&
+ !(evt->state & ShiftMask) &&
+ !(evt->state & ControlMask))
+ motTreeCallMultiUnSelectionCb(ih);
}
else if (evt->button==Button3)
motTreeCallRightClickCb(ih, evt->x, evt->y);
@@ -2436,21 +2262,18 @@ static void motTreeTransferProc(Widget drop_context, XtPointer client_data, Atom
if (motTreeCallDragDropCb(ih, wItemDrag, wItemDrop, &is_ctrl) == IUP_CONTINUE)
{
- /* Copy the dragged item to the new position. */
- Widget wNewItem = motTreeCopyNode(ih, wItemDrag, wItemDrop, is_ctrl);
+ /* Copy or move the dragged item to the new position. */
+ Widget wItemNew = motTreeCopyMoveNode(ih, wItemDrag, wItemDrop, is_ctrl);
- if (!is_ctrl)
+ /* Set focus and selection */
+ if (wItemNew)
{
- /* do not delete the user data, we copy the references in CopyNode */
- motTreeRemoveNode(ih, wItemDrag, 0);
- }
-
- /* Select the dragged item */
- XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
- XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
- XtVaSetValues(wNewItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
+ XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
+ XtVaSetValues(wItemNew, XmNvisualEmphasis, XmSELECTED, NULL);
- motTreeSetFocusNode(ih, wNewItem);
+ motTreeSetFocusNode(ih, wItemNew);
+ }
}
}
@@ -2475,8 +2298,8 @@ static void motTreeDropProc(Widget w, XtPointer client_data, XmDropProcCallbackS
drop_context = drop_data->dragContext;
/* retrieve the data targets */
- iupmotSetArg(args, num_args, XmNexportTargets, &exportTargets);
- iupmotSetArg(args, num_args, XmNnumExportTargets, &numExportTargets);
+ iupMOT_SETARG(args, num_args, XmNexportTargets, &exportTargets);
+ iupMOT_SETARG(args, num_args, XmNnumExportTargets, &numExportTargets);
XtGetValues(drop_context, args, num_args);
for (i = 0; i < (int)numExportTargets; i++)
@@ -2495,17 +2318,17 @@ static void motTreeDropProc(Widget w, XtPointer client_data, XmDropProcCallbackS
num_args = 0;
if ((!found) || (drop_data->dropAction != XmDROP) || (drop_data->operation != XmDROP_COPY && drop_data->operation != XmDROP_MOVE))
{
- iupmotSetArg(args, num_args, XmNtransferStatus, XmTRANSFER_FAILURE);
- iupmotSetArg(args, num_args, XmNnumDropTransfers, 0);
+ iupMOT_SETARG(args, num_args, XmNtransferStatus, XmTRANSFER_FAILURE);
+ iupMOT_SETARG(args, num_args, XmNnumDropTransfers, 0);
}
else
{
/* set up transfer requests for drop site */
transferList[0].target = atomTreeItem;
transferList[0].client_data = (XtPointer)wItemDrop;
- iupmotSetArg(args, num_args, XmNdropTransfers, transferList);
- iupmotSetArg(args, num_args, XmNnumDropTransfers, 1);
- iupmotSetArg(args, num_args, XmNtransferProc, motTreeTransferProc);
+ iupMOT_SETARG(args, num_args, XmNdropTransfers, transferList);
+ iupMOT_SETARG(args, num_args, XmNnumDropTransfers, 1);
+ iupMOT_SETARG(args, num_args, XmNtransferProc, motTreeTransferProc);
}
XmDropTransferStart(drop_context, args, num_args);
@@ -2584,23 +2407,23 @@ static void motTreeStartDrag(Widget w, XButtonEvent* evt, String* params, Cardin
XmNforeground, &fg,
NULL);
- iupmotSetArg(args, num_args, XmNpixmap, pixmap);
- iupmotSetArg(args, num_args, XmNmask, mask);
+ iupMOT_SETARG(args, num_args, XmNpixmap, pixmap);
+ iupMOT_SETARG(args, num_args, XmNmask, mask);
drag_icon = XmCreateDragIcon(w, "drag_icon", args, num_args);
exportList[0] = atomTreeItem;
/* specify resources for DragContext for the transfer */
num_args = 0;
- iupmotSetArg(args, num_args, XmNcursorBackground, bg);
- iupmotSetArg(args, num_args, XmNcursorForeground, fg);
- /* iupmotSetArg(args, num_args, XmNsourcePixmapIcon, drag_icon); works, but only outside the dialog, inside disapears */
- iupmotSetArg(args, num_args, XmNsourceCursorIcon, drag_icon); /* does not work, shows the default cursor */
- iupmotSetArg(args, num_args, XmNexportTargets, exportList);
- iupmotSetArg(args, num_args, XmNnumExportTargets, 1);
- iupmotSetArg(args, num_args, XmNdragOperations, XmDROP_MOVE|XmDROP_COPY);
- iupmotSetArg(args, num_args, XmNconvertProc, motTreeConvertProc);
- iupmotSetArg(args, num_args, XmNclientData, wItemDrag);
+ iupMOT_SETARG(args, num_args, XmNcursorBackground, bg);
+ iupMOT_SETARG(args, num_args, XmNcursorForeground, fg);
+ /* iupMOT_SETARG(args, num_args, XmNsourcePixmapIcon, drag_icon); works, but only outside the dialog, inside disapears */
+ iupMOT_SETARG(args, num_args, XmNsourceCursorIcon, drag_icon); /* does not work, shows the default cursor */
+ iupMOT_SETARG(args, num_args, XmNexportTargets, exportList);
+ iupMOT_SETARG(args, num_args, XmNnumExportTargets, 1);
+ iupMOT_SETARG(args, num_args, XmNdragOperations, XmDROP_MOVE|XmDROP_COPY);
+ iupMOT_SETARG(args, num_args, XmNconvertProc, motTreeConvertProc);
+ iupMOT_SETARG(args, num_args, XmNclientData, wItemDrag);
/* start the drag and register a callback to clean up when done */
drop_context = XmDragStart(w, (XEvent*)evt, args, num_args);
@@ -2628,10 +2451,10 @@ static void motTreeEnableDragDrop(Widget w)
XtOverrideTranslations(w, XtParseTranslationTable(dragTranslations));
importList[0] = atomTreeItem;
- iupmotSetArg(args, num_args, XmNimportTargets, importList);
- iupmotSetArg(args, num_args, XmNnumImportTargets, 1);
- iupmotSetArg(args, num_args, XmNdropSiteOperations, XmDROP_MOVE|XmDROP_COPY);
- iupmotSetArg(args, num_args, XmNdropProc, motTreeDropProc);
+ iupMOT_SETARG(args, num_args, XmNimportTargets, importList);
+ iupMOT_SETARG(args, num_args, XmNnumImportTargets, 1);
+ iupMOT_SETARG(args, num_args, XmNdropSiteOperations, XmDROP_MOVE|XmDROP_COPY);
+ iupMOT_SETARG(args, num_args, XmNdropProc, motTreeDropProc);
XmDropSiteUpdate(w, args, num_args);
XtVaSetValues(XmGetXmDisplay(iupmot_display), XmNenableDragIcon, True, NULL);
@@ -2648,13 +2471,13 @@ static int motTreeMapMethod(Ihandle* ih)
/******************************/
/* Create the scrolled window */
/******************************/
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAUTOMATIC);
- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
- iupmotSetArg(args, num_args, XmNborderWidth, 0);
- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAUTOMATIC);
+ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
+ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
+ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
sb_win = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -2672,37 +2495,37 @@ static int motTreeMapMethod(Ihandle* ih)
num_args = 0;
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
+ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
- iupmotSetArg(args, num_args, XmNlayoutType, XmOUTLINE);
- iupmotSetArg(args, num_args, XmNentryViewType, XmSMALL_ICON);
- iupmotSetArg(args, num_args, XmNselectionPolicy, XmSINGLE_SELECT);
- iupmotSetArg(args, num_args, XmNoutlineIndentation, 20);
+ iupMOT_SETARG(args, num_args, XmNlayoutType, XmOUTLINE);
+ iupMOT_SETARG(args, num_args, XmNentryViewType, XmSMALL_ICON);
+ iupMOT_SETARG(args, num_args, XmNselectionPolicy, XmSINGLE_SELECT);
+ iupMOT_SETARG(args, num_args, XmNoutlineIndentation, 20);
if (iupAttribGetBoolean(ih, "HIDELINES"))
- iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmNO_LINE);
+ iupMOT_SETARG(args, num_args, XmNoutlineLineStyle, XmNO_LINE);
else
- iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmSINGLE);
+ iupMOT_SETARG(args, num_args, XmNoutlineLineStyle, XmSINGLE);
if (iupAttribGetBoolean(ih, "HIDEBUTTONS"))
- iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_ABSENT);
+ iupMOT_SETARG(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_ABSENT);
else
- iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_PRESENT);
+ iupMOT_SETARG(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_PRESENT);
ih->handle = XtCreateManagedWidget(
child_id, /* child identifier */
@@ -2788,17 +2611,30 @@ static int motTreeMapMethod(Ihandle* ih)
if (!ih->data->def_image_expanded_mask) ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP;
}
- motTreeAddRootNode(ih);
+ if (iupAttribGetInt(ih, "ADDROOT"))
+ iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0);
IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motTreeConvertXYToPos);
+ iupdrvTreeUpdateMarkMode(ih);
+
return IUP_NOERROR;
}
+static void motTreeUnMapMethod(Ihandle* ih)
+{
+ motTreeRemoveAllNodes(ih, 0);
+
+ ih->data->node_count = 0;
+
+ iupdrvBaseUnMapMethod(ih);
+}
+
void iupdrvTreeInitClass(Iclass* ic)
{
/* Driver Dependent Class functions */
ic->Map = motTreeMapMethod;
+ ic->UnMap = motTreeUnMapMethod;
/* Visual */
iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTreeSetBgColorAttrib, "TXTBGCOLOR", NULL, IUPAF_DEFAULT);
@@ -2807,7 +2643,6 @@ void iupdrvTreeInitClass(Iclass* ic)
/* IupTree Attributes - GENERAL */
iupClassRegisterAttribute(ic, "EXPANDALL", NULL, motTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY||IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "INDENTATION", motTreeGetIndentationAttrib, motTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
- iupClassRegisterAttribute(ic, "COUNT", motTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, motTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
iupClassRegisterAttribute(ic, "TOPITEM", NULL, motTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
@@ -2827,7 +2662,6 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttributeId(ic, "COLOR", motTreeGetColorAttrib, motTreeSetColorAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "NAME", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TITLE", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT);
- iupClassRegisterAttributeId(ic, "USERDATA", motTreeGetUserDataAttrib, motTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "CHILDCOUNT", motTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TITLEFONT", motTreeGetTitleFontAttrib, motTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
@@ -2836,6 +2670,7 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttribute (ic, "MARK", NULL, motTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "STARTING", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "MARKSTART", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKEDNODES", motTreeGetMarkedNodesAttrib, motTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "VALUE", motTreeGetValueAttrib, motTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
@@ -2844,5 +2679,4 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "RENAME", NULL, motTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "MOVENODE", NULL, motTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "COPYNODE", NULL, motTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
- iupClassRegisterAttributeId(ic, "FINDUSERDATA", motTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
}
diff --git a/iup/src/mot/iupmot_val.c b/iup/src/mot/iupmot_val.c
index 200d2b4..ce9eba7 100755
--- a/iup/src/mot/iupmot_val.c
+++ b/iup/src/mot/iupmot_val.c
@@ -383,41 +383,41 @@ static int motValMapMethod(Ihandle* ih)
int show_ticks;
/* Core */
- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
+ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
+ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
/* Primitive */
if (iupAttribGetBoolean(ih, "CANFOCUS"))
- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
else
- iupmotSetArg(args, num_args, XmNtraversalOn, False);
- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
+ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
/* Scale */
- iupmotSetArg(args, num_args, XmNminimum, 0);
- iupmotSetArg(args, num_args, XmNmaximum, SHRT_MAX);
- iupmotSetArg(args, num_args, XmNslidingMode, XmSLIDER);
- iupmotSetArg(args, num_args, XmNsliderMark, XmETCHED_LINE);
- iupmotSetArg(args, num_args, XmNsliderSize, 16);
- iupmotSetArg(args, num_args, XmNshowValue, XmNONE);
+ iupMOT_SETARG(args, num_args, XmNminimum, 0);
+ iupMOT_SETARG(args, num_args, XmNmaximum, SHRT_MAX);
+ iupMOT_SETARG(args, num_args, XmNslidingMode, XmSLIDER);
+ iupMOT_SETARG(args, num_args, XmNsliderMark, XmETCHED_LINE);
+ iupMOT_SETARG(args, num_args, XmNsliderSize, 16);
+ iupMOT_SETARG(args, num_args, XmNshowValue, XmNONE);
if (ih->data->type == IVAL_HORIZONTAL)
{
- iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
+ iupMOT_SETARG(args, num_args, XmNorientation, XmHORIZONTAL);
if (ih->data->inverted)
- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_LEFT);
+ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_LEFT);
else
- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_RIGHT);
+ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_RIGHT);
}
else
{
- iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
+ iupMOT_SETARG(args, num_args, XmNorientation, XmVERTICAL);
if (ih->data->inverted)
- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_TOP);
+ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_TOP);
else
- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_BOTTOM);
+ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_BOTTOM);
}
ih->handle = XtCreateManagedWidget(
diff --git a/iup/src/mot/iupunix_info.c b/iup/src/mot/iupunix_info.c
index b522638..f09573c 100755
--- a/iup/src/mot/iupunix_info.c
+++ b/iup/src/mot/iupunix_info.c
@@ -282,7 +282,7 @@ char *iupdrvGetSystemName(void)
char *iupdrvGetSystemVersion(void)
{
struct utsname un;
- char *str = iupStrGetMemory(60);
+ char *str = iupStrGetMemory(100);
uname(&un);
strcpy(str, un.release);
diff --git a/iup/src/win/iupwin_button.c b/iup/src/win/iupwin_button.c
index 7f780e3..3b05ba7 100755
--- a/iup/src/win/iupwin_button.c
+++ b/iup/src/win/iupwin_button.c
@@ -27,6 +27,7 @@
#include "iupwin_drv.h"
#include "iupwin_handle.h"
#include "iupwin_draw.h"
+#include "iupwin_info.h"
#ifndef CDIS_SHOWKEYBOARDCUES
@@ -308,18 +309,22 @@ static void winButtonDrawText(Ihandle* ih, HDC hDC, int rect_width, int rect_hei
static void winButtonDrawItem(Ihandle* ih, DRAWITEMSTRUCT *drawitem)
{
+ HDC hDC;
iupwinBitmapDC bmpDC;
int border, draw_border;
int width = drawitem->rcItem.right - drawitem->rcItem.left;
int height = drawitem->rcItem.bottom - drawitem->rcItem.top;
- HDC hDC = iupwinDrawCreateBitmapDC(&bmpDC, drawitem->hDC, width, height);
+ hDC = iupwinDrawCreateBitmapDC(&bmpDC, drawitem->hDC, width, height);
iupwinDrawParentBackground(ih, hDC, &drawitem->rcItem);
if ((drawitem->itemState & ODS_FOCUS) && !(drawitem->itemState & ODS_HOTLIGHT))
drawitem->itemState |= ODS_DEFAULT;
+ if (iupAttribGet(ih, "_IUPWINBUT_SELECTED"))
+ drawitem->itemState |= ODS_SELECTED;
+
border = winButtonGetBorder();
if (ih->data->type & IUP_BUTTON_IMAGE && iupAttribGet(ih, "IMPRESS") && !iupAttribGetStr(ih, "IMPRESSBORDER"))
@@ -365,7 +370,7 @@ static int winButtonSetImageAttrib(Ihandle* ih, const char* value)
(void)value;
if (ih->data->type != IUP_BUTTON_TEXT)
{
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
return 1;
}
else
@@ -377,7 +382,7 @@ static int winButtonSetImInactiveAttrib(Ihandle* ih, const char* value)
(void)value;
if (ih->data->type != IUP_BUTTON_TEXT)
{
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
return 1;
}
else
@@ -389,7 +394,7 @@ static int winButtonSetImPressAttrib(Ihandle* ih, const char* value)
(void)value;
if (ih->data->type != IUP_BUTTON_TEXT)
{
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
return 1;
}
else
@@ -400,7 +405,7 @@ static int winButtonSetActiveAttrib(Ihandle* ih, const char* value)
{
/* redraw IMINACTIVE image if any */
if (ih->data->type != IUP_BUTTON_TEXT)
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
return iupBaseSetActiveAttrib(ih, value);
}
@@ -425,7 +430,7 @@ static int winButtonSetAlignmentAttrib(Ihandle* ih, const char* value)
else /* "ACENTER" */
ih->data->vert_alignment = IUP_ALIGN_ACENTER;
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
return 1;
}
@@ -443,7 +448,7 @@ static int winButtonSetPaddingAttrib(Ihandle* ih, const char* value)
{
iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
if (ih->handle)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
return 0;
}
@@ -454,7 +459,7 @@ static int winButtonSetBgColorAttrib(Ihandle* ih, const char* value)
{
iupAttribSetStr(ih, "BGCOLOR", value);
iupImageUpdateParent(ih);
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
return 1;
}
@@ -486,7 +491,9 @@ static int winButtonSetFgColorAttrib(Ihandle* ih, const char* value)
if (iupStrToRGB(value, &r, &g, &b))
{
ih->data->fgcolor = RGB(r,g,b);
- iupdrvDisplayRedraw(ih);
+
+ if (ih->handle)
+ iupdrvRedrawNow(ih);
}
return 1;
}
@@ -499,7 +506,7 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
{
/* redraw IMPRESS image if any */
if ((msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) && iupAttribGet(ih, "IMPRESS"))
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
switch (msg)
@@ -514,6 +521,13 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
case WM_RBUTTONDOWN:
{
iupwinButtonDown(ih, msg, wp, lp);
+
+ /* Feedback will NOT be done when not receiving the focus */
+ if (msg==WM_LBUTTONDOWN && !iupAttribGetBoolean(ih, "FOCUSONCLICK"))
+ {
+ iupAttribSetStr(ih, "_IUPWINBUT_SELECTED", "1");
+ iupdrvRedrawNow(ih);
+ }
break;
}
case WM_XBUTTONUP:
@@ -526,11 +540,24 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
/* BN_CLICKED will NOT be notified when not receiving the focus */
if (msg==WM_LBUTTONUP && !iupAttribGetBoolean(ih, "FOCUSONCLICK"))
{
- Icallback cb = IupGetCallback(ih, "ACTION");
+ Icallback cb;
+
+ iupAttribSetStr(ih, "_IUPWINBUT_SELECTED", NULL);
+ iupdrvRedrawNow(ih);
+
+ cb = IupGetCallback(ih, "ACTION");
if (cb && cb(ih) == IUP_CLOSE)
IupExitLoop();
}
+ if (!iupwinIsVistaOrNew())
+ {
+ /* TIPs desapear forever after a button click in XP,
+ so we force an update. */
+ char* tip = iupAttribGet(ih, "TIP");
+ if (tip)
+ iupdrvBaseSetTipAttrib(ih, tip);
+ }
break;
}
case WM_KEYDOWN:
@@ -549,7 +576,12 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
if (!iupwin_comctl32ver6)
{
iupAttribSetStr(ih, "_IUPWINBUT_ENTERWIN", NULL);
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
+ }
+ if (!iupAttribGetBoolean(ih, "FOCUSONCLICK"))
+ {
+ iupAttribSetStr(ih, "_IUPWINBUT_SELECTED", NULL);
+ iupdrvRedrawNow(ih);
}
break;
case WM_MOUSEMOVE:
@@ -558,7 +590,7 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
if (!iupAttribGet(ih, "_IUPWINBUT_ENTERWIN"))
{
iupAttribSetStr(ih, "_IUPWINBUT_ENTERWIN", "1");
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
}
break;
@@ -635,7 +667,7 @@ static int winButtonWmCommand(Ihandle* ih, WPARAM wp, LPARAM lp)
static int winButtonMapMethod(Ihandle* ih)
{
char* value;
- DWORD dwStyle = WS_CHILD |
+ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS |
BS_NOTIFY; /* necessary because of the base messages */
if (!ih->parent)
@@ -661,7 +693,7 @@ static int winButtonMapMethod(Ihandle* ih)
ih->data->type = IUP_BUTTON_IMAGE;
value = iupAttribGet(ih, "TITLE");
- if (value)
+ if (value && *value!=0)
ih->data->type |= IUP_BUTTON_TEXT;
}
else
diff --git a/iup/src/win/iupwin_canvas.c b/iup/src/win/iupwin_canvas.c
index bb88b8a..b865160 100755
--- a/iup/src/win/iupwin_canvas.c
+++ b/iup/src/win/iupwin_canvas.c
@@ -45,7 +45,7 @@ static void winCanvasSetScrollInfo(HWND hWnd, int imin, int imax, int ipos, int
static int winCanvasSetBgColorAttrib(Ihandle *ih, const char *value)
{
(void)value;
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
return 1;
}
@@ -220,7 +220,7 @@ static void winCanvasUpdateHorScroll(Ihandle* ih, WORD winop)
xmax = iupAttribGetFloat(ih,"XMAX");
xmin = iupAttribGetFloat(ih,"XMIN");
- winCanvasGetScrollInfo(ih->handle, &iposx, &ipagex, SB_HORZ, winop==SB_THUMBTRACK? 1: 0);
+ winCanvasGetScrollInfo(ih->handle, &iposx, &ipagex, SB_HORZ, winop==SB_THUMBTRACK||winop==SB_THUMBPOSITION? 1: 0);
if (!iupAttribGet(ih,"LINEX"))
{
@@ -296,7 +296,7 @@ static void winCanvasUpdateVerScroll(Ihandle* ih, WORD winop)
ymax = iupAttribGetFloat(ih,"YMAX");
ymin = iupAttribGetFloat(ih,"YMIN");
- winCanvasGetScrollInfo(ih->handle, &iposy, &ipagey, SB_VERT, winop==SB_THUMBTRACK? 1: 0);
+ winCanvasGetScrollInfo(ih->handle, &iposy, &ipagey, SB_VERT, winop==SB_THUMBTRACK||winop==SB_THUMBPOSITION? 1: 0);
if (!iupAttribGet(ih, "LINEY"))
{
@@ -372,6 +372,10 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
GetClientRect(ih->handle, &rect);
FillRect(hdc, &rect, iupwinBrushGet(color));
}
+ else
+ InvalidateRect(ih->handle,NULL,FALSE); /* This will invalidate all area.
+ Necessary in XP, or overlapping windows will have the effect of partial redrawing. */
+
/* always return non zero value */
*result = 1;
return 1;
@@ -382,7 +386,7 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(ih->handle, &ps);
- iupAttribSetStr(ih, "HDC_WMPAINT", (char*)&hdc);
+ iupAttribSetStr(ih, "HDC_WMPAINT", (char*)hdc);
iupAttribSetStrf(ih, "CLIPRECT", "%d %d %d %d", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top);
cb(ih, ih->data->posx, ih->data->posy);
@@ -542,27 +546,13 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
return iupwinBaseProc(ih, msg, wp, lp, result);
}
-static void winCanvasRegisterClass(void)
-{
- WNDCLASS wndclass;
- ZeroMemory(&wndclass, sizeof(WNDCLASS));
-
- wndclass.hInstance = iupwin_hinstance;
- wndclass.lpszClassName = "IupCanvas";
- wndclass.lpfnWndProc = (WNDPROC)iupwinBaseWinProc;
- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; /* using CS_OWNDC will minimize the work of cdActivate in the CD library */
- wndclass.hbrBackground = NULL; /* remove the background to optimize redraw */
-
- RegisterClass(&wndclass);
-}
-
static int winCanvasMapMethod(Ihandle* ih)
{
CLIENTCREATESTRUCT clientstruct;
void *clientdata = NULL;
char *classname;
- DWORD dwStyle = WS_CHILD, dwExStyle = 0;
+ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS,
+ dwExStyle = 0;
if (!ih->parent)
return IUP_ERROR;
@@ -574,14 +564,7 @@ static int winCanvasMapMethod(Ihandle* ih)
}
if (ih->firstchild) /* can be a container */
- {
- dwStyle |= WS_CLIPSIBLINGS;
-
- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
- dwExStyle |= WS_EX_COMPOSITED;
- else
- dwStyle |= WS_CLIPCHILDREN;
- }
+ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
if (iupAttribGetBoolean(ih, "MDICLIENT"))
{
@@ -693,6 +676,21 @@ static void winCanvasReleaseMethod(Iclass* ic)
UnregisterClass("IupCanvas", iupwin_hinstance);
}
+static void winCanvasRegisterClass(void)
+{
+ WNDCLASS wndclass;
+ ZeroMemory(&wndclass, sizeof(WNDCLASS));
+
+ wndclass.hInstance = iupwin_hinstance;
+ wndclass.lpszClassName = "IupCanvas";
+ wndclass.lpfnWndProc = (WNDPROC)iupwinBaseWinProc;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; /* using CS_OWNDC will minimize the work of cdActivate in the CD library */
+ wndclass.hbrBackground = NULL; /* remove the background to optimize redraw */
+
+ RegisterClass(&wndclass);
+}
+
void iupdrvCanvasInitClass(Iclass* ic)
{
if (!iupwinClassExist("IupCanvas"))
diff --git a/iup/src/win/iupwin_common.c b/iup/src/win/iupwin_common.c
index a1a7c0f..ba68b78 100755
--- a/iup/src/win/iupwin_common.c
+++ b/iup/src/win/iupwin_common.c
@@ -94,16 +94,17 @@ void iupdrvBaseLayoutUpdateMethod(Ihandle *ih)
SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER);
}
-void iupdrvDisplayRedraw(Ihandle *ih)
+void iupdrvRedrawNow(Ihandle *ih)
{
/* REDRAW Now */
- RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_NOCHILDREN|RDW_UPDATENOW);
+ RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_UPDATENOW);
}
-void iupdrvDisplayUpdate(Ihandle *ih)
+void iupdrvPostRedraw(Ihandle *ih)
{
/* Post a REDRAW */
- RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_NOCHILDREN);
+ /* can NOT use RDW_NOCHILDREN because IupList has internal children that needs to be redraw */
+ RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT);
}
void iupdrvScreenToClient(Ihandle* ih, int *x, int *y)
@@ -534,6 +535,8 @@ int iupdrvBaseSetZorderAttrib(Ihandle* ih, const char* value)
void iupdrvSetVisible(Ihandle* ih, int visible)
{
+ if (iupStrEqual(ih->iclass->name, "colorbar"))
+ ih=ih;
ShowWindow(ih->handle, visible? SW_SHOWNORMAL: SW_HIDE);
}
@@ -618,6 +621,18 @@ char* iupdrvBaseGetClientSizeAttrib(Ihandle* ih)
#define IDC_HELP MAKEINTRESOURCE(32651)
#endif
+static HCURSOR winLoadComCtlCursor(LPCTSTR lpCursorName)
+{
+ HCURSOR cur = NULL;
+ HINSTANCE hinstDll = LoadLibrary("comctl32.dll");
+ if (hinstDll)
+ {
+ cur = LoadCursor(hinstDll, lpCursorName);
+ FreeLibrary(hinstDll);
+ }
+ return cur;
+}
+
static HCURSOR winGetCursor(Ihandle* ih, const char* name)
{
static struct {
@@ -649,7 +664,7 @@ static HCURSOR winGetCursor(Ihandle* ih, const char* name)
{"APPSTARTING", IDC_APPSTARTING}
};
- HCURSOR cur;
+ HCURSOR cur = NULL;
char str[50];
int i, count = sizeof(table)/sizeof(table[0]);
@@ -676,14 +691,22 @@ static HCURSOR winGetCursor(Ihandle* ih, const char* name)
if (i == count)
{
/* check other system cursors */
- /* cursor PEN is handled here */
+
if (iupStrEqualNoCase(name, "PEN"))
- name = "CURSOR_PEN";
+ name = "CURSOR_PEN"; /* name in "iup.rc" */
/* check for an name defined cursor */
cur = iupImageGetCursor(name);
}
+ if (!cur)
+ {
+ if (iupStrEqualNoCase(name, "SPLITTER_VERT"))
+ cur = winLoadComCtlCursor(MAKEINTRESOURCE(107));
+ else if (iupStrEqualNoCase(name, "SPLITTER_HORIZ"))
+ cur = winLoadComCtlCursor(MAKEINTRESOURCE(135));
+ }
+
iupAttribSetStr(ih, str, (char*)cur);
return cur;
}
@@ -758,29 +781,29 @@ int iupwinButtonUp(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
if (msg==WM_LBUTTONUP)
{
b = IUP_BUTTON1;
- iupKEYSETBUTTON1(status);
+ iupKEY_SETBUTTON1(status);
}
else if (msg==WM_MBUTTONUP)
{
b = IUP_BUTTON2;
- iupKEYSETBUTTON2(status);
+ iupKEY_SETBUTTON2(status);
}
else if (msg==WM_RBUTTONUP)
{
b = IUP_BUTTON3;
- iupKEYSETBUTTON3(status);
+ iupKEY_SETBUTTON3(status);
}
else if (msg==WM_XBUTTONUP)
{
if (HIWORD(wp) == XBUTTON1)
{
b = IUP_BUTTON4;
- iupKEYSETBUTTON4(status);
+ iupKEY_SETBUTTON4(status);
}
else
{
b = IUP_BUTTON5;
- iupKEYSETBUTTON5(status);
+ iupKEY_SETBUTTON5(status);
}
}
@@ -807,6 +830,14 @@ int iupwinMouseMove(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
return 0;
}
+void iupwinGetNativeParentStyle(Ihandle* ih, DWORD *dwExStyle, DWORD *dwStyle)
+{
+ *dwStyle |= WS_CLIPCHILDREN;
+
+ if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
+ *dwExStyle |= WS_EX_COMPOSITED;
+}
+
int iupwinCreateWindowEx(Ihandle* ih, LPCSTR lpClassName, DWORD dwExStyle, DWORD dwStyle)
{
ih->serial = iupDialogGetChildId(ih);
diff --git a/iup/src/win/iupwin_dialog.c b/iup/src/win/iupwin_dialog.c
index 39fdc0c..c13b88d 100755
--- a/iup/src/win/iupwin_dialog.c
+++ b/iup/src/win/iupwin_dialog.c
@@ -102,9 +102,9 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
else
{
int has_titlebar = iupAttribGetBoolean(ih, "MAXBOX") ||
- iupAttribGetBoolean(ih, "MINBOX") ||
- iupAttribGetBoolean(ih, "MENUBOX") ||
- IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
+ iupAttribGetBoolean(ih, "MINBOX") ||
+ iupAttribGetBoolean(ih, "MENUBOX") ||
+ IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
*caption = 0;
if (has_titlebar)
@@ -118,14 +118,17 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
*border = 0;
if (iupAttribGetBoolean(ih, "RESIZE"))
{
+ /* has_border */
*border = GetSystemMetrics(SM_CXFRAME); /* Thickness of the sizing border around the perimeter of a window */
} /* that can be resized, in pixels. */
else if (has_titlebar)
{
+ /* has_border */
*border = GetSystemMetrics(SM_CXFIXEDFRAME); /* Thickness of the frame around the perimeter of a window */
} /* that has a caption but is not sizable, in pixels. */
else if (iupAttribGetBoolean(ih, "BORDER"))
{
+ /* has_border */
*border = GetSystemMetrics(SM_CXBORDER);
}
}
@@ -712,28 +715,27 @@ static int winDialogMapMethod(Ihandle* ih)
}
if (iupAttribGetBoolean(ih, "RESIZE"))
+ {
dwStyle |= WS_THICKFRAME;
+ has_border = 1;
+ }
else
iupAttribSetStr(ih, "MAXBOX", "NO"); /* Must also remove this to RESIZE=NO work */
-
if (iupAttribGetBoolean(ih, "MAXBOX"))
{
dwStyle |= WS_MAXIMIZEBOX;
has_titlebar = 1;
}
-
if (iupAttribGetBoolean(ih, "MINBOX"))
{
dwStyle |= WS_MINIMIZEBOX;
has_titlebar = 1;
}
-
if (iupAttribGetBoolean(ih, "MENUBOX"))
{
dwStyle |= WS_SYSMENU;
has_titlebar = 1;
}
-
if (iupAttribGetBoolean(ih, "BORDER") || has_titlebar)
has_border = 1;
@@ -815,10 +817,7 @@ static int winDialogMapMethod(Ihandle* ih)
if (iupAttribGetBoolean(ih, "DIALOGFRAME") && native_parent)
dwExStyle |= WS_EX_DLGMODALFRAME; /* this will hide the MENUBOX but not the close button */
- if (iupAttribGetBoolean(ih, "COMPOSITED"))
- dwExStyle |= WS_EX_COMPOSITED;
- else
- dwStyle |= WS_CLIPCHILDREN;
+ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
if (iupAttribGetBoolean(ih, "HELPBUTTON"))
dwExStyle |= WS_EX_CONTEXTHELP;
@@ -878,7 +877,6 @@ static int winDialogMapMethod(Ihandle* ih)
/* Reset attributes handled during creation that */
/* also can be changed later, and can be consulted from the native system. */
iupAttribSetStr(ih, "TITLE", NULL);
- iupAttribSetStr(ih, "BORDER", NULL);
/* Ignore VISIBLE before mapping */
iupAttribSetStr(ih, "VISIBLE", NULL);
@@ -956,7 +954,7 @@ static int winDialogSetBgColorAttrib(Ihandle* ih, const char* value)
{
iupAttribStoreStr(ih, "_IUPWIN_BACKGROUND_COLOR", value);
iupAttribSetStr(ih, "_IUPWIN_BACKGROUND_BITMAP", NULL);
- RedrawWindow(ih->handle, NULL, NULL, RDW_ERASE|RDW_ERASENOW); /* force a WM_ERASEBKGND now */
+ RedrawWindow(ih->handle, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); /* post WM_ERASEBKGND and WM_PAINT */
return 1;
}
return 0;
@@ -973,7 +971,7 @@ static int winDialogSetBackgroundAttrib(Ihandle* ih, const char* value)
{
iupAttribSetStr(ih, "_IUPWIN_BACKGROUND_COLOR", NULL);
iupAttribSetStr(ih, "_IUPWIN_BACKGROUND_BITMAP", (char*)hBitmap);
- RedrawWindow(ih->handle, NULL, NULL, RDW_ERASE|RDW_ERASENOW); /* force a WM_ERASEBKGND now */
+ RedrawWindow(ih->handle, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); /* post WM_ERASEBKGND and WM_PAINT */
return 1;
}
}
diff --git a/iup/src/win/iupwin_draw.c b/iup/src/win/iupwin_draw.c
index 4a810e6..f663d20 100755
--- a/iup/src/win/iupwin_draw.c
+++ b/iup/src/win/iupwin_draw.c
@@ -14,12 +14,16 @@
#include <stdio.h>
#include <string.h>
#include <memory.h>
+#include <math.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 "iupwin_drv.h"
#include "iupwin_info.h"
@@ -38,6 +42,11 @@
#endif
+/******************************************************************************
+ Themes
+*******************************************************************************/
+
+
typedef HTHEME (STDAPICALLTYPE *_winThemeOpenData)(HWND hwnd, LPCWSTR pszClassList);
typedef HRESULT (STDAPICALLTYPE *_winThemeCloseData)(HTHEME hTheme);
typedef HRESULT (STDAPICALLTYPE *_winThemeDrawBackground)(HTHEME hTheme, HDC hDC, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect);
@@ -61,58 +70,6 @@ static int winDrawThemeEnabled(void)
return winThemeOpenData? 1: 0;
}
-void iupwinDrawText(HDC hDC, const char* text, int x, int y, int width, int height, HFONT hFont, COLORREF fgcolor, int style)
-{
- COLORREF oldcolor;
- RECT rect;
- HFONT hOldFont = SelectObject(hDC, hFont);
-
- rect.left = x;
- rect.top = y;
- rect.right = x+width;
- rect.bottom = y+height;
-
- SetTextAlign(hDC, TA_TOP|TA_LEFT);
- SetBkMode(hDC, TRANSPARENT);
- oldcolor = SetTextColor(hDC, fgcolor);
-
- DrawText(hDC, text, -1, &rect, style|DT_NOCLIP);
-
- SelectObject(hDC, hOldFont);
- SetTextColor(hDC, oldcolor);
- SetBkMode(hDC, OPAQUE);
-}
-
-void iupwinDrawBitmap(HDC hDC, HBITMAP hBitmap, HBITMAP hMask, int x, int y, int width, int height, int bpp)
-{
- HDC hMemDC = CreateCompatibleDC(hDC);
- SelectObject(hMemDC, hBitmap);
-
- if (bpp == 32 && winAlphaBlend)
- {
- BLENDFUNCTION blendfunc;
- blendfunc.BlendOp = AC_SRC_OVER;
- blendfunc.BlendFlags = 0;
- blendfunc.SourceConstantAlpha = 0xFF;
- blendfunc.AlphaFormat = AC_SRC_ALPHA;
-
- winAlphaBlend(hDC, x, y, width, height,
- hMemDC, 0, 0, width, height,
- blendfunc);
- }
- else if (bpp == 8 && hMask)
- MaskBlt(hDC, x, y, width, height,
- hMemDC, 0, 0,
- hMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0000));
- else
- BitBlt(hDC, x, y, width, height,
- hMemDC, 0, 0,
- SRCCOPY);
-
-
- DeleteDC(hMemDC);
-}
-
void iupwinDrawInit(void)
{
if (!winAlphaBlend)
@@ -201,7 +158,7 @@ int iupwinDrawGetThemeTabsBgColor(HWND hWnd, COLORREF *color)
if (!hTheme)
return 0;
- if (iupwinIsVista())
+ if (iupwinIsVistaOrNew())
ret = winThemeGetColor(hTheme, TABP_AEROWIZARDBODY, TIS_NORMAL, TMT_FILLCOLORHINT, color);
else
ret = winThemeGetColor(hTheme, TABP_BODY, TIS_NORMAL, TMT_FILLCOLORHINT, color);
@@ -246,6 +203,79 @@ int iupwinDrawGetThemeFrameFgColor(HWND hWnd, COLORREF *color)
return (ret == S_OK)? 1: 0;
}
+void iupwinDrawRemoveTheme(HWND hwnd)
+{
+ typedef HRESULT (STDAPICALLTYPE *winSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
+ static winSetWindowTheme mySetWindowTheme = NULL;
+ if (!mySetWindowTheme)
+ {
+ HMODULE hinstDll = LoadLibrary("uxtheme.dll");
+ if (hinstDll)
+ mySetWindowTheme = (winSetWindowTheme)GetProcAddress(hinstDll, "SetWindowTheme");
+ }
+
+ if (mySetWindowTheme)
+ mySetWindowTheme(hwnd, L"", L"");
+}
+
+
+/******************************************************************************
+ Utilities
+*******************************************************************************/
+
+
+void iupwinDrawText(HDC hDC, const char* text, int x, int y, int width, int height, HFONT hFont, COLORREF fgcolor, int style)
+{
+ COLORREF oldcolor;
+ RECT rect;
+ HFONT hOldFont = SelectObject(hDC, hFont);
+
+ rect.left = x;
+ rect.top = y;
+ rect.right = x+width;
+ rect.bottom = y+height;
+
+ SetTextAlign(hDC, TA_TOP|TA_LEFT);
+ SetBkMode(hDC, TRANSPARENT);
+ oldcolor = SetTextColor(hDC, fgcolor);
+
+ DrawText(hDC, text, -1, &rect, style|DT_NOCLIP);
+
+ SelectObject(hDC, hOldFont);
+ SetTextColor(hDC, oldcolor);
+ SetBkMode(hDC, OPAQUE);
+}
+
+void iupwinDrawBitmap(HDC hDC, HBITMAP hBitmap, HBITMAP hMask, int x, int y, int width, int height, int bpp)
+{
+ HDC hMemDC = CreateCompatibleDC(hDC);
+ SelectObject(hMemDC, hBitmap);
+
+ if (bpp == 32 && winAlphaBlend)
+ {
+ BLENDFUNCTION blendfunc;
+ blendfunc.BlendOp = AC_SRC_OVER;
+ blendfunc.BlendFlags = 0;
+ blendfunc.SourceConstantAlpha = 0xFF;
+ blendfunc.AlphaFormat = AC_SRC_ALPHA;
+
+ winAlphaBlend(hDC, x, y, width, height,
+ hMemDC, 0, 0, width, height,
+ blendfunc);
+ }
+ else if (bpp == 8 && hMask)
+ MaskBlt(hDC, x, y, width, height,
+ hMemDC, 0, 0,
+ hMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0000));
+ else
+ BitBlt(hDC, x, y, width, height,
+ hMemDC, 0, 0,
+ SRCCOPY);
+
+
+ DeleteDC(hMemDC);
+}
+
static int winDrawGetStateId(int itemState)
{
if (itemState & ODS_DISABLED)
@@ -282,21 +312,6 @@ void iupdrvDrawFocusRect(Ihandle* ih, void* gc, int x, int y, int w, int h)
DrawFocusRect(hDC, &rect);
}
-void iupwinDrawRemoveTheme(HWND hwnd)
-{
- typedef HRESULT (STDAPICALLTYPE *winSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
- static winSetWindowTheme mySetWindowTheme = NULL;
- if (!mySetWindowTheme)
- {
- HMODULE hinstDll = LoadLibrary("uxtheme.dll");
- if (hinstDll)
- mySetWindowTheme = (winSetWindowTheme)GetProcAddress(hinstDll, "SetWindowTheme");
- }
-
- if (mySetWindowTheme)
- mySetWindowTheme(hwnd, L"", L"");
-}
-
void iupwinDrawParentBackground(Ihandle* ih, HDC hDC, RECT* rect)
{
unsigned char r=0, g=0, b=0;
@@ -326,3 +341,226 @@ void iupwinDrawDestroyBitmapDC(iupwinBitmapDC *bmpDC)
DeleteDC(bmpDC->hBitmapDC);
}
+
+/******************************************************************************
+ Simple Draw
+*******************************************************************************/
+
+struct _IdrawCanvas{
+ Ihandle* ih;
+ int w, h;
+
+ int release_dc;
+ HBITMAP hBitmap, hOldBitmap;
+ HDC hBitmapDC, hDC;
+};
+
+IdrawCanvas* iupDrawCreateCanvas(Ihandle* ih)
+{
+ IdrawCanvas* dc = calloc(1, sizeof(IdrawCanvas));
+ RECT rect;
+
+ /* valid only inside the ACTION callback of an IupCanvas */
+ dc->hDC = (HDC)IupGetAttribute(ih, "HDC_WMPAINT");
+ if (!dc->hDC)
+ {
+ dc->hDC = GetDC(ih->handle);
+ dc->release_dc = 1;
+ }
+
+ GetClientRect(ih->handle, &rect);
+ dc->w = rect.right - rect.left;
+ dc->h = rect.bottom - rect.top;
+
+ dc->hBitmap = CreateCompatibleBitmap(dc->hDC, dc->w, dc->h);
+ dc->hBitmapDC = CreateCompatibleDC(dc->hDC);
+ dc->hOldBitmap = SelectObject(dc->hBitmapDC, dc->hBitmap);
+
+ SetBkMode(dc->hBitmapDC, TRANSPARENT);
+ SetTextAlign(dc->hBitmapDC, TA_TOP|TA_LEFT);
+
+ return dc;
+}
+
+void iupDrawKillCanvas(IdrawCanvas* dc)
+{
+ SelectObject(dc->hBitmapDC, dc->hOldBitmap);
+ DeleteObject(dc->hBitmap);
+ DeleteDC(dc->hBitmapDC);
+ if (dc->release_dc)
+ DeleteDC(dc->hDC);
+
+ free(dc);
+}
+
+void iupDrawUpdateSize(IdrawCanvas* dc)
+{
+ int w, h;
+ RECT rect;
+ GetClientRect(dc->ih->handle, &rect);
+ w = rect.right - rect.left;
+ h = rect.bottom - rect.top;
+
+ if (w != dc->w || h != dc->h)
+ {
+ SelectObject(dc->hBitmapDC, dc->hOldBitmap);
+ DeleteObject(dc->hBitmap);
+ DeleteDC(dc->hBitmapDC);
+
+ dc->hBitmap = CreateCompatibleBitmap(dc->hDC, dc->w, dc->h);
+ dc->hBitmapDC = CreateCompatibleDC(dc->hDC);
+ dc->hOldBitmap = SelectObject(dc->hBitmapDC, dc->hBitmap);
+
+ SetBkMode(dc->hBitmapDC, TRANSPARENT);
+ SetTextAlign(dc->hBitmapDC, TA_TOP|TA_LEFT);
+ }
+}
+
+void iupDrawFlush(IdrawCanvas* dc)
+{
+ BitBlt(dc->hDC, 0, 0, dc->w, dc->h, dc->hBitmapDC, 0, 0, SRCCOPY);
+}
+
+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)
+{
+ RECT rect;
+ rect.left = x1; rect.top = y1; rect.right = x2+1; rect.bottom = y2+1;
+ SetDCBrushColor(dc->hBitmapDC, RGB(r,g,b));
+ if (filled)
+ FillRect(dc->hBitmapDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
+ else
+ FrameRect(dc->hBitmapDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
+}
+
+void iupDrawLine(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b)
+{
+ POINT line_poly[2];
+ HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
+ HPEN hPenOld = SelectObject(dc->hBitmapDC, hPen);
+ line_poly[0].x = x1;
+ line_poly[0].y = y1;
+ line_poly[1].x = x2;
+ line_poly[1].y = y2;
+ Polyline(dc->hBitmapDC, line_poly, 2);
+ SelectObject(dc->hBitmapDC, hPenOld);
+ DeleteObject(hPen);
+}
+
+#define IUP_DEG2RAD 0.01745329252 /* degrees to radians (rad = CD_DEG2RAD * deg) */
+
+static int winDrawCalcArc(int c1, int c2, double a, int start)
+{
+ double proj, off;
+ if (start)
+ proj = cos(IUP_DEG2RAD * a);
+ else
+ proj = sin(IUP_DEG2RAD * a);
+ off = (c2+c1)/2.0 + (c2-c1+1)*proj/2.0;
+ return iupROUND(off);
+}
+
+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)
+{
+ int XStartArc = winDrawCalcArc(x1, x2, a1, 1);
+ int XEndArc = winDrawCalcArc(x1, x2, a2, 0);
+ int YStartArc = winDrawCalcArc(y1, y2, a1, 1);
+ int YEndArc = winDrawCalcArc(y1, y2, a2, 0);
+
+ if (filled)
+ {
+ HBRUSH hBrush = CreateSolidBrush(RGB(r,g,b));
+ HPEN hBrushOld = SelectObject(dc->hBitmapDC, hBrush);
+ BeginPath(dc->hBitmapDC);
+ Pie(dc->hBitmapDC, x1, y1, x2+1, y2+1, XStartArc, YStartArc, XEndArc, YEndArc);
+ EndPath(dc->hBitmapDC);
+ FillPath(dc->hBitmapDC);
+ SelectObject(dc->hBitmapDC, hBrushOld);
+ DeleteObject(hBrush);
+ }
+ else
+ {
+ HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
+ HPEN hPenOld = SelectObject(dc->hBitmapDC, hPen);
+ Arc(dc->hBitmapDC, x1, y1, x2+1, y2+1, XStartArc, YStartArc, XEndArc, YEndArc);
+ SelectObject(dc->hBitmapDC, hPenOld);
+ DeleteObject(hPen);
+ }
+}
+
+void iupDrawPolygon(IdrawCanvas* dc, int* points, int count, unsigned char r, unsigned char g, unsigned char b, int filled)
+{
+ if (filled)
+ {
+ HBRUSH hBrush = CreateSolidBrush(RGB(r,g,b));
+ HPEN hBrushOld = SelectObject(dc->hBitmapDC, hBrush);
+ BeginPath(dc->hBitmapDC);
+ Polygon(dc->hBitmapDC, (POINT*)points, count);
+ EndPath(dc->hBitmapDC);
+ FillPath(dc->hBitmapDC);
+ SelectObject(dc->hBitmapDC, hBrushOld);
+ DeleteObject(hBrush);
+ }
+ else
+ {
+ HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
+ HPEN hPenOld = SelectObject(dc->hBitmapDC, hPen);
+ Polyline(dc->hBitmapDC, (POINT*)points, count);
+ SelectObject(dc->hBitmapDC, hPenOld);
+ DeleteObject(hPen);
+ }
+}
+
+void iupDrawSetClipRect(IdrawCanvas* dc, int x1, int y1, int x2, int y2)
+{
+ HRGN clip_hrgn = CreateRectRgn(x1, y1, x2, y2);
+ SelectClipRgn(dc->hBitmapDC, clip_hrgn);
+ DeleteObject(clip_hrgn);
+}
+
+void iupDrawResetClip(IdrawCanvas* dc)
+{
+ SelectClipRgn(dc->hBitmapDC, NULL);
+}
+
+void iupDrawText(IdrawCanvas* dc, const char* text, int len, int x, int y, unsigned char r, unsigned char g, unsigned char b)
+{
+ HFONT hOldFont, hFont = (HFONT)IupGetAttribute(dc->ih, "HFONT");
+ SetTextColor(dc->hBitmapDC, RGB(r, g, b));
+ hOldFont = SelectObject(dc->hBitmapDC, hFont);
+ TextOut(dc->hBitmapDC, x, y, text, len);
+ SelectObject(dc->hBitmapDC, hOldFont);
+}
+
+void iupDrawImage(IdrawCanvas* dc, const char* name, int make_inactive, int x, int y)
+{
+ int img_w, img_h, bpp;
+ HBITMAP hMask = NULL;
+ HBITMAP hBitmap = iupImageGetImage(name, dc->ih, make_inactive);
+ if (!hBitmap)
+ return;
+
+ /* must use this info, since image can be a driver image loaded from resources */
+ iupdrvImageGetInfo(hBitmap, &img_w, &img_h, &bpp);
+
+ if (bpp == 8)
+ hMask = iupdrvImageCreateMask(IupGetHandle(name));
+
+ iupwinDrawBitmap(dc->hBitmapDC, hBitmap, hMask, x, y, img_w, img_h, bpp);
+
+ if (hMask)
+ DeleteObject(hMask);
+}
diff --git a/iup/src/win/iupwin_drv.h b/iup/src/win/iupwin_drv.h
index 3372c1a..7407a7a 100755
--- a/iup/src/win/iupwin_drv.h
+++ b/iup/src/win/iupwin_drv.h
@@ -77,6 +77,7 @@ int iupwinBaseContainerProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT
/* Creates the Window with native parent and child ID, associate HWND with Ihandle*,
and replace the WinProc by iupwinBaseWinProc */
int iupwinCreateWindowEx(Ihandle* ih, LPCSTR lpClassName, DWORD dwExStyle, DWORD dwStyle);
+void iupwinGetNativeParentStyle(Ihandle* ih, DWORD *dwExStyle, DWORD *dwStyle);
int iupwinClassExist(const char* name);
int iupwinGetColorRef(Ihandle *ih, char *name, COLORREF *color);
@@ -97,8 +98,8 @@ char* iupwinGetClipboardText(Ihandle* ih);
int iupwinGetScreenRes(void);
/* 1 point = 1/72 inch */
/* pixel = (point/72)*(pixel/inch) */
-#define IUPWIN_PT2PIXEL(_pt, _res) MulDiv(_pt, _res, 72) /* (((_pt)*(_res))/72) */
-#define IUPWIN_PIXEL2PT(_pixel, _res) MulDiv(_pixel, 72, _res) /* (((_pixel)*72)/(_res)) */
+#define iupWIN_PT2PIXEL(_pt, _res) MulDiv(_pt, _res, 72) /* (((_pt)*(_res))/72) */
+#define iupWIN_PIXEL2PT(_pixel, _res) MulDiv(_pixel, 72, _res) /* (((_pixel)*72)/(_res)) */
/* child window identifier of the first MDI child window created,
diff --git a/iup/src/win/iupwin_filedlg.c b/iup/src/win/iupwin_filedlg.c
index da66b4b..26994e5 100755
--- a/iup/src/win/iupwin_filedlg.c
+++ b/iup/src/win/iupwin_filedlg.c
@@ -63,7 +63,7 @@ static INT CALLBACK winFileDlgBrowseCallback(HWND hWnd, UINT uMsg, LPARAM lParam
}
else if (uMsg == BFFM_SELCHANGED)
{
- char* buffer = iupStrGetMemory(MAX_FILENAME_SIZE);
+ char buffer[MAX_FILENAME_SIZE];
ITEMIDLIST* selecteditem = (ITEMIDLIST*)lParam;
buffer[0] = 0;
SHGetPathFromIDList(selecteditem, buffer);
@@ -90,7 +90,7 @@ static void winFileDlgGetFolder(Ihandle *ih)
browseinfo.pszDisplayName = buffer;
browseinfo.lpfn = winFileDlgBrowseCallback;
browseinfo.lParam = (LPARAM)ih;
- browseinfo.ulFlags = BIF_NEWDIALOGSTYLE;
+ browseinfo.ulFlags = IupGetGlobal("_IUPWIN_COINIT_MULTITHREADED")? 0: BIF_NEWDIALOGSTYLE;
browseinfo.hwndOwner = parent;
selecteditem = SHBrowseForFolder(&browseinfo);
@@ -112,6 +112,37 @@ static void winFileDlgGetFolder(Ihandle *ih)
/************************************************************************************************/
+static int winFileDlgGetSelectedFile(Ihandle* ih, HWND hWnd, char* filename)
+{
+ int ret = CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE);
+ if (ret < 0)
+ return 0;
+
+ if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
+ {
+ /* check if there are more than 1 files and return only the first one */
+ int found = 0;
+ while(*filename != 0)
+ {
+ if (*filename == '"')
+ {
+ if (!found)
+ found = 1;
+ else
+ {
+ *(filename-1) = 0;
+ return 1;
+ }
+ }
+ if (found)
+ *filename = *(filename+1);
+ filename++;
+ }
+ }
+
+ return 1;
+}
+
static UINT_PTR CALLBACK winFileDlgSimpleHook(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
(void)wParam;
@@ -152,16 +183,15 @@ static UINT_PTR CALLBACK winFileDlgSimpleHook(HWND hWnd, UINT uiMsg, WPARAM wPar
IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
if (cb)
{
- char* filename = iupStrGetMemory(MAX_FILENAME_SIZE);
- if (CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE) <= MAX_FILENAME_SIZE)
+ char filename[MAX_FILENAME_SIZE];
+ if (winFileDlgGetSelectedFile(ih, hWnd, filename))
{
int ret;
char* file_msg;
if (!iupdrvIsFile(filename))
- break;
-
- if (pofn->hdr.code == CDN_FILEOK)
+ file_msg = "OTHER";
+ else if (pofn->hdr.code == CDN_FILEOK)
file_msg = "OK";
else
file_msg = "SELECT";
@@ -267,9 +297,9 @@ static UINT_PTR CALLBACK winFileDlgPreviewHook(HWND hWnd, UINT uiMsg, WPARAM wPa
LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
Ihandle* ih = (Ihandle*)GetWindowLongPtr(hWnd, DWLP_USER);
IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
- char* filename = iupStrGetMemory(MAX_FILENAME_SIZE);
+ char filename[MAX_FILENAME_SIZE];
iupAttribSetStr(ih, "PREVIEWDC", (char*)lpDrawItem->hDC);
- if (CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE) <= MAX_FILENAME_SIZE)
+ if (winFileDlgGetSelectedFile(ih, hWnd, filename))
{
if (iupdrvIsFile(filename))
cb(ih, filename, "PAINT");
@@ -324,16 +354,15 @@ static UINT_PTR CALLBACK winFileDlgPreviewHook(HWND hWnd, UINT uiMsg, WPARAM wPa
case CDN_SELCHANGE:
{
HWND hWndPreview = GetDlgItem(hWnd, IUP_PREVIEWCANVAS);
- char* filename = iupStrGetMemory(MAX_FILENAME_SIZE);
- if (CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE) <= MAX_FILENAME_SIZE)
+ char filename[MAX_FILENAME_SIZE];
+ if (winFileDlgGetSelectedFile(ih, hWnd, filename))
{
int ret;
char* file_msg;
if (!iupdrvIsFile(filename))
- break;
-
- if (pofn->hdr.code == CDN_FILEOK)
+ file_msg = "OTHER";
+ else if (pofn->hdr.code == CDN_FILEOK)
file_msg = "OK";
else
file_msg = "SELECT";
@@ -520,9 +549,14 @@ static int winFileDlgPopup(Ihandle *ih, int x, int y)
if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
{
int i = 0;
-
+
+ char* dir = iupStrFileGetPath(openfilename.lpstrFile); /* the first part is the directory already */
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+ free(dir);
+
/* If there is more than one file, replace terminator by the separator */
- if (openfilename.lpstrFile && openfilename.lpstrFile[openfilename.nFileOffset-1] == 0 && openfilename.nFileOffset>0)
+ if (openfilename.lpstrFile[openfilename.nFileOffset-1] == 0 &&
+ openfilename.nFileOffset>0)
{
while (openfilename.lpstrFile[i] != 0 || openfilename.lpstrFile[i+1] != 0)
{
@@ -534,12 +568,16 @@ static int winFileDlgPopup(Ihandle *ih, int x, int y)
}
iupAttribSetStr(ih, "STATUS", "0");
- iupAttribSetStr(ih, "FILEEXIST", NULL);
+ iupAttribSetStr(ih, "FILEEXIST", "YES");
}
else
{
if (iupdrvIsFile(openfilename.lpstrFile)) /* check if file exists */
{
+ char* dir = iupStrFileGetPath(openfilename.lpstrFile);
+ iupAttribStoreStr(ih, "DIRECTORY", dir);
+ free(dir);
+
iupAttribSetStr(ih, "FILEEXIST", "YES");
iupAttribSetStr(ih, "STATUS", "0");
}
diff --git a/iup/src/win/iupwin_focus.c b/iup/src/win/iupwin_focus.c
index 63da02d..2328dea 100755
--- a/iup/src/win/iupwin_focus.c
+++ b/iup/src/win/iupwin_focus.c
@@ -32,7 +32,7 @@
/* Since Windows XP, the focus feedback only appears after the user press a key.
Except for the IupText where the feedback is the caret.
- Before that if you click in a control the focus feedback will be hidden.
+ Before a key is pressed if you click in a control the focus feedback will be hidden.
We manually send WM_CHANGEUISTATE because we do not use IsDialogMessage anymore,
and the focus feedback was not shown even after the used press a key.
@@ -43,19 +43,28 @@
void iupdrvSetFocus(Ihandle *ih)
{
SetFocus(ih->handle);
- SendMessage(ih->handle, WM_CHANGEUISTATE, UIS_CLEAR|UISF_HIDEFOCUS, 0);
+
+ /* See comments above */
+ SendMessage(ih->handle, WM_CHANGEUISTATE, UIS_CLEAR|UISF_HIDEFOCUS, 0); /* clear+hidefocus=showfocus */
}
void iupwinWmSetFocus(Ihandle *ih)
{
Ihandle* dialog = IupGetDialog(ih);
if (ih != dialog)
- iupAttribSetStr(dialog, "_IUPWIN_LASTFOCUS", (char*)ih); /* used by IupMenu */
+ iupAttribSetStr(dialog, "_IUPWIN_LASTFOCUS", (char*)ih); /* used by IupMenu and here. */
else
{
/* if a control inside that dialog had the focus, then reset to it when the dialog gets the focus */
Ihandle* lastfocus = (Ihandle*)iupAttribGet(dialog, "_IUPWIN_LASTFOCUS");
- if (lastfocus) IupSetFocus(lastfocus);
+ if (lastfocus)
+ {
+ /* call the callback and update current focus before changing it again */
+ iupCallGetFocusCb(ih);
+
+ IupSetFocus(lastfocus);
+ return;
+ }
}
iupCallGetFocusCb(ih);
diff --git a/iup/src/win/iupwin_font.c b/iup/src/win/iupwin_font.c
index 659e2d9..c10befb 100755
--- a/iup/src/win/iupwin_font.c
+++ b/iup/src/win/iupwin_font.c
@@ -70,7 +70,7 @@ static IwinFont* winFindFont(const char *standardfont)
if (height < 0)
height_pixels = height; /* already in pixels */
else
- height_pixels = -IUPWIN_PT2PIXEL(height, res);
+ height_pixels = -iupWIN_PT2PIXEL(height, res);
if (height_pixels == 0)
return NULL;
@@ -119,7 +119,7 @@ static void winFontFromLogFont(LOGFONT* logfont, char * font)
int is_strikeout = logfont->lfStrikeOut;
int height_pixels = logfont->lfHeight; /* negative value */
int res = iupwinGetScreenRes();
- int height = IUPWIN_PIXEL2PT(-height_pixels, res); /* return in points */
+ int height = iupWIN_PIXEL2PT(-height_pixels, res); /* return in points */
sprintf(font, "%s, %s%s%s%s %d", logfont->lfFaceName,
is_bold?"Bold ":"",
diff --git a/iup/src/win/iupwin_fontdlg.c b/iup/src/win/iupwin_fontdlg.c
index 0602441..ce27cf2 100755
--- a/iup/src/win/iupwin_fontdlg.c
+++ b/iup/src/win/iupwin_fontdlg.c
@@ -68,7 +68,7 @@ static int winFontDlgPopup(Ihandle* ih, int x, int y)
standardfont = iupAttribGet(ih, "VALUE");
if (!standardfont)
- return IUP_ERROR;
+ standardfont = IupGetGlobal("DEFAULTFONT");
/* parse the old format first */
if (!iupFontParseWin(standardfont, typeface, &height, &is_bold, &is_italic, &is_underline, &is_strikeout))
@@ -81,7 +81,7 @@ static int winFontDlgPopup(Ihandle* ih, int x, int y)
if (height < 0)
height_pixels = height; /* already in pixels */
else
- height_pixels = -IUPWIN_PT2PIXEL(height, res);
+ height_pixels = -iupWIN_PT2PIXEL(height, res);
if (height_pixels == 0)
return IUP_ERROR;
@@ -134,7 +134,7 @@ static int winFontDlgPopup(Ihandle* ih, int x, int y)
if (height < 0) /* not an error, use old value as a reference for the units */
height = height_pixels; /* return in pixels */
else
- height = IUPWIN_PIXEL2PT(-height_pixels, res); /* return in points */
+ height = iupWIN_PIXEL2PT(-height_pixels, res); /* return in points */
iupAttribSetStrf(ih, "VALUE", "%s, %s%s%s%s %d", logfont.lfFaceName,
is_bold?"Bold ":"",
diff --git a/iup/src/win/iupwin_frame.c b/iup/src/win/iupwin_frame.c
index 0949b5d..3f56aed 100755
--- a/iup/src/win/iupwin_frame.c
+++ b/iup/src/win/iupwin_frame.c
@@ -47,6 +47,27 @@ void iupdrvFrameGetDecorOffset(Ihandle* ih, int *x, int *y)
}
}
+static char* winFrameGetBgColorAttrib(Ihandle* ih)
+{
+ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+ return NULL;
+ else
+ return iupBaseNativeParentGetBgColorAttrib(ih);
+}
+
+static int winFrameSetBgColorAttrib(Ihandle* ih, const char* value)
+{
+ (void)value;
+
+ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+ {
+ IupUpdate(ih); /* post a redraw */
+ return 1;
+ }
+ else
+ return 0;
+}
+
static void winFrameDrawText(HDC hDC, const char* text, int x, int y, COLORREF fgcolor)
{
COLORREF oldcolor;
@@ -126,6 +147,16 @@ static void winFrameDrawItem(Ihandle* ih, DRAWITEMSTRUCT *drawitem)
DrawEdge(hDC, &drawitem->rcItem, EDGE_SUNKEN, BF_RECT);
else
DrawEdge(hDC, &drawitem->rcItem, EDGE_ETCHED, BF_RECT);
+
+ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
+ {
+ unsigned char r=0, g=0, b=0;
+ char* color = iupAttribGetStr(ih, "BGCOLOR");
+ iupStrToRGB(color, &r, &g, &b);
+ SetDCBrushColor(hDC, RGB(r,g,b));
+ InflateRect(&drawitem->rcItem, -2, -2);
+ FillRect(hDC, &drawitem->rcItem, (HBRUSH)GetStockObject(DC_BRUSH));
+ }
}
iupwinDrawDestroyBitmapDC(&bmpDC);
@@ -169,11 +200,13 @@ static int winFrameMapMethod(Ihandle* ih)
title = iupAttribGet(ih, "TITLE");
if (title)
iupAttribSetStr(ih, "_IUPFRAME_HAS_TITLE", "1");
-
- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
- dwExStyle |= WS_EX_COMPOSITED;
else
- dwStyle |= WS_CLIPCHILDREN;
+ {
+ if (iupAttribGet(ih, "BGCOLOR"))
+ iupAttribSetStr(ih, "_IUPFRAME_HAS_BGCOLOR", "1");
+ }
+
+ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
if (!iupwinCreateWindowEx(ih, "BUTTON", dwExStyle, dwStyle))
return IUP_ERROR;
@@ -195,7 +228,7 @@ void iupdrvFrameInitClass(Iclass* ic)
/* Driver Dependent Attribute functions */
/* Visual */
- iupClassRegisterAttribute(ic, "BGCOLOR", iupBaseNativeParentGetBgColorAttrib, NULL, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", winFrameGetBgColorAttrib, winFrameSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
/* Special */
iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_NOT_MAPPED);
diff --git a/iup/src/win/iupwin_globalattrib.c b/iup/src/win/iupwin_globalattrib.c
index a176925..bcd6355 100755
--- a/iup/src/win/iupwin_globalattrib.c
+++ b/iup/src/win/iupwin_globalattrib.c
@@ -148,6 +148,11 @@ int iupdrvSetGlobal(const char *name, const char *value)
winGlobalSendKey(key, 0x03);
return 0;
}
+ if (iupStrEqual(name, "DLL_HINSTANCE"))
+ {
+ iupwin_dll_hinstance = (HINSTANCE)value;
+ return 0;
+ }
return 1;
}
@@ -239,5 +244,7 @@ char *iupdrvGetGlobal(const char *name)
return "YES";
return "NO";
}
+ if (iupStrEqual(name, "DLL_HINSTANCE"))
+ return (char*)iupwin_dll_hinstance;
return NULL;
}
diff --git a/iup/src/win/iupwin_info.c b/iup/src/win/iupwin_info.c
index 8ea7dd4..4d57289 100755
--- a/iup/src/win/iupwin_info.c
+++ b/iup/src/win/iupwin_info.c
@@ -18,7 +18,7 @@
#include "iupwin_info.h"
-int iupwinIsVista(void)
+int iupwinIsVistaOrNew(void)
{
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
diff --git a/iup/src/win/iupwin_info.h b/iup/src/win/iupwin_info.h
index d39bae0..8d461fb 100755
--- a/iup/src/win/iupwin_info.h
+++ b/iup/src/win/iupwin_info.h
@@ -16,7 +16,7 @@ int iupwinGetSystemMajorVersion(void);
int iupwinGetComCtl32Version(void);
char* iupwinGetSystemLanguage(void);
int iupwinIsAppThemed(void);
-int iupwinIsVista(void);
+int iupwinIsVistaOrNew(void);
/* color */
void iupwinGetSysColor(char* color, int wincolor);
diff --git a/iup/src/win/iupwin_key.c b/iup/src/win/iupwin_key.c
index 921ed94..899e837 100755
--- a/iup/src/win/iupwin_key.c
+++ b/iup/src/win/iupwin_key.c
@@ -317,32 +317,32 @@ int iupwinKeyEvent(Ihandle* ih, int wincode, int press)
void iupwinButtonKeySetStatus(WORD keys, char* status, int doubleclick)
{
if (keys & MK_SHIFT)
- iupKEYSETSHIFT(status);
+ iupKEY_SETSHIFT(status);
if (keys & MK_CONTROL)
- iupKEYSETCONTROL(status);
+ iupKEY_SETCONTROL(status);
if (keys & MK_LBUTTON)
- iupKEYSETBUTTON1(status);
+ iupKEY_SETBUTTON1(status);
if (keys & MK_MBUTTON)
- iupKEYSETBUTTON2(status);
+ iupKEY_SETBUTTON2(status);
if (keys & MK_RBUTTON)
- iupKEYSETBUTTON3(status);
+ iupKEY_SETBUTTON3(status);
if (doubleclick)
- iupKEYSETDOUBLE(status);
+ iupKEY_SETDOUBLE(status);
if (GetKeyState(VK_MENU) & 0x8000)
- iupKEYSETALT(status);
+ iupKEY_SETALT(status);
if ((GetKeyState(VK_LWIN) & 0x8000) || (GetKeyState(VK_RWIN) & 0x8000))
- iupKEYSETSYS(status);
+ iupKEY_SETSYS(status);
if (keys & MK_XBUTTON1)
- iupKEYSETBUTTON4(status);
+ iupKEY_SETBUTTON4(status);
if (keys & MK_XBUTTON2)
- iupKEYSETBUTTON5(status);
+ iupKEY_SETBUTTON5(status);
}
diff --git a/iup/src/win/iupwin_label.c b/iup/src/win/iupwin_label.c
index d5a1f53..95dd10c 100755
--- a/iup/src/win/iupwin_label.c
+++ b/iup/src/win/iupwin_label.c
@@ -173,7 +173,7 @@ static int winLabelSetAlignmentAttrib(Ihandle* ih, const char* value)
else /* "ATOP" */
ih->data->vert_alignment = IUP_ALIGN_ATOP;
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
return 0;
}
@@ -197,7 +197,7 @@ static int winLabelSetPaddingAttrib(Ihandle* ih, const char* value)
iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
if (ih->handle && ih->data->type != IUP_LABEL_SEP_HORIZ && ih->data->type != IUP_LABEL_SEP_VERT)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
return 0;
}
@@ -211,7 +211,7 @@ static int winLabelSetWordWrapAttrib(Ihandle* ih, const char* value)
else
ih->data->text_style &= ~DT_WORDBREAK;
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
return 1;
@@ -226,7 +226,7 @@ static int winLabelSetEllipsisAttrib(Ihandle* ih, const char* value)
else
ih->data->text_style &= ~DT_END_ELLIPSIS;
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
return 1;
@@ -240,12 +240,24 @@ static int winLabelSetFgColorAttrib(Ihandle* ih, const char* value)
if (iupStrToRGB(value, &r, &g, &b))
{
ih->data->fgcolor = RGB(r,g,b);
- iupdrvDisplayRedraw(ih);
+
+ if (ih->handle)
+ iupdrvRedrawNow(ih);
}
}
return 1;
}
+static int winLabelSetUpdateAttrib(Ihandle* ih, const char* value)
+{
+ (void)value;
+
+ if (ih->handle)
+ iupdrvPostRedraw(ih); /* Post a redraw */
+
+ return 1;
+}
+
static int winLabelProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result)
{
switch (msg)
@@ -257,6 +269,7 @@ static int winLabelProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *re
*result = WVR_HREDRAW|WVR_VREDRAW;
return 1;
}
+ break;
}
}
@@ -266,7 +279,7 @@ static int winLabelProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *re
static int winLabelMapMethod(Ihandle* ih)
{
char* value;
- DWORD dwStyle = WS_CHILD |
+ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS |
SS_NOTIFY; /* SS_NOTIFY is necessary because of the base messages */
if (!ih->parent)
@@ -330,7 +343,7 @@ void iupdrvLabelInitClass(Iclass* ic)
/* IupLabel only */
iupClassRegisterAttribute(ic, "ALIGNMENT", winLabelGetAlignmentAttrib, winLabelSetAlignmentAttrib, IUPAF_SAMEASSYSTEM, "ALEFT:ACENTER", IUPAF_NO_INHERIT);
- iupClassRegisterAttribute(ic, "IMAGE", NULL, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGE", NULL, winLabelSetUpdateAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "PADDING", iupLabelGetPaddingAttrib, winLabelSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
/* IupLabel Windows and GTK only */
diff --git a/iup/src/win/iupwin_list.c b/iup/src/win/iupwin_list.c
index 8fdadb6..cb510b5 100755
--- a/iup/src/win/iupwin_list.c
+++ b/iup/src/win/iupwin_list.c
@@ -154,6 +154,8 @@ void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
SendMessage(ih->handle, WIN_INSERTSTRING(ih), pos, (LPARAM)value);
SendMessage(ih->handle, WIN_SETITEMDATA(ih), pos, (LPARAM)iupdrvFontGetStringWidth(ih, value));
winListUpdateScrollWidth(ih);
+
+ iupListUpdateOldValue(ih, pos, 0);
}
void iupdrvListRemoveItem(Ihandle* ih, int pos)
@@ -164,8 +166,14 @@ void iupdrvListRemoveItem(Ihandle* ih, int pos)
int curpos = SendMessage(ih->handle, WIN_GETCURSEL(ih), 0, 0);
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 */
+ }
SendMessage(ih->handle, WIN_SETCURSEL(ih), curpos, 0);
}
@@ -173,6 +181,8 @@ void iupdrvListRemoveItem(Ihandle* ih, int pos)
SendMessage(ih->handle, WIN_DELETESTRING(ih), pos, 0L);
winListUpdateScrollWidth(ih);
+
+ iupListUpdateOldValue(ih, pos, 1);
}
void iupdrvListRemoveAllItems(Ihandle* ih)
@@ -220,18 +230,29 @@ static void winListUpdateItemWidth(Ihandle* ih)
}
}
+static int winListSetBgColorAttrib(Ihandle *ih, const char *value)
+{
+ (void)value;
+ if (ih->handle)
+ iupdrvPostRedraw(ih);
+ return 1;
+}
+
static int winListSetStandardFontAttrib(Ihandle* ih, const char* value)
{
iupdrvSetStandardFontAttrib(ih, value);
- winListUpdateItemWidth(ih);
- winListUpdateScrollWidth(ih);
+ if (ih->handle)
+ {
+ winListUpdateItemWidth(ih);
+ winListUpdateScrollWidth(ih);
+ }
return 1;
}
static char* winListGetIdValueAttrib(Ihandle* ih, const char* name_id)
{
int pos = iupListGetPos(ih, name_id);
- if (pos != -1)
+ if (pos >= 0)
{
int len = SendMessage(ih->handle, WIN_GETTEXTLEN(ih), (WPARAM)pos, 0);
char* str = iupStrGetMemory(len+1);
@@ -514,8 +535,10 @@ static int winListSetNCAttrib(Ihandle* ih, const char* value)
{
HWND cbedit = (HWND)iupAttribGet(ih, "_IUPWIN_EDITBOX");
SendMessage(cbedit, EM_LIMITTEXT, ih->data->nc, 0L);
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int winListSetSelectionAttrib(Ihandle* ih, const char* value)
@@ -995,13 +1018,27 @@ static int winListEditProc(Ihandle* ih, HWND cbedit, UINT msg, WPARAM wp, LPARAM
if (msg==WM_KEYDOWN) /* process K_ANY before text callbacks */
{
ret = iupwinBaseProc(ih, msg, wp, lp, result);
- if (ret) return 1;
+ if (ret)
+ {
+ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", "1");
+ *result = 0;
+ return 1;
+ }
+ else
+ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
}
switch (msg)
{
case WM_CHAR:
{
+ if (iupAttribGet(ih, "_IUPWIN_IGNORE_CHAR"))
+ {
+ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
+ *result = 0;
+ return 1;
+ }
+
if ((char)wp == '\b')
{
if (!winListCallEditCb(ih, cbedit, NULL, 0, -1))
@@ -1301,7 +1338,7 @@ static void winListLayoutUpdateMethod(Ihandle *ih)
static int winListMapMethod(Ihandle* ih)
{
char* class_name;
- DWORD dwStyle = WS_CHILD,
+ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS,
dwExStyle = WS_EX_CLIENTEDGE;
if (!ih->parent)
@@ -1426,7 +1463,7 @@ void iupdrvListInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, winListSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED);
/* Visual */
- iupClassRegisterAttribute(ic, "BGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winListSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_NOT_MAPPED);
/* Special */
iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_NOT_MAPPED);
diff --git a/iup/src/win/iupwin_loop.c b/iup/src/win/iupwin_loop.c
index 7c5dbe7..fd25537 100755
--- a/iup/src/win/iupwin_loop.c
+++ b/iup/src/win/iupwin_loop.c
@@ -106,6 +106,18 @@ int IupMainLoop(void)
return IUP_NOERROR;
}
+int IupLoopStepWait(void)
+{
+ MSG msg;
+ int ret = GetMessage(&msg, NULL, 0, 0);
+ if (ret == -1) /* error */
+ return IUP_ERROR;
+ if (ret == 0 || /* WM_QUIT */
+ winLoopProcessMessage(&msg) == IUP_CLOSE) /* ret != 0 */
+ return IUP_CLOSE;
+ return IUP_DEFAULT;
+}
+
int IupLoopStep(void)
{
MSG msg;
diff --git a/iup/src/win/iupwin_menu.c b/iup/src/win/iupwin_menu.c
index 74a8b52..06ad93e 100755
--- a/iup/src/win/iupwin_menu.c
+++ b/iup/src/win/iupwin_menu.c
@@ -385,7 +385,10 @@ static int winMenuMapMethod(Ihandle* ih)
static void winMenuUnMapMethod(Ihandle* ih)
{
if (iupMenuIsMenuBar(ih))
+ {
SetMenu(ih->parent->handle, NULL);
+ ih->parent = NULL;
+ }
DestroyMenu((HMENU)ih->handle); /* DestroyMenu is recursive */
}
diff --git a/iup/src/win/iupwin_open.c b/iup/src/win/iupwin_open.c
index 7357cde..3629ce4 100755
--- a/iup/src/win/iupwin_open.c
+++ b/iup/src/win/iupwin_open.c
@@ -76,8 +76,9 @@ int iupdrvOpen(int *argc, char ***argv)
iupwin_hinstance = GetModuleHandle(NULL);
IupSetGlobal("HINSTANCE", (char*)iupwin_hinstance);
}
-
- CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ if (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)==RPC_E_CHANGED_MODE)
+ IupSetGlobal("_IUPWIN_COINIT_MULTITHREADED", "1");
{
INITCOMMONCONTROLSEX InitCtrls;
diff --git a/iup/src/win/iupwin_progressbar.c b/iup/src/win/iupwin_progressbar.c
index 9038d79..4a52cc4 100755
--- a/iup/src/win/iupwin_progressbar.c
+++ b/iup/src/win/iupwin_progressbar.c
@@ -106,7 +106,7 @@ static int winProgressBarSetFgColorAttrib(Ihandle* ih, const char* value)
static int winProgressBarMapMethod(Ihandle* ih)
{
- DWORD dwStyle = WS_CHILD;
+ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS;
if (!ih->parent)
return IUP_ERROR;
diff --git a/iup/src/win/iupwin_tabs.c b/iup/src/win/iupwin_tabs.c
index 682f451..b39f7fe 100755
--- a/iup/src/win/iupwin_tabs.c
+++ b/iup/src/win/iupwin_tabs.c
@@ -232,10 +232,7 @@ static HWND winTabCreatePageWindow(Ihandle* ih)
DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS,
dwExStyle = 0;
- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
- dwExStyle |= WS_EX_COMPOSITED;
- else
- dwStyle |= WS_CLIPCHILDREN;
+ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
hWnd = CreateWindowEx(dwExStyle, "IupTabsPage", NULL, dwStyle,
0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
@@ -255,9 +252,12 @@ static int winTabsSetPaddingAttrib(Ihandle* ih, const char* value)
iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
if (ih->handle)
+ {
SendMessage(ih->handle, TCM_SETPADDING, 0, MAKELPARAM(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 winTabsSetMultilineAttrib(Ihandle* ih, const char* value)
@@ -368,6 +368,13 @@ static char* winTabsGetBgColorAttrib(Ihandle* ih)
return IupGetGlobal("DLGBGCOLOR");
}
+static int winTabsSetBgColorAttrib(Ihandle *ih, const char *value)
+{
+ (void)value;
+ iupdrvPostRedraw(ih);
+ return 1;
+}
+
/* ------------------------------------------------------------------------- */
/* winTabs - Calls the user callback to change of tab */
@@ -397,6 +404,7 @@ static int winTabsWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
int prev_pos = SendMessage(ih->handle, TCM_GETCURSEL, 0, 0);
iupAttribSetInt(ih, "_IUPTABS_PREV_CHILD_POS", prev_pos);
+ /* save the previous handle if callback exists */
if (cb)
{
Ihandle* prev_child = IupGetChild(ih, prev_pos);
@@ -420,7 +428,9 @@ static int winTabsWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
Ihandle* prev_child = (Ihandle*)iupAttribGet(ih, "_IUPTABS_PREV_CHILD");
iupAttribSetStr(ih, "_IUPTABS_PREV_CHILD", NULL);
- cb(ih, child, prev_child);
+ /* avoid duplicate calls when a Tab is inside another Tab. */
+ if (prev_child)
+ cb(ih, child, prev_child);
}
}
@@ -522,7 +532,7 @@ static void winTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
}
}
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
}
}
@@ -535,12 +545,11 @@ static void winTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
if (tab_page)
{
int pos = winTabsGetPageWindowPos(ih, tab_page);
+ iupTabsTestRemoveTab(ih, pos);
+
SendMessage(ih->handle, TCM_DELETEITEM, pos, 0);
DestroyWindow(tab_page);
- if (pos==0) pos++;
- iupdrvTabsSetCurrentTab(ih, pos-1);
-
iupAttribSetStr(child, "_IUPTAB_CONTAINER", NULL);
}
}
@@ -564,19 +573,14 @@ static int winTabsMapMethod(Ihandle* ih)
if (ih->data->is_multiline)
dwStyle |= TCS_MULTILINE;
- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
- {
- dwExStyle |= WS_EX_COMPOSITED;
+ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
- if (!ih->data->is_multiline && iupwinIsVista())
- {
- /* workaround for composite bug in Vista */
- ih->data->is_multiline = 1;
- dwStyle |= TCS_MULTILINE;
- }
+ if (dwExStyle & WS_EX_COMPOSITED && !ih->data->is_multiline && iupwinIsVistaOrNew())
+ {
+ /* workaround for composite bug in Vista */
+ ih->data->is_multiline = 1;
+ dwStyle |= TCS_MULTILINE;
}
- else
- dwStyle |= WS_CLIPCHILDREN;
if (!iupwinCreateWindowEx(ih, WC_TABCONTROL, dwExStyle, dwStyle))
return IUP_ERROR;
@@ -665,7 +669,7 @@ void iupdrvTabsInitClass(Iclass* ic)
/* Driver Dependent Attribute functions */
/* Visual */
- iupClassRegisterAttribute(ic, "BGCOLOR", winTabsGetBgColorAttrib, NULL, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", winTabsGetBgColorAttrib, winTabsSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
/* Special */
iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_NOT_MAPPED);
@@ -676,5 +680,9 @@ void iupdrvTabsInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "MULTILINE", winTabsGetMultilineAttrib, winTabsSetMultilineAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TABTITLE", NULL, winTabsSetTabTitleAttrib, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, winTabsSetTabImageAttrib, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
- iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, winTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, winTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ /* necessary because transparent background does not work when not using visual styles */
+ if (!iupwin_comctl32ver6) /* Used by iupdrvImageCreateImage */
+ iupClassRegisterAttribute(ic, "FLAT_ALPHA", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
}
diff --git a/iup/src/win/iupwin_text.c b/iup/src/win/iupwin_text.c
index dfe489a..2a61724 100755
--- a/iup/src/win/iupwin_text.c
+++ b/iup/src/win/iupwin_text.c
@@ -432,8 +432,8 @@ static int winTextSetLinColToPosition(Ihandle *ih, int lin, int col)
col--;
linmax = SendMessage(ih->handle, EM_GETLINECOUNT, 0, 0L);
- if (lin > linmax)
- lin = linmax;
+ if (lin > linmax-1)
+ lin = linmax-1;
lineindex = SendMessage(ih->handle, EM_LINEINDEX, (WPARAM)lin, 0L);
@@ -639,8 +639,12 @@ static int winTextSetPaddingAttrib(Ihandle* ih, const char* value)
iupStrToIntInt(value, &(ih->data->horiz_padding), &(ih->data->vert_padding), 'x');
ih->data->vert_padding = 0;
if (ih->handle)
+ {
SendMessage(ih->handle, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELPARAM(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 */
}
static int winTextSetSelectedTextAttrib(Ihandle* ih, const char* value)
@@ -713,8 +717,11 @@ static int winTextSetNCAttrib(Ihandle* ih, const char* value)
SendMessage(ih->handle, EM_EXLIMITTEXT, 0, ih->data->nc); /* so it can be larger than 64k */
else
SendMessage(ih->handle, EM_LIMITTEXT, ih->data->nc, 0L);
+
+ return 0;
}
- return 0;
+ else
+ return 1; /* store until not mapped, when mapped will be set again */
}
static int winTextSetSelectionAttrib(Ihandle* ih, const char* value)
@@ -845,7 +852,7 @@ static char* winTextGetSelectionPosAttrib(Ihandle* ih)
static int winTextSetInsertAttrib(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)
{
@@ -867,9 +874,9 @@ static int winTextSetInsertAttrib(Ihandle* ih, const char* value)
static int winTextSetAppendAttrib(Ihandle* ih, const char* value)
{
- int len;
+ int pos;
char* str;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
if (!value) value = "";
str = (char*)value;
@@ -881,9 +888,9 @@ static int winTextSetAppendAttrib(Ihandle* ih, const char* value)
str = iupStrToDos(str);
}
- len = GetWindowTextLength(ih->handle)+1;
- SendMessage(ih->handle, EM_SETSEL, (WPARAM)len, (LPARAM)len);
- if (ih->data->is_multiline && ih->data->append_newline)
+ pos = GetWindowTextLength(ih->handle)+1;
+ SendMessage(ih->handle, EM_SETSEL, (WPARAM)pos, (LPARAM)pos);
+ if (ih->data->is_multiline && ih->data->append_newline && pos!=1)
{
if (ih->data->has_formatting)
SendMessage(ih->handle, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)"\r");
@@ -920,7 +927,7 @@ static int winTextSetTabSizeAttrib(Ihandle* ih, const char* value)
iupStrToInt(value, &tabsize);
tabsize *= 4;
SendMessage(ih->handle, EM_SETTABSTOPS, (WPARAM)1L, (LPARAM)&tabsize);
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
return 1;
}
@@ -1120,6 +1127,7 @@ static int winTextSetBgColorAttrib(Ihandle *ih, const char *value)
SendMessage(ih->handle, EM_SETBKGNDCOLOR, 0, (LPARAM)color);
}
}
+ iupdrvPostRedraw(ih);
return 1;
}
@@ -1529,15 +1537,27 @@ static int winTextProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
ret = iupwinBaseProc(ih, msg, wp, lp, result);
if (ret)
{
+ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", "1");
*result = 0;
return 1;
}
+ else
+ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
}
switch (msg)
{
case WM_CHAR:
{
+ /* even aborting WM_KEYDOWN, a WM_CHAR will be sent, so ignore it also */
+ /* if a dialog was shown, the loop will be processed, so ignore out of focus WM_CHAR messages */
+ if (GetFocus() != ih->handle || iupAttribGet(ih, "_IUPWIN_IGNORE_CHAR"))
+ {
+ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
+ *result = 0;
+ return 1;
+ }
+
if ((char)wp == '\b')
{
if (!winTextCallActionCb(ih, NULL, 0, -1))
@@ -1736,7 +1756,7 @@ static int winTextProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
static void winTextCreateSpin(Ihandle* ih)
{
HWND hSpin;
- DWORD dwStyle = WS_CHILD|UDS_ARROWKEYS|UDS_HOTTRACK|UDS_NOTHOUSANDS;
+ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS|UDS_ARROWKEYS|UDS_HOTTRACK|UDS_NOTHOUSANDS;
int serial = iupDialogGetChildId(ih);
if (iupStrEqualNoCase(iupAttribGetStr(ih, "SPINALIGN"), "LEFT"))
@@ -1826,7 +1846,7 @@ static void winTextLayoutUpdateMethod(Ihandle* ih)
static int winTextMapMethod(Ihandle* ih)
{
- DWORD dwStyle = WS_CHILD,
+ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS,
dwExStyle = 0;
char* winclass = "EDIT", *value;
@@ -1873,7 +1893,7 @@ static int winTextMapMethod(Ihandle* ih)
}
else
{
- dwStyle |= ES_AUTOHSCROLL|ES_NOHIDESEL;
+ dwStyle |= ES_AUTOHSCROLL;
if (iupAttribGetBoolean(ih, "PASSWORD"))
dwStyle |= ES_PASSWORD;
@@ -1950,8 +1970,8 @@ void iupdrvTextInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, winTextSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED);
/* Overwrite Visual */
- iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_NOT_MAPPED);
- iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, winTextSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, winTextSetVisibleAttrib, "YES", "NO", IUPAF_DEFAULT);
/* Special */
iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_NOT_MAPPED); /* usually black */
diff --git a/iup/src/win/iupwin_toggle.c b/iup/src/win/iupwin_toggle.c
index fcaa438..c17f594 100755
--- a/iup/src/win/iupwin_toggle.c
+++ b/iup/src/win/iupwin_toggle.c
@@ -35,7 +35,9 @@
void iupdrvToggleAddCheckBox(int *x, int *y)
{
- (*x) += 16+6;
+ (*x) += 16+8;
+ if (!iupwin_comctl32ver6)
+ (*x) += 4;
if ((*y) < 16) (*y) = 16; /* minimum height */
}
@@ -229,7 +231,7 @@ static int winToggleSetImageAttrib(Ihandle* ih, const char* value)
iupAttribSetStr(ih, "IMAGE", (char*)value);
if (iupwin_comctl32ver6)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
else
{
int check = SendMessage(ih->handle, BM_GETCHECK, 0L, 0L);
@@ -249,7 +251,7 @@ static int winToggleSetImInactiveAttrib(Ihandle* ih, const char* value)
iupAttribSetStr(ih, "IMINACTIVE", (char*)value);
if (iupwin_comctl32ver6)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
else
{
int check = SendMessage(ih->handle, BM_GETCHECK, 0L, 0L);
@@ -269,7 +271,7 @@ static int winToggleSetImPressAttrib(Ihandle* ih, const char* value)
iupAttribSetStr(ih, "IMPRESS", (char*)value);
if (iupwin_comctl32ver6)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
else
{
int check = SendMessage(ih->handle, BM_GETCHECK, 0L, 0L);
@@ -339,7 +341,7 @@ static int winToggleSetActiveAttrib(Ihandle* ih, const char* value)
if (iupwin_comctl32ver6)
{
iupBaseSetActiveAttrib(ih, value);
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
return 0;
}
else
@@ -382,11 +384,21 @@ static int winToggleSetPaddingAttrib(Ihandle* ih, const char* value)
iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
if (ih->handle && iupwin_comctl32ver6 && ih->data->type == IUP_TOGGLE_IMAGE)
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
return 0;
}
+static int winToggleSetUpdateAttrib(Ihandle* ih, const char* value)
+{
+ (void)value;
+
+ if (ih->handle)
+ iupdrvPostRedraw(ih); /* Post a redraw */
+
+ return 1;
+}
+
static int winToggleSetBgColorAttrib(Ihandle* ih, const char* value)
{
(void)value;
@@ -395,7 +407,7 @@ static int winToggleSetBgColorAttrib(Ihandle* ih, const char* value)
/* update internal image cache for controls that have the IMAGE attribute */
iupAttribSetStr(ih, "BGCOLOR", value);
iupImageUpdateParent(ih);
- iupdrvDisplayRedraw(ih);
+ iupdrvRedrawNow(ih);
}
return 1;
}
@@ -591,7 +603,7 @@ static int winToggleMapMethod(Ihandle* ih)
{
Ihandle* radio = iupRadioFindToggleParent(ih);
char* value;
- DWORD dwStyle = WS_CHILD |
+ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS |
BS_NOTIFY; /* necessary because of the base messages */
if (!ih->parent)
@@ -673,11 +685,11 @@ void iupdrvToggleInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "BGCOLOR", winToggleGetBgColorAttrib, winToggleSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
/* Special */
- iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, "DLGFGCOLOR", NULL, IUPAF_NOT_MAPPED); /* force the new default value */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, winToggleSetUpdateAttrib, "DLGFGCOLOR", NULL, IUPAF_NOT_MAPPED); /* force the new default value */
iupClassRegisterAttribute(ic, "TITLE", iupdrvBaseGetTitleAttrib, winToggleSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
/* IupToggle only */
- iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, NULL, IUPAF_SAMEASSYSTEM, "ACENTER:ACENTER", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, winToggleSetUpdateAttrib, IUPAF_SAMEASSYSTEM, "ACENTER:ACENTER", IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "IMAGE", NULL, winToggleSetImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "IMINACTIVE", NULL, winToggleSetImInactiveAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "IMPRESS", NULL, winToggleSetImPressAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
diff --git a/iup/src/win/iupwin_tree.c b/iup/src/win/iupwin_tree.c
index e6877dc..4a5f8be 100755
--- a/iup/src/win/iupwin_tree.c
+++ b/iup/src/win/iupwin_tree.c
@@ -31,17 +31,19 @@
#include "iupwin_draw.h"
#include "iupwin_info.h"
+
typedef struct _winTreeItemData
{
COLORREF color;
unsigned char kind;
- void* userdata;
HFONT hFont;
short image;
short image_expanded;
} winTreeItemData;
-#ifndef TVN_ITEMCHANGING /* Vista Only */
+/* Vista Only */
+
+#ifndef TVN_ITEMCHANGING
typedef struct tagNMTVITEMCHANGE {
NMHDR hdr;
UINT uChanged;
@@ -54,257 +56,125 @@ typedef struct tagNMTVITEMCHANGE {
#define TVN_ITEMCHANGINGW (TVN_FIRST-17)
#endif
-static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem);
-typedef int (*winTreeNodeFunc)(Ihandle* ih, HTREEITEM hItem, void* userdata);
-
-static int winTreeForEach(Ihandle* ih, HTREEITEM hItem, winTreeNodeFunc func, void* userdata)
-{
- HTREEITEM hItemChild;
-
- if (!hItem)
- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+#ifndef TVS_EX_DOUBLEBUFFER
+#define TVS_EX_DOUBLEBUFFER 0x0004
+#endif
- while(hItem != NULL)
- {
- if (!func(ih, hItem, userdata))
- return 0;
+#ifndef TVM_SETEXTENDEDSTYLE
+#define TVM_SETEXTENDEDSTYLE (TV_FIRST + 44)
+#endif
- hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
- if (hItemChild)
- {
- /* Recursively traverse child items */
- if (!winTreeForEach(ih, hItemChild, func, userdata))
- return 0;
- }
- /* Go to next sibling item */
- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
- }
+static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem);
- return 1;
-}
/*****************************************************************************/
/* FINDING ITEMS */
/*****************************************************************************/
-static HTREEITEM winTreeFindNodeID(Ihandle* ih, HTREEITEM hItem, HTREEITEM hNode)
-{
- TVITEM item;
- winTreeItemData* itemData;
-
- while(hItem != NULL)
- {
- /* ID control to traverse items */
- ih->data->id_control++;
-
- /* StateID founded! */
- if(hItem == hNode)
- return hItem;
- /* Get hItem attributes */
- item.hItem = hItem;
- item.mask = TVIF_HANDLE|TVIF_PARAM;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- itemData = (winTreeItemData*)item.lParam;
-
- /* Check whether we have child items */
- if (itemData->kind == ITREE_BRANCH)
- {
- /* Recursively traverse child items */
- HTREEITEM hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
- hItemChild = winTreeFindNodeID(ih, hItemChild, hNode);
-
- /* StateID founded! */
- if(hItemChild)
- return hItemChild;
- }
- /* Go to next sibling item */
- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
- }
-
- return NULL;
+InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih)
+{
+ return (InodeHandle*)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CARET, 0);
}
-static int winTreeGetNodeId(Ihandle* ih, HTREEITEM hItem)
+static HTREEITEM winTreeFindNodeXY(Ihandle* ih, int x, int y)
{
- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
- ih->data->id_control = -1;
- if (winTreeFindNodeID(ih, hItemRoot, hItem))
- return ih->data->id_control;
- else
- return -1;
+ TVHITTESTINFO info;
+ info.pt.x = x;
+ info.pt.y = y;
+ return (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)(LPTVHITTESTINFO)&info);
}
-static HTREEITEM winTreeFindUserDataID(Ihandle* ih, HTREEITEM hItem, void* userdata)
+static HTREEITEM winTreeFindNodePointed(Ihandle* ih)
{
- TVITEM item;
- winTreeItemData* itemData;
-
- while(hItem != NULL)
- {
- /* ID control to traverse items */
- ih->data->id_control++;
-
- /* Get hItem attributes */
- item.hItem = hItem;
- item.mask = TVIF_HANDLE|TVIF_PARAM;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- itemData = (winTreeItemData*)item.lParam;
-
- /* userdata founded! */
- if(itemData->userdata == userdata)
- return hItem;
-
- /* Check whether we have child items */
- if (itemData->kind == ITREE_BRANCH)
- {
- /* Recursively traverse child items */
- HTREEITEM hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
- hItemChild = winTreeFindUserDataID(ih, hItemChild, userdata);
-
- /* userdata founded! */
- if (hItemChild)
- return hItemChild;
- }
-
- /* Go to next sibling item */
- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
- }
-
- return NULL;
+ TVHITTESTINFO info;
+ DWORD pos = GetMessagePos();
+ info.pt.x = LOWORD(pos);
+ info.pt.y = HIWORD(pos);
+ ScreenToClient(ih->handle, &info.pt);
+ return (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)(LPTVHITTESTINFO)&info);
}
-static int winTreeGetUserDataId(Ihandle* ih, void* userdata)
+int iupwinGetColor(const char* value, COLORREF *color)
{
- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
- ih->data->id_control = -1;
- if (winTreeFindUserDataID(ih, hItemRoot, userdata))
- return ih->data->id_control;
- else
- return -1;
+ unsigned char r, g, b;
+ if (iupStrToRGB(value, &r, &g, &b))
+ {
+ *color = RGB(r,g,b);
+ return 1;
+ }
+ return 0;
}
-static HTREEITEM winTreeFindNodeFromID(Ihandle* ih, HTREEITEM hItem)
+static void winTreeChildCountRec(Ihandle* ih, HTREEITEM hItem, int *count)
{
- TVITEM item;
- winTreeItemData* itemData;
-
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
while(hItem != NULL)
{
- /* ID control to traverse items */
- ih->data->id_control--;
-
- /* StateID founded! */
- if(ih->data->id_control < 0)
- return hItem;
-
- /* Get hItem attributes */
- item.hItem = hItem;
- item.mask = TVIF_HANDLE|TVIF_PARAM;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- itemData = (winTreeItemData*)item.lParam;
-
- /* Check whether we have child items */
- if (itemData->kind == ITREE_BRANCH)
- {
- /* Recursively traverse child items */
- HTREEITEM hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
- hItemChild = winTreeFindNodeFromID(ih, hItemChild);
+ (*count)++;
- /* StateID founded! */
- if(ih->data->id_control < 0)
- return hItemChild;
- }
+ /* go recursive to children */
+ winTreeChildCountRec(ih, hItem, count);
/* Go to next sibling item */
hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
}
-
- return hItem;
}
-static HTREEITEM winTreeFindNodeFromString(Ihandle* ih, const char* name_id)
+int iupdrvTreeTotalChildCount(Ihandle* ih, HTREEITEM hItem)
{
- if (name_id[0])
- {
- HTREEITEM hRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
- iupStrToInt(name_id, &ih->data->id_control);
- return winTreeFindNodeFromID(ih, hRoot);
- }
- else
- return (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CARET, 0);
+ int count = 0;
+ winTreeChildCountRec(ih, hItem, &count);
+ return count;
}
-/* Recursively, find a new brother for the item
- that will have its depth changed. Returns the new brother. */
-static HTREEITEM winTreeFindNewBrother(Ihandle* ih, HTREEITEM hBrotherItem)
+static void winTreeChildRebuildCacheRec(Ihandle* ih, HTREEITEM hItem, int *id)
{
- TVITEM item;
- winTreeItemData* itemData;
-
- while(hBrotherItem != NULL)
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+ while(hItem != NULL)
{
- if(ih->data->id_control < 0)
- return hBrotherItem;
-
- item.hItem = hBrotherItem;
- item.mask = TVIF_HANDLE|TVIF_PARAM;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- itemData = (winTreeItemData*)item.lParam;
-
- if (itemData->kind == ITREE_BRANCH)
- {
- HTREEITEM hItemChild;
-
- ih->data->id_control--;
- hItemChild = winTreeFindNewBrother(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hBrotherItem));
+ (*id)++;
+ ih->data->node_cache[*id].node_handle = hItem;
- if(ih->data->id_control < 0)
- return hItemChild;
- }
+ /* go recursive to children */
+ winTreeChildRebuildCacheRec(ih, hItem, id);
- hBrotherItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hBrotherItem);
+ /* Go to next sibling item */
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
}
-
- return hBrotherItem;
}
-static HTREEITEM winTreeFindNodePointed(Ihandle* ih)
+static void winTreeRebuildNodeCache(Ihandle* ih, int id, HTREEITEM hItem)
{
- TVHITTESTINFO info;
- DWORD pos = GetMessagePos();
- info.pt.x = LOWORD(pos);
- info.pt.y = HIWORD(pos);
-
- ScreenToClient(ih->handle, &info.pt);
-
- return (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)(LPTVHITTESTINFO)&info);
+ ih->data->node_cache[id].node_handle = hItem;
+ winTreeChildRebuildCacheRec(ih, hItem, &id);
}
-int iupwinGetColor(const char* value, COLORREF *color)
-{
- unsigned char r, g, b;
- if (iupStrToRGB(value, &r, &g, &b))
- {
- *color = RGB(r,g,b);
- return 1;
- }
- return 0;
-}
/*****************************************************************************/
/* ADDING ITEMS */
/*****************************************************************************/
+
+static void winTreeExpandItem(Ihandle* ih, HTREEITEM hItem, int expand);
+
void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* title, int add)
{
- TVITEM item, tviPrevItem;
+ TVITEM item;
TVINSERTSTRUCT tvins;
- HTREEITEM hPrevItem = winTreeFindNodeFromString(ih, name_id);
- int kindPrev;
+ HTREEITEM hPrevItem = iupTreeGetNodeFromString(ih, name_id);
+ HTREEITEM hItemNew;
winTreeItemData* itemData;
if (!hPrevItem)
- return;
+ {
+ /* check if the root was really specified */
+ int id = 0;
+ if (!iupStrToInt(name_id, &id) || id != -1)
+ return;
+ }
+
+ if (!title)
+ title = "";
itemData = calloc(1, sizeof(winTreeItemData));
itemData->image = -1;
@@ -318,83 +188,71 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
iupwinGetColor(iupAttribGetStr(ih, "FGCOLOR"), &itemData->color);
if (kind == ITREE_BRANCH)
- {
item.iSelectedImage = item.iImage = (int)ih->data->def_image_collapsed;
-
- if (ih->data->add_expanded)
- {
- item.mask |= TVIF_STATE;
- item.state = item.stateMask = TVIS_EXPANDED;
- item.iSelectedImage = item.iImage = (int)ih->data->def_image_expanded;
- }
- }
else
item.iSelectedImage = item.iImage = (int)ih->data->def_image_leaf;
/* Save the heading level in the node's application-defined data area */
tvins.item = item;
- /* get the KIND attribute of node selected */
- tviPrevItem.hItem = hPrevItem;
- tviPrevItem.mask = TVIF_PARAM|TVIF_CHILDREN;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&tviPrevItem);
- kindPrev = ((winTreeItemData*)tviPrevItem.lParam)->kind;
-
- /* Define the parent and the position to the new node inside
- the list, using the KIND attribute of node selected */
- if (kindPrev == ITREE_BRANCH && add)
- {
- tvins.hParent = hPrevItem;
- tvins.hInsertAfter = TVI_FIRST; /* insert the new node after item selected, as first child */
- }
- else
- {
- tvins.hParent = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hPrevItem);
- tvins.hInsertAfter = hPrevItem; /* insert the new node after item selected */
- }
-
- /* Add the node to the tree-view control */
- SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
-
- if (kindPrev == ITREE_BRANCH && tviPrevItem.cChildren==0)
+ if (hPrevItem)
{
- /* this is the first child, redraw to update the '+'/'-' buttons */
- iupdrvDisplayRedraw(ih);
- }
-}
+ int kindPrev;
+ TVITEM tviPrevItem;
-static void winTreeAddRootNode(Ihandle* ih)
-{
- TVITEM item;
- TVINSERTSTRUCT tvins;
- HTREEITEM hNewItem;
- winTreeItemData* itemData;
+ /* get the KIND attribute of reference node */
+ tviPrevItem.hItem = hPrevItem;
+ tviPrevItem.mask = TVIF_PARAM|TVIF_CHILDREN;
+ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&tviPrevItem);
+ kindPrev = ((winTreeItemData*)tviPrevItem.lParam)->kind;
- itemData = calloc(1, sizeof(winTreeItemData));
- itemData->image = -1;
- itemData->image_expanded = -1;
- itemData->kind = ITREE_BRANCH;
+ /* Define the parent and the position to the new node inside
+ the list, using the KIND attribute of reference node */
+ if (kindPrev == ITREE_BRANCH && add)
+ {
+ /* depth+1 */
+ tvins.hParent = hPrevItem;
+ tvins.hInsertAfter = TVI_FIRST; /* insert the new node after the reference node, as first child */
+ }
+ else
+ {
+ /* same depth */
+ tvins.hParent = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hPrevItem);
+ tvins.hInsertAfter = hPrevItem; /* insert the new node after reference node */
+ }
- item.mask = TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
- item.state = item.stateMask = TVIS_EXPANDED;
- item.iSelectedImage = item.iImage = (int)ih->data->def_image_expanded;
- item.lParam = (LPARAM)itemData;
+ /* Add the new node */
+ hItemNew = (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
+ iupTreeAddToCache(ih, add, kindPrev, hPrevItem, hItemNew);
- iupwinGetColor(iupAttribGetStr(ih, "FGCOLOR"), &itemData->color);
+ if (kindPrev == ITREE_BRANCH && tviPrevItem.cChildren==0) /* was 0, now is 1 */
+ {
+ /* this is the first child, redraw to update the '+'/'-' buttons */
+ if (ih->data->add_expanded)
+ winTreeExpandItem(ih, hPrevItem, 1);
+ else
+ winTreeExpandItem(ih, hPrevItem, 0);
+ }
- /* Save the heading level in the node's application-defined data area */
- tvins.item = item;
- tvins.hInsertAfter = TVI_FIRST;
- tvins.hParent = TVI_ROOT;
+ }
+ else
+ {
+ tvins.hInsertAfter = TVI_FIRST;
+ tvins.hParent = TVI_ROOT;
- /* Add the node to the tree-view control */
- hNewItem = (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
+ /* Add the new node */
+ hItemNew = (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
+ iupTreeAddToCache(ih, 0, 0, NULL, hItemNew);
- /* MarkStart node */
- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)hNewItem);
+ if (ih->data->node_count == 1)
+ {
+ /* MarkStart node */
+ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)hItemNew);
- /* Set the default VALUE */
- winTreeSetFocusNode(ih, hNewItem);
+ /* Set the default VALUE */
+ winTreeSetFocusNode(ih, hItemNew);
+ }
+ }
}
static int winTreeIsItemExpanded(Ihandle* ih, HTREEITEM hItem)
@@ -408,13 +266,28 @@ static int winTreeIsItemExpanded(Ihandle* ih, HTREEITEM hItem)
static void winTreeExpandItem(Ihandle* ih, HTREEITEM hItem, int expand)
{
- if (expand == -1)
- expand = !winTreeIsItemExpanded(ih, hItem); /* toggle */
+ TVITEM item;
+ winTreeItemData* itemData;
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
+ /* it only works if the branch has children */
+ SendMessage(ih->handle, TVM_EXPAND, expand? TVE_EXPAND: TVE_COLLAPSE, (LPARAM)hItem);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL);
+
+ /* update image */
+ item.hItem = hItem;
+ item.mask = TVIF_HANDLE|TVIF_PARAM;
+ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ itemData = (winTreeItemData*)item.lParam;
if (expand)
- SendMessage(ih->handle, TVM_EXPAND, TVE_EXPAND, (LPARAM)hItem);
+ item.iSelectedImage = item.iImage = (itemData->image_expanded!=-1)? itemData->image_expanded: (int)ih->data->def_image_expanded;
else
- SendMessage(ih->handle, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hItem);
+ item.iSelectedImage = item.iImage = (itemData->image!=-1)? itemData->image: (int)ih->data->def_image_collapsed;
+
+ item.hItem = hItem;
+ item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
}
/*****************************************************************************/
@@ -445,12 +318,12 @@ static void winTreeExpandTree(Ihandle* ih, HTREEITEM hItem, int expand)
/* SELECTING ITEMS */
/*****************************************************************************/
-static int winTreeIsItemSelected(Ihandle* ih, HTREEITEM hItem)
+static int winTreeIsNodeSelected(Ihandle* ih, HTREEITEM hItem)
{
return ((SendMessage(ih->handle, TVM_GETITEMSTATE, (WPARAM)hItem, TVIS_SELECTED)) & TVIS_SELECTED)!=0;
}
-static void winTreeSelectItem(Ihandle* ih, HTREEITEM hItem, int select)
+static void winTreeSelectNode(Ihandle* ih, HTREEITEM hItem, int select)
{
TV_ITEM item;
item.mask = TVIF_STATE | TVIF_HANDLE;
@@ -458,16 +331,13 @@ static void winTreeSelectItem(Ihandle* ih, HTREEITEM hItem, int select)
item.hItem = hItem;
if (select == -1)
- select = !winTreeIsItemSelected(ih, hItem);
+ select = !winTreeIsNodeSelected(ih, hItem); /* toggle */
item.state = select ? TVIS_SELECTED : 0;
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)&item);
-}
-
-static HTREEITEM winTreeGetFocusNode(Ihandle* ih)
-{
- return (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CARET, 0);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
}
/* ------------Comment from wxWidgets--------------------
@@ -475,17 +345,17 @@ static HTREEITEM winTreeGetFocusNode(Ihandle* ih)
item without changing anything else. */
static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem)
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
if (hItem != hItemFocus)
{
/* remember the selection state of the item */
- int wasSelected = winTreeIsItemSelected(ih, hItem);
+ int wasSelected = winTreeIsNodeSelected(ih, hItem);
int wasFocusSelected = 0;
- if (iupwinIsVista())
+ if (iupwinIsVistaOrNew() && iupwin_comctl32ver6)
iupAttribSetStr(ih, "_IUPTREE_ALLOW_CHANGE", (char*)hItem); /* Vista Only */
else
- wasFocusSelected = hItemFocus && winTreeIsItemSelected(ih, hItemFocus);
+ wasFocusSelected = hItemFocus && winTreeIsNodeSelected(ih, hItemFocus);
iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
@@ -493,58 +363,42 @@ static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem)
{
/* prevent the tree from unselecting the old focus which it would do by default */
SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)NULL); /* remove the focus */
- winTreeSelectItem(ih, hItemFocus, 1); /* select again */
+ winTreeSelectNode(ih, hItemFocus, 1); /* select again */
}
SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem); /* set focus, selection, and unselect the previous focus */
if (!wasSelected)
- winTreeSelectItem(ih, hItem, 0); /* need to clear the selection if was not selected */
+ winTreeSelectNode(ih, hItem, 0); /* need to clear the selection if was not selected */
iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
iupAttribSetStr(ih, "_IUPTREE_ALLOW_CHANGE", NULL);
}
}
-typedef struct _winTreeRange{
- HTREEITEM hItem1, hItem2;
- char inside, clear;
-}winTreeRange;
-
-static int winTreeSelectRangeFunc(Ihandle* ih, HTREEITEM hItem, winTreeRange* range)
+static void winTreeSelectRange(Ihandle* ih, HTREEITEM hItem1, HTREEITEM hItem2, int clear)
{
- int end_range = 0;
-
- if (range->inside == 0) /* detect the range start */
+ int i;
+ int id1 = iupTreeFindNodeId(ih, hItem1);
+ int id2 = iupTreeFindNodeId(ih, hItem2);
+ if (id2 == -1) id2 = ih->data->node_count-1;
+ if (id1 > id2)
{
- if (range->hItem1 == hItem) range->inside=1;
- else if (range->hItem2 == hItem) range->inside=1;
+ int tmp = id1;
+ id1 = id2;
+ id2 = tmp;
}
- else if (range->inside == 1) /* detect the range end */
+
+ for (i = 0; i < ih->data->node_count; i++)
{
- if (range->hItem1 == hItem) end_range=1;
- else if (range->hItem2 == hItem) end_range=1;
+ if (i < id1 || i > id2)
+ {
+ if (clear)
+ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 0);
+ }
+ else
+ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 1);
}
-
- if (range->inside == 1) /* if inside, select */
- winTreeSelectItem(ih, hItem, 1);
- else if (range->clear) /* if outside and clear, unselect */
- winTreeSelectItem(ih, hItem, 0);
-
- if (end_range || (range->inside && range->hItem1==range->hItem2))
- range->inside=-1; /* update after selecting the node */
-
- return 1;
-}
-
-static void winTreeSelectRange(Ihandle* ih, HTREEITEM hItemFrom, HTREEITEM hItemTo, int clear)
-{
- winTreeRange range;
- range.hItem1 = hItemFrom;
- range.hItem2 = hItemTo;
- range.inside = 0;
- range.clear = (char)clear;
- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeSelectRangeFunc, &range);
}
static void winTreeSelectAll(Ihandle* ih)
@@ -558,9 +412,10 @@ static void winTreeClearSelection(Ihandle* ih, HTREEITEM hItemExcept)
winTreeSelectRange(ih, hItemExcept, hItemExcept, 1);
}
-static int winTreeInvertSelectFunc(Ihandle* ih, HTREEITEM hItem, void* userdata)
+static int winTreeInvertSelectFunc(Ihandle* ih, HTREEITEM hItem, int id, void* userdata)
{
- winTreeSelectItem(ih, hItem, -1);
+ (void)id;
+ winTreeSelectNode(ih, hItem, -1);
(void)userdata;
return 1;
}
@@ -568,14 +423,11 @@ static int winTreeInvertSelectFunc(Ihandle* ih, HTREEITEM hItem, void* userdata)
typedef struct _winTreeSelArray{
Iarray* markedArray;
char is_handle;
- int id_control;
}winTreeSelArray;
-static int winTreeSelectedArrayFunc(Ihandle* ih, HTREEITEM hItem, winTreeSelArray* selarray)
+static int winTreeSelectedArrayFunc(Ihandle* ih, HTREEITEM hItem, int id, winTreeSelArray* selarray)
{
- selarray->id_control++;
-
- if (winTreeIsItemSelected(ih, hItem))
+ if (winTreeIsNodeSelected(ih, hItem))
{
if (selarray->is_handle)
{
@@ -587,7 +439,7 @@ static int winTreeSelectedArrayFunc(Ihandle* ih, HTREEITEM hItem, winTreeSelArra
{
int* intArrayData = (int*)iupArrayInc(selarray->markedArray);
int i = iupArrayCount(selarray->markedArray);
- intArrayData[i-1] = selarray->id_control;
+ intArrayData[i-1] = id;
}
}
@@ -599,10 +451,9 @@ static Iarray* winTreeGetSelectedArray(Ihandle* ih)
Iarray* markedArray = iupArrayCreate(1, sizeof(HTREEITEM));
winTreeSelArray selarray;
selarray.markedArray = markedArray;
- selarray.id_control = -1;
selarray.is_handle = 1;
- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
+ iupTreeForEach(ih, (iupTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
return markedArray;
}
@@ -612,10 +463,9 @@ static Iarray* winTreeGetSelectedArrayId(Ihandle* ih)
Iarray* markedArray = iupArrayCreate(1, sizeof(int));
winTreeSelArray selarray;
selarray.markedArray = markedArray;
- selarray.id_control = -1;
selarray.is_handle = 0;
- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
+ iupTreeForEach(ih, (iupTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
return markedArray;
}
@@ -625,7 +475,7 @@ static Iarray* winTreeGetSelectedArrayId(Ihandle* ih)
/* COPYING ITEMS (Branches and its children) */
/*****************************************************************************/
/* Insert the copied item in a new location. Returns the new item. */
-static HTREEITEM winTreeCopyItem(Ihandle* ih, HTREEITEM hItem, HTREEITEM hParent, HTREEITEM hPosition, int full_copy)
+static HTREEITEM winTreeCopyItem(Ihandle* ih, HTREEITEM hItem, HTREEITEM hParent, HTREEITEM hPosition, int is_copy)
{
TVITEM item;
TVINSERTSTRUCT tvins;
@@ -637,34 +487,34 @@ static HTREEITEM winTreeCopyItem(Ihandle* ih, HTREEITEM hItem, HTREEITEM hParent
item.cchTextMax = 255;
SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- if (full_copy) /* during a full copy the userdata reference is not copied */
+ if (is_copy) /* during a copy the itemdata reference is not reused */
{
/* create a new one */
winTreeItemData* itemDataNew = malloc(sizeof(winTreeItemData));
memcpy(itemDataNew, (void*)item.lParam, sizeof(winTreeItemData));
- itemDataNew->userdata = NULL;
item.lParam = (LPARAM)itemDataNew;
}
- /* Copy everything including user data reference */
+ /* Copy everything including itemdata reference */
tvins.item = item;
tvins.hInsertAfter = hPosition;
tvins.hParent = hParent;
- /* Add the node to the tree-view control */
+ /* Add the new node */
+ ih->data->node_count++;
return (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
}
-static void winTreeCopyChildren(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int full_copy)
+static void winTreeCopyChildren(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int is_copy)
{
HTREEITEM hChildSrc = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItemSrc);
- HTREEITEM hNewItem = TVI_FIRST;
+ HTREEITEM hItemNew = TVI_FIRST;
while (hChildSrc != NULL)
{
- hNewItem = winTreeCopyItem(ih, hChildSrc, hItemDst, hNewItem, full_copy); /* Use the same order they where enumerated */
+ hItemNew = winTreeCopyItem(ih, hChildSrc, hItemDst, hItemNew, is_copy); /* Use the same order they where enumerated */
/* Recursively transfer all the items */
- winTreeCopyChildren(ih, hChildSrc, hNewItem, full_copy);
+ winTreeCopyChildren(ih, hChildSrc, hItemNew, is_copy);
/* Go to next sibling item */
hChildSrc = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hChildSrc);
@@ -672,11 +522,18 @@ static void winTreeCopyChildren(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItem
}
/* Copies all items in a branch to a new location. Returns the new branch node. */
-static HTREEITEM winTreeCopyNode(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int full_copy)
+static HTREEITEM winTreeCopyMoveNode(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int is_copy)
{
- HTREEITEM hNewItem, hParent;
+ HTREEITEM hItemNew, hParent;
TVITEM item;
winTreeItemData* itemDataDst;
+ int id_new, count, id_src, id_dst;
+
+ int old_count = ih->data->node_count;
+
+ id_src = iupTreeFindNodeId(ih, hItemSrc);
+ id_dst = iupTreeFindNodeId(ih, hItemDst);
+ id_new = id_dst+1; /* contains the position for a copy operation */
/* Get DST node attributes */
item.hItem = hItemDst;
@@ -691,31 +548,64 @@ static HTREEITEM winTreeCopyNode(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hIte
hItemDst = TVI_FIRST;
}
else
- {
+ {
+ if (itemDataDst->kind == ITREE_BRANCH)
+ {
+ int child_count = iupdrvTreeTotalChildCount(ih, hItemDst);
+ id_new += child_count;
+ }
+
/* copy as next brother of item or collapsed branch */
hParent = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItemDst);
}
- hNewItem = winTreeCopyItem(ih, hItemSrc, hParent, hItemDst, full_copy);
+ /* move to the same place does nothing */
+ if (!is_copy && id_new == id_src)
+ return NULL;
+
+ hItemNew = winTreeCopyItem(ih, hItemSrc, hParent, hItemDst, is_copy);
+
+ winTreeCopyChildren(ih, hItemSrc, hItemNew, is_copy);
+
+ count = ih->data->node_count - old_count;
+ iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy);
+
+ if (!is_copy)
+ {
+ /* Deleting the node (and its children) from the old position */
+ /* do not delete the itemdata, we reuse the references in CopyNode */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemSrc);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
- winTreeCopyChildren(ih, hItemSrc, hNewItem, full_copy);
+ /* restore count, because we remove src */
+ ih->data->node_count = old_count;
- return hNewItem;
+ /* compensate position for a move */
+ if (id_new > id_src)
+ id_new -= count;
+ }
+
+ winTreeRebuildNodeCache(ih, id_new, hItemNew);
+
+ return hItemNew;
}
/*****************************************************************************/
/* MANIPULATING IMAGES */
/*****************************************************************************/
-static void winTreeUpdateImages(Ihandle* ih, HTREEITEM hItem, int mode)
+static void winTreeUpdateImages(Ihandle* ih, int mode)
{
- HTREEITEM hItemChild;
+ HTREEITEM hItem;
TVITEM item;
winTreeItemData* itemData;
+ int i;
/* called when one of the default images is changed */
-
- while(hItem != NULL)
+ for (i = 0; i < ih->data->node_count; i++)
{
+ hItem = ih->data->node_cache[i].node_handle;
+
/* Get node attributes */
item.hItem = hItem;
item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
@@ -742,10 +632,6 @@ static void winTreeUpdateImages(Ihandle* ih, HTREEITEM hItem, int mode)
SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
}
}
-
- /* Recursively traverse child items */
- hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
- winTreeUpdateImages(ih, hItemChild, mode);
}
else
{
@@ -756,9 +642,6 @@ static void winTreeUpdateImages(Ihandle* ih, HTREEITEM hItem, int mode)
SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
}
}
-
- /* Go to next sibling node */
- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
}
}
@@ -828,29 +711,57 @@ static int winTreeCallBranchLeafCb(Ihandle* ih, HTREEITEM hItem)
if (itemData->kind == ITREE_BRANCH)
{
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB"))
+ return IUP_DEFAULT;
+
if (item.state & TVIS_EXPANDED)
{
IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
if (cbBranchClose)
- return cbBranchClose(ih, winTreeGetNodeId(ih, hItem));
+ return cbBranchClose(ih, iupTreeFindNodeId(ih, hItem));
}
else
{
IFni cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
if (cbBranchOpen)
- return cbBranchOpen(ih, winTreeGetNodeId(ih, hItem));
+ return cbBranchOpen(ih, iupTreeFindNodeId(ih, hItem));
}
}
else
{
IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
if (cbExecuteLeaf)
- return cbExecuteLeaf(ih, winTreeGetNodeId(ih, hItem));
+ return cbExecuteLeaf(ih, iupTreeFindNodeId(ih, hItem));
}
return IUP_DEFAULT;
}
+static void winTreeCallMultiUnSelectionCb(Ihandle* ih)
+{
+ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB");
+ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ if (cbSelec || cbMulti)
+ {
+ Iarray* markedArray = winTreeGetSelectedArrayId(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 void winTreeCallMultiSelectionCb(Ihandle* ih)
{
IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTISELECTION_CB");
@@ -885,6 +796,8 @@ static void winTreeCallSelectionCb(Ihandle* ih, int status, HTREEITEM hItem)
IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
if (cbSelec)
{
+ int id;
+
if (ih->data->mark_mode == ITREE_MARK_MULTIPLE && IupGetCallback(ih,"MULTISELECTION_CB"))
{
if ((GetKeyState(VK_SHIFT) & 0x8000))
@@ -894,7 +807,9 @@ static void winTreeCallSelectionCb(Ihandle* ih, int status, HTREEITEM hItem)
if (iupAttribGet(ih, "_IUPTREE_IGNORE_SELECTION_CB"))
return;
- cbSelec(ih, winTreeGetNodeId(ih, hItem), status);
+ id = iupTreeFindNodeId(ih, hItem);
+ if (id != -1)
+ cbSelec(ih, id, status);
}
}
@@ -911,8 +826,8 @@ static int winTreeCallDragDropCb(Ihandle* ih, HTREEITEM hItemDrag, HTREEITEM hIt
if (cbDragDrop)
{
- int drag_id = winTreeGetNodeId(ih, hItemDrag);
- int drop_id = winTreeGetNodeId(ih, hItemDrop);
+ int drag_id = iupTreeFindNodeId(ih, hItemDrag);
+ int drop_id = iupTreeFindNodeId(ih, hItemDrop);
return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
}
@@ -929,8 +844,8 @@ static int winTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
{
ih->data->def_image_expanded = (void*)winTreeGetImageIndex(ih, value);
- /* Update all images, starting at root node */
- winTreeUpdateImages(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0), ITREE_UPDATEIMAGE_EXPANDED);
+ /* Update all images */
+ winTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED);
return 1;
}
@@ -939,8 +854,8 @@ static int winTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
{
ih->data->def_image_collapsed = (void*)winTreeGetImageIndex(ih, value);
- /* Update all images, starting at root node */
- winTreeUpdateImages(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0), ITREE_UPDATEIMAGE_COLLAPSED);
+ /* Update all images */
+ winTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED);
return 1;
}
@@ -949,8 +864,8 @@ static int winTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
{
ih->data->def_image_leaf = (void*)winTreeGetImageIndex(ih, value);
- /* Update all images, starting at root node */
- winTreeUpdateImages(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0), ITREE_UPDATEIMAGE_LEAF);
+ /* Update all images */
+ winTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF);
return 1;
}
@@ -959,7 +874,7 @@ static int winTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const
{
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
@@ -986,7 +901,7 @@ static int winTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
{
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
@@ -1025,7 +940,7 @@ static int winTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
static int winTreeSetTopItemAttrib(Ihandle* ih, const char* value)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, value);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, value);
if (hItem)
SendMessage(ih->handle, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem);
return 0;
@@ -1056,9 +971,8 @@ static int winTreeSetSpacingAttrib(Ihandle* ih, const char* value)
static int winTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
{
HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
- HTREEITEM hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItemRoot); /* skip the root node that is always expanded */
int expand = iupStrBoolean(value);
- winTreeExpandTree(ih, hItem, expand);
+ winTreeExpandTree(ih, hItemRoot, expand);
return 0;
}
@@ -1131,7 +1045,7 @@ static char* winTreeGetTitle(Ihandle* ih, HTREEITEM hItem)
static char* winTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
return winTreeGetTitle(ih, hItem);
@@ -1140,10 +1054,13 @@ static char* winTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
static int winTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* value)
{
TVITEM item;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
+ if (!value)
+ value = "";
+
item.hItem = hItem;
item.mask = TVIF_HANDLE | TVIF_TEXT;
item.pszText = (char*)value;
@@ -1151,60 +1068,11 @@ static int winTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v
return 0;
}
-static char* winTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
-{
- int id;
- char* str = (char*)(name_id+1); /* skip ':' */
- void* userdata = NULL;
- if (sscanf(str, "%p", &userdata)!=1)
- return NULL;
- id = winTreeGetUserDataId(ih, userdata);
- if (id == -1)
- return NULL;
- str = iupStrGetMemory(16);
- sprintf(str, "%d", id);
- return str;
-}
-
-static char* winTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
-{
- TVITEM item;
- winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
- if (!hItem)
- return NULL;
-
- item.hItem = hItem;
- item.mask = TVIF_HANDLE | TVIF_PARAM;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- itemData = (winTreeItemData*)item.lParam;
-
- return itemData->userdata;
-}
-
-static int winTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
-{
- TVITEM item;
- winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
- if (!hItem)
- return 0;
-
- item.hItem = hItem;
- item.mask = TVIF_HANDLE | TVIF_PARAM;
- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
- itemData = (winTreeItemData*)item.lParam;
-
- itemData->userdata = (void*)value;
-
- return 0;
-}
-
static char* winTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
{
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
@@ -1220,7 +1088,7 @@ static int winTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
{
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
@@ -1230,11 +1098,23 @@ static int winTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
itemData = (winTreeItemData*)item.lParam;
if (value)
+ {
itemData->hFont = iupwinGetHFont(value);
+ if (itemData->hFont)
+ {
+ TV_ITEM item;
+ item.mask = TVIF_STATE | TVIF_HANDLE | TVIF_TEXT;
+ item.stateMask = TVIS_BOLD;
+ item.hItem = hItem;
+ item.pszText = winTreeGetTitle(ih, hItem); /* reset text to resize item */
+ item.state = (strstr(value, "Bold")||strstr(value, "BOLD"))? TVIS_BOLD: 0;
+ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)&item);
+ }
+ }
else
itemData->hFont = NULL;
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
return 0;
}
@@ -1259,7 +1139,7 @@ static char* winTreeGetStateAttrib(Ihandle* ih, const char* name_id)
{
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
@@ -1281,25 +1161,34 @@ static char* winTreeGetStateAttrib(Ihandle* ih, const char* name_id)
static int winTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* value)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ TVITEM item;
+ winTreeItemData* itemData;
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
- winTreeExpandItem(ih, hItem, iupStrEqualNoCase(value, "EXPANDED"));
+ /* Get Children: branch or leaf */
+ item.mask = TVIF_HANDLE|TVIF_PARAM;
+ item.hItem = hItem;
+ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ itemData = (winTreeItemData*)item.lParam;
+
+ if (itemData->kind == ITREE_BRANCH)
+ winTreeExpandItem(ih, hItem, iupStrEqualNoCase(value, "EXPANDED"));
+
return 0;
}
static char* winTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
- int depth = 0;
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ int depth = -1;
char* str;
- if (!hItem)
+ if (!hItem)
return NULL;
- while((hItemRoot != hItem) && (hItem != NULL))
+ while(hItem != NULL)
{
hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
depth++;
@@ -1314,12 +1203,13 @@ static int winTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
{
HTREEITEM hItemDst, hParent, hItemSrc;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
- hItemSrc = winTreeFindNodeFromString(ih, name_id);
+
+ hItemSrc = iupTreeGetNodeFromString(ih, name_id);
if (!hItemSrc)
return 0;
- hItemDst = winTreeFindNodeFromString(ih, value);
+ hItemDst = iupTreeGetNodeFromString(ih, value);
if (!hItemDst)
return 0;
@@ -1332,11 +1222,8 @@ static int winTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
return 0;
}
- /* Copying the node and its children to the new position */
- winTreeCopyNode(ih, hItemSrc, hItemDst, 0); /* not a full copy, preserve user data */
-
- /* do not delete the user data, we copy the references in CopyNode */
- SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemSrc);
+ /* Move the node and its children to the new position */
+ winTreeCopyMoveNode(ih, hItemSrc, hItemDst, 0);
return 0;
}
@@ -1345,12 +1232,13 @@ static int winTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
{
HTREEITEM hItemDst, hParent, hItemSrc;
- if (!ih->handle) /* do not store the action before map */
+ if (!ih->handle) /* do not do the action before map */
return 0;
- hItemSrc = winTreeFindNodeFromString(ih, name_id);
+
+ hItemSrc = iupTreeGetNodeFromString(ih, name_id);
if (!hItemSrc)
return 0;
- hItemDst = winTreeFindNodeFromString(ih, value);
+ hItemDst = iupTreeGetNodeFromString(ih, value);
if (!hItemDst)
return 0;
@@ -1363,8 +1251,8 @@ static int winTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
return 0;
}
- /* Copying the node and its children to the new position */
- winTreeCopyNode(ih, hItemSrc, hItemDst, 1);
+ /* Copy the node and its children to the new position */
+ winTreeCopyMoveNode(ih, hItemSrc, hItemDst, 1);
return 0;
}
@@ -1375,7 +1263,7 @@ static char* winTreeGetColorAttrib(Ihandle* ih, const char* name_id)
char* str;
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
@@ -1398,7 +1286,7 @@ static int winTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
unsigned char r, g, b;
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
@@ -1410,7 +1298,7 @@ static int winTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
if (iupStrToRGB(value, &r, &g, &b))
{
itemData->color = RGB(r,g,b);
- iupdrvDisplayUpdate(ih);
+ iupdrvPostRedraw(ih);
}
return 0;
@@ -1435,7 +1323,7 @@ static char* winTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
{
int count;
char* str;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
@@ -1454,18 +1342,11 @@ static char* winTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
return str;
}
-static char* winTreeGetCountAttrib(Ihandle* ih)
-{
- char* str = iupStrGetMemory(10);
- sprintf(str, "%d", (int)SendMessage(ih->handle, TVM_GETCOUNT, 0, 0));
- return str;
-}
-
static char* winTreeGetKindAttrib(Ihandle* ih, const char* name_id)
{
TVITEM item;
winTreeItemData* itemData;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
@@ -1483,7 +1364,7 @@ static char* winTreeGetKindAttrib(Ihandle* ih, const char* name_id)
static char* winTreeGetParentAttrib(Ihandle* ih, const char* name_id)
{
char* str;
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
@@ -1492,15 +1373,13 @@ static char* winTreeGetParentAttrib(Ihandle* ih, const char* name_id)
return NULL;
str = iupStrGetMemory(10);
- sprintf(str, "%d", winTreeGetNodeId(ih, hItem));
+ sprintf(str, "%d", iupTreeFindNodeId(ih, hItem));
return str;
}
-static void winTreeDelNodeData(Ihandle* ih, HTREEITEM hItem)
+static void winTreeRemoveItemData(Ihandle* ih, HTREEITEM hItem, IFns cb, int id)
{
TVITEM item;
- HTREEITEM hChildItem;
-
item.hItem = hItem;
item.mask = TVIF_HANDLE|TVIF_PARAM;
if (SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item))
@@ -1508,81 +1387,153 @@ static void winTreeDelNodeData(Ihandle* ih, HTREEITEM hItem)
winTreeItemData* itemData = (winTreeItemData*)item.lParam;
if (itemData)
{
- IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
- if (cb) cb(ih, winTreeGetNodeId(ih, hItem), (char*)itemData->userdata);
+ if (cb)
+ cb(ih, (char*)ih->data->node_cache[id].userdata);
+
free(itemData);
item.lParam = (LPARAM)NULL;
SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
}
}
+}
+
+static void winTreeRemoveNodeDataRec(Ihandle* ih, HTREEITEM hItem, IFns cb, int *id)
+{
+ int old_id = *id;
- hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+ /* Check whether we have child items */
+ /* remove from children first */
+ HTREEITEM hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
while (hChildItem)
{
- winTreeDelNodeData(ih, hChildItem);
+ /* go recursive to children */
+ winTreeRemoveNodeDataRec(ih, hChildItem, cb, id);
+
+ /* Go to next sibling item */
hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hChildItem);
}
+
+ /* actually do it for the node */
+ ih->data->node_count--;
+ (*id)++;
+
+ winTreeRemoveItemData(ih, hItem, cb, old_id);
+}
+
+static void winTreeRemoveNodeData(Ihandle* ih, HTREEITEM hItem, int call_cb)
+{
+ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
+ int old_count = ih->data->node_count;
+ int id = iupTreeFindNodeId(ih, hItem);
+ int old_id = id;
+
+ winTreeRemoveNodeDataRec(ih, hItem, cb, &id);
+
+ if (call_cb)
+ iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count);
+}
+
+static void winTreeRemoveAllNodeData(Ihandle* ih, int call_cb)
+{
+ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
+ int i, old_count = ih->data->node_count;
+ HTREEITEM hItem;
+
+ for (i = 0; i < ih->data->node_count; i++)
+ {
+ hItem = ih->data->node_cache[i].node_handle;
+ winTreeRemoveItemData(ih, hItem, cb, i);
+ }
+
+ ih->data->node_count = 0;
+
+ if (call_cb)
+ iupTreeDelFromCache(ih, 0, old_count);
}
static int winTreeSetDelNodeAttrib(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"))
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+ winTreeRemoveAllNodeData(ih, 1);
- /* the root node can't be deleted */
- if(!hItem || hItem == hItemRoot)
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ return 0;
+ }
+ if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference one */
+ {
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if(!hItem)
return 0;
- /* deleting the specified node (and it's children) */
- winTreeDelNodeData(ih, hItem);
+ /* deleting the reference node (and it's children) */
+ winTreeRemoveNodeData(ih, hItem, 1);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItem);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
return 0;
}
- else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
+ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
HTREEITEM hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
if(!hItem)
return 0;
- /* deleting the selected node's children */
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+
+ /* deleting the reference node children */
while (hChildItem)
{
- winTreeDelNodeData(ih, hChildItem);
+ winTreeRemoveNodeData(ih, hChildItem, 1);
SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hChildItem);
hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
}
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
return 0;
}
else if(iupStrEqualNoCase(value, "MARKED"))
{
- int i, count;
- Iarray* markedArray;
- HTREEITEM* hItemArrayData;
- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+ int i, del_focus = 0;
+ HTREEITEM hItemFocus;
- /* Delete the array of marked nodes */
- markedArray = winTreeGetSelectedArray(ih);
- hItemArrayData = (HTREEITEM*)iupArrayGetData(markedArray);
- count = iupArrayCount(markedArray);
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ hItemFocus = iupdrvTreeGetFocusNode(ih);
- for(i = 0; i < count; i++)
+ for(i = 1; i < ih->data->node_count; /* increment only if not removed */)
{
- if (hItemArrayData[i] != hItemRoot) /* the root node can't be deleted */
+ if (winTreeIsNodeSelected(ih, ih->data->node_cache[i].node_handle))
{
- winTreeDelNodeData(ih, hItemArrayData[i]);
- SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemArrayData[i]);
+ HTREEITEM hItem = ih->data->node_cache[i].node_handle;
+ if (hItemFocus == hItem)
+ {
+ del_focus = 1;
+ i++;
+ }
+ else
+ {
+ winTreeRemoveNodeData(ih, hItem, 1);
+ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItem);
+ }
}
+ else
+ i++;
}
- iupArrayDestroy(markedArray);
+ if (del_focus)
+ {
+ winTreeRemoveNodeData(ih, hItemFocus, 1);
+ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemFocus);
+ }
+
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
return 0;
}
@@ -1592,22 +1543,13 @@ static int winTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char*
static int winTreeSetRenameAttrib(Ihandle* ih, const char* value)
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
if (ih->data->show_rename)
{
- IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
- if (cbShowRename)
- cbShowRename(ih, winTreeGetNodeId(ih, hItemFocus));
-
+ HTREEITEM hItemFocus;
SetFocus(ih->handle); /* the tree must have focus to activate the edit */
+ hItemFocus = iupdrvTreeGetFocusNode(ih);
SendMessage(ih->handle, TVM_EDITLABEL, 0, (LPARAM)hItemFocus);
}
- else
- {
- IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
- if (cbRenameNode)
- cbRenameNode(ih, winTreeGetNodeId(ih, hItemFocus), winTreeGetTitle(ih, hItemFocus));
- }
(void)value;
return 0;
@@ -1615,11 +1557,11 @@ static int winTreeSetRenameAttrib(Ihandle* ih, const char* value)
static char* winTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return NULL;
- if (winTreeIsItemSelected(ih, hItem))
+ if (winTreeIsNodeSelected(ih, hItem))
return "YES";
else
return "NO";
@@ -1627,17 +1569,23 @@ static char* winTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
static int winTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
- winTreeSelectItem(ih, hItem, iupStrBoolean(value));
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ {
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ winTreeSelectNode(ih, hItemFocus, 0);
+ }
+
+ winTreeSelectNode(ih, hItem, iupStrBoolean(value));
return 0;
}
static int winTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
if (!hItem)
return 0;
@@ -1649,15 +1597,59 @@ static int winTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
static char* winTreeGetValueAttrib(Ihandle* ih)
{
char* str;
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
if (!hItemFocus)
- return "0"; /* default VALUE is root */
+ {
+ if (ih->data->node_count)
+ return "0"; /* default VALUE is root */
+ else
+ return "-1";
+ }
str = iupStrGetMemory(16);
- sprintf(str, "%d", winTreeGetNodeId(ih, hItemFocus));
+ sprintf(str, "%d", iupTreeFindNodeId(ih, hItemFocus));
+ return str;
+}
+
+static char* winTreeGetMarkedNodesAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(ih->data->node_count+1);
+ int i;
+
+ for (i=0; i<ih->data->node_count; i++)
+ {
+ if (winTreeIsNodeSelected(ih, ih->data->node_cache[i].node_handle))
+ str[i] = '+';
+ else
+ str[i] = '-';
+ }
+
+ str[ih->data->node_count] = 0;
return str;
}
+static int winTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value)
+{
+ int count, i;
+
+ 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;
+
+ for (i=0; i<count; i++)
+ {
+ if (value[i] == '+')
+ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 1);
+ else
+ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 0);
+ }
+
+ return 0;
+}
+
static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
{
if (ih->data->mark_mode==ITREE_MARK_SINGLE)
@@ -1665,7 +1657,7 @@ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
if(iupStrEqualNoCase(value, "BLOCK"))
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
winTreeSelectRange(ih, (HTREEITEM)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"), hItemFocus, 0);
}
else if(iupStrEqualNoCase(value, "CLEARALL"))
@@ -1673,14 +1665,14 @@ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
else if(iupStrEqualNoCase(value, "MARKALL"))
winTreeSelectAll(ih);
else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */
- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeInvertSelectFunc, NULL);
+ iupTreeForEach(ih, (iupTreeNodeFunc)winTreeInvertSelectFunc, NULL);
else if(iupStrEqualPartial(value, "INVERT")) /* iupStrEqualPartial allows the use of "INVERTid" form */
{
- HTREEITEM hItem = winTreeFindNodeFromString(ih, &value[strlen("INVERT")]);
+ HTREEITEM hItem = iupTreeGetNodeFromString(ih, &value[strlen("INVERT")]);
if (!hItem)
return 0;
- winTreeSelectItem(ih, hItem, -1); /* toggle */
+ winTreeSelectNode(ih, hItem, -1); /* toggle */
}
else
{
@@ -1690,10 +1682,10 @@ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
if (iupStrToStrStr(value, str1, str2, '-')!=2)
return 0;
- hItem1 = winTreeFindNodeFromString(ih, str1);
+ hItem1 = iupTreeGetNodeFromString(ih, str1);
if (!hItem1)
return 0;
- hItem2 = winTreeFindNodeFromString(ih, str2);
+ hItem2 = iupTreeGetNodeFromString(ih, str2);
if (!hItem2)
return 0;
@@ -1711,9 +1703,9 @@ static int winTreeSetValueAttrib(Ihandle* ih, const char* value)
if (winTreeSetMarkAttrib(ih, value))
return 0;
- hItemFocus = winTreeGetFocusNode(ih);
+ hItemFocus = iupdrvTreeGetFocusNode(ih);
- if(iupStrEqualNoCase(value, "ROOT"))
+ if(iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST"))
hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
else if(iupStrEqualNoCase(value, "LAST"))
hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0);
@@ -1759,15 +1751,14 @@ static int winTreeSetValueAttrib(Ihandle* ih, const char* value)
else if(iupStrEqualNoCase(value, "PREVIOUS"))
hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItemFocus);
else
- hItem = winTreeFindNodeFromString(ih, value);
+ hItem = iupTreeGetNodeFromString(ih, value);
if (hItem)
{
if (ih->data->mark_mode==ITREE_MARK_SINGLE)
{
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
- winTreeSelectItem(ih, hItem, 1);
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ winTreeSelectNode(ih, hItemFocus, 0);
+ winTreeSelectNode(ih, hItem, 1);
}
winTreeSetFocusNode(ih, hItem);
}
@@ -1832,27 +1823,60 @@ static LRESULT CALLBACK winTreeEditWinProc(HWND hwnd, UINT msg, WPARAM wp, LPARA
return CallWindowProc(oldProc, hwnd, msg, wp, lp);
}
-static void winTreeDrag(Ihandle* ih, int x, int y)
+static void winTreeBeginDrag(Ihandle* ih, int x, int y)
{
- HTREEITEM hItemDrop;
+ HIMAGELIST dragImageList;
+
+ HTREEITEM hItemDrag = winTreeFindNodeXY(ih, x, y);
+ if (!hItemDrag)
+ return;
+
+ SendMessage(ih->handle, TVM_ENDEDITLABELNOW, TRUE, 0);
+
+ /* store the drag-and-drop item */
+ iupAttribSetStr(ih, "_IUPTREE_DRAGITEM", (char*)hItemDrag);
+ /* get the image list for dragging */
+ dragImageList = (HIMAGELIST)SendMessage(ih->handle, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItemDrag);
+ if (dragImageList)
+ {
+ POINT pt;
+ ImageList_BeginDrag(dragImageList, 0, 0, 0);
+
+ pt.x = x;
+ pt.y = y;
+
+ ClientToScreen(ih->handle, &pt);
+ ImageList_DragEnter(NULL, pt.x, pt.y);
+
+ iupAttribSetStr(ih, "_IUPTREE_DRAGIMAGELIST", (char*)dragImageList);
+ }
+
+ ShowCursor(FALSE);
+ SetCapture(ih->handle); /* drag only inside the tree */
+}
+
+static void winTreeDrag(Ihandle* ih, int x, int y)
+{
+ HTREEITEM hItemDrop = winTreeFindNodeXY(ih, x, y);
+ HTREEITEM hItemDrag = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_DRAGITEM");
HIMAGELIST dragImageList = (HIMAGELIST)iupAttribGet(ih, "_IUPTREE_DRAGIMAGELIST");
+
if (dragImageList)
{
- POINT pnt;
- pnt.x = x;
- pnt.y = y;
- GetCursorPos(&pnt);
- ClientToScreen(GetDesktopWindow(), &pnt) ;
- ImageList_DragMove(pnt.x, pnt.y);
+ POINT pt;
+ pt.x = x;
+ pt.y = y;
+ ClientToScreen(ih->handle, &pt);
+ ImageList_DragMove(pt.x, pt.y);
}
- if ((hItemDrop = winTreeFindNodePointed(ih)) != NULL)
+ if (hItemDrop && hItemDrop!=hItemDrag)
{
if(dragImageList)
ImageList_DragShowNolock(FALSE);
- SendMessage(ih->handle, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItemDrop);
+ SendMessage(ih->handle, TVM_SETINSERTMARK, TRUE, (LPARAM)hItemDrop);
/* store the drop item to be executed */
iupAttribSetStr(ih, "_IUPTREE_DROPITEM", (char*)hItemDrop);
@@ -1860,6 +1884,8 @@ static void winTreeDrag(Ihandle* ih, int x, int y)
if(dragImageList)
ImageList_DragShowNolock(TRUE);
}
+ else
+ iupAttribSetStr(ih, "_IUPTREE_DROPITEM", NULL);
}
static void winTreeDrop(Ihandle* ih)
@@ -1882,7 +1908,7 @@ static void winTreeDrop(Ihandle* ih)
ShowCursor(TRUE);
/* Remove drop target highlighting */
- SendMessage(ih->handle, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)NULL);
+ SendMessage(ih->handle, TVM_SETINSERTMARK, 0, (LPARAM)NULL);
iupAttribSetStr(ih, "_IUPTREE_DRAGITEM", NULL);
iupAttribSetStr(ih, "_IUPTREE_DROPITEM", NULL);
@@ -1901,16 +1927,12 @@ static void winTreeDrop(Ihandle* ih)
if (winTreeCallDragDropCb(ih, hItemDrag, hItemDrop, &is_ctrl) == IUP_CONTINUE)
{
- /* Copy the dragged item to the new position. */
- HTREEITEM hItemNew = winTreeCopyNode(ih, hItemDrag, hItemDrop, is_ctrl);
-
- if (!is_ctrl)
- {
- /* do not delete the user data, we copy the references in CopyNode */
- SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemDrag);
- }
+ /* Copy or move the dragged item to the new position. */
+ HTREEITEM hItemNew = winTreeCopyMoveNode(ih, hItemDrag, hItemDrop, is_ctrl);
- SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItemNew); /* set focus and selection */
+ /* Set focus and selection */
+ if (hItemNew)
+ SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItemNew);
}
}
@@ -1929,9 +1951,7 @@ static void winTreeExtendSelect(Ihandle* ih, int x, int y)
hItemFirstSel = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_FIRSTSELITEM");
if (hItemFirstSel)
{
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
winTreeSelectRange(ih, hItemFirstSel, hItem, 1);
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
iupAttribSetStr(ih, "_IUPTREE_LASTSELITEM", (char*)hItem);
winTreeSetFocusNode(ih, hItem);
@@ -1952,10 +1972,10 @@ static int winTreeMouseMultiSelect(Ihandle* ih, int x, int y)
if (GetKeyState(VK_CONTROL) & 0x8000) /* Control key is down */
{
/* Toggle selection state */
- winTreeSelectItem(ih, hItem, -1);
+ winTreeSelectNode(ih, hItem, -1);
iupAttribSetStr(ih, "_IUPTREE_FIRSTSELITEM", (char*)hItem);
- winTreeCallSelectionCb(ih, winTreeIsItemSelected(ih, hItem), hItem);
+ winTreeCallSelectionCb(ih, winTreeIsNodeSelected(ih, hItem), hItem);
winTreeSetFocusNode(ih, hItem);
return 1;
@@ -1965,9 +1985,11 @@ static int winTreeMouseMultiSelect(Ihandle* ih, int x, int y)
HTREEITEM hItemFirstSel = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_FIRSTSELITEM");
if (hItemFirstSel)
{
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ int last_id = iupTreeFindNodeId(ih, hItem);
winTreeSelectRange(ih, hItemFirstSel, hItem, 1);
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+
+ /* if last selected item is a branch, then select its children */
+ iupTreeSelectLastCollapsedBranch(ih, &last_id);
winTreeCallMultiSelectionCb(ih);
winTreeSetFocusNode(ih, hItem);
@@ -1975,11 +1997,15 @@ static int winTreeMouseMultiSelect(Ihandle* ih, int x, int y)
}
}
+ winTreeCallMultiUnSelectionCb(ih);
+
/* simple click */
winTreeClearSelection(ih, hItem);
iupAttribSetStr(ih, "_IUPTREE_FIRSTSELITEM", (char*)hItem);
iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1");
+ /* Call SELECT_CB for all unselected nodes */
+
return 0;
}
@@ -2039,7 +2065,7 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
if (wp == VK_RETURN)
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
if (winTreeCallBranchLeafCb(ih, hItemFocus) != IUP_IGNORE)
winTreeExpandItem(ih, hItemFocus, -1);
@@ -2056,14 +2082,14 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
{
if (GetKeyState(VK_CONTROL) & 0x8000)
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
/* Toggle selection state */
- winTreeSelectItem(ih, hItemFocus, -1);
+ winTreeSelectNode(ih, hItemFocus, -1);
}
}
else if (wp == VK_UP || wp == VK_DOWN)
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
if (wp == VK_UP)
hItemFocus = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItemFocus);
else
@@ -2084,9 +2110,7 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
HTREEITEM hItemFirstSel = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_FIRSTSELITEM");
if (hItemFirstSel)
{
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
winTreeSelectRange(ih, hItemFirstSel, hItemFocus, 1);
- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
winTreeCallMultiSelectionCb(ih);
winTreeSetFocusNode(ih, hItemFocus);
@@ -2138,10 +2162,20 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
}
break;
case WM_MOUSEMOVE:
- if (ih->data->show_dragdrop && (HTREEITEM)iupAttribGet(ih, "_IUPTREE_DRAGITEM") != NULL)
- winTreeDrag(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
+ if (ih->data->show_dragdrop && (wp & MK_LBUTTON))
+ {
+ if (!iupAttribGet(ih, "_IUPTREE_DRAGITEM"))
+ winTreeBeginDrag(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
+ else
+ winTreeDrag(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
+ }
else if (iupAttribGet(ih, "_IUPTREE_EXTENDSELECT"))
- winTreeExtendSelect(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
+ {
+ if (wp & MK_LBUTTON)
+ winTreeExtendSelect(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
+ else
+ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", NULL);
+ }
iupwinMouseMove(ih, msg, wp, lp);
break;
@@ -2157,6 +2191,7 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
if (iupAttribGet(ih, "_IUPTREE_EXTENDSELECT"))
{
iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", NULL);
+
if (iupAttribGet(ih, "_IUPTREE_LASTSELITEM"))
{
winTreeCallMultiSelectionCb(ih);
@@ -2205,14 +2240,19 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
else if (msg_info->code == TVN_SELCHANGED)
{
NMTREEVIEW* info = (NMTREEVIEW*)msg_info;
- winTreeCallSelectionCb(ih, 0, info->itemOld.hItem); /* node unselected */
- winTreeCallSelectionCb(ih, 1, info->itemNew.hItem); /* node selected */
+ if (ih->data->mark_mode!=ITREE_MARK_MULTIPLE || /* (NOT) Multiple selection with Control or Shift key is down */
+ !(GetKeyState(VK_CONTROL) & 0x8000 || GetKeyState(VK_SHIFT) & 0x8000))
+ {
+ winTreeCallSelectionCb(ih, 0, info->itemOld.hItem); /* node unselected */
+ winTreeCallSelectionCb(ih, 1, info->itemNew.hItem); /* node selected */
+ }
}
else if(msg_info->code == TVN_BEGINLABELEDIT)
{
char* value;
HWND hEdit;
NMTVDISPINFO* info = (NMTVDISPINFO*)msg_info;
+ IFni cbShowRename;
if (iupAttribGet(ih, "_IUPTREE_EXTENDSELECT"))
{
@@ -2220,6 +2260,13 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
return 1;
}
+ cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+ if (cbShowRename && cbShowRename(ih, iupTreeFindNodeId(ih, info->item.hItem))==IUP_IGNORE)
+ {
+ *result = TRUE; /* prevent the change */
+ return 1;
+ }
+
hEdit = (HWND)SendMessage(ih->handle, TVM_GETEDITCONTROL, 0, 0);
/* save the edit box. */
@@ -2253,57 +2300,30 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
}
else if(msg_info->code == TVN_ENDLABELEDIT)
{
+ IFnis cbRename;
NMTVDISPINFO* info = (NMTVDISPINFO*)msg_info;
iupAttribSetStr(ih, "_IUPWIN_EDITBOX", NULL);
- if (info->item.pszText)
- {
- IFnis cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
- if (cbRename)
- {
- if (cbRename(ih, winTreeGetNodeId(ih, info->item.hItem), info->item.pszText) == IUP_IGNORE)
- {
- *result = FALSE;
- return 1;
- }
- }
+ if (!info->item.pszText) /* cancel, so abort */
+ return 0;
- *result = TRUE;
- return 1;
- }
- }
- else if(msg_info->code == TVN_BEGINDRAG)
- {
- if (ih->data->show_dragdrop)
+ cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
+ if (cbRename)
{
- NMTREEVIEW* pNMTreeView = (NMTREEVIEW*)msg_info;
- HTREEITEM hItemDrag = pNMTreeView->itemNew.hItem;
- HIMAGELIST dragImageList;
-
- /* store the drag-and-drop item */
- iupAttribSetStr(ih, "_IUPTREE_DRAGITEM", (char*)hItemDrag);
-
- /* get the image list for dragging */
- dragImageList = (HIMAGELIST)SendMessage(ih->handle, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItemDrag);
- if (dragImageList)
+ if (cbRename(ih, iupTreeFindNodeId(ih, info->item.hItem), info->item.pszText) == IUP_IGNORE)
{
- POINT pt = pNMTreeView->ptDrag;
- ImageList_BeginDrag(dragImageList, 0, 0, 0);
-
- ClientToScreen(ih->handle, &pt);
- ImageList_DragEnter(NULL, pt.x, pt.y);
-
- iupAttribSetStr(ih, "_IUPTREE_DRAGIMAGELIST", (char*)dragImageList);
+ *result = FALSE;
+ return 1;
}
-
- ShowCursor(FALSE);
- SetCapture(ih->handle); /* drag only inside the tree */
}
+
+ *result = TRUE;
+ return 1;
}
else if(msg_info->code == NM_DBLCLK)
{
- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
TVITEM item;
winTreeItemData* itemData;
@@ -2317,7 +2337,7 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
{
IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
if(cbExecuteLeaf)
- cbExecuteLeaf(ih, winTreeGetNodeId(ih, hItemFocus));
+ cbExecuteLeaf(ih, iupTreeFindNodeId(ih, hItemFocus));
}
}
else if(msg_info->code == TVN_ITEMEXPANDING)
@@ -2351,7 +2371,7 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
HTREEITEM hItem = winTreeFindNodePointed(ih);
IFni cbRightClick = (IFni)IupGetCallback(ih, "RIGHTCLICK_CB");
if (cbRightClick)
- cbRightClick(ih, winTreeGetNodeId(ih, hItem));
+ cbRightClick(ih, iupTreeFindNodeId(ih, hItem));
}
else if (msg_info->code == NM_CUSTOMDRAW)
{
@@ -2374,7 +2394,7 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
itemData = (winTreeItemData*)item.lParam;
- if (winTreeIsItemSelected(ih, hItem))
+ if (GetFocus()==ih->handle && (customdraw->nmcd.uItemState & CDIS_SELECTED))
customdraw->clrText = winTreeInvertColor(itemData->color);
else
customdraw->clrText = itemData->color;
@@ -2402,47 +2422,34 @@ static int winTreeConvertXYToPos(Ihandle* ih, int x, int y)
info.pt.y = y;
hItem = (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)&info);
if (hItem)
- return winTreeGetNodeId(ih, hItem);
+ return iupTreeFindNodeId(ih, hItem);
return -1;
}
/*******************************************************************************************/
-static void winTreeUnMapMethod(Ihandle* ih)
-{
- Iarray* bmp_array;
- HIMAGELIST image_list;
-
- HTREEITEM itemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
- winTreeDelNodeData(ih, itemRoot);
-
- image_list = (HIMAGELIST)SendMessage(ih->handle, TVM_GETIMAGELIST, TVSIL_NORMAL, 0);
- if (image_list)
- ImageList_Destroy(image_list);
-
- bmp_array = (Iarray*)iupAttribGet(ih, "_IUPWIN_BMPARRAY");
- if (bmp_array)
- iupArrayDestroy(bmp_array);
-
- iupdrvBaseUnMapMethod(ih);
-}
static int winTreeMapMethod(Ihandle* ih)
{
- DWORD dwStyle = WS_CHILD | WS_BORDER | TVS_SHOWSELALWAYS;
+ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER | TVS_SHOWSELALWAYS;
- /* can be set only on the Tree View creation */
+ /* styles can be set only on the Tree View creation */
- if (!ih->data->show_dragdrop)
- dwStyle |= TVS_DISABLEDRAGDROP;
+ /* always disable the internal drag&drop, because it affects our selection and drawing */
+ dwStyle |= TVS_DISABLEDRAGDROP;
if (ih->data->show_rename)
dwStyle |= TVS_EDITLABELS;
if (!iupAttribGetBoolean(ih, "HIDELINES"))
+ {
dwStyle |= TVS_HASLINES;
+ if (!iupAttribGetInt(ih, "ADDROOT"))
+ dwStyle |= TVS_LINESATROOT;
+ }
+
if (!iupAttribGetBoolean(ih, "HIDEBUTTONS"))
dwStyle |= TVS_HASBUTTONS;
@@ -2455,6 +2462,11 @@ static int winTreeMapMethod(Ihandle* ih)
if (!iupwinCreateWindowEx(ih, WC_TREEVIEW, 0, dwStyle))
return IUP_ERROR;
+ if (!iupwin_comctl32ver6) /* To improve drawing of items when TITLEFONT is set */
+ SendMessage(ih->handle, CCM_SETVERSION, 5, 0);
+ else
+ SendMessage(ih->handle, TVM_SETEXTENDEDSTYLE, TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
+
IupSetCallback(ih, "_IUPWIN_CTRLPROC_CB", (Icallback)winTreeProc);
IupSetCallback(ih, "_IUPWIN_NOTIFY_CB", (Icallback)winTreeWmNotify);
@@ -2466,7 +2478,7 @@ static int winTreeMapMethod(Ihandle* ih)
winTreeSetBgColorAttrib(ih, value);
iupAttribSetStr(ih, "BGCOLOR", NULL);
}
- else if (iupwinGetSystemMajorVersion()<6) /* force background in XP because of the editbox background */
+ else if (!iupwin_comctl32ver6 || iupwinGetSystemMajorVersion()<6) /* force background in XP because of the editbox background */
winTreeSetBgColorAttrib(ih, IupGetGlobal("TXTBGCOLOR"));
}
@@ -2475,8 +2487,8 @@ static int winTreeMapMethod(Ihandle* ih)
ih->data->def_image_collapsed = (void*)winTreeGetImageIndex(ih, "IMGCOLLAPSED");
ih->data->def_image_expanded = (void*)winTreeGetImageIndex(ih, "IMGEXPANDED");
- /* Add the Root Node */
- winTreeAddRootNode(ih);
+ if (iupAttribGetInt(ih, "ADDROOT"))
+ iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0);
/* configure for DRAG&DROP of files */
if (IupGetCallback(ih, "DROPFILES_CB"))
@@ -2484,9 +2496,31 @@ static int winTreeMapMethod(Ihandle* ih)
IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)winTreeConvertXYToPos);
+ iupdrvTreeUpdateMarkMode(ih);
+
return IUP_NOERROR;
}
+static void winTreeUnMapMethod(Ihandle* ih)
+{
+ Iarray* bmp_array;
+ HIMAGELIST image_list;
+
+ winTreeRemoveAllNodeData(ih, 0);
+
+ ih->data->node_count = 0;
+
+ image_list = (HIMAGELIST)SendMessage(ih->handle, TVM_GETIMAGELIST, TVSIL_NORMAL, 0);
+ if (image_list)
+ ImageList_Destroy(image_list);
+
+ bmp_array = (Iarray*)iupAttribGet(ih, "_IUPWIN_BMPARRAY");
+ if (bmp_array)
+ iupArrayDestroy(bmp_array);
+
+ iupdrvBaseUnMapMethod(ih);
+}
+
void iupdrvTreeInitClass(Iclass* ic)
{
/* Driver Dependent Class functions */
@@ -2500,7 +2534,6 @@ void iupdrvTreeInitClass(Iclass* ic)
/* IupTree Attributes - GENERAL */
iupClassRegisterAttribute(ic, "EXPANDALL", NULL, winTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "INDENTATION", winTreeGetIndentationAttrib, winTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
- iupClassRegisterAttribute(ic, "COUNT", winTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "DRAGDROP", NULL, iupwinSetDragDropAttrib, NULL, NULL, IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, winTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
iupClassRegisterAttribute(ic, "TOPITEM", NULL, winTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
@@ -2521,7 +2554,6 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttributeId(ic, "NAME", winTreeGetTitleAttrib, winTreeSetTitleAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TITLE", winTreeGetTitleAttrib, winTreeSetTitleAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "CHILDCOUNT", winTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
- iupClassRegisterAttributeId(ic, "USERDATA", winTreeGetUserDataAttrib, winTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "COLOR", winTreeGetColorAttrib, winTreeSetColorAttrib, IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "TITLEFONT", winTreeGetTitleFontAttrib, winTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
@@ -2530,6 +2562,7 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttribute (ic, "MARK", NULL, winTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "STARTING", NULL, winTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "MARKSTART", NULL, winTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKEDNODES", winTreeGetMarkedNodesAttrib, winTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
iupClassRegisterAttribute (ic, "VALUE", winTreeGetValueAttrib, winTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
@@ -2538,5 +2571,8 @@ void iupdrvTreeInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "RENAME", NULL, winTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "MOVENODE", NULL, winTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
iupClassRegisterAttributeId(ic, "COPYNODE", NULL, winTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
- iupClassRegisterAttributeId(ic, "FINDUSERDATA", winTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+
+ /* necessary because transparent background does not work when not using visual styles */
+ if (!iupwin_comctl32ver6) /* Used by iupdrvImageCreateImage */
+ iupClassRegisterAttribute(ic, "FLAT_ALPHA", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
}
diff --git a/iup/src/win/iupwin_val.c b/iup/src/win/iupwin_val.c
index 706c612..5c956d9 100755
--- a/iup/src/win/iupwin_val.c
+++ b/iup/src/win/iupwin_val.c
@@ -56,6 +56,13 @@ void iupdrvValGetMinSize(Ihandle* ih, int *w, int *h)
}
}
+static int winValSetBgColorAttrib(Ihandle *ih, const char *value)
+{
+ (void)value;
+ iupdrvPostRedraw(ih);
+ return 1;
+}
+
static int winValSetStepAttrib(Ihandle* ih, const char* value)
{
int linesize;
@@ -110,18 +117,6 @@ static int winValSetValueAttrib(Ihandle* ih, const char* value)
/*********************************************************************************************/
-static int winValCtlColor(Ihandle* ih, HDC hdc, LRESULT *result)
-{
- COLORREF cr;
- if (iupwinGetParentBgColor(ih, &cr))
- {
- SetDCBrushColor(hdc, cr);
- *result = (LRESULT)GetStockObject(DC_BRUSH);
- return 1;
- }
- return 0;
-}
-
static int winValCustomScroll(Ihandle* ih, int msg)
{
double old_val = ih->data->val;
@@ -190,6 +185,19 @@ static void winValIncPageValue(Ihandle *ih, int dir)
winValCustomScroll(ih, 0);
}
+static int winValCtlColor(Ihandle* ih, HDC hdc, LRESULT *result)
+{
+ COLORREF cr;
+ if (iupwinGetParentBgColor(ih, &cr))
+ {
+ SetBkColor(hdc, cr);
+ SetDCBrushColor(hdc, cr);
+ *result = (LRESULT)GetStockObject(DC_BRUSH);
+ return 1;
+ }
+ return 0;
+}
+
static int winValProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result)
{
(void)lp;
@@ -240,7 +248,7 @@ static int winValProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *resu
static int winValMapMethod(Ihandle* ih)
{
- DWORD dwStyle = WS_CHILD | TBS_AUTOTICKS;
+ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | TBS_AUTOTICKS;
int show_ticks;
if (!ih->parent)
@@ -312,4 +320,7 @@ void iupdrvValInitClass(Iclass* ic)
iupClassRegisterAttribute(ic, "STEP", iupValGetStepAttrib, winValSetStepAttrib, "0.01", NULL, IUPAF_NO_INHERIT); /* force new default value */
iupClassRegisterAttribute(ic, "TICKSPOS", NULL, NULL, "NORMAL", NULL, IUPAF_NOT_MAPPED);
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winValSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
}