Merge branch 'hotfix-1.4.1' into develop

This commit is contained in:
Jinhao 2017-03-16 02:07:37 +08:00
commit 33424f0c75
24 changed files with 451 additions and 368 deletions

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_layout_file>
<FileVersion major="1" minor="0" />
<ActiveTarget name="Debug" />
</CodeBlocks_layout_file>

View File

@ -222,9 +222,6 @@ namespace detail
basic_window* focus{nullptr};
basic_window* menubar{nullptr};
bool ime_enabled{false};
#if defined(NANA_WINDOWS)
cursor running_cursor{ nana::cursor::arrow };
#endif
cursor state_cursor{nana::cursor::arrow};
basic_window* state_cursor_window{ nullptr };

View File

@ -292,7 +292,7 @@ namespace API
* @param window_handle A handle to the window to be refreshed.
*/
void refresh_window(window window_handle);
void refresh_window_tree(window); ///< Refreshs the specified window and all its children windows, then display it immediately
void refresh_window_tree(window); ///< Refreshes the specified window and all its children windows, then display it immediately
void update_window(window); ///< Copies the off-screen buffer to the screen for immediate display.
void window_caption(window, const std::string& title_utf8);

View File

@ -1,7 +1,7 @@
/**
* A Categorize 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

View File

@ -1,6 +1,6 @@
/*
* A Tree Container class implementation
* 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
@ -58,6 +58,31 @@ namespace detail
t = t_next;
}
}
bool is_ancestor_of(const tree_node* child) const
{
while (child)
{
if (child->owner == this)
return true;
child = child->owner;
}
return false;
}
tree_node * front() const
{
if (this->owner && (this != this->owner->child))
{
auto i = this->owner->child;
while (i->next != this)
i = i->next;
return i;
}
return nullptr;
}
};
template<typename UserData>
@ -76,12 +101,17 @@ namespace detail
~tree_cont()
{
clear();
clear(&root_);
}
void clear()
void clear(node_type* node)
{
remove(root_.child);
while (node->child)
{
//If there is a sibling of child, the root_.child
//will be assigned with the sibling.
remove(node->child);
}
}
bool verify(const node_type* node) const

View File

@ -122,7 +122,9 @@ namespace nana
void value(size_type s)
{
if (s + metrics_.range > metrics_.peak)
if (metrics_.range > metrics_.peak)
s = 0;
else if (s + metrics_.range > metrics_.peak)
s = metrics_.peak - metrics_.range;
if (graph_ && (metrics_.value != s))

View File

@ -1,7 +1,7 @@
/**
* A Spin box widget
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2015 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

View File

@ -37,7 +37,7 @@ namespace nana
{
enum class component
{
begin, expender = begin, crook, icon, text, bground, end
begin, expander = begin, crook, icon, text, bground, end
};
struct node_image_tag
@ -119,27 +119,17 @@ namespace nana
implement * impl() const;
void check(node_type*, checkstate);
bool draw();
const tree_cont_type & tree() const;
tree_cont_type & tree();
void renderer(::nana::pat::cloneable<renderer_interface>&&);
const ::nana::pat::cloneable<renderer_interface>& renderer() const;
void placer(::nana::pat::cloneable<compset_placer_interface>&&);
const ::nana::pat::cloneable<compset_placer_interface>& placer() const;
nana::any & value(node_type*) const;
node_type* insert(node_type*, const std::string& key, std::string&&);
node_type* insert(const std::string& path, std::string&&);
bool verify_kinship(node_type* parent, node_type* child) const;
void remove(node_type*);
node_type * selected() const;
void selected(node_type*);
void set_expand(node_type*, bool);
void set_expand(const ::std::string& path, bool);
node_image_tag& icon(const ::std::string&) const;
void icon_erase(const ::std::string&);
@ -201,6 +191,9 @@ namespace nana
/// Set the check state, and it returns itself.
item_proxy& check(bool);
/// Clears the child nodes
item_proxy& clear();
/// Return true when the node is expanded \todo change to expanded ??
bool expanded() const;

View File

@ -38,6 +38,8 @@ namespace system{
void get(std::string& text_utf8);
void get(std::wstring& text);
std::wstring wget();
private:
bool _m_set(format, const void* buf, std::size_t size, native_window_type);
void* _m_get(format, size_t& size);

View File

@ -30,7 +30,7 @@
#define STRING2(x) #x
#define STRING2(...) #__VA_ARGS__
#define STRING(x) STRING2(x)
#define SHOW_VALUE(x) " " #x " = " STRING2(x)

View File

@ -1,7 +1,7 @@
/*
* Platform Specification 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 Nana Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -1163,8 +1163,16 @@ namespace detail
// 2 = msg_dispatcher should ignore the msg, because the XEvent is processed by _m_msg_filter
int platform_spec::_m_msg_filter(XEvent& evt, msg_packet_tag& msg)
{
auto & bedrock = detail::bedrock::instance();
platform_spec & self = instance();
if(SelectionNotify == evt.type)
if(KeyPress == evt.type || KeyRelease == evt.type)
{
auto menu_wd = bedrock.get_menu(reinterpret_cast<native_window_type>(evt.xkey.window), true);
if(menu_wd)
evt.xkey.window = reinterpret_cast<Window>(menu_wd);
}
else if(SelectionNotify == evt.type)
{
if(evt.xselection.property)
{
@ -1197,7 +1205,6 @@ namespace detail
}
}
self.selection_.items.erase(self.selection_.items.begin());
std::lock_guard<decltype(im->cond_mutex)> lock(im->cond_mutex);
@ -1373,9 +1380,8 @@ namespace detail
{
Window child;
::XTranslateCoordinates(self.display_, self.root_window(), evt.xclient.window, x, y, &self.xdnd_.pos.x, &self.xdnd_.pos.y, &child);
typedef detail::bedrock bedrock;
auto wd = bedrock::instance().wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos.x, self.xdnd_.pos.y);
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos.x, self.xdnd_.pos.y);
if(wd && wd->flags.dropable)
{
accepted = true;

View File

@ -1,6 +1,6 @@
/*
* Message Dispatcher Implementation
* 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
@ -51,7 +51,7 @@ namespace detail
typedef std::list<msg_packet_tag> msg_queue_type;
msg_dispatcher(Display* disp)
: display_(disp), is_work_(false)
: display_(disp)
{
proc_.event_proc = 0;
proc_.timer_proc = 0;
@ -338,7 +338,7 @@ namespace detail
private:
Display * display_;
volatile bool is_work_;
volatile bool is_work_{ false };
std::unique_ptr<std::thread> thrd_;
struct table_tag

View File

@ -611,11 +611,18 @@ namespace detail
//If a root window is created during the mouse_down event, Nana.GUI will ignore the mouse_up event.
if (msgwnd->root != native_interface::get_focus_window())
{
//call the drawer mouse up event for restoring the surface graphics
msgwnd->set_action(mouse_action::normal);
auto pos = native_interface::cursor_position();
auto rootwd = native_interface::find_window(pos.x, pos.y);
native_interface::calc_window_point(rootwd, pos);
if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y))
{
//call the drawer mouse up event for restoring the surface graphics
msgwnd->set_action(mouse_action::normal);
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
wd_manager.do_lazy_refresh(msgwnd, false);
arg.evt_code = event_code::mouse_up;
draw_invoker(&drawer::mouse_up, msgwnd, arg, &context);
wd_manager.do_lazy_refresh(msgwnd, false);
}
}
}
else
@ -1147,7 +1154,7 @@ namespace detail
}
}
void bedrock::pump_event(window modal_window, bool /*is_modal*/)
void bedrock::pump_event(window condition_wd, bool is_modal)
{
thread_context * context = open_thread_context();
if(0 == context->window_count)
@ -1162,11 +1169,11 @@ namespace detail
auto & lock = wd_manager().internal_lock();
lock.revert();
native_window_type owner_native = 0;
native_window_type owner_native{};
core_window_t * owner = 0;
if(modal_window)
if(condition_wd && is_modal)
{
native_window_type modal = reinterpret_cast<core_window_t*>(modal_window)->root;
native_window_type modal = reinterpret_cast<core_window_t*>(condition_wd)->root;
owner_native = native_interface::get_owner_window(modal);
if(owner_native)
{
@ -1177,7 +1184,7 @@ namespace detail
}
}
nana::detail::platform_spec::instance().msg_dispatch(modal_window ? reinterpret_cast<core_window_t*>(modal_window)->root : 0);
nana::detail::platform_spec::instance().msg_dispatch(condition_wd ? reinterpret_cast<core_window_t*>(condition_wd)->root : 0);
if(owner_native)
{
@ -1190,7 +1197,7 @@ namespace detail
if(0 == --(context->event_pump_ref_count))
{
if(0 == modal_window || 0 == context->window_count)
if(0 == condition_wd || 0 == context->window_count)
remove_thread_context();
}

View File

@ -1,7 +1,7 @@
/**
* A Bedrock 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
@ -345,7 +345,7 @@ namespace detail
}
}
void bedrock::pump_event(window modal_window, bool is_modal)
void bedrock::pump_event(window condition_wd, bool is_modal)
{
const unsigned tid = ::GetCurrentThreadId();
auto context = this->open_thread_context(tid);
@ -365,9 +365,9 @@ namespace detail
try
{
MSG msg;
if(modal_window)
if (condition_wd)
{
HWND native_handle = reinterpret_cast<HWND>(reinterpret_cast<core_window_t*>(modal_window)->root);
HWND native_handle = reinterpret_cast<HWND>(reinterpret_cast<core_window_t*>(condition_wd)->root);
if (is_modal)
{
HWND owner = ::GetWindow(native_handle, GW_OWNER);
@ -437,27 +437,27 @@ namespace detail
}
catch(std::exception& e)
{
(msgbox(modal_window, "An uncaptured std::exception during message pumping: ").icon(msgbox::icon_information)
<<"\n in form: "<< API::window_caption(modal_window)
<<"\n exception : "<< e.what()
).show();
(msgbox(condition_wd, "An uncaptured std::exception during message pumping: ").icon(msgbox::icon_information)
<< "\n in form: " << API::window_caption(condition_wd)
<<"\n exception : "<< e.what()
).show();
internal_scope_guard lock;
_m_except_handler();
internal_scope_guard lock;
_m_except_handler();
intr_locker.forward();
if (0 == --(context->event_pump_ref_count))
{
if ((nullptr == modal_window) || (0 == context->window_count))
remove_thread_context();
}
throw;
intr_locker.forward();
if (0 == --(context->event_pump_ref_count))
{
if ((nullptr == condition_wd) || (0 == context->window_count))
remove_thread_context();
}
throw;
}
catch(...)
{
(msgbox(modal_window, "An exception during message pumping!").icon(msgbox::icon_information)
(msgbox(condition_wd, "An exception during message pumping!").icon(msgbox::icon_information)
<<"An uncaptured non-std exception during message pumping!"
<< "\n in form: " << API::window_caption(modal_window)
<< "\n in form: " << API::window_caption(condition_wd)
).show();
internal_scope_guard lock;
_m_except_handler();
@ -465,7 +465,7 @@ namespace detail
intr_locker.forward();
if(0 == --(context->event_pump_ref_count))
{
if((nullptr == modal_window) || (0 == context->window_count))
if ((nullptr == condition_wd) || (0 == context->window_count))
remove_thread_context();
}
throw;
@ -474,7 +474,7 @@ namespace detail
intr_locker.forward();
if(0 == --(context->event_pump_ref_count))
{
if((nullptr == modal_window) || (0 == context->window_count))
if ((nullptr == condition_wd) || (0 == context->window_count))
remove_thread_context();
}
}//end pump_event
@ -784,7 +784,7 @@ namespace detail
static auto& brock = bedrock::instance();
static restrict::TRACKMOUSEEVENT track = {sizeof track, 0x00000002};
auto native_window = reinterpret_cast<native_window_type>(root_window);
auto const native_window = reinterpret_cast<native_window_type>(root_window);
auto & wd_manager = brock.wd_manager();
auto* root_runtime = wd_manager.root_runtime(native_window);
@ -1720,9 +1720,16 @@ namespace detail
thrd->cursor.handle = ::LoadCursor(nullptr, translate(cur));
}
if (wd->root_widget->other.attribute.root->running_cursor != cur)
auto this_cur = reinterpret_cast<HCURSOR>(
#ifdef _WIN64
::GetClassLongPtr(reinterpret_cast<HWND>(wd->root), GCLP_HCURSOR)
#else
::GetClassLong(reinterpret_cast<HWND>(wd->root), GCL_HCURSOR)
#endif
);
if(this_cur != thrd->cursor.handle)
{
wd->root_widget->other.attribute.root->running_cursor = cur;
#ifdef _WIN64
::SetClassLongPtr(reinterpret_cast<HWND>(wd->root), GCLP_HCURSOR,
reinterpret_cast<LONG_PTR>(thrd->cursor.handle));
@ -1731,6 +1738,7 @@ namespace detail
static_cast<unsigned long>(reinterpret_cast<size_t>(thrd->cursor.handle)));
#endif
}
if (cursor::arrow == thrd->cursor.predef_cursor)
{
thrd->cursor.window = nullptr;
@ -1804,10 +1812,7 @@ namespace detail
undefine_state_cursor(wd, thrd);
if(wd == thrd->cursor.window)
{
set_cursor(wd, cursor::arrow, thrd);
wd->root_widget->other.attribute.root->running_cursor = cursor::arrow;
}
break;
default:
break;

View File

@ -80,19 +80,22 @@ namespace nana
internal_scope_guard lock;
if (dockers_)
{
for (auto i = dockers_->begin(), end = dockers_->end(); i != end; ++i)
{
if (reinterpret_cast<detail::docker_interface*>(evt) == *i)
{
//Checks whether this event is working now.
if (emitting_count_ > 1)
if (emitting_count_)
{
static_cast<docker_base*>(*i)->flag_deleted = true;
deleted_flags_ = true;
}
else
{
bedrock::instance().evt_operation().cancel(evt);
dockers_->erase(i);
delete reinterpret_cast<detail::docker_interface*>(evt);
}
break;
}
}
@ -131,7 +134,11 @@ namespace nana
for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();)
{
if (static_cast<docker_base*>(*i)->flag_deleted)
{
bedrock::instance().evt_operation().cancel(reinterpret_cast<event_handle>(*i));
delete (*i);
i = evt_->dockers_->erase(i);
}
else
++i;
}

View File

@ -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
@ -197,6 +197,13 @@ namespace nana{
return rectangle{ primary_monitor_size() };
}
#ifdef NANA_X11
//The XMoveWindow and XMoveResizeWindow don't take effect if the specified window is
//unmapped, and the members x and y of XSetSizeHints is obsoluted. So the position that
//set to a unmapped windows should be kept and use the position when the window is mapped.
std::map<Window, ::nana::point> exposed_positions; //locked by platform_scope_guard
#endif
//platform-dependent
native_interface::window_result native_interface::create_window(native_window_type owner, bool nested, const rectangle& r, const appearance& app)
{
@ -289,6 +296,7 @@ namespace nana{
{
win_attr.save_under = True;
attr_mask |= CWSaveUnder;
parent = restrict::spec.root_window();
calc_screen_point(owner, pos);
}
@ -303,7 +311,12 @@ namespace nana{
{
//make owner if it is a popup window
if((!nested) && owner)
{
restrict::spec.make_owner(owner, reinterpret_cast<native_window_type>(handle));
exposed_positions[handle] = pos;
}
XChangeWindowAttributes(disp, handle, attr_mask, &win_attr);
XTextProperty name;
char text[] = "Nana Window";
@ -655,6 +668,14 @@ namespace nana{
if(show)
{
::XMapWindow(disp, reinterpret_cast<Window>(wd));
auto i = exposed_positions.find(reinterpret_cast<Window>(wd));
if(i != exposed_positions.end())
{
::XMoveWindow(disp, reinterpret_cast<Window>(wd), i->second.x, i->second.y);
exposed_positions.erase(i);
}
Window grab = restrict::spec.grab(0);
if(grab == reinterpret_cast<Window>(wd))
capture_window(wd, true);
@ -882,13 +903,7 @@ namespace nana{
XWindowAttributes attr;
::XGetWindowAttributes(disp, reinterpret_cast<Window>(wd), &attr);
if(attr.map_state == IsUnmapped)
{
XSizeHints hints;
hints.flags = USPosition;
hints.x = x;
hints.y = y;
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
}
exposed_positions[reinterpret_cast<Window>(wd)] = ::nana::point{x, y};
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
#endif
@ -959,11 +974,11 @@ namespace nana{
::XGetWindowAttributes(disp, reinterpret_cast<Window>(wd), &attr);
if(attr.map_state == IsUnmapped)
{
hints.flags |= (USPosition | USSize);
hints.x = x;
hints.y = y;
hints.flags |= USSize;
hints.width = r.width;
hints.height = r.height;
exposed_positions[reinterpret_cast<Window>(wd)] = point{x, y};
}
if(hints.flags)

View File

@ -1,7 +1,7 @@
/*
* Window Manager 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
@ -685,6 +685,30 @@ namespace detail
}
}
void sync_child_root_display(window_manager::core_window_t* wd)
{
for (auto & child : wd->children)
{
if (category::flags::root != child->other.category)
{
sync_child_root_display(child);
continue;
}
auto const vs_parents = child->visible_parents();
if (vs_parents != child->visible)
{
native_interface::show_window(child->root, vs_parents, false);
}
else
{
if (child->visible != native_interface::is_window_visible(child->root))
native_interface::show_window(child->root, child->visible, false);
}
}
}
//show
//@brief: show or hide a window
bool window_manager::show(core_window_t* wd, bool visible)
@ -719,8 +743,15 @@ namespace detail
if(category::flags::root != wd->other.category)
bedrock::instance().event_expose(wd, visible);
if(nv)
if (nv)
{
if (visible && !wd->visible_parents())
return true;
native_interface::show_window(nv, visible, wd->flags.take_active);
}
sync_child_root_display(wd);
}
return true;
}
@ -1386,6 +1417,8 @@ namespace detail
void window_manager::remove_trash_handle(unsigned tid)
{
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
impl_->wd_register.delete_trash(tid);
}

View File

@ -618,7 +618,7 @@ namespace nana
place_.field_display(img_fields[i], false);
}
size({desc_extent.width, height });
move(API::make_center(this->owner(), desc_extent.width, height));
caption(title);
}

View File

@ -1,7 +1,7 @@
/*
* A Categorize 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
@ -343,7 +343,7 @@ namespace nana
{
if(tree_.get_root()->child)
{
tree_.clear();
tree_.clear(tree_.get_root());
return true;
}
return false;

View File

@ -747,7 +747,7 @@ namespace nana
//add a is_wd_parent_menu to determine whether the menu wants the focus.
//if a submenu gets the focus, the program may cause a crash error when the submenu is being destroyed
: base_type(wd, false, rectangle(pos, nana::size(2, 2)), appear::bald<appear::floating>()),
want_focus_{ (!wd) || ((!is_wd_parent_menu) && (API::focus_window() != wd)) },
want_focus_{ (!wd) || ((!is_wd_parent_menu) && (API::root(API::focus_window()) != API::root(wd))) },
event_focus_{ nullptr }
{
caption("nana menu window");
@ -991,6 +991,12 @@ namespace nana
case keyboard::enter:
this->pick();
break;
case keyboard::escape:
//Leave sub menu. But if the sub menu doesn't exist,
//close the menu.
if (!this->submenu(false))
close();
break;
default:
if (2 != send_shortkey(arg.key))
{
@ -1141,7 +1147,14 @@ namespace nana
throw std::out_of_range("menu: a new item inserted to an invalid position");
std::unique_ptr<item_type> item{ new item_type{ std::move(text_utf8), handler } };
impl_->mbuilder.data().items.emplace(impl_->mbuilder.data().items.cbegin() + pos, item.get());
items.emplace(
#ifdef _MSC_VER
items.cbegin() + pos,
#else
items.begin() + pos,
#endif
item.get());
return item_proxy{ pos, *item.release() };
}

View File

@ -2050,24 +2050,29 @@ namespace nana{ namespace widgets
void text_editor::paste()
{
std::wstring text;
nana::system::dataexch().get(text);
auto text = system::dataexch{}.wget();
//If it is required check the acceptable
if (accepts::no_restrict != impl_->capacities.acceptive)
if ((accepts::no_restrict != impl_->capacities.acceptive) || impl_->capacities.pred_acceptive)
{
for (auto i = text.begin(); i != text.end(); ++i)
{
if (!_m_accepts(*i))
if (_m_accepts(*i))
{
if (accepts::no_restrict == impl_->capacities.acceptive)
put(*i);
continue;
}
if (accepts::no_restrict != impl_->capacities.acceptive)
{
text.erase(i, text.end());
break;
put(std::move(text));
}
break;
}
}
if (!text.empty())
put(std::move(text));
}
void text_editor::enter(bool record_undo)
@ -2794,8 +2799,12 @@ namespace nana{ namespace widgets
bool text_editor::_m_accepts(char_type ch) const
{
if(accepts::no_restrict == impl_->capacities.acceptive)
if (accepts::no_restrict == impl_->capacities.acceptive)
{
if (impl_->capacities.pred_acceptive)
return impl_->capacities.pred_acceptive(ch);
return true;
}
//Checks the input whether it meets the requirement for a numeric.
auto str = text();

View File

@ -1,7 +1,7 @@
/*
* A Spin box widget
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2015 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
@ -295,13 +295,13 @@ namespace nana
return range_->value();
}
bool value(const ::std::string& value_str)
bool value(const ::std::string& value_str, bool reset_editor)
{
bool diff;
if (!range_->value(value_str, diff))
return false;
if (diff)
if (diff && reset_editor)
reset_text();
return true;
}
@ -572,7 +572,7 @@ namespace nana
{
if (impl_->editor()->respond_char(arg))
{
if (!impl_->value(to_utf8(impl_->editor()->text())))
if (!impl_->value(to_utf8(impl_->editor()->text()), false))
impl_->draw_spins();
API::dev::lazy_refresh();
@ -657,7 +657,7 @@ namespace nana
internal_scope_guard lock;
if (handle())
{
if (get_drawer_trigger().impl()->value(s))
if (get_drawer_trigger().impl()->value(s, true))
API::refresh_window(handle());
}
}

View File

@ -14,7 +14,6 @@
#include <nana/gui/element.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/system/platform.hpp>
#include <stdexcept>
#include <map>
namespace nana
@ -166,7 +165,7 @@ namespace nana
class trigger::item_locator
{
public:
typedef tree_cont_type::node_type node_type;
using node_type = tree_cont_type::node_type;
item_locator(implement * impl, int item_pos, int x, int y);
int operator()(node_type &node, int affect);
@ -199,7 +198,7 @@ namespace nana
template<typename Renderer>
struct trigger::basic_implement
{
typedef trigger::node_type node_type;
using node_type = trigger::node_type;
struct rep_tag
{
@ -216,11 +215,10 @@ namespace nana
{
nana::upoint border;
nana::scroll<true> scroll;
std::size_t prev_first_value;
mutable std::map<std::string, node_image_tag> image_table;
tree_cont_type::node_type * first;
tree_cont_type::node_type * first; //The node at the top of screen
int indent_pixels;
int offset_x;
}shape;
@ -235,9 +233,9 @@ namespace nana
{
tooltip_window * tooltip;
component comp_pointed;
tree_cont_type::node_type * pointed;
tree_cont_type::node_type * selected;
tree_cont_type::node_type * event_node;
node_type * pointed;
node_type * selected;
node_type * pressed_node;
}node_state;
struct track_node_tag
@ -260,7 +258,6 @@ namespace nana
data.widget_ptr = nullptr;
data.stop_drawing = false;
shape.prev_first_value = 0;
shape.first = nullptr;
shape.indent_pixels = 10;
shape.offset_x = 0;
@ -271,7 +268,7 @@ namespace nana
node_state.comp_pointed = component::end;
node_state.pointed = nullptr;
node_state.selected = nullptr;
node_state.event_node = nullptr;
node_state.pressed_node = nullptr;
track_node.key_time = 0;
@ -304,19 +301,58 @@ namespace nana
}
}
bool draw(bool scrollbar_react)
bool unlink(node_type* node, bool perf_clear)
{
if (!attr.tree_cont.verify(node))
return false;
if (node->is_ancestor_of(shape.first))
{
shape.first = node->front();
if (shape.first)
shape.first = node->owner;
}
if (node->is_ancestor_of(node_state.pointed))
node_state.pointed = nullptr;
if (node->is_ancestor_of(node_state.selected))
node_state.selected = nullptr;
if (perf_clear)
{
if (node->child)
{
attr.tree_cont.clear(node);
return true;
}
return false;
}
attr.tree_cont.remove(node);
return true;
}
bool draw(bool reset_scroll, bool ignore_update = false, bool ignore_auto_draw = false)
{
if(data.graph && (false == data.stop_drawing))
{
if(scrollbar_react)
if (reset_scroll)
show_scroll();
//Draw background
data.graph->rectangle(true, data.widget_ptr->bgcolor());
if (attr.auto_draw || ignore_auto_draw)
{
//Draw background
data.graph->rectangle(true, data.widget_ptr->bgcolor());
//Draw tree
attr.tree_cont.for_each(shape.first, Renderer(this, nana::point(static_cast<int>(attr.tree_cont.indent_size(shape.first) * shape.indent_pixels) - shape.offset_x, 1)));
return true;
//Draw tree
attr.tree_cont.for_each(shape.first, Renderer(this, nana::point(static_cast<int>(attr.tree_cont.indent_size(shape.first) * shape.indent_pixels) - shape.offset_x, 1)));
if (!ignore_update)
API::update_window(data.widget_ptr->handle());
return true;
}
}
return false;
}
@ -402,42 +438,45 @@ namespace nana
return nullptr;
}
static bool check_kinship(const node_type* parent, const node_type * child)
{
if((!parent) || (!child))
return false;
while(child && (child != parent))
child = child->owner;
return (nullptr != child);
}
bool make_adjust(node_type * node, int reason)
{
if(!node) return false;
auto & tree_container = attr.tree_cont;
auto & tree = attr.tree_cont;
auto const first_pos = tree.distance_if(shape.first, pred_allow_child{});
auto const node_pos = tree.distance_if(node, pred_allow_child{});
auto const max_allow = max_allowed();
switch(reason)
{
case 0:
//adjust if the node expanded and the number of its children are over the max number allowed
if(shape.first != node)
if (node->value.second.expanded)
{
unsigned child_size = tree_container.child_size_if(*node, pred_allow_child());
const std::size_t max_allow = max_allowed();
if(child_size < max_allow)
//adjust if the number of its children are over the max number allowed
if (shape.first != node)
{
unsigned off1 = tree_container.distance_if(shape.first, pred_allow_child());
unsigned off2 = tree_container.distance_if(node, pred_allow_child());
const unsigned size = off2 - off1 + child_size + 1;
if(size > max_allow)
shape.first = tree_container.advance_if(shape.first, size - max_allow, pred_allow_child());
auto child_size = tree.child_size_if(*node, pred_allow_child());
if (child_size < max_allow)
{
auto const size = node_pos - first_pos + child_size + 1;
if (size > max_allow)
shape.first = tree.advance_if(shape.first, size - max_allow, pred_allow_child{});
}
else
shape.first = node;
}
}
else
{
//The node is shrank
auto visual_size = visual_item_size();
if (visual_size > max_allow)
{
if (first_pos + max_allow > visual_size)
shape.first = tree.advance_if(nullptr, visual_size - max_allow, pred_allow_child{});
}
else
shape.first = node;
shape.first = nullptr;
}
break;
case 1:
@ -445,7 +484,7 @@ namespace nana
case 3:
//param is the begin pos of an item in absolute.
{
int beg = static_cast<int>(tree_container.indent_size(node) * shape.indent_pixels) - shape.offset_x;
int beg = static_cast<int>(tree.indent_size(node) * shape.indent_pixels) - shape.offset_x;
int end = beg + static_cast<int>(node_w_pixels(node));
bool take_adjust = false;
@ -468,16 +507,14 @@ namespace nana
case 4:
if(shape.first != node)
{
unsigned off_first = tree_container.distance_if(shape.first, pred_allow_child());
unsigned off_node = tree_container.distance_if(node, pred_allow_child());
if(off_node < off_first)
if (node_pos < first_pos)
{
shape.first = node;
return true;
}
else if(off_node - off_first > max_allowed())
else if (node_pos - first_pos > max_allow)
{
shape.first = tree_container.advance_if(0, off_node - max_allowed() + 1, pred_allow_child());
shape.first = tree.advance_if(nullptr, node_pos - max_allow + 1, pred_allow_child{});
return true;
}
}
@ -535,7 +572,7 @@ namespace nana
if(value == false)
{
//if contracting a parent of the selected node, select the contracted node.
if(check_kinship(node, node_state.selected))
if (node->is_ancestor_of(node_state.selected))
set_selected(node);
}
@ -543,7 +580,6 @@ namespace nana
if(node->child)
{
data.stop_drawing = true;
//attr.ext_event.expand(data.widget_ptr->handle(), item_proxy(data.trigger_ptr, node), value);
item_proxy iprx(data.trigger_ptr, node);
data.widget_ptr->events().expanded.emit(::nana::arg_treebox{ *data.widget_ptr, iprx, value }, data.widget_ptr->handle());
data.stop_drawing = false;
@ -573,44 +609,24 @@ namespace nana
{
if(scroll.empty())
{
shape.prev_first_value = 0;
scroll.create(*data.widget_ptr, nana::rectangle(data.graph->width() - 16, 0, 16, data.graph->height()));
auto fn = [this](const arg_mouse& arg){
this->event_scrollbar(arg);
};
auto & events = scroll.events();
events.mouse_down(fn);
events.mouse_move(fn);
events.mouse_wheel(fn);
scroll.events().value_changed.connect_unignorable([this](const arg_scroll& arg)
{
adjust.scroll_timestamp = nana::system::timestamp();
adjust.timer.start();
shape.first = attr.tree_cont.advance_if(nullptr, shape.scroll.value(), pred_allow_child{});
draw(false, false, true);
});
}
scroll.amount(visual_items);
scroll.range(max_allow);
}
scroll.value(attr.tree_cont.distance_if(shape.first, pred_allow_child()));
}
void event_scrollbar(const arg_mouse& arg)
{
if((event_code::mouse_wheel == arg.evt_code) || arg.is_left_button())
{
if(shape.prev_first_value != shape.scroll.value())
{
shape.prev_first_value = shape.scroll.value();
adjust.scroll_timestamp = nana::system::timestamp();
adjust.timer.start();
shape.first = attr.tree_cont.advance_if(nullptr, shape.prev_first_value, pred_allow_child());
if(arg.window_handle == shape.scroll.handle())
{
draw(false);
API::update_window(data.widget_ptr->handle());
}
}
}
auto pos = attr.tree_cont.distance_if(shape.first, pred_allow_child{});
scroll.value(pos);
}
std::size_t visual_item_size() const
@ -672,11 +688,10 @@ namespace nana
attr.tree_cont.template for_each<item_locator&>(shape.first, nl);
bool redraw = false;
node_state.event_node = nl.node();
if(nl.node() && (nl.what() != component::end))
auto const node = nl.node();
if (node && (nl.what() != component::end))
{
if((nl.what() != node_state.comp_pointed || nl.node() != node_state.pointed))
if ((nl.what() != node_state.comp_pointed) || (node != node_state.pointed))
{
node_state.comp_pointed = nl.what();
@ -685,12 +700,11 @@ namespace nana
item_proxy iprx(data.trigger_ptr, node_state.pointed);
data.widget_ptr->events().hovered.emit(::nana::arg_treebox{ *data.widget_ptr, iprx, false }, data.widget_ptr->handle());
if (nl.node() != node_state.pointed)
if (node != node_state.pointed)
close_tooltip_window();
}
node_state.pointed = nl.node();
node_state.pointed = node;
item_proxy iprx(data.trigger_ptr, node_state.pointed);
data.widget_ptr->events().hovered.emit(::nana::arg_treebox{ *data.widget_ptr, iprx, true }, data.widget_ptr->handle());
@ -751,11 +765,11 @@ namespace nana
};
auto & events = node_state.tooltip->events();
events.mouse_leave(fn);
events.mouse_move(fn);
events.mouse_down.connect(fn);
events.mouse_up.connect(fn);
events.dbl_click.connect(fn);
events.mouse_leave.connect_unignorable(fn);
events.mouse_move.connect_unignorable(fn);
events.mouse_down.connect_unignorable(fn);
events.mouse_up.connect_unignorable(fn);
events.dbl_click.connect_unignorable(fn);
}
}
@ -866,7 +880,18 @@ namespace nana
item_proxy& item_proxy::check(bool ck)
{
trigger_->check(node_, ck ? checkstate::checked : checkstate::unchecked);
trigger_->draw();
trigger_->impl()->draw(false);
return *this;
}
item_proxy& item_proxy::clear()
{
if (node_)
{
auto impl = trigger_->impl();
if(impl->unlink(node_, true))
impl->draw(true);
}
return *this;
}
@ -879,10 +904,8 @@ namespace nana
{
auto * impl = trigger_->impl();
if(impl->set_expanded(node_, exp))
{
impl->draw(true);
API::update_window(impl->data.widget_ptr->handle());
}
return *this;
}
@ -895,10 +918,8 @@ namespace nana
{
auto * impl = trigger_->impl();
if(impl->set_selected(s ? node_ : nullptr))
{
impl->draw(true);
API::update_window(*impl->data.widget_ptr);
}
return *this;
}
@ -1133,7 +1154,7 @@ namespace nana
{
switch(comp)
{
case component_t::expender:
case component_t::expander:
if(attr.has_children)
{
r->width = item_offset;
@ -1222,7 +1243,7 @@ namespace nana
void expander(graph_reference graph, const compset_interface * compset) const override
{
comp_attribute_t attr;
if(compset->comp_attribute(component::expender, attr))
if(compset->comp_attribute(component::expander, attr))
{
facade<element::arrow> arrow("solid_triangle");
arrow.direction(direction::southeast);
@ -1323,29 +1344,31 @@ namespace nana
node_r.width = comp_placer->item_width(*impl_->data.graph, node_attr_);
node_r.height = comp_placer->item_height(*impl_->data.graph);
if(pos_.y < item_pos_.y + static_cast<int>(node_r.height))
if ((pos_.y < item_pos_.y + static_cast<int>(node_r.height)) && (pos_.y >= item_pos_.y))
{
auto logic_pos = pos_ - item_pos_;
node_ = &node;
auto const logic_pos = pos_ - item_pos_;
for(int comp = static_cast<int>(component::begin); comp != static_cast<int>(component::end); ++comp)
for (int comp = static_cast<int>(component::begin); comp != static_cast<int>(component::end); ++comp)
{
nana::rectangle r = node_r;
if(comp_placer->locate(static_cast<component>(comp), node_attr_, &r))
if (!comp_placer->locate(static_cast<component>(comp), node_attr_, &r))
continue;
if (r.is_hit(logic_pos))
{
if(r.is_hit(logic_pos))
{
what_ = static_cast<component>(comp);
if(component::expender == what_ && (false == node_attr_.has_children))
what_ = component::end;
node_ = &node;
what_ = static_cast<component>(comp);
if (component::expander == what_ && (false == node_attr_.has_children))
what_ = component::end;
if(component::text == what_)
node_text_r_ = r;
if (component::text == what_)
node_text_r_ = r;
return 0;
}
break;
}
}
return 0; //Stop iterating
}
item_pos_.y += node_r.height;
@ -1530,7 +1553,6 @@ namespace nana
}
impl_->draw(false);
API::update_window(impl_->data.widget_ptr->handle());
if (impl_->node_state.tooltip)
{
@ -1629,26 +1651,6 @@ namespace nana
}
}
bool trigger::draw()
{
if (!impl_->attr.auto_draw)
return false;
if(impl_->draw(false))
API::update_window(impl_->data.widget_ptr->handle());
return true;
}
auto trigger::tree() -> tree_cont_type &
{
return impl_->attr.tree_cont;
}
auto trigger::tree() const -> tree_cont_type const &
{
return impl_->attr.tree_cont;
}
void trigger::renderer(::nana::pat::cloneable<renderer_interface>&& r)
{
impl_->data.renderer = std::move(r);
@ -1669,14 +1671,6 @@ namespace nana
return impl_->data.comp_placer;
}
nana::any & trigger::value(node_type* node) const
{
if(impl_->attr.tree_cont.verify(node) == false)
throw std::invalid_argument("Nana.GUI.treebox.value() invalid node");
return node->value.second.value;
}
trigger::node_type* trigger::insert(node_type* node, const std::string& key, std::string&& title)
{
node_type * p = impl_->attr.tree_cont.node(node, key);
@ -1685,49 +1679,20 @@ namespace nana
else
p = impl_->attr.tree_cont.insert(node, key, treebox_node_type(std::move(title)));
if(p && impl_->attr.auto_draw && impl_->draw(true))
API::update_window(impl_->data.widget_ptr->handle());
if (p)
impl_->draw(true);
return p;
}
trigger::node_type* trigger::insert(const std::string& path, std::string&& title)
{
auto x = impl_->attr.tree_cont.insert(path, treebox_node_type(std::move(title)));
if(x && impl_->attr.auto_draw && impl_->draw(true))
API::update_window(impl_->data.widget_ptr->handle());
if (x)
impl_->draw(true);
return x;
}
bool trigger::verify_kinship(node_type* parent, node_type* child) const
{
if(false == (parent && child)) return false;
while(child && (child != parent))
child = child->owner;
return (nullptr != child);
}
void trigger::remove(node_type* node)
{
if (!tree().verify(node))
return;
auto & shape = impl_->shape;
auto & node_state = impl_->node_state;
if(verify_kinship(node, node_state.event_node))
node_state.event_node = nullptr;
if(verify_kinship(node, shape.first))
shape.first = nullptr;
if(verify_kinship(node, node_state.selected))
node_state.selected = nullptr;
impl_->attr.tree_cont.remove(node);
}
trigger::node_type* trigger::selected() const
{
return impl_->node_state.selected;
@ -1735,29 +1700,8 @@ namespace nana
void trigger::selected(node_type* node)
{
if(tree().verify(node) && impl_->set_selected(node))
{
if(impl_->draw(true))
API::update_window(impl_->data.widget_ptr->handle());
}
}
void trigger::set_expand(node_type* node, bool exp)
{
if((impl_->data.widget_ptr) && impl_->set_expanded(node, exp))
{
if(impl_->attr.tree_cont.verify(node) && impl_->set_selected(node))
impl_->draw(true);
API::update_window(impl_->data.widget_ptr->handle());
}
}
void trigger::set_expand(const std::string& path, bool exp)
{
if(impl_->set_expanded(impl_->attr.tree_cont.find(path), exp))
{
impl_->draw(true);
API::update_window(impl_->data.widget_ptr->handle());
}
}
node_image_tag& trigger::icon(const std::string& id) const
@ -1780,12 +1724,12 @@ namespace nana
void trigger::node_icon(node_type* node, const std::string& id)
{
if(tree().verify(node))
if(impl_->attr.tree_cont.verify(node))
{
node->value.second.img_idstr = id;
auto i = impl_->shape.image_table.find(id);
if((i != impl_->shape.image_table.end()) && impl_->draw(true))
API::update_window(impl_->data.widget_ptr->handle());
if (i != impl_->shape.image_table.end())
impl_->draw(true);
}
}
@ -1798,7 +1742,7 @@ namespace nana
bool trigger::rename(node_type *node, const char* key, const char* name)
{
if((key || name ) && tree().verify(node))
if((key || name ) && impl_->attr.tree_cont.verify(node))
{
if(key && (key != node->value.first))
{
@ -1831,7 +1775,8 @@ namespace nana
void trigger::refresh(graph_reference)
{
impl_->draw(false);
//Don't reset the scroll and update the window
impl_->draw(false, true);
}
void trigger::dbl_click(graph_reference, const arg_mouse& arg)
@ -1842,12 +1787,21 @@ namespace nana
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
if(nl.node() && (nl.what() == component::text || nl.what() == component::icon))
auto const node = nl.node();
if (!node)
return;
auto & node_state = impl_->node_state;
switch (nl.what())
{
impl_->node_state.event_node = nl.node();
impl_->set_expanded(impl_->node_state.event_node, !impl_->node_state.event_node->value.second.expanded);
impl_->draw(true);
case component::icon:
case component::text:
impl_->set_expanded(node, !node->value.second.expanded);
impl_->draw(true, true, false);
API::dev::lazy_refresh();
break;
default:
break;
}
}
@ -1862,34 +1816,20 @@ namespace nana
bool has_redraw = false;
auto & node_state = impl_->node_state;
node_state.event_node = nullptr;
node_state.pressed_node = nl.node();
if(nl.node())
if (node_state.pressed_node && (component::expander == nl.what()))
{
node_state.event_node = nl.node();
if(nl.what() != component::end)
{
if(nl.what() == component::expender)
{
if(impl_->set_expanded(node_state.event_node, !node_state.event_node->value.second.expanded))
impl_->make_adjust(node_state.event_node, 0);
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;
}
else if(nl.item_body())
{
if(node_state.selected != node_state.event_node)
{
impl_->set_selected(node_state.event_node);
has_redraw = true;
}
}
}
else if(node_state.selected != node_state.event_node)
{
impl_->set_selected(node_state.event_node);
has_redraw = true;
}
has_redraw = true; //btw, don't select the node
}
if ((!has_redraw) && (node_state.selected != node_state.pressed_node))
{
impl_->set_selected(node_state.pressed_node);
has_redraw = true;
}
if(has_redraw)
@ -1907,25 +1847,33 @@ namespace nana
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
auto const pressed_node = impl_->node_state.pressed_node;
impl_->node_state.pressed_node = nullptr;
if(!nl.node())
return;
if((impl_->node_state.selected != nl.node()) && nl.item_body())
if (pressed_node == nl.node())
{
impl_->set_selected(nl.node());
if(impl_->make_adjust(impl_->node_state.selected, 1))
impl_->adjust.scroll_timestamp = 1;
}
else if (nl.what() == component::crook)
{
checkstate cs = checkstate::unchecked;
if (checkstate::unchecked == nl.node()->value.second.checked)
cs = checkstate::checked;
if ((impl_->node_state.selected != nl.node()) && nl.item_body())
{
impl_->set_selected(nl.node());
if (impl_->make_adjust(impl_->node_state.selected, 1))
impl_->adjust.scroll_timestamp = 1;
}
else if (nl.what() == component::crook)
{
checkstate cs = checkstate::unchecked;
if (checkstate::unchecked == nl.node()->value.second.checked)
cs = checkstate::checked;
check(nl.node(), cs);
check(nl.node(), cs);
}
else
return; //Do not refresh
}
else
return; //Do not refresh
return; //Don't refresh
impl_->draw(true);
API::dev::lazy_refresh();
@ -1942,18 +1890,19 @@ namespace nana
void trigger::mouse_wheel(graph_reference, const arg_wheel& arg)
{
auto & shape = impl_->shape;
std::size_t prev = shape.prev_first_value;
auto & scroll = impl_->shape.scroll;
if (scroll.empty())
return;
shape.scroll.make_step(!arg.upwards);
auto const value_before = scroll.value();
impl_->event_scrollbar(arg);
scroll.make_step(!arg.upwards);
if(prev != shape.prev_first_value)
if (value_before != scroll.value())
{
impl_->track_mouse(arg.pos.x, arg.pos.y);
impl_->draw(false);
impl_->draw(false, true, true);
API::dev::lazy_refresh();
}
}
@ -2168,7 +2117,7 @@ namespace nana
if (comp_placer->enabled(component::crook) != enable)
{
comp_placer->enable(component::crook, enable);
get_drawer_trigger().draw();
impl->draw(false);
}
return *this;
}
@ -2181,8 +2130,8 @@ namespace nana
void treebox::clear()
{
auto impl = get_drawer_trigger().impl();
impl->attr.tree_cont.clear();
get_drawer_trigger().draw();
if (impl->unlink(impl->attr.tree_cont.get_root(), true))
impl->draw(true);
}
treebox::node_image_type& treebox::icon(const std::string& id) const
@ -2198,7 +2147,7 @@ namespace nana
auto treebox::find(const std::string& keypath) -> item_proxy
{
auto * trg = &get_drawer_trigger();
return item_proxy(trg, trg->tree().find(keypath));
return item_proxy(trg, trg->impl()->attr.tree_cont.find(keypath));
}
treebox::item_proxy treebox::insert(const std::string& path_key, std::string title)
@ -2214,20 +2163,21 @@ namespace nana
treebox::item_proxy treebox::erase(item_proxy i)
{
auto next = i.sibling();
get_drawer_trigger().remove(i._m_node());
if (get_drawer_trigger().impl()->unlink(i._m_node(), false))
get_drawer_trigger().impl()->draw(true);
return next;
}
void treebox::erase(const std::string& keypath)
{
auto i = find(keypath);
if(!i.empty())
get_drawer_trigger().remove(i._m_node());
if (!i.empty())
this->erase(i);
}
std::string treebox::make_key_path(item_proxy i, const std::string& splitter) const
{
auto & tree = get_drawer_trigger().tree();
auto & tree = get_drawer_trigger().impl()->attr.tree_cont;
auto pnode = i._m_node();
if(tree.verify(pnode))
{

View File

@ -118,6 +118,7 @@ namespace nana{ namespace system{
static_cast<void>(g); //eliminate unused parameter compiler warning.
static_cast<void>(owner);
throw std::logic_error("dataexch::set(const paint::graphics&, native_window_type owner) not implemented yet.");
return false;
#endif
}
@ -183,6 +184,14 @@ namespace nana{ namespace system{
#endif
}
}
std::wstring dataexch::wget()
{
std::wstring str;
this->get(str);
return str;
}
//private:
bool dataexch::_m_set(format fmt, const void* buf, std::size_t size, native_window_type owner)
{