Merge branch 'hotfix-1.5.5' into develop
This commit is contained in:
commit
7369b5437c
1
.gitignore
vendored
1
.gitignore
vendored
@ -39,6 +39,7 @@ lib/
|
||||
*.ninja*
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake-build-debug/
|
||||
.idea/
|
||||
cmake_install.cmake
|
||||
*.DS_Store
|
||||
|
@ -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
|
||||
@ -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 ..
|
||||
|
@ -35,6 +35,7 @@ option(NANA_CMAKE_SHARED_LIB "Compile nana as a shared library." OFF)
|
||||
option(NANA_CMAKE_VERBOSE_PREPROCESSOR "Show annoying debug messages during compilation." ON)
|
||||
option(NANA_CMAKE_STOP_VERBOSE_PREPROCESSOR "Stop compilation after showing the annoying debug messages." OFF)
|
||||
option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF)
|
||||
option(NANA_CLION "Activate some CLion specific workarounds" OFF)
|
||||
|
||||
# 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
|
||||
@ -64,11 +65,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)
|
||||
@ -139,10 +141,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
|
||||
|
||||
@ -314,10 +321,20 @@ 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
|
||||
RUNTIME DESTINATION bin)
|
||||
|
||||
# http://stackoverflow.com/questions/33788729/how-do-i-get-clion-to-run-an-install-target
|
||||
if(NANA_CLION) # the Clion IDE don't reconize the install target
|
||||
add_custom_target(install_${PROJECT_NAME}
|
||||
$(MAKE) install
|
||||
DEPENDS ${PROJECT_NAME}
|
||||
COMMENT "Installing ${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
set_property( TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14 )
|
||||
|
||||
if (NANA_CMAKE_SHARED_LIB)
|
||||
@ -347,6 +364,7 @@ if (NANA_CMAKE_SHARED_LIB)
|
||||
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)
|
||||
@ -370,6 +388,9 @@ message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR})
|
||||
message ( "CMAKE_CURRENT_SOURCE_DIR = " ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO})
|
||||
message ( "NANA_CMAKE_SHARED_LIB = " ${NANA_CMAKE_SHARED_LIB})
|
||||
message ( "NANA_CLION = " ${NANA_CLION})
|
||||
message ( "CMAKE_MAKE_PROGRAM = " ${CMAKE_MAKE_PROGRAM})
|
||||
|
||||
message ( "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})
|
||||
|
@ -252,6 +252,32 @@
|
||||
<ClCompile Include="..\..\source\threads\pool.cpp" />
|
||||
<ClCompile Include="..\..\source\unicode_bidi.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\nana\any.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\basic_types.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\c++defines.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\charset.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\concepts.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\config.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\datetime.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\deploy.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\fwd.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\gui.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\internationalization.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\key_type.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\optional.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\stdc++.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\std_condition_variable.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\std_mutex.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\std_thread.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\traits.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\unicode_bidi.hpp" />
|
||||
<ClInclude Include="..\..\include\nana\verbose_preprocessor.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\include\nana\pop_ignore_diagnostic" />
|
||||
<None Include="..\..\include\nana\push_ignore_diagnostic" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
@ -292,4 +292,74 @@
|
||||
<Filter>Source Files\detail</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\nana\any.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\basic_types.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\c++defines.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\charset.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\concepts.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\config.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\datetime.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\deploy.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\fwd.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\gui.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\internationalization.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\key_type.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\optional.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\std_condition_variable.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\std_mutex.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\std_thread.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\stdc++.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\traits.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\unicode_bidi.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\nana\verbose_preprocessor.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\include\nana\pop_ignore_diagnostic">
|
||||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\include\nana\push_ignore_diagnostic">
|
||||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -101,6 +101,7 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -113,6 +114,7 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -127,6 +129,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -143,6 +146,7 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -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;
|
||||
|
@ -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(<filesystem>)
|
||||
# undef STD_FILESYSTEM_NOT_SUPPORTED
|
||||
# endif
|
||||
# if __has_include(<mutex>)
|
||||
# undef STD_THREAD_NOT_SUPPORTED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // NANA_CXX_DEFINES_INCLUDED
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
@ -38,9 +38,9 @@ namespace nana
|
||||
{
|
||||
std::vector<std::shared_ptr<item_interface>> 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
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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<typename ItemRenderer>
|
||||
@ -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;///<returns the key path
|
||||
|
||||
item_proxy selected() const; ///< returns the selected node
|
||||
|
||||
};//end class treebox
|
||||
}//end namespace nana
|
||||
|
||||
#include <nana/pop_ignore_diagnostic>
|
||||
|
||||
#endif
|
||||
|
@ -85,12 +85,14 @@ 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) noexcept;
|
||||
|
||||
/// Creates a graphics/drawable resource
|
||||
/**
|
||||
* @param sz The dimension of the graphics to be requested. If sz is empty, it performs as release().
|
||||
|
@ -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,
|
||||
|
@ -835,6 +835,19 @@ namespace detail
|
||||
i->second->reinstate();
|
||||
i->second->pos = pos;
|
||||
}
|
||||
auto addr = i->second;
|
||||
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,
|
||||
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)
|
||||
|
@ -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
|
||||
|
@ -151,7 +151,8 @@ namespace nana
|
||||
arg.window_handle = reinterpret_cast<window>(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)
|
||||
|
@ -245,22 +245,31 @@ 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);
|
||||
|
||||
//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)
|
||||
|
@ -601,40 +601,6 @@ namespace detail
|
||||
::HeapFree(::GetProcessHeap(), 0, stru);
|
||||
}
|
||||
return true;
|
||||
case nana::detail::messages::remote_thread_move_window:
|
||||
{
|
||||
auto * mw = reinterpret_cast<nana::detail::messages::move_window*>(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<HWND>(wParam), 0, 0, 0, 0, static_cast<UINT>(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;
|
||||
}
|
||||
|
@ -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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(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<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
{
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(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<HWND>(wd), x, y, r.right - r.left, r.bottom - r.top, true);
|
||||
}
|
||||
else
|
||||
::MoveWindow(reinterpret_cast<HWND>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
|
||||
int x = r.x;
|
||||
int y = r.y;
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(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<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(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<HWND>(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<HWND>(wd), &client);
|
||||
::GetWindowRect(reinterpret_cast<HWND>(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<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true);
|
||||
RECT client, wd_area;
|
||||
::GetClientRect(reinterpret_cast<HWND>(wd), &client);
|
||||
::GetWindowRect(reinterpret_cast<HWND>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
{
|
||||
nana::internal_revert_guard irg;
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true));
|
||||
}
|
||||
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(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<Window>(wd), &hints);
|
||||
|
||||
::XMoveResizeWindow(disp, reinterpret_cast<Window>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
|
||||
HWND parent = ::GetParent(reinterpret_cast<HWND>(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<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(mw), 0);
|
||||
::POINT pos = {r.left, r.top};
|
||||
::ScreenToClient(parent, &pos);
|
||||
r.left = pos.x;
|
||||
r.top = pos.y;
|
||||
}
|
||||
else
|
||||
|
||||
if (::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
{
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
|
||||
HWND parent = ::GetParent(reinterpret_cast<HWND>(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<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true);
|
||||
nana::internal_revert_guard irg;
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true));
|
||||
}
|
||||
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(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<Window>(wd), &hints);
|
||||
}
|
||||
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -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<key_value_rep> 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 ?
|
||||
@ -953,24 +943,46 @@ 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);
|
||||
graph.typeface(wd->drawer.graphics.typeface());
|
||||
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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <nana/gui/widgets/scroll.hpp>
|
||||
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/gui/screen.hpp>
|
||||
|
||||
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<unsigned>(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<unsigned>(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<int>(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<int>(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<int>(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<unsigned>(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<int>(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<unsigned>(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()
|
||||
|
@ -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);
|
||||
};
|
||||
@ -4166,16 +4171,17 @@ 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)
|
||||
{
|
||||
//Deselects the previously selected item.
|
||||
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
|
||||
|
@ -29,7 +29,6 @@ namespace nana
|
||||
struct implement
|
||||
{
|
||||
widget* wdg_ptr{nullptr};
|
||||
paint::graphics* graph_ptr{nullptr};
|
||||
std::unique_ptr<content_measurer> measurer;
|
||||
|
||||
struct gradual_bground_tag
|
||||
@ -48,6 +47,23 @@ namespace nana
|
||||
std::unique_ptr<element::bground> 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(paint::graphics& graph, const size& dimension)
|
||||
{
|
||||
if (!API::dev::copy_transparent_background(*wdg_ptr, graph))
|
||||
{
|
||||
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.rectangle(true, wdg_ptr->bgcolor());
|
||||
else if (gradual_bground.gradual_from == gradual_bground.gradual_to)
|
||||
graph.rectangle(true, gradual_bground.gradual_from);
|
||||
else
|
||||
graph.gradual_rectangle(::nana::rectangle{graph_size }, gradual_bground.gradual_from, gradual_bground.gradual_to, !gradual_bground.horizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class content_measurer
|
||||
@ -88,32 +104,36 @@ 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;
|
||||
|
||||
if (!backimg.bground)
|
||||
{
|
||||
if (backimg.image.empty())
|
||||
{
|
||||
impl_->draw_background(graph, {});
|
||||
return;
|
||||
}
|
||||
|
||||
auto valid_area = backimg.valid_area;
|
||||
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)
|
||||
{
|
||||
@ -142,15 +162,12 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
_m_draw_background(fit_size.width, fit_size.height);
|
||||
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;
|
||||
@ -173,15 +190,14 @@ namespace nana
|
||||
break;
|
||||
}
|
||||
|
||||
_m_draw_background(valid_area.width, valid_area.height);
|
||||
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
|
||||
{
|
||||
_m_draw_background(graphsize.width, graphsize.height);
|
||||
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);
|
||||
@ -189,25 +205,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
|
||||
@ -233,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)
|
||||
@ -252,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)
|
||||
@ -275,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)
|
||||
@ -290,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)
|
||||
@ -303,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)
|
||||
|
@ -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<int>(progress_->value_px()) + static_cast<int>(border_px);
|
||||
rt_bground.width -= progress_->value_px();
|
||||
|
||||
|
@ -269,9 +269,9 @@ namespace paint
|
||||
return (!impl_->handle);
|
||||
}
|
||||
|
||||
graphics::operator const void *() const
|
||||
graphics::operator bool() const noexcept
|
||||
{
|
||||
return impl_->handle;
|
||||
return (impl_->handle != nullptr);
|
||||
}
|
||||
|
||||
drawable_type graphics::handle() const
|
||||
@ -291,9 +291,15 @@ namespace paint
|
||||
return (impl_->handle ? impl_->handle->context : nullptr);
|
||||
}
|
||||
|
||||
void graphics::swap(graphics& other) noexcept
|
||||
{
|
||||
if (context() != other.context())
|
||||
impl_.swap(other.impl_);
|
||||
}
|
||||
|
||||
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 +308,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<nana::detail::drawable_impl_type> 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 +321,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 +340,60 @@ namespace paint
|
||||
|
||||
HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&(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 +404,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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user