Merge branch 'hotfix-1.5.5' into develop

This commit is contained in:
Jinhao 2017-09-25 21:53:04 +08:00
commit a3ff2af4ab
12 changed files with 168 additions and 58 deletions

View File

@ -50,6 +50,7 @@
<Unit filename="../../source/datetime.cpp" />
<Unit filename="../../source/deploy.cpp" />
<Unit filename="../../source/detail/platform_abstraction.cpp" />
<Unit filename="../../source/detail/platform_spec_posix.cpp" />
<Unit filename="../../source/detail/platform_spec_windows.cpp" />
<Unit filename="../../source/filesystem/filesystem.cpp" />
<Unit filename="../../source/gui/animation.cpp" />

View File

@ -91,6 +91,8 @@ namespace nana
substitute = 0x1A, //Ctrl+Z
escape = 0x1B,
space = 0x20, //Space
del = 0x7F, //Delete
os_del = del, //Deprecated
//The following names are intuitive name of ASCII control codes
select_all = start_of_headline,
@ -106,8 +108,8 @@ namespace nana
os_ctrl = 0x11,
os_pageup = 0x21, os_pagedown,
os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down,
os_insert = 0x2D, os_del ,
os_end = 0x23 , os_home //Pos 1
os_insert = 0x2D,
os_end = 0x23, os_home //Pos 1
};
};

View File

@ -61,6 +61,7 @@ namespace nana
void focus(graph_reference, const arg_focus&) override;
void mouse_wheel(graph_reference, const arg_wheel&) override;
void dbl_click(graph_reference, const arg_mouse&) override;
void mouse_down(graph_reference, const arg_mouse&) override;
void mouse_move(graph_reference, const arg_mouse&) override;
void mouse_up(graph_reference, const arg_mouse& arg) override;

View File

@ -438,8 +438,8 @@ namespace detail
keysym = keyboard::os_arrow_left + (keysym - XK_Left); break;
case XK_Insert:
keysym = keyboard::os_insert; break;
case XK_Delete:
keysym = keyboard::os_del; break;
case XK_Delete: case XK_KP_Delete:
keysym = keyboard::del; break;
case XK_Shift_L: case XK_Shift_R: //shift
keysym = keyboard::os_shift; break;
case XK_Control_L: case XK_Control_R: //ctrl

View File

@ -775,6 +775,19 @@ namespace detail
if (thrd) thrd->event_window = prev_event_wd;
}
//Translate OS Virtual-Key into ASCII code
wchar_t translate_virtual_key(WPARAM vkey)
{
switch (vkey)
{
case VK_DELETE:
return 127;
case VK_DECIMAL:
return 46;
}
return static_cast<wchar_t>(vkey);
}
LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT window_proc_value = 0;
@ -1436,7 +1449,7 @@ namespace detail
arg.evt_code = event_code::key_press;
arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.ignore = false;
arg.key = static_cast<wchar_t>(wParam);
arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg);
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
@ -1522,7 +1535,7 @@ namespace detail
arg_keyboard arg;
arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.key = static_cast<wchar_t>(wParam);
arg.key = translate_virtual_key(wParam);
brock.get_key_state(arg);
arg.ignore = false;
brock.emit(event_code::key_release, msgwnd, arg, true, &context);

View File

@ -149,33 +149,34 @@ namespace nana
// reads the overlaps that are overlapped a rectangular block
bool window_layout::read_overlaps(core_window_t* wd, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks)
{
auto const is_wd_root = (category::flags::root == wd->other.category);
wd_rectangle block;
while (wd->parent)
{
auto & siblings = wd->parent->children;
//It should be checked that whether the window is still a chlid of its parent.
if (siblings.size())
auto i = std::find(wd->parent->children.cbegin(), wd->parent->children.cend(), wd);
if (i != wd->parent->children.cend())
{
auto i = &(siblings[0]);
auto *end = i + siblings.size();
i = std::find(i, end, wd);
if (i != end)
for (++i; i != wd->parent->children.cend(); ++i)
{
//find the widget that next to wd.
for (++i; i < end; ++i)
core_window_t* cover = *i;
if (!cover->visible)
continue;
if (is_wd_root ?
(category::flags::root == cover->other.category)
:
((category::flags::root != cover->other.category) && (nullptr == cover->effect.bground)))
{
core_window_t* cover = *i;
if ((category::flags::root != cover->other.category) && cover->visible && (nullptr == cover->effect.bground))
if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
{
if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
{
block.window = cover;
blocks.push_back(block);
}
block.window = cover;
blocks.push_back(block);
}
}
}
}
wd = wd->parent;
}
return (!blocks.empty());

View File

@ -435,20 +435,20 @@ namespace nana
nodes_.filesystem = tree_.insert("FS.ROOT", "Filesystem");
nodes_.filesystem.value(kind::filesystem);
std::vector<std::string> paths;
paths.emplace_back(fs_ext::path_user().native());
paths.emplace_back("/");
std::vector<std::pair<std::string, treebox::item_proxy>> paths;
paths.emplace_back(fs_ext::path_user().native(), nodes_.home);
paths.emplace_back("/", nodes_.filesystem);
fs::directory_iterator end;
for (auto & p : paths)
{
for (fs::directory_iterator i(p); i != end; ++i)
for (fs::directory_iterator i{p.first}; i != end; ++i)
{
auto name = i->path().filename().native();
if (!is_directory(i->status()) || (name.size() && name[0] == '.'))
continue;
item_proxy node = tree_.insert(nodes_.filesystem, name, name);
item_proxy node = tree_.insert(p.second, name, name);
if (false == node.empty())
{
node.value(kind::filesystem);
@ -569,28 +569,63 @@ namespace nana
if(cat_path.size() && cat_path[cat_path.size() - 1] != '/')
cat_path += '/';
auto beg = head.size();
while(true)
{
auto pos = path.find('/', beg);
auto folder = path.substr(beg, pos != path.npos ? pos - beg: path.npos);
if(folder.size() == 0) break;
if(folder.empty())
break;
(cat_path += folder) += '/';
(head += folder) += '/';
path_.caption(cat_path);
for(fs::directory_iterator i(head); i != end; ++i)
try
{
if (is_directory(*i))
path_.childset(i->path().filename().native(), 0);
for(fs::directory_iterator i(head); i != end; ++i)
{
if (is_directory(*i))
path_.childset(i->path().filename().native(), 0);
}
}
catch(fs::filesystem_error&)
{
//The directory iterator may throw filesystem_error when
//the user doesn't have permission to access the directory.
//It just loads the sub-directories
//to the category path.
}
if(pos == path.npos)
break;
beg = pos + 1;
}
_m_load_path(path);
_m_list_fs();
try
{
_m_load_path(path);
_m_list_fs();
}
catch(fs::filesystem_error&)
{
file_container_.clear();
drawing dw{ls_file_};
dw.clear();
dw.draw([](paint::graphics& graph){
std::string text = "Permission denied to access the directory";
auto txt_sz = graph.text_extent_size(text);
auto sz = graph.size();
graph.string({static_cast<int>(sz.width - txt_sz.width) / 2, static_cast<int>(sz.height - txt_sz.height) / 2}, text, colors::dark_gray);
});
ls_file_.clear();
}
}
bool _m_filter_allowed(const std::string& name, bool is_dir, const std::string& filter, const std::vector<std::string>* extension) const
@ -611,6 +646,8 @@ namespace nana
void _m_list_fs()
{
drawing{ls_file_}.clear();
auto filter = filter_.caption();
ls_file_.auto_draw(false);
@ -829,14 +866,28 @@ namespace nana
auto child = node.append(name, name, kind::filesystem);
if(!child.empty())
{
for(fs::directory_iterator u(i->path()); u != end; ++u)
//The try-catch can be eleminated by using
//directory_iterator( const std::filesystem::path& p, std::error_code& ec ) noexcept;
//in C++17
try
{
auto uname = i->path().filename().native();
if ((!is_directory(*i)) || (uname.size() && uname[0] == '.'))
continue;
for(fs::directory_iterator u(i->path()); u != end; ++u)
{
auto uname = u->path().filename().native();
if ((!is_directory(*u)) || (uname.size() && uname[0] == '.'))
continue;
child.append(uname, uname, kind::filesystem);
break;
child.append(uname, uname, kind::filesystem);
break;
}
}
catch(fs::filesystem_error&)
{
//The directory iterator may throw filesystem_error when
//the user doesn't have permission to access the directory.
//Catch the error without any process, because the loop is just
//to peak whether the directory(i->path) has a sub-directory.
}
}
}

View File

@ -403,8 +403,15 @@ namespace nana
ess_->state.nullify_mouse = true;
auto & menu_ptr = ess_->state.menu;
//menu_wd will be assigned with the handle of a menu window,
//It is used for checking whether the menu is closed. A menu handler
//may close the form, checking with the data member of this trigger
//is invalid, because the form is closed, the object of menubar may not exist.
window menu_wd = nullptr;
if(ess_->state.menu)
{
menu_wd = menu_ptr->handle();
switch(arg.key)
{
case keyboard::os_arrow_down:
@ -466,8 +473,11 @@ namespace nana
case keyboard::os_arrow_up:
case keyboard::os_arrow_down:
case keyboard::enter:
if(ess_->open_menu(true))
if (ess_->open_menu(true))
{
menu_wd = menu_ptr->handle();
menu_ptr->goto_next(true);
}
break;
case keyboard::escape:
if(essence::behavior::focus == ess_->state.behave)
@ -481,15 +491,21 @@ namespace nana
if(index != npos)
{
ess_->state.active = index;
if(ess_->open_menu(true))
if (ess_->open_menu(true))
{
menu_wd = menu_ptr->handle();
menu_ptr->goto_next(true);
}
}
break;
}
}
refresh(graph);
API::dev::lazy_refresh();
if (API::is_window(menu_wd))
{
refresh(graph);
API::dev::lazy_refresh();
}
}
void trigger::key_release(graph_reference graph, const arg_keyboard& arg)

View File

@ -556,6 +556,7 @@ namespace nana{ namespace widgets
virtual void merge_lines(std::size_t first, std::size_t second) = 0;
//Calculates how many lines the specified line of text takes with a specified pixels of width.
virtual void add_lines(std::size_t pos, std::size_t lines) = 0;
virtual void prepare() = 0;
virtual void pre_calc_line(std::size_t line, unsigned pixels) = 0;
virtual void pre_calc_lines(unsigned pixels) = 0;
virtual std::size_t take_lines() const = 0;
@ -668,6 +669,12 @@ namespace nana{ namespace widgets
}
}
void prepare() override
{
auto const line_count = editor_.textbase().lines();
this->sections_.resize(line_count);
}
void pre_calc_line(std::size_t pos, unsigned) override
{
auto const & text = editor_.textbase().getline(pos);
@ -781,6 +788,12 @@ namespace nana{ namespace widgets
}
}
void prepare() override
{
auto const lines = editor_.textbase().lines();
linemtr_.resize(lines);
}
void pre_calc_line(std::size_t line, unsigned pixels) override
{
const string_type& lnstr = editor_.textbase().getline(line);
@ -1220,7 +1233,7 @@ namespace nana{ namespace widgets
case keyboard::os_pagedown:
_m_handle_move_key(arg);
break;
case keyboard::os_del:
case keyboard::del:
// send delete to set_accept function
if (this->attr().editable && (!impl_->capacities.pred_acceptive || impl_->capacities.pred_acceptive(key)))
del();
@ -1234,7 +1247,7 @@ namespace nana{ namespace widgets
void text_editor::typeface_changed()
{
impl_->capacities.behavior->pre_calc_lines(width_pixels());
_m_reset_content_size(true);
}
void text_editor::indent(bool enb, std::function<std::string()> generator)
@ -1676,7 +1689,7 @@ namespace nana{ namespace widgets
impl_->try_refresh = sync_graph::refresh;
//_m_put calcs the lines
_m_reset_content_size(false);
_m_reset_content_size(true);
impl_->cview->sync(false);
}
}
@ -2886,10 +2899,14 @@ namespace nana{ namespace widgets
auto text_lines = textbase().lines();
if (text_lines <= max_lines)
{
impl_->capacities.behavior->prepare();
auto const width_px = _m_width_px(true);
std::size_t lines = 0;
for (std::size_t i = 0; i < text_lines; ++i)
{
impl_->capacities.behavior->pre_calc_line(i, csize.width);
impl_->capacities.behavior->pre_calc_line(i, width_px);
lines += impl_->capacities.behavior->take_lines(i);
if (lines > max_lines)

View File

@ -560,6 +560,12 @@ namespace nana
impl_->editor()->reset_caret();
API::dev::lazy_refresh();
}
void drawer::dbl_click(graph_reference, const arg_mouse& arg)
{
if (impl_->mouse_button(arg, true))
API::dev::lazy_refresh();
}
void drawer::mouse_down(graph_reference, const arg_mouse& arg)
{
@ -599,7 +605,10 @@ namespace nana
{
impl_->editor()->respond_char(arg);
if (impl_->editor()->try_refresh())
{
impl_->draw_spins();
API::dev::lazy_refresh();
}
}
void drawer::resized(graph_reference, const arg_resized&)

View File

@ -1825,7 +1825,6 @@ namespace nana
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
bool has_redraw = false;
auto & node_state = impl_->node_state;
node_state.pressed_node = nl.node();
@ -1834,21 +1833,17 @@ namespace nana
{
if(impl_->set_expanded(node_state.pressed_node, !node_state.pressed_node->value.second.expanded))
impl_->make_adjust(node_state.pressed_node, 0);
has_redraw = true; //btw, don't select the node
}
if ((!has_redraw) && (node_state.selected != node_state.pressed_node))
else if (node_state.selected != node_state.pressed_node)
{
impl_->set_selected(node_state.pressed_node);
has_redraw = true;
}
else
return;
if(has_redraw)
{
impl_->draw(true);
API::dev::lazy_refresh();
}
impl_->draw(true);
API::dev::lazy_refresh();
}
void trigger::mouse_up(graph_reference, const arg_mouse& arg)

View File

@ -240,12 +240,16 @@ namespace paint
graphics::graphics(graphics&& other)
: impl_(std::move(other.impl_))
{
other.impl_.reset(new implementation);
}
graphics& graphics::operator=(graphics&& other)
{
if (this != &other)
{
impl_ = std::move(other.impl_);
other.impl_.reset(new implementation);
}
return *this;
}