Numerous bug fixes to all platforms

Works both installed and not installed
This commit is contained in:
flithm 2007-08-28 01:54:45 +00:00
parent c913f9f99a
commit a81ea73566
68 changed files with 384 additions and 35286 deletions

View file

@ -2,6 +2,8 @@
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.

View file

@ -2,6 +2,8 @@
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
@ -38,7 +40,6 @@ IF(CMAKE_USER_MAKE_RULES_OVERRIDE_D)
INCLUDE(${CMAKE_USER_MAKE_RULES_OVERRIDE_D})
ENDIF(CMAKE_USER_MAKE_RULES_OVERRIDE_D)
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
# copy the values from the LIBRARY variables
@ -101,24 +102,73 @@ INCLUDE(CMakeCommonLanguageInclude)
# <CMAKE_AR>
# <CMAKE_RANLIB>
IF("$ENV{D_PATH}" STREQUAL "")
STRING(LENGTH ${CMAKE_D_COMPILER} CMAKE_D_COMPILER_LENGTH)
IF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
MATH(EXPR CMAKE_D_COMPILER_LENGTH "${CMAKE_D_COMPILER_LENGTH} - 12")
ELSE(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
MATH(EXPR CMAKE_D_COMPILER_LENGTH "${CMAKE_D_COMPILER_LENGTH} - 8")
ENDIF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
STRING(SUBSTRING ${CMAKE_D_COMPILER} 0 ${CMAKE_D_COMPILER_LENGTH} D_PATH)
ELSE("$ENV{D_PATH}" STREQUAL "")
SET(D_PATH "$ENV{D_PATH}")
ENDIF("$ENV{D_PATH}" STREQUAL "")
MESSAGE(STATUS "D Compiler Install Prefix (use D_PATH env var to override): ${D_PATH}")
IF(CMAKE_COMPILER_IS_GDC)
SET(CMAKE_OUTPUT_D_FLAG "-o ")
SET(CMAKE_SHARED_LIBRARY_D_FLAGS "-fPIC")
SET(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared")
SET(CMAKE_INCLUDE_FLAG_D "-I") # -I
SET(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty
SET(CMAKE_LIBRARY_PATH_FLAG "-L")
SET(CMAKE_LINK_LIBRARY_FLAG "-l")
SET(CMAKE_D_VERSION_FLAG "-fversion=")
ELSE(CMAKE_COMPILER_IS_GDC)
SET(CMAKE_OUTPUT_D_FLAG "-of")
IF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
SET(CMAKE_LINK_LIBRARY_FLAG "-L+")
SET(CMAKE_LIBRARY_PATH_FLAG "-I")
FIND_PROGRAM(DMD_LIBRARIAN "lib.exe")
ELSE(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
SET(CMAKE_SHARED_LIBRARY_D_FLAGS "-fPIC")
SET(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared")
SET(CMAKE_INCLUDE_FLAG_D "-I") # -I
SET(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty
SET(CMAKE_LIBRARY_PATH_FLAG "-L")
SET(CMAKE_LINK_LIBRARY_FLAG "-l")
SET(CMAKE_D_VERSION_FLAG "-version=")
ENDIF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
ENDIF(CMAKE_COMPILER_IS_GDC)
IF(CMAKE_D_USE_TANGO)
IF(CMAKE_COMPILER_IS_GDC)
SET(DSTDLIB_TYPE "-fversion=Tango")
SET(DSTDLIB_FLAGS "-lgtango")
ELSE(CMAKE_COMPILER_IS_GDC)
SET(DSTDLIB_TYPE "-version=Tango")
SET(DSTDLIB_FLAGS "-L${D_PATH}/lib -ltango -lphobos")
ENDIF(CMAKE_COMPILER_IS_GDC)
ENDIF(CMAKE_D_USE_TANGO)
IF(CMAKE_D_USE_PHOBOS)
IF(CMAKE_COMPILER_IS_GDC)
SET(DSTDLIB_TYPE "-fversion=Phobos")
SET(DSTDLIB_FLAGS "-lphobos -version=Phobos")
ELSE(CMAKE_COMPILER_IS_GDC)
SET(DSTDLIB_TYPE "-version=Phobos")
SET(DSTDLIB_FLAGS "-L${D_PATH}/lib -ltango -lphobos")
ENDIF(CMAKE_COMPILER_IS_GDC)
ENDIF(CMAKE_D_USE_PHOBOS)
# create a D shared library
IF(NOT CMAKE_D_CREATE_SHARED_LIBRARY)
IF(CMAKE_COMPILER_IS_GDC)
SET(CMAKE_D_CREATE_SHARED_LIBRARY
"<CMAKE_D_COMPILER> <CMAKE_SHARED_LIBRARY_D_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_D_FLAG><TARGET_SONAME> ${CMAKE_OUTPUT_D_FLAG}<TARGET> <OBJECTS> <LINK_LIBRARIES>")
ELSE(CMAKE_COMPILER_IS_GDC)
SET(CMAKE_D_CREATE_SHARED_LIBRARY
"<CMAKE_D_COMPILER> <CMAKE_SHARED_LIBRARY_D_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_D_FLAG><TARGET_SONAME> ${CMAKE_OUTPUT_D_FLAG}<TARGET> <OBJECTS> <LINK_LIBRARIES> ${DSTDLIB_FLAGS}")
ENDIF(CMAKE_COMPILER_IS_GDC)
ENDIF(NOT CMAKE_D_CREATE_SHARED_LIBRARY)
# create a D shared module just copy the shared library rule
@ -135,8 +185,8 @@ IF(NOT CMAKE_D_CREATE_STATIC_LIBRARY)
ELSE(CMAKE_COMPILER_IS_GDC)
IF(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
SET(CMAKE_D_CREATE_STATIC_LIBRARY
"<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS> "
"<CMAKE_RANLIB> <TARGET> ")
"<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>"
"<CMAKE_RANLIB> <TARGET>")
ELSE(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
SET(CMAKE_D_CREATE_STATIC_LIBRARY
"${DMD_LIBRARIAN} -c -p256 <TARGET> <OBJECTS>")
@ -153,11 +203,11 @@ ENDIF(NOT CMAKE_D_COMPILE_OBJECT)
IF(NOT CMAKE_D_LINK_EXECUTABLE)
IF(CMAKE_COMPILER_IS_GDC)
SET(CMAKE_D_LINK_EXECUTABLE
"<CMAKE_D_COMPILER> <FLAGS> <CMAKE_D_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> ${CMAKE_OUTPUT_D_FLAG}<TARGET> <LINK_LIBRARIES>")
"<CMAKE_D_COMPILER> <FLAGS> <CMAKE_D_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> ${CMAKE_OUTPUT_D_FLAG}<TARGET> <LINK_LIBRARIES> ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE}")
ELSE(CMAKE_COMPILER_IS_GDC)
IF(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
SET(CMAKE_D_LINK_EXECUTABLE
"gcc <CMAKE_D_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -lphobos -lpthread -lm")
"gcc ${DLINK_FLAGS} <CMAKE_D_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -lpthread -lm ${DSTDLIB_FLAGS}")
ELSE(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
SET(CMAKE_D_LINK_EXECUTABLE
"<CMAKE_D_COMPILER> <FLAGS> <CMAKE_D_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> ${CMAKE_OUTPUT_D_FLAG}<TARGET> <LINK_LIBRARIES>")

View file

@ -2,6 +2,8 @@
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
@ -93,8 +95,14 @@ ENDIF(NOT CMAKE_COMPILER_IS_GDC_RUN)
# configure variables set in this file for fast reload later on
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeDCompiler.cmake.in
IF(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in
"${CMAKE_PLATFORM_ROOT_BIN}/CMakeDCompiler.cmake" IMMEDIATE)
MARK_AS_ADVANCED(CMAKE_AR)
ELSE(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeDCompiler.cmake.in
"${CMAKE_PLATFORM_ROOT_BIN}/CMakeDCompiler.cmake" IMMEDIATE)
ENDIF(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
MARK_AS_ADVANCED(CMAKE_AR)
SET(CMAKE_D_COMPILER_ENV_VAR "DC")

View file

@ -2,6 +2,8 @@
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
@ -15,13 +17,14 @@ SET (MOD_SRCS
CMakeTestDCompiler.cmake
CMakeDetermineDCompiler.cmake
FindGDCPath.cmake
UseDDoc.cmake
)
SET (PLAT_SRCS
Linux-dmd.cmake
Linux-gdc.cmake
Windows-dmd.cmake
Windows-gdc.cmake
Platform/Linux-dmd.cmake
Platform/Linux-gdc.cmake
Platform/Windows-dmd.cmake
Platform/Windows-gdc.cmake
)
INSTALL (FILES ${MOD_SRCS} DESTINATION ${CMAKE_ROOT}/Modules)

View file

@ -2,6 +2,8 @@
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
@ -19,16 +21,31 @@
IF(NOT CMAKE_D_COMPILER_WORKS)
MESSAGE(STATUS "Check for working D compiler: ${CMAKE_D_COMPILER}")
FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
"import std.stdio;\n"
"int main(char[][] args)\n"
"{ writefln(\"%s\", args[0]); return args.sizeof-1;}\n")
"{return args.sizeof-1;}\n")
STRING(REGEX MATCH "dmd" DMDTEST "${CMAKE_D_COMPILER}")
IF(DMDTEST STREQUAL "dmd")
IF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
TRY_COMPILE(CMAKE_D_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
OUTPUT_VARIABLE OUTPUT)
ELSE(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
TRY_COMPILE(CMAKE_D_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
CMAKE_FLAGS "-DLINK_LIBRARIES=${D_PATH}/lib/libphobos.a"
OUTPUT_VARIABLE OUTPUT)
ENDIF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
ELSE(DMDTEST STREQUAL "dmd")
TRY_COMPILE(CMAKE_D_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
OUTPUT_VARIABLE OUTPUT)
ENDIF(DMDTEST STREQUAL "dmd")
SET(C_TEST_WAS_RUN 1)
ENDIF(NOT CMAKE_D_COMPILER_WORKS)
IF(NOT CMAKE_D_COMPILER_WORKS)
MESSAGE(STATUS "Check for working D compiler: ${CMAKE_D_COMPILER} -- broken")
message(STATUS "To force a specific D compiler set the DC environment variable")
message(STATUS " ie - export DC=\"/opt/dmd/bin/dmd\"")
message(STATUS "If the D path is not set please use the D_PATH variable")
message(STATUS " ie - export D_PATH=\"/opt/dmd\"")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the D compiler works failed with "
"the following output:\n${OUTPUT}\n\n")
@ -47,6 +64,81 @@ ELSE(NOT CMAKE_D_COMPILER_WORKS)
# re-configure this file CMakeDCompiler.cmake so that it gets
# the value for CMAKE_SIZEOF_VOID_P
# configure variables set in this file for fast reload later on
IF(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeDCompiler.cmake IMMEDIATE)
ELSE(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeDCompiler.cmake.in
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeDCompiler.cmake IMMEDIATE)
ENDIF(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
ENDIF(NOT CMAKE_D_COMPILER_WORKS)
IF(NOT CMAKE_D_PHOBOS_WORKS)
MESSAGE(STATUS "Check for working Phobos")
FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
"import std.stdio;\n"
"int main(char[][] args)\n"
"{ writefln(\"%s\", args[0]); return args.sizeof-1;}\n")
IF(CMAKE_COMPILER_IS_GDC)
TRY_COMPILE(CMAKE_D_PHOBOS_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
CMAKE_FLAGS "-DLINK_LIBRARIES=gphobos"
OUTPUT_VARIABLE OUTPUT)
ELSE(CMAKE_COMPILER_IS_GDC)
TRY_COMPILE(CMAKE_D_PHOBOS_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
CMAKE_FLAGS "-DLINK_LIBRARIES=${D_PATH}/lib/libphobos.a"
COMPILE_DEFINITIONS "-I${D_PATH}/include -I${D_PATH}/import"
OUTPUT_VARIABLE OUTPUT)
ENDIF(CMAKE_COMPILER_IS_GDC)
SET(C_TEST_WAS_RUN 1)
ENDIF(NOT CMAKE_D_PHOBOS_WORKS)
IF(NOT CMAKE_D_PHOBOS_WORKS)
MESSAGE(STATUS "Check for working Phobos -- unavailable")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if Phobos works failed with "
"the following output:\n${OUTPUT}\n\n")
#MESSAGE(FATAL_ERROR "Phobos does not work")
ELSE(NOT CMAKE_D_PHOBOS_WORKS)
IF(C_TEST_WAS_RUN)
MESSAGE(STATUS "Check for working Phobos -- works")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if Phobos works passed with "
"the following output:\n${OUTPUT}\n\n")
ENDIF(C_TEST_WAS_RUN)
SET(CMAKE_D_PHOBOS_WORKS 1 CACHE INTERNAL "")
ENDIF(NOT CMAKE_D_PHOBOS_WORKS)
IF(NOT CMAKE_D_TANGO_WORKS)
MESSAGE(STATUS "Check for working Tango")
FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
"import tango.io.Stdout;"
"int main(char[][] args)\n"
"{Stdout.newline();return args.sizeof-1;}\n")
IF(CMAKE_COMPILER_IS_GDC)
TRY_COMPILE(CMAKE_D_TANGO_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
CMAKE_FLAGS "-DLINK_LIBRARIES=gtango"
OUTPUT_VARIABLE OUTPUT)
ELSE(CMAKE_COMPILER_IS_GDC)
TRY_COMPILE(CMAKE_D_TANGO_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testDCompiler.d
CMAKE_FLAGS "-DLINK_LIBRARIES=${D_PATH}/lib/libtango.a;${D_PATH}/lib/libphobos.a"
COMPILE_DEFINITIONS "-I${D_PATH}/include -I${D_PATH}/import"
OUTPUT_VARIABLE OUTPUT)
ENDIF(CMAKE_COMPILER_IS_GDC)
SET(C_TEST_WAS_RUN 1)
ENDIF(NOT CMAKE_D_TANGO_WORKS)
IF(NOT CMAKE_D_TANGO_WORKS)
MESSAGE(STATUS "Check for working Tango -- unavailable")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if Tango works failed with "
"the following output:\n${OUTPUT}\n\n")
#MESSAGE(FATAL_ERROR "Tango does not work: \n${OUTPUT}\n\n")
ELSE(NOT CMAKE_D_TANGO_WORKS)
IF(C_TEST_WAS_RUN)
MESSAGE(STATUS "Check for working Tango -- works")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if Tango works passed with "
"the following output:\n${OUTPUT}\n\n")
ENDIF(C_TEST_WAS_RUN)
SET(CMAKE_D_TANGO_WORKS 1 CACHE INTERNAL "")
ENDIF(NOT CMAKE_D_TANGO_WORKS)

View file

@ -1,6 +1,8 @@
CMakeD - CMake module for D Language
Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
Tim Burrell <tim.burrell@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View file

@ -2,6 +2,8 @@
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
@ -14,6 +16,8 @@
#
SET(GDC_POSSIBLE_INCLUDE_PATHS
/usr/include/d/4.2.1
/usr/include/d/4.2.0
/usr/include/d/4.1.2
/usr/include/d/4.1.1
/usr/include/d/4.1.0

View file

@ -1,20 +0,0 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
SET (CMAKE_D_FLAGS_INIT "")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g")
# SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
# SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -1,21 +0,0 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
SET (CMAKE_D_FLAGS_INIT "")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g")
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
#SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -0,0 +1,35 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
IF(CMAKE_D_USE_TANGO)
SET(DSTDLIB_FLAGS "-version=Tango")
ENDIF(CMAKE_D_USE_TANGO)
IF(CMAKE_D_USE_PHOBOS)
SET(DSTDLIB_FLAGS "-version=Phobos")
ENDIF(CMAKE_D_USE_PHOBOS)
IF(CMAKE_D_BUILD_DOCS)
SET(DDOC_FLAGS "-D -Dddocumentation")
#FOREACH(item ${CMAKE_D_DDOC_FILES})
# SET(DDOC_FLAGS "${DDOC_FLAGS} ${item}")
#ENDFOREACH(item)
ENDIF(CMAKE_D_BUILD_DOCS)
SET (CMAKE_D_FLAGS_INIT "-version=Posix ${DSTDLIB_FLAGS} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}")
# SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g ${DDOC_FLAGS}")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
# SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -0,0 +1,36 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
IF(CMAKE_D_USE_TANGO)
SET(DSTDLIB_FLAGS "-fversion=Tango")
ENDIF(CMAKE_D_USE_TANGO)
IF(CMAKE_D_USE_PHOBOS)
SET(DSTDLIB_FLAGS "-fversion=Phobos")
ENDIF(CMAKE_D_USE_PHOBOS)
IF(CMAKE_D_BUILD_DOCS)
SET(DDOC_FLAGS "-fdoc -fdoc-dir=documentation")
FOREACH(item ${CMAKE_D_DDOC_FILES})
SET(DDOC_FLAGS "${DDOC_FLAGS} -fdoc-inc=${item}")
ENDFOREACH(item)
ENDIF(CMAKE_D_BUILD_DOCS)
SET (CMAKE_D_FLAGS_INIT "-fversion=Posix ${DSTDLIB_FLAGS}")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g ${DDOC_FLAGS}")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
#SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -0,0 +1,36 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
IF(CMAKE_D_USE_TANGO)
SET(DSTDLIB_FLAGS "-version=Tango")
ENDIF(CMAKE_D_USE_TANGO)
IF(CMAKE_D_USE_PHOBOS)
SET(DSTDLIB_FLAGS "-version=Phobos")
ENDIF(CMAKE_D_USE_PHOBOS)
IF(CMAKE_D_BUILD_DOCS)
SET(DDOC_FLAGS "-D -Dddocumentation")
#FOREACH(item ${CMAKE_D_DDOC_FILES})
# SET(DDOC_FLAGS "${DDOC_FLAGS} ${item}")
#ENDFOREACH(item)
ENDIF(CMAKE_D_BUILD_DOCS)
SET (CMAKE_D_FLAGS_INIT "-version=Posix ${DSTDLIB_FLAGS} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}")
# SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g ${DDOC_FLAGS}")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
# SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -0,0 +1,36 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
IF(CMAKE_D_USE_TANGO)
SET(DSTDLIB_FLAGS "-fversion=Tango")
ENDIF(CMAKE_D_USE_TANGO)
IF(CMAKE_D_USE_PHOBOS)
SET(DSTDLIB_FLAGS "-fversion=Phobos")
ENDIF(CMAKE_D_USE_PHOBOS)
IF(CMAKE_D_BUILD_DOCS)
SET(DDOC_FLAGS "-fdoc -fdoc-dir=documentation")
FOREACH(item ${CMAKE_D_DDOC_FILES})
SET(DDOC_FLAGS "${DDOC_FLAGS} -fdoc-inc=${item}")
ENDFOREACH(item)
ENDIF(CMAKE_D_BUILD_DOCS)
SET (CMAKE_D_FLAGS_INIT "-fversion=Posix ${DSTDLIB_FLAGS}")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions ${DDOC_FLAGS}")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g ${DDOC_FLAGS}")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
#SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

61
cmaked/UseDDoc.cmake Normal file
View file

@ -0,0 +1,61 @@
# check if the user wants to build ddocs
#
# Copyright (c) 2007 Tim Burrell <tim.burrell@gmail.com>
#
# All rights reserved.
#
# See Copyright.txt for details.
#
# Do not build documentation by default
if (NOT CMAKE_D_BUILD_DOCS)
set(CMAKE_D_BUILD_DOCS False CACHE BOOLEAN TRUE FORCE)
else (NOT CMAKE_D_BUILD_DOCS)
# check for specified ddoc files
# default to the candydoc usual
set(CMAKE_D_BUILD_DOCS True CACHE BOOLEAN FALSE FORCE)
if (NOT CMAKE_D_DDOC_FILES)
set(CMAKE_D_DDOC_FILES "documentation/candydoc/candy.ddoc;documentation/candydoc/modules.ddoc" CACHE STRING FALSE FORCE)
else (NOT CMAKE_D_DDOC_FILES)
set(CMAKE_D_DDOC_FILES "${CMAKE_D_DDOC_FILES}" CACHE STRING FALSE FORCE)
endif (NOT CMAKE_D_DDOC_FILES)
# copy the candydoc files
file(GLOB_RECURSE CANDY_DOC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/candydoc/*")
foreach(item ${CANDY_DOC_FILES})
string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" item ${item})
configure_file(${item} ${CMAKE_CURRENT_BINARY_DIR}/documentation/${item} COPYONLY)
endforeach(item)
# create modules.ddoc
file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/*.d")
set(first True)
foreach(item ${sources})
# first make sure we're not config.d
string(REGEX MATCH "config\\.d" ignore ${item})
if (NOT ${ignore} MATCHES "")
# fix up the output
string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" item ${item})
string(REGEX REPLACE "\\.d" ".html" htmlFile ${item})
string(REGEX REPLACE "^.*/" "" htmlFile ${htmlFile})
string(REGEX REPLACE "\\.d" "" item ${item})
string(REGEX REPLACE "/" "." item ${item})
if (first)
set(modules "${item}")
set(first False)
set(CMAKE_D_DDOC_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/documentation/${htmlFile}" CACHE STRING FALSE FORCE)
else (first)
set(modules "${modules};${item}")
set(CMAKE_D_DDOC_CLEAN_FILES "${CMAKE_D_DDOC_CLEAN_FILES}" "${CMAKE_CURRENT_BINARY_DIR}/documentation/${htmlFile}" CACHE STRING FALSE FORCE)
endif (first)
endif (NOT ${ignore} MATCHES "")
endforeach(item)
# create formatted modules string
set(modString "MODULES = \n")
foreach(item ${modules})
set(modString "${modString}\t$(MODULE ${item})\n")
endforeach(item)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/documentation/candydoc/modules.ddoc" ${modString})
endif (NOT CMAKE_D_BUILD_DOCS)

View file

@ -1,20 +0,0 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
SET (CMAKE_D_FLAGS_INIT "")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g")
# SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
# SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -1,21 +0,0 @@
#
# CMakeD - CMake module for D Language
#
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
# All rights reserved.
#
# See Copyright.txt for details.
#
# Modified from CMake 2.6.5 gcc.cmake
# See http://www.cmake.org/HTML/Copyright.html for details
#
SET (CMAKE_D_FLAGS_INIT "")
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g")
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os")
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions")
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
#SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")

View file

@ -1,35 +0,0 @@
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
PROJECT (minwin_gtk D)
FIND_PACKAGE (GTK2)
IF (GTK2_FOUND)
INCLUDE_DIRECTORIES ( ${GTK2_INCLUDE_DIRS} )
SET (SRCS
minwin/all.d minwin/font.d minwin/layout.d minwin/peerimpl.d
minwin/app.d minwin/geometry.d minwin/listbox.d minwin/scroll.d
minwin/button.d minwin/group.d minwin/logging.d minwin/text.d
minwin/canvas.d minwin/gtk.d minwin/menu.d minwin/unittest.d
minwin/combo.d minwin/gtk_peers.d minwin/window.d
minwin/component.d minwin/icon.d minwin/multidg.d
minwin/dialog.d minwin/image.d minwin/paint.d
minwin/event.d minwin/label.d minwin/peer.d )
IF(CMAKE_COMPILER_IS_GDC)
ADD_DEFINITIONS (-fversion=GTK ${GTK2_DEFINITIONS})
ELSE(CMAKE_COMPILER_IS_DMD)
ADD_DEFINITIONS (-version=GTK ${GTK2_DEFINITIONS})
ENDIF(CMAKE_COMPILER_IS_GDC)
ADD_LIBRARY (minwin_gtk ${SRCS})
TARGET_LINK_LIBRARIES (minwin_gtk ${GTK2_LIBRARIES})
ADD_SUBDIRECTORY (minwin/samples)
ENDIF (GTK2_FOUND)

View file

@ -1,9 +0,0 @@
minwinchanges.diff
------------------
applied changes for CMakeD and compiler error fixes.
minwin/docs
-----------
not included because of not installed sample
if you want to look, see http://minwin.dsource.org

View file

@ -1,36 +0,0 @@
/* MinWin global import
*
* MinWin is the Minimal Window Toolkit. The goal is to provide
* basic cross-platform capabilities while still giving complete
* access to native peers and platform-specific features.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.all;
public {
import minwin.app;
import minwin.component;
import minwin.window;
import minwin.dialog;
import minwin.geometry;
import minwin.paint;
import minwin.font;
import minwin.button;
import minwin.label;
import minwin.text;
import minwin.multidg;
import minwin.layout;
import minwin.menu;
import minwin.group;
import minwin.event;
import minwin.icon;
import minwin.image;
import minwin.combo;
import minwin.listbox;
import minwin.canvas;
import minwin.scroll;
}

View file

@ -1,244 +0,0 @@
/* MinWin Application structure
*
* An Application encapsulates the global state provided by
* the OS when starting the application and it manages the event queue.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.app;
private {
import minwin.logging;
import minwin.multidg;
import minwin.event;
import std.string;
}
version(MinWin32) {
private import minwin.mswindows;
}
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();
extern (C) int MinWinMain(Application* app);
const int NO_ID = -1;
class MinWinException : Exception {
int id = NO_ID;
this(char[] msg) {
super(msg);
}
this(char[] msg, int id) {
this.id = id;
if (id == NO_ID)
super(msg);
else
super(format("%s (error code %x)",msg,id));
}
}
// Assert a condition is true and if not throw an exception.
void sysAssert(bool passed, char[] msg, int id = 0) {
if (!passed) {
version (MinWin32) {
if (GetVersion() < 0x80_00_00_00 || id != 0) {
throw new MinWinException(msg,id);
} else {
throw new MinWinException(msg,GetLastError());
}
} else {
throw new MinWinException(msg,id);
}
}
}
Application gApp;
version (MinWin32) {
extern (Windows)
void MinWinIdleProc(HWND hWnd, uint msg, uint id, DWORD time) {
gApp.idleDelegate();
}
struct Application {
char[] rsrc(char[] id, char[] group = "strings") {
wchar[] wres;
char[] cres;
if (useWfuncs)
wres.length = 64;
else
cres.length = 64;
int len;
for (;;) {
if (useWfuncs) {
len = cast(int)LoadStringW(gApp.hInstance,toUTF16z(id),wres.ptr,wres.length);
if (len < wres.length) break;
else wres.length = 2*wres.length;
}
else {
len = cast(int)LoadStringA(gApp.hInstance,toMBSz(id),cres.ptr,cres.length);
if (len < cres.length) break;
else cres.length = 2*cres.length;
}
}
if (useWfuncs)
return toUTF8(wres[0..len]);
else {
return fromMBSz(cres[0..len].ptr);
}
}
char[][] cmdLineArgs(){
// TODO: parse cmd line args
return parsedCmdLineArgs;
}
MultiDelegate!() idleDelegate;
private uint fTimerID;
private uint fIdleTime;
uint idleTime() {
return fIdleTime;
}
void idleTime(uint t) { // time 0 means stop
fIdleTime = t;
if (fTimerID) {
BOOL ok = KillTimer(null,fTimerID);
sysAssert(ok != false, "Failed to kill existing timer");
}
if (t) {
fTimerID = SetTimer(null,0,t,&MinWinIdleProc);
sysAssert(fTimerID != 0, "Failed to set timer");
}
}
int enterEventLoop() {
while (nextEvent(&event)) {
// TODO: check IsDialogMessage
dispatchEvent(&event);
}
return 1;
}
void exitEventLoop() {
PostQuitMessage(0);
}
HINSTANCE hInstance;
HINSTANCE hPrevInstance;
LPSTR lpCmdLine;
char[][] parsedCmdLineArgs;
int nCmdShow;
Event event;
}
extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
int result;
gc_init(); // initialize garbage collector
_minit(); // initialize module constructor table
try
{
_moduleCtor(); // call module constructors
_moduleUnitTests(); // run unit tests (optional)
gApp.hInstance = hInstance;
gApp.hPrevInstance = hPrevInstance;
gApp.nCmdShow = nCmdShow;
version (LOG) log.writefln("about to enter MinWinMain");
result = MinWinMain(&gApp);
version (LOG) log.writefln("done with MinWinMain");
}
catch (Object o) // catch any uncaught exceptions
{
MessageBoxX(null, o.toString(), "Error",MB_OK | MB_ICONEXCLAMATION);
result = 0; // failed
}
version(LOG) log.close();
if (gApp.fTimerID) {
BOOL ok = KillTimer(null,gApp.fTimerID);
sysAssert(ok != false, "Failed to kill existing timer at exit");
}
gc_term(); // run finalizers; terminate garbage collector
return result;
}
} else version (GTK) {
private {
import minwin.gtk;
import std.string;
import std.file;
}
extern (C)
gboolean MinWinIdleProc(gpointer data) {
gApp.idleDelegate();
return true;
}
struct Application {
char[][] cmdLineArgs;
char[] rsrc(char[] id, char[] group = "strings") {
// TODO
return "";
}
char[] resourcePath;
int enterEventLoop() {
gtk_main();
return 1;
}
void exitEventLoop() {
gtk_main_quit();
}
MultiDelegate!() idleDelegate;
uint fIdleTime;
uint idleTime() {
return fIdleTime;
}
guint fTimerID;
static
void idleTime(uint t) {
gApp.fIdleTime = t;
if (gApp.fTimerID)
g_source_remove(gApp.fTimerID);
if (t)
gApp.fTimerID = g_timeout_add(t,&MinWinIdleProc,null);
}
}
int main(char[][] args) {
gApp.cmdLineArgs = args;
char*[] argv;
argv.length = args.length;
foreach (int n, char[] str; args) {
argv[n] = toStringz(str);
}
int argc = args.length;
char**argvp = argv.ptr;
gtk_init(&argc,&argvp);
int res = MinWinMain(&gApp);
version(LOG) log.close();
return res;
}
}

View file

@ -1,376 +0,0 @@
/* MinWin Button classes
*
* Various button classes like PushButtons
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.button;
public import minwin.component;
private {
import minwin.icon;
import minwin.app;
import minwin.window;
import minwin.peerimpl;
import minwin.logging;
import std.string;
import minwin.peer;
}
abstract class AbstractButton : WindowChild {
int cmd;
Icon icon();
void icon(Icon c);
char[] text();
void text(char[] c);
MultiDelegate!(Component) actionDelegate;
void doCommand(int cmd) {
// only command is action command
version(LOG) log.writefln("calling action delegate");
if (cmd == ButtonClickedCommand) {
actionDelegate(cast(Component)this);
if (this.cmd != 0) {
super.doCommand(this.cmd);
}
}
}
}
abstract class AbstractToggleButton : AbstractButton {
bool selected();
void selected(bool x);
}
version (MinWin32) {
version = SimpleToggleGroup;
}
version (SimpleToggleGroup) {
private import minwin.dialog;
// manages selected state between several ToggleButtons
class ToggleGroup {
AbstractToggleButton[] buttons;
void addButton(AbstractToggleButton[] btns ...) {
buttons ~= btns;
foreach(b; btns) {
b.actionDelegate ~= &select;
}
}
void select(Component c) {
version (LOG) log.writefln("selecting component ", c);
foreach(AbstractToggleButton b; buttons) {
b.selected = (b is c);
}
}
void select(int index) {
foreach(int n, AbstractToggleButton b; buttons) {
b.selected = n == index;
}
}
int selected() {
foreach(int n, AbstractToggleButton b; buttons) {
version(LOG)log.printf("testing button %d %x\n",n,b);
if (b && b.selected)
return n;
}
version(LOG)log.printf(" no button selected??\n");
return 0;
}
}
}
version (MinWin32) {
private import minwin.mswindows;
const int ButtonClickedCommand = BN_CLICKED;
template PreferredSizeImpl() {
const int paddingX;
const int paddingY;
Point preferredSize() {
int width,height;
HDC dc = GetDC(peer);
sysAssert(dc !is null, "Failed to get button DC in preferredSize");
SIZE s;
try {
Font f = standardFont(StandardFont.Gui);
HFONT oldfont = SelectObject(dc,f.peer);
sysAssert(oldfont !is null, "Failed to get Button font in preferredSize");
BOOL status = GetTextExtentPoint32X(dc,text_data,text_data.length,&s);
SelectObject(dc,oldfont);
sysAssert(status != false, "Failed to get font extents in preferredSize");
} finally {
ReleaseDC(peer,dc);
}
width = s.cx > 75-paddingX ? s.cx+paddingX*2 : 75;
height = s.cy > 23-paddingY ? s.cy+paddingY*2 : 23;
if (userPreferredWidth_data > 0)
width = userPreferredWidth_data;
if (userPreferredHeight_data > 0)
height = userPreferredHeight_data;
return XY(width,height);
// Requires WinXP
// SIZE sz;
// SendMessageA(peer,BCM_GETIDEALSIZE,0,cast(int)&sz);
// width = sz.cx;
// height = sz.cy;
}
}
template SelectedImpl() {
bool selected() {
version(LOG)log.printf("sending message...");
bool res = SendMessageA(peer,BM_GETCHECK,0,0) == BST_CHECKED;
version(LOG)log.printf(" got %d\n",res);
return res;
}
void selected(bool x) {
SendMessageA(peer,BM_SETCHECK,x,0);
}
}
template IconTextImpl() {
Icon icon_data;
Icon icon() { return icon_data; }
void icon(Icon c) {
icon_data = c;
SendMessageA(peer,BM_SETIMAGE,cast(WPARAM)c.peer,0);
}
char[] text_data;
char[] text() { return text_data; }
void text(char[] c) {
text_data = c;
SendMessageX(peer,WM_SETTEXT,0,c);
}
}
class Button : AbstractButton {
this(Component parent, char[] intext, char[] name = "") {
paddingX = GetSystemMetrics(SM_CXFIXEDFRAME)*2;
paddingY = GetSystemMetrics(SM_CXFIXEDFRAME)*2;
PeerForAdd parentp = parent.getPeerForAdd();
text_data = intext;
peer = CreateWindowX("BUTTON",intext,
BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer Button");
finish_button_setup(this,parent,name,peer);
}
mixin WindowChildImpl!();
mixin IconTextImpl!();
mixin PreferredSizeImpl!();
}
class CheckBox : AbstractToggleButton {
this(Component parent, char[] intext, char[] name = "") {
paddingX = GetSystemMetrics(SM_CXMENUCHECK);
paddingY = GetSystemMetrics(SM_CYFIXEDFRAME)*2;
PeerForAdd parentp = parent.getPeerForAdd();
text_data = intext;
peer = CreateWindowX("BUTTON",intext,
BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer CheckBox");
finish_button_setup(this,parent,name,peer);
}
mixin WindowChildImpl!();
mixin SelectedImpl!();
mixin IconTextImpl!();
mixin PreferredSizeImpl!();
}
class RadioButton : AbstractToggleButton {
this(Component parent, char[] intext, char[] name = "") {
paddingX = GetSystemMetrics(SM_CXMENUCHECK);
paddingY = GetSystemMetrics(SM_CYFIXEDFRAME)*2;
PeerForAdd parentp = parent.getPeerForAdd();
text_data = intext;
peer = CreateWindowX("BUTTON",intext,
BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer RadioButton");
finish_button_setup(this,parent,name,peer);
}
mixin WindowChildImpl!();
mixin SelectedImpl!();
mixin IconTextImpl!();
mixin PreferredSizeImpl!();
}
class ToggleButton : AbstractToggleButton {
this(Component parent, char[] intext, char[] name = "") {
paddingX = GetSystemMetrics(SM_CXFIXEDFRAME)*2;
paddingY = GetSystemMetrics(SM_CYFIXEDFRAME)*2;
PeerForAdd parentp = parent.getPeerForAdd();
text_data = intext;
peer = CreateWindowX("BUTTON",intext,
BS_PUSHLIKE | BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer ToggleButton");
finish_button_setup(this,parent,name,peer);
}
mixin WindowChildImpl!();
mixin SelectedImpl!();
mixin IconTextImpl!();
mixin PreferredSizeImpl!();
}
private void finish_button_setup(AbstractButton b,Component parent,
char[] name, WindowChildPeer peer) {
setWindowChildPeer(b,peer,OWNS_PEER);
b.name = name;
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
parent.addChild(b);
}
} else version (GTK) {
private import minwin.gtk;
private import std.c.string;
const int ButtonClickedCommand = 1;
abstract class HeavyAbstractToggleButton : AbstractToggleButton {
mixin WindowChildImpl!();
}
// manages selected state between several ToggleButtons
class ToggleGroup {
HeavyAbstractToggleButton[] buttons;
void addButton(HeavyAbstractToggleButton[] btns ...) {
buttons ~= btns;
foreach(b; btns) {
RadioButton rb = cast(RadioButton)b;
if (rb is null) {
b.actionDelegate ~= &select;
} else {
// set the RadioButton group to its sibling, if any
if (buttons.length != 0) {
GtkRadioButton* rbpeer1 = cast(GtkRadioButton*)buttons[0].peer;
GtkRadioButton* rbpeer = cast(GtkRadioButton*)rb.peer;
GSList* group = gtk_radio_button_get_group(rbpeer1);
gtk_radio_button_set_group(rbpeer,group);
}
}
}
}
void select(Component c) {
version (LOG) log.writefln("selecting component ", c);
foreach(HeavyAbstractToggleButton b; buttons) {
b.selected = (b is c);
}
}
void select(int index) {
foreach(int n, HeavyAbstractToggleButton b; buttons) {
b.selected = n == index;
}
}
int selected() {
foreach(int n, HeavyAbstractToggleButton b; buttons) {
if (b.selected)
return n;
}
}
}
template SelectedImpl() {
bool selected() {
return gtk_toggle_button_get_active(cast(GtkToggleButton*)peer) != 0;
}
void selected(bool x) {
gtk_toggle_button_set_active(cast(GtkToggleButton*)peer,x);
}
}
template IconTextImpl() {
Icon icon_data;
Icon icon() { return icon_data; }
void icon(Icon c) {
icon_data = c;
// SendMessageA(peer,BM_SETIMAGE,cast(WPARAM)c.peer,0);
}
char[] text() {
char* str = gtk_button_get_label(cast(GtkButton*)peer);
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] c) {
gtk_button_set_label(cast(GtkButton*)peer,toStringz(c));
}
}
class Button : AbstractButton {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_button_new_with_label(str);
finish_button_setup(this,peer,parentp,parent);
}
mixin WindowChildImpl!();
mixin IconTextImpl!();
}
class CheckBox : HeavyAbstractToggleButton {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_check_button_new_with_label(str);
finish_button_setup(this,peer,parentp,parent);
}
mixin SelectedImpl!();
mixin IconTextImpl!();
}
class RadioButton : HeavyAbstractToggleButton {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_radio_button_new_with_label(null,str);
finish_button_setup(this,peer,parentp,parent);
}
mixin SelectedImpl!();
mixin IconTextImpl!();
}
class ToggleButton : HeavyAbstractToggleButton {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_toggle_button_new_with_label(str);
finish_button_setup(this,peer,parentp,parent);
}
mixin SelectedImpl!();
mixin IconTextImpl!();
}
private void finish_button_setup(AbstractButton b,
WindowChildPeer peer,
PeerForAdd parentp,
Component parent) {
gtk_widget_set_sensitive(peer,true);
gtk_container_add(cast(GtkContainer*)parentp,peer);
g_signal_connect_data(peer,"clicked",
cast(GCallback)&mw_buttonclick_callback,
cast(gpointer)b,
null,cast(GConnectFlags)0);
setWindowChildPeer(b,peer,OWNS_PEER);
parent.addChild(b);
gtk_widget_realize(peer);
b.visible = true;
}
extern (C) void mw_buttonclick_callback(GtkButton *but, gpointer ud) {
Component c = cast(Component) ud;
if (c) {
c.doCommand(ButtonClickedCommand);
}
}
}

View file

@ -1,273 +0,0 @@
/* MinWin Canvas class
*
* A Canvas is a component that fires key and mouse events and has no
* other builtin capabilities
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.canvas;
private {
import minwin.component;
import minwin.event;
import minwin.app;
import minwin.paint;
import minwin.logging;
import minwin.window;
import minwin.peerimpl;
import minwin.image;
import std.string;
}
template SharedCanvasImpl() {
// events
MultiDelegate!(Component,KeyEvent*) keyDelegate;
MultiDelegate!(Component,MouseEvent*) mouseDelegate;
MultiDelegate!(Component,GContext) paintDelegate;
}
version (MinWin32) {
private import minwin.mswindows;
// generic heavyweight window child
class Canvas : WindowChild {
this(Component parent, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
peer = CreateWindowA("MinWinCanvas","",
WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer Canvas");
this.name = name;
version(LOG)log.printf("canvas ctor %x peer %x\n",this,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
}
mixin SharedCanvasImpl!();
mixin WindowChildImpl!();
Point preferredSize(){
int width = 60;
int height = 60;
if (userPreferredWidth > 0)
width = userPreferredWidth;
if (userPreferredHeight > 0)
height = userPreferredHeight;
return XY(width,height);
}
void backgroundColor(Color c) {
// TODO
}
mixin CommonEventSourceImpl!();
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
version (LOG) log.printf(" in canvas windowproc msg %d\n",uMsg);
bool doDefault = true;
if (uMsg <= WM_KEYLAST && uMsg >= WM_KEYFIRST) {
version(LOG) log.writefln("got canvas key event %d %d",uMsg,wParam);
keyDelegate(this, cast(KeyEvent*)&gApp.event);
} else if (uMsg <= WM_MOUSELAST && uMsg >= WM_MOUSEFIRST) {
MouseEvent ev;
mouseDelegate(this, cast(MouseEvent*)&gApp.event);
} else {
switch (uMsg) {
case WM_PAINT:
version (LOG) log.writefln(" got canvas paint");
repaintNow();
break;
case WM_DESTROY:
version (LOG) log.writefln(" got canvas destroy");
hasPeer = NO_PEER;
default:
version (LOG) log.writefln(" got canvas default");
break;
}
}
return doDefault;
}
}
extern(Windows) int MinWinCanvasProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
version(LOG) log.printf("in minwin canvas proc hwnd %p\n",hWnd);
bool doDefault = true;
Canvas canvas = cast(Canvas)peerToWindowChild(hWnd);
version(LOG) log.printf("in minwin canvas proc canvas %p\n",canvas);
if (canvas !is null)
doDefault = canvas.WindowProc(hWnd,uMsg,wParam,lParam) != 0;
if (doDefault)
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
else
return 0;
}
static this() {
HINSTANCE hInst = GetModuleHandleA(null);
WNDCLASSA wc;
wc.lpszClassName = "MinWinCanvas";
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MinWinCanvasProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_ARROW);
wc.hbrBackground = null;
// wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1); // not +1 for default
wc.lpszMenuName = null;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClassA(&wc);
}
} else version (GTK) {
private import minwin.gtk;
class Canvas : WindowChild {
this(Component parent, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
peer = gtk_drawing_area_new();
gtk_widget_add_events(peer,GdkEventMask.GDK_KEY_PRESS_MASK |
GdkEventMask.GDK_KEY_RELEASE_MASK |
GdkEventMask.GDK_EXPOSURE_MASK |
GdkEventMask.GDK_POINTER_MOTION_MASK |
GdkEventMask.GDK_BUTTON_PRESS_MASK |
GdkEventMask.GDK_BUTTON_RELEASE_MASK);
g_signal_connect_data(peer,"expose-event",
cast(GCallback)&mw_canvas_expose_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"key-press-event",
cast(GCallback)&mw_canvas_key_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"key-release-event",
cast(GCallback)&mw_canvas_key_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"motion-notify-event",
cast(GCallback)&mw_can_mouse_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"button-press-event",
cast(GCallback)&mw_can_button_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"button-release-event",
cast(GCallback)&mw_can_button_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
GtkObject* obj = cast(GtkObject*)peer;
obj.flags |= GtkWidgetFlags.GTK_CAN_FOCUS;
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
}
mixin CommonEventSourceImpl!();
void backgroundColor(Color c) {
GdkWindow* win = (cast(GtkWidget*)peer).window;
GdkColor nc;
// look up GdkColor for rgb values in c using rgb colormap
gdk_window_set_background(win,&nc);
}
GContext getGContext(Event* paintEvent) {
GContext gc = newGContext();
// GtkWidget* widget = cast(GtkWidget*)peer;
GdkWindow* gwin = peer.window;
sysAssert(gwin !is null,"Canvas peer has no window",0);
// version(LOG) log.printf(" CANVAS DRAWABLE is %x\n",gwin);
gc.drawable = cast(GdkDrawable*)gwin;
gc.layout = gtk_widget_create_pango_layout(peer,"");
gc.peer = gdk_gc_new(gc.drawable);
gc.hasPeer = OWNS_PEER;
gc.paintEvent = cast(GdkEventExpose*)paintEvent;
return gc;
}
// share with Window modulo peer vs content
Image getCompatibleImage(int width, int height) {
GtkWidget* widget = peer;
GdkDrawable* gwin = cast(GdkDrawable*)widget.window;
// ImagePeer bm = gdk_pixbuf_new(GdkColorspace.GDK_COLORSPACE_RGB,
// false,8,width,height);
int depth = gdk_drawable_get_depth(gwin);
ImagePeer bm = gdk_pixmap_new(gwin,width,height,depth);
version(LOG) log.writefln("create bitmap %x",cast(int)bm);
Image res = new Image(bm);
res.width = width;
res.height = height;
res.hasPeer = OWNS_PEER;
return res;
}
// share with Window modulo peer vs content
Image loadCompatibleImage(char[] imageKey, char[] fmt = "bmp") {
GtkWidget* widget = peer;
GdkDrawable* gwin = cast(GdkDrawable*)widget.window;
GError* err;
char[] fname = imageKey;
if (gApp.resourcePath.length > 0) {
fname = gApp.resourcePath ~ "/" ~ fname;
}
fname = fname ~ "." ~ fmt;
GdkPixbuf* pbuf = gdk_pixbuf_new_from_file(toStringz(fname),&err);
int width = gdk_pixbuf_get_width(pbuf);
int height = gdk_pixbuf_get_height(pbuf);
int depth = gdk_drawable_get_depth(gwin);
GdkColormap* cmap = gdk_drawable_get_colormap(gwin);
ImagePeer bm = gdk_pixmap_new(gwin,width,height,depth);
gdk_pixbuf_render_pixmap_and_mask_for_colormap(pbuf,cmap,&bm,null,0);
Image res = new Image(bm);
res.width = width;
res.height = height;
res.hasPeer = OWNS_PEER;
return res;
}
mixin SharedCanvasImpl!();
mixin WindowChildImpl!();
}
extern (C) gboolean mw_canvas_expose_callback(GtkWidget* w,
GdkEventExpose* event,
gpointer ud) {
Canvas c = cast(Canvas) ud;
if (c) {
c.repaintNow(cast(Event*)event);
}
return false;
}
extern (C) gboolean mw_canvas_key_callback(GtkWidget* w,
GdkEventKey* event,
gpointer ud) {
Canvas c = cast(Canvas) ud;
if (c && !c.keyDelegate.isEmpty) {
c.keyDelegate(c,cast(KeyEvent*)event);
}
return false;
}
extern (C) gboolean mw_can_mouse_callback(GtkWidget* w,
GdkEventMotion* event,
gpointer ud) {
Canvas c = cast(Canvas) ud;
if (c && !c.mouseDelegate.isEmpty) {
// TODO this should be made into a GdkEventButton
c.mouseDelegate(c,cast(MouseEvent*)event);
}
return false;
}
extern (C) gboolean mw_can_button_callback(GtkWidget* w,
GdkEventButton* event,
gpointer ud) {
Canvas c = cast(Canvas) ud;
if (c && !c.mouseDelegate.isEmpty) {
// TODO this should be made into a GdkEventButton
c.mouseDelegate(c,cast(MouseEvent*)event);
}
return false;
}
}

View file

@ -1,165 +0,0 @@
/* MinWin ComboBox class
*
* Drop-down list of items to choose from.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.combo;
private {
import minwin.component;
import minwin.app;
import minwin.window;
import minwin.peerimpl;
import std.string;
import minwin.logging;
}
version (MinWin32) {
// bug: clicking on the drop down button doesn't show the list
private import minwin.mswindows;
class ComboBox : WindowChild {
bool editable_data;
bool editable() { return editable_data; } // read-only
this(Component parent, char[][] text, bool editable = true, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
editable_data = editable;
int style = editable?(CBS_DROPDOWN|CBS_AUTOHSCROLL):CBS_DROPDOWN;
peer = CreateWindowX("COMBOBOX","",
style | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer ComboBox");
setWindowChildPeer(this,peer,OWNS_PEER);
foreach (char[] s; text) {
SendMessageX(peer,CB_ADDSTRING,0,s);
}
this.name = name;
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
parent.addChild(this);
}
mixin WindowChildImpl!();
Point preferredSize(){
// width = SendMessageA(peer,CB_GETDROPPEDWIDTH,0,0);
// height = SendMessageA(peer,CB_GETITEMHEIGHT,cast(WPARAM)-1,0);
int width = 75;
int height = 63;
return XY(width,height);
}
// -1 for custom text
int selection() {
return SendMessageA(peer,CB_GETCURSEL,0,0);
}
void selection(int n) {
SendMessageA(peer,CB_SETCURSEL,n,0);
version (LOG) log.writefln("number of item is %d",
SendMessageA(peer,CB_GETCOUNT,0,0));
}
}
/*
extern(Windows) int MinWinComboBoxProc(HWND hWnd, uint uMsg,
WPARAM wParam, LPARAM lParam) {
if (uMsg ==
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}
static this() {
HINSTANCE hInst = GetModuleHandleA(null);
WNDCLASSA wc;
wc.lpszClassName = "MinWinComboBox";
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MinWinComboBoxProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_ARROW);
wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1); // not +1 for default
wc.lpszMenuName = null;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClassA(&wc);
}
*/
} else version (GTK) {
private import minwin.gtk;
private import std.c.string;
class ComboBox : WindowChild {
bool editable_data;
bool editable() { return editable_data; } // read-only
this(Component parent, char[][] text, bool editable = true, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
editable_data = editable;
if (editable_data) {
peer = gtk_combo_box_entry_new_text();
} else {
peer = gtk_combo_box_new_text();
}
GtkComboBox* box = cast(GtkComboBox*)peer;
foreach (char[] s; text)
gtk_combo_box_append_text(box,toStringz(s));
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
}
// -1 for custom text
int selection() {
GtkComboBox* box = cast(GtkComboBox*)peer;
return gtk_combo_box_get_active(box);
}
void selection(int n) {
GtkComboBox* box = cast(GtkComboBox*)peer;
gtk_combo_box_set_active(box,n);
}
char[] text() {
char* str;
if (!editable) {
GtkComboBox* box = cast(GtkComboBox*)peer;
GtkTreeModel* model = gtk_combo_box_get_model(box);
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first(model,&iter)) {
int n = selection();
GValue* val;
while (n--) {
gtk_tree_model_iter_next(model,&iter);
}
gtk_tree_model_get_value(model,&iter,0,val);
str = *(cast(char**)val);
g_value_unset(val);
}
} else {
GtkEntry* box = cast(GtkEntry*)((cast(GtkBin*)peer).child);
str = gtk_entry_get_text(box);
}
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] s) {
if (editable) {
GtkEntry* box = cast(GtkEntry*)((cast(GtkBin*)peer).child);
char* str = toStringz(s);
gtk_entry_set_text(box,str);
}
}
mixin WindowChildImpl!();
}
}

View file

@ -1,279 +0,0 @@
/* MinWin Component class
*
* A Component is the root of the widget inheritance tree.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.component;
public {
import minwin.multidg;
import minwin.geometry;
import minwin.peer;
}
private {
import minwin.event;
import minwin.layout;
import minwin.logging;
}
abstract class Component {
// Peer management
mixin PeerMixin!();
// disposePeer will dipose of the system resource associated
// with this object if it owns the peer and the object does
// not have any parent. It is assumed that an object with a
// parent will have its peer disposed when the parent is disposed.
void disposePeer();
PeerForAdd getPeerForAdd() { return null; }
void getPeerOffset(inout int x, inout int y) {
x = 0;
y = 0;
}
void dispose() {
Component ch = child;
while (ch !is null) {
ch.dispose();
ch = ch.next;
}
disposePeer();
}
// Name property used for resource lookup on X and debugging
char[] name;
// Application data associative array for user data
void*[char[]] userdata;
void doCommand(int cmd) {
if (parent)
parent.doCommand(cmd);
}
void requestFocus() {}
// size management
void getMinimumSize(inout int width, inout int height) {
//todo: ask layout
width = 0;
height = 0;
}
void getMaximumSize(inout int width, inout int height) {
//todo: ask layout
width = int.max;
height = int.max;
}
abstract void getBounds(inout Rect r);
abstract void setBounds(inout Rect r);
Rect bounds() {
Rect r;
getBounds(r);
return r;
}
void bounds(Rect r) {
setBounds(r);
}
void getLayoutBounds(inout Rect r) {
Point s = size;
version(LOG)log.writefln("getLayoutBounds got size %d %d",s.x,s.y);
r.LTWH(0,0,s.x,s.y);
}
void size(Point s);
Point size() {
Rect bounds;
getBounds(bounds);
version(LOG)log.writefln("size function got width,height %d %d",bounds.width,bounds.height);
Point res;
res.x = bounds.width;
res.y = bounds.height;
return res;
}
int width() {
Rect bounds;
getBounds(bounds);
return bounds.width;
}
int height() {
Rect bounds;
getBounds(bounds);
return bounds.height;
}
// property to request a particular width no matter what layout
int userPreferredWidth_data;
final int userPreferredWidth() { return userPreferredWidth_data; }
void userPreferredWidth(int width) {
userPreferredWidth_data = width;
// childLayoutDirty = true;
// repaint();
}
// property to request a particular height no matter what layout
int userPreferredHeight_data;
final int userPreferredHeight() { return userPreferredHeight_data; }
void userPreferredHeight(int height) {
userPreferredHeight_data = height;
// childLayoutDirty = true;
// repaint();
}
void userPreferredSize(int width, int height) {
userPreferredHeight = height;
userPreferredWidth = width;
}
Point preferredSize(){
Point p;
if (layoutMgr) {
p = layoutMgr.preferredSize(this);
}
if (userPreferredWidth() > 0)
p.x = userPreferredWidth();
if (userPreferredHeight() > 0)
p.y = userPreferredHeight();
return p;
}
// visible property
void visible(bool vis);
bool visible();
// enabled property
void enabled(bool ena);
bool enabled();
Component getRootAncestor() {
Component top = this;
while (top.parent !is null) {
top = top.parent;
}
return top;
}
// hierarchy management
Component parent;
Component child;
Component next;
Component prev;
Component last() {
return child ? child.prev : null;
}
// loop over children
int opApply(int delegate(inout Component c) dg) {
int res = 0;
Component c = child;
if (c) {
do {
res = dg(c);
c = c.next;
} while(!res && c !is child);
}
return res;
}
// link two component as siblings.
// should an api be exposed to re-arrange without getting the peer?
void link(Component left, Component right) {
left.next = right;
right.prev = left;
}
void opCatAssign(Component x) {
addChild(x);
}
void addChild(Component x) {
x.parent = this;
if (!child) {
child = x;
x.prev = x.next = x;
} else {
link(last,x);
link(x,child);
}
}
void removeChild(Component x) {
Component old = last;
if (x is child) {
if (child is last)
child = null;
else
child = child.next;
}
link(x.prev,x.next);
x.prev = null;
x.next = null;
x.parent = null;
}
// layout management. TODO: invalidate and repaint on change
LayoutManager layoutMgr;
bool childLayoutDirty = true;
bool parentOwnsLayout_data = true;
bool parentOwnsLayout() { return parentOwnsLayout_data; }
void parentOwnsLayout(bool x) {
parentOwnsLayout_data = x;
if (parent) {
parent.childLayoutDirty = true;
parent.repaint();
}
}
bool parentOwnsVisibility = true;
void layout(bool validateParent) {
if (parent && validateParent)
parent.layout(true);
if (childLayoutDirty) {
if (layoutMgr)
layoutMgr.layout(this);
childLayoutDirty = false;
}
foreach( Component ch; this) {
ch.layout(false);
}
}
void pack() {
int width,height;
Point s;
if (layoutMgr) {
s = layoutMgr.preferredSize(this);
version(LOG) log.writefln("preferred size %d %d",s.x,s.y);
size = s;
childLayoutDirty = true;
version(LOG) log.printf("in pack about to repaint %x\n",this);
repaint();
version(LOG) log.printf("in pack done repaint about to layout %x\n",this);
layout(false);
version(LOG) log.printf("in pack done layout %x\n",this);
}
}
// painting and graphics context management
void repaint() {
version(LOG) log.printf("in component.repaint for %x\n",this);
foreach ( Component c; this) {
version(LOG) log.printf(" repaint for child %x of %x\n",c,this);
c.repaint();
}
}
bool clearBackgroundOnPaint = true;
void repaint(inout Rect r) {}
}
class WindowChild : Component {
WindowChildPeer getPeer() { return null; }
}

View file

@ -1,468 +0,0 @@
/* MinWin Dialog class
*
* A general dialog class and utility helper dialogs
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.dialog;
private {
import std.string;
import std.c.string;
import minwin.peerimpl;
import minwin.font;
import minwin.event;
import minwin.component;
import minwin.menu;
import minwin.app;
import minwin.logging;
import minwin.icon;
import minwin.image;
}
version (MinWin32) {
private import minwin.mswindows;
class Dialog : AbstractWindow {
AbstractWindow owner;
bool modal_data;
bool visible_data;
this(AbstractWindow owner, char[] title = "", bool modal = true, char[] name = "") {
Rect r;
owner.getBounds(r);
DWORD style = WS_TABSTOP | WS_POPUP | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU;
peer = CreateWindowX("MinWinDialog", title,
style & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX,
r.left, r.top,
DefaultWindowWidth, DefaultWindowHeight,
owner.peer,
cast(HMENU) null, gApp.hInstance, null);
sysAssert(peer !is null, "Failed to create peer Dialog");
setWindowPeer(this,peer,OWNS_PEER);
backgroundPeer = CreateSolidBrush(systemBackgroundColor().native);
this.name = name;
this.owner = owner;
modal_data = modal;
WindowList[this] = this; // prevent garbage collection
}
this(WindowPeer peer) {
setWindowPeer(this,peer,FOREIGN_PEER);
WindowList[this] = this; // prevent garbage collection
}
AbstractWindow[] originalWindows;
int[] originalEnabledState;
void visible(bool vis) {
if (modal_data && !vis && visible_data) {
// make sure original states are restored before hiding
foreach(int n, AbstractWindow w; originalWindows) {
if (IsWindow(w.peer)) {
EnableWindow(w.peer,originalEnabledState[n]);
}
}
originalWindows = null;
originalEnabledState = null;
}
version (LOG) log.writefln("setting dialog visible %d",cast(int)vis);
super.visible(vis);
version (LOG) log.writefln("done with super vis");
visible_data = vis;
if (modal_data && vis) {
cancelCloseDelegate ~= delegate bool(Component c) {
Dialog dlg = cast(Dialog)c;
if (!dlg || !dlg.owner) return false;
EnableWindow(dlg.owner.peer,1);
return false;
};
version (LOG) log.writefln("disabling windows dialog");
originalWindows = WindowList.values;
originalEnabledState.length = originalWindows.length;
foreach(int n, AbstractWindow w; originalWindows) {
originalEnabledState[n] = IsWindowEnabled(w.peer) != 0;
version (LOG) log.writefln("disable %d %p for dialog",n,w);
if (originalEnabledState[n] != 0 && (w !is this)) {
EnableWindow(w.peer,0);
}
}
while (visible_data && IsWindow(peer)) {
version (LOG) log.writefln("in modal loop for %p",this);
if (!GetMessageA(&gApp.event.native, cast(HWND) null, 0, 0)) {
PostQuitMessage(0); // quit out of next event loop
break;
}
if (!IsDialogMessageA(peer, &gApp.event.native)) {
TranslateMessage(&gApp.event.native);
DispatchMessageA(&gApp.event.native);
}
}
visible_data = false;
foreach(int n, AbstractWindow w; originalWindows) {
if (IsWindow(w.peer)) {
EnableWindow(w.peer,originalEnabledState[n]);
}
}
}
}
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
bool doDefault = true;
if (uMsg <= WM_KEYLAST && uMsg >= WM_KEYFIRST) {
keyDelegate(this,cast(KeyEvent*)&gApp.event);
} else if (uMsg <= WM_MOUSELAST && uMsg >= WM_MOUSEFIRST) {
mouseDelegate(this,cast(MouseEvent*)&gApp.event);
} else {
doDefault = super.WindowProc(hWnd,uMsg,wParam,lParam) != 0;
}
return doDefault;
}
// also handle tab key by calling GetNextDlgTabItem
}
static this() {
if (DefaultWindowIcon is null) {
IconPeer ip = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
DefaultWindowIcon = DefaultWindowSmallIcon = new Icon(ip);
}
HINSTANCE hInst = GetModuleHandleA(null);
WNDCLASSA wc;
wc.lpszClassName = "MinWinDialog";
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MinWinWindowProc;
wc.hInstance = hInst;
wc.hIcon = DefaultWindowIcon.peer;
wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_ARROW);
wc.hbrBackground = null;
// wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW); // not +1 for default
wc.lpszMenuName = null;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClassA(&wc);
}
} else version (GTK) {
private import minwin.gtk;
private import minwin.gtk_peers;
class Dialog : AbstractWindow {
AbstractWindow owner;
this(AbstractWindow owner, char[] title = "", bool modal = true, char[] name = "") {
char* str = toStringz(title);
this.owner = owner;
// TODO: application name vs window name??
peer = cast(GtkWindow*)gtk_window_new(GtkWindowType.GTK_WINDOW_TOPLEVEL);
if (modal) {
gtk_window_set_modal(peer,modal);
gtk_window_set_transient_for(peer,owner.peer);
}
gtk_window_set_title(peer,str);
gtk_window_set_resizable(peer,0);
gtk_window_set_default_size(peer,DefaultWindowWidth,DefaultWindowHeight);
this.name = name;
g_signal_connect_data(peer,"destroy",
cast(GCallback)&mw_destroy_callback,
cast(gpointer)this,
null,cast(GConnectFlags)0);
g_signal_connect_data(peer,"delete-event",
cast(GCallback)&mw_dialog_close_callback,
cast(gpointer)this,
null,cast(GConnectFlags)0);
setWindowPeer(this,peer,OWNS_PEER);
WindowList[this] = this; // prevent garbage collection
content = cast(MinWinGtkPeer*)MinWinGtkPeer_new();
GtkWidget* wcontent = cast(GtkWidget*)content;
gtk_widget_set_sensitive(wcontent,true);
content.sizeRequest = &gtkRequest;
content.sizeAllocate = &gtkAllocate;
gtk_container_add(cast(GtkContainer*)peer,wcontent);
g_signal_connect_data(peer,"expose-event",
cast(GCallback)&mw_expose_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
gtk_widget_realize(wcontent);
gtk_widget_show(wcontent);
}
this(AbstractWindow owner, WindowPeer peer) {
setWindowPeer(this,peer,FOREIGN_PEER);
this.owner = owner;
WindowList[this] = this; // prevent garbage collection
}
GMainLoop* loop;
void visible(bool vis) {
version(LOG)log.writefln("calling super.visible %d",vis);
version(LOG)log.flush();
super.visible(vis);
version(LOG)log.writefln("done calling super.visible %d",vis);
version(LOG)log.flush();
if (!gtk_window_get_modal(peer)) return;
if (vis) {
version(LOG)log.writefln("making event loop");
version(LOG)log.flush();
loop = g_main_loop_new(null, false);
g_main_loop_run(loop);
g_main_loop_unref(loop);
version(LOG)log.writefln("exiting event loop");
version(LOG)log.flush();
// that's it?
} else {
if (g_main_loop_is_running(loop))
g_main_loop_quit(loop);
version(LOG)log.writefln("visible off quit loop event loop");
version(LOG)log.flush();
}
}
}
extern (C) void mw_dialog_close_callback(GtkWidget* w, GdkEvent* ev, gpointer ud) {
AbstractWindow win = cast(AbstractWindow) ud;
version(LOG)log.printf("mw_dialog_close_callback\n");
if (win) {
win.visible = false;
// win.close(); // destroys dialog so dont do this
}
}
}
/***************************************
Helper dialogs
***************************************/
// used in open and save file dialogs for filtering
struct FileFilter {
char[] description;
char[][] extensions;
}
version (GTK) {
version = SharedFileDialogData;
}
version (SharedFileDialogData) {
struct FileDialogData {
char[] title;
FileFilter[] filter;
char[] initialDir;
char[] initialFile;
char[] result;
int filterIndex;
int done;
// can get the requested buffer length...
bool isBufferTooShort() {
return false; // TODO
}
}
}
version (MinWin32) {
private {
import minwin.mswindows;
import std.c.stdlib;
}
void informationDialog(AbstractWindow owner, char[] text, char[] title) {
//version(LOG) log.writefln("info dialog peer is %x",cast(uint)owner.peer);
MessageBoxX(owner.peer, text, title, MB_OK | MB_ICONINFORMATION);
}
void warningDialog(AbstractWindow owner, char[] text, char[] title) {
MessageBoxX(owner.peer, text, title, MB_OK | MB_ICONWARNING);
}
void errorDialog(AbstractWindow owner, char[] text, char[] title) {
MessageBoxX(owner.peer, text, title, MB_OK | MB_ICONERROR);
}
void messageDialog(AbstractWindow owner, char[] text, char[] title,...) {
MessageBoxX(owner.peer, text, title, MB_OK | MB_ICONINFORMATION);
}
alias OPENFILENAMEA FileDialogNative;
struct FileDialogData {
FileDialogNative native;
void title(char[] title) {
native.lpstrTitle = toStringz(title);
}
char[] title() {
return native.lpstrTitle[0 .. strlen(native.lpstrTitle)];
}
void filter(FileFilter[] filters) {
char[] total;
foreach (FileFilter f; filters) {
total ~= f.description;
total ~= 0;
if (f.extensions.length > 0) {
foreach (char[] ext; f.extensions) {
total ~= "*.";
total ~= ext;
total ~= ";";
}
total.length = total.length - 1; // remove last ;
}
total ~= 0;
}
total ~= 0;
total ~= 0;
native.lpstrFilter = total.ptr;
}
void initialDir(char[] initialDir) {
native.lpstrInitialDir = toStringz(initialDir);
}
void initialFile(char[] f) {
if (native.lpstrFile is null) {
native.lpstrFile = (new char[MAX_PATH]).ptr;
native.nMaxFile = MAX_PATH;
}
int len = f.length < native.nMaxFile-1 ? f.length : native.nMaxFile-1;
native.lpstrFile[0 .. len] = f[0 .. len];
native.lpstrFile[len] = 0;
}
char[] result() {
return native.lpstrFile[0 .. strlen(native.lpstrFile)];
}
// can get the requested buffer length...
bool isBufferTooShort() {
// bool res = CommDlgExtendedError() == FNERR_BUFFERTOOSMALL;
return false;
}
int filterIndex() {
return native.nFilterIndex;
}
}
bool openFileDialog(AbstractWindow owner, inout FileDialogData data) {
data.native.hwndOwner = owner.peer;
data.native.lStructSize = OPENFILENAMEA.sizeof;
// data.flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
data.native.Flags = OFN_PATHMUSTEXIST;
if (data.native.lpstrFile is null) {
data.native.lpstrFile = (new char[MAX_PATH]).ptr;
data.native.nMaxFile = MAX_PATH;
data.native.lpstrFile[0] = 0;
}
bool res = GetOpenFileNameA(&data.native) != 0;
/* if (!res)
check if the name was too long for the buffer
*/
return res;
}
bool saveFileDialog(AbstractWindow owner, inout FileDialogData data) {
data.native.hwndOwner = owner.peer;
data.native.lStructSize = OPENFILENAMEA.sizeof;
data.native.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
if (data.native.lpstrFile is null) {
data.native.lpstrFile = (new char[MAX_PATH]).ptr;
data.native.nMaxFile = MAX_PATH;
data.native.lpstrFile[0] = 0;
}
bool res = GetSaveFileNameA(&data.native) != 0;
/* if (!res)
check if the name was too long for the buffer
*/
return res;
}
} else version(GTK) {
private import minwin.gtk;
private import minwin.window;
void informationDialog(AbstractWindow owner, char* text, char[]
title) {
msgDialog(owner,text,title,GtkMessageType.GTK_MESSAGE_INFO,
GtkButtonsType.GTK_BUTTONS_OK);
}
void warningDialog(AbstractWindow owner, char* text, char[] title) {
msgDialog(owner,text,title,GtkMessageType.GTK_MESSAGE_WARNING,
GtkButtonsType.GTK_BUTTONS_OK);
}
void errorDialog(AbstractWindow owner, char* text, char[] title) {
msgDialog(owner,text,title,GtkMessageType.GTK_MESSAGE_ERROR,
GtkButtonsType.GTK_BUTTONS_OK);
}
alias informationDialog messageDialog;
void msgDialog(AbstractWindow owner, char* text, char[] title,
GtkMessageType type, GtkButtonsType buttons) {
// TODO: title?
GtkWidget* d = gtk_message_dialog_new(owner.peer,
GtkDialogFlags.GTK_DIALOG_DESTROY_WITH_PARENT,
type,buttons,text);
gtk_dialog_run(cast(GtkDialog*)d);
gtk_widget_destroy(d);
}
bool openFileDialog(AbstractWindow owner, inout FileDialogData data) {
bool result;
GtkWidget* peer =
gtk_file_chooser_dialog_new(toStringz(data.title),owner.peer,
GtkFileChooserAction.GTK_FILE_CHOOSER_ACTION_OPEN,
cast(char*)"gtk-cancel", cast(uint)GtkResponseType.GTK_RESPONSE_CANCEL,
cast(char*)"gtk-open", cast(uint)GtkResponseType.GTK_RESPONSE_ACCEPT,
null);
GtkFileChooser* fc = cast(GtkFileChooser*)peer;
return opensaveFileDialog(data,peer,fc);
}
bool saveFileDialog(AbstractWindow owner, inout FileDialogData data) {
GtkWidget* peer =
gtk_file_chooser_dialog_new(toStringz(data.title),owner.peer,
GtkFileChooserAction.GTK_FILE_CHOOSER_ACTION_SAVE,
cast(char*)"gtk-cancel", cast(uint)GtkResponseType.GTK_RESPONSE_CANCEL,
cast(char*)"gtk-save", cast(uint)GtkResponseType.GTK_RESPONSE_ACCEPT,
null);
GtkFileChooser* fc = cast(GtkFileChooser*)peer;
if (data.initialFile.length > 0)
gtk_file_chooser_set_current_name(fc,toStringz(data.initialFile));
return opensaveFileDialog(data,peer,fc);
}
bool opensaveFileDialog(inout FileDialogData data,
GtkWidget* peer,
GtkFileChooser* fc) {
bool result;
if (data.initialDir.length > 0)
gtk_file_chooser_set_current_folder(fc,toStringz(data.initialDir));
foreach( FileFilter filt ; data.filter) {
GtkFileFilter* f = gtk_file_filter_new();
gtk_file_filter_set_name(f,toStringz(filt.description));
foreach( char[] ext; filt.extensions) {
gtk_file_filter_add_pattern(f,cast(char*)("*."~ext));
}
gtk_file_chooser_add_filter(fc,f);
}
// TODO: assertion local_full_path[0] = /
result = gtk_dialog_run(cast(GtkDialog*)peer) == GtkResponseType.GTK_RESPONSE_ACCEPT;
if (result) {
char* name = gtk_file_chooser_get_filename(fc);
int len = strlen(name);
data.result = name[0..len].dup;
g_free(name);
}
gtk_widget_destroy(peer);
return result;
}
}
// utility dialogs:
// query dialog
// file chooser dialog
// color chooser?
// print dialog?

View file

@ -1,219 +0,0 @@
/* MinWin Event classes
*
* Various event classes for key, mouse, focus events, etc
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.event;
private import minwin.geometry;
enum Modifier {
Shift = 1,
Alt = 2,
Ctrl = 4,
Command = 8,
Meta = 16
}
version (MinWin32) {
private import minwin.mswindows;
alias MSG EventNative;
template EventBaseImpl() {
int modifiers() {
int mod = 0;
if ((GetKeyState(VK_LSHIFT) | GetKeyState(VK_RSHIFT)) & 0x8000)
mod |= Modifier.Shift;
if ((GetKeyState(VK_LCONTROL) | GetKeyState(VK_RCONTROL)) & 0x8000)
mod |= Modifier.Ctrl;
if ((GetKeyState(VK_LMENU) | GetKeyState(VK_RMENU)) & 0x8000)
mod |= Modifier.Alt;
return mod;
}
int id() { return native.message; }
}
struct Event {
EventNative native;
mixin EventBaseImpl!();
}
Event toEvent(EventNative nat) {
Event res;
res.native = nat;
return res;
}
alias MSG KeyEventNative;
struct KeyEvent {
KeyEventNative native;
// UTF-32 character typed
dchar keyChar() { return cast(dchar)native.wParam; }
// key code
int keyCode() { return native.wParam; }
int keyRepeat() { return native.lParam & 0x0F; }
mixin EventBaseImpl!();
}
alias WM_CHAR KeyPressedEvent;
alias WM_KEYDOWN KeyDownEvent;
alias WM_KEYUP KeyUpEvent;
alias WM_MOUSEMOVE MouseMoveEvent;
alias WM_LBUTTONDOWN MouseDownEvent;
alias WM_LBUTTONUP MouseUpEvent;
alias WM_RBUTTONDOWN MouseAlt1DownEvent;
alias WM_RBUTTONUP MouseAlt1UpEvent;
alias WM_MBUTTONDOWN MouseAlt2DownEvent;
alias WM_MBUTTONUP MouseAlt2UpEvent;
alias MSG MouseEventNative;
struct MouseEvent {
MouseEventNative native;
Point point() {
return XY(LOWORD(native.lParam),HIWORD(native.lParam));
}
mixin EventBaseImpl!();
}
// alias WM_ACTIVATE WindowActivateEvent;
// also focus event, destory event
alias WM_SIZE WindowSizeEvent;
alias WM_SIZING WindowSizingEvent;
alias WM_MOVE WindowMoveEvent;
alias WM_MOVING WindowMovingEvent;
alias MSG WindowEventNative;
struct WindowEvent {
WindowEventNative native;
mixin EventBaseImpl!();
}
// TODO: add event filter api
bool nextEvent(Event* event) {
return GetMessageA(&event.native,cast(HWND)null,0,0) != 0;
}
bool peekEvent(Event* event) {
return PeekMessageA(&event.native,cast(HWND)null,0,0,PM_REMOVE) != 0;
}
void dispatchEvent(Event* event) {
TranslateMessage(&event.native);
DispatchMessageA(&event.native);
}
// alias void* KeyEventPeer;
// alias void* MouseEventPeer;
// alias void* MotionEventPeer;
} else version (GTK) {
private import minwin.gtk;
alias GdkEvent EventNative;
template EventBaseImpl() {
int modifiers() {
int mod;
int state;
if (native.type == GdkEventType.GDK_KEY_PRESS || native.type == GdkEventType.GDK_KEY_RELEASE) {
GdkEventKey* ke = cast(GdkEventKey*)(&native);
state = ke.state;
} else {
// return event.message;
}
return mod;
}
GdkEventType id() { return native.type; }
}
struct Event {
EventNative native;
mixin EventBaseImpl!();
}
Event toEvent(EventNative nat) {
Event res;
res.native = nat;
return res;
}
alias GdkEventType.GDK_KEY_PRESS KeyPressedEvent;
alias GdkEventType.GDK_KEY_PRESS KeyDownEvent;
alias GdkEventType.GDK_KEY_RELEASE KeyUpEvent;
alias GdkEventKey KeyEventNative;
struct KeyEvent {
KeyEventNative native;
// UTF-32 character typed
dchar keyChar() { return cast(dchar)native.keyval; }
// key code
int keyCode() { return native.keyval; }
int keyRepeat() { return 0; }
mixin EventBaseImpl!();
}
alias GdkEventType.GDK_MOTION_NOTIFY MouseMoveEvent;
alias GdkEventType.GDK_BUTTON_PRESS MouseDownEvent;
alias GdkEventType.GDK_BUTTON_RELEASE MouseUpEvent;
alias GdkEventType.GDK_2BUTTON_PRESS MouseAlt1DownEvent;
alias GdkEventType.GDK_BUTTON_RELEASE MouseAlt1UpEvent;
alias GdkEventType.GDK_3BUTTON_PRESS MouseAlt2DownEvent;
alias GdkEventType.GDK_BUTTON_RELEASE MouseAlt2UpEvent;
alias GdkEventButton MouseEventNative;
alias GdkEventButton MotionEventNative;
struct MouseEvent {
MouseEventNative native;
Point point() {
return XY(cast(int)native.x,cast(int)native.y);
}
mixin EventBaseImpl!();
}
// alias WM_ACTIVATE WindowActivateEvent;
alias GdkEventType.GDK_CONFIGURE WindowSizeEvent;
alias GdkEventType.GDK_CONFIGURE WindowSizingEvent;
alias GdkEventType.GDK_CONFIGURE WindowMoveEvent;
alias GdkEventType.GDK_CONFIGURE WindowMovingEvent;
alias GdkEventConfigure WindowEventNative;
struct WindowEvent {
WindowEventNative native;
mixin EventBaseImpl!();
}
// TODO: add event filter api
bool nextEvent(Event* event) {
assert(false);
while (gtk_events_pending() == 0) {} // busy wait - icky
peekEvent(event);
return true; // how does one check if a Quit is pending?
}
bool peekEvent(Event* event) {
Event* e = cast(Event*)gdk_event_get();
if (e) {
*event = *e;
gdk_event_free(cast(GdkEvent*)e);
}
return e !is null;
}
void dispatchEvent(Event* event) {
gtk_main_do_event(&event.native);
}
}

View file

@ -1,192 +0,0 @@
/* MinWin Font class
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.font;
private {
import minwin.app;
import minwin.component;
import minwin.peerimpl;
import std.string;
import std.c.string;
}
enum FontWeight {
Any = 0,
Thin = 100,
ExtraLight = 200,
Light = 300,
Normal = 400,
Medium = 500,
SemiBold = 600,
Bold = 700,
ExtraBold = 800,
Heavy = 900
}
enum StandardFont {
Gui, Fixed, Variable
}
version (GTK) version = GenericFontDataStruct;
version (GenericFontDataStruct) {
struct FontData {
int size;
FontWeight weight;
bool italic;
char[] name;
}
}
version (MinWin32) {
private import minwin.mswindows;
alias HFONT FontPeer;
alias LOGFONTA FontDataNative;
struct FontData {
FontDataNative native;
void size(int size) { native.lfHeight = size; }
int size() { return native.lfHeight; }
void weight(FontWeight w) { native.lfWeight = w; }
FontWeight weight() { return cast(FontWeight)native.lfWeight; }
void italic(bool i) { native.lfItalic = i; }
bool italic() { return native.lfItalic != 0; }
char[] name() {
char* s = native.lfFaceName.ptr;
return s[0..strlen(s)];
}
void name(char[] n) {
native.lfFaceName[0 .. n.length] = n[];
}
}
alias TEXTMETRICA FontMetricsNative;
struct FontMetrics {
FontMetricsNative native;
int size() { return native.tmHeight; }
int ascent() { return native.tmAscent; }
int descent() { return native.tmDescent; }
int leading() { return native.tmExternalLeading; }
int maxWidth() { return native.tmMaxCharWidth; }
}
class Font {
FontPeer peer;
this(inout FontData d) {
d.native.lfCharSet = DEFAULT_CHARSET;
peer = CreateFontIndirectA(&d.native);
sysAssert(peer !is null, "Failed to create peer Font");
hasPeer = OWNS_PEER;
}
// mixin CommonFontCtor!();
this(FontPeer p) {
peer = p;
hasPeer = FOREIGN_PEER;
}
this(char[] name, int size = 0, FontWeight weight = FontWeight.Normal) {
FontData fd;
if (size > 0)
fd.size = size;
if (weight > 0)
fd.weight = weight;
if (name.length > 0)
fd.name = name;
this(fd);
}
mixin SimplePeerMixin!();
}
Font standardFont(StandardFont id) {
static Font[5] fonts;
if (fonts[0] is null && id == StandardFont.Gui) {
fonts[0] = new Font(GetStockObject(DEFAULT_GUI_FONT));
} else if (fonts[1] is null && id == StandardFont.Fixed) {
fonts[1] = new Font(GetStockObject(ANSI_FIXED_FONT));
} else if (fonts[2] is null && id == StandardFont.Variable) {
fonts[2] = new Font(GetStockObject(ANSI_VAR_FONT));
}
return fonts[id];
}
} else version (GTK) {
private import minwin.app;
private import minwin.gtk;
private import std.string;
alias PangoFontDescription* FontPeer;
struct FontMetrics {
int size;
int ascent;
int descent;
int leading;
int maxWidth;
}
class Font {
FontPeer peer;
this(inout FontData d) {
peer = pango_font_description_new();
if (d.name.length > 0)
pango_font_description_set_family(peer,toStringz(d.name));
if (d.size > 0)
pango_font_description_set_size(peer,d.size*PANGO_SCALE);
if (d.weight > 0)
pango_font_description_set_weight(peer,cast(PangoWeight)d.weight);
hasPeer = OWNS_PEER;
}
// mixin CommonFontCtor!();
this(FontPeer p) {
peer = p;
hasPeer = FOREIGN_PEER;
}
this(char[] name, int size = 0, FontWeight weight = FontWeight.Normal) {
FontData fd;
if (size > 0)
fd.size = size;
if (weight > 0)
fd.weight = weight;
if (name.length > 0)
fd.name = name;
this(fd);
}
mixin PeerMixin!();
void dispose() { disposePeer(); }
void disposePeer() {
if (hasPeer == OWNS_PEER)
pango_font_description_free(peer);
hasPeer = NO_PEER;
}
}
// TODO: what are the standard GTK fonts??
Font standardFont(StandardFont id) {
static Font[5] fonts;
FontData d;
if (fonts[0] is null && id == StandardFont.Gui) {
fonts[0] = new Font("variable");
} else if (fonts[1] is null && id == StandardFont.Fixed) {
fonts[1] = new Font("fixed");
} else if (fonts[2] is null && id == StandardFont.Variable) {
fonts[2] = new Font("variable");
}
return fonts[id];
}
}

View file

@ -1,521 +0,0 @@
/* MinWin geometry types
*
* Defines Point, Rect, Region and Color and associated functions.
* These are structs with a single field called "native" that stores
* the native type or, in the case of color on Unix system, an
* int with the RGB triple. A Region is a class wrapping a system
* region resource.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.geometry;
private {
import minwin.peer;
import minwin.app;
import minwin.logging;
import std.string;
}
enum FillRule {
EvenOdd, Winding
}
template CommonPointImpl() {
PointNative native;
void x(int v) { native.x = v; }
int x() { return native.x; }
void y(int v) { native.y = v; }
int y() { return native.y; }
void XY(int x, int y) {
native.x = x;
native.y = y;
}
Point opAdd(Point b) {
Point res;
res.x = x+b.x;
res.y = y+b.y;
return res;
}
Point opSub(Point b) {
Point res;
res.x = x-b.x;
res.y = y-b.y;
return res;
}
char[] toString() {
return format("[Point x:%.3d y:%.3d]",x(),y());
}
}
template CommonRectImpl() {
RectNative native;
void translate(Point p) {
left = left + p.x;
top = top + p.y;
right = right + p.x;
bottom = bottom + p.y;
}
char[] toString() {
return format("[Rect l:%.3d t:%.3d w:%.3d h:%.3d]",left(),top(),width(),height());
}
bool contains(Point p) {
return (p.x >= left) && (p.x <= right) && (p.y >= top) && (p.y <= bottom);
}
}
template CommonColorImpl() {
ColorNative native;
char[] toString() {
return format("[Color r:%.3d g:%.3d b:%.3d]",red,green,blue);
}
}
version(GTK)
version = WidthHeightRect;
version(WidthHeightRect) {
template WidthHeightRectImpl() {
void LTWH(int left, int top, int width, int height) {
native.x = left;
native.y = top;
native.width = width;
native.height = height;
}
void LTRB(int left, int top, int right, int bottom) {
native.x = left;
native.y = top;
native.width = right-left;
native.height = bottom-top;
}
int left() { return native.x; }
int top() { return native.y; }
int right() { return native.x + native.width; }
int bottom() { return native.y + native.height; }
int width() { return native.width; }
int height() { return native.height; }
void left(int v) { native.x = v; }
void top(int v) { native.y = v; }
void right(int v) { native.width = v - native.x; }
void bottom(int v) { native.height = v - native.y; }
void width(int v) { native.width = v; }
void height(int v) { native.height = v; }
}
}
version(GTK)
version = CommonUnixColor;
// should check x display? RGB masks says red FF0000, blue FF
version(CommonUnixColor) {
alias uint ColorNative;
struct Color {
ColorNative native;
void RGB(ubyte r, ubyte g, ubyte b) {
native = ((cast(uint)r)<<16) | ((cast(uint)g)<<8) | (cast(uint)b);
}
ubyte red(){ return cast(ubyte)((native & 0x0FF0000)>>16); }
ubyte green(){ return cast(ubyte)((native & 0x0FF00)>>8); }
ubyte blue(){ return cast(ubyte)(native & 0x0FF); }
void red(ubyte r) { native |= ((cast(uint)r)<<16);}
void green(ubyte g) { native |= ((cast(uint)g)<<8);}
void blue(ubyte b) { native |= b; }
package static int rescale(int v, int s1, int s2) {
double x = 1.0*s2/s1;
return cast(int)(x*v);
}
}
}
version (MinWin32) {
private import minwin.mswindows;
private import std.c.stdlib;
alias POINT PointNative;
struct Point {
mixin CommonPointImpl!();
}
alias RECT RectNative;
struct Rect {
mixin CommonRectImpl!();
void LTWH(int left, int top, int width, int height) {
native.left = left;
native.top = top;
native.right = left+width;
native.bottom = top+height;
}
void LTRB(int left, int top, int right, int bottom) {
native.left = left;
native.top = top;
native.right = right;
native.bottom = bottom;
}
int left() { return native.left; }
int top() { return native.top; }
int right() { return native.right; }
int bottom() { return native.bottom; }
int width() { return native.right - native.left; }
int height() { return native.bottom - native.top; }
void left(int v) { native.left = v; }
void top(int v) { native.top = v; }
void right(int v) { native.right = v; }
void bottom(int v) { native.bottom = v; }
void width(int v) { native.right = native.left + v; }
void height(int v) { native.bottom = native.top + v; }
}
alias COLORREF ColorNative;
struct Color {
mixin CommonColorImpl!();
void RGB(ubyte r, ubyte g, ubyte b) {
native = std.c.windows.windows.RGB(r,g,b);
}
ubyte red(){ return cast(ubyte)(native & 0x0FF); }
ubyte green(){ return cast(ubyte)((native & 0x0FF00)>>8); }
ubyte blue(){ return cast(ubyte)((native & 0x0FF0000)>>16); }
void red(ubyte r) { native |= r; }
void green(ubyte g) { native |= ((cast(uint)g)<<8);}
void blue(ubyte b) { native |= ((cast(uint)b)<<16);}
}
Color systemBackgroundColor() {
return toColor(GetSysColor(COLOR_MENU));
}
alias HRGN RegionPeer;
class Region {
RegionPeer peer;
mixin SimplePeerMixin!();
this(inout Rect r) {
peer = CreateRectRgnIndirect(&r.native);
sysAssert(peer !is null, "Failed to create peer Region");
hasPeer = OWNS_PEER;
}
this(Point[] pts, FillRule rule = FillRule.Winding) {
peer = CreatePolygonRgn(cast(POINT*)pts.ptr, pts.length, rule);
sysAssert(peer !is null, "Failed to create peer polygon Region");
hasPeer = OWNS_PEER;
}
this(RegionPeer rgn) {
peer = rgn;
hasPeer = FOREIGN_PEER;
}
int opEquals(Object o) {
Region r = cast(Region)o;
return r && EqualRgn(peer,r.peer);
}
Region unionRgn(Region r) {
int ok = CombineRgn(peer,peer,r.peer,RGN_OR);
sysAssert(ok != false, "Failed to combine regions",0);
return this;
}
Region unionRect(inout Rect r) {
Region rectRgn = new Region(r);
int ok = CombineRgn(peer,peer,rectRgn.peer,RGN_OR);
sysAssert(ok != false, "Failed to union regions",0);
return this;
}
Region intersectRgn(Region r) {
int ok = CombineRgn(peer,peer,r.peer,RGN_AND);
sysAssert(ok != false, "Failed to intersect regions",0);
return this;
}
bool contains(Point p) {
return PtInRegion(peer,p.x,p.y) != 0;
}
Region dup() {
RGNDATA* data;
DWORD siz = GetRegionData(peer,0,null);
sysAssert(siz != 0, "Failed to get region data size",0);
data = cast(RGNDATA*)malloc(RGNDATAHEADER.sizeof+siz);
sysAssert(data !is null, "Failed to malloc region data",0);
Region r;
try {
siz = GetRegionData(peer,siz,data);
sysAssert(siz != 0, "Failed to get region data",0);
HRGN p = ExtCreateRegion(null,siz,data);
sysAssert(p !is null, "Failed to duplicate region",0);
r = new Region(p);
} finally {
free(data);
}
return r;
}
}
} else version (GTK) {
private import minwin.gtk;
alias GdkPoint PointNative;
struct Point {
mixin CommonPointImpl!();
}
alias GdkRectangle RectNative;
struct Rect {
mixin CommonRectImpl!();
mixin WidthHeightRectImpl!();
}
GdkColor* toNativeColor(Color c) {
GdkColor* r = new GdkColor;
r.red = Color.rescale(c.red,ubyte.max,ushort.max);
r.green = Color.rescale(c.green,ubyte.max,ushort.max);
r.blue = Color.rescale(c.blue,ubyte.max,ushort.max);
version(LOG)log.writefln("rescaled color %x %x %x to %x %x %x",
cast(int)c.red,cast(int)c.green,cast(int)c.blue,
cast(int)r.red,cast(int)r.green,cast(int)r.blue);
return r;
}
Color systemBackgroundColor() {
GtkStyle* style = gtk_widget_get_default_style();
GdkColor* c = &style.bg[GtkStateType.GTK_STATE_NORMAL];
ubyte r = Color.rescale(c.red,ushort.max,ubyte.max);
ubyte g = Color.rescale(c.green,ushort.max,ubyte.max);
ubyte b = Color.rescale(c.blue,ushort.max,ubyte.max);
Color c2;
c2.RGB(r,g,b);
return c2;
}
alias GdkRegion* RegionPeer;
class Region {
RegionPeer peer;
mixin PeerMixin!();
void dispose() { disposePeer(); }
void disposePeer() {
if (hasPeer == OWNS_PEER) {
gdk_region_destroy(peer);
}
hasPeer = NO_PEER;
}
this(inout Rect r) {
peer = gdk_region_new();
gdk_region_union_with_rect(peer,&r.native);
hasPeer = OWNS_PEER;
}
this(Point[] pts, FillRule rule = FillRule.Winding) {
peer = gdk_region_polygon(cast(GdkPoint*)pts.ptr, pts.length,
cast(GdkFillRule)rule);
hasPeer = OWNS_PEER;
}
this(RegionPeer rgn) {
peer = rgn;
hasPeer = FOREIGN_PEER;
}
int opEquals(Object o) {
Region r = cast(Region)o;
return r && gdk_region_equal(peer,r.peer);
}
Region unionRgn(Region r) {
gdk_region_union(peer,r.peer);
return this;
}
Region unionRect(inout Rect r) {
gdk_region_union_with_rect(peer,&r.native);
return this;
}
Region intersectRgn(Region r) {
gdk_region_intersect(peer,r.peer);
return this;
}
bool contains(Point p) {
return gdk_region_point_in(peer,p.x,p.y) != 0;
}
Region dup() {
GdkRegion* r = gdk_region_new();
gdk_region_union(r,peer);
Region mwr = new Region(r);
mwr.hasPeer = OWNS_PEER;
return mwr;
}
}
}
Point toPoint(PointNative nat) {
Point r;
r.native = nat;
return r;
}
Point XY(int x, int y) {
Point p;
p.XY(x,y);
return p;
}
Rect toRect(RectNative nat) {
Rect r;
r.native = nat;
return r;
}
Rect LTWH(int left, int top, int width, int height) {
Rect r;
r.LTWH(left,top,width,height);
return r;
}
Rect LTRB(int left, int top, int right, int bottom) {
Rect r;
r.LTRB(left,top,right,bottom);
return r;
}
Color toColor(ColorNative nat) {
Color r;
r.native = nat;
return r;
}
Color RGB(ubyte r, ubyte g, ubyte b) {
Color res;
res.RGB(r,g,b);
return res;
}
private {
final int max(int a,int b){ return a>b?a:b; }
final int min(int a,int b){ return a<b?a:b; }
}
void intersectRect(inout Rect res, inout Rect r1, inout Rect r2) {
int l,t,r,b;
l = max(r1.left,r2.left);
t = max(r1.top,r2.top);
r = min(r1.right,r2.right);
b = min(r1.bottom,r2.bottom);
if (l>r || t>b) {
res.LTRB(0,0,0,0);
} else {
res.LTRB(l,t,r,b);
}
}
void unionRect(inout Rect res, inout Rect r1, inout Rect r2) {
int l,t,r,b;
l = min(r1.left,r2.left);
t = min(r1.top,r2.top);
r = max(r1.right,r2.right);
b = max(r1.bottom,r2.bottom);
res.LTRB(l,t,r,b);
}
void offsetRect(inout Rect res, int x, int y) {
res.LTWH(res.left+x,res.top+y,res.width,res.height);
}
// Region unittests
unittest {
Rect r = LTWH(10,10,100,100);
Region rgn = new Region(r);
assert(rgn.contains(XY(50,50)));
assert(!rgn.contains(XY(0,50)));
Rect r2 = LTWH(-10,10,40,60);
rgn.unionRect(r2);
assert(rgn.contains(XY(0,50)));
Region rgn2 = rgn.dup;
assert(rgn == rgn2);
assert(rgn !is rgn2);
Point[] x;
x.length = 5;
x[0].XY(0,-10);
x[1].XY(100,100);
x[2].XY(0,200);
x[3].XY(-100,100);
x[4].XY(0,-10);
rgn2.intersectRgn(new Region(x));
assert(rgn2.contains(XY(0,50)));
}
// Color unittests
unittest {
Color c = RGB(30,40,60);
assert(c.red == 30);
assert(c.green == 40);
assert(c.blue == 60);
}
// Rect unittests
unittest {
Rect r1 = LTWH(10,20,100,200);
assert(r1.left == 10);
assert(r1.top == 20);
assert(r1.width == 100);
assert(r1.height == 200);
assert(r1.right == 110);
assert(r1.bottom == 220);
r1.LTWH(-10,-20,10,20);
assert(r1.right == 0);
assert(r1.bottom == 0);
r1.LTRB(-10,-20,10,20);
assert(r1.right == 10);
assert(r1.bottom == 20);
assert(r1.width == 20);
assert(r1.height == 40);
Rect r5;
r5.left = -10;
r5.top = -20;
r5.width = 30;
r5.height = 50;
assert(r5.left == -10);
assert(r5.top == -20);
assert(r5.right == 20);
assert(r5.bottom == 30);
Rect r2 = LTRB(-10,-20,10,20);
assert(r1 == r2);
Rect r3;
r2.LTWH(0,5,20,20);
intersectRect(r3,r1,r2);
assert(r3 == LTRB(0,5,10,20));
Rect r4 = LTWH(-100,-100,300,300);
intersectRect(r3,r1,r4);
assert(r3 == r1);
intersectRect(r3,r4,r1);
assert(r3 == r1);
r4.LTWH(0,0,100,10);
unionRect(r3,r4,r1);
assert(r3 == LTRB(-10,-20,100,20));
offsetRect(r4,10,20);
assert(r4 == LTWH(10,20,100,10));
}
// Point unittests
unittest {
Point p = XY(100,200);
assert(p.x == 100);
assert(p.y == 200);
p.XY(300,-400);
assert(p.x == 300);
assert(p.y == -400);
// try platform-specific properties that happen to work
assert(p.native.x == 300);
assert(p.native.y == -400);
assert(p == XY(300,-400));
Rect r = LTWH(10,20,300,400);
assert(r.contains(XY(200,300)));
assert(r.contains(XY(10,200)));
assert(r.contains(XY(10,420)));
assert(!r.contains(XY(0,200)));
assert(!r.contains(XY(200,1000)));
}

View file

@ -1,265 +0,0 @@
/* MinWin Group class
*
* A Group is a lightweight component (meaning it has
* no peer) that contains and lays out other components.
*
* A GroupBox is a potentially heavyweight component that
* puts a box and label around other components.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.group;
private {
import minwin.component;
import minwin.window;
import minwin.peerimpl;
import minwin.logging;
import std.string;
}
// lightweight group of other children - no peer
class Group : Component {
Rect bounds;
this(Component parent, char[] name = "") {
hasPeer = NO_PEER;
this.name = name;
if (parent)
parent.addChild(this);
}
void disposePeer(){}
PeerForAdd getPeerForAdd() {
return parent.getPeerForAdd();
}
void getPeerOffset(inout int x, inout int y) {
int px, py;
if (parent)
parent.getPeerOffset(px,py);
x = bounds.left+px;
y = bounds.top+py;
}
void getBounds(inout Rect r) {
r = bounds;
}
void setBounds(inout Rect r) {
bounds = r;
version(LOG) log.writefln("setting group bounds to %d %d %d %d",
r.left,r.top,r.width,r.height);
childLayoutDirty = true;
repaint();
}
void size(Point s) {
bounds.LTWH(bounds.left,bounds.top,s.x,s.y);
childLayoutDirty = true;
repaint();
}
void visible(bool vis) {
foreach(Component ch; this) {
ch.visible = vis;
}
childLayoutDirty = true;
layout(false);
}
bool visible() {
bool vis = false;
foreach(Component ch; this) {
vis = vis || ch.visible();
}
return vis;
}
void enabled(bool b) {
foreach(Component ch; this) {
ch.enabled = b;
}
}
bool enabled() {
bool b = false;
foreach(Component ch; this) {
b = b || ch.enabled;
}
return b;
}
}
private import minwin.layout;
unittest {
Group g = new Group(null);
g.layoutMgr = new FlowLayout;
Group g2 = new Group(g);
g2.layoutMgr = new FlowLayout;
g2.userPreferredSize(40,50);
Group g3 = new Group(g);
g3.layoutMgr = new FlowLayout;
Group g4 = new Group(g3);
g4.userPreferredSize(50,10);
Group g5 = new Group(g3);
g5.userPreferredSize(60,20);
Group g6 = new Group(g3);
g6.userPreferredSize(70,30);
g.pack();
Rect r2;
g.getBounds(r2);
assert( r2 == LTWH(0,0,70,110) );
g6.getBounds(r2);
assert( r2 == LTWH(0,30,70,30) );
g5.getBounds(r2);
assert( r2 == LTWH(5,10,60,20) );
g4.getBounds(r2);
assert( r2 == LTWH(10,0,50,10) );
int x,y;
g6.getPeerOffset(x,y);
assert( x == 0 );
assert( y == 80 );
}
version (MinWin32) {
private {
import minwin.app;
import minwin.mswindows;
import std.utf;
}
class GroupBox : WindowChild {
int labelHeight;
char[] text_data;
char[] text() { return text_data; }
void text(char[] c) {
text_data = c;
SendMessageX(peer,WM_SETTEXT,0,c);
}
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
text_data = text;
peer = CreateWindowX("BUTTON",text,
BS_GROUPBOX | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer Button");
setWindowChildPeer(this,peer,OWNS_PEER);
this.name = name;
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
HDC dc = GetDC(peer);
HFONT oldFont = SelectObject(dc,f.peer);
TEXTMETRICA metrics;
GetTextMetricsA(dc,&metrics);
labelHeight = metrics.tmHeight;
SelectObject(dc,oldFont);
ReleaseDC(peer,dc);
parent.addChild(this);
}
void getLayoutBounds(inout Rect r) {
super.getLayoutBounds(r);
r.LTWH(r.left+2, r.top+labelHeight+2, r.width-4, r.height-labelHeight-4);
}
Point preferredSize() {
Point s;
if (layoutMgr) {
s = layoutMgr.preferredSize(this);
}
s.y = s.y + labelHeight+4;
s.x = s.x + 4;
if (userPreferredWidth() > 0)
s.x = userPreferredWidth();
if (userPreferredHeight() > 0)
s.y = userPreferredHeight();
return s;
}
mixin WindowChildImpl!();
}
} else version (GTK) {
private import minwin.gtk;
private import minwin.gtk_peers;
private import std.c.string;
class GroupBox : WindowChild {
MinWinGtkPeer* content;
char[] text() {
char* str = gtk_frame_get_label(cast(GtkFrame*)peer);
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] c) {
gtk_frame_set_label(cast(GtkFrame*)peer,g_strdup(c.ptr));
}
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_frame_new(str);
gtk_container_add(cast(GtkContainer*)parentp,peer);
// add our peer to hook into GTK size allocation algorithm
GtkWidget* wcontent = MinWinGtkPeer_new();
content = cast(MinWinGtkPeer*)wcontent;
gtk_widget_set_sensitive(wcontent,true);
content.sizeRequest = &gtkRequest;
content.sizeAllocate = &gtkAllocate;
gtk_container_add(cast(GtkContainer*)peer,wcontent);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(wcontent);
gtk_widget_show(wcontent);
gtk_widget_realize(peer);
visible = true;
}
mixin WindowChildImpl!();
PeerForAdd getPeerForAdd() {
return cast(GtkWidget*)content;
}
// callback from the GTK peer asking for preferred size
private void gtkRequest(GtkWidget *w, GtkRequisition* req) {
version(LOG)log.writefln("gtkRequest for groupbox");
Point s;
if (layoutMgr) {
s = layoutMgr.preferredSize(this);
req.width = s.x;
req.height = s.y;
} else {
req.width = 0;
req.height = 0;
}
version(LOG)log.writefln("done gtkRequest for groupbox");
}
// callback from GTK peer telling us our position
private void gtkAllocate(GtkWidget *w, GtkAllocation* req) {
version(LOG)log.writefln("gtkAllocate for groupbox");
if (layoutMgr) {
layoutMgr.layout(this);
}
childLayoutDirty = false;
version(LOG)log.writefln("done gtkAllocate for groupbox");
}
void getLayoutBounds(inout Rect r) {
GtkWidget* w = cast(GtkWidget*)content;
r = toRect(w.allocation);
}
}
}

View file

@ -1,7 +0,0 @@
all.d
-allobj
-Tlibminwin_gtk
-I..
-fversion=GTK
-lib
-g

File diff suppressed because it is too large Load diff

View file

@ -1,152 +0,0 @@
/* MinWin GTK Container Peer
*
* A MinWinGtkPeer is a GTK container that calls delegates to handle
* size requests and allocation. These delegates are usually filled
* by MinWin layout managers.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.gtk_peers;
private import minwin.gtk;
private GtkContainerClass* parent_cls = null;
private GType container_type = 0;
alias void delegate(GtkWidget *widget,GtkRequisition *requisition) SizeRequestDel;
alias void delegate(GtkWidget *widget,GtkAllocation *allocation) SizeAllocateDel;
struct MinWinGtkPeer {
GtkContainer parent;
GList* children;
SizeRequestDel sizeRequest;
SizeAllocateDel sizeAllocate;
}
struct MinWinGtkPeerClass {
GtkContainerClass parent;
}
extern (C)
GType MinWinGtkPeer_get_type() {
if (container_type == 0) {
static GTypeInfo info;
info.class_size = MinWinGtkPeerClass.sizeof;
info.class_init = cast(GClassInitFunc)&MinWinGtkPeer_class_init;
info.instance_size = MinWinGtkPeer.sizeof;
info.instance_init = cast(GInstanceInitFunc)&MinWinGtkPeer_init;
container_type = g_type_register_static(gtk_container_get_type(),
"MinWinGtkPeer",&info, cast(GTypeFlags)0);
}
return container_type;
}
extern (C)
void MinWinGtkPeer_class_init(MinWinGtkPeerClass* cls,gpointer p) {
GtkWidgetClass* wcls = cast(GtkWidgetClass*) cls;
GtkContainerClass* ccls = cast(GtkContainerClass*) cls;
parent_cls = cast(GtkContainerClass*)g_type_class_peek_parent (cls);
wcls.realize = &MinWinGtkPeer_realize;
wcls.size_request = &MinWinGtkPeer_size_request;
wcls.size_allocate = &MinWinGtkPeer_size_allocate;
ccls.add = &MinWinGtkPeer_add;
ccls.remove = &MinWinGtkPeer_remove;
ccls.forall = &MinWinGtkPeer_forall;
ccls.child_type = &MinWinGtkPeer_child_type;
}
extern (C)
GType MinWinGtkPeer_child_type(GtkContainer* container) {
return gtk_widget_get_type();
}
extern (C)
void MinWinGtkPeer_init(MinWinGtkPeer* c) {
GtkObject* obj = cast(GtkObject*)c;
obj.flags = GtkWidgetFlags.GTK_NO_WINDOW;
c.children = null;
c.sizeRequest = null;
c.sizeAllocate = null;
}
extern (C)
GtkWidget* MinWinGtkPeer_new() {
return cast(GtkWidget*)g_object_new(MinWinGtkPeer_get_type(), null);
}
extern (C)
void MinWinGtkPeer_add(GtkContainer* c,GtkWidget* widget) {
MinWinGtkPeer* mwc = cast(MinWinGtkPeer*)c;
GtkWidget* child = widget;
gtk_widget_set_parent(widget,cast(GtkWidget*)(c));
mwc.children = g_list_append(mwc.children, child);
}
extern (C)
void MinWinGtkPeer_realize(GtkWidget *widget) {
GtkWidgetClass* wcls = cast(GtkWidgetClass*)parent_cls;
wcls.realize(widget);
}
extern (C)
void MinWinGtkPeer_size_request(GtkWidget* w,GtkRequisition* req) {
MinWinGtkPeer* c = cast(MinWinGtkPeer*) w;
req.width = 0;
req.height = 0;
if (c.sizeRequest !is null) {
c.sizeRequest(w,req);
}
}
extern (C)
void MinWinGtkPeer_size_allocate(GtkWidget* w, GtkAllocation* a){
MinWinGtkPeer* c = cast(MinWinGtkPeer*) w;
w.allocation = *a;
if (c.sizeAllocate !is null) {
c.sizeAllocate(w,a);
}
}
extern (C)
void MinWinGtkPeer_remove(GtkContainer* container,GtkWidget* widget) {
MinWinGtkPeer *c;
GtkWidget *child;
GList *children;
c = cast(MinWinGtkPeer*)(container);
children = c.children;
while (children) {
child = cast(GtkWidget*)children.data;
if (child is widget) {
gtk_widget_unparent (widget);
c.children = g_list_remove_link (c.children, children);
g_list_free (children);
break;
}
children = children.next;
}
}
extern (C)
void MinWinGtkPeer_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data) {
MinWinGtkPeer *c;
GtkWidget *child;
GList *children;
c = cast(MinWinGtkPeer*)(container);
children = c.children;
while (children) {
child = cast(GtkWidget*)children.data;
children = children.next;
callback(child, callback_data);
}
}

View file

@ -1,87 +0,0 @@
/* MinWin Icon class
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.icon;
private {
import minwin.component;
import minwin.image;
}
version (MinWin32) {
private import minwin.mswindows;
private import minwin.app;
alias HICON IconPeer;
/*
struct IconData {
ICONINFO iconinfo;
void bitmap(Bitmap bm) {
iconinfo.hbmColor = bm.peer;
}
void mask(Bitmap mask) {
iconinfo.hbmMask = bm.peer;
}
}
*/
class Icon {
IconPeer peer;
this(char[] iconName) {
if (useWfuncs)
peer = LoadIconW(gApp.hInstance, toUTF16z(iconName));
else
peer = LoadIconA(gApp.hInstance, toMBSz(iconName));
hasPeer = OWNS_PEER;
}
/*
this(IconData* info) {
info.iconinfo.fIcon = true;
peer = CreateIconIndirect(&info.iconinfo);
hasPeer = OWNS_PEER;
}
*/
/*
this(Bitmap bitmap, Bitmap mask = null) {
ICONINFO iinfo;
iinfo.fIcon = true;
iinfo.hbmColor = bitmap.peer;
if (mask)
iinfo.hbmMask = mask.peer;
peer = CreateIconIndirect(&iinfo);
hasPeer = OWNS_PEER;
}
*/
this(IconPeer p) {
peer = p;
hasPeer = FOREIGN_PEER;
}
~this() {
dispose();
}
void dispose() {
disposePeer();
}
// Peer management
int hasPeer;
void disposePeer() {
if (hasPeer == OWNS_PEER)
DeleteObject(peer);
hasPeer = NO_PEER;
}
}
} else version (GTK) {
private import minwin.gtk;
private import minwin.app;
// peer is pixbuf
class Icon{}
}

View file

@ -1,76 +0,0 @@
/* MinWin Image class
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.image;
public import minwin.component;
private {
import minwin.app;
import minwin.paint;
}
version (MinWin32) {
private import minwin.mswindows;
alias HBITMAP ImagePeer;
class Image {
int width,height;
ImagePeer peer;
this(ImagePeer bm) {
peer = bm;
hasPeer = FOREIGN_PEER;
}
void getBits() {
// call GetDIBits. make sure bitmap isn't selected in memGC
getGContext();
// GetDIBits(memGC.peer,sdf);
}
GContext getGContext() {
GContext gc = newGContext();
gc.peer = CreateCompatibleDC(null); // hmm. null is for screen
sysAssert(gc.peer !is null, "Failed to create compatible DC for image");
gc.hasPeer = OWNS_PEER;
SelectObject(gc.peer,peer);
return gc;
}
mixin SimplePeerMixin!();
}
} else version (GTK) {
private import minwin.window;
private import minwin.gtk;
// alias GdkPixbuf* ImagePeer;
alias GdkPixmap* ImagePeer;
class Image {
int width,height;
ImagePeer peer;
this(ImagePeer bm) {
peer = bm;
hasPeer = FOREIGN_PEER;
}
GContext getGContext() {
GContext gc = newGContext();
gc.drawable = peer;
gc.peer = gdk_gc_new(gc.drawable);
gc.hasPeer = OWNS_PEER;
return gc;
}
mixin SimplePeerMixin!();
}
}

View file

@ -1,109 +0,0 @@
/* MinWin Label class
*
* Static text label
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.label;
public import minwin.component;
private {
import minwin.app;
import minwin.window;
import minwin.peerimpl;
import std.string;
import minwin.logging;
}
version (MinWin32) {
private import minwin.mswindows;
template LabelPrefSizeImpl() {
Point preferredSize() {
HDC dc = GetDC(peer);
sysAssert(dc !is null, "Failed to get label DC in preferredSize");
SIZE s;
try {
Font f = standardFont(StandardFont.Gui);
HFONT oldfont = SelectObject(dc,f.peer);
sysAssert(oldfont !is null, "Failed to get Label font in preferredSize");
BOOL ok = GetTextExtentPoint32X(dc,text_data,text_data.length,&s);
SelectObject(dc,oldfont);
sysAssert(ok != false, "Failed to get font extents in preferredSize");
} finally {
ReleaseDC(peer,dc);
}
POINT p;
p.x = s.cx;
p.y = s.cy;
if (userPreferredWidth > 0)
p.x = userPreferredWidth;
if (userPreferredHeight > 0)
p.y = userPreferredHeight;
return toPoint(p);
}
}
class Label : WindowChild {
private char[] text_data;
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
peer = CreateWindowX("STATIC",text,
SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer Label");
this.name = name;
text_data = text;
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
}
char[] text() {return text_data;}
void text(char[] c) {
text_data = c;
SendMessageX(peer,WM_SETTEXT,0,c);
}
mixin LabelPrefSizeImpl!();
mixin WindowChildImpl!();
}
} else version (GTK) {
private import minwin.gtk;
private import std.c.string;
class Label : WindowChild {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_label_new(str);
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
}
mixin WindowChildImpl!();
char[] text() {
char* str = gtk_label_get_text(cast(GtkLabel*)peer);
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] c) {
gtk_label_set_text(cast(GtkLabel*)peer,toStringz(c));
}
}
}

View file

@ -1,471 +0,0 @@
/* MinWin Layout management
*
* Defines a LayoutManager interface and some layout managers
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.layout;
public import minwin.component;
private import minwin.logging;
interface LayoutManager {
// layout children of c. Can reuse cached information from previous
// preferredSize() or layout() calls in which case the layout
// manager should only be used for a single component.
void layout(Component c);
// compute preferred layout size. Does not reuse cached information.
Point preferredSize(Component c);
// clear cache if present
void reset();
}
/***************** Flow Layout *********************/
enum Dir {
Horizontal, // left to right, then right to left
Vertical // top to bottom, then bottom to top
}
class FlowLayout : LayoutManager {
Dir dir;
int flowGap; // gap between items along flow direction
int flowReverse = 1000; // number of items to lay out before
// flipping to the other side
double endGap = 0.0; // gap at ends of layout, values <= 1 are
// percentage of space
int sideGap; // gap between largest item and side
bool sideStretch; // true means items are stretched to fit to side
int prefWidth;
int prefHeight;
this(Dir dir = Dir.Vertical) {
this.dir = dir;
prefWidth = -1;
prefHeight = -1;
}
void layout(Component c) {
Rect r;
if (c.child is null) return;
version(LOG) log.printf("laying out %x\n",c);
c.getLayoutBounds(r);
version(LOG) log.writefln("layout got bounds %d %d %d %d",
r.left,r.top,r.width,r.height);
int width = r.width;
int height = r.height;
if (prefWidth < 0) {
Point s = preferredSize(c);
prefWidth = s.x;
prefHeight = s.y;
}
int actEndGap = cast(int)endGap; // actual end gap in pixels
int actFlowGap = flowGap;
int x = r.left;
int y = r.top;
int left = x;
int top = y;
int bottom = r.bottom;
int right = r.right;
if (dir == Dir.Vertical) {
if (endGap <= 1.0)
actEndGap = cast(int)(endGap*(height - prefHeight)/2);
y += actEndGap;
} else {
if (endGap <= 1.0)
actEndGap = cast(int)(endGap*(width - prefWidth)/2);
x += actEndGap;
}
int n = 0;
bool isVisible = c.visible();
foreach (Component ch; c ) {
int w, h;
version(LOG) log.printf("doing flow layout for child %x\n",ch);
if (n == flowReverse) {
if (dir == Dir.Vertical)
y = top + height - actEndGap;
else
x = left + width - actEndGap;
actFlowGap = -actFlowGap;
}
if (ch.parentOwnsLayout) {
Point s = ch.preferredSize();
w = s.x;
h = s.y;
version(LOG) log.printf(" got flow child size for %x\n",ch);
if (dir == Dir.Vertical) {
if (n != 0 && n < flowReverse) y += flowGap; // what about first item?
if (n >= flowReverse) y -= h;
int x1 = x, w1 = width;
if (!sideStretch && (w < width)) {
x1 = x+(width-w)/2;
w1 = w;
}
r.LTWH(x1,y,w1,h);
if ((r.top > bottom || r.bottom < top) && ch.parentOwnsVisibility) {
version(LOG)log.printf("layout setting visible off on %x %d %d\n",
ch,r.bottom,height);
ch.visible = false;
} else {
version(LOG)log.writefln("about to set bounds on child %s",
ch.classinfo.name);
ch.setBounds(r);
version(LOG)log.printf("layout checking for visible on %x\n",ch);
if (ch.parentOwnsVisibility && isVisible) {
version(LOG)log.printf("layout setting visible on %x\n",ch);
ch.visible = true;
}
ch.layout(false);
}
if (n < flowReverse) y += h;
} else {
if (n < flowReverse) x += flowGap;
if (n >= flowReverse) x -= w;
int y1 = y, h1 = height;
if (!sideStretch && (h < height)) {
y1 = y+(height-h)/2;
h1 = h;
}
r.LTWH(x,y1,w,h1);
if ((r.left > right || r.right < left) && ch.parentOwnsVisibility) {
version(LOG)log.printf("layout setting visible off on %x\n",ch);
ch.visible = false;
} else {
ch.setBounds(r);
if (ch.parentOwnsVisibility && isVisible)
ch.visible = true;
ch.layout(false);
}
if (n < flowReverse) x += w;
}
}
++n;
}
version(LOG) log.printf(" done laying out %x\n",c);
}
Point preferredSize(Component c) {
version(LOG) log.printf("preferred size for %x\n",c);
int width = 0;
int height = 0;
foreach (Component ch; c ) {
int w, h;
if (ch.parentOwnsLayout) {
Point s = ch.preferredSize;
w = s.x;
h = s.y;
if (dir == Dir.Vertical) {
height += flowGap;
width = width < w ? w : width;
height += h;
} else {
width += flowGap;
height = height < h ? h : height;
width += w;
}
}
}
if (dir == Dir.Vertical) {
height += 2*cast(int)endGap;
width += 2*sideGap;
} else {
width += 2*cast(int)endGap;
height += 2*sideGap;
}
prefWidth = width;
prefHeight = height;
version(LOG) log.printf(" done preferred size for %x %d %d\n",c,width,height);
return XY(width,height);
}
void reset() {
prefWidth = -1;
prefHeight = -1;
}
}
/***************** Table Layout *********************/
// A TableLayout first computes the sum of all the preferred
// sizes of the rows and columns and then divides up the remaining
// space according to the user-supplied distribution. If the
// preferred sizes are greater then the available space the
// preferred sizes are shrunk by the user-supplied distribution to fit
class TableLayout : LayoutManager {
double[] rowScales;
double[] colScales;
int gap;
bool cache;
double[] prows; // preferred row heights
double[] pcols; // preferred column widths
double[] arows; // actual row heights
double[] acols; // actual column widths
// constructs a TableLayout with given scales. The scale
// arrays are duplicated.
this(double[] colScales, double[] rowScales, int gap = 0) {
this.rowScales = rowScales.dup;
this.colScales = colScales.dup;
this.gap = gap;
reset();
}
void reset() {
prows.length = rowScales.length;
pcols.length = colScales.length;
prows[] = 0;
pcols[] = 0;
arows.length = rowScales.length;
acols.length = colScales.length;
cache = false;
}
void layout(Component comp) {
int r,c;
int pref_width, pref_height;
if (comp.child is null) return;
version(LOG) log.printf("laying out %x\n",comp);
if (!cache)
fillPreferredData(comp);
computePreferredSize(comp,pref_width,pref_height);
Rect b,pb;
version(LOG) log.printf("about to get bounds of comp %x\n",comp);
comp.getLayoutBounds(pb);
version(LOG) log.writefln("layout got bounds %d %d %d %d",
pb.left,pb.top,pb.width,pb.height);
int width = pb.width;
int height = pb.height;
// distribute extra space or trim to fit in given space
int extra_width = width - pref_width;
int extra_height = height - pref_height;
version(LOG) log.writefln("extra %d %d \n",extra_width,extra_height);
foreach(int n, double x; prows) {
arows[n] = x + rowScales[n]*extra_height;
version(LOG) log.writefln("rows[n] %g",arows[n]);
}
double total = 0;
foreach(int n, double x; arows) {
total += x;
arows[n] = cast(int)total;
}
foreach(int n, double x; pcols) {
acols[n] = x + colScales[n]*extra_width;
version(LOG) log.writefln("cols[n] %g",acols[n]);
}
total = 0;
foreach(int n, double x; acols) {
total += x;
acols[n] = cast(int)total;
}
int x,y;
c = 0;
r = 0;
foreach (Component ch; comp ) {
if (ch.parentOwnsLayout) {
int nx = cast(int)acols[c];
int ny = cast(int)arows[r];
version(LOG) log.writefln("nx ny %d %d",nx,ny);
b.LTRB(pb.left+x,pb.top+y,nx,ny);
x = nx;
version(LOG) log.printf("setting bounds of %x during layout for %x\n",ch,comp);
ch.setBounds(b);
version(LOG) log.printf("child layout %x during layout for %x\n",ch,comp);
ch.layout(false);
if (++c >= colScales.length) {
c = 0;
x = 0;
y = ny;
if (++r >= rowScales.length)
break; // just stop if too many children
}
}
}
version(LOG) log.printf(" done laying out %x\n",comp);
}
Point preferredSize(Component comp) {
int width,height;
version(LOG) log.printf("preferred size for %x\n",comp);
fillPreferredData(comp);
computePreferredSize(comp,width,height);
version(LOG) log.printf(" done preferred size for %x\n",comp);
return XY(width,height);
}
private void fillPreferredData(Component comp) {
int r,c;
prows[] = 0;
pcols[] = 0;
foreach (Component ch; comp ) {
int w, h;
if (ch.parentOwnsLayout) {
Point s = ch.preferredSize;
w = s.x;
h = s.y;
version(LOG) log.writefln("pref size %d %d",w,h);
prows[r] = prows[r]>h ? prows[r] : h;
pcols[c] = pcols[c]>w ? pcols[c] : w;
version(LOG) log.writefln("row col %g %g",prows[r],pcols[c]);
if (++c >= colScales.length) {
c = 0;
if (++r >= rowScales.length)
break; // just stop if too many children
}
}
}
cache = true;
}
private void computePreferredSize(Component comp,
inout int width,
inout int height) {
double total = 0;
foreach(double x; pcols) { total += x; }
width = cast(int)total;
total = 0;
foreach(double x; prows) { total += x; }
height = cast(int)total;
}
}
/***************** Border Layout *********************/
/*
---------------
| N |
|-------------|
| | | |
|W | C | E|
| | | |
|-------------|
| S |
---------------
*/
enum Loc {
North, South, East, West, Center
}
class BorderLayout : LayoutManager {
Component[Loc.max+1] location; // user fills this in
void layout(Component c) {
Rect r;
if (c.child is null) return;
c.getLayoutBounds(r);
version(LOG) log.writefln("layout got bounds %d %d %d %d",
r.left,r.top,r.width,r.height);
int width = r.width;
int height = r.height;
int west,east,north,south;
int dummy;
if (location[Loc.North])
north = location[Loc.North].preferredSize().y;
if (location[Loc.South])
south = location[Loc.South].preferredSize().y;
if (location[Loc.East])
east = location[Loc.East].preferredSize().x;
if (location[Loc.West])
west = location[Loc.West].preferredSize().x;
Rect cr;
int x0 = r.left;
int y0 = r.top;
// TODO: visible off if not enough space
if (location[Loc.North]) {
cr.LTWH(x0,y0,r.width,north);
location[Loc.North].setBounds(cr);
}
if (location[Loc.South]) {
cr.LTWH(x0,y0+r.height-south,r.width,south);
location[Loc.South].setBounds(cr);
}
if (location[Loc.West]) {
cr.LTWH(x0,y0+north,west,r.height-south-north);
location[Loc.West].setBounds(cr);
}
if (location[Loc.East]) {
cr.LTWH(x0+r.width-east,y0+north,east,r.height-south-north);
location[Loc.East].setBounds(cr);
}
if (location[Loc.Center]) {
cr.LTWH(x0+west,y0+north,width-east-west,height-south-north);
location[Loc.Center].setBounds(cr);
}
}
Point preferredSize(Component c) {
int width = 0;
int height = 0;
int west,east,north,south,centerWidth,centerHeight;
int dummy;
Point center;
Point eastPt;
Point westPt;
if (location[Loc.North])
north = location[Loc.North].preferredSize().y;
if (location[Loc.South])
south = location[Loc.South].preferredSize().y;
if (location[Loc.East])
eastPt = location[Loc.East].preferredSize();
if (location[Loc.West])
westPt = location[Loc.West].preferredSize();
if (location[Loc.Center])
center = location[Loc.Center].preferredSize;
east = eastPt.x;
west = westPt.x;
int maxy = eastPt.y>westPt.y?eastPt.y:westPt.y;
maxy = maxy>center.y?maxy:center.y;
width = east + west + center.x;
height = north + south + maxy;
version(LOG)log.writefln("BorderLayout preferred size %d %d",width,height);
return XY(width,height);
}
void reset() { }
}
unittest {
// simple component for testing layout
class Foo : Component {
Rect bounds;
this(Component parent) {
if (parent)
parent.addChild(this);
}
void disposePeer(){}
PeerForAdd getPeerForAdd() {return parent.getPeerForAdd();}
void getPeerOffset(inout int x, inout int y) {}
void getBounds(inout Rect r) { r = bounds; }
void setBounds(inout Rect r) {
bounds = r;
childLayoutDirty = true;
}
void size(Point s) {
bounds.LTWH(bounds.left,bounds.top,s.x,s.y);
childLayoutDirty = true;
}
void visible(bool vis) { }
bool visible() { return true; }
void repaint() { }
}
Foo a = new Foo(null);
Foo c1 = new Foo(a);
Foo c2 = new Foo(a);
Foo c3 = new Foo(a);
}

View file

@ -1,140 +0,0 @@
/* MinWin ListBox class
*
* Display a list of items to choose from.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.listbox;
// TODO: multi-select
public import minwin.component;
private {
import minwin.app;
import minwin.window;
import minwin.peerimpl;
import std.string;
import minwin.logging;
}
version (MinWin32) {
private import minwin.mswindows;
class ListBox : WindowChild {
this(Component parent, char[][] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
HINSTANCE hInst = GetModuleHandleA(null);
peer = CreateWindowA("LISTBOX","",
WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,hInst,null);
sysAssert(peer !is null, "Failed to create peer ListBox");
foreach (char[] s; text) {
SendMessageX(peer,LB_ADDSTRING,0,s);
}
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
}
mixin WindowChildImpl!();
Point preferredSize() {
// width = SendMessageA(peer,CB_GETDROPPEDWIDTH,0,0);
int height = SendMessageA(peer,LB_GETITEMHEIGHT,cast(WPARAM)-1,0)*
SendMessageA(peer,LB_GETCOUNT,0,0);
int width = 75;
return XY(width,height);
}
// -1 for custom text
int selection() {
return SendMessageA(peer,LB_GETCURSEL,0,0);
}
void selection(int n) {
SendMessageA(peer,LB_SETCURSEL,n,0);
version (LOG) log.writefln("number of item is %d",
SendMessageA(peer,CB_GETCOUNT,0,0));
}
}
} else version (GTK) {
private import minwin.gtk;
private import std.c.string;
class ListBox : WindowChild {
this(Component parent, char[][] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
GType the_type = g_type_fundamental(16); // means string
GtkListStore* model = gtk_list_store_newv(1,&the_type);
GtkTreeIter iter;
foreach (char[] s; text) {
gtk_list_store_append(model,&iter);
int[3] args;
args[0] = 0;
args[1] = cast(int)toStringz(s);
args[2] = -1;
gtk_list_store_set_valist(model,&iter,&args);
}
peer = gtk_tree_view_new_with_model(cast(GtkTreeModel*)model);
g_object_unref(cast(GObject*)model);
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
gtk_tree_view_columns_autosize(cast(GtkTreeView*)peer);
gtk_tree_view_expand_all(cast(GtkTreeView*)peer);
GList* objs = gtk_tree_view_get_columns(cast(GtkTreeView*)peer);
// printf("len %d\n",g_list_length(objs));
// printf("cols %d\n",gtk_tree_model_get_n_columns(cast(GtkTreeModel*)model));
g_list_free(objs);
}
// -1 for custom text
int selection() {
// GtkComboBox* box = cast(GtkComboBox*)peer;
// return gtk_combo_box_get_active(box);
return 0;
}
void selection(int n) {
// GtkComboBox* box = cast(GtkComboBox*)peer;
// gtk_combo_box_set_active(box,n);
}
char[] text() {
char* str;
GtkTreeView* list = cast(GtkTreeView*)peer;
GtkTreeModel* model = gtk_tree_view_get_model(list);
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first(model,&iter)) {
int n = selection();
GValue* val;
while (n--) {
gtk_tree_model_iter_next(model,&iter);
}
gtk_tree_model_get_value(model,&iter,0,val);
str = *(cast(char**)val);
g_value_unset(val);
}
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] s) {
assert(false);
}
mixin WindowChildImpl!();
}
}

View file

@ -1,19 +0,0 @@
module minwin.logging;
public import std.stream;
//version=StdOutLog;
version (LOG) {
Stream log;
version (StdOutLog) {
static this() {
log = stdout;
}
} else {
static this() {
log = new BufferedFile("log.txt",FileMode.OutNew);
}
}
}

View file

@ -1,128 +0,0 @@
module minwin.menu;
public import minwin.window;
private {
import minwin.app;
import std.string;
}
// todo: disposePeer?
version (MinWin32) {
private import minwin.mswindows;
alias HMENU MenuPeer;
alias HMENU MenuBarPeer;
class MenuBar {
MenuBarPeer peer;
char[] name;
Window owner;
Menu[] menus;
this(Window parent, char[] name = "") {
peer = CreateMenu();
BOOL ok = SetMenu(parent.peer,peer); // destroy old menu?
sysAssert(ok != false, "Failed to set menu");
owner = parent;
owner.menubar = this;
this.name = name;
}
}
class Menu {
MenuPeer peer;
char[] name;
MenuBar parentBar;
this(inout MenuBar bar, char[] label, char[] name = "") {
this.name = name;
parentBar = bar;
peer = CreateMenu();
BOOL ok = AppendMenuX(bar.peer,MF_POPUP,cast(void*)peer,label);
sysAssert(ok != false, "Failed to append to menubar");
bar.menus ~= this;
ok = DrawMenuBar(bar.owner.peer);
sysAssert(ok != false, "Failed to draw menu bar");
}
void addSeparator() {
BOOL ok = AppendMenuA(peer,MF_SEPARATOR,null,null);
sysAssert(ok != false, "Failed to append separator to menu");
}
void add(char[] name, int cmd) {
BOOL ok = AppendMenuX(peer,MF_STRING,cast(void*)(cmd),name);
sysAssert(ok != false, "Failed to append to menu");
}
}
} else version (GTK) {
private import minwin.gtk;
alias GtkWidget* MenuPeer;
alias GtkWidget* MenuBarPeer;
class MenuBar {
MenuBarPeer peer;
char[] name;
Window owner;
Menu[] menus;
this(Window parent, char[] name = "") {
this.name = name;
peer = gtk_menu_bar_new();
GtkContainer* p = cast(GtkContainer*)parent.getPeerForAdd();
gtk_container_add(p,peer);
gtk_widget_show(peer);
owner = parent;
owner.menubar = this;
}
}
class Menu {
MenuPeer peer;
char[] name;
MenuBar parentBar;
GtkWidget* trigger;
this(inout MenuBar bar, char[] label, char[] name = "") {
this.name = name;
parentBar = bar;
char* cname = toStringz(label);
peer = gtk_menu_new();
trigger = gtk_menu_item_new_with_label(cname);
gtk_menu_item_set_submenu(cast(GtkMenuItem*)trigger,peer);
gtk_menu_shell_append(cast(GtkMenuShell*)bar.peer,trigger);
gtk_widget_show(trigger);
bar.menus ~= this;
}
void addSeparator() {
GtkWidget* item = gtk_separator_menu_item_new();
gtk_menu_shell_append(cast(GtkMenuShell*)peer,item);
gtk_widget_show(item);
}
void add(char[] name, int cmd) {
char* cname = toStringz(name);
GtkWidget* item = gtk_menu_item_new_with_label(cname);
gtk_menu_shell_append(cast(GtkMenuShell*)peer,item);
g_object_set_data(cast(GObject*)item,"MinWinItemCommand",
cast(gpointer)cmd);
g_signal_connect_data(item,"activate",
cast(GCallback)&mw_menuitem_callback,
cast(gpointer)parentBar.owner,
null,cast(GConnectFlags)0);
gtk_widget_show(item);
}
}
extern (C)
void mw_menuitem_callback(GtkWidget* w, gpointer ud) {
Window x = cast(Window)ud;
if (x) {
int cmd = cast(int)g_object_get_data(cast(GObject*)w,"MinWinItemCommand");
x.doCommand(cmd);
}
}
}

View file

@ -1,609 +0,0 @@
/*
* Windows API not covered by std.c.windows.windows
*/
module minwin.mswindows;
public import std.c.windows.windows;
package import std.windows.charset;
package import std.utf;
extern (Windows):
export BOOL PostMessageA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
export BOOL SendMessageA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
export BOOL SendMessageW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
export UINT SetTimer(HWND hWnd, uint id,uint time, TIMERPROC proc);
export BOOL KillTimer(HWND hWnd, uint id);
export BOOL IsWindowVisible (HWND hWnd);
export BOOL IsWindowEnabled (HWND hWnd);
export BOOL IsWindow (HWND hWnd);
export BOOL EnableWindow (HWND hWnd, BOOL enable);
export BOOL BringWindowToTop (HWND hWnd);
export BOOL DestroyWindow (HWND hWnd);
export BOOL MoveWindow (HWND hWnd, int x, int y, int w, int h, byte bRepaint);
export int SetWindowLongA (HWND hWnd, int nIndex, int dwNewLong);
export int GetWindowLongA (HWND hWnd, int nIndex);
export int GetWindowTextA (HWND hWnd, LPTSTR str, int count);
export int GetWindowTextW (HWND hWnd, LPWSTR str, int count);
export BOOL SetWindowTextA (HWND hWnd, LPTSTR str);
export BOOL SetWindowTextW (HWND hWnd, LPWSTR str);
export ushort GetKeyState(int key);
export ATOM RegisterClassExA(WNDCLASSEXA *lpWndClass);
export BOOL GetTextExtentPoint32A(HDC dc, LPCSTR str, int len, SIZE* s);
export BOOL GetTextExtentPoint32W(HDC dc, LPWSTR str, int len, SIZE* s);
export BOOL IsDialogMessageA(HWND hWnd, PMSG msg);
export int LoadStringA(HINSTANCE inst, LPSTR id, LPTSTR buf, int siz);
export int LoadStringW(HINSTANCE inst, LPWSTR id, LPWSTR buf, int siz);
export int MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
export int GetSystemMetrics(int nIndex);
/*
struct INITCOMMONCONTROLSEX {
DWORD dwSize;
DWORD dwICC;
}
export void InitCommonControls();
export BOOL InitCommonControlsEx(INITCOMMONCONTROLSEX*);
*/
export DWORD GetSysColor(int);
const uint WM_PAINTICON = 0x0026;
const uint WM_ICONERASEBKGND = 0x0027;
const uint WM_NEXTDLGCTL = 0x0028;
const uint WM_SPOOLERSTATUS = 0x002A;
const uint WM_DRAWITEM = 0x002B;
const uint WM_MEASUREITEM = 0x002C;
const uint WM_DELETEITEM = 0x002D;
const uint WM_VKEYTOITEM = 0x002E;
const uint WM_CHARTOITEM = 0x002F;
const uint WM_SETFONT = 0x0030;
const uint WM_GETFONT = 0x0031;
const uint WM_SETHOTKEY = 0x0032;
const uint WM_GETHOTKEY = 0x0033;
const uint WM_QUERYDRAGICON = 0x0037;
const uint WM_COMPAREITEM = 0x0039;
const uint WM_SIZING= 0x0214;
const uint WM_CAPTURECHANGED= 0x0215;
const uint WM_MOVING= 0x0216;
const uint WM_POWERBROADCAST= 0x0218;
const uint WM_DEVICECHANGE= 0x0219;
const uint DS_MODALFRAME = 0x80;
const uint ICON_SMALL = 0;
const uint ICON_BIG = 1;
export BOOL GdiFlush();
struct SIZE {
int cx;
int cy;
}
alias SIZE* PSIZE;
const uint SBM_SETPOS =0x00E0;
const uint SBM_GETPOS =0x00E1;
const uint SBM_SETRANGE =0x00E2;
const uint SBM_SETRANGEREDRAW =0x00E6;
const uint SBM_GETRANGE =0x00E3;
const uint SBM_ENABLE_ARROWS =0x00E4;
const uint SBM_SETSCROLLINFO =0x00E9;
const uint SBM_GETSCROLLINFO =0x00EA;
const uint SIF_RANGE =0x0001;
const uint SIF_PAGE =0x0002;
const uint SIF_POS =0x0004;
const uint SIF_DISABLENOSCROLL =0x0008;
const uint SIF_TRACKPOS =0x0010;
const uint SIF_ALL =(SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS);
const uint SW_SCROLLCHILDREN =0x0001;
const uint SW_INVALIDATE =0x0002;
const uint SW_ERASE =0x0004;
struct SCROLLINFO {
UINT cbSize;
UINT fMask;
int nMin;
int nMax;
UINT nPage;
int nPos;
int nTrackPos;
}
export int SetScrollInfo(HWND, int, SCROLLINFO*, BOOL);
export BOOL GetScrollInfo(HWND, int, SCROLLINFO*);
struct ICONINFO {
BOOL fIcon;
DWORD xHotspot;
DWORD yHotspot;
HBITMAP hbmMask;
HBITMAP hbmColor;
}
alias ICONINFO* PICONINFO;
export HICON CreateIconIndirect(PICONINFO piconinfo);
export HBITMAP CreateCompatibleBitmap(HDC hdc,int width,int height);
export COLORREF GetPixel(HDC hdc,int x,int y);
export HBRUSH CreateSolidBrush(COLORREF c);
export BOOL BitBlt(HDC dest,int x,int y,int width,int height,
HDC src,int xsrc,int ysrc, DWORD op);
//alias HANDLE HBRUSH;
export HANDLE LoadImageA(HINSTANCE hInstance, LPCSTR lpName,UINT utype,
int cx, int cy, UINT load);
export HANDLE LoadImageW(HINSTANCE hInstance, LPCWSTR lpName,UINT utype,
int cx, int cy, UINT load);
enum { IMAGE_BITMAP, IMAGE_CURSOR, IMAGE_ICON };
const uint GW_HWNDFIRST = 0;
const uint GW_HWNDLAST = 1;
const uint GW_HWNDNEXT = 2;
const uint GW_HWNDPREV = 3;
const uint GW_OWNER = 4;
const uint GW_CHILD = 5;
const uint GW_MAX = 5;
const int GWL_USERDATA = -21;
export HWND GetWindow (HWND hWnd, int dir);
const uint MF_INSERT =0x00000000L;
const uint MF_CHANGE =0x00000080L;
const uint MF_APPEND =0x00000100L;
const uint MF_DELETE =0x00000200L;
const uint MF_REMOVE =0x00001000L;
const uint MF_BYCOMMAND =0x00000000L;
const uint MF_BYPOSITION =0x00000400L;
const uint MF_SEPARATOR =0x00000800L;
const uint MF_ENABLED =0x00000000L;
const uint MF_GRAYED =0x00000001L;
const uint MF_DISABLED =0x00000002L;
const uint MF_UNCHECKED =0x00000000L;
const uint MF_CHECKED =0x00000008L;
const uint MF_USECHECKBITMAPS =0x00000200L;
const uint MF_STRING =0x00000000L;
const uint MF_BITMAP =0x00000004L;
const uint MF_OWNERDRAW =0x00000100L;
const uint MF_POPUP =0x00000010L;
const uint MF_MENUBARBREAK =0x00000020L;
const uint MF_MENUBREAK =0x00000040L;
const uint MF_UNHILITE =0x00000000L;
const uint MF_HILITE =0x00000080L;
const uint MF_SYSMENU =0x00002000L;
const uint MF_HELP =0x00004000L;
const uint MF_MOUSESELECT =0x00008000L;
export HMENU CreateMenu();
export BOOL DrawMenuBar(HWND win);
export BOOL SetMenu(HWND win, HMENU menu);
export BOOL AppendMenuA(HMENU menu, uint flags, void*item, char* str);
export BOOL AppendMenuW(HMENU menu, uint flags, void*item, wchar* str);
// 32 bit version
void* SetWindowLongPtr (HWND hWnd, int nIndex, void* dwNewLong) {
return cast(void*)SetWindowLongA(hWnd,nIndex,cast(int)dwNewLong);
}
void* GetWindowLongPtr (HWND hWnd, int nIndex) {
return cast(void*)GetWindowLongA(hWnd,nIndex);
}
/* CombineRgn() Styles */
enum {
RGN_AND = 1,
RGN_OR = 2,
RGN_XOR = 3,
RGN_DIFF = 4,
RGN_COPY = 5
}
export BOOL EqualRgn(HRGN a, HRGN b);
export BOOL RectInRegion(HRGN r, RECT *);
export BOOL PtInRegion(HRGN r, int x, int y);
export int OffsetRgn(HRGN r, int x, int y);
export HRGN CreatePolygonRgn(POINT *p, int n, int rule);
export HRGN CreateRectRgnIndirect(RECT *r);
export HRGN CreateEllipticRgnIndirect(RECT *r);
export HRGN CreateRoundRectRgn(int a, int b, int c, int d, int e, int f);
export int CombineRgn(HRGN r, HRGN a, HRGN b, int n);
export int GetRgnBox(HRGN r, LPRECT p);
export BOOL PaintRgn(HDC dc, HRGN r);
struct RGNDATAHEADER {
DWORD dwSize;
DWORD iType;
DWORD nCount;
DWORD nRgnSize;
RECT rcBound;
}
struct RGNDATA {
RGNDATAHEADER rdh;
char Buffer[1];
}
struct XFORM {
FLOAT eM11;
FLOAT eM12;
FLOAT eM21;
FLOAT eM22;
FLOAT eDx;
FLOAT eDy;
}
export DWORD GetRegionData(HRGN h, DWORD s, RGNDATA* data);
export HRGN ExtCreateRegion(XFORM *t, DWORD s, RGNDATA *data);
export int FillRect(HDC hDC,RECT *lprc,HBRUSH hbr);
export int FrameRect(HDC hDC,RECT *lprc,HBRUSH hbr);
export BOOL InvertRect(HDC hDC,RECT *lprc);
export BOOL IntersectRect(LPRECT lprcDst,RECT *lprcSrc1,RECT *lprcSrc2);
export BOOL UnionRect(LPRECT lprcDst,RECT *lprcSrc1,RECT *lprcSrc2);
export BOOL SubtractRect(LPRECT lprcDst,RECT *lprcSrc1,RECT *lprcSrc2);
export BOOL OffsetRect(LPRECT lprc,int dx,int dy);
export BOOL IsRectEmpty(RECT *lprc);
export BOOL EqualRect(RECT *lprc1,RECT *lprc2);
export BOOL PtInRect(RECT *lprc,POINT pt);
/* PolyFill() Modes */
enum {
ALTERNATE = 1,
WINDING = 2
}
export int SetPolyFillMode(HDC hdc, int m);
export int GetPolyFillMode(HDC hdc);
/*
* Combo Box messages
*/
const uint CB_GETEDITSEL =0x0140;
const uint CB_LIMITTEXT =0x0141;
const uint CB_SETEDITSEL =0x0142;
const uint CB_ADDSTRING =0x0143;
const uint CB_DELETESTRING =0x0144;
const uint CB_DIR =0x0145;
const uint CB_GETCOUNT =0x0146;
const uint CB_GETCURSEL =0x0147;
const uint CB_GETLBTEXT =0x0148;
const uint CB_GETLBTEXTLEN =0x0149;
const uint CB_INSERTSTRING =0x014A;
const uint CB_RESETCONTENT =0x014B;
const uint CB_FINDSTRING =0x014C;
const uint CB_SELECTSTRING =0x014D;
const uint CB_SETCURSEL =0x014E;
const uint CB_SHOWDROPDOWN =0x014F;
const uint CB_GETITEMDATA =0x0150;
const uint CB_SETITEMDATA =0x0151;
const uint CB_GETDROPPEDCONTROLRECT =0x0152;
const uint CB_SETITEMHEIGHT =0x0153;
const uint CB_GETITEMHEIGHT =0x0154;
const uint CB_SETEXTENDEDUI =0x0155;
const uint CB_GETEXTENDEDUI =0x0156;
const uint CB_GETDROPPEDSTATE =0x0157;
const uint CB_FINDSTRINGEXACT =0x0158;
const uint CB_SETLOCALE =0x0159;
const uint CB_GETLOCALE =0x015A;
const uint CB_GETTOPINDEX =0x015b;
const uint CB_SETTOPINDEX =0x015c;
const uint CB_GETHORIZONTALEXTENT =0x015d;
const uint CB_SETHORIZONTALEXTENT =0x015e;
const uint CB_GETDROPPEDWIDTH =0x015f;
const uint CB_SETDROPPEDWIDTH =0x0160;
const uint CB_INITSTORAGE =0x0161;
const uint CBN_SELCHANGE =1;
const uint CBN_DBLCLK =2;
const uint CBN_SETFOCUS =3;
const uint CBN_KILLFOCUS =4;
const uint CBN_EDITCHANGE =5;
const uint CBN_EDITUPDATE =6;
const uint CBN_DROPDOWN =7;
const uint CBN_CLOSEUP =8;
const uint CBN_SELENDOK =9;
const uint CBN_SELENDCANCEL =10;
/*
* Combo Box styles
*/
const uint CBS_SIMPLE =0x0001L;
const uint CBS_DROPDOWN =0x0002L;
const uint CBS_DROPDOWNLIST =0x0003L;
const uint CBS_OWNERDRAWFIXED =0x0010L;
const uint CBS_OWNERDRAWVARIABLE =0x0020L;
const uint CBS_AUTOHSCROLL =0x0040L;
const uint CBS_OEMCONVERT =0x0080L;
const uint CBS_SORT =0x0100L;
const uint CBS_HASSTRINGS =0x0200L;
const uint CBS_NOINTEGRALHEIGHT =0x0400L;
const uint CBS_DISABLENOSCROLL =0x0800L;
const uint CBS_UPPERCASE =0x2000L;
const uint CBS_LOWERCASE =0x4000L;
/*
* Listbox messages
*/
const uint LB_ADDSTRING =0x0180;
const uint LB_INSERTSTRING =0x0181;
const uint LB_DELETESTRING =0x0182;
const uint LB_SELITEMRANGEEX =0x0183;
const uint LB_RESETCONTENT =0x0184;
const uint LB_SETSEL =0x0185;
const uint LB_SETCURSEL =0x0186;
const uint LB_GETSEL =0x0187;
const uint LB_GETCURSEL =0x0188;
const uint LB_GETTEXT =0x0189;
const uint LB_GETTEXTLEN =0x018A;
const uint LB_GETCOUNT =0x018B;
const uint LB_SELECTSTRING =0x018C;
const uint LB_DIR =0x018D;
const uint LB_GETTOPINDEX =0x018E;
const uint LB_FINDSTRING =0x018F;
const uint LB_GETSELCOUNT =0x0190;
const uint LB_GETSELITEMS =0x0191;
const uint LB_SETTABSTOPS =0x0192;
const uint LB_GETHORIZONTALEXTENT =0x0193;
const uint LB_SETHORIZONTALEXTENT =0x0194;
const uint LB_SETCOLUMNWIDTH =0x0195;
const uint LB_ADDFILE =0x0196;
const uint LB_SETTOPINDEX =0x0197;
const uint LB_GETITEMRECT =0x0198;
const uint LB_GETITEMDATA =0x0199;
const uint LB_SETITEMDATA =0x019A;
const uint LB_SELITEMRANGE =0x019B;
const uint LB_SETANCHORINDEX =0x019C;
const uint LB_GETANCHORINDEX =0x019D;
const uint LB_SETCARETINDEX =0x019E;
const uint LB_GETCARETINDEX =0x019F;
const uint LB_SETITEMHEIGHT =0x01A0;
const uint LB_GETITEMHEIGHT =0x01A1;
const uint LB_FINDSTRINGEXACT =0x01A2;
const uint LB_SETLOCALE =0x01A5;
const uint LB_GETLOCALE =0x01A6;
const uint LB_SETCOUNT =0x01A7;
const uint LB_INITSTORAGE =0x01A8;
const uint LB_ITEMFROMPOINT =0x01A9;
/*
* Listbox Styles
*/
const uint LBS_NOTIFY =0x0001L;
const uint LBS_SORT =0x0002L;
const uint LBS_NOREDRAW =0x0004L;
const uint LBS_MULTIPLESEL =0x0008L;
const uint LBS_OWNERDRAWFIXED =0x0010L;
const uint LBS_OWNERDRAWVARIABLE =0x0020L;
const uint LBS_HASSTRINGS =0x0040L;
const uint LBS_USETABSTOPS =0x0080L;
const uint LBS_NOINTEGRALHEIGHT =0x0100L;
const uint LBS_MULTICOLUMN =0x0200L;
const uint LBS_WANTKEYBOARDINPUT =0x0400L;
const uint LBS_EXTENDEDSEL =0x0800L;
const uint LBS_DISABLENOSCROLL =0x1000L;
const uint LBS_NODATA =0x2000L;
const uint LBS_NOSEL =0x4000L;
const uint LBS_STANDARD =(LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER);
const uint OFN_READONLY =0x00000001;
const uint OFN_OVERWRITEPROMPT =0x00000002;
const uint OFN_HIDEREADONLY =0x00000004;
const uint OFN_NOCHANGEDIR =0x00000008;
const uint OFN_SHOWHELP =0x00000010;
const uint OFN_ENABLEHOOK =0x00000020;
const uint OFN_ENABLETEMPLATE =0x00000040;
const uint OFN_ENABLETEMPLATEHANDLE =0x00000080;
const uint OFN_NOVALIDATE =0x00000100;
const uint OFN_ALLOWMULTISELECT =0x00000200;
const uint OFN_EXTENSIONDIFFERENT =0x00000400;
const uint OFN_PATHMUSTEXIST =0x00000800;
const uint OFN_FILEMUSTEXIST =0x00001000;
const uint OFN_CREATEPROMPT =0x00002000;
const uint OFN_SHAREAWARE =0x00004000;
const uint OFN_NOREADONLYRETURN =0x00008000;
const uint OFN_NOTESTFILECREATE =0x00010000;
const uint OFN_NONETWORKBUTTON =0x00020000;
const uint OFN_NOLONGNAMES =0x00040000;
const uint OFN_EXPLORER =0x00080000;
const uint OFN_NODEREFERENCELINKS =0x00100000;
const uint OFN_LONGNAMES =0x00200000;
const uint SBS_HORZ =0x0000;
const uint SBS_VERT =0x0001;
const uint SBS_TOPALIGN =0x0002;
const uint SBS_LEFTALIGN =0x0002;
const uint SBS_BOTTOMALIGN =0x0004;
const uint SBS_RIGHTALIGN =0x0004;
const uint SBS_SIZEBOXTOPLEFTALIGN =0x0002;
const uint SBS_SIZEBOXBOTTOMRIGHTALIGN =0x0004;
const uint SBS_SIZEBOX =0x0008;
export HWND CreateWindowExW(
DWORD dwExStyle,
LPWSTR lpClassName,
LPWSTR lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent ,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam);
HWND CreateWindowW(
LPWSTR lpClassName,
LPWSTR lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent ,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam)
{
return CreateWindowExW(0, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}
// PIXELFORMATDESCRIPTOR stuff
const uint PFD_TYPE_RGBA = 0;
const uint PFD_TYPE_COLORINDEX = 1;
const uint PFD_MAIN_PLANE = 0;
const uint PFD_OVERLAY_PLANE = 1;
const uint PFD_DOUBLEBUFFER = 1;
const uint PFD_STEREO = 2;
const uint PFD_DRAW_TO_WINDOW = 4;
const uint PFD_DRAW_TO_BITMAP = 8;
const uint PFD_SUPPORT_GDI = 16;
const uint PFD_SUPPORT_OPENGL = 32;
const uint PFD_GENERIC_FORMAT = 64;
const uint PFD_NEED_PALETTE = 128;
const uint PFD_NEED_SYSTEM_PALETTE = 0x00000100;
const uint PFD_SWAP_EXCHANGE = 0x00000200;
const uint PFD_SWAP_COPY = 0x00000400;
const uint PFD_SWAP_LAYER_BUFFERS = 0x00000800;
const uint PFD_GENERIC_ACCELERATED = 0x00001000;
const uint PFD_DEPTH_DONTCARE = 0x20000000;
const uint PFD_DOUBLEBUFFER_DONTCARE = 0x40000000;
const uint PFD_STEREO_DONTCARE = 0x80000000;
export int ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR* ppfd);
export int DescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes, PIXELFORMATDESCRIPTOR* ppfd);
alias HANDLE HGLRC;
const int WGL_SWAP_MAIN_PLANE = 1;
//int wglUseFontOutlinesW(HDC, uint, uint, uint, float, float, int, _GLYPHMETRICSFLOAT *);
//int wglUseFontOutlinesA(HDC, uint, uint, uint, float, float, int, _GLYPHMETRICSFLOAT *);
//int wglUseFontBitmapsW(HDC, uint, uint, uint);
//int wglUseFontBitmapsA(HDC, uint, uint, uint);
//int wglSetLayerPaletteEntries(HDC, int, int, int, uint*);
//int wglRealizeLayerPalette(HDC, int, int);
//int wglGetLayerPaletteEntries(HDC, int, int, int, uint*);
//int wglDescribeLayerPlane(HDC*, int, int, uint, LAYERPLANEDESCRIPTOR *);
//HGLRC wglCreateLayerContext(HDC, int);
export int wglSwapLayerBuffers(HDC, uint);
export int wglShareLists(HGLRC, HGLRC);
export int wglMakeCurrent(HDC, HGLRC);
export void* wglGetProcAddress(char*);
export HDC wglGetCurrentDC();
export HGLRC wglGetCurrentContext();
export int wglDeleteContext(HGLRC);
export HGLRC wglCreateContext(HDC);
export int wglCopyContext(HGLRC, HGLRC, uint);
export BOOL SwapBuffers(HDC);
const int SM_CXBORDER = 5;
const int SM_CYBORDER = 5;
const int SM_CXFIXEDFRAME = 7;
const int SM_CYFIXEDFRAME = 8;
const int SM_CXEDGE = 45;
const int SM_CYEDGE= 46;
const int SM_CXMENUCHECK = 71;
const int SM_CYMENUCHECK = 72;
//
// these wrappers makes windows unicode look alot better and avoids excessive code duplication
package
{
HWND CreateWindowX(
char[] lpClassName,
char[] lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent ,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam)
{
if (useWfuncs)
return CreateWindowExW(0, toUTF16z(lpClassName), toUTF16z(lpWindowName), dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
else
return CreateWindowExA(0, toMBSz(lpClassName), toMBSz(lpWindowName), dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}
BOOL SendMessageX(HWND hWnd, UINT msg, WPARAM wParam, char[] lParam)
{
if (useWfuncs)
return SendMessageW(hWnd, msg, wParam, cast(LPARAM)toUTF16z(lParam));
else
return SendMessageW(hWnd, msg, wParam, cast(LPARAM)toMBSz(lParam));
}
int MessageBoxX(HWND hWnd, char[] lpText, char[] lpCaption, UINT uType)
{
if (useWfuncs)
return MessageBoxW(hWnd, toUTF16z(lpText), toUTF16z(lpCaption), uType);
else
return MessageBoxA(hWnd, toMBSz(lpText), toMBSz(lpCaption), uType);
}
BOOL GetTextExtentPoint32X(HDC dc, char[] str, int len, SIZE* s)
{
if (useWfuncs) {
wchar[] wstr = toUTF16(str);
return GetTextExtentPoint32W(dc, wstr.ptr, wstr.length, s);
} else {
size_t al;
char* ansi = toMBSzl(str, al);
return GetTextExtentPoint32A(dc, ansi, al, s);
}
}
BOOL AppendMenuX(HMENU menu, uint flags, void*item, char[] str)
{
if (useWfuncs)
return AppendMenuW(menu, flags, item, toUTF16z(str));
else
return AppendMenuA(menu, flags, item, toMBSz(str));
}
}
/******************************************
* Converts the UTF-8 string s into a null-terminated string in a Windows
* 8-bit character set.
*
* Params:
* s = UTF-8 string to convert.
* reslen = the number of bytes in the resulting buffer
* (not including the null terminator) will be place here.
* codePage = is the number of the target codepage, or
* 0 - ANSI,
* 1 - OEM,
* 2 - Mac
*
* Authors:
* yaneurao, Walter Bright, Stewart Gordon
*/
private import std.windows.syserror;
char* toMBSzl(char[] s, out size_t reslen, uint codePage = 0)
{
// Only need to do this if any chars have the high bit set
foreach (char c; s)
{
if (c >= 0x80)
{
char[] result;
int readLen;
wchar* ws = std.utf.toUTF16z(s);
result.length = WideCharToMultiByte(codePage, 0, ws, -1, null, 0,
null, null);
if (result.length)
{
readLen = WideCharToMultiByte(codePage, 0, ws, -1, result.ptr,
result.length, null, null);
}
if (!readLen || readLen != result.length)
{
throw new Exception("Couldn't convert string: " ~
sysErrorString(GetLastError()));
}
reslen = result.length ? result.length-1 : 0;
return result.ptr;
}
}
reslen = s.length;
return std.string.toStringz(s);
}

View file

@ -1,155 +0,0 @@
/* MultiDelegate: add, remove and fire multiple delegates
*
* A multi-delegate is similar to a C# multicast delegate.
* It has array copy semantics so assignment will copy the
* length and data pointer but modification could allocate
* a distinct copy. Delegates in a multi-delegate are fired
* in the order they were added.
*
* A MultiBoolDelegate is a multi-delegates where each
* delegate returns a bool and the result of executing
* the MultiBoolDelegate is the or'ed value of all the bools.
*
* To append to a multi-delegate use ~=
* To remove a delegate from a multi-delegate use remove()
* To fire all the delegates in order use opCall: multidg()
* To test if the multi-delegate is empty use isEmpty()
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.multidg;
template DelegateMixin() {
// Append dg to the end of the multi-delegate.
// If dg is null nothing changes.
void opCatAssign(Callback dg) {
if (dg is null) return;
bool found = false;
int len = dgs.length;
int n = len-1;
while (n >= 0 && dgs[n] is null)
--n;
if (n < len-1)
dgs[n+1] = dg;
else
dgs ~= dg;
}
// Remove the first occurance of dg from the multi-delegate.
// If dg is not in the multi-delegate nothing changes.
void remove(Callback dg) {
if (dgs.length == 0) return;
bool found = false;
for (int n=0 ; n < dgs.length-1; ++n) {
if (!found && dgs[n] is dg) found = true;
if (found) dgs[n] = dgs[n+1];
if (dgs[n] is null) break;
}
if (found || dgs[length-1] is dg)
dgs[length-1] = null;
}
bool isEmpty() {
if (dgs.length == 0)
return true;
else if (dgs[0] is null)
return true;
else
return false;
}
// the array of delegate with possible trailing nulls
Callback[] dgs;
}
// MultiDelegate with variadic args
struct MultiDelegate(T...)
{
alias void delegate(T) Callback;
mixin DelegateMixin!();
void opCall(T args) {
foreach( Callback dg; dgs) {
if (dg is null) break;
dg(args);
}
}
}
// MultiBoolDelegate with variadic args
struct MultiBoolDelegate(T...) {
alias bool delegate(T) Callback;
mixin DelegateMixin!();
bool opCall(T args) {
bool result = false;
foreach( Callback dg; dgs) {
if (dg is null) break;
result |= dg(args);
}
return result;
}
}
unittest {
/** Example class illustrating multi-delegates based on Qt's example at
* http://doc.trolltech.com/3.3/signalsandslots.html
*
*/
class Foo {
MultiDelegate!(int) valueChanged;
private int val;
int value() {
return val;
}
void value(int v) {
if (val != v) {
val = v;
valueChanged(v);
}
}
MultiBoolDelegate!(int,double) boolDelegate;
private int val2;
int value2() {
return val2;
}
void value2(int v) {
if (val2 != v && !boolDelegate(v,2.0*v)) {
val2 = v;
}
}
}
Foo a = new Foo;
Foo b = new Foo;
Foo c = new Foo;
a.valueChanged ~= &b.value;
assert( a.value == 0 );
assert( b.value == 0 );
b.value = 11;
assert( a.value == 0 );
assert( b.value == 11 );
a.value = 79;
assert( a.value == 79 );
assert( b.value == 79 );
a.valueChanged ~= &c.value;
a.value = 80;
assert( a.value == 80 );
assert( b.value == 80 );
assert( c.value == 80 );
a.valueChanged.remove(&b.value);
a.value = 100;
assert( a.value == 100 );
assert( b.value == 80 );
assert( c.value == 100 );
a.boolDelegate ~= delegate bool(int x,double y) {
return (y > 10.0);
};
a.value2 = 2;
assert( a.value2 == 2 );
a.value2 = 20;
assert( a.value2 == 2 );
}

View file

@ -1,605 +0,0 @@
/* MinWin Paint module
*
* An GContext is a simple 2D drawing API similar to a Windows DC
* and an X11 Graphics Context. A GXContext is a more advanced
* painting API that is similar to GDI+ or Quartz.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.paint;
public {
import minwin.geometry;
import minwin.peer;
}
private {
import minwin.app;
import minwin.image;
import minwin.logging;
}
// TODO: gdi+
// maybe also add a template paint context with coordinates in non-int
GContext newGContext() {
GContext gc = GContext.freeList;
if (gc) {
GContext.freeList = GContext.freeList.next;
} else {
gc = new GContext;
}
return gc;
}
enum PenStyle {
Solid = 0,
Dash = 1, /* ------- */
Dot = 2, /* ....... */
DashDot = 3 /* _._._._ */
// todo: None?
}
enum LineJoin {
Round,
Bevel,
Miter
}
enum PaintMode {
Copy, Invert, And, Or, Xor
}
version (GTK)
version = SharedPenBrushImpl;
version (SharedPenBrushImpl) {
struct PenData {
uint width;
Color color;
PenStyle style;
LineJoin join;
}
class Pen {
PenData data;
this(PenData* data) {
this.data = *data;
}
this(Color color) {
data.color = color;
}
void dispose(){}
}
class Brush {
Color color;
this(Color color) {
this.color = color;
}
}
}
version (MinWin32) {
private import minwin.mswindows;
public import minwin.font;
alias HDC GContextPeer;
class GXContext { } // GDI+
alias HPEN PenPeer;
alias HBRUSH BrushPeer;
private DWORD paintModeToNative(PaintMode mode) {
DWORD nmode;
switch (mode) {
case PaintMode.Copy: nmode = SRCCOPY; break;
case PaintMode.Invert: nmode = NOTSRCCOPY; break;
case PaintMode.And: nmode = SRCAND; break;
case PaintMode.Or: nmode = SRCPAINT; break;
case PaintMode.Xor: nmode = SRCINVERT; break;
default: assert(0);
}
return nmode;
}
struct PenData {
LOGPEN native;
void width(uint w) {
native.lopnWidth = XY(w,w).native;
}
void color(Color c) {
native.lopnColor = c.native;
}
void style(PenStyle s) {
native.lopnStyle = s;
}
void lineJoin(LineJoin j) {
}
}
class Pen {
PenPeer peer;
mixin SimplePeerMixin!();
this(PenData* data) {
peer = CreatePenIndirect(&data.native);
sysAssert(peer !is null, "Failed to create pen");
hasPeer = OWNS_PEER;
}
this(Color color) {
PenData pd;
pd.color = color;
this(&pd);
}
this(PenPeer peer) {
this.peer = peer;
hasPeer = FOREIGN_PEER;
}
}
class Brush {
BrushPeer peer;
mixin SimplePeerMixin!();
this(Color color) {
peer = CreateSolidBrush(color.native);
sysAssert(peer !is null, "Failed to create brush");
hasPeer = OWNS_PEER;
}
this(BrushPeer peer) {
this.peer = peer;
hasPeer = FOREIGN_PEER;
}
}
class GContext {
GContextPeer peer;
GContext next; // free list link
static GContext freeList;
bool release;
HWND hwnd; // companion hwnd used if release is true
Font font;
FontPeer origFont; // stores font in used before setFont is called
Pen pen;
PenPeer origPen;
Brush brush;
BrushPeer origBrush;
Region cliprgn;
PAINTSTRUCT paintstruct;
~this() {
disposePeer();
}
int hasPeer;
void dispose() {
disposePeer();
next = freeList;
freeList = this;
}
void disposePeer() {
pen = null;
font = null;
origFont = origPen = origBrush = null;
brush = null;
cliprgn = null;
if (hasPeer == OWNS_PEER) {
if (release)
ReleaseDC(hwnd,peer);
else {
BOOL ok = DeleteDC(peer);
sysAssert(ok != false, "Failed to delete DC");
}
}
}
Rect updateRect() {
return toRect(paintstruct.rcPaint);
}
Font setFont(Font f) {
Font oldFont = font;
font = f;
if (f is null) {
SelectObject(peer, cast(HGDIOBJ) origFont);
} else if (oldFont is null) {
origFont = cast(FontPeer)SelectObject(peer, cast(HGDIOBJ) font.peer);
} else {
SelectObject(peer, cast(HGDIOBJ) font.peer);
}
return oldFont;
}
void getFontMetrics(inout FontMetrics f) {
BOOL ok = GetTextMetricsA(peer,&f.native);
sysAssert(ok != false, "Failed to get font metrics");
}
Pen setPen(Pen p) {
Pen oldPen = pen;
pen = p;
if (p is null) {
SelectObject(peer, cast(HGDIOBJ) origPen);
} else if (oldPen is null) {
origPen = cast(PenPeer)SelectObject(peer, cast(HGDIOBJ) pen.peer);
} else {
SelectObject(peer, cast(HGDIOBJ) pen.peer);
}
return oldPen;
}
Brush setBrush(Brush p) {
Brush oldBrush = brush;
brush = p;
if (p is null) {
SelectObject(peer, cast(HGDIOBJ) origBrush);
} else if (oldBrush is null) {
origBrush = cast(BrushPeer)SelectObject(peer, cast(HGDIOBJ) brush.peer);
} else {
SelectObject(peer, cast(HGDIOBJ) brush.peer);
}
return oldBrush;
}
void getClip(Region rgn) {
int res = GetClipRgn(peer,rgn.peer);
sysAssert(res != -1, "Failed to get clip region");
}
// in postscript could mean intersect with current clip region
void setClip(Region rgn) {
int res = SelectClipRgn(peer,rgn.peer);
sysAssert(res != 0, "Failed to set clip region");
}
// pen must be set
void drawRect(inout Rect r) {
// TODO: move in by pen width
BOOL ok = MoveToEx(peer,r.left,r.top,null);
sysAssert(ok != false, "Failed to draw rect");
LineTo(peer,r.left,r.bottom-1);
LineTo(peer,r.right-1,r.bottom-1);
LineTo(peer,r.right-1,r.top);
LineTo(peer,r.left,r.top);
}
// brush must be set
void fillRect(inout Rect r) {
sysAssert(brush !is null, "Brush must be set for fillRect");
int ok = FillRect(peer,&r.native,brush.peer);
sysAssert(ok != false, "Failed to fill rect");
}
void drawText(int x, int y, char[] str) {
BOOL ok;
if (useWfuncs) {
wchar[] buf = toUTF16(str);
ok = TextOutW(peer, x, y, buf.ptr, buf.length);
}
else {
auto buf = toMBSz(str);
ok = TextOutA(peer, x, y, buf, std.c.string.strlen(buf));
}
sysAssert(ok != false, "Failed to draw text");
}
void drawLine(int x1, int y1, int x2, int y2) {
BOOL ok = MoveToEx(peer,x1,y1,null);
sysAssert(ok != false, "Failed to draw line");
LineTo(peer,x2,y2);
}
void drawPolyline(Point[] pts) {
if (pts.length > 1) {
BOOL ok = MoveToEx(peer,pts[0].x,pts[0].y,null);
sysAssert(ok != false, "Failed to draw polyline");
for (int n=1; n < pts.length; ++n) {
LineTo(peer,pts[n].x,pts[n].y);
}
}
}
void drawPolygon(Point[] pts) {
if (pts.length > 1) {
BOOL ok = MoveToEx(peer,pts[0].x,pts[0].y,null);
sysAssert(ok != false, "Failed to draw polygon");
for (int n=1; n < pts.length; ++n) {
LineTo(peer,pts[n].x,pts[n].y);
}
LineTo(peer,pts[0].x,pts[0].y);
}
}
void drawBezier(Point[] pts) {
// PolyBezier(peer,pts.ptr,pts.length);
}
void fillPolygon(Point[] pts) {
//?
}
void fillRegion(Region rgn) {
sysAssert(brush !is null, "Brush must be set for fillRect");
// FillRgn(peer,rgn,brush);
}
void drawRegion(Region rgn) {
BOOL ok = PaintRgn(peer,rgn.peer);
sysAssert(ok != false, "Failed to draw region");
}
void drawImage(Image im, int x, int y, PaintMode mode = PaintMode.Copy) {
HDC memDC = CreateCompatibleDC(peer);
sysAssert(memDC !is null, "Failed to create compatible DC in drawImage");
HANDLE res = SelectObject(memDC,im.peer);
sysAssert(res !is null, "Failed to select bitmap in drawImage");
version(LOG)log.writefln("drawing image %x %d %d",
im,im.width,im.height);
DWORD nmode = paintModeToNative(mode);
BOOL ok = BitBlt(peer,x,y,im.width,im.height,memDC,0,0,nmode);
sysAssert(ok != false, "Failed to BitBlt drawImage");
version(LOG)log.writefln(" result %d",cast(int)res);
ok = DeleteDC(memDC);
sysAssert(ok != false, "Failed to delete compatible DC in drawImage");
}
void stretchImage(Image im, int x, int y,
int w, int h, PaintMode mode = PaintMode.Copy) {
HDC memDC = CreateCompatibleDC(peer);
sysAssert(memDC !is null, "Failed to create compatible DC in stretchImage");
SelectObject(memDC,im.peer);
DWORD nmode = paintModeToNative(mode);
BOOL ok = StretchBlt(peer,x,y,w,h,memDC,0,0,im.width,im.height,nmode);
sysAssert(ok != false, "Failed to StretchBlt in stretchImage");
DeleteDC(memDC);
}
void drawSubImage(Image im, int x, int y,
int sx, int sy, int sw, int sh,
PaintMode mode = PaintMode.Copy) {
HDC memDC = CreateCompatibleDC(peer);
sysAssert(memDC !is null, "Failed to create compatible DC in drawSubImage");
SelectObject(memDC,im.peer);
DWORD nmode = paintModeToNative(mode);
BOOL ok = BitBlt(peer,x,y,sw,sh,memDC,sx,sx,nmode);
sysAssert(ok != false, "Failed to BitBlt in drawSubImage");
DeleteDC(memDC);
}
void stretchSubImage(Image im, int x, int y, int w, int h,
int sx, int sy, int sw, int sh,
PaintMode mode = PaintMode.Copy) {
HDC memDC = CreateCompatibleDC(peer);
sysAssert(memDC !is null, "Failed to create compatible DC in stretchSubImage");
SelectObject(memDC,im.peer);
DWORD nmode = paintModeToNative(mode);
BOOL ok = StretchBlt(peer,x,y,w,h,memDC,sx,sy,sw,sh,nmode);
sysAssert(ok != false, "Failed to StretchBlt in stretchSubImage");
DeleteDC(memDC);
}
void flush() {
GdiFlush();
}
}
} else version (GTK) {
private import minwin.gtk;
public import minwin.font;
private GdkFunction paintModeToNative(PaintMode mode) {
GdkFunction nmode;
switch (mode) {
case PaintMode.Copy: nmode = GdkFunction.GDK_COPY; break;
case PaintMode.Invert: nmode = GdkFunction.GDK_COPY_INVERT; break;
case PaintMode.And: nmode = GdkFunction.GDK_AND; break;
case PaintMode.Or: nmode = GdkFunction.GDK_OR; break;
case PaintMode.Xor: nmode = GdkFunction.GDK_XOR; break;
default: assert(0);
}
return nmode;
}
alias GdkGC* GContextPeer;
class GXContext { } // not impl in GDK
class GContext {
GContextPeer peer;
GContext next; // free list link
static GContext freeList;
GdkDrawable* drawable;
PangoLayout* layout;
Font font;
Pen pen;
Brush brush;
bool penActive;
GdkEventExpose* paintEvent;
~this() {
disposePeer();
}
int hasPeer;
void dispose() {
disposePeer();
next = freeList;
freeList = this;
}
void disposePeer() {
pen = null;
font = null;
brush = null;
penActive = false;
if (hasPeer == OWNS_PEER) {
g_object_unref(cast(GObject*)peer);
// g_object_unref(cast(GObject*)layout);
}
}
Rect updateRect() {
Rect r;
if (paintEvent)
r = toRect(paintEvent.area);
return r;
}
Font setFont(Font f) {
Font oldFont = font;
// if (oldFont is null)
// oldFont = DefaultFont;
font = f;
if (font)
pango_layout_set_font_description(layout,font.peer);
return oldFont;
}
void getFontMetrics(inout FontMetrics f) {
PangoContext* c = pango_layout_get_context(layout);
PangoFontMetrics* data = pango_context_get_metrics(c,font.peer,null);
f.ascent = pango_font_metrics_get_ascent(data);
f.descent = pango_font_metrics_get_descent(data);
// f.leading = f.descent;
f.leading = 0;
f.size = f.ascent+f.descent;
f.maxWidth = pango_font_metrics_get_approximate_char_width(data)/PANGO_SCALE;
f.size /= PANGO_SCALE;
f.ascent /= PANGO_SCALE;
f.descent /= PANGO_SCALE;
f.leading /= PANGO_SCALE;
pango_font_metrics_unref(data);
}
private void setForeground(Color rgb) {
GdkColor c;
c.red = Color.rescale(rgb.red,ubyte.max,ushort.max);
c.green = Color.rescale(rgb.green,ubyte.max,ushort.max);
c.blue = Color.rescale(rgb.blue,ubyte.max,ushort.max);
gdk_gc_set_rgb_fg_color(peer,&c);
}
Pen setPen(Pen p) {
Pen oldPen = pen;
pen = p;
if (p !is null) {
GdkLineStyle style = GdkLineStyle.GDK_LINE_SOLID;
if (p.data.style != PenStyle.Solid) {
style = GdkLineStyle.GDK_LINE_ON_OFF_DASH;
gdk_gc_set_dashes(peer,0,dashlist[style-1].ptr,
dashlist[style-1].length);
}
gdk_gc_set_line_attributes(peer,p.data.width,style,
GdkCapStyle.GDK_CAP_BUTT,
cast(GdkJoinStyle)p.data.join);
setForeground(p.data.color);
penActive = true;
}
return oldPen;
}
Brush setBrush(Brush p) {
Brush oldBrush = brush;
brush = p;
if (brush) {
setForeground(brush.color);
penActive = false;
}
return oldBrush;
}
void drawRect(inout Rect r) {
if (pen && !penActive) {
setForeground(pen.data.color);
penActive = true;
}
gdk_draw_rectangle(drawable,peer,false,
r.left,r.top,r.width-1,r.height-1);
}
// brush must be set
void fillRect(inout Rect r) {
if (brush && penActive) {
setForeground(brush.color);
penActive = false;
}
gdk_draw_rectangle(drawable,peer,true,
r.left,r.top,r.width,r.height);
}
private static {
byte[][3] dashlist;
byte[2] dashed = [6,6];
byte[2] dotted = [4,2];
byte[4] dashdotted = [4,6,4,2];
}
static this() {
dashlist[0] = dashed;
dashlist[1] = dotted;
dashlist[2] = dashdotted;
}
void drawLine(int x1, int y1, int x2, int y2) {
gdk_draw_line(drawable, peer, x1,y1,x2,y2);
}
void drawPolyline(Point[] pts) {
gdk_draw_lines(drawable, peer, cast(GdkPoint*)pts.ptr, pts.length);
}
void drawPolygon(Point[] pts) {
gdk_draw_polygon(drawable, peer, false, cast(GdkPoint*)pts.ptr, pts.length);
}
void fillPolygon(Point[] pts) {
gdk_draw_polygon(drawable, peer, true, cast(GdkPoint*)pts.ptr, pts.length);
}
void drawText(int x, int y, char[] str) {
pango_layout_set_text(layout,str.ptr,str.length);
gdk_draw_layout(drawable,peer,x,y,layout);
}
void drawImage(Image im, int x, int y, PaintMode mode = PaintMode.Copy) {
GdkGCValues vals;
gdk_gc_get_values(peer,&vals);
gdk_gc_set_function(peer,paintModeToNative(mode));
gdk_draw_drawable(drawable,peer,im.peer,0,0,x,y,-1,-1);
gdk_gc_set_function(peer,vals.Function);
}
void drawSubImage(Image im, int x, int y,
int sx, int sy, int sw, int sh,
PaintMode mode = PaintMode.Copy) {
GdkGCValues vals;
gdk_gc_get_values(peer,&vals);
gdk_gc_set_function(peer,paintModeToNative(mode));
gdk_draw_drawable(drawable,peer,im.peer,sx,sy,x,y,sw,sh);
gdk_gc_set_function(peer,vals.Function);
}
void stretchImage(Image im, int x, int y, int w, int h,
PaintMode mode = PaintMode.Copy) {
// TODO
GdkGCValues vals;
gdk_gc_get_values(peer,&vals);
gdk_gc_set_function(peer,paintModeToNative(mode));
gdk_draw_drawable(drawable,peer,im.peer,0,0,x,y,-1,-1);
gdk_gc_set_function(peer,vals.Function);
}
void stretchSubImage(Image im, int x, int y, int w, int h,
int sx, int sy, int sw, int sh,
PaintMode mode = PaintMode.Copy) {
// TODO
GdkGCValues vals;
gdk_gc_get_values(peer,&vals);
gdk_gc_set_function(peer,paintModeToNative(mode));
gdk_draw_drawable(drawable,peer,im.peer,sx,sy,x,y,sw,sh);
gdk_gc_set_function(peer,vals.Function);
}
void flush() { gdk_flush(); }
}
}

View file

@ -1,54 +0,0 @@
/* MinWin Peer module
*
* Mixin templates to simplify peer management
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.peer;
version (MinWin32) {
private import minwin.mswindows;
alias HWND PeerForAdd;
alias PeerForAdd WindowChildPeer;
} else version (GTK) {
private import minwin.gtk;
alias GtkWidget* PeerForAdd;
alias PeerForAdd WindowChildPeer;
}
// possible values for hasPeer property
enum {
NO_PEER, // object has no peer
FOREIGN_PEER, // peer is not owned by object
OWNS_PEER // object owns peer
}
template PeerMixin() {
~this() {
disposePeer();
}
int hasPeer;
}
template SimplePeerMixin() {
~this() {
disposePeer();
}
int hasPeer;
void dispose() { disposePeer(); }
void disposePeer() {
if (hasPeer == OWNS_PEER) {
version (MinWin32) {
int ok = DeleteObject(peer);
sysAssert(ok != false, "Failed to dispose peer Font");
} else version (GTK) {
g_object_unref(cast(GObject*)peer);
}
}
hasPeer = NO_PEER;
}
}

View file

@ -1,265 +0,0 @@
/* MinWin PeerImpl module
*
* Mixin template to implement heavyweight peer for window children.
* Plus PeerWrapper to insert peer children into the MinWin tree.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.peerimpl;
private {
import minwin.app;
import minwin.component;
import minwin.window;
import std.string;
import minwin.logging;
}
version (MinWin32) {
public import minwin.paint;
private import minwin.mswindows;
template WindowChildImpl() {
WindowChildPeer peer;
PeerForAdd getPeerForAdd() { return peer; }
WindowChildPeer getPeer() { return peer;}
void disposePeer(){
if (hasPeer == OWNS_PEER && parent is null) {
int ok = DeleteObject(peer);
sysAssert(ok != false, "Failed to dispose peer child");
}
hasPeer = NO_PEER;
}
void visible(bool vis) {
ShowWindow(peer,vis ? SW_SHOW : SW_HIDE); // ignore bool result
}
bool visible() {
return IsWindowVisible(peer) != 0;
}
void enabled(bool b) {
EnableWindow(peer, b);
}
bool enabled() {
return IsWindowEnabled(peer) == TRUE;
}
void requestFocus() {
HWND old = SetFocus(peer);
sysAssert(old !is null, "Failed to requestFocus");
}
// gets window bounds that encose the entire widget in parent coordinates
void getBounds(inout Rect r) {
Rect r2;
BOOL ok = GetWindowRect(peer,&r2.native);
sysAssert(ok != false, "Failed to get window bounds");
int x,y;
parent.getPeerOffset(x,y);
r2.LTWH(r2.left+x,r2.top+y,r2.width,r2.height);
r = r2;
}
void setBounds(inout Rect r) {
Rect r2,r3 = r;
getBounds(r2);
int x,y;
parent.getPeerOffset(x,y);
r3.LTWH(r3.left+x,r3.top+y,r3.width,r3.height);
BOOL ok = MoveWindow(peer,r3.left,r3.top,r3.width,r3.height,true);
sysAssert(ok != false, "Failed to move window in setBounds");
if (r2 != r)
childLayoutDirty = true;
}
alias Component.size size;
void size(Point s) {
Rect r2;
BOOL ok = GetWindowRect(peer,&r2.native);
sysAssert(ok != false, "Failed to get window rect in size");
ok = MoveWindow(peer,r2.left,r2.top,s.x,s.y,true);
sysAssert(ok != false, "Failed to move window in size");
if (r2.width != s.x || r2.height != s.y)
childLayoutDirty = true;
}
void repaint() {
BOOL ok = InvalidateRect(peer,null,clearBackgroundOnPaint);
sysAssert(ok != false, "Failed to invalidate rect in repaint");
}
GContext getGContext() {
GContext gc = newGContext();
gc.peer = GetDC(peer);
sysAssert(gc.peer !is null, "Failed to get DC in getGContext");
gc.hasPeer = OWNS_PEER;
return gc;
}
}
// Get the Component object associated with the given peer.
// The peer is accessed from the Component using the peer property.
WindowChild peerToWindowChild(WindowChildPeer peer) {
return cast(WindowChild)cast(void*)GetWindowLongA(peer,GWL_USERDATA);
}
// Associate c with the peer. On Windows this overwrites the
// window UserData.
void setWindowChildPeer(Component c, WindowChildPeer peer,int peerState) {
SetWindowLongA(peer,GWL_USERDATA,cast(int)cast(void*)c);
c.hasPeer = peerState;
// TODO investigate if we need a destroy callback to clear hasPeer
}
} else version(GTK) {
private import minwin.gtk;
extern (C)
gint mw_exposechild_callback(GtkWidget w, GdkEventExpose*ev,
gpointer ud) {
Component win = cast(Component) ud;
if (win) {
win.layout(true);
}
return 0;
}
template WindowChildImpl() {
WindowChildPeer peer;
PeerForAdd getPeerForAdd() { return peer; }
WindowChildPeer getPeer() { return peer;}
void disposePeer() {
if (hasPeer == OWNS_PEER && parent is null)
gtk_widget_destroy(peer);
hasPeer = NO_PEER;
}
void visible(bool vis) {
if (vis) {
gtk_widget_show(peer);
} else {
gtk_widget_hide(peer);
}
}
bool visible() {
GtkObject* obj = cast(GtkObject*)peer;
return ((obj.flags & GtkWidgetFlags.GTK_VISIBLE) != 0);
}
void enabled(bool b) {
gtk_widget_set_sensitive(peer,cast(int)b);
}
bool enabled() {
GtkObject* obj = cast(GtkObject*)peer;
return ((obj.flags & GtkWidgetFlags.GTK_SENSITIVE) != 0);
}
override void requestFocus() {
GtkObject* obj = cast(GtkObject*)peer;
// printf("%d\n", cast(int)((obj.flags & GtkWidgetFlags.GTK_CAN_FOCUS) != 0));
gtk_widget_grab_focus(peer);
}
void getBounds(inout Rect r) {
int x,y,x2,y2,w,h,depth;
parent.getPeerOffset(x,y);
// gdk_window_get_geometry(peer.window,&x2,&y2,&w,&h,&depth);
Rect r2 = toRect(peer.allocation);
r.LTWH(r2.left+x,r2.top+y,r2.width,r2.height);
// version(LOG) log.writefln("get bounds got %d %d %d %d",
// x2+x,y2+y,w,h);
}
void setBounds(inout Rect r) {
version(LOG) log.writefln("setBounds %d %d %d %d",
r.left,r.top,r.width,r.height);
int x,y;
parent.getPeerOffset(x,y);
Rect r2 = r;
r2.left = r2.left+x;
r2.top = r2.top+y;
gtk_widget_size_allocate(peer,&r2.native);
/*
int x2,y2,w,h,depth;
gdk_window_get_geometry(peer.window,&x2,&y2,&w,&h,&depth);
r.LTWH(x2+x,y2+y,w,h);
version(LOG) log.writefln("after set bounds got %d %d %d %d",
x2,y2,w,h);
if (r2.width != r.width || r2.height != r.height)
*/
childLayoutDirty = true;
}
alias Component.size size;
void size(Point s) {
Rect r;
getBounds(r);
r.LTWH(r.left,r.top,s.x,s.y);
setBounds(r);
}
Point preferredSize() {
GtkRequisition req;
gtk_widget_size_request(peer,&req);
int width = req.width;
int height = req.height;
if (userPreferredWidth > 0)
width = userPreferredWidth;
if (userPreferredHeight > 0)
height = userPreferredHeight;
return XY(width,height);
}
// mark as needing a repaint and post event to event queue
void repaint() {
Rect r;
getBounds(r);
gdk_window_invalidate_rect(peer.window,&r.native,true);
}
}
WindowChild peerToWindowChild(WindowChildPeer peer) {
gpointer ptr = g_object_get_data(cast(GObject*)peer,"MinWinUserData");
return cast(WindowChild)ptr;
}
void setWindowChildPeer(Component c, WindowChildPeer peer,int peerState) {
g_object_set_data(cast(GObject*)peer,"MinWinUserData",cast(gpointer)peer);
g_signal_connect_data(peer,"destroy",
cast(GCallback)&mw_wcdestroy_callback,
cast(gpointer)c,
null,GConnectFlags.G_CONNECT_AFTER);
c.hasPeer = peerState;
}
extern (C)
void mw_wcdestroy_callback(GtkObject w, gpointer ud) {
Component wc = cast(Component) ud;
if (wc && (wc.hasPeer == OWNS_PEER)) {
wc.hasPeer = NO_PEER;
}
}
}
// assumes the peer has already been parented to the result of
// parent.getPeerForAdd
class PeerWrapper : WindowChild {
this(Component parent, WindowChildPeer peer) {
this.peer = peer;
setWindowChildPeer(this,peer,FOREIGN_PEER);
parent.addChild(this);
}
mixin WindowChildImpl!();
}

View file

@ -1,9 +0,0 @@
MinWin originally written by Ben Hinkle.
Updated on 20060520 by Christopher E. Miller.
My changes are donated to the MinWin project.
Updated on 20061128 by Tomas L. Olsen.
It should now compile using DMD 0.175.
http://www.dprogramming.com/minwin.php

View file

@ -1,37 +0,0 @@
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
FIND_PACKAGE (GTK2)
IF (GTK2_FOUND)
INCLUDE_DIRECTORIES (${minwin_gtk_SOURCE_DIR} ${GTK2_INCLUDE_DIRS})
LINK_DIRECTORIES (${minwin_gtk_SOURCE_DIR} ${GTK2_LIBRARY_DIRS})
ADD_EXECUTABLE (sample sample.d)
TARGET_LINK_LIBRARIES (sample minwin_gtk)
ADD_EXECUTABLE (layout layout.d)
TARGET_LINK_LIBRARIES (layout minwin_gtk)
ADD_EXECUTABLE (topgroup topgroup.d)
TARGET_LINK_LIBRARIES (topgroup minwin_gtk)
ADD_EXECUTABLE (widgets widgets.d)
TARGET_LINK_LIBRARIES (widgets minwin_gtk)
ADD_EXECUTABLE (menus menus.d)
TARGET_LINK_LIBRARIES (menus minwin_gtk)
ADD_EXECUTABLE (painting painting.d)
TARGET_LINK_LIBRARIES (painting minwin_gtk)
ADD_EXECUTABLE (sdialog sdialog.d)
TARGET_LINK_LIBRARIES (sdialog minwin_gtk)
ADD_EXECUTABLE (sdialog2 sdialog2.d)
TARGET_LINK_LIBRARIES (sdialog2 minwin_gtk)
ADD_EXECUTABLE (idle idle.d)
TARGET_LINK_LIBRARIES (idle minwin_gtk)
ENDIF (GTK2_FOUND)

View file

@ -1,40 +0,0 @@
/* Sample MinWin application: idle processing
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.idle;
import minwin.all;
import std.random;
import std.string;
import std.utf;
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("Idle processing");
char[] text = "Idle processing...";
char[] cur = "";
win.quitOnDestroy = true;
win.paintDelegate ~= delegate void(Component source, GContext gc) {
auto Font font = new Font("",14,FontWeight.Bold);
Font oldfont = gc.setFont(font);
gc.drawText(100,100,text);
gc.setFont(oldfont);
};
win.keyDelegate ~= delegate void(Component source, KeyEvent* event) {
if (event.id == KeyPressedEvent) {
char[4] buf;
cur = toUTF8(buf,event.keyCode).dup;
}
};
app.idleTime = 1000; // every second
app.idleDelegate ~= delegate void() {
text = cur ~ " " ~ toString(rand());
win.repaint();
};
win.visible = true;
return app.enterEventLoop();
}

View file

@ -1,84 +0,0 @@
/* Sample MinWin application: layout and groups
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.layout;
import minwin.all;
import std.random;
import std.string;
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("Layout Sample");
char[] text = "Click the Random number button";
win.quitOnDestroy = true;
// set table layout
static double[3] yy = [.3, .2, .5];
static double[2] xx = [.5,.5];
win.layoutMgr = new TableLayout(xx,yy);
// define some buttons to put in the table
Button b1 = new Button(win,"Random number");
Button b2 = new Button(win,"hide groups");
Button b3 = new Button(win,"hide layout");
// define a group to put in the table
Group g = new Group(win);
FlowLayout flow = new FlowLayout();
flow.sideStretch = true;
g.layoutMgr = flow;
Button sub1 = new Button(g,"click random");
Button sub2 = new Button(g,"sub2");
// make a sub-group of g
Group g2 = new Group(g);
flow = new FlowLayout(Dir.Horizontal);
flow.flowReverse = 1;
g2.layoutMgr = flow;
Button sub3 = new Button(g2,"sub3");
Button sub4 = new Button(g2,"sub4");
Button sub5 = new Button(g2,"sub5");
Button b4 = new Button(win,"b3");
// define actions
b1.actionDelegate ~= delegate void(Component source) {
sub1.text = toString(rand());
};
b2.actionDelegate ~= delegate void(Component source) {
g.visible = !g.visible;
};
b3.actionDelegate ~= delegate void(Component source) {
// remove from layout computations
g.parentOwnsLayout = !g.parentOwnsLayout;
};
win.pack();
win.visible = true;
Window win2 = new Window("Border Layout Sample");
win2.quitOnDestroy = true;
BorderLayout bl = new BorderLayout();
Button w2b1 = new Button(win2,"north");
bl.location[Loc.North] = w2b1;
Button w2b2 = new Button(win2,"south");
bl.location[Loc.South] = w2b2;
Button w2b3 = new Button(win2,"east");
bl.location[Loc.East] = w2b3;
Button w2b4 = new Button(win2,"west");
bl.location[Loc.West] = w2b4;
Button w2b5 = new Button(win2,"center");
bl.location[Loc.Center] = w2b5;
win2.layoutMgr = bl;
win2.pack();
win2.visible = true;
return app.enterEventLoop();
}

View file

@ -1,23 +0,0 @@
# To build the samples type "make -f win32.mak"
#VER = Motif
#LIB = libminwin_motif.a
#XLIBS = -L-L/usr/X11R6/lib -L-lXm -L-lXt -L-lX11 -L-lImlib
VER = GTK
LIB = libminwin_gtk.a
XLIBS = -L-L/usr/X11R6/lib -L-lgtk-x11-2.0 -L-lX11
DMD = dmd
TARGETS= sample layout topgroup \
widgets menus painting sdialog sdialog2 idle
targets : $(TARGETS)
% : %.d
$(DMD) -g ../$(LIB) -I../.. $(XLIBS) -version=$(VER) -of$@ $< -version=LOG
clean:
- rm *.o $(TARGETS)

View file

@ -1,61 +0,0 @@
/* Sample MinWin application: Menus
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.menus;
import minwin.all;
import std.string;
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("Menu Sample");
win.quitOnDestroy = true;
win.layoutMgr = new FlowLayout;
MenuBar mb = new MenuBar(win);
Menu file = new Menu(mb,"File");
file.add("Open...",100);
file.addSeparator();
file.add("Save...",234);
Menu edit = new Menu(mb,"Edit");
edit.add("Hello",400);
edit.add("World",500);
char[] text = "select menu";
win.commandDelegate ~= delegate void(Component source, int cmd) {
text = toString(cmd);
win.repaint();
if (cmd == 100) {
// show open file dialog
FileDialogData data;
data.title = "Open File";
if (openFileDialog(win,data)) {
text = "you selected " ~ data.result;
}
} else if (cmd == 234) {
// show save file dialog
FileFilter[2] filt;
filt[0].description = "Foo bar files";
filt[0].extensions ~= "*.foo";
filt[1].description = "All files";
filt[1].extensions ~= "*";
FileDialogData data;
data.title = "Save File";
data.filter = filt;
if (saveFileDialog(win,data)) {
text = "you saved " ~ data.result;
}
}
};
win.paintDelegate ~= delegate void(Component source, GContext gc) {
auto Font font = new Font("",12);
Font oldfont = gc.setFont(font);
gc.drawText(100,100,text);
gc.setFont(oldfont);
};
win.visible = true;
return app.enterEventLoop();
}

View file

@ -1,81 +0,0 @@
/* Sample MinWin application: Graphics and painting
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.painting;
import minwin.all;
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("Painting Sample");
win.quitOnDestroy = true;
Image im = win.getCompatibleImage(100,150);
GContext gc = im.getGContext();
auto Pen p2 = new Pen(RGB(0,0,0));
Pen oldPen = gc.setPen(p2);
Rect r = LTWH(0,0,100,150);
auto Brush b2 = new Brush(RGB(255,255,255));
Brush oldBrush = gc.setBrush(b2);
gc.fillRect(r);
gc.drawRect(r);
gc.setBrush(oldBrush);
PenData pd;
pd.width = 4;
pd.style = PenStyle.Solid;
pd.color = RGB(100,0,120);
auto Pen p = new Pen(&pd);
gc.setPen(p);
gc.drawLine(0,0,100,150);
gc.drawLine(100,0,0,150);
gc.drawLine(50,0,50,150);
gc.setPen(oldPen);
gc.dispose();
win.paintDelegate ~= delegate void(Component source, GContext pc) {
auto Font font = new Font("", 20, FontWeight.Bold);
Font oldfont = pc.setFont(font);
pc.drawText(100,100,"testing");
pc.setFont(oldfont);
pc.drawLine(10,10,20,20);
pc.drawLine(30,10,35,50);
static Point[3] pts = [{{40,10}}, {{45,50}}, {{50,30}}];
pc.drawPolyline(pts);
static Point[4] pts2 = [{{70,10}},{{75,50}},{{80,30}},{{90,10}}];
pc.drawPolygon(pts2);
static Point[4] pts3 = [{{100,10}},{{105,50}},{{110,30}},{{120,10}}];
pc.fillPolygon(pts3);
// try different line styles and colors
PenData pd;
pd.width = 4;
pd.color = RGB(100,200,0);
pd.style = PenStyle.Dash;
auto Pen p1 = new Pen(&pd);
Pen oldPen = pc.setPen(p1);
pc.drawLine(10,100,20,200);
pd.color = RGB(0,200,200);
auto Pen p2 = new Pen(&pd);
pc.setPen(p2);
pc.drawLine(50,100,50,200);
pc.setPen(oldPen);
pc.drawImage(im,180,30);
};
win.visible = true;
return app.enterEventLoop();
}

View file

@ -1,67 +0,0 @@
/* Sample MinWin application to mimic winsamp.d
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.sample;
import minwin.all;
import minwin.logging;
import std.string;
version (Windows) {
import minwin.mswindows;
}
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("MinWin Sample");
char[] text = "D Does Windows, Motif and GTK";
win.quitOnDestroy = true;
win.paintDelegate ~= delegate void(Component source, GContext gc) {
FontData fd;
fd.size = 18;
fd.weight = FontWeight.Bold;
auto Font font = new Font(fd);
Font oldfont = gc.setFont(font);
gc.drawText(100,100,text);
gc.setFont(oldfont);
// Image im = win.loadCompatibleImage(44);
// gc.drawImage(im,200,200);
};
win.mouseDelegate ~= delegate void(Component source, MouseEvent* event) {
Point pt = event.point;
text = pt.toString ~ " " ~ toString(cast(int)event.id) ~ " " ~ toString(event.modifiers);
win.repaint();
};
Button b = new Button(win,"Click me");
Button b2 = new Button(win,"Don't click me");
// like winsamp.d place buttons by hand
Point s = b.preferredSize;
Rect r = LTWH(20,50,s.x,s.y);
b.setBounds(r);
s = b2.preferredSize;
r.LTWH(100,50,s.x,s.y);
b2.setBounds(r);
// define actions to perform on button clicks
b.actionDelegate ~= delegate void(Component source) {
informationDialog(win, "Hello, world!", "Greeting");
};
b2.actionDelegate ~= delegate void(Component source) {
warningDialog(win, "You've been warned...", "Prepare to GP fault");
*(cast(int*) null) = 666;
};
// show window
version (Windows) {
ShowWindow(win.peer,gApp.nCmdShow);
} else {
win.visible = true;
}
return app.enterEventLoop();
}

View file

@ -1,2 +0,0 @@
EXETYPE NT
SUBSYSTEM WINDOWS,5.0

View file

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Pub.MinWin.Sample"
type="win32"
/>
<description>Sample MinWin application.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

View file

@ -1,2 +0,0 @@
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "sample.exe.manifest"

View file

@ -1,63 +0,0 @@
/* Sample dialog application with OOP style
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.sdialog;
import minwin.all;
import minwin.logging;
class MyDialog : Dialog {
int result;
this(MyWindow win, char[] str) {
super(win,str);
layoutMgr = new FlowLayout;
Button clicked;
Button ok = new Button(this,"OK");
Button cancel = new Button(this,"Cancel");
CheckBox bb = new CheckBox(this,"this is a big check");
CheckBox bb2 = new CheckBox(this,"this check");
ok.actionDelegate ~= &okCallback;
cancel.actionDelegate ~= &cancelCallback;
pack();
}
void okCallback(Component c) {
MyWindow win = cast(MyWindow)owner;
win.title = "you hit ok";
result = 100;
visible = false;
}
void cancelCallback(Component c) {
MyWindow win = cast(MyWindow)owner;
win.title = "you hit cancel";
result = 101;
visible = false;
}
}
class MyWindow : Window {
this(char[] str) {
super(str);
layoutMgr = new FlowLayout;
Button but = new Button(this,"click me");
but.actionDelegate ~= &doDialogCallback;
}
void doDialogCallback(Component c){doDialog();}
void doDialog() {
MyDialog dlg = new MyDialog(this,"hello");
dlg.visible = true;
if (dlg.result == 0) {
title = "you destroyed the dialog";
}
}
}
extern (C)
int MinWinMain(Application* app) {
MyWindow win = new MyWindow("window");
win.quitOnDestroy = true;
win.visible = true;
return app.enterEventLoop();
}

View file

@ -1,56 +0,0 @@
/* Sample dialog application with procedural style
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.sdialog2;
import minwin.all;
const int OK = 100;
const int CANCEL = 101;
const char[] KEY = "result";
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("window");
win.quitOnDestroy = true;
win.layoutMgr = new FlowLayout;
Button but = new Button(win,"click me");
but.actionDelegate ~= delegate void (Component c) {
Window w = cast(Window)c.parent;
Dialog dlg = new Dialog(w,"hit ok or cancel");
dlg.layoutMgr = new FlowLayout;
Button ok = new Button(dlg,"OK");
ok.cmd = OK;
Button cancel = new Button(dlg,"Cancel");
cancel.cmd = CANCEL;
dlg.commandDelegate ~= delegate void(Component c, int cmd) {
Dialog dlg = cast(Dialog)c;
switch (cmd) {
case OK:
dlg.owner.title = "you hit ok";
break;
case CANCEL:
dlg.owner.title = "you hit cancel";
break;
default: assert(0);
}
// indicate a button was clicked
int* data = new int;
*data = cmd;
dlg.userdata[KEY] = data;
// end the dialog modality
dlg.visible = false;
};
dlg.pack();
dlg.visible = true;
if ((KEY in dlg.userdata) is null) {
w.title = "you destroyed the dialog";
}
};
win.visible = true;
return app.enterEventLoop();
}

View file

@ -1,41 +0,0 @@
/* MinWin Sample: Groups of top-level windows
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.topgroup;
import minwin.all;
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("Close window 2");
win.cancelCloseDelegate ~= delegate bool(Component c) {
// we could pop up a confirm dialog but let's just say
// you can't destroy this window
return true;
};
Window win2 = new Window("Testing 2");
win2.quitOnDestroy = true;
Group g = new Group(null);
g ~= win;
g ~= win2;
static double[2] x = [.5,.5];
static double[1] y = [1];
g.layoutMgr = new TableLayout(x,y);
Rect r;
r.LTWH(100,100,600,300);
g.setBounds(r);
g.layout(false);
g.visible = true;
return app.enterEventLoop();
}

View file

@ -1,80 +0,0 @@
/* Sample MinWin application: widgets
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.samples.widgets;
import minwin.all;
import minwin.logging;
import std.utf;
extern (C)
int MinWinMain(Application* app) {
Window win = new Window("Widgets");
win.quitOnDestroy = true;
win.backgroundColor = systemBackgroundColor();
win.layoutMgr = new FlowLayout;
CheckBox b3 = new CheckBox(win,"check 1");
CheckBox b4 = new CheckBox(win,"check 2");
ToggleButton b5 = new ToggleButton(win,"toggle 1");
ToggleGroup g = new ToggleGroup;
GroupBox box = new GroupBox(win,"Group");
box.layoutMgr = new FlowLayout;
RadioButton b1 = new RadioButton(box,"click me");
RadioButton b2 = new RadioButton(box,"no, click me");
g.addButton(b1);
g.addButton(b2);
g.select(0);
Label lab = new Label(win,"This is a label");
Text t1 = new Text(win,"single line");
t1.userPreferredWidth = 60;
MultiLineText t2 = new MultiLineText(win,"multi line text area");
t2.userPreferredSize(60,60);
char[][] strs;
strs ~= "hello";
strs ~= "world";
strs ~= "bye";
ComboBox combo = new ComboBox(win,strs);
combo.selection = 0;
ListBox list = new ListBox(win,strs);
list.selection = 0;
list.userPreferredHeight = 60;
Canvas p = new Canvas(win);
p.keyDelegate ~= delegate void(Component source, KeyEvent* event) {
if (event.id == KeyPressedEvent) {
char[4] buf;
win.title = "you hit the " ~ toUTF8(buf,event.keyChar) ~ " key";
}
};
p.paintDelegate ~= delegate void(Component source, GContext gc) {
assert(source !is null);
scope Brush b = new Brush(RGB(250,20,20));
Brush oldBrush = gc.setBrush(b);
Rect r = LTWH(0,0,source.width(),source.height());
gc.fillRect(r);
gc.setBrush(oldBrush);
};
p.userPreferredSize(20,20);
ScrollBar sb = new ScrollBar(win,Horizontal);
ScrollPane sp = new ScrollPane(win);
MultiLineText t3 = new MultiLineText(sp,"This is a big text block that needs some scrolling maybe if we are lucky");
t3.userPreferredSize(221,334); // make a large scrollable area
sp.userPreferredSize(100,100);
win.pack();
win.visible = true;
p.requestFocus(); // on GTK must be made visible first
return app.enterEventLoop();
}

View file

@ -1,14 +0,0 @@
# To build the samples type "make -f win32.mak"
DMD = dmd
targets : sample.exe layout.exe topgroup.exe \
widgets.exe menus.exe painting.exe sdialog.exe sdialog2.exe \
idle.exe
.d.exe :
$(DMD) sample.def comdlg32.lib gdi32.lib ..\minwin.lib ..\app.obj -I..\.. -of$@ $< -g -version=LOG
clean:
- del *.obj *.exe

View file

@ -1,319 +0,0 @@
/* MinWin Scroll classes
*
* ScrollBar and ScrollPane
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.scroll;
public import minwin.component;
private {
import minwin.app;
import minwin.window;
import minwin.peerimpl;
import std.string;
import minwin.logging;
}
version (GTK) version = SharedScrollData;
version (SharedScrollData) {
struct ScrollData {
int min;
int max;
int increment;
int value;
}
}
enum ScrollMask {
Range = 1, Increment = 2, Value = 4
}
const int Horizontal = 1;
const int Vertical = 2;
version (MinWin32) {
private import minwin.mswindows;
alias SCROLLINFO ScrollData;
class ScrollBar : WindowChild {
int orientation;
this(Component parent, int orientation, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
uint style = orientation==Horizontal?SBS_HORZ:SBS_VERT;
peer = CreateWindowA("SCROLLBAR","",
style | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,gApp.hInstance,null);
sysAssert(peer !is null, "Failed to create peer scrollbar");
this.name = name;
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
}
Point preferredSize() {
int width,height;
if (orientation == Vertical) {
height = 50;
width = 16;
} else {
height = 16;
width = 50;
}
if (userPreferredWidth > 0)
width = userPreferredWidth;
if (userPreferredHeight > 0)
height = userPreferredHeight;
return XY(width,height);
}
mixin WindowChildImpl!();
private uint windowsMask(uint mask) {
uint res = 0;
if (mask & ScrollMask.Range)
res |= SIF_RANGE;
if (mask & ScrollMask.Value)
res |= SIF_POS;
if (mask & ScrollMask.Increment)
res |= SIF_PAGE;
return res;
}
void setData(inout ScrollData state, uint mask) {
state.cbSize = SCROLLINFO.sizeof;
state.fMask = windowsMask(mask);
SetScrollInfo(peer,SB_CTL,&state, false);
}
void getData(inout ScrollData state, uint mask) {
state.cbSize = SCROLLINFO.sizeof;
state.fMask = windowsMask(mask);
GetScrollInfo(peer,SB_CTL,&state);
}
int value() {
ScrollData state;
getData(state,ScrollMask.Value);
return state.nPos;
}
}
class ScrollPane : WindowChild {
Point origin;
// how to customize page size and steps and limits? need API to each scrollbar
int hstep = 1; // given bounds of child this is how quickly to move through it
int vstep = 1;
this(Component parent, int orientations = Horizontal | Vertical, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
int style;
if (orientations & Horizontal) style |= WS_HSCROLL;
if (orientations & Vertical) style |= WS_VSCROLL;
peer = CreateWindowA("MinWinScrollWindow","",
style | WS_CHILD | WS_VISIBLE,
0,0,50,50,parentp,
cast(HMENU)0,gApp.hInstance,null);
this.name = name;
clearBackgroundOnPaint = false;
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
}
mixin WindowChildImpl!();
void layout(bool validateParent) {
if (parent && validateParent)
parent.layout(true);
if (childLayoutDirty && child) {
Point s = child.preferredSize;
Rect r = LTWH(origin.x,origin.y,s.x,s.y);
child.setBounds(r);
childLayoutDirty = false;
}
foreach( Component ch; this) {
ch.layout(false);
}
}
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
version (LOG) log.printf(" in ScrollPane windowproc msg %d\n",uMsg);
bool doDefault = true;
if (uMsg == WM_HSCROLL) {
SCROLLINFO data;
data.cbSize = SCROLLINFO.sizeof;
data.fMask = SIF_ALL;
GetScrollInfo(hWnd, SB_HORZ, &data);
int cmd = LOWORD(wParam);
int oldPos = data.nPos;
if (cmd == SB_LINELEFT) data.nPos--;
if (cmd == SB_LINERIGHT) data.nPos++;
if (cmd == SB_PAGELEFT) data.nPos -= data.nPage;
if (cmd == SB_PAGERIGHT) data.nPos += data.nPage;
data.fMask = SIF_POS;
SetScrollInfo(hWnd, SB_HORZ, &data, true);
GetScrollInfo(hWnd, SB_HORZ, &data);
if (data.nPos != oldPos) {
int step = hstep*(oldPos-data.nPos);
ScrollWindowEx(hWnd,step,0,null,null,null,null,SW_INVALIDATE | SW_ERASE);
// ScrollWindow(hWnd,step,0,null,null);
if (child) {
WindowChild wc = cast(WindowChild)child;
MoveWindow(wc.getPeer,step,0,0,0,false);
UpdateWindow(wc.getPeer);
}
origin.XY(origin.x + step, origin.y);
}
doDefault = false;
} else if (uMsg == WM_VSCROLL) {
SCROLLINFO data;
data.cbSize = SCROLLINFO.sizeof;
data.fMask = SIF_ALL;
GetScrollInfo(hWnd, SB_VERT, &data);
int cmd = LOWORD(wParam);
int oldPos = data.nPos;
if (cmd == SB_LINEUP) data.nPos--;
if (cmd == SB_LINEDOWN) data.nPos++;
if (cmd == SB_PAGEUP) data.nPos -= data.nPage;
if (cmd == SB_PAGEDOWN) data.nPos += data.nPage;
data.fMask = SIF_POS;
SetScrollInfo(hWnd, SB_VERT, &data, true);
GetScrollInfo(hWnd, SB_VERT, &data);
if (data.nPos != oldPos) {
int step = vstep*(oldPos-data.nPos);
ScrollWindowEx(hWnd,0,step,null,null,null,null,SW_INVALIDATE | SW_ERASE);
// ScrollWindow(hWnd,0,step,null,null);
if (child) {
WindowChild wc = cast(WindowChild)child;
MoveWindow(wc.getPeer,0,step,0,0,false);
UpdateWindow(wc.getPeer);
}
origin.XY(origin.x, origin.y + step);
}
doDefault = false;
}
return doDefault;
}
}
extern(Windows) int MinWinScrollWindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
version(LOG) log.printf("in minwin scroll window proc hwnd %p %d %d %d\n",hWnd,uMsg,wParam,lParam);
bool doDefault = true;
ScrollPane pane = cast(ScrollPane)peerToWindowChild(hWnd);
version(LOG) log.printf("in minwin scroll window proc win %p\n",pane);
if (pane !is null)
doDefault = pane.WindowProc(hWnd,uMsg,wParam,lParam) != 0;
if (doDefault)
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
else
return 0;
}
static this() {
HINSTANCE hInst = GetModuleHandleA(null);
WNDCLASSA wc;
wc.lpszClassName = "MinWinScrollWindow";
wc.style = CS_CLASSDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MinWinScrollWindowProc;
wc.hInstance = hInst;
wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
// wc.hIconSm = DefaultWindowSmallIcon.peer;
wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_ARROW);
wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1); // not +1 for default
wc.lpszMenuName = null;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClassA(&wc);
}
} else version (GTK) {
private import minwin.gtk;
private import minwin.gtk_peers;
class ScrollBar : WindowChild {
this(Component parent, int orientation, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
if (orientation == Horizontal)
peer = gtk_hscrollbar_new(null);
else
peer = gtk_vscrollbar_new(null);
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
}
mixin WindowChildImpl!();
}
class ScrollPane : WindowChild {
MinWinGtkPeer* content;
this(Component parent, int orientations = Horizontal | Vertical, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
peer = gtk_scrolled_window_new(null,null);
gtk_container_add(cast(GtkContainer*)parentp,peer);
GtkWidget* view = gtk_viewport_new(null,null);
gtk_container_add(cast(GtkContainer*)peer,view);
// add our peer to hook into GTK size allocation algorithm
GtkWidget* wcontent = MinWinGtkPeer_new();
content = cast(MinWinGtkPeer*)wcontent;
gtk_widget_set_sensitive(wcontent,true);
content.sizeRequest = &gtkRequest;
content.sizeAllocate = &gtkAllocate;
gtk_container_add(cast(GtkContainer*)view,wcontent);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
// are all of these really needed?
gtk_widget_realize(wcontent);
gtk_widget_show(wcontent);
gtk_widget_realize(view);
gtk_widget_show(view);
gtk_widget_realize(peer);
visible = true;
}
mixin WindowChildImpl!();
void layout(bool validateParent) {
if (parent && validateParent)
parent.layout(true);
childLayoutDirty = false;
}
PeerForAdd getPeerForAdd() {
return cast(GtkWidget*)content;
}
// callback from the GTK peer asking for preferred size
private void gtkRequest(GtkWidget *w, GtkRequisition* req) {
version(LOG)log.writefln("gtkRequest for scrollpane");
Component ch = child;
if (ch is null) return;
Point s = ch.preferredSize;
req.width = s.x;
req.height = s.y;
version(LOG)log.writefln("done gtkRequest for scrollpane");
}
// callback from GTK peer telling us our position
private void gtkAllocate(GtkWidget *w, GtkAllocation* req) {
version(LOG)log.writefln("gtkAllocate for scrollpane");
Component ch = child;
if (ch is null) return;
Rect r = toRect(*req);
ch.size = XY(r.width,r.height);
ch.layout(false);
childLayoutDirty = false;
version(LOG)log.writefln("done gtkAllocate for scrollpane");
}
}
}

View file

@ -1,172 +0,0 @@
/* MinWin Text class
*
* A single or multi-line editable text area
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.text;
public import minwin.component;
private {
import minwin.app;
import minwin.window;
import minwin.peerimpl;
import std.string;
import std.c.string;
import minwin.logging;
}
version (MinWin32) {
private import minwin.mswindows;
template TextPrefSizeImpl() {
Point preferredSize() {
HDC dc = GetDC(peer);
sysAssert(dc !is null, "Failed to get label DC in preferredSize");
SIZE s;
try {
Font f = standardFont(StandardFont.Gui);
HFONT oldfont = SelectObject(dc,f.peer);
sysAssert(oldfont !is null, "Failed to get Text font in preferredSize");
BOOL ok;
int len;
if (useWfuncs) {
wchar[128] buf;
len = SendMessageW(peer,WM_GETTEXT,cast(WPARAM)128,cast(LPARAM)buf.ptr);
ok = GetTextExtentPoint32W(dc,buf.ptr,len,&s);
}
else {
char[128] buf;
len = SendMessageA(peer,WM_GETTEXT,cast(WPARAM)128,cast(LPARAM)buf.ptr);
ok = GetTextExtentPoint32A(dc,buf.ptr,len,&s);
}
SelectObject(dc,oldfont);
sysAssert(ok != false, "Failed to get text extents in preferredSize");
} finally {
ReleaseDC(peer,dc);
}
int width = s.cx;
int height = s.cy;
if (userPreferredWidth() > 0)
width = userPreferredWidth();
if (userPreferredHeight() > 0)
height = userPreferredHeight();
return XY(width,height);
}
}
class Text : WindowChild {
this(Component parent, char[] text = "", char[] name = "") {
HINSTANCE hInst = GetModuleHandleA(null);
PeerForAdd parentp = parent.getPeerForAdd();
peer = CreateWindowX("EDIT",text,
ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE,
0,0,20,20,parentp,
cast(HMENU)0,hInst,null);
sysAssert(peer !is null, "Failed to create peer Text");
this.name = name;
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
version(LOG) log.writefln("done making text edit");
}
mixin TextPrefSizeImpl!();
mixin WindowChildImpl!();
}
class MultiLineText : WindowChild {
this(Component parent, char[] text = "", char[] name = "") {
HINSTANCE hInst = GetModuleHandleA(null);
PeerForAdd parentp = parent.getPeerForAdd();
peer = CreateWindowX("EDIT",text,
ES_MULTILINE | WS_CHILD | WS_VISIBLE,
0,0,10,10,parentp,
cast(HMENU)0,hInst,null);
sysAssert(peer !is null, "Failed to create peer MultiLineText");
this.name = name;
Font f = standardFont(StandardFont.Gui);
SendMessageA(peer,WM_SETFONT,cast(WPARAM)f.peer,0);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
}
mixin TextPrefSizeImpl!();
mixin WindowChildImpl!();
}
} else version (GTK) {
private import minwin.gtk;
class Text : WindowChild {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_entry_new();
gtk_entry_set_text(cast(GtkEntry*)peer,str);
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
}
mixin WindowChildImpl!();
char[] text() {
char* str;
str = gtk_entry_get_text(cast(GtkEntry*)peer);
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] c) {
char* str = toStringz(c);
gtk_entry_set_text(cast(GtkEntry*)peer,str);
}
}
class MultiLineText : WindowChild {
this(Component parent, char[] text, char[] name = "") {
PeerForAdd parentp = parent.getPeerForAdd();
this.name = name;
char* str = toStringz(text);
peer = gtk_text_view_new();
GtkTextView* view = cast(GtkTextView*)peer;
GtkTextBuffer* buf = gtk_text_view_get_buffer(view);
gtk_text_buffer_set_text(buf,text.ptr,text.length);
gtk_text_view_set_wrap_mode(view,GtkWrapMode.GTK_WRAP_WORD);
gtk_container_add(cast(GtkContainer*)parentp,peer);
setWindowChildPeer(this,peer,OWNS_PEER);
parent.addChild(this);
gtk_widget_realize(peer);
visible = true;
}
mixin WindowChildImpl!();
char[] text() {
char* str;
GtkTextBuffer* buffer =gtk_text_view_get_buffer(cast(GtkTextView*)peer);
// str = gtk_text_buffer_get_text(buffer,0);
assert(false); // TODO
if (str is null)
return "";
else
return str[0..strlen(str)].dup;
}
void text(char[] c) {
GtkTextView* view = cast(GtkTextView*)peer;
GtkTextBuffer* buf = gtk_text_view_get_buffer(view);
gtk_text_buffer_set_text(buf,c.ptr,c.length);
}
}
}

View file

@ -1,56 +0,0 @@
* clean up build response files: brf. It seems like comments are not
allowed so I'll put the comments here. On linux the build will fail since
it uses Windows commands for creating a library. If the build fails with
"lib not found" or something run
ar -r libminwin_gtk.a *.o
Get build from www.dsource.org and run with
build @gtk.brf or @win32.brf
* x11
- font/fontset/encoding
- window resizing/repaint DONE
* mswindows
- A vs W for string inputs - convert to wchar (DONE except for save/openFileDialog)
* events: key, mouse DONE (well, some mouse)
* event: window, focus, window-destroy etc etc
* canvas DONE
* framed panel DONE
* layout mgr DONE
* label DONE
* cursor control
* List widget
* group-component DONE
* images/offscreen rendering DONE
* GXContext extensions for gdi+ and fancy drawing
* color mgnt needed? just assume true-color on X DONE-true-color
* double-buffering
* abstract button DONE
* toggle/radio button DONE
* text widgets DONE
* selection/clipboard
* modal/nonmodal dialog DONE
* util dialog boxes DONE(file)
* screen access
* cmd line parsing
* printing (where supported)
* scroll pane/scroll bars DONE
* sash
* menus DONE(basic)
* context menus/popup menus
* layout min/max size and
* layout hide on overflow DONE
requests:
window title getter DONE
custom window background color (not just white) DONE
get pen and font data from peers
test image, brush on gtk DONE
fillPolygon on Windows
bugs:
dropdown on windows doesn't work
GroupBox doesn't let radio buttons switch
list on gtk is squished
border layout completely untested

View file

@ -1,17 +0,0 @@
/* MinWin unittest
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
import minwin.all;
extern (C)
int MinWinMain(Application* app) {
Point p = XY(100,100);
Group g = new Group(null);
app.rsrc("100");
return 0;
}

View file

@ -1,9 +0,0 @@
all.d
logging.d
-version=MinWin32
-allobj
-Tminwin.lib
-I..
-lib
-g
-w

View file

@ -1,87 +0,0 @@
# To build minwin.lib type "make -f win32.mak"
# The minwin.lib and object files will be created in the source directory.
# flags to use building unittest.exe
DUNITFLAGS=-g -unittest -I..
# flags to use when building the minwi.lib library
#DLIBFLAGS=-O -release -I..
DLIBFLAGS=-g -I..
DMD = dmd
LIB = lib
targets : minwin
#unittest : unittest.exe
LIBNAME = minwin.lib
minwin : $(LIBNAME)
SRC = app.d \
window.d \
peerimpl.d \
paint.d \
font.d \
logging.d \
geometry.d \
mswindows.d \
multidg.d \
component.d \
button.d \
menu.d \
event.d \
icon.d \
dialog.d \
group.d \
image.d \
peer.d \
label.d \
text.d \
combo.d \
listbox.d \
canvas.d \
scroll.d \
layout.d
OBJS = app.obj \
window.obj \
peerimpl.obj \
paint.obj \
font.obj \
logging.obj \
geometry.obj \
mswindows.obj \
multidg.obj \
component.obj \
button.obj \
menu.obj \
event.obj \
icon.obj \
dialog.obj \
group.obj \
image.obj \
peer.obj \
label.obj \
text.obj \
combo.obj \
listbox.obj \
canvas.obj \
scroll.obj \
layout.obj
.d.obj :
$(DMD) -c $(DLIBFLAGS) -of$@ $<
$(LIBNAME) : $(OBJS) $(SRC)
$(LIB) -c $@ $(OBJS)
#unittest.exe : $(LIBNAME) $(SRC)
# $(DMD) $(DUNITFLAGS) unittest.d -ofunittest.exe $(SRC)
clean:
- del *.obj
- del $(LIBNAME)
- del unittest.exe

View file

@ -1,826 +0,0 @@
/* MinWin Window class
*
* An AbstractWindow is a top-level window. Concrete subclasses
* are Window and Dialog.
*
* Written by Ben Hinkle and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
*/
module minwin.window;
private {
import std.string;
import std.c.string;
import minwin.peerimpl;
import minwin.font;
import minwin.event;
import minwin.component;
import minwin.menu;
import minwin.app;
import minwin.paint;
import minwin.logging;
import minwin.icon;
import minwin.image;
}
int DefaultWindowWidth = 400;
int DefaultWindowHeight = 300;
Icon DefaultWindowIcon;
Icon DefaultWindowSmallIcon;
version (MinWin32) {
public import std.utf : toUTF16z, toUTF16, toUTF8;
}
template CommonEventSourceImpl() {
version (MinWin32) {
HBRUSH backgroundPeer;
void repaintNow() {
UpdateWindow(peer);
}
GContext getGContext() {
GContext gc = newGContext();
gc.peer = GetDC(peer);
sysAssert(gc.peer !is null, "Failed to get DC in getGContext");
gc.hasPeer = OWNS_PEER;
gc.release = true;
gc.hwnd = peer;
return gc;
}
Image getCompatibleImage(int width, int height) {
HDC dc = GetDC(peer);
sysAssert(dc !is null, "Failed to get DC in getCompatibleImage");
ImagePeer bm = CreateCompatibleBitmap(dc,width,height);
sysAssert(bm !is null, "Failed to create compatible bitmap");
version(LOG) log.writefln("create bitmap %x",cast(int)bm);
Image res = new Image(bm);
res.width = width;
res.height = height;
res.hasPeer = OWNS_PEER;
ReleaseDC(peer,dc);
return res;
}
Image loadCompatibleImage(char[] imageKey, char[] fmt = "bmp") {
// TODO: use fmt
ImagePeer bm;
if (useWfuncs)
bm = LoadImageW(gApp.hInstance,toUTF16z(imageKey),IMAGE_BITMAP,0,0,0);
else
bm = LoadImageA(gApp.hInstance,toMBSz(imageKey),IMAGE_BITMAP,0,0,0);
sysAssert(bm !is null, format("Failed to load image %s",imageKey));
BITMAP bm_data;
int ok = GetObjectA(bm,bm_data.sizeof,&bm_data);
sysAssert(ok != false, "Failed to get bitmap data in loadCompatibleImage");
version(LOG) log.writefln("create bitmap %x",cast(int)bm);
Image res = new Image(bm);
res.width = bm_data.bmWidth;
res.height = bm_data.bmHeight;
res.hasPeer = OWNS_PEER;
return res;
}
} else version (GTK) {
void repaintNow(Event* paintEvent = null) {
layout(true);
if (!paintDelegate.isEmpty) {
GContext gc = getGContext(paintEvent);
paintDelegate(this,gc);
gc.dispose();
}
}
}
}
template CommonWindowImpl() {
static AbstractWindow[AbstractWindow] WindowList;
bool quitOnDestroy;
void doCommand(int cmd) {
commandDelegate(this,cmd);
}
MultiDelegate!(Component, GContext) paintDelegate;
MultiDelegate!(Component, GXContext) paintXDelegate;
MultiDelegate!(Component, int) commandDelegate;
MultiBoolDelegate!(Component) cancelCloseDelegate; // don't quit if bool is true
// events
MultiDelegate!(Component, KeyEvent*) keyDelegate;
MultiDelegate!(Component, MouseEvent*) mouseDelegate;
MultiDelegate!(Component, WindowEvent*) windowDelegate;
Point preferredSize() {
Point s;
if (layoutMgr) {
s = layoutMgr.preferredSize(this);
} else {
s.x = DefaultWindowWidth;
s.y = DefaultWindowHeight;
}
if (userPreferredWidth > 0)
s.x = userPreferredWidth;
if (userPreferredHeight > 0)
s.y = userPreferredHeight;
return s;
}
}
version (MinWin32) {
private import minwin.mswindows;
alias HWND WindowPeer;
const int MinWinWindowStyle = WS_OVERLAPPEDWINDOW;
// Get the Window object associated with the given peer.
// The peer is accessed from the Window using the peer property.
AbstractWindow peerToWindow(WindowPeer peer) {
return cast(AbstractWindow)cast(void*)GetWindowLongA(peer,GWL_USERDATA);
}
// Associate c with the peer. This overwrites the window UserData.
void setWindowPeer(AbstractWindow c, WindowPeer peer, int peerState) {
SetWindowLongA(peer,GWL_USERDATA,cast(int)cast(void*)c);
c.hasPeer = peerState;
}
class AbstractWindow : Component {
WindowPeer peer;
MenuBar menubar;
mixin CommonWindowImpl!();
void title(char[] str) {
BOOL ok;
if (useWfuncs)
ok = SetWindowTextW(peer,toUTF16z(str));
else
ok = SetWindowTextA(peer,toMBSz(str));
sysAssert(ok != false, "Failed to set window title");
}
char[] title() {
if (useWfuncs) {
wchar[64] res;
int len = GetWindowTextW(peer,res.ptr,res.length);
return toUTF8(res[0..len]);
}
else {
char[64] res;
int len = GetWindowTextA(peer,res.ptr,res.length);
return fromMBSz(res[0..len].ptr);
}
}
PeerForAdd getPeerForAdd() { return peer; }
void disposePeer() {
if (hasPeer == OWNS_PEER) {
BOOL ok = DestroyWindow(peer);
sysAssert(ok != false, "Failed to destroy window");
}
hasPeer = NO_PEER;
//delete WindowList[this]; // remove global reference
WindowList.remove(this); // remove global reference
}
void close() {
SendMessageA(peer,WM_CLOSE,0,0);
}
void visible(bool vis) {
ShowWindow(peer,vis ? SW_SHOW : SW_HIDE); // ignore bool result
}
bool visible() {
return IsWindowVisible(peer) != 0;
}
void enabled(bool ena) {
EnableWindow(peer, ena);
}
bool enabled() {
return IsWindowEnabled(peer) == TRUE;
}
void backgroundColor(Color c) {
version(LOG) log.writefln("making background %d %d %d",
cast(int)c.red,
cast(int)c.green,
cast(int)c.blue);
if (backgroundPeer)
DeleteObject(backgroundPeer);
backgroundPeer = CreateSolidBrush(c.native);
// use GetSysColorBrush?
}
// returns client bounds in screen coordinates
void getBounds(inout Rect r) {
BOOL ok = GetClientRect(peer,&r.native);
sysAssert(ok != false, "Failed to get client rect");
Point pt = XY(r.left,r.top);
ClientToScreen(peer,&pt.native);
int x,y;
if (parent) parent.getPeerOffset(x,y);
r.LTWH(pt.x+x,pt.y+y,r.width,r.height);
}
// should be the same as AdjustWindowRect but it seems like
// that doesn't account for the title bar.
protected final void adjustBounds(inout Rect r) {
BOOL ok = AdjustWindowRect(&r.native,MinWinWindowStyle,menubar !is null);
sysAssert(ok != false, "Failed to adjust window bounds");
}
void setBounds(inout Rect r) {
Rect r2 = r;
adjustBounds(r2);
int x,y;
if (parent) parent.getPeerOffset(x,y);
BOOL ok = MoveWindow(peer,r2.left+x,r2.top+y,r2.width,r2.height,true);
sysAssert(ok != false, "Failed to move window in setBounds");
childLayoutDirty = true;
}
alias Component.size size;
void size(Point s) {
Rect r;
getBounds(r);
r.width = s.x;
r.height = s.y;
adjustBounds(r);
BOOL ok = MoveWindow(peer,r.left,r.top,r.width,r.height,true);
sysAssert(ok != false, "Failed to move window in size");
childLayoutDirty = true;
}
void toFront() {
BOOL ok = BringWindowToTop(peer);
sysAssert(ok != false, "Failed to bring window to front");
}
// mark as needing a repaint and post event to event queue
void repaint() {
InvalidateRect(peer,null,clearBackgroundOnPaint);
super.repaint();
}
void repaint(inout Rect r) {
InvalidateRect(peer,&r.native,clearBackgroundOnPaint);
}
mixin CommonEventSourceImpl!();
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
//version (LOG) log.printf(" in windowproc msg %x LowW %x HiW %x L %x\n",
//uMsg,cast(int)LOWORD(wParam),cast(int)HIWORD(wParam),lParam);
bool doDefault = true;
if (uMsg <= WM_KEYLAST && uMsg >= WM_KEYFIRST) {
// version(LOG) log.writefln("got key event %d %d",uMsg,wParam);
keyDelegate(this, cast(KeyEvent*)&gApp.event);
} else if (uMsg <= WM_MOUSELAST && uMsg >= WM_MOUSEFIRST) {
mouseDelegate(this, cast(MouseEvent*)&gApp.event);
} else {
switch (uMsg) {
case WM_COMMAND:
// version (LOG) log.printf(" got command %x %x from %x\n",
// HIWORD(wParam),LOWORD(wParam),lParam);
Component c = peerToWindowChild(cast(HWND)lParam);
// version (LOG) log.printf(" got pointer %p\n",c);
if (c !is null) {
c.doCommand(wParam);
} else {
doCommand(LOWORD(wParam));
}
break;
case WM_PAINT:
// version (LOG) log.writefln(" got paint");
layout(true);
GContext gc = newGContext();
gc.peer = BeginPaint(peer, &gc.paintstruct);
sysAssert(gc.peer !is null, "Failed to get DC in repaintNow");
// version(LOG)log.writefln("Paint rect: %s",toRect(gc.paintstruct.rcPaint).toString);
gc.hasPeer = FOREIGN_PEER; // don't call DisposeDC
if (clearBackgroundOnPaint && backgroundPeer) {
Point s = super.size;
Rect r = LTWH(0,0,s.x,s.y);
// version(LOG)log.writefln("painting background %d %d",width,height);
FillRect(gc.peer,&r.native,backgroundPeer);
}
if (!paintDelegate.isEmpty) {
paintDelegate(this,gc);
}
EndPaint(peer, &gc.paintstruct);
gc.dispose();
break;
/*
case CBN_DROPDOWN:
// TODO: doesn't work!
Rect r;
HWND ctrl = cast(HWND)lParam;
BOOL ok = GetWindowRect(ctrl,&r.native);
// sysAssert(ok != false, "Failed to get drop down bounds");
// BOOL ok = SendMessageA(ctrl,CB_GETDROPPEDCONTROLRECT,0,cast(LPARAM)&r);
// sysAssert(ok != false, "Failed to get drop down bounds");
int height1 = SendMessageA(ctrl,CB_GETITEMHEIGHT,cast(WPARAM)-1,0);
int n = SendMessageA(ctrl,CB_GETITEMHEIGHT,cast(WPARAM)0,0);
version(LOG)log.writefln("got drop down command %d %d",height1,n);
// MoveWindow(peer,rectL(r),rectR(r),rectW(r),height1+n,false);
// MoveWindow(ctrl,rectL(r),rectR(r),rectW(r),rectH(r),false);
break;
*/
case WM_SIZE:
case WM_SIZING:
// version (LOG) log.writefln(" got size");
childLayoutDirty = true;
if (!windowDelegate.isEmpty) {
WindowEvent event;
event.native.hwnd = hWnd;
event.native.wParam = wParam;
event.native.lParam = lParam;
event.native.message = uMsg;
windowDelegate(this, &event);
}
break;
case WM_MOVE:
case WM_MOVING:
// version (LOG) log.writefln(" got move");
if (!windowDelegate.isEmpty) {
WindowEvent event;
event.native.hwnd = hWnd;
event.native.wParam = wParam;
event.native.lParam = lParam;
event.native.message = uMsg;
windowDelegate(this, &event);
}
break;
case WM_CLOSE:
version (LOG) log.writefln(" got close");
doDefault = !cancelCloseDelegate(this);
break;
case WM_DESTROY:
version (LOG) log.writefln(" got destroy");
hasPeer = NO_PEER;
if (quitOnDestroy)
gApp.exitEventLoop();
break;
default:
// version (LOG) log.writefln(" got default");
break;
}
}
return doDefault;
}
}
class Window : AbstractWindow {
this(char[] title = "", char[] name = "") {
peer = CreateWindowX("MinWinWindow", title,
MinWinWindowStyle,
CW_USEDEFAULT, CW_USEDEFAULT,
DefaultWindowWidth, DefaultWindowHeight,
HWND_DESKTOP,
cast(HMENU) null, gApp.hInstance, null);
sysAssert(peer !is null, "Failed to create peer Window");
this.name = name;
setWindowPeer(this,peer,OWNS_PEER);
backgroundPeer = GetStockObject(WHITE_BRUSH);
WindowList[this] = this; // prevent garbage collection
}
this(WindowPeer peer) {
setWindowPeer(this,peer,FOREIGN_PEER);
WindowList[this] = this; // prevent garbage collection
}
}
extern(Windows)
int MinWinWindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
// version(LOG) log.printf("in minwin window proc hwnd %p\n",hWnd);
bool doDefault = true;
AbstractWindow win = cast(AbstractWindow)peerToWindow(hWnd);
// version(LOG) log.printf("in minwin window proc win %p\n",win);
if (win !is null)
doDefault = win.WindowProc(hWnd,uMsg,wParam,lParam) != 0;
if (doDefault)
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
else
return 0;
}
static this() {
if (DefaultWindowIcon is null) {
IconPeer ip = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
DefaultWindowIcon = DefaultWindowSmallIcon = new Icon(ip);
}
HINSTANCE hInst = GetModuleHandleA(null);
WNDCLASSA wc;
wc.lpszClassName = "MinWinWindow";
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &MinWinWindowProc;
wc.hInstance = hInst;
wc.hIcon = DefaultWindowIcon.peer;
// wc.hIconSm = DefaultWindowSmallIcon.peer;
wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_ARROW);
wc.hbrBackground = null;
// wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1); // not +1 for default
wc.lpszMenuName = null;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClassA(&wc);
}
} else version (GTK) {
private import minwin.gtk;
private import minwin.gtk_peers;
alias GtkWindow* WindowPeer;
class AbstractWindow : Component {
WindowPeer peer;
MinWinGtkPeer* content;
MenuBar menubar;
mixin CommonWindowImpl!();
void title(char[] str) {
gtk_window_set_title(peer,toStringz(str));
}
char[] title() {
char* cstr = gtk_window_get_title(peer);
if (cstr is null)
return "";
return cstr[0..strlen(cstr)].dup;
}
// TODO
void backgroundColor(Color c) {
GtkWidget* wid = cast(GtkWidget*)peer;
GdkColor* nc = toNativeColor(c);
GtkStyle* style = gtk_widget_get_style(wid);
style.bg[GtkStateType.GTK_STATE_NORMAL] = *nc;
gtk_widget_set_style(wid,style);
}
// callback from the GTK peer asking for preferred size
private void gtkRequest(GtkWidget *w, GtkRequisition* req) {
version(LOG)log.writefln("gtkRequest for toplevel window");
if (layoutMgr) {
Point s = layoutMgr.preferredSize(this);
req.width = s.x;
req.height = s.y;
} else {
req.width = 0;
req.height = 0;
}
version(LOG)log.writefln("done gtkRequest for toplevel window");
}
// callback from GTK peer telling us our position
private void gtkAllocate(GtkWidget *w, GtkAllocation* req) {
version(LOG)log.writefln("gtkAllocate for toplevel window");
Rect r = toRect(*req);
this.size = XY(r.width,r.height);
if (layoutMgr) {
layoutMgr.layout(this);
}
childLayoutDirty = false;
version(LOG)log.writefln("done gtkAllocate for toplevel window");
}
PeerForAdd getPeerForAdd() { return cast(GtkWidget*)content; }
void disposePeer() {
if (hasPeer == OWNS_PEER) {
gtk_widget_destroy(cast(GtkWidget*)peer);
}
hasPeer = NO_PEER;
//delete WindowList[this]; // remove global reference
WindowList.remove(this); // remove global reference
}
void close() {
if (!cancelCloseDelegate(this)) {
gtk_widget_destroy(cast(GtkWidget*)peer);
}
}
void resizable(bool vis) {
gtk_window_set_resizable(peer,vis);
}
bool resizable() {
return gtk_window_get_resizable(peer) != 0;
}
void visible(bool vis) {
if (vis) {
gtk_widget_show(cast(GtkWidget*)peer);
} else {
gtk_widget_hide(cast(GtkWidget*)peer);
}
}
bool visible() {
GtkObject* obj = cast(GtkObject*)peer;
return ((obj.flags & GtkWidgetFlags.GTK_VISIBLE) != 0);
}
void enabled(bool b) {
gtk_widget_set_sensitive(cast(GtkWidget*)peer,cast(int)b);
}
bool enabled() {
GtkObject* obj = cast(GtkObject*)peer;
return ((obj.flags & GtkWidgetFlags.GTK_SENSITIVE) != 0);
}
void getPeerOffset(inout int x, inout int y) {
x = 0;
y = 0;
if (menubar !is null) {
GtkRequisition req;
gtk_widget_size_request(menubar.peer,&req);
y = req.height;
}
}
override void layout(bool validateParent) {
if (parent && validateParent)
parent.layout(true);
if (menubar !is null) {
positionMenuBar();
}
if (childLayoutDirty) {
if (layoutMgr)
layoutMgr.layout(this);
childLayoutDirty = false;
}
foreach( Component ch; this) {
ch.layout(false);
}
}
void positionMenuBar() {
Rect r;
getBounds(r);
MenuBarPeer w = menubar.peer;
GtkRequisition req;
gtk_widget_size_request(menubar.peer,&req);
r.height = req.height;
gtk_widget_size_allocate(w,&r.native);
}
void getBounds(inout Rect r) {
int x,y;
r = toRect((cast(GtkWidget*)peer).allocation);
if (parent) parent.getPeerOffset(x,y);
r.left = r.left+x;
r.top = r.top+y;
}
void setBounds(inout Rect r) {
int x,y;
if (parent) parent.getPeerOffset(x,y);
gtk_window_move(peer,r.left+x,r.top+y);
childLayoutDirty = true;
gtk_window_resize(peer,r.width,r.height);
}
alias Component.size size;
void size(Point s) {
gtk_window_resize(peer,s.x,s.y);
}
void toFront() {
gdk_window_raise((cast(GtkWidget*)peer).window);
}
// mark as needing a repaint and post event to event queue
void repaint() {
Rect r;
GdkWindow* win = (cast(GtkWidget*)peer).window;
getBounds(r);
gdk_window_invalidate_rect(win,&r.native,1);
}
void repaint(inout Rect r) {
GdkWindow* win = (cast(GtkWidget*)peer).window;
gdk_window_invalidate_rect(win,&r.native,1);
}
mixin CommonEventSourceImpl!();
GContext getGContext(Event* paintEvent = null) {
GContext gc = newGContext();
GtkWidget* widget = cast(GtkWidget*)content;
GdkWindow* gwin = widget.window;
gc.drawable = cast(GdkDrawable*)gwin;
gc.layout = gtk_widget_create_pango_layout(widget,"");
gc.peer = gdk_gc_new(gc.drawable);
gc.hasPeer = OWNS_PEER;
gc.paintEvent = cast(GdkEventExpose*)paintEvent;
return gc;
}
Image getCompatibleImage(int width, int height) {
GtkWidget* widget = cast(GtkWidget*)content;
GdkDrawable* gwin = cast(GdkDrawable*)widget.window;
int depth = gdk_drawable_get_depth(gwin);
ImagePeer bm = gdk_pixmap_new(gwin,width,height,depth);
version(LOG) log.writefln("create bitmap %x",cast(int)bm);
Image res = new Image(bm);
res.width = width;
res.height = height;
res.hasPeer = OWNS_PEER;
return res;
}
Image loadCompatibleImage(char[] imageKey, char[] fmt = "bmp") {
GtkWidget* widget = cast(GtkWidget*)content;
GdkDrawable* gwin = cast(GdkDrawable*)widget.window;
GError* err;
char[] fname = imageKey;
if (gApp.resourcePath.length > 0) {
fname = gApp.resourcePath ~ "/" ~ fname;
}
fname = fname ~ "." ~ fmt;
GdkPixbuf* pbuf = gdk_pixbuf_new_from_file(toStringz(fname),&err);
int width = gdk_pixbuf_get_width(pbuf);
int height = gdk_pixbuf_get_height(pbuf);
int depth = gdk_drawable_get_depth(gwin);
GdkColormap* cmap = gdk_drawable_get_colormap(gwin);
ImagePeer bm = gdk_pixmap_new(gwin,width,height,depth);
gdk_pixbuf_render_pixmap_and_mask_for_colormap(pbuf,cmap,&bm,null,0);
Image res = new Image(bm);
res.width = width;
res.height = height;
res.hasPeer = OWNS_PEER;
return res;
}
}
class Window : AbstractWindow {
this(char[] title = "", char[] name = "") {
char* str = toStringz(title);
// TODO: application name vs window name??
peer = cast(GtkWindow*)gtk_window_new(GtkWindowType.GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(peer,str);
gtk_window_set_default_size(peer,DefaultWindowWidth,DefaultWindowHeight);
backgroundColor = RGB(255,255,255);
this.name = name;
gtk_widget_add_events(cast(GtkWidget*)peer,GdkEventMask.GDK_KEY_PRESS_MASK |
GdkEventMask.GDK_KEY_RELEASE_MASK |
GdkEventMask.GDK_EXPOSURE_MASK |
GdkEventMask.GDK_STRUCTURE_MASK |
GdkEventMask.GDK_POINTER_MOTION_MASK |
GdkEventMask.GDK_BUTTON_PRESS_MASK |
GdkEventMask.GDK_BUTTON_RELEASE_MASK);
g_signal_connect_data(peer,"destroy",
cast(GCallback)&mw_destroy_callback,
cast(gpointer)this,
null,cast(GConnectFlags)0);
g_signal_connect_data(peer,"delete-event",
cast(GCallback)&mw_close_callback,
cast(gpointer)this,
null,cast(GConnectFlags)0);
g_signal_connect_data(peer,"configure-event",
cast(GCallback)&mw_notify_callback,
cast(gpointer)this,
null,cast(GConnectFlags)0);
setWindowPeer(this,peer,OWNS_PEER);
WindowList[this] = this; // prevent garbage collection
GtkWidget* wcontent = MinWinGtkPeer_new();
content = cast(MinWinGtkPeer*)wcontent;
gtk_widget_set_sensitive(wcontent,true);
content.sizeRequest = &gtkRequest;
content.sizeAllocate = &gtkAllocate;
gtk_container_add(cast(GtkContainer*)peer,wcontent);
g_signal_connect_data(peer,"expose-event",
cast(GCallback)&mw_expose_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"key-press-event",
cast(GCallback)&mw_key_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"key-release-event",
cast(GCallback)&mw_key_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"motion-notify-event",
cast(GCallback)&mw_win_mouse_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"button-press-event",
cast(GCallback)&mw_win_button_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
g_signal_connect_data(peer,"button-release-event",
cast(GCallback)&mw_win_button_callback,
cast(gpointer)this,
null,GConnectFlags.G_CONNECT_AFTER);
gtk_widget_realize(wcontent);
gtk_widget_show(wcontent);
}
this(WindowPeer peer) {
setWindowPeer(this,peer,FOREIGN_PEER);
WindowList[this] = this; // prevent garbage collection
}
}
// Get the Window object associated with the given peer.
// The peer is accessed from the Window using the peer property.
AbstractWindow peerToWindow(WindowPeer peer) {
gpointer ptr = g_object_get_data(cast(GObject*)peer,"MinWinUserData");
return cast(AbstractWindow)ptr;
}
// Associate c with the peer. This overwrites the window UserData.
void setWindowPeer(AbstractWindow c, WindowPeer peer, int peerState) {
g_object_set_data(cast(GObject*)peer,"MinWinUserData",cast(gpointer)peer);
c.hasPeer = peerState;
}
extern (C) gboolean mw_expose_callback(GtkWidget* w,
GdkEventExpose* event,
gpointer ud) {
Window win = cast(Window) ud;
if (win) {
win.repaintNow(cast(Event*)event);
}
return false;
}
extern (C) gboolean mw_key_callback(GtkWidget* w,
GdkEventKey* event,
gpointer ud) {
Window win = cast(Window) ud;
if (win && !win.keyDelegate.isEmpty) {
win.keyDelegate(win,cast(KeyEvent*)event);
}
return false;
}
extern (C) gboolean mw_win_mouse_callback(GtkWidget* w,
GdkEventMotion* event,
gpointer ud) {
version(LOG)log.writefln("got mouse motion event");
Window win = cast(Window) ud;
if (win && !win.mouseDelegate.isEmpty) {
// TODO this should be made into a GdkEventButton
win.mouseDelegate(win,cast(MouseEvent*)event);
}
return false;
}
extern (C) gboolean mw_win_button_callback(GtkWidget* w,
GdkEventButton* event,
gpointer ud) {
Window win = cast(Window) ud;
if (win && !win.mouseDelegate.isEmpty) {
win.mouseDelegate(win,cast(MouseEvent*)event);
}
return false;
}
extern (C) void mw_destroy_callback(GtkObject* w, gpointer ud) {
Window win = cast(Window) ud;
if (win) {
version(LOG)log.printf("mw_destroy_callback\n");
win.hasPeer = NO_PEER;
if (win.quitOnDestroy)
gApp.exitEventLoop();
if (win in Window.WindowList) {
//delete Window.WindowList[win];
Window.WindowList.remove(win);
}
}
}
extern (C) void mw_close_callback(GtkWidget* w, GdkEvent* ev, gpointer ud) {
Window win = cast(Window) ud;
version(LOG)log.printf("mw_close_callback\n");
if (win)
win.close();
}
extern (C) void mw_notify_callback(GtkWidget* w, GdkEvent* ev, gpointer ud) {
Window win = cast(Window) ud;
if (win && ev.type == GdkEventType.GDK_CONFIGURE) {
if (!win.windowDelegate.isEmpty) {
win.windowDelegate(win, cast(WindowEvent*)ev);
}
}
}
}

View file

@ -1,127 +0,0 @@
diff -Naur ../minwin_org/CMakeLists.txt minwin_gtk/CMakeLists.txt
--- ../minwin_org/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000
+++ minwin_gtk/CMakeLists.txt 2007-03-10 08:54:43.000000000 +0000
@@ -0,0 +1,31 @@
+SET(CMAKE_FIND_LIBRARY_PREFIXES "")
+SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
+
+PROJECT (minwin_gtk D)
+
+FIND_PACKAGE (GTK2)
+
+IF (GTK2_FOUND)
+
+ INCLUDE_DIRECTORIES ( ${GTK2_INCLUDE_DIRS} )
+
+
+ SET (SRCS
+ minwin/all.d minwin/font.d minwin/layout.d minwin/peerimpl.d
+ minwin/app.d minwin/geometry.d minwin/listbox.d minwin/scroll.d
+ minwin/button.d minwin/group.d minwin/logging.d minwin/text.d
+ minwin/canvas.d minwin/gtk.d minwin/menu.d minwin/unittest.d
+ minwin/combo.d minwin/gtk_peers.d minwin/window.d
+ minwin/component.d minwin/icon.d minwin/multidg.d
+ minwin/dialog.d minwin/image.d minwin/paint.d
+ minwin/event.d minwin/label.d minwin/peer.d )
+
+ ADD_DEFINITIONS (-fversion=GTK ${GTK2_DEFINITIONS})
+
+ ADD_LIBRARY (minwin_gtk ${SRCS})
+
+ TARGET_LINK_LIBRARIES (minwin_gtk ${GTK2_LIBRARIES})
+
+ ADD_SUBDIRECTORY (minwin/samples)
+
+ENDIF (GTK2_FOUND)
diff -Naur ../minwin_org/minwin/dialog.d minwin_gtk/minwin/dialog.d
--- ../minwin_org/minwin/dialog.d 2007-03-15 14:30:47.000000000 +0000
+++ minwin_gtk/minwin/dialog.d 2007-03-09 20:32:38.000000000 +0000
@@ -383,20 +383,21 @@
private import minwin.gtk;
private import minwin.window;
- void informationDialog(AbstractWindow owner, char[] text, char[] title) {
+ void informationDialog(AbstractWindow owner, char* text, char[]
+title) {
msgDialog(owner,text,title,GtkMessageType.GTK_MESSAGE_INFO,
GtkButtonsType.GTK_BUTTONS_OK);
}
- void warningDialog(AbstractWindow owner, char[] text, char[] title) {
+ void warningDialog(AbstractWindow owner, char* text, char[] title) {
msgDialog(owner,text,title,GtkMessageType.GTK_MESSAGE_WARNING,
GtkButtonsType.GTK_BUTTONS_OK);
}
- void errorDialog(AbstractWindow owner, char[] text, char[] title) {
+ void errorDialog(AbstractWindow owner, char* text, char[] title) {
msgDialog(owner,text,title,GtkMessageType.GTK_MESSAGE_ERROR,
GtkButtonsType.GTK_BUTTONS_OK);
}
alias informationDialog messageDialog;
- void msgDialog(AbstractWindow owner, char[] text, char[] title,
+ void msgDialog(AbstractWindow owner, char* text, char[] title,
GtkMessageType type, GtkButtonsType buttons) {
// TODO: title?
GtkWidget* d = gtk_message_dialog_new(owner.peer,
@@ -440,7 +441,7 @@
GtkFileFilter* f = gtk_file_filter_new();
gtk_file_filter_set_name(f,toStringz(filt.description));
foreach( char[] ext; filt.extensions) {
- gtk_file_filter_add_pattern(f,"*."~ext);
+ gtk_file_filter_add_pattern(f,cast(char*)("*."~ext));
}
gtk_file_chooser_add_filter(fc,f);
}
diff -Naur ../minwin_org/minwin/listbox.d minwin_gtk/minwin/listbox.d
--- ../minwin_org/minwin/listbox.d 2007-03-15 14:30:47.000000000 +0000
+++ minwin_gtk/minwin/listbox.d 2007-03-09 20:09:04.000000000 +0000
@@ -82,7 +82,7 @@
args[0] = 0;
args[1] = cast(int)toStringz(s);
args[2] = -1;
- gtk_list_store_set_valist(model,&iter,args);
+ gtk_list_store_set_valist(model,&iter,&args);
}
peer = gtk_tree_view_new_with_model(cast(GtkTreeModel*)model);
g_object_unref(cast(GObject*)model);
diff -Naur ../minwin_org/minwin/samples/CMakeLists.txt minwin_gtk/minwin/samples/CMakeLists.txt
--- ../minwin_org/minwin/samples/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000
+++ minwin_gtk/minwin/samples/CMakeLists.txt 2007-03-10 09:00:08.000000000 +0000
@@ -0,0 +1,37 @@
+SET(CMAKE_FIND_LIBRARY_PREFIXES "")
+SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
+
+FIND_PACKAGE (GTK2)
+
+IF (GTK2_FOUND)
+ INCLUDE_DIRECTORIES (${minwin_gtk_SOURCE_DIR} ${GTK2_INCLUDE_DIRS})
+ LINK_DIRECTORIES (${minwin_gtk_SOURCE_DIR} ${GTK2_LIBRARY_DIRS})
+
+ ADD_EXECUTABLE (sample sample.d)
+ TARGET_LINK_LIBRARIES (sample minwin_gtk)
+
+ ADD_EXECUTABLE (layout layout.d)
+ TARGET_LINK_LIBRARIES (layout minwin_gtk)
+
+ ADD_EXECUTABLE (topgroup topgroup.d)
+ TARGET_LINK_LIBRARIES (topgroup minwin_gtk)
+
+ ADD_EXECUTABLE (widgets widgets.d)
+ TARGET_LINK_LIBRARIES (widgets minwin_gtk)
+
+ ADD_EXECUTABLE (menus menus.d)
+ TARGET_LINK_LIBRARIES (menus minwin_gtk)
+
+ ADD_EXECUTABLE (painting painting.d)
+ TARGET_LINK_LIBRARIES (painting minwin_gtk)
+
+ ADD_EXECUTABLE (sdialog sdialog.d)
+ TARGET_LINK_LIBRARIES (sdialog minwin_gtk)
+
+ ADD_EXECUTABLE (sdialog2 sdialog2.d)
+ TARGET_LINK_LIBRARIES (sdialog2 minwin_gtk)
+
+ ADD_EXECUTABLE (idle idle.d)
+ TARGET_LINK_LIBRARIES (idle minwin_gtk)
+
+ENDIF (GTK2_FOUND)
\ No newline at end of file