commit
40085f24cc
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.sln text eol=crlf
|
||||
*.vcxproj text eol=crlf
|
||||
*.vcxproj.filters text eol=crlf
|
||||
*.vcxproj.user text eol=crlf
|
||||
*.bat text eol=crlf
|
||||
Makefile text eolf=lf
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,6 +42,7 @@ lib/
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake-build-debug/
|
||||
cmake-build-*/
|
||||
.idea/
|
||||
cmake_install.cmake
|
||||
*.DS_Store
|
||||
|
||||
32
.travis.yml
32
.travis.yml
@ -20,6 +20,7 @@ matrix:
|
||||
- alsa-oss
|
||||
- libx11-dev
|
||||
- libxft-dev
|
||||
- libxcursor-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
@ -36,15 +37,18 @@ matrix:
|
||||
- alsa-oss
|
||||
- libx11-dev
|
||||
- libxft-dev
|
||||
- libxcursor-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise
|
||||
|
||||
before_install:
|
||||
- git clone --depth=1 --branch=develop https://github.com/qPCR4vir/nana-demo.git ../nana-demo
|
||||
- cd ..
|
||||
- git clone --depth=1 --branch=cmake-dev https://github.com/qPCR4vir/nana-demo.git nana-demo
|
||||
- export PATH="$HOME/bin:$PATH"
|
||||
|
||||
#- mkdir ~/bin #it seemd that a bin already exists from 20170901
|
||||
- wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.4/cmake-3.4.0-rc3-Linux-x86_64.sh || true
|
||||
- wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.12/cmake-3.12.0-rc3-Linux-x86_64.sh || true
|
||||
- chmod -R +x /tmp/tools
|
||||
|
||||
install:
|
||||
@ -57,31 +61,15 @@ before_script :
|
||||
- sleep 3 # give xvfb some time to start
|
||||
# we have: qPCR4vir/nana/../nana-demo and now we are in: qPCR4vir/nana/ our executable tests will access: ../nana-demo/Examples/*.bmp etc.(need to be in parallel with nana-demo/Examples)
|
||||
#- cd ../nana-demo
|
||||
- mkdir ../nana_lib
|
||||
- mkdir ../nana_demo_bin
|
||||
- cd ../nana_lib
|
||||
- mkdir bin
|
||||
- cd bin
|
||||
- mkdir demo-build
|
||||
- cd demo-build
|
||||
|
||||
script:
|
||||
# Installing: the static "nana lib" will be in DESTDIR/CMAKE_INSTALL_PREFIX/lib/
|
||||
# and the includes files "nana" in DESTDIR/CMAKE_INSTALL_PREFIX/include/
|
||||
# we are in "... nana/../nana_lib/bin/" we need "../../nana" to get the CMakeList.txt of nana.
|
||||
# Thus, make install will put the nana.lib in "... nana/../nana_lib/lib/"
|
||||
# and the includes in "... nana/../nana_lib/include/"
|
||||
- cmake -G"Unix Makefiles" ../../nana -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_ENABLE_PNG=OFF -DNANA_CMAKE_BUILD_DEMOS=ON -DNANA_CMAKE_ENABLE_AUDIO=OFF -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=ON -DNANA_CMAKE_BOOST_FILESYSTEM_FORCE=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON
|
||||
- make install
|
||||
- ls
|
||||
- cd ..
|
||||
- ls
|
||||
- cd ..
|
||||
- ls
|
||||
- cd nana_demo_bin
|
||||
- cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_ENABLE_PNG=OFF -DNANA_CMAKE_BUILD_DEMOS=ON -DNANA_CMAKE_ENABLE_AUDIO=OFF -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=ON -DNANA_CMAKE_BOOST_FILESYSTEM_FORCE=OFF -DNANA_CMAKE_INCLUDE_EXPERIMENTAL_DEMOS=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON
|
||||
- cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=ON -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON
|
||||
- make install
|
||||
# todo: separate resources from sources (a directory for images)
|
||||
- ls
|
||||
- cd ../bin
|
||||
- cd ../nana-test/bin
|
||||
- ls
|
||||
- ./a_group_impl
|
||||
- ./animate-bmp
|
||||
|
||||
457
CMakeLists.txt
457
CMakeLists.txt
@ -1,381 +1,140 @@
|
||||
# CMake configuration for Nana
|
||||
# Author: Andrew Kornilov(https://github.com/ierofant)
|
||||
# Contributors:
|
||||
# Andrew Kornilov (ierofant) - original version
|
||||
# Jinhao
|
||||
# Robert Hauck - Enable support for PNG/Freetype
|
||||
# Qiangqiang Wu - Add biicode support
|
||||
# Ariel Vina-Rodriguez (qPCR4vir)
|
||||
# (King_DuckZ)
|
||||
# Robert Hauck - Enable support for PNG/Freetype
|
||||
# Pavel O. - fix compilation with boost::filesystem (#281)
|
||||
# Frostbane - Add option for compiling a shared library (#263,#265)
|
||||
# Qiangqiang Wu - Add biicode support: todo migrate to https://conan.io/
|
||||
#
|
||||
# Nana uses some build systems: MS-VS solution, MAKE, bakefile, codeblock, etc. manually optimized.
|
||||
# In the future CMake could be the prefered, and maybe will be used to generate the others and the central nana repo
|
||||
# will distribute all of them. But by now CMake is just one of them and all the other distributed build system
|
||||
# files/projects are manually write. This current CMakeList.txt reflect this fact and that is why we don't
|
||||
# Maybe CMake will be used in the future to generate some of them in the central nana repository.
|
||||
# But by now CMake is just one option and all the other build system
|
||||
# files/projects distributed are manually writen. This current CMakeList.txt reflect this fact and that is why we don't
|
||||
# generate here configurated *.h files or explicitly enumerate the sources files: anyway this CM-list
|
||||
# will be "touched" to force a re-run of cmake.
|
||||
|
||||
#https://cmake.org/cmake-tutorial/
|
||||
#https://cmake.org/cmake/help/v3.3/module/CMakeDependentOption.html?highlight=cmakedependentoption
|
||||
# use CACHE FORCE or set(ENABLE_MINGW_STD_THREADS_WITH_MEGANZ ON) or delete CMakecache.txt or the entirely build dir
|
||||
# if your changes don't execute
|
||||
# It seems that project() defines essential system variables like CMAKE_FIND_LIBRARY_PREFIXES.
|
||||
# https://bbs.archlinux.org/viewtopic.php?id=84967
|
||||
# https://cliutils.gitlab.io/modern-cmake/
|
||||
# https://cmake.org/cmake-tutorial/
|
||||
# https://cmake.org/cmake/help/v3.12/module/CMakeDependentOption.html?highlight=cmakedependentoption
|
||||
# cmake 3.12 have more better modern c++ support
|
||||
|
||||
project(nana)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
project(nana VERSION 1.6.2
|
||||
DESCRIPTION "C++ GUI library"
|
||||
HOMEPAGE_URL http://nanapro.org
|
||||
LANGUAGES CXX )
|
||||
|
||||
option(NANA_CMAKE_INSTALL_INCLUDES "Install nana includes when compile the library" ON)
|
||||
option(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ "replaced boost.thread with meganz's mingw-std-threads." OFF)
|
||||
option(NANA_CMAKE_ENABLE_PNG "Enable the use of PNG" OFF)
|
||||
option(NANA_CMAKE_LIBPNG_FROM_OS "Use libpng from operating system." ON)
|
||||
option(NANA_CMAKE_ENABLE_JPEG "Enable the use of JPEG" OFF)
|
||||
option(NANA_CMAKE_LIBJPEG_FROM_OS "Use libjpeg from operating system." ON)
|
||||
option(NANA_CMAKE_ENABLE_AUDIO "Enable class audio::play for PCM playback." OFF)
|
||||
option(NANA_CMAKE_SHARED_LIB "Compile nana as a shared library." OFF)
|
||||
option(NANA_CMAKE_VERBOSE_PREPROCESSOR "Show annoying debug messages during compilation." ON)
|
||||
option(NANA_CMAKE_STOP_VERBOSE_PREPROCESSOR "Stop compilation after showing the annoying debug messages." OFF)
|
||||
option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF)
|
||||
option(NANA_CLION "Activate some CLion specific workarounds" OFF)
|
||||
####################### Main setting of Nana targets, sources and installs #####################
|
||||
|
||||
# The ISO C++ File System Technical Specification (ISO-TS, or STD) is optional.
|
||||
# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf
|
||||
# This is not a workaround, but an user option.
|
||||
# The library maybe available in the std library in use or from Boost (almost compatible)
|
||||
# http://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm
|
||||
# or you can choose to use the (partial, but functional) implementation provided by nana.
|
||||
# If you include the file <nana/filesystem/filesystem.hpp> or <nana/filesystem/filesystem_ext.hpp>
|
||||
# the selected option will be set by nana into std::experimental::filesystem
|
||||
# By default Nana will try to use the STD. If STD is not available and NANA_CMAKE_FIND_BOOST_FILESYSTEM
|
||||
# is set to ON nana will try to use boost if available. Nana own implementation will be use if none of
|
||||
# the previus were selected or available.
|
||||
# You can change that default if you change one of the following
|
||||
# (please don't define more than one of the _XX_FORCE options):
|
||||
option(NANA_CMAKE_FIND_BOOST_FILESYSTEM "Search: Is Boost filesystem available?" OFF)
|
||||
option(NANA_CMAKE_NANA_FILESYSTEM_FORCE "Force nana filesystem over ISO and boost?" OFF)
|
||||
option(NANA_CMAKE_STD_FILESYSTEM_FORCE "Use of STD filesystem?(a compilation error will ocurre if not available)" OFF)
|
||||
option(NANA_CMAKE_BOOST_FILESYSTEM_FORCE "Force use of Boost filesystem if available (over STD)?" OFF)
|
||||
add_library(nana)
|
||||
target_compile_features(nana PUBLIC cxx_std_17)
|
||||
|
||||
########### Compatibility with CMake 3.1
|
||||
if(POLICY CMP0054)
|
||||
# http://www.cmake.org/cmake/help/v3.1/policy/CMP0054.html
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
# need after cxx_std_14 or cxx_std_17 ??
|
||||
target_compile_features(nana
|
||||
PUBLIC cxx_nullptr
|
||||
PUBLIC cxx_range_for
|
||||
PUBLIC cxx_lambdas
|
||||
PUBLIC cxx_decltype_auto
|
||||
PUBLIC cxx_defaulted_functions
|
||||
PUBLIC cxx_deleted_functions
|
||||
PUBLIC cxx_auto_type
|
||||
PUBLIC cxx_decltype_incomplete_return_types
|
||||
PUBLIC cxx_defaulted_move_initializers
|
||||
PUBLIC cxx_noexcept
|
||||
PUBLIC cxx_rvalue_references
|
||||
)
|
||||
|
||||
########### OS
|
||||
### collect all source sub-directories in a list to avoid duplication ###
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
# Global MSVC definitions. You may prefer the hand-tuned sln and projects from the nana repository.
|
||||
if(MSVC)
|
||||
option(MSVC_USE_MP "Set to ON to build nana with the /MP option (Visual Studio 2005 and above)." ON)
|
||||
option(MSVC_USE_STATIC_RUNTIME "Set to ON to build nana with the /MT(d) option." ON)
|
||||
# By using CMAKE_CURRENT_LIST_DIR here you can compile and consume nana by just:
|
||||
# add_subdirectory(../nana ../cmake-nana-build-${CONFIG} ) or simmilar
|
||||
# in your own CMakeLists.txt, and them :
|
||||
# target_link_libraries(yourApp PRIVATE nana )
|
||||
|
||||
# Change the MSVC Compiler flags
|
||||
if(MSVC_USE_MP)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif()
|
||||
set(NANA_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/source)
|
||||
|
||||
if(MSVC_USE_STATIC_RUNTIME)
|
||||
foreach(flag
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
if(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ)
|
||||
add_definitions(-DSTD_THREAD_NOT_SUPPORTED)
|
||||
add_definitions(-DNANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(DLLTOOL OFF)
|
||||
else()
|
||||
# mingw: If dlltool is found the def and lib file will be created
|
||||
find_program (DLLTOOL dlltool)
|
||||
if(NOT DLLTOOL)
|
||||
message(WARNING "dlltool not found. Skipping import library generation.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
add_definitions(-DAPPLE)
|
||||
include_directories(/opt/X11/include/)
|
||||
list(APPEND NANA_LINKS -L/opt/X11/lib/ -liconv)
|
||||
set(ENABLE_AUDIO OFF)
|
||||
elseif(UNIX)
|
||||
add_definitions(-Dlinux)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
list(APPEND NANA_LINKS -lX11)
|
||||
include(FindFreetype)
|
||||
if(FREETYPE_FOUND)
|
||||
include_directories( ${FREETYPE_INCLUDE_DIRS})
|
||||
list(APPEND NANA_LINKS -lXft -lfontconfig)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
########### Compilers
|
||||
#
|
||||
# Using gcc: gcc 4.8 don't support C++14 and make_unique. You may want to update at least to 4.9.
|
||||
# gcc 5.3 and 5.4 include filesytem, but you need to add the link flag: -lstdc++fs
|
||||
#
|
||||
# In Windows, the gcc which come with CLion was 4.8 from MinGW.
|
||||
# CLion was updated to MinGW with gcc 6.3 ? Allways check this in File/Settings.../toolchains
|
||||
# You could install MinGW-w64 from the TDM-GCC Compiler Suite for Windows which will update you to gcc 5.1.
|
||||
# It is posible to follow https://computingabdn.com/softech/mingw-howto-install-gcc-for-windows/
|
||||
# and install MinGW with gcc 7.1 with has STD_THREADS and fs, from: https://sourceforge.net/projects/mingw-w64/files/
|
||||
#
|
||||
#
|
||||
# see at end of: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html
|
||||
#
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
||||
set(CMAKE_CXX_FLAGS "-std=gnu++14 -Wall -I/usr/local/include")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-std=gnu++14 -Wall")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-std=c++14 -Wall")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
if(NANA_CMAKE_SHARED_LIB)
|
||||
list(APPEND NANA_LINKS -lgcc -lstdc++ -pthread)
|
||||
else()
|
||||
if(MINGW)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static -pthread")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread")
|
||||
endif()
|
||||
endif(NANA_CMAKE_SHARED_LIB)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
|
||||
# GCC 4.9
|
||||
list(APPEND NANA_LINKS "-lboost_system -lboost_thread")
|
||||
elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3)
|
||||
# IS_GNUCXX < 5.3
|
||||
else()
|
||||
list(APPEND NANA_LINKS -lstdc++fs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if (APPLE AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # APPLE Clang
|
||||
list(APPEND NANA_LINKS -stdlib=libstdc++)
|
||||
endif ()
|
||||
|
||||
|
||||
############# Optional libraries
|
||||
|
||||
# Find PNG
|
||||
if(NANA_CMAKE_ENABLE_PNG)
|
||||
if(NANA_CMAKE_LIBPNG_FROM_OS)
|
||||
find_package(PNG)
|
||||
if(PNG_FOUND)
|
||||
include_directories(${PNG_INCLUDE_DIRS})
|
||||
list(APPEND NANA_LINKS ${PNG_LIBRARIES})
|
||||
add_definitions(-DNANA_ENABLE_PNG -DUSE_LIBPNG_FROM_OS)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DNANA_ENABLE_PNG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Find JPEG
|
||||
if(NANA_CMAKE_ENABLE_JPEG)
|
||||
add_definitions(-DNANA_ENABLE_JPEG)
|
||||
if(NANA_CMAKE_LIBJPEG_FROM_OS)
|
||||
find_package(JPEG)
|
||||
if(JPEG_FOUND)
|
||||
include_directories( ${JPEG_INCLUDE_DIR})
|
||||
list(APPEND NANA_LINKS ${JPEG_LIBRARY})
|
||||
add_definitions(-DNANA_ENABLE_JPEG -DUSE_LIBJPEG_FROM_OS)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DNANA_ENABLE_JPEG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Find ASOUND
|
||||
set(NANA_SOURCE_SUBDIRS
|
||||
/.
|
||||
/detail
|
||||
/detail/posix
|
||||
/filesystem
|
||||
/gui
|
||||
/gui/detail
|
||||
/gui/widgets
|
||||
/gui/widgets/skeletons
|
||||
/paint
|
||||
/paint/detail
|
||||
/system
|
||||
/threads
|
||||
)
|
||||
if(NANA_CMAKE_ENABLE_AUDIO)
|
||||
add_definitions(-DNANA_ENABLE_AUDIO)
|
||||
if(UNIX)
|
||||
find_package(ASOUND)
|
||||
if(ASOUND_FOUND)
|
||||
include_directories(${ASOUND_INCLUDE_DIRS})
|
||||
list(APPEND NANA_LINKS -lasound)
|
||||
else()
|
||||
message(FATAL_ERROR "libasound is not found")
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND NANA_SOURCE_SUBDIRS
|
||||
/audio
|
||||
/audio/detail
|
||||
)
|
||||
endif()
|
||||
|
||||
# Find/Select filesystem
|
||||
if(NANA_CMAKE_NANA_FILESYSTEM_FORCE)
|
||||
add_definitions(-DNANA_FILESYSTEM_FORCE)
|
||||
elseif(NANA_CMAKE_STD_FILESYSTEM_FORCE)
|
||||
add_definitions(-DSTD_FILESYSTEM_FORCE)
|
||||
elseif(NANA_CMAKE_FIND_BOOST_FILESYSTEM OR NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
||||
if(NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
||||
add_definitions(-DBOOST_FILESYSTEM_FORCE)
|
||||
endif()
|
||||
# https://cmake.org/cmake/help/git-master/module/FindBoost.html
|
||||
# Implicit dependencies such as Boost::filesystem requiring Boost::system will be automatically detected and satisfied,
|
||||
# even if system is not specified when using find_package and if Boost::system is not added to target_link_libraries.
|
||||
# If using Boost::thread, then Thread::Thread will also be added automatically.
|
||||
find_package(Boost COMPONENTS filesystem)
|
||||
if(Boost_FOUND)
|
||||
add_definitions(-DBOOST_FILESYSTEM_AVAILABLE)
|
||||
include_directories(SYSTEM "${Boost_INCLUDE_DIR}")
|
||||
list(APPEND NANA_LINKS ${Boost_LIBRARIES})
|
||||
endif()
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
# collect all source files in the source-sub-dir
|
||||
foreach(subdir ${NANA_SOURCE_SUBDIRS})
|
||||
aux_source_directory(${NANA_SOURCE_DIR}${subdir} SOURCES) # todo: use GLOB to add headers too ??
|
||||
endforeach()
|
||||
|
||||
target_sources(nana PRIVATE ${SOURCES})
|
||||
|
||||
### collect all headers sub-directories in a list to avoid duplication ###
|
||||
# To show .h files in Visual Studio, add them to the list of sources in add_executable / add_library / target_sources
|
||||
# and Use SOURCE_GROUP if all your sources are in the same directory
|
||||
set(NANA_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
|
||||
set(NANA_INCLUDE_SUBDIRS
|
||||
/.
|
||||
/filesystem
|
||||
/gui
|
||||
/gui/detail
|
||||
/gui/widgets
|
||||
/gui/widgets/skeletons
|
||||
/paint
|
||||
/paint/detail
|
||||
/pat
|
||||
/system
|
||||
/threads
|
||||
)
|
||||
if(NANA_CMAKE_ENABLE_AUDIO)
|
||||
list(APPEND NANA_INCLUDE_SUBDIRS
|
||||
/audio
|
||||
/audio/detail
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(subdir ${NANA_INCLUDE_SUBDIRS})
|
||||
aux_source_directory(${NANA_INCLUDE_DIR}/nana${subdir} HEADERS) # todo: use GLOB to add headers too !!!!!!!
|
||||
endforeach()
|
||||
|
||||
### Some nana compilation options ###
|
||||
option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF)
|
||||
option(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ "replaced boost.thread with meganz's mingw-std-threads." OFF) # deprecate?
|
||||
|
||||
######## Nana options
|
||||
|
||||
add_definitions(-DNANA_IGNORE_CONF)
|
||||
if(NANA_CMAKE_VERBOSE_PREPROCESSOR)
|
||||
add_definitions(-DVERBOSE_PREPROCESSOR)
|
||||
endif()
|
||||
target_compile_definitions(nana PRIVATE NANA_IGNORE_CONF) # really ?
|
||||
if(NANA_CMAKE_AUTOMATIC_GUI_TESTING)
|
||||
add_definitions(-DNANA_AUTOMATIC_GUI_TESTING)
|
||||
enable_testing()
|
||||
target_compile_definitions(nana PUBLIC NANA_AUTOMATIC_GUI_TESTING)
|
||||
# todo: enable_testing() # ??
|
||||
endif()
|
||||
|
||||
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/build/cmake/Modules)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/install_nana.cmake) # includes and libs, or just expose the nana target
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/OS.cmake) # windows, unix, linux, apple, ...
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/shared_libs.cmake) # static vs shared
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/compilers.cmake) # VC, gcc, clang
|
||||
|
||||
####################### Main setting of Nana sources, targets and install
|
||||
############# Optional libraries #####################
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/enable_png.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/enable_jpeg.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/enable_audio.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/select_filesystem.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/build/cmake/verbose.cmake) # Just for information
|
||||
|
||||
set(NANA_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/source)
|
||||
set(NANA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
# collect all source sub-directories in a list to avoid duplication here
|
||||
set(NANA_SOURCE_SUBDIRS /.
|
||||
/detail
|
||||
/filesystem
|
||||
/gui
|
||||
/gui/detail
|
||||
/gui/widgets
|
||||
/gui/widgets/skeletons
|
||||
/paint
|
||||
/paint/detail
|
||||
/system
|
||||
/threads
|
||||
)
|
||||
if(NANA_CMAKE_ENABLE_AUDIO)
|
||||
list(APPEND NANA_SOURCE_SUBDIRS /audio
|
||||
/audio/detail
|
||||
)
|
||||
endif()
|
||||
# collect all source files in the source-sub-dir
|
||||
# To show .h files in Visual Studio, add them to the list of sources in add_executable / add_library
|
||||
# and Use SOURCE_GROUP if all your sources are in the same directory
|
||||
foreach(subdir ${NANA_SOURCE_SUBDIRS})
|
||||
aux_source_directory(${NANA_SOURCE_DIR}${subdir} SOURCES)
|
||||
endforeach()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
add_definitions(-fmax-errors=3)
|
||||
endif()
|
||||
|
||||
set(CMAKE_DEBUG_POSTFIX "_d")
|
||||
|
||||
if(NANA_CMAKE_SHARED_LIB)
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCES})
|
||||
else()
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${NANA_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} ${NANA_LINKS})
|
||||
|
||||
# Headers: use INCLUDE_DIRECTORIES
|
||||
# Libraries: use FIND_LIBRARY and link with the result of it (try to avoid LINK_DIRECTORIES)
|
||||
|
||||
# Installing: the static "nana lib" will be in DESTDIR/CMAKE_INSTALL_PREFIX/lib/
|
||||
# and the includes files "include/nana/" in DESTDIR/CMAKE_INSTALL_PREFIX/include/nana/
|
||||
# unfortunatelly install() is still ignored by CLion:
|
||||
# https://intellij-support.jetbrains.com/hc/en-us/community/posts/205822949-CMake-install-isn-t-supported-
|
||||
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin)
|
||||
|
||||
# http://stackoverflow.com/questions/33788729/how-do-i-get-clion-to-run-an-install-target
|
||||
if(NANA_CLION) # the Clion IDE don't reconize the install target
|
||||
add_custom_target(install_${PROJECT_NAME}
|
||||
$(MAKE) install
|
||||
DEPENDS ${PROJECT_NAME}
|
||||
COMMENT "Installing ${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
if(NANA_CMAKE_SHARED_LIB)
|
||||
if(WIN32)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
if(DLLTOOL)
|
||||
#generate the lib and def files needed by msvc
|
||||
set_target_properties (${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}"
|
||||
ARCHIVE_OUTPUT_NAME "${PROJECT_NAME}"
|
||||
LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} -Wl,--output-def=${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.def")
|
||||
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
COMMAND echo " Generating import library"
|
||||
COMMAND "${DLLTOOL}" --dllname "lib${PROJECT_NAME}.dll"
|
||||
--input-def "lib${PROJECT_NAME}.def"
|
||||
--output-lib "lib${PROJECT_NAME}.lib")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.def"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.lib" DESTINATION lib)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message("")
|
||||
message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib")
|
||||
# Install the include directories too.
|
||||
if(NANA_CMAKE_INSTALL_INCLUDES)
|
||||
install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include)
|
||||
message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
|
||||
endif()
|
||||
|
||||
|
||||
# Just for information:
|
||||
message ("")
|
||||
message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID})
|
||||
message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG})
|
||||
message ( "CMAKE_COMPILER_IS_GNUCXX = " ${CMAKE_COMPILER_IS_GNUCXX})
|
||||
message ( "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS})
|
||||
message ( "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS})
|
||||
message ( "CMAKE_STATIC_LINKER_FLAGS = " ${CMAKE_STATIC_LINKER_FLAGS})
|
||||
message ( "NANA_LINKS = " ${NANA_LINKS})
|
||||
message ( "DESTDIR = " ${DESTDIR})
|
||||
message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX})
|
||||
message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR})
|
||||
message ( "CMAKE_CURRENT_SOURCE_DIR = " ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO})
|
||||
message ( "NANA_CMAKE_SHARED_LIB = " ${NANA_CMAKE_SHARED_LIB})
|
||||
message ( "NANA_CLION = " ${NANA_CLION})
|
||||
message ( "CMAKE_MAKE_PROGRAM = " ${CMAKE_MAKE_PROGRAM})
|
||||
message ( "CMAKE_CXX_COMPILER_VERSION = " ${CMAKE_CXX_COMPILER_VERSION})
|
||||
|
||||
message ( "NANA_CMAKE_FIND_BOOST_FILESYSTEM = " ${NANA_CMAKE_FIND_BOOST_FILESYSTEM})
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_FORCE = " ${NANA_CMAKE_BOOST_FILESYSTEM_FORCE})
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT = " ${NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT})
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_LIB = " ${NANA_CMAKE_BOOST_FILESYSTEM_LIB})
|
||||
message ( "NANA_CMAKE_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_AUTOMATIC_GUI_TESTING})
|
||||
message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING})
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
# Minimal layout, with all auxiliary folders inside "bii" and
|
||||
# The binary "bin" folder as is, and enabled code edition in the project root
|
||||
cmake: bii/cmake
|
||||
lib: bii/lib
|
||||
build: bii/build
|
||||
|
||||
deps: bii/deps
|
||||
# Setting this to True enables directly editing in the project root
|
||||
# instead of blocks/youruser/yourblock
|
||||
# the block will be named as your project folder
|
||||
auto-root-block: True
|
||||
root-block: qiangwu/nana
|
||||
@ -1,11 +0,0 @@
|
||||
# This file configures your finds of dependencies.
|
||||
#
|
||||
# It is an ordered list of rules, which will be evaluated in order, of the form:
|
||||
# block_pattern: TAG
|
||||
#
|
||||
# For each possible block that could resolve your dependencies,
|
||||
# only versions with tag >= TAG will be accepted
|
||||
|
||||
qiangwu/* : DEV
|
||||
* : STABLE
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
cmake: {generator: MinGW Makefiles}
|
||||
os: {arch: 32bit, family: Windows, subfamily: '7', version: 6.1.7601}
|
||||
49
biicode.conf
49
biicode.conf
@ -1,49 +0,0 @@
|
||||
# Biicode configuration file
|
||||
|
||||
[requirements]
|
||||
glenn/png: 6
|
||||
|
||||
[parent]
|
||||
# The parent version of this block. Must match folder name. E.g.
|
||||
# user/block # No version number means not published yet
|
||||
# You can change it to publish to a different track, and change version, e.g.
|
||||
# user/block(track): 7
|
||||
qiangwu/nana: 0
|
||||
|
||||
[paths]
|
||||
# Local directories to look for headers (within block)
|
||||
# /
|
||||
include
|
||||
|
||||
[dependencies]
|
||||
# Manual adjust file implicit dependencies, add (+), remove (-), or overwrite (=)
|
||||
# hello.h + hello_imp.cpp hello_imp2.cpp
|
||||
# *.h + *.cpp
|
||||
include/nana/config.hpp + include/*
|
||||
include/nana/config.hpp + source/*
|
||||
|
||||
[mains]
|
||||
# Manual adjust of files that define an executable
|
||||
# !main.cpp # Do not build executable from this file
|
||||
# main2.cpp # Build it (it doesnt have a main() function, but maybe it includes it)
|
||||
|
||||
[tests]
|
||||
# Manual adjust of files that define a CTest test
|
||||
# test/* pattern to evaluate this test/ folder sources like tests
|
||||
|
||||
[hooks]
|
||||
# These are defined equal to [dependencies],files names matching bii*stage*hook.py
|
||||
# will be launched as python scripts at stage = {post_process, clean}
|
||||
# CMakeLists.txt + bii/my_post_process1_hook.py bii_clean_hook.py
|
||||
|
||||
[includes]
|
||||
# Mapping of include patterns to external blocks
|
||||
# hello*.h: user3/depblock # includes will be processed as user3/depblock/hello*.h
|
||||
png.h: glenn/png
|
||||
|
||||
[data]
|
||||
# Manually define data files dependencies, that will be copied to bin for execution
|
||||
# By default they are copied to bin/user/block/... which should be taken into account
|
||||
# when loading from disk such data
|
||||
# image.cpp + image.jpg # code should write open("user/block/image.jpg")
|
||||
|
||||
@ -30,6 +30,7 @@ library nana {
|
||||
detail/platform_spec_selector.cpp
|
||||
gui/animation.cpp
|
||||
gui/basis.cpp
|
||||
gui/dragdrop.cpp
|
||||
gui/dragger.cpp
|
||||
gui/drawing.cpp
|
||||
gui/effects.cpp
|
||||
@ -62,7 +63,6 @@ library nana {
|
||||
gui/widgets/date_chooser.cpp
|
||||
gui/widgets/float_listbox.cpp
|
||||
gui/widgets/form.cpp
|
||||
gui/widgets/frame.cpp
|
||||
gui/widgets/label.cpp
|
||||
gui/widgets/listbox.cpp
|
||||
gui/widgets/menubar.cpp
|
||||
|
||||
69
build/cmake/Modules/FindFontconfig.cmake
Normal file
69
build/cmake/Modules/FindFontconfig.cmake
Normal file
@ -0,0 +1,69 @@
|
||||
# - Try to find the Fontconfig
|
||||
# Once done this will define
|
||||
#
|
||||
# FONTCONFIG_FOUND - system has Fontconfig
|
||||
# FONTCONFIG_INCLUDE_DIR - The include directory to use for the fontconfig headers
|
||||
# FONTCONFIG_LIBRARIES - Link these to use FONTCONFIG
|
||||
# FONTCONFIG_DEFINITIONS - Compiler switches required for using FONTCONFIG
|
||||
|
||||
# Copyright (c) 2006,2007 Laurent Montel, <montel@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
if (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR)
|
||||
|
||||
# in cache already
|
||||
set(FONTCONFIG_FOUND TRUE)
|
||||
|
||||
else (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR)
|
||||
|
||||
if (NOT WIN32)
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_FONTCONFIG fontconfig)
|
||||
|
||||
set(FONTCONFIG_DEFINITIONS ${PC_FONTCONFIG_CFLAGS_OTHER})
|
||||
endif (NOT WIN32)
|
||||
|
||||
find_path(FONTCONFIG_INCLUDE_DIR fontconfig/fontconfig.h
|
||||
PATHS
|
||||
${PC_FONTCONFIG_INCLUDEDIR}
|
||||
${PC_FONTCONFIG_INCLUDE_DIRS}
|
||||
/usr/X11/include
|
||||
)
|
||||
|
||||
find_library(FONTCONFIG_LIBRARIES NAMES fontconfig
|
||||
PATHS
|
||||
${PC_FONTCONFIG_LIBDIR}
|
||||
${PC_FONTCONFIG_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Fontconfig DEFAULT_MSG FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR )
|
||||
|
||||
mark_as_advanced(FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR)
|
||||
|
||||
endif (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR)
|
||||
70
build/cmake/OS.cmake
Normal file
70
build/cmake/OS.cmake
Normal file
@ -0,0 +1,70 @@
|
||||
########### OS
|
||||
# https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html
|
||||
# http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
|
||||
|
||||
if(WIN32)
|
||||
target_compile_definitions(nana PUBLIC WIN32) # todo: why not simple test for _WIN32 in code??
|
||||
set(CMAKE_DEBUG_POSTFIX "_d") # ??
|
||||
# Global MSVC definitions. You may prefer the hand-tuned sln and projects from the nana repository.
|
||||
if(MSVC)
|
||||
option(MSVC_USE_MP "Set to ON to build nana with the /MP option (Visual Studio 2005 and above)." ON)
|
||||
option(MSVC_USE_STATIC_RUNTIME "Set to ON to build nana with the /MT(d) option." ON)
|
||||
|
||||
# Change the MSVC Compiler flags
|
||||
if(MSVC_USE_MP)
|
||||
target_compile_options(nana PUBLIC "/MP" )
|
||||
endif()
|
||||
|
||||
if(MSVC_USE_STATIC_RUNTIME)
|
||||
foreach(flag
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
if(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) # deprecated ?????
|
||||
target_compile_definitions(nana PUBLIC STD_THREAD_NOT_SUPPORTED
|
||||
PUBLIC NANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_compile_definitions(nana PUBLIC APPLE) # ??? not added by compilers? use __APPLE__ ?
|
||||
target_include_directories(nana PUBLIC /opt/X11/include/)
|
||||
target_link_libraries(nana PRIVATE iconv)
|
||||
set(ENABLE_AUDIO OFF)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
|
||||
find_package(X11 REQUIRED) # X11 - todo test PRIVATE
|
||||
target_link_libraries(nana
|
||||
PUBLIC ${X11_LIBRARIES}
|
||||
PUBLIC ${X11_Xft_LIB}
|
||||
)
|
||||
target_include_directories(nana SYSTEM
|
||||
PUBLIC ${X11_Xft_INCLUDE_PATH}
|
||||
PUBLIC ${X11_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
find_package(Freetype) # Freetype - todo test PRIVATE
|
||||
if (FREETYPE_FOUND)
|
||||
find_package(Fontconfig REQUIRED)
|
||||
target_include_directories(nana SYSTEM
|
||||
PUBLIC ${FREETYPE_INCLUDE_DIRS}
|
||||
PUBLIC ${FONTCONFIG_INCLUDE_DIR}
|
||||
)
|
||||
target_link_libraries(nana
|
||||
PUBLIC ${FREETYPE_LIBRARIES}
|
||||
PUBLIC ${FONTCONFIG_LIBRARIES}
|
||||
)
|
||||
endif(FREETYPE_FOUND)
|
||||
endif(UNIX)
|
||||
48
build/cmake/compilers.cmake
Normal file
48
build/cmake/compilers.cmake
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
########### Compilers
|
||||
#
|
||||
# Using gcc: gcc 4.8 don't support C++14 and make_unique. You may want to update at least to 4.9.
|
||||
# gcc 5.3 and 5.4 include filesytem, but you need to add the link flag: -lstdc++fs
|
||||
#
|
||||
# In Windows, with CLion Allways check in File/Settings.../toolchains
|
||||
# You could install MinGW-w64 from the TDM-GCC Compiler Suite for Windows which will update you to gcc 5.1.
|
||||
# It is posible to follow https://computingabdn.com/softech/mingw-howto-install-gcc-for-windows/
|
||||
# and install MinGW with gcc 7.1 with has STD_THREADS and fs, from: https://sourceforge.net/projects/mingw-w64/files/
|
||||
#
|
||||
# see at end of: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html
|
||||
#
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW??
|
||||
|
||||
target_compile_options(nana PRIVATE -Wall
|
||||
PUBLIC -g )
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON) # todo - test this
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(nana PRIVATE Threads::Threads)
|
||||
# target_compile_options(nana PUBLIC -pthread)
|
||||
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
||||
target_compile_options(nana PUBLIC -I/usr/local/include)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# target_link_libraries(nana PRIVATE stdc++fs) # ??
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
if (APPLE AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # APPLE Clang
|
||||
target_compile_options(nana PUBLIC -stdlib=libstdc++)
|
||||
endif ()
|
||||
|
||||
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
target_compile_options(nana PRIVATE -fmax-errors=3)
|
||||
endif()
|
||||
|
||||
15
build/cmake/enable_audio.cmake
Normal file
15
build/cmake/enable_audio.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
option(NANA_CMAKE_ENABLE_AUDIO "Enable class audio::play for PCM playback." OFF)
|
||||
|
||||
# todo: decide - PUBLIC vs PRIVATE
|
||||
if(NANA_CMAKE_ENABLE_AUDIO)
|
||||
target_compile_definitions(nana PUBLIC NANA_ENABLE_AUDIO)
|
||||
if(UNIX)
|
||||
find_package(ASOUND) # ? https://github.com/hintjens/demidi/blob/master/Findasound.cmake
|
||||
if(ASOUND_FOUND)
|
||||
target_include_directories(nana PUBLIC ${ASOUND_INCLUDE_DIRS})
|
||||
target_link_libraries(nana PUBLIC ${ASOUND_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "libasound is not found")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
24
build/cmake/enable_jpeg.cmake
Normal file
24
build/cmake/enable_jpeg.cmake
Normal file
@ -0,0 +1,24 @@
|
||||
option(NANA_CMAKE_ENABLE_JPEG "Enable the use of JPEG" OFF)
|
||||
option(NANA_CMAKE_LIBJPEG_FROM_OS "Use libjpeg from operating system." ON)
|
||||
option(JPEG_HAVE_BOOLEAN "Defining HAVE_BOOLEAN before including jpeglib.h" OFF)
|
||||
|
||||
# todo: decide - PUBLIC vs PRIVATE
|
||||
|
||||
if(NANA_CMAKE_ENABLE_JPEG)
|
||||
target_compile_definitions(nana PUBLIC NANA_ENABLE_JPEG)
|
||||
if(NANA_CMAKE_LIBJPEG_FROM_OS)
|
||||
find_package(JPEG)
|
||||
if(JPEG_FOUND)
|
||||
target_include_directories(nana PUBLIC ${JPEG_INCLUDE_DIRS})
|
||||
target_link_libraries (nana PUBLIC ${JPEG_LIBRARIES})
|
||||
target_compile_definitions(nana PUBLIC USE_LIBJPEG_FROM_OS)
|
||||
endif()
|
||||
else()
|
||||
target_compile_definitions(nana PUBLIC -ljpeg)
|
||||
endif()
|
||||
if(JPEG_HAVE_BOOLEAN)
|
||||
# ... Defining HAVE_BOOLEAN before including jpeglib.h should make it work...
|
||||
target_compile_definitions(nana PUBLIC HAVE_BOOLEAN)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
20
build/cmake/enable_png.cmake
Normal file
20
build/cmake/enable_png.cmake
Normal file
@ -0,0 +1,20 @@
|
||||
option(NANA_CMAKE_ENABLE_PNG "Enable the use of PNG" OFF)
|
||||
option(NANA_CMAKE_LIBPNG_FROM_OS "Use libpng from operating system." ON)
|
||||
|
||||
# todo: decide - PUBLIC vs PRIVATE
|
||||
|
||||
if(NANA_CMAKE_ENABLE_PNG)
|
||||
target_compile_definitions(nana PUBLIC NANA_ENABLE_PNG)
|
||||
if(NANA_CMAKE_LIBPNG_FROM_OS)
|
||||
find_package(PNG)
|
||||
if(PNG_FOUND)
|
||||
target_include_directories(nana PUBLIC ${PNG_INCLUDE_DIRS})
|
||||
target_link_libraries (nana PUBLIC ${PNG_LIBRARIES})
|
||||
target_compile_definitions(nana PUBLIC USE_LIBPNG_FROM_OS ${PNG_DEFINITIONS})
|
||||
# target_include_directories (nana SYSTEM PUBLIC PNG::PNG) # ??
|
||||
# target_compile_definitions (nana PUBLIC USE_LIBPNG_FROM_OS)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(nana PUBLIC png) # provided by nana?
|
||||
endif()
|
||||
endif()
|
||||
23
build/cmake/install_nana.cmake
Normal file
23
build/cmake/install_nana.cmake
Normal file
@ -0,0 +1,23 @@
|
||||
option(NANA_CMAKE_INSTALL "Install nana when compile the library (to be consumed without cmake)" OFF)
|
||||
|
||||
# Install the include directories too.
|
||||
if(NANA_CMAKE_INSTALL)
|
||||
# this is the prefered method to consume nana directly with some specific bulid system
|
||||
# Is your responsability to ensure all compiler options are compatible with the compilation
|
||||
# of the project linking to the nana lib here generated
|
||||
target_sources(nana PRIVATE ${HEADERS})
|
||||
target_include_directories(nana PRIVATE ${NANA_INCLUDE_DIR})
|
||||
message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib")
|
||||
# Actually in DESTDIR/CMAKE_INSTALL_PREFIX/lib but in windows there is no DESTDIR/ part.
|
||||
install(TARGETS nana
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin)
|
||||
install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include) # in ${CMAKE_INSTALL_PREFIX}/include/nana
|
||||
message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
|
||||
else()
|
||||
# this is the prefered method to consume nana with cmake
|
||||
target_sources(nana PUBLIC ${HEADERS})
|
||||
target_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
55
build/cmake/select_filesystem.cmake
Normal file
55
build/cmake/select_filesystem.cmake
Normal file
@ -0,0 +1,55 @@
|
||||
# The ISO C++ File System Technical Specification (ISO-TS, or STD) is optional.
|
||||
# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf
|
||||
# This is not a workaround, but an user option.
|
||||
# The library maybe available in the std library in use or from Boost (almost compatible)
|
||||
# http://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm
|
||||
# or you can choose to use the (partial, but functional) implementation provided by nana.
|
||||
# If you include the file <nana/filesystem/filesystem.hpp> or <nana/filesystem/filesystem_ext.hpp>
|
||||
# the selected option will be set by nana into std::experimental::filesystem
|
||||
# By default Nana will try to use the STD. If STD is not available and NANA_CMAKE_FIND_BOOST_FILESYSTEM
|
||||
# is set to ON nana will try to use boost if available. Nana own implementation will be use if none of
|
||||
# the previus were selected or available.
|
||||
# You can change that default if you change one of the following
|
||||
# (please don't define more than one of the _XX_FORCE options):
|
||||
option(NANA_CMAKE_NANA_FILESYSTEM_FORCE "Force nana filesystem over ISO and boost?" OFF)
|
||||
option(NANA_CMAKE_STD_FILESYSTEM_FORCE "Use of STD filesystem?(a compilation error will ocurre if not available)" OFF)
|
||||
option(NANA_CMAKE_BOOST_FILESYSTEM_FORCE "Force use of Boost filesystem if available (over STD)?" OFF)
|
||||
option(NANA_CMAKE_FIND_BOOST_FILESYSTEM "Search: Is Boost filesystem available?" OFF)
|
||||
|
||||
if(NANA_CMAKE_NANA_FILESYSTEM_FORCE)
|
||||
target_compile_definitions(nana PUBLIC NANA_FILESYSTEM_FORCE)
|
||||
|
||||
elseif(NANA_CMAKE_STD_FILESYSTEM_FORCE)
|
||||
target_compile_definitions(nana PUBLIC STD_FILESYSTEM_FORCE)
|
||||
target_link_libraries (nana PUBLIC stdc++fs)
|
||||
|
||||
elseif(NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
||||
target_compile_definitions(nana PUBLIC BOOST_FILESYSTEM_FORCE)
|
||||
# https://cmake.org/cmake/help/git-master/module/FindBoost.html
|
||||
# Implicit dependencies such as Boost::filesystem requiring Boost::system will be automatically detected and satisfied,
|
||||
# even if system is not specified when using find_package and if Boost::system is not added to target_link_libraries.
|
||||
# If using Boost::thread, then Thread::Thread will also be added automatically.
|
||||
find_package(Boost REQUIRED COMPONENTS filesystem)
|
||||
if(Boost_FOUND)
|
||||
target_compile_definitions(nana PUBLIC BOOST_FILESYSTEM_AVAILABLE)
|
||||
# SYSTEM - ignore warnings from here
|
||||
target_include_directories(nana SYSTEM PUBLIC "${Boost_INCLUDE_DIR}") # ?? SYSTEM
|
||||
target_link_libraries (nana PUBLIC ${Boost_LIBRARIES})
|
||||
# target_include_directories (nana SYSTEM PUBLIC Boost::Boost)
|
||||
# message("boost found true")
|
||||
endif()
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
else()
|
||||
# todo test for std (for now just force nana or boost if there no std)
|
||||
target_link_libraries (nana PUBLIC stdc++fs)
|
||||
|
||||
# todo if not test for boost
|
||||
# if not add nana filesystem
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
51
build/cmake/shared_libs.cmake
Normal file
51
build/cmake/shared_libs.cmake
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
option(BUILD_SHARED_LIBS "Compile nana as a shared library." OFF)
|
||||
|
||||
if(BUILD_SHARED_LIBS) # todo test
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
if(MSVC)
|
||||
set(DLLTOOL OFF)
|
||||
else()
|
||||
# mingw: If dlltool is found the def and lib file will be created
|
||||
find_program (DLLTOOL dlltool)
|
||||
if(NOT DLLTOOL)
|
||||
message(WARNING "dlltool not found. Skipping import library generation.")
|
||||
endif()
|
||||
endif()
|
||||
if(DLLTOOL)
|
||||
#generate the lib and def files needed by msvc
|
||||
set_target_properties (nana PROPERTIES
|
||||
OUTPUT_NAME nana
|
||||
ARCHIVE_OUTPUT_NAME nana
|
||||
LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} -Wl,--output-def=${CMAKE_CURRENT_BINARY_DIR}/libnana.def"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET nana POST_BUILD
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
COMMAND echo " Generating import library"
|
||||
COMMAND "${DLLTOOL}" --dllname "libnana.dll"
|
||||
--input-def "libnana.def"
|
||||
--output-lib "libnana.lib")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnana.def"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libnana.lib" DESTINATION lib)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW??
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_options(nana PUBLIC -lgcc -lstdc++)
|
||||
else()
|
||||
|
||||
if(MINGW)
|
||||
target_compile_options(nana PUBLIC -static) # -static ?? cmake knows BUILD_SHARED_LIBS
|
||||
else()
|
||||
target_compile_options(nana PUBLIC -static-libgcc -static-libstdc++)
|
||||
endif()
|
||||
endif(BUILD_SHARED_LIBS)
|
||||
|
||||
endif()
|
||||
57
build/cmake/verbose.cmake
Normal file
57
build/cmake/verbose.cmake
Normal file
@ -0,0 +1,57 @@
|
||||
option(NANA_CMAKE_VERBOSE_PREPROCESSOR "Show annoying debug messages during compilation." OFF)
|
||||
option(NANA_CMAKE_STOP_VERBOSE_PREPROCESSOR "Stop compilation after showing the annoying debug messages." OFF)
|
||||
|
||||
|
||||
if (NANA_CMAKE_VERBOSE_PREPROCESSOR)
|
||||
|
||||
target_compile_definitions(nana PRIVATE VERBOSE_PREPROCESSOR)
|
||||
|
||||
### Just for information: ########################################
|
||||
include(CMakePrintHelpers)
|
||||
# see: https://cmake.org/cmake/help/v3.12/manual/cmake-properties.7.html#properties-on-targets
|
||||
cmake_print_properties(TARGETS nana PROPERTIES
|
||||
COMPILE_DEFINITIONS COMPILE_OPTIONS COMPILE_FLAGS LINK_LIBRARIES
|
||||
INCLUDE_DIRECTORIES INSTALL_NAME_DIR LINK_FLAGS VERSION
|
||||
)
|
||||
|
||||
#message ("")
|
||||
# cmake_print_variables(SOURCES)
|
||||
cmake_print_variables(HEADERS)
|
||||
cmake_print_variables(PUBLIC_HEADERS)
|
||||
cmake_print_variables(NANA_CMAKE_INSTALL)
|
||||
|
||||
cmake_print_variables(Boost_INCLUDE_DIR)
|
||||
cmake_print_variables(Boost_LIBRARIES)
|
||||
cmake_print_variables(Boost::filesystem)
|
||||
|
||||
cmake_print_variables(PNG_INCLUDE_DIRS)
|
||||
cmake_print_variables(PNG_LIBRARIES)
|
||||
cmake_print_variables(PNG::PNG)
|
||||
|
||||
cmake_print_variables(CMAKE_BUILD_TYPE)
|
||||
cmake_print_variables(CMAKE_CONFIGURATION_TYPES)
|
||||
message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID})
|
||||
message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG})
|
||||
message ( "CMAKE_COMPILER_IS_GNUCXX = " ${CMAKE_COMPILER_IS_GNUCXX})
|
||||
message ( "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS})
|
||||
message ( "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS})
|
||||
message ( "CMAKE_STATIC_LINKER_FLAGS = " ${CMAKE_STATIC_LINKER_FLAGS})
|
||||
|
||||
message ( "DESTDIR = " ${DESTDIR})
|
||||
message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX})
|
||||
message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR})
|
||||
message ( "CMAKE_CURRENT_SOURCE_DIR = " ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO})
|
||||
message ( "NANA_CMAKE_SHARED_LIB = " ${NANA_CMAKE_SHARED_LIB})
|
||||
message ( "CMAKE_MAKE_PROGRAM = " ${CMAKE_MAKE_PROGRAM})
|
||||
message ( "CMAKE_CXX_COMPILER_VERSION = " ${CMAKE_CXX_COMPILER_VERSION})
|
||||
|
||||
message ( "NANA_CMAKE_NANA_FILESYSTEM_FORCE = " ${NANA_CMAKE_NANA_FILESYSTEM_FORCE})
|
||||
message ( "NANA_CMAKE_FIND_BOOST_FILESYSTEM = " ${NANA_CMAKE_FIND_BOOST_FILESYSTEM})
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_FORCE = " ${NANA_CMAKE_BOOST_FILESYSTEM_FORCE})
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT = " ${NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT})
|
||||
message ( "NANA_CMAKE_BOOST_FILESYSTEM_LIB = " ${NANA_CMAKE_BOOST_FILESYSTEM_LIB})
|
||||
message ( "NANA_CMAKE_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_AUTOMATIC_GUI_TESTING})
|
||||
message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING})
|
||||
|
||||
endif(NANA_CMAKE_VERBOSE_PREPROCESSOR)
|
||||
@ -66,6 +66,7 @@
|
||||
<Unit filename="../../source/gui/detail/native_window_interface.cpp" />
|
||||
<Unit filename="../../source/gui/detail/window_layout.cpp" />
|
||||
<Unit filename="../../source/gui/detail/window_manager.cpp" />
|
||||
<Unit filename="../../source/gui/dragdrop.cpp" />
|
||||
<Unit filename="../../source/gui/dragger.cpp" />
|
||||
<Unit filename="../../source/gui/drawing.cpp" />
|
||||
<Unit filename="../../source/gui/effects.cpp" />
|
||||
@ -87,7 +88,6 @@
|
||||
<Unit filename="../../source/gui/widgets/date_chooser.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/float_listbox.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/form.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/frame.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/group.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/label.cpp" />
|
||||
<Unit filename="../../source/gui/widgets/listbox.cpp" />
|
||||
|
||||
@ -202,6 +202,7 @@
|
||||
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\dragdrop.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\dragger.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\drawing.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\effects.cpp" />
|
||||
@ -223,7 +224,6 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\label.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp" />
|
||||
@ -324,7 +324,6 @@
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\detail\tree_cont.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\float_listbox.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\form.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\frame.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\group.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\label.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\listbox.hpp" />
|
||||
|
||||
@ -147,9 +147,6 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp">
|
||||
<Filter>Source Files\nana\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp">
|
||||
<Filter>Source Files\nana\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\label.cpp">
|
||||
<Filter>Source Files\nana\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
@ -333,6 +330,9 @@
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp">
|
||||
<Filter>Source Files\nana\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\dragdrop.cpp">
|
||||
<Filter>Source Files\nana\gui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
||||
@ -361,9 +361,6 @@
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\form.hpp">
|
||||
<Filter>Header Files\gui\widgets</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\frame.hpp">
|
||||
<Filter>Header Files\gui\widgets</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\label.hpp">
|
||||
<Filter>Header Files\gui\widgets</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@ -196,6 +196,7 @@
|
||||
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\dragdrop.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\dragger.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\drawing.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\effects.cpp" />
|
||||
@ -217,7 +218,6 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\label.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp" />
|
||||
|
||||
@ -141,9 +141,6 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp">
|
||||
<Filter>Source Files\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp">
|
||||
<Filter>Source Files\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
||||
<Filter>Source Files\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
@ -291,6 +288,9 @@
|
||||
<ClCompile Include="..\..\source\detail\platform_abstraction.cpp">
|
||||
<Filter>Source Files\detail</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\dragdrop.cpp">
|
||||
<Filter>Source Files\gui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\nana\any.hpp">
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
<ProjectGuid>{42D0520F-EFA5-4831-84FE-2B9085301C5D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>nana</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@ -102,6 +101,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -115,6 +115,7 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -130,6 +131,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -147,6 +149,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -179,6 +182,7 @@
|
||||
<ClCompile Include="..\..\source\gui\detail\native_window_interface.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_layout.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\detail\window_manager.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\dragdrop.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\dragger.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\drawing.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\effects.cpp" />
|
||||
@ -200,7 +204,6 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\date_chooser.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\float_listbox.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\label.cpp" />
|
||||
<ClCompile Include="..\..\source\gui\widgets\listbox.cpp" />
|
||||
@ -270,7 +273,6 @@
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\date_chooser.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\float_listbox.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\form.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\frame.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\group.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\label.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\listbox.hpp" />
|
||||
|
||||
@ -151,9 +151,6 @@
|
||||
<ClCompile Include="..\..\source\gui\widgets\form.cpp">
|
||||
<Filter>Sources\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\frame.cpp">
|
||||
<Filter>Sources\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
||||
<Filter>Sources\gui\widgets</Filter>
|
||||
</ClCompile>
|
||||
@ -292,6 +289,9 @@
|
||||
<ClCompile Include="..\..\source\gui\wvl.cpp">
|
||||
<Filter>Sources\gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\gui\dragdrop.cpp">
|
||||
<Filter>Sources\gui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\spinbox.hpp">
|
||||
@ -363,9 +363,6 @@
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\form.hpp">
|
||||
<Filter>Include\gui\widgets</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\gui\widgets\frame.hpp">
|
||||
<Filter>Include\gui\widgets</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\gui\animation.hpp">
|
||||
<Filter>Include\gui</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
Please refer to the Library Installation Documentation for the detailed installation instructions.
|
||||
http://nanapro.org/en-us/help/instl_lib_doc.htm
|
||||
https://github.com/qPCR4vir/nana-docs/wiki/Installation
|
||||
NOTE: The method of library installation for VC2003/2005/2008/2010/2012 is only for the version older than 0.8. Since version 0.8, the library only works in VC2013 and later. If you have not VC2013 installed, please choose the latest Codeblocks instead.
|
||||
|
||||
Using Clang
|
||||
https://github.com/cnjinhao/nana/wiki/Compiling-Nana-with-Clang-8.0
|
||||
|
||||
请参考库安装文档获取详细的安装步骤。
|
||||
http://nanapro.org/zh-cn/help/instl_lib_doc.htm
|
||||
https://github.com/qPCR4vir/nana-docs/wiki/Installation
|
||||
注意: 针对VC2003/2005/2008/2010/2012的安装方法只适用于低于0.8的版本。从0.8版起,该库对Visual C++的最低版本要求是2013。如果您没有安装VC2013,可以使用最新版的CodeBlocks代替。
|
||||
|
||||
|
||||
使用 Clang
|
||||
https://github.com/cnjinhao/nana/wiki/Compiling-Nana-with-Clang-8.0
|
||||
@ -1,13 +1,13 @@
|
||||
/*
|
||||
/**
|
||||
* Basic Types definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/basic_types.hpp
|
||||
* @file nana/basic_types.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_BASIC_TYPES_HPP
|
||||
|
||||
@ -211,10 +211,10 @@
|
||||
|
||||
|
||||
#undef _nana_std_optional
|
||||
#if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201703))) || \
|
||||
((__cplusplus < 201703L) || \
|
||||
#if ((defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201703))) || \
|
||||
((!defined(_MSC_VER)) && ((__cplusplus < 201703L) || \
|
||||
(defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ < 400)) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 701)) \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 701))) \
|
||||
)
|
||||
# define _nana_std_optional
|
||||
#endif
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Nana Configuration
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -25,10 +25,6 @@
|
||||
|
||||
#include "c++defines.hpp"
|
||||
|
||||
//This marco is defined since 1.4 and until 1.5 for deprecating frame widget.
|
||||
//This marco and class frame will be removed in version 1.5
|
||||
#define WIDGET_FRAME_DEPRECATED
|
||||
|
||||
//The following basic configurations are ignored when NANA_IGNORE_CONF is defined.
|
||||
//The NANA_IGNORE_CONF may be specified by CMake generated makefile.
|
||||
#ifndef NANA_IGNORE_CONF
|
||||
@ -71,7 +67,7 @@
|
||||
///////////////////
|
||||
// Support of PCM playback
|
||||
//
|
||||
#define NANA_ENABLE_AUDIO
|
||||
//#define NANA_ENABLE_AUDIO
|
||||
|
||||
///////////////////
|
||||
// Support for PNG
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Date Time Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -27,7 +27,7 @@ namespace nana
|
||||
};
|
||||
|
||||
date(); ///< the initialized date is today.
|
||||
date(const std::tm&);
|
||||
explicit date(const std::tm&);
|
||||
date(int year, int month, int day);
|
||||
|
||||
date operator - (int off) const;
|
||||
@ -44,8 +44,8 @@ namespace nana
|
||||
void set(const std::tm&);
|
||||
|
||||
static int day_of_week(int year, int month, int day);
|
||||
static unsigned year_days(unsigned year); ///< the number of days in the specified year.
|
||||
static unsigned month_days(unsigned year, unsigned month); ///< the number of days in the specified month.
|
||||
static unsigned year_days(const unsigned year); ///< the number of days in the specified year.
|
||||
static unsigned month_days(const unsigned year, const unsigned month); ///< the number of days in the specified month.
|
||||
static unsigned day_in_year(unsigned y, unsigned m, unsigned d); ///< Returns the index of the specified day in this year, at range[1, 365] or [1, 366]
|
||||
private:
|
||||
date _m_add(unsigned x) const;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A ISO C++ filesystem Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -13,7 +13,7 @@
|
||||
* and need VC2015 or a C++11 compiler. With a few correction can be compiler by VC2013
|
||||
*/
|
||||
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf --- last pdf of std draft N4100 <filesystem> 2014-07-04
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf --- pdf of std draft N4100 <filesystem> 2014-07-04
|
||||
// http://en.cppreference.com/w/cpp/experimental/fs
|
||||
// http://cpprocks.com/introduction-to-tr2-filesystem-library-in-vs2012/ --- TR2 filesystem in VS2012
|
||||
// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.140%29.aspx --- C++ 14, the <filesystem> header VS2015
|
||||
@ -55,36 +55,6 @@
|
||||
#define NANA_USING_BOOST_FILESYSTEM 1
|
||||
# include <chrono>
|
||||
# include <boost/filesystem.hpp>
|
||||
// dont include generic_u8string
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/path.hpp
|
||||
// enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/operations.hpp
|
||||
// but travis come with an oooold version of boost
|
||||
// NOT enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_54_0/boost/filesystem/operations.hpp
|
||||
namespace boost
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
|
||||
// enable directory_iterator C++11 range-base for statement use --------------------//
|
||||
|
||||
// begin() and end() are only used by a range-based for statement in the context of
|
||||
// auto - thus the top-level const is stripped - so returning const is harmless and
|
||||
// emphasizes begin() is just a pass through.
|
||||
inline const directory_iterator& begin(const directory_iterator& iter) BOOST_NOEXCEPT
|
||||
{
|
||||
return iter;
|
||||
}
|
||||
|
||||
inline directory_iterator end(const directory_iterator&) BOOST_NOEXCEPT
|
||||
{
|
||||
return directory_iterator();
|
||||
}
|
||||
|
||||
} // namespace filesystem
|
||||
}
|
||||
|
||||
|
||||
// add boost::filesystem into std::experimental::filesystem
|
||||
namespace std {
|
||||
@ -105,24 +75,57 @@ namespace std {
|
||||
socket = boost::filesystem::file_type::socket_file,
|
||||
unknown = boost::filesystem::file_type::type_unknown,
|
||||
};
|
||||
/// enable directory_iterator range-based for statements
|
||||
//inline directory_iterator begin(directory_iterator iter) noexcept
|
||||
//{
|
||||
// return iter;
|
||||
//}
|
||||
// Boost dont include generic_u8string
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/path.hpp
|
||||
//
|
||||
// Boost versions: 1.67.0, 1.66.0, ... 1.56.0 enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/operations.hpp
|
||||
// but travis come with an oooold version of boost
|
||||
// 1.55.0 NOT enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_54_0/boost/filesystem/operations.hpp
|
||||
#if BOOST_VERSION < 105600
|
||||
namespace boost
|
||||
// enable directory_iterator C++11 range-base for statement use --------------------//
|
||||
|
||||
// begin() and end() are only used by a range-based for statement in the context of
|
||||
// auto - thus the top-level const is stripped - so returning const is harmless and
|
||||
// emphasizes begin() is just a pass through.
|
||||
inline const directory_iterator& begin(const directory_iterator& iter) BOOST_NOEXCEPT
|
||||
{
|
||||
return iter;
|
||||
}
|
||||
|
||||
inline directory_iterator end(const directory_iterator&) BOOST_NOEXCEPT
|
||||
{
|
||||
return directory_iterator();
|
||||
}
|
||||
#endif
|
||||
|
||||
//inline directory_iterator end(const directory_iterator&) noexcept
|
||||
//{
|
||||
// return {};
|
||||
//}
|
||||
} // filesystem
|
||||
} // experimental
|
||||
|
||||
namespace filesystem
|
||||
{
|
||||
using namespace experimental::filesystem;
|
||||
}
|
||||
} // std
|
||||
|
||||
#else
|
||||
# undef NANA_USING_STD_FILESYSTEM
|
||||
# define NANA_USING_STD_FILESYSTEM 1
|
||||
# include <experimental/filesystem>
|
||||
# if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) || \
|
||||
((__cplusplus >= 201703L) && \
|
||||
(defined(__clang__) && (__clang_major__ >= 7) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 8))) )
|
||||
# include <filesystem>
|
||||
# else
|
||||
# include <experimental/filesystem>
|
||||
namespace std{
|
||||
namespace filesystem{
|
||||
using namespace std::experimental::filesystem;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -172,7 +175,13 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
unknown = 0xFFFF ///< not known, such as when a file_status object is created without specifying the permissions
|
||||
};
|
||||
//enum class copy_options;
|
||||
//enum class directory_options;
|
||||
|
||||
enum class directory_options
|
||||
{
|
||||
none,
|
||||
follow_directory_symlink,
|
||||
skip_permission_denied
|
||||
};
|
||||
|
||||
struct space_info
|
||||
{
|
||||
@ -231,7 +240,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
}
|
||||
|
||||
// modifiers
|
||||
//void clear() noexcept;
|
||||
void clear() noexcept;
|
||||
path& make_preferred();
|
||||
path& remove_filename();
|
||||
//path& replace_filename(const path& replacement);
|
||||
@ -239,10 +248,10 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
//void swap(path& rhs) noexcept;
|
||||
|
||||
// decomposition
|
||||
//path root_name() const;
|
||||
//path root_directory() const;
|
||||
//path root_path() const;
|
||||
//path relative_path() const;
|
||||
path root_name() const;
|
||||
path root_directory() const;
|
||||
path root_path() const;
|
||||
path relative_path() const;
|
||||
path parent_path() const;
|
||||
path filename() const;
|
||||
//path stem() const;
|
||||
@ -250,16 +259,16 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
|
||||
// query
|
||||
bool empty() const noexcept;
|
||||
//bool has_root_name() const;
|
||||
//bool has_root_directory() const;
|
||||
//bool has_root_path() const;
|
||||
//bool has_relative_path() const;
|
||||
bool has_parent_path() const { return !parent_path().string().empty(); }; // temp;;
|
||||
bool has_filename() const { return !filename().string().empty(); }; // temp;
|
||||
bool has_root_name() const { return !root_name().empty(); }
|
||||
bool has_root_directory() const { return !root_directory().empty(); }
|
||||
bool has_root_path() const { return !root_path().empty(); }
|
||||
bool has_relative_path() const { return !relative_path().empty(); }
|
||||
bool has_parent_path() const { return !parent_path().empty(); }; // temp;;
|
||||
bool has_filename() const { return !filename().empty(); }; // temp;
|
||||
//bool has_stem() const;
|
||||
bool has_extension() const { return !extension().string().empty(); }; // temp
|
||||
//bool is_absolute() const;
|
||||
//bool is_relative() const;
|
||||
bool has_extension() const { return !extension().empty(); }; // temp
|
||||
bool is_absolute() const;
|
||||
bool is_relative() const;
|
||||
|
||||
int compare(const path& other) const;
|
||||
|
||||
@ -354,7 +363,8 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
public:
|
||||
|
||||
directory_iterator() noexcept;
|
||||
explicit directory_iterator(const path& dir);
|
||||
explicit directory_iterator(const path& p);
|
||||
directory_iterator(const path& p, directory_options opt);
|
||||
|
||||
const value_type& operator*() const;
|
||||
const value_type* operator->() const;
|
||||
@ -378,6 +388,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
private:
|
||||
bool end_{false};
|
||||
path::string_type path_;
|
||||
directory_options option_{ directory_options::none };
|
||||
|
||||
std::shared_ptr<find_handle> find_ptr_;
|
||||
find_handle handle_{nullptr};
|
||||
@ -417,14 +428,13 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
file_status status(const path& p, std::error_code&);
|
||||
|
||||
std::uintmax_t file_size(const path& p);
|
||||
//uintmax_t file_size(const path& p, error_code& ec) noexcept;
|
||||
std::uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
|
||||
|
||||
inline bool is_directory(file_status s) noexcept
|
||||
{ return s.type() == file_type::directory ;}
|
||||
|
||||
bool is_directory(const path& p);
|
||||
|
||||
//bool is_directory(const path& p, error_code& ec) noexcept;
|
||||
bool is_directory(const path& p, std::error_code& ec) noexcept;
|
||||
|
||||
inline bool is_regular_file(file_status s) noexcept
|
||||
{
|
||||
@ -520,10 +530,31 @@ namespace std {
|
||||
# else
|
||||
using namespace nana::experimental::filesystem::v1;
|
||||
# endif
|
||||
|
||||
} // filesystem
|
||||
} // experimental
|
||||
|
||||
namespace filesystem {
|
||||
using namespace std::experimental::filesystem;
|
||||
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || \
|
||||
(defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703)))
|
||||
path absolute(const path& p);
|
||||
path absolute(const path& p, std::error_code& err);
|
||||
|
||||
path canonical(const path& p);
|
||||
path canonical(const path& p, std::error_code& err);
|
||||
#endif
|
||||
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || defined(NANA_MINGW)
|
||||
bool exists( std::filesystem::file_status s ) noexcept;
|
||||
bool exists( const std::filesystem::path& p );
|
||||
bool exists( const std::filesystem::path& p, std::error_code& ec ) noexcept;
|
||||
#endif
|
||||
}
|
||||
} // std
|
||||
|
||||
|
||||
#endif //NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
@ -33,10 +33,10 @@ namespace filesystem_ext
|
||||
constexpr auto const def_rootname = "Root/";
|
||||
#endif
|
||||
|
||||
std::experimental::filesystem::path path_user(); ///< extention ?
|
||||
std::filesystem::path path_user(); ///< extention ?
|
||||
|
||||
/// workaround Boost not having path.generic_u8string() - a good point for http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0251r0.pdf
|
||||
inline std::string generic_u8string(const std::experimental::filesystem::path& p)
|
||||
inline std::string generic_u8string(const std::filesystem::path& p)
|
||||
{
|
||||
#if NANA_USING_BOOST_FILESYSTEM
|
||||
return nana::to_utf8(p.generic_wstring());
|
||||
@ -45,15 +45,15 @@ inline std::string generic_u8string(const std::experimental::filesystem::path& p
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool is_directory(const std::experimental::filesystem::directory_entry& dir) noexcept
|
||||
inline bool is_directory(const std::filesystem::directory_entry& dir) noexcept
|
||||
{
|
||||
return is_directory(dir.status());
|
||||
}
|
||||
|
||||
//template<class DI> // DI = directory_iterator from std, boost, or nana : return directory_entry
|
||||
class directory_only_iterator : public std::experimental::filesystem::directory_iterator
|
||||
class directory_only_iterator : public std::filesystem::directory_iterator
|
||||
{
|
||||
using directory_iterator = std::experimental::filesystem::directory_iterator;
|
||||
using directory_iterator = std::filesystem::directory_iterator;
|
||||
|
||||
directory_only_iterator& find_first()
|
||||
{
|
||||
@ -93,9 +93,9 @@ inline directory_only_iterator end(const directory_only_iterator&) noexcept
|
||||
}
|
||||
|
||||
//template<class DI> // DI = directory_iterator from std, boost, or nana : value_type directory_entry
|
||||
class regular_file_only_iterator : public std::experimental::filesystem::directory_iterator
|
||||
class regular_file_only_iterator : public std::filesystem::directory_iterator
|
||||
{
|
||||
using directory_iterator = std::experimental::filesystem::directory_iterator;
|
||||
using directory_iterator = std::filesystem::directory_iterator;
|
||||
regular_file_only_iterator& find_first()
|
||||
{
|
||||
while (((*this) != directory_iterator{}) && !is_regular_file((**this).status()))
|
||||
@ -128,11 +128,11 @@ inline regular_file_only_iterator end(const regular_file_only_iterator&) noexcep
|
||||
return{};
|
||||
}
|
||||
|
||||
std::string pretty_file_size(const std::experimental::filesystem::path& path);
|
||||
std::string pretty_file_size(const std::filesystem::path& path);
|
||||
|
||||
std::string pretty_file_date(const std::experimental::filesystem::path& path);
|
||||
std::string pretty_file_date(const std::filesystem::path& path);
|
||||
|
||||
bool modified_file_time(const std::experimental::filesystem::path& p, struct tm&); ///< extention ?
|
||||
bool modified_file_time(const std::filesystem::path& p, struct tm&); ///< extention ?
|
||||
|
||||
} // filesystem_ext
|
||||
} // nana
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An Animation Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -49,24 +49,18 @@ namespace nana
|
||||
|
||||
struct impl;
|
||||
class performance_manager;
|
||||
|
||||
/// Non-copyable
|
||||
animation(const animation&) = delete;
|
||||
animation& operator=(const animation&) = delete;
|
||||
public:
|
||||
animation(std::size_t fps = 23);
|
||||
~animation();
|
||||
|
||||
void push_back(frameset frms);
|
||||
/*
|
||||
void branch(const std::string& name, const frameset& frms)
|
||||
{
|
||||
impl_->branches[name].frames = frms;
|
||||
}
|
||||
animation(animation&&);
|
||||
animation& operator=(animation&&);
|
||||
|
||||
void branch(const std::string& name, const frameset& frms, std::function<std::size_t(const std::string&, std::size_t, std::size_t&)> condition)
|
||||
{
|
||||
auto & br = impl_->branches[name];
|
||||
br.frames = frms;
|
||||
br.condition = condition;
|
||||
}
|
||||
*/
|
||||
void push_back(frameset frms);
|
||||
|
||||
void looped(bool enable); ///< Enables or disables the animation repeating playback.
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Basis Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -65,6 +65,13 @@ namespace nana
|
||||
blend
|
||||
};
|
||||
|
||||
enum class dragdrop_status
|
||||
{
|
||||
not_ready,
|
||||
ready,
|
||||
in_progress
|
||||
};
|
||||
|
||||
namespace category
|
||||
{
|
||||
enum class flags
|
||||
@ -73,17 +80,11 @@ namespace nana
|
||||
widget = 0x1,
|
||||
lite_widget = 0x3,
|
||||
root = 0x5
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
,frame = 0x9
|
||||
#endif
|
||||
};
|
||||
//wait for constexpr
|
||||
struct widget_tag{ static const flags value = flags::widget; };
|
||||
struct lite_widget_tag : public widget_tag{ static const flags value = flags::lite_widget; };
|
||||
struct root_tag : public widget_tag{ static const flags value = flags::root; };
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
struct frame_tag : public widget_tag{ static const flags value = flags::frame; };
|
||||
#endif
|
||||
}// end namespace category
|
||||
|
||||
using native_window_type = detail::native_window_handle_impl*;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Basic Window Widget Definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -116,10 +116,6 @@ namespace detail
|
||||
/// bind a native window and baisc_window
|
||||
void bind_native_window(native_window_type, unsigned width, unsigned height, unsigned extra_width, unsigned extra_height, paint::graphics&);
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
void frame_window(native_window_type);
|
||||
#endif
|
||||
|
||||
bool is_ancestor_of(const basic_window* wd) const;
|
||||
bool visible_parents() const;
|
||||
bool displayed() const;
|
||||
@ -179,7 +175,9 @@ namespace detail
|
||||
bool ignore_menubar_focus : 1; ///< A flag indicates whether the menubar sets the focus.
|
||||
bool ignore_mouse_focus : 1; ///< A flag indicates whether the widget accepts focus when clicking on it
|
||||
bool space_click_enabled : 1; ///< A flag indicates whether enable mouse_down/click/mouse_up when pressing and releasing whitespace key.
|
||||
unsigned Reserved :18;
|
||||
bool draggable : 1;
|
||||
bool ignore_child_mapping : 1;
|
||||
unsigned Reserved :16;
|
||||
unsigned char tab; ///< indicate a window that can receive the keyboard TAB
|
||||
mouse_action action;
|
||||
mouse_action action_before;
|
||||
@ -205,19 +203,8 @@ namespace detail
|
||||
|
||||
struct other_tag
|
||||
{
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
struct attr_frame_tag
|
||||
{
|
||||
native_window_type container{nullptr};
|
||||
std::vector<native_window_type> attach;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct attr_root_tag
|
||||
{
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
container frames; ///< initialization is null, it will be created while creating a frame widget. Refer to WindowManager::create_frame
|
||||
#endif
|
||||
container tabstop;
|
||||
std::vector<edge_nimbus_action> effects_edge_nimbus;
|
||||
basic_window* focus{nullptr};
|
||||
@ -234,13 +221,13 @@ namespace detail
|
||||
///< if the active_window is null, the parent of this window keeps focus.
|
||||
paint::graphics glass_buffer; ///< if effect.bground is avaiable. Refer to window_layout::make_bground.
|
||||
update_state upd_state;
|
||||
dragdrop_status dnd_state{ dragdrop_status::not_ready };
|
||||
|
||||
container mapping_requester; ///< Children which are ignored to mapping
|
||||
|
||||
union
|
||||
{
|
||||
attr_root_tag * root;
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
attr_frame_tag * frame;
|
||||
#endif
|
||||
}attribute;
|
||||
|
||||
other_tag(category::flags);
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
#ifndef NANA_DETAIL_BEDROCK_PI_DATA_HPP
|
||||
#define NANA_DETAIL_BEDROCK_PI_DATA_HPP
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include "color_schemes.hpp"
|
||||
#include "events_operation.hpp"
|
||||
#include "window_manager.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct bedrock::pi_data
|
||||
{
|
||||
color_schemes scheme;
|
||||
events_operation evt_operation;
|
||||
window_manager wd_manager;
|
||||
std::set<core_window_t*> auto_form_set;
|
||||
bool shortkey_occurred{ false };
|
||||
|
||||
struct menu_rep
|
||||
{
|
||||
core_window_t* taken_window{ nullptr };
|
||||
bool delay_restore{ false };
|
||||
native_window_type window{ nullptr };
|
||||
native_window_type owner{ nullptr };
|
||||
bool has_keyboard{ false };
|
||||
}menu;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
#endif
|
||||
@ -91,7 +91,7 @@ namespace nana
|
||||
virtual void shortkey(graph_reference, const arg_keyboard&);
|
||||
|
||||
void filter_event(const event_code evt_code, const bool bDisabled);
|
||||
void filter_event(const std::vector<event_code> evt_codes, const bool bDisabled);
|
||||
void filter_event(const std::vector<event_code>& evt_codes, const bool bDisabled);
|
||||
void filter_event(const event_filter_status& evt_all_states);
|
||||
bool filter_event(const event_code evt_code);
|
||||
event_filter_status filter_event();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Definition of General Events
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,6 +17,7 @@
|
||||
#include <nana/gui/basis.hpp>
|
||||
#include "event_code.hpp"
|
||||
#include "internal_scope_guard.hpp"
|
||||
#include "../../filesystem/filesystem.hpp"
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
@ -46,12 +47,11 @@ namespace nana
|
||||
struct docker_base
|
||||
: public docker_interface
|
||||
{
|
||||
event_interface * event_ptr;
|
||||
bool flag_deleted{ false };
|
||||
event_interface * const event_ptr;
|
||||
bool flag_deleted;
|
||||
const bool unignorable;
|
||||
|
||||
docker_base(event_interface*, bool unignorable_flag);
|
||||
|
||||
detail::event_interface * get_event() const override;
|
||||
};
|
||||
|
||||
@ -220,33 +220,16 @@ namespace nana
|
||||
|
||||
//The dockers may resize when a new event handler is created by a calling handler.
|
||||
//Traverses with position can avaid crash error which caused by a iterator which becomes invalid.
|
||||
|
||||
auto i = dockers_->data();
|
||||
auto const end = i + dockers_->size();
|
||||
|
||||
for (; i != end; ++i)
|
||||
for (std::size_t i = 0; i < dockers_->size(); ++i)
|
||||
{
|
||||
if (static_cast<docker*>(*i)->flag_deleted)
|
||||
auto d = static_cast<docker*>(dockers_->data()[i]);
|
||||
if (d->flag_deleted || (arg.propagation_stopped() && !d->unignorable))
|
||||
continue;
|
||||
|
||||
static_cast<docker*>(*i)->invoke(arg);
|
||||
d->invoke(arg);
|
||||
|
||||
if (window_handle && (!detail::check_window(window_handle)))
|
||||
break;
|
||||
|
||||
if (arg.propagation_stopped())
|
||||
{
|
||||
for (++i; i != end; ++i)
|
||||
{
|
||||
if (!static_cast<docker*>(*i)->unignorable || static_cast<docker*>(*i)->flag_deleted)
|
||||
continue;
|
||||
|
||||
static_cast<docker*>(*i)->invoke(arg);
|
||||
if (window_handle && (!detail::check_window(window_handle)))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
@ -297,34 +280,16 @@ namespace nana
|
||||
};
|
||||
}
|
||||
|
||||
static std::function<void(arg_reference)> build_second(fn_type&& fn, void(fn_type::*)(arg_reference))
|
||||
template<typename Tfn, typename Ret>
|
||||
static std::function<void(arg_reference)> build_second(Tfn&& fn, Ret(fn_type::*)(arg_reference))
|
||||
{
|
||||
return std::move(fn);
|
||||
return std::forward<Tfn>(fn);
|
||||
}
|
||||
|
||||
static std::function<void(arg_reference)> build_second(fn_type&& fn, void(fn_type::*)(arg_reference) const)
|
||||
template<typename Tfn, typename Ret>
|
||||
static std::function<void(arg_reference)> build_second(Tfn&& fn, Ret(fn_type::*)(arg_reference)const)
|
||||
{
|
||||
return std::move(fn);
|
||||
}
|
||||
|
||||
static std::function<void(arg_reference)> build_second(fn_type& fn, void(fn_type::*)(arg_reference))
|
||||
{
|
||||
return fn;
|
||||
}
|
||||
|
||||
static std::function<void(arg_reference)> build_second(fn_type& fn, void(fn_type::*)(arg_reference) const)
|
||||
{
|
||||
return fn;
|
||||
}
|
||||
|
||||
static std::function<void(arg_reference)> build_second(const fn_type& fn, void(fn_type::*)(arg_reference))
|
||||
{
|
||||
return fn;
|
||||
}
|
||||
|
||||
static std::function<void(arg_reference)> build_second(const fn_type& fn, void(fn_type::*)(arg_reference) const)
|
||||
{
|
||||
return fn;
|
||||
return std::forward<Tfn>(fn);
|
||||
}
|
||||
|
||||
template<typename Tfn, typename Ret, typename Arg2>
|
||||
@ -420,7 +385,7 @@ namespace nana
|
||||
typedef typename std::remove_reference<arg_reference>::type arg_type;
|
||||
static_assert(std::is_convertible<arg_type, Arg2>::value, "The parameter type is not allowed, please check the function parameter type where you connected the event function.");
|
||||
|
||||
static std::function<void(arg_reference)> build(Ret(*fn)(Arg))
|
||||
static std::function<void(arg_reference)> build(Ret(*fn)(Arg2))
|
||||
{
|
||||
return[fn](arg_reference arg){
|
||||
fn(arg);
|
||||
@ -470,9 +435,9 @@ namespace nana
|
||||
|
||||
struct arg_dropfiles : public event_arg
|
||||
{
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
::nana::point pos; ///< cursor position in the event window
|
||||
std::vector<std::string> files; ///< external filenames
|
||||
::nana::window window_handle; ///< A handle to the event window
|
||||
::nana::point pos; ///< cursor position in the event window
|
||||
std::vector<std::filesystem::path> files; ///< external filenames
|
||||
};
|
||||
|
||||
struct arg_expose : public event_arg
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Widget Geometrics
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -22,12 +22,17 @@ namespace nana
|
||||
public:
|
||||
color_proxy(const color_proxy&);
|
||||
color_proxy(color_rgb);
|
||||
color_proxy(color_argb);
|
||||
color_proxy(color_rgba);
|
||||
color_proxy(colors);
|
||||
color_proxy& operator=(const color_proxy&);
|
||||
color_proxy& operator=(const ::nana::color&);
|
||||
color_proxy& operator=(color_rgb);
|
||||
color_proxy& operator=(color_argb);
|
||||
color_proxy& operator=(color_rgba);
|
||||
color_proxy& operator=(colors);
|
||||
color get_color() const;
|
||||
color get(const color& default_color) const;
|
||||
operator color() const;
|
||||
private:
|
||||
std::shared_ptr<color> color_;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Window Manager Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -83,12 +83,6 @@ namespace detail
|
||||
|
||||
core_window_t* create_root(core_window_t*, bool nested, rectangle, const appearance&, widget*);
|
||||
core_window_t* create_widget(core_window_t*, const rectangle&, bool is_lite, widget*);
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
core_window_t* create_frame(core_window_t*, const rectangle&, widget*);
|
||||
|
||||
bool insert_frame(core_window_t* frame, native_window);
|
||||
bool insert_frame(core_window_t* frame, core_window_t*);
|
||||
#endif
|
||||
void close(core_window_t*);
|
||||
|
||||
//destroy
|
||||
@ -122,11 +116,8 @@ namespace detail
|
||||
void refresh_tree(core_window_t*);
|
||||
|
||||
void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false);
|
||||
void map_requester(core_window_t*);
|
||||
|
||||
bool get_graphics(core_window_t*, nana::paint::graphics&);
|
||||
bool get_visual_rectangle(core_window_t*, nana::rectangle&);
|
||||
|
||||
std::vector<core_window_t*> get_children(core_window_t*) const;
|
||||
bool set_parent(core_window_t* wd, core_window_t* new_parent);
|
||||
core_window_t* set_focus(core_window_t*, bool root_has_been_focused, arg_focus::reason);
|
||||
|
||||
@ -149,7 +140,6 @@ namespace detail
|
||||
|
||||
bool register_shortkey(core_window_t*, unsigned long key);
|
||||
void unregister_shortkey(core_window_t*, bool with_children);
|
||||
std::vector<std::pair<core_window_t*, unsigned long>> shortkeys(core_window_t*, bool with_children);
|
||||
|
||||
core_window_t* find_shortkey(native_window_type, unsigned long key);
|
||||
|
||||
@ -159,6 +149,7 @@ namespace detail
|
||||
void _m_disengage(core_window_t*, core_window_t* for_new);
|
||||
void _m_destroy(core_window_t*);
|
||||
void _m_move_core(core_window_t*, const point& delta);
|
||||
void _m_shortkeys(core_window_t*, bool with_chlidren, std::vector<std::pair<core_window_t*, unsigned long>>& keys) const;
|
||||
core_window_t* _m_find(core_window_t*, const point&);
|
||||
static bool _m_effective(core_window_t*, const point& root_pos);
|
||||
private:
|
||||
|
||||
129
include/nana/gui/dragdrop.hpp
Normal file
129
include/nana/gui/dragdrop.hpp
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Drag and Drop Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2018-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/dragdrop.hpp
|
||||
* @author: Jinhao(cnjinhao@hotmail.com)
|
||||
*/
|
||||
#ifndef NANA_GUI_DRAGDROP_INCLUDED
|
||||
#define NANA_GUI_DRAGDROP_INCLUDED
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
#include <functional>
|
||||
#include "basis.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
/// Drag and drop actions
|
||||
enum class dnd_action
|
||||
{
|
||||
copy, ///< Copy the data to target.
|
||||
move, ///< Move the data to target.
|
||||
link ///< Create a link from source data to target.
|
||||
};
|
||||
|
||||
class simple_dragdrop
|
||||
{
|
||||
struct implementation;
|
||||
|
||||
simple_dragdrop(const simple_dragdrop&) = delete;
|
||||
simple_dragdrop& operator=(const simple_dragdrop&) = delete;
|
||||
|
||||
simple_dragdrop(simple_dragdrop&&) = delete;
|
||||
simple_dragdrop& operator=(simple_dragdrop&&) = delete;
|
||||
public:
|
||||
simple_dragdrop(window source);
|
||||
~simple_dragdrop();
|
||||
|
||||
/// Condition checker
|
||||
/**
|
||||
* Sets a condition checker that determines whether the drag-and-drop operation can start. If a condition checker is not set, it always start drag-and-drop operation.
|
||||
* @param predicate_fn Unary predicate which returns #true# for starting drag-and-drop operation.
|
||||
*/
|
||||
void condition(std::function<bool()> predicate_fn);
|
||||
void make_drop(window target, std::function<void()> drop_fn);
|
||||
private:
|
||||
implementation* const impl_;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct dragdrop_data;
|
||||
}
|
||||
|
||||
class dragdrop
|
||||
{
|
||||
struct implementation;
|
||||
|
||||
/// Non-copyable
|
||||
dragdrop(const dragdrop&) = delete;
|
||||
dragdrop& operator=(const dragdrop&) = delete;
|
||||
|
||||
/// Non-movable
|
||||
dragdrop(dragdrop&&) = delete;
|
||||
dragdrop& operator=(dragdrop&&) = delete;
|
||||
public:
|
||||
class data
|
||||
{
|
||||
friend struct dragdrop::implementation;
|
||||
|
||||
/// Non-copyable
|
||||
data(const data&) = delete;
|
||||
data& operator=(const data&) = delete;
|
||||
public:
|
||||
/// Constructor
|
||||
/**
|
||||
* Constructs a data object used for drag and drop
|
||||
* @param requested_action Indicates how the data to be transferred.
|
||||
*/
|
||||
data(dnd_action requested_action = dnd_action::copy);
|
||||
data(data&&);
|
||||
~data();
|
||||
|
||||
data& operator=(data&& rhs);
|
||||
|
||||
void insert(std::filesystem::path);
|
||||
private:
|
||||
detail::dragdrop_data* real_data_;
|
||||
};
|
||||
|
||||
dragdrop(window source);
|
||||
~dragdrop();
|
||||
|
||||
/// Condition checker
|
||||
/***
|
||||
* Sets a condition checker that determines whether the drag-and-drop operation can start. If a condition checker is not set, it always start drag-and-drop operation.
|
||||
* @param predicate_fn A predicate function to be set.
|
||||
*/
|
||||
void condition(std::function<bool()> predicate_fn);
|
||||
|
||||
/// Transferred data
|
||||
/**
|
||||
* Set a data generator. When drag begins, it is called to generate a data object for transferring.
|
||||
* @param generator It returns the data for transferring.
|
||||
*/
|
||||
void prepare_data(std::function<data()> generator);
|
||||
|
||||
/// Drop handler
|
||||
/**
|
||||
* The drop handler is called when the drop operation is completed. There are 3 parameters for the handler
|
||||
* dropped Indicates whether the data is accepted by a target window.
|
||||
* executed_action Indicates the action returned by target window. Ignore if dropped is false.
|
||||
* data_transferred The data object which is generated by the generator.
|
||||
* @param finish_fn The drop handling function.
|
||||
*/
|
||||
void drop_finished(std::function<void(bool dropped, dnd_action executed_action, data& data_transferred)> finish_fn);
|
||||
private:
|
||||
implementation* const impl_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -23,9 +23,10 @@ namespace nana
|
||||
class drawing
|
||||
:private nana::noncopyable
|
||||
{
|
||||
struct draw_fn_handle;
|
||||
public:
|
||||
typedef struct{}* diehard_t; ///< A handle to a drawing method
|
||||
typedef std::function<void(paint::graphics&)> draw_fn_t; ///< A function to draw
|
||||
using diehard_t = draw_fn_handle * ; ///< A handle to a drawing method
|
||||
using draw_fn_t = std::function<void(paint::graphics&)>; ///< A function to draw
|
||||
|
||||
drawing(window w); ///< Create a drawing object for a widget w
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Background Effects Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -45,7 +45,7 @@ namespace nana
|
||||
: public bground_factory_interface
|
||||
{
|
||||
public:
|
||||
bground_transparent(std::size_t percent);
|
||||
explicit bground_transparent(std::size_t percent);
|
||||
private:
|
||||
bground_interface* create() const override;
|
||||
private:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Filebox
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -9,14 +9,13 @@
|
||||
*
|
||||
* @file nana/gui/filebox.hpp
|
||||
* @author Jinhao
|
||||
* @brief a dialog to chose file(s), implemented "native" in windows but using nana for X11
|
||||
* @brief dialogs to chose file(s) or a directory, implemented "native" in windows but using nana for X11
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_FILEBOX_HPP
|
||||
#define NANA_GUI_FILEBOX_HPP
|
||||
#include <nana/gui/basis.hpp>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
#include <nana/optional.hpp>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
@ -29,9 +28,8 @@ namespace nana
|
||||
filebox(filebox&&) = delete;
|
||||
filebox& operator=(filebox&&) = delete;
|
||||
public:
|
||||
using filters = std::vector<std::pair< ::std::string, ::std::string>>;
|
||||
using path_type = std::filesystem::path;
|
||||
|
||||
filebox(bool is_open_mode);
|
||||
filebox(window owner, bool is_open_mode);
|
||||
filebox(const filebox&);
|
||||
~filebox();
|
||||
@ -39,43 +37,54 @@ namespace nana
|
||||
filebox& operator=(const filebox&);
|
||||
|
||||
/// Change owner window
|
||||
void owner(window);
|
||||
|
||||
/// Set a new title for the dialog
|
||||
/// @param string a text for title
|
||||
/// @return the old title.
|
||||
::std::string title( ::std::string new_title);
|
||||
|
||||
/** @brief Suggest initial path used to locate a directory when the filebox starts.
|
||||
* @param string initial_directory a path of initial directory
|
||||
* @note the behavior of init_path is different between Win7 and Win2K/XP/Vista, but its behavior under Linux is conformed with Win7.
|
||||
/**
|
||||
* Changes the owner window for the filebox. When #show()/operator()# are invoked, the dialog of filebox will be created with the specified owner.
|
||||
* @param handle A handle to a window which will be used for the owner of filebox
|
||||
*/
|
||||
filebox& init_path(const ::std::string& initial_directory);
|
||||
void owner(window handle);
|
||||
|
||||
filebox& init_file(const ::std::string&); ///< Init file, if it contains a path, the init path is replaced by the path of init file.
|
||||
/// Changes new title
|
||||
/**
|
||||
* Changes the title. When #show()/operator()# are invoked, the dialog of filebox will be created with the specified title.
|
||||
* @param text Text of title
|
||||
* @return the reference of *this.
|
||||
*/
|
||||
filebox& title( ::std::string text);
|
||||
|
||||
/// Sets a initial path
|
||||
/**
|
||||
* Suggest initial path used to locate a directory when the filebox starts.
|
||||
* @note the behavior of init_path is different between Win7 and Win2K/XP/Vista, but its behavior under Linux is conformed with Win7.
|
||||
* @param path a path of initial directory
|
||||
* @return reference of *this.
|
||||
*/
|
||||
filebox& init_path(const path_type& path);
|
||||
|
||||
/// Sets a initial filename
|
||||
/**
|
||||
* Suggest a filename when filebox starts. If the filename contains a path, the initial path will be replaced with the path presents in initial filename.
|
||||
* @param filename a filename used for a initial filename when filebox starts.
|
||||
* @return reference of *this.
|
||||
*/
|
||||
filebox& init_file(const ::std::string& filename); ///< Init file, if it contains a path, the init path is replaced by the path of init file.
|
||||
|
||||
/// \brief Add a filetype filter.
|
||||
/// To specify multiple filter in a single description, use a semicolon to separate the patterns(for example,"*.TXT;*.DOC;*.BAK").
|
||||
filebox& add_filter(const ::std::string& description, ///< for example. "Text File"
|
||||
const ::std::string& filetype ///< filter pattern(for example, "*.TXT")
|
||||
filebox& add_filter(const ::std::string& description, ///< for example: "Text File"
|
||||
const ::std::string& filetype ///< filter pattern(for example: "*.TXT")
|
||||
);
|
||||
|
||||
filebox& add_filter(const filters &ftres)
|
||||
{
|
||||
for (auto &f : ftres)
|
||||
add_filter(f.first, f.second);
|
||||
return *this;
|
||||
};
|
||||
filebox& add_filter(const std::vector<std::pair<std::string, std::string>> &filters);
|
||||
|
||||
const path_type& path() const;
|
||||
|
||||
::std::string path() const;
|
||||
::std::string file() const;
|
||||
filebox& allow_multi_select(bool allow);
|
||||
|
||||
/// Display the filebox dialog
|
||||
bool show() const;
|
||||
std::vector<path_type> show() const;
|
||||
|
||||
/// a function object method alternative to show() to display the filebox dialog,
|
||||
bool operator()() const
|
||||
std::vector<path_type> operator()() const
|
||||
{
|
||||
return show();
|
||||
}
|
||||
@ -92,17 +101,26 @@ namespace nana
|
||||
folderbox(folderbox&&) = delete;
|
||||
folderbox& operator=(folderbox&&) = delete;
|
||||
public:
|
||||
using path_type = std::experimental::filesystem::path;
|
||||
using path_type = std::filesystem::path;
|
||||
|
||||
folderbox(window owner = nullptr, const path_type& init_path = {});
|
||||
explicit folderbox(window owner = nullptr, const path_type& init_path = {}, std::string title={});
|
||||
~folderbox();
|
||||
|
||||
std::optional<path_type> show() const;
|
||||
/// Enables/disables multi select
|
||||
folderbox& allow_multi_select(bool allow);
|
||||
|
||||
std::optional<path_type> operator()() const
|
||||
std::vector<path_type> show() const;
|
||||
|
||||
std::vector<path_type> operator()() const
|
||||
{
|
||||
return show();
|
||||
}
|
||||
|
||||
/// Changes title
|
||||
/**
|
||||
* @param text Text of title
|
||||
*/
|
||||
folderbox& title(std::string text);
|
||||
private:
|
||||
implement* impl_;
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nana GUI Programming Interface Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -95,9 +95,7 @@ namespace API
|
||||
window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached);
|
||||
window create_widget(window, const rectangle&, widget* attached);
|
||||
window create_lite_widget(window, const rectangle&, widget* attached);
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
window create_frame(window, const rectangle&, widget* attached);
|
||||
#endif
|
||||
|
||||
paint::graphics* window_graphics(window);
|
||||
|
||||
void delay_restore(bool);
|
||||
@ -117,6 +115,9 @@ namespace API
|
||||
void lazy_refresh();
|
||||
|
||||
void draw_shortkey_underline(paint::graphics&, const std::string& text, wchar_t shortkey, std::size_t shortkey_position, const point& text_pos, const color&);
|
||||
|
||||
void window_draggable(window, bool enabled);
|
||||
bool window_draggable(window);
|
||||
}//end namespace dev
|
||||
|
||||
|
||||
@ -229,13 +230,7 @@ namespace API
|
||||
window root(native_window_type); ///< Retrieves the native window of a Nana.GUI window.
|
||||
|
||||
void fullscreen(window, bool);
|
||||
bool enabled_double_click(window, bool);
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
bool insert_frame(window frame, native_window_type);
|
||||
native_window_type frame_container(window frame);
|
||||
native_window_type frame_element(window frame, unsigned index);
|
||||
#endif
|
||||
void close_window(window);
|
||||
void show_window(window, bool show); ///< Sets a window visible state.
|
||||
void restore_window(window);
|
||||
@ -243,6 +238,7 @@ namespace API
|
||||
bool visible(window);
|
||||
window get_parent_window(window);
|
||||
window get_owner_window(window);
|
||||
|
||||
bool set_parent_window(window, window new_parent);
|
||||
|
||||
template<typename Widget=::nana::widget>
|
||||
@ -439,6 +435,7 @@ namespace API
|
||||
/// Sets the window active state. If a window active state is false, the window will not obtain the focus when a mouse clicks on it wich will be obteined by take_if_has_active_false.
|
||||
void take_active(window, bool has_active, window take_if_has_active_false);
|
||||
|
||||
/// Copies the graphics of a specified to a new graphics object.
|
||||
bool window_graphics(window, nana::paint::graphics&);
|
||||
bool root_graphics(window, nana::paint::graphics&);
|
||||
bool get_visual_rectangle(window, nana::rectangle&);
|
||||
@ -476,6 +473,8 @@ namespace API
|
||||
::std::optional<std::pair<::nana::size, ::nana::size>> content_extent(window wd, unsigned limited_px, bool limit_width);
|
||||
|
||||
unsigned screen_dpi(bool x_requested);
|
||||
|
||||
dragdrop_status window_dragdrop_status(::nana::window);
|
||||
}//end namespace API
|
||||
|
||||
}//end namespace nana
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
/**
|
||||
* A Button Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/button.hpp
|
||||
* @contributor
|
||||
* besh81(pr#361)
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGET_BUTTON_HPP
|
||||
@ -90,7 +92,12 @@ namespace nana{
|
||||
button(window, const char* caption, bool visible = true);
|
||||
button(window, const nana::rectangle& = rectangle(), bool visible = true);
|
||||
|
||||
button& icon(const nana::paint::image&);
|
||||
/// Shows an icon in front of caption
|
||||
/**
|
||||
* @param image Icon to be shown. If image is empty, the current icon is erased from the button.
|
||||
* @return the reference of *this.
|
||||
*/
|
||||
button& icon(const nana::paint::image& image);
|
||||
button& enable_pushed(bool);
|
||||
bool pushed() const;
|
||||
button& pushed(bool);
|
||||
|
||||
@ -37,6 +37,13 @@ namespace drawerbase
|
||||
{
|
||||
namespace checkbox
|
||||
{
|
||||
struct scheme
|
||||
: public widget_geometrics
|
||||
{
|
||||
color_proxy square_bgcolor{ static_cast<color_argb>(0x0) };
|
||||
color_proxy square_border_color{ colors::black };
|
||||
};
|
||||
|
||||
struct events_type
|
||||
: public general_events
|
||||
{
|
||||
@ -67,7 +74,7 @@ namespace drawerbase
|
||||
|
||||
|
||||
class checkbox
|
||||
: public widget_object<category::widget_tag, drawerbase::checkbox::drawer, drawerbase::checkbox::events_type>
|
||||
: public widget_object<category::widget_tag, drawerbase::checkbox::drawer, drawerbase::checkbox::events_type, drawerbase::checkbox::scheme>
|
||||
{
|
||||
public:
|
||||
checkbox();
|
||||
@ -97,6 +104,7 @@ namespace drawerbase
|
||||
struct element_tag
|
||||
{
|
||||
checkbox * uiobj;
|
||||
event_handle eh_clicked;
|
||||
event_handle eh_checked;
|
||||
event_handle eh_destroy;
|
||||
event_handle eh_keyboard;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Concept of Component Set
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -46,7 +46,7 @@ namespace nana{ namespace widgets{ namespace detail
|
||||
};
|
||||
|
||||
/// A component set placer used for specifying component position and size.
|
||||
template<typename Component, typename ItemAttribute>
|
||||
template<typename Component, typename ItemAttribute, typename WidgetScheme>
|
||||
class compset_placer
|
||||
{
|
||||
public:
|
||||
@ -56,8 +56,11 @@ namespace nana{ namespace widgets{ namespace detail
|
||||
|
||||
/// A type of widget-defined item attribute.
|
||||
typedef ItemAttribute item_attribute_t;
|
||||
|
||||
/// Widget scheme.
|
||||
typedef WidgetScheme widget_scheme_t;
|
||||
public:
|
||||
/// The destrcutor.
|
||||
/// The destructor.
|
||||
virtual ~compset_placer(){}
|
||||
|
||||
/// Enable/Disable the specified component.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A Tree Container class implementation
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -63,7 +63,7 @@ namespace detail
|
||||
{
|
||||
while (child)
|
||||
{
|
||||
if (child->owner == this)
|
||||
if (child == this)
|
||||
return true;
|
||||
|
||||
child = child->owner;
|
||||
@ -357,12 +357,12 @@ namespace detail
|
||||
}
|
||||
|
||||
template<typename PredAllowChild>
|
||||
unsigned distance_if(const node_type * node, PredAllowChild pac) const
|
||||
std::size_t distance_if(const node_type * node, PredAllowChild pac) const
|
||||
{
|
||||
if(nullptr == node) return 0;
|
||||
const node_type * iterator = root_.child;
|
||||
|
||||
unsigned off = 0;
|
||||
std::size_t off = 0;
|
||||
std::stack<const node_type* > stack;
|
||||
|
||||
while(iterator && iterator != node)
|
||||
@ -479,6 +479,8 @@ namespace detail
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// foreach elements of key.
|
||||
// the root name "/" and "\\" are treated as a node. This is a feature that can easily support the UNIX-like path.
|
||||
template<typename Function>
|
||||
void _m_for_each(const ::std::string& key, Function function) const
|
||||
{
|
||||
@ -491,18 +493,24 @@ namespace detail
|
||||
{
|
||||
if(beg != end)
|
||||
{
|
||||
if(function(key.substr(beg, end - beg)) == false)
|
||||
if(!function(key.substr(beg, end - beg)))
|
||||
return;
|
||||
}
|
||||
|
||||
auto next = key.find_first_not_of("\\/", end);
|
||||
if(next != ::std::string::npos)
|
||||
{
|
||||
beg = next;
|
||||
end = key.find_first_of("\\/", beg);
|
||||
}
|
||||
else
|
||||
|
||||
if ((next == ::std::string::npos) && end)
|
||||
return;
|
||||
|
||||
if (0 == end)
|
||||
{
|
||||
if ((!function(key.substr(0, 1))) || (next == ::std::string::npos))
|
||||
return;
|
||||
}
|
||||
|
||||
beg = next;
|
||||
end = key.find_first_of("\\/", beg);
|
||||
|
||||
}
|
||||
|
||||
function(key.substr(beg, key.size() - beg));
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
/**
|
||||
* A Frame Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/frame.hpp
|
||||
*
|
||||
* @brief A frame provides a way to contain the platform window in a stdex GUI Window
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_WIDGET_FRAME_HPP
|
||||
#define NANA_GUI_WIDGET_FRAME_HPP
|
||||
|
||||
#include "widget.hpp"
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
namespace nana
|
||||
{
|
||||
/**
|
||||
\brief Container for system native windows. Provides an approach to
|
||||
display a control that is not written with Nana.GUI in a Nana.GUI window.
|
||||
|
||||
Notes:
|
||||
|
||||
1. nana::native_window_type is a type of system handle of windows.
|
||||
2. all the children windows of a nana::frame is topmost to Nana.GUI windows.
|
||||
3. a simple example. Displaying a Windows Edit Control.
|
||||
|
||||
nana::frame frame(parent, 0, 0 200, 100);
|
||||
HWND frame_handle = reinterpret_cast<HWND>(frame.container());
|
||||
HWND edit = ::CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"Test",
|
||||
WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 200, 100,
|
||||
frame_handle, 0, ::GetModuleHandle(0), 0);
|
||||
if(edit)
|
||||
frame.insert(edit);
|
||||
|
||||
*/
|
||||
class frame: public widget_object<category::frame_tag, int, nana::general_events>
|
||||
{
|
||||
typedef widget_object<category::frame_tag, int> base_type;
|
||||
public:
|
||||
frame();
|
||||
frame(window, bool visible);
|
||||
frame(window, const rectangle& = rectangle(), bool visible = true);
|
||||
bool insert(native_window_type); ///< Inserts a platform native window.
|
||||
native_window_type element(unsigned index); ///< Returns the child window through index.
|
||||
|
||||
native_window_type container() const; ///< Returns the frame container native window handle.
|
||||
};
|
||||
}//end namespace nana
|
||||
#endif
|
||||
#endif
|
||||
@ -42,6 +42,13 @@ namespace nana{
|
||||
using field_reference = place::field_reference;
|
||||
constexpr static const std::size_t npos = static_cast<std::size_t>(-1);
|
||||
|
||||
enum class background_mode
|
||||
{
|
||||
none,
|
||||
transparent,
|
||||
blending
|
||||
};
|
||||
|
||||
/// The default construction
|
||||
group();
|
||||
|
||||
@ -66,17 +73,28 @@ namespace nana{
|
||||
checkbox& add_option(::std::string);
|
||||
|
||||
/// Modifies the alignment of the title
|
||||
void caption_align(align position);
|
||||
group& caption_align(align position);
|
||||
group& caption_background_mode(background_mode mode);
|
||||
|
||||
/// Enables/disables the radio mode which is single selection
|
||||
group& radio_mode(bool);
|
||||
|
||||
/// Returns the index of option in radio_mode, it throws a logic_error if radio_mode is false.
|
||||
/// Returns the index of selected option in radio_mode, it throws a logic_error if radio_mode is false.
|
||||
std::size_t option() const;
|
||||
|
||||
/** Set check/unchecked status of specified option
|
||||
@param[in] pos zero-based index of option to set
|
||||
@param[in] check status required, defaults to checked
|
||||
throws an out_of_range if !(pos < number of options)
|
||||
*/
|
||||
void option_check( std::size_t pos, bool check = true );
|
||||
|
||||
/// Determines whether a specified option is checked, it throws an out_of_range if !(pos < number of options)
|
||||
bool option_checked(std::size_t pos) const;
|
||||
|
||||
/// Change typeface of caption label ( does not effect child widgets )
|
||||
void typeface( const nana::paint::font& font );
|
||||
|
||||
group& enable_format_caption(bool format);
|
||||
|
||||
group& collocate() noexcept;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A List Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -1461,6 +1461,23 @@ the nana::detail::basic_window member pointer scheme
|
||||
/// Returns the number of columns
|
||||
size_type column_size() const;
|
||||
|
||||
/// Move column to view_position
|
||||
void move_column(size_type abs_pos, size_type view_pos);
|
||||
|
||||
/// Sort columns in range first_col to last_col inclusive using the values from a row
|
||||
void reorder_columns(size_type first_col,
|
||||
size_type last_col,
|
||||
index_pair row, bool reverse,
|
||||
std::function<bool(const std::string &cell1, size_type col1,
|
||||
const std::string &cell2, size_type col2,
|
||||
const nana::any *rowval,
|
||||
bool reverse)> comp);
|
||||
|
||||
void column_resizable(bool resizable);
|
||||
bool column_resizable() const;
|
||||
void column_movable(bool);
|
||||
bool column_movable() const;
|
||||
|
||||
/// Returns a rectangle in where the content is drawn.
|
||||
rectangle content_area() const;
|
||||
|
||||
@ -1481,9 +1498,19 @@ the nana::detail::basic_window member pointer scheme
|
||||
*/
|
||||
void insert_item(const index_pair& abs_pos, const ::std::wstring& text);
|
||||
|
||||
|
||||
void insert_item(index_pair abs_pos, const listbox& rhs, const index_pairs& indexes);
|
||||
|
||||
/// Returns an index of item which contains the specified point.
|
||||
index_pair cast(const point & screen_pos) const;
|
||||
|
||||
/// Returns the item which is hovered
|
||||
/**
|
||||
* @param return_end Indicates whether to return an end position instead of empty position if an item is not hovered.
|
||||
* @return The position of the hovered item. If return_end is true, it returns the position next to the last item of last category if an item is not hovered.
|
||||
*/
|
||||
index_pair hovered(bool return_end) const;
|
||||
|
||||
/// Returns the absolute position of column which contains the specified point.
|
||||
size_type column_from_pos(const point & pos) const;
|
||||
|
||||
@ -1502,7 +1529,8 @@ the nana::detail::basic_window member pointer scheme
|
||||
|
||||
///Sets a strict weak ordering comparer for a column
|
||||
void set_sort_compare( size_type col,
|
||||
std::function<bool(const std::string&, nana::any*, const std::string&, nana::any*, bool reverse)> strick_ordering);
|
||||
std::function<bool(const std::string&, nana::any*,
|
||||
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
||||
|
||||
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||
void sort_col(size_type col, bool reverse = false);
|
||||
@ -1523,6 +1551,7 @@ the nana::detail::basic_window member pointer scheme
|
||||
|
||||
void enable_single(bool for_selection, bool category_limited);
|
||||
void disable_single(bool for_selection);
|
||||
bool is_single_enabled(bool for_selection) const noexcept; ///< Determines whether the single selection/check is enabled.
|
||||
export_options& def_export_options();
|
||||
|
||||
|
||||
@ -1540,6 +1569,27 @@ the nana::detail::basic_window member pointer scheme
|
||||
* @return the reference of *this.
|
||||
*/
|
||||
listbox& category_icon(const paint::image& img_expanded, const paint::image&& img_collapsed);
|
||||
|
||||
/// Returns first visible element
|
||||
/**
|
||||
* It may return an item or a category item.
|
||||
* @return the index of first visible element.
|
||||
*/
|
||||
index_pair first_visible() const;
|
||||
|
||||
/// Returns last visible element
|
||||
/**
|
||||
* It may return an item or a category item.
|
||||
* @return the index of last visible element.
|
||||
*/
|
||||
index_pair last_visible() const;
|
||||
|
||||
/// Returns all visible items
|
||||
/**
|
||||
* It returns all visible items that are displayed in listbox window.
|
||||
* @return index_pairs containing all visible items.
|
||||
*/
|
||||
index_pairs visibles() const;
|
||||
private:
|
||||
drawerbase::listbox::essence & _m_ess() const;
|
||||
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const override;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Menubar implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -34,26 +34,6 @@ namespace nana
|
||||
color_proxy border_highlight{ colors::highlight };
|
||||
};
|
||||
|
||||
class item_renderer
|
||||
{
|
||||
public:
|
||||
enum class state
|
||||
{
|
||||
normal, highlighted, selected
|
||||
};
|
||||
|
||||
using graph_reference = paint::graphics&;
|
||||
using scheme = ::nana::drawerbase::menubar::scheme;
|
||||
|
||||
item_renderer(window, graph_reference);
|
||||
virtual void background(const point&, const ::nana::size&, state);
|
||||
virtual void caption(const point&, const native_string_type&);
|
||||
scheme *scheme_ptr() const { return scheme_ptr_; };
|
||||
private:
|
||||
graph_reference graph_;
|
||||
scheme *scheme_ptr_;
|
||||
};
|
||||
|
||||
class trigger
|
||||
: public drawer_trigger
|
||||
{
|
||||
|
||||
@ -67,30 +67,30 @@ namespace nana
|
||||
class drawer
|
||||
{
|
||||
public:
|
||||
struct states
|
||||
enum class states
|
||||
{
|
||||
enum{ none, highlight, actived, selected };
|
||||
none, highlight, actived, selected
|
||||
};
|
||||
|
||||
using graph_reference = paint::graphics&;
|
||||
const static unsigned fixedsize = 16; // make it part of a new "metric" in the widget_scheme
|
||||
|
||||
drawer(metrics_type& m);
|
||||
void set_vertical(bool);
|
||||
drawer(bool vert);
|
||||
buttons what(graph_reference, const point&);
|
||||
void scroll_delta_pos(graph_reference, int);
|
||||
void auto_scroll();
|
||||
void draw(graph_reference, buttons);
|
||||
void draw(graph_reference);
|
||||
|
||||
private:
|
||||
bool _m_check() const;
|
||||
void _m_adjust_scroll(graph_reference);
|
||||
void _m_background(graph_reference);
|
||||
void _m_button_frame(graph_reference, ::nana::rectangle, int state);
|
||||
void _m_draw_scroll(graph_reference, int state);
|
||||
void _m_draw_button(graph_reference, ::nana::rectangle, buttons what, int state);
|
||||
private:
|
||||
metrics_type &metrics_;
|
||||
bool vertical_;
|
||||
void _m_button_frame(graph_reference, ::nana::rectangle, states state);
|
||||
void _m_draw_scroll(graph_reference, states state);
|
||||
void _m_draw_button(graph_reference, ::nana::rectangle, buttons what, states state);
|
||||
public:
|
||||
metrics_type metrics;
|
||||
bool const vert;
|
||||
};
|
||||
|
||||
template<bool Vertical>
|
||||
@ -101,35 +101,34 @@ namespace nana
|
||||
typedef metrics_type::size_type size_type;
|
||||
|
||||
trigger()
|
||||
: graph_(nullptr), drawer_(metrics_)
|
||||
: graph_(nullptr), drawer_(Vertical)
|
||||
{
|
||||
drawer_.set_vertical(Vertical);
|
||||
}
|
||||
|
||||
const metrics_type& metrics() const
|
||||
{
|
||||
return metrics_;
|
||||
return drawer_.metrics;
|
||||
}
|
||||
|
||||
void peak(size_type s)
|
||||
{
|
||||
if (graph_ && (metrics_.peak != s))
|
||||
if (graph_ && (drawer_.metrics.peak != s))
|
||||
{
|
||||
metrics_.peak = s;
|
||||
drawer_.metrics.peak = s;
|
||||
API::refresh_window(widget_->handle());
|
||||
}
|
||||
}
|
||||
|
||||
void value(size_type s)
|
||||
{
|
||||
if (metrics_.range > metrics_.peak)
|
||||
if (drawer_.metrics.range > drawer_.metrics.peak)
|
||||
s = 0;
|
||||
else if (s + metrics_.range > metrics_.peak)
|
||||
s = metrics_.peak - metrics_.range;
|
||||
else if (s + drawer_.metrics.range > drawer_.metrics.peak)
|
||||
s = drawer_.metrics.peak - drawer_.metrics.range;
|
||||
|
||||
if (graph_ && (metrics_.value != s))
|
||||
if (graph_ && (drawer_.metrics.value != s))
|
||||
{
|
||||
metrics_.value = s;
|
||||
drawer_.metrics.value = s;
|
||||
_m_emit_value_changed();
|
||||
|
||||
API::refresh_window(*widget_);
|
||||
@ -138,16 +137,16 @@ namespace nana
|
||||
|
||||
void range(size_type s)
|
||||
{
|
||||
if (graph_ && (metrics_.range != s))
|
||||
if (graph_ && (drawer_.metrics.range != s))
|
||||
{
|
||||
metrics_.range = s;
|
||||
drawer_.metrics.range = s;
|
||||
API::refresh_window(widget_->handle());
|
||||
}
|
||||
}
|
||||
|
||||
void step(size_type s)
|
||||
{
|
||||
metrics_.step = (s ? s : 1);
|
||||
drawer_.metrics.step = (s ? s : 1);
|
||||
}
|
||||
|
||||
bool make_step(bool forward, unsigned multiple)
|
||||
@ -155,12 +154,12 @@ namespace nana
|
||||
if (!graph_)
|
||||
return false;
|
||||
|
||||
size_type step = (multiple > 1 ? metrics_.step * multiple : metrics_.step);
|
||||
size_type value = metrics_.value;
|
||||
size_type step = (multiple > 1 ? drawer_.metrics.step * multiple : drawer_.metrics.step);
|
||||
size_type value = drawer_.metrics.value;
|
||||
if (forward)
|
||||
{
|
||||
size_type maxv = metrics_.peak - metrics_.range;
|
||||
if (metrics_.peak > metrics_.range && value < maxv)
|
||||
size_type maxv = drawer_.metrics.peak - drawer_.metrics.range;
|
||||
if (drawer_.metrics.peak > drawer_.metrics.range && value < maxv)
|
||||
{
|
||||
if (maxv - value >= step)
|
||||
value += step;
|
||||
@ -175,8 +174,8 @@ namespace nana
|
||||
else
|
||||
value = 0;
|
||||
}
|
||||
size_type cmpvalue = metrics_.value;
|
||||
metrics_.value = value;
|
||||
size_type cmpvalue = drawer_.metrics.value;
|
||||
drawer_.metrics.value = value;
|
||||
if (value != cmpvalue)
|
||||
{
|
||||
_m_emit_value_changed();
|
||||
@ -191,6 +190,9 @@ namespace nana
|
||||
widget_ = static_cast< ::nana::scroll<Vertical>*>(&widget);
|
||||
widget.caption("nana scroll");
|
||||
|
||||
//scroll doesn't want the keyboard focus.
|
||||
API::take_active(widget, false, widget.parent());
|
||||
|
||||
timer_.stop();
|
||||
timer_.elapse(std::bind(&trigger::_m_tick, this));
|
||||
}
|
||||
@ -202,47 +204,42 @@ namespace nana
|
||||
|
||||
void refresh(graph_reference graph) override
|
||||
{
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
drawer_.draw(graph);
|
||||
}
|
||||
|
||||
void resized(graph_reference graph, const ::nana::arg_resized&) override
|
||||
{
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_enter(graph_reference graph, const ::nana::arg_mouse& arg) override
|
||||
{
|
||||
metrics_.what = drawer_.what(graph, arg.pos);
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
drawer_.metrics.what = drawer_.what(graph, arg.pos);
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_move(graph_reference graph, const ::nana::arg_mouse& arg) override
|
||||
{
|
||||
bool redraw = false;
|
||||
if (metrics_.pressed && (metrics_.what == buttons::scroll))
|
||||
if (drawer_.metrics.pressed && (drawer_.metrics.what == buttons::scroll))
|
||||
{
|
||||
size_type cmpvalue = metrics_.value;
|
||||
size_type cmpvalue = drawer_.metrics.value;
|
||||
drawer_.scroll_delta_pos(graph, (Vertical ? arg.pos.y : arg.pos.x));
|
||||
if (cmpvalue != metrics_.value)
|
||||
if (cmpvalue != drawer_.metrics.value)
|
||||
_m_emit_value_changed();
|
||||
redraw = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
buttons what = drawer_.what(graph, arg.pos);
|
||||
if (metrics_.what != what)
|
||||
{
|
||||
redraw = true;
|
||||
metrics_.what = what;
|
||||
}
|
||||
}
|
||||
if (redraw)
|
||||
{
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
API::dev::lazy_refresh();
|
||||
if (drawer_.metrics.what == what)
|
||||
return; //no change, don't redraw
|
||||
|
||||
drawer_.metrics.what = what;
|
||||
}
|
||||
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void dbl_click(graph_reference graph, const arg_mouse& arg) override
|
||||
@ -254,33 +251,33 @@ namespace nana
|
||||
{
|
||||
if (arg.left_button)
|
||||
{
|
||||
metrics_.pressed = true;
|
||||
metrics_.what = drawer_.what(graph, arg.pos);
|
||||
switch (metrics_.what)
|
||||
drawer_.metrics.pressed = true;
|
||||
drawer_.metrics.what = drawer_.what(graph, arg.pos);
|
||||
switch (drawer_.metrics.what)
|
||||
{
|
||||
case buttons::first:
|
||||
case buttons::second:
|
||||
make_step(metrics_.what == buttons::second, 1);
|
||||
make_step(drawer_.metrics.what == buttons::second, 1);
|
||||
timer_.interval(1000);
|
||||
timer_.start();
|
||||
break;
|
||||
case buttons::scroll:
|
||||
widget_->set_capture(true);
|
||||
metrics_.scroll_mouse_offset = (Vertical ? arg.pos.y : arg.pos.x) - metrics_.scroll_pos;
|
||||
drawer_.metrics.scroll_mouse_offset = (Vertical ? arg.pos.y : arg.pos.x) - drawer_.metrics.scroll_pos;
|
||||
break;
|
||||
case buttons::forward:
|
||||
case buttons::backward:
|
||||
{
|
||||
size_type cmpvalue = metrics_.value;
|
||||
size_type cmpvalue = drawer_.metrics.value;
|
||||
drawer_.auto_scroll();
|
||||
if (cmpvalue != metrics_.value)
|
||||
if (cmpvalue != drawer_.metrics.value)
|
||||
_m_emit_value_changed();
|
||||
}
|
||||
break;
|
||||
default: //Ignore buttons::none
|
||||
break;
|
||||
}
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
@ -291,18 +288,18 @@ namespace nana
|
||||
|
||||
widget_->release_capture();
|
||||
|
||||
metrics_.pressed = false;
|
||||
metrics_.what = drawer_.what(graph, arg.pos);
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
drawer_.metrics.pressed = false;
|
||||
drawer_.metrics.what = drawer_.what(graph, arg.pos);
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
void mouse_leave(graph_reference graph, const arg_mouse&) override
|
||||
{
|
||||
if (metrics_.pressed) return;
|
||||
if (drawer_.metrics.pressed) return;
|
||||
|
||||
metrics_.what = buttons::none;
|
||||
drawer_.draw(graph, buttons::none);
|
||||
drawer_.metrics.what = buttons::none;
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
|
||||
@ -310,7 +307,7 @@ namespace nana
|
||||
{
|
||||
if (make_step(arg.upwards == false, 3))
|
||||
{
|
||||
drawer_.draw(graph, metrics_.what);
|
||||
drawer_.draw(graph);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
@ -322,14 +319,13 @@ namespace nana
|
||||
|
||||
void _m_tick()
|
||||
{
|
||||
make_step(metrics_.what == buttons::second, 1);
|
||||
make_step(drawer_.metrics.what == buttons::second, 1);
|
||||
API::refresh_window(widget_->handle());
|
||||
timer_.interval(100);
|
||||
}
|
||||
private:
|
||||
::nana::scroll<Vertical> * widget_;
|
||||
nana::paint::graphics * graph_;
|
||||
metrics_type metrics_;
|
||||
drawer drawer_;
|
||||
timer timer_;
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A text editor implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -66,6 +66,7 @@ namespace nana{ namespace widgets
|
||||
using char_type = wchar_t;
|
||||
using size_type = textbase<char_type>::size_type;
|
||||
using string_type = textbase<char_type>::string_type;
|
||||
using path_type = std::filesystem::path;
|
||||
|
||||
using event_interface = text_editor_event_interface;
|
||||
|
||||
@ -105,7 +106,7 @@ namespace nana{ namespace widgets
|
||||
void indent(bool, std::function<std::string()> generator);
|
||||
void set_event(event_interface*);
|
||||
|
||||
bool load(const char*);
|
||||
bool load(const path_type& file);
|
||||
|
||||
void text_align(::nana::align alignment);
|
||||
|
||||
@ -135,13 +136,11 @@ namespace nana{ namespace widgets
|
||||
void enable_background(bool);
|
||||
void enable_background_counterpart(bool);
|
||||
|
||||
void undo_enabled(bool);
|
||||
bool undo_enabled() const;
|
||||
void undo_clear();
|
||||
void undo_max_steps(std::size_t);
|
||||
std::size_t undo_max_steps() const;
|
||||
|
||||
renderers& customized_renderers();
|
||||
void clear_undo(); ///< same with undo_max_steps(0)
|
||||
|
||||
unsigned line_height() const;
|
||||
unsigned screen_lines(bool completed_line = false) const;
|
||||
@ -167,6 +166,8 @@ namespace nana{ namespace widgets
|
||||
|
||||
bool select(bool);
|
||||
|
||||
bool select_points(nana::upoint arg_a, nana::upoint arg_b);
|
||||
|
||||
/// Sets the end position of a selected string.
|
||||
void set_end_caret(bool stay_in_view);
|
||||
|
||||
@ -200,12 +201,11 @@ namespace nana{ namespace widgets
|
||||
void del();
|
||||
void backspace(bool record_undo, bool perform_event);
|
||||
void undo(bool reverse);
|
||||
void set_undo_queue_length(std::size_t len);
|
||||
void move_ns(bool to_north); //Moves up and down
|
||||
void move_left();
|
||||
void move_right();
|
||||
const upoint& mouse_caret(const point& screen_pos, bool stay_in_view);
|
||||
const upoint& caret() const;
|
||||
const upoint& caret() const noexcept;
|
||||
point caret_screen_pos() const;
|
||||
bool scroll(bool upwards, bool vertical);
|
||||
|
||||
@ -215,8 +215,8 @@ namespace nana{ namespace widgets
|
||||
void mouse_pressed(const arg_mouse& arg);
|
||||
bool select_word(const arg_mouse& arg);
|
||||
|
||||
skeletons::textbase<char_type>& textbase();
|
||||
const skeletons::textbase<char_type>& textbase() const;
|
||||
skeletons::textbase<char_type>& textbase() noexcept;
|
||||
const skeletons::textbase<char_type>& textbase() const noexcept;
|
||||
|
||||
bool try_refresh();
|
||||
|
||||
|
||||
@ -682,7 +682,6 @@ namespace nana{ namespace widgets{ namespace skeletons
|
||||
{
|
||||
return lines_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
void _m_parse_format(tokenizer & tknizer, std::stack<fblock*> & fbstack)
|
||||
{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A textbase class implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -18,10 +18,11 @@
|
||||
#include <nana/charset.hpp>
|
||||
#include <nana/basic_types.hpp>
|
||||
#include <nana/traits.hpp>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
#include "textbase_export_interface.hpp"
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
@ -36,15 +37,16 @@ namespace skeletons
|
||||
: public ::nana::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef CharT char_type;
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
typedef typename string_type::size_type size_type;
|
||||
using char_type = CharT;
|
||||
using string_type = std::basic_string<CharT>;
|
||||
using size_type = typename string_type::size_type;
|
||||
using path_type = std::filesystem::path;
|
||||
|
||||
textbase()
|
||||
{
|
||||
attr_max_.reset();
|
||||
//Insert an empty string for the first line of empty text.
|
||||
text_cont_.emplace_back(new string_type);
|
||||
text_cont_.emplace_back();
|
||||
}
|
||||
|
||||
void set_event_agent(textbase_event_agent_interface * evt)
|
||||
@ -55,21 +57,19 @@ namespace skeletons
|
||||
bool empty() const
|
||||
{
|
||||
return (text_cont_.empty() ||
|
||||
((text_cont_.size() == 1) && (text_cont_.front()->empty())));
|
||||
((text_cont_.size() == 1) && text_cont_.front().empty()));
|
||||
}
|
||||
|
||||
bool load(const char* file_utf8)
|
||||
bool load(const path_type& file)
|
||||
{
|
||||
if (!file_utf8)
|
||||
return false;
|
||||
|
||||
std::ifstream ifs(to_osmbstr(file_utf8));
|
||||
std::ifstream ifs{ file.string() };
|
||||
if (!ifs)
|
||||
return false;
|
||||
|
||||
ifs.seekg(0, std::ios::end);
|
||||
std::size_t bytes = static_cast<std::size_t>(ifs.tellg());
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
std::error_code err;
|
||||
auto const bytes = file_size(file, err);
|
||||
if (err)
|
||||
return false;
|
||||
|
||||
if(bytes >= 2)
|
||||
{
|
||||
@ -81,7 +81,7 @@ namespace skeletons
|
||||
if(0xBB == ch && 0xBF == ifs.get())
|
||||
{
|
||||
ifs.close();
|
||||
return load(file_utf8, nana::unicode::utf8);
|
||||
return load(file, nana::unicode::utf8);
|
||||
}
|
||||
}
|
||||
else if(0xFF == ch)
|
||||
@ -89,16 +89,13 @@ namespace skeletons
|
||||
if(0xFE == ifs.get())
|
||||
{
|
||||
//UTF16,UTF32
|
||||
if(bytes >= 4)
|
||||
if((bytes >= 4) && (ifs.get() == 0 && ifs.get() == 0))
|
||||
{
|
||||
if(ifs.get() == 0 && ifs.get() == 0)
|
||||
{
|
||||
ifs.close();
|
||||
return load(file_utf8, nana::unicode::utf32);
|
||||
}
|
||||
ifs.close();
|
||||
return load(file, nana::unicode::utf32);
|
||||
}
|
||||
ifs.close();
|
||||
return load(file_utf8, nana::unicode::utf16);
|
||||
return load(file, nana::unicode::utf16);
|
||||
}
|
||||
}
|
||||
else if(0xFE == ch)
|
||||
@ -107,7 +104,7 @@ namespace skeletons
|
||||
{
|
||||
//UTF16(big-endian)
|
||||
ifs.close();
|
||||
return load(file_utf8, nana::unicode::utf16);
|
||||
return load(file, nana::unicode::utf16);
|
||||
}
|
||||
}
|
||||
else if(0 == ch)
|
||||
@ -119,7 +116,7 @@ namespace skeletons
|
||||
{
|
||||
//UTF32(big_endian)
|
||||
ifs.close();
|
||||
return load(file_utf8, nana::unicode::utf32);
|
||||
return load(file, nana::unicode::utf32);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -135,15 +132,15 @@ namespace skeletons
|
||||
while(ifs.good())
|
||||
{
|
||||
std::getline(ifs, str_mbs);
|
||||
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str_mbs })));
|
||||
if(text_cont_.back()->size() > attr_max_.size)
|
||||
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str_mbs }));
|
||||
if (text_cont_.back().size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = text_cont_.back()->size();
|
||||
attr_max_.size = text_cont_.back().size();
|
||||
attr_max_.line = text_cont_.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
_m_saved(file_utf8);
|
||||
_m_saved(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -175,12 +172,9 @@ namespace skeletons
|
||||
}
|
||||
}
|
||||
|
||||
bool load(const char* file_utf8, nana::unicode encoding)
|
||||
bool load(const path_type& file, nana::unicode encoding)
|
||||
{
|
||||
if (!file_utf8)
|
||||
return false;
|
||||
|
||||
std::ifstream ifs(to_osmbstr(file_utf8));
|
||||
std::ifstream ifs{ file.string() };
|
||||
|
||||
if (!ifs)
|
||||
return false;
|
||||
@ -218,9 +212,8 @@ namespace skeletons
|
||||
byte_order_translate_4bytes(str);
|
||||
}
|
||||
|
||||
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str, encoding })));
|
||||
|
||||
attr_max_.size = text_cont_.back()->size();
|
||||
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str, encoding }));
|
||||
attr_max_.size = text_cont_.back().size();
|
||||
attr_max_.line = 0;
|
||||
}
|
||||
|
||||
@ -236,21 +229,21 @@ namespace skeletons
|
||||
byte_order_translate_4bytes(str);
|
||||
}
|
||||
|
||||
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str, encoding })));
|
||||
if(text_cont_.back()->size() > attr_max_.size)
|
||||
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str, encoding }));
|
||||
if (text_cont_.back().size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = text_cont_.back()->size();
|
||||
attr_max_.size = text_cont_.back().size();
|
||||
attr_max_.line = text_cont_.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
_m_saved(file_utf8);
|
||||
_m_saved(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
void store(std::string fs, bool is_unicode, ::nana::unicode encoding) const
|
||||
void store(const path_type& filename, bool is_unicode, ::nana::unicode encoding) const
|
||||
{
|
||||
std::ofstream ofs(to_osmbstr(fs), std::ios::binary);
|
||||
std::ofstream ofs(filename.string(), std::ios::binary);
|
||||
if(ofs && text_cont_.size())
|
||||
{
|
||||
auto i = text_cont_.cbegin();
|
||||
@ -277,27 +270,26 @@ namespace skeletons
|
||||
|
||||
for (std::size_t pos = 0; pos < count; ++pos)
|
||||
{
|
||||
auto mbs = nana::charset(**(i++)).to_bytes(encoding);
|
||||
auto mbs = nana::charset(*(i++)).to_bytes(encoding);
|
||||
ofs.write(mbs.c_str(), static_cast<std::streamsize>(mbs.size()));
|
||||
ofs.write("\r\n", 2);
|
||||
}
|
||||
|
||||
last_mbs = nana::charset(*text_cont_.back()).to_bytes(encoding);
|
||||
last_mbs = nana::charset(text_cont_.back()).to_bytes(encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t pos = 0; pos < count; ++pos)
|
||||
{
|
||||
std::string mbs = nana::charset(**(i++));
|
||||
std::string mbs = nana::charset(*(i++));
|
||||
ofs.write(mbs.c_str(), mbs.size());
|
||||
ofs.write("\r\n", 2);
|
||||
}
|
||||
|
||||
last_mbs = nana::charset(*text_cont_.back());
|
||||
last_mbs = nana::charset(text_cont_.back());
|
||||
}
|
||||
|
||||
ofs.write(last_mbs.c_str(), static_cast<std::streamsize>(last_mbs.size()));
|
||||
_m_saved(std::move(fs));
|
||||
_m_saved(filename);
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +303,7 @@ namespace skeletons
|
||||
{
|
||||
if (!changed_)
|
||||
{
|
||||
_m_first_change();
|
||||
_m_emit_first_change();
|
||||
changed_ = true;
|
||||
}
|
||||
|
||||
@ -332,8 +324,7 @@ namespace skeletons
|
||||
const string_type& getline(size_type pos) const
|
||||
{
|
||||
if (pos < text_cont_.size())
|
||||
return *text_cont_[pos];
|
||||
|
||||
return text_cont_[pos];
|
||||
return nullstr_;
|
||||
}
|
||||
|
||||
@ -346,7 +337,7 @@ namespace skeletons
|
||||
{
|
||||
if (text_cont_.size() <= pos)
|
||||
{
|
||||
text_cont_.emplace_back(new string_type(std::move(text)));
|
||||
text_cont_.emplace_back(std::move(text));
|
||||
pos = text_cont_.size() - 1;
|
||||
}
|
||||
else
|
||||
@ -369,7 +360,7 @@ namespace skeletons
|
||||
}
|
||||
else
|
||||
{
|
||||
text_cont_.emplace_back(new string_type(std::move(str)));
|
||||
text_cont_.emplace_back(std::move(str));
|
||||
pos.y = static_cast<unsigned>(text_cont_.size() - 1);
|
||||
}
|
||||
|
||||
@ -380,9 +371,9 @@ namespace skeletons
|
||||
void insertln(size_type pos, string_type&& str)
|
||||
{
|
||||
if (pos < text_cont_.size())
|
||||
text_cont_.emplace(_m_iat(pos), new string_type(std::move(str)));
|
||||
text_cont_.emplace(_m_iat(pos), std::move(str));
|
||||
else
|
||||
text_cont_.emplace_back(new string_type(std::move(str)));
|
||||
text_cont_.emplace_back(std::move(str));
|
||||
|
||||
_m_make_max(pos);
|
||||
edited_ = true;
|
||||
@ -429,9 +420,9 @@ namespace skeletons
|
||||
{
|
||||
text_cont_.clear();
|
||||
attr_max_.reset();
|
||||
text_cont_.emplace_back(new string_type); //text_cont_ must not be empty
|
||||
text_cont_.emplace_back(); //text_cont_ must not be empty
|
||||
|
||||
_m_saved(std::string());
|
||||
_m_saved({});
|
||||
}
|
||||
|
||||
void merge(size_type pos)
|
||||
@ -439,7 +430,8 @@ namespace skeletons
|
||||
if(pos + 1 < text_cont_.size())
|
||||
{
|
||||
auto i = _m_iat(pos + 1);
|
||||
_m_at(pos) += **i;
|
||||
_m_at(pos) += *i;
|
||||
|
||||
text_cont_.erase(i);
|
||||
_m_make_max(pos);
|
||||
|
||||
@ -453,7 +445,7 @@ namespace skeletons
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& filename() const
|
||||
const path_type& filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
@ -463,33 +455,25 @@ namespace skeletons
|
||||
return changed_;
|
||||
}
|
||||
|
||||
void edited_reset()
|
||||
void reset_status(bool remain_saved_filename)
|
||||
{
|
||||
changed_ = false;
|
||||
}
|
||||
if(!remain_saved_filename)
|
||||
filename_.clear();
|
||||
|
||||
void reset()
|
||||
{
|
||||
filename_.clear();
|
||||
changed_ = false;
|
||||
}
|
||||
|
||||
bool saved() const
|
||||
{
|
||||
return ! not_saved();
|
||||
}
|
||||
|
||||
bool not_saved() const
|
||||
{
|
||||
return edited() || filename_.empty();
|
||||
return !(changed_ || filename_.empty());
|
||||
}
|
||||
private:
|
||||
string_type& _m_at(size_type pos)
|
||||
{
|
||||
return **_m_iat(pos);
|
||||
return *_m_iat(pos);
|
||||
}
|
||||
|
||||
typename std::deque<std::unique_ptr<string_type>>::iterator _m_iat(size_type pos)
|
||||
typename std::deque<string_type>::iterator _m_iat(size_type pos)
|
||||
{
|
||||
return text_cont_.begin() + pos;
|
||||
}
|
||||
@ -506,50 +490,40 @@ namespace skeletons
|
||||
|
||||
void _m_scan_for_max()
|
||||
{
|
||||
attr_max_.size = 0;
|
||||
std::size_t n = 0;
|
||||
for(auto & p : text_cont_)
|
||||
{
|
||||
if(p->size() > attr_max_.size)
|
||||
{
|
||||
attr_max_.size = p->size();
|
||||
attr_max_.line = n;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
attr_max_.reset();
|
||||
for (std::size_t i = 0; i < text_cont_.size(); ++i)
|
||||
_m_make_max(i);
|
||||
}
|
||||
|
||||
void _m_first_change() const
|
||||
void _m_emit_first_change() const
|
||||
{
|
||||
if (evt_agent_)
|
||||
evt_agent_->first_change();
|
||||
}
|
||||
|
||||
void _m_saved(std::string && filename) const
|
||||
void _m_saved(const path_type& filename) const
|
||||
{
|
||||
if(filename_ != filename)
|
||||
if((filename_ != filename) || changed_)
|
||||
{
|
||||
filename_ = std::move(filename);
|
||||
_m_first_change();
|
||||
filename_ = filename;
|
||||
_m_emit_first_change();
|
||||
}
|
||||
else if(changed_)
|
||||
_m_first_change();
|
||||
|
||||
changed_ = false;
|
||||
}
|
||||
private:
|
||||
std::deque<std::unique_ptr<string_type>> text_cont_;
|
||||
std::deque<string_type> text_cont_;
|
||||
textbase_event_agent_interface* evt_agent_{ nullptr };
|
||||
|
||||
mutable bool changed_{ false };
|
||||
mutable bool edited_{ false };
|
||||
mutable std::string filename_; //A string for the saved filename.
|
||||
mutable path_type filename_; ///< The saved filename
|
||||
const string_type nullstr_;
|
||||
|
||||
struct attr_max
|
||||
{
|
||||
std::size_t line;
|
||||
std::size_t size;
|
||||
std::size_t line; ///< The line number of max line
|
||||
std::size_t size; ///< The number of characters in max line
|
||||
|
||||
void reset()
|
||||
{
|
||||
|
||||
@ -151,7 +151,13 @@ namespace nana
|
||||
bool vertical() const;
|
||||
void maximum(unsigned);
|
||||
unsigned maximum() const;
|
||||
void value(unsigned);
|
||||
|
||||
/** Set slider value
|
||||
@param[in] v new value for slider.
|
||||
v will be clipped to the range 0 to maximum
|
||||
*/
|
||||
void value(int );
|
||||
|
||||
unsigned value() const;
|
||||
unsigned move_step(bool forward); ///< Increase or decrease the value of slider.
|
||||
unsigned adorn() const;
|
||||
|
||||
@ -29,17 +29,56 @@ namespace nana
|
||||
{
|
||||
tabbar<T> & widget;
|
||||
T & value;
|
||||
std::size_t item_pos; ///< position of the item
|
||||
|
||||
arg_tabbar(tabbar<T>& wdg, T& v)
|
||||
: widget(wdg), value{ v }
|
||||
arg_tabbar(tabbar<T>& wdg, T& v, std::size_t p)
|
||||
: widget(wdg), value{ v }, item_pos(p)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct arg_tabbar_click : public arg_tabbar<T>
|
||||
{
|
||||
arg_tabbar_click(tabbar<T>& wdg, T& v, std::size_t p)
|
||||
: arg_tabbar<T>({wdg, v, p})
|
||||
{}
|
||||
|
||||
bool left_button = false; ///< true if mouse left button is pressed
|
||||
bool mid_button = false; ///< true if mouse middle button is pressed
|
||||
bool right_button = false; ///< true if mouse right button is pressed
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct arg_tabbar_mouse
|
||||
: public arg_mouse
|
||||
{
|
||||
arg_tabbar_mouse(const arg_mouse& arg, tabbar<T>& wdg, T& v, std::size_t p)
|
||||
: arg_mouse{ arg }, widget(wdg), value{ v }, item_pos(p)
|
||||
{}
|
||||
|
||||
tabbar<T> & widget;
|
||||
T & value;
|
||||
std::size_t item_pos; ///< position of the item
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct arg_tabbar_adding
|
||||
: public event_arg
|
||||
{
|
||||
arg_tabbar_adding(tabbar<T>& wdg, std::size_t p)
|
||||
: widget(wdg), where(p)
|
||||
{}
|
||||
|
||||
tabbar<T> & widget;
|
||||
mutable bool add = true; ///< determines whether to add the item
|
||||
std::size_t where; ///< position where to add the item
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct arg_tabbar_removed : public arg_tabbar<T>
|
||||
{
|
||||
arg_tabbar_removed(tabbar<T>& wdg, T& v)
|
||||
: arg_tabbar<T>({wdg, v})
|
||||
arg_tabbar_removed(tabbar<T>& wdg, T& v, std::size_t p)
|
||||
: arg_tabbar<T>({wdg, v, p})
|
||||
{}
|
||||
|
||||
mutable bool remove = true; ///< determines whether to remove the item
|
||||
@ -56,7 +95,9 @@ namespace nana
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
basic_event<arg_tabbar_adding<value_type>> adding;
|
||||
basic_event<arg_tabbar<value_type>> added;
|
||||
basic_event<arg_tabbar_mouse<value_type>> tab_click;
|
||||
basic_event<arg_tabbar<value_type>> activated;
|
||||
basic_event<arg_tabbar_removed<value_type>> removed;
|
||||
};
|
||||
@ -65,7 +106,9 @@ namespace nana
|
||||
{
|
||||
public:
|
||||
virtual ~event_agent_interface() = default;
|
||||
virtual bool adding(std::size_t) = 0;
|
||||
virtual void added(std::size_t) = 0;
|
||||
virtual bool click(const arg_mouse&, std::size_t) = 0;
|
||||
virtual void activated(std::size_t) = 0;
|
||||
virtual bool removed(std::size_t, bool & close_attached) = 0;
|
||||
};
|
||||
@ -107,26 +150,40 @@ namespace nana
|
||||
: tabbar_(tb), drawer_trigger_(dtr)
|
||||
{}
|
||||
|
||||
bool adding(std::size_t pos) override
|
||||
{
|
||||
::nana::arg_tabbar_adding<T> arg_ta(tabbar_, pos);
|
||||
tabbar_.events().adding.emit(arg_ta, tabbar_);
|
||||
return arg_ta.add;
|
||||
}
|
||||
|
||||
void added(std::size_t pos) override
|
||||
{
|
||||
if(pos != npos)
|
||||
{
|
||||
drawer_trigger_.at_no_bound_check(pos) = T();
|
||||
tabbar_.events().added.emit(arg_tabbar({ tabbar_, tabbar_[pos] }), tabbar_);
|
||||
tabbar_.events().added.emit(arg_tabbar({ tabbar_, tabbar_[pos], pos }), tabbar_);
|
||||
}
|
||||
}
|
||||
|
||||
bool click(const arg_mouse& arg, std::size_t pos) override
|
||||
{
|
||||
::nana::arg_tabbar_mouse<T> arg_tm(arg, tabbar_, tabbar_[pos], pos);
|
||||
tabbar_.events().tab_click.emit(arg_tm, tabbar_);
|
||||
return arg_tm.propagation_stopped();
|
||||
}
|
||||
|
||||
void activated(std::size_t pos) override
|
||||
{
|
||||
if(pos != npos)
|
||||
tabbar_.events().activated.emit(arg_tabbar({ tabbar_, tabbar_[pos]}), tabbar_);
|
||||
tabbar_.events().activated.emit(arg_tabbar({ tabbar_, tabbar_[pos], pos}), tabbar_);
|
||||
}
|
||||
|
||||
bool removed(std::size_t pos, bool & close_attach) override
|
||||
{
|
||||
if (pos != npos)
|
||||
if(pos != npos)
|
||||
{
|
||||
::nana::arg_tabbar_removed<T> arg(tabbar_, tabbar_[pos]);
|
||||
::nana::arg_tabbar_removed<T> arg(tabbar_, tabbar_[pos], pos);
|
||||
tabbar_.events().removed.emit(arg, tabbar_);
|
||||
close_attach = arg.close_attach_window;
|
||||
return arg.remove;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Textbox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -109,6 +109,8 @@ namespace nana
|
||||
using text_focus_behavior = widgets::skeletons::text_focus_behavior;
|
||||
using text_positions = std::vector<upoint>;
|
||||
|
||||
using path_type = std::filesystem::path;
|
||||
|
||||
/// The default constructor without creating the widget.
|
||||
textbox();
|
||||
|
||||
@ -136,9 +138,9 @@ namespace nana
|
||||
textbox(window, const rectangle& = rectangle(), bool visible = true);
|
||||
|
||||
/// \brief Loads a text file. When attempt to load a unicode encoded text file, be sure the file have a BOM header.
|
||||
void load(std::string file);
|
||||
void store(std::string file);
|
||||
void store(std::string file, nana::unicode encoding);
|
||||
void load(const path_type& file);
|
||||
void store(const path_type& file);
|
||||
void store(const path_type& file, nana::unicode encoding);
|
||||
|
||||
colored_area_access_interface* colored_area_access();
|
||||
|
||||
@ -158,7 +160,7 @@ namespace nana
|
||||
textbox& reset(const std::string& text = std::string(), bool end_caret = true); ///< discard the old text and set a new text
|
||||
|
||||
/// The file of last store operation.
|
||||
std::string filename() const;
|
||||
path_type filename() const;
|
||||
|
||||
/// Determine whether the text was edited.
|
||||
bool edited() const;
|
||||
@ -224,6 +226,8 @@ namespace nana
|
||||
/// Selects/unselects all text.
|
||||
void select(bool);
|
||||
|
||||
void select_points(nana::upoint arg_a, nana::upoint arg_b);
|
||||
|
||||
/// Returns the bounds of a text selection
|
||||
/**
|
||||
* @return no selection if pair.first == pair.second.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Tree Box Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE or copy at
|
||||
@ -60,8 +60,26 @@ namespace nana
|
||||
::std::string text;
|
||||
};
|
||||
|
||||
struct scheme
|
||||
: public widget_geometrics
|
||||
{
|
||||
color_proxy item_bg_selected{ static_cast<color_rgb>(0xD5EFFC) }; ///< item selected: background color
|
||||
color_proxy item_fg_selected{ static_cast<color_rgb>(0x99DEFD) }; ///< item selected: foreground color
|
||||
color_proxy item_bg_highlighted{ static_cast<color_rgb>(0xE8F5FD) }; ///< item highlighted: background color
|
||||
color_proxy item_fg_highlighted{ static_cast<color_rgb>(0xD8F0FA) }; ///< item highlighted: foreground color
|
||||
color_proxy item_bg_selected_and_highlighted{ static_cast<color_rgb>(0xC4E8FA) }; ///< item selected and highlighted: background color
|
||||
color_proxy item_fg_selected_and_highlighted{ static_cast<color_rgb>(0xB6E6FB) }; ///< item selected and highlighted: foreground color
|
||||
|
||||
unsigned item_offset{ 16 }; ///< item position displacement in pixels
|
||||
unsigned text_offset{ 4 }; ///< text position displacement in pixels
|
||||
unsigned icon_size{ 16 }; ///< icon size in pixels
|
||||
unsigned crook_size{ 16 }; ///< crook size in pixels (TODO: the function that draw the crook doesn't scale the shape)
|
||||
|
||||
unsigned indent_displacement{ 18 }; ///< children position displacement in pixels (def=18 (before was 10))
|
||||
};
|
||||
|
||||
typedef widgets::detail::compset<component, node_attribute> compset_interface;
|
||||
typedef widgets::detail::compset_placer<component, node_attribute> compset_placer_interface;
|
||||
typedef widgets::detail::compset_placer<component, node_attribute, scheme> compset_placer_interface;
|
||||
|
||||
class renderer_interface
|
||||
{
|
||||
@ -87,13 +105,8 @@ namespace nana
|
||||
class trigger
|
||||
:public drawer_trigger
|
||||
{
|
||||
template<typename Renderer>
|
||||
struct basic_implement;
|
||||
|
||||
class item_renderer;
|
||||
class implementation;
|
||||
class item_locator;
|
||||
|
||||
typedef basic_implement<item_renderer> implement;
|
||||
public:
|
||||
struct treebox_node_type
|
||||
{
|
||||
@ -116,27 +129,25 @@ namespace nana
|
||||
trigger();
|
||||
~trigger();
|
||||
|
||||
implement * impl() const;
|
||||
implementation * impl() const;
|
||||
|
||||
void check(node_type*, checkstate);
|
||||
|
||||
void renderer(::nana::pat::cloneable<renderer_interface>&&);
|
||||
const ::nana::pat::cloneable<renderer_interface>& renderer() const;
|
||||
pat::cloneable<renderer_interface>& renderer() const;
|
||||
|
||||
void placer(::nana::pat::cloneable<compset_placer_interface>&&);
|
||||
const ::nana::pat::cloneable<compset_placer_interface>& placer() const;
|
||||
|
||||
node_type* insert(node_type*, const std::string& key, std::string&&);
|
||||
node_type* insert(const std::string& path, std::string&&);
|
||||
|
||||
node_type * selected() const;
|
||||
void selected(node_type*);
|
||||
|
||||
node_image_tag& icon(const ::std::string&) const;
|
||||
node_image_tag& icon(const ::std::string&);
|
||||
void icon_erase(const ::std::string&);
|
||||
void node_icon(node_type*, const ::std::string& id);
|
||||
unsigned node_width(const node_type*) const;
|
||||
|
||||
bool rename(node_type*, const char* key, const char* name);
|
||||
|
||||
private:
|
||||
//Overrides drawer_trigger methods
|
||||
void attached(widget_reference, graph_reference) override;
|
||||
@ -152,7 +163,7 @@ namespace nana
|
||||
void key_press(graph_reference, const arg_keyboard&) override;
|
||||
void key_char(graph_reference, const arg_keyboard&) override;
|
||||
private:
|
||||
implement * const impl_;
|
||||
implementation * const impl_;
|
||||
}; //end class trigger
|
||||
|
||||
|
||||
@ -171,11 +182,11 @@ namespace nana
|
||||
|
||||
/// Append a child with a specified value (user object.).
|
||||
template<typename T>
|
||||
item_proxy append(const ::std::string& key, ::std::string name, const T&t)
|
||||
item_proxy append(const ::std::string& key, ::std::string name, T&& t)
|
||||
{
|
||||
item_proxy ip = append(key, std::move(name));
|
||||
if(false == ip.empty())
|
||||
ip.value(t);
|
||||
ip.value(std::forward<T>(t));
|
||||
return ip;
|
||||
}
|
||||
|
||||
@ -291,17 +302,10 @@ namespace nana
|
||||
return *p;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
item_proxy & value(const T& t)
|
||||
{
|
||||
_m_value() = t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
item_proxy & value(T&& t)
|
||||
{
|
||||
_m_value() = std::move(t);
|
||||
_m_value() = std::forward<T>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -346,7 +350,7 @@ namespace nana
|
||||
/// \brief Displays a hierarchical list of items, such as the files and directories on a disk.
|
||||
/// See also in [documentation](http://nanapro.org/en-us/documentation/widgets/treebox.htm)
|
||||
class treebox
|
||||
:public widget_object < category::widget_tag, drawerbase::treebox::trigger, drawerbase::treebox::treebox_events>
|
||||
:public widget_object <category::widget_tag, drawerbase::treebox::trigger, drawerbase::treebox::treebox_events, drawerbase::treebox::scheme>
|
||||
{
|
||||
public:
|
||||
/// A type refers to the item and is also used to iterate through the nodes.
|
||||
@ -378,7 +382,7 @@ namespace nana
|
||||
template<typename ItemRenderer>
|
||||
treebox & renderer(const ItemRenderer & rd) ///< set user-defined node renderer
|
||||
{
|
||||
get_drawer_trigger().renderer(::nana::pat::cloneable<renderer_interface>(rd));
|
||||
get_drawer_trigger().renderer() = ::nana::pat::cloneable<renderer_interface>{rd};
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -403,6 +407,23 @@ namespace nana
|
||||
/// @param enable bool whether to enable.
|
||||
void auto_draw(bool enable);
|
||||
|
||||
/// Prevents drawing during execution.
|
||||
template<typename Function>
|
||||
void avoid_drawing(Function fn)
|
||||
{
|
||||
this->auto_draw(false);
|
||||
try
|
||||
{
|
||||
fn();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
this->auto_draw(true);
|
||||
throw;
|
||||
}
|
||||
this->auto_draw(true);
|
||||
}
|
||||
|
||||
/// \brief Enable the checkboxs for each item of the widget.
|
||||
/// @param enable bool indicates whether to show or hide the checkboxs.
|
||||
treebox & checkable(bool enable);
|
||||
@ -419,8 +440,9 @@ namespace nana
|
||||
/// These states are 'normal', 'hovered' and 'expanded'.
|
||||
/// If 'hovered' or 'expanded' are not set, it uses 'normal' state image for these 2 states.
|
||||
/// See also in [documentation](http://nanapro.org/en-us/help/widgets/treebox.htm)
|
||||
node_image_type& icon(const ::std::string& id ///< the name of an icon scheme. If the name is not existing, it creates a new scheme for the name.
|
||||
) const;
|
||||
/// @param id The name of an icon scheme. If the name is not existing, it creates a new scheme for the name.
|
||||
/// @return The reference of node image scheme correspending with the specified id.
|
||||
node_image_type& icon(const ::std::string& id);
|
||||
|
||||
void icon_erase(const ::std::string& id);
|
||||
|
||||
@ -445,6 +467,19 @@ namespace nana
|
||||
|
||||
item_proxy selected() const; ///< returns the selected node
|
||||
|
||||
/// Scrolls a specified item into view.
|
||||
/**
|
||||
* @param item An item to be requested.
|
||||
* @param bearing The position where the item to be positioned in the view.
|
||||
*/
|
||||
void scroll_into_view(item_proxy item, align_v bearing);
|
||||
|
||||
/// Scrolls a specified item into view.
|
||||
/**
|
||||
* @param item An item to be requested.
|
||||
*/
|
||||
void scroll_into_view(item_proxy item);
|
||||
|
||||
private:
|
||||
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* The fundamental widget class implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -499,72 +499,6 @@ namespace nana
|
||||
std::unique_ptr<scheme_type> scheme_;
|
||||
};//end class widget_object<root_tag>
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
/// Base class of all the classes defined as a frame window. \see nana::frame
|
||||
template<typename Drawer, typename Events, typename Scheme>
|
||||
class widget_object<category::frame_tag, Drawer, Events, Scheme>: public widget{};
|
||||
|
||||
/// Especialization. Base class of all the classes defined as a frame window. \see nana::frame
|
||||
template<typename Events, typename Scheme>
|
||||
class widget_object<category::frame_tag, int, Events, Scheme>: public detail::widget_base
|
||||
{
|
||||
protected:
|
||||
typedef int drawer_trigger_t;
|
||||
public:
|
||||
using scheme_type = Scheme;
|
||||
using event_type = Events;
|
||||
|
||||
widget_object()
|
||||
: events_{ std::make_shared<Events>() }, scheme_{ API::dev::make_scheme<scheme_type>() }
|
||||
{}
|
||||
|
||||
~widget_object()
|
||||
{
|
||||
API::close_window(handle());
|
||||
}
|
||||
|
||||
event_type& events() const
|
||||
{
|
||||
return *events_;
|
||||
}
|
||||
|
||||
bool create(window parent_wd, bool visible) ///< Creates a no-size (zero-size) widget. in a widget/root window specified by parent_wd.
|
||||
{
|
||||
return create(parent_wd, rectangle(), visible);
|
||||
}
|
||||
/// Creates in a widget/root window specified by parent_wd.
|
||||
bool create(window parent_wd, const rectangle& r = rectangle(), bool visible = true)
|
||||
{
|
||||
if(parent_wd && this->empty())
|
||||
{
|
||||
handle_ = API::dev::create_frame(parent_wd, r, this);
|
||||
API::dev::set_events(handle_, events_);
|
||||
API::dev::set_scheme(handle_, scheme_.get());
|
||||
API::show_window(handle_, visible);
|
||||
this->_m_complete_creation();
|
||||
}
|
||||
return (this->empty() == false);
|
||||
}
|
||||
|
||||
scheme_type& scheme() const
|
||||
{
|
||||
return *scheme_;
|
||||
}
|
||||
private:
|
||||
virtual drawer_trigger* get_drawer_trigger()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
general_events& _m_get_general_events() const override
|
||||
{
|
||||
return *events_;
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<Events> events_;
|
||||
std::unique_ptr<scheme_type> scheme_;
|
||||
};//end class widget_object<category::frame_tag>
|
||||
#endif
|
||||
}//end namespace nana
|
||||
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
@ -16,7 +16,7 @@ namespace nana{ namespace paint{
|
||||
public:
|
||||
using graph_reference = nana::paint::graphics&;
|
||||
virtual ~image_impl_interface() = 0; //The destructor is defined in ../image.cpp
|
||||
virtual bool open(const std::experimental::filesystem::path& file) = 0;
|
||||
virtual bool open(const std::filesystem::path& file) = 0;
|
||||
virtual bool open(const void* data, std::size_t bytes) = 0; // reads image from memory
|
||||
virtual bool alpha_channel() const = 0;
|
||||
virtual bool empty() const = 0;
|
||||
|
||||
@ -33,7 +33,7 @@ namespace nana
|
||||
{
|
||||
friend class graphics;
|
||||
public:
|
||||
using path_type = ::std::experimental::filesystem::path;
|
||||
using path_type = ::std::filesystem::path;
|
||||
|
||||
using font_style = ::nana::detail::font_style;
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
|
||||
namespace {
|
||||
std::tm localtime()
|
||||
@ -239,18 +240,20 @@ namespace nana
|
||||
return days + d;
|
||||
}
|
||||
|
||||
unsigned date::month_days(unsigned year, unsigned month)
|
||||
unsigned date::month_days(const unsigned year, const unsigned month)
|
||||
{
|
||||
unsigned num[] = {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
if(month != 2)
|
||||
return num[month - 1];
|
||||
if (month != 2)
|
||||
{
|
||||
constexpr std::array<unsigned, 12> days_in_month = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
return days_in_month[month - 1];
|
||||
}
|
||||
|
||||
if(((year % 4 == 0) && (year % 100)) || (year % 400 == 0))
|
||||
return 29;
|
||||
return 28;
|
||||
}
|
||||
|
||||
unsigned date::year_days(unsigned year)
|
||||
unsigned date::year_days(const unsigned year)
|
||||
{
|
||||
if(((year % 4 == 0) && (year % 100)) || (year % 400 == 0))
|
||||
return 366;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Platform Specification Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,7 +7,7 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/detail/platform_spec.hpp
|
||||
* @file nana/detail/platform_spec.hpp
|
||||
*
|
||||
* This file provides basis class and data structrue that required by nana
|
||||
* This file should not be included by any header files.
|
||||
|
||||
@ -158,7 +158,7 @@ namespace nana
|
||||
: public font_interface
|
||||
{
|
||||
public:
|
||||
using path_type = std::experimental::filesystem::path;
|
||||
using path_type = std::filesystem::path;
|
||||
|
||||
internal_font(const path_type& ttf, const std::string& font_family, double font_size, const font_style& fs, native_font_type native_font):
|
||||
ttf_(ttf),
|
||||
|
||||
@ -28,7 +28,7 @@ namespace nana
|
||||
public:
|
||||
using font = font_interface;
|
||||
|
||||
using path_type = ::std::experimental::filesystem::path;
|
||||
using path_type = ::std::filesystem::path;
|
||||
|
||||
static void initialize();
|
||||
/// Shutdown before destruction of platform_spec
|
||||
|
||||
@ -500,20 +500,23 @@ namespace detail
|
||||
atombase_.net_wm_window_type_dialog = ::XInternAtom(display_, "_NET_WM_WINDOW_TYPE_DIALOG", False);
|
||||
atombase_.motif_wm_hints = ::XInternAtom(display_, "_MOTIF_WM_HINTS", False);
|
||||
|
||||
atombase_.clipboard = ::XInternAtom(display_, "CLIPBOARD", True);
|
||||
atombase_.text = ::XInternAtom(display_, "TEXT", True);
|
||||
atombase_.text_uri_list = ::XInternAtom(display_, "text/uri-list", True);
|
||||
atombase_.utf8_string = ::XInternAtom(display_, "UTF8_STRING", True);
|
||||
atombase_.targets = ::XInternAtom(display_, "TARGETS", True);
|
||||
atombase_.clipboard = ::XInternAtom(display_, "CLIPBOARD", False);
|
||||
atombase_.text = ::XInternAtom(display_, "TEXT", False);
|
||||
atombase_.text_uri_list = ::XInternAtom(display_, "text/uri-list", False);
|
||||
atombase_.utf8_string = ::XInternAtom(display_, "UTF8_STRING", False);
|
||||
atombase_.targets = ::XInternAtom(display_, "TARGETS", False);
|
||||
|
||||
atombase_.xdnd_aware = ::XInternAtom(display_, "XdndAware", False);
|
||||
atombase_.xdnd_enter = ::XInternAtom(display_, "XdndEnter", False);
|
||||
atombase_.xdnd_position = ::XInternAtom(display_, "XdndPosition", False);
|
||||
atombase_.xdnd_status = ::XInternAtom(display_, "XdndStatus", False);
|
||||
atombase_.xdnd_action_copy = ::XInternAtom(display_, "XdndActionCopy", False);
|
||||
atombase_.xdnd_action_move = ::XInternAtom(display_, "XdndActionMove", False);
|
||||
atombase_.xdnd_action_link = ::XInternAtom(display_, "XdndActionLink", False);
|
||||
atombase_.xdnd_drop = ::XInternAtom(display_, "XdndDrop", False);
|
||||
atombase_.xdnd_selection = ::XInternAtom(display_, "XdndSelection", False);
|
||||
atombase_.xdnd_typelist = ::XInternAtom(display_, "XdndTypeList", False);
|
||||
atombase_.xdnd_leave = ::XInternAtom(display_, "XdndLeave", False);
|
||||
atombase_.xdnd_finished = ::XInternAtom(display_, "XdndFinished", False);
|
||||
|
||||
msg_dispatcher_ = new msg_dispatcher(display_);
|
||||
@ -658,21 +661,31 @@ namespace detail
|
||||
platform_scope_guard lock;
|
||||
if(umake_owner(wd))
|
||||
{
|
||||
auto & wd_manager = detail::bedrock::instance().wd_manager();
|
||||
|
||||
std::vector<native_window_type> owned_children;
|
||||
|
||||
auto i = wincontext_.find(wd);
|
||||
if(i != wincontext_.end())
|
||||
{
|
||||
if(i->second.owned)
|
||||
{
|
||||
set_error_handler();
|
||||
auto & wd_manager = detail::bedrock::instance().wd_manager();
|
||||
for(auto u = i->second.owned->rbegin(); u != i->second.owned->rend(); ++u)
|
||||
wd_manager.close(wd_manager.root(*u));
|
||||
|
||||
rev_error_handler();
|
||||
|
||||
delete i->second.owned;
|
||||
for(auto child : *i->second.owned)
|
||||
owned_children.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
//Closing a child will erase the wd from the table wincontext_, so the
|
||||
//iterator i can't be reused after children closed.
|
||||
set_error_handler();
|
||||
for(auto u = owned_children.rbegin(); u != owned_children.rend(); ++u)
|
||||
wd_manager.close(wd_manager.root(*u));
|
||||
rev_error_handler();
|
||||
|
||||
i = wincontext_.find(wd);
|
||||
if(i != wincontext_.end())
|
||||
{
|
||||
delete i->second.owned;
|
||||
wincontext_.erase(i);
|
||||
}
|
||||
}
|
||||
@ -1031,6 +1044,12 @@ namespace detail
|
||||
msg_dispatcher_->dispatch(reinterpret_cast<Window>(modal));
|
||||
}
|
||||
|
||||
void platform_spec::msg_dispatch(std::function<propagation_chain(const msg_packet_tag&)> msg_filter_fn)
|
||||
{
|
||||
msg_dispatcher_->dispatch(msg_filter_fn);
|
||||
|
||||
}
|
||||
|
||||
void* platform_spec::request_selection(native_window_type requestor, Atom type, size_t& size)
|
||||
{
|
||||
if(requestor)
|
||||
@ -1094,6 +1113,62 @@ namespace detail
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
bool platform_spec::register_dragdrop(native_window_type wd, x11_dragdrop_interface* ddrop)
|
||||
{
|
||||
platform_scope_guard lock;
|
||||
if(0 != xdnd_.dragdrop.count(wd))
|
||||
return false;
|
||||
|
||||
xdnd_.dragdrop[wd] = ddrop;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t platform_spec::dragdrop_target(native_window_type wd, bool insert, std::size_t count)
|
||||
{
|
||||
std::size_t new_val = 0;
|
||||
platform_scope_guard lock;
|
||||
if(insert)
|
||||
{
|
||||
new_val = (xdnd_.targets[wd] += count);
|
||||
if(1 == new_val)
|
||||
{
|
||||
int dndver = 5;
|
||||
::XChangeProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
|
||||
PropModeReplace, reinterpret_cast<unsigned char*>(&dndver), 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto i = xdnd_.targets.find(wd);
|
||||
if(i == xdnd_.targets.end())
|
||||
return 0;
|
||||
|
||||
new_val = (i->second > count ? i->second - count : 0);
|
||||
if(0 == new_val)
|
||||
{
|
||||
xdnd_.targets.erase(wd);
|
||||
::XDeleteProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware);
|
||||
}
|
||||
else
|
||||
i->second = new_val;
|
||||
}
|
||||
return new_val;
|
||||
}
|
||||
|
||||
x11_dragdrop_interface* platform_spec::remove_dragdrop(native_window_type wd)
|
||||
{
|
||||
platform_scope_guard lock;
|
||||
auto i = xdnd_.dragdrop.find(wd);
|
||||
if(i == xdnd_.dragdrop.end())
|
||||
return nullptr;
|
||||
|
||||
auto ddrop = i->second;
|
||||
xdnd_.dragdrop.erase(i);
|
||||
|
||||
return ddrop;
|
||||
}
|
||||
|
||||
//_m_msg_filter
|
||||
//@return: _m_msg_filter returns three states
|
||||
// 0 = msg_dispatcher dispatches the XEvent
|
||||
@ -1153,7 +1228,7 @@ namespace detail
|
||||
else if(evt.xselection.property == self.atombase_.xdnd_selection)
|
||||
{
|
||||
bool accepted = false;
|
||||
msg.kind = msg.kind_mouse_drop;
|
||||
msg.kind = msg_packet_tag::pkt_family::mouse_drop;
|
||||
msg.u.mouse_drop.window = 0;
|
||||
if(bytes_left > 0 && type == self.xdnd_.good_type)
|
||||
{
|
||||
@ -1163,8 +1238,9 @@ namespace detail
|
||||
0, AnyPropertyType, &type, &format, &len,
|
||||
&dummy_bytes_left, &data))
|
||||
{
|
||||
auto files = new std::vector<std::string>;
|
||||
auto files = new std::vector<std::filesystem::path>;
|
||||
std::stringstream ss(reinterpret_cast<char*>(data));
|
||||
|
||||
while(true)
|
||||
{
|
||||
std::string file;
|
||||
@ -1182,8 +1258,9 @@ namespace detail
|
||||
break;
|
||||
}
|
||||
|
||||
files->push_back(file);
|
||||
files->emplace_back(file);
|
||||
}
|
||||
|
||||
if(files->size())
|
||||
{
|
||||
msg.u.mouse_drop.window = evt.xselection.requestor;
|
||||
@ -1198,8 +1275,9 @@ namespace detail
|
||||
::XFree(data);
|
||||
}
|
||||
}
|
||||
XEvent respond;
|
||||
::XEvent respond;
|
||||
::memset(respond.xclient.data.l, 0, sizeof(respond.xclient.data.l));
|
||||
respond.xany.type = ClientMessage;
|
||||
respond.xclient.display = self.display_;
|
||||
respond.xclient.window = self.xdnd_.wd_src;
|
||||
respond.xclient.message_type = self.atombase_.xdnd_finished;
|
||||
@ -1222,6 +1300,10 @@ namespace detail
|
||||
}
|
||||
else if(SelectionRequest == evt.type)
|
||||
{
|
||||
//Skip if it is requested by XDND, it will be processed by dragdrop's xdnd_protocol
|
||||
if(self.atombase_.xdnd_selection == evt.xselectionrequest.selection)
|
||||
return 0;
|
||||
|
||||
auto disp = evt.xselectionrequest.display;
|
||||
XEvent respond;
|
||||
|
||||
@ -1286,24 +1368,56 @@ namespace detail
|
||||
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, self.atombase_.xdnd_typelist,
|
||||
0, bytes_left, False, XA_ATOM,
|
||||
&type, &format, &len, &bytes_left, &data);
|
||||
|
||||
if(XA_ATOM == type && len > 0)
|
||||
atoms = reinterpret_cast<const Atom*>(data);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEBUG_XdndDirectSave
|
||||
#ifdef DEBUG_XdndDirectSave
|
||||
Atom XdndDirectSave = 0;
|
||||
#endif
|
||||
self.xdnd_.good_type = None;
|
||||
for(unsigned long i = 0; i < len; ++i)
|
||||
{
|
||||
auto name = XGetAtomName(self.display_, atoms[i]); //debug
|
||||
if(name)
|
||||
{
|
||||
#ifdef DEBUG_XdndDirectSave
|
||||
if(strstr(name, "XdndDirectSave"))
|
||||
XdndDirectSave = atoms[i];
|
||||
#endif
|
||||
::XFree(name);
|
||||
}
|
||||
|
||||
if(atoms[i] == self.atombase_.text_uri_list)
|
||||
{
|
||||
self.xdnd_.good_type = self.atombase_.text_uri_list;
|
||||
break;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
if(data)
|
||||
::XFree(data);
|
||||
|
||||
#ifdef DEBUG_XdndDirectSave //debug
|
||||
if(XdndDirectSave)
|
||||
{
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long bytes_left;
|
||||
|
||||
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, XdndDirectSave, 0, 0, False, XA_ATOM, &type, &format, &len, &bytes_left, &data);
|
||||
|
||||
if(bytes_left > 0)
|
||||
{
|
||||
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, XdndDirectSave,
|
||||
0, bytes_left, False, type,
|
||||
&type, &format, &len, &bytes_left, &data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 2;
|
||||
}
|
||||
else if(self.atombase_.xdnd_position == evt.xclient.message_type)
|
||||
@ -1312,7 +1426,7 @@ namespace detail
|
||||
int x = (evt.xclient.data.l[2] >> 16);
|
||||
int y = (evt.xclient.data.l[2] & 0xFFFF);
|
||||
|
||||
bool accepted = false;
|
||||
int accepted = 0; //0 means refusing, 1 means accpeting
|
||||
//We have got the type what we want.
|
||||
if(self.xdnd_.good_type != None)
|
||||
{
|
||||
@ -1322,9 +1436,10 @@ namespace detail
|
||||
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos);
|
||||
if(wd && wd->flags.dropable)
|
||||
{
|
||||
accepted = true;
|
||||
//Cache the time stamp in XdndPosition, and the time stamp must be passed to XConvertSelection for requesting selection
|
||||
self.xdnd_.timestamp = evt.xclient.data.l[3];
|
||||
self.xdnd_.pos = wd->pos_root;
|
||||
accepted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1339,7 +1454,7 @@ namespace detail
|
||||
//Target window
|
||||
respond.xclient.data.l[0] = evt.xclient.window;
|
||||
//Accept set
|
||||
respond.xclient.data.l[1] = (accepted ? 1 : 0);
|
||||
respond.xclient.data.l[1] = accepted;
|
||||
respond.xclient.data.l[2] = 0;
|
||||
respond.xclient.data.l[3] = 0;
|
||||
respond.xclient.data.l[4] = self.atombase_.xdnd_action_copy;
|
||||
@ -1347,10 +1462,15 @@ namespace detail
|
||||
::XSendEvent(self.display_, wd_src, True, NoEventMask, &respond);
|
||||
return 2;
|
||||
}
|
||||
else if(self.atombase_.xdnd_status == evt.xclient.message_type)
|
||||
{
|
||||
//Platform Recv XdndStatus
|
||||
}
|
||||
else if(self.atombase_.xdnd_drop == evt.xclient.message_type)
|
||||
{
|
||||
::XConvertSelection(self.display_, self.atombase_.xdnd_selection, self.xdnd_.good_type, self.atombase_.xdnd_selection,
|
||||
evt.xclient.window, self.xdnd_.timestamp);
|
||||
|
||||
//The XdndDrop should send a XdndFinished to source window.
|
||||
//This operation is implemented in SelectionNotify, because
|
||||
//XdndFinished should be sent after retrieving data.
|
||||
|
||||
@ -143,7 +143,7 @@ namespace detail
|
||||
{
|
||||
//Make a cleanup msg packet to infor the dispatcher the window is closed.
|
||||
msg_packet_tag msg;
|
||||
msg.kind = msg.kind_cleanup;
|
||||
msg.kind = msg_packet_tag::pkt_family::cleanup;
|
||||
msg.u.packet_window = wd;
|
||||
thr->msg_queue.push_back(msg);
|
||||
}
|
||||
@ -171,6 +171,37 @@ namespace detail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MsgFilter>
|
||||
void dispatch(MsgFilter msg_filter_fn)
|
||||
{
|
||||
auto tid = nana::system::this_thread_id();
|
||||
msg_packet_tag msg;
|
||||
int qstate;
|
||||
|
||||
//Test whether the thread is registered for window, and retrieve the queue state for event
|
||||
while((qstate = _m_read_queue(tid, msg, 0)))
|
||||
{
|
||||
//the queue is empty
|
||||
if(-1 == qstate)
|
||||
{
|
||||
if(false == _m_wait_for_queue(tid))
|
||||
proc_.timer_proc(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(msg_filter_fn(msg))
|
||||
{
|
||||
case propagation_chain::exit:
|
||||
return;
|
||||
case propagation_chain::stop:
|
||||
break;
|
||||
case propagation_chain::pass:
|
||||
proc_.event_proc(display_, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
void _m_msg_driver()
|
||||
{
|
||||
@ -220,7 +251,7 @@ namespace detail
|
||||
switch(proc_.filter_proc(event, msg_pack))
|
||||
{
|
||||
case 0:
|
||||
msg_pack.kind = msg_pack.kind_xevent;
|
||||
msg_pack.kind = msg_packet_tag::pkt_family::xevent;
|
||||
msg_pack.u.xevent = event;
|
||||
_m_msg_dispatch(msg_pack);
|
||||
break;
|
||||
@ -246,9 +277,9 @@ namespace detail
|
||||
{
|
||||
switch(pack.kind)
|
||||
{
|
||||
case msg_packet_tag::kind_xevent:
|
||||
case msg_packet_tag::pkt_family::xevent:
|
||||
return _m_event_window(pack.u.xevent);
|
||||
case msg_packet_tag::kind_mouse_drop:
|
||||
case msg_packet_tag::pkt_family::mouse_drop:
|
||||
return pack.u.mouse_drop.window;
|
||||
default:
|
||||
break;
|
||||
@ -294,7 +325,7 @@ namespace detail
|
||||
//Check whether the event dispatcher is used for the modal window
|
||||
//and when the modal window is closing, the event dispatcher would
|
||||
//stop event pumping.
|
||||
if((modal == msg.u.packet_window) && (msg.kind == msg.kind_cleanup))
|
||||
if((modal == msg.u.packet_window) && (msg.kind == msg_packet_tag::pkt_family::cleanup))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
@ -3,15 +3,23 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <vector>
|
||||
#include <nana/deploy.hpp>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
enum class propagation_chain
|
||||
{
|
||||
exit, //Exit the chain
|
||||
stop, //Stop propagating
|
||||
pass //propagate
|
||||
};
|
||||
|
||||
struct msg_packet_tag
|
||||
{
|
||||
enum kind_t{kind_xevent, kind_mouse_drop, kind_cleanup};
|
||||
kind_t kind;
|
||||
enum class pkt_family{xevent, mouse_drop, cleanup};
|
||||
pkt_family kind;
|
||||
union
|
||||
{
|
||||
XEvent xevent;
|
||||
@ -22,7 +30,7 @@ namespace detail
|
||||
Window window;
|
||||
int x;
|
||||
int y;
|
||||
std::vector<std::string> * files;
|
||||
std::vector<std::filesystem::path> * files;
|
||||
}mouse_drop;
|
||||
}u;
|
||||
};
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include "msg_packet.hpp"
|
||||
#include "../platform_abstraction_types.hpp"
|
||||
|
||||
@ -158,9 +159,12 @@ namespace detail
|
||||
Atom xdnd_position;
|
||||
Atom xdnd_status;
|
||||
Atom xdnd_action_copy;
|
||||
Atom xdnd_action_move;
|
||||
Atom xdnd_action_link;
|
||||
Atom xdnd_drop;
|
||||
Atom xdnd_selection;
|
||||
Atom xdnd_typelist;
|
||||
Atom xdnd_leave;
|
||||
Atom xdnd_finished;
|
||||
};
|
||||
|
||||
@ -176,6 +180,15 @@ namespace detail
|
||||
~platform_scope_guard();
|
||||
};
|
||||
|
||||
class x11_dragdrop_interface
|
||||
{
|
||||
public:
|
||||
virtual ~x11_dragdrop_interface() = default;
|
||||
|
||||
virtual void add_ref() = 0;
|
||||
virtual std::size_t release() = 0;
|
||||
};
|
||||
|
||||
class platform_spec
|
||||
{
|
||||
typedef platform_spec self_type;
|
||||
@ -246,6 +259,7 @@ namespace detail
|
||||
void msg_insert(native_window_type);
|
||||
void msg_set(timer_proc_type, event_proc_type);
|
||||
void msg_dispatch(native_window_type modal);
|
||||
void msg_dispatch(std::function<propagation_chain(const msg_packet_tag&)>);
|
||||
|
||||
//X Selections
|
||||
void* request_selection(native_window_type requester, Atom type, size_t & bufsize);
|
||||
@ -255,6 +269,10 @@ namespace detail
|
||||
//@biref: The image object should be kept for a long time till the window is closed,
|
||||
// the image object is release in remove() method.
|
||||
const nana::paint::graphics& keep_window_icon(native_window_type, const nana::paint::image&);
|
||||
|
||||
bool register_dragdrop(native_window_type, x11_dragdrop_interface*);
|
||||
std::size_t dragdrop_target(native_window_type, bool insert, std::size_t count);
|
||||
x11_dragdrop_interface* remove_dragdrop(native_window_type);
|
||||
private:
|
||||
static int _m_msg_filter(XEvent&, msg_packet_tag&);
|
||||
void _m_caret_routine();
|
||||
@ -311,6 +329,9 @@ namespace detail
|
||||
int timestamp;
|
||||
Window wd_src;
|
||||
nana::point pos;
|
||||
|
||||
std::map<native_window_type, x11_dragdrop_interface*> dragdrop;
|
||||
std::map<native_window_type, std::size_t> targets;
|
||||
}xdnd_;
|
||||
|
||||
msg_dispatcher * msg_dispatcher_;
|
||||
|
||||
326
source/detail/posix/theme.cpp
Normal file
326
source/detail/posix/theme.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
#include <nana/c++defines.hpp>
|
||||
#if defined(NANA_POSIX) && defined(NANA_X11)
|
||||
#include "theme.hpp"
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
static int gschema_override_priority(const std::string& filename)
|
||||
{
|
||||
if(filename.size() < 3)
|
||||
return -1;
|
||||
|
||||
auto str = filename.substr(0, 2);
|
||||
if('0' <= str[0] && str[0] <= '9' && '0' <= str[1] && str[1] <= '9')
|
||||
return std::stoi(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Removes the wrap of ' and " character.
|
||||
std::string remove_decoration(const std::string& primitive_value)
|
||||
{
|
||||
auto pos = primitive_value.find_first_of("'\"");
|
||||
if(pos == primitive_value.npos)
|
||||
return primitive_value;
|
||||
|
||||
auto endpos = primitive_value.find(primitive_value[pos], pos + 1);
|
||||
if(endpos == primitive_value.npos)
|
||||
return primitive_value;
|
||||
|
||||
return primitive_value.substr(pos + 1, endpos - pos - 1);
|
||||
}
|
||||
|
||||
std::string find_value(std::ifstream& ifs, const std::string& category, const std::string& key)
|
||||
{
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
|
||||
std::string dec_categ = "[" + category + "]";
|
||||
|
||||
bool found_cat = false;
|
||||
while(ifs.good())
|
||||
{
|
||||
std::string text;
|
||||
std::getline(ifs, text);
|
||||
|
||||
if((text.size() > 2) && ('[' == text[0]))
|
||||
{
|
||||
if(found_cat)
|
||||
break;
|
||||
|
||||
found_cat = (text == dec_categ);
|
||||
}
|
||||
else if(found_cat && (text.find(key + "=") == 0))
|
||||
{
|
||||
return remove_decoration(text.substr(key.size() + 1));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string> split_value(const std::string& value_string)
|
||||
{
|
||||
std::vector<std::string> values;
|
||||
|
||||
std::size_t start_pos = 0;
|
||||
while(start_pos != value_string.npos)
|
||||
{
|
||||
auto pos = value_string.find(',', start_pos);
|
||||
if(value_string.npos == pos)
|
||||
{
|
||||
if(start_pos < value_string.size())
|
||||
values.emplace_back(value_string.substr(start_pos));
|
||||
break;
|
||||
}
|
||||
|
||||
values.emplace_back(value_string.substr(start_pos, pos - start_pos));
|
||||
|
||||
start_pos = value_string.find_first_not_of(',', pos);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
std::string find_gnome_theme_name()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Searches all the gschema override files
|
||||
std::vector<std::string> overrides;
|
||||
for(fs::directory_iterator i{"/usr/share/glib-2.0/schemas"}, end; i != end; ++i)
|
||||
{
|
||||
auto filename = i->path().filename().string();
|
||||
if(filename.size() > 17 && filename.substr(filename.size() - 17) == ".gschema.override")
|
||||
{
|
||||
auto priority = gschema_override_priority(filename);
|
||||
if(priority < 0)
|
||||
continue;
|
||||
|
||||
auto i = std::find_if(overrides.cbegin(), overrides.cend(), [priority](const std::string& ovrd){
|
||||
return (priority > gschema_override_priority(ovrd));
|
||||
});
|
||||
|
||||
overrides.emplace(i, std::move(filename));
|
||||
//overrides.insert(i, filename);
|
||||
}
|
||||
}
|
||||
|
||||
//Searches the org.gnome.desktop.interface in override files.
|
||||
for(auto & gschema_override : overrides)
|
||||
{
|
||||
std::ifstream ifs{"/usr/share/glib-2.0/schemas/" + gschema_override};
|
||||
auto value = find_value(ifs, "org.gnome.desktop.interface", "icon-theme");
|
||||
if(!value.empty())
|
||||
return value;
|
||||
}
|
||||
|
||||
//Return the value from org.gnome.desktop.interface.gschema.xml
|
||||
fs::path xml = "/usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml";
|
||||
auto bytes = fs::file_size(xml);
|
||||
if(0 == bytes)
|
||||
return {};
|
||||
|
||||
std::ifstream xml_ifs{"/usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml", std::ios::binary};
|
||||
if(xml_ifs)
|
||||
{
|
||||
std::string data;
|
||||
data.resize(bytes);
|
||||
|
||||
xml_ifs.read(&data.front(), bytes);
|
||||
|
||||
auto pos = data.find("\"icon-theme\"");
|
||||
if(pos != data.npos)
|
||||
{
|
||||
|
||||
pos = data.find("<default>", pos + 22);
|
||||
if(pos != data.npos)
|
||||
{
|
||||
pos += 9;
|
||||
auto endpos = data.find("</default>", pos);
|
||||
if(endpos != data.npos)
|
||||
{
|
||||
return remove_decoration(data.substr(pos, endpos - pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(...){}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
std::string find_kde_theme_name()
|
||||
{
|
||||
auto home = getenv("HOME");
|
||||
if(home)
|
||||
{
|
||||
fs::path kdeglobals{home};
|
||||
kdeglobals /= ".kde/share/config/kdeglobals";
|
||||
|
||||
std::error_code err;
|
||||
if(fs::exists(kdeglobals, err))
|
||||
{
|
||||
std::ifstream ifs{kdeglobals};
|
||||
return find_value(ifs, "Icons", "Theme");
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string find_theme_name()
|
||||
{
|
||||
auto name = find_kde_theme_name();
|
||||
|
||||
if(name.empty())
|
||||
return find_gnome_theme_name();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
class icon_theme
|
||||
{
|
||||
public:
|
||||
icon_theme(const std::string& name):
|
||||
theme_name_(name),
|
||||
ifs_("/usr/share/icons/" + name + "/index.theme")
|
||||
{
|
||||
//First of all, read the Inherits and Directories
|
||||
inherits_ = split_value(find_value(ifs_, "Icon Theme", "Inherits"));
|
||||
directories_ = split_value(find_value(ifs_, "Icon Theme", "Directories"));
|
||||
|
||||
}
|
||||
|
||||
std::string find(const std::string& name, std::size_t size_wanted) const
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
//candidates
|
||||
std::vector<std::pair<std::string,int>> first, second, third;
|
||||
|
||||
fs::path theme_path = "/usr/share/icons/" + theme_name_;
|
||||
|
||||
std::string base_path = "/usr/share/icons/" + theme_name_ + "/";
|
||||
std::string filename = "/" + name + ".png";
|
||||
|
||||
std::error_code err;
|
||||
for(auto & dir : directories_)
|
||||
{
|
||||
if(!fs::exists(theme_path / dir / (name + ".png"), err))
|
||||
continue;
|
||||
|
||||
auto size = find_value(ifs_, dir, "Size");
|
||||
auto type = find_value(ifs_, dir, "Type");
|
||||
auto scaled = find_value(ifs_, dir, "Scale");
|
||||
|
||||
if(size.empty() || ("Fixed" != type))
|
||||
continue;
|
||||
|
||||
int int_size = std::stoi(size);
|
||||
|
||||
if(!scaled.empty())
|
||||
int_size *= std::stoi(scaled);
|
||||
|
||||
auto distance = std::abs(static_cast<int>(size_wanted) - int_size);
|
||||
|
||||
if(0 == distance)
|
||||
{
|
||||
if(scaled.empty() || scaled == "1")
|
||||
return base_path + dir + filename;
|
||||
else
|
||||
first.emplace_back(dir, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(scaled.empty() || scaled == "1")
|
||||
second.emplace_back(dir, distance);
|
||||
else
|
||||
third.emplace_back(dir, distance);
|
||||
}
|
||||
}
|
||||
|
||||
using pair_type = std::pair<std::string,int>;
|
||||
auto comp = [](const pair_type& a, const pair_type& b){
|
||||
return a.second < b.second;
|
||||
};
|
||||
|
||||
std::sort(first.begin(), first.end(), comp);
|
||||
std::sort(second.begin(), second.end(), comp);
|
||||
std::sort(third.begin(), third.end(), comp);
|
||||
|
||||
std::string closer_dir;
|
||||
if(!first.empty())
|
||||
closer_dir = first.front().first;
|
||||
else if(!second.empty())
|
||||
closer_dir = second.front().first;
|
||||
else if(!third.empty())
|
||||
closer_dir = third.front().first;
|
||||
|
||||
|
||||
if(closer_dir.empty())
|
||||
{
|
||||
for(auto & inh : inherits_)
|
||||
{
|
||||
auto dir = icon_theme{inh}.find(name, size_wanted);
|
||||
if(!dir.empty())
|
||||
return dir;
|
||||
}
|
||||
|
||||
//Avoid recursively traverse directory for hicolor if current theme name is hicolor
|
||||
if("hicolor" == theme_name_)
|
||||
return {};
|
||||
|
||||
return icon_theme{"hicolor"}.find(name, size_wanted);
|
||||
}
|
||||
|
||||
return base_path + closer_dir + filename;
|
||||
}
|
||||
private:
|
||||
const std::string theme_name_;
|
||||
mutable std::ifstream ifs_;
|
||||
std::vector<std::string> inherits_;
|
||||
std::vector<std::string> directories_;
|
||||
};
|
||||
|
||||
theme::theme():
|
||||
path_("/usr/share/icons/"),
|
||||
ifs_("/usr/share/icons/default/index.theme")
|
||||
{
|
||||
}
|
||||
|
||||
std::string theme::cursor(const std::string& name) const
|
||||
{
|
||||
auto theme = find_value(ifs_, "Icon Theme", "Inherits");
|
||||
return path_ + theme + "/cursors/" + name;
|
||||
}
|
||||
|
||||
std::string theme::icon(const std::string& name, std::size_t size_wanted) const
|
||||
{
|
||||
//Lookup in cache
|
||||
auto i = iconcache_.find(name);
|
||||
if(i != iconcache_.end())
|
||||
{
|
||||
for(auto & p : i->second)
|
||||
{
|
||||
if(p.first == size_wanted)
|
||||
return p.second;
|
||||
}
|
||||
}
|
||||
|
||||
//Cache is missed.
|
||||
auto file = icon_theme{find_theme_name()}.find(name, size_wanted);
|
||||
if(!file.empty())
|
||||
iconcache_[name].emplace_back(size_wanted, file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
31
source/detail/posix/theme.hpp
Normal file
31
source/detail/posix/theme.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef NANA_DETAIL_THEME_INCLUDED
|
||||
#define NANA_DETAIL_THEME_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class theme
|
||||
{
|
||||
public:
|
||||
theme();
|
||||
|
||||
std::string cursor(const std::string& name) const;
|
||||
std::string icon(const std::string& name, std::size_t size_wanted) const;
|
||||
private:
|
||||
std::string path_;
|
||||
mutable std::ifstream ifs_;
|
||||
|
||||
mutable std::map<std::string, std::vector<std::pair<std::size_t, std::string>>> iconcache_;
|
||||
};
|
||||
|
||||
}//end namespace detail
|
||||
|
||||
}//end namespace nana
|
||||
|
||||
#endif
|
||||
303
source/detail/posix/xdnd_protocol.hpp
Normal file
303
source/detail/posix/xdnd_protocol.hpp
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* X-Window XDND Protocol Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2018-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/detail/posix/xdnd_protocol.hpp
|
||||
*
|
||||
* The XDS is not supported.
|
||||
*/
|
||||
#ifndef NANA_DETAIL_POSIX_XDND_PROTOCOL_INCLUDED
|
||||
#define NANA_DETAIL_POSIX_XDND_PROTOCOL_INCLUDED
|
||||
|
||||
#include "platform_spec.hpp"
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
#include "theme.hpp"
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace nana{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct xdnd_data
|
||||
{
|
||||
Atom requested_action;
|
||||
std::vector<std::filesystem::path> files;
|
||||
};
|
||||
|
||||
class xdnd_protocol
|
||||
{
|
||||
public:
|
||||
enum class xdnd_status_state
|
||||
{
|
||||
normal,
|
||||
position,
|
||||
drop, //Use the 'accept' flag of XdndStatus when mouse has released(XdndDrop has been sent).
|
||||
status_ignore
|
||||
};
|
||||
|
||||
xdnd_protocol(Window source):
|
||||
spec_(nana::detail::platform_spec::instance()),
|
||||
source_(source)
|
||||
{
|
||||
auto disp = spec_.open_display();
|
||||
detail::platform_scope_guard lock;
|
||||
::XSetSelectionOwner(disp, spec_.atombase().xdnd_selection, source, CurrentTime);
|
||||
|
||||
cursor_.dnd_copy = ::XcursorLibraryLoadCursor(disp, "dnd-copy");
|
||||
cursor_.dnd_move = ::XcursorLibraryLoadCursor(disp, "dnd-move");
|
||||
cursor_.dnd_none = ::XcursorLibraryLoadCursor(disp, "dnd-none");
|
||||
}
|
||||
|
||||
~xdnd_protocol()
|
||||
{
|
||||
auto disp = spec_.open_display();
|
||||
::XFreeCursor(disp, cursor_.dnd_copy);
|
||||
::XFreeCursor(disp, cursor_.dnd_move);
|
||||
::XFreeCursor(disp, cursor_.dnd_none);
|
||||
}
|
||||
|
||||
void mouse_move(Window wd, const nana::point& pos, Atom requested_action)
|
||||
{
|
||||
if(wd != target_)
|
||||
{
|
||||
_m_xdnd_leave();
|
||||
|
||||
if(_m_xdnd_enter(wd))
|
||||
_m_xdnd_position(pos, requested_action);
|
||||
}
|
||||
else
|
||||
_m_xdnd_position(pos, requested_action);
|
||||
}
|
||||
|
||||
void mouse_leave()
|
||||
{
|
||||
_m_xdnd_leave();
|
||||
}
|
||||
|
||||
bool mouse_release()
|
||||
{
|
||||
return _m_xdnd_drop();
|
||||
}
|
||||
|
||||
Atom executed_action() const
|
||||
{
|
||||
return executed_action_;
|
||||
}
|
||||
|
||||
//Return true to exit xdnd_protocol event handler
|
||||
bool client_message(const ::XClientMessageEvent& xclient)
|
||||
{
|
||||
auto & atombase = spec_.atombase();
|
||||
|
||||
if(atombase.xdnd_status == xclient.message_type)
|
||||
{
|
||||
if(xdnd_status_state::position != xstate_ && xdnd_status_state::drop != xstate_)
|
||||
return false;
|
||||
|
||||
Window target_wd = static_cast<Window>(xclient.data.l[0]);
|
||||
bool is_accepted_by_target = (xclient.data.l[1] & 1);
|
||||
|
||||
if(xclient.data.l[1] & 0x2)
|
||||
{
|
||||
rectangle rct{
|
||||
static_cast<int>(xclient.data.l[2] >> 16),
|
||||
static_cast<int>(xclient.data.l[2] & 0xFFFF),
|
||||
static_cast<unsigned>(xclient.data.l[3] >> 16),
|
||||
static_cast<unsigned>(xclient.data.l[3] & 0xFFFF)
|
||||
};
|
||||
|
||||
if(!rct.empty())
|
||||
mvout_table_[target_wd] = rct;
|
||||
}
|
||||
_m_cursor(is_accepted_by_target);
|
||||
|
||||
if((!is_accepted_by_target) && (xdnd_status_state::drop == xstate_))
|
||||
{
|
||||
_m_xdnd_leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
executed_action_ = xclient.data.l[4];
|
||||
xstate_ = xdnd_status_state::normal;
|
||||
}
|
||||
else if(atombase.xdnd_finished == xclient.message_type)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void selection_request(const ::XSelectionRequestEvent& xselectionrequest, const xdnd_data& data)
|
||||
{
|
||||
if(spec_.atombase().xdnd_selection == xselectionrequest.selection)
|
||||
{
|
||||
::XEvent evt;
|
||||
evt.xselection.type = SelectionNotify;
|
||||
evt.xselection.display = xselectionrequest.display;
|
||||
evt.xselection.requestor = xselectionrequest.requestor;
|
||||
evt.xselection.selection = xselectionrequest.selection;
|
||||
evt.xselection.target = 0;
|
||||
evt.xselection.property = 0;
|
||||
evt.xselection.time = xselectionrequest.time;
|
||||
|
||||
if(xselectionrequest.target == spec_.atombase().text_uri_list)
|
||||
{
|
||||
if(data.files.size())
|
||||
{
|
||||
std::string uri_list;
|
||||
for(auto& file : data.files)
|
||||
{
|
||||
uri_list += "file://";
|
||||
uri_list += file.u8string();
|
||||
uri_list += "\r\n";
|
||||
}
|
||||
|
||||
::XChangeProperty (spec_.open_display(),
|
||||
xselectionrequest.requestor,
|
||||
xselectionrequest.property,
|
||||
xselectionrequest.target,
|
||||
8, PropModeReplace,
|
||||
reinterpret_cast<unsigned char*>(&uri_list.front()), uri_list.size() + 1);
|
||||
|
||||
evt.xselection.property = xselectionrequest.property;
|
||||
evt.xselection.target = xselectionrequest.target;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
platform_scope_guard lock;
|
||||
::XSendEvent(spec_.open_display(), xselectionrequest.requestor, False, 0, &evt);
|
||||
::XFlush(spec_.open_display());
|
||||
|
||||
if(0 == evt.xselection.target)
|
||||
_m_xdnd_leave();
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool _m_xdnd_enter(Window wd)
|
||||
{
|
||||
//xdnd version of the window
|
||||
auto xdnd_ver = _m_xdnd_aware(wd);
|
||||
if(0 == xdnd_ver)
|
||||
return false;
|
||||
|
||||
target_ = wd;
|
||||
_m_client_msg(spec_.atombase().xdnd_enter, (xdnd_ver << 24), spec_.atombase().text_uri_list, XA_STRING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void _m_xdnd_position(const nana::point& pos, Atom requested_action)
|
||||
{
|
||||
if(xdnd_status_state::normal != xstate_)
|
||||
return;
|
||||
|
||||
auto i = mvout_table_.find(target_);
|
||||
if(i != mvout_table_.end() && i->second.is_hit(pos))
|
||||
return;
|
||||
|
||||
xstate_ = xdnd_status_state::position;
|
||||
//Send XdndPosition
|
||||
long position = (pos.x << 16 | pos.y);
|
||||
_m_client_msg(spec_.atombase().xdnd_position, 0, position, CurrentTime, requested_action);
|
||||
}
|
||||
|
||||
void _m_xdnd_leave()
|
||||
{
|
||||
::XUndefineCursor(spec_.open_display(), source_);
|
||||
|
||||
if(target_)
|
||||
{
|
||||
_m_client_msg(spec_.atombase().xdnd_leave, 0, 0, 0);
|
||||
target_ = 0;
|
||||
executed_action_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool _m_xdnd_drop()
|
||||
{
|
||||
::XUndefineCursor(spec_.open_display(), source_);
|
||||
xstate_ = xdnd_status_state::drop;
|
||||
|
||||
if(executed_action_)
|
||||
_m_client_msg(spec_.atombase().xdnd_drop, 0, CurrentTime, 0);
|
||||
|
||||
target_ = 0;
|
||||
|
||||
return (executed_action_ != 0);
|
||||
}
|
||||
private:
|
||||
//dndversion<<24, fl_XdndURIList, XA_STRING, 0
|
||||
void _m_client_msg(Atom xdnd_atom, long data1, long data2, long data3, long data4 = 0)
|
||||
{
|
||||
auto const display = spec_.open_display();
|
||||
XEvent evt;
|
||||
::memset(&evt, 0, sizeof evt);
|
||||
evt.xany.type = ClientMessage;
|
||||
evt.xany.display = display;
|
||||
evt.xclient.window = target_;
|
||||
evt.xclient.message_type = xdnd_atom;
|
||||
evt.xclient.format = 32;
|
||||
|
||||
//Target window
|
||||
evt.xclient.data.l[0] = source_;
|
||||
|
||||
evt.xclient.data.l[1] = data1;
|
||||
evt.xclient.data.l[2] = data2;
|
||||
evt.xclient.data.l[3] = data3;
|
||||
evt.xclient.data.l[4] = data4;
|
||||
|
||||
::XSendEvent(display, target_, True, NoEventMask, &evt);
|
||||
}
|
||||
|
||||
// Returns the XDND version of specified window
|
||||
//@return the XDND version. If the specified window does not have property XdndAware, it returns 0
|
||||
int _m_xdnd_aware(Window wd)
|
||||
{
|
||||
Atom actual; int format; unsigned long count, remaining;
|
||||
unsigned char *data = 0;
|
||||
::XGetWindowProperty(spec_.open_display(), wd, spec_.atombase().xdnd_aware,
|
||||
0, 4, False, XA_ATOM, &actual, &format, &count, &remaining, &data);
|
||||
|
||||
int version = 0;
|
||||
if (data)
|
||||
{
|
||||
if ((actual == XA_ATOM) && (format==32) && count)
|
||||
version = int(*(Atom*)data);
|
||||
|
||||
::XFree(data);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
void _m_cursor(bool accepted)
|
||||
{
|
||||
::XDefineCursor(spec_.open_display(), source_, (accepted ? cursor_.dnd_move : cursor_.dnd_none));
|
||||
}
|
||||
private:
|
||||
nana::detail::platform_spec& spec_;
|
||||
Window const source_;
|
||||
Window target_{ 0 };
|
||||
Atom executed_action_{ 0 };
|
||||
xdnd_status_state xstate_{xdnd_status_state::normal};
|
||||
std::map<Window, nana::rectangle> mvout_table_;
|
||||
|
||||
struct cursor_rep
|
||||
{
|
||||
Cursor dnd_copy{ 0 };
|
||||
Cursor dnd_move{ 0 };
|
||||
Cursor dnd_none{ 0 };
|
||||
}cursor_;
|
||||
}; //end class xdnd_protocol
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* A ISO C++ FileSystem Implementation
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -45,7 +45,7 @@
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -102,6 +102,22 @@ namespace nana
|
||||
|
||||
std::string pretty_file_date(const fs::path& path) // todo: move to .cpp
|
||||
{
|
||||
struct tm t;
|
||||
if (modified_file_time(path, t))
|
||||
{
|
||||
std::stringstream tm;
|
||||
tm << std::put_time(&t, "%Y-%m-%d, %H:%M:%S");
|
||||
return tm.str();
|
||||
}
|
||||
return {};
|
||||
|
||||
/*
|
||||
// Deprecated
|
||||
//Windows stores file times using the FILETIME structure, which is a 64 bit value of 100ns intervals from January 1, 1601.
|
||||
//What's worse is that this 1601 date is fairly common to see given that it's the all zeroes value, and it is far before the
|
||||
//earliest date representable with time_t.std::filesystem can't change the reality of the underlying platform.
|
||||
|
||||
|
||||
try {
|
||||
#if NANA_USING_BOOST_FILESYSTEM
|
||||
// The return type of boost::filesystem::last_write_time isn't
|
||||
@ -117,11 +133,8 @@ namespace nana
|
||||
|
||||
if (ftime == ((fs::file_time_type::min)())) return{};
|
||||
|
||||
//std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime);
|
||||
|
||||
//A workaround for VC2013
|
||||
using time_point = decltype(ftime);
|
||||
|
||||
auto cftime = time_point::clock::to_time_t(ftime);
|
||||
|
||||
std::stringstream tm;
|
||||
@ -131,6 +144,8 @@ namespace nana
|
||||
catch (...) {
|
||||
return{};
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
bool modified_file_time(const fs::path& p, struct tm& t)
|
||||
@ -209,9 +224,9 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
|
||||
//Because of No wide character version of POSIX
|
||||
#if defined(NANA_POSIX)
|
||||
const char* splstr = "/";
|
||||
const char* separators = "/";
|
||||
#else
|
||||
const wchar_t* splstr = L"/\\";
|
||||
const wchar_t* separators = L"/\\";
|
||||
#endif
|
||||
|
||||
//class file_status
|
||||
@ -249,14 +264,23 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
/// true if the path is empty, false otherwise. ??
|
||||
bool path::empty() const noexcept
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
return (::GetFileAttributes(pathstr_.c_str()) == INVALID_FILE_ATTRIBUTES);
|
||||
#elif defined(NANA_POSIX)
|
||||
struct stat sta;
|
||||
return (::stat(pathstr_.c_str(), &sta) == -1);
|
||||
return pathstr_.empty();
|
||||
}
|
||||
|
||||
bool path::is_absolute() const
|
||||
{
|
||||
#ifdef NANA_WINDOWS
|
||||
return has_root_name() && has_root_directory();
|
||||
#else
|
||||
return has_root_directory();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool path::is_relative() const
|
||||
{
|
||||
return !is_absolute();
|
||||
}
|
||||
|
||||
path path::extension() const
|
||||
{
|
||||
// todo: make more globlal
|
||||
@ -277,6 +301,107 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
return path(pathstr_.substr(pos));
|
||||
}
|
||||
|
||||
bool is_directory_separator(path::value_type ch)
|
||||
{
|
||||
return (ch == '/')
|
||||
#ifdef NANA_WINDOWS
|
||||
|| (ch == path::preferred_separator)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
path path::root_name() const
|
||||
{
|
||||
auto pos = pathstr_.find_first_not_of(separators);
|
||||
if (pathstr_.npos != pos)
|
||||
{
|
||||
pos = pathstr_.find_first_of(separators, pos + 1);
|
||||
if (pathstr_.npos != pos)
|
||||
{
|
||||
if ((is_directory_separator(pathstr_[0]) && is_directory_separator(pathstr_[1]))
|
||||
#ifdef NANA_WINDOWS
|
||||
|| (pathstr_[pos - 1] == ':')
|
||||
#endif
|
||||
)
|
||||
return pathstr_.substr(0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
return path{};
|
||||
}
|
||||
|
||||
std::size_t root_directory_pos(const path::string_type& str)
|
||||
{
|
||||
#ifdef NANA_WINDOWS
|
||||
// case "c:/"
|
||||
if (str.size() > 2
|
||||
&& str[1] == ':'
|
||||
&& is_directory_separator(str[2])) return 2;
|
||||
#endif
|
||||
|
||||
// case "//"
|
||||
if (str.size() == 2
|
||||
&& is_directory_separator(str[0])
|
||||
&& is_directory_separator(str[1])) return path::string_type::npos;
|
||||
|
||||
#ifdef NANA_WINDOWS
|
||||
// case "\\?\"
|
||||
if (str.size() > 4
|
||||
&& is_directory_separator(str[0])
|
||||
&& is_directory_separator(str[1])
|
||||
&& str[2] == '?'
|
||||
&& is_directory_separator(str[3]))
|
||||
{
|
||||
auto pos = str.find_first_of(separators, 4);
|
||||
return pos < str.size() ? pos : str.npos;
|
||||
}
|
||||
#endif
|
||||
|
||||
// case "//net {/}"
|
||||
if (str.size() > 3
|
||||
&& is_directory_separator(str[0])
|
||||
&& is_directory_separator(str[1])
|
||||
&& !is_directory_separator(str[2]))
|
||||
{
|
||||
auto pos = str.find_first_of(separators, 2);
|
||||
return pos < str.size() ? pos : str.npos;
|
||||
}
|
||||
|
||||
// case "/"
|
||||
if (str.size() > 0 && is_directory_separator(str[0])) return 0;
|
||||
|
||||
return str.npos;
|
||||
}
|
||||
|
||||
path path::root_directory() const
|
||||
{
|
||||
auto pos = root_directory_pos(pathstr_);
|
||||
|
||||
return pos == string_type::npos
|
||||
? path()
|
||||
: path(pathstr_.substr(pos, 1));
|
||||
}
|
||||
|
||||
path path::root_path() const
|
||||
{
|
||||
return root_name().pathstr_ + root_directory().pathstr_;
|
||||
}
|
||||
|
||||
path path::relative_path() const
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
auto pos = root_directory_pos(pathstr_);
|
||||
|
||||
pos = pathstr_.find_first_not_of(separators, pos);
|
||||
if (pathstr_.npos != pos)
|
||||
return path{ pathstr_.substr(pos) };
|
||||
}
|
||||
return{};
|
||||
}
|
||||
|
||||
path path::parent_path() const
|
||||
{
|
||||
return{nana_fs::parent_path(pathstr_)};
|
||||
@ -310,14 +435,14 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
|
||||
path path::filename() const
|
||||
{
|
||||
auto pos = pathstr_.find_last_of(splstr);
|
||||
auto pos = pathstr_.find_last_of(separators);
|
||||
if (pos != pathstr_.npos)
|
||||
{
|
||||
if (pos + 1 == pathstr_.size())
|
||||
{
|
||||
value_type tmp[2] = {preferred_separator, 0};
|
||||
|
||||
if (pathstr_.npos != pathstr_.find_last_not_of(splstr, pos))
|
||||
if (pathstr_.npos != pathstr_.find_last_not_of(separators, pos))
|
||||
tmp[0] = '.';
|
||||
|
||||
return{ tmp };
|
||||
@ -328,6 +453,21 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
return{ pathstr_ };
|
||||
}
|
||||
|
||||
void path::clear() noexcept
|
||||
{
|
||||
pathstr_.clear();
|
||||
}
|
||||
|
||||
path& path::make_preferred()
|
||||
{
|
||||
#ifdef NANA_WINDOWS
|
||||
std::replace(pathstr_.begin(), pathstr_.end(), L'/', L'\\');
|
||||
#else
|
||||
std::replace(pathstr_.begin(), pathstr_.end(), '\\', '/');
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
path& path::remove_filename()
|
||||
{
|
||||
#ifdef NANA_WINDOWS
|
||||
@ -418,10 +558,10 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
if (this == &p)
|
||||
{
|
||||
auto other = p.pathstr_;
|
||||
if ((other.front() != '/') && (other.front() == path::preferred_separator))
|
||||
if (!is_directory_separator(other.front()))
|
||||
{
|
||||
if (!this->pathstr_.empty() && (pathstr_.back() != '/' && pathstr_.back() == path::preferred_separator))
|
||||
pathstr_.append(path::preferred_separator, 1);
|
||||
if (!pathstr_.empty() && !is_directory_separator(pathstr_.back()))
|
||||
pathstr_.append(1, path::preferred_separator);
|
||||
}
|
||||
|
||||
pathstr_ += other;
|
||||
@ -429,10 +569,10 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
else
|
||||
{
|
||||
auto & other = p.pathstr_;
|
||||
if ((other.front() != '/') && (other.front() == path::preferred_separator))
|
||||
if (!is_directory_separator(other.front()))
|
||||
{
|
||||
if (!this->pathstr_.empty() && (pathstr_.back() != '/' && pathstr_.back() == path::preferred_separator))
|
||||
pathstr_.append(path::preferred_separator, 1);
|
||||
if (!pathstr_.empty() && !is_directory_separator(pathstr_.back()))
|
||||
pathstr_.append(1, path::preferred_separator);
|
||||
}
|
||||
|
||||
pathstr_ += p.pathstr_;
|
||||
@ -534,6 +674,12 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
_m_prepare(file_path);
|
||||
}
|
||||
|
||||
directory_iterator::directory_iterator(const path& p, directory_options opt):
|
||||
option_(opt)
|
||||
{
|
||||
_m_prepare(p);
|
||||
}
|
||||
|
||||
const directory_iterator::value_type& directory_iterator::operator*() const { return value_; }
|
||||
|
||||
const directory_iterator::value_type*
|
||||
@ -790,7 +936,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
auto stat = status(p, err);
|
||||
|
||||
if (err != std::error_code())
|
||||
throw filesystem_error("nana::experimental::filesystem::status", p, err);
|
||||
throw filesystem_error("nana::filesystem::status", p, err);
|
||||
|
||||
return stat;
|
||||
}
|
||||
@ -849,8 +995,23 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
return (status(p).type() == file_type::directory);
|
||||
}
|
||||
|
||||
bool is_directory(const path& p, std::error_code& ec) noexcept
|
||||
{
|
||||
return (status(p, ec).type() == file_type::directory);
|
||||
}
|
||||
|
||||
std::uintmax_t file_size(const path& p)
|
||||
{
|
||||
std::error_code err;
|
||||
auto bytes = file_size(p, err);
|
||||
if (err)
|
||||
throw filesystem_error("nana::filesystem::status", p, err);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
std::uintmax_t file_size(const path& p, std::error_code& ec) noexcept
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
//Some compilation environment may fail to link to GetFileSizeEx
|
||||
typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER);
|
||||
@ -868,23 +1029,25 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
return li.QuadPart;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
ec.assign(static_cast<int>(::GetLastError()), std::generic_category());
|
||||
#elif defined(NANA_POSIX)
|
||||
FILE * stream = ::fopen(p.c_str(), "rb");
|
||||
long long size = 0;
|
||||
if (stream)
|
||||
{
|
||||
long long bytes = 0;
|
||||
# if defined(NANA_LINUX)
|
||||
fseeko64(stream, 0, SEEK_END);
|
||||
size = ftello64(stream);
|
||||
bytes = ftello64(stream);
|
||||
# elif defined(NANA_POSIX)
|
||||
fseeko(stream, 0, SEEK_END);
|
||||
size = ftello(stream);
|
||||
bytes = ftello(stream);
|
||||
# endif
|
||||
::fclose(stream);
|
||||
return bytes;
|
||||
}
|
||||
return size;
|
||||
ec.assign(static_cast<int>(::errno), std::generic_category());
|
||||
#endif
|
||||
return static_cast<std::uintmax_t>(-1);
|
||||
}
|
||||
|
||||
|
||||
@ -976,5 +1139,141 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
}//end namespace filesystem
|
||||
} //end namespace experimental
|
||||
}//end namespace nana
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || \
|
||||
(defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703)))
|
||||
path absolute(const path& p)
|
||||
{
|
||||
if (p.empty())
|
||||
return p;
|
||||
|
||||
auto abs_base = current_path();
|
||||
|
||||
// store expensive to compute values that are needed multiple times
|
||||
path p_root_name(p.root_name());
|
||||
path base_root_name(abs_base.root_name());
|
||||
path p_root_directory(p.root_directory());
|
||||
|
||||
if (!p_root_name.empty()) // p.has_root_name()
|
||||
{
|
||||
if (p_root_directory.empty()) // !p.has_root_directory()
|
||||
return p_root_name / abs_base.root_directory()
|
||||
/ abs_base.relative_path() / p.relative_path();
|
||||
// p is absolute, so fall through to return p at end of block
|
||||
}
|
||||
else if (!p_root_directory.empty()) // p.has_root_directory()
|
||||
{
|
||||
#ifdef NANA_POSIX
|
||||
// POSIX can have root name it it is a network path
|
||||
if (base_root_name.empty()) // !abs_base.has_root_name()
|
||||
return p;
|
||||
#endif
|
||||
return base_root_name / p;
|
||||
}
|
||||
else
|
||||
return abs_base / p;
|
||||
|
||||
return p; // p.is_absolute() is true
|
||||
}
|
||||
|
||||
path absolute(const path& p, std::error_code& err)
|
||||
{
|
||||
return absolute(p);
|
||||
}
|
||||
|
||||
path canonical(const path& p, std::error_code* err)
|
||||
{
|
||||
path source(p.is_absolute() ? p : absolute(p));
|
||||
path root(source.root_path());
|
||||
path result;
|
||||
|
||||
std::error_code local_ec;
|
||||
file_status stat(status(source, local_ec));
|
||||
|
||||
if (stat.type() == file_type::not_found)
|
||||
{
|
||||
if (nullptr == err)
|
||||
throw (filesystem_error(
|
||||
"nana::filesystem::canonical", source,
|
||||
error_code(static_cast<int>(errc::no_such_file_or_directory), generic_category())));
|
||||
err->assign(static_cast<int>(errc::no_such_file_or_directory), generic_category());
|
||||
return result;
|
||||
}
|
||||
else if (local_ec)
|
||||
{
|
||||
if (nullptr == err)
|
||||
throw (filesystem_error(
|
||||
"nana::filesystem::canonical", source, local_ec));
|
||||
*err = local_ec;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
auto tmp_p = source;
|
||||
|
||||
std::vector<path> source_elements;
|
||||
while (tmp_p != root)
|
||||
{
|
||||
source_elements.emplace(source_elements.begin(), tmp_p.filename());
|
||||
tmp_p.remove_filename();
|
||||
}
|
||||
|
||||
result = root;
|
||||
|
||||
for(auto & e : source_elements)
|
||||
{
|
||||
auto str = e.string();
|
||||
if("." == str)
|
||||
continue;
|
||||
else if(".." == str)
|
||||
{
|
||||
if(result != root)
|
||||
result.remove_filename();
|
||||
continue;
|
||||
}
|
||||
|
||||
result /= e;
|
||||
}
|
||||
|
||||
if (err)
|
||||
err->clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
path canonical(const path& p)
|
||||
{
|
||||
return canonical(p, nullptr);
|
||||
}
|
||||
|
||||
path canonical(const path& p, std::error_code& err)
|
||||
{
|
||||
return canonical(p, &err);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || defined(NANA_MINGW)
|
||||
bool exists( std::filesystem::file_status s ) noexcept
|
||||
{
|
||||
return s.type() != file_type::not_found;
|
||||
}
|
||||
|
||||
bool exists( const std::filesystem::path& p )
|
||||
{
|
||||
return exists(status(p));
|
||||
}
|
||||
|
||||
bool exists( const std::filesystem::path& p, std::error_code& ec ) noexcept
|
||||
{
|
||||
return exists(status(p, ec));
|
||||
}
|
||||
#endif
|
||||
}//end namespace filesystem
|
||||
}//end namespace std
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An Animation Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -571,6 +571,25 @@ namespace nana
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
animation::animation(animation&& rhs)
|
||||
: impl_(rhs.impl_)
|
||||
{
|
||||
rhs.impl_ = new impl(23);
|
||||
}
|
||||
|
||||
animation& animation::operator=(animation&& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
auto imp = new impl{ 23 };
|
||||
|
||||
delete impl_;
|
||||
impl_ = rhs.impl_;
|
||||
rhs.impl_ = imp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void animation::push_back(frameset frms)
|
||||
{
|
||||
impl_->framesets.emplace_back(std::move(frms));
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Basic Window Widget Definition
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -216,40 +216,14 @@ namespace nana
|
||||
basic_window::other_tag::other_tag(category::flags categ)
|
||||
: category(categ), active_window(nullptr), upd_state(update_state::none)
|
||||
{
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
switch(categ)
|
||||
{
|
||||
case category::flags::root:
|
||||
attribute.root = new attr_root_tag;
|
||||
break;
|
||||
case category::flags::frame:
|
||||
attribute.frame = new attr_frame_tag;
|
||||
break;
|
||||
default:
|
||||
attribute.root = nullptr;
|
||||
}
|
||||
#else
|
||||
if (category::flags::root == categ)
|
||||
attribute.root = new attr_root_tag;
|
||||
else
|
||||
attribute.root = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
basic_window::other_tag::~other_tag()
|
||||
{
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
switch(category)
|
||||
{
|
||||
case category::flags::root:
|
||||
delete attribute.root;
|
||||
break;
|
||||
case category::flags::frame:
|
||||
delete attribute.frame;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
if (category::flags::root == category)
|
||||
delete attribute.root;
|
||||
}
|
||||
@ -290,14 +264,6 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
void basic_window::frame_window(native_window_type wd)
|
||||
{
|
||||
if(category::flags::frame == this->other.category)
|
||||
other.attribute.frame->container = wd;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool basic_window::is_ancestor_of(const basic_window* wd) const
|
||||
{
|
||||
while (wd)
|
||||
@ -410,6 +376,7 @@ namespace nana
|
||||
flags.enabled = true;
|
||||
flags.modal = false;
|
||||
flags.take_active = true;
|
||||
flags.draggable = false;
|
||||
flags.dropable = false;
|
||||
flags.fullscreen = false;
|
||||
flags.tab = nana::detail::tab_type::none;
|
||||
@ -423,6 +390,7 @@ namespace nana
|
||||
flags.ignore_menubar_focus = false;
|
||||
flags.ignore_mouse_focus = false;
|
||||
flags.space_click_enabled = false;
|
||||
flags.ignore_child_mapping = false;
|
||||
|
||||
visible = false;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Bedrock Platform-Independent Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#include <nana/gui/detail/bedrock_pi_data.hpp>
|
||||
#include "bedrock_types.hpp"
|
||||
#include <nana/gui/detail/event_code.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <sstream>
|
||||
@ -94,6 +94,12 @@ namespace nana
|
||||
|
||||
};
|
||||
|
||||
bedrock::core_window_t* bedrock::focus()
|
||||
{
|
||||
auto wd = wd_manager().root(native_interface::get_focus_window());
|
||||
return (wd ? wd->other.attribute.root->focus : nullptr);
|
||||
}
|
||||
|
||||
events_operation& bedrock::evt_operation()
|
||||
{
|
||||
return pi_data_->evt_operation;
|
||||
@ -164,17 +170,10 @@ namespace nana
|
||||
caret_wd->annex.caret_ptr->visible(false);
|
||||
}
|
||||
|
||||
if (!exposed)
|
||||
if ((!exposed) && (category::flags::root != wd->other.category))
|
||||
{
|
||||
if (category::flags::root != wd->other.category)
|
||||
{
|
||||
//find an ancestor until it is not a lite_widget
|
||||
wd = wd->seek_non_lite_widget_ancestor();
|
||||
}
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
else if (category::flags::frame == wd->other.category)
|
||||
wd = wd_manager().find_window(wd->root, wd->pos_root.x, wd->pos_root.y);
|
||||
#endif
|
||||
//find an ancestor until it is not a lite_widget
|
||||
wd = wd->seek_non_lite_widget_ancestor();
|
||||
}
|
||||
|
||||
wd_manager().refresh_tree(wd);
|
||||
@ -609,5 +608,93 @@ namespace nana
|
||||
throw std::runtime_error("Invalid event code");
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::thread_context_destroy(core_window_t * wd)
|
||||
{
|
||||
auto ctx = get_thread_context(0);
|
||||
if(ctx && ctx->event_window == wd)
|
||||
ctx->event_window = nullptr;
|
||||
}
|
||||
|
||||
void bedrock::thread_context_lazy_refresh()
|
||||
{
|
||||
auto ctx = get_thread_context(0);
|
||||
if(ctx && ctx->event_window)
|
||||
ctx->event_window->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
|
||||
bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal)
|
||||
{
|
||||
if(wd_manager().available(wd) == false)
|
||||
return false;
|
||||
|
||||
core_window_t * prev_wd = nullptr;
|
||||
if(thrd)
|
||||
{
|
||||
prev_wd = thrd->event_window;
|
||||
thrd->event_window = wd;
|
||||
_m_event_filter(evt_code, wd, thrd);
|
||||
}
|
||||
|
||||
using update_state = basic_window::update_state;
|
||||
|
||||
if (update_state::none == wd->other.upd_state)
|
||||
wd->other.upd_state = update_state::lazy;
|
||||
|
||||
auto ignore_mapping_value = wd->flags.ignore_child_mapping;
|
||||
wd->flags.ignore_child_mapping = true;
|
||||
|
||||
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
|
||||
|
||||
wd->flags.ignore_child_mapping = ignore_mapping_value;
|
||||
|
||||
bool good_wd = false;
|
||||
if(wd_manager().available(wd))
|
||||
{
|
||||
//A child of wd may not be drawn if it was out of wd's range before wd resized,
|
||||
//so refresh all children of wd when a resized occurs.
|
||||
if(ask_update || (event_code::resized == evt_code) || (update_state::refreshed == wd->other.upd_state))
|
||||
{
|
||||
wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code));
|
||||
}
|
||||
else
|
||||
{
|
||||
wd_manager().map_requester(wd);
|
||||
wd->other.upd_state = update_state::none;
|
||||
}
|
||||
|
||||
good_wd = true;
|
||||
}
|
||||
|
||||
|
||||
if(thrd) thrd->event_window = prev_wd;
|
||||
return good_wd;
|
||||
}
|
||||
|
||||
void bedrock::_m_event_filter(event_code event_id, core_window_t * wd, thread_context * thrd)
|
||||
{
|
||||
auto not_state_cur = (wd->root_widget->other.attribute.root->state_cursor == nana::cursor::arrow);
|
||||
|
||||
switch(event_id)
|
||||
{
|
||||
case event_code::mouse_enter:
|
||||
if (not_state_cur)
|
||||
set_cursor(wd, wd->predef_cursor, thrd);
|
||||
break;
|
||||
case event_code::mouse_leave:
|
||||
if (not_state_cur && (wd->predef_cursor != cursor::arrow))
|
||||
set_cursor(wd, nana::cursor::arrow, thrd);
|
||||
break;
|
||||
case event_code::destroy:
|
||||
if (wd->root_widget->other.attribute.root->state_cursor_window == wd)
|
||||
undefine_state_cursor(wd, thrd);
|
||||
|
||||
if(wd == thrd->cursor.window)
|
||||
set_cursor(wd, cursor::arrow, thrd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}//end namespace detail
|
||||
}//end namespace nana
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Bedrock Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -12,7 +12,6 @@
|
||||
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#if defined(NANA_POSIX) && defined(NANA_X11)
|
||||
#include <nana/gui/detail/bedrock_pi_data.hpp>
|
||||
#include <nana/gui/detail/event_code.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
@ -22,6 +21,8 @@
|
||||
#include <errno.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "bedrock_types.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
@ -52,38 +53,6 @@ namespace detail
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct bedrock::thread_context
|
||||
{
|
||||
unsigned event_pump_ref_count{0};
|
||||
|
||||
int window_count{0}; //The number of windows
|
||||
core_window_t* event_window{nullptr};
|
||||
bool is_alt_pressed{false};
|
||||
bool is_ctrl_pressed{false};
|
||||
|
||||
struct platform_detail_tag
|
||||
{
|
||||
native_window_type motion_window;
|
||||
nana::point motion_pointer_pos;
|
||||
}platform;
|
||||
|
||||
struct cursor_tag
|
||||
{
|
||||
core_window_t * window;
|
||||
native_window_type native_handle;
|
||||
nana::cursor predef_cursor;
|
||||
Cursor handle;
|
||||
}cursor;
|
||||
|
||||
thread_context()
|
||||
{
|
||||
cursor.window = nullptr;
|
||||
cursor.native_handle = nullptr;
|
||||
cursor.predef_cursor = nana::cursor::arrow;
|
||||
cursor.handle = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct bedrock::private_impl
|
||||
{
|
||||
typedef std::map<unsigned, thread_context> thr_context_container;
|
||||
@ -247,12 +216,6 @@ namespace detail
|
||||
return bedrock_object;
|
||||
}
|
||||
|
||||
bedrock::core_window_t* bedrock::focus()
|
||||
{
|
||||
core_window_t* wd = wd_manager().root(native_interface::get_focus_window());
|
||||
return (wd ? wd->other.attribute.root->focus : 0);
|
||||
}
|
||||
|
||||
void bedrock::get_key_state(arg_keyboard& arg)
|
||||
{
|
||||
XKeyEvent xkey;
|
||||
@ -289,46 +252,6 @@ namespace detail
|
||||
//No implementation for Linux
|
||||
}
|
||||
|
||||
bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal)
|
||||
{
|
||||
if(wd_manager().available(wd) == false)
|
||||
return false;
|
||||
|
||||
core_window_t * prev_wd = nullptr;
|
||||
if(thrd)
|
||||
{
|
||||
prev_wd = thrd->event_window;
|
||||
thrd->event_window = wd;
|
||||
_m_event_filter(evt_code, wd, thrd);
|
||||
}
|
||||
|
||||
using update_state = basic_window::update_state;
|
||||
|
||||
if(wd->other.upd_state == update_state::none)
|
||||
wd->other.upd_state = update_state::lazy;
|
||||
|
||||
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
|
||||
|
||||
bool good_wd = false;
|
||||
if(wd_manager().available(wd))
|
||||
{
|
||||
//A child of wd may not be drawn if it was out of wd's range before wd resized,
|
||||
//so refresh all children of wd when a resized occurs.
|
||||
if(ask_update || (event_code::resized == evt_code) || (update_state::refreshed == wd->other.upd_state))
|
||||
{
|
||||
wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code));
|
||||
}
|
||||
else
|
||||
wd->other.upd_state = update_state::none;
|
||||
|
||||
good_wd = true;
|
||||
}
|
||||
|
||||
|
||||
if(thrd) thrd->event_window = prev_wd;
|
||||
return good_wd;
|
||||
}
|
||||
|
||||
void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt)
|
||||
{
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
@ -418,10 +341,10 @@ namespace detail
|
||||
{
|
||||
switch(msg.kind)
|
||||
{
|
||||
case nana::detail::msg_packet_tag::kind_xevent:
|
||||
case nana::detail::msg_packet_tag::pkt_family::xevent:
|
||||
window_proc_for_xevent(display, msg.u.xevent);
|
||||
break;
|
||||
case nana::detail::msg_packet_tag::kind_mouse_drop:
|
||||
case nana::detail::msg_packet_tag::pkt_family::mouse_drop:
|
||||
window_proc_for_packet(display, msg);
|
||||
break;
|
||||
default: break;
|
||||
@ -441,8 +364,9 @@ namespace detail
|
||||
|
||||
switch(msg.kind)
|
||||
{
|
||||
case nana::detail::msg_packet_tag::kind_mouse_drop:
|
||||
case nana::detail::msg_packet_tag::pkt_family::mouse_drop:
|
||||
msgwd = brock.wd_manager().find_window(native_window, {msg.u.mouse_drop.x, msg.u.mouse_drop.y});
|
||||
|
||||
if(msgwd)
|
||||
{
|
||||
arg_dropfiles arg;
|
||||
@ -973,7 +897,12 @@ namespace detail
|
||||
case Expose:
|
||||
if(msgwnd->visible && (msgwnd->root_graph->empty() == false))
|
||||
{
|
||||
nana::detail::platform_scope_guard lock;
|
||||
nana::internal_scope_guard lock;
|
||||
//Don't lock this scope using platform-scope-guard. Because it would cause the platform-scope-lock to be locked
|
||||
//before the internal-scope-guard, and the order of locking would cause dead-lock.
|
||||
//
|
||||
//Locks this scope using internal-scope-guard is correct and safe. In the scope, the Xlib functions aren't called
|
||||
//directly.
|
||||
if(msgwnd->is_draw_through())
|
||||
{
|
||||
msgwnd->other.attribute.root->draw_through();
|
||||
@ -1243,10 +1172,12 @@ namespace detail
|
||||
default:
|
||||
if(message == ClientMessage)
|
||||
{
|
||||
auto & atoms = nana::detail::platform_spec::instance().atombase();
|
||||
if(atoms.wm_protocols == xevent.xclient.message_type)
|
||||
auto & spec = ::nana::detail::platform_spec::instance();
|
||||
auto & xclient = xevent.xclient;
|
||||
auto & atoms = spec.atombase();
|
||||
if(atoms.wm_protocols == xclient.message_type)
|
||||
{
|
||||
if(msgwnd->flags.enabled && (atoms.wm_delete_window == static_cast<Atom>(xevent.xclient.data.l[0])))
|
||||
if(msgwnd->flags.enabled && (atoms.wm_delete_window == static_cast<Atom>(xclient.data.l[0])))
|
||||
{
|
||||
arg_unload arg;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@ -1338,20 +1269,6 @@ namespace detail
|
||||
|
||||
}//end bedrock::event_loop
|
||||
|
||||
void bedrock::thread_context_destroy(core_window_t * wd)
|
||||
{
|
||||
bedrock::thread_context * thr = get_thread_context(0);
|
||||
if(thr && thr->event_window == wd)
|
||||
thr->event_window = nullptr;
|
||||
}
|
||||
|
||||
void bedrock::thread_context_lazy_refresh()
|
||||
{
|
||||
thread_context* thrd = get_thread_context(0);
|
||||
if(thrd && thrd->event_window)
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
|
||||
//Dynamically set a cursor for a window
|
||||
void bedrock::set_cursor(core_window_t* wd, nana::cursor cur, thread_context* thrd)
|
||||
{
|
||||
@ -1421,32 +1338,6 @@ namespace detail
|
||||
if (rev_wd)
|
||||
set_cursor(rev_wd, rev_wd->predef_cursor, thrd);
|
||||
}
|
||||
|
||||
void bedrock::_m_event_filter(event_code event_id, core_window_t * wd, thread_context * thrd)
|
||||
{
|
||||
auto not_state_cur = (wd->root_widget->other.attribute.root->state_cursor == nana::cursor::arrow);
|
||||
|
||||
switch(event_id)
|
||||
{
|
||||
case event_code::mouse_enter:
|
||||
if (not_state_cur)
|
||||
set_cursor(wd, wd->predef_cursor, thrd);
|
||||
break;
|
||||
case event_code::mouse_leave:
|
||||
if (not_state_cur && (wd->predef_cursor != cursor::arrow))
|
||||
set_cursor(wd, nana::cursor::arrow, thrd);
|
||||
break;
|
||||
case event_code::destroy:
|
||||
if (wd->root_widget->other.attribute.root->state_cursor_window == wd)
|
||||
undefine_state_cursor(wd, thrd);
|
||||
|
||||
if(wd == thrd->cursor.window)
|
||||
set_cursor(wd, cursor::arrow, thrd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}//end namespace detail
|
||||
}//end namespace nana
|
||||
#endif //NANA_POSIX && NANA_X11
|
||||
|
||||
101
source/gui/detail/bedrock_types.hpp
Normal file
101
source/gui/detail/bedrock_types.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef NANA_GUI_DETAIL_BEDROCK_TYPES_INCLUDED
|
||||
#define NANA_GUI_DETAIL_BEDROCK_TYPES_INCLUDED
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include <nana/gui/detail/color_schemes.hpp>
|
||||
#include <nana/gui/detail/events_operation.hpp>
|
||||
#include <nana/gui/detail/window_manager.hpp>
|
||||
#include <set>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct bedrock::pi_data
|
||||
{
|
||||
color_schemes scheme;
|
||||
events_operation evt_operation;
|
||||
window_manager wd_manager;
|
||||
std::set<core_window_t*> auto_form_set;
|
||||
bool shortkey_occurred{ false };
|
||||
|
||||
struct menu_rep
|
||||
{
|
||||
core_window_t* taken_window{ nullptr };
|
||||
bool delay_restore{ false };
|
||||
native_window_type window{ nullptr };
|
||||
native_window_type owner{ nullptr };
|
||||
bool has_keyboard{ false };
|
||||
}menu;
|
||||
};
|
||||
|
||||
|
||||
#ifdef NANA_WINDOWS
|
||||
struct bedrock::thread_context
|
||||
{
|
||||
unsigned event_pump_ref_count{0};
|
||||
int window_count{0}; //The number of windows
|
||||
core_window_t* event_window{nullptr};
|
||||
|
||||
struct platform_detail_tag
|
||||
{
|
||||
wchar_t keychar;
|
||||
}platform;
|
||||
|
||||
struct cursor_tag
|
||||
{
|
||||
core_window_t * window;
|
||||
native_window_type native_handle;
|
||||
nana::cursor predef_cursor;
|
||||
HCURSOR handle;
|
||||
}cursor;
|
||||
|
||||
thread_context()
|
||||
{
|
||||
cursor.window = nullptr;
|
||||
cursor.native_handle = nullptr;
|
||||
cursor.predef_cursor = nana::cursor::arrow;
|
||||
cursor.handle = nullptr;
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct bedrock::thread_context
|
||||
{
|
||||
unsigned event_pump_ref_count{0};
|
||||
|
||||
int window_count{0}; //The number of windows
|
||||
core_window_t* event_window{nullptr};
|
||||
bool is_alt_pressed{false};
|
||||
bool is_ctrl_pressed{false};
|
||||
|
||||
struct platform_detail_tag
|
||||
{
|
||||
native_window_type motion_window;
|
||||
nana::point motion_pointer_pos;
|
||||
}platform;
|
||||
|
||||
struct cursor_tag
|
||||
{
|
||||
core_window_t * window;
|
||||
native_window_type native_handle;
|
||||
nana::cursor predef_cursor;
|
||||
Cursor handle;
|
||||
}cursor;
|
||||
|
||||
thread_context()
|
||||
{
|
||||
cursor.window = nullptr;
|
||||
cursor.native_handle = nullptr;
|
||||
cursor.predef_cursor = nana::cursor::arrow;
|
||||
cursor.handle = 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
#endif
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Bedrock Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -14,8 +14,7 @@
|
||||
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include <nana/gui/detail/bedrock_pi_data.hpp>
|
||||
#include "bedrock_types.hpp"
|
||||
#include <nana/gui/detail/event_code.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <nana/system/timepiece.hpp>
|
||||
@ -36,6 +35,8 @@
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
||||
#include "bedrock_types.hpp"
|
||||
|
||||
typedef void (CALLBACK *win_event_proc_t)(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
|
||||
|
||||
namespace nana
|
||||
@ -135,34 +136,6 @@ namespace detail
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct bedrock::thread_context
|
||||
{
|
||||
unsigned event_pump_ref_count{0};
|
||||
int window_count{0}; //The number of windows
|
||||
core_window_t* event_window{nullptr};
|
||||
|
||||
struct platform_detail_tag
|
||||
{
|
||||
wchar_t keychar;
|
||||
}platform;
|
||||
|
||||
struct cursor_tag
|
||||
{
|
||||
core_window_t * window;
|
||||
native_window_type native_handle;
|
||||
nana::cursor predef_cursor;
|
||||
HCURSOR handle;
|
||||
}cursor;
|
||||
|
||||
thread_context()
|
||||
{
|
||||
cursor.window = nullptr;
|
||||
cursor.native_handle = nullptr;
|
||||
cursor.predef_cursor = nana::cursor::arrow;
|
||||
cursor.handle = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct bedrock::private_impl
|
||||
{
|
||||
typedef std::map<unsigned, thread_context> thr_context_container;
|
||||
@ -1176,10 +1149,10 @@ namespace detail
|
||||
std::unique_ptr<wchar_t[]> varbuf;
|
||||
std::size_t bufsize = 0;
|
||||
|
||||
unsigned size = ::DragQueryFile(drop, 0xFFFFFFFF, 0, 0);
|
||||
unsigned size = ::DragQueryFile(drop, 0xFFFFFFFF, nullptr, 0);
|
||||
for(unsigned i = 0; i < size; ++i)
|
||||
{
|
||||
unsigned reqlen = ::DragQueryFile(drop, i, 0, 0) + 1;
|
||||
unsigned reqlen = ::DragQueryFile(drop, i, nullptr, 0) + 1;
|
||||
if(bufsize < reqlen)
|
||||
{
|
||||
varbuf.reset(new wchar_t[reqlen]);
|
||||
@ -1187,8 +1160,7 @@ namespace detail
|
||||
}
|
||||
|
||||
::DragQueryFile(drop, i, varbuf.get(), reqlen);
|
||||
|
||||
dropfiles.files.emplace_back(to_utf8(varbuf.get()));
|
||||
dropfiles.files.emplace_back(varbuf.get());
|
||||
}
|
||||
|
||||
while(msgwnd && (msgwnd->flags.dropable == false))
|
||||
@ -1594,12 +1566,6 @@ namespace detail
|
||||
return ::DefWindowProc(root_window, message, wParam, lParam);
|
||||
}
|
||||
|
||||
auto bedrock::focus() ->core_window_t*
|
||||
{
|
||||
core_window_t* wd = wd_manager().root(native_interface::get_focus_window());
|
||||
return (wd ? wd->other.attribute.root->focus : nullptr);
|
||||
}
|
||||
|
||||
void bedrock::get_key_state(arg_keyboard& kb)
|
||||
{
|
||||
kb.alt = (0 != (::GetKeyState(VK_MENU) & 0x80));
|
||||
@ -1677,42 +1643,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
bool bedrock::emit(event_code evt_code, core_window_t* wd, const ::nana::event_arg& arg, bool ask_update, thread_context* thrd, const bool bForce__EmitInternal)
|
||||
{
|
||||
if (wd_manager().available(wd) == false)
|
||||
return false;
|
||||
|
||||
basic_window* prev_event_wd = nullptr;
|
||||
if (thrd)
|
||||
{
|
||||
prev_event_wd = thrd->event_window;
|
||||
thrd->event_window = wd;
|
||||
_m_event_filter(evt_code, wd, thrd);
|
||||
}
|
||||
|
||||
using update_state = basic_window::update_state;
|
||||
|
||||
if (update_state::none == wd->other.upd_state)
|
||||
wd->other.upd_state = update_state::lazy;
|
||||
|
||||
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
|
||||
|
||||
bool good_wd = false;
|
||||
if (wd_manager().available(wd))
|
||||
{
|
||||
//Ignore ask_update if update state is refreshed.
|
||||
if (ask_update || (update_state::refreshed == wd->other.upd_state))
|
||||
wd_manager().do_lazy_refresh(wd, false);
|
||||
else
|
||||
wd->other.upd_state = update_state::none;
|
||||
|
||||
good_wd = true;
|
||||
}
|
||||
|
||||
if (thrd) thrd->event_window = prev_event_wd;
|
||||
return good_wd;
|
||||
}
|
||||
|
||||
const wchar_t* translate(cursor id)
|
||||
{
|
||||
const wchar_t* name = IDC_ARROW;
|
||||
@ -1741,20 +1671,6 @@ namespace detail
|
||||
return name;
|
||||
}
|
||||
|
||||
void bedrock::thread_context_destroy(core_window_t * wd)
|
||||
{
|
||||
auto * thr = get_thread_context(0);
|
||||
if (thr && thr->event_window == wd)
|
||||
thr->event_window = nullptr;
|
||||
}
|
||||
|
||||
void bedrock::thread_context_lazy_refresh()
|
||||
{
|
||||
auto* thrd = get_thread_context(0);
|
||||
if (thrd && thrd->event_window)
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
|
||||
//Dynamically set a cursor for a window
|
||||
void bedrock::set_cursor(core_window_t* wd, nana::cursor cur, thread_context* thrd)
|
||||
{
|
||||
@ -1847,32 +1763,6 @@ namespace detail
|
||||
::ShowCursor(FALSE);
|
||||
::SetCursor(rev_handle);
|
||||
}
|
||||
|
||||
void bedrock::_m_event_filter(event_code event_id, core_window_t * wd, thread_context * thrd)
|
||||
{
|
||||
auto not_state_cur = (wd->root_widget->other.attribute.root->state_cursor == nana::cursor::arrow);
|
||||
|
||||
switch(event_id)
|
||||
{
|
||||
case event_code::mouse_enter:
|
||||
if (not_state_cur)
|
||||
set_cursor(wd, wd->predef_cursor, thrd);
|
||||
break;
|
||||
case event_code::mouse_leave:
|
||||
if (not_state_cur && (wd->predef_cursor != cursor::arrow))
|
||||
set_cursor(wd, cursor::arrow, thrd);
|
||||
break;
|
||||
case event_code::destroy:
|
||||
if (wd->root_widget->other.attribute.root->state_cursor_window == wd)
|
||||
undefine_state_cursor(wd, thrd);
|
||||
|
||||
if(wd == thrd->cursor.window)
|
||||
set_cursor(wd, cursor::arrow, thrd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}//end namespace detail
|
||||
}//end namespace nana
|
||||
#endif //NANA_WINDOWS
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Color Schemes
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -24,6 +24,14 @@ namespace nana
|
||||
: color_(std::make_shared<color>(clr))
|
||||
{}
|
||||
|
||||
color_proxy::color_proxy(color_argb clr)
|
||||
: color_(std::make_shared<color>(clr))
|
||||
{}
|
||||
|
||||
color_proxy::color_proxy(color_rgba clr)
|
||||
: color_(std::make_shared<color>(clr))
|
||||
{}
|
||||
|
||||
color_proxy::color_proxy(colors clr)
|
||||
: color_(std::make_shared<color>(clr))
|
||||
{}
|
||||
@ -47,6 +55,18 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
color_proxy& color_proxy::operator = (color_argb clr)
|
||||
{
|
||||
color_ = std::make_shared<::nana::color>(clr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
color_proxy& color_proxy::operator = (color_rgba clr)
|
||||
{
|
||||
color_ = std::make_shared<::nana::color>(clr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
color_proxy& color_proxy::operator = (colors clr)
|
||||
{
|
||||
color_ = std::make_shared<::nana::color>(clr);
|
||||
@ -58,9 +78,16 @@ namespace nana
|
||||
return *color_;
|
||||
}
|
||||
|
||||
color color_proxy::get(const color& default_color) const
|
||||
{
|
||||
if (color_ && !color_->invisible())
|
||||
return *color_;
|
||||
return default_color;
|
||||
}
|
||||
|
||||
color_proxy::operator color() const
|
||||
{
|
||||
return *color_;
|
||||
return (color_ ? *color_ : color{});
|
||||
}
|
||||
//end class color_proxy
|
||||
|
||||
|
||||
@ -136,11 +136,12 @@ namespace nana
|
||||
evt_disabled_ &= ~(1 << static_cast<int>(evt_code)); // clear
|
||||
}
|
||||
|
||||
void drawer_trigger::filter_event(const std::vector<event_code> evt_codes, const bool bDisabled)
|
||||
void drawer_trigger::filter_event(const std::vector<event_code>& evt_codes, const bool bDisabled)
|
||||
{
|
||||
const auto it_end = evt_codes.end();
|
||||
for (auto it = evt_codes.begin(); it != it_end; it++)
|
||||
filter_event(*it, bDisabled);
|
||||
for (auto evt_code : evt_codes)
|
||||
{
|
||||
filter_event(evt_code, bDisabled);
|
||||
}
|
||||
}
|
||||
|
||||
void drawer_trigger::filter_event(const event_filter_status& evt_all_states)
|
||||
|
||||
@ -34,8 +34,10 @@ namespace nana
|
||||
|
||||
|
||||
//class docker_base
|
||||
docker_base::docker_base(event_interface* evt, bool unignorable_flag)
|
||||
: event_ptr(evt), unignorable(unignorable_flag)
|
||||
docker_base::docker_base(event_interface* evt, bool unignorable_flag):
|
||||
event_ptr(evt),
|
||||
flag_deleted(false),
|
||||
unignorable(unignorable_flag)
|
||||
{}
|
||||
|
||||
detail::event_interface * docker_base::get_event() const
|
||||
|
||||
@ -46,7 +46,7 @@ namespace nana{
|
||||
|
||||
void umake(window wd);
|
||||
|
||||
std::vector<unsigned long> keys(window wd) const;
|
||||
const std::vector<unsigned long>* keys(window wd) const;
|
||||
|
||||
window find(unsigned long key) const;
|
||||
private:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Platform Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
#include "../../paint/image_accessor.hpp"
|
||||
|
||||
|
||||
namespace nana{
|
||||
namespace detail{
|
||||
|
||||
@ -371,6 +372,8 @@ namespace nana{
|
||||
}
|
||||
|
||||
Window parent = (owner ? reinterpret_cast<Window>(owner) : restrict::spec.root_window());
|
||||
|
||||
//The position passed to XCreateWindow is a screen coordinate.
|
||||
nana::point pos(r.x, r.y);
|
||||
if((false == nested) && owner)
|
||||
{
|
||||
@ -396,7 +399,9 @@ namespace nana{
|
||||
{
|
||||
auto origin_owner = (owner ? owner : reinterpret_cast<native_window_type>(restrict::spec.root_window()));
|
||||
restrict::spec.make_owner(origin_owner, reinterpret_cast<native_window_type>(handle));
|
||||
exposed_positions[handle] = pos;
|
||||
|
||||
//The exposed_position is a relative position to its owner/parent.
|
||||
exposed_positions[handle] = r.position();
|
||||
}
|
||||
|
||||
XChangeWindowAttributes(disp, handle, attr_mask, &win_attr);
|
||||
@ -844,12 +849,17 @@ namespace nana{
|
||||
#endif
|
||||
}
|
||||
|
||||
void native_interface::refresh_window(native_window_type wd)
|
||||
void native_interface::refresh_window(native_window_type native_wd)
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
::InvalidateRect(reinterpret_cast<HWND>(wd), nullptr, true);
|
||||
auto wd = reinterpret_cast<HWND>(native_wd);
|
||||
RECT r;
|
||||
::GetClientRect(wd, &r);
|
||||
::InvalidateRect(wd, &r, FALSE);
|
||||
#elif defined(NANA_X11)
|
||||
static_cast<void>(wd); //eliminate unused parameter compiler warning.
|
||||
Display * disp = restrict::spec.open_display();
|
||||
::XClearArea(disp, reinterpret_cast<Window>(native_wd), 0, 0, 1, 1, true);
|
||||
::XFlush(disp);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -945,13 +955,6 @@ namespace nana{
|
||||
auto fm_extents = window_frame_extents(wd);
|
||||
origin.x = -fm_extents.left;
|
||||
origin.y = -fm_extents.top;
|
||||
|
||||
if(reinterpret_cast<Window>(coord_wd) != restrict::spec.root_window())
|
||||
{
|
||||
fm_extents = window_frame_extents(coord_wd);
|
||||
origin.x += fm_extents.left;
|
||||
origin.y += fm_extents.top;
|
||||
}
|
||||
}
|
||||
else
|
||||
coord_wd = get_window(wd, window_relationship::parent);
|
||||
@ -1009,9 +1012,11 @@ namespace nana{
|
||||
auto const owner = restrict::spec.get_owner(wd);
|
||||
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
|
||||
{
|
||||
auto origin = window_position(owner);
|
||||
x += origin.x;
|
||||
y += origin.y;
|
||||
int origin_x, origin_y;
|
||||
Window child_useless_for_API;
|
||||
::XTranslateCoordinates(disp, reinterpret_cast<Window>(owner), restrict::spec.root_window(), 0, 0, &origin_x, &origin_y, &child_useless_for_API);
|
||||
x += origin_x;
|
||||
y += origin_y;
|
||||
}
|
||||
|
||||
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
||||
@ -1058,7 +1063,6 @@ namespace nana{
|
||||
XSizeHints hints;
|
||||
nana::detail::platform_scope_guard psg;
|
||||
|
||||
|
||||
//Returns if the requested rectangle is same with the current rectangle.
|
||||
//In some X-Server versions/implementations, XMapWindow() doesn't generate
|
||||
//a ConfigureNotify if the requested rectangle is same with the current rectangle.
|
||||
@ -1098,9 +1102,11 @@ namespace nana{
|
||||
auto const owner = restrict::spec.get_owner(wd);
|
||||
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
|
||||
{
|
||||
auto origin = window_position(owner);
|
||||
x += origin.x;
|
||||
y += origin.y;
|
||||
int origin_x, origin_y;
|
||||
Window child_useless_for_API;
|
||||
::XTranslateCoordinates(disp, reinterpret_cast<Window>(owner), restrict::spec.root_window(), 0, 0, &origin_x, &origin_y, &child_useless_for_API);
|
||||
x += origin_x;
|
||||
y += origin_y;
|
||||
}
|
||||
|
||||
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
||||
@ -1438,6 +1444,8 @@ namespace nana{
|
||||
{
|
||||
if(owner)
|
||||
return owner;
|
||||
|
||||
return x11_parent_window(wd);
|
||||
}
|
||||
else if(window_relationship::owner == rsp)
|
||||
return owner;
|
||||
@ -1580,14 +1588,17 @@ namespace nana{
|
||||
pos.y = point.y;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#elif defined(NANA_X11)
|
||||
nana::detail::platform_scope_guard psg;
|
||||
int x = pos.x, y = pos.y;
|
||||
Window child;
|
||||
return (True == ::XTranslateCoordinates(restrict::spec.open_display(),
|
||||
reinterpret_cast<Window>(wd), restrict::spec.root_window(), x, y, &pos.x, &pos.y, &child));
|
||||
if(True == ::XTranslateCoordinates(restrict::spec.open_display(),
|
||||
reinterpret_cast<Window>(wd), restrict::spec.root_window(), x, y, &pos.x, &pos.y, &child))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool native_interface::calc_window_point(native_window_type wd, nana::point& pos)
|
||||
@ -1600,14 +1611,16 @@ namespace nana{
|
||||
pos.y = point.y;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#elif defined(NANA_X11)
|
||||
nana::detail::platform_scope_guard psg;
|
||||
int x = pos.x, y = pos.y;
|
||||
Window child;
|
||||
return (True == ::XTranslateCoordinates(restrict::spec.open_display(),
|
||||
restrict::spec.root_window(), reinterpret_cast<Window>(wd), x, y, &pos.x, &pos.y, &child));
|
||||
if(True == ::XTranslateCoordinates(restrict::spec.open_display(), restrict::spec.root_window(), reinterpret_cast<Window>(wd), x, y, &pos.x, &pos.y, &child))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
native_window_type native_interface::find_window(int x, int y)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Window Layout Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -66,20 +66,9 @@ namespace nana
|
||||
nana::point p_src;
|
||||
for (auto & el : blocks)
|
||||
{
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if (category::flags::frame == el.window->other.category)
|
||||
{
|
||||
native_window_type container = el.window->other.attribute.frame->container;
|
||||
native_interface::refresh_window(container);
|
||||
graph.bitblt(el.r, container);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
p_src.x = el.r.x - el.window->pos_root.x;
|
||||
p_src.y = el.r.y - el.window->pos_root.y;
|
||||
graph.bitblt(el.r, (el.window->drawer.graphics), p_src);
|
||||
}
|
||||
p_src.x = el.r.x - el.window->pos_root.x;
|
||||
p_src.y = el.r.y - el.window->pos_root.y;
|
||||
graph.bitblt(el.r, (el.window->drawer.graphics), p_src);
|
||||
|
||||
_m_paste_children(el.window, false, req_refresh_children, el.r, graph, nana::point{});
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Window Manager Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -111,17 +111,17 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned long> shortkey_container::keys(window wd) const
|
||||
const std::vector<unsigned long>* shortkey_container::keys(window wd) const
|
||||
{
|
||||
if (wd)
|
||||
{
|
||||
for (auto & m : impl_->base)
|
||||
{
|
||||
if (m.handle == wd)
|
||||
return m.keys;
|
||||
return &m.keys;
|
||||
}
|
||||
}
|
||||
return{};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
window shortkey_container::find(unsigned long key) const
|
||||
@ -513,12 +513,7 @@ namespace detail
|
||||
if (owner->flags.destroying)
|
||||
throw std::runtime_error("the specified owner is destoryed");
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
native = (category::flags::frame == owner->other.category ?
|
||||
owner->other.attribute.frame->container : owner->root_widget->root);
|
||||
#else
|
||||
native = owner->root_widget->root;
|
||||
#endif
|
||||
r.x += owner->pos_root.x;
|
||||
r.y += owner->pos_root.y;
|
||||
}
|
||||
@ -550,11 +545,6 @@ namespace detail
|
||||
wd->bind_native_window(result.native_handle, result.width, result.height, result.extra_width, result.extra_height, value->root_graph);
|
||||
impl_->wd_register.insert(wd);
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if (owner && (category::flags::frame == owner->other.category))
|
||||
insert_frame(owner, wd);
|
||||
#endif
|
||||
|
||||
bedrock::inc_window(wd->thread_id);
|
||||
this->icon(wd, impl_->default_icon_small, impl_->default_icon_big);
|
||||
return wd;
|
||||
@ -562,56 +552,6 @@ namespace detail
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
window_manager::core_window_t* window_manager::create_frame(core_window_t* parent, const rectangle& r, widget* wdg)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
|
||||
if (impl_->wd_register.available(parent) == false) return nullptr;
|
||||
|
||||
core_window_t * wd = new core_window_t(parent, widget_notifier_interface::get_notifier(wdg), r, (category::frame_tag**)nullptr);
|
||||
wd->frame_window(native_interface::create_child_window(parent->root, rectangle(wd->pos_root.x, wd->pos_root.y, r.width, r.height)));
|
||||
impl_->wd_register.insert(wd, wd->thread_id);
|
||||
|
||||
//Insert the frame_widget into its root frames container.
|
||||
wd->root_widget->other.attribute.root->frames.push_back(wd);
|
||||
return (wd);
|
||||
}
|
||||
|
||||
|
||||
bool window_manager::insert_frame(core_window_t* frame, native_window wd)
|
||||
{
|
||||
if(frame)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if(category::flags::frame == frame->other.category)
|
||||
frame->other.attribute.frame->attach.push_back(wd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool window_manager::insert_frame(core_window_t* frame, core_window_t* wd)
|
||||
{
|
||||
if(frame)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if(category::flags::frame == frame->other.category)
|
||||
{
|
||||
if (impl_->wd_register.available(wd) && (category::flags::root == wd->other.category) && wd->root != frame->root)
|
||||
{
|
||||
frame->other.attribute.frame->attach.push_back(wd->root);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
window_manager::core_window_t* window_manager::create_widget(core_window_t* parent, const rectangle& r, bool is_lite, widget* wdg)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
@ -706,11 +646,7 @@ namespace detail
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return;
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if((category::flags::root == wd->other.category) || (category::flags::frame != wd->other.category))
|
||||
#else
|
||||
if (category::flags::root == wd->other.category)
|
||||
#endif
|
||||
{
|
||||
impl_->misc_register.erase(wd->root);
|
||||
impl_->wd_register.remove(wd);
|
||||
@ -749,20 +685,7 @@ namespace detail
|
||||
|
||||
if(visible != wd->visible)
|
||||
{
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
native_window_type nv = nullptr;
|
||||
switch(wd->other.category)
|
||||
{
|
||||
case category::flags::root:
|
||||
nv = wd->root; break;
|
||||
case category::flags::frame:
|
||||
nv = wd->other.attribute.frame->container; break;
|
||||
default: //category::widget_tag, category::lite_widget_tag
|
||||
break;
|
||||
}
|
||||
#else
|
||||
auto nv = (category::flags::root == wd->other.category ? wd->root : nullptr);
|
||||
#endif
|
||||
|
||||
if(visible && wd->effect.bground)
|
||||
window_layer::make_bground(wd);
|
||||
@ -1012,22 +935,11 @@ namespace detail
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
else if(category::flags::frame == wd->other.category)
|
||||
{
|
||||
native_interface::window_size(wd->other.attribute.frame->container, sz);
|
||||
for(auto natwd : wd->other.attribute.frame->attach)
|
||||
native_interface::window_size(natwd, sz);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
else if(wd->effect.bground && wd->parent)
|
||||
{
|
||||
//update the bground buffer of glass window.
|
||||
if(wd->effect.bground && wd->parent)
|
||||
{
|
||||
wd->other.glass_buffer.make(sz);
|
||||
window_layer::make_bground(wd);
|
||||
}
|
||||
wd->other.glass_buffer.make(sz);
|
||||
window_layer::make_bground(wd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1072,8 +984,19 @@ namespace detail
|
||||
auto parent = wd->parent;
|
||||
while (parent)
|
||||
{
|
||||
if (parent->flags.refreshing)
|
||||
if(parent->flags.ignore_child_mapping || parent->flags.refreshing)
|
||||
{
|
||||
auto top = parent;
|
||||
while(parent->parent)
|
||||
{
|
||||
parent = parent->parent;
|
||||
if(parent->flags.ignore_child_mapping || parent->flags.refreshing)
|
||||
top = parent;
|
||||
}
|
||||
|
||||
top->other.mapping_requester.push_back(wd);
|
||||
return;
|
||||
}
|
||||
parent = parent->parent;
|
||||
}
|
||||
|
||||
@ -1091,6 +1014,12 @@ namespace detail
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return false;
|
||||
|
||||
if ((wd->other.category == category::flags::root) && wd->is_draw_through())
|
||||
{
|
||||
native_interface::refresh_window(wd->root);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (wd->displayed())
|
||||
{
|
||||
using paint_operation = window_layer::paint_operation;
|
||||
@ -1162,42 +1091,24 @@ namespace detail
|
||||
window_layer::paint(wd, paint_operation::try_refresh, refresh_tree); //only refreshing if it has an invisible parent
|
||||
}
|
||||
wd->other.upd_state = core_window_t::update_state::none;
|
||||
return;
|
||||
wd->other.mapping_requester.clear();
|
||||
}
|
||||
|
||||
//get_graphics
|
||||
//@brief: Get a copy of the graphics object of a window.
|
||||
// the copy of the graphics object has a same buf handle with the graphics object's, they are count-refered
|
||||
// here returns a reference that because the framework does not guarantee the wnd's
|
||||
// graphics object available after a get_graphics call.
|
||||
bool window_manager::get_graphics(core_window_t* wd, nana::paint::graphics& result)
|
||||
void window_manager::map_requester(core_window_t* wd)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (!impl_->wd_register.available(wd))
|
||||
return false;
|
||||
|
||||
result.make(wd->drawer.graphics.size());
|
||||
result.bitblt(0, 0, wd->drawer.graphics);
|
||||
window_layer::paste_children_to_graphics(wd, result);
|
||||
return true;
|
||||
}
|
||||
if (false == impl_->wd_register.available(wd))
|
||||
return;
|
||||
|
||||
bool window_manager::get_visual_rectangle(core_window_t* wd, nana::rectangle& r)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
return (impl_->wd_register.available(wd) ?
|
||||
window_layer::read_visual_rectangle(wd, r) :
|
||||
false);
|
||||
}
|
||||
if (wd->visible_parents())
|
||||
{
|
||||
for(auto requestor : wd->other.mapping_requester)
|
||||
this->map(requestor, true);
|
||||
}
|
||||
|
||||
std::vector<window_manager::core_window_t*> window_manager::get_children(core_window_t* wd) const
|
||||
{
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
return wd->children;
|
||||
return{};
|
||||
wd->other.mapping_requester.clear();
|
||||
}
|
||||
|
||||
bool window_manager::set_parent(core_window_t* wd, core_window_t* newpa)
|
||||
@ -1405,7 +1316,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// preconditions of get_tabstop: tabstop is not empty and at least one window is visible
|
||||
window_manager::core_window_t* get_tabstop(window_manager::core_window_t* wd, bool forward)
|
||||
{
|
||||
@ -1518,9 +1428,8 @@ namespace detail
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
{
|
||||
auto object = root_runtime(wd->root);
|
||||
if(object)
|
||||
return object->shortkeys.make(reinterpret_cast<window>(wd), key);
|
||||
//the root runtime must exist, because the wd is valid. Otherse, it's bug of library
|
||||
return root_runtime(wd->root)->shortkeys.make(reinterpret_cast<window>(wd), key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1543,35 +1452,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
auto window_manager::shortkeys(core_window_t* wd, bool with_children) -> std::vector<std::pair<core_window_t*, unsigned long>>
|
||||
{
|
||||
std::vector<std::pair<core_window_t*, unsigned long>> result;
|
||||
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
{
|
||||
auto root_rt = root_runtime(wd->root);
|
||||
if (root_rt)
|
||||
{
|
||||
auto keys = root_rt->shortkeys.keys(reinterpret_cast<window>(wd));
|
||||
for (auto key : keys)
|
||||
result.emplace_back(wd, key);
|
||||
|
||||
if (with_children)
|
||||
{
|
||||
for (auto child : wd->children)
|
||||
{
|
||||
auto child_keys = shortkeys(child, true);
|
||||
std::copy(child_keys.begin(), child_keys.end(), std::back_inserter(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
window_manager::core_window_t* window_manager::find_shortkey(native_window_type native_window, unsigned long key)
|
||||
{
|
||||
if(native_window)
|
||||
@ -1631,7 +1511,6 @@ namespace detail
|
||||
{
|
||||
auto * const wdpa = wd->parent;
|
||||
|
||||
|
||||
bool established = (for_new && (wdpa != for_new));
|
||||
decltype(for_new->root_widget->other.attribute.root) pa_root_attr = nullptr;
|
||||
|
||||
@ -1657,7 +1536,7 @@ namespace detail
|
||||
if (root_attr->menubar && check_tree(wd, root_attr->menubar))
|
||||
root_attr->menubar = nullptr;
|
||||
|
||||
sk_holder = shortkeys(wd, true);
|
||||
_m_shortkeys(wd, true, sk_holder);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1752,17 +1631,6 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if (category::flags::frame == wd->other.category)
|
||||
{
|
||||
//remove the frame handle from the WM frames manager.
|
||||
utl::erase(root_attr->frames, wd);
|
||||
|
||||
if (established)
|
||||
pa_root_attr->frames.push_back(wd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (established)
|
||||
{
|
||||
wd->parent = for_new;
|
||||
@ -1851,18 +1719,6 @@ namespace detail
|
||||
wd->drawer.detached();
|
||||
wd->widget_notifier->destroy();
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if(category::flags::frame == wd->other.category)
|
||||
{
|
||||
//The frame widget does not have an owner, and close their element windows without activating owner.
|
||||
//close the frame container window, it's a native window.
|
||||
for(auto i : wd->other.attribute.frame->attach)
|
||||
native_interface::close_window(i);
|
||||
|
||||
native_interface::close_window(wd->other.attribute.frame->container);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(wd->other.category != category::flags::root) //Not a root window
|
||||
impl_->wd_register.remove(wd);
|
||||
|
||||
@ -1875,18 +1731,9 @@ namespace detail
|
||||
if(category::flags::root != wd->other.category) //A root widget always starts at (0, 0) and its childs are not to be changed
|
||||
{
|
||||
wd->pos_root += delta;
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
if (category::flags::frame != wd->other.category)
|
||||
{
|
||||
if (wd->annex.caret_ptr && wd->annex.caret_ptr->visible())
|
||||
wd->annex.caret_ptr->update();
|
||||
}
|
||||
else
|
||||
native_interface::move_window(wd->other.attribute.frame->container, wd->pos_root.x, wd->pos_root.y);
|
||||
#else
|
||||
|
||||
if (wd->annex.caret_ptr && wd->annex.caret_ptr->visible())
|
||||
wd->annex.caret_ptr->update();
|
||||
#endif
|
||||
|
||||
if (wd->displayed() && wd->effect.bground)
|
||||
window_layer::make_bground(wd);
|
||||
@ -1901,6 +1748,28 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
void window_manager::_m_shortkeys(core_window_t* wd, bool with_children, std::vector<std::pair<core_window_t*, unsigned long>>& keys) const
|
||||
{
|
||||
if (impl_->wd_register.available(wd))
|
||||
{
|
||||
//The root_rt must exist, because wd is valid. Otherwise, it's a bug of the library.
|
||||
auto root_rt = root_runtime(wd->root);
|
||||
|
||||
auto pkeys = root_rt->shortkeys.keys(reinterpret_cast<window>(wd));
|
||||
if (pkeys)
|
||||
{
|
||||
for (auto key : *pkeys)
|
||||
keys.emplace_back(wd, key);
|
||||
}
|
||||
|
||||
if (with_children)
|
||||
{
|
||||
for (auto child : wd->children)
|
||||
_m_shortkeys(child, true, keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_m_find
|
||||
//@brief: find a window on root window through a given root coordinate.
|
||||
// the given root coordinate must be in the rectangle of wnd.
|
||||
|
||||
1203
source/gui/dragdrop.cpp
Normal file
1203
source/gui/dragdrop.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Dragger Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -93,9 +93,7 @@ namespace nana
|
||||
for (auto & t : targets_)
|
||||
{
|
||||
t.origin = API::window_position(t.wd);
|
||||
window owner = API::get_owner_window(t.wd);
|
||||
if (owner)
|
||||
API::calc_screen_point(owner, t.origin);
|
||||
API::calc_screen_point(API::get_owner_window(t.wd), t.origin);
|
||||
}
|
||||
break;
|
||||
case event_code::mouse_move:
|
||||
@ -108,10 +106,8 @@ namespace nana
|
||||
{
|
||||
if (API::is_window_zoomed(t.wd, true) == false)
|
||||
{
|
||||
auto owner = API::get_owner_window(t.wd);
|
||||
auto wdps = t.origin;
|
||||
if (owner)
|
||||
API::calc_window_point(owner, wdps);
|
||||
API::calc_window_point(API::get_owner_window(t.wd), wdps);
|
||||
|
||||
switch (t.move_direction)
|
||||
{
|
||||
|
||||
@ -163,7 +163,8 @@ namespace nana
|
||||
bld_fgcolor = fgcolor.blend(highlighted, 0.6);
|
||||
break;
|
||||
case element_state::disabled:
|
||||
bld_bgcolor = bld_fgcolor = static_cast<color_rgb>(0xb2b7bc);
|
||||
bld_bgcolor = static_cast<color_rgb>(0xE0E0E0);
|
||||
bld_fgcolor = static_cast<color_rgb>(0x999A9E);
|
||||
break;
|
||||
default:
|
||||
//Leave things as they are
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1228,9 +1228,10 @@ namespace nana
|
||||
impl->browse.events().click.connect_unignorable([wd, impl](const arg_click&)
|
||||
{
|
||||
impl->fbox.owner(wd);
|
||||
if (impl->fbox.show())
|
||||
auto files = impl->fbox.show();
|
||||
if(!files.empty())
|
||||
{
|
||||
impl->value = impl->fbox.file();
|
||||
impl->value = files.front().u8string();
|
||||
impl->path_edit.caption(impl->value);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Nana GUI Programming Interface Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -15,6 +15,7 @@
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include <nana/gui/detail/basic_window.hpp>
|
||||
#include <nana/gui/detail/window_manager.hpp>
|
||||
#include <nana/gui/detail/window_layout.hpp>
|
||||
#include <nana/system/platform.hpp>
|
||||
#include <nana/gui/detail/native_window_interface.hpp>
|
||||
#include <nana/gui/widgets/widget.hpp>
|
||||
@ -90,16 +91,21 @@ namespace API
|
||||
|
||||
void enum_widgets_function_base::enum_widgets(window wd, bool recursive)
|
||||
{
|
||||
using basic_window = ::nana::detail::basic_window;
|
||||
auto iwd = reinterpret_cast<nana::detail::basic_window*>(wd);
|
||||
|
||||
internal_scope_guard lock;
|
||||
|
||||
auto children = restrict::wd_manager().get_children(reinterpret_cast<basic_window*>(wd));
|
||||
for (auto child : children)
|
||||
if (restrict::wd_manager().available(iwd))
|
||||
{
|
||||
auto widget_ptr = API::get_widget(reinterpret_cast<window>(child));
|
||||
if (widget_ptr)
|
||||
//Use a copy, because enum function may close a child window and the original children container would be changed,
|
||||
//in the situation, the walking thorugh directly to the iwd->children would cause error.
|
||||
auto children = iwd->children;
|
||||
|
||||
for (auto child : children)
|
||||
{
|
||||
auto widget_ptr = API::get_widget(reinterpret_cast<window>(child));
|
||||
if (!widget_ptr)
|
||||
continue;
|
||||
|
||||
_m_enum_fn(widget_ptr);
|
||||
if (recursive)
|
||||
enum_widgets(reinterpret_cast<window>(child), recursive);
|
||||
@ -303,13 +309,6 @@ namespace API
|
||||
return reinterpret_cast<window>(restrict::wd_manager().create_widget(reinterpret_cast<basic_window*>(parent), r, true, wdg));
|
||||
}
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
window create_frame(window parent, const rectangle& r, widget* wdg)
|
||||
{
|
||||
return reinterpret_cast<window>(restrict::wd_manager().create_frame(reinterpret_cast<basic_window*>(parent), r, wdg));
|
||||
}
|
||||
#endif
|
||||
|
||||
paint::graphics* window_graphics(window wd)
|
||||
{
|
||||
internal_scope_guard isg;
|
||||
@ -411,6 +410,26 @@ namespace API
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void window_draggable(window wd, bool enabled)
|
||||
{
|
||||
auto real_wd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(real_wd))
|
||||
real_wd->flags.draggable = enabled;
|
||||
}
|
||||
|
||||
bool window_draggable(window wd)
|
||||
{
|
||||
auto real_wd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(real_wd))
|
||||
return real_wd->flags.draggable;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}//end namespace dev
|
||||
|
||||
widget* get_widget(window wd)
|
||||
@ -580,34 +599,6 @@ namespace API
|
||||
reinterpret_cast<basic_window*>(wd)->flags.fullscreen = v;
|
||||
}
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
bool insert_frame(window frame, native_window_type native_window)
|
||||
{
|
||||
return restrict::wd_manager().insert_frame(reinterpret_cast<basic_window*>(frame), native_window);
|
||||
}
|
||||
|
||||
native_window_type frame_container(window frame)
|
||||
{
|
||||
auto frm = reinterpret_cast<basic_window*>(frame);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(frm) && (frm->other.category == category::flags::frame))
|
||||
return frm->other.attribute.frame->container;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
native_window_type frame_element(window frame, unsigned index)
|
||||
{
|
||||
auto frm = reinterpret_cast<basic_window*>(frame);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(frm) && (frm->other.category == category::flags::frame))
|
||||
{
|
||||
if (index < frm->other.attribute.frame->attach.size())
|
||||
return frm->other.attribute.frame->attach.at(index);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
void close_window(window wd)
|
||||
{
|
||||
restrict::wd_manager().close(reinterpret_cast<basic_window*>(wd));
|
||||
@ -658,7 +649,15 @@ namespace API
|
||||
auto iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(iwd))
|
||||
{
|
||||
if (category::flags::root == iwd->other.category)
|
||||
{
|
||||
return reinterpret_cast<window>(restrict::wd_manager().root(
|
||||
interface_type::get_window(iwd->root, window_relationship::parent)
|
||||
));
|
||||
}
|
||||
return reinterpret_cast<window>(iwd->parent);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -942,7 +941,6 @@ namespace API
|
||||
restrict::wd_manager().update(reinterpret_cast<basic_window*>(wd), false, true);
|
||||
}
|
||||
|
||||
|
||||
void window_caption(window wd, const std::string& title_utf8)
|
||||
{
|
||||
throw_not_utf8(title_utf8);
|
||||
@ -1324,7 +1322,16 @@ namespace API
|
||||
|
||||
bool window_graphics(window wd, nana::paint::graphics& graph)
|
||||
{
|
||||
return restrict::wd_manager().get_graphics(reinterpret_cast<basic_window*>(wd), graph);
|
||||
auto iwd = reinterpret_cast<basic_window*>(wd);
|
||||
|
||||
internal_scope_guard lock;
|
||||
if (!restrict::wd_manager().available(iwd))
|
||||
return false;
|
||||
|
||||
graph.make(iwd->drawer.graphics.size());
|
||||
graph.bitblt(0, 0, iwd->drawer.graphics);
|
||||
nana::detail::window_layout::paste_children_to_graphics(iwd, graph);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool root_graphics(window wd, nana::paint::graphics& graph)
|
||||
@ -1341,7 +1348,12 @@ namespace API
|
||||
|
||||
bool get_visual_rectangle(window wd, nana::rectangle& r)
|
||||
{
|
||||
return restrict::wd_manager().get_visual_rectangle(reinterpret_cast<basic_window*>(wd), r);
|
||||
auto iwd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
if (restrict::wd_manager().available(iwd))
|
||||
return nana::detail::window_layout::read_visual_rectangle(iwd, r);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void typeface(window wd, const nana::paint::font& font)
|
||||
@ -1518,5 +1530,16 @@ namespace API
|
||||
{
|
||||
return ::nana::platform_abstraction::screen_dpi(x_requested);
|
||||
}
|
||||
|
||||
dragdrop_status window_dragdrop_status(::nana::window wd)
|
||||
{
|
||||
auto real_wd = reinterpret_cast<basic_window*>(wd);
|
||||
internal_scope_guard lock;
|
||||
|
||||
if (restrict::wd_manager().available(real_wd))
|
||||
return real_wd->other.dnd_state;
|
||||
|
||||
return dragdrop_status::not_ready;
|
||||
}
|
||||
}//end namespace API
|
||||
}//end namespace nana
|
||||
|
||||
@ -379,7 +379,12 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
void trigger::icon(const nana::paint::image& img)
|
||||
{
|
||||
if(img.empty()) return;
|
||||
if(img.empty())
|
||||
{
|
||||
delete attr_.icon;
|
||||
attr_.icon = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if(nullptr == attr_.icon)
|
||||
attr_.icon = new paint::image;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A CheckBox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -24,6 +24,7 @@ namespace nana{ namespace drawerbase
|
||||
struct drawer::implement
|
||||
{
|
||||
widget * widget_ptr;
|
||||
scheme * scheme_ptr;
|
||||
bool react;
|
||||
bool radio;
|
||||
facade<element::crook> crook;
|
||||
@ -47,6 +48,7 @@ namespace nana{ namespace drawerbase
|
||||
void drawer::attached(widget_reference widget, graph_reference)
|
||||
{
|
||||
impl_->widget_ptr = &widget;
|
||||
impl_->scheme_ptr =static_cast<scheme*>(API::dev::get_scheme(widget));
|
||||
API::dev::enable_space_click(widget, true);
|
||||
}
|
||||
|
||||
@ -78,12 +80,18 @@ namespace nana{ namespace drawerbase
|
||||
}
|
||||
|
||||
//draw crook
|
||||
#ifdef _nana_std_has_string_view
|
||||
auto txt_px = graph.text_extent_size(std::wstring_view( L"jN", 2 )).height + 2;
|
||||
#else
|
||||
auto txt_px = graph.text_extent_size(L"jN", 2).height + 2;
|
||||
#endif
|
||||
impl_->crook.draw(graph, wdg->bgcolor(), wdg->fgcolor(), rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), API::element_state(*wdg));
|
||||
|
||||
unsigned txt_px = 0, descent = 0, ileading = 0;
|
||||
graph.text_metrics(txt_px, descent, ileading);
|
||||
txt_px += (descent + 2);
|
||||
|
||||
auto e_state = API::element_state(*wdg);
|
||||
if(!wdg->enabled())
|
||||
e_state = element_state::disabled;
|
||||
|
||||
impl_->crook.draw(graph,
|
||||
impl_->scheme_ptr->square_bgcolor.get(wdg->bgcolor()), impl_->scheme_ptr->square_border_color.get(wdg->fgcolor()),
|
||||
rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), e_state);
|
||||
}
|
||||
|
||||
void drawer::mouse_down(graph_reference graph, const arg_mouse&)
|
||||
@ -208,6 +216,7 @@ namespace nana{ namespace drawerbase
|
||||
{
|
||||
e.uiobj->radio(false);
|
||||
e.uiobj->react(true);
|
||||
API::umake_event(e.eh_clicked);
|
||||
API::umake_event(e.eh_checked);
|
||||
API::umake_event(e.eh_destroy);
|
||||
API::umake_event(e.eh_keyboard);
|
||||
@ -224,7 +233,7 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
el.uiobj = &uiobj;
|
||||
|
||||
uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg)
|
||||
el.eh_checked = uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg)
|
||||
{
|
||||
if (arg.widget->checked())
|
||||
{
|
||||
@ -236,7 +245,7 @@ namespace nana{ namespace drawerbase
|
||||
}
|
||||
}, true);
|
||||
|
||||
el.eh_checked = uiobj.events().click.connect_unignorable([this](const arg_click& arg)
|
||||
el.eh_clicked = uiobj.events().click.connect_unignorable([this](const arg_click& arg)
|
||||
{
|
||||
for (auto & i : ui_container_)
|
||||
i.uiobj->check(arg.window_handle == i.uiobj->handle());
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* A Frame Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/frame.cpp
|
||||
*
|
||||
* A frame provides a way to contain the platform window in a stdex GUI Window
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/frame.hpp>
|
||||
|
||||
#ifndef WIDGET_FRAME_DEPRECATED
|
||||
|
||||
namespace nana
|
||||
{
|
||||
//class frame:: public widget_object<category::frame_tag>
|
||||
frame::frame(){}
|
||||
|
||||
frame::frame(window wd, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
}
|
||||
|
||||
frame::frame(window wd, const nana::rectangle& r, bool visible)
|
||||
{
|
||||
create(wd, r, visible);
|
||||
}
|
||||
|
||||
bool frame::insert(native_window_type wd)
|
||||
{
|
||||
return API::insert_frame(handle(), wd);
|
||||
}
|
||||
|
||||
native_window_type frame::element(unsigned index)
|
||||
{
|
||||
return API::frame_element(handle(), index);
|
||||
}
|
||||
|
||||
native_window_type frame::container() const
|
||||
{
|
||||
return API::frame_container(handle());
|
||||
}
|
||||
//end class frame
|
||||
}//end namespace nana
|
||||
|
||||
#endif
|
||||
|
||||
@ -27,121 +27,124 @@
|
||||
if(empty()) \
|
||||
throw std::logic_error("the group is invalid");
|
||||
|
||||
namespace nana{
|
||||
namespace nana
|
||||
{
|
||||
|
||||
static const char* field_title = "__nana_group_title__";
|
||||
static const char* field_options = "__nana_group_options__";
|
||||
static const char* field_title = "__nana_group_title__";
|
||||
static const char* field_options = "__nana_group_options__";
|
||||
|
||||
struct group::implement
|
||||
{
|
||||
label caption;
|
||||
align caption_align{ align::left };
|
||||
background_mode caption_mode{ background_mode::blending };
|
||||
place place_content;
|
||||
unsigned gap{2};
|
||||
std::string usr_div_str;
|
||||
|
||||
nana::size caption_dimension;
|
||||
nana::size caption_dimension;
|
||||
|
||||
std::vector<std::unique_ptr<checkbox>> options;
|
||||
radio_group * radio_logic{nullptr};
|
||||
std::vector<std::unique_ptr<checkbox>> options;
|
||||
radio_group * radio_logic{nullptr};
|
||||
|
||||
implement() = default;
|
||||
implement() = default;
|
||||
|
||||
implement(window grp_panel, ::std::string titel, bool vsb, unsigned gap=2)
|
||||
: caption (grp_panel, std::move(titel), vsb),
|
||||
place_content{grp_panel},
|
||||
gap{gap}
|
||||
{
|
||||
}
|
||||
implement(window grp_panel, ::std::string titel, bool vsb, unsigned gap=2)
|
||||
: caption (grp_panel, std::move(titel), vsb),
|
||||
place_content{grp_panel},
|
||||
gap{gap}
|
||||
{
|
||||
}
|
||||
|
||||
void create(window pnl)
|
||||
{
|
||||
caption.create(pnl);
|
||||
caption.caption("");
|
||||
place_content.bind(pnl);
|
||||
void create(window pnl)
|
||||
{
|
||||
caption.create(pnl);
|
||||
caption.caption("");
|
||||
place_content.bind(pnl);
|
||||
|
||||
if (!radio_logic)
|
||||
radio_logic = new radio_group;
|
||||
}
|
||||
if (!radio_logic)
|
||||
radio_logic = new radio_group;
|
||||
}
|
||||
|
||||
void update_div()
|
||||
{
|
||||
const std::size_t padding = 10;
|
||||
caption_dimension = caption.measure(1000);
|
||||
caption_dimension.width += 1;
|
||||
void update_div()
|
||||
{
|
||||
const std::size_t padding = 10;
|
||||
caption_dimension = caption.measure(1000);
|
||||
caption_dimension.width += 1;
|
||||
|
||||
std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
|
||||
std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
|
||||
|
||||
div += "<weight=" + std::to_string(caption_dimension.height) + " ";
|
||||
div += "<weight=" + std::to_string(caption_dimension.height) + " ";
|
||||
|
||||
if (align::left == caption_align)
|
||||
div += "<weight=" + std::to_string(padding) + ">";
|
||||
else
|
||||
div += "<>"; //right or center
|
||||
if (align::left == caption_align)
|
||||
div += "<weight=" + std::to_string(padding) + ">";
|
||||
else
|
||||
div += "<>"; //right or center
|
||||
|
||||
div += "<" + std::string{ field_title } + " weight=" + std::to_string(caption_dimension.width) + ">";
|
||||
div += "<" + std::string{ field_title } + " weight=" + std::to_string(caption_dimension.width) + ">";
|
||||
|
||||
if (align::right == caption_align)
|
||||
div += "<weight=" + std::to_string(padding) + ">";
|
||||
else if (align::center == caption_align)
|
||||
div += "<>";
|
||||
if (align::right == caption_align)
|
||||
div += "<weight=" + std::to_string(padding) + ">";
|
||||
else if (align::center == caption_align)
|
||||
div += "<>";
|
||||
|
||||
div += "><<vert margin=5 " + std::string(field_options) + ">";
|
||||
div += "><<vert margin=5 " + std::string(field_options) + ">";
|
||||
|
||||
if (!usr_div_str.empty())
|
||||
div += "<" + usr_div_str + ">>";
|
||||
else
|
||||
div += ">";
|
||||
if (!usr_div_str.empty())
|
||||
div += "<" + usr_div_str + ">>";
|
||||
else
|
||||
div += ">";
|
||||
|
||||
place_content.div(div.c_str());
|
||||
place_content.div(div.c_str());
|
||||
|
||||
if (options.empty())
|
||||
place_content.field_display(field_options, false);
|
||||
if (options.empty())
|
||||
place_content.field_display(field_options, false);
|
||||
|
||||
if (caption.caption().empty())
|
||||
place_content.field_display(field_title, false);
|
||||
}
|
||||
};
|
||||
if (caption.caption().empty())
|
||||
place_content.field_display(field_title, false);
|
||||
}
|
||||
};
|
||||
|
||||
group::group()
|
||||
: impl_(new implement)
|
||||
{
|
||||
}
|
||||
group::group()
|
||||
: impl_(new implement)
|
||||
{
|
||||
}
|
||||
|
||||
group::group(window parent, const rectangle& r, bool vsb)
|
||||
: group()
|
||||
{
|
||||
create(parent, r, vsb);
|
||||
}
|
||||
group::group(window parent, const rectangle& r, bool vsb)
|
||||
: group()
|
||||
{
|
||||
create(parent, r, vsb);
|
||||
}
|
||||
|
||||
using groupbase_type = widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>;
|
||||
using groupbase_type = widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>;
|
||||
|
||||
group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb)
|
||||
: group(parent, r, vsb)
|
||||
{
|
||||
this->bgcolor(API::bgcolor(parent));
|
||||
group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb)
|
||||
: group(parent, r, vsb)
|
||||
{
|
||||
this->bgcolor(API::bgcolor(parent));
|
||||
|
||||
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
|
||||
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
|
||||
|
||||
impl_->caption.format(formatted);
|
||||
_m_init();
|
||||
}
|
||||
impl_->caption.format(formatted);
|
||||
_m_init();
|
||||
}
|
||||
|
||||
group::~group()
|
||||
{
|
||||
delete impl_->radio_logic;
|
||||
}
|
||||
group::~group()
|
||||
{
|
||||
delete impl_->radio_logic;
|
||||
}
|
||||
|
||||
checkbox& group::add_option(std::string text)
|
||||
{
|
||||
_THROW_IF_EMPTY()
|
||||
checkbox& group::add_option(std::string text)
|
||||
{
|
||||
_THROW_IF_EMPTY()
|
||||
|
||||
#ifdef _nana_std_has_emplace_return_type
|
||||
auto & opt = impl_->options.emplace_back(new checkbox{ handle() });
|
||||
auto & opt = impl_->options.emplace_back(new checkbox { handle() });
|
||||
#else
|
||||
impl_->options.emplace_back(new checkbox(handle()));
|
||||
auto & opt = impl_->options.back();
|
||||
impl_->options.emplace_back(new checkbox(handle()));
|
||||
auto & opt = impl_->options.back();
|
||||
#endif
|
||||
|
||||
opt->transparent(true);
|
||||
opt->caption(std::move(text));
|
||||
impl_->place_content[field_options] << *opt;
|
||||
@ -154,7 +157,7 @@ namespace nana{
|
||||
return *impl_->options.back();
|
||||
}
|
||||
|
||||
void group::caption_align(align position)
|
||||
group& group::caption_align(align position)
|
||||
{
|
||||
if (position != impl_->caption_align)
|
||||
{
|
||||
@ -163,6 +166,32 @@ namespace nana{
|
||||
impl_->place_content.collocate();
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
group& group::caption_background_mode(background_mode mode)
|
||||
{
|
||||
if (mode != impl_->caption_mode)
|
||||
{
|
||||
impl_->caption_mode = mode;
|
||||
switch (mode)
|
||||
{
|
||||
case background_mode::none:
|
||||
impl_->caption.bgcolor(this->bgcolor());
|
||||
impl_->caption.transparent(false);
|
||||
break;
|
||||
case background_mode::blending:
|
||||
impl_->caption.transparent(true);
|
||||
impl_->caption.bgcolor(API::bgcolor(this->parent()).blend(colors::black, 0.025));
|
||||
break;
|
||||
case background_mode::transparent:
|
||||
impl_->caption.transparent(true);
|
||||
impl_->caption.bgcolor(API::bgcolor(this->parent()).blend(colors::black, 0.025));
|
||||
break;
|
||||
}
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
group& group::radio_mode(bool enable)
|
||||
@ -197,6 +226,12 @@ namespace nana{
|
||||
throw std::logic_error("the radio_mode of the group is disabled");
|
||||
}
|
||||
|
||||
void group::option_check( std::size_t pos, bool check )
|
||||
{
|
||||
_THROW_IF_EMPTY();
|
||||
return impl_->options.at(pos)->check( check );
|
||||
}
|
||||
|
||||
bool group::option_checked(std::size_t pos) const
|
||||
{
|
||||
_THROW_IF_EMPTY();
|
||||
@ -206,6 +241,14 @@ namespace nana{
|
||||
group& group::enable_format_caption(bool format)
|
||||
{
|
||||
impl_->caption.format(format);
|
||||
|
||||
// if the caption is already set, make sure the layout is updated
|
||||
if(!caption().empty())
|
||||
{
|
||||
impl_->update_div();
|
||||
impl_->place_content.collocate();
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -289,17 +332,20 @@ namespace nana{
|
||||
),
|
||||
3, 3, this->scheme().border, true, this->bgcolor());
|
||||
|
||||
auto opt_r = API::window_rectangle(impl_->caption);
|
||||
if (opt_r)
|
||||
if (background_mode::blending == impl_->caption_mode)
|
||||
{
|
||||
rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width + 4, static_cast<unsigned>(top_round_line - opt_r->y) } };
|
||||
auto opt_r = API::window_rectangle(impl_->caption);
|
||||
if (opt_r)
|
||||
{
|
||||
rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width + 4, static_cast<unsigned>(top_round_line - opt_r->y) } };
|
||||
|
||||
grad_r.y += top_round_line*2 / 3;
|
||||
grad_r.x -= 2;
|
||||
grad_r.y += top_round_line * 2 / 3;
|
||||
grad_r.x -= 2;
|
||||
|
||||
graph.gradual_rectangle(grad_r,
|
||||
API::bgcolor(this->parent()), this->bgcolor(), true
|
||||
);
|
||||
graph.gradual_rectangle(grad_r,
|
||||
API::bgcolor(this->parent()), this->bgcolor(), true
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -322,5 +368,6 @@ namespace nana{
|
||||
impl_->update_div();
|
||||
impl_->place_content.collocate();
|
||||
}
|
||||
|
||||
}//end namespace nana
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user