diff options
Diffstat (limited to 'iup/src/win')
26 files changed, 1430 insertions, 892 deletions
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); } |