diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 64b37d97..86b907a6 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -108,11 +108,16 @@ namespace std { { using namespace experimental::filesystem; } + +#ifndef __cpp_lib_experimental_filesystem +# define __cpp_lib_experimental_filesystem 201406 +#endif } // std #else # undef NANA_USING_STD_FILESYSTEM # define NANA_USING_STD_FILESYSTEM 1 + //Detects whether the compiler supports std::filesystem under current options # if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) || \ ((__cplusplus >= 201703L) && \ (defined(__clang__) && (__clang_major__ >= 7) || \ @@ -125,14 +130,11 @@ namespace std { using namespace std::experimental::filesystem; } } +# undef NANA_USING_STD_EXPERIMENTAL_FILESYSTEM +# define NANA_USING_STD_EXPERIMENTAL_FILESYSTEM # endif #endif - -#ifndef __cpp_lib_experimental_filesystem -# define __cpp_lib_experimental_filesystem 201406 -#endif - #if NANA_USING_NANA_FILESYSTEM #include @@ -558,7 +560,23 @@ namespace std { #endif } } // std +#else +//Implements the missing functions for various version of experimental/filesystem +# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) + namespace std + { + namespace filesystem + { + //Visual Studio 2017 + #if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \ + (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801)) + path weakly_canonical(const path& p); + path weakly_canonical(const path& p, std::error_code& err); + #endif + } + } +# endif #endif //NANA_USING_NANA_FILESYSTEM diff --git a/include/nana/gui/widgets/detail/tree_cont.hpp b/include/nana/gui/widgets/detail/tree_cont.hpp index 3aa3b4f9..e2373bb5 100644 --- a/include/nana/gui/widgets/detail/tree_cont.hpp +++ b/include/nana/gui/widgets/detail/tree_cont.hpp @@ -1,6 +1,6 @@ /* * A Tree Container class implementation - * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -193,6 +193,11 @@ namespace detail node_type* insert(const std::string& key, const element_type& elem) { auto node = _m_locate(key); + + //Doesn't return the root node + if (node == &root_) + return nullptr; + if(node) node->value.second = elem; return node; @@ -206,12 +211,14 @@ namespace detail node_type* find(const std::string& path) const { - return _m_locate(path); + auto p = _m_locate(path); + return (&root_ == p ? nullptr : p); } node_type* ref(const std::string& path) { - return _m_locate(path); + auto p = _m_locate(path); + return (&root_ == p ? nullptr : p); } unsigned indent_size(const node_type* node) const @@ -479,42 +486,42 @@ namespace detail return nullptr; } - // foreach elements of key. - // the root name "/" and "\\" are treated as a node. This is a feature that can easily support the UNIX-like path. template void _m_for_each(const ::std::string& key, Function function) const { - if(key.size()) + //Ignores separaters at the begin of key. + ::std::string::size_type beg = key.find_first_not_of("\\/"); + if (key.npos == beg) + return; + + auto end = key.find_first_of("\\/", beg); + + + while(end != ::std::string::npos) { - ::std::string::size_type beg = 0; - auto end = key.find_first_of("\\/"); - - while(end != ::std::string::npos) + if(beg != end) { - if(beg != end) - { - if(!function(key.substr(beg, end - beg))) - return; - } - - auto next = key.find_first_not_of("\\/", end); - - if ((next == ::std::string::npos) && end) + if(!function(key.substr(beg, end - beg))) return; - - if (0 == end) - { - if ((!function(key.substr(0, 1))) || (next == ::std::string::npos)) - return; - } - - beg = next; - end = key.find_first_of("\\/", beg); - } - function(key.substr(beg, key.size() - beg)); + auto next = key.find_first_not_of("\\/", end); + + if ((next == ::std::string::npos) && end) + return; + + if (0 == end) + { + if ((!function(key.substr(0, 1))) || (next == ::std::string::npos)) + return; + } + + beg = next; + end = key.find_first_of("\\/", beg); + } + + function(key.substr(beg, key.size() - beg)); } template diff --git a/include/nana/gui/widgets/float_listbox.hpp b/include/nana/gui/widgets/float_listbox.hpp index 30492c27..ac842845 100644 --- a/include/nana/gui/widgets/float_listbox.hpp +++ b/include/nana/gui/widgets/float_listbox.hpp @@ -1,7 +1,7 @@ /** * A float_listbox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -46,8 +46,10 @@ namespace nana class item_renderer { public: - typedef widget& widget_reference; - typedef paint::graphics& graph_reference; + using widget_reference = widget&; + using graph_reference = paint::graphics&; + using item_interface = float_listbox::item_interface; + enum state_t{StateNone, StateHighlighted}; virtual ~item_renderer() = default; diff --git a/include/nana/gui/widgets/treebox.hpp b/include/nana/gui/widgets/treebox.hpp index bbf8fa85..fd48b022 100644 --- a/include/nana/gui/widgets/treebox.hpp +++ b/include/nana/gui/widgets/treebox.hpp @@ -480,6 +480,8 @@ namespace nana */ void scroll_into_view(item_proxy item); + /// Gets the current hovered node. + item_proxy hovered(bool exclude_expander) const; private: std::shared_ptr _m_scroll_operation() override; diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index 0eb56505..8be0cce9 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -1130,7 +1130,7 @@ namespace nana { namespace experimental { namespace filesystem ::fclose(stream); return bytes; } - ec.assign(static_cast(::errno), std::generic_category()); + ec.assign(static_cast(errno), std::generic_category()); #endif return static_cast(-1); } @@ -1265,7 +1265,7 @@ namespace std return p; // p.is_absolute() is true } - path absolute(const path& p, std::error_code& err) + path absolute(const path& p, std::error_code& /*err*/) { return absolute(p); } @@ -1350,7 +1350,7 @@ namespace std { //error if (nullptr == ec) throw (filesystem_error( - "nana::filesystem::canonical", p, + message, p, error_code(err_val, generic_category()))); else ec->assign(err_val, system_category()); @@ -1435,5 +1435,162 @@ namespace std }//end namespace filesystem }//end namespace std -#endif +#else //NANA_USING_NANA_FILESYSTEM +# if defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) + + //Defines the functions that are not provided by experimental/filesystem + namespace std + { + namespace filesystem + { + #if (defined(_MSC_VER) && (_MSC_VER > 1912)) || \ + (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 801)) + + namespace detail + { + bool try_throw(int err_val, const path& p, std::error_code* ec, const char* message) + { + if (0 == err_val) + { + if (ec) ec->clear(); + } + else + { //error + if (nullptr == ec) + throw (filesystem_error( + message, p, + error_code(err_val, generic_category()))); + else + ec->assign(err_val, system_category()); + } + return err_val != 0; + } + + path lexically_normal(path p) + { + if (p.empty()) + return p; + + std::vector elements; + + while (!p.empty()) + { + elements.emplace_back(p.filename()); + p.remove_filename(); + } + + auto start = elements.begin(); + auto last = elements.end(); + auto stop = last--; + for (auto itr(start); itr != stop; ++itr) + { + // ignore "." except at start and last + if (itr->native().size() == 1 + && (itr->native())[0] == '.' + && itr != start + && itr != last) continue; + + // ignore a name and following ".." + if (!p.empty() + && itr->native().size() == 2 + && (itr->native())[0] == '.' + && (itr->native())[1] == '.') // dot dot + { + auto lf(p.filename().native()); + if (lf.size() > 0 + && (lf.size() != 1 + || (lf[0] != '.' + && (lf[0] != '/' && lf[0] != '\\'))) + && (lf.size() != 2 + || (lf[0] != '.' + && lf[1] != '.' + # ifdef NANA_WINDOWS + && lf[1] != ':' + # endif + ) + ) + ) + { + p.remove_filename(); + auto next = itr; + if (p.empty() && ++next != stop + && next == last && last->string() == ".") + { + p /= "."; + } + continue; + } + } + + p /= *itr; + }; + + if (p.empty()) + p = "."; + return p; + } + } + + path weakly_canonical(const path& p, std::error_code* err) + { + path head{ p }; + + std::error_code tmp_err; + std::vector elements; + while (!head.empty()) + { + auto head_status = status(head, tmp_err); + + if (head_status.type() == file_type::unknown) + { + if (detail::try_throw(static_cast(errc::invalid_argument), head, err, "nana::filesystem::weakly_canonical")) + return path{}; + } + if (head_status.type() != file_type::not_found) + break; + + elements.emplace_back(head.filename()); + head.remove_filename(); + } + + bool tail_has_dots = false; + path tail; + + for (auto & e : elements) + { + tail /= e; + // for a later optimization, track if any dot or dot-dot elements are present + if (e.native().size() <= 2 + && e.native()[0] == '.' + && (e.native().size() == 1 || e.native()[1] == '.')) + tail_has_dots = true; + } + + if (head.empty()) + return detail::lexically_normal(p); + head = canonical(head, tmp_err); + if (detail::try_throw(tmp_err.value(), head, err, "nana::filesystem::weakly_canonical")) + return path(); + return tail.empty() + ? head + : (tail_has_dots // optimization: only normalize if tail had dot or dot-dot element + ? detail::lexically_normal(head / tail) + : head / tail); + } + + path weakly_canonical(const path& p) + { + return weakly_canonical(p, nullptr); + } + + path weakly_canonical(const path& p, std::error_code& err) + { + return weakly_canonical(p, &err); + } + #endif + } + } +# endif + +#endif //NANA_USING_NANA_FILESYSTEM diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index da3b2fb8..00e2052a 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -15,6 +15,7 @@ * Benjamin Navarro(pr#81) * besh81(pr#130) * dankan1890(pr#158) + * ErrorFlynn(pr#418) * */ #include @@ -5455,9 +5456,12 @@ namespace nana internal_scope_guard lock; if (_m_ess().lister.enable_ordered(enable)) + { _m_ess().update(); + return true; + } - return true; + return false; } void listbox::auto_draw(bool enabled) noexcept diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 35c8156b..377d0e7a 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -2371,6 +2371,19 @@ namespace nana API::refresh_window(*this); } + treebox::item_proxy treebox::hovered(bool exclude_expander) const + { + internal_scope_guard lock; + auto dw = &get_drawer_trigger(); + if (dw->impl()->node_state.pointed) + { + //Returns empty item_proxy if the mouse is on expander and exclude_expander is required. + if (exclude_expander && (dw->impl()->node_state.comp_pointed == drawerbase::treebox::component::expander)) + return item_proxy{}; + } + return item_proxy(const_cast(dw), dw->impl()->node_state.pointed); + } + std::shared_ptr treebox::_m_scroll_operation() { internal_scope_guard lock;