refactor menubar
This commit is contained in:
parent
64899a3d6a
commit
fba4097851
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A Menubar implementation
|
* A Menubar implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -58,13 +58,12 @@ namespace nana
|
|||||||
: public drawer_trigger
|
: public drawer_trigger
|
||||||
{
|
{
|
||||||
class itembase;
|
class itembase;
|
||||||
|
|
||||||
|
struct essence;
|
||||||
public:
|
public:
|
||||||
trigger();
|
trigger();
|
||||||
~trigger();
|
~trigger();
|
||||||
nana::menu* push_back(const std::string&);
|
essence& ess() const;
|
||||||
nana::menu* at(size_t) const;
|
|
||||||
std::size_t size() const;
|
|
||||||
bool cancel();
|
|
||||||
private:
|
private:
|
||||||
void attached(widget_reference, graph_reference) override;
|
void attached(widget_reference, graph_reference) override;
|
||||||
void refresh(graph_reference) override;
|
void refresh(graph_reference) override;
|
||||||
@ -77,38 +76,9 @@ namespace nana
|
|||||||
void key_release(graph_reference, const arg_keyboard&) override;
|
void key_release(graph_reference, const arg_keyboard&) override;
|
||||||
void shortkey(graph_reference, const arg_keyboard&) override;
|
void shortkey(graph_reference, const arg_keyboard&) override;
|
||||||
private:
|
private:
|
||||||
void _m_move(bool to_left);
|
void _m_move(graph_reference, bool to_left);
|
||||||
bool _m_popup_menu();
|
|
||||||
void _m_total_close();
|
|
||||||
bool _m_close_menu();
|
|
||||||
std::size_t _m_item_by_pos(const ::nana::point&);
|
|
||||||
bool _m_track_mouse(const ::nana::point&);
|
|
||||||
private:
|
private:
|
||||||
widget *widget_;
|
essence * const ess_;
|
||||||
paint::graphics *graph_;
|
|
||||||
|
|
||||||
itembase* items_;
|
|
||||||
|
|
||||||
struct state_type
|
|
||||||
{
|
|
||||||
enum behavior_t
|
|
||||||
{
|
|
||||||
behavior_none, behavior_focus, behavior_menu,
|
|
||||||
};
|
|
||||||
|
|
||||||
state_type();
|
|
||||||
|
|
||||||
std::size_t active;
|
|
||||||
behavior_t behavior;
|
|
||||||
|
|
||||||
bool menu_active;
|
|
||||||
bool passive_close;
|
|
||||||
|
|
||||||
bool nullify_mouse;
|
|
||||||
|
|
||||||
nana::menu *menu;
|
|
||||||
nana::point mouse_pos;
|
|
||||||
}state_;
|
|
||||||
};
|
};
|
||||||
}//end namespace menubar
|
}//end namespace menubar
|
||||||
}//end namespace drawerbase
|
}//end namespace drawerbase
|
||||||
|
@ -30,7 +30,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
struct item_type
|
struct item_type
|
||||||
{
|
{
|
||||||
item_type(const native_string_type text, unsigned long shortkey)
|
item_type(const native_string_type& text, unsigned long shortkey)
|
||||||
: text(text), shortkey(shortkey)
|
: text(text), shortkey(shortkey)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -83,6 +83,131 @@ namespace nana
|
|||||||
container cont_;
|
container cont_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct trigger::essence
|
||||||
|
{
|
||||||
|
widget *widget_ptr{ nullptr };
|
||||||
|
//paint::graphics *graph{ nullptr };
|
||||||
|
|
||||||
|
itembase items;
|
||||||
|
|
||||||
|
enum class behavior
|
||||||
|
{
|
||||||
|
none, focus, menu,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct state_type
|
||||||
|
{
|
||||||
|
std::size_t active{ nana::npos };
|
||||||
|
behavior behave{ behavior::none };
|
||||||
|
|
||||||
|
bool menu_active{ false };
|
||||||
|
bool passive_close{ true };
|
||||||
|
|
||||||
|
bool nullify_mouse{ false };
|
||||||
|
|
||||||
|
nana::menu *menu{ nullptr };
|
||||||
|
nana::point mouse_pos;
|
||||||
|
}state;
|
||||||
|
|
||||||
|
//functions
|
||||||
|
nana::menu& push_back(const std::string& text)
|
||||||
|
{
|
||||||
|
wchar_t shortkey;
|
||||||
|
API::transform_shortkey_text(text, shortkey, nullptr);
|
||||||
|
|
||||||
|
if (shortkey)
|
||||||
|
API::register_shortkey(this->widget_ptr->handle(), shortkey);
|
||||||
|
|
||||||
|
this->items.append(to_nstring(text), shortkey);
|
||||||
|
API::refresh_window(this->widget_ptr->handle());
|
||||||
|
|
||||||
|
return this->items.cont()[this->items.cont().size() - 1]->menu_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cancel()
|
||||||
|
{
|
||||||
|
if (nana::npos == state.active)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this->close_menu();
|
||||||
|
state.menu_active = false;
|
||||||
|
state.behave = behavior::none;
|
||||||
|
|
||||||
|
auto pos = API::cursor_position();
|
||||||
|
API::calc_window_point(widget_ptr->handle(), pos);
|
||||||
|
state.active = find(pos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool open_menu()
|
||||||
|
{
|
||||||
|
auto pos = state.active;
|
||||||
|
if (pos >= items.cont().size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto item_ptr = items.cont()[pos];
|
||||||
|
|
||||||
|
if (state.menu_active && (state.menu != &(item_ptr->menu_obj)))
|
||||||
|
{
|
||||||
|
API::dev::delay_restore(true);
|
||||||
|
this->close_menu();
|
||||||
|
API::dev::delay_restore(false);
|
||||||
|
state.active = pos;
|
||||||
|
|
||||||
|
state.menu = &(item_ptr->menu_obj);
|
||||||
|
state.menu->destroy_answer([this]
|
||||||
|
{
|
||||||
|
state.menu = nullptr;
|
||||||
|
if (state.passive_close)
|
||||||
|
{
|
||||||
|
cancel();
|
||||||
|
API::refresh_window(*widget_ptr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (API::focus_window() != this->widget_ptr->handle())
|
||||||
|
API::focus_window(widget_ptr->handle());
|
||||||
|
menu_accessor::popup(*state.menu, *widget_ptr, item_ptr->pos.x, item_ptr->pos.y + static_cast<int>(item_ptr->size.height));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool close_menu()
|
||||||
|
{
|
||||||
|
if (state.menu)
|
||||||
|
{
|
||||||
|
state.passive_close = false;
|
||||||
|
state.menu->close();
|
||||||
|
state.passive_close = true;
|
||||||
|
state.menu = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t find(const ::nana::point& pos)
|
||||||
|
{
|
||||||
|
if ((2 <= pos.x) && (2 <= pos.y) && (pos.y < 25))
|
||||||
|
{
|
||||||
|
int item_x = 2;
|
||||||
|
std::size_t index = 0;
|
||||||
|
for (auto i : items.cont())
|
||||||
|
{
|
||||||
|
if (item_x <= pos.x && pos.x < item_x + static_cast<int>(i->size.width))
|
||||||
|
return index;
|
||||||
|
|
||||||
|
item_x += i->size.width;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//class item_renderer
|
//class item_renderer
|
||||||
item_renderer::item_renderer(window wd, graph_reference graph)
|
item_renderer::item_renderer(window wd, graph_reference graph)
|
||||||
:graph_(graph), scheme_ptr_(static_cast<scheme*>(API::dev::get_scheme(wd)))
|
:graph_(graph), scheme_ptr_(static_cast<scheme*>(API::dev::get_scheme(wd)))
|
||||||
@ -91,19 +216,17 @@ namespace nana
|
|||||||
void item_renderer::background(const nana::point& pos, const nana::size& size, state item_state)
|
void item_renderer::background(const nana::point& pos, const nana::size& size, state item_state)
|
||||||
{
|
{
|
||||||
auto bground = scheme_ptr_->text_fgcolor;
|
auto bground = scheme_ptr_->text_fgcolor;
|
||||||
::nana::color border, body, corner;
|
::nana::color border, body;
|
||||||
|
|
||||||
switch (item_state)
|
switch (item_state)
|
||||||
{
|
{
|
||||||
case state::highlighted:
|
case state::highlighted:
|
||||||
border = scheme_ptr_->border_highlight;
|
border = scheme_ptr_->border_highlight;
|
||||||
body = scheme_ptr_->body_highlight;
|
body = scheme_ptr_->body_highlight;
|
||||||
corner = body.blend(bground, 0.5);
|
|
||||||
break;
|
break;
|
||||||
case state::selected:
|
case state::selected:
|
||||||
border = scheme_ptr_->border_selected;
|
border = scheme_ptr_->border_selected;
|
||||||
body = scheme_ptr_->body_selected;
|
body = scheme_ptr_->body_selected;
|
||||||
corner = body.blend(bground, 0.5);
|
|
||||||
break;
|
break;
|
||||||
default: //Don't process other states.
|
default: //Don't process other states.
|
||||||
return;
|
return;
|
||||||
@ -112,7 +235,7 @@ namespace nana
|
|||||||
nana::rectangle r(pos, size);
|
nana::rectangle r(pos, size);
|
||||||
graph_.rectangle(r, false, border);
|
graph_.rectangle(r, false, border);
|
||||||
|
|
||||||
graph_.palette(false, corner);
|
graph_.palette(false, body.blend(bground, 0.5));
|
||||||
|
|
||||||
paint::draw{ graph_ }.corner(r, 1);
|
paint::draw{ graph_ }.corner(r, 1);
|
||||||
graph_.rectangle(r.pare_off(1), true, body);
|
graph_.rectangle(r.pare_off(1), true, body);
|
||||||
@ -127,86 +250,52 @@ namespace nana
|
|||||||
|
|
||||||
//class trigger
|
//class trigger
|
||||||
trigger::trigger()
|
trigger::trigger()
|
||||||
: widget_(nullptr)
|
: ess_(new essence)
|
||||||
, graph_(nullptr)
|
{}
|
||||||
, items_(new itembase) {}
|
|
||||||
|
|
||||||
trigger::~trigger()
|
trigger::~trigger()
|
||||||
{
|
{
|
||||||
delete items_;
|
delete ess_;
|
||||||
}
|
}
|
||||||
|
|
||||||
nana::menu* trigger::push_back(const std::string& text)
|
auto trigger::ess() const -> essence&
|
||||||
{
|
{
|
||||||
wchar_t shkey;
|
return *ess_;
|
||||||
API::transform_shortkey_text(text, shkey, nullptr);
|
|
||||||
|
|
||||||
if(shkey)
|
|
||||||
API::register_shortkey(widget_->handle(), shkey);
|
|
||||||
|
|
||||||
auto pos = items_->cont().size();
|
|
||||||
items_->append(to_nstring(text), shkey);
|
|
||||||
refresh(*graph_);
|
|
||||||
API::update_window(*widget_);
|
|
||||||
|
|
||||||
return at(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
nana::menu* trigger::at(std::size_t pos) const
|
|
||||||
{
|
|
||||||
if (pos < items_->cont().size())
|
|
||||||
return &(items_->cont()[pos]->menu_obj);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t trigger::size() const
|
|
||||||
{
|
|
||||||
return items_->cont().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool trigger::cancel()
|
|
||||||
{
|
|
||||||
if (nana::npos == state_.active)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_m_total_close();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::attached(widget_reference widget, graph_reference graph)
|
void trigger::attached(widget_reference widget, graph_reference graph)
|
||||||
{
|
{
|
||||||
graph_ = &graph;
|
ess_->widget_ptr = &widget;
|
||||||
widget_ = &widget;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::refresh(graph_reference graph)
|
void trigger::refresh(graph_reference graph)
|
||||||
{
|
{
|
||||||
auto bgcolor = API::bgcolor(*widget_);
|
auto bgcolor = API::bgcolor(*ess_->widget_ptr);
|
||||||
graph_->rectangle(true, bgcolor);
|
|
||||||
|
|
||||||
item_renderer ird(*widget_, graph);
|
graph.rectangle(true, bgcolor);
|
||||||
|
|
||||||
|
item_renderer ird{ *ess_->widget_ptr, graph };
|
||||||
|
|
||||||
nana::point item_pos(2, 2);
|
nana::point item_pos(2, 2);
|
||||||
nana::size item_s(0, 23);
|
nana::size item_s(0, 23);
|
||||||
|
|
||||||
unsigned long index = 0;
|
unsigned long index = 0;
|
||||||
for (auto i : items_->cont())
|
for (auto pm : ess_->items.cont())
|
||||||
{
|
{
|
||||||
//Transform the text if it contains the hotkey character
|
//Transform the text if it contains the hotkey character
|
||||||
wchar_t hotkey;
|
wchar_t hotkey;
|
||||||
::std::wstring::size_type hotkey_pos;
|
::std::wstring::size_type hotkey_pos;
|
||||||
auto text = API::transform_shortkey_text(to_utf8(i->text), hotkey, &hotkey_pos);
|
auto text = API::transform_shortkey_text(to_utf8(pm->text), hotkey, &hotkey_pos);
|
||||||
|
|
||||||
nana::size text_s = graph.text_extent_size(text);
|
nana::size text_s = graph.text_extent_size(text);
|
||||||
|
|
||||||
item_s.width = text_s.width + 16;
|
item_s.width = text_s.width + 16;
|
||||||
|
|
||||||
i->pos = item_pos;
|
pm->pos = item_pos;
|
||||||
i->size = item_s;
|
pm->size = item_s;
|
||||||
|
|
||||||
using state = item_renderer::state;
|
using state = item_renderer::state;
|
||||||
state item_state = (index != state_.active ? state::normal : (state_.menu_active ? state::selected : state::highlighted));
|
state item_state = (index != ess_->state.active ? state::normal : (ess_->state.menu_active ? state::selected : state::highlighted));
|
||||||
ird.background(item_pos, item_s, item_state);
|
ird.background(item_pos, item_s, item_state);
|
||||||
|
|
||||||
if (state::selected == item_state)
|
if (state::selected == item_state)
|
||||||
@ -223,59 +312,67 @@ namespace nana
|
|||||||
|
|
||||||
API::dev::draw_shortkey_underline(graph, text, hotkey, hotkey_pos, { item_pos.x + 8, item_pos.y + text_top_off }, ird.scheme_ptr()->text_fgcolor);
|
API::dev::draw_shortkey_underline(graph, text, hotkey, hotkey_pos, { item_pos.x + 8, item_pos.y + text_top_off }, ird.scheme_ptr()->text_fgcolor);
|
||||||
|
|
||||||
item_pos.x += i->size.width;
|
item_pos.x += pm->size.width;
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||||
{
|
{
|
||||||
if (arg.pos != state_.mouse_pos)
|
|
||||||
state_.nullify_mouse = false;
|
if (arg.pos != ess_->state.mouse_pos)
|
||||||
|
ess_->state.nullify_mouse = false;
|
||||||
|
|
||||||
bool popup = false;
|
bool popup = false;
|
||||||
if(state_.behavior == state_type::behavior_focus)
|
if(essence::behavior::focus == ess_->state.behave)
|
||||||
{
|
{
|
||||||
auto index = _m_item_by_pos(arg.pos);
|
auto index = ess_->find(arg.pos);
|
||||||
if(index != npos && state_.active != index)
|
if(index != npos && ess_->state.active != index)
|
||||||
{
|
{
|
||||||
state_.active = index;
|
ess_->state.active = index;
|
||||||
|
popup = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!ess_->state.nullify_mouse)
|
||||||
|
{
|
||||||
|
auto which = ess_->find(arg.pos);
|
||||||
|
if ((which != ess_->state.active) && (which != npos || (false == ess_->state.menu_active)))
|
||||||
|
{
|
||||||
|
ess_->state.active = which;
|
||||||
popup = true;
|
popup = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
popup = _m_track_mouse(arg.pos);
|
|
||||||
|
|
||||||
if(popup)
|
if(popup)
|
||||||
{
|
{
|
||||||
_m_popup_menu();
|
ess_->open_menu();
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
state_.mouse_pos = arg.pos;
|
ess_->state.mouse_pos = arg.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::mouse_leave(graph_reference graph, const arg_mouse& arg)
|
void trigger::mouse_leave(graph_reference graph, const arg_mouse& arg)
|
||||||
{
|
{
|
||||||
state_.nullify_mouse = false;
|
ess_->state.nullify_mouse = false;
|
||||||
mouse_move(graph, arg);
|
mouse_move(graph, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::mouse_down(graph_reference graph, const arg_mouse& arg)
|
void trigger::mouse_down(graph_reference graph, const arg_mouse& arg)
|
||||||
{
|
{
|
||||||
state_.nullify_mouse = false;
|
ess_->state.nullify_mouse = false;
|
||||||
state_.active = _m_item_by_pos(arg.pos);
|
ess_->state.active = ess_->find(arg.pos);
|
||||||
|
|
||||||
if (npos != state_.active)
|
if (npos != ess_->state.active)
|
||||||
{
|
{
|
||||||
if (!state_.menu_active)
|
if (!ess_->state.menu_active)
|
||||||
state_.menu_active = true;
|
ess_->state.menu_active = true;
|
||||||
|
|
||||||
_m_popup_menu();
|
ess_->open_menu();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_m_total_close();
|
ess_->cancel();
|
||||||
|
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
@ -283,17 +380,17 @@ namespace nana
|
|||||||
|
|
||||||
void trigger::mouse_up(graph_reference graph, const arg_mouse&)
|
void trigger::mouse_up(graph_reference graph, const arg_mouse&)
|
||||||
{
|
{
|
||||||
state_.nullify_mouse = false;
|
ess_->state.nullify_mouse = false;
|
||||||
|
|
||||||
if(state_.behavior != state_.behavior_menu)
|
if(ess_->state.behave != essence::behavior::menu)
|
||||||
{
|
{
|
||||||
if(state_.menu_active)
|
if(ess_->state.menu_active)
|
||||||
state_.behavior = state_.behavior_menu;
|
ess_->state.behave = essence::behavior::menu;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state_.behavior = state_.behavior_none;
|
ess_->state.behave = essence::behavior::none;
|
||||||
_m_total_close();
|
ess_->cancel();
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
@ -301,13 +398,13 @@ namespace nana
|
|||||||
|
|
||||||
void trigger::focus(graph_reference graph, const arg_focus& arg)
|
void trigger::focus(graph_reference graph, const arg_focus& arg)
|
||||||
{
|
{
|
||||||
if((arg.getting == false) && (state_.active != npos))
|
if((arg.getting == false) && (ess_->state.active != npos))
|
||||||
{
|
{
|
||||||
state_.behavior = state_type::behavior_none;
|
ess_->state.behave = essence::behavior::none;
|
||||||
state_.nullify_mouse = true;
|
ess_->state.nullify_mouse = true;
|
||||||
state_.menu_active = false;
|
ess_->state.menu_active = false;
|
||||||
_m_close_menu();
|
ess_->close_menu();
|
||||||
state_.active = npos;
|
ess_->state.active = npos;
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
@ -315,53 +412,55 @@ namespace nana
|
|||||||
|
|
||||||
void trigger::key_press(graph_reference graph, const arg_keyboard& arg)
|
void trigger::key_press(graph_reference graph, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
state_.nullify_mouse = true;
|
ess_->state.nullify_mouse = true;
|
||||||
if(state_.menu)
|
|
||||||
|
auto & menu_ptr = ess_->state.menu;
|
||||||
|
if(ess_->state.menu)
|
||||||
{
|
{
|
||||||
switch(arg.key)
|
switch(arg.key)
|
||||||
{
|
{
|
||||||
case keyboard::os_arrow_down:
|
case keyboard::os_arrow_down:
|
||||||
case keyboard::backspace:
|
case keyboard::backspace:
|
||||||
case keyboard::os_arrow_up:
|
case keyboard::os_arrow_up:
|
||||||
state_.menu->goto_next(keyboard::os_arrow_down == arg.key);
|
menu_ptr->goto_next(keyboard::os_arrow_down == arg.key);
|
||||||
break;
|
break;
|
||||||
case keyboard::os_arrow_right:
|
case keyboard::os_arrow_right:
|
||||||
if(state_.menu->goto_submen() == false)
|
if(menu_ptr->goto_submen() == false)
|
||||||
_m_move(false);
|
_m_move(graph, false);
|
||||||
break;
|
break;
|
||||||
case keyboard::os_arrow_left:
|
case keyboard::os_arrow_left:
|
||||||
if(state_.menu->exit_submenu() == false)
|
if(menu_ptr->exit_submenu() == false)
|
||||||
_m_move(true);
|
_m_move(graph, true);
|
||||||
break;
|
break;
|
||||||
case keyboard::escape:
|
case keyboard::escape:
|
||||||
if(state_.menu->exit_submenu() == false)
|
if(menu_ptr->exit_submenu() == false)
|
||||||
{
|
{
|
||||||
_m_close_menu();
|
ess_->close_menu();
|
||||||
state_.behavior = state_.behavior_focus;
|
ess_->state.behave = essence::behavior::focus;
|
||||||
state_.menu_active = false;
|
ess_->state.menu_active = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case keyboard::enter:
|
case keyboard::enter:
|
||||||
state_.menu->pick();
|
menu_ptr->pick();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//Katsuhisa Yuasa: menubar key_press improvements
|
//Katsuhisa Yuasa: menubar key_press improvements
|
||||||
//send_shortkey has 3 states, 0 = UNKNOWN KEY, 1 = ITEM, 2 = GOTO SUBMENU
|
//send_shortkey has 3 states, 0 = UNKNOWN KEY, 1 = ITEM, 2 = GOTO SUBMENU
|
||||||
int sk_state = state_.menu->send_shortkey(arg.key);
|
int sk_state = menu_ptr->send_shortkey(arg.key);
|
||||||
switch(sk_state)
|
switch(sk_state)
|
||||||
{
|
{
|
||||||
case 0: //UNKNOWN KEY
|
case 0: //UNKNOWN KEY
|
||||||
break;
|
break;
|
||||||
case 1: //ITEM
|
case 1: //ITEM
|
||||||
if (state_.active != npos)
|
if (ess_->state.active != npos)
|
||||||
{
|
{
|
||||||
_m_total_close();
|
ess_->cancel();
|
||||||
if (arg.key == 18) //ALT
|
if (arg.key == 18) //ALT
|
||||||
state_.behavior = state_.behavior_focus;
|
ess_->state.behave = essence::behavior::focus;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: //GOTO SUBMENU
|
case 2: //GOTO SUBMENU
|
||||||
state_.menu->goto_submen();
|
menu_ptr->goto_submen();
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -375,30 +474,30 @@ namespace nana
|
|||||||
case keyboard::os_arrow_right:
|
case keyboard::os_arrow_right:
|
||||||
case keyboard::backspace:
|
case keyboard::backspace:
|
||||||
case keyboard::os_arrow_left:
|
case keyboard::os_arrow_left:
|
||||||
_m_move(keyboard::os_arrow_right != arg.key);
|
_m_move(graph, keyboard::os_arrow_right != arg.key);
|
||||||
break;
|
break;
|
||||||
case keyboard::os_arrow_up:
|
case keyboard::os_arrow_up:
|
||||||
case keyboard::os_arrow_down:
|
case keyboard::os_arrow_down:
|
||||||
case keyboard::enter:
|
case keyboard::enter:
|
||||||
state_.menu_active = true;
|
ess_->state.menu_active = true;
|
||||||
if(_m_popup_menu())
|
if(ess_->open_menu())
|
||||||
state_.menu->goto_next(true);
|
menu_ptr->goto_next(true);
|
||||||
break;
|
break;
|
||||||
case keyboard::escape:
|
case keyboard::escape:
|
||||||
if(state_.behavior == state_.behavior_focus)
|
if(essence::behavior::focus == ess_->state.behave)
|
||||||
{
|
{
|
||||||
state_.active= npos;
|
ess_->state.active= npos;
|
||||||
state_.behavior = state_.behavior_none;
|
ess_->state.behave = essence::behavior::none;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
auto index = items_->find(arg.key);
|
auto index = ess_->items.find(arg.key);
|
||||||
if(index != npos)
|
if(index != npos)
|
||||||
{
|
{
|
||||||
state_.active = index;
|
ess_->state.active = index;
|
||||||
state_.menu_active = true;
|
ess_->state.menu_active = true;
|
||||||
if(_m_popup_menu())
|
if(ess_->open_menu())
|
||||||
state_.menu->goto_next(true);
|
menu_ptr->goto_next(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -412,20 +511,20 @@ namespace nana
|
|||||||
{
|
{
|
||||||
if(arg.key == 18)
|
if(arg.key == 18)
|
||||||
{
|
{
|
||||||
if(state_.behavior == state_type::behavior_none)
|
if(essence::behavior::none == ess_->state.behave)
|
||||||
{
|
{
|
||||||
state_.behavior = state_type::behavior_focus;
|
ess_->state.behave = essence::behavior::focus;
|
||||||
state_.active = 0;
|
ess_->state.active = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state_.behavior = state_type::behavior_none;
|
ess_->state.behave = essence::behavior::none;
|
||||||
auto pos = API::cursor_position();
|
auto pos = API::cursor_position();
|
||||||
API::calc_window_point(widget_->handle(), pos);
|
API::calc_window_point(ess_->widget_ptr->handle(), pos);
|
||||||
state_.active = _m_item_by_pos(pos);
|
ess_->state.active = ess_->find(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
state_.menu_active = false;
|
ess_->state.menu_active = false;
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
@ -433,31 +532,31 @@ namespace nana
|
|||||||
|
|
||||||
void trigger::shortkey(graph_reference graph, const arg_keyboard& arg)
|
void trigger::shortkey(graph_reference graph, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
API::focus_window(widget_->handle());
|
API::focus_window(ess_->widget_ptr->handle());
|
||||||
|
|
||||||
auto index = items_->find(arg.key);
|
auto index = ess_->items.find(arg.key);
|
||||||
if(index != npos && (index != state_.active || nullptr == state_.menu))
|
if(index != npos && (index != ess_->state.active || nullptr == ess_->state.menu))
|
||||||
{
|
{
|
||||||
_m_close_menu();
|
ess_->close_menu();
|
||||||
state_.menu_active = true;
|
ess_->state.menu_active = true;
|
||||||
state_.nullify_mouse = true;
|
ess_->state.nullify_mouse = true;
|
||||||
state_.active = index;
|
ess_->state.active = index;
|
||||||
|
|
||||||
if(_m_popup_menu())
|
if(ess_->open_menu())
|
||||||
state_.menu->goto_next(true);
|
ess_->state.menu->goto_next(true);
|
||||||
|
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
state_.behavior = state_.behavior_menu;
|
ess_->state.behave = essence::behavior::menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::_m_move(bool to_left)
|
void trigger::_m_move(graph_reference graph, bool to_left)
|
||||||
{
|
{
|
||||||
if(items_->cont().empty()) return;
|
if(ess_->items.cont().empty()) return;
|
||||||
|
|
||||||
const std::size_t last_pos = items_->cont().size() - 1;
|
const std::size_t last_pos = ess_->items.cont().size() - 1;
|
||||||
auto index = state_.active;
|
auto index = ess_->state.active;
|
||||||
if(to_left)
|
if(to_left)
|
||||||
{
|
{
|
||||||
--index;
|
--index;
|
||||||
@ -471,121 +570,16 @@ namespace nana
|
|||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index != state_.active)
|
if(index != ess_->state.active)
|
||||||
{
|
{
|
||||||
state_.active = index;
|
ess_->state.active = index;
|
||||||
refresh(*graph_);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
|
|
||||||
if(_m_popup_menu())
|
if(ess_->open_menu())
|
||||||
state_.menu->goto_next(true);
|
ess_->state.menu->goto_next(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool trigger::_m_popup_menu()
|
|
||||||
{
|
|
||||||
auto& items = items_->cont();
|
|
||||||
|
|
||||||
auto pos = state_.active;
|
|
||||||
if (pos >= items.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(state_.menu_active && (state_.menu != &(items[pos]->menu_obj)))
|
|
||||||
{
|
|
||||||
API::dev::delay_restore(true);
|
|
||||||
_m_close_menu();
|
|
||||||
API::dev::delay_restore(false);
|
|
||||||
state_.active = pos;
|
|
||||||
|
|
||||||
auto & m = items[pos];
|
|
||||||
state_.menu = &(m->menu_obj);
|
|
||||||
state_.menu->destroy_answer([this]
|
|
||||||
{
|
|
||||||
state_.menu = nullptr;
|
|
||||||
if (state_.passive_close)
|
|
||||||
{
|
|
||||||
_m_total_close();
|
|
||||||
|
|
||||||
refresh(*graph_);
|
|
||||||
API::update_window(widget_->handle());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (API::focus_window() != this->widget_->handle())
|
|
||||||
API::focus_window(widget_->handle());
|
|
||||||
menu_accessor::popup(*state_.menu, *widget_, m->pos.x, m->pos.y + static_cast<int>(m->size.height));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void trigger::_m_total_close()
|
|
||||||
{
|
|
||||||
_m_close_menu();
|
|
||||||
state_.menu_active = false;
|
|
||||||
state_.behavior = state_.behavior_none;
|
|
||||||
|
|
||||||
auto pos = API::cursor_position();
|
|
||||||
API::calc_window_point(widget_->handle(), pos);
|
|
||||||
state_.active = _m_item_by_pos(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool trigger::_m_close_menu()
|
|
||||||
{
|
|
||||||
if(state_.menu)
|
|
||||||
{
|
|
||||||
state_.passive_close = false;
|
|
||||||
state_.menu->close();
|
|
||||||
state_.passive_close = true;
|
|
||||||
state_.menu = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t trigger::_m_item_by_pos(const ::nana::point& pos)
|
|
||||||
{
|
|
||||||
if((2 <= pos.x) && (2 <= pos.y) && (pos.y < 25))
|
|
||||||
{
|
|
||||||
int item_x = 2;
|
|
||||||
std::size_t index = 0;
|
|
||||||
for(auto i : items_->cont())
|
|
||||||
{
|
|
||||||
if(item_x <= pos.x && pos.x < item_x + static_cast<int>(i->size.width))
|
|
||||||
return index;
|
|
||||||
|
|
||||||
item_x += i->size.width;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool trigger::_m_track_mouse(const ::nana::point& pos)
|
|
||||||
{
|
|
||||||
if(state_.nullify_mouse == false)
|
|
||||||
{
|
|
||||||
auto which = _m_item_by_pos(pos);
|
|
||||||
if((which != state_.active) && (which != npos || (false == state_.menu_active)))
|
|
||||||
{
|
|
||||||
state_.active = which;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//struct state_type
|
|
||||||
trigger::state_type::state_type()
|
|
||||||
: active(npos),
|
|
||||||
behavior(behavior_none),
|
|
||||||
menu_active(false),
|
|
||||||
passive_close(true),
|
|
||||||
nullify_mouse(false),
|
|
||||||
menu(nullptr)
|
|
||||||
{}
|
|
||||||
//end struct state_type
|
|
||||||
//end class trigger
|
//end class trigger
|
||||||
}//end namespace menubar
|
}//end namespace menubar
|
||||||
}//end namespace drawerbase
|
}//end namespace drawerbase
|
||||||
@ -608,7 +602,7 @@ namespace nana
|
|||||||
::create(wd, rectangle(nana::size(API::window_size(wd).width, 28)));
|
::create(wd, rectangle(nana::size(API::window_size(wd).width, 28)));
|
||||||
|
|
||||||
API::dev::set_menubar(handle(), true);
|
API::dev::set_menubar(handle(), true);
|
||||||
evt_resized_ = API::events(wd).resized.connect([this](const ::nana::arg_resized& arg)
|
evt_resized_ = API::events(wd).resized.connect_unignorable([this](const ::nana::arg_resized& arg)
|
||||||
{
|
{
|
||||||
auto sz = this->size();
|
auto sz = this->size();
|
||||||
sz.width = arg.width;
|
sz.width = arg.width;
|
||||||
@ -618,25 +612,22 @@ namespace nana
|
|||||||
|
|
||||||
menu& menubar::push_back(const std::string& text)
|
menu& menubar::push_back(const std::string& text)
|
||||||
{
|
{
|
||||||
return *(get_drawer_trigger().push_back(text));
|
return get_drawer_trigger().ess().push_back(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu& menubar::at(std::size_t index) const
|
menu& menubar::at(std::size_t pos) const
|
||||||
{
|
{
|
||||||
auto p = get_drawer_trigger().at(index);
|
return get_drawer_trigger().ess().items.cont().at(pos)->menu_obj;
|
||||||
if(nullptr == p)
|
|
||||||
throw std::out_of_range("menubar::at, out of range");
|
|
||||||
return *p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t menubar::length() const
|
std::size_t menubar::length() const
|
||||||
{
|
{
|
||||||
return get_drawer_trigger().size();
|
return get_drawer_trigger().ess().items.cont().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool menubar::cancel()
|
bool menubar::cancel()
|
||||||
{
|
{
|
||||||
return get_drawer_trigger().cancel();
|
return get_drawer_trigger().ess().cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool menubar::hovered() const
|
bool menubar::hovered() const
|
||||||
@ -648,14 +639,15 @@ namespace nana
|
|||||||
if (wd == this->handle())
|
if (wd == this->handle())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
auto & items = get_drawer_trigger().ess().items.cont();
|
||||||
while (wd)
|
while (wd)
|
||||||
{
|
{
|
||||||
auto owner = API::get_owner_window(wd);
|
auto owner = API::get_owner_window(wd);
|
||||||
if (API::root(owner) == native_handle)
|
if (API::root(owner) == native_handle)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < get_drawer_trigger().size(); ++i)
|
for (auto p : items)
|
||||||
{
|
{
|
||||||
if(get_drawer_trigger().at(i)->handle() == wd)
|
if (p->menu_obj.handle() == wd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user