From dfe32d0cc58a2fe72c40c2ebe4babae2438f1032 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 27 Aug 2017 16:29:57 +0200 Subject: [PATCH 01/43] ignore cmake-build-debug/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6580f35b..0972b5ae 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ lib/ *.ninja* CMakeCache.txt CMakeFiles/ +cmake-build-debug/ .idea/ cmake_install.cmake *.DS_Store From c94f69fde5497048370f33be0c3b87bffae1cf1b Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 27 Aug 2017 16:32:32 +0200 Subject: [PATCH 02/43] conveniently add include files to the project it make browsing files and navigating the code easier. /todo add all the other .h files --- build/vc2015/nana.vcxproj | 26 ++++++++++++ build/vc2015/nana.vcxproj.filters | 70 +++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/build/vc2015/nana.vcxproj b/build/vc2015/nana.vcxproj index 9dd9c3bc..3ec4cf7d 100644 --- a/build/vc2015/nana.vcxproj +++ b/build/vc2015/nana.vcxproj @@ -252,6 +252,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/vc2015/nana.vcxproj.filters b/build/vc2015/nana.vcxproj.filters index 32f7afd6..d1d7ba78 100644 --- a/build/vc2015/nana.vcxproj.filters +++ b/build/vc2015/nana.vcxproj.filters @@ -292,4 +292,74 @@ Source Files\detail + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Header Files + + + Header Files + + \ No newline at end of file From 463ba5403fe2dff23d486f53fb5830551cf181dd Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Tue, 5 Sep 2017 00:14:05 +0200 Subject: [PATCH 03/43] RuntimeLibrary->MultiThreaded (/MT or /MTd) by default, static linked --- build/vc2017/nana.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/vc2017/nana.vcxproj b/build/vc2017/nana.vcxproj index 818d6cf8..7b457574 100644 --- a/build/vc2017/nana.vcxproj +++ b/build/vc2017/nana.vcxproj @@ -101,6 +101,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDebug Windows @@ -113,6 +114,7 @@ Level3 Disabled _DEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDebug Windows @@ -127,6 +129,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded Windows @@ -143,6 +146,7 @@ true true NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded Windows From 18264f197451d03f9ec8d2bde93cb2a028a05447 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Tue, 5 Sep 2017 15:51:52 +0200 Subject: [PATCH 04/43] Manually-specified variables were not used by the project Forgot to clean this in: Commit: a68155c7d70c2e5d05acbd0ad30b96664d27d79f [a68155c7] Parents: 11bd0bcf88 Author: qPCR4vir Date: Montag, 27. Juni 2016 01:25:48 Build build demos separately. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4543e6b3..c80e2146 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,7 +84,7 @@ script: # we are in "... nana/../nana_lib/bin/" we need "../../nana" to get the CMakeList.txt of nana. # Thus, make install will put the nana.lib in "... nana/../nana_lib/lib/" # and the includes in "... nana/../nana_lib/include/" - - cmake -G"Unix Makefiles" ../../nana -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_ENABLE_PNG=OFF -DNANA_CMAKE_BUILD_DEMOS=ON -DNANA_CMAKE_ENABLE_AUDIO=OFF -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=ON -DNANA_CMAKE_BOOST_FILESYSTEM_FORCE=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON + - cmake -G"Unix Makefiles" ../../nana -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_ENABLE_PNG=OFF -DNANA_CMAKE_ENABLE_AUDIO=OFF -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=ON -DNANA_CMAKE_BOOST_FILESYSTEM_FORCE=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON - make install - ls - cd .. From 263776812e13c6d3baf92e696efa79e0cda67424 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Tue, 5 Sep 2017 15:53:43 +0200 Subject: [PATCH 05/43] git clone branch=hotfix-1.5/nana-demo in hotfix-1.5.4/nana travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c80e2146..9f6d3ed3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ matrix: - llvm-toolchain-precise before_install: - - git clone --depth=1 --branch=develop https://github.com/qPCR4vir/nana-demo.git ../nana-demo + - git clone --depth=1 --branch=hotfix-1.5 https://github.com/qPCR4vir/nana-demo.git ../nana-demo - export PATH="$HOME/bin:$PATH" #- mkdir ~/bin #it seemd that a bin already exists from 20170901 - wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.4/cmake-3.4.0-rc3-Linux-x86_64.sh || true From 252b8cbf650eea663b35d6198e1127f6d8562cd3 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 7 Sep 2017 12:32:53 +0200 Subject: [PATCH 06/43] #if __has_include() --- include/nana/c++defines.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 4c7a244e..04b5113f 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -173,6 +173,7 @@ //Assume the std::thread is not implement on MinGW //But some toolchains may implement std::thread. +// it seems that MinGW 6.3 and 7.1 have std::thread #ifdef NANA_MINGW # ifndef STD_THREAD_NOT_SUPPORTED # define STD_THREAD_NOT_SUPPORTED @@ -220,6 +221,9 @@ # if __has_include() # undef STD_FILESYSTEM_NOT_SUPPORTED # endif +# if __has_include() +# undef STD_THREAD_NOT_SUPPORTED +# endif #endif #endif // NANA_CXX_DEFINES_INCLUDED From c13b66559498f60476abb5c96b7cfe74b536e743 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 7 Sep 2017 12:36:02 +0200 Subject: [PATCH 07/43] CLion cmake workaround --- CMakeLists.txt | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f89337e..0b6e1afe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ option(NANA_CMAKE_ENABLE_AUDIO "Enable class audio::play for PCM playback." OFF) option(NANA_CMAKE_VERBOSE_PREPROCESSOR "Show annoying debug messages during compilation." ON) option(NANA_CMAKE_STOP_VERBOSE_PREPROCESSOR "Stop compilation after showing the annoying debug messages." OFF) option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF) +option(NANA_CLION "Activate some CLion specific workarounds" OFF) # The ISO C++ File System Technical Specification (ISO-TS, or STD) is optional. # http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf @@ -62,11 +63,12 @@ if(POLICY CMP0004) # ignore leading space cmake_policy(SET CMP0004 OLD) endif() +set(CMAKE_DEBUG_POSTFIX "_d") + ########### OS if(WIN32) add_definitions(-DWIN32) - set(CMAKE_DEBUG_POSTFIX "_d") #Global MSVC definitions. You may prefer the hand-tuned sln and projects from the nana repository. if(MSVC) option(MSVC_USE_MP "Set to ON to build nana with the /MP option (Visual Studio 2005 and above)." ON) @@ -121,10 +123,15 @@ endif(UNIX) ########### Compilers # # Using gcc: gcc 4.8 don't support C++14 and make_unique. You may want to update at least to 4.9. -# In Windows, the gcc which come with CLion was 4.8 from MinGW. You may want to install MinGW-w64 from the -# TDM-GCC Compiler Suite for Windows which will update you to gcc 5.1. # gcc 5.3 and 5.4 include filesytem, but you need to add the link flag: -lstdc++fs # +# In Windows, the gcc which come with CLion was 4.8 from MinGW. +# CLion was updated to MinGW with gcc 6.3 ? Allways check this in File/Settings.../toolchains +# You could install MinGW-w64 from the TDM-GCC Compiler Suite for Windows which will update you to gcc 5.1. +# It is posible to follow https://computingabdn.com/softech/mingw-howto-install-gcc-for-windows/ +# and install MinGW with gcc 7.1 with has STD_THREADS and fs, from: https://sourceforge.net/projects/mingw-w64/files/ +# +# # see at end of: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # Clang || GNU @@ -275,8 +282,19 @@ target_link_libraries(${PROJECT_NAME} ${NANA_LINKS}) # Installing: the static "nana lib" will be in DESTDIR/CMAKE_INSTALL_PREFIX/lib/ # and the includes files "include/nana/" in DESTDIR/CMAKE_INSTALL_PREFIX/include/nana/ +# unfortunatelly install() is still ignored by CLion: +# https://intellij-support.jetbrains.com/hc/en-us/community/posts/205822949-CMake-install-isn-t-supported- install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib) + +# http://stackoverflow.com/questions/33788729/how-do-i-get-clion-to-run-an-install-target +if(NANA_CLION) # the Clion IDE don't reconize the install target + add_custom_target(install_${PROJECT_NAME} + $(MAKE) install + DEPENDS ${PROJECT_NAME} + COMMENT "Installing ${PROJECT_NAME}") +endif() + message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib") # Install the include directories too. if(NANA_CMAKE_INSTALL_INCLUDES) @@ -299,6 +317,9 @@ message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX}) message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR}) message ( "CMAKE_CURRENT_SOURCE_DIR= " ${CMAKE_CURRENT_SOURCE_DIR}) message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO}) +message ( "NANA_CLION = " ${NANA_CLION}) +message ( "CMAKE_MAKE_PROGRAM = " ${CMAKE_MAKE_PROGRAM}) + message ( "NANA_CMAKE_FIND_BOOST_FILESYSTEM = " ${NANA_CMAKE_FIND_BOOST_FILESYSTEM}) message ( "NANA_CMAKE_BOOST_FILESYSTEM_FORCE = " ${NANA_CMAKE_BOOST_FILESYSTEM_FORCE}) message ( "NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT = " ${NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT}) From c348ec40095c55f947f5b72720b96bc0222359e6 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 10 Sep 2017 13:33:38 +0800 Subject: [PATCH 08/43] fix bug that widgets are mistakenly drawn on nested_form(#252) --- source/gui/detail/window_layout.cpp | 33 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index 6c3b7578..27357217 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -149,33 +149,34 @@ namespace nana // reads the overlaps that are overlapped a rectangular block bool window_layout::read_overlaps(core_window_t* wd, const nana::rectangle& vis_rect, std::vector& blocks) { + auto const is_wd_root = (category::flags::root == wd->other.category); wd_rectangle block; while (wd->parent) { - auto & siblings = wd->parent->children; - //It should be checked that whether the window is still a chlid of its parent. - if (siblings.size()) + auto i = std::find(wd->parent->children.cbegin(), wd->parent->children.cend(), wd); + if (i != wd->parent->children.cend()) { - auto i = &(siblings[0]); - auto *end = i + siblings.size(); - i = std::find(i, end, wd); - if (i != end) + for (++i; i != wd->parent->children.cend(); ++i) { - //find the widget that next to wd. - for (++i; i < end; ++i) + core_window_t* cover = *i; + + if (!cover->visible) + continue; + + if (is_wd_root ? + (category::flags::root == cover->other.category) + : + ((category::flags::root != cover->other.category) && (nullptr == cover->effect.bground))) { - core_window_t* cover = *i; - if ((category::flags::root != cover->other.category) && cover->visible && (nullptr == cover->effect.bground)) + if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r)) { - if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r)) - { - block.window = cover; - blocks.push_back(block); - } + block.window = cover; + blocks.push_back(block); } } } } + wd = wd->parent; } return (!blocks.empty()); From 8cb29a1617e2be8d34530e6fb09f1bdff644623c Mon Sep 17 00:00:00 2001 From: cnjinhao Date: Mon, 11 Sep 2017 14:42:20 +0800 Subject: [PATCH 09/43] fix issue that filebox incorrectly loads folder tree on Linux --- source/gui/filebox.cpp | 14 +++++++------- source/gui/widgets/treebox.cpp | 17 ++++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index c3fa7fb0..89382828 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -435,20 +435,20 @@ namespace nana nodes_.filesystem = tree_.insert("FS.ROOT", "Filesystem"); nodes_.filesystem.value(kind::filesystem); - std::vector paths; - paths.emplace_back(fs_ext::path_user().native()); - paths.emplace_back("/"); + std::vector> paths; + paths.emplace_back(fs_ext::path_user().native(), nodes_.home); + paths.emplace_back("/", nodes_.filesystem); fs::directory_iterator end; for (auto & p : paths) { - for (fs::directory_iterator i(p); i != end; ++i) + for (fs::directory_iterator i{p.first}; i != end; ++i) { auto name = i->path().filename().native(); if (!is_directory(i->status()) || (name.size() && name[0] == '.')) continue; - item_proxy node = tree_.insert(nodes_.filesystem, name, name); + item_proxy node = tree_.insert(p.second, name, name); if (false == node.empty()) { node.value(kind::filesystem); @@ -831,8 +831,8 @@ namespace nana { for(fs::directory_iterator u(i->path()); u != end; ++u) { - auto uname = i->path().filename().native(); - if ((!is_directory(*i)) || (uname.size() && uname[0] == '.')) + auto uname = u->path().filename().native(); + if ((!is_directory(*u)) || (uname.size() && uname[0] == '.')) continue; child.append(uname, uname, kind::filesystem); diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 906bd969..88468861 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -1825,7 +1825,6 @@ namespace nana item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y); impl_->attr.tree_cont.for_each(shape.first, nl); - bool has_redraw = false; auto & node_state = impl_->node_state; node_state.pressed_node = nl.node(); @@ -1834,21 +1833,17 @@ namespace nana { if(impl_->set_expanded(node_state.pressed_node, !node_state.pressed_node->value.second.expanded)) impl_->make_adjust(node_state.pressed_node, 0); - - has_redraw = true; //btw, don't select the node } - - if ((!has_redraw) && (node_state.selected != node_state.pressed_node)) + else if (node_state.selected != node_state.pressed_node) { impl_->set_selected(node_state.pressed_node); - has_redraw = true; } + else + return; - if(has_redraw) - { - impl_->draw(true); - API::dev::lazy_refresh(); - } + + impl_->draw(true); + API::dev::lazy_refresh(); } void trigger::mouse_up(graph_reference, const arg_mouse& arg) From b0a58ed62f2cfa438131c9f6a3eb6362942955e0 Mon Sep 17 00:00:00 2001 From: cnjinhao Date: Mon, 11 Sep 2017 15:54:42 +0800 Subject: [PATCH 10/43] fix issue that filebox throws exception when permission denied(#251) --- source/gui/filebox.cpp | 75 +++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index 89382828..96f1e1c6 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -569,28 +569,63 @@ namespace nana if(cat_path.size() && cat_path[cat_path.size() - 1] != '/') cat_path += '/'; + auto beg = head.size(); while(true) { auto pos = path.find('/', beg); auto folder = path.substr(beg, pos != path.npos ? pos - beg: path.npos); - if(folder.size() == 0) break; + + if(folder.empty()) + break; + (cat_path += folder) += '/'; (head += folder) += '/'; path_.caption(cat_path); - for(fs::directory_iterator i(head); i != end; ++i) + try { - if (is_directory(*i)) - path_.childset(i->path().filename().native(), 0); + for(fs::directory_iterator i(head); i != end; ++i) + { + if (is_directory(*i)) + path_.childset(i->path().filename().native(), 0); + } + } + catch(fs::filesystem_error&) + { + //The directory iterator may throw filesystem_error when + //the user doesn't have permission to access the directory. + + //It just loads the sub-directories + //to the category path. } if(pos == path.npos) break; beg = pos + 1; } - _m_load_path(path); - _m_list_fs(); + + try + { + _m_load_path(path); + _m_list_fs(); + } + catch(fs::filesystem_error&) + { + file_container_.clear(); + + drawing dw{ls_file_}; + dw.clear(); + dw.draw([](paint::graphics& graph){ + std::string text = "Permission denied to access the directory"; + auto txt_sz = graph.text_extent_size(text); + auto sz = graph.size(); + + graph.string({static_cast(sz.width - txt_sz.width) / 2, static_cast(sz.height - txt_sz.height) / 2}, text, colors::dark_gray); + }); + + ls_file_.clear(); + } } bool _m_filter_allowed(const std::string& name, bool is_dir, const std::string& filter, const std::vector* extension) const @@ -611,6 +646,8 @@ namespace nana void _m_list_fs() { + drawing{ls_file_}.clear(); + auto filter = filter_.caption(); ls_file_.auto_draw(false); @@ -829,14 +866,28 @@ namespace nana auto child = node.append(name, name, kind::filesystem); if(!child.empty()) { - for(fs::directory_iterator u(i->path()); u != end; ++u) + //The try-catch can be eleminated by using + //directory_iterator( const std::filesystem::path& p, std::error_code& ec ) noexcept; + //in C++17 + try { - auto uname = u->path().filename().native(); - if ((!is_directory(*u)) || (uname.size() && uname[0] == '.')) - continue; + for(fs::directory_iterator u(i->path()); u != end; ++u) + { + auto uname = u->path().filename().native(); + if ((!is_directory(*u)) || (uname.size() && uname[0] == '.')) + continue; - child.append(uname, uname, kind::filesystem); - break; + child.append(uname, uname, kind::filesystem); + break; + } + } + catch(fs::filesystem_error&) + { + //The directory iterator may throw filesystem_error when + //the user doesn't have permission to access the directory. + + //Catch the error without any process, because the loop is just + //to peak whether the directory(i->path) has a sub-directory. } } } From 803acb13f0a85ea9b5048c429ae21d02d64b2f5a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 12 Sep 2017 08:15:22 +0800 Subject: [PATCH 11/43] fix move-ctor and move-assignement operator of graphics(#253) --- source/paint/graphics.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index b7dd3426..c617b3ee 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -240,12 +240,16 @@ namespace paint graphics::graphics(graphics&& other) : impl_(std::move(other.impl_)) { + other.impl_.reset(new implementation); } graphics& graphics::operator=(graphics&& other) { if (this != &other) + { impl_ = std::move(other.impl_); + other.impl_.reset(new implementation); + } return *this; } From c45f621eeab9e7f739ef0afddb38f05dd45e2f1e Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 13 Sep 2017 04:58:05 +0800 Subject: [PATCH 12/43] fix crash where text_editor enables the linewrap(#254) --- source/gui/widgets/skeletons/text_editor.cpp | 21 ++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index f39638b2..5688b2be 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -556,6 +556,7 @@ namespace nana{ namespace widgets virtual void merge_lines(std::size_t first, std::size_t second) = 0; //Calculates how many lines the specified line of text takes with a specified pixels of width. virtual void add_lines(std::size_t pos, std::size_t lines) = 0; + virtual void prepare() = 0; virtual void pre_calc_line(std::size_t line, unsigned pixels) = 0; virtual void pre_calc_lines(unsigned pixels) = 0; virtual std::size_t take_lines() const = 0; @@ -668,6 +669,12 @@ namespace nana{ namespace widgets } } + void prepare() override + { + auto const line_count = editor_.textbase().lines(); + this->sections_.resize(line_count); + } + void pre_calc_line(std::size_t pos, unsigned) override { auto const & text = editor_.textbase().getline(pos); @@ -781,6 +788,12 @@ namespace nana{ namespace widgets } } + void prepare() override + { + auto const lines = editor_.textbase().lines(); + linemtr_.resize(lines); + } + void pre_calc_line(std::size_t line, unsigned pixels) override { const string_type& lnstr = editor_.textbase().getline(line); @@ -1234,7 +1247,7 @@ namespace nana{ namespace widgets void text_editor::typeface_changed() { - impl_->capacities.behavior->pre_calc_lines(width_pixels()); + _m_reset_content_size(true); } void text_editor::indent(bool enb, std::function generator) @@ -2886,10 +2899,14 @@ namespace nana{ namespace widgets auto text_lines = textbase().lines(); if (text_lines <= max_lines) { + impl_->capacities.behavior->prepare(); + + auto const width_px = _m_width_px(true); + std::size_t lines = 0; for (std::size_t i = 0; i < text_lines; ++i) { - impl_->capacities.behavior->pre_calc_line(i, csize.width); + impl_->capacities.behavior->pre_calc_line(i, width_px); lines += impl_->capacities.behavior->take_lines(i); if (lines > max_lines) From 6e9296166f395bbd0c4b49d055116551a9342a14 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 14 Sep 2017 02:21:03 +0800 Subject: [PATCH 13/43] fix bug that platform_spec_posix.cpp is missing in code::blocks project --- build/codeblocks/nana.cbp | 1 + 1 file changed, 1 insertion(+) diff --git a/build/codeblocks/nana.cbp b/build/codeblocks/nana.cbp index c598a95d..18c78755 100644 --- a/build/codeblocks/nana.cbp +++ b/build/codeblocks/nana.cbp @@ -50,6 +50,7 @@ + From 3b454cc2c52504274fe397e902bedfdc0a20baa9 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 14 Sep 2017 19:39:56 +0200 Subject: [PATCH 14/43] minor doxygen changes --- include/nana/gui/widgets/detail/tree_cont.hpp | 6 ++-- include/nana/gui/widgets/treebox.hpp | 30 +++++++++++-------- source/gui/widgets/treebox.cpp | 8 +++-- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/include/nana/gui/widgets/detail/tree_cont.hpp b/include/nana/gui/widgets/detail/tree_cont.hpp index 2490ab95..3acbc6fa 100644 --- a/include/nana/gui/widgets/detail/tree_cont.hpp +++ b/include/nana/gui/widgets/detail/tree_cont.hpp @@ -1,12 +1,12 @@ -/* +/** * A Tree Container class implementation * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at + * (See accompanying file LICENSE or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/gui/widgets/detail/tree_cont.hpp + * @file nana/gui/widgets/detail/tree_cont.hpp */ #ifndef NANA_GUI_WIDGETS_DETAIL_TREE_CONT_HPP diff --git a/include/nana/gui/widgets/treebox.hpp b/include/nana/gui/widgets/treebox.hpp index 1ddb448d..08548dd4 100644 --- a/include/nana/gui/widgets/treebox.hpp +++ b/include/nana/gui/widgets/treebox.hpp @@ -4,10 +4,10 @@ * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at + * (See accompanying file LICENSE or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/gui/widgets/treebox.hpp + * @file nana/gui/widgets/treebox.hpp * @brief * The treebox organizes the nodes by a key string. * The treebox would have a vertical scrollbar if there are too many nodes @@ -344,7 +344,7 @@ namespace nana }//end namespace drawerbase /// \brief Displays a hierarchical list of items, such as the files and directories on a disk. - /// See also in [documentation](http://nanapro.org/en-us/help/widgets/treebox.htm) + /// See also in [documentation](http://nanapro.org/en-us/documentation/widgets/treebox.htm) class treebox :public widget_object < category::widget_tag, drawerbase::treebox::trigger, drawerbase::treebox::treebox_events> { @@ -372,7 +372,7 @@ namespace nana /// \brief The construct that creates a widget. /// @param wd A handle to the parent window of the widget being created. /// @param r the size and position of the widget in its parent window coordinate. - /// @param visible specifying the visible after creating. + /// @param visible specifying if visible after creating. treebox(window, const nana::rectangle& = rectangle(), bool visible = true); template @@ -397,18 +397,18 @@ namespace nana /// /// The treebox automatically redraws after certain operations, but, /// under some circumstances, it is good to disable the automatic drawing mode, - /// for example, before adding nodes in a loop, disable the mode to avoiding + /// for example, before adding nodes in a loop, disable the mode avoiding /// frequent and useless refresh for better performance, and then, after /// the operations, enable the automatic redraw mode again. - /// @param bool whether to enable. - void auto_draw(bool); + /// @param enable bool whether to enable. + void auto_draw(bool enable); /// \brief Enable the checkboxs for each item of the widget. - /// @param bool indicates whether to show or hide the checkboxs. + /// @param enable bool indicates whether to show or hide the checkboxs. treebox & checkable(bool enable); - bool checkable() const; ///< Determinte whether the checkboxs are enabled. + bool checkable() const; ///< Are the checkboxs are enabled? /// Clears the contents void clear(); @@ -424,26 +424,30 @@ namespace nana void icon_erase(const ::std::string& id); - item_proxy find(const ::std::string& keypath); ///< Find an item though a specified keypath. + item_proxy find(const ::std::string& keypath); ///< Find an item through a specified keypath. - /// Inserts a new node to treebox, but if the keypath exists returns the existing node. + /// Inserts a new node to treebox, but if the keypath exists change and returns the existing node. item_proxy insert(const ::std::string& path_key, ///< specifies the node hierarchy ::std::string title ///< used for displaying ); - /// Inserts a new node to treebox, but if the keypath exists returns the existing node. + /// Inserts a new node to treebox, but if the keypath exists change and returns the existing node. item_proxy insert( item_proxy pos, ///< the parent item node const ::std::string& key, ///< specifies the new node ::std::string title ///< title used for displaying in the new node. ); - item_proxy erase(item_proxy i); ///< Removes the node at pos and return the Item proxy following the removed node + + item_proxy erase(item_proxy i); ///< Removes the node at i and return the Item proxy following the removed node void erase(const ::std::string& keypath); ///< Removes the node by the key path. ::std::string make_key_path(item_proxy i, const ::std::string& splitter) const;/// #endif diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 88468861..17696e53 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -1,13 +1,15 @@ -/* +/** * A Treebox Implementation * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at + * (See accompanying file LICENSE or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/gui/widgets/treebox.cpp + * @file nana/gui/widgets/treebox.cpp + * @brief + * */ #include #include From dbc9bc55ff5bd055f2f01c80d119e35a7a981f41 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 18 Sep 2017 23:36:40 +0800 Subject: [PATCH 15/43] fix bug that fast clicking a spinbox doesn't change the value(#257) --- include/nana/gui/widgets/spinbox.hpp | 1 + source/gui/widgets/spinbox.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp index 2ecabc78..15cbc694 100644 --- a/include/nana/gui/widgets/spinbox.hpp +++ b/include/nana/gui/widgets/spinbox.hpp @@ -61,6 +61,7 @@ namespace nana void focus(graph_reference, const arg_focus&) override; void mouse_wheel(graph_reference, const arg_wheel&) override; + void dbl_click(graph_reference, const arg_mouse&) override; void mouse_down(graph_reference, const arg_mouse&) override; void mouse_move(graph_reference, const arg_mouse&) override; void mouse_up(graph_reference, const arg_mouse& arg) override; diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 2fad022f..89423eab 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -560,6 +560,12 @@ namespace nana impl_->editor()->reset_caret(); API::dev::lazy_refresh(); } + + void drawer::dbl_click(graph_reference, const arg_mouse& arg) + { + if (impl_->mouse_button(arg, true)) + API::dev::lazy_refresh(); + } void drawer::mouse_down(graph_reference, const arg_mouse& arg) { From c1654f75eca2ea61fa18f86fc8c49d58ee5eb539 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 18 Sep 2017 23:46:02 +0800 Subject: [PATCH 16/43] fix issue that typing text for spinbox doesn't draw spin buttons border --- source/gui/widgets/spinbox.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 89423eab..41b592f3 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -605,7 +605,10 @@ namespace nana { impl_->editor()->respond_char(arg); if (impl_->editor()->try_refresh()) + { + impl_->draw_spins(); API::dev::lazy_refresh(); + } } void drawer::resized(graph_reference, const arg_resized&) From bb47cdc6c9711c366f2fc5bd7e369ad2eab9f2fc Mon Sep 17 00:00:00 2001 From: cnjinhao Date: Fri, 22 Sep 2017 15:47:12 +0800 Subject: [PATCH 17/43] fix bug that DEL key is incorrect in key_press/key_release(#259) --- include/nana/gui/basis.hpp | 6 ++++-- source/gui/detail/bedrock_posix.cpp | 4 ++-- source/gui/detail/bedrock_windows.cpp | 17 +++++++++++++++-- source/gui/widgets/skeletons/text_editor.cpp | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index a13b3bac..69b97c1f 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -91,6 +91,8 @@ namespace nana substitute = 0x1A, //Ctrl+Z escape = 0x1B, space = 0x20, //Space + del = 0x7F, //Delete + os_del = del, //Deprecated //The following names are intuitive name of ASCII control codes select_all = start_of_headline, @@ -106,8 +108,8 @@ namespace nana os_ctrl = 0x11, os_pageup = 0x21, os_pagedown, os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down, - os_insert = 0x2D, os_del , - os_end = 0x23 , os_home //Pos 1 + os_insert = 0x2D, + os_end = 0x23, os_home //Pos 1 }; }; diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 9b0e24e0..4e7c8a07 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -438,8 +438,8 @@ namespace detail keysym = keyboard::os_arrow_left + (keysym - XK_Left); break; case XK_Insert: keysym = keyboard::os_insert; break; - case XK_Delete: - keysym = keyboard::os_del; break; + case XK_Delete: case XK_KP_Delete: + keysym = keyboard::del; break; case XK_Shift_L: case XK_Shift_R: //shift keysym = keyboard::os_shift; break; case XK_Control_L: case XK_Control_R: //ctrl diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index ebf32705..67f40ffe 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -775,6 +775,19 @@ namespace detail if (thrd) thrd->event_window = prev_event_wd; } + //Translate OS Virtual-Key into ASCII code + wchar_t translate_virtual_key(WPARAM vkey) + { + switch (vkey) + { + case VK_DELETE: + return 127; + case VK_DECIMAL: + return 46; + } + return static_cast(vkey); + } + LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT window_proc_value = 0; @@ -1436,7 +1449,7 @@ namespace detail arg.evt_code = event_code::key_press; arg.window_handle = reinterpret_cast(msgwnd); arg.ignore = false; - arg.key = static_cast(wParam); + arg.key = translate_virtual_key(wParam); brock.get_key_state(arg); brock.emit(event_code::key_press, msgwnd, arg, true, &context); @@ -1522,7 +1535,7 @@ namespace detail arg_keyboard arg; arg.evt_code = event_code::key_release; arg.window_handle = reinterpret_cast(msgwnd); - arg.key = static_cast(wParam); + arg.key = translate_virtual_key(wParam); brock.get_key_state(arg); arg.ignore = false; brock.emit(event_code::key_release, msgwnd, arg, true, &context); diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 5688b2be..72cec7ee 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1233,7 +1233,7 @@ namespace nana{ namespace widgets case keyboard::os_pagedown: _m_handle_move_key(arg); break; - case keyboard::os_del: + case keyboard::del: // send delete to set_accept function if (this->attr().editable && (!impl_->capacities.pred_acceptive || impl_->capacities.pred_acceptive(key))) del(); From eec7344c6d11616b2198d8889e1e9ad29d7cb93a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 23 Sep 2017 07:25:16 +0800 Subject: [PATCH 18/43] fix issue that typing text for spinbox doesn't draw spin buttons border --- source/gui/widgets/skeletons/text_editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 72cec7ee..fefaf1ed 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1689,7 +1689,7 @@ namespace nana{ namespace widgets impl_->try_refresh = sync_graph::refresh; //_m_put calcs the lines - _m_reset_content_size(false); + _m_reset_content_size(true); impl_->cview->sync(false); } } From 13761be5e9d83a8a49158efc1bb151e8d810b570 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 23 Sep 2017 07:33:31 +0800 Subject: [PATCH 19/43] fix crash where a menubar popups a menu and exits by shortcut(#261) --- source/gui/widgets/menubar.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/gui/widgets/menubar.cpp b/source/gui/widgets/menubar.cpp index a83c3d86..5071c094 100644 --- a/source/gui/widgets/menubar.cpp +++ b/source/gui/widgets/menubar.cpp @@ -403,8 +403,15 @@ namespace nana ess_->state.nullify_mouse = true; auto & menu_ptr = ess_->state.menu; + + //menu_wd will be assigned with the handle of a menu window, + //It is used for checking whether the menu is closed. A menu handler + //may close the form, checking with the data member of this trigger + //is invalid, because the form is closed, the object of menubar may not exist. + window menu_wd = nullptr; if(ess_->state.menu) { + menu_wd = menu_ptr->handle(); switch(arg.key) { case keyboard::os_arrow_down: @@ -466,8 +473,11 @@ namespace nana case keyboard::os_arrow_up: case keyboard::os_arrow_down: case keyboard::enter: - if(ess_->open_menu(true)) + if (ess_->open_menu(true)) + { + menu_wd = menu_ptr->handle(); menu_ptr->goto_next(true); + } break; case keyboard::escape: if(essence::behavior::focus == ess_->state.behave) @@ -481,15 +491,21 @@ namespace nana if(index != npos) { ess_->state.active = index; - if(ess_->open_menu(true)) + if (ess_->open_menu(true)) + { + menu_wd = menu_ptr->handle(); menu_ptr->goto_next(true); + } } break; } } - refresh(graph); - API::dev::lazy_refresh(); + if (API::is_window(menu_wd)) + { + refresh(graph); + API::dev::lazy_refresh(); + } } void trigger::key_release(graph_reference graph, const arg_keyboard& arg) From dcb472cb062b88102953082f15c626596eebcd63 Mon Sep 17 00:00:00 2001 From: Mexsut Date: Mon, 25 Sep 2017 15:20:38 +0800 Subject: [PATCH 20/43] add a native wstring version textbox::append added a textbox::append which accepts texts in std::wstring --- include/nana/gui/widgets/textbox.hpp | 2 +- source/gui/widgets/textbox.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp index d0ac2f67..5f6dbc91 100644 --- a/include/nana/gui/widgets/textbox.hpp +++ b/include/nana/gui/widgets/textbox.hpp @@ -185,7 +185,7 @@ namespace nana /// Appends an string. If `at_caret` is `true`, the string is inserted at the position of caret, otherwise, it is appended at end of the textbox. textbox& append(const std::string& text, bool at_caret); - + textbox& append(const std::wstring& text, bool at_caret); /// Determines whether the text is line wrapped. bool line_wrapped() const; textbox& line_wrapped(bool); diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index e29b0d88..de6e2dd9 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -435,7 +435,23 @@ namespace drawerbase { } return *this; } + //a native wstring version textbox::append + textbox& textbox::append(const std::wstring& text, bool at_caret) + { + internal_scope_guard lock; + auto editor = get_drawer_trigger().editor(); + if(editor) + { + if(at_caret == false) + editor->move_caret_end(false); + editor->put(text); + + editor->try_refresh(); + API::update_window(this->handle()); + } + return *this; + } /// Determine wheter the text is auto-line changed. bool textbox::line_wrapped() const { From 8d9351e0519ca32bff2931cbcc1e4c7026b9799c Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 27 Sep 2017 08:13:55 +0800 Subject: [PATCH 21/43] graphics::make throws std::bad_alloc when it fails --- source/paint/graphics.cpp | 86 +++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index c617b3ee..6ced8b96 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -293,7 +293,7 @@ namespace paint void graphics::make(const ::nana::size& sz) { - if(impl_->handle == nullptr || impl_->size != sz) + if (impl_->handle == nullptr || impl_->size != sz) { if (sz.empty()) { @@ -302,9 +302,10 @@ namespace paint } //The object will be delete while dwptr_ is performing a release. - drawable_type dw = new nana::detail::drawable_impl_type; + std::shared_ptr dw{ new nana::detail::drawable_impl_type, detail::drawable_deleter{} }; + //Reuse the old font - if(impl_->platform_drawable) + if (impl_->platform_drawable) { drawable_type reuse = impl_->platform_drawable.get(); dw->font = reuse->font; @@ -314,8 +315,13 @@ namespace paint dw->font = impl_->font_shadow.impl_->real_font; #if defined(NANA_WINDOWS) - HDC hdc = ::GetDC(0); + HDC hdc = ::GetDC(nullptr); HDC cdc = ::CreateCompatibleDC(hdc); + if (nullptr == cdc) + { + ::ReleaseDC(nullptr, hdc); + throw std::bad_alloc{}; + } BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); @@ -328,34 +334,60 @@ namespace paint HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast(&(dw->pixbuf_ptr)), 0, 0); - if(bmp) - { - ::DeleteObject((HBITMAP)::SelectObject(cdc, bmp)); - ::DeleteObject(::SelectObject(cdc, dw->font->native_handle())); - - dw->context = cdc; - dw->pixmap = bmp; - ::SetBkMode(cdc, TRANSPARENT); - } - else + if (nullptr == bmp) { ::DeleteDC(cdc); - delete dw; - dw = nullptr; - release(); + ::ReleaseDC(nullptr, hdc); + throw std::bad_alloc{}; } + ::DeleteObject((HBITMAP)::SelectObject(cdc, bmp)); + ::DeleteObject(::SelectObject(cdc, dw->font->native_handle())); + + dw->context = cdc; + dw->pixmap = bmp; + ::SetBkMode(cdc, TRANSPARENT); + ::ReleaseDC(0, hdc); #elif defined(NANA_X11) auto & spec = nana::detail::platform_spec::instance(); - Display* disp = spec.open_display(); - int screen = DefaultScreen(disp); - Window root = ::XRootWindow(disp, screen); - dw->pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen)); - dw->context = ::XCreateGC(disp, dw->pixmap, 0, 0); - #if defined(NANA_USE_XFT) - dw->xftdraw = ::XftDrawCreate(disp, dw->pixmap, spec.screen_visual(), spec.colormap()); - #endif + { + nana::detail::platform_scope_guard psg; + + spec.set_error_handler(); + + Display* disp = spec.open_display(); + int screen = DefaultScreen(disp); + Window root = ::XRootWindow(disp, screen); + auto pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen)); + if(spec.error_code) + { + spec.rev_error_handler(); + throw std::bad_alloc(); + } + auto context = ::XCreateGC(disp, pixmap, 0, 0); + if (spec.error_code) + { + ::XFreePixmap(disp, pixmap); + spec.rev_error_handler(); + throw std::bad_alloc(); + } +# if defined(NANA_USE_XFT) + auto xftdraw = ::XftDrawCreate(disp, pixmap, spec.screen_visual(), spec.colormap()); + if (spec.error_code) + { + ::XFreeGC(disp, context); + ::XFreePixmap(disp, pixmap); + + spec.rev_error_handler(); + throw std::bad_alloc(); + } + + dw->xftdraw = xftdraw; +# endif + dw->pixmap = pixmap; + dw->context = context; + } #endif if(dw) { @@ -366,8 +398,8 @@ namespace paint #else dw->update_text_color(); #endif - impl_->platform_drawable.reset(dw, detail::drawable_deleter{}); - impl_->handle = dw; + impl_->platform_drawable = dw; + impl_->handle = dw.get(); impl_->size = sz; impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; From d715c87d933649cf25d38cab02dc0b24e9a265a5 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 28 Sep 2017 08:29:19 +0800 Subject: [PATCH 22/43] correct the process of failure of resizing a window --- .../gui/detail/native_window_interface.hpp | 6 +- include/nana/paint/graphics.hpp | 2 + source/detail/mswin/platform_spec.hpp | 11 -- source/gui/detail/bedrock_posix.cpp | 21 ++- source/gui/detail/bedrock_windows.cpp | 45 +------ source/gui/detail/native_window_interface.cpp | 126 ++++++++---------- source/gui/detail/window_manager.cpp | 29 +++- source/paint/graphics.cpp | 6 + 8 files changed, 115 insertions(+), 131 deletions(-) diff --git a/include/nana/gui/detail/native_window_interface.hpp b/include/nana/gui/detail/native_window_interface.hpp index c80d51f1..25b2fc7f 100644 --- a/include/nana/gui/detail/native_window_interface.hpp +++ b/include/nana/gui/detail/native_window_interface.hpp @@ -1,7 +1,7 @@ /* * Platform Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -66,11 +66,11 @@ namespace detail static nana::point window_position(native_window_type); static void move_window(native_window_type, int x, int y); - static void move_window(native_window_type, const rectangle&); + static bool move_window(native_window_type, const rectangle&); static void bring_top(native_window_type, bool activated); static void set_window_z_order(native_window_type, native_window_type wd_after, z_order_action action_if_no_wd_after); - static void window_size(native_window_type, const size&); + static bool window_size(native_window_type, const size&); static void get_window_rect(native_window_type, rectangle&); static void window_caption(native_window_type, const native_string_type&); static native_string_type window_caption(native_window_type); diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index 8843a03f..7d6d6df8 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -91,6 +91,8 @@ namespace nana const void* pixmap() const; const void* context() const; + void swap(graphics& other); + /// Creates a graphics/drawable resource /** * @param sz The dimension of the graphics to be requested. If sz is empty, it performs as release(). diff --git a/source/detail/mswin/platform_spec.hpp b/source/detail/mswin/platform_spec.hpp index 30bc8b84..5eb6df45 100644 --- a/source/detail/mswin/platform_spec.hpp +++ b/source/detail/mswin/platform_spec.hpp @@ -47,16 +47,6 @@ namespace detail bool visible; }; - struct move_window - { - enum { Pos = 1, Size = 2}; - int x; - int y; - unsigned width; - unsigned height; - unsigned ignore; //determinate that pos or size would be ignored. - }; - struct map_thread { rectangle update_area; @@ -77,7 +67,6 @@ namespace detail async_set_focus, remote_flush_surface, remote_thread_destroy_window, - remote_thread_move_window, operate_caret, //wParam: 1=Destroy, 2=SetPos remote_thread_set_window_pos, remote_thread_set_window_text, diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 4e7c8a07..94dd0562 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -250,17 +250,24 @@ namespace detail _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); - //A child of wd may not be drawn if it was out of wd's range before wd resized, - //so refresh all children of wd when a resized occurs. - if(ask_update || (event_code::resized == evt_code)) + bool good_wd = false; + if(wd_manager().available(wd)) { - wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code)); + //A child of wd may not be drawn if it was out of wd's range before wd resized, + //so refresh all children of wd when a resized occurs. + if(ask_update || (event_code::resized == evt_code) || (update_state::refreshed == wd->other.upd_state)) + { + wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code)); + } + else + wd->other.upd_state = update_state::none; + + good_wd = true; } - else if(wd_manager().available(wd)) - wd->other.upd_state = core_window_t::update_state::none; + if(thrd) thrd->event_window = prev_wd; - return true; + return good_wd; } void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt) diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 67f40ffe..2d75e7d4 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -601,40 +601,6 @@ namespace detail ::HeapFree(::GetProcessHeap(), 0, stru); } return true; - case nana::detail::messages::remote_thread_move_window: - { - auto * mw = reinterpret_cast(wParam); - - ::RECT r; - ::GetWindowRect(wd, &r); - if(mw->ignore & mw->Pos) - { - mw->x = r.left; - mw->y = r.top; - } - else - { - HWND owner = ::GetWindow(wd, GW_OWNER); - if(owner) - { - ::RECT owr; - ::GetWindowRect(owner, &owr); - ::POINT pos = {owr.left, owr.top}; - ::ScreenToClient(owner, &pos); - mw->x += (owr.left - pos.x); - mw->y += (owr.top - pos.y); - } - } - - if(mw->ignore & mw->Size) - { - mw->width = r.right - r.left; - mw->height = r.bottom - r.top; - } - ::MoveWindow(wd, mw->x, mw->y, mw->width, mw->height, true); - delete mw; - } - return true; case nana::detail::messages::remote_thread_set_window_pos: ::SetWindowPos(wd, reinterpret_cast(wParam), 0, 0, 0, 0, static_cast(lParam)); return true; @@ -1652,18 +1618,21 @@ namespace detail _m_event_filter(evt_code, wd, thrd); } - if (wd->other.upd_state == core_window_t::update_state::none) - wd->other.upd_state = core_window_t::update_state::lazy; + using update_state = basic_window::update_state; + + if (update_state::none == wd->other.upd_state) + wd->other.upd_state = update_state::lazy; _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); bool good_wd = false; if (wd_manager().available(wd)) { - if (ask_update) + //Ignore ask_update if update state is refreshed. + if (ask_update || (update_state::refreshed == wd->other.upd_state)) wd_manager().do_lazy_refresh(wd, false); else - wd->other.upd_state = basic_window::update_state::none; + wd->other.upd_state = update_state::none; good_wd = true; } diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index 821296c1..a054dba7 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -863,30 +863,27 @@ namespace nana{ void native_interface::move_window(native_window_type wd, int x, int y) { #if defined(NANA_WINDOWS) - if(::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + ::RECT r; + ::GetWindowRect(reinterpret_cast(wd), &r); + HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); + if(owner) { - nana::detail::messages::move_window * mw = new nana::detail::messages::move_window; - mw->x = x; - mw->y = y; - mw->ignore = mw->Size; - ::PostMessage(reinterpret_cast(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast(mw), 0); + ::RECT owner_rect; + ::GetWindowRect(owner, &owner_rect); + ::POINT pos = {owner_rect.left, owner_rect.top}; + ::ScreenToClient(owner, &pos); + x += (owner_rect.left - pos.x); + y += (owner_rect.top - pos.y); } - else + + + if (::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) { - ::RECT r; - ::GetWindowRect(reinterpret_cast(wd), &r); - HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); - if(owner) - { - ::RECT owner_rect; - ::GetWindowRect(owner, &owner_rect); - ::POINT pos = {owner_rect.left, owner_rect.top}; - ::ScreenToClient(owner, &pos); - x += (owner_rect.left - pos.x); - y += (owner_rect.top - pos.y); - } + nana::internal_revert_guard irg; ::MoveWindow(reinterpret_cast(wd), x, y, r.right - r.left, r.bottom - r.top, true); } + else + ::MoveWindow(reinterpret_cast(wd), x, y, r.right - r.left, r.bottom - r.top, true); #elif defined(NANA_X11) Display * disp = restrict::spec.open_display(); @@ -908,41 +905,36 @@ namespace nana{ #endif } - void native_interface::move_window(native_window_type wd, const rectangle& r) + bool native_interface::move_window(native_window_type wd, const rectangle& r) { #if defined(NANA_WINDOWS) - if(::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + + int x = r.x; + int y = r.y; + HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); + if(owner) { - auto * mw = new nana::detail::messages::move_window; - mw->x = r.x; - mw->y = r.y; - mw->width = r.width; - mw->height = r.height; - mw->ignore = 0; - ::PostMessage(reinterpret_cast(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast(mw), 0); + ::RECT owner_rect; + ::GetWindowRect(owner, &owner_rect); + ::POINT pos = {owner_rect.left, owner_rect.top}; + ::ScreenToClient(owner, &pos); + x += (owner_rect.left - pos.x); + y += (owner_rect.top - pos.y); } - else - { - int x = r.x; - int y = r.y; - HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); - if(owner) - { - ::RECT owner_rect; - ::GetWindowRect(owner, &owner_rect); - ::POINT pos = {owner_rect.left, owner_rect.top}; - ::ScreenToClient(owner, &pos); - x += (owner_rect.left - pos.x); - y += (owner_rect.top - pos.y); - } - RECT client, wd_area; - ::GetClientRect(reinterpret_cast(wd), &client); - ::GetWindowRect(reinterpret_cast(wd), &wd_area); - unsigned ext_w = (wd_area.right - wd_area.left) - client.right; - unsigned ext_h = (wd_area.bottom - wd_area.top) - client.bottom; - ::MoveWindow(reinterpret_cast(wd), x, y, r.width + ext_w, r.height + ext_h, true); + RECT client, wd_area; + ::GetClientRect(reinterpret_cast(wd), &client); + ::GetWindowRect(reinterpret_cast(wd), &wd_area); + unsigned ext_w = (wd_area.right - wd_area.left) - client.right; + unsigned ext_h = (wd_area.bottom - wd_area.top) - client.bottom; + + if (::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + { + nana::internal_revert_guard irg; + return (FALSE != ::MoveWindow(reinterpret_cast(wd), x, y, r.width + ext_w, r.height + ext_h, true)); } + + return (FALSE != ::MoveWindow(reinterpret_cast(wd), x, y, r.width + ext_w, r.height + ext_h, true)); #elif defined(NANA_X11) Display * disp = restrict::spec.open_display(); long supplied; @@ -984,6 +976,7 @@ namespace nana{ ::XSetWMNormalHints(disp, reinterpret_cast(wd), &hints); ::XMoveResizeWindow(disp, reinterpret_cast(wd), x, y, r.width, r.height); + return true; #endif } @@ -1062,32 +1055,28 @@ namespace nana{ #endif } - void native_interface::window_size(native_window_type wd, const size& sz) + bool native_interface::window_size(native_window_type wd, const size& sz) { #if defined(NANA_WINDOWS) - if(::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + ::RECT r; + ::GetWindowRect(reinterpret_cast(wd), &r); + HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); + HWND parent = ::GetParent(reinterpret_cast(wd)); + if(parent && (parent != owner)) { - auto * mw = new nana::detail::messages::move_window; - mw->width = sz.width; - mw->height = sz.height; - mw->ignore = mw->Pos; - ::PostMessage(reinterpret_cast(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast(mw), 0); + ::POINT pos = {r.left, r.top}; + ::ScreenToClient(parent, &pos); + r.left = pos.x; + r.top = pos.y; } - else + + if (::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) { - ::RECT r; - ::GetWindowRect(reinterpret_cast(wd), &r); - HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); - HWND parent = ::GetParent(reinterpret_cast(wd)); - if(parent && (parent != owner)) - { - ::POINT pos = {r.left, r.top}; - ::ScreenToClient(parent, &pos); - r.left = pos.x; - r.top = pos.y; - } - ::MoveWindow(reinterpret_cast(wd), r.left, r.top, static_cast(sz.width), static_cast(sz.height), true); + nana::internal_revert_guard irg; + return (FALSE != ::MoveWindow(reinterpret_cast(wd), r.left, r.top, static_cast(sz.width), static_cast(sz.height), true)); } + + return (FALSE != ::MoveWindow(reinterpret_cast(wd), r.left, r.top, static_cast(sz.width), static_cast(sz.height), true)); #elif defined(NANA_X11) auto disp = restrict::spec.open_display(); nana::detail::platform_scope_guard psg; @@ -1104,6 +1093,7 @@ namespace nana{ ::XSetWMNormalHints(disp, reinterpret_cast(wd), &hints); } ::XResizeWindow(disp, reinterpret_cast(wd), sz.width, sz.height); + return true; #endif } diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 701eb530..e948aeec 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -953,24 +953,45 @@ namespace detail if (wd->dimension == sz) return false; + //Before resiz the window, creates the new graphics + paint::graphics graph; + paint::graphics root_graph; + if (category::flags::lite_widget != wd->other.category) + { + //If allocation fails, here throws std::bad_alloc. + graph.make(sz); + if (category::flags::root == wd->other.category) + root_graph.make(sz); + } + + auto pre_sz = wd->dimension; + wd->dimension = sz; if(category::flags::lite_widget != wd->other.category) { bool graph_state = wd->drawer.graphics.empty(); - wd->drawer.graphics.make(sz); + wd->drawer.graphics.swap(graph); //It shall make a typeface_changed() call when the graphics state is changing. - //Because when a widget is created with zero-size, it may get some wrong result in typeface_changed() call + //Because when a widget is created with zero-size, it may get some wrong results in typeface_changed() call //due to the invaliable graphics object. if(graph_state != wd->drawer.graphics.empty()) wd->drawer.typeface_changed(); if(category::flags::root == wd->other.category) { - wd->root_graph->make(sz); + //wd->root_graph->make(sz); + wd->root_graph->swap(root_graph); if(false == passive) - native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height)); + if (!native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height))) + { + wd->dimension = pre_sz; + wd->drawer.graphics.swap(graph); + wd->root_graph->swap(root_graph); + wd->drawer.typeface_changed(); + return false; + } } #ifndef WIDGET_FRAME_DEPRECATED else if(category::flags::frame == wd->other.category) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 6ced8b96..a048423c 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -291,6 +291,12 @@ namespace paint return (impl_->handle ? impl_->handle->context : nullptr); } + void graphics::swap(graphics& other) + { + if (context() != other.context()) + impl_.swap(other.impl_); + } + void graphics::make(const ::nana::size& sz) { if (impl_->handle == nullptr || impl_->size != sz) From a3cd37b9d5a4cbc4901bd06db4c542c5ce4e3938 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 28 Sep 2017 08:42:11 +0800 Subject: [PATCH 23/43] fix a GCC compiler error --- source/gui/detail/bedrock_posix.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 94dd0562..5f4fa1fa 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -245,8 +245,10 @@ namespace detail _m_event_filter(evt_code, wd, thrd); } - if(wd->other.upd_state == core_window_t::update_state::none) - wd->other.upd_state = core_window_t::update_state::lazy; + using update_state = basic_window::update_state; + + if(wd->other.upd_state == update_state::none) + wd->other.upd_state = update_state::lazy; _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); From d86a8cfad251218fa98fbd50ef0a040440e3b113 Mon Sep 17 00:00:00 2001 From: Ac Date: Fri, 29 Sep 2017 11:06:22 +0900 Subject: [PATCH 24/43] use std::thread if gcc is compiled with c++11 threading support NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ option must still be enabled but mingw.thread.h and mingw.mutex.h will be ignored if _GLIBCXX_HAS_GTHREADS is defined --- include/nana/std_mutex.hpp | 4 ++++ include/nana/std_thread.hpp | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/nana/std_mutex.hpp b/include/nana/std_mutex.hpp index 38c07aaf..55f486e4 100644 --- a/include/nana/std_mutex.hpp +++ b/include/nana/std_mutex.hpp @@ -14,8 +14,12 @@ #include // http://lxr.free-electrons.com/source/include/uapi/asm-generic/errno.h#L53 //#define EPROTO 71 /* Protocol error */ +#ifdef _GLIBCXX_HAS_GTHREADS +# include +#else #include #include +#endif #else #include #include diff --git a/include/nana/std_thread.hpp b/include/nana/std_thread.hpp index e1df7ef7..87db1e5a 100644 --- a/include/nana/std_thread.hpp +++ b/include/nana/std_thread.hpp @@ -6,7 +6,11 @@ #if defined(NANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) -#include +#ifdef _GLIBCXX_HAS_GTHREADS +# include +#else +# include +#endif #else #include namespace std From 28e9bb8a7d04ec173168a50553348c4e08cd4b6f Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 30 Sep 2017 07:19:15 +0800 Subject: [PATCH 25/43] fix some legacy issues --- include/nana/paint/graphics.hpp | 4 ++-- source/paint/graphics.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index 7d6d6df8..9ce35704 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -85,13 +85,13 @@ namespace nana bool changed() const; ///< Returns true if the graphics object is operated bool empty() const; ///< Returns true if the graphics object does not refer to any resource. - operator const void*() const; + explicit operator bool() const noexcept; drawable_type handle() const; const void* pixmap() const; const void* context() const; - void swap(graphics& other); + void swap(graphics& other) noexcept; /// Creates a graphics/drawable resource /** diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index a048423c..00cb26de 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -269,7 +269,7 @@ namespace paint return (!impl_->handle); } - graphics::operator const void *() const + graphics::operator bool() const { return impl_->handle; } From b730f368a4edf83a3da6b32c3c5bb60476b8d81b Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 30 Sep 2017 07:29:27 +0800 Subject: [PATCH 26/43] fix syntax errors --- source/paint/graphics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 00cb26de..f31f3afd 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -269,7 +269,7 @@ namespace paint return (!impl_->handle); } - graphics::operator bool() const + graphics::operator bool() const noexcept { return impl_->handle; } @@ -291,7 +291,7 @@ namespace paint return (impl_->handle ? impl_->handle->context : nullptr); } - void graphics::swap(graphics& other) + void graphics::swap(graphics& other) noexcept { if (context() != other.context()) impl_.swap(other.impl_); From b486823177d201b3de97cbc3e167809336724811 Mon Sep 17 00:00:00 2001 From: Ac Date: Thu, 5 Oct 2017 09:59:32 +0900 Subject: [PATCH 27/43] add cmake option for dynamic linking --- CMakeLists.txt | 153 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 112 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f89337e..1a43b5b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,11 @@ # CMake configuration for Nana # Author: Andrew Kornilov(https://github.com/ierofant) # Contributors: -# Jinhao +# Jinhao # Robert Hauck - Enable support for PNG/Freetype # Qiangqiang Wu - Add biicode support -# Ariel Vina-Rodriguez (qPCR4vir) +# Ariel Vina-Rodriguez (qPCR4vir) +# Frostbane - Add option for compiling a shared library # # Nana uses some build systems: MS-VS solution, MAKE, bakefile, codeblock, etc. manually optimized. # In the future CMake could be the prefered, and maybe will be used to generate the others and the central nana repo @@ -30,6 +31,7 @@ option(NANA_CMAKE_LIBPNG_FROM_OS "Use libpng from operating system." ON) option(NANA_CMAKE_ENABLE_JPEG "Enable the use of JPEG" OFF) option(NANA_CMAKE_LIBJPEG_FROM_OS "Use libjpeg from operating system." ON) option(NANA_CMAKE_ENABLE_AUDIO "Enable class audio::play for PCM playback." OFF) +option(NANA_CMAKE_SHARED_LIB "Compile nana as a shared library." OFF) option(NANA_CMAKE_VERBOSE_PREPROCESSOR "Show annoying debug messages during compilation." ON) option(NANA_CMAKE_STOP_VERBOSE_PREPROCESSOR "Stop compilation after showing the annoying debug messages." OFF) option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF) @@ -45,7 +47,7 @@ option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF) # By default Nana will try to use the STD. If STD is not available and NANA_CMAKE_FIND_BOOST_FILESYSTEM # is set to ON nana will try to use boost if available. Nana own implementation will be use if none of # the previus were selected or available. -# You can change that default if you change one of the following +# You can change that default if you change one of the following # (please don't define more than one of the _XX_FORCE options): option(NANA_CMAKE_FIND_BOOST_FILESYSTEM "Search: Is Boost filesystem available?" OFF) option(NANA_CMAKE_NANA_FILESYSTEM_FORCE "Force nana filesystem over ISO and boost?" OFF) @@ -96,8 +98,24 @@ if(WIN32) add_definitions(-DNANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) endif(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ) endif(MINGW) + + if (MSVC) + set (DLLTOOL OFF) + else () + # mingw: If dlltool is found the def and lib file will be created + message (STATUS "Detecting dlltool") + find_program (DLLTOOL dlltool) + if (DLLTOOL) + message (STATUS "Found dlltool: ${DLLTOOL}") + else () + message (WARNING "dlltool not found. Skipping import library generation.") + endif (DLLTOOL) + endif (MSVC) + endif(WIN32) + + if(APPLE) add_definitions(-DAPPLE) include_directories(/opt/X11/include/) @@ -105,7 +123,7 @@ if(APPLE) set(ENABLE_AUDIO OFF) elseif(UNIX) add_definitions(-Dlinux) - message("added -D linux") + message("added -D linux") endif(APPLE) if(UNIX) @@ -129,27 +147,34 @@ endif(UNIX) if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # Clang || GNU if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14 -Wall -g") # Clang - + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14 -Wall -g") # Clang + else ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -g") # GNU - + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -g") # GNU + endif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # enable static linkage # GNU || CLang not MinGW if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW - # set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread") - list(APPEND NANA_LINKS -static-libgcc -static-libstdc++ -pthread) - # message("Setting NANA_LINKS to -static-libgcc -static-libstdc++ -pthread or ${NANA_LINKS}") + + if(NANA_CMAKE_SHARED_LIB) + list(APPEND NANA_LINKS -lgcc -lstdc++ -pthread) + else() + set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread") + # message("Setting NANA_LINKS to -static-libgcc -static-libstdc++ -pthread or ${NANA_LINKS}") + endif(NANA_CMAKE_SHARED_LIB) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3) - # IS_GNUCXX < 5.3 + # IS_GNUCXX < 5.3 else(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3) - # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++fs") # IS_GNUCXX 5.3 or more - list(APPEND NANA_LINKS -lstdc++fs) + + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++fs") # IS_GNUCXX 5.3 or more + list(APPEND NANA_LINKS -lstdc++fs) + endif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3) - + endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW @@ -163,14 +188,16 @@ endif () # Find PNG if(NANA_CMAKE_ENABLE_PNG) - add_definitions(-DNANA_ENABLE_PNG) if(NANA_CMAKE_LIBPNG_FROM_OS) find_package(PNG) if (PNG_FOUND) include_directories( ${PNG_INCLUDE_DIRS}) list(APPEND NANA_LINKS ${PNG_LIBRARIES}) - add_definitions(-DUSE_LIBPNG_FROM_OS) + add_definitions("-DNANA_ENABLE_PNG" + "-DUSE_LIBPNG_FROM_OS") endif(PNG_FOUND) + else() + add_definitions(-DNANA_ENABLE_PNG) endif(NANA_CMAKE_LIBPNG_FROM_OS) endif(NANA_CMAKE_ENABLE_PNG) @@ -182,8 +209,11 @@ if(NANA_CMAKE_ENABLE_JPEG) if (JPEG_FOUND) include_directories( ${JPEG_INCLUDE_DIR}) list(APPEND NANA_LINKS ${JPEG_LIBRARY}) - add_definitions(-DUSE_LIBJPEG_FROM_OS) + add_definitions("-DNANA_ENABLE_JPEG" + "-DUSE_LIBJPEG_FROM_OS") endif(JPEG_FOUND) + else() + add_definitions(-DNANA_ENABLE_JPEG) endif(NANA_CMAKE_LIBJPEG_FROM_OS) endif(NANA_CMAKE_ENABLE_JPEG) @@ -232,8 +262,8 @@ if(NANA_CMAKE_VERBOSE_PREPROCESSOR) add_definitions(-DVERBOSE_PREPROCESSOR) endif(NANA_CMAKE_VERBOSE_PREPROCESSOR) if(NANA_CMAKE_AUTOMATIC_GUI_TESTING) - add_definitions(-DNANA_AUTOMATIC_GUI_TESTING) - enable_testing () + add_definitions(-DNANA_AUTOMATIC_GUI_TESTING) + enable_testing () endif(NANA_CMAKE_AUTOMATIC_GUI_TESTING) @@ -266,7 +296,16 @@ foreach(subdir ${NANA_SOURCE_SUBDIRS}) # message("Subir: ${subdir}") # message("Files: ${sources}") endforeach(subdir ${NANA_SOURCE_SUBDIRS}) -add_library(${PROJECT_NAME} ${sources} ) +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + add_definitions(-fmax-errors=3) +endif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + +if(NANA_CMAKE_SHARED_LIB) + add_library(${PROJECT_NAME} SHARED ${sources} ) +else() + add_library(${PROJECT_NAME} STATIC ${sources} ) +endif(NANA_CMAKE_SHARED_LIB) + target_include_directories(${PROJECT_NAME} PUBLIC ${NANA_INCLUDE_DIR}) target_link_libraries(${PROJECT_NAME} ${NANA_LINKS}) @@ -276,32 +315,64 @@ target_link_libraries(${PROJECT_NAME} ${NANA_LINKS}) # Installing: the static "nana lib" will be in DESTDIR/CMAKE_INSTALL_PREFIX/lib/ # and the includes files "include/nana/" in DESTDIR/CMAKE_INSTALL_PREFIX/include/nana/ install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib) -message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib") -# Install the include directories too. -if(NANA_CMAKE_INSTALL_INCLUDES) - install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include ) - message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include") -endif(NANA_CMAKE_INSTALL_INCLUDES) + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) set_property( TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14 ) +if (NANA_CMAKE_SHARED_LIB) + if (WIN32) + set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + + if (DLLTOOL) + #message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}") + + #generate the lib and def files needed by msvc + set_target_properties (${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}" + ARCHIVE_OUTPUT_NAME "${PROJECT_NAME}" + LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} -Wl,--output-def=${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.def") + + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + COMMAND echo " Generating import library" + COMMAND "${DLLTOOL}" --dllname "lib${PROJECT_NAME}.dll" + --input-def "lib${PROJECT_NAME}.def" + --output-lib "lib${PROJECT_NAME}.lib") + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.def" + "${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.lib" DESTINATION lib) + endif () + + endif (WIN32) +endif (NANA_CMAKE_SHARED_LIB) + +message ("") +message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib") +# Install the include directories too. +if(NANA_CMAKE_INSTALL_INCLUDES) + install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include ) + message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include") +endif(NANA_CMAKE_INSTALL_INCLUDES) + + # Just for information: -message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID}) -message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG}) -message ( "CMAKE_COMPILER_IS_GNUCXX= " ${CMAKE_COMPILER_IS_GNUCXX}) -message ( "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS}) -message ( "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS}) -message ( "CMAKE_STATIC_LINKER_FLAGS=" ${CMAKE_STATIC_LINKER_FLAGS}) -message ( "NANA_LINKS = " ${NANA_LINKS}) -message ( "DESTDIR = " ${DESTDIR}) -message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX}) -message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR}) -message ( "CMAKE_CURRENT_SOURCE_DIR= " ${CMAKE_CURRENT_SOURCE_DIR}) -message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO}) +message ("") +message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID}) +message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG}) +message ( "CMAKE_COMPILER_IS_GNUCXX = " ${CMAKE_COMPILER_IS_GNUCXX}) +message ( "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS}) +message ( "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS}) +message ( "CMAKE_STATIC_LINKER_FLAGS = " ${CMAKE_STATIC_LINKER_FLAGS}) +message ( "NANA_LINKS = " ${NANA_LINKS}) +message ( "DESTDIR = " ${DESTDIR}) +message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX}) +message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR}) +message ( "CMAKE_CURRENT_SOURCE_DIR = " ${CMAKE_CURRENT_SOURCE_DIR}) +message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO}) +message ( "NANA_CMAKE_SHARED_LIB = " ${NANA_CMAKE_SHARED_LIB}) message ( "NANA_CMAKE_FIND_BOOST_FILESYSTEM = " ${NANA_CMAKE_FIND_BOOST_FILESYSTEM}) message ( "NANA_CMAKE_BOOST_FILESYSTEM_FORCE = " ${NANA_CMAKE_BOOST_FILESYSTEM_FORCE}) message ( "NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT = " ${NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT}) message ( "NANA_CMAKE_BOOST_FILESYSTEM_LIB = " ${NANA_CMAKE_BOOST_FILESYSTEM_LIB}) message ( "NANA_CMAKE_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_AUTOMATIC_GUI_TESTING}) -message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING}) \ No newline at end of file +message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING}) From 99a0cd2f8d219a939fdab32edf9fed588335ce06 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 17 Oct 2017 03:35:04 +0800 Subject: [PATCH 28/43] fix issue that listbox selected event behaves incorrectly in single mode In single selection mode, the selected event is firstly raised for the deselecting item. It is different from the selected event in multi-selection mode. --- source/gui/widgets/listbox.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index c49841c5..21a5f5f6 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -4166,16 +4166,16 @@ namespace nana { if (item_ptr->flags.selected != sel) { - item_ptr->flags.selected = sel; - lister.emit_cs(abs_item_pos, true); - - if (item_ptr->flags.selected) + if (sel) { lister.cancel_others_if_single_enabled(true, abs_item_pos); essence_->lister.latest_selected_abs = abs_item_pos; } else if (essence_->lister.latest_selected_abs == abs_item_pos) essence_->lister.latest_selected_abs.set_both(npos); + + item_ptr->flags.selected = sel; + lister.emit_cs(abs_item_pos, true); } } else From 24bbfc649319d13821904c763da63ed088c8fbe3 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 17 Oct 2017 06:49:39 +0800 Subject: [PATCH 29/43] small changes --- include/nana/basic_types.hpp | 9 ++++++++- source/gui/detail/window_manager.cpp | 14 ++------------ source/paint/graphics.cpp | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/nana/basic_types.hpp b/include/nana/basic_types.hpp index b190ea42..a041279b 100644 --- a/include/nana/basic_types.hpp +++ b/include/nana/basic_types.hpp @@ -312,7 +312,14 @@ namespace nana /// @param lightness in range of [0, 1] color& from_hsl(double hue, double saturation, double lightness); ///< immutable alpha channel - color blend(const color& blending_color, double alpha) const; + /// Blends color + /** + * Returns a color which is blended as this * (1 - fade_rate) + blending_color * fade_rate + * @param blending_color Color to blend + * @param fade_rate Blending rate for blending_color + * @return a blended color + */ + color blend(const color& blending_color, double fade_rate) const; /// Determines whether the color is completely transparent. bool invisible() const; diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index e948aeec..476b657b 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -219,8 +219,6 @@ namespace detail Key first; Value second; - key_value_rep() = default; - key_value_rep(const Key& k) : first(k), second{} { @@ -258,15 +256,7 @@ namespace detail std::vector table_; }; - //class window_manager - struct window_handle_deleter - { - void operator()(basic_window* wd) const - { - delete wd; - } - }; - + //class window_manager //struct wdm_private_impl struct window_manager::wdm_private_impl { @@ -506,7 +496,7 @@ namespace detail if (impl_->wd_register.available(owner)) { if (owner->flags.destroying) - throw std::runtime_error("the specified owner is destory"); + throw std::runtime_error("the specified owner is destoryed"); #ifndef WIDGET_FRAME_DEPRECATED native = (category::flags::frame == owner->other.category ? diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index f31f3afd..62f74016 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -271,7 +271,7 @@ namespace paint graphics::operator bool() const noexcept { - return impl_->handle; + return (impl_->handle != nullptr); } drawable_type graphics::handle() const From 94ab3b9f7823e1ecba2eceaf06d701b83ea079a1 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Fri, 20 Oct 2017 04:19:35 +0800 Subject: [PATCH 30/43] fix bug that dropdown list of combox may excess screen --- include/nana/gui/widgets/float_listbox.hpp | 6 +- source/gui/widgets/float_listbox.cpp | 119 ++++++++++++++------- source/gui/widgets/listbox.cpp | 1 + 3 files changed, 82 insertions(+), 44 deletions(-) diff --git a/include/nana/gui/widgets/float_listbox.hpp b/include/nana/gui/widgets/float_listbox.hpp index 590479fd..97670410 100644 --- a/include/nana/gui/widgets/float_listbox.hpp +++ b/include/nana/gui/widgets/float_listbox.hpp @@ -38,9 +38,9 @@ namespace nana { std::vector> items; - std::size_t max_items{10}; // the number of items display. - mutable std::size_t index{::nana::npos}; // the result of the selection. - mutable bool have_selected; + std::size_t max_items{ 10 }; // the number of items display. + mutable std::size_t index{ ::nana::npos }; // the result of the selection. + mutable bool have_selected{ false }; }; class item_renderer diff --git a/source/gui/widgets/float_listbox.cpp b/source/gui/widgets/float_listbox.cpp index 2b2d9180..7613b5bb 100644 --- a/source/gui/widgets/float_listbox.cpp +++ b/source/gui/widgets/float_listbox.cpp @@ -14,6 +14,7 @@ #include #include +#include namespace nana { @@ -198,16 +199,14 @@ namespace nana return widget_; } - void attach(widget* wd, nana::paint::graphics* graph) + void attach(widget& wd, nana::paint::graphics& graph) { - if(wd) - { - widget_ = wd; - wd->events().mouse_wheel.connect_unignorable([this](const arg_wheel& arg){ - scroll_items(arg.upwards); - }); - } - if(graph) graph_ = graph; + widget_ = &wd; + wd.events().mouse_wheel.connect_unignorable([this](const arg_wheel& arg){ + scroll_items(arg.upwards); + }); + + graph_ = &graph; } void detach() @@ -219,9 +218,46 @@ namespace nana { if(module_) { - std::size_t items = (module_->max_items <= module_->items.size() ? module_->max_items : module_->items.size()); - std::size_t h = items * state_.renderer->item_pixels(*graph_); - widget_->size(size{ widget_->size().width, static_cast(h + 4) }); + + auto const items = (module_->max_items <= module_->items.size() ? module_->max_items : module_->items.size()); + + rectangle list_r{ + 0, 0, + widget_->size().width, + static_cast(items * state_.renderer->item_pixels(*graph_)) + 4 + }; + + //Test if the listbox excesses the screen + + screen scr; + auto & disp = scr.from_window(*widget_); + + auto disp_r = disp.area(); + + point pos; + API::calc_screen_point(*widget_, pos); + list_r.position(pos); + + if (widget_->size().width >= disp_r.width) + { + pos.x = 0; + list_r.width = disp_r.width; + } + else if (list_r.right() > disp_r.right()) + pos.x = disp_r.right() - static_cast(list_r.width); + + if (list_r.height >= disp_r.height) + { + pos.y = 0; + list_r.height = disp_r.height; + } + else if (list_r.bottom() > disp_r.bottom()) + pos.y = disp_r.bottom() - static_cast(list_r.height); + + API::calc_window_point(API::get_owner_window(*widget_), pos); + list_r.position(pos); + + widget_->move(list_r); } } @@ -312,36 +348,37 @@ namespace nana void _m_open_scrollbar(widget_reference wd, bool v) { - if(v) + if (!v) { - if(scrollbar_.empty() && module_) - { - scrollbar_.create(wd, rectangle(static_cast(wd.size().width - 18), 2, 16, wd.size().height - 4)); - scrollbar_.amount(module_->items.size()); - scrollbar_.range(module_->max_items); - scrollbar_.value(state_.offset_y); - - auto & events = scrollbar_.events(); - events.mouse_wheel.connect([this](const arg_wheel& arg) - { - scroll_items(arg.upwards); - }); - - auto fn = [this](const arg_mouse& arg) - { - if (arg.is_left_button() && (scrollbar_.value() != state_.offset_y)) - { - state_.offset_y = static_cast(scrollbar_.value()); - draw(); - API::update_window(*widget_); - } - }; - events.mouse_move.connect(fn); - events.mouse_up.connect(fn); - } - } - else scrollbar_.close(); + return; + } + + if(scrollbar_.empty() && module_) + { + scrollbar_.create(wd, rectangle(static_cast(wd.size().width - 18), 2, 16, wd.size().height - 4)); + scrollbar_.amount(module_->items.size()); + scrollbar_.range(module_->max_items); + scrollbar_.value(state_.offset_y); + + auto & events = scrollbar_.events(); + events.mouse_wheel.connect([this](const arg_wheel& arg) + { + scroll_items(arg.upwards); + }); + + auto fn = [this](const arg_mouse& arg) + { + if (arg.is_left_button() && (scrollbar_.value() != state_.offset_y)) + { + state_.offset_y = static_cast(scrollbar_.value()); + draw(); + API::update_window(*widget_); + } + }; + events.mouse_move.connect(fn); + events.mouse_up.connect(fn); + } } private: widget * widget_{nullptr}; @@ -393,7 +430,7 @@ namespace nana void trigger::attached(widget_reference widget, graph_reference graph) { - drawer_->attach(&widget, &graph); + drawer_->attach(widget, graph); } void trigger::detached() diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 21a5f5f6..385b5140 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -4168,6 +4168,7 @@ namespace nana { if (sel) { + //Deselects the previously selected item. lister.cancel_others_if_single_enabled(true, abs_item_pos); essence_->lister.latest_selected_abs = abs_item_pos; } From 97ca4ac3de92f98d7feccd01275c1ae1b7964860 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 20 Oct 2017 02:08:13 +0200 Subject: [PATCH 31/43] add h file into project for convenient IDE browsing --- build/vc2017/nana.vcxproj | 67 ++++++++++ build/vc2017/nana.vcxproj.filters | 202 ++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) diff --git a/build/vc2017/nana.vcxproj b/build/vc2017/nana.vcxproj index 818d6cf8..e1032aef 100644 --- a/build/vc2017/nana.vcxproj +++ b/build/vc2017/nana.vcxproj @@ -232,6 +232,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/vc2017/nana.vcxproj.filters b/build/vc2017/nana.vcxproj.filters index ef973d0c..10e92180 100644 --- a/build/vc2017/nana.vcxproj.filters +++ b/build/vc2017/nana.vcxproj.filters @@ -41,6 +41,15 @@ {c1cdf46a-519f-422a-947f-39e173045414} + + {d68bd89c-170f-445f-b79f-aa03c881ab6b} + + + {a5d87649-2cd1-4a8f-a1f9-7151eaf6c772} + + + {0e6a58ab-652c-45d7-b9aa-8d9f2fa80ea1} + @@ -284,4 +293,197 @@ Sources\gui + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui\widgets + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include\gui + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + + + Include + + + Include + + \ No newline at end of file From 708152ed7880c61c122f551c89f1ad82b1df2299 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 20 Oct 2017 02:05:52 +0200 Subject: [PATCH 32/43] FEATURE: use width and height instead of weight --- source/gui/place.cpp | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/source/gui/place.cpp b/source/gui/place.cpp index 257e4656..f243fcf0 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -58,7 +58,7 @@ namespace nana { div_start, div_end, splitter, identifier, dock, fit, hfit, vfit, vert, grid, number, array, reparray, - weight, gap, margin, arrange, variable, repeated, min_px, max_px, left, right, top, bottom, undisplayed, invisible, + weight, width, height, gap, margin, arrange, variable, repeated, min_px, max_px, left, right, top, bottom, undisplayed, invisible, collapse, parameters, equal, eof, error @@ -235,15 +235,21 @@ namespace nana idstr_.assign(idstart, sp_); - if ("weight" == idstr_ || "min" == idstr_ || "max" == idstr_) + if ( "weight" == idstr_ + || "min" == idstr_ + || "max" == idstr_ + || "width" == idstr_ + || "height" == idstr_ + ) { - auto ch = idstr_[1]; + auto c3 = idstr_[2], c1 =idstr_[0]; _m_attr_number_value(); - switch (ch) + switch (c3) { - case 'e': return token::weight; - case 'i': return token::min_px; - case 'a': return token::max_px; + case 'i': return c1=='w'? token::weight : token::height; + case 'n': return token::min_px; + case 'x': return token::max_px; + case 'd': return token::width; } } else if ("dock" == idstr_) @@ -742,6 +748,7 @@ namespace nana { public: enum class kind{ arrange, vertical_arrange, grid, splitter, dock, dockpane}; + using token = place_parts::tokenizer::token; division(kind k, std::string&& n) noexcept : kind_of_division(k), @@ -1082,6 +1089,7 @@ namespace nana ::nana::rectangle field_area; number_t weight; + token weigth_type=token::weight; number_t min_px, max_px; place_parts::margin margin; @@ -2616,10 +2624,10 @@ namespace nana auto place::implement::scan_div(place_parts::tokenizer& tknizer) -> std::unique_ptr { - typedef place_parts::tokenizer::token token; + using token = place_parts::tokenizer::token ; std::unique_ptr div; - token div_type = token::eof; + token div_type = token::eof , weight_type=token::weight; auto fit = fit_policy::none; place_parts::repeated_array fit_parameters; @@ -2726,7 +2734,7 @@ namespace nana } } break; - case token::weight: case token::min_px: case token::max_px: + case token::weight: case token::min_px: case token::max_px: case token::width: case token::height: { auto n = tknizer.number(); //If n is the type of real, convert it to integer. @@ -2736,7 +2744,9 @@ namespace nana switch (tk) { - case token::weight: weight = n; break; + case token::weight: weight = n; weight_type = token::weight; break; // we could detect errors here (redefinitions and duplicates) + case token::width : weight = n; weight_type = token::width ; break; + case token::height: weight = n; weight_type = token::height; break; case token::min_px: min_px = n; break; case token::max_px: max_px = n; break; default: break; //Useless @@ -2805,10 +2815,16 @@ namespace nana } } + token unmatch = token::width; switch (div_type) { - case token::eof: - case token::vert: + case token::eof: unmatch = token::height; // "horitontal" div + case token::vert: // "vertical" div + for (auto& ch : children) + if (ch->weigth_type == unmatch) + throw std::invalid_argument("nana.place: unmatch vertical-heigth/horizontal-width betwen division '" + +name+"' and children division '" + ch->name); + div.reset(new div_arrange(token::vert == div_type, std::move(name), std::move(arrange))); break; case token::grid: @@ -2837,6 +2853,7 @@ namespace nana default: throw std::invalid_argument("nana.place: invalid division type."); } + div->weigth_type = weight_type; //Requirements for min/max //1, min and max != negative From 7c7b0333d464e34b19737bbb7a500f011e0ba296 Mon Sep 17 00:00:00 2001 From: Cjacker Date: Wed, 25 Oct 2017 15:03:21 +0800 Subject: [PATCH 33/43] Fix input method cursor follow issue under X11 --- source/detail/platform_spec_posix.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/detail/platform_spec_posix.cpp b/source/detail/platform_spec_posix.cpp index e495cf7d..58e936ee 100644 --- a/source/detail/platform_spec_posix.cpp +++ b/source/detail/platform_spec_posix.cpp @@ -835,6 +835,19 @@ namespace detail i->second->reinstate(); i->second->pos = pos; } + auto addr = i->second; + XPoint spot; + XVaNestedList list; + if(addr->input_context) { + spot.x = pos.x; + spot.y = pos.y + addr->size.height; + list = ::XVaCreateNestedList(0, XNSpotLocation, &spot, + XNForeground, 0, + XNBackground, 0, + (void *)0); + ::XSetICValues(addr->input_context, XNPreeditAttributes, list, NULL); + ::XFree(list); + } } void platform_spec::caret_visible(native_window_type wd, bool vis) From 9379f19c19e4bc6142e004792330f77806c33361 Mon Sep 17 00:00:00 2001 From: Cjacker Date: Wed, 25 Oct 2017 15:09:09 +0800 Subject: [PATCH 34/43] Use tab instead of space to match original source format --- source/detail/platform_spec_posix.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/source/detail/platform_spec_posix.cpp b/source/detail/platform_spec_posix.cpp index 58e936ee..906aaf93 100644 --- a/source/detail/platform_spec_posix.cpp +++ b/source/detail/platform_spec_posix.cpp @@ -835,19 +835,19 @@ namespace detail i->second->reinstate(); i->second->pos = pos; } - auto addr = i->second; - XPoint spot; - XVaNestedList list; - if(addr->input_context) { - spot.x = pos.x; - spot.y = pos.y + addr->size.height; - list = ::XVaCreateNestedList(0, XNSpotLocation, &spot, - XNForeground, 0, - XNBackground, 0, - (void *)0); - ::XSetICValues(addr->input_context, XNPreeditAttributes, list, NULL); - ::XFree(list); - } + auto addr = i->second; + XPoint spot; + XVaNestedList list; + if(addr->input_context) { + spot.x = pos.x; + spot.y = pos.y + addr->size.height; + list = ::XVaCreateNestedList(0, XNSpotLocation, &spot, + XNForeground, 0, + XNBackground, 0, + (void *)0); + ::XSetICValues(addr->input_context, XNPreeditAttributes, list, NULL); + ::XFree(list); + } } void platform_spec::caret_visible(native_window_type wd, bool vis) From b7ad2d99e0744b0330cf0205cc717e5fca57078d Mon Sep 17 00:00:00 2001 From: Cjacker Date: Wed, 25 Oct 2017 15:29:29 +0800 Subject: [PATCH 35/43] Also need to check addr --- source/detail/platform_spec_posix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/detail/platform_spec_posix.cpp b/source/detail/platform_spec_posix.cpp index 906aaf93..7f825395 100644 --- a/source/detail/platform_spec_posix.cpp +++ b/source/detail/platform_spec_posix.cpp @@ -836,9 +836,9 @@ namespace detail i->second->pos = pos; } auto addr = i->second; - XPoint spot; - XVaNestedList list; - if(addr->input_context) { + if(addr && addr->input_context) { + XPoint spot; + XVaNestedList list; spot.x = pos.x; spot.y = pos.y + addr->size.height; list = ::XVaCreateNestedList(0, XNSpotLocation, &spot, From 0796c1540b14e7340e3f7566841d6c2795db17bc Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 1 Nov 2017 11:57:52 +0800 Subject: [PATCH 36/43] fix issue that listbox scheme mouse_wheel.lines has no effect --- include/nana/gui/widgets/detail/tree_cont.hpp | 6 +++--- source/gui/widgets/listbox.cpp | 5 +++++ source/gui/widgets/treebox.cpp | 8 +++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/nana/gui/widgets/detail/tree_cont.hpp b/include/nana/gui/widgets/detail/tree_cont.hpp index 3acbc6fa..2490ab95 100644 --- a/include/nana/gui/widgets/detail/tree_cont.hpp +++ b/include/nana/gui/widgets/detail/tree_cont.hpp @@ -1,12 +1,12 @@ -/** +/* * A Tree Container class implementation * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE or copy at + * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file nana/gui/widgets/detail/tree_cont.hpp + * @file: nana/gui/widgets/detail/tree_cont.hpp */ #ifndef NANA_GUI_WIDGETS_DETAIL_TREE_CONT_HPP diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 385b5140..e473a080 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3931,6 +3931,11 @@ namespace nana essence_->content_view.reset(new widgets::skeletons::content_view{ widget.handle() }); essence_->resize_disp_area(); + //Set the content_view wheel speed with the listbox scheme. + essence_->content_view->set_wheel_speed([this] { + return essence_->scheme_ptr->mouse_wheel.lines; + }); + essence_->content_view->events().hover_outside = [this](const point& cur_pos) { essence_->update_mouse_selection(cur_pos); }; diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 17696e53..88468861 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -1,15 +1,13 @@ -/** +/* * A Treebox Implementation * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE or copy at + * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file nana/gui/widgets/treebox.cpp - * @brief - * + * @file: nana/gui/widgets/treebox.cpp */ #include #include From 74f5a8f40bc1b86c6b09369969bd4183e0dd4c23 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 2 Nov 2017 16:36:23 +0800 Subject: [PATCH 37/43] fix caret issue --- include/nana/gui/basis.hpp | 1 + include/nana/gui/detail/basic_window.hpp | 1 + source/gui/detail/basic_window.cpp | 31 ++++++++++++------------ source/gui/detail/bedrock_pi.cpp | 3 ++- source/gui/programming_interface.cpp | 7 ++++++ 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index 69b97c1f..2cc656ca 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -273,6 +273,7 @@ that return a corresponding nana::appearance with predefined values. public: virtual ~caret_interface() = default; + virtual bool activated() const = 0; virtual void disable_throw() noexcept = 0; virtual void effective_range(const rectangle& range) = 0; diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index c686f889..3f90c300 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -55,6 +55,7 @@ namespace detail void dimension(const size& s) override; void visible(bool visibility) override; bool visible() const override; + bool activated() const override; private: basic_window * owner_; point position_; diff --git a/source/gui/detail/basic_window.cpp b/source/gui/detail/basic_window.cpp index 67b24139..dc072370 100644 --- a/source/gui/detail/basic_window.cpp +++ b/source/gui/detail/basic_window.cpp @@ -204,6 +204,11 @@ namespace nana { return (visible_state::invisible != visibility_); } + + bool caret::activated() const + { + return (visible_state::displayed == visibility_); + } //end class caret //struct basic_window @@ -329,24 +334,18 @@ namespace nana return false; } - const basic_window* get_child_caret(const basic_window* wd, bool this_is_a_child) - { - if (this_is_a_child && wd->annex.caret_ptr) - return wd; - - for (auto child : wd->children) - { - auto caret_wd = get_child_caret(child, true); - if (caret_wd) - return caret_wd; - } - - return nullptr; - } - const basic_window * basic_window::child_caret() const { - return get_child_caret(this, false); + for (auto child : children) { + //Only return the child who has activated caret. + if (child->annex.caret_ptr && child->annex.caret_ptr->activated()) + return child; + + auto caret = child->child_caret(); + if (caret) + return caret; + } + return nullptr; } bool basic_window::is_draw_through() const diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index ec27ac07..3422beaa 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -151,7 +151,8 @@ namespace nana arg.window_handle = reinterpret_cast(wd); if (emit(event_code::expose, wd, arg, false, get_thread_context())) { - const core_window_t * caret_wd = (wd->annex.caret_ptr ? wd : wd->child_caret()); + //Get the window who has the activated caret + const core_window_t * caret_wd = ((wd->annex.caret_ptr && wd->annex.caret_ptr->activated()) ? wd : wd->child_caret()); if (caret_wd) { if (exposed) diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index 1fd7d158..22e22cac 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -1183,6 +1183,13 @@ namespace API auto caret = _m_caret(); return (caret && caret->visible()); } + + bool activated() const override + { + internal_scope_guard lock; + auto caret = _m_caret(); + return (caret && caret->activated()); + } private: caret_interface* _m_caret() const { From 3dc7e3ae5b7e13218afda306639d6919042e699d Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 2 Nov 2017 17:55:14 +0800 Subject: [PATCH 38/43] fix bug where picture throws if image is empty --- include/nana/gui/widgets/picture.hpp | 1 - source/gui/widgets/picture.cpp | 48 +++++++++++++++------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/include/nana/gui/widgets/picture.hpp b/include/nana/gui/widgets/picture.hpp index 9050f8be..d4805662 100644 --- a/include/nana/gui/widgets/picture.hpp +++ b/include/nana/gui/widgets/picture.hpp @@ -36,7 +36,6 @@ namespace nana void attached(widget_reference, graph_reference) override; private: void refresh(graph_reference) override; - void _m_draw_background(unsigned,unsigned); private: implement * const impl_; }; diff --git a/source/gui/widgets/picture.cpp b/source/gui/widgets/picture.cpp index b1e40aae..e9747a4e 100644 --- a/source/gui/widgets/picture.cpp +++ b/source/gui/widgets/picture.cpp @@ -48,6 +48,22 @@ namespace nana std::unique_ptr bground; //If it is not a null ptr, the widget is stretchable mode bool stretchable{ false }; //If it is true, the widget is stretchable mode without changing aspect ratio. }backimg; + + void draw_background(const size& dimension) + { + if (graph_ptr && (!API::dev::copy_transparent_background(*wdg_ptr, *graph_ptr))) + { + if (dimension.width < graph_ptr->size().width || dimension.height < graph_ptr->size().height || backimg.image.alpha()) + { + if (gradual_bground.gradual_from.invisible() || gradual_bground.gradual_to.invisible()) + graph_ptr->rectangle(true, wdg_ptr->bgcolor()); + else if (gradual_bground.gradual_from == gradual_bground.gradual_to) + graph_ptr->rectangle(true, gradual_bground.gradual_from); + else + graph_ptr->gradual_rectangle(::nana::rectangle{ graph_ptr->size() }, gradual_bground.gradual_from, gradual_bground.gradual_to, !gradual_bground.horizontal); + } + } + } }; class content_measurer @@ -106,6 +122,13 @@ namespace nana if (!backimg.bground) { + if (backimg.image.empty()) + { + impl_->draw_background({}); + graph.setsta(); + return; + } + auto valid_area = backimg.valid_area; if (valid_area.empty()) valid_area.dimension(backimg.image.size()); @@ -142,7 +165,7 @@ namespace nana } } - _m_draw_background(fit_size.width, fit_size.height); + impl_->draw_background(fit_size); backimg.image.stretch(valid_area, graph, ::nana::rectangle{ pos, fit_size }); } @@ -173,7 +196,7 @@ namespace nana break; } - _m_draw_background(valid_area.width, valid_area.height); + impl_->draw_background(valid_area.dimension()); if ( ! backimg.image.empty()) backimg.image.paste(valid_area, graph, pos); @@ -181,7 +204,7 @@ namespace nana } else { - _m_draw_background(graphsize.width, graphsize.height); + impl_->draw_background(graphsize); color invalid_clr_for_call; backimg.bground->draw(graph, invalid_clr_for_call, invalid_clr_for_call, rectangle{ graphsize }, element_state::normal); @@ -189,25 +212,6 @@ namespace nana graph.setsta(); } - - void drawer::_m_draw_background(unsigned w, unsigned h) - { - auto graph = impl_->graph_ptr; - - if (graph && (!API::dev::copy_transparent_background(*impl_->wdg_ptr, *graph))) - { - if (w < graph->size().width || h < graph->size().height || impl_->backimg.image.alpha()) - { - auto & bground = impl_->gradual_bground; - if (bground.gradual_from.invisible() || bground.gradual_to.invisible()) - graph->rectangle(true, impl_->wdg_ptr->bgcolor()); - else if (bground.gradual_from == bground.gradual_to) - graph->rectangle(true, bground.gradual_from); - else - graph->gradual_rectangle(::nana::rectangle{ graph->size() }, bground.gradual_from, bground.gradual_to, !bground.horizontal); - } - } - } //end class drawer }//end namespace picture }//end namespace drawerbase From 60c85cff52d62019e90c16192b750c568823f86a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 6 Nov 2017 05:56:08 +0800 Subject: [PATCH 39/43] refactor picture widget --- source/gui/widgets/picture.cpp | 78 +++++++++++----------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/source/gui/widgets/picture.cpp b/source/gui/widgets/picture.cpp index e9747a4e..356072b9 100644 --- a/source/gui/widgets/picture.cpp +++ b/source/gui/widgets/picture.cpp @@ -29,7 +29,6 @@ namespace nana struct implement { widget* wdg_ptr{nullptr}; - paint::graphics* graph_ptr{nullptr}; std::unique_ptr measurer; struct gradual_bground_tag @@ -49,18 +48,19 @@ namespace nana bool stretchable{ false }; //If it is true, the widget is stretchable mode without changing aspect ratio. }backimg; - void draw_background(const size& dimension) + void draw_background(paint::graphics& graph, const size& dimension) { - if (graph_ptr && (!API::dev::copy_transparent_background(*wdg_ptr, *graph_ptr))) + if (!API::dev::copy_transparent_background(*wdg_ptr, graph)) { - if (dimension.width < graph_ptr->size().width || dimension.height < graph_ptr->size().height || backimg.image.alpha()) + auto const graph_size = graph.size(); + if (dimension.width < graph_size.width || dimension.height < graph_size.height || backimg.image.alpha()) { if (gradual_bground.gradual_from.invisible() || gradual_bground.gradual_to.invisible()) - graph_ptr->rectangle(true, wdg_ptr->bgcolor()); + graph.rectangle(true, wdg_ptr->bgcolor()); else if (gradual_bground.gradual_from == gradual_bground.gradual_to) - graph_ptr->rectangle(true, gradual_bground.gradual_from); + graph.rectangle(true, gradual_bground.gradual_from); else - graph_ptr->gradual_rectangle(::nana::rectangle{ graph_ptr->size() }, gradual_bground.gradual_from, gradual_bground.gradual_to, !gradual_bground.horizontal); + graph.gradual_rectangle(::nana::rectangle{graph_size }, gradual_bground.gradual_from, gradual_bground.gradual_to, !gradual_bground.horizontal); } } } @@ -104,19 +104,15 @@ namespace nana delete impl_; } - void drawer::attached(widget_reference& wdg, graph_reference graph) + void drawer::attached(widget_reference& wdg, graph_reference) { impl_->wdg_ptr = &wdg; - impl_->graph_ptr = &graph; API::dev::set_measurer(wdg, impl_->measurer.get()); } void drawer::refresh(graph_reference graph) { - if (!graph.changed()) - return; - - auto graphsize = graph.size(); + auto const graphsize = graph.size(); auto & backimg = impl_->backimg; @@ -124,8 +120,7 @@ namespace nana { if (backimg.image.empty()) { - impl_->draw_background({}); - graph.setsta(); + impl_->draw_background(graph, {}); return; } @@ -133,10 +128,12 @@ namespace nana if (valid_area.empty()) valid_area.dimension(backimg.image.size()); + //The position where the image to be drawn. + ::nana::point pos; + if (backimg.stretchable) { - auto fit_size = fit_zoom({ valid_area.width, valid_area.height }, graphsize); - ::nana::point pos; + auto fit_size = fit_zoom(valid_area.dimension(), graphsize); if (fit_size.width != graphsize.width) { @@ -165,15 +162,12 @@ namespace nana } } - impl_->draw_background(fit_size); + impl_->draw_background(graph, fit_size); backimg.image.stretch(valid_area, graph, ::nana::rectangle{ pos, fit_size }); } else { - //The point in which position the image to be drawn. - ::nana::point pos; - switch (backimg.align_horz) { case ::nana::align::left: break; @@ -196,15 +190,14 @@ namespace nana break; } - impl_->draw_background(valid_area.dimension()); + impl_->draw_background(graph, valid_area.dimension()); - if ( ! backimg.image.empty()) - backimg.image.paste(valid_area, graph, pos); + backimg.image.paste(valid_area, graph, pos); } } else { - impl_->draw_background(graphsize); + impl_->draw_background(graph, graphsize); color invalid_clr_for_call; backimg.bground->draw(graph, invalid_clr_for_call, invalid_clr_for_call, rectangle{ graphsize }, element_state::normal); @@ -237,11 +230,7 @@ namespace nana if (backimg.bground) backimg.bground->image(backimg.image, true, valid_area); - if (handle()) - { - get_drawer_trigger().impl_->graph_ptr->set_changed(); - API::refresh_window(*this); - } + API::refresh_window(*this); } void picture::align(::nana::align horz, align_v vert) @@ -256,18 +245,11 @@ namespace nana backimg.align_horz = horz; backimg.align_vert = vert; - if (handle()) - { - get_drawer_trigger().impl_->graph_ptr->set_changed(); - API::refresh_window(*this); - } + API::refresh_window(*this); } void picture::stretchable(unsigned left, unsigned top, unsigned right, unsigned bottom) { - if (!handle()) - return; - internal_scope_guard lock; auto & backimg = get_drawer_trigger().impl_->backimg; if (!backimg.bground) @@ -279,11 +261,8 @@ namespace nana backimg.bground->stretch_parts(left, top, right, bottom); backimg.stretchable = false; - if (handle()) - { - get_drawer_trigger().impl_->graph_ptr->set_changed(); - API::refresh_window(*this); - } + + API::refresh_window(*this); } void picture::stretchable(bool enables) @@ -294,11 +273,7 @@ namespace nana backimg.bground.reset(); backimg.stretchable = enables; - if (handle()) - { - get_drawer_trigger().impl_->graph_ptr->set_changed(); - API::refresh_window(*this); - } + API::refresh_window(*this); } void picture::set_gradual_background(const ::nana::color& from, const ::nana::color& to, bool horizontal) @@ -307,11 +282,8 @@ namespace nana bground.gradual_from = from; bground.gradual_to = to; bground.horizontal = horizontal; - if (handle()) - { - get_drawer_trigger().impl_->graph_ptr->set_changed(); - API::refresh_window(*this); - } + + API::refresh_window(*this); } void picture::transparent(bool enabled) From 77f7bdb37c5c12ec5378a5c98f5bbb90f9b9f81d Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 14 Nov 2017 02:06:48 +0800 Subject: [PATCH 40/43] fix bug that a font lapse after widget resizes --- source/gui/detail/window_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 476b657b..4bfd1900 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -950,6 +950,7 @@ namespace detail { //If allocation fails, here throws std::bad_alloc. graph.make(sz); + graph.typeface(wd->drawer.graphics.typeface()); if (category::flags::root == wd->other.category) root_graph.make(sz); } From 14cc7cdaa1b3959e27a1ac54f81679c5fc555793 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 19 Nov 2017 07:04:34 +0800 Subject: [PATCH 41/43] fix issue that progress is incorrect when it is resized --- source/gui/widgets/progress.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/source/gui/widgets/progress.cpp b/source/gui/widgets/progress.cpp index 20b46ddc..2c498f7c 100644 --- a/source/gui/widgets/progress.cpp +++ b/source/gui/widgets/progress.cpp @@ -91,19 +91,26 @@ namespace nana { return value_px_; } + + bool value_px_sync() + { + if (widget_) + { + auto value_px = (widget_->size().width - border_px * 2) * value_ / max_; + + if (value_px != value_px_) + { + value_px_ = value_px; + return true; + } + } + return false; + } private: void _m_try_refresh() { - if (nullptr == widget_) - return; - - auto value_px = (widget_->size().width - border_px * 2) * value_ / max_; - - if (value_px != value_px_) - { - value_px_ = value_px; + if (value_px_sync()) API::refresh_window(*widget_); - } } private: nana::progress * widget_{ nullptr }; @@ -144,6 +151,9 @@ namespace nana auto rt_bground = rt_val; if (false == progress_->unknown(nullptr)) { + //Sync the value_px otherwise the progress is incorrect when it is resized. + progress_->value_px_sync(); + rt_bground.x = static_cast(progress_->value_px()) + static_cast(border_px); rt_bground.width -= progress_->value_px(); From 7e68068c2501a681dbbcbce9abf60073f35687ee Mon Sep 17 00:00:00 2001 From: pavelxdd Date: Sat, 25 Nov 2017 04:26:01 +0300 Subject: [PATCH 42/43] fix compilation with boost::filesystem CMakeLists.txt: --------------------------- Until now build with boost::filesystem was completely broken, since cmake exported definitions with wrong name prefixes, and nana always defaulted to internal filesystem implementation. After fixing the boost definitions, a number of errors came up due to incompatibility of boost::filesystem with nana and std filesystems. This commit tries to fix them all. filesystem.cpp, filesystem.hpp, filebox.cpp: -------------------------------------------- boost::filesystem doesn't have a file_time_type, so declared it in the filesystem.hpp header. boost::filesystem::last_write_time has a return type std::time_t unlike the other two implementations of this function in nana and std, so added ifdef to convert the result to file_time_type. fixed build on gcc-4.9, since it doesn't have a std::put_time function, included in that case. boost::filesystem::file_type types have different names than std::experimental::filesystem::file_type types, fixed it by creating an enum class file_type with the same type names as in std::experimental::filesystem::file_type. This fix requires static_cast from functions results to internal file_type, since boost file_type and std file_type a different enum classes. changed switch to if, bacause old gcc fails on converting enum class members to int. stdc++.hpp: ----------- added ifndef guards to prevent errors on multiple includes of this header. wvl.cpp: -------- added boost/chrono.hpp include for the cases when std::thread is not available. travis: ------- added boost system, thread, chrono libs to install, they are needed for the nana-demo to compile. --- .travis.yml | 3 +++ CMakeLists.txt | 4 ++-- include/nana/filesystem/filesystem.hpp | 15 +++++++++++++++ include/nana/stdc++.hpp | 7 ++++++- source/filesystem/filesystem.cpp | 14 +++++++++++++- source/gui/filebox.cpp | 26 ++++++++++++-------------- source/gui/wvl.cpp | 7 ++++++- 7 files changed, 57 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4543e6b3..c7b02176 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,9 @@ matrix: - libx11-dev - libxft-dev - libboost-filesystem-dev + - libboost-system-dev + - libboost-thread-dev + - libboost-chrono-dev sources: - ubuntu-toolchain-r-test diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a43b5b5..cc4622bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,7 +238,7 @@ elseif (NANA_CMAKE_STD_FILESYSTEM_FORCE) add_definitions(-DSTD_FILESYSTEM_FORCE) elseif (NANA_CMAKE_FIND_BOOST_FILESYSTEM OR NANA_CMAKE_BOOST_FILESYSTEM_FORCE) if (NANA_CMAKE_BOOST_FILESYSTEM_FORCE) - add_definitions(-DNANA_BOOST_FILESYSTEM_FORCE) + add_definitions(-DBOOST_FILESYSTEM_FORCE) endif(NANA_CMAKE_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, @@ -246,7 +246,7 @@ elseif (NANA_CMAKE_FIND_BOOST_FILESYSTEM OR NANA_CMAKE_BOOST_FILESYSTEM_FORCE) # If using Boost::thread, then Thread::Thread will also be added automatically. find_package(Boost COMPONENTS filesystem) if (Boost_FOUND) - add_definitions(-DNANA_BOOST_FILESYSTEM_AVAILABLE) + add_definitions(-DBOOST_FILESYSTEM_AVAILABLE) include_directories(SYSTEM "${Boost_INCLUDE_DIR}") list(APPEND NANA_LINKS ${Boost_LIBRARIES}) ###### FIRST !!!!!!!!!!!!!!!!! add is not first endif (Boost_FOUND) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 59020d68..067586f5 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -53,6 +53,7 @@ #undef NANA_USING_BOOST_FILESYSTEM #define NANA_USING_BOOST_FILESYSTEM 1 +# include # include // add boost::filesystem into std::experimental::filesystem @@ -60,6 +61,20 @@ namespace std { namespace experimental { namespace filesystem { using namespace boost::filesystem; + using file_time_type = std::chrono::time_point; + + enum class file_type { + none = boost::filesystem::file_type::status_unknown, + not_found = boost::filesystem::file_type::file_not_found, + regular = boost::filesystem::file_type::regular_file, + directory = boost::filesystem::file_type::directory_file, + symlink = boost::filesystem::file_type::symlink_file, + block = boost::filesystem::file_type::block_file, + character = boost::filesystem::file_type::character_file, + fifo = boost::filesystem::file_type::fifo_file, + socket = boost::filesystem::file_type::socket_file, + unknown = boost::filesystem::file_type::type_unknown, + }; } // filesystem } // experimental } // std diff --git a/include/nana/stdc++.hpp b/include/nana/stdc++.hpp index 4d8bbef9..fc2d6568 100644 --- a/include/nana/stdc++.hpp +++ b/include/nana/stdc++.hpp @@ -12,6 +12,9 @@ * @brief Implement the lack support of standard library. */ +#ifndef NANA_STDCXX_INCLUDED +#define NANA_STDCXX_INCLUDED + #include "c++defines.hpp" //Implement workarounds for GCC/MinGW which version is below 4.8.2 @@ -153,4 +156,6 @@ namespace std return (v < lo ? lo : (hi < v ? hi : v)); } } -#endif \ No newline at end of file +#endif + +#endif // NANA_STDCXX_INCLUDED diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index 4613ca7a..fa5a8cb8 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -14,7 +14,13 @@ #include #include #include -#include //put_time + +#include +#ifdef _enable_std_put_time + #include +#else + #include +#endif #if defined(NANA_WINDOWS) #include @@ -97,7 +103,13 @@ namespace nana std::string pretty_file_date(const fs::path& path) // todo: move to .cpp { try { +#if NANA_USING_BOOST_FILESYSTEM + // The return type of boost::filesystem::last_write_time isn't + // the same as in nana and std implementations of this function + auto ftime = std::chrono::system_clock::from_time_t(fs::last_write_time(path)); +#else auto ftime = fs::last_write_time(path); +#endif // crash: VS2015 will not read the time for some files (for example: C:/hiberfil.sys) // and will return file_time_type(-1) without throwing diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index 96f1e1c6..b31653cc 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -505,21 +505,18 @@ namespace nana auto fpath = i->path().native(); auto fattr = fs::status(fpath); + auto ftype = static_cast(fattr.type()); item_fs m; m.name = name; m.directory = fs::is_directory(fattr); - switch(fattr.type()) - { - case fs::file_type::not_found: - case fs::file_type::unknown: - case fs::file_type::directory: + if (ftype == fs::file_type::not_found || + ftype == fs::file_type::unknown || + ftype == fs::file_type::directory) m.bytes = 0; - break; - default: + else m.bytes = fs::file_size(fpath); - } fs_ext::modified_file_time(fpath, m.modified_time); @@ -692,13 +689,12 @@ namespace nana return; } - using file_type = fs::file_type; - fs::path fspath(fb_.addr_.filesystem + path); - auto fst = fs::status(fspath); + auto fattr = fs::status(fspath); + auto ftype = static_cast(fattr.type()); - if(fst.type() != file_type::not_found && fst.type() != file_type::none) + if(ftype != fs::file_type::not_found && ftype != fs::file_type::none) { mb<(fattr.type()); //Check if the selected name is a directory auto is_dir = fs::is_directory(fattr); @@ -808,6 +805,7 @@ namespace nana { //Add the extension, then check if it is a directory again. fattr = fs::status(tar); + ftype = static_cast(fattr.type()); is_dir = fs::is_directory(fattr); } @@ -820,7 +818,7 @@ namespace nana if(io_read_) { - if(fs::file_type::not_found == fattr.type()) + if(fs::file_type::not_found == ftype) { msgbox mb(*this, caption()); mb.icon(msgbox::icon_information); @@ -832,7 +830,7 @@ namespace nana } else { - if(fs::file_type::not_found != fattr.type()) + if(fs::file_type::not_found != ftype) { msgbox mb(*this, caption(), msgbox::yes_no); mb.icon(msgbox::icon_question); diff --git a/source/gui/wvl.cpp b/source/gui/wvl.cpp index 820a8ba7..610484cd 100644 --- a/source/gui/wvl.cpp +++ b/source/gui/wvl.cpp @@ -15,7 +15,12 @@ #include #include #include -#include + +#ifdef STD_THREAD_NOT_SUPPORTED +# include +#else +# include +#endif //#define NANA_AUTOMATIC_GUI_TESTING namespace nana From 81018c21fd0c399e2ad8315d8f6e2ff1bac2f528 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 3 Dec 2017 13:13:12 +0800 Subject: [PATCH 43/43] add contribution info --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e9cf66b..2cdeb93d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,8 @@ # Robert Hauck - Enable support for PNG/Freetype # Qiangqiang Wu - Add biicode support # Ariel Vina-Rodriguez (qPCR4vir) -# Frostbane - Add option for compiling a shared library +# Pavel O. - fix compilation with boost::filesystem (#281) +# Frostbane - Add option for compiling a shared library (#263,#265) # # Nana uses some build systems: MS-VS solution, MAKE, bakefile, codeblock, etc. manually optimized. # In the future CMake could be the prefered, and maybe will be used to generate the others and the central nana repo