Numerous bug fixes to all platforms
Works both installed and not installed
This commit is contained in:
parent
c913f9f99a
commit
a81ea73566
68 changed files with 384 additions and 35286 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
@ -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>")
|
||||
|
|
|
@ -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
|
||||
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)
|
||||
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)
|
||||
MARK_AS_ADVANCED(CMAKE_AR)
|
||||
ENDIF(EXISTS ${CMAKE_SOURCE_DIR}/cmake/Modules/CMakeDCompiler.cmake.in)
|
||||
|
||||
MARK_AS_ADVANCED(CMAKE_AR)
|
||||
SET(CMAKE_D_COMPILER_ENV_VAR "DC")
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ")
|
|
@ -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 ")
|
||||
|
35
cmaked/Platform/Linux-dmd.cmake
Normal file
35
cmaked/Platform/Linux-dmd.cmake
Normal 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 ")
|
36
cmaked/Platform/Linux-gdc.cmake
Normal file
36
cmaked/Platform/Linux-gdc.cmake
Normal 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 ")
|
||||
|
36
cmaked/Platform/Windows-dmd.cmake
Normal file
36
cmaked/Platform/Windows-dmd.cmake
Normal 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 ")
|
||||
|
36
cmaked/Platform/Windows-gdc.cmake
Normal file
36
cmaked/Platform/Windows-gdc.cmake
Normal 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
61
cmaked/UseDDoc.cmake
Normal 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)
|
||||
|
|
@ -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 ")
|
|
@ -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 ")
|
||||
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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!();
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
|
@ -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 = >kRequest;
|
||||
content.sizeAllocate = >kAllocate;
|
||||
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?
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
|
|
@ -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 = >kRequest;
|
||||
content.sizeAllocate = >kAllocate;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
all.d
|
||||
-allobj
|
||||
-Tlibminwin_gtk
|
||||
-I..
|
||||
-fversion=GTK
|
||||
-lib
|
||||
-g
|
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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{}
|
||||
|
||||
}
|
|
@ -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!();
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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!();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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(); }
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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!();
|
||||
}
|
|
@ -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
|
|
@ -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)
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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)
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
EXETYPE NT
|
||||
SUBSYSTEM WINDOWS,5.0
|
|
@ -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>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "sample.exe.manifest"
|
||||
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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 = >kRequest;
|
||||
content.sizeAllocate = >kAllocate;
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
all.d
|
||||
logging.d
|
||||
-version=MinWin32
|
||||
-allobj
|
||||
-Tminwin.lib
|
||||
-I..
|
||||
-lib
|
||||
-g
|
||||
-w
|
|
@ -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
|
|
@ -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 = >kRequest;
|
||||
content.sizeAllocate = >kAllocate;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue