Merge branch 'hotfix-1.4.1' into develop
This commit is contained in:
commit
33424f0c75
5
build/codeblocks/nana.layout
Normal file
5
build/codeblocks/nana.layout
Normal 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>
|
||||
@ -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 };
|
||||
|
||||
|
||||
@ -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 it’s 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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
|
||||
|
||||
#define STRING2(x) #x
|
||||
#define STRING2(...) #__VA_ARGS__
|
||||
#define STRING(x) STRING2(x)
|
||||
#define SHOW_VALUE(x) " " #x " = " STRING2(x)
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() };
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user