fix bug that listbox incorrectly performs scroll_down/up

This commit is contained in:
Jinhao 2018-02-03 06:40:10 +08:00
parent 3f7dd3fe3e
commit f21bbd5deb
2 changed files with 78 additions and 27 deletions

View File

@ -1273,6 +1273,7 @@ namespace nana
} }
//Backward //Backward
n = -n;
dpos = pos; dpos = pos;
if (good(dpos.cat)) if (good(dpos.cat))
{ {
@ -1618,7 +1619,7 @@ namespace nana
} }
/// return absolute positions, no relative to display /// return absolute positions, no relative to display
index_pairs pick_items(bool for_selection) const index_pairs pick_items(bool for_selection, bool find_first = false) const
{ {
index_pairs results; index_pairs results;
index_pair id; index_pair id;
@ -1629,7 +1630,11 @@ namespace nana
for (auto & m : cat.items) for (auto & m : cat.items)
{ {
if (for_selection ? m.flags.selected : m.flags.checked) if (for_selection ? m.flags.selected : m.flags.checked)
{
results.push_back(id); // absolute positions, no relative to display results.push_back(id); // absolute positions, no relative to display
if (find_first)
return results;
}
++id.item; ++id.item;
} }
++id.cat; ++id.cat;
@ -4336,8 +4341,9 @@ namespace nana
void trigger::key_press(graph_reference graph, const arg_keyboard& arg) void trigger::key_press(graph_reference graph, const arg_keyboard& arg)
{ {
auto & list = essence_->lister;
// Exit if list is empty // Exit if list is empty
if (essence_->lister.first().empty()) if (list.first().empty())
return; return;
bool upward = false; bool upward = false;
@ -4347,12 +4353,12 @@ namespace nana
case keyboard::os_arrow_up: case keyboard::os_arrow_up:
upward = true; upward = true;
case keyboard::os_arrow_down: case keyboard::os_arrow_down:
essence_->lister.move_select(upward, !arg.shift, true); list.move_select(upward, !arg.shift, true);
break; break;
case L' ': case L' ':
{ {
index_pairs s; index_pairs s;
bool ck = ! essence_->lister.item_selected_all_checked(s); bool ck = ! list.item_selected_all_checked(s);
for(auto i : s) for(auto i : s)
item_proxy(essence_, i).check(ck); item_proxy(essence_, i).check(ck);
} }
@ -4361,30 +4367,69 @@ namespace nana
upward = true; upward = true;
case keyboard::os_pagedown: case keyboard::os_pagedown:
{ {
//Turns page, then returns if no change occurs auto const item_px = essence_->item_height();
if (!essence_->content_view->turn_page(!upward, false)) auto picked_items = list.pick_items(true, true);
return; index_pair init_idx = (picked_items.empty() ? list.first() : picked_items[0]);
essence_->lister.select_for_all(false); essence_->lister.select_for_all(false);
auto idx = essence_->first_display(); //Get the pixels between the init item and top edge or bottom edge
auto logic_top = static_cast<int>(list.distance(list.first(), init_idx) * item_px);
if (!upward) auto const screen_top = essence_->content_view->origin().y;
idx = essence_->lister.advance(idx, static_cast<int>(essence_->count_of_exposed(false)) - 1); auto const screen_bottom = screen_top + essence_->content_view->view_area().height;
index_pair target_idx;
if (!idx.is_category()) //Check if it scrolls in current screen window
item_proxy::from_display(essence_, idx).select(true); //condition: top of target item is not less than top edge of content view and
else if (!essence_->lister.single_status(true)) //not selected //the bottom of target item is not greater than bottom edge of content view.
essence_->lister.cat_status(idx.cat, true, true); if ((screen_top + item_px <= logic_top) && (logic_top + item_px + item_px <= screen_bottom))
{
int offset = (static_cast<int>(upward ? screen_top : screen_bottom - item_px) - logic_top) / static_cast<int>(item_px);
target_idx = list.advance(init_idx, offset);
}
else
{
//turn page
auto page_item_count = (std::max)(1, static_cast<int>(essence_->count_of_exposed(false)));
break; auto origin = essence_->content_view->origin();
if (upward)
{
target_idx = list.advance(init_idx, -page_item_count);
if (target_idx.empty())
target_idx = list.first();
origin.y = list.distance(list.first(), target_idx) * item_px;
}
else
{
target_idx = list.advance(init_idx, page_item_count);
if (target_idx.empty())
target_idx = list.last();
origin.y = list.distance(list.first(), target_idx) * item_px + item_px;
if (origin.y >= (screen_bottom - screen_top))
origin.y -= (screen_bottom - screen_top);
else
origin.y = 0;
}
essence_->content_view->move_origin(origin - essence_->content_view->origin());
}
if (!target_idx.is_category())
item_proxy::from_display(essence_, target_idx).select(true);
else if (!list.single_status(true)) //not selected
list.cat_status(target_idx.cat, true, true);
} }
break;
case keyboard::os_home: case keyboard::os_home:
case keyboard::os_end: case keyboard::os_end:
{ {
essence_->lister.select_for_all(false); list.select_for_all(false);
auto pos = (keyboard::os_home == arg.key ? essence_->lister.first() : essence_->lister.last()); auto pos = (keyboard::os_home == arg.key ? list.first() : list.last());
if (!pos.empty()) if (!pos.empty())
{ {
//When the pos indicates an empty category, then search forwards/backwards(depending on arg.key whether it is Home or End) for a non empty category. //When the pos indicates an empty category, then search forwards/backwards(depending on arg.key whether it is Home or End) for a non empty category.
@ -4393,9 +4438,9 @@ namespace nana
{ {
if (keyboard::os_home == arg.key) if (keyboard::os_home == arg.key)
{ {
while (0 == essence_->lister.size_item(pos.cat)) while (0 == list.size_item(pos.cat))
{ {
if (++pos.cat >= essence_->lister.cat_container().size()) if (++pos.cat >= list.cat_container().size())
{ {
pos = index_pair{ npos, npos }; pos = index_pair{ npos, npos };
break; break;
@ -4404,7 +4449,7 @@ namespace nana
} }
else else
{ {
while (0 == essence_->lister.size_item(pos.cat)) while (0 == list.size_item(pos.cat))
{ {
if (pos.cat-- == 0) if (pos.cat-- == 0)
{ {
@ -4416,7 +4461,7 @@ namespace nana
if (!pos.empty()) if (!pos.empty())
{ {
if (essence_->lister.expand(pos.cat)) if (list.expand(pos.cat))
pos.item = 0; pos.item = 0;
} }
} }
@ -4425,8 +4470,8 @@ namespace nana
{ {
if (pos.is_category()) if (pos.is_category())
{ {
if (!essence_->lister.single_status(true)) //multiple selection is not enabled if (!list.single_status(true)) //multiple selection is not enabled
essence_->lister.cat_status(pos.cat, true, true); list.cat_status(pos.cat, true, true);
} }
else else
item_proxy::from_display(essence_, pos).select(true); item_proxy::from_display(essence_, pos).select(true);

View File

@ -1,7 +1,7 @@
/* /*
* A Scroll Implementation * A Scroll Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -20,9 +20,15 @@ namespace nana
namespace scroll namespace scroll
{ {
//struct metrics_type //struct metrics_type
metrics_type::metrics_type() metrics_type::metrics_type():
:peak(1), range(1), step(1), value(0), peak(1),
what(buttons::none), pressed(false), scroll_length(0), scroll_pos(0) range(1),
step(1),
value(0),
what(buttons::none),
pressed(false),
scroll_length(0),
scroll_pos(0)
{} {}
//end struct metrics_type //end struct metrics_type