Merge remote-tracking branch 'nana_jinhao/hotfixes-1.0.2' into hotfixes-1.0.2
This commit is contained in:
@@ -84,6 +84,7 @@ namespace nana
|
|||||||
end_of_medium = 0x19, //Ctrl+Y
|
end_of_medium = 0x19, //Ctrl+Y
|
||||||
substitute = 0x1A, //Ctrl+Z
|
substitute = 0x1A, //Ctrl+Z
|
||||||
escape = 0x1B,
|
escape = 0x1B,
|
||||||
|
space = 0x20, //Space
|
||||||
|
|
||||||
//The following names are intuitive name of ASCII control codes
|
//The following names are intuitive name of ASCII control codes
|
||||||
select_all = start_of_headline,
|
select_all = start_of_headline,
|
||||||
|
|||||||
@@ -118,9 +118,11 @@ namespace detail
|
|||||||
|
|
||||||
bool is_ancestor_of(const basic_window* wd) const;
|
bool is_ancestor_of(const basic_window* wd) const;
|
||||||
bool visible_parents() const;
|
bool visible_parents() const;
|
||||||
|
bool displayed() const;
|
||||||
bool belong_to_lazy() const;
|
bool belong_to_lazy() const;
|
||||||
|
const basic_window * child_caret() const; //Returns a child which owns a caret
|
||||||
|
|
||||||
bool is_draw_through() const; ///< Determines whether it is a draw-through window.
|
bool is_draw_through() const; // Determines whether it is a draw-through window.
|
||||||
public:
|
public:
|
||||||
//Override event_holder
|
//Override event_holder
|
||||||
bool set_events(const std::shared_ptr<general_events>&) override;
|
bool set_events(const std::shared_ptr<general_events>&) override;
|
||||||
|
|||||||
@@ -23,12 +23,18 @@ namespace nana
|
|||||||
{
|
{
|
||||||
class widget;
|
class widget;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
class drawer;
|
||||||
|
}
|
||||||
|
|
||||||
class drawer_trigger
|
class drawer_trigger
|
||||||
: ::nana::noncopyable, ::nana::nonmovable
|
: ::nana::noncopyable, ::nana::nonmovable
|
||||||
{
|
{
|
||||||
|
friend class detail::drawer;
|
||||||
public:
|
public:
|
||||||
typedef widget& widget_reference;
|
using widget_reference = widget&;
|
||||||
typedef paint::graphics& graph_reference;
|
using graph_reference = paint::graphics&;
|
||||||
|
|
||||||
virtual ~drawer_trigger();
|
virtual ~drawer_trigger();
|
||||||
virtual void attached(widget_reference, graph_reference); //none-const
|
virtual void attached(widget_reference, graph_reference); //none-const
|
||||||
@@ -56,10 +62,11 @@ namespace nana
|
|||||||
virtual void key_release(graph_reference, const arg_keyboard&);
|
virtual void key_release(graph_reference, const arg_keyboard&);
|
||||||
virtual void shortkey(graph_reference, const arg_keyboard&);
|
virtual void shortkey(graph_reference, const arg_keyboard&);
|
||||||
|
|
||||||
void _m_reset_overrided();
|
|
||||||
bool _m_overrided() const;
|
|
||||||
private:
|
private:
|
||||||
bool overrided_{false};
|
void _m_reset_overrided();
|
||||||
|
bool _m_overrided(event_code) const;
|
||||||
|
private:
|
||||||
|
unsigned overrided_{ 0xFFFFFFFF };
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -83,7 +90,7 @@ namespace nana
|
|||||||
|
|
||||||
enum class method_state
|
enum class method_state
|
||||||
{
|
{
|
||||||
unknown,
|
pending,
|
||||||
overrided,
|
overrided,
|
||||||
not_overrided
|
not_overrided
|
||||||
};
|
};
|
||||||
@@ -127,23 +134,20 @@ namespace nana
|
|||||||
|
|
||||||
template<typename Arg, typename Mfptr>
|
template<typename Arg, typename Mfptr>
|
||||||
void _m_emit(event_code evt_code, const Arg& arg, Mfptr mfptr)
|
void _m_emit(event_code evt_code, const Arg& arg, Mfptr mfptr)
|
||||||
{
|
|
||||||
if (realizer_)
|
|
||||||
{
|
{
|
||||||
const int pos = static_cast<int>(evt_code);
|
const int pos = static_cast<int>(evt_code);
|
||||||
if (method_state::not_overrided != mth_state_[pos])
|
if (realizer_ && (method_state::not_overrided != mth_state_[pos]))
|
||||||
{
|
{
|
||||||
_m_bground_pre();
|
_m_bground_pre();
|
||||||
|
|
||||||
if (method_state::unknown == mth_state_[pos])
|
if (method_state::pending == mth_state_[pos])
|
||||||
{
|
{
|
||||||
realizer_->_m_reset_overrided();
|
|
||||||
(realizer_->*mfptr)(graphics, arg);
|
(realizer_->*mfptr)(graphics, arg);
|
||||||
|
|
||||||
//Check realizer, when the window is closed in that event handler, the drawer will be
|
//Check realizer, when the window is closed in that event handler, the drawer will be
|
||||||
//detached and realizer will be a nullptr
|
//detached and realizer will be a nullptr
|
||||||
if(realizer_)
|
if(realizer_)
|
||||||
mth_state_[pos] = (realizer_->_m_overrided() ? method_state::overrided : method_state::not_overrided);
|
mth_state_[pos] = (realizer_->_m_overrided(evt_code) ? method_state::overrided : method_state::not_overrided);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(realizer_->*mfptr)(graphics, arg);
|
(realizer_->*mfptr)(graphics, arg);
|
||||||
@@ -155,7 +159,6 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
nana::paint::graphics graphics;
|
nana::paint::graphics graphics;
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace nana{
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t weight() const
|
unsigned weight() const
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@@ -55,22 +55,23 @@ namespace nana{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr)
|
void render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr)
|
||||||
{
|
{
|
||||||
bool rendered = false;
|
bool copy_separately = true;
|
||||||
core_window_t * root_wd = wd->root_widget;
|
std::vector<std::pair<rectangle, core_window_t*>> rd_set;
|
||||||
|
|
||||||
|
if (wd->root_widget->other.attribute.root->effects_edge_nimbus.size())
|
||||||
|
{
|
||||||
|
auto root_wd = wd->root_widget;
|
||||||
|
|
||||||
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
|
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
|
||||||
|
|
||||||
if(nimbus.size())
|
auto focused = root_wd->other.attribute.root->focus;
|
||||||
{
|
|
||||||
core_window_t * focused = root_wd->other.attribute.root->focus;
|
const unsigned pixels = weight();
|
||||||
native_window_type native = root_wd->root;
|
|
||||||
std::size_t pixels = weight();
|
|
||||||
|
|
||||||
auto graph = root_wd->root_graph;
|
auto graph = root_wd->root_graph;
|
||||||
|
|
||||||
std::vector<core_window_t*> erase;
|
|
||||||
std::vector<std::pair<rectangle,core_window_t*>> rd_set;
|
|
||||||
nana::rectangle r;
|
nana::rectangle r;
|
||||||
for(auto & action : nimbus)
|
for(auto & action : nimbus)
|
||||||
{
|
{
|
||||||
@@ -80,11 +81,11 @@ namespace nana{
|
|||||||
{
|
{
|
||||||
if (update_area)
|
if (update_area)
|
||||||
::nana::overlap(*update_area, rectangle(r), r);
|
::nana::overlap(*update_area, rectangle(r), r);
|
||||||
rendered = true;
|
copy_separately = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
|
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
|
||||||
if ((forced && (action.window == wd)) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
|
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
|
||||||
{
|
{
|
||||||
rd_set.emplace_back(r, action.window);
|
rd_set.emplace_back(r, action.window);
|
||||||
action.rendered = true;
|
action.rendered = true;
|
||||||
@@ -93,30 +94,37 @@ namespace nana{
|
|||||||
else if(action.rendered)
|
else if(action.rendered)
|
||||||
{
|
{
|
||||||
action.rendered = false;
|
action.rendered = false;
|
||||||
erase.push_back(action.window);
|
|
||||||
|
if (action.window == wd)
|
||||||
|
copy_separately = false;
|
||||||
|
|
||||||
|
::nana::rectangle erase_r(
|
||||||
|
action.window->pos_root.x - static_cast<int>(pixels),
|
||||||
|
action.window->pos_root.y - static_cast<int>(pixels),
|
||||||
|
static_cast<unsigned>(action.window->dimension.width + (pixels << 1)),
|
||||||
|
static_cast<unsigned>(action.window->dimension.height + (pixels << 1))
|
||||||
|
);
|
||||||
|
|
||||||
|
graph->paste(root_wd->root, erase_r, erase_r.x, erase_r.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Erase
|
if (copy_separately)
|
||||||
for(auto el : erase)
|
|
||||||
{
|
{
|
||||||
if(el == wd)
|
rectangle vr;
|
||||||
rendered = true;
|
if (window_layer::read_visual_rectangle(wd, vr))
|
||||||
|
{
|
||||||
r.x = el->pos_root.x - static_cast<int>(pixels);
|
if (update_area)
|
||||||
r.y = el->pos_root.y - static_cast<int>(pixels);
|
::nana::overlap(*update_area, rectangle(vr), vr);
|
||||||
r.width = static_cast<unsigned>(el->dimension.width + (pixels << 1));
|
wd->root_graph->paste(wd->root, vr, vr.x, vr.y);
|
||||||
r.height = static_cast<unsigned>(el->dimension.height + (pixels << 1));
|
}
|
||||||
|
|
||||||
graph->paste(native, r, r.x, r.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Render
|
//Render
|
||||||
for (auto & rd : rd_set)
|
for (auto & rd : rd_set)
|
||||||
_m_render_edge_nimbus(rd.second, rd.first);
|
_m_render_edge_nimbus(rd.second, rd.first);
|
||||||
}
|
}
|
||||||
return rendered;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
static bool _m_edge_nimbus(core_window_t * focused_wd, core_window_t * wd)
|
static bool _m_edge_nimbus(core_window_t * focused_wd, core_window_t * wd)
|
||||||
{
|
{
|
||||||
@@ -135,7 +143,7 @@ namespace nana{
|
|||||||
if(overlap(r, wd->root_graph->size(), good_r))
|
if(overlap(r, wd->root_graph->size(), good_r))
|
||||||
{
|
{
|
||||||
if ((good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) ||
|
if ((good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) ||
|
||||||
(good_r.x + good_r.width > visual.x + visual.width) || (good_r.y + good_r.height > visual.y + visual.height))
|
(good_r.right() > visual.right()) || (good_r.bottom() > visual.bottom()))
|
||||||
{
|
{
|
||||||
auto graph = wd->root_graph;
|
auto graph = wd->root_graph;
|
||||||
nana::paint::pixel_buffer pixbuf(graph->handle(), r);
|
nana::paint::pixel_buffer pixbuf(graph->handle(), r);
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace nana
|
|||||||
if(real_visible_state_ != isshow)
|
if(real_visible_state_ != isshow)
|
||||||
{
|
{
|
||||||
real_visible_state_ = isshow;
|
real_visible_state_ = isshow;
|
||||||
native_interface::caret_visible(wd_->root, isshow);
|
native_interface::caret_visible(wd_->root, isshow && wd_->displayed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,6 +282,11 @@ namespace nana
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool basic_window::displayed() const
|
||||||
|
{
|
||||||
|
return (visible && visible_parents());
|
||||||
|
}
|
||||||
|
|
||||||
bool basic_window::belong_to_lazy() const
|
bool basic_window::belong_to_lazy() const
|
||||||
{
|
{
|
||||||
for (auto wd = this; wd; wd = wd->parent)
|
for (auto wd = this; wd; wd = wd->parent)
|
||||||
@@ -292,6 +297,26 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const basic_window* get_child_caret(const basic_window* wd, bool this_is_a_child)
|
||||||
|
{
|
||||||
|
if (this_is_a_child && wd->together.caret)
|
||||||
|
return wd;
|
||||||
|
|
||||||
|
for (auto child : wd->children)
|
||||||
|
{
|
||||||
|
auto caret_wd = get_child_caret(child, true);
|
||||||
|
if (caret_wd)
|
||||||
|
return caret_wd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const basic_window * basic_window::child_caret() const
|
||||||
|
{
|
||||||
|
return get_child_caret(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
bool basic_window::is_draw_through() const
|
bool basic_window::is_draw_through() const
|
||||||
{
|
{
|
||||||
if (::nana::category::flags::root == this->other.category)
|
if (::nana::category::flags::root == this->other.category)
|
||||||
|
|||||||
@@ -63,15 +63,16 @@ namespace nana
|
|||||||
arg.window_handle = reinterpret_cast<window>(wd);
|
arg.window_handle = reinterpret_cast<window>(wd);
|
||||||
if (emit(event_code::expose, wd, arg, false, get_thread_context()))
|
if (emit(event_code::expose, wd, arg, false, get_thread_context()))
|
||||||
{
|
{
|
||||||
if (wd->together.caret)
|
const core_window_t * caret_wd = (wd->together.caret ? wd : wd->child_caret());
|
||||||
|
if (caret_wd)
|
||||||
{
|
{
|
||||||
if (exposed)
|
if (exposed)
|
||||||
{
|
{
|
||||||
if (wd->root_widget->other.attribute.root->focus == wd)
|
if (wd->root_widget->other.attribute.root->focus == caret_wd)
|
||||||
wd->together.caret->visible(true);
|
caret_wd->together.caret->visible(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wd->together.caret->visible(false);
|
caret_wd->together.caret->visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exposed)
|
if (!exposed)
|
||||||
@@ -102,7 +103,7 @@ namespace nana
|
|||||||
arg.x = x;
|
arg.x = x;
|
||||||
arg.y = y;
|
arg.y = y;
|
||||||
if (emit(event_code::move, wd, arg, false, get_thread_context()))
|
if (emit(event_code::move, wd, arg, false, get_thread_context()))
|
||||||
wd_manager.update(wd, true, true);
|
wd_manager.update(wd, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,99 +34,99 @@ namespace nana
|
|||||||
|
|
||||||
void drawer_trigger::resizing(graph_reference, const arg_resizing&)
|
void drawer_trigger::resizing(graph_reference, const arg_resizing&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::resizing));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::resized(graph_reference graph, const arg_resized&)
|
void drawer_trigger::resized(graph_reference graph, const arg_resized&)
|
||||||
{
|
{
|
||||||
overrided_ = true;
|
overrided_ |= (1 << static_cast<int>(event_code::resized));
|
||||||
this->refresh(graph);
|
this->refresh(graph);
|
||||||
detail::bedrock::instance().thread_context_lazy_refresh();
|
detail::bedrock::instance().thread_context_lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::move(graph_reference, const arg_move&)
|
void drawer_trigger::move(graph_reference, const arg_move&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::move));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::click(graph_reference, const arg_mouse&)
|
void drawer_trigger::click(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::click));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::dbl_click(graph_reference, const arg_mouse&)
|
void drawer_trigger::dbl_click(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::dbl_click));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_enter(graph_reference, const arg_mouse&)
|
void drawer_trigger::mouse_enter(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_enter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_move(graph_reference, const arg_mouse&)
|
void drawer_trigger::mouse_move(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_move));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_leave(graph_reference, const arg_mouse&)
|
void drawer_trigger::mouse_leave(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_leave));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_down(graph_reference, const arg_mouse&)
|
void drawer_trigger::mouse_down(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_down));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_up(graph_reference, const arg_mouse&)
|
void drawer_trigger::mouse_up(graph_reference, const arg_mouse&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_up));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_wheel(graph_reference, const arg_wheel&)
|
void drawer_trigger::mouse_wheel(graph_reference, const arg_wheel&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_wheel));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::mouse_dropfiles(graph_reference, const arg_dropfiles&)
|
void drawer_trigger::mouse_dropfiles(graph_reference, const arg_dropfiles&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::mouse_drop));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::focus(graph_reference, const arg_focus&)
|
void drawer_trigger::focus(graph_reference, const arg_focus&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::focus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
|
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::key_press));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::key_char(graph_reference, const arg_keyboard&)
|
void drawer_trigger::key_char(graph_reference, const arg_keyboard&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::key_char));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::key_release(graph_reference, const arg_keyboard&)
|
void drawer_trigger::key_release(graph_reference, const arg_keyboard&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::key_release));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::shortkey(graph_reference, const arg_keyboard&)
|
void drawer_trigger::shortkey(graph_reference, const arg_keyboard&)
|
||||||
{
|
{
|
||||||
overrided_ = false;
|
overrided_ &= ~(1 << static_cast<int>(event_code::shortkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawer_trigger::_m_reset_overrided()
|
void drawer_trigger::_m_reset_overrided()
|
||||||
{
|
{
|
||||||
overrided_ = true;
|
overrided_ = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drawer_trigger::_m_overrided() const
|
bool drawer_trigger::_m_overrided(event_code evt_code) const
|
||||||
{
|
{
|
||||||
return overrided_;
|
return 0 != (overrided_ & (1 << static_cast<int>(evt_code)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//end class drawer_trigger
|
//end class drawer_trigger
|
||||||
@@ -244,8 +244,8 @@ namespace nana
|
|||||||
{
|
{
|
||||||
if(wd)
|
if(wd)
|
||||||
{
|
{
|
||||||
bedrock_type::core_window_t* iwd = reinterpret_cast<bedrock_type::core_window_t*>(wd);
|
auto iwd = reinterpret_cast<bedrock_type::core_window_t*>(wd);
|
||||||
bedrock_type::core_window_t * caret_wd = iwd->root_widget->other.attribute.root->focus;
|
auto caret_wd = iwd->root_widget->other.attribute.root->focus;
|
||||||
|
|
||||||
bool owns_caret = (caret_wd && (caret_wd->together.caret) && (caret_wd->together.caret->visible()));
|
bool owns_caret = (caret_wd && (caret_wd->together.caret) && (caret_wd->together.caret->visible()));
|
||||||
|
|
||||||
@@ -262,16 +262,7 @@ namespace nana
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false == edge_nimbus_renderer_t::instance().render(iwd, forced, update_area))
|
edge_nimbus_renderer_t::instance().render(iwd, forced, update_area);
|
||||||
{
|
|
||||||
rectangle vr;
|
|
||||||
if (bedrock_type::window_manager_t::window_layer::read_visual_rectangle(iwd, vr))
|
|
||||||
{
|
|
||||||
if (update_area)
|
|
||||||
::nana::overlap(*update_area, rectangle(vr), vr);
|
|
||||||
iwd->root_graph->paste(iwd->root, vr, vr.x, vr.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(owns_caret)
|
if(owns_caret)
|
||||||
{
|
{
|
||||||
@@ -306,9 +297,10 @@ namespace nana
|
|||||||
void drawer::attached(widget& wd, drawer_trigger& realizer)
|
void drawer::attached(widget& wd, drawer_trigger& realizer)
|
||||||
{
|
{
|
||||||
for (auto i = std::begin(mth_state_), end = std::end(mth_state_); i != end; ++i)
|
for (auto i = std::begin(mth_state_), end = std::end(mth_state_); i != end; ++i)
|
||||||
*i = method_state::unknown;
|
*i = method_state::pending;
|
||||||
|
|
||||||
realizer_ = &realizer;
|
realizer_ = &realizer;
|
||||||
|
realizer._m_reset_overrided();
|
||||||
realizer.attached(wd, graphics);
|
realizer.attached(wd, graphics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -937,11 +937,10 @@ namespace detail
|
|||||||
if(msgwnd->visible && (msgwnd->root_graph->empty() == false))
|
if(msgwnd->visible && (msgwnd->root_graph->empty() == false))
|
||||||
{
|
{
|
||||||
nana::detail::platform_scope_guard psg;
|
nana::detail::platform_scope_guard psg;
|
||||||
nana::detail::drawable_impl_type* drawer_impl = msgwnd->root_graph->handle();
|
//Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed.
|
||||||
::XCopyArea(display, drawer_impl->pixmap, reinterpret_cast<Window>(native_window), drawer_impl->context,
|
::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height);
|
||||||
xevent.xexpose.x, xevent.xexpose.y,
|
if (!update_area.empty())
|
||||||
xevent.xexpose.width, xevent.xexpose.height,
|
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area);
|
||||||
xevent.xexpose.x, xevent.xexpose.y);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
@@ -1149,6 +1148,8 @@ namespace detail
|
|||||||
brock.get_key_state(arg);
|
brock.get_key_state(arg);
|
||||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.platform.keychar < keyboard::os_arrow_left || keyboard::os_arrow_down < wParam)
|
||||||
brock.delay_restore(2); //Restores while key release
|
brock.delay_restore(2); //Restores while key release
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ namespace detail
|
|||||||
void bedrock::pump_event(window modal_window, bool is_modal)
|
void bedrock::pump_event(window modal_window, bool is_modal)
|
||||||
{
|
{
|
||||||
const unsigned tid = ::GetCurrentThreadId();
|
const unsigned tid = ::GetCurrentThreadId();
|
||||||
thread_context * context = this->open_thread_context(tid);
|
auto context = this->open_thread_context(tid);
|
||||||
if(0 == context->window_count)
|
if(0 == context->window_count)
|
||||||
{
|
{
|
||||||
//test if there is not a window
|
//test if there is not a window
|
||||||
@@ -1310,13 +1310,11 @@ namespace detail
|
|||||||
::PAINTSTRUCT ps;
|
::PAINTSTRUCT ps;
|
||||||
::HDC dc = ::BeginPaint(root_window, &ps);
|
::HDC dc = ::BeginPaint(root_window, &ps);
|
||||||
|
|
||||||
if((ps.rcPaint.left != ps.rcPaint.right) && (ps.rcPaint.bottom != ps.rcPaint.top))
|
//Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed.
|
||||||
{
|
::nana::rectangle update_area(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top);
|
||||||
::BitBlt(dc,
|
if (!update_area.empty())
|
||||||
ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
|
msgwnd->drawer.map(reinterpret_cast<window>(msgwnd), true, &update_area);
|
||||||
reinterpret_cast<HDC>(msgwnd->root_graph->handle()->context),
|
|
||||||
ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
|
|
||||||
}
|
|
||||||
::EndPaint(root_window, &ps);
|
::EndPaint(root_window, &ps);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1474,6 +1472,9 @@ namespace detail
|
|||||||
else
|
else
|
||||||
brock.set_keyboard_shortkey(false);
|
brock.set_keyboard_shortkey(false);
|
||||||
|
|
||||||
|
//Do delay restore if key is not arrow_left/right/up/down, otherwise
|
||||||
|
//A menubar will be restored if the item is empty(not have a menu item)
|
||||||
|
if (wParam < 37 || 40 < wParam)
|
||||||
brock.delay_restore(2); //Restores while key release
|
brock.delay_restore(2); //Restores while key release
|
||||||
break;
|
break;
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ namespace nana
|
|||||||
if (wd->parent)
|
if (wd->parent)
|
||||||
{
|
{
|
||||||
std::vector<wd_rectangle> blocks;
|
std::vector<wd_rectangle> blocks;
|
||||||
blocks.reserve(10);
|
|
||||||
if (read_overlaps(wd, vr, blocks))
|
if (read_overlaps(wd, vr, blocks))
|
||||||
{
|
{
|
||||||
nana::point p_src;
|
nana::point p_src;
|
||||||
@@ -99,7 +98,7 @@ namespace nana
|
|||||||
// The result is a rectangle that is a visible area for its ancesters.
|
// The result is a rectangle that is a visible area for its ancesters.
|
||||||
bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual)
|
bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual)
|
||||||
{
|
{
|
||||||
if (false == wd->visible) return false;
|
if (! wd->displayed()) return false;
|
||||||
|
|
||||||
visual = rectangle{ wd->pos_root, wd->dimension };
|
visual = rectangle{ wd->pos_root, wd->dimension };
|
||||||
|
|
||||||
@@ -354,7 +353,7 @@ namespace nana
|
|||||||
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
|
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
|
||||||
for (auto wd : data_sect.effects_bground_windows)
|
for (auto wd : data_sect.effects_bground_windows)
|
||||||
{
|
{
|
||||||
if (wd == sigwd || !wd->visible || !wd->visible_parents() ||
|
if (wd == sigwd || !wd->displayed() ||
|
||||||
(false == overlap(nana::rectangle{ wd->pos_root, wd->dimension }, r_of_sigwd)))
|
(false == overlap(nana::rectangle{ wd->pos_root, wd->dimension }, r_of_sigwd)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -698,7 +698,7 @@ namespace detail
|
|||||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||||
if (impl_->wd_register.available(wd) == false) return false;
|
if (impl_->wd_register.available(wd) == false) return false;
|
||||||
|
|
||||||
if (wd->visible && wd->visible_parents())
|
if (wd->displayed())
|
||||||
{
|
{
|
||||||
if(forced || (false == wd->belong_to_lazy()))
|
if(forced || (false == wd->belong_to_lazy()))
|
||||||
{
|
{
|
||||||
@@ -722,7 +722,7 @@ namespace detail
|
|||||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||||
|
|
||||||
//It's not worthy to redraw if visible is false
|
//It's not worthy to redraw if visible is false
|
||||||
if (impl_->wd_register.available(wd) && wd->visible && wd->visible_parents())
|
if (impl_->wd_register.available(wd) && wd->displayed())
|
||||||
window_layer::paint(wd, true, true);
|
window_layer::paint(wd, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1060,7 +1060,7 @@ namespace detail
|
|||||||
bool precondition = false;
|
bool precondition = false;
|
||||||
for (auto & tab_wd : tabs)
|
for (auto & tab_wd : tabs)
|
||||||
{
|
{
|
||||||
if (tab_wd->visible)
|
if (tab_wd->displayed())
|
||||||
{
|
{
|
||||||
precondition = true;
|
precondition = true;
|
||||||
break;
|
break;
|
||||||
@@ -1073,7 +1073,7 @@ namespace detail
|
|||||||
|
|
||||||
while (new_stop && (wd != new_stop))
|
while (new_stop && (wd != new_stop))
|
||||||
{
|
{
|
||||||
if (new_stop->flags.enabled && new_stop->visible)
|
if (new_stop->flags.enabled && new_stop->displayed())
|
||||||
return new_stop;
|
return new_stop;
|
||||||
|
|
||||||
new_stop = get_tabstop(new_stop, forward);
|
new_stop = get_tabstop(new_stop, forward);
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ namespace nana{ namespace drawerbase
|
|||||||
|
|
||||||
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
if(arg.key == static_cast<char_t>(keyboard::enter))
|
if (static_cast<char_t>(keyboard::enter) == arg.key || static_cast<char_t>(keyboard::space) == arg.key)
|
||||||
emit_click();
|
emit_click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3512,6 +3512,7 @@ namespace nana
|
|||||||
m.flags.checked = ck;
|
m.flags.checked = ck;
|
||||||
arg_listbox arg{*this, ck};
|
arg_listbox arg{*this, ck};
|
||||||
ess_->lister.wd_ptr()->events().checked.emit(arg);
|
ess_->lister.wd_ptr()->events().checked.emit(arg);
|
||||||
|
ess_->update();
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -3539,6 +3540,7 @@ namespace nana
|
|||||||
else if (ess_->lister.last_selected_abs == pos_)
|
else if (ess_->lister.last_selected_abs == pos_)
|
||||||
ess_->lister.last_selected_abs.set_both(npos);
|
ess_->lister.last_selected_abs.set_both(npos);
|
||||||
|
|
||||||
|
ess_->update();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
if(at.item_state == state::active)
|
if(at.item_state == state::active)
|
||||||
{
|
{
|
||||||
graph.rectangle(r, false, {0xa8, 0xd8, 0xeb});
|
graph.rectangle(r, false, static_cast<color_rgb>(0xa8d8eb));
|
||||||
nana::point points[4] = {
|
nana::point points[4] = {
|
||||||
nana::point(r.x, r.y),
|
nana::point(r.x, r.y),
|
||||||
nana::point(r.x + r.width - 1, r.y),
|
nana::point(r.x + r.width - 1, r.y),
|
||||||
@@ -200,8 +200,9 @@ namespace nana
|
|||||||
|
|
||||||
void checked(std::size_t index, bool check)
|
void checked(std::size_t index, bool check)
|
||||||
{
|
{
|
||||||
if(root_.items.size() > index)
|
if (root_.items.size() <= index)
|
||||||
{
|
return;
|
||||||
|
|
||||||
item_type & m = root_.items[index];
|
item_type & m = root_.items[index];
|
||||||
if(check && (checks::option == m.style))
|
if(check && (checks::option == m.style))
|
||||||
{
|
{
|
||||||
@@ -229,7 +230,6 @@ namespace nana
|
|||||||
}
|
}
|
||||||
m.flags.checked = check;
|
m.flags.checked = check;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
menu_type& data()
|
menu_type& data()
|
||||||
{
|
{
|
||||||
@@ -304,7 +304,7 @@ namespace nana
|
|||||||
: public drawer_trigger
|
: public drawer_trigger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef menu_item_type::item_proxy item_proxy;
|
using item_proxy = menu_item_type::item_proxy;
|
||||||
|
|
||||||
renderer_interface * renderer;
|
renderer_interface * renderer;
|
||||||
|
|
||||||
@@ -330,12 +330,12 @@ namespace nana
|
|||||||
detail_.monitor_pos = API::cursor_position();
|
detail_.monitor_pos = API::cursor_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouse_move(graph_reference, const arg_mouse& arg)
|
void mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||||
{
|
{
|
||||||
state_.nullify_mouse = false;
|
state_.nullify_mouse = false;
|
||||||
if(track_mouse(arg.pos.x, arg.pos.y))
|
if(track_mouse(arg.pos))
|
||||||
{
|
{
|
||||||
draw();
|
refresh(graph);
|
||||||
API::lazy_refresh();
|
API::lazy_refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,9 +350,70 @@ namespace nana
|
|||||||
state_.nullify_mouse = false;
|
state_.nullify_mouse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh(graph_reference)
|
void refresh(graph_reference graph)
|
||||||
{
|
{
|
||||||
draw();
|
if (nullptr == menu_) return;
|
||||||
|
|
||||||
|
_m_adjust_window_size();
|
||||||
|
|
||||||
|
renderer->background(graph, *widget_);
|
||||||
|
|
||||||
|
const unsigned item_h_px = _m_item_height();
|
||||||
|
const unsigned image_px = item_h_px - 2;
|
||||||
|
nana::rectangle item_r(2, 2, graph_->width() - 4, item_h_px);
|
||||||
|
|
||||||
|
unsigned strpixels = item_r.width - 60;
|
||||||
|
|
||||||
|
int text_top_off = (item_h_px - graph.text_extent_size(STR("jh({[")).height) / 2;
|
||||||
|
|
||||||
|
std::size_t pos = 0;
|
||||||
|
for (auto & m : menu_->items)
|
||||||
|
{
|
||||||
|
if (m.flags.splitter)
|
||||||
|
{
|
||||||
|
graph_->set_color(colors::gray_border);
|
||||||
|
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph.width()) - 1, item_r.y });
|
||||||
|
item_r.y += 2;
|
||||||
|
++pos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
|
||||||
|
//Draw item background
|
||||||
|
renderer->item(*graph_, item_r, attr);
|
||||||
|
|
||||||
|
//Draw text, the text is transformed from orignal for hotkey character
|
||||||
|
nana::char_t hotkey;
|
||||||
|
nana::string::size_type hotkey_pos;
|
||||||
|
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
|
||||||
|
|
||||||
|
if (m.image.empty() == false)
|
||||||
|
renderer->item_image(graph, nana::point(item_r.x + 5, item_r.y + static_cast<int>(item_h_px - image_px) / 2 - 1), image_px, m.image);
|
||||||
|
|
||||||
|
renderer->item_text(graph, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
|
||||||
|
|
||||||
|
if (hotkey)
|
||||||
|
{
|
||||||
|
m.hotkey = hotkey;
|
||||||
|
if (m.flags.enabled)
|
||||||
|
{
|
||||||
|
unsigned off_w = (hotkey_pos ? graph.text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
|
||||||
|
nana::size hotkey_size = graph.text_extent_size(text.c_str() + hotkey_pos, 1);
|
||||||
|
int x = item_r.x + 40 + off_w;
|
||||||
|
int y = item_r.y + text_top_off + hotkey_size.height;
|
||||||
|
|
||||||
|
graph_->set_color(colors::black);
|
||||||
|
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.sub_menu)
|
||||||
|
renderer->sub_arrow(graph, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
|
||||||
|
|
||||||
|
item_r.y += item_r.height + 1;
|
||||||
|
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t active() const
|
std::size_t active() const
|
||||||
@@ -411,18 +472,18 @@ namespace nana
|
|||||||
state_.active = pos;
|
state_.active = pos;
|
||||||
state_.sub_window = false;
|
state_.sub_window = false;
|
||||||
|
|
||||||
draw();
|
refresh(*graph_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool track_mouse(int x, int y)
|
bool track_mouse(const ::nana::point& pos)
|
||||||
{
|
{
|
||||||
if(state_.nullify_mouse == false)
|
if (!state_.nullify_mouse)
|
||||||
{
|
{
|
||||||
std::size_t index = _m_get_index_by_pos(x, y);
|
std::size_t index = _m_get_index_by_pos(pos.x, pos.y);
|
||||||
if (index != state_.active)
|
if (index != state_.active)
|
||||||
{
|
{
|
||||||
if ((index == npos) && menu_->items.at(state_.active).sub_menu && state_.sub_window)
|
if ((index == npos) && menu_->items.at(state_.active).sub_menu && state_.sub_window)
|
||||||
@@ -433,6 +494,7 @@ namespace nana
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,29 +513,35 @@ namespace nana
|
|||||||
state_.sub_window = subw;
|
state_.sub_window = subw;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_type* retrive_sub_menu(nana::point& pos, std::size_t interval) const
|
menu_type* get_sub(nana::point& pos, unsigned long& tmstamp) const
|
||||||
{
|
{
|
||||||
if(state_.active != npos && (nana::system::timestamp() - state_.active_timestamp >= interval))
|
if (npos == state_.active)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto sub = menu_->items.at(state_.active).sub_menu;
|
||||||
|
if (sub)
|
||||||
{
|
{
|
||||||
pos.x = graph_->width() - 2;
|
pos.x = static_cast<int>(graph_->width()) - 2;
|
||||||
pos.y = 2;
|
pos.y = 2;
|
||||||
|
|
||||||
std::size_t index = 0;
|
auto index = state_.active;
|
||||||
for (auto & m : menu_->items)
|
for (auto & m : menu_->items)
|
||||||
{
|
{
|
||||||
if(false == m.flags.splitter)
|
if (m.flags.splitter)
|
||||||
{
|
{
|
||||||
if(index == state_.active)
|
pos.y += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == index)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pos.y += _m_item_height() + 1;
|
pos.y += _m_item_height() + 1;
|
||||||
|
--index;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
pos.y += 2;
|
|
||||||
|
|
||||||
++index;
|
tmstamp = state_.active_timestamp;
|
||||||
}
|
return sub;
|
||||||
return (menu_->items.at(state_.active).sub_menu);
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -498,8 +566,7 @@ namespace nana
|
|||||||
state_.active = index;
|
state_.active = index;
|
||||||
state_.active_timestamp = nana::system::timestamp();
|
state_.active_timestamp = nana::system::timestamp();
|
||||||
|
|
||||||
draw();
|
API::refresh_window(*widget_);
|
||||||
API::update_window(*widget_);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else if(m.flags.enabled)
|
else if(m.flags.enabled)
|
||||||
@@ -514,72 +581,6 @@ namespace nana
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw() const
|
|
||||||
{
|
|
||||||
if(nullptr == menu_) return;
|
|
||||||
|
|
||||||
_m_adjust_window_size();
|
|
||||||
|
|
||||||
renderer->background(*graph_, *widget_);
|
|
||||||
|
|
||||||
const unsigned item_h_px = _m_item_height();
|
|
||||||
const unsigned image_px = item_h_px - 2;
|
|
||||||
nana::rectangle item_r(2, 2, graph_->width() - 4, item_h_px);
|
|
||||||
|
|
||||||
unsigned strpixels = item_r.width - 60;
|
|
||||||
|
|
||||||
int text_top_off = (item_h_px - graph_->text_extent_size(STR("jh({[")).height) / 2;
|
|
||||||
|
|
||||||
std::size_t pos = 0;
|
|
||||||
for(auto & m : menu_->items)
|
|
||||||
{
|
|
||||||
if(m.flags.splitter)
|
|
||||||
{
|
|
||||||
graph_->set_color(colors::gray_border);
|
|
||||||
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph_->width()) - 1, item_r.y });
|
|
||||||
item_r.y += 2;
|
|
||||||
++pos;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
|
|
||||||
//Draw item background
|
|
||||||
renderer->item(*graph_, item_r, attr);
|
|
||||||
|
|
||||||
//Draw text, the text is transformed from orignal for hotkey character
|
|
||||||
nana::char_t hotkey;
|
|
||||||
nana::string::size_type hotkey_pos;
|
|
||||||
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
|
|
||||||
|
|
||||||
if(m.image.empty() == false)
|
|
||||||
renderer->item_image(*graph_, nana::point(item_r.x + 5, item_r.y + static_cast<int>(item_h_px - image_px) / 2 - 1), image_px, m.image);
|
|
||||||
|
|
||||||
renderer->item_text(*graph_, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
|
|
||||||
|
|
||||||
if(hotkey)
|
|
||||||
{
|
|
||||||
m.hotkey = hotkey;
|
|
||||||
if(m.flags.enabled)
|
|
||||||
{
|
|
||||||
unsigned off_w = (hotkey_pos ? graph_->text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
|
|
||||||
nana::size hotkey_size = graph_->text_extent_size(text.c_str() + hotkey_pos, 1);
|
|
||||||
int x = item_r.x + 40 + off_w;
|
|
||||||
int y = item_r.y + text_top_off + hotkey_size.height;
|
|
||||||
|
|
||||||
graph_->set_color(colors::black);
|
|
||||||
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m.sub_menu)
|
|
||||||
renderer->sub_arrow(*graph_, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
|
|
||||||
|
|
||||||
item_r.y += item_r.height + 1;
|
|
||||||
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
static renderer_interface::attr _m_make_renderer_attr(bool active, const menu_item_type & m)
|
static renderer_interface::attr _m_make_renderer_attr(bool active, const menu_item_type & m)
|
||||||
{
|
{
|
||||||
@@ -685,9 +686,9 @@ namespace nana
|
|||||||
struct state
|
struct state
|
||||||
{
|
{
|
||||||
std::size_t active;
|
std::size_t active;
|
||||||
unsigned long active_timestamp;
|
unsigned active_timestamp;
|
||||||
unsigned long sub_window: 1;
|
bool sub_window: 1;
|
||||||
unsigned long nullify_mouse: 1;
|
bool nullify_mouse: 1;
|
||||||
}state_;
|
}state_;
|
||||||
|
|
||||||
struct widget_detail
|
struct widget_detail
|
||||||
@@ -722,7 +723,19 @@ namespace nana
|
|||||||
submenu_.child = submenu_.parent = nullptr;
|
submenu_.child = submenu_.parent = nullptr;
|
||||||
submenu_.object = nullptr;
|
submenu_.object = nullptr;
|
||||||
|
|
||||||
_m_make_mouse_event();
|
state_.mouse_pos = API::cursor_position();
|
||||||
|
events().mouse_move.connect_unignorable([this]{
|
||||||
|
nana::point pos = API::cursor_position();
|
||||||
|
if (pos != state_.mouse_pos)
|
||||||
|
{
|
||||||
|
menu_window * root = this;
|
||||||
|
while (root->submenu_.parent)
|
||||||
|
root = root->submenu_.parent;
|
||||||
|
root->state_.auto_popup_submenu = true;
|
||||||
|
|
||||||
|
state_.mouse_pos = pos;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void popup(menu_type& menu, bool owner_menubar)
|
void popup(menu_type& menu, bool owner_menubar)
|
||||||
@@ -749,13 +762,19 @@ namespace nana
|
|||||||
_m_key_down(arg);
|
_m_key_down(arg);
|
||||||
});
|
});
|
||||||
|
|
||||||
events().mouse_up.connect_unignorable([this]{
|
events().mouse_down.connect_unignorable([this](const arg_mouse& arg)
|
||||||
|
{
|
||||||
|
this->_m_open_sub(0); //Try to open submenu immediately
|
||||||
|
});
|
||||||
|
|
||||||
|
events().mouse_up.connect_unignorable([this](const arg_mouse& arg){
|
||||||
|
if (arg.left_button)
|
||||||
pick();
|
pick();
|
||||||
});
|
});
|
||||||
|
|
||||||
timer_.interval(100);
|
timer_.interval(100);
|
||||||
timer_.elapse([this]{
|
timer_.elapse([this]{
|
||||||
this->_m_check_repeatly();
|
this->_m_open_sub(500); //Try to open submenu
|
||||||
});
|
});
|
||||||
timer_.start();
|
timer_.start();
|
||||||
|
|
||||||
@@ -801,29 +820,27 @@ namespace nana
|
|||||||
|
|
||||||
bool submenu(bool enter)
|
bool submenu(bool enter)
|
||||||
{
|
{
|
||||||
menu_window * object = this;
|
menu_window * menu_wd = this;
|
||||||
while (object->submenu_.child)
|
while (menu_wd->submenu_.child)
|
||||||
object = object->submenu_.child;
|
menu_wd = menu_wd->submenu_.child;
|
||||||
|
|
||||||
state_.auto_popup_submenu = false;
|
state_.auto_popup_submenu = false;
|
||||||
|
|
||||||
if (enter)
|
if (!enter)
|
||||||
{
|
{
|
||||||
if (object->submenu_.parent)
|
if (menu_wd->submenu_.parent)
|
||||||
{
|
{
|
||||||
auto & sub = object->submenu_.parent->submenu_;
|
auto & sub = menu_wd->submenu_.parent->submenu_;
|
||||||
sub.child = nullptr;
|
sub.child = nullptr;
|
||||||
sub.object = nullptr;
|
sub.object = nullptr;
|
||||||
|
|
||||||
object->close();
|
menu_wd->close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nana::point pos;
|
return menu_wd->_m_manipulate_sub(0, true);
|
||||||
menu_type * sbm = object->get_drawer_trigger().retrive_sub_menu(pos, 0);
|
|
||||||
return object->_m_show_submenu(sbm, pos, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_shortkey(nana::char_t key)
|
int send_shortkey(nana::char_t key)
|
||||||
@@ -969,62 +986,50 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _m_make_mouse_event()
|
bool _m_manipulate_sub(unsigned long delay_ms, bool forced)
|
||||||
{
|
{
|
||||||
state_.mouse_pos = API::cursor_position();
|
auto & drawer = get_drawer_trigger();
|
||||||
events().mouse_move.connect_unignorable([this]{
|
::nana::point pos;
|
||||||
_m_mouse_event();
|
unsigned long tmstamp;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _m_mouse_event()
|
auto menu_ptr = drawer.get_sub(pos, tmstamp);
|
||||||
{
|
|
||||||
nana::point pos = API::cursor_position();
|
|
||||||
if(pos != state_.mouse_pos)
|
|
||||||
{
|
|
||||||
menu_window * root = this;
|
|
||||||
while(root->submenu_.parent)
|
|
||||||
root = root->submenu_.parent;
|
|
||||||
root->state_.auto_popup_submenu = true;
|
|
||||||
|
|
||||||
state_.mouse_pos = pos;
|
if (menu_ptr == submenu_.object)
|
||||||
}
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
bool _m_show_submenu(menu_type* sbm, nana::point pos, bool forced)
|
if (menu_ptr && (::nana::system::timestamp() - tmstamp < delay_ms))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (submenu_.object && (menu_ptr != submenu_.object))
|
||||||
{
|
{
|
||||||
auto & mdtrigger = get_drawer_trigger();
|
drawer.set_sub_window(false);
|
||||||
if(submenu_.object && (sbm != submenu_.object))
|
|
||||||
{
|
|
||||||
mdtrigger.set_sub_window(false);
|
|
||||||
submenu_.child->close();
|
submenu_.child->close();
|
||||||
submenu_.child = nullptr;
|
submenu_.child = nullptr;
|
||||||
submenu_.object = nullptr;
|
submenu_.object = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sbm)
|
if (menu_ptr)
|
||||||
{
|
{
|
||||||
menu_window * root = this;
|
menu_window * root = this;
|
||||||
while (root->submenu_.parent)
|
while (root->submenu_.parent)
|
||||||
root = root->submenu_.parent;
|
root = root->submenu_.parent;
|
||||||
|
|
||||||
if((submenu_.object == nullptr) && sbm && (forced || root->state_.auto_popup_submenu))
|
if ((submenu_.object == nullptr) && menu_ptr && (forced || root->state_.auto_popup_submenu))
|
||||||
{
|
{
|
||||||
sbm->item_pixels = mdtrigger.data()->item_pixels;
|
menu_ptr->item_pixels = drawer.data()->item_pixels;
|
||||||
sbm->gaps = mdtrigger.data()->gaps;
|
menu_ptr->gaps = drawer.data()->gaps;
|
||||||
pos.x += sbm->gaps.x;
|
pos += menu_ptr->gaps;
|
||||||
pos.y += sbm->gaps.y;
|
|
||||||
|
|
||||||
menu_window & mwnd = form_loader<menu_window, false>()(handle(), true, pos, mdtrigger.renderer);
|
menu_window & mwnd = form_loader<menu_window, false>()(handle(), true, pos, drawer.renderer);
|
||||||
mwnd.state_.self_submenu = true;
|
mwnd.state_.self_submenu = true;
|
||||||
submenu_.child = &mwnd;
|
submenu_.child = &mwnd;
|
||||||
submenu_.child->submenu_.parent = this;
|
submenu_.child->submenu_.parent = this;
|
||||||
submenu_.object = sbm;
|
submenu_.object = menu_ptr;
|
||||||
|
|
||||||
API::set_window_z_order(handle(), mwnd.handle(), z_order_action::none);
|
API::set_window_z_order(handle(), mwnd.handle(), z_order_action::none);
|
||||||
|
|
||||||
mwnd.popup(*sbm, state_.owner_menubar);
|
mwnd.popup(*menu_ptr, state_.owner_menubar);
|
||||||
mdtrigger.set_sub_window(true);
|
drawer.set_sub_window(true);
|
||||||
if (forced)
|
if (forced)
|
||||||
mwnd.goto_next(true);
|
mwnd.goto_next(true);
|
||||||
|
|
||||||
@@ -1034,17 +1039,16 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _m_check_repeatly()
|
void _m_open_sub(unsigned delay_ms) //check_repeatly
|
||||||
{
|
{
|
||||||
if(state_.auto_popup_submenu)
|
if(state_.auto_popup_submenu)
|
||||||
{
|
{
|
||||||
nana::point pos = API::cursor_position();
|
auto pos = API::cursor_position();
|
||||||
|
|
||||||
drawer_type& drawer = get_drawer_trigger();
|
|
||||||
API::calc_window_point(handle(), pos);
|
API::calc_window_point(handle(), pos);
|
||||||
drawer.track_mouse(pos.x, pos.y);
|
get_drawer_trigger().track_mouse(pos);
|
||||||
menu_type* sbm = drawer.retrive_sub_menu(pos, 500);
|
|
||||||
_m_show_submenu(sbm, pos, false);
|
_m_manipulate_sub(delay_ms, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user