Merge branch 'hotfixes-1.0.1' into develop
Conflicts: .gitignore include/nana/deploy.hpp source/deploy.cpp source/gui/widgets/listbox.cpp
This commit is contained in:
@@ -129,22 +129,26 @@ namespace checkbox
|
||||
checkbox::checkbox(window wd, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
checkbox::checkbox(window wd, const nana::string& text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
checkbox::checkbox(window wd, const nana::char_t* text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
checkbox::checkbox(window wd, const nana::rectangle& r, bool visible)
|
||||
{
|
||||
bgcolor(API::bgcolor(wd));
|
||||
create(wd, r, visible);
|
||||
}
|
||||
|
||||
|
||||
@@ -677,6 +677,7 @@ namespace nana
|
||||
if(!drawer_->widget_ptr()->enabled())
|
||||
return;
|
||||
|
||||
bool call_other_keys = false;
|
||||
if(drawer_->editable())
|
||||
{
|
||||
bool is_move_up = false;
|
||||
@@ -684,7 +685,7 @@ namespace nana
|
||||
{
|
||||
case keyboard::os_arrow_left:
|
||||
case keyboard::os_arrow_right:
|
||||
drawer_->editor()->move(arg.key);
|
||||
drawer_->editor()->respond_key(arg.key);
|
||||
drawer_->editor()->reset_caret();
|
||||
break;
|
||||
case keyboard::os_arrow_up:
|
||||
@@ -692,6 +693,8 @@ namespace nana
|
||||
case keyboard::os_arrow_down:
|
||||
drawer_->move_items(is_move_up, true);
|
||||
break;
|
||||
default:
|
||||
call_other_keys = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -706,14 +709,19 @@ namespace nana
|
||||
case keyboard::os_arrow_down:
|
||||
drawer_->move_items(is_move_up, true);
|
||||
break;
|
||||
default:
|
||||
call_other_keys = true;
|
||||
}
|
||||
}
|
||||
if (call_other_keys)
|
||||
drawer_->editor()->respond_key(arg.key);
|
||||
|
||||
API::lazy_refresh();
|
||||
}
|
||||
|
||||
void trigger::key_char(graph_reference graph, const arg_keyboard& arg)
|
||||
{
|
||||
if (drawer_->editor()->respone_keyboard(arg.key))
|
||||
if (drawer_->editor()->respond_char(arg.key))
|
||||
API::lazy_refresh();
|
||||
}
|
||||
//end class trigger
|
||||
|
||||
@@ -37,21 +37,25 @@ namespace nana
|
||||
::nana::color clr{ 0xaf, 0xc7, 0xe3 };
|
||||
graph.rectangle(r, false, clr);
|
||||
|
||||
auto right = r.right() - 1;
|
||||
auto bottom = r.bottom() - 1;
|
||||
graph.set_color(colors::white);
|
||||
graph.set_pixel(r.x, r.y);
|
||||
graph.set_pixel(r.x + r.width - 1, r.y);
|
||||
graph.set_pixel(r.x, r.y + r.height - 1);
|
||||
graph.set_pixel(r.x + r.width - 1, r.y + r.height - 1);
|
||||
graph.set_pixel(right, r.y);
|
||||
graph.set_pixel(r.x, bottom);
|
||||
graph.set_pixel(right, bottom);
|
||||
|
||||
--right;
|
||||
--bottom;
|
||||
graph.set_color(clr);
|
||||
graph.set_pixel(r.x + 1, r.y + 1);
|
||||
graph.set_pixel(r.x + r.width - 2, r.y + 1);
|
||||
graph.set_pixel(r.x + 1, r.y + r.height - 2);
|
||||
graph.set_pixel(r.x + r.width - 2, r.y + r.height - 2);
|
||||
graph.set_pixel(right, r.y + 1);
|
||||
graph.set_pixel(r.x + 1, bottom);
|
||||
graph.set_pixel(right, bottom);
|
||||
|
||||
nana::rectangle po_r(r);
|
||||
graph.rectangle(po_r.pare_off(1), false, { 0xEB, 0xF4, 0xFB });
|
||||
graph.gradual_rectangle(po_r.pare_off(1), { 0xDD, 0xEC, 0xFD }, { 0xC2, 0xDC, 0xFD }, true);
|
||||
graph.rectangle(po_r.pare_off(1), false, static_cast<color_rgb>(0xEBF4FB));
|
||||
graph.gradual_rectangle(po_r.pare_off(1), static_cast<color_rgb>(0xDDECFD), static_cast<color_rgb>(0xC2DCFD), true);
|
||||
}
|
||||
else
|
||||
graph.rectangle(r, true, colors::white);
|
||||
@@ -113,13 +117,8 @@ namespace nana
|
||||
class drawer_impl
|
||||
{
|
||||
public:
|
||||
typedef widget& widget_reference;
|
||||
typedef nana::paint::graphics& graph_reference;
|
||||
|
||||
drawer_impl()
|
||||
: widget_(nullptr), graph_(nullptr), image_pixels_(16),
|
||||
ignore_first_mouseup_(true), module_(nullptr)
|
||||
{}
|
||||
using widget_reference = widget&;
|
||||
using graph_reference = paint::graphics&;
|
||||
|
||||
void clear_state()
|
||||
{
|
||||
@@ -151,25 +150,19 @@ namespace nana
|
||||
{
|
||||
if(scrollbar_.empty()) return;
|
||||
|
||||
bool update = false;
|
||||
const auto before_change = state_.offset_y;
|
||||
if(upwards)
|
||||
{
|
||||
if(state_.offset_y)
|
||||
{
|
||||
if (before_change)
|
||||
--(state_.offset_y);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((state_.offset_y + module_->max_items) < module_->items.size())
|
||||
{
|
||||
if ((before_change + module_->max_items) < module_->items.size())
|
||||
++(state_.offset_y);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(update)
|
||||
if(before_change != state_.offset_y)
|
||||
{
|
||||
draw();
|
||||
scrollbar_.value(state_.offset_y);
|
||||
@@ -323,8 +316,7 @@ namespace nana
|
||||
state_.renderer->image(_m_image_enabled(), image_pixels_);
|
||||
for(std::size_t i = state_.offset_y; i < items; ++i)
|
||||
{
|
||||
item_renderer::state_t state = item_renderer::StateNone;
|
||||
if(i == state_.index) state = item_renderer::StateHighlighted;
|
||||
auto state = (i != state_.index ? item_renderer::StateNone : item_renderer::StateHighlighted);
|
||||
|
||||
state_.renderer->render(*widget_, *graph_, item_r, module_->items[i].get(), state);
|
||||
item_r.y += item_pixels;
|
||||
@@ -384,20 +376,20 @@ namespace nana
|
||||
scrollbar_.close();
|
||||
}
|
||||
private:
|
||||
widget * widget_;
|
||||
nana::paint::graphics * graph_;
|
||||
unsigned image_pixels_; //Define the width pixels of the image area
|
||||
widget * widget_{nullptr};
|
||||
nana::paint::graphics * graph_{nullptr};
|
||||
unsigned image_pixels_{16}; //Define the width pixels of the image area
|
||||
|
||||
bool ignore_first_mouseup_;
|
||||
bool ignore_first_mouseup_{true};
|
||||
struct state_type
|
||||
{
|
||||
std::size_t offset_y;
|
||||
std::size_t index; //The index of the selected item.
|
||||
std::size_t offset_y{0};
|
||||
std::size_t index{npos}; //The index of the selected item.
|
||||
|
||||
item_renderer * const orig_renderer;
|
||||
item_renderer * renderer;
|
||||
|
||||
state_type(): offset_y(0), index(npos), orig_renderer(new def_item_renderer), renderer(orig_renderer){}
|
||||
state_type(): orig_renderer(new def_item_renderer), renderer(orig_renderer){}
|
||||
~state_type()
|
||||
{
|
||||
delete orig_renderer;
|
||||
@@ -405,7 +397,7 @@ namespace nana
|
||||
}state_;
|
||||
nana::scroll<true> scrollbar_;
|
||||
|
||||
const module_def* module_;
|
||||
const module_def* module_{nullptr};
|
||||
};
|
||||
|
||||
//class drawer_impl;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: source/gui/widgets/label.cpp
|
||||
* @author: Jinhao
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/label.hpp>
|
||||
@@ -586,8 +588,6 @@ namespace nana
|
||||
|
||||
std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos)
|
||||
{
|
||||
std::pair<std::size_t, std::size_t> r;
|
||||
|
||||
std::size_t n = i->data_ptr->text().length();
|
||||
while(pos >= n)
|
||||
{
|
||||
@@ -765,23 +765,27 @@ namespace nana
|
||||
label::label(window wd, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
label::label(window wd, const nana::string& text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
label::label(window wd, const nana::char_t* text, bool visible)
|
||||
{
|
||||
create(wd, rectangle(), visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
caption(text);
|
||||
}
|
||||
|
||||
label::label(window wd, const rectangle& r, bool visible)
|
||||
{
|
||||
create(wd, r, visible);
|
||||
bgcolor(API::bgcolor(wd));
|
||||
}
|
||||
|
||||
label& label::transparent(bool enabled)
|
||||
@@ -847,24 +851,16 @@ namespace nana
|
||||
|
||||
label& label::text_align(align th, align_v tv)
|
||||
{
|
||||
internal_scope_guard isg;
|
||||
internal_scope_guard lock;
|
||||
auto impl = get_drawer_trigger().impl();
|
||||
|
||||
bool to_update = false;
|
||||
if(impl->text_align != th)
|
||||
if (th != impl->text_align || tv != impl->text_align_v)
|
||||
{
|
||||
impl->text_align = th;
|
||||
to_update = true;
|
||||
}
|
||||
|
||||
if(impl->text_align_v != tv)
|
||||
{
|
||||
impl->text_align_v = tv;
|
||||
to_update = true;
|
||||
API::refresh_window(*this);
|
||||
}
|
||||
|
||||
if(to_update)
|
||||
API::refresh_window(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Menu implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -106,7 +106,7 @@ namespace nana
|
||||
sz.width -= 30;
|
||||
sz.height -= 2;
|
||||
graph.rectangle(false, colors::gray_border);
|
||||
graph.rectangle({ 1, 1, 28, sz.height }, true, { 0xf6, 0xf6, 0xf6 });
|
||||
graph.rectangle({ 1, 1, 28, sz.height }, true, static_cast<color_rgb>(0xf6f6f6));
|
||||
graph.rectangle({ 29, 1, sz.width, sz.height }, true, colors::white);
|
||||
}
|
||||
|
||||
@@ -122,17 +122,17 @@ namespace nana
|
||||
nana::point(r.x + r.width - 1, r.y + r.height - 1)
|
||||
};
|
||||
|
||||
graph.set_color({0xc0, 0xdd, 0xfc});
|
||||
graph.set_color(static_cast<color_rgb>(0xc0ddfc));
|
||||
for(int i = 0; i < 4; ++i)
|
||||
graph.set_pixel(points[i].x, points[i].y);
|
||||
|
||||
if(at.enabled)
|
||||
graph.gradual_rectangle(nana::rectangle(r).pare_off(1), { 0xE8, 0xF0, 0xF4 }, { 0xDB,0xEC,0xF4 }, true);
|
||||
graph.gradual_rectangle(nana::rectangle(r).pare_off(1), static_cast<color_rgb>(0xE8F0F4), static_cast<color_rgb>(0xDBECF4), true);
|
||||
}
|
||||
|
||||
if(at.checked && (checks::none != at.check_style))
|
||||
{
|
||||
graph.rectangle(r, false, { 0xCD, 0xD3, 0xE6 });
|
||||
graph.rectangle(r, false, static_cast<color_rgb>(0xCDD3E6));
|
||||
|
||||
::nana::color clr(0xE6, 0xEF, 0xF4);
|
||||
graph.rectangle(nana::rectangle(r).pare_off(1), true, clr);
|
||||
@@ -151,7 +151,7 @@ namespace nana
|
||||
|
||||
void item_text(graph_reference graph, const nana::point& pos, const nana::string& text, unsigned text_pixels, const attr& at)
|
||||
{
|
||||
graph.set_color(at.enabled ? colors::black : colors::gray_border);
|
||||
graph.set_text_color(at.enabled ? colors::black : colors::gray_border);
|
||||
nana::paint::text_renderer tr(graph);
|
||||
tr.render(pos, text.c_str(), text.length(), text_pixels, true);
|
||||
}
|
||||
@@ -363,59 +363,58 @@ namespace nana
|
||||
bool goto_next(bool forword)
|
||||
{
|
||||
state_.nullify_mouse = true;
|
||||
if(menu_->items.size())
|
||||
{
|
||||
std::size_t index = state_.active;
|
||||
if (menu_->items.empty())
|
||||
return false;
|
||||
|
||||
bool end = false;
|
||||
while(true)
|
||||
auto pos = state_.active;
|
||||
const auto lastpos = menu_->items.size() - 1;
|
||||
|
||||
bool end = false;
|
||||
while(true)
|
||||
{
|
||||
if(forword)
|
||||
{
|
||||
if(forword)
|
||||
if(pos == lastpos)
|
||||
{
|
||||
if(index == menu_->items.size() - 1)
|
||||
if (end)
|
||||
{
|
||||
if(end == false)
|
||||
{
|
||||
end = true;
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = npos;
|
||||
break;
|
||||
}
|
||||
pos = npos;
|
||||
break;
|
||||
}
|
||||
else
|
||||
++index;
|
||||
|
||||
end = true;
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(index == 0 || index == npos)
|
||||
{
|
||||
if(end == false)
|
||||
{
|
||||
end = true;
|
||||
index = menu_->items.size() - 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
--index;
|
||||
}
|
||||
if(menu_->items.at(index).flags.splitter == false)
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
|
||||
if(index != npos && index != state_.active)
|
||||
else
|
||||
{
|
||||
state_.active = index;
|
||||
state_.sub_window = false;
|
||||
|
||||
draw();
|
||||
return true;
|
||||
if(pos == 0 || pos == npos)
|
||||
{
|
||||
if (end)
|
||||
break;
|
||||
|
||||
end = true;
|
||||
pos = lastpos;
|
||||
}
|
||||
else
|
||||
--pos;
|
||||
}
|
||||
|
||||
if(! menu_->items.at(pos).flags.splitter)
|
||||
break;
|
||||
}
|
||||
|
||||
if(pos != npos && pos != state_.active)
|
||||
{
|
||||
state_.active = pos;
|
||||
state_.sub_window = false;
|
||||
|
||||
draw();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -486,30 +485,32 @@ namespace nana
|
||||
std::size_t index = 0;
|
||||
for(auto & m : menu_->items)
|
||||
{
|
||||
if(std::tolower(m.hotkey) == key)
|
||||
if (std::tolower(m.hotkey) != key)
|
||||
{
|
||||
if(!m.flags.splitter)
|
||||
{
|
||||
if(m.sub_menu)
|
||||
{
|
||||
state_.active = index;
|
||||
state_.active_timestamp = nana::system::timestamp();
|
||||
|
||||
draw();
|
||||
API::update_window(*widget_);
|
||||
return 2;
|
||||
}
|
||||
else if(m.flags.enabled)
|
||||
{
|
||||
std::move(fn_close_tree_)();
|
||||
item_proxy ip(index, m);
|
||||
m.functor.operator()(ip);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
++index;
|
||||
continue;
|
||||
}
|
||||
++index;
|
||||
|
||||
if(!m.flags.splitter)
|
||||
{
|
||||
if(m.sub_menu)
|
||||
{
|
||||
state_.active = index;
|
||||
state_.active_timestamp = nana::system::timestamp();
|
||||
|
||||
draw();
|
||||
API::update_window(*widget_);
|
||||
return 2;
|
||||
}
|
||||
else if(m.flags.enabled)
|
||||
{
|
||||
std::move(fn_close_tree_)();
|
||||
item_proxy ip(index, m);
|
||||
m.functor.operator()(ip);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -529,53 +530,53 @@ namespace nana
|
||||
|
||||
int text_top_off = (item_h_px - graph_->text_extent_size(STR("jh({[")).height) / 2;
|
||||
|
||||
std::size_t index = 0;
|
||||
std::size_t pos = 0;
|
||||
for(auto & m : menu_->items)
|
||||
{
|
||||
if(false == m.flags.splitter)
|
||||
{
|
||||
renderer_interface::attr attr = _m_make_renderer_attr(index == 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 + (item_h_px - m.image.size().height) / 2), 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;
|
||||
}
|
||||
else
|
||||
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 + (item_h_px - m.image.size().height) / 2), 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 });
|
||||
}
|
||||
}
|
||||
|
||||
++index;
|
||||
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:
|
||||
@@ -592,9 +593,9 @@ namespace nana
|
||||
std::size_t _m_get_index_by_pos(int x, int y) const
|
||||
{
|
||||
if( (x < static_cast<int>(detail_.border.x)) ||
|
||||
(x > static_cast<int>(graph_->width() - detail_.border.x)) ||
|
||||
(x > static_cast<int>(graph_->width()) - static_cast<int>(detail_.border.x)) ||
|
||||
(y < static_cast<int>(detail_.border.y)) ||
|
||||
(y > static_cast<int>(graph_->height() - detail_.border.y)))
|
||||
(y > static_cast<int>(graph_->height()) - static_cast<int>(detail_.border.y)))
|
||||
return npos;
|
||||
|
||||
int pos = detail_.border.y;
|
||||
@@ -659,14 +660,14 @@ namespace nana
|
||||
API::calc_screen_point(*widget_, pos);
|
||||
|
||||
//get the screen coordinates of the widget pos.
|
||||
auto scr_area = screen::from_point(detail_.monitor_pos)->area();
|
||||
auto scr_area = screen().from_point(detail_.monitor_pos).workarea();
|
||||
|
||||
if(pos.x + size.width > scr_area.x + scr_area.width)
|
||||
pos.x = static_cast<int>(scr_area.x + scr_area.width - size.width);
|
||||
if(pos.x + static_cast<int>(size.width) > scr_area.right())
|
||||
pos.x = scr_area.right() - static_cast<int>(size.width);
|
||||
if(pos.x < scr_area.x) pos.x = scr_area.x;
|
||||
|
||||
if(pos.y + size.height > scr_area.y + scr_area.height)
|
||||
pos.y = static_cast<int>(scr_area.y + scr_area.height - size.height);
|
||||
if(pos.y + static_cast<int>(size.height) > scr_area.bottom())
|
||||
pos.y = scr_area.bottom() - static_cast<int>(size.height);
|
||||
if(pos.y < scr_area.y) pos.y = scr_area.y;
|
||||
|
||||
auto owner = API::get_owner_window(*widget_);
|
||||
@@ -705,7 +706,7 @@ namespace nana
|
||||
|
||||
menu_window(window wd, const point& pos, renderer_interface * rdptr)
|
||||
: base_type(wd, false, rectangle(pos, nana::size(2, 2)), appear::bald<appear::floating>()),
|
||||
want_focus_(nullptr == wd),
|
||||
want_focus_(nullptr == wd || (API::focus_window() != wd)),
|
||||
event_focus_(nullptr)
|
||||
{
|
||||
caption(STR("nana menu window"));
|
||||
@@ -729,11 +730,6 @@ namespace nana
|
||||
API::activate_window(this->parent());
|
||||
API::take_active(this->handle(), false, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
activate();
|
||||
focus();
|
||||
}
|
||||
|
||||
if(submenu_.parent == nullptr)
|
||||
{
|
||||
@@ -753,14 +749,6 @@ namespace nana
|
||||
pick();
|
||||
});
|
||||
|
||||
if (want_focus_)
|
||||
{
|
||||
event_focus_ = events().focus.connect_unignorable([this](const arg_focus& arg)
|
||||
{
|
||||
_m_focus_changed(arg);
|
||||
});
|
||||
}
|
||||
|
||||
timer_.interval(100);
|
||||
timer_.elapse([this]{
|
||||
this->_m_check_repeatly();
|
||||
@@ -768,6 +756,30 @@ namespace nana
|
||||
timer_.start();
|
||||
|
||||
show();
|
||||
|
||||
if (want_focus_)
|
||||
{
|
||||
event_focus_ = events().focus.connect_unignorable([this](const arg_focus& arg)
|
||||
{
|
||||
//when the focus of the menu window is losing, close the menu.
|
||||
//But here is not every menu window may have focus event installed,
|
||||
//It is only installed when the owner of window is the desktop window.
|
||||
|
||||
if (false == arg.getting && (arg.receiver != API::root(*this)))
|
||||
{
|
||||
for (auto child = submenu_.child; child; child = child->submenu_.child)
|
||||
{
|
||||
if (API::root(child->handle()) == arg.receiver)
|
||||
return;
|
||||
}
|
||||
|
||||
_m_close_all();
|
||||
}
|
||||
});
|
||||
|
||||
focus();
|
||||
activate();
|
||||
}
|
||||
}
|
||||
|
||||
void goto_next(bool forward)
|
||||
@@ -783,39 +795,33 @@ namespace nana
|
||||
API::update_window(object->handle());
|
||||
}
|
||||
|
||||
bool goto_submenu()
|
||||
bool submenu(bool enter)
|
||||
{
|
||||
menu_window * object = this;
|
||||
while(object->submenu_.child)
|
||||
while (object->submenu_.child)
|
||||
object = object->submenu_.child;
|
||||
|
||||
state_.auto_popup_submenu = false;
|
||||
|
||||
if (enter)
|
||||
{
|
||||
if (object->submenu_.parent)
|
||||
{
|
||||
auto & sub = object->submenu_.parent->submenu_;
|
||||
sub.child = nullptr;
|
||||
sub.object = nullptr;
|
||||
|
||||
object->close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nana::point pos;
|
||||
menu_type * sbm = object->get_drawer_trigger().retrive_sub_menu(pos, 0);
|
||||
return object->_m_show_submenu(sbm, pos, true);
|
||||
}
|
||||
|
||||
bool exit_submenu()
|
||||
{
|
||||
menu_window * object =this;
|
||||
while(object->submenu_.child)
|
||||
object = object->submenu_.child;
|
||||
|
||||
state_.auto_popup_submenu = false;
|
||||
|
||||
if (object->submenu_.parent)
|
||||
{
|
||||
auto & sub = object->submenu_.parent->submenu_;
|
||||
sub.child = nullptr;
|
||||
sub.object = nullptr;
|
||||
|
||||
object->close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int send_shortkey(nana::char_t key)
|
||||
{
|
||||
menu_window * object = this;
|
||||
@@ -832,62 +838,52 @@ namespace nana
|
||||
object = object->submenu_.child;
|
||||
|
||||
auto active = object->get_drawer_trigger().active();
|
||||
if (active != npos)
|
||||
auto * menu = object->get_drawer_trigger().data();
|
||||
if ((npos == active) || !menu)
|
||||
return;
|
||||
|
||||
menu_item_type & item = menu->items.at(active);
|
||||
if (item.flags.splitter == false && item.sub_menu == nullptr)
|
||||
{
|
||||
auto * menu = object->get_drawer_trigger().data();
|
||||
if (menu)
|
||||
//There is a situation that menu will not call functor if the item style is check_option
|
||||
//and it is checked before clicking.
|
||||
bool call_functor = true;
|
||||
|
||||
if (checks::highlight == item.style)
|
||||
{
|
||||
menu_item_type & item = menu->items.at(active);
|
||||
if (item.flags.splitter == false && item.sub_menu == nullptr)
|
||||
item.flags.checked = !item.flags.checked;
|
||||
}
|
||||
else if (checks::option == item.style)
|
||||
{
|
||||
//Forward Looks for a splitter
|
||||
auto pos = active;
|
||||
while (pos)
|
||||
{
|
||||
//There is a situation that menu will not call functor if the item style is check_option
|
||||
//and it is checked before clicking.
|
||||
bool call_functor = true;
|
||||
|
||||
if (checks::highlight == item.style)
|
||||
{
|
||||
item.flags.checked = !item.flags.checked;
|
||||
}
|
||||
else if (checks::option == item.style)
|
||||
{
|
||||
if (active > 0)
|
||||
{
|
||||
//clear the checked state in front of active if it is check_option.
|
||||
auto i = active;
|
||||
do
|
||||
{
|
||||
--i;
|
||||
menu_item_type & im = menu->items.at(i);
|
||||
if (im.flags.splitter) break;
|
||||
|
||||
if (checks::option == im.style && im.flags.checked)
|
||||
im.flags.checked = false;
|
||||
} while (i);
|
||||
}
|
||||
|
||||
for (auto i = active + 1; i < menu->items.size(); ++i)
|
||||
{
|
||||
menu_item_type & im = menu->items.at(i);
|
||||
if (im.flags.splitter) break;
|
||||
|
||||
if ((checks::option == im.style) && im.flags.checked)
|
||||
im.flags.checked = false;
|
||||
}
|
||||
|
||||
item.flags.checked = true;
|
||||
}
|
||||
|
||||
this->_m_close_all(); //means deleting this;
|
||||
//The deleting operation has moved here, because item.functor.operator()(ip)
|
||||
//may create a window, which make a killing focus for menu window, if so the close_all
|
||||
//operation preformences after item.functor.operator()(ip), that would be deleting this object twice!
|
||||
|
||||
if (call_functor && item.flags.enabled && item.functor)
|
||||
{
|
||||
item_type::item_proxy ip(active, item);
|
||||
item.functor.operator()(ip);
|
||||
}
|
||||
if (menu->items.at(--pos).flags.splitter)
|
||||
break;
|
||||
}
|
||||
|
||||
for (; pos < menu->items.size(); ++pos)
|
||||
{
|
||||
menu_item_type & im = menu->items.at(pos);
|
||||
if (im.flags.splitter) break;
|
||||
|
||||
if ((checks::option == im.style) && im.flags.checked)
|
||||
im.flags.checked = false;
|
||||
}
|
||||
|
||||
item.flags.checked = true;
|
||||
}
|
||||
|
||||
this->_m_close_all(); //means deleting this;
|
||||
//The deleting operation has moved here, because item.functor.operator()(ip)
|
||||
//may create a window, which make a killing focus for menu window, if so the close_all
|
||||
//operation preformences after item.functor.operator()(ip), that would be deleting this object twice!
|
||||
|
||||
if (call_functor && item.flags.enabled && item.functor)
|
||||
{
|
||||
item_type::item_proxy ip(active, item);
|
||||
item.functor.operator()(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -943,50 +939,29 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
//when the focus of the menu window is losing, close the menu.
|
||||
//But here is not every menu window may have focus event installed,
|
||||
//It is only installed when the owner of window is the desktop window.
|
||||
void _m_focus_changed(const arg_focus& arg)
|
||||
{
|
||||
if (false == arg.getting)
|
||||
{
|
||||
for (auto child = submenu_.child; child; child = child->submenu_.child)
|
||||
{
|
||||
if (API::root(child->handle()) == arg.receiver)
|
||||
return;
|
||||
}
|
||||
|
||||
_m_close_all();
|
||||
}
|
||||
}
|
||||
|
||||
void _m_key_down(const arg_keyboard& arg)
|
||||
{
|
||||
switch(arg.key)
|
||||
{
|
||||
case keyboard::os_arrow_up:
|
||||
this->goto_next(false);
|
||||
break;
|
||||
case keyboard::os_arrow_down:
|
||||
this->goto_next(true);
|
||||
this->goto_next(keyboard::os_arrow_down == arg.key);
|
||||
break;
|
||||
case keyboard::os_arrow_left:
|
||||
this->exit_submenu();
|
||||
break;
|
||||
case keyboard::os_arrow_right:
|
||||
this->goto_submenu();
|
||||
this->submenu(keyboard::os_arrow_right == arg.key);
|
||||
break;
|
||||
case keyboard::enter:
|
||||
this->pick();
|
||||
break;
|
||||
default:
|
||||
if(2 != send_shortkey(arg.key))
|
||||
if (2 != send_shortkey(arg.key))
|
||||
{
|
||||
if(API::empty_window(*this) == false)
|
||||
if (API::empty_window(*this) == false)
|
||||
close();
|
||||
}
|
||||
else
|
||||
goto_submenu();
|
||||
this->submenu(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1165,7 +1140,7 @@ namespace nana
|
||||
{
|
||||
if(impl_->mbuilder.set_sub_menu(index, menu_obj.impl_->mbuilder.data()))
|
||||
{
|
||||
implement::info& minfo = impl_->sub_container[index];
|
||||
auto& minfo = impl_->sub_container[index];
|
||||
minfo.handle = &menu_obj;
|
||||
minfo.kill = false;
|
||||
return true;
|
||||
@@ -1184,9 +1159,10 @@ namespace nana
|
||||
menu *menu::create_sub_menu(std::size_t index)
|
||||
{
|
||||
menu * sub = new menu;
|
||||
if(link(index, *sub))
|
||||
|
||||
if (this->link(index, *sub))
|
||||
{
|
||||
implement::info& minfo = impl_->sub_container[index];
|
||||
auto& minfo = impl_->sub_container[index];
|
||||
minfo.handle = sub;
|
||||
minfo.kill = true;
|
||||
return sub;
|
||||
@@ -1255,12 +1231,12 @@ namespace nana
|
||||
|
||||
bool menu::goto_submen()
|
||||
{
|
||||
return (impl_->uiobj ? impl_->uiobj->goto_submenu() : false);
|
||||
return (impl_->uiobj ? impl_->uiobj->submenu(true) : false);
|
||||
}
|
||||
|
||||
bool menu::exit_submenu()
|
||||
{
|
||||
return (impl_->uiobj ? impl_->uiobj->exit_submenu() : false);
|
||||
return (impl_->uiobj ? impl_->uiobj->submenu(false) : false);
|
||||
}
|
||||
|
||||
std::size_t menu::size() const
|
||||
@@ -1311,21 +1287,17 @@ namespace nana
|
||||
impl_->mbuilder.renderer(rd);
|
||||
}
|
||||
|
||||
void menu::_m_destroy_menu_window()
|
||||
{
|
||||
impl_->uiobj = nullptr;
|
||||
if(impl_->destroy_answer)
|
||||
impl_->destroy_answer();
|
||||
}
|
||||
|
||||
void menu::_m_popup(window wd, int x, int y, bool called_by_menubar)
|
||||
{
|
||||
if (impl_->mbuilder.data().items.size())
|
||||
{
|
||||
close();
|
||||
|
||||
impl_->uiobj = &(form_loader<drawerbase::menu::menu_window, false>()(wd, point(x, y), &(*impl_->mbuilder.renderer())));
|
||||
impl_->uiobj->events().destroy.connect_unignorable([this]{
|
||||
_m_destroy_menu_window();
|
||||
impl_->uiobj = nullptr;
|
||||
if (impl_->destroy_answer)
|
||||
impl_->destroy_answer();
|
||||
});
|
||||
impl_->uiobj->popup(impl_->mbuilder.data(), called_by_menubar);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Menubar implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2009-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2009-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -30,21 +30,21 @@ namespace nana
|
||||
{
|
||||
struct item_type
|
||||
{
|
||||
item_type(const nana::string& text, unsigned long shortkey)
|
||||
item_type(const ::nana::string& text, unsigned long shortkey)
|
||||
: text(text), shortkey(shortkey)
|
||||
{}
|
||||
|
||||
nana::string text;
|
||||
::nana::string text;
|
||||
unsigned long shortkey;
|
||||
nana::menu menu_obj;
|
||||
nana::point pos;
|
||||
nana::size size;
|
||||
::nana::menu menu_obj;
|
||||
::nana::point pos;
|
||||
::nana::size size;
|
||||
};
|
||||
|
||||
class trigger::itembase
|
||||
{
|
||||
public:
|
||||
typedef std::vector<item_type*> container;
|
||||
using container = std::vector<item_type*>;
|
||||
|
||||
~itembase()
|
||||
{
|
||||
@@ -52,22 +52,12 @@ namespace nana
|
||||
delete i;
|
||||
}
|
||||
|
||||
void append(const nana::string& text, unsigned long shortkey)
|
||||
void append(const ::nana::string& text, unsigned long shortkey)
|
||||
{
|
||||
if(shortkey && shortkey < 0x61) shortkey += (0x61 - 0x41);
|
||||
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);
|
||||
@@ -122,17 +112,19 @@ namespace nana
|
||||
nana::rectangle r(pos, size);
|
||||
graph_.rectangle(r, false, border);
|
||||
|
||||
int right = pos.x + static_cast<int>(size.width) - 1;
|
||||
int bottom = pos.y + static_cast<int>(size.height) - 1;
|
||||
graph_.set_color(corner);
|
||||
graph_.set_pixel(pos.x, pos.y);
|
||||
graph_.set_pixel(pos.x + size.width - 1, pos.y);
|
||||
graph_.set_pixel(pos.x, pos.y + size.height - 1);
|
||||
graph_.set_pixel(pos.x + size.width - 1, pos.y + size.height - 1);
|
||||
graph_.set_pixel(right, pos.y);
|
||||
graph_.set_pixel(pos.x, bottom);
|
||||
graph_.set_pixel(right, bottom);
|
||||
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
|
||||
|
||||
@@ -146,23 +138,28 @@ namespace nana
|
||||
delete items_;
|
||||
}
|
||||
|
||||
nana::menu* trigger::push_back(const nana::string& text)
|
||||
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();
|
||||
return items_->get_menu(i);
|
||||
API::update_window(*widget_);
|
||||
|
||||
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
|
||||
@@ -219,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();
|
||||
}
|
||||
else if(npos == state_.active)
|
||||
_m_total_close();
|
||||
else
|
||||
|
||||
_m_popup_menu();
|
||||
}
|
||||
else
|
||||
_m_total_close();
|
||||
|
||||
_m_draw();
|
||||
API::lazy_refresh();
|
||||
@@ -256,7 +248,6 @@ namespace nana
|
||||
_m_draw();
|
||||
API::lazy_refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void trigger::focus(graph_reference, const arg_focus& arg)
|
||||
@@ -281,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,17 +296,26 @@ namespace nana
|
||||
state_.menu->pick();
|
||||
break;
|
||||
default:
|
||||
if(2 != state_.menu->send_shortkey(arg.key))
|
||||
//Katsuhisa Yuasa: menubar key_press improvements
|
||||
//send_shortkey has 3 states, 0 = UNKNOWN KEY, 1 = ITEM, 2 = GOTO SUBMENU
|
||||
int sk_state = state_.menu->send_shortkey(arg.key);
|
||||
switch(sk_state)
|
||||
{
|
||||
if(state_.active != npos)
|
||||
case 0: //UNKNOWN KEY
|
||||
break;
|
||||
case 1: //ITEM
|
||||
if (state_.active != npos)
|
||||
{
|
||||
_m_total_close();
|
||||
if(arg.key == 18) //ALT
|
||||
if (arg.key == 18) //ALT
|
||||
state_.behavior = state_.behavior_focus;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2: //GOTO SUBMENU
|
||||
state_.menu->goto_submen();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -323,19 +323,34 @@ 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::os_arrow_up:
|
||||
case keyboard::os_arrow_down:
|
||||
case keyboard::enter:
|
||||
state_.menu_active = true;
|
||||
if(_m_popup_menu())
|
||||
state_.menu->goto_next(true);
|
||||
break;
|
||||
case keyboard::escape:
|
||||
if(state_.behavior == state_.behavior_focus)
|
||||
{
|
||||
state_.active= npos;
|
||||
state_.behavior = state_.behavior_none;
|
||||
API::restore_menubar_taken_window();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::size_t index = items_->find(arg.key);
|
||||
if(index != npos)
|
||||
{
|
||||
state_.active = index;
|
||||
state_.menu_active = true;
|
||||
if(_m_popup_menu())
|
||||
state_.menu->goto_next(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,20 +434,37 @@ 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());
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -443,8 +475,6 @@ namespace nana
|
||||
state_.menu_active = false;
|
||||
state_.behavior = state_.behavior_none;
|
||||
|
||||
API::restore_menubar_taken_window();
|
||||
|
||||
auto pos = API::cursor_position();
|
||||
API::calc_window_point(widget_->handle(), pos);
|
||||
state_.active = _m_item_by_pos(pos);
|
||||
@@ -463,17 +493,6 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
|
||||
void trigger::_m_unload_menu_window()
|
||||
{
|
||||
state_.menu = nullptr;
|
||||
if(state_.passive_close)
|
||||
{
|
||||
_m_total_close();
|
||||
_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))
|
||||
@@ -521,9 +540,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);
|
||||
|
||||
@@ -532,10 +551,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;
|
||||
@@ -545,7 +565,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)
|
||||
{
|
||||
@@ -566,7 +586,12 @@ namespace nana
|
||||
|
||||
//struct state_type
|
||||
trigger::state_type::state_type()
|
||||
:active(npos), behavior(behavior_none), menu_active(false), passive_close(true), nullify_mouse(false), menu(nullptr)
|
||||
: active(npos),
|
||||
behavior(behavior_none),
|
||||
menu_active(false),
|
||||
passive_close(true),
|
||||
nullify_mouse(false),
|
||||
menu(nullptr)
|
||||
{}
|
||||
//end struct state_type
|
||||
//end class trigger
|
||||
|
||||
@@ -109,8 +109,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
if (fit_size.width < graphsize.width || fit_size.height < graphsize.height)
|
||||
_m_draw_background();
|
||||
_m_draw_background(fit_size.width, fit_size.height);
|
||||
|
||||
backimg.image.stretch(valid_area, graph, { pos, fit_size });
|
||||
}
|
||||
@@ -141,14 +140,15 @@ namespace nana
|
||||
break;
|
||||
}
|
||||
|
||||
if (valid_area.width < graphsize.width || valid_area.height < graphsize.height)
|
||||
_m_draw_background();
|
||||
_m_draw_background(valid_area.width, valid_area.height);
|
||||
|
||||
backimg.image.paste(valid_area, graph, pos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_m_draw_background(graphsize.width, graphsize.height);
|
||||
|
||||
color invalid_clr_for_call;
|
||||
backimg.bground->draw(graph, invalid_clr_for_call, invalid_clr_for_call, graphsize, element_state::normal);
|
||||
}
|
||||
@@ -156,18 +156,22 @@ namespace nana
|
||||
graph.setsta();
|
||||
}
|
||||
|
||||
void drawer::_m_draw_background()
|
||||
void drawer::_m_draw_background(unsigned w, unsigned h)
|
||||
{
|
||||
auto graph = impl_->graph_ptr;
|
||||
|
||||
if (graph && (bground_mode::basic != API::effects_bground_mode(*impl_->wdg_ptr)))
|
||||
{
|
||||
auto & bground = impl_->gradual_bground;
|
||||
if (bground.gradual_from.invisible() || bground.gradual_to.invisible())
|
||||
graph->rectangle(true, impl_->wdg_ptr->bgcolor());
|
||||
else if (bground.gradual_from == bground.gradual_to)
|
||||
graph->rectangle(true, bground.gradual_from);
|
||||
else
|
||||
graph->gradual_rectangle(graph->size(), bground.gradual_from, bground.gradual_to, !bground.horizontal);
|
||||
if (w < graph->size().width || h < graph->size().width || impl_->backimg.image.alpha())
|
||||
{
|
||||
auto & bground = impl_->gradual_bground;
|
||||
if (bground.gradual_from.invisible() || bground.gradual_to.invisible())
|
||||
graph->rectangle(true, impl_->wdg_ptr->bgcolor());
|
||||
else if (bground.gradual_from == bground.gradual_to)
|
||||
graph->rectangle(true, bground.gradual_from);
|
||||
else
|
||||
graph->gradual_rectangle(graph->size(), bground.gradual_from, bground.gradual_to, !bground.horizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
//end class drawer
|
||||
|
||||
@@ -52,20 +52,11 @@ namespace nana
|
||||
pos = screen_pos.x;
|
||||
}
|
||||
|
||||
if(scale >= fixedsize * 2)
|
||||
{
|
||||
if(pos < static_cast<int>(fixedsize))
|
||||
return buttons::first;
|
||||
if(pos > static_cast<int>(scale - fixedsize))
|
||||
return buttons::second;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pos < static_cast<int>(scale / 2))
|
||||
return buttons::first;
|
||||
if(pos > static_cast<int>(scale / 2))
|
||||
return buttons::second;
|
||||
}
|
||||
const auto bound_pos = static_cast<int>(scale >= fixedsize * 2 ? fixedsize : scale / 2);
|
||||
if (pos < bound_pos)
|
||||
return buttons::first;
|
||||
if (pos > static_cast<int>(scale) - bound_pos)
|
||||
return buttons::second;
|
||||
|
||||
if(metrics_.scroll_length)
|
||||
{
|
||||
@@ -100,7 +91,7 @@ namespace nana
|
||||
metrics_.scroll_pos = pos;
|
||||
auto value_max = metrics_.peak - metrics_.range;
|
||||
metrics_.value = pos * value_max / scroll_area;
|
||||
if(metrics_.value < metrics_.peak - metrics_.range)
|
||||
if(metrics_.value < value_max)
|
||||
{
|
||||
int selfpos = static_cast<int>(metrics_.value * scroll_area / value_max);
|
||||
int nextpos = static_cast<int>((metrics_.value + 1) * scroll_area / value_max);
|
||||
@@ -115,22 +106,22 @@ namespace nana
|
||||
|
||||
void drawer::auto_scroll()
|
||||
{
|
||||
if(_m_check())
|
||||
if (!_m_check())
|
||||
return;
|
||||
|
||||
if(buttons::forward == metrics_.what)
|
||||
{ //backward
|
||||
if(metrics_.value <= metrics_.range)
|
||||
metrics_.value = 0;
|
||||
else
|
||||
metrics_.value -= (metrics_.range-1);
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
if(buttons::forward == metrics_.what)
|
||||
{ //backward
|
||||
if(metrics_.value <= metrics_.range)
|
||||
metrics_.value = 0;
|
||||
else
|
||||
metrics_.value -= metrics_.range;
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
if(metrics_.peak - metrics_.range - metrics_.value <= metrics_.range)
|
||||
metrics_.value = metrics_.peak - metrics_.range;
|
||||
else
|
||||
metrics_.value += metrics_.range;
|
||||
}
|
||||
if(metrics_.peak - metrics_.range - metrics_.value <= metrics_.range)
|
||||
metrics_.value = metrics_.peak - metrics_.range;
|
||||
else
|
||||
metrics_.value += (metrics_.range-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,26 +132,20 @@ namespace nana
|
||||
|
||||
_m_background(graph);
|
||||
|
||||
::nana::rectangle r(graph.size());
|
||||
if(vertical_)
|
||||
{
|
||||
r.y = r.height - fixedsize;
|
||||
r.height = fixedsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.x = r.width - fixedsize;
|
||||
r.width = fixedsize;
|
||||
}
|
||||
rectangle_rotator r(vertical_, graph.size());
|
||||
r.x_ref() = static_cast<int>(r.w() - fixedsize);
|
||||
r.w_ref() = fixedsize;
|
||||
|
||||
int state = ((_m_check() == false || what == buttons::none) ? states::none : states::highlight);
|
||||
int moused_state = (_m_check() ? (metrics_.pressed ? states::selected : states::actived) : states::none);
|
||||
|
||||
auto result = r.result();
|
||||
|
||||
//draw first
|
||||
_m_draw_button(graph, { 0, 0, r.width, r.height }, buttons::first, (buttons::first == what ? moused_state : state));
|
||||
_m_draw_button(graph, { 0, 0, result.width, result.height }, buttons::first, (buttons::first == what ? moused_state : state));
|
||||
|
||||
//draw second
|
||||
_m_draw_button(graph, r, buttons::second, (buttons::second == what ? moused_state : state));
|
||||
_m_draw_button(graph, result, buttons::second, (buttons::second == what ? moused_state : state));
|
||||
|
||||
//draw scroll
|
||||
_m_draw_scroll(graph, (buttons::scroll == what ? moused_state : states::highlight));
|
||||
@@ -171,64 +156,61 @@ namespace nana
|
||||
{
|
||||
graph.rectangle(true, {0xf0, 0xf0, 0xf0});
|
||||
|
||||
if(metrics_.pressed && _m_check())
|
||||
if (!metrics_.pressed || !_m_check())
|
||||
return;
|
||||
|
||||
nana::rectangle_rotator r(vertical_, graph.size());
|
||||
if(metrics_.what == buttons::forward)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
unsigned width = graph.width(), height = graph.height();
|
||||
|
||||
if(metrics_.what == buttons::forward)
|
||||
{
|
||||
*(vertical_ ? &y : &x) = fixedsize;
|
||||
*(vertical_ ? &height: &width) = metrics_.scroll_pos;
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
*(vertical_ ? &y : &x) = static_cast<int>(fixedsize + metrics_.scroll_pos + metrics_.scroll_length);
|
||||
*(vertical_ ? &height: &width) = static_cast<unsigned>((vertical_ ? graph.height() : graph.width()) - (fixedsize * 2 + metrics_.scroll_pos + metrics_.scroll_length));
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
if(width && height)
|
||||
graph.rectangle({ x, y, width, height }, true, {0xDC, 0xDC, 0xDC});
|
||||
r.x_ref() = static_cast<int>(fixedsize);
|
||||
r.w_ref() = metrics_.scroll_pos;
|
||||
}
|
||||
else if(buttons::backward == metrics_.what)
|
||||
{
|
||||
r.x_ref() = static_cast<int>(fixedsize + metrics_.scroll_pos + metrics_.scroll_length);
|
||||
r.w_ref() = static_cast<unsigned>((vertical_ ? graph.height() : graph.width()) - (fixedsize * 2 + metrics_.scroll_pos + metrics_.scroll_length));
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
auto result = r.result();
|
||||
if (!result.empty())
|
||||
graph.rectangle(result, true, static_cast<color_rgb>(0xDCDCDC));
|
||||
}
|
||||
|
||||
void drawer::_m_button_frame(graph_reference graph, rectangle r, int state)
|
||||
{
|
||||
if(state)
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
::nana::color clr{0x97, 0x97, 0x97}; //highlight
|
||||
switch(state)
|
||||
{
|
||||
::nana::color clr{0x97, 0x97, 0x97}; //highlight
|
||||
switch(state)
|
||||
{
|
||||
case states::actived:
|
||||
clr.from_rgb(0x86, 0xD5, 0xFD); break;
|
||||
case states::selected:
|
||||
clr.from_rgb(0x3C, 0x7F, 0xB1); break;
|
||||
}
|
||||
|
||||
graph.rectangle(r, false, clr);
|
||||
|
||||
clr = clr.blend(colors::white, 0.5);
|
||||
graph.set_color(clr);
|
||||
|
||||
r.pare_off(2);
|
||||
|
||||
if(vertical_)
|
||||
{
|
||||
unsigned half = r.width / 2;
|
||||
graph.rectangle({ r.x + static_cast<int>(r.width - half), r.y, half, r.height }, true);
|
||||
r.width -= half;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned half = r.height / 2;
|
||||
graph.rectangle({r.x, r.y + static_cast<int>(r.height - half), r.width, half}, true);
|
||||
r.height -= half;
|
||||
}
|
||||
//graph.shadow_rectangle(x, y, width, height, 0xFFFFFF, color_x, !vertical_);
|
||||
graph.gradual_rectangle(r, colors::white, clr, !vertical_);
|
||||
case states::actived:
|
||||
clr.from_rgb(0x86, 0xD5, 0xFD); break;
|
||||
case states::selected:
|
||||
clr.from_rgb(0x3C, 0x7F, 0xB1); break;
|
||||
}
|
||||
|
||||
graph.rectangle(r, false, clr);
|
||||
|
||||
clr = clr.blend(colors::white, 0.5);
|
||||
graph.set_color(clr);
|
||||
|
||||
r.pare_off(2);
|
||||
if(vertical_)
|
||||
{
|
||||
unsigned half = r.width / 2;
|
||||
graph.rectangle({ r.x + static_cast<int>(r.width - half), r.y, half, r.height }, true);
|
||||
r.width -= half;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned half = r.height / 2;
|
||||
graph.rectangle({r.x, r.y + static_cast<int>(r.height - half), r.width, half}, true);
|
||||
r.height -= half;
|
||||
}
|
||||
graph.gradual_rectangle(r, colors::white, clr, !vertical_);
|
||||
}
|
||||
|
||||
bool drawer::_m_check() const
|
||||
@@ -271,20 +253,11 @@ namespace nana
|
||||
{
|
||||
if(_m_check())
|
||||
{
|
||||
::nana::rectangle r(graph.size());
|
||||
rectangle_rotator r(vertical_, graph.size());
|
||||
r.x_ref() = static_cast<int>(fixedsize + metrics_.scroll_pos);
|
||||
r.w_ref() = static_cast<unsigned>(metrics_.scroll_length);
|
||||
|
||||
if(vertical_)
|
||||
{
|
||||
r.y = fixedsize + metrics_.scroll_pos;
|
||||
r.height = static_cast<unsigned>(metrics_.scroll_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.x = fixedsize + metrics_.scroll_pos;
|
||||
r.width = static_cast<unsigned>(metrics_.scroll_length);
|
||||
}
|
||||
|
||||
_m_button_frame(graph, r, state);
|
||||
_m_button_frame(graph, r.result(), state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
* A text editor implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/skeletons/text_editor.cpp
|
||||
* @description:
|
||||
*/
|
||||
* A text editor implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* @file: nana/gui/widgets/skeletons/text_editor.cpp
|
||||
* @contributors: Ariel Vina-Rodriguez
|
||||
*/
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/widgets/skeletons/textbase_export_interface.hpp>
|
||||
#include <nana/gui/element.hpp>
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <numeric>
|
||||
#include <cwctype>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana{ namespace widgets
|
||||
{
|
||||
@@ -314,7 +315,13 @@ namespace nana{ namespace widgets
|
||||
if (pos.y > static_cast<unsigned>(textbase.lines()))
|
||||
pos.y = static_cast<unsigned>(textbase.lines());
|
||||
|
||||
pos.x = editor_._m_pixels_by_char(textbase.getline(pos.y), pos.x) + editor_.text_area_.area.x;
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (editor_.mask_char_)
|
||||
mask_str.reset(new nana::string(textbase.getline(pos.y).size(), editor_.mask_char_));
|
||||
|
||||
auto & lnstr = editor_.mask_char_ ? *mask_str : textbase.getline(pos.y);
|
||||
|
||||
pos.x = editor_._m_pixels_by_char(lnstr, pos.x) + editor_.text_area_.area.x;
|
||||
|
||||
int pos_y = static_cast<int>((pos.y - editor_.points_.offset.y) * editor_.line_height() + editor_._m_text_top_base());
|
||||
int pos_x = static_cast<int>(pos.x - editor_.points_.offset.x);
|
||||
@@ -327,7 +334,13 @@ namespace nana{ namespace widgets
|
||||
nana::upoint res{ 0, static_cast<unsigned>(_m_textline_from_screen(scrpos.y)) };
|
||||
|
||||
//Convert the screen point to text caret point
|
||||
const string_type& lnstr = editor_.textbase_.getline(res.y);
|
||||
const string_type& real_str = editor_.textbase_.getline(res.y);
|
||||
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (editor_.mask_char_)
|
||||
mask_str.reset(new nana::string(real_str.size(), editor_.mask_char_));
|
||||
|
||||
auto & lnstr = (editor_.mask_char_ ? *mask_str : real_str);
|
||||
if (lnstr.size() > 0)
|
||||
{
|
||||
scrpos.x += (editor_.points_.offset.x - editor_.text_area_.area.x);
|
||||
@@ -676,7 +689,7 @@ namespace nana{ namespace widgets
|
||||
}
|
||||
}
|
||||
else
|
||||
editor_.render(API::is_focus_window(editor_.window_));
|
||||
editor_.render(API::is_focus_ready(editor_.window_));
|
||||
}
|
||||
|
||||
void render(const ::nana::color& fgcolor) override
|
||||
@@ -737,17 +750,24 @@ namespace nana{ namespace widgets
|
||||
nana::point scrpos;
|
||||
if (0 != pos.x)
|
||||
{
|
||||
nana::string str;
|
||||
for (auto & sec : mtr.line_sections)
|
||||
{
|
||||
std::size_t chsize = sec.end - sec.begin;
|
||||
str.clear();
|
||||
if (editor_.mask_char_)
|
||||
str.append(chsize, editor_.mask_char_);
|
||||
else
|
||||
str.append(sec.begin, sec.end);
|
||||
|
||||
if (pos.x < chsize)
|
||||
{
|
||||
scrpos.x = editor_._m_pixels_by_char(nana::string(sec.begin, sec.end), pos.x);
|
||||
scrpos.x = editor_._m_pixels_by_char(str, pos.x);
|
||||
break;
|
||||
}
|
||||
else if (pos.x == chsize)
|
||||
{
|
||||
scrpos.x = editor_._m_text_extent_size(nana::string(sec.begin, sec.end).data(), sec.end - sec.begin).width;
|
||||
scrpos.x = editor_._m_text_extent_size(str.data(), sec.end - sec.begin).width;
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -773,13 +793,19 @@ namespace nana{ namespace widgets
|
||||
return{ 0, static_cast<unsigned>(primary) };
|
||||
|
||||
//First of all, find the text of secondary.
|
||||
auto str = mtr.line_sections[secondary];
|
||||
auto real_str = mtr.line_sections[secondary];
|
||||
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (editor_.mask_char_)
|
||||
mask_str.reset(new nana::string(real_str.end - real_str.begin, editor_.mask_char_));
|
||||
|
||||
const ::nana::char_t * str = (editor_.mask_char_ ? mask_str->data() : real_str.begin);
|
||||
|
||||
std::vector<unicode_bidi::entity> reordered;
|
||||
unicode_bidi bidi;
|
||||
bidi.linestr(str.begin, str.end - str.begin, reordered);
|
||||
bidi.linestr(str, real_str.end - real_str.begin, reordered);
|
||||
|
||||
nana::upoint res(static_cast<unsigned>(str.begin - mtr.line_sections.front().begin), static_cast<unsigned>(primary));
|
||||
nana::upoint res(static_cast<unsigned>(real_str.begin - mtr.line_sections.front().begin), static_cast<unsigned>(primary));
|
||||
scrpos.x -= editor_.text_area_.area.x;
|
||||
if (scrpos.x < 0)
|
||||
scrpos.x = 0;
|
||||
@@ -793,7 +819,7 @@ namespace nana{ namespace widgets
|
||||
std::unique_ptr<unsigned[]> pxbuf(new unsigned[len]);
|
||||
|
||||
res.x += editor_._m_char_by_pixels(ent.begin, len, pxbuf.get(), str_px, scrpos.x, _m_is_right_text(ent));
|
||||
res.x += static_cast<unsigned>(ent.begin - str.begin);
|
||||
res.x += static_cast<unsigned>(ent.begin - str);
|
||||
return res;
|
||||
}
|
||||
scrpos.x -= str_px;
|
||||
@@ -1133,12 +1159,14 @@ namespace nana{ namespace widgets
|
||||
public:
|
||||
void parse(const ::nana::string& text, const keywords* kwptr)
|
||||
{
|
||||
if (text.empty())
|
||||
if ( kwptr->kwbase.empty() || text.empty() )
|
||||
return;
|
||||
|
||||
using index = ::nana::string::size_type;
|
||||
|
||||
std::vector<entity> entities;
|
||||
|
||||
auto test_whole_word = [&text](std::size_t pos, std::size_t len)
|
||||
auto test_whole_word = [&text](index pos, index len)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
@@ -1160,53 +1188,48 @@ namespace nana{ namespace widgets
|
||||
::nana::cistring cistr;
|
||||
for (auto & ds : kwptr->kwbase)
|
||||
{
|
||||
std::size_t pos;
|
||||
const ::nana::char_t* begin;
|
||||
const ::nana::char_t* end;
|
||||
if (ds.case_sensitive)
|
||||
{
|
||||
pos = text.find(ds.text);
|
||||
if (pos == text.npos)
|
||||
continue;
|
||||
index pos{0} ;
|
||||
for (index rest{text.size()}; rest >= ds.text.size() ; ++pos, rest = text.size() - pos)
|
||||
{
|
||||
if (ds.case_sensitive)
|
||||
{
|
||||
pos = text.find(ds.text, pos);
|
||||
if (pos == text.npos)
|
||||
break;
|
||||
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cistr.empty())
|
||||
cistr.append(text.data(), text.size());
|
||||
|
||||
begin = text.data() + pos;
|
||||
end = begin + ds.text.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cistr.empty())
|
||||
cistr.append(text.data(), text.size());
|
||||
pos = cistr.find(ds.text.data(), pos);
|
||||
if (pos == cistr.npos)
|
||||
break;
|
||||
|
||||
pos = cistr.find(ds.text.data());
|
||||
if (pos == cistr.npos)
|
||||
continue;
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ds.whole_word_matched)
|
||||
{
|
||||
if (!test_whole_word(pos, ds.text.size()))
|
||||
continue;
|
||||
}
|
||||
|
||||
begin = text.data() + pos;
|
||||
end = begin + ds.text.size();
|
||||
}
|
||||
|
||||
auto ki = kwptr->schemes.find(ds.scheme);
|
||||
if (ki != kwptr->schemes.end() && ki->second)
|
||||
{
|
||||
schemes_.emplace(ds.scheme, ki->second);
|
||||
entities.emplace_back();
|
||||
auto & last = entities.back();
|
||||
last.begin = begin;
|
||||
last.end = end;
|
||||
last.scheme = ki->second.get();
|
||||
}
|
||||
auto ki = kwptr->schemes.find(ds.scheme);
|
||||
if (ki != kwptr->schemes.end() && ki->second)
|
||||
{
|
||||
schemes_.emplace(ds.scheme, ki->second);
|
||||
entities.emplace_back();
|
||||
auto & last = entities.back();
|
||||
last.begin = text.data() + pos;
|
||||
last.end = last.begin + ds.text.size();
|
||||
last.scheme = ki->second.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!entities.empty())
|
||||
@@ -1221,7 +1244,7 @@ namespace nana{ namespace widgets
|
||||
while(i != entities.end())
|
||||
{
|
||||
if (previous->end > i->begin)
|
||||
i = entities.erase(i);
|
||||
i = entities.erase(i); // erase overlaping. Left only the first.
|
||||
else
|
||||
++i;
|
||||
}
|
||||
@@ -1326,7 +1349,7 @@ namespace nana{ namespace widgets
|
||||
attributes_.acceptive = acceptive;
|
||||
}
|
||||
|
||||
bool text_editor::respone_keyboard(char_type key) //key is a character of ASCII code
|
||||
bool text_editor::respond_char(char_type key) //key is a character of ASCII code
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
@@ -1377,6 +1400,24 @@ namespace nana{ namespace widgets
|
||||
return false;
|
||||
}
|
||||
|
||||
bool text_editor::respond_key(char_type key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case keyboard::os_arrow_left: move_left(); break;
|
||||
case keyboard::os_arrow_right: move_right(); break;
|
||||
case keyboard::os_arrow_up: move_ns(true); break;
|
||||
case keyboard::os_arrow_down: move_ns(false); break;
|
||||
case keyboard::os_del:
|
||||
if (this->attr().editable)
|
||||
del();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void text_editor::typeface_changed()
|
||||
{
|
||||
behavior_->pre_calc_lines(width_pixels());
|
||||
@@ -1407,7 +1448,7 @@ namespace nana{ namespace widgets
|
||||
move_caret(upoint{});
|
||||
|
||||
_m_scrollbar();
|
||||
render(API::is_focus_window(window_));
|
||||
render(API::is_focus_ready(window_));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1425,7 +1466,7 @@ namespace nana{ namespace widgets
|
||||
|
||||
_m_reset();
|
||||
behavior_->pre_calc_lines(width_pixels());
|
||||
render(API::is_focus_window(window_));
|
||||
render(API::is_focus_ready(window_));
|
||||
_m_scrollbar();
|
||||
return true;
|
||||
}
|
||||
@@ -1676,7 +1717,7 @@ namespace nana{ namespace widgets
|
||||
//Set caret position through text coordinate
|
||||
void text_editor::move_caret(const upoint& crtpos)
|
||||
{
|
||||
if (!API::is_focus_window(window_))
|
||||
if (!API::is_focus_ready(window_))
|
||||
return;
|
||||
|
||||
const unsigned line_pixels = line_height();
|
||||
@@ -1718,7 +1759,7 @@ namespace nana{ namespace widgets
|
||||
|
||||
void text_editor::show_caret(bool isshow)
|
||||
{
|
||||
if(isshow == false || API::is_focus_window(window_))
|
||||
if(isshow == false || API::is_focus_ready(window_))
|
||||
API::caret_visible(window_, isshow);
|
||||
}
|
||||
|
||||
@@ -1883,7 +1924,7 @@ namespace nana{ namespace widgets
|
||||
{
|
||||
behavior_->adjust_caret_into_screen();
|
||||
reset_caret();
|
||||
render(API::is_focus_window(window_));
|
||||
render(API::is_focus_ready(window_));
|
||||
_m_scrollbar();
|
||||
|
||||
points_.xpos = points_.caret.x;
|
||||
@@ -2105,25 +2146,6 @@ namespace nana{ namespace widgets
|
||||
|
||||
}
|
||||
|
||||
bool text_editor::move(nana::char_t key)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case keyboard::os_arrow_left: move_left(); break;
|
||||
case keyboard::os_arrow_right: move_right(); break;
|
||||
case keyboard::os_arrow_up: move_ns(true); break;
|
||||
case keyboard::os_arrow_down: move_ns(false); break;
|
||||
case keyboard::os_del:
|
||||
if (this->attr().editable)
|
||||
del();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void text_editor::move_ns(bool to_north)
|
||||
{
|
||||
const bool redraw_required = _m_cancel_select(0);
|
||||
@@ -2528,7 +2550,7 @@ namespace nana{ namespace widgets
|
||||
|
||||
//The number of new lines minus one
|
||||
const auto chp_end = text.data() + (begin == text.npos ? text.size() : begin);
|
||||
for (auto chp = text.data() + (pos + 2); chp != chp_end; ++chp)
|
||||
for (auto chp = text.data() + (pos + 1); chp != chp_end; ++chp)
|
||||
if (*chp == '\n')
|
||||
lines.emplace_back(0, 0);
|
||||
|
||||
@@ -2764,18 +2786,17 @@ namespace nana{ namespace widgets
|
||||
}
|
||||
}
|
||||
|
||||
void text_editor::_m_draw_string(int top, const ::nana::color& clr, const nana::upoint& str_pos, const nana::string& linestr, bool if_mask) const
|
||||
void text_editor::_m_draw_string(int top, const ::nana::color& clr, const nana::upoint& str_pos, const nana::string& str, bool if_mask) const
|
||||
{
|
||||
::nana::point text_pos{ text_area_.area.x - points_.offset.x, top };
|
||||
const int xend = text_area_.area.x + static_cast<int>(text_area_.area.width);
|
||||
|
||||
std::unique_ptr<nana::string> mask_str;
|
||||
if (if_mask && mask_char_)
|
||||
{
|
||||
nana::string maskstr;
|
||||
maskstr.append(linestr.size(), mask_char_);
|
||||
graph_.string(text_pos, maskstr, clr);
|
||||
return;
|
||||
}
|
||||
mask_str.reset(new nana::string(str.size(), mask_char_));
|
||||
|
||||
|
||||
auto & linestr = (if_mask && mask_char_ ? *mask_str : str);
|
||||
|
||||
unicode_bidi bidi;
|
||||
std::vector<unicode_bidi::entity> reordered;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/element.hpp>
|
||||
#include <nana/gui/timer.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@@ -328,7 +329,7 @@ namespace nana
|
||||
|
||||
void render()
|
||||
{
|
||||
editor_->render(API::is_focus_window(editor_->window_handle()));
|
||||
editor_->render(API::is_focus_ready(editor_->window_handle()));
|
||||
_m_draw_spins(spin_stated_);
|
||||
}
|
||||
|
||||
@@ -420,7 +421,7 @@ namespace nana
|
||||
if (!editor_)
|
||||
return;
|
||||
|
||||
if (API::is_focus_window(editor_->window_handle()))
|
||||
if (API::is_focus_ready(editor_->window_handle()))
|
||||
editor_->text(range_->value());
|
||||
else
|
||||
editor_->text(modifier_.prefix + range_->value() + modifier_.suffix);
|
||||
@@ -559,7 +560,7 @@ namespace nana
|
||||
|
||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if (impl_->editor()->move(arg.key))
|
||||
if (impl_->editor()->respond_key(arg.key))
|
||||
{
|
||||
impl_->editor()->reset_caret();
|
||||
impl_->draw_spins();
|
||||
@@ -569,7 +570,7 @@ namespace nana
|
||||
|
||||
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if (impl_->editor()->respone_keyboard(arg.key))
|
||||
if (impl_->editor()->respond_char(arg.key))
|
||||
{
|
||||
if (!impl_->value(impl_->editor()->text()))
|
||||
impl_->draw_spins();
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace drawerbase {
|
||||
|
||||
void drawer::refresh(graph_reference graph)
|
||||
{
|
||||
editor_->render(API::is_focus_window(*widget_));
|
||||
editor_->render(API::is_focus_ready(*widget_));
|
||||
}
|
||||
|
||||
void drawer::focus(graph_reference graph, const arg_focus& arg)
|
||||
@@ -136,7 +136,7 @@ namespace drawerbase {
|
||||
|
||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if(editor_->move(arg.key))
|
||||
if(editor_->respond_key(arg.key))
|
||||
{
|
||||
editor_->reset_caret();
|
||||
API::lazy_refresh();
|
||||
@@ -145,7 +145,7 @@ namespace drawerbase {
|
||||
|
||||
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if (editor_->respone_keyboard(arg.key))
|
||||
if (editor_->respond_char(arg.key))
|
||||
API::lazy_refresh();
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ namespace drawerbase {
|
||||
internal_scope_guard lock;
|
||||
auto editor = get_drawer_trigger().editor();
|
||||
if (editor->line_wrapped(autl))
|
||||
editor->render(API::is_focus_window(handle()));
|
||||
API::update_window(handle());
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -389,7 +389,7 @@ namespace drawerbase {
|
||||
internal_scope_guard lock;
|
||||
auto editor = get_drawer_trigger().editor();
|
||||
if(editor && editor->select(yes))
|
||||
API::refresh_window(*this);
|
||||
API::update_window(*this);
|
||||
}
|
||||
|
||||
void textbox::copy() const
|
||||
@@ -407,7 +407,7 @@ namespace drawerbase {
|
||||
if(editor)
|
||||
{
|
||||
editor->paste();
|
||||
API::refresh_window(*this);
|
||||
API::update_window(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace nana
|
||||
|
||||
bool widget::focused() const
|
||||
{
|
||||
return API::is_focus_window(handle());
|
||||
return (API::focus_window() == handle());
|
||||
}
|
||||
|
||||
void widget::show()
|
||||
|
||||
Reference in New Issue
Block a user