fix menubar behavior issue

no key_press and key_release after destroying caret under X11
missing some key_press events
menu text color issue
This commit is contained in:
Jinhao
2015-04-21 22:33:18 +08:00
parent f11e5efe80
commit 3c4f8ae6d9
16 changed files with 315 additions and 249 deletions

View File

@@ -58,16 +58,6 @@ namespace nana
cont_.push_back(new item_type(text, shortkey));
}
nana::menu* get_menu(std::size_t index) const
{
return (index < cont_.size() ? &(cont_[index]->menu_obj) : nullptr);
}
const item_type& at(std::size_t index) const
{
return *cont_.at(index);
}
std::size_t find(unsigned long shortkey) const
{
if(shortkey)
@@ -98,19 +88,19 @@ namespace nana
:handle_(wd), graph_(graph)
{}
void item_renderer::background(const nana::point& pos, const nana::size& size, state_t state)
void item_renderer::background(const nana::point& pos, const nana::size& size, state item_state)
{
auto bground = API::fgcolor(handle_);
::nana::color border, body, corner;
switch(state)
switch (item_state)
{
case item_renderer::state_highlight:
case state::highlighted:
border = colors::highlight;
body.from_rgb(0xC0, 0xDD, 0xFC);
corner = body.blend(bground, 0.5);
break;
case item_renderer::state_selected:
case state::selected:
border = colors::dark_border;
body = colors::white;
corner = body.blend(bground, 0.5);
@@ -132,9 +122,9 @@ namespace nana
graph_.rectangle(r.pare_off(1), true, body);
}
void item_renderer::caption(int x, int y, const nana::string& text)
void item_renderer::caption(const point& pos, const nana::string& text)
{
graph_.string({ x, y }, text, colors::black);
graph_.string(pos, text, colors::black);
}
//end class item_renderer
@@ -150,22 +140,26 @@ namespace nana
nana::menu* trigger::push_back(const ::nana::string& text)
{
::nana::string::value_type shkey;
::nana::char_t shkey;
API::transform_shortkey_text(text, shkey, nullptr);
if(shkey)
API::register_shortkey(widget_->handle(), shkey);
auto i = items_->cont().size();
auto pos = items_->cont().size();
items_->append(text, shkey);
_m_draw();
API::update_window(*widget_);
return items_->get_menu(i);
return at(pos);
}
nana::menu* trigger::at(std::size_t index) const
nana::menu* trigger::at(std::size_t pos) const
{
return items_->get_menu(index);
if (pos < items_->cont().size())
return &(items_->cont()[pos]->menu_obj);
return nullptr;
}
std::size_t trigger::size() const
@@ -222,22 +216,17 @@ namespace nana
void trigger::mouse_down(graph_reference graph, const arg_mouse& arg)
{
state_.nullify_mouse = false;
state_.active = _m_item_by_pos(arg.pos);
if(state_.menu_active == false)
if (npos != state_.active)
{
if(state_.active != npos)
{
if (!state_.menu_active)
state_.menu_active = true;
_m_popup_menu();
}
else
_m_total_close(true);
}
else if(npos == state_.active)
_m_total_close(true);
else
_m_popup_menu();
}
else
_m_total_close();
_m_draw();
API::lazy_refresh();
@@ -255,11 +244,10 @@ namespace nana
else
{
state_.behavior = state_.behavior_none;
_m_total_close(true);
_m_total_close();
_m_draw();
API::lazy_refresh();
}
}
void trigger::focus(graph_reference, const arg_focus& arg)
@@ -284,10 +272,10 @@ namespace nana
switch(arg.key)
{
case keyboard::os_arrow_down:
state_.menu->goto_next(true); break;
case keyboard::backspace:
case keyboard::os_arrow_up:
state_.menu->goto_next(false); break;
state_.menu->goto_next(keyboard::os_arrow_down == arg.key);
break;
case keyboard::os_arrow_right:
if(state_.menu->goto_submen() == false)
_m_move(false);
@@ -305,19 +293,14 @@ namespace nana
}
break;
case keyboard::enter:
state_.delay_restore = true;
state_.menu->pick();
break;
default:
if(2 != state_.menu->send_shortkey(arg.key))
if (2 != state_.menu->send_shortkey(arg.key))
{
if (state_.active != npos)
{
state_.delay_restore = true;
_m_total_close(false);
if (arg.key == 18) //ALT
state_.behavior = state_.behavior_focus;
}
_m_total_close();
if (arg.key == 18) //ALT
state_.behavior = state_.behavior_focus;
}
else
state_.menu->goto_submen();
@@ -328,18 +311,15 @@ namespace nana
switch(arg.key)
{
case keyboard::os_arrow_right:
_m_move(false);
break;
case keyboard::backspace:
case keyboard::os_arrow_left:
_m_move(true);
_m_move(keyboard::os_arrow_right != arg.key);
break;
case keyboard::escape:
if(state_.behavior == state_.behavior_focus)
{
state_.active= npos;
state_.behavior = state_.behavior_none;
API::restore_menubar_taken_window();
}
}
}
@@ -369,12 +349,6 @@ namespace nana
_m_draw();
API::lazy_refresh();
}
if (state_.delay_restore)
{
API::restore_menubar_taken_window();
state_.delay_restore = false;
}
}
void trigger::shortkey(graph_reference graph, const arg_keyboard& arg)
@@ -430,33 +404,44 @@ namespace nana
bool trigger::_m_popup_menu()
{
if(state_.menu_active && (state_.menu != items_->get_menu(state_.active)))
{
std::size_t index = state_.active;
_m_close_menu();
state_.active = index;
auto& items = items_->cont();
state_.menu = items_->get_menu(state_.active);
if(state_.menu)
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]
{
const item_type &m = items_->at(state_.active);
state_.menu->destroy_answer(std::bind(&trigger::_m_unload_menu_window, this));
menu_accessor::popup(*state_.menu, widget_->handle(), m.pos.x, m.pos.y + m.size.height);
return true;
}
state_.menu = nullptr;
if (state_.passive_close)
{
_m_total_close();
_m_draw();
API::update_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(bool try_restore)
void trigger::_m_total_close()
{
_m_close_menu();
state_.menu_active = false;
state_.behavior = state_.behavior_none;
if (try_restore)
API::restore_menubar_taken_window();
auto pos = API::cursor_position();
API::calc_window_point(widget_->handle(), pos);
state_.active = _m_item_by_pos(pos);
@@ -475,18 +460,6 @@ namespace nana
return false;
}
void trigger::_m_unload_menu_window()
{
state_.menu = nullptr;
if(state_.passive_close)
{
_m_total_close(false);
_m_draw();
API::update_window(widget_->handle());
}
}
std::size_t trigger::_m_item_by_pos(const ::nana::point& pos)
{
if((2 <= pos.x) && (2 <= pos.y) && (pos.y < 25))
@@ -534,9 +507,9 @@ namespace nana
for(auto i : items_->cont())
{
//Transform the text if it contains the hotkey character
nana::string::value_type hotkey;
nana::string::size_type hotkey_pos;
nana::string text = API::transform_shortkey_text(i->text, hotkey, &hotkey_pos);
::nana::char_t hotkey;
::nana::string::size_type hotkey_pos;
auto text = API::transform_shortkey_text(i->text, hotkey, &hotkey_pos);
nana::size text_s = graph_->text_extent_size(text);
@@ -545,10 +518,11 @@ namespace nana
i->pos = item_pos;
i->size = item_s;
item_renderer::state_t state = (index != state_.active ? ird.state_normal : (state_.menu_active ? ird.state_selected : ird.state_highlight));
ird.background(item_pos, item_s, state);
using state = item_renderer::state;
state item_state = (index != state_.active ? state::normal : (state_.menu_active ? state::selected : state::highlighted));
ird.background(item_pos, item_s, item_state);
if(state == ird.state_selected)
if (state::selected == item_state)
{
int x = item_pos.x + item_s.width;
int y1 = item_pos.y + 2, y2 = item_pos.y + item_s.height - 1;
@@ -558,7 +532,7 @@ namespace nana
//Draw text, the text is transformed from orignal for hotkey character
int text_top_off = (item_s.height - text_s.height) / 2;
ird.caption(item_pos.x + 8, item_pos.y + text_top_off, text);
ird.caption({ item_pos.x + 8, item_pos.y + text_top_off }, text);
if(hotkey)
{
@@ -584,8 +558,7 @@ namespace nana
menu_active(false),
passive_close(true),
nullify_mouse(false),
menu(nullptr),
delay_restore(false)
menu(nullptr)
{}
//end struct state_type
//end class trigger