diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f89337e..1a43b5b5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,11 @@
# CMake configuration for Nana
# Author: Andrew Kornilov(https://github.com/ierofant)
# Contributors:
-# Jinhao
+# Jinhao
# Robert Hauck - Enable support for PNG/Freetype
# Qiangqiang Wu - Add biicode support
-# Ariel Vina-Rodriguez (qPCR4vir)
+# Ariel Vina-Rodriguez (qPCR4vir)
+# Frostbane - Add option for compiling a shared library
#
# Nana uses some build systems: MS-VS solution, MAKE, bakefile, codeblock, etc. manually optimized.
# In the future CMake could be the prefered, and maybe will be used to generate the others and the central nana repo
@@ -30,6 +31,7 @@ option(NANA_CMAKE_LIBPNG_FROM_OS "Use libpng from operating system." ON)
option(NANA_CMAKE_ENABLE_JPEG "Enable the use of JPEG" OFF)
option(NANA_CMAKE_LIBJPEG_FROM_OS "Use libjpeg from operating system." ON)
option(NANA_CMAKE_ENABLE_AUDIO "Enable class audio::play for PCM playback." OFF)
+option(NANA_CMAKE_SHARED_LIB "Compile nana as a shared library." OFF)
option(NANA_CMAKE_VERBOSE_PREPROCESSOR "Show annoying debug messages during compilation." ON)
option(NANA_CMAKE_STOP_VERBOSE_PREPROCESSOR "Stop compilation after showing the annoying debug messages." OFF)
option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF)
@@ -45,7 +47,7 @@ option(NANA_CMAKE_AUTOMATIC_GUI_TESTING "Activate automatic GUI testing?" OFF)
# By default Nana will try to use the STD. If STD is not available and NANA_CMAKE_FIND_BOOST_FILESYSTEM
# is set to ON nana will try to use boost if available. Nana own implementation will be use if none of
# the previus were selected or available.
-# You can change that default if you change one of the following
+# You can change that default if you change one of the following
# (please don't define more than one of the _XX_FORCE options):
option(NANA_CMAKE_FIND_BOOST_FILESYSTEM "Search: Is Boost filesystem available?" OFF)
option(NANA_CMAKE_NANA_FILESYSTEM_FORCE "Force nana filesystem over ISO and boost?" OFF)
@@ -96,8 +98,24 @@ if(WIN32)
add_definitions(-DNANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ)
endif(NANA_CMAKE_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ)
endif(MINGW)
+
+ if (MSVC)
+ set (DLLTOOL OFF)
+ else ()
+ # mingw: If dlltool is found the def and lib file will be created
+ message (STATUS "Detecting dlltool")
+ find_program (DLLTOOL dlltool)
+ if (DLLTOOL)
+ message (STATUS "Found dlltool: ${DLLTOOL}")
+ else ()
+ message (WARNING "dlltool not found. Skipping import library generation.")
+ endif (DLLTOOL)
+ endif (MSVC)
+
endif(WIN32)
+
+
if(APPLE)
add_definitions(-DAPPLE)
include_directories(/opt/X11/include/)
@@ -105,7 +123,7 @@ if(APPLE)
set(ENABLE_AUDIO OFF)
elseif(UNIX)
add_definitions(-Dlinux)
- message("added -D linux")
+ message("added -D linux")
endif(APPLE)
if(UNIX)
@@ -129,27 +147,34 @@ endif(UNIX)
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # Clang || GNU
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14 -Wall -g") # Clang
-
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14 -Wall -g") # Clang
+
else ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -g") # GNU
-
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -g") # GNU
+
endif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# enable static linkage # GNU || CLang not MinGW
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW
- # set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread")
- list(APPEND NANA_LINKS -static-libgcc -static-libstdc++ -pthread)
- # message("Setting NANA_LINKS to -static-libgcc -static-libstdc++ -pthread or ${NANA_LINKS}")
+
+ if(NANA_CMAKE_SHARED_LIB)
+ list(APPEND NANA_LINKS -lgcc -lstdc++ -pthread)
+ else()
+ set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -pthread")
+ # message("Setting NANA_LINKS to -static-libgcc -static-libstdc++ -pthread or ${NANA_LINKS}")
+ endif(NANA_CMAKE_SHARED_LIB)
+
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3)
- # IS_GNUCXX < 5.3
+ # IS_GNUCXX < 5.3
else(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3)
- # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++fs") # IS_GNUCXX 5.3 or more
- list(APPEND NANA_LINKS -lstdc++fs)
+
+ # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++fs") # IS_GNUCXX 5.3 or more
+ list(APPEND NANA_LINKS -lstdc++fs)
+
endif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.3)
-
+
endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AND NOT MINGW
@@ -163,14 +188,16 @@ endif ()
# Find PNG
if(NANA_CMAKE_ENABLE_PNG)
- add_definitions(-DNANA_ENABLE_PNG)
if(NANA_CMAKE_LIBPNG_FROM_OS)
find_package(PNG)
if (PNG_FOUND)
include_directories( ${PNG_INCLUDE_DIRS})
list(APPEND NANA_LINKS ${PNG_LIBRARIES})
- add_definitions(-DUSE_LIBPNG_FROM_OS)
+ add_definitions("-DNANA_ENABLE_PNG"
+ "-DUSE_LIBPNG_FROM_OS")
endif(PNG_FOUND)
+ else()
+ add_definitions(-DNANA_ENABLE_PNG)
endif(NANA_CMAKE_LIBPNG_FROM_OS)
endif(NANA_CMAKE_ENABLE_PNG)
@@ -182,8 +209,11 @@ if(NANA_CMAKE_ENABLE_JPEG)
if (JPEG_FOUND)
include_directories( ${JPEG_INCLUDE_DIR})
list(APPEND NANA_LINKS ${JPEG_LIBRARY})
- add_definitions(-DUSE_LIBJPEG_FROM_OS)
+ add_definitions("-DNANA_ENABLE_JPEG"
+ "-DUSE_LIBJPEG_FROM_OS")
endif(JPEG_FOUND)
+ else()
+ add_definitions(-DNANA_ENABLE_JPEG)
endif(NANA_CMAKE_LIBJPEG_FROM_OS)
endif(NANA_CMAKE_ENABLE_JPEG)
@@ -232,8 +262,8 @@ if(NANA_CMAKE_VERBOSE_PREPROCESSOR)
add_definitions(-DVERBOSE_PREPROCESSOR)
endif(NANA_CMAKE_VERBOSE_PREPROCESSOR)
if(NANA_CMAKE_AUTOMATIC_GUI_TESTING)
- add_definitions(-DNANA_AUTOMATIC_GUI_TESTING)
- enable_testing ()
+ add_definitions(-DNANA_AUTOMATIC_GUI_TESTING)
+ enable_testing ()
endif(NANA_CMAKE_AUTOMATIC_GUI_TESTING)
@@ -266,7 +296,16 @@ foreach(subdir ${NANA_SOURCE_SUBDIRS})
# message("Subir: ${subdir}") # message("Files: ${sources}")
endforeach(subdir ${NANA_SOURCE_SUBDIRS})
-add_library(${PROJECT_NAME} ${sources} )
+if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
+ add_definitions(-fmax-errors=3)
+endif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
+
+if(NANA_CMAKE_SHARED_LIB)
+ add_library(${PROJECT_NAME} SHARED ${sources} )
+else()
+ add_library(${PROJECT_NAME} STATIC ${sources} )
+endif(NANA_CMAKE_SHARED_LIB)
+
target_include_directories(${PROJECT_NAME} PUBLIC ${NANA_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${NANA_LINKS})
@@ -276,32 +315,64 @@ target_link_libraries(${PROJECT_NAME} ${NANA_LINKS})
# Installing: the static "nana lib" will be in DESTDIR/CMAKE_INSTALL_PREFIX/lib/
# and the includes files "include/nana/" in DESTDIR/CMAKE_INSTALL_PREFIX/include/nana/
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib
- LIBRARY DESTINATION lib)
-message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib")
-# Install the include directories too.
-if(NANA_CMAKE_INSTALL_INCLUDES)
- install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include )
- message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
-endif(NANA_CMAKE_INSTALL_INCLUDES)
+ LIBRARY DESTINATION lib
+ RUNTIME DESTINATION bin)
set_property( TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14 )
+if (NANA_CMAKE_SHARED_LIB)
+ if (WIN32)
+ set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+
+ if (DLLTOOL)
+ #message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}")
+
+ #generate the lib and def files needed by msvc
+ set_target_properties (${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}"
+ ARCHIVE_OUTPUT_NAME "${PROJECT_NAME}"
+ LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} -Wl,--output-def=${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.def")
+
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ COMMAND echo " Generating import library"
+ COMMAND "${DLLTOOL}" --dllname "lib${PROJECT_NAME}.dll"
+ --input-def "lib${PROJECT_NAME}.def"
+ --output-lib "lib${PROJECT_NAME}.lib")
+
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.def"
+ "${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.lib" DESTINATION lib)
+ endif ()
+
+ endif (WIN32)
+endif (NANA_CMAKE_SHARED_LIB)
+
+message ("")
+message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib")
+# Install the include directories too.
+if(NANA_CMAKE_INSTALL_INCLUDES)
+ install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include )
+ message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
+endif(NANA_CMAKE_INSTALL_INCLUDES)
+
+
# Just for information:
-message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID})
-message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG})
-message ( "CMAKE_COMPILER_IS_GNUCXX= " ${CMAKE_COMPILER_IS_GNUCXX})
-message ( "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS})
-message ( "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS})
-message ( "CMAKE_STATIC_LINKER_FLAGS=" ${CMAKE_STATIC_LINKER_FLAGS})
-message ( "NANA_LINKS = " ${NANA_LINKS})
-message ( "DESTDIR = " ${DESTDIR})
-message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX})
-message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR})
-message ( "CMAKE_CURRENT_SOURCE_DIR= " ${CMAKE_CURRENT_SOURCE_DIR})
-message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO})
+message ("")
+message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID})
+message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG})
+message ( "CMAKE_COMPILER_IS_GNUCXX = " ${CMAKE_COMPILER_IS_GNUCXX})
+message ( "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS})
+message ( "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS})
+message ( "CMAKE_STATIC_LINKER_FLAGS = " ${CMAKE_STATIC_LINKER_FLAGS})
+message ( "NANA_LINKS = " ${NANA_LINKS})
+message ( "DESTDIR = " ${DESTDIR})
+message ( "CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX})
+message ( "NANA_INCLUDE_DIR = " ${NANA_INCLUDE_DIR})
+message ( "CMAKE_CURRENT_SOURCE_DIR = " ${CMAKE_CURRENT_SOURCE_DIR})
+message ( "NANA_CMAKE_ENABLE_AUDIO = " ${NANA_CMAKE_ENABLE_AUDIO})
+message ( "NANA_CMAKE_SHARED_LIB = " ${NANA_CMAKE_SHARED_LIB})
message ( "NANA_CMAKE_FIND_BOOST_FILESYSTEM = " ${NANA_CMAKE_FIND_BOOST_FILESYSTEM})
message ( "NANA_CMAKE_BOOST_FILESYSTEM_FORCE = " ${NANA_CMAKE_BOOST_FILESYSTEM_FORCE})
message ( "NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT = " ${NANA_CMAKE_BOOST_FILESYSTEM_INCLUDE_ROOT})
message ( "NANA_CMAKE_BOOST_FILESYSTEM_LIB = " ${NANA_CMAKE_BOOST_FILESYSTEM_LIB})
message ( "NANA_CMAKE_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_AUTOMATIC_GUI_TESTING})
-message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING})
\ No newline at end of file
+message ( "NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING = " ${NANA_CMAKE_ADD_DEF_AUTOMATIC_GUI_TESTING})
diff --git a/build/codeblocks/nana.cbp b/build/codeblocks/nana.cbp
index c598a95d..18c78755 100644
--- a/build/codeblocks/nana.cbp
+++ b/build/codeblocks/nana.cbp
@@ -50,6 +50,7 @@
+
diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp
index a13b3bac..69b97c1f 100644
--- a/include/nana/gui/basis.hpp
+++ b/include/nana/gui/basis.hpp
@@ -91,6 +91,8 @@ namespace nana
substitute = 0x1A, //Ctrl+Z
escape = 0x1B,
space = 0x20, //Space
+ del = 0x7F, //Delete
+ os_del = del, //Deprecated
//The following names are intuitive name of ASCII control codes
select_all = start_of_headline,
@@ -106,8 +108,8 @@ namespace nana
os_ctrl = 0x11,
os_pageup = 0x21, os_pagedown,
os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down,
- os_insert = 0x2D, os_del ,
- os_end = 0x23 , os_home //Pos 1
+ os_insert = 0x2D,
+ os_end = 0x23, os_home //Pos 1
};
};
diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp
index 2ecabc78..15cbc694 100644
--- a/include/nana/gui/widgets/spinbox.hpp
+++ b/include/nana/gui/widgets/spinbox.hpp
@@ -61,6 +61,7 @@ namespace nana
void focus(graph_reference, const arg_focus&) override;
void mouse_wheel(graph_reference, const arg_wheel&) override;
+ void dbl_click(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse& arg) override;
diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp
index d0ac2f67..5f6dbc91 100644
--- a/include/nana/gui/widgets/textbox.hpp
+++ b/include/nana/gui/widgets/textbox.hpp
@@ -185,7 +185,7 @@ namespace nana
/// Appends an string. If `at_caret` is `true`, the string is inserted at the position of caret, otherwise, it is appended at end of the textbox.
textbox& append(const std::string& text, bool at_caret);
-
+ textbox& append(const std::wstring& text, bool at_caret);
/// Determines whether the text is line wrapped.
bool line_wrapped() const;
textbox& line_wrapped(bool);
diff --git a/include/nana/std_mutex.hpp b/include/nana/std_mutex.hpp
index 38c07aaf..55f486e4 100644
--- a/include/nana/std_mutex.hpp
+++ b/include/nana/std_mutex.hpp
@@ -14,8 +14,12 @@
#include
// http://lxr.free-electrons.com/source/include/uapi/asm-generic/errno.h#L53
//#define EPROTO 71 /* Protocol error */
+#ifdef _GLIBCXX_HAS_GTHREADS
+# include
+#else
#include
#include
+#endif
#else
#include
#include
diff --git a/include/nana/std_thread.hpp b/include/nana/std_thread.hpp
index e1df7ef7..87db1e5a 100644
--- a/include/nana/std_thread.hpp
+++ b/include/nana/std_thread.hpp
@@ -6,7 +6,11 @@
#if defined(NANA_ENABLE_MINGW_STD_THREADS_WITH_MEGANZ)
-#include
+#ifdef _GLIBCXX_HAS_GTHREADS
+# include
+#else
+# include
+#endif
#else
#include
namespace std
diff --git a/source/audio/detail/buffer_preparation.cpp b/source/audio/detail/buffer_preparation.cpp
index 82942846..febe3a77 100644
--- a/source/audio/detail/buffer_preparation.cpp
+++ b/source/audio/detail/buffer_preparation.cpp
@@ -78,7 +78,7 @@ namespace nana{ namespace audio
void buffer_preparation::revert(meta * m)
{
std::lock_guard lock(token_prepared_);
- bool if_signal = prepared_.empty();
+ auto const if_signal = prepared_.empty();
prepared_.emplace_back(m);
if(if_signal)
cond_prepared_.notify_one();
diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp
index 9b0e24e0..4e7c8a07 100644
--- a/source/gui/detail/bedrock_posix.cpp
+++ b/source/gui/detail/bedrock_posix.cpp
@@ -438,8 +438,8 @@ namespace detail
keysym = keyboard::os_arrow_left + (keysym - XK_Left); break;
case XK_Insert:
keysym = keyboard::os_insert; break;
- case XK_Delete:
- keysym = keyboard::os_del; break;
+ case XK_Delete: case XK_KP_Delete:
+ keysym = keyboard::del; break;
case XK_Shift_L: case XK_Shift_R: //shift
keysym = keyboard::os_shift; break;
case XK_Control_L: case XK_Control_R: //ctrl
diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp
index ebf32705..67f40ffe 100644
--- a/source/gui/detail/bedrock_windows.cpp
+++ b/source/gui/detail/bedrock_windows.cpp
@@ -775,6 +775,19 @@ namespace detail
if (thrd) thrd->event_window = prev_event_wd;
}
+ //Translate OS Virtual-Key into ASCII code
+ wchar_t translate_virtual_key(WPARAM vkey)
+ {
+ switch (vkey)
+ {
+ case VK_DELETE:
+ return 127;
+ case VK_DECIMAL:
+ return 46;
+ }
+ return static_cast(vkey);
+ }
+
LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT window_proc_value = 0;
@@ -1436,7 +1449,7 @@ namespace detail
arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast(msgwnd);
arg.ignore = false;
- arg.key = static_cast(wParam);
+ arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg);
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
@@ -1522,7 +1535,7 @@ namespace detail
arg_keyboard arg;
arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast(msgwnd);
- arg.key = static_cast(wParam);
+ arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg);
arg.ignore = false;
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp
index 6c3b7578..27357217 100644
--- a/source/gui/detail/window_layout.cpp
+++ b/source/gui/detail/window_layout.cpp
@@ -149,33 +149,34 @@ namespace nana
// reads the overlaps that are overlapped a rectangular block
bool window_layout::read_overlaps(core_window_t* wd, const nana::rectangle& vis_rect, std::vector& blocks)
{
+ auto const is_wd_root = (category::flags::root == wd->other.category);
wd_rectangle block;
while (wd->parent)
{
- auto & siblings = wd->parent->children;
- //It should be checked that whether the window is still a chlid of its parent.
- if (siblings.size())
+ auto i = std::find(wd->parent->children.cbegin(), wd->parent->children.cend(), wd);
+ if (i != wd->parent->children.cend())
{
- auto i = &(siblings[0]);
- auto *end = i + siblings.size();
- i = std::find(i, end, wd);
- if (i != end)
+ for (++i; i != wd->parent->children.cend(); ++i)
{
- //find the widget that next to wd.
- for (++i; i < end; ++i)
+ core_window_t* cover = *i;
+
+ if (!cover->visible)
+ continue;
+
+ if (is_wd_root ?
+ (category::flags::root == cover->other.category)
+ :
+ ((category::flags::root != cover->other.category) && (nullptr == cover->effect.bground)))
{
- core_window_t* cover = *i;
- if ((category::flags::root != cover->other.category) && cover->visible && (nullptr == cover->effect.bground))
+ if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
{
- if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
- {
- block.window = cover;
- blocks.push_back(block);
- }
+ block.window = cover;
+ blocks.push_back(block);
}
}
}
}
+
wd = wd->parent;
}
return (!blocks.empty());
diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp
index c3fa7fb0..96f1e1c6 100644
--- a/source/gui/filebox.cpp
+++ b/source/gui/filebox.cpp
@@ -435,20 +435,20 @@ namespace nana
nodes_.filesystem = tree_.insert("FS.ROOT", "Filesystem");
nodes_.filesystem.value(kind::filesystem);
- std::vector paths;
- paths.emplace_back(fs_ext::path_user().native());
- paths.emplace_back("/");
+ std::vector> paths;
+ paths.emplace_back(fs_ext::path_user().native(), nodes_.home);
+ paths.emplace_back("/", nodes_.filesystem);
fs::directory_iterator end;
for (auto & p : paths)
{
- for (fs::directory_iterator i(p); i != end; ++i)
+ for (fs::directory_iterator i{p.first}; i != end; ++i)
{
auto name = i->path().filename().native();
if (!is_directory(i->status()) || (name.size() && name[0] == '.'))
continue;
- item_proxy node = tree_.insert(nodes_.filesystem, name, name);
+ item_proxy node = tree_.insert(p.second, name, name);
if (false == node.empty())
{
node.value(kind::filesystem);
@@ -569,28 +569,63 @@ namespace nana
if(cat_path.size() && cat_path[cat_path.size() - 1] != '/')
cat_path += '/';
+
auto beg = head.size();
while(true)
{
auto pos = path.find('/', beg);
auto folder = path.substr(beg, pos != path.npos ? pos - beg: path.npos);
- if(folder.size() == 0) break;
+
+ if(folder.empty())
+ break;
+
(cat_path += folder) += '/';
(head += folder) += '/';
path_.caption(cat_path);
- for(fs::directory_iterator i(head); i != end; ++i)
+ try
{
- if (is_directory(*i))
- path_.childset(i->path().filename().native(), 0);
+ for(fs::directory_iterator i(head); i != end; ++i)
+ {
+ if (is_directory(*i))
+ path_.childset(i->path().filename().native(), 0);
+ }
+ }
+ catch(fs::filesystem_error&)
+ {
+ //The directory iterator may throw filesystem_error when
+ //the user doesn't have permission to access the directory.
+
+ //It just loads the sub-directories
+ //to the category path.
}
if(pos == path.npos)
break;
beg = pos + 1;
}
- _m_load_path(path);
- _m_list_fs();
+
+ try
+ {
+ _m_load_path(path);
+ _m_list_fs();
+ }
+ catch(fs::filesystem_error&)
+ {
+ file_container_.clear();
+
+ drawing dw{ls_file_};
+ dw.clear();
+ dw.draw([](paint::graphics& graph){
+ std::string text = "Permission denied to access the directory";
+ auto txt_sz = graph.text_extent_size(text);
+ auto sz = graph.size();
+
+ graph.string({static_cast(sz.width - txt_sz.width) / 2, static_cast(sz.height - txt_sz.height) / 2}, text, colors::dark_gray);
+ });
+
+ ls_file_.clear();
+ }
}
bool _m_filter_allowed(const std::string& name, bool is_dir, const std::string& filter, const std::vector* extension) const
@@ -611,6 +646,8 @@ namespace nana
void _m_list_fs()
{
+ drawing{ls_file_}.clear();
+
auto filter = filter_.caption();
ls_file_.auto_draw(false);
@@ -829,14 +866,28 @@ namespace nana
auto child = node.append(name, name, kind::filesystem);
if(!child.empty())
{
- for(fs::directory_iterator u(i->path()); u != end; ++u)
+ //The try-catch can be eleminated by using
+ //directory_iterator( const std::filesystem::path& p, std::error_code& ec ) noexcept;
+ //in C++17
+ try
{
- auto uname = i->path().filename().native();
- if ((!is_directory(*i)) || (uname.size() && uname[0] == '.'))
- continue;
+ for(fs::directory_iterator u(i->path()); u != end; ++u)
+ {
+ auto uname = u->path().filename().native();
+ if ((!is_directory(*u)) || (uname.size() && uname[0] == '.'))
+ continue;
- child.append(uname, uname, kind::filesystem);
- break;
+ child.append(uname, uname, kind::filesystem);
+ break;
+ }
+ }
+ catch(fs::filesystem_error&)
+ {
+ //The directory iterator may throw filesystem_error when
+ //the user doesn't have permission to access the directory.
+
+ //Catch the error without any process, because the loop is just
+ //to peak whether the directory(i->path) has a sub-directory.
}
}
}
diff --git a/source/gui/widgets/menubar.cpp b/source/gui/widgets/menubar.cpp
index a14db116..5071c094 100644
--- a/source/gui/widgets/menubar.cpp
+++ b/source/gui/widgets/menubar.cpp
@@ -169,7 +169,7 @@ namespace nana
}
- std::size_t find(unsigned long shortkey) const
+ std::size_t find(wchar_t shortkey) const
{
if (shortkey)
{
@@ -262,7 +262,7 @@ namespace nana
return *ess_;
}
- void trigger::attached(widget_reference widget, graph_reference graph)
+ void trigger::attached(widget_reference widget, graph_reference)
{
ess_->widget_ptr = &widget;
}
@@ -403,8 +403,15 @@ namespace nana
ess_->state.nullify_mouse = true;
auto & menu_ptr = ess_->state.menu;
+
+ //menu_wd will be assigned with the handle of a menu window,
+ //It is used for checking whether the menu is closed. A menu handler
+ //may close the form, checking with the data member of this trigger
+ //is invalid, because the form is closed, the object of menubar may not exist.
+ window menu_wd = nullptr;
if(ess_->state.menu)
{
+ menu_wd = menu_ptr->handle();
switch(arg.key)
{
case keyboard::os_arrow_down:
@@ -466,8 +473,11 @@ namespace nana
case keyboard::os_arrow_up:
case keyboard::os_arrow_down:
case keyboard::enter:
- if(ess_->open_menu(true))
+ if (ess_->open_menu(true))
+ {
+ menu_wd = menu_ptr->handle();
menu_ptr->goto_next(true);
+ }
break;
case keyboard::escape:
if(essence::behavior::focus == ess_->state.behave)
@@ -481,15 +491,21 @@ namespace nana
if(index != npos)
{
ess_->state.active = index;
- if(ess_->open_menu(true))
+ if (ess_->open_menu(true))
+ {
+ menu_wd = menu_ptr->handle();
menu_ptr->goto_next(true);
+ }
}
break;
}
}
- refresh(graph);
- API::dev::lazy_refresh();
+ if (API::is_window(menu_wd))
+ {
+ refresh(graph);
+ API::dev::lazy_refresh();
+ }
}
void trigger::key_release(graph_reference graph, const arg_keyboard& arg)
diff --git a/source/gui/widgets/progress.cpp b/source/gui/widgets/progress.cpp
index 5e66334b..20b46ddc 100644
--- a/source/gui/widgets/progress.cpp
+++ b/source/gui/widgets/progress.cpp
@@ -136,10 +136,8 @@ namespace nana
{
const unsigned border_px = substance::border_px;
- unsigned width = graph.width() - border_px * 2;
- unsigned height = graph.height() - border_px * 2;
-
rectangle rt_val{ graph.size() };
+ auto const width = rt_val.width - border_px * 2;
rt_val.pare_off(static_cast(border_px));
diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp
index f39638b2..fefaf1ed 100644
--- a/source/gui/widgets/skeletons/text_editor.cpp
+++ b/source/gui/widgets/skeletons/text_editor.cpp
@@ -556,6 +556,7 @@ namespace nana{ namespace widgets
virtual void merge_lines(std::size_t first, std::size_t second) = 0;
//Calculates how many lines the specified line of text takes with a specified pixels of width.
virtual void add_lines(std::size_t pos, std::size_t lines) = 0;
+ virtual void prepare() = 0;
virtual void pre_calc_line(std::size_t line, unsigned pixels) = 0;
virtual void pre_calc_lines(unsigned pixels) = 0;
virtual std::size_t take_lines() const = 0;
@@ -668,6 +669,12 @@ namespace nana{ namespace widgets
}
}
+ void prepare() override
+ {
+ auto const line_count = editor_.textbase().lines();
+ this->sections_.resize(line_count);
+ }
+
void pre_calc_line(std::size_t pos, unsigned) override
{
auto const & text = editor_.textbase().getline(pos);
@@ -781,6 +788,12 @@ namespace nana{ namespace widgets
}
}
+ void prepare() override
+ {
+ auto const lines = editor_.textbase().lines();
+ linemtr_.resize(lines);
+ }
+
void pre_calc_line(std::size_t line, unsigned pixels) override
{
const string_type& lnstr = editor_.textbase().getline(line);
@@ -1220,7 +1233,7 @@ namespace nana{ namespace widgets
case keyboard::os_pagedown:
_m_handle_move_key(arg);
break;
- case keyboard::os_del:
+ case keyboard::del:
// send delete to set_accept function
if (this->attr().editable && (!impl_->capacities.pred_acceptive || impl_->capacities.pred_acceptive(key)))
del();
@@ -1234,7 +1247,7 @@ namespace nana{ namespace widgets
void text_editor::typeface_changed()
{
- impl_->capacities.behavior->pre_calc_lines(width_pixels());
+ _m_reset_content_size(true);
}
void text_editor::indent(bool enb, std::function generator)
@@ -1676,7 +1689,7 @@ namespace nana{ namespace widgets
impl_->try_refresh = sync_graph::refresh;
//_m_put calcs the lines
- _m_reset_content_size(false);
+ _m_reset_content_size(true);
impl_->cview->sync(false);
}
}
@@ -2886,10 +2899,14 @@ namespace nana{ namespace widgets
auto text_lines = textbase().lines();
if (text_lines <= max_lines)
{
+ impl_->capacities.behavior->prepare();
+
+ auto const width_px = _m_width_px(true);
+
std::size_t lines = 0;
for (std::size_t i = 0; i < text_lines; ++i)
{
- impl_->capacities.behavior->pre_calc_line(i, csize.width);
+ impl_->capacities.behavior->pre_calc_line(i, width_px);
lines += impl_->capacities.behavior->take_lines(i);
if (lines > max_lines)
diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp
index 2fad022f..41b592f3 100644
--- a/source/gui/widgets/spinbox.cpp
+++ b/source/gui/widgets/spinbox.cpp
@@ -560,6 +560,12 @@ namespace nana
impl_->editor()->reset_caret();
API::dev::lazy_refresh();
}
+
+ void drawer::dbl_click(graph_reference, const arg_mouse& arg)
+ {
+ if (impl_->mouse_button(arg, true))
+ API::dev::lazy_refresh();
+ }
void drawer::mouse_down(graph_reference, const arg_mouse& arg)
{
@@ -599,7 +605,10 @@ namespace nana
{
impl_->editor()->respond_char(arg);
if (impl_->editor()->try_refresh())
+ {
+ impl_->draw_spins();
API::dev::lazy_refresh();
+ }
}
void drawer::resized(graph_reference, const arg_resized&)
diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp
index e29b0d88..de6e2dd9 100644
--- a/source/gui/widgets/textbox.cpp
+++ b/source/gui/widgets/textbox.cpp
@@ -435,7 +435,23 @@ namespace drawerbase {
}
return *this;
}
+ //a native wstring version textbox::append
+ textbox& textbox::append(const std::wstring& text, bool at_caret)
+ {
+ internal_scope_guard lock;
+ auto editor = get_drawer_trigger().editor();
+ if(editor)
+ {
+ if(at_caret == false)
+ editor->move_caret_end(false);
+ editor->put(text);
+
+ editor->try_refresh();
+ API::update_window(this->handle());
+ }
+ return *this;
+ }
/// Determine wheter the text is auto-line changed.
bool textbox::line_wrapped() const
{
diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp
index 906bd969..88468861 100644
--- a/source/gui/widgets/treebox.cpp
+++ b/source/gui/widgets/treebox.cpp
@@ -1825,7 +1825,6 @@ namespace nana
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
impl_->attr.tree_cont.for_each(shape.first, nl);
- bool has_redraw = false;
auto & node_state = impl_->node_state;
node_state.pressed_node = nl.node();
@@ -1834,21 +1833,17 @@ namespace nana
{
if(impl_->set_expanded(node_state.pressed_node, !node_state.pressed_node->value.second.expanded))
impl_->make_adjust(node_state.pressed_node, 0);
-
- has_redraw = true; //btw, don't select the node
}
-
- if ((!has_redraw) && (node_state.selected != node_state.pressed_node))
+ else if (node_state.selected != node_state.pressed_node)
{
impl_->set_selected(node_state.pressed_node);
- has_redraw = true;
}
+ else
+ return;
- if(has_redraw)
- {
- impl_->draw(true);
- API::dev::lazy_refresh();
- }
+
+ impl_->draw(true);
+ API::dev::lazy_refresh();
}
void trigger::mouse_up(graph_reference, const arg_mouse& arg)
diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp
index b7dd3426..c617b3ee 100644
--- a/source/paint/graphics.cpp
+++ b/source/paint/graphics.cpp
@@ -240,12 +240,16 @@ namespace paint
graphics::graphics(graphics&& other)
: impl_(std::move(other.impl_))
{
+ other.impl_.reset(new implementation);
}
graphics& graphics::operator=(graphics&& other)
{
if (this != &other)
+ {
impl_ = std::move(other.impl_);
+ other.impl_.reset(new implementation);
+ }
return *this;
}