Merge branch 'develop'
This commit is contained in:
commit
b72490f8b6
76
.travis.yml
76
.travis.yml
@ -43,8 +43,12 @@ matrix:
|
||||
- llvm-toolchain-precise
|
||||
|
||||
before_install:
|
||||
# donwload nana-demo first
|
||||
# we are in: 'user'/nana/
|
||||
- cd ..
|
||||
# we are in: 'user'/
|
||||
- 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"
|
||||
- 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
|
||||
@ -53,76 +57,24 @@ install:
|
||||
- /tmp/tools/cmake --prefix="$HOME" --exclude-subdir
|
||||
|
||||
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/
|
||||
- "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
|
||||
# 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:
|
||||
- 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
|
||||
- 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)
|
||||
- ls
|
||||
# we were still in: 'user'/demo-build/
|
||||
- cd ../nana-test/bin
|
||||
- ls
|
||||
- ./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
|
||||
- ls -lh
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
# cmake 3.12 have more better modern c++ support
|
||||
|
||||
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
|
||||
project(nana VERSION 1.7.1
|
||||
project(nana VERSION 1.7.3
|
||||
DESCRIPTION "C++ GUI library"
|
||||
HOMEPAGE_URL http://nanapro.org
|
||||
LANGUAGES CXX )
|
||||
@ -32,6 +32,7 @@ project(nana VERSION 1.7.1
|
||||
add_library(nana)
|
||||
add_library(nana::nana ALIAS nana)
|
||||
target_compile_features(nana PUBLIC cxx_std_17)
|
||||
# set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# need after cxx_std_14 or cxx_std_17 ??
|
||||
target_compile_features(nana
|
||||
@ -116,7 +117,7 @@ option(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ "replaced boost.thread wi
|
||||
|
||||
######## 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)
|
||||
target_compile_definitions(nana PUBLIC NANA_AUTOMATIC_GUI_TESTING)
|
||||
# todo: enable_testing() # ??
|
||||
|
@ -1,12 +1,12 @@
|
||||
# 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)
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
@ -38,13 +38,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AN
|
||||
endif()
|
||||
|
||||
|
||||
if (APPLE AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # APPLE Clang
|
||||
target_compile_options(nana PUBLIC -stdlib=libstdc++)
|
||||
endif ()
|
||||
|
||||
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
target_compile_options(nana PRIVATE -fmax-errors=3)
|
||||
endif()
|
||||
|
||||
|
@ -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.
|
||||
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
|
||||
# of the project linking to the nana lib here generated
|
||||
target_sources(nana PRIVATE ${HEADERS})
|
||||
target_include_directories(nana PRIVATE ${NANA_INCLUDE_DIR})
|
||||
message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib")
|
||||
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.
|
||||
install(TARGETS nana
|
||||
ARCHIVE DESTINATION lib
|
||||
@ -15,8 +18,13 @@ if(NANA_CMAKE_INSTALL)
|
||||
RUNTIME DESTINATION bin)
|
||||
install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include) # in ${CMAKE_INSTALL_PREFIX}/include/nana
|
||||
message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
|
||||
target_include_directories(nana PUBLIC $<BUILD_INTERFACE:${NANA_INCLUDE_DIR}>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
else()
|
||||
# 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_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR})
|
||||
endif()
|
||||
|
@ -1,30 +1,36 @@
|
||||
# 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
|
||||
# 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
|
||||
# to "implement" it (ab)using Boost (almost compatible)
|
||||
# The library may be not available or working correctly in the std library you use.
|
||||
# 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
|
||||
# or you can choose to use the (partial, but functional) implementation provided by nana.
|
||||
# If you include the file <nana/filesystem/filesystem.hpp> or <nana/filesystem/filesystem_ext.hpp>
|
||||
# the selected option will be set by nana into std::filesystem
|
||||
# By default Nana will try to use the STD. If STD is not available and NANA_CMAKE_FIND_BOOST_FILESYSTEM
|
||||
# is set to ON nana will try to use boost if available. Nana own implementation will be use if none of
|
||||
# the previus were selected or available.
|
||||
# By ncluding the file <nana/filesystem/filesystem.hpp> or <nana/filesystem/filesystem_ext.hpp>
|
||||
# the selected option is inlined 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.
|
||||
# You can change that default if you change one of the following
|
||||
# (please don't define more than one of the _XX_FORCE options):
|
||||
option(NANA_CMAKE_NANA_FILESYSTEM_FORCE "Force nana filesystem over ISO and boost?" OFF)
|
||||
option(NANA_CMAKE_STD_FILESYSTEM_FORCE "Use of STD filesystem?(a compilation error will ocurre if not available)" OFF)
|
||||
option(NANA_CMAKE_BOOST_FILESYSTEM_FORCE "Force use of Boost filesystem if available (over STD)?" OFF)
|
||||
option(NANA_CMAKE_FIND_BOOST_FILESYSTEM "Search: Is Boost filesystem available?" OFF)
|
||||
set (TEST_FS_LIB OFF)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
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)
|
||||
# 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,
|
||||
@ -43,14 +49,131 @@ elseif(NANA_CMAKE_BOOST_FILESYSTEM_FORCE)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
else()
|
||||
# todo test for std (for now just force nana or boost if there no std)
|
||||
|
||||
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()
|
||||
|
||||
# todo if not test for boost
|
||||
# if not add nana filesystem
|
||||
endif()
|
||||
|
||||
|
||||
# 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(NANA_STATIC_STDLIB "Link nana statically to C++ standard library" ON)
|
||||
|
||||
if(BUILD_SHARED_LIBS) # todo test
|
||||
|
||||
@ -35,12 +36,11 @@ if(BUILD_SHARED_LIBS) # todo test
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW??
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_options(nana PUBLIC -lgcc -lstdc++)
|
||||
else()
|
||||
target_link_libraries(nana PUBLIC -static-libgcc -static-libstdc++)
|
||||
endif(BUILD_SHARED_LIBS)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Compiler>
|
||||
<Add option="-std=c++11" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=c++11" />
|
||||
<Add option="-g" />
|
||||
<Add directory="../../include" />
|
||||
<Add directory="../../extrlib/mingw" />
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define NANA_ANY_HPP
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "c++defines.hpp"
|
||||
|
||||
@ -74,7 +75,7 @@ namespace nana
|
||||
any(Value && value,
|
||||
typename std::enable_if<!std::is_same<any&, 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>
|
||||
any& operator=(Value&& other)
|
||||
{
|
||||
any(other).swap(*this);
|
||||
any(std::forward<Value>(other)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Predefined Symbols for C++
|
||||
* 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.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -48,14 +48,15 @@
|
||||
|
||||
#ifndef NANA_CXX_DEFINES_INCLUDED
|
||||
#define NANA_CXX_DEFINES_INCLUDED
|
||||
#define STD_FILESYSTEM_NOT_SUPPORTED
|
||||
// #define STD_FILESYSTEM_NOT_SUPPORTED
|
||||
|
||||
//C++ language
|
||||
#if defined(_MSC_VER)
|
||||
# if (_MSC_VER < 1900)
|
||||
# if (_MSC_VER < 1900) // VC2013
|
||||
# //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,
|
||||
# //So Nana use nana.filesystem implement instead for VC2013
|
||||
# define STD_FILESYSTEM_NOT_SUPPORTED
|
||||
#
|
||||
# //Nana defines some macros for lack of support of keywords
|
||||
# define _ALLOW_KEYWORD_MACROS
|
||||
@ -64,8 +65,6 @@
|
||||
# define noexcept //no support of noexcept until Visual C++ 2015
|
||||
|
||||
# define constexpr //no support of constexpr until Visual C++ 2015 ? const ??
|
||||
# else
|
||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||
# endif
|
||||
#elif defined(__GNUC__) && not defined(__clang__)
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
|
||||
@ -89,7 +88,7 @@
|
||||
#define NANA_MINGW
|
||||
#endif // MINGW
|
||||
|
||||
#elif defined(APPLE) //Mac OS X
|
||||
#elif defined(__APPLE__) || defined(APPLE) //Mac OS X
|
||||
//Symbols for MACOS
|
||||
#define NANA_MACOS
|
||||
#define NANA_POSIX
|
||||
@ -125,16 +124,16 @@
|
||||
|
||||
#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__)
|
||||
//<codecvt> is a known issue on libstdc++, it works on libc++
|
||||
#define STD_CODECVT_NOT_SUPPORTED
|
||||
#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__)
|
||||
//<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
|
||||
|
||||
//It's a known issue of libstdc++ on MinGW
|
||||
@ -155,6 +154,8 @@
|
||||
|
||||
# if ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 3 ) ) )
|
||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||
# else
|
||||
# define STD_FILESYSTEM_NOT_SUPPORTED
|
||||
# endif
|
||||
|
||||
#if (__GNUC__ == 4)
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @file nana/filesystem/filesystem.hpp
|
||||
* @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
|
||||
*/
|
||||
|
||||
@ -34,32 +34,26 @@
|
||||
//Filesystem Selection
|
||||
#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_STD_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
|
||||
#define NANA_USING_NANA_FILESYSTEM 1
|
||||
|
||||
#elif (defined(BOOST_FILESYSTEM_AVAILABLE) && ( defined(BOOST_FILESYSTEM_FORCE) || ( defined(STD_FILESYSTEM_NOT_SUPPORTED) && !defined(STD_FILESYSTEM_FORCE) ) ))
|
||||
|
||||
#undef NANA_USING_BOOST_FILESYSTEM
|
||||
#define NANA_USING_BOOST_FILESYSTEM 1
|
||||
# include <chrono>
|
||||
# include <boost/filesystem.hpp>
|
||||
|
||||
// add boost::filesystem into std::experimental::filesystem
|
||||
// inline boost::filesystem into std::filesystem
|
||||
namespace std {
|
||||
namespace experimental {
|
||||
namespace filesystem {
|
||||
inline namespace boost_filesystem {
|
||||
using namespace boost::filesystem;
|
||||
using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
|
||||
|
||||
@ -75,16 +69,16 @@ namespace std {
|
||||
socket = boost::filesystem::file_type::socket_file,
|
||||
unknown = boost::filesystem::file_type::type_unknown,
|
||||
};
|
||||
// Boost dont include generic_u8string
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/path.hpp
|
||||
//
|
||||
// Boost versions: 1.67.0, 1.66.0, ... 1.56.0 enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/operations.hpp
|
||||
// but travis come with an oooold version of boost
|
||||
// 1.55.0 NOT enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_54_0/boost/filesystem/operations.hpp
|
||||
#if BOOST_VERSION < 105600
|
||||
namespace boost
|
||||
// Boost dont include generic_u8string
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/path.hpp
|
||||
//
|
||||
// Boost versions: 1.67.0, 1.66.0, ... 1.56.0 enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_66_0/boost/filesystem/operations.hpp
|
||||
// but travis come with an oooold version of boost
|
||||
// 1.55.0 NOT enable directory_iterator C++11 range-base for
|
||||
// http://www.boost.org/doc/libs/1_54_0/boost/filesystem/operations.hpp
|
||||
#if BOOST_VERSION < 105600
|
||||
namespace boost { // todo ??
|
||||
// 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
|
||||
@ -99,19 +93,10 @@ namespace std {
|
||||
{
|
||||
return directory_iterator();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // filesystem
|
||||
} // experimental
|
||||
|
||||
namespace filesystem
|
||||
{
|
||||
using namespace experimental::filesystem;
|
||||
}
|
||||
|
||||
#ifndef __cpp_lib_experimental_filesystem
|
||||
# define __cpp_lib_experimental_filesystem 201406
|
||||
#endif
|
||||
#endif
|
||||
} // boost_filesystem
|
||||
} // filesystem
|
||||
} // std
|
||||
|
||||
#else
|
||||
@ -133,7 +118,7 @@ namespace std {
|
||||
# undef NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
||||
# define NANA_USING_STD_EXPERIMENTAL_FILESYSTEM
|
||||
# endif
|
||||
#endif
|
||||
#endif // BOOST_FILESYSTEM and NANA_FILESYSTEM
|
||||
|
||||
#if NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
@ -148,25 +133,21 @@ namespace std {
|
||||
|
||||
#include <nana/deploy.hpp>
|
||||
|
||||
namespace nana { namespace experimental { namespace filesystem
|
||||
{
|
||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
||||
inline namespace v1
|
||||
{
|
||||
#endif
|
||||
namespace nana {
|
||||
namespace filesystem {
|
||||
|
||||
enum class file_type
|
||||
{
|
||||
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
|
||||
regular = 1,
|
||||
directory = 2 ,
|
||||
symlink =3, ///< Symbolic link file
|
||||
block =4, ///< Block special file
|
||||
character= 5 , ///< Character special file
|
||||
fifo = 6 , ///< FIFO or pipe file
|
||||
socket =7,
|
||||
unknown= 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other
|
||||
directory = 2,
|
||||
symlink = 3, ///< Symbolic link file
|
||||
block = 4, ///< Block special file
|
||||
character = 5, ///< Character special file
|
||||
fifo = 6, ///< FIFO or pipe file
|
||||
socket = 7,
|
||||
unknown = 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other
|
||||
};
|
||||
|
||||
enum class perms
|
||||
@ -204,11 +185,14 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
|
||||
// observers
|
||||
file_type type() const;
|
||||
|
||||
perms permissions() const;
|
||||
|
||||
// modifiers
|
||||
void type(file_type ft);
|
||||
|
||||
void permissions(perms prms);
|
||||
|
||||
private:
|
||||
file_type value_;
|
||||
perms perms_;
|
||||
@ -236,105 +220,142 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
path() = default;
|
||||
|
||||
template<typename Source>
|
||||
path(const Source& source)
|
||||
path(const Source &source)
|
||||
{
|
||||
_m_assign(source);
|
||||
}
|
||||
|
||||
// modifiers
|
||||
void clear() noexcept;
|
||||
path& make_preferred();
|
||||
path& remove_filename();
|
||||
|
||||
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 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
|
||||
bool empty() const noexcept;
|
||||
bool has_root_name() const { return !root_name().empty(); }
|
||||
bool has_root_directory() const { return !root_directory().empty(); }
|
||||
bool has_root_path() const { return !root_path().empty(); }
|
||||
bool has_relative_path() const { return !relative_path().empty(); }
|
||||
bool has_parent_path() const { return !parent_path().empty(); }; // temp;;
|
||||
bool has_filename() const { return !filename().empty(); }; // temp;
|
||||
|
||||
bool has_root_name() const
|
||||
{ return !root_name().empty(); }
|
||||
|
||||
bool has_root_directory() const
|
||||
{ return !root_directory().empty(); }
|
||||
|
||||
bool has_root_path() const
|
||||
{ return !root_path().empty(); }
|
||||
|
||||
bool has_relative_path() const
|
||||
{ return !relative_path().empty(); }
|
||||
|
||||
bool has_parent_path() const
|
||||
{ return !parent_path().empty(); }; // temp;;
|
||||
bool has_filename() const
|
||||
{ return !filename().empty(); }; // temp;
|
||||
//bool has_stem() const;
|
||||
bool has_extension() const { return !extension().empty(); }; // temp
|
||||
bool has_extension() const
|
||||
{ return !extension().empty(); }; // temp
|
||||
bool is_absolute() const;
|
||||
|
||||
bool is_relative() const;
|
||||
|
||||
int compare(const path& other) const;
|
||||
int compare(const path &other) const;
|
||||
|
||||
file_type what() const;
|
||||
|
||||
const value_type*c_str() const;
|
||||
const string_type& native() 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::string u8string() const;
|
||||
// std::u16string u16string() const;
|
||||
// std::u32string u32string() const;
|
||||
|
||||
std::string generic_string() const ;
|
||||
std::string generic_string() const;
|
||||
|
||||
std::wstring generic_wstring() const;
|
||||
std::string generic_u8string() 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);
|
||||
path &operator/=(const path &other);
|
||||
|
||||
template<typename Source>
|
||||
path& operator/=(const Source& source)
|
||||
path &operator/=(const Source &source)
|
||||
{
|
||||
path other(source);
|
||||
return this->operator/=(other);
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
path& append(const Source& 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);
|
||||
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);
|
||||
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
|
||||
: public std::system_error
|
||||
{
|
||||
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, const path& path2, std::error_code err);
|
||||
filesystem_error(const std::string &msg, const path &path1, std::error_code err);
|
||||
|
||||
const path& path1() const noexcept;
|
||||
const path& path2() const noexcept;
|
||||
filesystem_error(const std::string &msg, const path &path1, const path &path2, std::error_code err);
|
||||
|
||||
const path &path1() const noexcept;
|
||||
|
||||
const path &path2() const noexcept;
|
||||
// const char* what() const noexcept;
|
||||
private:
|
||||
path path1_;
|
||||
@ -346,65 +367,78 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
{
|
||||
public:
|
||||
directory_entry() = default;
|
||||
explicit directory_entry(const ::nana::experimental::filesystem::path&);
|
||||
|
||||
explicit directory_entry(const filesystem::path &);
|
||||
|
||||
//modifiers
|
||||
void assign(const ::nana::experimental::filesystem::path&);
|
||||
void replace_filename(const ::nana::experimental::filesystem::path&);
|
||||
void assign(const filesystem::path &);
|
||||
|
||||
void replace_filename(const filesystem::path &);
|
||||
|
||||
//observers
|
||||
file_status status() const;
|
||||
operator const filesystem::path&() const { return path_; };
|
||||
const filesystem::path& path() const;
|
||||
|
||||
operator const filesystem::path &() const
|
||||
{ return path_; };
|
||||
|
||||
const filesystem::path &path() const;
|
||||
|
||||
private:
|
||||
::nana::experimental::filesystem::path path_;
|
||||
filesystem::path path_;
|
||||
};
|
||||
|
||||
/// InputIterator that iterate over the sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator
|
||||
class directory_iterator :public std::iterator<std::input_iterator_tag, directory_entry>
|
||||
class directory_iterator : public std::iterator<std::input_iterator_tag, directory_entry>
|
||||
{
|
||||
using find_handle = void*;
|
||||
using find_handle = void *;
|
||||
public:
|
||||
|
||||
directory_iterator() noexcept;
|
||||
explicit directory_iterator(const path& p);
|
||||
directory_iterator(const path& p, directory_options opt);
|
||||
|
||||
const value_type& operator*() const;
|
||||
const value_type* operator->() const;
|
||||
explicit directory_iterator(const path &p);
|
||||
|
||||
directory_iterator(const path &p, directory_options opt);
|
||||
|
||||
const value_type &operator*() const;
|
||||
|
||||
const value_type *operator->() const;
|
||||
|
||||
directory_iterator &operator++();
|
||||
|
||||
directory_iterator& operator++();
|
||||
directory_iterator operator++(int); ///< extention
|
||||
|
||||
bool equal(const directory_iterator& x) const;
|
||||
bool equal(const directory_iterator &x) const;
|
||||
|
||||
private:
|
||||
template<typename Char>
|
||||
static bool _m_ignore(const Char * p)
|
||||
static bool _m_ignore(const Char *p)
|
||||
{
|
||||
while(*p == '.')
|
||||
while (*p == '.')
|
||||
++p;
|
||||
return (*p == 0);
|
||||
}
|
||||
|
||||
void _m_prepare(const path& file_path);
|
||||
void _m_prepare(const path &file_path);
|
||||
|
||||
void _m_read();
|
||||
|
||||
private:
|
||||
bool end_{false};
|
||||
path::string_type path_;
|
||||
directory_options option_{ directory_options::none };
|
||||
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
|
||||
inline directory_iterator begin(directory_iterator iter) noexcept
|
||||
{
|
||||
return iter;
|
||||
}
|
||||
|
||||
inline directory_iterator end( const directory_iterator&) noexcept
|
||||
inline directory_iterator end(const directory_iterator &) noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@ -416,42 +450,46 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
//recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
|
||||
file_status status(const path& p);
|
||||
file_status status(const path& p, std::error_code&);
|
||||
file_status status(const path &p);
|
||||
|
||||
std::uintmax_t file_size(const path& p);
|
||||
std::uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
|
||||
file_status status(const path &p, std::error_code &);
|
||||
|
||||
std::uintmax_t file_size(const path &p);
|
||||
|
||||
std::uintmax_t file_size(const path &p, std::error_code &ec) noexcept;
|
||||
|
||||
inline bool is_directory(file_status s) noexcept
|
||||
{ return s.type() == file_type::directory ;}
|
||||
{ return s.type() == file_type::directory; }
|
||||
|
||||
bool is_directory(const path& p);
|
||||
bool is_directory(const path& p, std::error_code& ec) noexcept;
|
||||
bool is_directory(const path &p);
|
||||
|
||||
bool is_directory(const path &p, std::error_code &ec) noexcept;
|
||||
|
||||
inline bool is_regular_file(file_status s) noexcept
|
||||
{
|
||||
return s.type() == file_type::regular;
|
||||
}
|
||||
inline bool is_regular_file(const path& p)
|
||||
|
||||
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.
|
||||
// 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)
|
||||
inline bool is_empty(const path &p)
|
||||
{
|
||||
auto fs = status(p);
|
||||
|
||||
@ -463,34 +501,38 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
// 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_directory(const path &p);
|
||||
|
||||
//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);
|
||||
//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
|
||||
/// 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
|
||||
//file_time_type last_write_time(const path& p, error_code& ec) noexcept;
|
||||
|
||||
|
||||
path current_path();
|
||||
|
||||
//path current_path(error_code& ec);
|
||||
void current_path(const path& p); ///< chdir
|
||||
void current_path(const path &p); ///< chdir
|
||||
//void current_path(const path& p, error_code& ec) noexcept;
|
||||
|
||||
bool remove(const path& p);
|
||||
bool remove(const path& p, std::error_code& ec); // noexcept;
|
||||
bool remove(const path &p);
|
||||
|
||||
bool remove(const path &p, std::error_code &ec); // noexcept;
|
||||
|
||||
//uintmax_t remove_all(const path& p);
|
||||
//uintmax_t remove_all(const path& p, error_code& ec) noexcept;
|
||||
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> parent_path(const std::basic_string<CharType>& path)
|
||||
std::basic_string<CharType> parent_path(const std::basic_string<CharType> &path)
|
||||
{
|
||||
auto index = path.size();
|
||||
|
||||
@ -515,34 +557,45 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
|
||||
return index ? path.substr(0, index + 1) : std::basic_string<CharType>();
|
||||
}
|
||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
||||
} //end namespace v1
|
||||
#endif
|
||||
} //end namespace filesystem
|
||||
} //end namespace experimental
|
||||
|
||||
//namespace filesystem = experimental::filesystem;
|
||||
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
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
#if defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || _MSVC_LANG < 201703)
|
||||
using namespace ::nana::filesystem;
|
||||
#else
|
||||
inline namespace nana_filesystem
|
||||
{
|
||||
using namespace ::nana::filesystem;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
namespace experimental {
|
||||
namespace filesystem {
|
||||
|
||||
# ifdef CXX_NO_INLINE_NAMESPACE
|
||||
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)))
|
||||
#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
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
#if defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703))
|
||||
path absolute(const path& p);
|
||||
path absolute(const path& p, std::error_code& err);
|
||||
|
||||
@ -552,33 +605,23 @@ namespace std {
|
||||
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)
|
||||
/*
|
||||
#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
|
||||
}
|
||||
} // std
|
||||
#else
|
||||
|
||||
//Implements the missing functions for various version of experimental/filesystem
|
||||
# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM)
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
*/
|
||||
//Visual Studio 2017
|
||||
#if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801))
|
||||
#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, std::error_code& err);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
} // namespace filesystem
|
||||
} // namespace std
|
||||
|
||||
#endif //NANA_USING_NANA_FILESYSTEM
|
||||
#endif // incomplete STD_FILESYSTEM
|
||||
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
#endif //NANA_FILESYSTEM_HPP
|
||||
|
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file nana\filesystem\filesystem_ext.hpp
|
||||
* @autor by Ariel Vina-Rodriguez:
|
||||
* @autor Ariel Vina-Rodriguez:
|
||||
* @brief Some convenient extensions to the filesystem library.
|
||||
*
|
||||
*/
|
||||
@ -15,8 +15,8 @@
|
||||
#ifndef NANA_FILESYSTEM_EXT_HPP
|
||||
#define NANA_FILESYSTEM_EXT_HPP
|
||||
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
#include <nana/deploy.hpp>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -35,16 +35,6 @@ namespace filesystem_ext
|
||||
|
||||
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
|
||||
{
|
||||
return is_directory(dir.status());
|
||||
@ -57,10 +47,10 @@ class directory_only_iterator : public std::filesystem::directory_iterator
|
||||
|
||||
directory_only_iterator& find_first()
|
||||
{
|
||||
auto end = directory_only_iterator{};
|
||||
directory_only_iterator end{};
|
||||
while (*this != end)
|
||||
{
|
||||
if (is_directory((**this).status()))
|
||||
if (is_directory((*(*this)).status()))
|
||||
return *this;
|
||||
this->directory_iterator::operator++();
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ namespace nana
|
||||
virtual void mouse_dropfiles(graph_reference, const arg_dropfiles&);
|
||||
|
||||
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_char(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 move(const arg_move&, 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_char(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.
|
||||
destroy, ///< A widget is about to be destroyed.
|
||||
focus, ///< A widget's focus is changed.
|
||||
key_ime,
|
||||
key_press, ///< A keyboard is pressed on a focus widget.
|
||||
key_char, ///< The focus widget received a character.
|
||||
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
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
event_code evt_code; ///< it is event_code::key_press in current event
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <memory>
|
||||
namespace nana
|
||||
{
|
||||
/// a tool to share and set a color common to many uses
|
||||
class color_proxy
|
||||
{
|
||||
public:
|
||||
@ -38,6 +39,7 @@ namespace nana
|
||||
std::shared_ptr<color> color_;
|
||||
};//end namespace color_proxy
|
||||
|
||||
/// define common color and geometrical properties
|
||||
struct widget_geometrics
|
||||
{
|
||||
virtual ~widget_geometrics() = default;
|
||||
|
@ -1,13 +1,13 @@
|
||||
/*
|
||||
/**
|
||||
* A Message Box Class
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/msgbox.hpp
|
||||
* @file nana/gui/msgbox.hpp
|
||||
*/
|
||||
|
||||
#ifndef NANA_GUI_MSGBOX_HPP
|
||||
@ -81,8 +81,8 @@ namespace nana
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Displays the message that buffered in the stream.
|
||||
/// @return, the button that user clicked.
|
||||
/// \brief Displays the message buffered in the stream.
|
||||
/// @return, the button the user clicked.
|
||||
pick_t show() const;
|
||||
|
||||
/// A function object method alternative to show()
|
||||
@ -98,6 +98,9 @@ namespace nana
|
||||
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
|
||||
{
|
||||
struct abstract_content
|
||||
@ -110,6 +113,8 @@ namespace nana
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Shows a checkbox for boolean input
|
||||
class boolean
|
||||
: public abstract_content
|
||||
{
|
||||
@ -128,6 +133,7 @@ namespace nana
|
||||
std::unique_ptr<implement> impl_;
|
||||
};
|
||||
|
||||
/// Integer input
|
||||
class integer
|
||||
: public abstract_content
|
||||
{
|
||||
@ -146,6 +152,7 @@ namespace nana
|
||||
std::unique_ptr<implement> impl_;
|
||||
};
|
||||
|
||||
/// Floating-point number input.
|
||||
class real
|
||||
: public abstract_content
|
||||
{
|
||||
@ -164,6 +171,7 @@ namespace nana
|
||||
std::unique_ptr<implement> impl_;
|
||||
};
|
||||
|
||||
/// String input or an option from a dropdown list.
|
||||
class text
|
||||
: public abstract_content
|
||||
{
|
||||
@ -192,6 +200,7 @@ namespace nana
|
||||
std::unique_ptr<implement> impl_;
|
||||
};
|
||||
|
||||
/// Date input
|
||||
class date
|
||||
: public abstract_content
|
||||
{
|
||||
@ -214,6 +223,10 @@ namespace nana
|
||||
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
|
||||
: public abstract_content
|
||||
{
|
||||
@ -231,11 +244,26 @@ namespace nana
|
||||
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 = {});
|
||||
void image_v(::nana::paint::image, bool is_top, const rectangle& valid_area = {});
|
||||
/// shows images at left/right side of inputbox
|
||||
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>
|
||||
bool show(Args&& ... args)
|
||||
{
|
||||
@ -251,6 +279,10 @@ namespace nana
|
||||
return _m_open(contents, false);
|
||||
}
|
||||
|
||||
/// 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)
|
||||
{
|
||||
@ -267,7 +299,7 @@ namespace nana
|
||||
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);
|
||||
|
||||
/** 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.
|
||||
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);
|
||||
|
||||
color fgcolor(window);
|
||||
|
@ -48,7 +48,7 @@ namespace nana
|
||||
template<typename Function>
|
||||
void elapse(Function && fn)
|
||||
{
|
||||
elapse_.connect(std::forward<Function>(fn));
|
||||
elapse_->connect(std::forward<Function>(fn));
|
||||
}
|
||||
|
||||
void reset();
|
||||
@ -66,7 +66,7 @@ namespace nana
|
||||
private:
|
||||
unsigned _m_interval() const;
|
||||
private:
|
||||
nana::basic_event<arg_elapse> elapse_;
|
||||
std::shared_ptr<nana::basic_event<arg_elapse>> elapse_;
|
||||
implement * const impl_;
|
||||
};
|
||||
}//end namespace nana
|
||||
|
@ -87,10 +87,10 @@ namespace nana{
|
||||
typedef widget_object<category::widget_tag, drawerbase::button::trigger> base_type;
|
||||
public:
|
||||
button();
|
||||
button(window, bool visible);
|
||||
button(window, const ::std::string& caption, bool visible = true);
|
||||
button(window, const char* caption, bool visible = true);
|
||||
button(window, const nana::rectangle& = rectangle(), bool visible = true);
|
||||
button(window parent, bool visible);
|
||||
button(window parent, const ::std::string& caption, bool visible = true);
|
||||
button(window parent, const char* caption, bool visible = true);
|
||||
button(window parent, const nana::rectangle& = rectangle(), bool visible = true);
|
||||
|
||||
/// Shows an icon in front of caption
|
||||
/**
|
||||
|
@ -65,6 +65,7 @@ namespace nana
|
||||
void mouse_up(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 key_ime(graph_reference, const arg_ime&) override;
|
||||
void key_press(graph_reference, const arg_keyboard&) override;
|
||||
void key_char(graph_reference, const arg_keyboard&) override;
|
||||
private:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -95,6 +95,13 @@ namespace detail
|
||||
typedef tree_node<element_type> node_type;
|
||||
typedef typename node_type::value_type value_type;
|
||||
|
||||
enum class enum_order
|
||||
{
|
||||
stop, //Stop enumeration
|
||||
proceed_with_children,
|
||||
proceed
|
||||
};
|
||||
|
||||
tree_cont()
|
||||
:root_(nullptr)
|
||||
{}
|
||||
@ -234,59 +241,6 @@ namespace detail
|
||||
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>
|
||||
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.
|
||||
while(node)
|
||||
{
|
||||
switch(f(*node, state))
|
||||
enum_order order = f(*node, state);
|
||||
|
||||
if (enum_order::stop == order)
|
||||
{
|
||||
case 0: return;
|
||||
case 1:
|
||||
{
|
||||
if(node->child)
|
||||
return;
|
||||
}
|
||||
else if (node->child && (enum_order::proceed_with_children == order))
|
||||
{
|
||||
node = node->child;
|
||||
state = 1;
|
||||
}
|
||||
else
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(node->next)
|
||||
else if(node->next)
|
||||
{
|
||||
node = node->next;
|
||||
state = 0;
|
||||
@ -340,31 +288,37 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PredAllowChild>
|
||||
unsigned child_size_if(const ::std::string& key, PredAllowChild pac) const
|
||||
template<typename PredAllowChild, typename PredAllowNode>
|
||||
unsigned child_size_if(const ::std::string& key, PredAllowChild pac, PredAllowNode pan) const
|
||||
{
|
||||
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>
|
||||
unsigned child_size_if(const node_type& node, PredAllowChild pac) const
|
||||
template<typename PredAllowChild, typename PredAllowNode>
|
||||
unsigned child_size_if(const node_type& node, PredAllowChild pac, PredAllowNode pan) const
|
||||
{
|
||||
unsigned size = 0;
|
||||
const node_type* pnode = node.child;
|
||||
while(pnode)
|
||||
{
|
||||
if (!pan(*pnode))
|
||||
{
|
||||
pnode = pnode->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
++size;
|
||||
if(pnode->child && pac(*pnode))
|
||||
size += child_size_if<PredAllowChild>(*pnode, pac);
|
||||
size += child_size_if<PredAllowChild>(*pnode, pac, pan);
|
||||
|
||||
pnode = pnode->next;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
template<typename PredAllowChild>
|
||||
std::size_t distance_if(const node_type * node, PredAllowChild pac) const
|
||||
template<typename PredAllowChild, typename PredAllowNode>
|
||||
std::size_t distance_if(const node_type * node, PredAllowChild pac, PredAllowNode pan) const
|
||||
{
|
||||
if(nullptr == node) return 0;
|
||||
const node_type * iterator = root_.child;
|
||||
@ -374,6 +328,12 @@ namespace detail
|
||||
|
||||
while(iterator && iterator != node)
|
||||
{
|
||||
if (!pan(*iterator))
|
||||
{
|
||||
iterator = iterator->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
++off;
|
||||
|
||||
if(iterator->child && pac(*iterator))
|
||||
@ -393,8 +353,8 @@ namespace detail
|
||||
return off;
|
||||
}
|
||||
|
||||
template<typename PredAllowChild>
|
||||
node_type* advance_if(node_type* node, std::size_t off, PredAllowChild pac)
|
||||
template<typename PredAllowChild, typename PredAllowNode>
|
||||
node_type* advance_if(node_type* node, std::size_t off, PredAllowChild pac, PredAllowNode pan)
|
||||
{
|
||||
if(nullptr == node) node = root_.child;
|
||||
|
||||
@ -402,6 +362,12 @@ namespace detail
|
||||
|
||||
while(node && off)
|
||||
{
|
||||
if (!pan(*node))
|
||||
{
|
||||
node = node->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
--off;
|
||||
if(node->child && pac(*node))
|
||||
{
|
||||
@ -490,7 +456,7 @@ namespace detail
|
||||
void _m_for_each(const ::std::string& key, Function function) const
|
||||
{
|
||||
//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)
|
||||
return;
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* A Form Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* 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
|
||||
@ -42,7 +42,7 @@ namespace nana
|
||||
//place methods
|
||||
|
||||
place & get_place();
|
||||
void div(const char* div_text);
|
||||
void div(std::string div_text);
|
||||
place::field_reference operator[](const char* field_name);
|
||||
void collocate() noexcept;
|
||||
private:
|
||||
@ -51,22 +51,29 @@ namespace nana
|
||||
}//end namespace form
|
||||
}//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
|
||||
class form
|
||||
: public drawerbase::form::form_base
|
||||
{
|
||||
public:
|
||||
/// helper template class for creating the appearance of the form.
|
||||
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.
|
||||
form(const rectangle& = API::make_center(300, 200), const appearance& = {}); //Default constructor
|
||||
/// Creates a window form owned by the desktop, at the point and size specified by rect, and with the specified appearance.
|
||||
explicit form(const rectangle& = API::make_center(300, 200), const appearance& = {}); //Default 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.
|
||||
explicit form(window owner, const ::nana::size& = { 300, 200 }, const appearance& = {});
|
||||
explicit form(window owner, const rectangle&, const appearance& = {});
|
||||
form(const form&, const ::nana::size& = { 300, 200 }, const appearance& = {}); //Copy constructor
|
||||
form(window, 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.
|
||||
form(window, const rectangle&, const appearance& = {});
|
||||
|
||||
/// Blocks the execution and other windows' messages until this window is closed.
|
||||
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);
|
||||
|
@ -47,10 +47,10 @@ namespace nana
|
||||
class column_interface
|
||||
{
|
||||
public:
|
||||
/// Destructor
|
||||
// Destructor
|
||||
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;
|
||||
|
||||
/// Sets width
|
||||
@ -824,6 +824,10 @@ namespace nana
|
||||
/// Determines whether the item is displayed on the screen
|
||||
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;
|
||||
|
||||
/// 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
|
||||
using oresolver = drawerbase::listbox::oresolver;
|
||||
|
||||
/// The representation of an item
|
||||
/// The representation of an item 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;
|
||||
|
||||
/// 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;
|
||||
public:
|
||||
|
||||
/// Constructors
|
||||
// Constructors
|
||||
listbox() = default;
|
||||
listbox(window, bool visible);
|
||||
listbox(window, const rectangle& = {}, bool visible = true);
|
||||
|
||||
//Element access
|
||||
// Element access
|
||||
|
||||
/// Returns the category at specified location pos, with bounds checking.
|
||||
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);
|
||||
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
|
||||
/**
|
||||
@ -1391,7 +1395,7 @@ the nana::detail::basic_window member pointer scheme
|
||||
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
|
||||
*/
|
||||
@ -1406,7 +1410,6 @@ the nana::detail::basic_window member pointer scheme
|
||||
|
||||
bool assoc_ordered(bool);
|
||||
|
||||
|
||||
void auto_draw(bool) noexcept; ///< Set state: Redraw automatically after an operation
|
||||
|
||||
template<typename Function>
|
||||
@ -1432,6 +1435,8 @@ the nana::detail::basic_window member pointer scheme
|
||||
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
|
||||
///
|
||||
/// 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::wstring text, unsigned width = 120);
|
||||
|
||||
@ -1480,7 +1485,7 @@ the nana::detail::basic_window member pointer scheme
|
||||
void column_movable(bool);
|
||||
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;
|
||||
|
||||
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
|
||||
/**
|
||||
* @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);
|
||||
|
||||
@ -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);
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Returns the item which is hovered
|
||||
/**
|
||||
* @param return_end Indicates whether to return an end position instead of empty position if an item is not hovered.
|
||||
* @return The position of the hovered item. If return_end is true, it returns the position next to the last item of last category if an item is not hovered.
|
||||
* @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 and no item is hovered it returns the position next to the last item of last category.
|
||||
*/
|
||||
index_pair hovered(bool return_end) const;
|
||||
|
||||
/// Returns the absolute position of column which contains the specified point.
|
||||
size_type column_from_pos(const point & pos) const;
|
||||
/// Returns the absolute position of the column which contains the specified "screen" point.
|
||||
size_type column_from_pos(const point & screen_pos) const;
|
||||
|
||||
void checkable(bool);
|
||||
index_pairs checked() const; ///<Returns the items which are checked.
|
||||
void checkable(bool make_checkeable); ///< Display a checkbox at te links of each item if make_checkeable=true
|
||||
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(); ///<Removes all the items from all categories
|
||||
void erase(size_type cat); ///<Erases a category
|
||||
void erase(); ///<Erases all categories.
|
||||
void erase(index_pairs indexes); ///<Erases specified items.
|
||||
item_proxy erase(item_proxy);
|
||||
void clear(size_type cat); ///< Removes all the items from the specified category
|
||||
void clear(); ///< Removes all the items from all categories
|
||||
void erase(size_type cat); ///< Erases a category
|
||||
void erase(); ///< Erases all categories.
|
||||
void erase(index_pairs indexes); ///< Erases specified items.
|
||||
item_proxy erase(item_proxy indx); ///< Erases specified item.
|
||||
|
||||
bool sortable() const;
|
||||
void sortable(bool enable);
|
||||
bool sortable() const; ///< return whether the listbox is set to be sortable
|
||||
void sortable(bool enable); ///< set the listbox to be or not to be sortable
|
||||
|
||||
///Sets a strict weak ordering comparer for a column
|
||||
void set_sort_compare( size_type col,
|
||||
std::function<bool(const std::string&, nana::any*,
|
||||
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
||||
|
||||
/// 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);
|
||||
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();
|
||||
|
||||
///< Prevent sorting until `freeze` is set to false.
|
||||
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);
|
||||
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 disable_single(bool for_selection);
|
||||
bool is_single_enabled(bool for_selection) const noexcept; ///< Determines whether the single selection/check is enabled.
|
||||
export_options& def_export_options();
|
||||
export_options& def_export_options(); ///< return a modifiable reference to the export options in use
|
||||
|
||||
|
||||
/// 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(accepts);
|
||||
bool respond_ime(const arg_ime& arg);
|
||||
bool respond_char(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 shift_begin_caret;
|
||||
}points_;
|
||||
|
||||
size_t composition_size_ { 0 };
|
||||
};
|
||||
}//end namespace skeletons
|
||||
}//end namespace widgets
|
||||
|
@ -66,6 +66,7 @@ namespace nana
|
||||
void mouse_move(graph_reference, const arg_mouse&) override;
|
||||
void mouse_up(graph_reference, const arg_mouse& arg) 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_char(graph_reference, const arg_keyboard&) 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_leave(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_char(graph_reference, const arg_keyboard&) override;
|
||||
void mouse_wheel(graph_reference, const arg_wheel&) override;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Tree Box Implementation
|
||||
* 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.
|
||||
* (See accompanying file LICENSE or copy at
|
||||
@ -49,7 +49,7 @@ namespace nana
|
||||
|
||||
struct node_attribute
|
||||
{
|
||||
bool has_children;
|
||||
bool has_children; ///< Determines whether the node has visible children
|
||||
bool expended;
|
||||
checkstate checked;
|
||||
bool selected;
|
||||
@ -117,6 +117,7 @@ namespace nana
|
||||
::std::string text;
|
||||
nana::any value;
|
||||
bool expanded;
|
||||
bool hidden;
|
||||
checkstate checked;
|
||||
::std::string img_idstr;
|
||||
};
|
||||
@ -218,6 +219,12 @@ namespace nana
|
||||
/// Select the node, and returns itself..
|
||||
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.
|
||||
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> 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> hidden; ///< a user hides or shows a node
|
||||
};
|
||||
}//end namespace treebox
|
||||
}//end namespace drawerbase
|
||||
@ -484,6 +492,14 @@ namespace nana
|
||||
|
||||
/// Gets the current hovered node.
|
||||
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:
|
||||
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() override;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* 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
|
||||
@ -170,8 +170,16 @@ namespace nana
|
||||
}
|
||||
|
||||
/// 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
|
||||
{
|
||||
protected:
|
||||
@ -293,8 +301,13 @@ namespace nana
|
||||
std::unique_ptr<scheme_type> scheme_;
|
||||
};//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
|
||||
template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger
|
||||
/// 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
|
||||
/// 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
|
||||
{
|
||||
protected:
|
||||
@ -360,7 +373,13 @@ namespace nana
|
||||
|
||||
|
||||
/// 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
|
||||
{
|
||||
protected:
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Character Encoding Set Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -245,8 +245,12 @@ namespace nana
|
||||
int bytes = ::WideCharToMultiByte(CP_ACP, 0, s, -1, 0, 0, 0, 0);
|
||||
if(bytes > 1)
|
||||
{
|
||||
mbstr.resize(bytes - 1);
|
||||
::WideCharToMultiByte(CP_ACP, 0, s, -1, &(mbstr[0]), bytes - 1, 0, 0);
|
||||
// the bytes is the length of the string with null character.
|
||||
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;
|
||||
#else
|
||||
@ -279,8 +283,12 @@ namespace nana
|
||||
int chars = ::MultiByteToWideChar(CP_ACP, 0, s, -1, 0, 0);
|
||||
if(chars > 1)
|
||||
{
|
||||
wcstr.resize(chars - 1);
|
||||
::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars - 1);
|
||||
// the length of the string with null character.
|
||||
wcstr.resize(chars);
|
||||
::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars);
|
||||
|
||||
// remove the null character written by MultiByteToWideChar
|
||||
wcstr.pop_back();
|
||||
}
|
||||
#else
|
||||
locale_initializer::init();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A ISO C++ FileSystem Implementation
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
@ -6,16 +6,17 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/filesystem/filesystem.cpp
|
||||
* @description:
|
||||
* @file nana/filesystem/filesystem.cpp
|
||||
* @description
|
||||
* provide some interface for file management
|
||||
*/
|
||||
|
||||
#include <nana/config.hpp>
|
||||
#include <nana/filesystem/filesystem_ext.hpp>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <nana/config.hpp>
|
||||
#ifdef _nana_std_put_time
|
||||
#include <nana/stdc++.hpp>
|
||||
#else
|
||||
@ -148,16 +149,13 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
#if NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
namespace nana_fs = nana::experimental::filesystem;
|
||||
|
||||
namespace nana { namespace experimental { namespace filesystem
|
||||
{
|
||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
||||
inline namespace v1 {
|
||||
#endif
|
||||
#if NANA_USING_NANA_FILESYSTEM // and BOOST ?
|
||||
|
||||
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)
|
||||
@ -185,7 +183,6 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
}
|
||||
//end class filesystem_error
|
||||
|
||||
|
||||
//Because of No wide character version of POSIX
|
||||
#if defined(NANA_POSIX)
|
||||
const char* separators = "/";
|
||||
@ -512,10 +509,10 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
return to_wstring(pathstr_);
|
||||
}
|
||||
|
||||
std::string path::u8string() const
|
||||
/*std::string path::u8string() const
|
||||
{
|
||||
return to_utf8(pathstr_);
|
||||
}
|
||||
}*/
|
||||
std::string path::generic_string() const
|
||||
{
|
||||
auto str = string();
|
||||
@ -528,12 +525,12 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
std::replace(str.begin(), str.end(), L'\\', L'/');
|
||||
return str;
|
||||
}
|
||||
std::string path::generic_u8string() const // uppss ...
|
||||
/*std::string path::generic_u8string() const // uppss ...
|
||||
{
|
||||
auto str = pathstr_;
|
||||
std::replace(str.begin(), str.end(), '\\', '/'); // uppss ... revise this !!!!!
|
||||
return to_utf8(str);
|
||||
}
|
||||
}*/
|
||||
|
||||
path path::lexically_normal() const
|
||||
{
|
||||
@ -667,7 +664,7 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
}
|
||||
|
||||
//class directory_entry
|
||||
directory_entry::directory_entry(const nana_fs::path& p)
|
||||
directory_entry::directory_entry(const filesystem::path& p)
|
||||
:path_{ p }
|
||||
{}
|
||||
|
||||
@ -978,7 +975,6 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
#endif
|
||||
}//end namespace detail
|
||||
|
||||
|
||||
file_status status(const path& p)
|
||||
{
|
||||
std::error_code err;
|
||||
@ -1182,19 +1178,216 @@ namespace nana { namespace experimental { namespace filesystem
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CXX_NO_INLINE_NAMESPACE
|
||||
} //end namespace v1
|
||||
path absolute(const path& p)
|
||||
{
|
||||
if (p.empty())
|
||||
return p;
|
||||
|
||||
auto abs_base = current_path();
|
||||
|
||||
// store expensive to compute values that are needed multiple times
|
||||
path p_root_name(p.root_name());
|
||||
path base_root_name(abs_base.root_name());
|
||||
path p_root_directory(p.root_directory());
|
||||
|
||||
if (!p_root_name.empty()) // p.has_root_name()
|
||||
{
|
||||
if (p_root_directory.empty()) // !p.has_root_directory()
|
||||
return p_root_name / abs_base.root_directory()
|
||||
/ abs_base.relative_path() / p.relative_path();
|
||||
// p is absolute, so fall through to return p at end of block
|
||||
}
|
||||
else if (!p_root_directory.empty()) // p.has_root_directory()
|
||||
{
|
||||
#ifdef NANA_POSIX
|
||||
// POSIX can have root name it it is a network path
|
||||
if (base_root_name.empty()) // !abs_base.has_root_name()
|
||||
return p;
|
||||
#endif
|
||||
}//end namespace filesystem
|
||||
} //end namespace experimental
|
||||
return base_root_name / p;
|
||||
}
|
||||
else
|
||||
return abs_base / p;
|
||||
|
||||
return p; // p.is_absolute() is true
|
||||
}
|
||||
|
||||
path absolute(const path& p, std::error_code& /*err*/)
|
||||
{
|
||||
return absolute(p);
|
||||
}
|
||||
|
||||
path canonical(const path& p, std::error_code* err)
|
||||
{
|
||||
path source(p.is_absolute() ? p : absolute(p));
|
||||
path root(source.root_path());
|
||||
path result;
|
||||
|
||||
std::error_code local_ec;
|
||||
file_status stat(status(source, local_ec));
|
||||
|
||||
if (stat.type() == file_type::not_found)
|
||||
{
|
||||
if (nullptr == err)
|
||||
throw (filesystem_error(
|
||||
"nana::filesystem::canonical", source,
|
||||
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
|
||||
#else
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || \
|
||||
(defined(_MSC_VER) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703)))
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900) && ((!defined(_MSVC_LANG)) || (_MSVC_LANG < 201703))
|
||||
|
||||
path absolute(const path& p)
|
||||
{
|
||||
if (p.empty())
|
||||
@ -1379,8 +1572,8 @@ namespace std
|
||||
return weakly_canonical(p, &err);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NANA_FILESYSTEM_FORCE) || defined(NANA_MINGW)
|
||||
/*
|
||||
#if defined(NANA_MINGW)
|
||||
bool exists( std::filesystem::file_status s ) noexcept
|
||||
{
|
||||
return s.type() != file_type::not_found;
|
||||
@ -1395,20 +1588,10 @@ namespace std
|
||||
{
|
||||
return exists(status(p, ec));
|
||||
}
|
||||
#endif
|
||||
}//end namespace filesystem
|
||||
}//end namespace std
|
||||
*/
|
||||
|
||||
#else //NANA_USING_NANA_FILESYSTEM
|
||||
# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM)
|
||||
|
||||
//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))
|
||||
#if (defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) && defined(_MSC_VER) && (_MSC_VER > 1912)) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603 || (__GNUC__* 100 + __GNUC_MINOR__ < 801)))
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@ -1551,10 +1734,9 @@ namespace std
|
||||
{
|
||||
return weakly_canonical(p, &err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
}//end namespace filesystem
|
||||
}//end namespace std
|
||||
|
||||
#endif //NANA_USING_NANA_FILESYSTEM
|
||||
|
||||
|
@ -622,6 +622,7 @@ namespace detail
|
||||
}
|
||||
break;
|
||||
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))
|
||||
{
|
||||
auto & cf = xevent.xconfigure;
|
||||
@ -890,7 +891,12 @@ namespace detail
|
||||
case MapNotify:
|
||||
case UnmapNotify:
|
||||
if(xevent.type == MapNotify)
|
||||
{
|
||||
++(root_runtime->x11msg.map);
|
||||
x11_apply_exposed_position(native_window);
|
||||
}
|
||||
else
|
||||
++(root_runtime->x11msg.unmap);
|
||||
|
||||
brock.event_expose(msgwnd, (xevent.type == MapNotify));
|
||||
context.platform.motion_window = nullptr;
|
||||
|
@ -77,6 +77,9 @@ namespace detail
|
||||
|
||||
typedef BOOL (__stdcall* imm_set_composition_window_type)(HIMC, LPCOMPOSITIONFORM);
|
||||
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)
|
||||
//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);
|
||||
|
||||
HINSTANCE windows_module_handle()
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
static int dummy;
|
||||
VirtualQuery(&dummy, &mbi, sizeof(mbi));
|
||||
return reinterpret_cast<HINSTANCE>(mbi.AllocationBase);
|
||||
}
|
||||
|
||||
bedrock::bedrock()
|
||||
: pi_data_(new pi_data),
|
||||
impl_(new private_impl)
|
||||
{
|
||||
nana::detail::platform_spec::instance(); //to guaranty the platform_spec object is initialized before using.
|
||||
|
||||
|
||||
WNDCLASSEX wincl;
|
||||
wincl.hInstance = ::GetModuleHandle(0);
|
||||
wincl.hInstance = windows_module_handle();
|
||||
wincl.lpszClassName = L"NanaWindowInternal";
|
||||
wincl.lpfnWndProc = &Bedrock_WIN32_WindowProc;
|
||||
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>(
|
||||
::GetProcAddress(imm32, "ImmSetCompositionWindow"));
|
||||
|
||||
restrict::imm_get_composition_string = reinterpret_cast<restrict::imm_get_composition_string_type>(
|
||||
::GetProcAddress(imm32, "ImmGetCompositionStringW"));
|
||||
}
|
||||
|
||||
bedrock::~bedrock()
|
||||
@ -223,6 +236,8 @@ namespace detail
|
||||
|
||||
delete impl_;
|
||||
delete pi_data_;
|
||||
|
||||
::UnregisterClass(L"NanaWindowInternal", windows_module_handle());
|
||||
}
|
||||
|
||||
|
||||
@ -639,6 +654,8 @@ namespace detail
|
||||
case WM_NCRBUTTONDOWN:
|
||||
case WM_NCMBUTTONDOWN:
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
case WM_IME_CHAR:
|
||||
case WM_DROPFILES:
|
||||
case WM_MOUSELEAVE:
|
||||
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;
|
||||
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();
|
||||
LOGFONTW logfont;
|
||||
::GetObjectW(reinterpret_cast<HFONT>(native_font), sizeof logfont, &logfont);
|
||||
msgwnd = brock.focus();
|
||||
if (msgwnd && msgwnd->flags.enabled)
|
||||
{
|
||||
auto & wd_manager = brock.wd_manager();
|
||||
auto composition_index = static_cast<DWORD>(lParam & (GCS_COMPSTR | GCS_RESULTSTR));
|
||||
|
||||
arg_ime arg;
|
||||
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;
|
||||
}
|
||||
|
||||
HIMC imc = restrict::imm_get_context(root_window);
|
||||
restrict::imm_set_composition_font(imc, &logfont);
|
||||
|
||||
POINT pos;
|
||||
::GetCaretPos(&pos);
|
||||
|
||||
COMPOSITIONFORM cf = { CFS_POINT };
|
||||
cf.ptCurrentPos = pos;
|
||||
restrict::imm_set_composition_window(imc, &cf);
|
||||
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);
|
||||
|
||||
if (wd_manager.available(msgwnd))
|
||||
draw_invoker(&drawer::key_ime, msgwnd, arg, &context);
|
||||
|
||||
wd_manager.do_lazy_refresh(msgwnd, false);
|
||||
}
|
||||
}
|
||||
def_window_proc = true;
|
||||
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:
|
||||
{
|
||||
bool take_over = false;
|
||||
|
@ -96,6 +96,11 @@ namespace nana
|
||||
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&)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
_m_emit(event_code::key_press, arg, &drawer_trigger::key_press, bForce__EmitInternal);
|
||||
|
@ -21,6 +21,10 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef NANA_X11
|
||||
# include <atomic>
|
||||
#endif
|
||||
|
||||
namespace nana{
|
||||
namespace detail
|
||||
{
|
||||
@ -75,6 +79,15 @@ namespace nana{
|
||||
root_misc(root_misc&&);
|
||||
root_misc(basic_window * wd, unsigned width, unsigned height);
|
||||
~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:
|
||||
root_misc(const root_misc&) = delete;
|
||||
root_misc& operator=(const root_misc&) = delete;
|
||||
|
@ -17,14 +17,15 @@
|
||||
#include <nana/gui/detail/window_manager.hpp>
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#if defined(STD_THREAD_NOT_SUPPORTED)
|
||||
#include <nana/std_mutex.hpp>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
#include <map>
|
||||
# if defined(STD_THREAD_NOT_SUPPORTED)
|
||||
# include <nana/std_mutex.hpp>
|
||||
# else
|
||||
# include <mutex>
|
||||
# endif
|
||||
# include <map>
|
||||
#elif defined(NANA_X11)
|
||||
#include <nana/system/platform.hpp>
|
||||
# include <nana/system/platform.hpp>
|
||||
# include "inner_fwd_implement.hpp"
|
||||
#endif
|
||||
|
||||
#include "../../paint/image_accessor.hpp"
|
||||
@ -34,6 +35,10 @@ namespace nana{
|
||||
namespace detail{
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
|
||||
//This function is defined in bedrock_windows.cpp
|
||||
HINSTANCE windows_module_handle();
|
||||
|
||||
class tray_manager
|
||||
{
|
||||
struct window_extra_t
|
||||
@ -199,26 +204,87 @@ namespace nana{
|
||||
|
||||
namespace x11_wait
|
||||
{
|
||||
struct param
|
||||
{
|
||||
Window handle;
|
||||
root_misc * misc;
|
||||
std::size_t comp_value;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
::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
|
||||
|
||||
@ -315,7 +381,7 @@ namespace nana{
|
||||
HWND native_wd = ::CreateWindowEx(style_ex, L"NanaWindowInternal", L"Nana Window",
|
||||
style,
|
||||
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.
|
||||
::RECT client;
|
||||
@ -504,7 +570,7 @@ namespace nana{
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
|
||||
r.x, r.y, r.width, r.height,
|
||||
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)
|
||||
nana::detail::platform_scope_guard psg;
|
||||
|
||||
@ -758,13 +824,17 @@ namespace nana{
|
||||
if(show == is_window_visible(wd))
|
||||
return;
|
||||
|
||||
auto misc = bedrock::instance().wd_manager().root_runtime(wd);
|
||||
|
||||
if(show)
|
||||
{
|
||||
std::size_t cmp_value = misc->x11msg.map;
|
||||
|
||||
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
|
||||
//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.
|
||||
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);
|
||||
if(grab == reinterpret_cast<Window>(wd))
|
||||
@ -772,10 +842,12 @@ namespace nana{
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t cmp_value = misc->x11msg.unmap;
|
||||
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
|
||||
//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.
|
||||
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.
|
||||
@ -1019,11 +1091,15 @@ namespace nana{
|
||||
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);
|
||||
|
||||
//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.
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
||||
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1109,6 +1185,9 @@ namespace nana{
|
||||
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);
|
||||
|
||||
//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
|
||||
//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;
|
||||
#endif
|
||||
@ -1283,11 +1362,15 @@ namespace nana{
|
||||
hints.min_height = hints.max_height = sz.height;
|
||||
::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);
|
||||
|
||||
//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.
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
@ -1517,20 +1517,30 @@ namespace nana
|
||||
path_type parent_path{ str };
|
||||
str += (len + 1);
|
||||
|
||||
// if only one file was selected, the ofn.lpstrFile
|
||||
// is returning only that file, without any parent
|
||||
if (!*str)
|
||||
{
|
||||
targets.emplace_back(parent_path);
|
||||
impl_->path = parent_path.parent_path().string();
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
len = ::wcslen(str);
|
||||
targets.emplace_back(parent_path / path_type{str});
|
||||
str += (len + 1);
|
||||
}
|
||||
impl_->path = parent_path.u8string();
|
||||
impl_->path = parent_path.string();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wfile.resize(std::wcslen(wfile.data()));
|
||||
|
||||
targets.emplace_back(wfile);
|
||||
impl_->path = targets.front().parent_path().u8string();
|
||||
impl_->path = targets.front().parent_path().string();
|
||||
}
|
||||
|
||||
#elif defined(NANA_POSIX)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* A Message Box Class
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,10 +7,15 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/msgbox.hpp
|
||||
* @file nana/gui/msgbox.hpp
|
||||
* @Contributors
|
||||
* 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/msgbox.hpp>
|
||||
@ -27,8 +32,7 @@
|
||||
#include <nana/datetime.hpp>
|
||||
#include <nana/internationalization.hpp>
|
||||
#include <nana/gui/filebox.hpp>
|
||||
#include <functional>
|
||||
#include <cstdlib> //include std::abs
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(NANA_X11)
|
||||
@ -494,21 +498,29 @@ namespace nana
|
||||
//end class msgbox
|
||||
|
||||
|
||||
//class inputbox
|
||||
//class inputbox todo: add schema
|
||||
|
||||
class inputbox_window
|
||||
: public ::nana::form
|
||||
{
|
||||
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<>())
|
||||
{
|
||||
throw_not_utf8(desc);
|
||||
throw_not_utf8(description);
|
||||
throw_not_utf8(title);
|
||||
|
||||
desc_.create(*this);
|
||||
desc_.format(true).caption(desc);
|
||||
auto desc_extent = desc_.measure(470);
|
||||
description_.create(*this);
|
||||
description_.format(true).caption(description);
|
||||
auto description_size = description_.measure(470);
|
||||
|
||||
btn_ok_.create(*this);
|
||||
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK"));
|
||||
@ -527,32 +539,26 @@ namespace nana
|
||||
close();
|
||||
});
|
||||
|
||||
unsigned height = 20 + desc_extent.height + 10 + 38;
|
||||
|
||||
unsigned height = 20 + description_size.height + 10 + 38;
|
||||
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)
|
||||
{
|
||||
unsigned px = 27;
|
||||
if (each_height[i] > 27)
|
||||
px = each_height[i];
|
||||
unsigned px = std::max(27u, 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 (desc_extent.width < 200)
|
||||
desc_extent.width = 200;
|
||||
if (description_size.width < 200)
|
||||
description_size.width = 200;
|
||||
|
||||
//Make sure the complete display of input extent
|
||||
if (desc_extent.width < fixed_pixels)
|
||||
desc_extent.width = fixed_pixels;
|
||||
if (description_size.width < fixed_pixels)
|
||||
description_size.width = fixed_pixels;
|
||||
|
||||
desc_extent.width += 20;
|
||||
description_size.width += 20; // 2x margin 10
|
||||
|
||||
::nana::size img_sz[4];
|
||||
|
||||
@ -566,8 +572,9 @@ namespace nana
|
||||
}
|
||||
else
|
||||
sz = imgs[2].size();
|
||||
sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height)));
|
||||
desc_extent.width += sz.width;
|
||||
const double scale_factor = double(height) / double(sz.height);
|
||||
sz.width = static_cast<size::value_type>(double(sz.width) * scale_factor);
|
||||
description_size.width += sz.width;
|
||||
}
|
||||
|
||||
if (imgs[3]) //Right
|
||||
@ -581,7 +588,7 @@ namespace nana
|
||||
else
|
||||
sz = imgs[3].size();
|
||||
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
|
||||
@ -594,7 +601,8 @@ namespace nana
|
||||
}
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
@ -608,16 +616,28 @@ namespace nana
|
||||
}
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
place.div(ss.str().c_str());
|
||||
place["desc"] << desc_;
|
||||
place["description"] << description_;
|
||||
place["buttons"] << btn_ok_ << btn_cancel_;
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
move(API::make_center(this->owner(), desc_extent.width, height));
|
||||
move(API::make_center(this->owner(), description_size.width, height));
|
||||
caption(title);
|
||||
}
|
||||
|
||||
@ -659,7 +679,7 @@ namespace nana
|
||||
return valid_input_;
|
||||
}
|
||||
private:
|
||||
::nana::label desc_;
|
||||
::nana::label description_;
|
||||
::nana::button btn_ok_;
|
||||
::nana::button btn_cancel_;
|
||||
bool valid_input_{ false };
|
||||
@ -1247,7 +1267,7 @@ namespace nana
|
||||
auto files = impl->fbox.show();
|
||||
if(!files.empty())
|
||||
{
|
||||
impl->value = files.front().u8string();
|
||||
impl->value = files.front().string();
|
||||
impl->path_edit.caption(impl->value);
|
||||
}
|
||||
});
|
||||
|
@ -146,6 +146,7 @@ namespace nana
|
||||
|
||||
//draw caption
|
||||
auto text = to_wstring(API::window_caption(window_handle_));
|
||||
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
|
||||
|
@ -111,13 +111,13 @@ namespace nana
|
||||
{
|
||||
public:
|
||||
#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),
|
||||
timer_(tmid),
|
||||
evt_elapse_(evt_elapse)
|
||||
{}
|
||||
#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),
|
||||
timer_(this),
|
||||
evt_elapse_(evt_elapse)
|
||||
@ -142,12 +142,15 @@ namespace nana
|
||||
{
|
||||
arg_elapse arg;
|
||||
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:
|
||||
timer * const sender_;
|
||||
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
|
||||
|
||||
|
||||
@ -175,8 +178,9 @@ namespace nana
|
||||
};
|
||||
|
||||
//class timer
|
||||
timer::timer()
|
||||
: impl_(new implement)
|
||||
timer::timer():
|
||||
elapse_(std::make_shared<nana::basic_event<arg_elapse>>()),
|
||||
impl_(new implement)
|
||||
{
|
||||
}
|
||||
|
||||
@ -195,7 +199,7 @@ namespace nana
|
||||
void timer::reset()
|
||||
{
|
||||
stop();
|
||||
elapse_.clear();
|
||||
elapse_->clear();
|
||||
}
|
||||
|
||||
void timer::start()
|
||||
|
@ -773,6 +773,13 @@ namespace nana
|
||||
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)
|
||||
{
|
||||
drawer_->editor()->respond_char(arg);
|
||||
|
@ -39,7 +39,7 @@ namespace nana
|
||||
place & form_base::get_place()
|
||||
{
|
||||
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_)
|
||||
place_.reset(new place{ *this });
|
||||
@ -47,9 +47,9 @@ namespace nana
|
||||
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)
|
||||
|
@ -184,7 +184,13 @@ namespace nana
|
||||
index(pos),
|
||||
ess_(ess)
|
||||
{
|
||||
if (px == 0)
|
||||
{
|
||||
fit_width_to_header();
|
||||
}
|
||||
}
|
||||
|
||||
void fit_width_to_header();
|
||||
private:
|
||||
/// The definition is provided after essence
|
||||
void _m_refresh() noexcept;
|
||||
@ -2308,7 +2314,8 @@ namespace nana
|
||||
size_type count_of_exposed(bool with_rest) const
|
||||
{
|
||||
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
|
||||
@ -2394,7 +2401,9 @@ namespace nana
|
||||
nana::rectangle 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))
|
||||
new_where.first = parts::checker;
|
||||
}
|
||||
@ -2881,10 +2890,26 @@ namespace nana
|
||||
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
|
||||
void es_header::column::_m_refresh() noexcept
|
||||
{
|
||||
ess_->update(true);
|
||||
ess_->update(false);
|
||||
}
|
||||
|
||||
size_type es_header::column::position(bool disp_order) const noexcept
|
||||
@ -3316,16 +3341,27 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
|
||||
// init ir end to grab a header
|
||||
void grab(const nana::point& pos, bool is_grab)
|
||||
{
|
||||
if(is_grab)
|
||||
if(is_grab) // init grabbing the header
|
||||
{
|
||||
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
|
||||
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))
|
||||
essence_->header.move(essence_->pointer_where.second, grab_terminal_.index, grab_terminal_.place_front);
|
||||
else // end to grab the header
|
||||
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
|
||||
@ -4273,7 +4309,10 @@ namespace nana
|
||||
auto const good_list_r = essence_->rect_lister(list_r);
|
||||
|
||||
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;
|
||||
if(good_head_r)
|
||||
@ -4282,7 +4321,8 @@ namespace nana
|
||||
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));
|
||||
|
||||
@ -4455,13 +4495,16 @@ namespace nana
|
||||
bool need_refresh = false;
|
||||
|
||||
//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
|
||||
if(essence_->pointer_where.second < essence_->header.cont().size())
|
||||
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;
|
||||
essence_->widget_to_header(pos);
|
||||
@ -4762,7 +4805,7 @@ namespace nana
|
||||
|
||||
bool item_proxy::empty() const noexcept
|
||||
{
|
||||
return !ess_;
|
||||
return !(ess_ && ess_->lister.good(pos_));
|
||||
}
|
||||
|
||||
item_proxy & item_proxy::check(bool ck, bool scroll_view)
|
||||
@ -5959,6 +6002,7 @@ namespace nana
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
_m_ess().lister.sort_column(col, &reverse);
|
||||
_m_ess().update();
|
||||
}
|
||||
|
||||
auto listbox::sort_col() const -> size_type
|
||||
@ -6073,7 +6117,15 @@ namespace nana
|
||||
|
||||
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
|
||||
|
@ -922,7 +922,25 @@ namespace nana
|
||||
}
|
||||
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;
|
||||
|
@ -96,11 +96,11 @@ namespace nana
|
||||
{
|
||||
if (widget_)
|
||||
{
|
||||
auto value_px = (widget_->size().width - border_px * 2);
|
||||
unsigned value_px = (widget_->size().width - border_px * 2);
|
||||
|
||||
//avoid overflow
|
||||
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_)
|
||||
{
|
||||
|
@ -1163,6 +1163,43 @@ namespace nana {
|
||||
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
|
||||
{
|
||||
if (!API::window_enabled(window_))
|
||||
|
@ -621,6 +621,13 @@ namespace nana
|
||||
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)
|
||||
{
|
||||
if (impl_->editor()->respond_key(arg))
|
||||
|
@ -1229,7 +1229,8 @@ namespace nana
|
||||
|
||||
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)
|
||||
|
@ -152,6 +152,13 @@ namespace drawerbase {
|
||||
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)
|
||||
{
|
||||
editor_->respond_key(arg);
|
||||
|
@ -104,6 +104,7 @@ namespace nana
|
||||
delete ptr;
|
||||
|
||||
cont_.clear();
|
||||
right_ = npos;
|
||||
}
|
||||
|
||||
|
||||
@ -683,6 +684,7 @@ namespace nana
|
||||
if(m && (m->textout != show))
|
||||
{
|
||||
m->textout = show;
|
||||
m->pixels = 0; //force width calculation
|
||||
API::refresh_window(this->handle());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Treebox Implementation
|
||||
* 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.
|
||||
* (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)
|
||||
{
|
||||
if(node->value.second.expanded)
|
||||
if(node->value.second.expanded && !node->value.second.hidden)
|
||||
{
|
||||
node = node->child;
|
||||
while(node)
|
||||
@ -79,7 +79,7 @@ namespace nana
|
||||
|
||||
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);
|
||||
if(t || finish)
|
||||
@ -184,10 +184,11 @@ namespace nana
|
||||
class trigger::item_locator
|
||||
{
|
||||
public:
|
||||
using enum_order = tree_cont_type::enum_order;
|
||||
using node_type = tree_cont_type::node_type;
|
||||
|
||||
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;
|
||||
component what() 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
|
||||
//@brief: some data for treebox trigger
|
||||
class trigger::implementation
|
||||
@ -220,6 +229,7 @@ namespace nana
|
||||
: public compset_interface
|
||||
{
|
||||
public:
|
||||
using enum_order = tree_cont_type::enum_order;
|
||||
using node_type = tree_cont_type::node_type;
|
||||
|
||||
item_rendering_director(implementation * impl, const nana::point& pos):
|
||||
@ -232,9 +242,11 @@ namespace nana
|
||||
//0 = Sibling, the last is a sibling 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.
|
||||
int operator()(const node_type& node, int affect)
|
||||
enum_order operator()(const node_type& node, int affect)
|
||||
{
|
||||
iterated_node_ = &node;
|
||||
|
||||
// Increase/decrease indent
|
||||
switch (affect)
|
||||
{
|
||||
case 1:
|
||||
@ -245,6 +257,9 @@ namespace nana
|
||||
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;
|
||||
|
||||
impl_->assign_node_attr(node_attr_, iterated_node_);
|
||||
@ -263,9 +278,9 @@ namespace nana
|
||||
pos_.y += node_r_.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:
|
||||
//Overrides compset_interface
|
||||
@ -280,7 +295,12 @@ namespace nana
|
||||
if (impl_->data.comp_placer->locate(comp, node_attr_, &attr.area))
|
||||
{
|
||||
attr.mouse_pointed = node_attr_.mouse_pointed;
|
||||
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
@ -347,6 +367,9 @@ namespace nana
|
||||
std::size_t scroll_timestamp;
|
||||
nana::timer timer;
|
||||
}adjust;
|
||||
|
||||
bool use_entire_line;
|
||||
|
||||
public:
|
||||
implementation()
|
||||
{
|
||||
@ -371,11 +394,24 @@ namespace nana
|
||||
adjust.offset_x_adjust = 0;
|
||||
adjust.node = nullptr;
|
||||
adjust.scroll_timestamp = 0;
|
||||
|
||||
use_entire_line = false;
|
||||
}
|
||||
|
||||
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.text = node->value.second.text;
|
||||
ndattr.checked = node->value.second.checked;
|
||||
@ -552,7 +588,7 @@ namespace nana
|
||||
|
||||
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;
|
||||
continue;
|
||||
@ -603,8 +639,8 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
auto pos = tree.distance_if(node, pred_allow_child{});
|
||||
auto last_pos = tree.distance_if(last(true), 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{}, pred_allow_node{});
|
||||
|
||||
auto const capacity = screen_capacity(true);
|
||||
|
||||
@ -612,7 +648,7 @@ namespace nana
|
||||
//position of the requested item.
|
||||
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)
|
||||
bearing = align_v::top;
|
||||
@ -655,7 +691,7 @@ namespace nana
|
||||
}
|
||||
|
||||
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
|
||||
show_scroll();
|
||||
@ -669,8 +705,8 @@ namespace nana
|
||||
|
||||
auto & tree = attr.tree_cont;
|
||||
|
||||
auto const first_pos = tree.distance_if(shape.first, pred_allow_child{});
|
||||
auto const node_pos = tree.distance_if(node, 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{}, pred_allow_node{});
|
||||
auto const max_allow = max_allowed();
|
||||
switch(reason)
|
||||
{
|
||||
@ -680,12 +716,12 @@ namespace nana
|
||||
//adjust if the number of its children are over the max number allowed
|
||||
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)
|
||||
{
|
||||
auto const size = node_pos - first_pos + child_size + 1;
|
||||
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
|
||||
shape.first = node;
|
||||
@ -698,7 +734,7 @@ namespace nana
|
||||
if (visual_size > max_allow)
|
||||
{
|
||||
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
|
||||
shape.first = nullptr;
|
||||
@ -739,7 +775,7 @@ namespace nana
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -814,6 +850,27 @@ namespace nana
|
||||
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()
|
||||
{
|
||||
if(nullptr == data.graph) return;
|
||||
@ -841,7 +898,7 @@ namespace nana
|
||||
adjust.scroll_timestamp = nana::system::timestamp();
|
||||
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);
|
||||
});
|
||||
}
|
||||
@ -850,13 +907,13 @@ namespace nana
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
@ -1153,6 +1210,20 @@ namespace nana
|
||||
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
|
||||
{
|
||||
return node_->value.second.img_idstr;
|
||||
@ -1274,7 +1345,10 @@ namespace nana
|
||||
|
||||
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*()
|
||||
@ -1395,7 +1469,7 @@ namespace nana
|
||||
switch(comp)
|
||||
{
|
||||
case component_t::expander:
|
||||
if(attr.has_children)
|
||||
if (attr.has_children)
|
||||
{
|
||||
r->width = scheme_.item_offset;
|
||||
return true;
|
||||
@ -1581,7 +1655,7 @@ namespace nana
|
||||
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)
|
||||
{
|
||||
@ -1592,6 +1666,9 @@ namespace nana
|
||||
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);
|
||||
nana::rectangle node_r;
|
||||
auto & comp_placer = impl_->data.comp_placer;
|
||||
@ -1609,7 +1686,7 @@ namespace nana
|
||||
if (!comp_placer->locate(static_cast<component>(comp), node_attr_, &r))
|
||||
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;
|
||||
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;
|
||||
|
||||
if(node.value.second.expanded && node.child)
|
||||
return 1;
|
||||
|
||||
return 2;
|
||||
return ((node.child && node.value.second.expanded) ? enum_order::proceed_with_children : enum_order::proceed);
|
||||
}
|
||||
|
||||
trigger::item_locator::node_type * trigger::item_locator::node() const
|
||||
@ -1662,11 +1736,11 @@ namespace nana
|
||||
//class trigger
|
||||
//struct 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)
|
||||
: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)
|
||||
@ -1952,13 +2026,14 @@ namespace nana
|
||||
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
|
||||
|
||||
auto const node = nl.node();
|
||||
if (!node)
|
||||
if (!node || !node->child)
|
||||
return;
|
||||
|
||||
switch (nl.what())
|
||||
{
|
||||
case component::icon:
|
||||
case component::text:
|
||||
case component::bground:
|
||||
impl_->set_expanded(node, !node->value.second.expanded);
|
||||
impl_->draw(true, true, false);
|
||||
API::dev::lazy_refresh();
|
||||
@ -2384,6 +2459,12 @@ namespace nana
|
||||
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()
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
|
@ -1473,7 +1473,7 @@ namespace paint
|
||||
{
|
||||
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;
|
||||
for (; y < endpos; ++y)
|
||||
{
|
||||
@ -1489,7 +1489,7 @@ namespace paint
|
||||
}
|
||||
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;
|
||||
for (; x < endpos; ++x)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Paint Image Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
|
||||
@ -7,9 +7,8 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/paint/image.cpp
|
||||
* @contributors:
|
||||
* nabijaczleweli(pr#106)
|
||||
* @file nana/paint/image.cpp
|
||||
* @contributors nabijaczleweli(pr#106)
|
||||
*/
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
|
@ -238,10 +238,18 @@ namespace nana{ namespace paint
|
||||
auto d = rawptr;
|
||||
const unsigned char* s;
|
||||
|
||||
int src_line_bytes;
|
||||
|
||||
if (is_negative)
|
||||
{
|
||||
s = rawbits;
|
||||
src_line_bytes = -static_cast<int>(bytes_per_line);
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -256,7 +264,7 @@ namespace nana{ namespace paint
|
||||
s_p += 3;
|
||||
}
|
||||
d += pixel_size.width;
|
||||
s -= bytes_per_line;
|
||||
s -= src_line_bytes;
|
||||
}
|
||||
}
|
||||
else if(16 == bits_per_pixel)
|
||||
|
Loading…
x
Reference in New Issue
Block a user