Merge branch 'develop'
This commit is contained in:
commit
b72490f8b6
78
.travis.yml
78
.travis.yml
@ -43,8 +43,12 @@ matrix:
|
|||||||
- llvm-toolchain-precise
|
- llvm-toolchain-precise
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
# donwload nana-demo first
|
||||||
|
# we are in: 'user'/nana/
|
||||||
- cd ..
|
- cd ..
|
||||||
|
# we are in: 'user'/
|
||||||
- git clone --depth=1 --branch=master https://github.com/qPCR4vir/nana-demo.git nana-demo
|
- git clone --depth=1 --branch=master https://github.com/qPCR4vir/nana-demo.git nana-demo
|
||||||
|
# now we have 'user'/nana-demo, 'user'/nana/ and we are in: 'user'/
|
||||||
- export PATH="$HOME/bin:$PATH"
|
- export PATH="$HOME/bin:$PATH"
|
||||||
- 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
|
- 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
|
- chmod -R +x /tmp/tools
|
||||||
@ -53,76 +57,24 @@ install:
|
|||||||
- /tmp/tools/cmake --prefix="$HOME" --exclude-subdir
|
- /tmp/tools/cmake --prefix="$HOME" --exclude-subdir
|
||||||
|
|
||||||
before_script :
|
before_script :
|
||||||
# travis don't have a physical monitor. We need to install an emulator: https://docs.travis-ci.com/user/gui-and-headless-browsers/
|
- mkdir demo-build
|
||||||
- "export DISPLAY=:99.0"
|
|
||||||
- "sh -e /etc/init.d/xvfb start"
|
|
||||||
- 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 demo-build
|
|
||||||
- cd demo-build
|
- cd demo-build
|
||||||
|
# now we have 'user'/nana-demo, 'user'/nana/ , 'user'/demo-build/ and we are in: 'user'/demo-build/
|
||||||
|
|
||||||
|
services:
|
||||||
|
# travis don't have a physical monitor. We need to install an emulator:
|
||||||
|
# https://docs.travis-ci.com/user/gui-and-headless-browsers/
|
||||||
|
- xvfb
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON -DNANA_CMAKE_INSTALL=OFF
|
- cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON -DNANA_CMAKE_INSTALL=OFF
|
||||||
- make install
|
- make install
|
||||||
|
- ctest --verbose # todo set correct working directory, and show output
|
||||||
|
# we have installed in 'user'/ ('user'/demo-build/..), and cmake created 'user'/nana-test/
|
||||||
# todo: separate resources from sources (a directory for images)
|
# todo: separate resources from sources (a directory for images)
|
||||||
- ls
|
- ls
|
||||||
|
# we were still in: 'user'/demo-build/
|
||||||
- cd ../nana-test/bin
|
- cd ../nana-test/bin
|
||||||
- ls
|
- ls -lh
|
||||||
- ./a_group_impl
|
|
||||||
- ./animate-bmp
|
|
||||||
- ./audio_player
|
|
||||||
- ./background-effects
|
|
||||||
#- ./calculator # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1159
|
|
||||||
- ./categ
|
|
||||||
- ./clicked
|
|
||||||
- ./decore
|
|
||||||
- ./dock
|
|
||||||
- ./drag-button
|
|
||||||
- ./draw
|
|
||||||
- ./file_explorer
|
|
||||||
#- ./example_menu # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1348
|
|
||||||
- ./example_listbox
|
|
||||||
#- ./example_combox # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1378
|
|
||||||
- ./example.button
|
|
||||||
#- ./filebox-txt # https://travis-ci.org/qPCR4vir/nana/jobs/140250744#L1393
|
|
||||||
- ./folder_tree
|
|
||||||
#- ./folder_tree_nana # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1408
|
|
||||||
#- ./folder_tree_std # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1421
|
|
||||||
- ./framework_design_1
|
|
||||||
- ./framework_design_2
|
|
||||||
- ./framework_design_3
|
|
||||||
- ./group
|
|
||||||
- ./HelloWord
|
|
||||||
#- ./helloword_quit # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1572
|
|
||||||
#- ./inputbox # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1585
|
|
||||||
- ./label_listener
|
|
||||||
- ./lambda_event.Cpp11
|
|
||||||
- ./listbox_inline_widget
|
|
||||||
- ./listbox_Resolver
|
|
||||||
- ./loader_1
|
|
||||||
#- ./loader_2 # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1732
|
|
||||||
- ./mbox
|
|
||||||
- ./main
|
|
||||||
- ./menu_debug
|
|
||||||
#- ./modal_form # https://travis-ci.org/qPCR4vir/nana/jobs/140250744#L1736
|
|
||||||
#- ./MontiHall # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1775
|
|
||||||
#- ./helloworld_demo # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1786
|
|
||||||
#- ./notepad # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1799
|
|
||||||
- ./menu_debug
|
|
||||||
- ./menu_popuper
|
|
||||||
#- ./modal_form # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1846
|
|
||||||
#- ./widget_show2 # https://travis-ci.org/qPCR4vir/nana/jobs/140245437#L1730
|
|
||||||
#- ./widget_show # https://travis-ci.org/qPCR4vir/nana/jobs/140245437#L1740
|
|
||||||
- ./place_login
|
|
||||||
- ./png
|
|
||||||
#- ./screen # https://travis-ci.org/qPCR4vir/nana/jobs/140238537#L1909
|
|
||||||
- ./stretch_image
|
|
||||||
#- ./threading # https://travis-ci.org/qPCR4vir/nana/jobs/140245437#L1826 ?
|
|
||||||
#- ./thread-pool # https://travis-ci.org/qPCR4vir/nana/jobs/140247564#L1782
|
|
||||||
- ./various_events
|
|
||||||
#- ./window-dragger # https://travis-ci.org/qPCR4vir/nana/jobs/140245438#L1820
|
|
||||||
- ./windows-subclassing
|
|
||||||
- ./textbox_line_number
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
# cmake 3.12 have more better modern c++ support
|
# cmake 3.12 have more better modern c++ support
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||||
project(nana VERSION 1.7.1
|
project(nana VERSION 1.7.3
|
||||||
DESCRIPTION "C++ GUI library"
|
DESCRIPTION "C++ GUI library"
|
||||||
HOMEPAGE_URL http://nanapro.org
|
HOMEPAGE_URL http://nanapro.org
|
||||||
LANGUAGES CXX )
|
LANGUAGES CXX )
|
||||||
@ -32,6 +32,7 @@ project(nana VERSION 1.7.1
|
|||||||
add_library(nana)
|
add_library(nana)
|
||||||
add_library(nana::nana ALIAS nana)
|
add_library(nana::nana ALIAS nana)
|
||||||
target_compile_features(nana PUBLIC cxx_std_17)
|
target_compile_features(nana PUBLIC cxx_std_17)
|
||||||
|
# set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
# need after cxx_std_14 or cxx_std_17 ??
|
# need after cxx_std_14 or cxx_std_17 ??
|
||||||
target_compile_features(nana
|
target_compile_features(nana
|
||||||
@ -116,7 +117,7 @@ option(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ "replaced boost.thread wi
|
|||||||
|
|
||||||
######## Nana options
|
######## Nana options
|
||||||
|
|
||||||
target_compile_definitions(nana PRIVATE NANA_IGNORE_CONF) # really ?
|
target_compile_definitions(nana PRIVATE NANA_IGNORE_CONF) # really ??
|
||||||
if(NANA_CMAKE_AUTOMATIC_GUI_TESTING)
|
if(NANA_CMAKE_AUTOMATIC_GUI_TESTING)
|
||||||
target_compile_definitions(nana PUBLIC NANA_AUTOMATIC_GUI_TESTING)
|
target_compile_definitions(nana PUBLIC NANA_AUTOMATIC_GUI_TESTING)
|
||||||
# todo: enable_testing() # ??
|
# todo: enable_testing() # ??
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
# Nana C++ Library
|
# Nana C++ Library
|
||||||
[Linux (gcc 5.4.0 and 4.9.2)](https://travis-ci.org/cnjinhao/nana) including [(nana-demos)](https://github.com/qPCR4vir/nana-demo)
|
[Linux (gcc 8.3.0 and 9.2)](https://travis-ci.org/cnjinhao/nana) including [(nana-demos)](https://github.com/qPCR4vir/nana-demo)
|
||||||
|
|
||||||
[Windows (Microsoft (R) Build Engine version 14.0.24720.0) ](https://ci.appveyor.com/project/qPCR4vir/nana)
|
[Windows (Microsoft (R) Build Engine version 15.9.21) ](https://ci.appveyor.com/project/qPCR4vir/nana)
|
||||||
|
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
|
|
||||||
Nana is a C++ library designed to allow developers to easily create cross-platform GUI applications with modern C++11 style. Currently it can work on Linux(X11) and Windows. The [nana repository](https://github.com/cnjinhao/nana) contains the entire source of the library. You can browse the source code and submit your pull request for contributing.
|
Nana is a C++ standard-like GUI library designed to allow developers to easily create cross-platform GUI applications with modern C++ style. Currently it is regularly tested on Linux(X11) and Windows, and experimentally on macOS and FreeBSD. The [nana repository](https://github.com/cnjinhao/nana) contains the entire source of the library. You can browse the source code and submit your pull request for contributing.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -38,13 +38,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AN
|
|||||||
endif()
|
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")
|
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||||
target_compile_options(nana PRIVATE -fmax-errors=3)
|
target_compile_options(nana PRIVATE -fmax-errors=3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
option(NANA_CMAKE_INSTALL "Install nana when compile the library (to be consumed without cmake)" ON)
|
option(NANA_CMAKE_INSTALL "Install nana after compiling the library (to be consumed WITHOUT cmake!!)" OFF)
|
||||||
|
|
||||||
# Install the include directories too.
|
# Install the include directories too.
|
||||||
if(NANA_CMAKE_INSTALL)
|
if(NANA_CMAKE_INSTALL)
|
||||||
@ -6,8 +6,11 @@ if(NANA_CMAKE_INSTALL)
|
|||||||
# Is your responsability to ensure all compiler options are compatible with the compilation
|
# Is your responsability to ensure all compiler options are compatible with the compilation
|
||||||
# of the project linking to the nana lib here generated
|
# of the project linking to the nana lib here generated
|
||||||
target_sources(nana PRIVATE ${HEADERS})
|
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")
|
message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
message("WARNING !!! You are using the 'installed' nana! Not recommended! ")
|
||||||
|
message("If this was not your intention, please tern OFF option NANA_CMAKE_INSTALL ")
|
||||||
|
message("for example by adding: -DNANA_CMAKE_INSTALL=OFF to your call to cmake. ")
|
||||||
|
|
||||||
# Actually in DESTDIR/CMAKE_INSTALL_PREFIX/lib but in windows there is no DESTDIR/ part.
|
# Actually in DESTDIR/CMAKE_INSTALL_PREFIX/lib but in windows there is no DESTDIR/ part.
|
||||||
install(TARGETS nana
|
install(TARGETS nana
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
@ -15,8 +18,13 @@ if(NANA_CMAKE_INSTALL)
|
|||||||
RUNTIME DESTINATION bin)
|
RUNTIME DESTINATION bin)
|
||||||
install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include) # in ${CMAKE_INSTALL_PREFIX}/include/nana
|
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")
|
message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
|
||||||
|
target_include_directories(nana PUBLIC $<BUILD_INTERFACE:${NANA_INCLUDE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:include> )
|
||||||
else()
|
else()
|
||||||
# this is the prefered method to consume nana with cmake
|
# this is the prefered method to consume nana with cmake
|
||||||
|
message("You are using nana directly from original sources. (Recommended!) "
|
||||||
|
"If this was not your intention, and what you want is to install precomplied nana first, then "
|
||||||
|
"please tern ON option NANA_CMAKE_INSTALL ")
|
||||||
target_sources(nana PUBLIC ${HEADERS})
|
target_sources(nana PUBLIC ${HEADERS})
|
||||||
target_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR})
|
target_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,30 +1,36 @@
|
|||||||
# The ISO C++ File System Technical Specification (ISO-TS, or STD) was optional.
|
# The ISO C++ File System Technical Specification (ISO-TS, or STD) was optional.
|
||||||
# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf
|
# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf
|
||||||
# It is part of c++17.
|
# It is part of c++17.
|
||||||
# The library may be not available or working correctly in the std library in use. As a workaround we may try
|
# The library may be not available or working correctly in the std library you use.
|
||||||
# to "implement" it (ab)using Boost (almost compatible)
|
# As a workaround we will use Nana own partial, but functional implementation.
|
||||||
|
# You may opt to try to "implement" the std filesystem it (ab)using Boost (almost compatible)
|
||||||
# http://www.boost.org/doc/libs/1_60_0/libs/filesystem/doc/index.htm
|
# 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.
|
# By ncluding the file <nana/filesystem/filesystem.hpp> or <nana/filesystem/filesystem_ext.hpp>
|
||||||
# If you include the file <nana/filesystem/filesystem.hpp> or <nana/filesystem/filesystem_ext.hpp>
|
# the selected option is inlined by nana into std::filesystem.
|
||||||
# the selected option will be set by nana into std::filesystem
|
# By default Nana will try to use the STD. If STD is not available Nana own implementation will be used.
|
||||||
# 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
|
# You can change that default if you change one of the following
|
||||||
# (please don't define more than one of the _XX_FORCE options):
|
# (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_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_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_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)
|
set (TEST_FS_LIB OFF)
|
||||||
|
|
||||||
|
|
||||||
if(NANA_CMAKE_NANA_FILESYSTEM_FORCE)
|
if(NANA_CMAKE_NANA_FILESYSTEM_FORCE)
|
||||||
|
if(NANA_CMAKE_STD_FILESYSTEM_FORCE)
|
||||||
|
message (FATAL_ERROR "Defined NANA_CMAKE_NANA_FILESYSTEM_FORCE and NANA_CMAKE_STD_FILESYSTEM_FORCE")
|
||||||
|
endif()
|
||||||
|
if(NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
||||||
|
message (FATAL_ERROR "Defined NANA_CMAKE_NANA_FILESYSTEM_FORCE and NANA_CMAKE_BOOST_FILESYSTEM_FORCE")
|
||||||
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(nana PUBLIC 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)
|
elseif(NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
||||||
|
if(NANA_CMAKE_STD_FILESYSTEM_FORCE)
|
||||||
|
message (FATAL_ERROR "Defined NANA_CMAKE_BOOST_FILESYSTEM_FORCE and NANA_CMAKE_STD_FILESYSTEM_FORCE")
|
||||||
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(nana PUBLIC BOOST_FILESYSTEM_FORCE)
|
target_compile_definitions(nana PUBLIC BOOST_FILESYSTEM_FORCE)
|
||||||
# https://cmake.org/cmake/help/git-master/module/FindBoost.html
|
# 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,
|
# Implicit dependencies such as Boost::filesystem requiring Boost::system will be automatically detected and satisfied,
|
||||||
@ -43,14 +49,131 @@ elseif(NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
|||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
set(Boost_USE_STATIC_RUNTIME ON)
|
||||||
|
|
||||||
else()
|
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()
|
|
||||||
|
|
||||||
|
|
||||||
|
if(NANA_CMAKE_STD_FILESYSTEM_FORCE)
|
||||||
|
target_compile_definitions(nana PUBLIC STD_FILESYSTEM_FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_include_file_cxx (filesystem NANA_HAVE_FILESYSTEM)
|
||||||
|
if (NANA_HAVE_FILESYSTEM)
|
||||||
|
message (STATUS "C++ Filesystem header: <filesystem>")
|
||||||
|
set (TEST_FS_LIB ON)
|
||||||
|
set (CXXSTD_FS_TEST_SOURCE
|
||||||
|
"#include <filesystem>
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::filesystem::path p{\"\tmp/\"};
|
||||||
|
throw std::filesystem::filesystem_error(\"Empty file name!\", std::make_error_code(std::errc::invalid_argument));
|
||||||
|
}")
|
||||||
|
else()
|
||||||
|
check_include_file_cxx (experimental/filesystem NANA_HAVE_EXP_FILESYSTEM)
|
||||||
|
if (NANA_HAVE_EXP_FILESYSTEM)
|
||||||
|
message (STATUS "C++ Filesystem header: <experimental/filesystem>")
|
||||||
|
set (TEST_FS_LIB ON)
|
||||||
|
set (CXXSTD_FS_TEST_SOURCE
|
||||||
|
"#include <experimental/filesystem>
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::experimental::filesystem::path p{\"/tmp/\"};
|
||||||
|
throw std::experimental::filesystem::filesystem_error(\"Empty file name!\", std::make_error_code(std::errc::invalid_argument));
|
||||||
|
}")
|
||||||
|
else ()
|
||||||
|
message (WARNING "No std::filesystem include file found: nana::filesystem will be used.
|
||||||
|
Set NANA_CMAKE_NANA_FILESYSTEM_FORCE to ON to avoid this warning.")
|
||||||
|
target_compile_definitions(nana PUBLIC STD_FILESYSTEM_NOT_SUPPORTED)
|
||||||
|
set (TEST_FS_LIB OFF)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (TEST_FS_LIB)
|
||||||
|
include (FindPackageMessage)
|
||||||
|
include (CheckIncludeFileCXX)
|
||||||
|
include (CheckCXXSourceCompiles)
|
||||||
|
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||||
|
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||||
|
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||||
|
set (CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH})
|
||||||
|
set (CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
|
||||||
|
set (CMAKE_REQUIRED_FLAGS_ORIGINAL ${CMAKE_REQUIRED_FLAGS})
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES_ORIGINAL ${CMAKE_REQUIRED_LIBRARIES})
|
||||||
|
|
||||||
|
# c++: builtin
|
||||||
|
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_ORIGINAL}")
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_ORIGINAL})
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXXBuiltIn_FS_BuiltIn)
|
||||||
|
if (CXXBuiltIn_FS_BuiltIn)
|
||||||
|
message (STATUS "C++ Filesystem library: builtin")
|
||||||
|
else()
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_ORIGINAL} stdc++fs")
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXXBuiltIn_FS_stdcppfs)
|
||||||
|
if (CXXBuiltIn_FS_stdcppfs)
|
||||||
|
message (STATUS "C++ Filesystem library: stdc++fs")
|
||||||
|
target_link_libraries (nana PUBLIC stdc++fs)
|
||||||
|
else()
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_ORIGINAL} c++fs")
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXXBuiltIn_FS_cppfs)
|
||||||
|
if (CXXBuiltIn_FS_cppfs)
|
||||||
|
message (STATUS "C++ Filesystem library: c++fs")
|
||||||
|
target_link_libraries (nana PUBLIC c++fs)
|
||||||
|
else()
|
||||||
|
|
||||||
|
# c++: -std=c++17
|
||||||
|
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_ORIGINAL} -std=c++17")
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_ORIGINAL})
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXX_std__cpp17_FS_BuiltIn)
|
||||||
|
if (CXX_std__cpp17_FS_BuiltIn)
|
||||||
|
message (STATUS "C++: -std=c++17; Filesystem library: builtin")
|
||||||
|
else()
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_ORIGINAL} stdc++fs")
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXX_std__cpp17_FS_stdcppfs)
|
||||||
|
if (CXX_std__cpp17_FS_stdcppfs)
|
||||||
|
message (STATUS "C++: -std=c++17; Filesystem library: stdc++fs")
|
||||||
|
target_link_libraries (nana PUBLIC stdc++fs)
|
||||||
|
else()
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_ORIGINAL} c++fs")
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXX_std__cpp17_FS_cppfs)
|
||||||
|
if (CXX_std__cpp17_FS_cppfs)
|
||||||
|
message (STATUS "C++: -std=c++17; Filesystem library: c++fs")
|
||||||
|
target_link_libraries (nana PUBLIC c++fs)
|
||||||
|
else()
|
||||||
|
|
||||||
|
# c++: /std:c++17
|
||||||
|
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_ORIGINAL} /std:c++17")
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_ORIGINAL})
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXX_std_cpp17_FS_BuiltIn)
|
||||||
|
if (CXX_std_cpp17_FS_BuiltIn)
|
||||||
|
message (STATUS "C++: /std:c++17; Filesystem library: builtin")
|
||||||
|
else()
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_ORIGINAL} stdc++fs")
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXX_std_cpp17_FS_stdcppfs)
|
||||||
|
if (CXX_std_cpp17_FS_stdcppfs)
|
||||||
|
message (STATUS "C++: /std:c++17; Filesystem library: stdc++fs")
|
||||||
|
target_link_libraries (nana PUBLIC stdc++fs)
|
||||||
|
else()
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_ORIGINAL} c++fs")
|
||||||
|
check_cxx_source_compiles ("${CXXSTD_FS_TEST_SOURCE}" CXX_std_cpp17_FS_cppfs)
|
||||||
|
if (CXX_std_cpp17_FS_cppfs)
|
||||||
|
message (STATUS "C++: /std:c++17; Filesystem library: c++fs")
|
||||||
|
target_link_libraries (nana PUBLIC c++fs)
|
||||||
|
|
||||||
|
else ()
|
||||||
|
message (WARNING "No std::filesystem library found: nana::filesystem will be used.
|
||||||
|
Set NANA_CMAKE_NANA_FILESYSTEM_FORCE to ON to avoid this warning.")
|
||||||
|
target_compile_definitions(nana PUBLIC STD_FILESYSTEM_NOT_SUPPORTED)
|
||||||
|
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_ORIGINAL})
|
||||||
|
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS_ORIGINAL}")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
endif (TEST_FS_LIB)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Compile nana as a shared library." OFF)
|
option(BUILD_SHARED_LIBS "Compile nana as a shared library." OFF)
|
||||||
|
option(NANA_STATIC_STDLIB "Link nana statically to C++ standard library" ON)
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS) # todo test
|
if(BUILD_SHARED_LIBS) # todo test
|
||||||
|
|
||||||
@ -35,12 +36,11 @@ if(BUILD_SHARED_LIBS) # todo test
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW??
|
if(NANA_STATIC_STDLIB)
|
||||||
|
target_link_libraries(nana
|
||||||
|
PUBLIC
|
||||||
|
$<$<CXX_COMPILER_ID:GNU>:-static-libgcc -static-libstdc++>
|
||||||
|
$<$<CXX_COMPILER_ID:Clang>:-static-libgcc -static-libstdc++>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
target_compile_options(nana PUBLIC -lgcc -lstdc++)
|
|
||||||
else()
|
|
||||||
target_link_libraries(nana PUBLIC -static-libgcc -static-libstdc++)
|
|
||||||
endif(BUILD_SHARED_LIBS)
|
|
||||||
|
|
||||||
endif()
|
|
@ -14,8 +14,8 @@
|
|||||||
<Option compiler="gcc" />
|
<Option compiler="gcc" />
|
||||||
<Option createDefFile="1" />
|
<Option createDefFile="1" />
|
||||||
<Compiler>
|
<Compiler>
|
||||||
<Add option="-std=c++11" />
|
|
||||||
<Add option="-Wall" />
|
<Add option="-Wall" />
|
||||||
|
<Add option="-std=c++11" />
|
||||||
<Add option="-g" />
|
<Add option="-g" />
|
||||||
<Add directory="../../include" />
|
<Add directory="../../include" />
|
||||||
<Add directory="../../extrlib/mingw" />
|
<Add directory="../../extrlib/mingw" />
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#define NANA_ANY_HPP
|
#define NANA_ANY_HPP
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "c++defines.hpp"
|
#include "c++defines.hpp"
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ namespace nana
|
|||||||
any(Value && value,
|
any(Value && value,
|
||||||
typename std::enable_if<!std::is_same<any&, Value>::value>::type * = nullptr,
|
typename std::enable_if<!std::is_same<any&, Value>::value>::type * = nullptr,
|
||||||
typename std::enable_if<!std::is_const<Value>::value>::type* = nullptr)
|
typename std::enable_if<!std::is_const<Value>::value>::type* = nullptr)
|
||||||
: content_(new holder<typename std::decay<Value>::type>(static_cast<Value&&>(value)))
|
: content_(new holder<typename std::decay<Value>::type>(std::forward<Value>(value)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ namespace nana
|
|||||||
template<class Value>
|
template<class Value>
|
||||||
any& operator=(Value&& other)
|
any& operator=(Value&& other)
|
||||||
{
|
{
|
||||||
any(other).swap(*this);
|
any(std::forward<Value>(other)).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Predefined Symbols for C++
|
* Predefined Symbols for C++
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2016-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2016-2019 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -48,14 +48,15 @@
|
|||||||
|
|
||||||
#ifndef NANA_CXX_DEFINES_INCLUDED
|
#ifndef NANA_CXX_DEFINES_INCLUDED
|
||||||
#define NANA_CXX_DEFINES_INCLUDED
|
#define NANA_CXX_DEFINES_INCLUDED
|
||||||
#define STD_FILESYSTEM_NOT_SUPPORTED
|
// #define STD_FILESYSTEM_NOT_SUPPORTED
|
||||||
|
|
||||||
//C++ language
|
//C++ language
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# if (_MSC_VER < 1900)
|
# if (_MSC_VER < 1900) // VC2013
|
||||||
# //About std.experimental.filesystem.
|
# //About std.experimental.filesystem.
|
||||||
# //Through VC2013 has provided <filesystem>, but all the names are given in namespace std. It's hard to alias these names into std::experimental,
|
# //Through VC2013 has provided <filesystem>, but all the names are given in namespace std. It's hard to alias these names into std::experimental,
|
||||||
# //So Nana use nana.filesystem implement instead for VC2013
|
# //So Nana use nana.filesystem implement instead for VC2013
|
||||||
|
# define STD_FILESYSTEM_NOT_SUPPORTED
|
||||||
#
|
#
|
||||||
# //Nana defines some macros for lack of support of keywords
|
# //Nana defines some macros for lack of support of keywords
|
||||||
# define _ALLOW_KEYWORD_MACROS
|
# define _ALLOW_KEYWORD_MACROS
|
||||||
@ -64,8 +65,6 @@
|
|||||||
# define noexcept //no support of noexcept until Visual C++ 2015
|
# define noexcept //no support of noexcept until Visual C++ 2015
|
||||||
|
|
||||||
# define constexpr //no support of constexpr until Visual C++ 2015 ? const ??
|
# define constexpr //no support of constexpr until Visual C++ 2015 ? const ??
|
||||||
# else
|
|
||||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__GNUC__) && not defined(__clang__)
|
#elif defined(__GNUC__) && not defined(__clang__)
|
||||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
|
# if (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
|
||||||
@ -89,7 +88,7 @@
|
|||||||
#define NANA_MINGW
|
#define NANA_MINGW
|
||||||
#endif // MINGW
|
#endif // MINGW
|
||||||
|
|
||||||
#elif defined(APPLE) //Mac OS X
|
#elif defined(__APPLE__) || defined(APPLE) //Mac OS X
|
||||||
//Symbols for MACOS
|
//Symbols for MACOS
|
||||||
#define NANA_MACOS
|
#define NANA_MACOS
|
||||||
#define NANA_POSIX
|
#define NANA_POSIX
|
||||||
@ -125,16 +124,16 @@
|
|||||||
|
|
||||||
#elif defined(__clang__) //Clang
|
#elif defined(__clang__) //Clang
|
||||||
|
|
||||||
#include <iosfwd> //Introduces some implement-specific flags of ISO C++ Library
|
#include <iosfwd> // Introduces some implement-specific flags of ISO C++ Library
|
||||||
#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||||
//<codecvt> is a known issue on libstdc++, it works on libc++
|
//<codecvt> is a known issue on libstdc++, it works on libc++
|
||||||
#define STD_CODECVT_NOT_SUPPORTED
|
#define STD_CODECVT_NOT_SUPPORTED
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__GNUC__) //GCC
|
#elif defined(__GNUC__) // GCC
|
||||||
|
|
||||||
#include <iosfwd> //Introduces some implement-specific flags of ISO C++ Library
|
#include <iosfwd> // Introduces some implementation-specific flags of ISO C++ Library
|
||||||
#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||||
//<codecvt> is a known issue on libstdc++, it works on libc++
|
//<codecvt> is a known issue on libstdc++, it works on libc++ todo review !
|
||||||
#define STD_CODECVT_NOT_SUPPORTED
|
#define STD_CODECVT_NOT_SUPPORTED
|
||||||
|
|
||||||
//It's a known issue of libstdc++ on MinGW
|
//It's a known issue of libstdc++ on MinGW
|
||||||
@ -155,6 +154,8 @@
|
|||||||
|
|
||||||
# if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) )
|
# if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) )
|
||||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||||
|
# else
|
||||||
|
# define STD_FILESYSTEM_NOT_SUPPORTED
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#if (__GNUC__ == 4)
|
#if (__GNUC__ == 4)
|
||||||
@ -252,7 +253,7 @@
|
|||||||
# if __has_include(<filesystem>)
|
# if __has_include(<filesystem>)
|
||||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||||
# endif
|
# endif
|
||||||
# if __has_include(<mutex>)
|
# if __has_include(<mutex>)
|
||||||
# if !(defined(NANA_MINGW) && !defined(_GLIBCXX_HAS_GTHREADS))
|
# if !(defined(NANA_MINGW) && !defined(_GLIBCXX_HAS_GTHREADS))
|
||||||
//See the comment above regarding MinGW's threading support
|
//See the comment above regarding MinGW's threading support
|
||||||
# undef STD_THREAD_NOT_SUPPORTED
|
# undef STD_THREAD_NOT_SUPPORTED
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* @file nana/filesystem/filesystem.hpp
|
* @file nana/filesystem/filesystem.hpp
|
||||||
* @author Ariel Vina-Rodriguez, Jinhao
|
* @author Ariel Vina-Rodriguez, Jinhao
|
||||||
* @brief Mimic std::experimental::filesystem::v1 (boost v3)
|
* @brief Mimic std::filesystem
|
||||||
* and need VC2015 or a C++11 compiler. With a few correction can be compiler by VC2013
|
* and need VC2015 or a C++11 compiler. With a few correction can be compiler by VC2013
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -34,32 +34,26 @@
|
|||||||
//Filesystem Selection
|
//Filesystem Selection
|
||||||
#include <nana/config.hpp>
|
#include <nana/config.hpp>
|
||||||
|
|
||||||
#if defined(NANA_USING_NANA_FILESYSTEM) || defined(NANA_USING_STD_FILESYSTEM) || defined(NANA_USING_BOOST_FILESYSTEM)
|
|
||||||
#undef NANA_USING_NANA_FILESYSTEM
|
|
||||||
#undef NANA_USING_STD_FILESYSTEM
|
|
||||||
#undef NANA_USING_BOOST_FILESYSTEM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NANA_USING_NANA_FILESYSTEM 0
|
#define NANA_USING_NANA_FILESYSTEM 0
|
||||||
#define NANA_USING_STD_FILESYSTEM 0
|
#define NANA_USING_STD_FILESYSTEM 0
|
||||||
#define NANA_USING_BOOST_FILESYSTEM 0
|
#define NANA_USING_BOOST_FILESYSTEM 0
|
||||||
|
|
||||||
#if (defined(NANA_FILESYSTEM_FORCE) || ( (defined(STD_FILESYSTEM_NOT_SUPPORTED) && !defined(BOOST_FILESYSTEM_AVAILABLE)) && !(defined(BOOST_FILESYSTEM_FORCE) || defined(STD_FILESYSTEM_FORCE)) ) )
|
//#define NANA_FILESYSTEM_FORCE 1
|
||||||
|
|
||||||
|
#if (defined(NANA_FILESYSTEM_FORCE) || ( (defined(STD_FILESYSTEM_NOT_SUPPORTED) && !defined(BOOST_FILESYSTEM_AVAILABLE)) && !(defined(BOOST_FILESYSTEM_FORCE) || defined(STD_FILESYSTEM_FORCE)) ) )
|
||||||
#undef NANA_USING_NANA_FILESYSTEM
|
#undef NANA_USING_NANA_FILESYSTEM
|
||||||
#define NANA_USING_NANA_FILESYSTEM 1
|
#define NANA_USING_NANA_FILESYSTEM 1
|
||||||
|
|
||||||
#elif (defined(BOOST_FILESYSTEM_AVAILABLE) && ( defined(BOOST_FILESYSTEM_FORCE) || ( defined(STD_FILESYSTEM_NOT_SUPPORTED) && !defined(STD_FILESYSTEM_FORCE) ) ))
|
#elif (defined(BOOST_FILESYSTEM_AVAILABLE) && ( defined(BOOST_FILESYSTEM_FORCE) || ( defined(STD_FILESYSTEM_NOT_SUPPORTED) && !defined(STD_FILESYSTEM_FORCE) ) ))
|
||||||
|
|
||||||
#undef NANA_USING_BOOST_FILESYSTEM
|
#undef NANA_USING_BOOST_FILESYSTEM
|
||||||
#define NANA_USING_BOOST_FILESYSTEM 1
|
#define NANA_USING_BOOST_FILESYSTEM 1
|
||||||
# include <chrono>
|
# include <chrono>
|
||||||
# include <boost/filesystem.hpp>
|
# include <boost/filesystem.hpp>
|
||||||
|
|
||||||
// add boost::filesystem into std::experimental::filesystem
|
// inline boost::filesystem into std::filesystem
|
||||||
namespace std {
|
namespace std {
|
||||||
namespace experimental {
|
namespace filesystem {
|
||||||
namespace filesystem {
|
inline namespace boost_filesystem {
|
||||||
using namespace boost::filesystem;
|
using namespace boost::filesystem;
|
||||||
using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
|
using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
|
||||||
|
|
||||||
@ -75,43 +69,34 @@ namespace std {
|
|||||||
socket = boost::filesystem::file_type::socket_file,
|
socket = boost::filesystem::file_type::socket_file,
|
||||||
unknown = boost::filesystem::file_type::type_unknown,
|
unknown = boost::filesystem::file_type::type_unknown,
|
||||||
};
|
};
|
||||||
// Boost dont include generic_u8string
|
// Boost dont include generic_u8string
|
||||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/path.hpp
|
// 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
|
// 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
|
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/operations.hpp
|
||||||
// but travis come with an oooold version of boost
|
// but travis come with an oooold version of boost
|
||||||
// 1.55.0 NOT enable directory_iterator C++11 range-base for
|
// 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
|
// http://www.boost.org/doc/libs/1_54_0/boost/filesystem/operations.hpp
|
||||||
#if BOOST_VERSION < 105600
|
#if BOOST_VERSION < 105600
|
||||||
namespace boost
|
namespace boost { // todo ??
|
||||||
// enable directory_iterator C++11 range-base for statement use --------------------//
|
// 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
|
// 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
|
// auto - thus the top-level const is stripped - so returning const is harmless and
|
||||||
// emphasizes begin() is just a pass through.
|
// emphasizes begin() is just a pass through.
|
||||||
inline const directory_iterator& begin(const directory_iterator& iter) BOOST_NOEXCEPT
|
inline const directory_iterator& begin(const directory_iterator& iter) BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline directory_iterator end(const directory_iterator&) BOOST_NOEXCEPT
|
inline directory_iterator end(const directory_iterator&) BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
return directory_iterator();
|
return directory_iterator();
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
#endif
|
||||||
} // filesystem
|
} // boost_filesystem
|
||||||
} // experimental
|
} // filesystem
|
||||||
|
|
||||||
namespace filesystem
|
|
||||||
{
|
|
||||||
using namespace experimental::filesystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __cpp_lib_experimental_filesystem
|
|
||||||
# define __cpp_lib_experimental_filesystem 201406
|
|
||||||
#endif
|
|
||||||
} // std
|
} // std
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -133,7 +118,7 @@ namespace std {
|
|||||||
# undef NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
# undef NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
||||||
# define NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
# define NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif // BOOST_FILESYSTEM and NANA_FILESYSTEM
|
||||||
|
|
||||||
#if NANA_USING_NANA_FILESYSTEM
|
#if NANA_USING_NANA_FILESYSTEM
|
||||||
|
|
||||||
@ -148,437 +133,495 @@ namespace std {
|
|||||||
|
|
||||||
#include <nana/deploy.hpp>
|
#include <nana/deploy.hpp>
|
||||||
|
|
||||||
namespace nana { namespace experimental { namespace filesystem
|
namespace nana {
|
||||||
{
|
namespace filesystem {
|
||||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
|
||||||
inline namespace v1
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum class file_type
|
enum class file_type
|
||||||
{
|
{
|
||||||
none = 0, ///< has not been determined or an error occurred while trying to determine
|
none = 0, ///< has not been determined or an error occurred while trying to determine
|
||||||
not_found = -1, ///< Pseudo-type: file was not found. Is not considered an error
|
not_found = -1, ///< Pseudo-type: file was not found. Is not considered an error
|
||||||
regular = 1,
|
regular = 1,
|
||||||
directory = 2 ,
|
directory = 2,
|
||||||
symlink =3, ///< Symbolic link file
|
symlink = 3, ///< Symbolic link file
|
||||||
block =4, ///< Block special file
|
block = 4, ///< Block special file
|
||||||
character= 5 , ///< Character special file
|
character = 5, ///< Character special file
|
||||||
fifo = 6 , ///< FIFO or pipe file
|
fifo = 6, ///< FIFO or pipe file
|
||||||
socket =7,
|
socket = 7,
|
||||||
unknown= 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other
|
unknown = 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class perms
|
enum class perms
|
||||||
{
|
{
|
||||||
none = 0, ///< There are no permissions set for the file.
|
none = 0, ///< There are no permissions set for the file.
|
||||||
all = 0x1FF, ///< owner_all | group_all | others_all
|
all = 0x1FF, ///< owner_all | group_all | others_all
|
||||||
mask = 0xFFF, ///< all | set_uid | set_gid | sticky_bit.
|
mask = 0xFFF, ///< all | set_uid | set_gid | sticky_bit.
|
||||||
unknown = 0xFFFF ///< not known, such as when a file_status object is created without specifying the permissions
|
unknown = 0xFFFF ///< not known, such as when a file_status object is created without specifying the permissions
|
||||||
};
|
};
|
||||||
//enum class copy_options;
|
//enum class copy_options;
|
||||||
|
|
||||||
enum class directory_options
|
enum class directory_options
|
||||||
{
|
{
|
||||||
none,
|
none,
|
||||||
follow_directory_symlink,
|
follow_directory_symlink,
|
||||||
skip_permission_denied
|
skip_permission_denied
|
||||||
};
|
};
|
||||||
|
|
||||||
struct space_info
|
struct space_info
|
||||||
{
|
{
|
||||||
uintmax_t capacity;
|
uintmax_t capacity;
|
||||||
uintmax_t free;
|
uintmax_t free;
|
||||||
uintmax_t available;
|
uintmax_t available;
|
||||||
};
|
};
|
||||||
|
|
||||||
using file_time_type = std::chrono::time_point<std::chrono::system_clock>; ///< trivial-clock> ;
|
using file_time_type = std::chrono::time_point<std::chrono::system_clock>; ///< trivial-clock> ;
|
||||||
|
|
||||||
class file_status
|
class file_status
|
||||||
{
|
{
|
||||||
file_type m_ft = file_type::none;
|
file_type m_ft = file_type::none;
|
||||||
perms m_prms = perms::unknown;
|
perms m_prms = perms::unknown;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown);
|
explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown);
|
||||||
|
|
||||||
// observers
|
// observers
|
||||||
file_type type() const;
|
file_type type() const;
|
||||||
perms permissions() const;
|
|
||||||
|
|
||||||
// modifiers
|
perms permissions() const;
|
||||||
void type(file_type ft);
|
|
||||||
void permissions(perms prms);
|
|
||||||
private:
|
|
||||||
file_type value_;
|
|
||||||
perms perms_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// concerned only with lexical and syntactic aspects and does not necessarily exist in
|
// modifiers
|
||||||
/// external storage, and the pathname is not necessarily valid for the current operating system
|
void type(file_type ft);
|
||||||
/// or for a particular file system
|
|
||||||
/// A sequence of elements that identify the location of a file within a filesystem.
|
void permissions(perms prms);
|
||||||
/// The elements are the:
|
|
||||||
/// rootname (opt), root-directory (opt), and an optional sequence of filenames.
|
private:
|
||||||
/// The maximum number of elements in the sequence is operating system dependent.
|
file_type value_;
|
||||||
class path
|
perms perms_;
|
||||||
{
|
};
|
||||||
public:
|
|
||||||
|
/// concerned only with lexical and syntactic aspects and does not necessarily exist in
|
||||||
|
/// external storage, and the pathname is not necessarily valid for the current operating system
|
||||||
|
/// or for a particular file system
|
||||||
|
/// A sequence of elements that identify the location of a file within a filesystem.
|
||||||
|
/// The elements are the:
|
||||||
|
/// rootname (opt), root-directory (opt), and an optional sequence of filenames.
|
||||||
|
/// The maximum number of elements in the sequence is operating system dependent.
|
||||||
|
class path
|
||||||
|
{
|
||||||
|
public:
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
using value_type = wchar_t;
|
using value_type = wchar_t;
|
||||||
const static value_type preferred_separator = L'\\';
|
const static value_type preferred_separator = L'\\';
|
||||||
#else
|
#else
|
||||||
using value_type = char;
|
using value_type = char;
|
||||||
const static value_type preferred_separator = '/';
|
const static value_type preferred_separator = '/';
|
||||||
#endif
|
#endif
|
||||||
using string_type = std::basic_string<value_type>;
|
using string_type = std::basic_string<value_type>;
|
||||||
|
|
||||||
path() = default;
|
path() = default;
|
||||||
|
|
||||||
template<typename Source>
|
template<typename Source>
|
||||||
path(const Source& source)
|
path(const Source &source)
|
||||||
{
|
{
|
||||||
_m_assign(source);
|
_m_assign(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
path& make_preferred();
|
|
||||||
path& remove_filename();
|
|
||||||
//path& replace_filename(const path& replacement);
|
|
||||||
//path& replace_extension(const path& replacement = path());
|
|
||||||
//void swap(path& rhs) noexcept;
|
|
||||||
|
|
||||||
// decomposition
|
path &make_preferred();
|
||||||
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;
|
|
||||||
path extension() const;
|
|
||||||
|
|
||||||
// query
|
path &remove_filename();
|
||||||
bool empty() const noexcept;
|
//path& replace_filename(const path& replacement);
|
||||||
bool has_root_name() const { return !root_name().empty(); }
|
//path& replace_extension(const path& replacement = path());
|
||||||
bool has_root_directory() const { return !root_directory().empty(); }
|
//void swap(path& rhs) noexcept;
|
||||||
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().empty(); }; // temp
|
|
||||||
bool is_absolute() const;
|
|
||||||
bool is_relative() const;
|
|
||||||
|
|
||||||
int compare(const path& other) const;
|
// decomposition
|
||||||
|
path root_name() const;
|
||||||
|
|
||||||
file_type what() const;
|
path root_directory() const;
|
||||||
|
|
||||||
const value_type*c_str() const;
|
path root_path() const;
|
||||||
const string_type& native() const;
|
|
||||||
operator string_type() const;
|
|
||||||
|
|
||||||
std::string string() const;
|
path relative_path() const;
|
||||||
std::wstring wstring() const;
|
|
||||||
std::string u8string() const;
|
|
||||||
// std::u16string u16string() const;
|
|
||||||
// std::u32string u32string() const;
|
|
||||||
|
|
||||||
std::string generic_string() const ;
|
path parent_path() const;
|
||||||
std::wstring generic_wstring() const;
|
|
||||||
std::string generic_u8string() const;
|
|
||||||
// std::u16string generic_u16string() const;
|
|
||||||
// std::u32string generic_u32string() const;
|
|
||||||
|
|
||||||
path lexically_normal() const;
|
path filename() const;
|
||||||
|
|
||||||
//appends
|
path stem() const;
|
||||||
path& operator/=(const path& other);
|
|
||||||
|
|
||||||
template<typename Source>
|
path extension() const;
|
||||||
path& operator/=(const Source& source)
|
|
||||||
{
|
|
||||||
path other(source);
|
|
||||||
return this->operator/=(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Source>
|
// query
|
||||||
path& append(const Source& source)
|
bool empty() const noexcept;
|
||||||
{
|
|
||||||
path other(source);
|
|
||||||
return this->operator/=(other);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void _m_assign(const std::string& source_utf8);
|
|
||||||
void _m_assign(const std::wstring& source);
|
|
||||||
private:
|
|
||||||
string_type pathstr_;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool operator==(const path& lhs, const path& rhs);
|
bool has_root_name() const
|
||||||
bool operator!=(const path& lhs, const path& rhs);
|
{ return !root_name().empty(); }
|
||||||
bool operator<(const path& lhs, const path& rhs);
|
|
||||||
bool operator>(const path& lhs, const path& rhs);
|
bool has_root_directory() const
|
||||||
path operator/(const path& lhs, const path& rhs);
|
{ 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().empty(); }; // temp
|
||||||
|
bool is_absolute() const;
|
||||||
|
|
||||||
|
bool is_relative() const;
|
||||||
|
|
||||||
|
int compare(const path &other) const;
|
||||||
|
|
||||||
|
file_type what() const;
|
||||||
|
|
||||||
|
const value_type *c_str() const;
|
||||||
|
|
||||||
|
const string_type &native() const;
|
||||||
|
|
||||||
|
operator string_type() const;
|
||||||
|
|
||||||
|
std::string string() const;
|
||||||
|
|
||||||
|
std::wstring wstring() const;
|
||||||
|
|
||||||
|
// std::string u8string() const;
|
||||||
|
// std::u16string u16string() const;
|
||||||
|
// std::u32string u32string() const;
|
||||||
|
|
||||||
|
std::string generic_string() const;
|
||||||
|
|
||||||
|
std::wstring generic_wstring() const;
|
||||||
|
|
||||||
|
// std::string generic_u8string() const;
|
||||||
|
// std::u16string generic_u16string() const;
|
||||||
|
// std::u32string generic_u32string() const;
|
||||||
|
|
||||||
|
path lexically_normal() const;
|
||||||
|
|
||||||
|
//appends
|
||||||
|
path &operator/=(const path &other);
|
||||||
|
|
||||||
|
template<typename Source>
|
||||||
|
path &operator/=(const Source &source)
|
||||||
|
{
|
||||||
|
path other(source);
|
||||||
|
return this->operator/=(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Source>
|
||||||
|
path &append(const Source &source)
|
||||||
|
{
|
||||||
|
path other(source);
|
||||||
|
return this->operator/=(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _m_assign(const std::string &source_utf8);
|
||||||
|
|
||||||
|
void _m_assign(const std::wstring &source);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string_type pathstr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const path &lhs, const path &rhs);
|
||||||
|
|
||||||
|
bool operator!=(const path &lhs, const path &rhs);
|
||||||
|
|
||||||
|
bool operator<(const path &lhs, const path &rhs);
|
||||||
|
|
||||||
|
bool operator>(const path &lhs, const path &rhs);
|
||||||
|
|
||||||
|
path operator/(const path &lhs, const path &rhs);
|
||||||
|
|
||||||
|
|
||||||
class filesystem_error
|
class filesystem_error
|
||||||
: public std::system_error
|
: public std::system_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit filesystem_error(const std::string& msg, std::error_code);
|
explicit filesystem_error(const std::string &msg, std::error_code);
|
||||||
|
|
||||||
filesystem_error(const std::string& msg, const path& path1, std::error_code err);
|
filesystem_error(const std::string &msg, const path &path1, std::error_code err);
|
||||||
filesystem_error(const std::string& msg, const path& path1, const path& path2, std::error_code err);
|
|
||||||
|
|
||||||
const path& path1() const noexcept;
|
filesystem_error(const std::string &msg, const path &path1, const path &path2, std::error_code err);
|
||||||
const path& path2() const noexcept;
|
|
||||||
// const char* what() const noexcept;
|
const path &path1() const noexcept;
|
||||||
private:
|
|
||||||
path path1_;
|
const path &path2() const noexcept;
|
||||||
path path2_;
|
// const char* what() const noexcept;
|
||||||
};
|
private:
|
||||||
|
path path1_;
|
||||||
|
path path2_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class directory_entry
|
class directory_entry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
directory_entry() = default;
|
directory_entry() = default;
|
||||||
explicit directory_entry(const ::nana::experimental::filesystem::path&);
|
|
||||||
|
|
||||||
//modifiers
|
explicit directory_entry(const filesystem::path &);
|
||||||
void assign(const ::nana::experimental::filesystem::path&);
|
|
||||||
void replace_filename(const ::nana::experimental::filesystem::path&);
|
|
||||||
|
|
||||||
//observers
|
//modifiers
|
||||||
file_status status() const;
|
void assign(const filesystem::path &);
|
||||||
operator const filesystem::path&() const { return path_; };
|
|
||||||
const filesystem::path& path() const;
|
|
||||||
private:
|
|
||||||
::nana::experimental::filesystem::path path_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// InputIterator that iterate over the sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator
|
void replace_filename(const filesystem::path &);
|
||||||
class directory_iterator :public std::iterator<std::input_iterator_tag, directory_entry>
|
|
||||||
{
|
|
||||||
using find_handle = void*;
|
|
||||||
public:
|
|
||||||
|
|
||||||
directory_iterator() noexcept;
|
//observers
|
||||||
explicit directory_iterator(const path& p);
|
file_status status() const;
|
||||||
directory_iterator(const path& p, directory_options opt);
|
|
||||||
|
|
||||||
const value_type& operator*() const;
|
operator const filesystem::path &() const
|
||||||
const value_type* operator->() const;
|
{ return path_; };
|
||||||
|
|
||||||
directory_iterator& operator++();
|
const filesystem::path &path() const;
|
||||||
directory_iterator operator++(int); ///< extention
|
|
||||||
|
|
||||||
bool equal(const directory_iterator& x) const;
|
private:
|
||||||
|
filesystem::path path_;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
/// InputIterator that iterate over the sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator
|
||||||
template<typename Char>
|
class directory_iterator : public std::iterator<std::input_iterator_tag, directory_entry>
|
||||||
static bool _m_ignore(const Char * p)
|
{
|
||||||
{
|
using find_handle = void *;
|
||||||
while(*p == '.')
|
public:
|
||||||
++p;
|
|
||||||
return (*p == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _m_prepare(const path& file_path);
|
directory_iterator() noexcept;
|
||||||
void _m_read();
|
|
||||||
private:
|
|
||||||
bool end_{false};
|
|
||||||
path::string_type path_;
|
|
||||||
directory_options option_{ directory_options::none };
|
|
||||||
|
|
||||||
std::shared_ptr<find_handle> find_ptr_;
|
explicit directory_iterator(const path &p);
|
||||||
find_handle handle_{nullptr};
|
|
||||||
value_type value_;
|
|
||||||
};
|
|
||||||
/// enable directory_iterator range-based for statements
|
|
||||||
inline directory_iterator begin( directory_iterator iter) noexcept
|
|
||||||
{
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline directory_iterator end( const directory_iterator&) noexcept
|
directory_iterator(const path &p, directory_options opt);
|
||||||
{
|
|
||||||
return {};
|
const value_type &operator*() const;
|
||||||
}
|
|
||||||
|
const value_type *operator->() const;
|
||||||
|
|
||||||
|
directory_iterator &operator++();
|
||||||
|
|
||||||
|
directory_iterator operator++(int); ///< extention
|
||||||
|
|
||||||
|
bool equal(const directory_iterator &x) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename Char>
|
||||||
|
static bool _m_ignore(const Char *p)
|
||||||
|
{
|
||||||
|
while (*p == '.')
|
||||||
|
++p;
|
||||||
|
return (*p == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_prepare(const path &file_path);
|
||||||
|
|
||||||
|
void _m_read();
|
||||||
|
|
||||||
|
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};
|
||||||
|
value_type value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// enable directory_iterator range-based for statements
|
||||||
|
inline directory_iterator begin(directory_iterator iter) noexcept
|
||||||
|
{
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline directory_iterator end(const directory_iterator &) noexcept
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//class recursive_directory_iterator;
|
//class recursive_directory_iterator;
|
||||||
//// enable recursive_directory_iterator range-based for statements
|
//// enable recursive_directory_iterator range-based for statements
|
||||||
//recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
|
//recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
|
||||||
//recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
|
//recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
|
||||||
|
|
||||||
//template<typename Value_Type>
|
//template<typename Value_Type>
|
||||||
inline bool operator==(const directory_iterator/*<Value_Type>*/ & x, const directory_iterator/*<Value_Type>*/ & y)
|
inline bool operator==(const directory_iterator/*<Value_Type>*/ &x, const directory_iterator/*<Value_Type>*/ &y)
|
||||||
{
|
{
|
||||||
return x.equal(y);
|
return x.equal(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//template<typename Value_Type>
|
//template<typename Value_Type>
|
||||||
inline bool operator!=(const directory_iterator/*<Value_Type>*/ & x, const directory_iterator/*<Value_Type>*/ & y)
|
inline bool operator!=(const directory_iterator/*<Value_Type>*/ &x, const directory_iterator/*<Value_Type>*/ &y)
|
||||||
{
|
{
|
||||||
return !x.equal(y);
|
return !x.equal(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
file_status status(const path& p);
|
file_status status(const path &p);
|
||||||
file_status status(const path& p, std::error_code&);
|
|
||||||
|
|
||||||
std::uintmax_t file_size(const path& p);
|
file_status status(const path &p, std::error_code &);
|
||||||
std::uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
|
|
||||||
|
|
||||||
inline bool is_directory(file_status s) noexcept
|
std::uintmax_t file_size(const path &p);
|
||||||
{ return s.type() == file_type::directory ;}
|
|
||||||
|
|
||||||
bool is_directory(const path& p);
|
std::uintmax_t file_size(const path &p, std::error_code &ec) noexcept;
|
||||||
bool is_directory(const path& p, std::error_code& ec) noexcept;
|
|
||||||
|
|
||||||
inline bool is_regular_file(file_status s) noexcept
|
inline bool is_directory(file_status s) noexcept
|
||||||
{
|
{ return s.type() == file_type::directory; }
|
||||||
return s.type() == file_type::regular;
|
|
||||||
}
|
|
||||||
inline bool is_regular_file(const path& p)
|
|
||||||
{
|
|
||||||
return is_regular_file(status(p));
|
|
||||||
}
|
|
||||||
// bool is_regular_file(const path& p, error_code& ec) noexcept;
|
|
||||||
// Returns: is_regular_file(status(p, ec)).Returns false if an error occurs.
|
|
||||||
|
|
||||||
inline bool is_empty(const path& p)
|
bool is_directory(const path &p);
|
||||||
{
|
|
||||||
auto fs = status(p);
|
|
||||||
|
|
||||||
if (is_directory(fs))
|
bool is_directory(const path &p, std::error_code &ec) noexcept;
|
||||||
return (directory_iterator() == directory_iterator(p));
|
|
||||||
|
|
||||||
return (file_size(p) == 0);
|
inline bool is_regular_file(file_status s) noexcept
|
||||||
}
|
{
|
||||||
// bool is_empty(const path& p, error_code& ec) noexcept;
|
return s.type() == file_type::regular;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_regular_file(const path &p)
|
||||||
|
{
|
||||||
|
return is_regular_file(status(p));
|
||||||
|
}
|
||||||
|
// bool is_regular_file(const path& p, error_code& ec) noexcept; // todo:
|
||||||
|
// Returns: is_regular_file(status(p, ec)).Returns false if an error occurs. // todo:
|
||||||
|
|
||||||
|
inline bool is_empty(const path &p)
|
||||||
|
{
|
||||||
|
auto fs = status(p);
|
||||||
|
|
||||||
|
if (is_directory(fs))
|
||||||
|
return (directory_iterator() == directory_iterator(p));
|
||||||
|
|
||||||
|
return (file_size(p) == 0);
|
||||||
|
}
|
||||||
|
// bool is_empty(const path& p, error_code& ec) noexcept;
|
||||||
|
|
||||||
|
|
||||||
bool create_directories(const path& p);
|
bool create_directories(const path &p);
|
||||||
//bool create_directories(const path& p, error_code& ec) noexcept;
|
|
||||||
bool create_directory(const path& p);
|
//bool create_directories(const path& p, error_code& ec) noexcept;
|
||||||
//bool create_directory(const path& p, error_code& ec) noexcept;
|
bool create_directory(const path &p);
|
||||||
bool create_directory(const path& p, const path& attributes);
|
|
||||||
//bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept;
|
//bool create_directory(const path& p, error_code& ec) noexcept;
|
||||||
|
bool create_directory(const path &p, const path &attributes);
|
||||||
|
//bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept;
|
||||||
|
|
||||||
|
|
||||||
/// The time of last data modification of p, determined as if by the value of the POSIX
|
/// The time of last data modification of p, determined as if by the value of the POSIX
|
||||||
/// stat structure member st_mtime obtained as if by POSIX stat().
|
/// stat structure member st_mtime obtained as if by POSIX stat().
|
||||||
file_time_type last_write_time(const path& p);
|
file_time_type last_write_time(const path &p);
|
||||||
/// returns file_time_type::min() if an error occurs
|
/// returns file_time_type::min() if an error occurs
|
||||||
//file_time_type last_write_time(const path& p, error_code& ec) noexcept;
|
//file_time_type last_write_time(const path& p, error_code& ec) noexcept;
|
||||||
|
|
||||||
|
|
||||||
path current_path();
|
path current_path();
|
||||||
//path current_path(error_code& ec);
|
|
||||||
void current_path(const path& p); ///< chdir
|
|
||||||
//void current_path(const path& p, error_code& ec) noexcept;
|
|
||||||
|
|
||||||
bool remove(const path& p);
|
//path current_path(error_code& ec);
|
||||||
bool remove(const path& p, std::error_code& ec); // noexcept;
|
void current_path(const path &p); ///< chdir
|
||||||
|
//void current_path(const path& p, error_code& ec) noexcept;
|
||||||
|
|
||||||
//uintmax_t remove_all(const path& p);
|
bool remove(const path &p);
|
||||||
//uintmax_t remove_all(const path& p, error_code& ec) noexcept;
|
|
||||||
|
|
||||||
template<typename CharType>
|
bool remove(const path &p, std::error_code &ec); // noexcept;
|
||||||
std::basic_string<CharType> parent_path(const std::basic_string<CharType>& path)
|
|
||||||
{
|
|
||||||
auto index = path.size();
|
|
||||||
|
|
||||||
if (index)
|
//uintmax_t remove_all(const path& p);
|
||||||
{
|
//uintmax_t remove_all(const path& p, error_code& ec) noexcept;
|
||||||
auto str = path.c_str();
|
|
||||||
|
|
||||||
for (--index; index > 0; --index)
|
template<typename CharType>
|
||||||
{
|
std::basic_string<CharType> parent_path(const std::basic_string<CharType> &path)
|
||||||
auto c = str[index];
|
{
|
||||||
if (c != '\\' && c != '/')
|
auto index = path.size();
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (--index; index > 0; --index)
|
if (index)
|
||||||
{
|
{
|
||||||
auto c = str[index];
|
auto str = path.c_str();
|
||||||
if (c == '\\' || c == '/')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index ? path.substr(0, index + 1) : std::basic_string<CharType>();
|
for (--index; index > 0; --index)
|
||||||
}
|
{
|
||||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
auto c = str[index];
|
||||||
} //end namespace v1
|
if (c != '\\' && c != '/')
|
||||||
#endif
|
break;
|
||||||
} //end namespace filesystem
|
}
|
||||||
} //end namespace experimental
|
|
||||||
|
|
||||||
//namespace filesystem = experimental::filesystem;
|
for (--index; index > 0; --index)
|
||||||
|
{
|
||||||
|
auto c = str[index];
|
||||||
|
if (c == '\\' || c == '/')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index ? path.substr(0, index + 1) : std::basic_string<CharType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
path weakly_canonical(const path& p);
|
||||||
|
path weakly_canonical(const path& p, std::error_code& err);
|
||||||
|
|
||||||
|
bool exists( file_status s ) noexcept;
|
||||||
|
bool exists( const path& p );
|
||||||
|
bool exists( const path& p, std::error_code& ec ) noexcept;
|
||||||
|
} //end namespace filesystem
|
||||||
} //end namespace nana
|
} //end namespace nana
|
||||||
|
|
||||||
|
namespace std
|
||||||
namespace std {
|
{
|
||||||
namespace experimental {
|
namespace filesystem
|
||||||
namespace filesystem {
|
{
|
||||||
|
#if defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201703)
|
||||||
# ifdef CXX_NO_INLINE_NAMESPACE
|
using namespace ::nana::filesystem;
|
||||||
using namespace nana::experimental::filesystem;
|
|
||||||
# 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);
|
|
||||||
|
|
||||||
path weakly_canonical(const path& p);
|
|
||||||
path weakly_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
|
|
||||||
#else
|
#else
|
||||||
|
inline namespace nana_filesystem
|
||||||
|
{
|
||||||
|
using namespace ::nana::filesystem;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else // not #if NANA_USING_NANA_FILESYSTEM and not BOOST_FILESYSTEM, also incomplete STD_FILESYSTEM
|
||||||
//Implements the missing functions for various version of experimental/filesystem
|
//Implements the missing functions for various version of experimental/filesystem
|
||||||
# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM)
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
namespace filesystem
|
namespace filesystem
|
||||||
{
|
{
|
||||||
//Visual Studio 2017
|
#if defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703))
|
||||||
#if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
path absolute(const path& p);
|
||||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801))
|
path absolute(const path& p, std::error_code& err);
|
||||||
|
|
||||||
|
path canonical(const path& p);
|
||||||
|
path canonical(const path& p, std::error_code& err);
|
||||||
|
|
||||||
|
path weakly_canonical(const path& p);
|
||||||
|
path weakly_canonical(const path& p, std::error_code& err);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
#if defined(NANA_MINGW) // todo ??
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
//Visual Studio 2017
|
||||||
|
#if (defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) && defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
||||||
|
(!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603 || (__GNUC__* 100 + __GNUC_MINOR__ < 801)))
|
||||||
path weakly_canonical(const path& p);
|
path weakly_canonical(const path& p);
|
||||||
path weakly_canonical(const path& p, std::error_code& err);
|
path weakly_canonical(const path& p, std::error_code& err);
|
||||||
#endif
|
#endif
|
||||||
}
|
} // namespace filesystem
|
||||||
}
|
} // namespace std
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif //NANA_USING_NANA_FILESYSTEM
|
#endif // incomplete STD_FILESYSTEM
|
||||||
|
|
||||||
#include <nana/pop_ignore_diagnostic>
|
#include <nana/pop_ignore_diagnostic>
|
||||||
#endif //NANA_FILESYSTEM_HPP
|
#endif //NANA_FILESYSTEM_HPP
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file nana\filesystem\filesystem_ext.hpp
|
* @file nana\filesystem\filesystem_ext.hpp
|
||||||
* @autor by Ariel Vina-Rodriguez:
|
* @autor Ariel Vina-Rodriguez:
|
||||||
* @brief Some convenient extensions to the filesystem library.
|
* @brief Some convenient extensions to the filesystem library.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -15,8 +15,8 @@
|
|||||||
#ifndef NANA_FILESYSTEM_EXT_HPP
|
#ifndef NANA_FILESYSTEM_EXT_HPP
|
||||||
#define NANA_FILESYSTEM_EXT_HPP
|
#define NANA_FILESYSTEM_EXT_HPP
|
||||||
|
|
||||||
#include <nana/filesystem/filesystem.hpp>
|
|
||||||
#include <nana/deploy.hpp>
|
#include <nana/deploy.hpp>
|
||||||
|
#include <nana/filesystem/filesystem.hpp>
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
@ -35,16 +35,6 @@ namespace filesystem_ext
|
|||||||
|
|
||||||
std::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::filesystem::path& p)
|
|
||||||
{
|
|
||||||
#if NANA_USING_BOOST_FILESYSTEM
|
|
||||||
return nana::to_utf8(p.generic_wstring());
|
|
||||||
#else
|
|
||||||
return p.generic_u8string();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_directory(const std::filesystem::directory_entry& dir) noexcept
|
inline bool is_directory(const std::filesystem::directory_entry& dir) noexcept
|
||||||
{
|
{
|
||||||
return is_directory(dir.status());
|
return is_directory(dir.status());
|
||||||
@ -57,10 +47,10 @@ class directory_only_iterator : public std::filesystem::directory_iterator
|
|||||||
|
|
||||||
directory_only_iterator& find_first()
|
directory_only_iterator& find_first()
|
||||||
{
|
{
|
||||||
auto end = directory_only_iterator{};
|
directory_only_iterator end{};
|
||||||
while (*this != end)
|
while (*this != end)
|
||||||
{
|
{
|
||||||
if (is_directory((**this).status()))
|
if (is_directory((*(*this)).status()))
|
||||||
return *this;
|
return *this;
|
||||||
this->directory_iterator::operator++();
|
this->directory_iterator::operator++();
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ namespace nana
|
|||||||
virtual void mouse_dropfiles(graph_reference, const arg_dropfiles&);
|
virtual void mouse_dropfiles(graph_reference, const arg_dropfiles&);
|
||||||
|
|
||||||
virtual void focus(graph_reference, const arg_focus&);
|
virtual void focus(graph_reference, const arg_focus&);
|
||||||
|
virtual void key_ime(graph_reference, const arg_ime&);
|
||||||
virtual void key_press(graph_reference, const arg_keyboard&);
|
virtual void key_press(graph_reference, const arg_keyboard&);
|
||||||
virtual void key_char(graph_reference, const arg_keyboard&);
|
virtual void key_char(graph_reference, const arg_keyboard&);
|
||||||
virtual void key_release(graph_reference, const arg_keyboard&);
|
virtual void key_release(graph_reference, const arg_keyboard&);
|
||||||
@ -140,6 +141,7 @@ namespace nana
|
|||||||
void resized(const arg_resized&, const bool);
|
void resized(const arg_resized&, const bool);
|
||||||
void move(const arg_move&, const bool);
|
void move(const arg_move&, const bool);
|
||||||
void focus(const arg_focus&, const bool);
|
void focus(const arg_focus&, const bool);
|
||||||
|
void key_ime(const arg_ime& arg, const bool bForce__EmitInternal);
|
||||||
void key_press(const arg_keyboard&, const bool);
|
void key_press(const arg_keyboard&, const bool);
|
||||||
void key_char(const arg_keyboard&, const bool);
|
void key_char(const arg_keyboard&, const bool);
|
||||||
void key_release(const arg_keyboard&, const bool);
|
void key_release(const arg_keyboard&, const bool);
|
||||||
|
@ -34,6 +34,7 @@ namespace nana
|
|||||||
unload, ///< A form is closed by clicking the X button, only works for root widget.
|
unload, ///< A form is closed by clicking the X button, only works for root widget.
|
||||||
destroy, ///< A widget is about to be destroyed.
|
destroy, ///< A widget is about to be destroyed.
|
||||||
focus, ///< A widget's focus is changed.
|
focus, ///< A widget's focus is changed.
|
||||||
|
key_ime,
|
||||||
key_press, ///< A keyboard is pressed on a focus widget.
|
key_press, ///< A keyboard is pressed on a focus widget.
|
||||||
key_char, ///< The focus widget received a character.
|
key_char, ///< The focus widget received a character.
|
||||||
key_release, ///< A keyboard is released on a focus widget.
|
key_release, ///< A keyboard is released on a focus widget.
|
||||||
|
@ -466,6 +466,19 @@ namespace nana
|
|||||||
reason focus_reason; ///< determines how the widget receives keyboard focus, it is ignored when 'getting' is equal to false
|
reason focus_reason; ///< determines how the widget receives keyboard focus, it is ignored when 'getting' is equal to false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct arg_ime: public event_arg
|
||||||
|
{
|
||||||
|
enum class reason
|
||||||
|
{
|
||||||
|
composition,
|
||||||
|
result
|
||||||
|
};
|
||||||
|
|
||||||
|
::nana::window window_handle; ///< A handle to the event window
|
||||||
|
reason ime_reason;
|
||||||
|
std::wstring composition_string;
|
||||||
|
};
|
||||||
|
|
||||||
struct arg_keyboard : public event_arg
|
struct arg_keyboard : public event_arg
|
||||||
{
|
{
|
||||||
event_code evt_code; ///< it is event_code::key_press in current event
|
event_code evt_code; ///< it is event_code::key_press in current event
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
class color_proxy
|
/// a tool to share and set a color common to many uses
|
||||||
|
class color_proxy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
color_proxy(const color_proxy&);
|
color_proxy(const color_proxy&);
|
||||||
@ -38,6 +39,7 @@ namespace nana
|
|||||||
std::shared_ptr<color> color_;
|
std::shared_ptr<color> color_;
|
||||||
};//end namespace color_proxy
|
};//end namespace color_proxy
|
||||||
|
|
||||||
|
/// define common color and geometrical properties
|
||||||
struct widget_geometrics
|
struct widget_geometrics
|
||||||
{
|
{
|
||||||
virtual ~widget_geometrics() = default;
|
virtual ~widget_geometrics() = default;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/*
|
/**
|
||||||
* A Message Box Class
|
* A Message Box Class
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/gui/msgbox.hpp
|
* @file nana/gui/msgbox.hpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NANA_GUI_MSGBOX_HPP
|
#ifndef NANA_GUI_MSGBOX_HPP
|
||||||
@ -81,8 +81,8 @@ namespace nana
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Displays the message that buffered in the stream.
|
/// \brief Displays the message buffered in the stream.
|
||||||
/// @return, the button that user clicked.
|
/// @return, the button the user clicked.
|
||||||
pick_t show() const;
|
pick_t show() const;
|
||||||
|
|
||||||
/// A function object method alternative to show()
|
/// A function object method alternative to show()
|
||||||
@ -98,6 +98,9 @@ namespace nana
|
|||||||
icon_t icon_;
|
icon_t icon_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Simple convenience dialog to get values from the user.
|
||||||
|
///
|
||||||
|
/// The input value can be a boolean, string, a number, an option from a dropdown list or a date.
|
||||||
class inputbox
|
class inputbox
|
||||||
{
|
{
|
||||||
struct abstract_content
|
struct abstract_content
|
||||||
@ -110,6 +113,8 @@ namespace nana
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// Shows a checkbox for boolean input
|
||||||
class boolean
|
class boolean
|
||||||
: public abstract_content
|
: public abstract_content
|
||||||
{
|
{
|
||||||
@ -128,6 +133,7 @@ namespace nana
|
|||||||
std::unique_ptr<implement> impl_;
|
std::unique_ptr<implement> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Integer input
|
||||||
class integer
|
class integer
|
||||||
: public abstract_content
|
: public abstract_content
|
||||||
{
|
{
|
||||||
@ -146,6 +152,7 @@ namespace nana
|
|||||||
std::unique_ptr<implement> impl_;
|
std::unique_ptr<implement> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Floating-point number input.
|
||||||
class real
|
class real
|
||||||
: public abstract_content
|
: public abstract_content
|
||||||
{
|
{
|
||||||
@ -164,6 +171,7 @@ namespace nana
|
|||||||
std::unique_ptr<implement> impl_;
|
std::unique_ptr<implement> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// String input or an option from a dropdown list.
|
||||||
class text
|
class text
|
||||||
: public abstract_content
|
: public abstract_content
|
||||||
{
|
{
|
||||||
@ -192,6 +200,7 @@ namespace nana
|
|||||||
std::unique_ptr<implement> impl_;
|
std::unique_ptr<implement> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Date input
|
||||||
class date
|
class date
|
||||||
: public abstract_content
|
: public abstract_content
|
||||||
{
|
{
|
||||||
@ -214,6 +223,10 @@ namespace nana
|
|||||||
std::unique_ptr<implement> impl_;
|
std::unique_ptr<implement> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Path of a file.
|
||||||
|
///
|
||||||
|
/// The path requires an object of filebox. When the user clicks the `Browse` button,
|
||||||
|
/// it invokes the filebox with proper configurations to query a filename.
|
||||||
class path
|
class path
|
||||||
: public abstract_content
|
: public abstract_content
|
||||||
{
|
{
|
||||||
@ -231,11 +244,26 @@ namespace nana
|
|||||||
std::unique_ptr<implement> impl_;
|
std::unique_ptr<implement> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inputbox(window, ::std::string description, ::std::string title = ::std::string());
|
inputbox(window owner, ///< A handle to an owner window (just a parent form or widget works)
|
||||||
|
::std::string description, ///< tells users what the purpose for the input. It can be a formatted-text.
|
||||||
|
::std::string title = ::std::string() ///< The title for the inputbox.
|
||||||
|
);
|
||||||
|
|
||||||
void image(::nana::paint::image, bool is_left, const rectangle& valid_area = {});
|
/// shows images at left/right side of inputbox
|
||||||
void image_v(::nana::paint::image, bool is_top, const rectangle& valid_area = {});
|
void image(::nana::paint::image image, ///< The image
|
||||||
|
bool is_left, ///< true to place the image at left side, false to the right side
|
||||||
|
const rectangle& valid_area = {} ///< The area of the image to be displayed
|
||||||
|
);
|
||||||
|
|
||||||
|
/// shows images at top/bottom side of inputbox
|
||||||
|
void image_v(::nana::paint::image, ///< The image
|
||||||
|
bool is_top, ///< `true` to place the image at top side, `false` at bottom side
|
||||||
|
const rectangle& valid_area = {} ///< The area of the image to be displayed
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Shows the inputbox and wait for the user input.
|
||||||
|
///
|
||||||
|
/// This method shows the inputbox without preventing the user interacts with other windows.
|
||||||
template<typename ...Args>
|
template<typename ...Args>
|
||||||
bool show(Args&& ... args)
|
bool show(Args&& ... args)
|
||||||
{
|
{
|
||||||
@ -251,7 +279,11 @@ namespace nana
|
|||||||
return _m_open(contents, false);
|
return _m_open(contents, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...Args>
|
/// Shows the inputbox and wait for the user input blocking other windows.
|
||||||
|
///
|
||||||
|
/// This method blocks the execution and prevents user interaction with other
|
||||||
|
/// windows until the inputbox is closed.
|
||||||
|
template<typename ...Args>
|
||||||
bool show_modal(Args&& ... args)
|
bool show_modal(Args&& ... args)
|
||||||
{
|
{
|
||||||
std::vector<abstract_content*> contents;
|
std::vector<abstract_content*> contents;
|
||||||
@ -267,7 +299,7 @@ namespace nana
|
|||||||
return _m_open(contents, true);
|
return _m_open(contents, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a verifier to verify the user input.
|
/// Sets a verifier to verify the user input, taking a handle to the inputbox.
|
||||||
void verify(std::function<bool(window)> verifier);
|
void verify(std::function<bool(window)> verifier);
|
||||||
|
|
||||||
/** Sets the minimum width for the entry fields
|
/** Sets the minimum width for the entry fields
|
||||||
|
@ -395,7 +395,7 @@ namespace API
|
|||||||
/// Blocks the execution and other windows' messages until the specified window is closed.
|
/// Blocks the execution and other windows' messages until the specified window is closed.
|
||||||
void modal_window(window);
|
void modal_window(window);
|
||||||
|
|
||||||
/// Blocks the execution until the specified window is closesd.
|
/// Blocks the execution until the specified window is closed.
|
||||||
void wait_for(window);
|
void wait_for(window);
|
||||||
|
|
||||||
color fgcolor(window);
|
color fgcolor(window);
|
||||||
|
@ -48,7 +48,7 @@ namespace nana
|
|||||||
template<typename Function>
|
template<typename Function>
|
||||||
void elapse(Function && fn)
|
void elapse(Function && fn)
|
||||||
{
|
{
|
||||||
elapse_.connect(std::forward<Function>(fn));
|
elapse_->connect(std::forward<Function>(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
@ -66,7 +66,7 @@ namespace nana
|
|||||||
private:
|
private:
|
||||||
unsigned _m_interval() const;
|
unsigned _m_interval() const;
|
||||||
private:
|
private:
|
||||||
nana::basic_event<arg_elapse> elapse_;
|
std::shared_ptr<nana::basic_event<arg_elapse>> elapse_;
|
||||||
implement * const impl_;
|
implement * const impl_;
|
||||||
};
|
};
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
@ -87,10 +87,10 @@ namespace nana{
|
|||||||
typedef widget_object<category::widget_tag, drawerbase::button::trigger> base_type;
|
typedef widget_object<category::widget_tag, drawerbase::button::trigger> base_type;
|
||||||
public:
|
public:
|
||||||
button();
|
button();
|
||||||
button(window, bool visible);
|
button(window parent, bool visible);
|
||||||
button(window, const ::std::string& caption, bool visible = true);
|
button(window parent, const ::std::string& caption, bool visible = true);
|
||||||
button(window, const char* caption, bool visible = true);
|
button(window parent, const char* caption, bool visible = true);
|
||||||
button(window, const nana::rectangle& = rectangle(), bool visible = true);
|
button(window parent, const nana::rectangle& = rectangle(), bool visible = true);
|
||||||
|
|
||||||
/// Shows an icon in front of caption
|
/// Shows an icon in front of caption
|
||||||
/**
|
/**
|
||||||
|
@ -65,6 +65,7 @@ namespace nana
|
|||||||
void mouse_up(graph_reference, const arg_mouse&) override;
|
void mouse_up(graph_reference, const arg_mouse&) override;
|
||||||
void mouse_move(graph_reference, const arg_mouse&) override;
|
void mouse_move(graph_reference, const arg_mouse&) override;
|
||||||
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
||||||
|
void key_ime(graph_reference, const arg_ime&) override;
|
||||||
void key_press(graph_reference, const arg_keyboard&) override;
|
void key_press(graph_reference, const arg_keyboard&) override;
|
||||||
void key_char(graph_reference, const arg_keyboard&) override;
|
void key_char(graph_reference, const arg_keyboard&) override;
|
||||||
private:
|
private:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* A Tree Container class implementation
|
* A Tree Container class implementation
|
||||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2020 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -95,6 +95,13 @@ namespace detail
|
|||||||
typedef tree_node<element_type> node_type;
|
typedef tree_node<element_type> node_type;
|
||||||
typedef typename node_type::value_type value_type;
|
typedef typename node_type::value_type value_type;
|
||||||
|
|
||||||
|
enum class enum_order
|
||||||
|
{
|
||||||
|
stop, //Stop enumeration
|
||||||
|
proceed_with_children,
|
||||||
|
proceed
|
||||||
|
};
|
||||||
|
|
||||||
tree_cont()
|
tree_cont()
|
||||||
:root_(nullptr)
|
:root_(nullptr)
|
||||||
{}
|
{}
|
||||||
@ -234,59 +241,6 @@ namespace detail
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Functor>
|
|
||||||
void for_each(node_type* node, Functor f)
|
|
||||||
{
|
|
||||||
if(nullptr == node) node = root_.child;
|
|
||||||
int state = 0; //0: Sibling, the last is a sibling of node
|
|
||||||
//1: Owner, the last is the owner of node
|
|
||||||
//>= 2: Children, the last is is a child of the node that before this node.
|
|
||||||
while(node)
|
|
||||||
{
|
|
||||||
switch(f(*node, state))
|
|
||||||
{
|
|
||||||
case 0: return;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
if(node->child)
|
|
||||||
{
|
|
||||||
node = node->child;
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node->next)
|
|
||||||
{
|
|
||||||
node = node->next;
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state = 1;
|
|
||||||
if(node == &root_) return;
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
++state;
|
|
||||||
if(node->owner->next)
|
|
||||||
{
|
|
||||||
node = node->owner->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
node = node->owner;
|
|
||||||
|
|
||||||
if(node == &root_) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
void for_each(node_type* node, Functor f) const
|
void for_each(node_type* node, Functor f) const
|
||||||
{
|
{
|
||||||
@ -296,24 +250,18 @@ namespace detail
|
|||||||
//>= 2: Children, the last is is a child of the node that before this node.
|
//>= 2: Children, the last is is a child of the node that before this node.
|
||||||
while(node)
|
while(node)
|
||||||
{
|
{
|
||||||
switch(f(*node, state))
|
enum_order order = f(*node, state);
|
||||||
{
|
|
||||||
case 0: return;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
if(node->child)
|
|
||||||
{
|
|
||||||
node = node->child;
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node->next)
|
if (enum_order::stop == order)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (node->child && (enum_order::proceed_with_children == order))
|
||||||
|
{
|
||||||
|
node = node->child;
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
else if(node->next)
|
||||||
{
|
{
|
||||||
node = node->next;
|
node = node->next;
|
||||||
state = 0;
|
state = 0;
|
||||||
@ -340,31 +288,37 @@ namespace detail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PredAllowChild>
|
template<typename PredAllowChild, typename PredAllowNode>
|
||||||
unsigned child_size_if(const ::std::string& key, PredAllowChild pac) const
|
unsigned child_size_if(const ::std::string& key, PredAllowChild pac, PredAllowNode pan) const
|
||||||
{
|
{
|
||||||
auto node = _m_locate(key);
|
auto node = _m_locate(key);
|
||||||
return (node ? child_size_if<PredAllowChild>(*node, pac) : 0);
|
return (node ? child_size_if<PredAllowChild, PredAllowNode>(*node, pac, pan) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PredAllowChild>
|
template<typename PredAllowChild, typename PredAllowNode>
|
||||||
unsigned child_size_if(const node_type& node, PredAllowChild pac) const
|
unsigned child_size_if(const node_type& node, PredAllowChild pac, PredAllowNode pan) const
|
||||||
{
|
{
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
const node_type* pnode = node.child;
|
const node_type* pnode = node.child;
|
||||||
while(pnode)
|
while(pnode)
|
||||||
{
|
{
|
||||||
|
if (!pan(*pnode))
|
||||||
|
{
|
||||||
|
pnode = pnode->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
++size;
|
++size;
|
||||||
if(pnode->child && pac(*pnode))
|
if(pnode->child && pac(*pnode))
|
||||||
size += child_size_if<PredAllowChild>(*pnode, pac);
|
size += child_size_if<PredAllowChild>(*pnode, pac, pan);
|
||||||
|
|
||||||
pnode = pnode->next;
|
pnode = pnode->next;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PredAllowChild>
|
template<typename PredAllowChild, typename PredAllowNode>
|
||||||
std::size_t distance_if(const node_type * node, PredAllowChild pac) const
|
std::size_t distance_if(const node_type * node, PredAllowChild pac, PredAllowNode pan) const
|
||||||
{
|
{
|
||||||
if(nullptr == node) return 0;
|
if(nullptr == node) return 0;
|
||||||
const node_type * iterator = root_.child;
|
const node_type * iterator = root_.child;
|
||||||
@ -374,6 +328,12 @@ namespace detail
|
|||||||
|
|
||||||
while(iterator && iterator != node)
|
while(iterator && iterator != node)
|
||||||
{
|
{
|
||||||
|
if (!pan(*iterator))
|
||||||
|
{
|
||||||
|
iterator = iterator->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
++off;
|
++off;
|
||||||
|
|
||||||
if(iterator->child && pac(*iterator))
|
if(iterator->child && pac(*iterator))
|
||||||
@ -393,8 +353,8 @@ namespace detail
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PredAllowChild>
|
template<typename PredAllowChild, typename PredAllowNode>
|
||||||
node_type* advance_if(node_type* node, std::size_t off, PredAllowChild pac)
|
node_type* advance_if(node_type* node, std::size_t off, PredAllowChild pac, PredAllowNode pan)
|
||||||
{
|
{
|
||||||
if(nullptr == node) node = root_.child;
|
if(nullptr == node) node = root_.child;
|
||||||
|
|
||||||
@ -402,6 +362,12 @@ namespace detail
|
|||||||
|
|
||||||
while(node && off)
|
while(node && off)
|
||||||
{
|
{
|
||||||
|
if (!pan(*node))
|
||||||
|
{
|
||||||
|
node = node->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
--off;
|
--off;
|
||||||
if(node->child && pac(*node))
|
if(node->child && pac(*node))
|
||||||
{
|
{
|
||||||
@ -490,7 +456,7 @@ namespace detail
|
|||||||
void _m_for_each(const ::std::string& key, Function function) const
|
void _m_for_each(const ::std::string& key, Function function) const
|
||||||
{
|
{
|
||||||
//Ignores separaters at the begin of key.
|
//Ignores separaters at the begin of key.
|
||||||
::std::string::size_type beg = key.find_first_not_of("\\/");
|
auto beg = key.find_first_not_of("\\/");
|
||||||
if (key.npos == beg)
|
if (key.npos == beg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* A Form Implementation
|
* A Form Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/gui/widgets/form.hpp
|
* @file nana/gui/widgets/form.hpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NANA_GUI_WIDGET_FORM_HPP
|
#ifndef NANA_GUI_WIDGET_FORM_HPP
|
||||||
@ -42,7 +42,7 @@ namespace nana
|
|||||||
//place methods
|
//place methods
|
||||||
|
|
||||||
place & get_place();
|
place & get_place();
|
||||||
void div(const char* div_text);
|
void div(std::string div_text);
|
||||||
place::field_reference operator[](const char* field_name);
|
place::field_reference operator[](const char* field_name);
|
||||||
void collocate() noexcept;
|
void collocate() noexcept;
|
||||||
private:
|
private:
|
||||||
@ -51,23 +51,30 @@ namespace nana
|
|||||||
}//end namespace form
|
}//end namespace form
|
||||||
}//end namespace drawerbase
|
}//end namespace drawerbase
|
||||||
|
|
||||||
/// \brief Pop-up window. Is different from other window widgets: its default constructor creates the window.
|
/// The form widget represents a popup window.
|
||||||
|
///
|
||||||
|
/// Overall it is a root widget (\see: Overview of widgets) which attaches the OS/Windowing system's native window.
|
||||||
|
/// It is different from other window widgets in that its default constructor creates the window.
|
||||||
/// \see nana::appearance
|
/// \see nana::appearance
|
||||||
class form
|
class form
|
||||||
: public drawerbase::form::form_base
|
: public drawerbase::form::form_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// helper template class for creating the appearance of the form.
|
||||||
using appear = ::nana::appear;
|
using appear = ::nana::appear;
|
||||||
|
|
||||||
/// Creates a window at the point and size specified by rect, and with the specified appearance. Creates a form owned by the desktop.
|
/// Creates a window form owned by the desktop, at the point and size specified by rect, and with the specified appearance.
|
||||||
form(const rectangle& = API::make_center(300, 200), const appearance& = {}); //Default constructor
|
explicit form(const rectangle& = API::make_center(300, 200), const appearance& = {}); //Default constructor
|
||||||
form(const form&, const ::nana::size& = { 300, 200 }, const appearance& = {}); //Copy constructor
|
/// Creates a window always floating above its owner at the point and size specified by rect, with the specified appearance. This window is always floating above its owner.
|
||||||
form(window, const ::nana::size& = { 300, 200 }, const appearance& = {});
|
explicit form(window owner, const ::nana::size& = { 300, 200 }, const appearance& = {});
|
||||||
/// Creates a window at the point and size specified by rect, with the specified appearance. This window is always floating above its owner.
|
explicit form(window owner, const rectangle&, const appearance& = {});
|
||||||
form(window, const rectangle&, const appearance& = {});
|
form(const form&, const ::nana::size& = { 300, 200 }, const appearance& = {}); //Copy constructor
|
||||||
|
|
||||||
void modality() const;
|
/// Blocks the execution and other windows' messages until this window is closed.
|
||||||
void wait_for_this();
|
void modality() const;
|
||||||
|
|
||||||
|
/// Blocks the execution until this window is closed.
|
||||||
|
void wait_for_this();
|
||||||
|
|
||||||
void keyboard_accelerator(const accel_key&, const std::function<void()>& fn);
|
void keyboard_accelerator(const accel_key&, const std::function<void()>& fn);
|
||||||
};
|
};
|
||||||
|
@ -47,10 +47,10 @@ namespace nana
|
|||||||
class column_interface
|
class column_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Destructor
|
// Destructor
|
||||||
virtual ~column_interface() = default;
|
virtual ~column_interface() = default;
|
||||||
|
|
||||||
/// Returns the width of column, in pixel
|
/// Returns the width of the column, in pixel
|
||||||
virtual unsigned width() const noexcept = 0;
|
virtual unsigned width() const noexcept = 0;
|
||||||
|
|
||||||
/// Sets width
|
/// Sets width
|
||||||
@ -824,6 +824,10 @@ namespace nana
|
|||||||
/// Determines whether the item is displayed on the screen
|
/// Determines whether the item is displayed on the screen
|
||||||
bool displayed() const;
|
bool displayed() const;
|
||||||
|
|
||||||
|
/// Determines whether the item_proxy refers to invalid item.
|
||||||
|
/**
|
||||||
|
* @return true if the item_proxy refers to an invalid item, false otherwise.
|
||||||
|
*/
|
||||||
bool empty() const noexcept;
|
bool empty() const noexcept;
|
||||||
|
|
||||||
/// Checks/unchecks the item
|
/// Checks/unchecks the item
|
||||||
@ -1319,10 +1323,10 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
/// The output resolver that converts an item to an object
|
/// The output resolver that converts an item to an object
|
||||||
using oresolver = drawerbase::listbox::oresolver;
|
using oresolver = drawerbase::listbox::oresolver;
|
||||||
|
|
||||||
/// The representation of an item
|
/// The representation of an item cell
|
||||||
using cell = drawerbase::listbox::cell;
|
using cell = drawerbase::listbox::cell;
|
||||||
|
|
||||||
/// The options of exporting items into a string variable
|
/// The options for exporting items into a string variable
|
||||||
using export_options = drawerbase::listbox::export_options;
|
using export_options = drawerbase::listbox::export_options;
|
||||||
|
|
||||||
/// The interface for user-defined inline widgets
|
/// The interface for user-defined inline widgets
|
||||||
@ -1332,12 +1336,12 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
using column_interface = drawerbase::listbox::column_interface;
|
using column_interface = drawerbase::listbox::column_interface;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Constructors
|
// Constructors
|
||||||
listbox() = default;
|
listbox() = default;
|
||||||
listbox(window, bool visible);
|
listbox(window, bool visible);
|
||||||
listbox(window, const rectangle& = {}, bool visible = true);
|
listbox(window, const rectangle& = {}, bool visible = true);
|
||||||
|
|
||||||
//Element access
|
// Element access
|
||||||
|
|
||||||
/// Returns the category at specified location pos, with bounds checking.
|
/// Returns the category at specified location pos, with bounds checking.
|
||||||
cat_proxy at(size_type pos);
|
cat_proxy at(size_type pos);
|
||||||
@ -1356,7 +1360,7 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
item_proxy operator[](const index_pair& abs_pos);
|
item_proxy operator[](const index_pair& abs_pos);
|
||||||
const item_proxy operator[](const index_pair &abs_pos) const;
|
const item_proxy operator[](const index_pair &abs_pos) const;
|
||||||
|
|
||||||
//Associative category access
|
// Associative category access
|
||||||
|
|
||||||
/// Returns a proxy to the category of the key or create a new one in the right order
|
/// Returns a proxy to the category of the key or create a new one in the right order
|
||||||
/**
|
/**
|
||||||
@ -1391,7 +1395,7 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
return cat_proxy(&_m_ess(), categ);
|
return cat_proxy(&_m_ess(), categ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a category which is associated with the specified key
|
/// Removes the category associated with the specified key
|
||||||
/**
|
/**
|
||||||
* @param key The key of category to remove
|
* @param key The key of category to remove
|
||||||
*/
|
*/
|
||||||
@ -1406,7 +1410,6 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
|
|
||||||
bool assoc_ordered(bool);
|
bool assoc_ordered(bool);
|
||||||
|
|
||||||
|
|
||||||
void auto_draw(bool) noexcept; ///< Set state: Redraw automatically after an operation
|
void auto_draw(bool) noexcept; ///< Set state: Redraw automatically after an operation
|
||||||
|
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
@ -1432,15 +1435,17 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
void scroll(bool to_bottom, const index_pair& abs_pos);
|
void scroll(bool to_bottom, const index_pair& abs_pos);
|
||||||
|
|
||||||
/// Appends a new column with a header text and the specified width at the end, and return it position
|
/// Appends a new column with a header text and the specified width at the end, and return it position
|
||||||
|
///
|
||||||
|
/// If a width of 0 is passed the width will be set to fit the header text.
|
||||||
size_type append_header(std::string text_utf8, unsigned width = 120);
|
size_type append_header(std::string text_utf8, unsigned width = 120);
|
||||||
size_type append_header(std::wstring text, unsigned width = 120);
|
size_type append_header(std::wstring text, unsigned width = 120);
|
||||||
|
|
||||||
void clear_headers(); ///< Removes all the columns.
|
void clear_headers(); ///< Removes all the columns.
|
||||||
|
|
||||||
cat_proxy append(std::string category); ///< Appends a new category to the end
|
cat_proxy append(std::string category); ///< Appends a new category to the end
|
||||||
cat_proxy append(std::wstring category); ///< Appends a new category to the end
|
cat_proxy append(std::wstring category); ///< Appends a new category to the end
|
||||||
void append(std::initializer_list<std::string> categories); ///< Appends categories to the end
|
void append(std::initializer_list<std::string> categories); ///< Appends categories to the end
|
||||||
void append(std::initializer_list<std::wstring> categories); ///< Appends categories to the end
|
void append(std::initializer_list<std::wstring> categories); ///< Appends categories to the end
|
||||||
|
|
||||||
/// Access a column at specified position
|
/// Access a column at specified position
|
||||||
/**
|
/**
|
||||||
@ -1480,7 +1485,7 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
void column_movable(bool);
|
void column_movable(bool);
|
||||||
bool column_movable() const;
|
bool column_movable() const;
|
||||||
|
|
||||||
/// Returns a rectangle in where the content is drawn.
|
/// Returns the rectangle where the content is drawn.
|
||||||
rectangle content_area() const;
|
rectangle content_area() const;
|
||||||
|
|
||||||
cat_proxy insert(cat_proxy, ::std::string);
|
cat_proxy insert(cat_proxy, ::std::string);
|
||||||
@ -1489,7 +1494,7 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
/// Inserts an item before a specified position
|
/// Inserts an item before a specified position
|
||||||
/**
|
/**
|
||||||
* @param abs_pos The absolute position before which an item will be inserted.
|
* @param abs_pos The absolute position before which an item will be inserted.
|
||||||
* @param text Text of the first column, in UTF-8 encoded.
|
* @param text Text of the first column, UTF-8 encoded.
|
||||||
*/
|
*/
|
||||||
void insert_item(const index_pair& abs_pos, ::std::string text);
|
void insert_item(const index_pair& abs_pos, ::std::string text);
|
||||||
|
|
||||||
@ -1503,46 +1508,54 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
|
|
||||||
void insert_item(index_pair abs_pos, const listbox& rhs, const index_pairs& indexes);
|
void insert_item(index_pair abs_pos, const listbox& rhs, const index_pairs& indexes);
|
||||||
|
|
||||||
/// Returns an index of item which contains the specified point.
|
/// Returns the index pair of the item which contains the specified "screen" point.
|
||||||
index_pair cast(const point & screen_pos) const;
|
index_pair cast(const point & screen_pos) const;
|
||||||
|
|
||||||
/// Returns the item which is hovered
|
/// 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.
|
* @param return_end Indicates whether to return an end position instead of an empty position if no item is 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.
|
* @return The position of the hovered item. If return_end is true and no item is hovered it returns the position next to the last item of last category.
|
||||||
*/
|
*/
|
||||||
index_pair hovered(bool return_end) const;
|
index_pair hovered(bool return_end) const;
|
||||||
|
|
||||||
/// Returns the absolute position of column which contains the specified point.
|
/// Returns the absolute position of the column which contains the specified "screen" point.
|
||||||
size_type column_from_pos(const point & pos) const;
|
size_type column_from_pos(const point & screen_pos) const;
|
||||||
|
|
||||||
void checkable(bool);
|
void checkable(bool make_checkeable); ///< Display a checkbox at te links of each item if make_checkeable=true
|
||||||
index_pairs checked() const; ///<Returns the items which are checked.
|
index_pairs checked() const; ///< Returns all the items which are checked.
|
||||||
|
|
||||||
void clear(size_type cat); ///<Removes all the items from the specified category
|
void clear(size_type cat); ///< Removes all the items from the specified category
|
||||||
void clear(); ///<Removes all the items from all categories
|
void clear(); ///< Removes all the items from all categories
|
||||||
void erase(size_type cat); ///<Erases a category
|
void erase(size_type cat); ///< Erases a category
|
||||||
void erase(); ///<Erases all categories.
|
void erase(); ///< Erases all categories.
|
||||||
void erase(index_pairs indexes); ///<Erases specified items.
|
void erase(index_pairs indexes); ///< Erases specified items.
|
||||||
item_proxy erase(item_proxy);
|
item_proxy erase(item_proxy indx); ///< Erases specified item.
|
||||||
|
|
||||||
bool sortable() const;
|
bool sortable() const; ///< return whether the listbox is set to be sortable
|
||||||
void sortable(bool enable);
|
void sortable(bool enable); ///< set the listbox to be or not to be sortable
|
||||||
|
|
||||||
///Sets a strict weak ordering comparer for a column
|
///Sets a strict weak ordering comparer for a column
|
||||||
void set_sort_compare( size_type col,
|
void set_sort_compare( size_type col,
|
||||||
std::function<bool(const std::string&, nana::any*,
|
std::function<bool(const std::string&, nana::any*,
|
||||||
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
||||||
|
|
||||||
/// sort() and invalidates any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
/// Sort the items using the specified column.
|
||||||
|
///
|
||||||
|
/// Invalidates 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);
|
void sort_col(size_type col, bool reverse = false);
|
||||||
size_type sort_col() const;
|
size_type sort_col() const; ///< return the column currently used to sort items
|
||||||
|
|
||||||
/// potentially invalidates any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
/// Eliminate any "column sorting", effectively setting the items in the order of creation.
|
||||||
|
///
|
||||||
|
/// Potentially invalidates any existing reference from display position to absolute item,
|
||||||
|
/// that is: after unsort() display offset may point to different items
|
||||||
void unsort();
|
void unsort();
|
||||||
|
|
||||||
|
///< Prevent sorting until `freeze` is set to false.
|
||||||
bool freeze_sort(bool freeze);
|
bool freeze_sort(bool freeze);
|
||||||
|
|
||||||
index_pairs selected() const; ///<Get the absolute indexs of all the selected items
|
index_pairs selected() const; ///<Get the absolute indexes of all the selected items
|
||||||
|
|
||||||
void show_header(bool);
|
void show_header(bool);
|
||||||
bool visible_header() const;
|
bool visible_header() const;
|
||||||
@ -1554,7 +1567,7 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
void enable_single(bool for_selection, bool category_limited);
|
void enable_single(bool for_selection, bool category_limited);
|
||||||
void disable_single(bool for_selection);
|
void disable_single(bool for_selection);
|
||||||
bool is_single_enabled(bool for_selection) const noexcept; ///< Determines whether the single selection/check is enabled.
|
bool is_single_enabled(bool for_selection) const noexcept; ///< Determines whether the single selection/check is enabled.
|
||||||
export_options& def_export_options();
|
export_options& def_export_options(); ///< return a modifiable reference to the export options in use
|
||||||
|
|
||||||
|
|
||||||
/// Sets a renderer for category icon
|
/// Sets a renderer for category icon
|
||||||
|
@ -98,6 +98,7 @@ namespace nana{ namespace widgets
|
|||||||
|
|
||||||
void set_accept(std::function<bool(char_type)>);
|
void set_accept(std::function<bool(char_type)>);
|
||||||
void set_accept(accepts);
|
void set_accept(accepts);
|
||||||
|
bool respond_ime(const arg_ime& arg);
|
||||||
bool respond_char(const arg_keyboard& arg);
|
bool respond_char(const arg_keyboard& arg);
|
||||||
bool respond_key(const arg_keyboard& arg);
|
bool respond_key(const arg_keyboard& arg);
|
||||||
|
|
||||||
@ -328,6 +329,8 @@ namespace nana{ namespace widgets
|
|||||||
nana::upoint caret; //position of caret by text, it specifies the position of a new character
|
nana::upoint caret; //position of caret by text, it specifies the position of a new character
|
||||||
nana::upoint shift_begin_caret;
|
nana::upoint shift_begin_caret;
|
||||||
}points_;
|
}points_;
|
||||||
|
|
||||||
|
size_t composition_size_ { 0 };
|
||||||
};
|
};
|
||||||
}//end namespace skeletons
|
}//end namespace skeletons
|
||||||
}//end namespace widgets
|
}//end namespace widgets
|
||||||
|
@ -66,6 +66,7 @@ namespace nana
|
|||||||
void mouse_move(graph_reference, const arg_mouse&) override;
|
void mouse_move(graph_reference, const arg_mouse&) override;
|
||||||
void mouse_up(graph_reference, const arg_mouse& arg) override;
|
void mouse_up(graph_reference, const arg_mouse& arg) override;
|
||||||
void mouse_leave(graph_reference, const arg_mouse&) override;
|
void mouse_leave(graph_reference, const arg_mouse&) override;
|
||||||
|
void key_ime(graph_reference, const arg_ime& arg) override;
|
||||||
void key_press(graph_reference, const arg_keyboard&) override;
|
void key_press(graph_reference, const arg_keyboard&) override;
|
||||||
void key_char(graph_reference, const arg_keyboard&) override;
|
void key_char(graph_reference, const arg_keyboard&) override;
|
||||||
void resized(graph_reference, const arg_resized&) override;
|
void resized(graph_reference, const arg_resized&) override;
|
||||||
|
@ -83,6 +83,7 @@ namespace nana
|
|||||||
void mouse_enter(graph_reference, const arg_mouse&) override;
|
void mouse_enter(graph_reference, const arg_mouse&) override;
|
||||||
void mouse_leave(graph_reference, const arg_mouse&) override;
|
void mouse_leave(graph_reference, const arg_mouse&) override;
|
||||||
void dbl_click(graph_reference, const arg_mouse&) override;
|
void dbl_click(graph_reference, const arg_mouse&) override;
|
||||||
|
void key_ime(graph_reference, const arg_ime&) override;
|
||||||
void key_press(graph_reference, const arg_keyboard&)override;
|
void key_press(graph_reference, const arg_keyboard&)override;
|
||||||
void key_char(graph_reference, const arg_keyboard&) override;
|
void key_char(graph_reference, const arg_keyboard&) override;
|
||||||
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* A Tree Box Implementation
|
* A Tree Box Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2020 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE or copy at
|
* (See accompanying file LICENSE or copy at
|
||||||
@ -49,7 +49,7 @@ namespace nana
|
|||||||
|
|
||||||
struct node_attribute
|
struct node_attribute
|
||||||
{
|
{
|
||||||
bool has_children;
|
bool has_children; ///< Determines whether the node has visible children
|
||||||
bool expended;
|
bool expended;
|
||||||
checkstate checked;
|
checkstate checked;
|
||||||
bool selected;
|
bool selected;
|
||||||
@ -117,6 +117,7 @@ namespace nana
|
|||||||
::std::string text;
|
::std::string text;
|
||||||
nana::any value;
|
nana::any value;
|
||||||
bool expanded;
|
bool expanded;
|
||||||
|
bool hidden;
|
||||||
checkstate checked;
|
checkstate checked;
|
||||||
::std::string img_idstr;
|
::std::string img_idstr;
|
||||||
};
|
};
|
||||||
@ -218,6 +219,12 @@ namespace nana
|
|||||||
/// Select the node, and returns itself..
|
/// Select the node, and returns itself..
|
||||||
item_proxy& select(bool);
|
item_proxy& select(bool);
|
||||||
|
|
||||||
|
/// Return true when the node is hidden.
|
||||||
|
bool hidden() const;
|
||||||
|
|
||||||
|
/// Hide the node, and returns itself.
|
||||||
|
item_proxy& hide(bool);
|
||||||
|
|
||||||
/// Return the icon.
|
/// Return the icon.
|
||||||
const ::std::string& icon() const;
|
const ::std::string& icon() const;
|
||||||
|
|
||||||
@ -343,6 +350,7 @@ namespace nana
|
|||||||
basic_event<arg_treebox> checked; ///< a user checks or unchecks a node
|
basic_event<arg_treebox> checked; ///< a user checks or unchecks a node
|
||||||
basic_event<arg_treebox> selected; ///< a user selects or unselects a node
|
basic_event<arg_treebox> selected; ///< a user selects or unselects a node
|
||||||
basic_event<arg_treebox> hovered; ///< a user moves the cursor over a node
|
basic_event<arg_treebox> hovered; ///< a user moves the cursor over a node
|
||||||
|
basic_event<arg_treebox> hidden; ///< a user hides or shows a node
|
||||||
};
|
};
|
||||||
}//end namespace treebox
|
}//end namespace treebox
|
||||||
}//end namespace drawerbase
|
}//end namespace drawerbase
|
||||||
@ -484,6 +492,14 @@ namespace nana
|
|||||||
|
|
||||||
/// Gets the current hovered node.
|
/// Gets the current hovered node.
|
||||||
item_proxy hovered(bool exclude_expander) const;
|
item_proxy hovered(bool exclude_expander) const;
|
||||||
|
|
||||||
|
|
||||||
|
/// Enable/disable the interactions (selection, click, ...) on the entire line of the treebox.
|
||||||
|
/**
|
||||||
|
* @param enable bool whether to enable.
|
||||||
|
*/
|
||||||
|
void use_entire_line(bool enable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;
|
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/gui/widgets/widget.hpp
|
* @file nana/gui/widgets/widget.hpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NANA_GUI_WIDGET_HPP
|
#ifndef NANA_GUI_WIDGET_HPP
|
||||||
@ -48,8 +48,8 @@ namespace nana
|
|||||||
widget() = default;
|
widget() = default;
|
||||||
|
|
||||||
virtual ~widget() = default;
|
virtual ~widget() = default;
|
||||||
virtual window handle() const = 0; ///< Returns the handle of window, returns 0 if window is not created.
|
virtual window handle() const = 0; ///< Returns the handle of window, returns 0 if window is not created.
|
||||||
bool empty() const; ///< Determines whether the manipulator is handling a window.
|
bool empty() const; ///< Determines whether the manipulator is handling a window.
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
window parent() const;
|
window parent() const;
|
||||||
@ -169,9 +169,17 @@ namespace nana
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Base class of all the classes defined as a widget window. Defaultly a widget_tag
|
/// Base class of all the classes defined as a widget window. Defaultly a widget_tag
|
||||||
template<typename Category, typename DrawerTrigger, typename Events = ::nana::general_events, typename Scheme = ::nana::widget_geometrics,
|
///
|
||||||
typename = typename std::enable_if<std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value>::type> //type DrawerTrigger must be derived from nana::drawer_trigger
|
/// \tparam Category
|
||||||
|
/// \tparam DrawerTrigger must be derived from nana::drawer_trigger
|
||||||
|
/// \tparam Events
|
||||||
|
/// \tparam Scheme
|
||||||
|
template<typename Category,
|
||||||
|
typename DrawerTrigger,
|
||||||
|
typename Events = ::nana::general_events,
|
||||||
|
typename Scheme = ::nana::widget_geometrics,
|
||||||
|
typename = typename std::enable_if<std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value>::type>
|
||||||
class widget_object: public detail::widget_base
|
class widget_object: public detail::widget_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -293,8 +301,13 @@ namespace nana
|
|||||||
std::unique_ptr<scheme_type> scheme_;
|
std::unique_ptr<scheme_type> scheme_;
|
||||||
};//end class widget_object
|
};//end class widget_object
|
||||||
|
|
||||||
/// Base class of all the classes defined as a non-graphics-buffer widget window. The second template parameter DrawerTrigger is always ignored.\see nana::panel
|
/// Base class of all the classes defined as a non-graphics-buffer widget window.
|
||||||
template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger
|
///
|
||||||
|
/// The second template parameter DrawerTrigger is always ignored.\see nana::panel
|
||||||
|
/// type DrawerTrigger must be derived from nana::drawer_trigger
|
||||||
|
template<typename DrawerTrigger,
|
||||||
|
typename Events,
|
||||||
|
typename Scheme>
|
||||||
class widget_object<category::lite_widget_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
|
class widget_object<category::lite_widget_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -359,8 +372,14 @@ namespace nana
|
|||||||
};//end class widget_object
|
};//end class widget_object
|
||||||
|
|
||||||
|
|
||||||
/// Base class of all the classes defined as a root window. \see nana::form
|
/// Base class of all the classes defined as a root window. \see nana::form
|
||||||
template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger
|
///
|
||||||
|
/// \tparam DrawerTrigger must be derived from nana::drawer_trigger
|
||||||
|
/// \tparam Events
|
||||||
|
/// \tparam Scheme
|
||||||
|
template<typename DrawerTrigger,
|
||||||
|
typename Events,
|
||||||
|
typename Scheme>
|
||||||
class widget_object<category::root_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
|
class widget_object<category::root_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* A Character Encoding Set Implementation
|
* A Character Encoding Set Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -245,8 +245,12 @@ namespace nana
|
|||||||
int bytes = ::WideCharToMultiByte(CP_ACP, 0, s, -1, 0, 0, 0, 0);
|
int bytes = ::WideCharToMultiByte(CP_ACP, 0, s, -1, 0, 0, 0, 0);
|
||||||
if(bytes > 1)
|
if(bytes > 1)
|
||||||
{
|
{
|
||||||
mbstr.resize(bytes - 1);
|
// the bytes is the length of the string with null character.
|
||||||
::WideCharToMultiByte(CP_ACP, 0, s, -1, &(mbstr[0]), bytes - 1, 0, 0);
|
mbstr.resize(bytes);
|
||||||
|
::WideCharToMultiByte(CP_ACP, 0, s, -1, &(mbstr[0]), bytes, 0, 0);
|
||||||
|
|
||||||
|
//Remove the null character written by WideCharToMultiByte
|
||||||
|
mbstr.pop_back();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
@ -279,8 +283,12 @@ namespace nana
|
|||||||
int chars = ::MultiByteToWideChar(CP_ACP, 0, s, -1, 0, 0);
|
int chars = ::MultiByteToWideChar(CP_ACP, 0, s, -1, 0, 0);
|
||||||
if(chars > 1)
|
if(chars > 1)
|
||||||
{
|
{
|
||||||
wcstr.resize(chars - 1);
|
// the length of the string with null character.
|
||||||
::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars - 1);
|
wcstr.resize(chars);
|
||||||
|
::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars);
|
||||||
|
|
||||||
|
// remove the null character written by MultiByteToWideChar
|
||||||
|
wcstr.pop_back();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
locale_initializer::init();
|
locale_initializer::init();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/**
|
||||||
* A ISO C++ FileSystem Implementation
|
* A ISO C++ FileSystem Implementation
|
||||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
@ -6,16 +6,17 @@
|
|||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/filesystem/filesystem.cpp
|
* @file nana/filesystem/filesystem.cpp
|
||||||
* @description:
|
* @description
|
||||||
* provide some interface for file management
|
* provide some interface for file management
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <nana/config.hpp>
|
||||||
#include <nana/filesystem/filesystem_ext.hpp>
|
#include <nana/filesystem/filesystem_ext.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <nana/config.hpp>
|
|
||||||
#ifdef _nana_std_put_time
|
#ifdef _nana_std_put_time
|
||||||
#include <nana/stdc++.hpp>
|
#include <nana/stdc++.hpp>
|
||||||
#else
|
#else
|
||||||
@ -148,45 +149,41 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NANA_USING_NANA_FILESYSTEM
|
#if NANA_USING_NANA_FILESYSTEM // and BOOST ?
|
||||||
|
|
||||||
namespace nana_fs = nana::experimental::filesystem;
|
namespace nana_fs = nana::filesystem;
|
||||||
|
namespace nana
|
||||||
|
{
|
||||||
|
namespace filesystem
|
||||||
|
{
|
||||||
|
//class filesystem_error
|
||||||
|
filesystem_error::filesystem_error(const std::string& msg, std::error_code err)
|
||||||
|
: std::system_error(err, msg)
|
||||||
|
{}
|
||||||
|
|
||||||
namespace nana { namespace experimental { namespace filesystem
|
filesystem_error::filesystem_error(const std::string& msg, const path& path1, std::error_code err)
|
||||||
{
|
: std::system_error(err, msg),
|
||||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
path1_(path1)
|
||||||
inline namespace v1 {
|
{}
|
||||||
#endif
|
|
||||||
|
|
||||||
//class filesystem_error
|
filesystem_error::filesystem_error(const std::string& msg, const path& path1, const path& path2, std::error_code err)
|
||||||
filesystem_error::filesystem_error(const std::string& msg, std::error_code err)
|
: std::system_error(err, msg),
|
||||||
: std::system_error(err, msg)
|
path1_(path1),
|
||||||
{}
|
path2_(path2)
|
||||||
|
{}
|
||||||
|
|
||||||
filesystem_error::filesystem_error(const std::string& msg, const path& path1, std::error_code err)
|
const path& filesystem_error::path1() const noexcept
|
||||||
: std::system_error(err, msg),
|
{
|
||||||
path1_(path1)
|
return path1_;
|
||||||
{}
|
}
|
||||||
|
|
||||||
filesystem_error::filesystem_error(const std::string& msg, const path& path1, const path& path2, std::error_code err)
|
const path& filesystem_error::path2() const noexcept
|
||||||
: std::system_error(err, msg),
|
{
|
||||||
path1_(path1),
|
return path2_;
|
||||||
path2_(path2)
|
}
|
||||||
{}
|
//end class filesystem_error
|
||||||
|
|
||||||
const path& filesystem_error::path1() const noexcept
|
//Because of No wide character version of POSIX
|
||||||
{
|
|
||||||
return path1_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const path& filesystem_error::path2() const noexcept
|
|
||||||
{
|
|
||||||
return path2_;
|
|
||||||
}
|
|
||||||
//end class filesystem_error
|
|
||||||
|
|
||||||
|
|
||||||
//Because of No wide character version of POSIX
|
|
||||||
#if defined(NANA_POSIX)
|
#if defined(NANA_POSIX)
|
||||||
const char* separators = "/";
|
const char* separators = "/";
|
||||||
const char separator = '/';
|
const char separator = '/';
|
||||||
@ -512,10 +509,10 @@ namespace nana { namespace experimental { namespace filesystem
|
|||||||
return to_wstring(pathstr_);
|
return to_wstring(pathstr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path::u8string() const
|
/*std::string path::u8string() const
|
||||||
{
|
{
|
||||||
return to_utf8(pathstr_);
|
return to_utf8(pathstr_);
|
||||||
}
|
}*/
|
||||||
std::string path::generic_string() const
|
std::string path::generic_string() const
|
||||||
{
|
{
|
||||||
auto str = string();
|
auto str = string();
|
||||||
@ -528,12 +525,12 @@ namespace nana { namespace experimental { namespace filesystem
|
|||||||
std::replace(str.begin(), str.end(), L'\\', L'/');
|
std::replace(str.begin(), str.end(), L'\\', L'/');
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
std::string path::generic_u8string() const // uppss ...
|
/*std::string path::generic_u8string() const // uppss ...
|
||||||
{
|
{
|
||||||
auto str = pathstr_;
|
auto str = pathstr_;
|
||||||
std::replace(str.begin(), str.end(), '\\', '/'); // uppss ... revise this !!!!!
|
std::replace(str.begin(), str.end(), '\\', '/'); // uppss ... revise this !!!!!
|
||||||
return to_utf8(str);
|
return to_utf8(str);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
path path::lexically_normal() const
|
path path::lexically_normal() const
|
||||||
{
|
{
|
||||||
@ -667,7 +664,7 @@ namespace nana { namespace experimental { namespace filesystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
//class directory_entry
|
//class directory_entry
|
||||||
directory_entry::directory_entry(const nana_fs::path& p)
|
directory_entry::directory_entry(const filesystem::path& p)
|
||||||
:path_{ p }
|
:path_{ p }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -713,112 +710,112 @@ namespace nana { namespace experimental { namespace filesystem
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
directory_iterator::directory_iterator() noexcept
|
directory_iterator::directory_iterator() noexcept
|
||||||
: end_(true),
|
: end_(true),
|
||||||
handle_(nullptr)
|
handle_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
directory_iterator::directory_iterator(const path& file_path)
|
directory_iterator::directory_iterator(const path& file_path)
|
||||||
{
|
{
|
||||||
_m_prepare(file_path);
|
_m_prepare(file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
directory_iterator::directory_iterator(const path& p, directory_options opt):
|
directory_iterator::directory_iterator(const path& p, directory_options opt):
|
||||||
option_(opt)
|
option_(opt)
|
||||||
{
|
{
|
||||||
_m_prepare(p);
|
_m_prepare(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
const directory_iterator::value_type& directory_iterator::operator*() const { return value_; }
|
const directory_iterator::value_type& directory_iterator::operator*() const { return value_; }
|
||||||
|
|
||||||
const directory_iterator::value_type*
|
const directory_iterator::value_type*
|
||||||
directory_iterator::operator->() const { return &(operator*()); }
|
directory_iterator::operator->() const { return &(operator*()); }
|
||||||
|
|
||||||
directory_iterator& directory_iterator::operator++()
|
directory_iterator& directory_iterator::operator++()
|
||||||
{
|
{
|
||||||
_m_read(); return *this;
|
_m_read(); return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
directory_iterator directory_iterator::operator++(int)
|
directory_iterator directory_iterator::operator++(int)
|
||||||
{
|
{
|
||||||
directory_iterator tmp = *this;
|
directory_iterator tmp = *this;
|
||||||
_m_read();
|
_m_read();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool directory_iterator::equal(const directory_iterator& x) const
|
bool directory_iterator::equal(const directory_iterator& x) const
|
||||||
{
|
{
|
||||||
if (end_ && (end_ == x.end_)) return true;
|
if (end_ && (end_ == x.end_)) return true;
|
||||||
return (value_.path().filename() == x.value_.path().filename());
|
return (value_.path().filename() == x.value_.path().filename());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void directory_iterator::_m_prepare(const path& file_path)
|
void directory_iterator::_m_prepare(const path& file_path)
|
||||||
{
|
{
|
||||||
path_ = file_path.native();
|
path_ = file_path.native();
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
if (!path_.empty() && (path_.back() != L'/' && path_.back() != L'\\'))
|
if (!path_.empty() && (path_.back() != L'/' && path_.back() != L'\\'))
|
||||||
path_ += L'\\';
|
path_ += L'\\';
|
||||||
|
|
||||||
auto pat = path_;
|
auto pat = path_;
|
||||||
DWORD attr = ::GetFileAttributes(pat.data());
|
DWORD attr = ::GetFileAttributes(pat.data());
|
||||||
if ((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY))
|
if ((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
pat += L"*";
|
pat += L"*";
|
||||||
|
|
||||||
WIN32_FIND_DATAW wfd;
|
WIN32_FIND_DATAW wfd;
|
||||||
::HANDLE handle = ::FindFirstFile(pat.data(), &wfd);
|
::HANDLE handle = ::FindFirstFile(pat.data(), &wfd);
|
||||||
|
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
end_ = true;
|
end_ = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (_m_ignore(wfd.cFileName))
|
while (_m_ignore(wfd.cFileName))
|
||||||
{
|
{
|
||||||
if (::FindNextFile(handle, &wfd) == 0)
|
if (::FindNextFile(handle, &wfd) == 0)
|
||||||
{
|
{
|
||||||
end_ = true;
|
end_ = true;
|
||||||
::FindClose(handle);
|
::FindClose(handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value_ = value_type(path(path_ + wfd.cFileName));
|
value_ = value_type(path(path_ + wfd.cFileName));
|
||||||
|
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
if (path_.size() && (path_.back() != '/'))
|
if (path_.size() && (path_.back() != '/'))
|
||||||
path_ += '/';
|
path_ += '/';
|
||||||
auto handle = opendir(path_.c_str());
|
auto handle = opendir(path_.c_str());
|
||||||
end_ = true;
|
end_ = true;
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
struct dirent * dnt = readdir(handle);
|
struct dirent * dnt = readdir(handle);
|
||||||
if (dnt)
|
if (dnt)
|
||||||
{
|
{
|
||||||
while (_m_ignore(dnt->d_name))
|
while (_m_ignore(dnt->d_name))
|
||||||
{
|
{
|
||||||
dnt = readdir(handle);
|
dnt = readdir(handle);
|
||||||
if (dnt == 0)
|
if (dnt == 0)
|
||||||
{
|
{
|
||||||
closedir(handle);
|
closedir(handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value_ = value_type(path_ + dnt->d_name);
|
value_ = value_type(path_ + dnt->d_name);
|
||||||
end_ = false;
|
end_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (false == end_)
|
if (false == end_)
|
||||||
{
|
{
|
||||||
find_ptr_ = std::shared_ptr<find_handle>(new find_handle(handle), inner_handle_deleter());
|
find_ptr_ = std::shared_ptr<find_handle>(new find_handle(handle), inner_handle_deleter());
|
||||||
handle_ = handle;
|
handle_ = handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void directory_iterator::_m_read()
|
void directory_iterator::_m_read()
|
||||||
{
|
{
|
||||||
if (handle_)
|
if (handle_)
|
||||||
{
|
{
|
||||||
@ -978,7 +975,6 @@ namespace nana { namespace experimental { namespace filesystem
|
|||||||
#endif
|
#endif
|
||||||
}//end namespace detail
|
}//end namespace detail
|
||||||
|
|
||||||
|
|
||||||
file_status status(const path& p)
|
file_status status(const path& p)
|
||||||
{
|
{
|
||||||
std::error_code err;
|
std::error_code err;
|
||||||
@ -1108,93 +1104,290 @@ namespace nana { namespace experimental { namespace filesystem
|
|||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool create_directory(const path& p)
|
bool create_directory(const path& p)
|
||||||
{
|
{
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
return (FALSE != ::CreateDirectoryW(p.c_str(), 0));
|
return (FALSE != ::CreateDirectoryW(p.c_str(), 0));
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
return (0 == ::mkdir(p.c_str(), static_cast<int>(perms::all)));
|
return (0 == ::mkdir(p.c_str(), static_cast<int>(perms::all)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove(const path& p)
|
bool remove(const path& p)
|
||||||
{
|
{
|
||||||
auto stat = status(p);
|
auto stat = status(p);
|
||||||
if (stat.type() == file_type::directory)
|
if (stat.type() == file_type::directory)
|
||||||
return detail::rm_dir(p);
|
return detail::rm_dir(p);
|
||||||
|
|
||||||
return detail::rm_file(p);
|
return detail::rm_file(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove(const path& p, std::error_code & ec)
|
bool remove(const path& p, std::error_code & ec)
|
||||||
{
|
{
|
||||||
ec.clear();
|
ec.clear();
|
||||||
auto stat = status(p);
|
auto stat = status(p);
|
||||||
if (stat.type() == file_type::directory)
|
if (stat.type() == file_type::directory)
|
||||||
return detail::rm_dir(p);
|
return detail::rm_dir(p);
|
||||||
|
|
||||||
return detail::rm_file(p);
|
return detail::rm_file(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
path current_path()
|
path current_path()
|
||||||
{
|
{
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
wchar_t buf[MAX_PATH];
|
wchar_t buf[MAX_PATH];
|
||||||
DWORD len = ::GetCurrentDirectoryW(MAX_PATH, buf);
|
DWORD len = ::GetCurrentDirectoryW(MAX_PATH, buf);
|
||||||
if (len)
|
if (len)
|
||||||
{
|
{
|
||||||
if (len > MAX_PATH)
|
if (len > MAX_PATH)
|
||||||
{
|
{
|
||||||
wchar_t * p = new wchar_t[len + 1];
|
wchar_t * p = new wchar_t[len + 1];
|
||||||
::GetCurrentDirectoryW(len + 1, p);
|
::GetCurrentDirectoryW(len + 1, p);
|
||||||
std::wstring s = p;
|
std::wstring s = p;
|
||||||
delete[] p;
|
delete[] p;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
char buf[260];
|
char buf[260];
|
||||||
auto pstr = ::getcwd(buf, 260);
|
auto pstr = ::getcwd(buf, 260);
|
||||||
if (pstr)
|
if (pstr)
|
||||||
return pstr;
|
return pstr;
|
||||||
|
|
||||||
int bytes = 260 + 260;
|
int bytes = 260 + 260;
|
||||||
while (ERANGE == errno)
|
while (ERANGE == errno)
|
||||||
{
|
{
|
||||||
std::unique_ptr<char[]> buf(new char[bytes]);
|
std::unique_ptr<char[]> buf(new char[bytes]);
|
||||||
auto pstr = ::getcwd(buf.get(), bytes);
|
auto pstr = ::getcwd(buf.get(), bytes);
|
||||||
if (pstr)
|
if (pstr)
|
||||||
return path(pstr);
|
return path(pstr);
|
||||||
|
|
||||||
bytes += 260;
|
bytes += 260;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return path();
|
return path();
|
||||||
}
|
}
|
||||||
|
|
||||||
void current_path(const path& p)
|
void current_path(const path& p)
|
||||||
{
|
{
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
::SetCurrentDirectoryW(p.c_str());
|
::SetCurrentDirectoryW(p.c_str());
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
::chdir(p.c_str());
|
::chdir(p.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
path absolute(const path& p)
|
||||||
} //end namespace v1
|
{
|
||||||
|
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
|
#endif
|
||||||
}//end namespace filesystem
|
return base_root_name / p;
|
||||||
} //end namespace experimental
|
}
|
||||||
|
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,
|
||||||
|
std::error_code(static_cast<int>(std::errc::no_such_file_or_directory), std::generic_category())));
|
||||||
|
err->assign(static_cast<int>(std::errc::no_such_file_or_directory), std::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_throw(int err_val, const path& p, std::error_code* ec, const char* message)
|
||||||
|
{
|
||||||
|
if (0 == err_val)
|
||||||
|
{
|
||||||
|
if (ec) ec->clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //error
|
||||||
|
if (nullptr == ec)
|
||||||
|
throw (filesystem_error(
|
||||||
|
message, p,
|
||||||
|
std::error_code(err_val, std::generic_category())));
|
||||||
|
else
|
||||||
|
ec->assign(err_val, std::system_category());
|
||||||
|
}
|
||||||
|
return err_val != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
path weakly_canonical(const path& p, std::error_code* err)
|
||||||
|
{
|
||||||
|
path head{ p };
|
||||||
|
|
||||||
|
std::error_code tmp_err;
|
||||||
|
std::vector<path> elements;
|
||||||
|
while (!head.empty())
|
||||||
|
{
|
||||||
|
auto head_status = status(head, tmp_err);
|
||||||
|
|
||||||
|
if (head_status.type() == file_type::unknown)
|
||||||
|
{
|
||||||
|
if (try_throw(static_cast<int>(std::errc::invalid_argument), head, err, "nana::filesystem::weakly_canonical"))
|
||||||
|
return path{};
|
||||||
|
}
|
||||||
|
if (head_status.type() != file_type::not_found)
|
||||||
|
break;
|
||||||
|
|
||||||
|
elements.emplace_back(head.filename());
|
||||||
|
head.remove_filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tail_has_dots = false;
|
||||||
|
path tail;
|
||||||
|
|
||||||
|
for (auto & e : elements)
|
||||||
|
{
|
||||||
|
tail /= e;
|
||||||
|
// for a later optimization, track if any dot or dot-dot elements are present
|
||||||
|
if (e.native().size() <= 2
|
||||||
|
&& e.native()[0] == '.'
|
||||||
|
&& (e.native().size() == 1 || e.native()[1] == '.'))
|
||||||
|
tail_has_dots = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head.empty())
|
||||||
|
return p.lexically_normal();
|
||||||
|
head = canonical(head, tmp_err);
|
||||||
|
if (try_throw(tmp_err.value(), head, err, "nana::filesystem::weakly_canonical"))
|
||||||
|
return path();
|
||||||
|
return tail.empty()
|
||||||
|
? head
|
||||||
|
: (tail_has_dots // optimization: only normalize if tail had dot or dot-dot element
|
||||||
|
? (head / tail).lexically_normal()
|
||||||
|
: head / tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
path weakly_canonical(const path& p)
|
||||||
|
{
|
||||||
|
return weakly_canonical(p, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
path weakly_canonical(const path& p, std::error_code& err)
|
||||||
|
{
|
||||||
|
return weakly_canonical(p, &err);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} //end namespace filesystem
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
#else
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
namespace filesystem
|
namespace filesystem
|
||||||
{
|
{
|
||||||
#if defined(NANA_FILESYSTEM_FORCE) || \
|
#if defined(_MSC_VER) && (_MSC_VER < 1900) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703))
|
||||||
(defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703)))
|
|
||||||
path absolute(const path& p)
|
path absolute(const path& p)
|
||||||
{
|
{
|
||||||
if (p.empty())
|
if (p.empty())
|
||||||
@ -1379,8 +1572,8 @@ namespace std
|
|||||||
return weakly_canonical(p, &err);
|
return weakly_canonical(p, &err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/*
|
||||||
#if defined(NANA_FILESYSTEM_FORCE) || defined(NANA_MINGW)
|
#if defined(NANA_MINGW)
|
||||||
bool exists( std::filesystem::file_status s ) noexcept
|
bool exists( std::filesystem::file_status s ) noexcept
|
||||||
{
|
{
|
||||||
return s.type() != file_type::not_found;
|
return s.type() != file_type::not_found;
|
||||||
@ -1395,20 +1588,10 @@ namespace std
|
|||||||
{
|
{
|
||||||
return exists(status(p, ec));
|
return exists(status(p, ec));
|
||||||
}
|
}
|
||||||
#endif
|
*/
|
||||||
}//end namespace filesystem
|
|
||||||
}//end namespace std
|
|
||||||
|
|
||||||
#else //NANA_USING_NANA_FILESYSTEM
|
#if (defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) && defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
||||||
# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM)
|
(!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603 || (__GNUC__* 100 + __GNUC_MINOR__ < 801)))
|
||||||
|
|
||||||
//Defines the functions that are not provided by experimental/filesystem
|
|
||||||
namespace std
|
|
||||||
{
|
|
||||||
namespace filesystem
|
|
||||||
{
|
|
||||||
#if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
|
||||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801))
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@ -1551,10 +1734,9 @@ namespace std
|
|||||||
{
|
{
|
||||||
return weakly_canonical(p, &err);
|
return weakly_canonical(p, &err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}//end namespace filesystem
|
||||||
}
|
}//end namespace std
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif //NANA_USING_NANA_FILESYSTEM
|
#endif //NANA_USING_NANA_FILESYSTEM
|
||||||
|
|
||||||
|
@ -622,6 +622,7 @@ namespace detail
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
|
++(root_runtime->x11msg.config);
|
||||||
if(msgwnd->dimension.width != static_cast<unsigned>(xevent.xconfigure.width) || msgwnd->dimension.height != static_cast<unsigned>(xevent.xconfigure.height))
|
if(msgwnd->dimension.width != static_cast<unsigned>(xevent.xconfigure.width) || msgwnd->dimension.height != static_cast<unsigned>(xevent.xconfigure.height))
|
||||||
{
|
{
|
||||||
auto & cf = xevent.xconfigure;
|
auto & cf = xevent.xconfigure;
|
||||||
@ -890,7 +891,12 @@ namespace detail
|
|||||||
case MapNotify:
|
case MapNotify:
|
||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
if(xevent.type == MapNotify)
|
if(xevent.type == MapNotify)
|
||||||
|
{
|
||||||
|
++(root_runtime->x11msg.map);
|
||||||
x11_apply_exposed_position(native_window);
|
x11_apply_exposed_position(native_window);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++(root_runtime->x11msg.unmap);
|
||||||
|
|
||||||
brock.event_expose(msgwnd, (xevent.type == MapNotify));
|
brock.event_expose(msgwnd, (xevent.type == MapNotify));
|
||||||
context.platform.motion_window = nullptr;
|
context.platform.motion_window = nullptr;
|
||||||
|
@ -77,6 +77,9 @@ namespace detail
|
|||||||
|
|
||||||
typedef BOOL (__stdcall* imm_set_composition_window_type)(HIMC, LPCOMPOSITIONFORM);
|
typedef BOOL (__stdcall* imm_set_composition_window_type)(HIMC, LPCOMPOSITIONFORM);
|
||||||
imm_set_composition_window_type imm_set_composition_window;
|
imm_set_composition_window_type imm_set_composition_window;
|
||||||
|
|
||||||
|
typedef LONG(__stdcall* imm_get_composition_string_type)(HIMC, DWORD, LPVOID, DWORD);
|
||||||
|
imm_get_composition_string_type imm_get_composition_string;
|
||||||
}
|
}
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
//Decoder of WPARAM and LPARAM
|
//Decoder of WPARAM and LPARAM
|
||||||
@ -170,15 +173,22 @@ namespace detail
|
|||||||
|
|
||||||
static LRESULT WINAPI Bedrock_WIN32_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
static LRESULT WINAPI Bedrock_WIN32_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
HINSTANCE windows_module_handle()
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
static int dummy;
|
||||||
|
VirtualQuery(&dummy, &mbi, sizeof(mbi));
|
||||||
|
return reinterpret_cast<HINSTANCE>(mbi.AllocationBase);
|
||||||
|
}
|
||||||
|
|
||||||
bedrock::bedrock()
|
bedrock::bedrock()
|
||||||
: pi_data_(new pi_data),
|
: pi_data_(new pi_data),
|
||||||
impl_(new private_impl)
|
impl_(new private_impl)
|
||||||
{
|
{
|
||||||
nana::detail::platform_spec::instance(); //to guaranty the platform_spec object is initialized before using.
|
nana::detail::platform_spec::instance(); //to guaranty the platform_spec object is initialized before using.
|
||||||
|
|
||||||
|
|
||||||
WNDCLASSEX wincl;
|
WNDCLASSEX wincl;
|
||||||
wincl.hInstance = ::GetModuleHandle(0);
|
wincl.hInstance = windows_module_handle();
|
||||||
wincl.lpszClassName = L"NanaWindowInternal";
|
wincl.lpszClassName = L"NanaWindowInternal";
|
||||||
wincl.lpfnWndProc = &Bedrock_WIN32_WindowProc;
|
wincl.lpfnWndProc = &Bedrock_WIN32_WindowProc;
|
||||||
wincl.style = CS_DBLCLKS | CS_OWNDC;
|
wincl.style = CS_DBLCLKS | CS_OWNDC;
|
||||||
@ -210,6 +220,9 @@ namespace detail
|
|||||||
|
|
||||||
restrict::imm_set_composition_window = reinterpret_cast<restrict::imm_set_composition_window_type>(
|
restrict::imm_set_composition_window = reinterpret_cast<restrict::imm_set_composition_window_type>(
|
||||||
::GetProcAddress(imm32, "ImmSetCompositionWindow"));
|
::GetProcAddress(imm32, "ImmSetCompositionWindow"));
|
||||||
|
|
||||||
|
restrict::imm_get_composition_string = reinterpret_cast<restrict::imm_get_composition_string_type>(
|
||||||
|
::GetProcAddress(imm32, "ImmGetCompositionStringW"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bedrock::~bedrock()
|
bedrock::~bedrock()
|
||||||
@ -223,6 +236,8 @@ namespace detail
|
|||||||
|
|
||||||
delete impl_;
|
delete impl_;
|
||||||
delete pi_data_;
|
delete pi_data_;
|
||||||
|
|
||||||
|
::UnregisterClass(L"NanaWindowInternal", windows_module_handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -639,6 +654,8 @@ namespace detail
|
|||||||
case WM_NCRBUTTONDOWN:
|
case WM_NCRBUTTONDOWN:
|
||||||
case WM_NCMBUTTONDOWN:
|
case WM_NCMBUTTONDOWN:
|
||||||
case WM_IME_STARTCOMPOSITION:
|
case WM_IME_STARTCOMPOSITION:
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
case WM_IME_CHAR:
|
||||||
case WM_DROPFILES:
|
case WM_DROPFILES:
|
||||||
case WM_MOUSELEAVE:
|
case WM_MOUSELEAVE:
|
||||||
case WM_MOUSEWHEEL: //The WM_MOUSELAST may not include the WM_MOUSEWHEEL/WM_MOUSEHWHEEL when the version of SDK is low.
|
case WM_MOUSEWHEEL: //The WM_MOUSELAST may not include the WM_MOUSEWHEEL/WM_MOUSEHWHEEL when the version of SDK is low.
|
||||||
@ -786,25 +803,67 @@ namespace detail
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_IME_STARTCOMPOSITION:
|
case WM_IME_STARTCOMPOSITION:
|
||||||
if (msgwnd->other.attribute.root->ime_enabled)
|
break;
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
if (lParam & (GCS_COMPSTR | GCS_RESULTSTR))
|
||||||
{
|
{
|
||||||
auto native_font = msgwnd->drawer.graphics.typeface().handle();
|
msgwnd = brock.focus();
|
||||||
LOGFONTW logfont;
|
if (msgwnd && msgwnd->flags.enabled)
|
||||||
::GetObjectW(reinterpret_cast<HFONT>(native_font), sizeof logfont, &logfont);
|
{
|
||||||
|
auto & wd_manager = brock.wd_manager();
|
||||||
|
auto composition_index = static_cast<DWORD>(lParam & (GCS_COMPSTR | GCS_RESULTSTR));
|
||||||
|
|
||||||
HIMC imc = restrict::imm_get_context(root_window);
|
arg_ime arg;
|
||||||
restrict::imm_set_composition_font(imc, &logfont);
|
arg.window_handle = msgwnd;
|
||||||
|
if (lParam & GCS_COMPSTR)
|
||||||
|
{
|
||||||
|
arg.ime_reason = arg_ime::reason::composition;
|
||||||
|
}
|
||||||
|
if (lParam & GCS_RESULTSTR)
|
||||||
|
{
|
||||||
|
arg.ime_reason = arg_ime::reason::result;
|
||||||
|
}
|
||||||
|
|
||||||
POINT pos;
|
HIMC imc = restrict::imm_get_context(root_window);
|
||||||
::GetCaretPos(&pos);
|
auto size = restrict::imm_get_composition_string(imc, composition_index, nullptr, 0);
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
wchar_t * buffer = new wchar_t[100 / sizeof(wchar_t) + 1];
|
||||||
|
size = restrict::imm_get_composition_string(imc, composition_index, buffer, size + sizeof(wchar_t));
|
||||||
|
buffer[size / sizeof(wchar_t)] = '\0';
|
||||||
|
arg.composition_string = std::move(buffer);
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
restrict::imm_release_context(root_window, imc);
|
||||||
|
|
||||||
COMPOSITIONFORM cf = { CFS_POINT };
|
if (wd_manager.available(msgwnd))
|
||||||
cf.ptCurrentPos = pos;
|
draw_invoker(&drawer::key_ime, msgwnd, arg, &context);
|
||||||
restrict::imm_set_composition_window(imc, &cf);
|
|
||||||
restrict::imm_release_context(root_window, imc);
|
wd_manager.do_lazy_refresh(msgwnd, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
def_window_proc = true;
|
def_window_proc = true;
|
||||||
break;
|
break;
|
||||||
|
case WM_IME_CHAR:
|
||||||
|
msgwnd = brock.focus();
|
||||||
|
if (msgwnd && msgwnd->flags.enabled)
|
||||||
|
{
|
||||||
|
auto & wd_manager = brock.wd_manager();
|
||||||
|
|
||||||
|
arg_keyboard arg;
|
||||||
|
arg.evt_code = event_code::key_char;
|
||||||
|
arg.window_handle = msgwnd;
|
||||||
|
arg.key = static_cast<wchar_t>(wParam);
|
||||||
|
brock.get_key_state(arg);
|
||||||
|
arg.ignore = false;
|
||||||
|
|
||||||
|
msgwnd->annex.events_ptr->key_char.emit(arg, msgwnd);
|
||||||
|
if ((false == arg.ignore) && wd_manager.available(msgwnd))
|
||||||
|
draw_invoker(&drawer::key_char, msgwnd, arg, &context);
|
||||||
|
|
||||||
|
wd_manager.do_lazy_refresh(msgwnd, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WM_GETMINMAXINFO:
|
case WM_GETMINMAXINFO:
|
||||||
{
|
{
|
||||||
bool take_over = false;
|
bool take_over = false;
|
||||||
|
@ -96,6 +96,11 @@ namespace nana
|
|||||||
overridden_ &= ~(1 << static_cast<int>(event_code::focus));
|
overridden_ &= ~(1 << static_cast<int>(event_code::focus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawer_trigger::key_ime(graph_reference, const arg_ime&)
|
||||||
|
{
|
||||||
|
overridden_ &= ~(1 << static_cast<int>(event_code::key_ime));
|
||||||
|
}
|
||||||
|
|
||||||
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
|
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
|
||||||
{
|
{
|
||||||
overridden_ &= ~(1 << static_cast<int>(event_code::key_press));
|
overridden_ &= ~(1 << static_cast<int>(event_code::key_press));
|
||||||
@ -318,6 +323,11 @@ namespace nana
|
|||||||
_m_emit(event_code::focus, arg, &drawer_trigger::focus, bForce__EmitInternal);
|
_m_emit(event_code::focus, arg, &drawer_trigger::focus, bForce__EmitInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawer::key_ime(const arg_ime& arg, const bool bForce__EmitInternal)
|
||||||
|
{
|
||||||
|
_m_emit(event_code::key_ime, arg, &drawer_trigger::key_ime, bForce__EmitInternal);
|
||||||
|
}
|
||||||
|
|
||||||
void drawer::key_press(const arg_keyboard& arg, const bool bForce__EmitInternal)
|
void drawer::key_press(const arg_keyboard& arg, const bool bForce__EmitInternal)
|
||||||
{
|
{
|
||||||
_m_emit(event_code::key_press, arg, &drawer_trigger::key_press, bForce__EmitInternal);
|
_m_emit(event_code::key_press, arg, &drawer_trigger::key_press, bForce__EmitInternal);
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#ifdef NANA_X11
|
||||||
|
# include <atomic>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nana{
|
namespace nana{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@ -75,6 +79,15 @@ namespace nana{
|
|||||||
root_misc(root_misc&&);
|
root_misc(root_misc&&);
|
||||||
root_misc(basic_window * wd, unsigned width, unsigned height);
|
root_misc(basic_window * wd, unsigned width, unsigned height);
|
||||||
~root_misc();
|
~root_misc();
|
||||||
|
|
||||||
|
#ifdef NANA_X11
|
||||||
|
struct x11msg_confirm
|
||||||
|
{
|
||||||
|
std::atomic<std::size_t> config{ 0 };
|
||||||
|
std::atomic<std::size_t> map{ 0 };
|
||||||
|
std::atomic<std::size_t> unmap{ 0 };
|
||||||
|
}x11msg;
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
root_misc(const root_misc&) = delete;
|
root_misc(const root_misc&) = delete;
|
||||||
root_misc& operator=(const root_misc&) = delete;
|
root_misc& operator=(const root_misc&) = delete;
|
||||||
|
@ -17,14 +17,15 @@
|
|||||||
#include <nana/gui/detail/window_manager.hpp>
|
#include <nana/gui/detail/window_manager.hpp>
|
||||||
|
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
#if defined(STD_THREAD_NOT_SUPPORTED)
|
# if defined(STD_THREAD_NOT_SUPPORTED)
|
||||||
#include <nana/std_mutex.hpp>
|
# include <nana/std_mutex.hpp>
|
||||||
#else
|
# else
|
||||||
#include <mutex>
|
# include <mutex>
|
||||||
#endif
|
# endif
|
||||||
#include <map>
|
# include <map>
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
#include <nana/system/platform.hpp>
|
# include <nana/system/platform.hpp>
|
||||||
|
# include "inner_fwd_implement.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../paint/image_accessor.hpp"
|
#include "../../paint/image_accessor.hpp"
|
||||||
@ -34,6 +35,10 @@ namespace nana{
|
|||||||
namespace detail{
|
namespace detail{
|
||||||
|
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
|
|
||||||
|
//This function is defined in bedrock_windows.cpp
|
||||||
|
HINSTANCE windows_module_handle();
|
||||||
|
|
||||||
class tray_manager
|
class tray_manager
|
||||||
{
|
{
|
||||||
struct window_extra_t
|
struct window_extra_t
|
||||||
@ -199,26 +204,87 @@ namespace nana{
|
|||||||
|
|
||||||
namespace x11_wait
|
namespace x11_wait
|
||||||
{
|
{
|
||||||
|
struct param
|
||||||
|
{
|
||||||
|
Window handle;
|
||||||
|
root_misc * misc;
|
||||||
|
std::size_t comp_value;
|
||||||
|
};
|
||||||
|
|
||||||
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == ConfigureNotify) && (evt->xconfigure.window == *reinterpret_cast<Window*>(arg));
|
auto p = reinterpret_cast<param*>(arg);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
if(p->misc->x11msg.config != p->comp_value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(disp && evt && (evt->type == ConfigureNotify))
|
||||||
|
{
|
||||||
|
if(evt->xconfigure.window == p->handle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool map(Display *disp, XEvent *evt, char *arg)
|
static Bool map(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == MapNotify) && (evt->xmap.window == *reinterpret_cast<Window*>(arg));
|
auto p = reinterpret_cast<param*>(arg);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
if(p->misc->x11msg.map != p->comp_value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(disp && evt && (evt->type == MapNotify))
|
||||||
|
{
|
||||||
|
if(evt->xmap.window == p->handle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool unmap(Display *disp, XEvent *evt, char *arg)
|
static Bool unmap(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == MapNotify) && (evt->xunmap.window == *reinterpret_cast<Window*>(arg));
|
auto p = reinterpret_cast<param*>(arg);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
if(p->misc->x11msg.unmap != p->comp_value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(disp && evt && (evt->type == UnmapNotify))
|
||||||
|
{
|
||||||
|
if(evt->xunmap.window == p->handle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*))
|
static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*), std::size_t comp_value)
|
||||||
{
|
{
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
x11_wait::param p;
|
||||||
|
p.handle = wd;
|
||||||
|
p.misc = misc;
|
||||||
|
|
||||||
|
if(pred_fn == &x11_wait::configure)
|
||||||
|
p.comp_value = misc->x11msg.config;
|
||||||
|
else if(pred_fn == &x11_wait::map)
|
||||||
|
p.comp_value = misc->x11msg.map;
|
||||||
|
else if(pred_fn == &x11_wait::unmap)
|
||||||
|
p.comp_value = misc->x11msg.unmap;
|
||||||
|
|
||||||
|
//Checks whether the msg is received.
|
||||||
|
if(p.comp_value != comp_value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p.comp_value = comp_value;
|
||||||
|
|
||||||
XEvent dummy;
|
XEvent dummy;
|
||||||
::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&wd));
|
::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&p));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -315,7 +381,7 @@ namespace nana{
|
|||||||
HWND native_wd = ::CreateWindowEx(style_ex, L"NanaWindowInternal", L"Nana Window",
|
HWND native_wd = ::CreateWindowEx(style_ex, L"NanaWindowInternal", L"Nana Window",
|
||||||
style,
|
style,
|
||||||
pt.x, pt.y, 100, 100,
|
pt.x, pt.y, 100, 100,
|
||||||
reinterpret_cast<HWND>(owner), 0, ::GetModuleHandle(0), 0);
|
reinterpret_cast<HWND>(owner), 0, windows_module_handle(), 0);
|
||||||
|
|
||||||
//A window may have a border, this should be adjusted the client area fit for the specified size.
|
//A window may have a border, this should be adjusted the client area fit for the specified size.
|
||||||
::RECT client;
|
::RECT client;
|
||||||
@ -504,7 +570,7 @@ namespace nana{
|
|||||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
|
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
|
||||||
r.x, r.y, r.width, r.height,
|
r.x, r.y, r.width, r.height,
|
||||||
reinterpret_cast<HWND>(parent), // The window is a child-window to desktop
|
reinterpret_cast<HWND>(parent), // The window is a child-window to desktop
|
||||||
0, ::GetModuleHandle(0), 0);
|
0, windows_module_handle(), 0);
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
nana::detail::platform_scope_guard psg;
|
nana::detail::platform_scope_guard psg;
|
||||||
|
|
||||||
@ -758,13 +824,17 @@ namespace nana{
|
|||||||
if(show == is_window_visible(wd))
|
if(show == is_window_visible(wd))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(wd);
|
||||||
|
|
||||||
if(show)
|
if(show)
|
||||||
{
|
{
|
||||||
|
std::size_t cmp_value = misc->x11msg.map;
|
||||||
|
|
||||||
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
||||||
|
|
||||||
//Wait for the mapping notify to update the local attribute of visibility so that
|
//Wait for the mapping notify to update the local attribute of visibility so that
|
||||||
//the followed window_visible() call can return the updated visibility value.
|
//the followed window_visible() call can return the updated visibility value.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map, cmp_value);
|
||||||
|
|
||||||
Window grab = restrict::spec.grab(0);
|
Window grab = restrict::spec.grab(0);
|
||||||
if(grab == reinterpret_cast<Window>(wd))
|
if(grab == reinterpret_cast<Window>(wd))
|
||||||
@ -772,10 +842,12 @@ namespace nana{
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::size_t cmp_value = misc->x11msg.unmap;
|
||||||
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
||||||
|
|
||||||
//Wait for the mapping notify to update the local attribute of visibility so that
|
//Wait for the mapping notify to update the local attribute of visibility so that
|
||||||
//the followed window_visible() call can return the updated visibility value.
|
//the followed window_visible() call can return the updated visibility value.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap, cmp_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static_cast<void>(active); //eliminate unused parameter compiler warning.
|
static_cast<void>(active); //eliminate unused parameter compiler warning.
|
||||||
@ -1019,11 +1091,15 @@ namespace nana{
|
|||||||
y += origin_y;
|
y += origin_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
std::size_t cmp_value = misc->x11msg.config;
|
||||||
|
|
||||||
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
||||||
|
|
||||||
//Wait for the configuration notify to update the local attribute of position so that
|
//Wait for the configuration notify to update the local attribute of position so that
|
||||||
//the followed window_position() call can return the updated position value.
|
//the followed window_position() call can return the updated position value.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
|
||||||
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1109,6 +1185,9 @@ namespace nana{
|
|||||||
y += origin_y;
|
y += origin_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
std::size_t cmp_value = misc->x11msg.config;
|
||||||
|
|
||||||
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
||||||
|
|
||||||
//Wait for the configuration notify to update the local attribute of position so that
|
//Wait for the configuration notify to update the local attribute of position so that
|
||||||
@ -1116,7 +1195,7 @@ namespace nana{
|
|||||||
|
|
||||||
//It seems that XMoveResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
//It seems that XMoveResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
||||||
//to make sure the local attribute is updated.
|
//to make sure the local attribute is updated.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -1283,11 +1362,15 @@ namespace nana{
|
|||||||
hints.min_height = hints.max_height = sz.height;
|
hints.min_height = hints.max_height = sz.height;
|
||||||
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
|
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
std::size_t cmp_value = misc->x11msg.config;
|
||||||
|
|
||||||
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
|
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
|
||||||
|
|
||||||
//It seems that XResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
//It seems that XResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
||||||
//to make sure the local attribute is updated.
|
//to make sure the local attribute is updated.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1516,21 +1516,31 @@ namespace nana
|
|||||||
|
|
||||||
path_type parent_path{ str };
|
path_type parent_path{ str };
|
||||||
str += (len + 1);
|
str += (len + 1);
|
||||||
|
|
||||||
while(*str)
|
// if only one file was selected, the ofn.lpstrFile
|
||||||
|
// is returning only that file, without any parent
|
||||||
|
if (!*str)
|
||||||
{
|
{
|
||||||
len = ::wcslen(str);
|
targets.emplace_back(parent_path);
|
||||||
targets.emplace_back(parent_path / path_type{str});
|
impl_->path = parent_path.parent_path().string();
|
||||||
str += (len + 1);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
len = ::wcslen(str);
|
||||||
|
targets.emplace_back(parent_path / path_type{str});
|
||||||
|
str += (len + 1);
|
||||||
|
}
|
||||||
|
impl_->path = parent_path.string();
|
||||||
}
|
}
|
||||||
impl_->path = parent_path.u8string();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wfile.resize(std::wcslen(wfile.data()));
|
wfile.resize(std::wcslen(wfile.data()));
|
||||||
|
|
||||||
targets.emplace_back(wfile);
|
targets.emplace_back(wfile);
|
||||||
impl_->path = targets.front().parent_path().u8string();
|
impl_->path = targets.front().parent_path().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/**
|
||||||
* A Message Box Class
|
* A Message Box Class
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||||
@ -7,10 +7,15 @@
|
|||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/gui/msgbox.hpp
|
* @file nana/gui/msgbox.hpp
|
||||||
* @Contributors
|
* @Contributors
|
||||||
* James Bremner
|
* James Bremner
|
||||||
|
* Ariel Vina-Rodriguez
|
||||||
*/
|
*/
|
||||||
|
#define NOMINMAX
|
||||||
|
#include <algorithm> // max
|
||||||
|
#include <functional>
|
||||||
|
#include <cstdlib> //include std::abs
|
||||||
|
|
||||||
#include <nana/gui/compact.hpp>
|
#include <nana/gui/compact.hpp>
|
||||||
#include <nana/gui/msgbox.hpp>
|
#include <nana/gui/msgbox.hpp>
|
||||||
@ -27,8 +32,7 @@
|
|||||||
#include <nana/datetime.hpp>
|
#include <nana/datetime.hpp>
|
||||||
#include <nana/internationalization.hpp>
|
#include <nana/internationalization.hpp>
|
||||||
#include <nana/gui/filebox.hpp>
|
#include <nana/gui/filebox.hpp>
|
||||||
#include <functional>
|
|
||||||
#include <cstdlib> //include std::abs
|
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
@ -494,21 +498,29 @@ namespace nana
|
|||||||
//end class msgbox
|
//end class msgbox
|
||||||
|
|
||||||
|
|
||||||
//class inputbox
|
//class inputbox todo: add schema
|
||||||
|
|
||||||
class inputbox_window
|
class inputbox_window
|
||||||
: public ::nana::form
|
: public ::nana::form
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inputbox_window(window owner, paint::image (&imgs)[4], ::nana::rectangle (&valid_areas)[4], const ::std::string & desc, const ::std::string& title, std::size_t contents, unsigned fixed_pixels, const std::vector<unsigned>& each_height)
|
inputbox_window(window owner,
|
||||||
|
paint::image (&imgs)[4], ///< 4 ref to images
|
||||||
|
::nana::rectangle (&valid_areas)[4],
|
||||||
|
const ::std::string & description,
|
||||||
|
const ::std::string& title,
|
||||||
|
std::size_t contents,
|
||||||
|
unsigned fixed_pixels,
|
||||||
|
const std::vector<unsigned>& each_height)
|
||||||
|
|
||||||
: form(owner, API::make_center(owner, 500, 300), appear::decorate<>())
|
: form(owner, API::make_center(owner, 500, 300), appear::decorate<>())
|
||||||
{
|
{
|
||||||
throw_not_utf8(desc);
|
throw_not_utf8(description);
|
||||||
throw_not_utf8(title);
|
throw_not_utf8(title);
|
||||||
|
|
||||||
desc_.create(*this);
|
description_.create(*this);
|
||||||
desc_.format(true).caption(desc);
|
description_.format(true).caption(description);
|
||||||
auto desc_extent = desc_.measure(470);
|
auto description_size = description_.measure(470);
|
||||||
|
|
||||||
btn_ok_.create(*this);
|
btn_ok_.create(*this);
|
||||||
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK"));
|
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK"));
|
||||||
@ -527,32 +539,26 @@ namespace nana
|
|||||||
close();
|
close();
|
||||||
});
|
});
|
||||||
|
|
||||||
unsigned height = 20 + desc_extent.height + 10 + 38;
|
unsigned height = 20 + description_size.height + 10 + 38;
|
||||||
|
|
||||||
std::stringstream ss_content;
|
std::stringstream ss_content;
|
||||||
ss_content << "<margin=10 vert <desc weight=" << desc_extent.height << "><vert margin=[10]";
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < contents; ++i)
|
for (std::size_t i = 0; i < contents; ++i)
|
||||||
{
|
{
|
||||||
unsigned px = 27;
|
unsigned px = std::max(27u, each_height[i]);
|
||||||
if (each_height[i] > 27)
|
|
||||||
px = each_height[i];
|
|
||||||
|
|
||||||
ss_content << "<weight=" << (px + 3) << " margin=[3] input_" << i << ">";
|
ss_content << "<height=" << (px + 3) << " margin=[3] input_" << i << ">";
|
||||||
|
|
||||||
height += px + 1;
|
height += px + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss_content << "><margin=[15] weight=38<><buttons arrange=80 gap=10 weight=170>>>";
|
if (description_size.width < 200)
|
||||||
|
description_size.width = 200;
|
||||||
if (desc_extent.width < 200)
|
|
||||||
desc_extent.width = 200;
|
|
||||||
|
|
||||||
//Make sure the complete display of input extent
|
//Make sure the complete display of input extent
|
||||||
if (desc_extent.width < fixed_pixels)
|
if (description_size.width < fixed_pixels)
|
||||||
desc_extent.width = fixed_pixels;
|
description_size.width = fixed_pixels;
|
||||||
|
|
||||||
desc_extent.width += 20;
|
description_size.width += 20; // 2x margin 10
|
||||||
|
|
||||||
::nana::size img_sz[4];
|
::nana::size img_sz[4];
|
||||||
|
|
||||||
@ -566,8 +572,9 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
sz = imgs[2].size();
|
sz = imgs[2].size();
|
||||||
sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height)));
|
const double scale_factor = double(height) / double(sz.height);
|
||||||
desc_extent.width += sz.width;
|
sz.width = static_cast<size::value_type>(double(sz.width) * scale_factor);
|
||||||
|
description_size.width += sz.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imgs[3]) //Right
|
if (imgs[3]) //Right
|
||||||
@ -581,7 +588,7 @@ namespace nana
|
|||||||
else
|
else
|
||||||
sz = imgs[3].size();
|
sz = imgs[3].size();
|
||||||
sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height)));
|
sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height)));
|
||||||
desc_extent.width += sz.width;
|
description_size.width += sz.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imgs[0]) //Top
|
if (imgs[0]) //Top
|
||||||
@ -594,7 +601,8 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
sz = imgs[0].size();
|
sz = imgs[0].size();
|
||||||
sz.height = static_cast<size::value_type>(double(sz.height) * (double(desc_extent.width) / double(sz.width)));
|
const double scale_factor = double(description_size.width) / double(sz.width);
|
||||||
|
sz.height = static_cast<size::value_type>(double(sz.height) * scale_factor );
|
||||||
height += sz.height;
|
height += sz.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,16 +616,28 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
sz = imgs[1].size();
|
sz = imgs[1].size();
|
||||||
sz.height = static_cast<size::value_type>(double(sz.height) * (double(desc_extent.width) / double(sz.width)));
|
const double scale_factor = double(description_size.width) / double(sz.width);
|
||||||
|
sz.height = static_cast<size::value_type>(double(sz.height) * scale_factor);
|
||||||
height += sz.height;
|
height += sz.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "vert<img_top weight="<<img_sz[0].height<<"><<img_left weight="<<img_sz[2].width<<">"<<ss_content.str()<<"<img_right weight="<<img_sz[3].width<<">><img_bottom weight="<<img_sz[1].height<<">";
|
ss << "vert< img_top height="<<img_sz[0].height<<">"
|
||||||
|
<<" << img_left width=" <<img_sz[2].width <<">"
|
||||||
|
<<" <margin=10 vert <description height=" << description_size.height << ">" // added height: 2x10
|
||||||
|
<<" <vert margin=[10]" // added height: 10
|
||||||
|
<< ss_content.str()
|
||||||
|
<<" >"
|
||||||
|
<<" <height=38 margin=[15] <><width=170 buttons arrange=80 gap=10>"
|
||||||
|
<<" >>" // added height: 38
|
||||||
|
<<" < img_right width=" <<img_sz[3].width
|
||||||
|
<<" >>< img_bottom height="<<img_sz[1].height<<">";
|
||||||
|
|
||||||
|
// added height: 10 x3 = 30 + 38
|
||||||
|
|
||||||
auto& place = this->get_place();
|
auto& place = this->get_place();
|
||||||
place.div(ss.str().c_str());
|
place.div(ss.str().c_str());
|
||||||
place["desc"] << desc_;
|
place["description"] << description_;
|
||||||
place["buttons"] << btn_ok_ << btn_cancel_;
|
place["buttons"] << btn_ok_ << btn_cancel_;
|
||||||
|
|
||||||
const char * img_fields[4] = {"img_top", "img_bottom", "img_left", "img_right"};
|
const char * img_fields[4] = {"img_top", "img_bottom", "img_left", "img_right"};
|
||||||
@ -635,7 +655,7 @@ namespace nana
|
|||||||
place.field_display(img_fields[i], imgs[i]);
|
place.field_display(img_fields[i], imgs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
move(API::make_center(this->owner(), desc_extent.width, height));
|
move(API::make_center(this->owner(), description_size.width, height));
|
||||||
caption(title);
|
caption(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +679,7 @@ namespace nana
|
|||||||
return valid_input_;
|
return valid_input_;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
::nana::label desc_;
|
::nana::label description_;
|
||||||
::nana::button btn_ok_;
|
::nana::button btn_ok_;
|
||||||
::nana::button btn_cancel_;
|
::nana::button btn_cancel_;
|
||||||
bool valid_input_{ false };
|
bool valid_input_{ false };
|
||||||
@ -1247,7 +1267,7 @@ namespace nana
|
|||||||
auto files = impl->fbox.show();
|
auto files = impl->fbox.show();
|
||||||
if(!files.empty())
|
if(!files.empty())
|
||||||
{
|
{
|
||||||
impl->value = files.front().u8string();
|
impl->value = files.front().string();
|
||||||
impl->path_edit.caption(impl->value);
|
impl->path_edit.caption(impl->value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -146,7 +146,8 @@ namespace nana
|
|||||||
|
|
||||||
//draw caption
|
//draw caption
|
||||||
auto text = to_wstring(API::window_caption(window_handle_));
|
auto text = to_wstring(API::window_caption(window_handle_));
|
||||||
text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, paint::text_renderer::mode::truncate_with_ellipsis);
|
if((graph.size().width > 20) && (graph.size().width - 20 > 10))
|
||||||
|
text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, paint::text_renderer::mode::truncate_with_ellipsis);
|
||||||
|
|
||||||
//draw x button
|
//draw x button
|
||||||
auto r = _m_button_area();
|
auto r = _m_button_area();
|
||||||
|
@ -111,13 +111,13 @@ namespace nana
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if defined(NANA_WINDOWS)
|
#if defined(NANA_WINDOWS)
|
||||||
timer_core(timer* sender, timer_identifier tmid, basic_event<arg_elapse>& evt_elapse):
|
timer_core(timer* sender, timer_identifier tmid, std::shared_ptr<basic_event<arg_elapse>> evt_elapse):
|
||||||
sender_(sender),
|
sender_(sender),
|
||||||
timer_(tmid),
|
timer_(tmid),
|
||||||
evt_elapse_(evt_elapse)
|
evt_elapse_(evt_elapse)
|
||||||
{}
|
{}
|
||||||
#else
|
#else
|
||||||
timer_core(timer* sender, basic_event<arg_elapse>& evt_elapse):
|
timer_core(timer* sender, std::shared_ptr<basic_event<arg_elapse>> evt_elapse):
|
||||||
sender_(sender),
|
sender_(sender),
|
||||||
timer_(this),
|
timer_(this),
|
||||||
evt_elapse_(evt_elapse)
|
evt_elapse_(evt_elapse)
|
||||||
@ -142,12 +142,15 @@ namespace nana
|
|||||||
{
|
{
|
||||||
arg_elapse arg;
|
arg_elapse arg;
|
||||||
arg.sender = sender_;
|
arg.sender = sender_;
|
||||||
evt_elapse_.emit(arg, nullptr);
|
|
||||||
|
//retain the object to avoid it to be deleted during calling of emit
|
||||||
|
auto retain = evt_elapse_;
|
||||||
|
retain->emit(arg, nullptr);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
timer * const sender_;
|
timer * const sender_;
|
||||||
const timer_identifier timer_;
|
const timer_identifier timer_;
|
||||||
nana::basic_event<arg_elapse> & evt_elapse_;
|
std::shared_ptr<nana::basic_event<arg_elapse>> evt_elapse_;
|
||||||
}; //end class timer_core
|
}; //end class timer_core
|
||||||
|
|
||||||
|
|
||||||
@ -175,8 +178,9 @@ namespace nana
|
|||||||
};
|
};
|
||||||
|
|
||||||
//class timer
|
//class timer
|
||||||
timer::timer()
|
timer::timer():
|
||||||
: impl_(new implement)
|
elapse_(std::make_shared<nana::basic_event<arg_elapse>>()),
|
||||||
|
impl_(new implement)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +199,7 @@ namespace nana
|
|||||||
void timer::reset()
|
void timer::reset()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
elapse_.clear();
|
elapse_->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer::start()
|
void timer::start()
|
||||||
|
@ -773,6 +773,13 @@ namespace nana
|
|||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void trigger::key_ime(graph_reference, const arg_ime& arg)
|
||||||
|
{
|
||||||
|
drawer_->editor()->respond_ime(arg);
|
||||||
|
if (drawer_->editor()->try_refresh())
|
||||||
|
API::dev::lazy_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
drawer_->editor()->respond_char(arg);
|
drawer_->editor()->respond_char(arg);
|
||||||
|
@ -39,7 +39,7 @@ namespace nana
|
|||||||
place & form_base::get_place()
|
place & form_base::get_place()
|
||||||
{
|
{
|
||||||
if (this->empty())
|
if (this->empty())
|
||||||
throw std::runtime_error("form::get_plac: the form has destroyed.");
|
throw std::runtime_error("form::get_place(): the form has been destroyed.");
|
||||||
|
|
||||||
if (!place_)
|
if (!place_)
|
||||||
place_.reset(new place{ *this });
|
place_.reset(new place{ *this });
|
||||||
@ -47,9 +47,9 @@ namespace nana
|
|||||||
return *place_;
|
return *place_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void form_base::div(const char* div_text)
|
void form_base::div(std::string div_text)
|
||||||
{
|
{
|
||||||
get_place().div(div_text);
|
get_place().div(std::move(div_text));
|
||||||
}
|
}
|
||||||
|
|
||||||
place::field_reference form_base::operator[](const char* field_name)
|
place::field_reference form_base::operator[](const char* field_name)
|
||||||
|
@ -167,7 +167,7 @@ namespace nana
|
|||||||
|
|
||||||
column(column&& other):
|
column(column&& other):
|
||||||
caption(std::move(other.caption)),
|
caption(std::move(other.caption)),
|
||||||
width_px(other.width_px),
|
width_px(other.width_px),
|
||||||
range_width_px(other.range_width_px),
|
range_width_px(other.range_width_px),
|
||||||
visible_state(other.visible_state),
|
visible_state(other.visible_state),
|
||||||
index(other.index),
|
index(other.index),
|
||||||
@ -184,7 +184,13 @@ namespace nana
|
|||||||
index(pos),
|
index(pos),
|
||||||
ess_(ess)
|
ess_(ess)
|
||||||
{
|
{
|
||||||
|
if (px == 0)
|
||||||
|
{
|
||||||
|
fit_width_to_header();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fit_width_to_header();
|
||||||
private:
|
private:
|
||||||
/// The definition is provided after essence
|
/// The definition is provided after essence
|
||||||
void _m_refresh() noexcept;
|
void _m_refresh() noexcept;
|
||||||
@ -2308,7 +2314,8 @@ namespace nana
|
|||||||
size_type count_of_exposed(bool with_rest) const
|
size_type count_of_exposed(bool with_rest) const
|
||||||
{
|
{
|
||||||
auto lister_s = this->content_view->view_area().height;
|
auto lister_s = this->content_view->view_area().height;
|
||||||
return (lister_s / item_height()) + (with_rest && (lister_s % item_height()) ? 1 : 0);
|
return (lister_s / item_height()) + (with_rest &&
|
||||||
|
listbox_ptr->scroll_operation()->visible(true) && (lister_s % item_height()) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(bool ignore_auto_draw = false) noexcept
|
void update(bool ignore_auto_draw = false) noexcept
|
||||||
@ -2394,7 +2401,9 @@ namespace nana
|
|||||||
nana::rectangle r;
|
nana::rectangle r;
|
||||||
if (rect_lister(r))
|
if (rect_lister(r))
|
||||||
{
|
{
|
||||||
auto top = new_where.second * item_h + header_visible_px();
|
//potential displacement due to partially visible first visible item
|
||||||
|
auto disp = origin.y - first_display().item * item_h;
|
||||||
|
auto top = new_where.second * item_h + header_visible_px() - disp;
|
||||||
if (checkarea(item_xpos(r), static_cast<int>(top)).is_hit(pos))
|
if (checkarea(item_xpos(r), static_cast<int>(top)).is_hit(pos))
|
||||||
new_where.first = parts::checker;
|
new_where.first = parts::checker;
|
||||||
}
|
}
|
||||||
@ -2881,10 +2890,26 @@ namespace nana
|
|||||||
return max_px;
|
return max_px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void es_header::column::fit_width_to_header()
|
||||||
|
{
|
||||||
|
std::unique_ptr<paint::graphics> graph_helper;
|
||||||
|
auto graph = ess_->graph;
|
||||||
|
if (graph->empty())
|
||||||
|
{
|
||||||
|
//Creates a helper if widget graph is empty(when its size is 0).
|
||||||
|
graph_helper.reset(new paint::graphics{ nana::size{ 5, 5 } });
|
||||||
|
graph_helper->typeface(ess_->graph->typeface());
|
||||||
|
graph = graph_helper.get();
|
||||||
|
}
|
||||||
|
width_px = ess_->scheme_ptr->text_margin * 2; //margin at left/right end.
|
||||||
|
|
||||||
|
width_px += graph->text_extent_size(caption).width;
|
||||||
|
}
|
||||||
|
|
||||||
//es_header::column member functions
|
//es_header::column member functions
|
||||||
void es_header::column::_m_refresh() noexcept
|
void es_header::column::_m_refresh() noexcept
|
||||||
{
|
{
|
||||||
ess_->update(true);
|
ess_->update(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type es_header::column::position(bool disp_order) const noexcept
|
size_type es_header::column::position(bool disp_order) const noexcept
|
||||||
@ -3316,16 +3341,27 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init ir end to grab a header
|
||||||
void grab(const nana::point& pos, bool is_grab)
|
void grab(const nana::point& pos, bool is_grab)
|
||||||
{
|
{
|
||||||
if(is_grab)
|
if(is_grab) // init grabbing the header
|
||||||
{
|
{
|
||||||
grabs_.start_pos = pos.x;
|
grabs_.start_pos = pos.x;
|
||||||
if(grabs_.splitter != npos) // resize header item, not move it
|
if(grabs_.splitter == npos) // No splitter, no resize header, just moving
|
||||||
grabs_.item_width = essence_->header.at(grabs_.splitter).width_px;
|
return;
|
||||||
|
|
||||||
|
// splitter grabbed - resize the header: take initial width
|
||||||
|
grabs_.item_width = essence_->header.at(grabs_.splitter).width_px;
|
||||||
}
|
}
|
||||||
else if((grab_terminal_.index != npos) && (grab_terminal_.index != essence_->pointer_where.second))
|
else // end to grab the header
|
||||||
essence_->header.move(essence_->pointer_where.second, grab_terminal_.index, grab_terminal_.place_front);
|
if (grabs_.splitter != npos) // some Splitter grab, just resizing, no need to move
|
||||||
|
return;
|
||||||
|
else if( (grab_terminal_.index != npos)
|
||||||
|
&& (grab_terminal_.index != essence_->pointer_where.second) )
|
||||||
|
// move header to terminal position
|
||||||
|
essence_->header.move(essence_->pointer_where.second, // from
|
||||||
|
grab_terminal_.index, // to
|
||||||
|
grab_terminal_.place_front);
|
||||||
}
|
}
|
||||||
|
|
||||||
//grab_move
|
//grab_move
|
||||||
@ -4273,7 +4309,10 @@ namespace nana
|
|||||||
auto const good_list_r = essence_->rect_lister(list_r);
|
auto const good_list_r = essence_->rect_lister(list_r);
|
||||||
|
|
||||||
auto & ptr_where = essence_->pointer_where;
|
auto & ptr_where = essence_->pointer_where;
|
||||||
if((ptr_where.first == parts::header) && (ptr_where.second != npos || (drawer_header_->splitter() != npos)))
|
|
||||||
|
if( (ptr_where.first == parts::header) // click on header
|
||||||
|
&& ( ptr_where.second != npos // in ..
|
||||||
|
|| (drawer_header_->splitter() != npos))) // or splitter
|
||||||
{
|
{
|
||||||
essence_->ptr_state = item_state::pressed;
|
essence_->ptr_state = item_state::pressed;
|
||||||
if(good_head_r)
|
if(good_head_r)
|
||||||
@ -4282,7 +4321,8 @@ namespace nana
|
|||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(ptr_where.first == parts::list || ptr_where.first == parts::checker)
|
else if( ptr_where.first == parts::list // click on list
|
||||||
|
|| ptr_where.first == parts::checker) // on a checker
|
||||||
{
|
{
|
||||||
index_pair item_pos = lister.advance(essence_->first_display(), static_cast<int>(ptr_where.second));
|
index_pair item_pos = lister.advance(essence_->first_display(), static_cast<int>(ptr_where.second));
|
||||||
|
|
||||||
@ -4455,13 +4495,16 @@ namespace nana
|
|||||||
bool need_refresh = false;
|
bool need_refresh = false;
|
||||||
|
|
||||||
//Don't sort the column when the mouse is due to released for stopping resizing column.
|
//Don't sort the column when the mouse is due to released for stopping resizing column.
|
||||||
if ((drawer_header_->splitter() == npos) && essence_->header.attrib().sortable && essence_->pointer_where.first == parts::header && prev_state == item_state::pressed)
|
if ( (drawer_header_->splitter() == npos) // no header splitter was selected
|
||||||
|
&& essence_->header.attrib().sortable
|
||||||
|
&& essence_->pointer_where.first == parts::header
|
||||||
|
&& prev_state == item_state::pressed)
|
||||||
{
|
{
|
||||||
//Try to sort the column
|
//Try to sort the column
|
||||||
if(essence_->pointer_where.second < essence_->header.cont().size())
|
if(essence_->pointer_where.second < essence_->header.cont().size())
|
||||||
need_refresh = essence_->lister.sort_column(essence_->pointer_where.second, nullptr);
|
need_refresh = essence_->lister.sort_column(essence_->pointer_where.second, nullptr);
|
||||||
}
|
}
|
||||||
else if (item_state::grabbed == prev_state)
|
else if (item_state::grabbed == prev_state) // selected splitter and grabbed
|
||||||
{
|
{
|
||||||
nana::point pos = arg.pos;
|
nana::point pos = arg.pos;
|
||||||
essence_->widget_to_header(pos);
|
essence_->widget_to_header(pos);
|
||||||
@ -4762,7 +4805,7 @@ namespace nana
|
|||||||
|
|
||||||
bool item_proxy::empty() const noexcept
|
bool item_proxy::empty() const noexcept
|
||||||
{
|
{
|
||||||
return !ess_;
|
return !(ess_ && ess_->lister.good(pos_));
|
||||||
}
|
}
|
||||||
|
|
||||||
item_proxy & item_proxy::check(bool ck, bool scroll_view)
|
item_proxy & item_proxy::check(bool ck, bool scroll_view)
|
||||||
@ -5959,6 +6002,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
internal_scope_guard lock;
|
internal_scope_guard lock;
|
||||||
_m_ess().lister.sort_column(col, &reverse);
|
_m_ess().lister.sort_column(col, &reverse);
|
||||||
|
_m_ess().update();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto listbox::sort_col() const -> size_type
|
auto listbox::sort_col() const -> size_type
|
||||||
@ -6073,7 +6117,15 @@ namespace nana
|
|||||||
|
|
||||||
auto listbox::last_visible() const -> index_pair
|
auto listbox::last_visible() const -> index_pair
|
||||||
{
|
{
|
||||||
return _m_ess().lister.advance(_m_ess().first_display(), static_cast<int>(_m_ess().count_of_exposed(true)));
|
if(!const_cast<listbox*>(this)->scroll_operation()->visible(true))
|
||||||
|
{
|
||||||
|
auto last_cat = size_categ()-1;
|
||||||
|
index_pair ip(last_cat, at(last_cat).size()-1);
|
||||||
|
if(last_cat == 0 && ip.item == npos) // if the listbox is empty
|
||||||
|
ip.cat = npos; // return empty index_pair
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
return _m_ess().lister.advance(_m_ess().first_display(), static_cast<int>(_m_ess().count_of_exposed(true)-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto listbox::visibles() const -> index_pairs
|
auto listbox::visibles() const -> index_pairs
|
||||||
|
@ -922,7 +922,25 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else if (checks::option == item.style)
|
else if (checks::option == item.style)
|
||||||
{
|
{
|
||||||
get_drawer_trigger().mbuilder().checked(active, true);
|
if(active > 0)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
if(menu->items[--active]->flags.splitter)
|
||||||
|
{
|
||||||
|
++active;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(active > 0);
|
||||||
|
}
|
||||||
|
while(active < menu->items.size())
|
||||||
|
{
|
||||||
|
menu_item_type &el = *(menu->items[active++]);
|
||||||
|
if(el.flags.splitter)
|
||||||
|
break;
|
||||||
|
if(checks::option == el.style)
|
||||||
|
el.flags.checked = false;
|
||||||
|
}
|
||||||
|
item.flags.checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_m_close_all(); //means deleting this;
|
this->_m_close_all(); //means deleting this;
|
||||||
|
@ -96,11 +96,11 @@ namespace nana
|
|||||||
{
|
{
|
||||||
if (widget_)
|
if (widget_)
|
||||||
{
|
{
|
||||||
auto value_px = (widget_->size().width - border_px * 2);
|
unsigned value_px = (widget_->size().width - border_px * 2);
|
||||||
|
|
||||||
//avoid overflow
|
//avoid overflow
|
||||||
if (unknown_ || (value_ < max_))
|
if (unknown_ || (value_ < max_))
|
||||||
value_px = static_cast<unsigned>(value_px * (double(value_) / double(max_)));
|
value_px = unsigned(double(value_px) * (double(value_) / double(max_)));
|
||||||
|
|
||||||
if (value_px != value_px_)
|
if (value_px != value_px_)
|
||||||
{
|
{
|
||||||
|
@ -1163,6 +1163,43 @@ namespace nana {
|
|||||||
impl_->capacities.acceptive = acceptive;
|
impl_->capacities.acceptive = acceptive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool text_editor::respond_ime(const arg_ime& arg)
|
||||||
|
{
|
||||||
|
if (!API::window_enabled(window_))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (select_.a != select_.b)
|
||||||
|
{
|
||||||
|
points_.caret = _m_erase_select(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < composition_size_; ++i)
|
||||||
|
{
|
||||||
|
backspace(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.ime_reason == arg_ime::reason::composition)
|
||||||
|
{
|
||||||
|
composition_size_ = arg.composition_string.length();
|
||||||
|
points_.caret = _m_put(std::move(arg.composition_string), false);
|
||||||
|
|
||||||
|
_m_reset_content_size(true);
|
||||||
|
textbase().text_changed();
|
||||||
|
|
||||||
|
if (this->_m_adjust_view())
|
||||||
|
impl_->cview->sync(false);
|
||||||
|
|
||||||
|
reset_caret();
|
||||||
|
impl_->try_refresh = sync_graph::refresh;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
composition_size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool text_editor::respond_char(const arg_keyboard& arg) //key is a character of ASCII code
|
bool text_editor::respond_char(const arg_keyboard& arg) //key is a character of ASCII code
|
||||||
{
|
{
|
||||||
if (!API::window_enabled(window_))
|
if (!API::window_enabled(window_))
|
||||||
|
@ -621,6 +621,13 @@ namespace nana
|
|||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawer::key_ime(graph_reference, const arg_ime& arg)
|
||||||
|
{
|
||||||
|
impl_->editor()->respond_ime(arg);
|
||||||
|
if (impl_->editor()->try_refresh())
|
||||||
|
API::dev::lazy_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
if (impl_->editor()->respond_key(arg))
|
if (impl_->editor()->respond_key(arg))
|
||||||
|
@ -1229,7 +1229,8 @@ namespace nana
|
|||||||
|
|
||||||
void trigger::erase(std::size_t pos)
|
void trigger::erase(std::size_t pos)
|
||||||
{
|
{
|
||||||
layouter_->erase(pos);
|
if (layouter_->erase(pos))
|
||||||
|
API::refresh_window(layouter_->widget_handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::tab_color(std::size_t i, bool is_bgcolor, const ::nana::color& clr)
|
void trigger::tab_color(std::size_t i, bool is_bgcolor, const ::nana::color& clr)
|
||||||
|
@ -152,6 +152,13 @@ namespace drawerbase {
|
|||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawer::key_ime(graph_reference, const arg_ime& arg)
|
||||||
|
{
|
||||||
|
editor_->respond_ime(arg);
|
||||||
|
if (editor_->try_refresh())
|
||||||
|
API::dev::lazy_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
editor_->respond_key(arg);
|
editor_->respond_key(arg);
|
||||||
|
@ -104,6 +104,7 @@ namespace nana
|
|||||||
delete ptr;
|
delete ptr;
|
||||||
|
|
||||||
cont_.clear();
|
cont_.clear();
|
||||||
|
right_ = npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -683,6 +684,7 @@ namespace nana
|
|||||||
if(m && (m->textout != show))
|
if(m && (m->textout != show))
|
||||||
{
|
{
|
||||||
m->textout = show;
|
m->textout = show;
|
||||||
|
m->pixels = 0; //force width calculation
|
||||||
API::refresh_window(this->handle());
|
API::refresh_window(this->handle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A Treebox Implementation
|
* A Treebox Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2020 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -70,7 +70,7 @@ namespace nana
|
|||||||
|
|
||||||
const node_type* find_track_child_node(const node_type* node, const node_type * end, const char* pattern, std::size_t len, bool &finish)
|
const node_type* find_track_child_node(const node_type* node, const node_type * end, const char* pattern, std::size_t len, bool &finish)
|
||||||
{
|
{
|
||||||
if(node->value.second.expanded)
|
if(node->value.second.expanded && !node->value.second.hidden)
|
||||||
{
|
{
|
||||||
node = node->child;
|
node = node->child;
|
||||||
while(node)
|
while(node)
|
||||||
@ -79,7 +79,7 @@ namespace nana
|
|||||||
|
|
||||||
if(node == end) break;
|
if(node == end) break;
|
||||||
|
|
||||||
if(node->value.second.expanded)
|
if(node->value.second.expanded && !node->value.second.hidden)
|
||||||
{
|
{
|
||||||
auto t = find_track_child_node(node, end, pattern, len, finish);
|
auto t = find_track_child_node(node, end, pattern, len, finish);
|
||||||
if(t || finish)
|
if(t || finish)
|
||||||
@ -184,10 +184,11 @@ namespace nana
|
|||||||
class trigger::item_locator
|
class trigger::item_locator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using enum_order = tree_cont_type::enum_order;
|
||||||
using node_type = tree_cont_type::node_type;
|
using node_type = tree_cont_type::node_type;
|
||||||
|
|
||||||
item_locator(implementation * impl, int item_pos, int x, int y);
|
item_locator(implementation * impl, int item_pos, int x, int y);
|
||||||
int operator()(node_type &node, int affect);
|
enum_order operator()(node_type &node, int affect);
|
||||||
node_type * node() const;
|
node_type * node() const;
|
||||||
component what() const;
|
component what() const;
|
||||||
bool item_body() const;
|
bool item_body() const;
|
||||||
@ -212,6 +213,14 @@ namespace nana
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pred_allow_node
|
||||||
|
{
|
||||||
|
bool operator()(const trigger::tree_cont_type::node_type& node)
|
||||||
|
{
|
||||||
|
return !node.value.second.hidden;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//struct implementation
|
//struct implementation
|
||||||
//@brief: some data for treebox trigger
|
//@brief: some data for treebox trigger
|
||||||
class trigger::implementation
|
class trigger::implementation
|
||||||
@ -220,6 +229,7 @@ namespace nana
|
|||||||
: public compset_interface
|
: public compset_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using enum_order = tree_cont_type::enum_order;
|
||||||
using node_type = tree_cont_type::node_type;
|
using node_type = tree_cont_type::node_type;
|
||||||
|
|
||||||
item_rendering_director(implementation * impl, const nana::point& pos):
|
item_rendering_director(implementation * impl, const nana::point& pos):
|
||||||
@ -232,9 +242,11 @@ namespace nana
|
|||||||
//0 = Sibling, the last is a sibling of node
|
//0 = Sibling, the last is a sibling of node
|
||||||
//1 = Owner, the last is the owner of node
|
//1 = Owner, the last is the owner of node
|
||||||
//>=2 = Children, the last is a child of a node that before this node.
|
//>=2 = Children, the last is a child of a node that before this node.
|
||||||
int operator()(const node_type& node, int affect)
|
enum_order operator()(const node_type& node, int affect)
|
||||||
{
|
{
|
||||||
iterated_node_ = &node;
|
iterated_node_ = &node;
|
||||||
|
|
||||||
|
// Increase/decrease indent
|
||||||
switch (affect)
|
switch (affect)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@ -245,6 +257,9 @@ namespace nana
|
|||||||
pos_.x -= impl_->data.scheme_ptr->indent_displacement * (affect - 1);
|
pos_.x -= impl_->data.scheme_ptr->indent_displacement * (affect - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iterated_node_->value.second.hidden) // Skip drawing if the node is hidden
|
||||||
|
return enum_order::proceed;
|
||||||
|
|
||||||
auto & comp_placer = impl_->data.comp_placer;
|
auto & comp_placer = impl_->data.comp_placer;
|
||||||
|
|
||||||
impl_->assign_node_attr(node_attr_, iterated_node_);
|
impl_->assign_node_attr(node_attr_, iterated_node_);
|
||||||
@ -263,9 +278,9 @@ namespace nana
|
|||||||
pos_.y += node_r_.height;
|
pos_.y += node_r_.height;
|
||||||
|
|
||||||
if (pos_.y > static_cast<int>(impl_->data.graph->height()))
|
if (pos_.y > static_cast<int>(impl_->data.graph->height()))
|
||||||
return 0;
|
return enum_order::stop;
|
||||||
|
|
||||||
return (node.child && node.value.second.expanded ? 1 : 2);
|
return ((node.child && node.value.second.expanded) ? enum_order::proceed_with_children : enum_order::proceed);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
//Overrides compset_interface
|
//Overrides compset_interface
|
||||||
@ -280,7 +295,12 @@ namespace nana
|
|||||||
if (impl_->data.comp_placer->locate(comp, node_attr_, &attr.area))
|
if (impl_->data.comp_placer->locate(comp, node_attr_, &attr.area))
|
||||||
{
|
{
|
||||||
attr.mouse_pointed = node_attr_.mouse_pointed;
|
attr.mouse_pointed = node_attr_.mouse_pointed;
|
||||||
attr.area.x += pos_.x;
|
|
||||||
|
if(comp == component_t::bground && impl_->use_entire_line)
|
||||||
|
attr.area.width = impl_->visible_w_pixels();
|
||||||
|
else
|
||||||
|
attr.area.x += pos_.x;
|
||||||
|
|
||||||
attr.area.y += pos_.y;
|
attr.area.y += pos_.y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -347,6 +367,9 @@ namespace nana
|
|||||||
std::size_t scroll_timestamp;
|
std::size_t scroll_timestamp;
|
||||||
nana::timer timer;
|
nana::timer timer;
|
||||||
}adjust;
|
}adjust;
|
||||||
|
|
||||||
|
bool use_entire_line;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
implementation()
|
implementation()
|
||||||
{
|
{
|
||||||
@ -371,11 +394,24 @@ namespace nana
|
|||||||
adjust.offset_x_adjust = 0;
|
adjust.offset_x_adjust = 0;
|
||||||
adjust.node = nullptr;
|
adjust.node = nullptr;
|
||||||
adjust.scroll_timestamp = 0;
|
adjust.scroll_timestamp = 0;
|
||||||
|
|
||||||
|
use_entire_line = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign_node_attr(node_attribute& ndattr, const node_type* node) const
|
void assign_node_attr(node_attribute& ndattr, const node_type* node) const
|
||||||
{
|
{
|
||||||
ndattr.has_children = (nullptr != node->child);
|
// Check if there is a visible child that node has.
|
||||||
|
// This is an improvement based on a new feature that allows treebox node to be hidden(PR#500)
|
||||||
|
ndattr.has_children = false;
|
||||||
|
for (auto p = node->child; p; p = p->next)
|
||||||
|
{
|
||||||
|
if (!p->value.second.hidden)
|
||||||
|
{
|
||||||
|
ndattr.has_children = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ndattr.expended = node->value.second.expanded;
|
ndattr.expended = node->value.second.expanded;
|
||||||
ndattr.text = node->value.second.text;
|
ndattr.text = node->value.second.text;
|
||||||
ndattr.checked = node->value.second.checked;
|
ndattr.checked = node->value.second.checked;
|
||||||
@ -552,7 +588,7 @@ namespace nana
|
|||||||
|
|
||||||
if (p->child)
|
if (p->child)
|
||||||
{
|
{
|
||||||
if (p->value.second.expanded || !ignore_folded_children)
|
if ((p->value.second.expanded || !ignore_folded_children) && !p->value.second.hidden)
|
||||||
{
|
{
|
||||||
p = p->child;
|
p = p->child;
|
||||||
continue;
|
continue;
|
||||||
@ -603,8 +639,8 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pos = tree.distance_if(node, pred_allow_child{});
|
auto pos = tree.distance_if(node, pred_allow_child{}, pred_allow_node{});
|
||||||
auto last_pos = tree.distance_if(last(true), pred_allow_child{});
|
auto last_pos = tree.distance_if(last(true), pred_allow_child{}, pred_allow_node{});
|
||||||
|
|
||||||
auto const capacity = screen_capacity(true);
|
auto const capacity = screen_capacity(true);
|
||||||
|
|
||||||
@ -612,7 +648,7 @@ namespace nana
|
|||||||
//position of the requested item.
|
//position of the requested item.
|
||||||
if (!use_bearing)
|
if (!use_bearing)
|
||||||
{
|
{
|
||||||
auto first_pos = tree.distance_if(shape.first, pred_allow_child{});
|
auto first_pos = tree.distance_if(shape.first, pred_allow_child{}, pred_allow_node{});
|
||||||
|
|
||||||
if (pos < first_pos)
|
if (pos < first_pos)
|
||||||
bearing = align_v::top;
|
bearing = align_v::top;
|
||||||
@ -655,7 +691,7 @@ namespace nana
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto prv_first = shape.first;
|
auto prv_first = shape.first;
|
||||||
shape.first = attr.tree_cont.advance_if(nullptr, pos, drawerbase::treebox::pred_allow_child{});
|
shape.first = attr.tree_cont.advance_if(nullptr, pos, drawerbase::treebox::pred_allow_child{}, pred_allow_node{});
|
||||||
|
|
||||||
//Update the position of scroll
|
//Update the position of scroll
|
||||||
show_scroll();
|
show_scroll();
|
||||||
@ -669,8 +705,8 @@ namespace nana
|
|||||||
|
|
||||||
auto & tree = attr.tree_cont;
|
auto & tree = attr.tree_cont;
|
||||||
|
|
||||||
auto const first_pos = tree.distance_if(shape.first, pred_allow_child{});
|
auto const first_pos = tree.distance_if(shape.first, pred_allow_child{}, pred_allow_node{});
|
||||||
auto const node_pos = tree.distance_if(node, pred_allow_child{});
|
auto const node_pos = tree.distance_if(node, pred_allow_child{}, pred_allow_node{});
|
||||||
auto const max_allow = max_allowed();
|
auto const max_allow = max_allowed();
|
||||||
switch(reason)
|
switch(reason)
|
||||||
{
|
{
|
||||||
@ -680,12 +716,12 @@ namespace nana
|
|||||||
//adjust if the number of its children are over the max number allowed
|
//adjust if the number of its children are over the max number allowed
|
||||||
if (shape.first != node)
|
if (shape.first != node)
|
||||||
{
|
{
|
||||||
auto child_size = tree.child_size_if(*node, pred_allow_child());
|
auto child_size = tree.child_size_if(*node, pred_allow_child(), pred_allow_node{});
|
||||||
if (child_size < max_allow)
|
if (child_size < max_allow)
|
||||||
{
|
{
|
||||||
auto const size = node_pos - first_pos + child_size + 1;
|
auto const size = node_pos - first_pos + child_size + 1;
|
||||||
if (size > max_allow)
|
if (size > max_allow)
|
||||||
shape.first = tree.advance_if(shape.first, size - max_allow, pred_allow_child{});
|
shape.first = tree.advance_if(shape.first, size - max_allow, pred_allow_child{}, pred_allow_node{});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
shape.first = node;
|
shape.first = node;
|
||||||
@ -698,7 +734,7 @@ namespace nana
|
|||||||
if (visual_size > max_allow)
|
if (visual_size > max_allow)
|
||||||
{
|
{
|
||||||
if (first_pos + max_allow > visual_size)
|
if (first_pos + max_allow > visual_size)
|
||||||
shape.first = tree.advance_if(nullptr, visual_size - max_allow, pred_allow_child{});
|
shape.first = tree.advance_if(nullptr, visual_size - max_allow, pred_allow_child{}, pred_allow_node{});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
shape.first = nullptr;
|
shape.first = nullptr;
|
||||||
@ -739,7 +775,7 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else if (node_pos - first_pos > max_allow)
|
else if (node_pos - first_pos > max_allow)
|
||||||
{
|
{
|
||||||
shape.first = tree.advance_if(nullptr, node_pos - max_allow + 1, pred_allow_child{});
|
shape.first = tree.advance_if(nullptr, node_pos - max_allow + 1, pred_allow_child{}, pred_allow_node{});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -814,6 +850,27 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool set_hidden(node_type* node, bool value)
|
||||||
|
{
|
||||||
|
if (node && node->value.second.hidden != value)
|
||||||
|
{
|
||||||
|
if (value == false)
|
||||||
|
{
|
||||||
|
//if hiding a parent of the selected node or the selected node itself - select nothing.
|
||||||
|
if (node->is_ancestor_of(node_state.selected) || node_state.selected == node)
|
||||||
|
set_selected(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
node->value.second.hidden = value;
|
||||||
|
data.stop_drawing = true;
|
||||||
|
item_proxy iprx(data.trigger_ptr, node);
|
||||||
|
data.widget_ptr->events().hidden.emit(::nana::arg_treebox{ *data.widget_ptr, iprx, value }, data.widget_ptr->handle());
|
||||||
|
data.stop_drawing = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void show_scroll()
|
void show_scroll()
|
||||||
{
|
{
|
||||||
if(nullptr == data.graph) return;
|
if(nullptr == data.graph) return;
|
||||||
@ -841,7 +898,7 @@ namespace nana
|
|||||||
adjust.scroll_timestamp = nana::system::timestamp();
|
adjust.scroll_timestamp = nana::system::timestamp();
|
||||||
adjust.timer.start();
|
adjust.timer.start();
|
||||||
|
|
||||||
shape.first = attr.tree_cont.advance_if(nullptr, shape.scroll->value(), pred_allow_child{});
|
shape.first = attr.tree_cont.advance_if(nullptr, shape.scroll->value(), pred_allow_child{}, pred_allow_node{});
|
||||||
draw(false, false, true);
|
draw(false, false, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -850,13 +907,13 @@ namespace nana
|
|||||||
scroll.range(max_allow);
|
scroll.range(max_allow);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pos = attr.tree_cont.distance_if(shape.first, pred_allow_child{});
|
auto pos = attr.tree_cont.distance_if(shape.first, pred_allow_child{}, pred_allow_node{});
|
||||||
scroll.value(pos);
|
scroll.value(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t visual_item_size() const
|
std::size_t visual_item_size() const
|
||||||
{
|
{
|
||||||
return attr.tree_cont.child_size_if(std::string(), pred_allow_child{});
|
return attr.tree_cont.child_size_if(std::string(), pred_allow_child{}, pred_allow_node{});
|
||||||
}
|
}
|
||||||
|
|
||||||
int visible_w_pixels() const
|
int visible_w_pixels() const
|
||||||
@ -1153,6 +1210,20 @@ namespace nana
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool item_proxy::hidden() const
|
||||||
|
{
|
||||||
|
return node_->value.second.hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_proxy& item_proxy::hide(bool h)
|
||||||
|
{
|
||||||
|
auto* impl = trigger_->impl();
|
||||||
|
if (impl->set_hidden(node_, h))
|
||||||
|
impl->draw(true);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& item_proxy::icon() const
|
const std::string& item_proxy::icon() const
|
||||||
{
|
{
|
||||||
return node_->value.second.img_idstr;
|
return node_->value.second.img_idstr;
|
||||||
@ -1274,7 +1345,10 @@ namespace nana
|
|||||||
|
|
||||||
item_proxy item_proxy::operator++(int)
|
item_proxy item_proxy::operator++(int)
|
||||||
{
|
{
|
||||||
return sibling();
|
item_proxy ip(*this);
|
||||||
|
if(trigger_ && node_)
|
||||||
|
node_ = node_->next;
|
||||||
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
item_proxy& item_proxy::operator*()
|
item_proxy& item_proxy::operator*()
|
||||||
@ -1395,7 +1469,7 @@ namespace nana
|
|||||||
switch(comp)
|
switch(comp)
|
||||||
{
|
{
|
||||||
case component_t::expander:
|
case component_t::expander:
|
||||||
if(attr.has_children)
|
if (attr.has_children)
|
||||||
{
|
{
|
||||||
r->width = scheme_.item_offset;
|
r->width = scheme_.item_offset;
|
||||||
return true;
|
return true;
|
||||||
@ -1581,7 +1655,7 @@ namespace nana
|
|||||||
node_(nullptr)
|
node_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int trigger::item_locator::operator()(node_type &node, int affect)
|
auto trigger::item_locator::operator()(node_type &node, int affect) -> enum_order
|
||||||
{
|
{
|
||||||
switch(affect)
|
switch(affect)
|
||||||
{
|
{
|
||||||
@ -1592,6 +1666,9 @@ namespace nana
|
|||||||
item_pos_.x -= static_cast<int>(impl_->data.scheme_ptr->indent_displacement) * (affect - 1);
|
item_pos_.x -= static_cast<int>(impl_->data.scheme_ptr->indent_displacement) * (affect - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.value.second.hidden) // Do not account for hidden nodes
|
||||||
|
return enum_order::proceed;
|
||||||
|
|
||||||
impl_->assign_node_attr(node_attr_, &node);
|
impl_->assign_node_attr(node_attr_, &node);
|
||||||
nana::rectangle node_r;
|
nana::rectangle node_r;
|
||||||
auto & comp_placer = impl_->data.comp_placer;
|
auto & comp_placer = impl_->data.comp_placer;
|
||||||
@ -1608,8 +1685,8 @@ namespace nana
|
|||||||
nana::rectangle r = node_r;
|
nana::rectangle r = node_r;
|
||||||
if (!comp_placer->locate(static_cast<component>(comp), node_attr_, &r))
|
if (!comp_placer->locate(static_cast<component>(comp), node_attr_, &r))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (r.is_hit(logic_pos))
|
if((comp == static_cast<int>(component::bground) && impl_->use_entire_line) || r.is_hit(logic_pos))
|
||||||
{
|
{
|
||||||
node_ = &node;
|
node_ = &node;
|
||||||
what_ = static_cast<component>(comp);
|
what_ = static_cast<component>(comp);
|
||||||
@ -1623,15 +1700,12 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; //Stop iterating
|
return enum_order::stop; //Stop iterating
|
||||||
}
|
}
|
||||||
|
|
||||||
item_pos_.y += node_r.height;
|
item_pos_.y += node_r.height;
|
||||||
|
|
||||||
if(node.value.second.expanded && node.child)
|
return ((node.child && node.value.second.expanded) ? enum_order::proceed_with_children : enum_order::proceed);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger::item_locator::node_type * trigger::item_locator::node() const
|
trigger::item_locator::node_type * trigger::item_locator::node() const
|
||||||
@ -1662,11 +1736,11 @@ namespace nana
|
|||||||
//class trigger
|
//class trigger
|
||||||
//struct treebox_node_type
|
//struct treebox_node_type
|
||||||
trigger::treebox_node_type::treebox_node_type()
|
trigger::treebox_node_type::treebox_node_type()
|
||||||
:expanded(false), checked(checkstate::unchecked)
|
:expanded(false), checked(checkstate::unchecked), hidden(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
trigger::treebox_node_type::treebox_node_type(std::string text)
|
trigger::treebox_node_type::treebox_node_type(std::string text)
|
||||||
:text(std::move(text)), expanded(false), checked(checkstate::unchecked)
|
:text(std::move(text)), expanded(false), checked(checkstate::unchecked), hidden(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
trigger::treebox_node_type& trigger::treebox_node_type::operator=(const treebox_node_type& rhs)
|
trigger::treebox_node_type& trigger::treebox_node_type::operator=(const treebox_node_type& rhs)
|
||||||
@ -1952,13 +2026,14 @@ namespace nana
|
|||||||
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
|
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
|
||||||
|
|
||||||
auto const node = nl.node();
|
auto const node = nl.node();
|
||||||
if (!node)
|
if (!node || !node->child)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (nl.what())
|
switch (nl.what())
|
||||||
{
|
{
|
||||||
case component::icon:
|
case component::icon:
|
||||||
case component::text:
|
case component::text:
|
||||||
|
case component::bground:
|
||||||
impl_->set_expanded(node, !node->value.second.expanded);
|
impl_->set_expanded(node, !node->value.second.expanded);
|
||||||
impl_->draw(true, true, false);
|
impl_->draw(true, true, false);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
@ -2384,6 +2459,12 @@ namespace nana
|
|||||||
return item_proxy(const_cast<drawer_trigger_t*>(dw), dw->impl()->node_state.pointed);
|
return item_proxy(const_cast<drawer_trigger_t*>(dw), dw->impl()->node_state.pointed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void treebox::use_entire_line(bool enable)
|
||||||
|
{
|
||||||
|
auto dw = &get_drawer_trigger();
|
||||||
|
dw->impl()->use_entire_line = enable;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<scroll_operation_interface> treebox::_m_scroll_operation()
|
std::shared_ptr<scroll_operation_interface> treebox::_m_scroll_operation()
|
||||||
{
|
{
|
||||||
internal_scope_guard lock;
|
internal_scope_guard lock;
|
||||||
|
@ -1473,7 +1473,7 @@ namespace paint
|
|||||||
{
|
{
|
||||||
if (vertical)
|
if (vertical)
|
||||||
{
|
{
|
||||||
int x1 = good_rct.x, x2 = good_rct.right();
|
int x1 = good_rct.x, x2 = good_rct.right() - 1;
|
||||||
auto y = good_rct.y;
|
auto y = good_rct.y;
|
||||||
for (; y < endpos; ++y)
|
for (; y < endpos; ++y)
|
||||||
{
|
{
|
||||||
@ -1489,7 +1489,7 @@ namespace paint
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int y1 = good_rct.y, y2 = good_rct.bottom();
|
int y1 = good_rct.y, y2 = good_rct.bottom() - 1;
|
||||||
auto x = good_rct.x;
|
auto x = good_rct.x;
|
||||||
for (; x < endpos; ++x)
|
for (; x < endpos; ++x)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/**
|
||||||
* Paint Image Implementation
|
* Paint Image Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||||
@ -7,9 +7,8 @@
|
|||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/paint/image.cpp
|
* @file nana/paint/image.cpp
|
||||||
* @contributors:
|
* @contributors nabijaczleweli(pr#106)
|
||||||
* nabijaczleweli(pr#106)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nana/push_ignore_diagnostic>
|
#include <nana/push_ignore_diagnostic>
|
||||||
|
@ -238,10 +238,18 @@ namespace nana{ namespace paint
|
|||||||
auto d = rawptr;
|
auto d = rawptr;
|
||||||
const unsigned char* s;
|
const unsigned char* s;
|
||||||
|
|
||||||
|
int src_line_bytes;
|
||||||
|
|
||||||
if (is_negative)
|
if (is_negative)
|
||||||
|
{
|
||||||
s = rawbits;
|
s = rawbits;
|
||||||
|
src_line_bytes = -static_cast<int>(bytes_per_line);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
s = rawbits + bytes_per_line * (height - 1);
|
s = rawbits + bytes_per_line * (height - 1);
|
||||||
|
src_line_bytes = static_cast<int>(bytes_per_line);
|
||||||
|
}
|
||||||
|
|
||||||
for(std::size_t i = 0; i < height; ++i)
|
for(std::size_t i = 0; i < height; ++i)
|
||||||
{
|
{
|
||||||
@ -256,7 +264,7 @@ namespace nana{ namespace paint
|
|||||||
s_p += 3;
|
s_p += 3;
|
||||||
}
|
}
|
||||||
d += pixel_size.width;
|
d += pixel_size.width;
|
||||||
s -= bytes_per_line;
|
s -= src_line_bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(16 == bits_per_pixel)
|
else if(16 == bits_per_pixel)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user