improve dockable place
add a new API::at_safe_place()
This commit is contained in:
parent
5d2127e613
commit
460490040e
@ -161,6 +161,9 @@ namespace detail
|
|||||||
std::vector<std::pair<core_window_t*, unsigned long>> shortkeys(core_window_t*, bool with_children);
|
std::vector<std::pair<core_window_t*, unsigned long>> shortkeys(core_window_t*, bool with_children);
|
||||||
|
|
||||||
core_window_t* find_shortkey(native_window_type, unsigned long key);
|
core_window_t* find_shortkey(native_window_type, unsigned long key);
|
||||||
|
|
||||||
|
void set_safe_place(core_window_t* wd, std::function<void()>&& fn);
|
||||||
|
void call_safe_place(unsigned thread_id);
|
||||||
private:
|
private:
|
||||||
void _m_disengage(core_window_t*, core_window_t* for_new);
|
void _m_disengage(core_window_t*, core_window_t* for_new);
|
||||||
void _m_destroy(core_window_t*);
|
void _m_destroy(core_window_t*);
|
||||||
|
|||||||
@ -298,6 +298,8 @@ namespace API
|
|||||||
|
|
||||||
bool ignore_mouse_focus(window, bool ignore); ///< Enables/disables the mouse focus, it returns the previous state
|
bool ignore_mouse_focus(window, bool ignore); ///< Enables/disables the mouse focus, it returns the previous state
|
||||||
bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled
|
bool ignore_mouse_focus(window); ///< Determines whether the mouse focus is enabled
|
||||||
|
|
||||||
|
void at_safe_place(window, std::function<void()>);
|
||||||
}//end namespace API
|
}//end namespace API
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|
||||||
|
|||||||
@ -379,6 +379,9 @@ namespace nana
|
|||||||
|
|
||||||
void push_back(std::string text, ::nana::any par = {});
|
void push_back(std::string text, ::nana::any par = {});
|
||||||
void push_front(std::string text, ::nana::any par = {});
|
void push_front(std::string text, ::nana::any par = {});
|
||||||
|
|
||||||
|
std::size_t selected() const;
|
||||||
|
void erase(std::size_t pos, bool close_attached = true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1207,8 +1207,11 @@ namespace detail
|
|||||||
if(context) context->event_window = pre_event_window;
|
if(context) context->event_window = pre_event_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto thread_id = ::nana::system::this_thread_id()
|
||||||
|
brock.wd_manager.call_safe_place(thread_id);
|
||||||
|
|
||||||
if(msgwnd)
|
if(msgwnd)
|
||||||
brock.wd_manager.remove_trash_handle(::nana::system::this_thread_id());
|
brock.wd_manager.remove_trash_handle(thread_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -413,6 +413,7 @@ namespace detail
|
|||||||
::DispatchMessage(&msg);
|
::DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wd_manager.call_safe_place(tid);
|
||||||
wd_manager.remove_trash_handle(tid);
|
wd_manager.remove_trash_handle(tid);
|
||||||
if (msg.message == WM_DESTROY && msg.hwnd == native_handle)
|
if (msg.message == WM_DESTROY && msg.hwnd == native_handle)
|
||||||
break;
|
break;
|
||||||
@ -432,6 +433,7 @@ namespace detail
|
|||||||
::DispatchMessage(&msg);
|
::DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wd_manager.call_safe_place(tid);
|
||||||
wd_manager.remove_trash_handle(tid);
|
wd_manager.remove_trash_handle(tid);
|
||||||
}//end while
|
}//end while
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,8 @@ namespace detail
|
|||||||
handle_manager<core_window_t*, window_manager, window_handle_deleter> wd_register;
|
handle_manager<core_window_t*, window_manager, window_handle_deleter> wd_register;
|
||||||
paint::image default_icon_big;
|
paint::image default_icon_big;
|
||||||
paint::image default_icon_small;
|
paint::image default_icon_small;
|
||||||
|
|
||||||
|
std::map<core_window_t*, std::vector<std::function<void()>>> safe_place;
|
||||||
};
|
};
|
||||||
//end struct wdm_private_impl
|
//end struct wdm_private_impl
|
||||||
|
|
||||||
@ -1192,6 +1194,36 @@ namespace detail
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void window_manager::set_safe_place(core_window_t* wd, std::function<void()>&& fn)
|
||||||
|
{
|
||||||
|
if (fn)
|
||||||
|
{
|
||||||
|
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||||
|
if (!available(wd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
impl_->safe_place[wd].emplace_back(std::move(fn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_manager::call_safe_place(unsigned thread_id)
|
||||||
|
{
|
||||||
|
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||||
|
|
||||||
|
for (auto i = impl_->safe_place.begin(); i != impl_->safe_place.end();)
|
||||||
|
{
|
||||||
|
if (i->first->thread_id == thread_id)
|
||||||
|
{
|
||||||
|
for (auto & fn : i->second)
|
||||||
|
fn();
|
||||||
|
|
||||||
|
i = impl_->safe_place.erase(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool check_tree(basic_window* wd, basic_window* const cond)
|
bool check_tree(basic_window* wd, basic_window* const cond)
|
||||||
{
|
{
|
||||||
if (wd == cond) return true;
|
if (wd == cond) return true;
|
||||||
|
|||||||
@ -1717,13 +1717,27 @@ namespace nana
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_move_stopped()
|
void notify_move_stopped() override
|
||||||
{
|
{
|
||||||
if (_m_dockable() && dockable_field && dockable_field->dockarea)
|
if (_m_dockable() && dockable_field && dockable_field->dockarea)
|
||||||
dockable_field->dockarea->dock();
|
dockable_field->dockarea->dock();
|
||||||
|
|
||||||
indicator_.docker.reset();
|
indicator_.docker.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void request_close() override
|
||||||
|
{
|
||||||
|
auto window_handle = dockable_field->dockarea->handle();
|
||||||
|
|
||||||
|
//a workaround for capture
|
||||||
|
auto ptr = dockable_field->dockarea.release();
|
||||||
|
API::at_safe_place(window_handle, [this, ptr]
|
||||||
|
{
|
||||||
|
decltype(dockable_field->dockarea) del(ptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
API::close_window(window_handle);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
bool _m_indicator() const
|
bool _m_indicator() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -57,12 +57,19 @@ namespace nana
|
|||||||
virtual void notify_dock() = 0;
|
virtual void notify_dock() = 0;
|
||||||
virtual void notify_move() = 0;
|
virtual void notify_move() = 0;
|
||||||
virtual void notify_move_stopped() = 0;
|
virtual void notify_move_stopped() = 0;
|
||||||
|
|
||||||
|
//a dockarea requests to close the dockpane
|
||||||
|
virtual void request_close() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class dockcaption_dtrigger
|
class dockcaption_dtrigger
|
||||||
: public drawer_trigger
|
: public drawer_trigger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void on_close(std::function<void()>&& fn)
|
||||||
|
{
|
||||||
|
close_fn_ = std::move(fn);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
virtual void attached(widget_reference wdg, graph_reference graph) override
|
virtual void attached(widget_reference wdg, graph_reference graph) override
|
||||||
{
|
{
|
||||||
@ -84,10 +91,18 @@ namespace nana
|
|||||||
//draw x button
|
//draw x button
|
||||||
auto r = _m_button_area();
|
auto r = _m_button_area();
|
||||||
if (x_pointed_)
|
if (x_pointed_)
|
||||||
graph.rectangle(r, true, colors::red);
|
{
|
||||||
|
color xclr = colors::red;
|
||||||
|
|
||||||
|
if(x_state_ == ::nana::mouse_action::pressed)
|
||||||
|
xclr = xclr.blend(colors::white, 0.8);
|
||||||
|
|
||||||
|
graph.rectangle(r, true, xclr);
|
||||||
|
}
|
||||||
|
|
||||||
r.x += (r.width - 16) / 2;
|
r.x += (r.width - 16) / 2;
|
||||||
r.y = (r.height - 16) / 2;
|
r.y = (r.height - 16) / 2;
|
||||||
|
|
||||||
x_icon_.draw(graph, colors::red, colors::white, r, element_state::normal);
|
x_icon_.draw(graph, colors::red, colors::white, r, element_state::normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +120,29 @@ namespace nana
|
|||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::lazy_refresh();
|
API::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mouse_down(graph_reference graph, const arg_mouse&) override
|
||||||
|
{
|
||||||
|
if (!x_pointed_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
x_state_ = ::nana::mouse_action::pressed;
|
||||||
|
|
||||||
|
refresh(graph);
|
||||||
|
API::lazy_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_up(graph_reference graph, const arg_mouse&) override
|
||||||
|
{
|
||||||
|
if (!x_pointed_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
x_state_ = ::nana::mouse_action::over;
|
||||||
|
refresh(graph);
|
||||||
|
API::lazy_refresh();
|
||||||
|
|
||||||
|
close_fn_();
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
::nana::rectangle _m_button_area() const
|
::nana::rectangle _m_button_area() const
|
||||||
{
|
{
|
||||||
@ -118,12 +156,21 @@ namespace nana
|
|||||||
window window_handle_;
|
window window_handle_;
|
||||||
std::unique_ptr<paint::text_renderer> text_rd_;
|
std::unique_ptr<paint::text_renderer> text_rd_;
|
||||||
bool x_pointed_{ false };
|
bool x_pointed_{ false };
|
||||||
|
::nana::mouse_action x_state_{ ::nana::mouse_action::normal };
|
||||||
facade<element::x_icon> x_icon_;
|
facade<element::x_icon> x_icon_;
|
||||||
|
|
||||||
|
std::function<void()> close_fn_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class dockarea_caption
|
class dockarea_caption
|
||||||
: public widget_object < category::widget_tag, dockcaption_dtrigger >
|
: public widget_object < category::widget_tag, dockcaption_dtrigger >
|
||||||
{};
|
{
|
||||||
|
public:
|
||||||
|
void on_close(std::function<void()> fn)
|
||||||
|
{
|
||||||
|
get_drawer_trigger().on_close(std::move(fn));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class dock_page
|
class dock_page
|
||||||
: public form
|
: public form
|
||||||
@ -158,6 +205,22 @@ namespace nana
|
|||||||
base_type::create(parent, true);
|
base_type::create(parent, true);
|
||||||
this->caption("dockarea");
|
this->caption("dockarea");
|
||||||
caption_.create(*this, true);
|
caption_.create(*this, true);
|
||||||
|
caption_.on_close([this]
|
||||||
|
{
|
||||||
|
bool destroy_dockarea = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tabbar_->erase(tabbar_->selected());
|
||||||
|
destroy_dockarea = (0 == tabbar_->length());
|
||||||
|
}
|
||||||
|
catch (std::out_of_range&)
|
||||||
|
{
|
||||||
|
destroy_dockarea = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destroy_dockarea)
|
||||||
|
notifier_->request_close();
|
||||||
|
});
|
||||||
|
|
||||||
this->events().resized([this](const arg_resized& arg)
|
this->events().resized([this](const arg_resized& arg)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1314,5 +1314,10 @@ namespace API
|
|||||||
internal_scope_guard lock;
|
internal_scope_guard lock;
|
||||||
return (restrict::window_manager.available(iwd) ? iwd->flags.ignore_mouse_focus : false);
|
return (restrict::window_manager.available(iwd) ? iwd->flags.ignore_mouse_focus : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void at_safe_place(window wd, std::function<void()> fn)
|
||||||
|
{
|
||||||
|
restrict::window_manager.set_safe_place(reinterpret_cast<restrict::core_window_t*>(wd), std::move(fn));
|
||||||
|
}
|
||||||
}//end namespace API
|
}//end namespace API
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|||||||
@ -1555,15 +1555,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
auto& items = get_drawer_trigger().get_model()->items();
|
auto& items = get_drawer_trigger().get_model()->items();
|
||||||
internal_scope_guard lock;
|
internal_scope_guard lock;
|
||||||
|
return static_cast<std::size_t>(std::distance(items.cbegin(), items.cend()));
|
||||||
std::size_t off = 0;
|
|
||||||
auto i = items.cbegin(), end = items.cend();
|
|
||||||
while (i != end)
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
++off;
|
|
||||||
}
|
|
||||||
return off;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//modifiers
|
//modifiers
|
||||||
@ -1613,5 +1605,54 @@ namespace nana
|
|||||||
items.emplace_front(std::move(text), std::move(any));
|
items.emplace_front(std::move(text), std::move(any));
|
||||||
API::refresh_window(handle());
|
API::refresh_window(handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t tabbar_lite::selected() const
|
||||||
|
{
|
||||||
|
auto model = get_drawer_trigger().get_model();
|
||||||
|
internal_scope_guard lock;
|
||||||
|
|
||||||
|
return model->get_indexes().active_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabbar_lite::erase(std::size_t pos, bool close_attached)
|
||||||
|
{
|
||||||
|
auto model = get_drawer_trigger().get_model();
|
||||||
|
internal_scope_guard lock;
|
||||||
|
|
||||||
|
const auto len = length();
|
||||||
|
|
||||||
|
if (len <= pos)
|
||||||
|
throw std::out_of_range("tabbar_lite: out of range");
|
||||||
|
|
||||||
|
auto active_pos = model->get_indexes().active_pos;
|
||||||
|
|
||||||
|
if (pos == active_pos)
|
||||||
|
{
|
||||||
|
if (active_pos + 1 == len)
|
||||||
|
{
|
||||||
|
if (active_pos)
|
||||||
|
--active_pos;
|
||||||
|
else
|
||||||
|
active_pos = npos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pos < active_pos)
|
||||||
|
--active_pos;
|
||||||
|
|
||||||
|
model->get_indexes().active_pos = active_pos;
|
||||||
|
|
||||||
|
auto i = model->items().cbefore_begin();
|
||||||
|
std::advance(i, pos);
|
||||||
|
|
||||||
|
auto attached_wd = std::next(i)->attached_window;
|
||||||
|
|
||||||
|
model->items().erase_after(i);
|
||||||
|
|
||||||
|
model->show_attached_window();
|
||||||
|
API::refresh_window(handle());
|
||||||
|
|
||||||
|
if (close_attached && attached_wd)
|
||||||
|
API::close_window(attached_wd);
|
||||||
|
}
|
||||||
//end class tabbar
|
//end class tabbar
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user