summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/comctl32_windows.c7
-rw-r--r--redo/imagelist.go29
-rw-r--r--redo/imagelist_windows.c86
-rw-r--r--redo/imagelist_windows.go45
-rw-r--r--redo/winapi_windows.h7
5 files changed, 174 insertions, 0 deletions
diff --git a/redo/comctl32_windows.c b/redo/comctl32_windows.c
index 6af4f30..9dd67c1 100644
--- a/redo/comctl32_windows.c
+++ b/redo/comctl32_windows.c
@@ -9,6 +9,8 @@ static HMODULE comctl32;
BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+HIMAGELIST (*WINAPI fv_ImageList_Create)(int, int, UINT, int, int);
+int (*WINAPI fv_ImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
#define wantedICCClasses ( \
ICC_PROGRESS_CLASS | /* progress bars */ \
@@ -115,6 +117,11 @@ DWORD initCommonControls(char **errmsg)
fv_RemoveWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR)) f;
LOAD("DefSubclassProc");
fv_DefSubclassProc = (LRESULT (*WINAPI)(HWND, UINT, WPARAM, LPARAM)) f;
+ LOAD("ImageList_Create");
+ fv_ImageList_Create = (HIMAGELIST (*WINAPI)(int, int, UINT, int, int)) f;
+ LOAD("ImageList_Add");
+ fv_ImageList_Add = (int (*WINAPI)(HIMAGELIST, HBITMAP, HBITMAP)) f;
+
if ((*ficc)(&icc) == FALSE) {
*errmsg = "error initializing Common Controls (comctl32.dll)";
diff --git a/redo/imagelist.go b/redo/imagelist.go
new file mode 100644
index 0000000..6b34b28
--- /dev/null
+++ b/redo/imagelist.go
@@ -0,0 +1,29 @@
+// 16 august 2014
+
+package ui
+
+import (
+ "image"
+)
+
+// ImageList is a list of images that can be used in the rows of a Table or Tree.
+// ImageList maintains a copy of each image added.
+// Images in an ImageList will be automatically scaled to the needed size.
+type ImageList interface {
+ // Append inserts an image into the ImageList.
+ Append(i *image.RGBA)
+
+ // Len returns the number of images in the ImageList.
+ Len() ImageIndex
+
+ imageListApply
+}
+
+// NewImageList creates a new ImageList.
+// The ImageList is initially empty.
+func NewImageList() ImageList {
+ return newImageList()
+}
+
+// ImageIndex is a special type used to denote an entry in a Table or Tree's ImageList.
+type ImageIndex int
diff --git a/redo/imagelist_windows.c b/redo/imagelist_windows.c
new file mode 100644
index 0000000..434190c
--- /dev/null
+++ b/redo/imagelist_windows.c
@@ -0,0 +1,86 @@
+// 16 august 2014
+
+#include "winapi_windows.h"
+#include "_cgo_export.h"
+
+HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
+{
+ BITMAPINFO bi;
+ VOID *ppvBits;
+ HBITMAP bitmap;
+
+ ZeroMemory(&bi, sizeof (BITMAPINFO));
+ bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = (LONG) dx;
+ bi.bmiHeader.biHeight = -((LONG) dy); // negative height to force top-down drawing;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biSizeImage = (DWORD) (dx * dy * 4);
+ bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
+ if (bitmap == NULL)
+ xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
+ dotoARGB(i, (void *) ppvBits);
+ return bitmap;
+}
+
+HIMAGELIST newImageList(int width, int height)
+{
+ HIMAGELIST il;
+
+ // TODO does this strip alpha?
+ // sinni800 in irc.freenode.net/#go-nuts suggests our use of *image.RGBA makes this not so much of an issue
+ il = (*fv_ImageList_Create)(width, height, ILC_COLOR32, 20, 20); // should be reasonable
+ if (il == NULL)
+ xpanic("error creating image list", GetLastError());
+ return il;
+}
+
+void addImage(HIMAGELIST il, HBITMAP bitmap, int origwid, int oright, int width, int height)
+{
+ BOOL wasScaled = FALSE;
+ HDC scaledDC, origDC;
+ HBITMAP scaled;
+ HBITMAP prevscaled, prevorig;
+
+ // first we need to scale the bitmap
+ if (origwid == width && oright == height) {
+ scaled = bitmap;
+ goto noscale;
+ }
+ wasScaled = TRUE;
+ scaledDC = GetDC(NULL);
+ if (scaledDC == NULL)
+ xpanic("error getting screen DC for scaled ImageList bitmap", GetLastError());
+ scaled = CreateCompatibleBitmap(scaledDC, width, height);
+ if (scaled == NULL)
+ xpanic("error creating scaled ImageList bitmap", GetLastError());
+ prevscaled = SelectObject(scaledDC, scaled);
+ if (prevscaled == NULL)
+ xpanic("error selecting scaled ImageList bitmap into screen DC", GetLastError());
+ origDC = GetDC(NULL);
+ if (origDC == NULL)
+ xpanic("error getting screen DC for original ImageList bitmap", GetLastError());
+ prevorig = SelectObject(origDC, bitmap);
+ if (prevorig == NULL)
+ xpanic("error selecting original ImageList bitmap into screen DC", GetLastError());
+ if (StretchBlt(scaledDC, 0, 0, width, height,
+ origDC, 0, 0, origwid, oright,
+ SRCCOPY) == 0)
+ xpanic("error scaling ImageList bitmap down", GetLastError());
+ if (SelectObject(origDC, prevorig) != bitmap)
+ xpanic("error selecting previous bitmap into original image's screen DC", GetLastError());
+ if (DeleteDC(origDC) == 0)
+ xpanic("error deleting original image's screen DC", GetLastError());
+ if (SelectObject(scaledDC, prevscaled) != scaled)
+ xpanic("error selecting previous bitmap into scaled image's screen DC", GetLastError());
+ if (DeleteDC(scaledDC) == 0)
+ xpanic("error deleting scaled image's screen DC", GetLastError());
+
+noscale:
+ if ((*fv_ImageList_Add)(il, scaled, NULL) == -1)
+ xpanic("error adding ImageList image to image list", GetLastError());
+ if (wasScaled) // clean up
+ if (DeleteObject(scaled) == 0)
+ xpanic("error deleting scaled bitmap", GetLastError());
+}
diff --git a/redo/imagelist_windows.go b/redo/imagelist_windows.go
new file mode 100644
index 0000000..389c553
--- /dev/null
+++ b/redo/imagelist_windows.go
@@ -0,0 +1,45 @@
+// 16 august 2014
+
+package ui
+
+import (
+ "image"
+ "unsafe"
+)
+
+// #include "winapi_windows.h"
+import "C"
+
+type imagelist struct {
+ list []C.HBITMAP
+ width []int
+ height []int
+}
+
+func newImageList() ImageList {
+ return new(imagelist)
+}
+
+func (i *imagelist) Append(img *image.RGBA) {
+ i.list = append(i.list, C.unscaledBitmap(unsafe.Pointer(img), C.intptr_t(img.Rect.Dx()), C.intptr_t(img.Rect.Dy())))
+ i.width = append(i.width, img.Rect.Dx())
+ i.height = append(i.height, img.Rect.Dy())
+}
+
+func (i *imagelist) Len() ImageIndex {
+ return ImageIndex(len(i.list))
+}
+
+type imageListApply interface {
+ apply()
+}
+
+func (i *imagelist) apply() {
+ width := C.GetSystemMetrics(C.SM_CXSMICON)
+ height := C.GetSystemMetrics(C.SM_CYSMICON)
+ il := C.newImageList(width, height)
+ for index := range i.list {
+ C.addImage(il, i.list[index], C.int(i.width[index]), C.int(i.height[index]), width, height)
+ }
+ // TODO do stuff
+}
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 028f3c3..c6a2c63 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -44,6 +44,8 @@ extern DWORD initCommonControls(char **);
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+extern HIMAGELIST (*WINAPI fv_ImageList_Create)(int, int, UINT, int, int);
+extern int (*WINAPI fv_ImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
// control_windows.c
extern HWND newControl(LPWSTR, DWORD, DWORD);
@@ -112,4 +114,9 @@ extern void repaintArea(HWND);
extern DWORD makeAreaWindowClass(char **);
extern HWND newArea(void *);
+// imagelist_windows.c
+extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
+extern HIMAGELIST newImageList(int, int);
+extern void addImage(HIMAGELIST, HBITMAP, int, int, int, int);
+
#endif