From dfe32d0cc58a2fe72c40c2ebe4babae2438f1032 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 27 Aug 2017 16:29:57 +0200 Subject: [PATCH 01/25] 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/25] 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/25] 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/25] 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/25] 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/25] #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/25] 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 3b454cc2c52504274fe397e902bedfdc0a20baa9 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 14 Sep 2017 19:39:56 +0200 Subject: [PATCH 08/25] 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 8d9351e0519ca32bff2931cbcc1e4c7026b9799c Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 27 Sep 2017 08:13:55 +0800 Subject: [PATCH 09/25] 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 10/25] 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 11/25] 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 28e9bb8a7d04ec173168a50553348c4e08cd4b6f Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 30 Sep 2017 07:19:15 +0800 Subject: [PATCH 12/25] 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 13/25] 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 99a0cd2f8d219a939fdab32edf9fed588335ce06 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 17 Oct 2017 03:35:04 +0800 Subject: [PATCH 14/25] 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 15/25] 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 16/25] 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 7c7b0333d464e34b19737bbb7a500f011e0ba296 Mon Sep 17 00:00:00 2001 From: Cjacker Date: Wed, 25 Oct 2017 15:03:21 +0800 Subject: [PATCH 17/25] 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 18/25] 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 19/25] 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 20/25] 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 21/25] 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 22/25] 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 23/25] 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 24/25] 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 25/25] 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();