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:
Jinhao
2015-05-03 03:08:26 +08:00
81 changed files with 2639 additions and 1737 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -101,7 +101,7 @@ namespace nana
bool widget::focused() const
{
return API::is_focus_window(handle());
return (API::focus_window() == handle());
}
void widget::show()