improve dockable place

add a new API::at_safe_place()
This commit is contained in:
Jinhao 2015-09-20 23:21:44 +08:00
parent 5d2127e613
commit 460490040e
10 changed files with 181 additions and 13 deletions

View File

@ -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*);

View File

@ -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

View File

@ -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);
}; };
} }

View File

@ -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);
} }
} }

View File

@ -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

View File

@ -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;

View File

@ -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
{ {

View File

@ -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)
{ {

View File

@ -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

View File

@ -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