fix issue that reverse box selection works incorrectly
new bug from develop-1.7
This commit is contained in:
parent
e057724f98
commit
3e9b08c0cc
@ -2011,6 +2011,8 @@ namespace nana
|
|||||||
{
|
{
|
||||||
bool started{ false };
|
bool started{ false };
|
||||||
bool reverse_selection{ false };
|
bool reverse_selection{ false };
|
||||||
|
bool scroll_direction;
|
||||||
|
bool deselect_when_start_to_move;
|
||||||
|
|
||||||
point screen_pos;
|
point screen_pos;
|
||||||
point begin_position; ///< Logical position to the
|
point begin_position; ///< Logical position to the
|
||||||
@ -2018,9 +2020,18 @@ namespace nana
|
|||||||
index_pairs already_selected;
|
index_pairs already_selected;
|
||||||
index_pairs selections;
|
index_pairs selections;
|
||||||
|
|
||||||
bool scroll_direction;
|
|
||||||
unsigned scroll_step{ 1 };
|
unsigned scroll_step{ 1 };
|
||||||
unsigned mouse_move_timestamp{ 0 };
|
unsigned mouse_move_timestamp{ 0 };
|
||||||
|
|
||||||
|
bool is_already_selected(const index_pair& abs_pos) const noexcept
|
||||||
|
{
|
||||||
|
return (already_selected.cend() != std::find(already_selected.cbegin(), already_selected.cend(), abs_pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_selected(const index_pair& abs_pos) const noexcept
|
||||||
|
{
|
||||||
|
return (selections.cend() != std::find(selections.cbegin(), selections.cend(), abs_pos));
|
||||||
|
}
|
||||||
}mouse_selection;
|
}mouse_selection;
|
||||||
|
|
||||||
|
|
||||||
@ -2118,6 +2129,7 @@ namespace nana
|
|||||||
mouse_selection.started = true;
|
mouse_selection.started = true;
|
||||||
mouse_selection.begin_position = logic_pos;
|
mouse_selection.begin_position = logic_pos;
|
||||||
mouse_selection.end_position = logic_pos;
|
mouse_selection.end_position = logic_pos;
|
||||||
|
mouse_selection.deselect_when_start_to_move = true;
|
||||||
|
|
||||||
if (arg.ctrl || arg.shift)
|
if (arg.ctrl || arg.shift)
|
||||||
{
|
{
|
||||||
@ -2133,6 +2145,17 @@ namespace nana
|
|||||||
if (!mouse_selection.started)
|
if (!mouse_selection.started)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// When the button is pressed and start to move the mouse, the listbox should deselect all items.
|
||||||
|
// But when ctrl is clicked
|
||||||
|
if (mouse_selection.deselect_when_start_to_move)
|
||||||
|
{
|
||||||
|
mouse_selection.deselect_when_start_to_move = false;
|
||||||
|
if (mouse_selection.already_selected.empty())
|
||||||
|
lister.select_for_all(false);
|
||||||
|
|
||||||
|
mouse_selection.selections.clear();
|
||||||
|
}
|
||||||
|
|
||||||
mouse_selection.screen_pos = screen_pos;
|
mouse_selection.screen_pos = screen_pos;
|
||||||
|
|
||||||
auto logic_pos = coordinate_cast(screen_pos, true);
|
auto logic_pos = coordinate_cast(screen_pos, true);
|
||||||
@ -2148,7 +2171,7 @@ namespace nana
|
|||||||
|
|
||||||
mouse_selection.end_position = logic_pos;
|
mouse_selection.end_position = logic_pos;
|
||||||
|
|
||||||
bool cancel_selections = true;
|
std::vector<std::pair<index_pair, bool>> selections;
|
||||||
|
|
||||||
auto content_x = coordinate_cast({ columns_range().first, 0 }, true).x;
|
auto content_x = coordinate_cast({ columns_range().first, 0 }, true).x;
|
||||||
if ((std::max)(mouse_selection.end_position.x, mouse_selection.begin_position.x) >= content_x &&
|
if ((std::max)(mouse_selection.end_position.x, mouse_selection.begin_position.x) >= content_x &&
|
||||||
@ -2159,18 +2182,18 @@ namespace nana
|
|||||||
auto begin = lister.advance(lister.first(), begin_off);
|
auto begin = lister.advance(lister.first(), begin_off);
|
||||||
if (!begin.empty())
|
if (!begin.empty())
|
||||||
{
|
{
|
||||||
std::vector<std::pair<index_pair, bool>> selections;
|
|
||||||
|
|
||||||
if ((mouse_selection.end_position.y < 0) || (lister.distance(lister.first(), begin) == begin_off))
|
if ((mouse_selection.end_position.y < 0) || (lister.distance(lister.first(), begin) == begin_off))
|
||||||
{
|
{
|
||||||
//The range [begin_off, last_off] is a range of box selection
|
//The range [begin_off, last_off] is a range of box selection
|
||||||
auto last_off = (std::max)(mouse_selection.begin_position.y, mouse_selection.end_position.y) / item_height();
|
auto last_off = (std::max)(mouse_selection.begin_position.y, mouse_selection.end_position.y) / item_height();
|
||||||
auto last = lister.advance(lister.first(), last_off);
|
auto last = lister.advance(lister.first(), last_off);
|
||||||
|
|
||||||
|
//Tries to select the items in the box, then returns the items with their previous selected states
|
||||||
selections = lister.select_display_range_if(begin, last, false, [this](const index_pair& abs_pos) {
|
selections = lister.select_display_range_if(begin, last, false, [this](const index_pair& abs_pos) {
|
||||||
if (this->mouse_selection.reverse_selection)
|
if (mouse_selection.reverse_selection)
|
||||||
{
|
{
|
||||||
if (mouse_selection.already_selected.cend() != std::find(mouse_selection.already_selected.cbegin(), mouse_selection.already_selected.cend(), abs_pos))
|
//Deselects the items in the box which has been already selected
|
||||||
|
if(mouse_selection.is_already_selected(abs_pos))
|
||||||
{
|
{
|
||||||
item_proxy{ this, abs_pos }.select(false);
|
item_proxy{ this, abs_pos }.select(false);
|
||||||
return false;
|
return false;
|
||||||
@ -2181,21 +2204,21 @@ namespace nana
|
|||||||
|
|
||||||
for (auto & pair : selections)
|
for (auto & pair : selections)
|
||||||
{
|
{
|
||||||
|
//Continue if the previous state is selected. It indicates the item now is not selected.
|
||||||
if (pair.second)
|
if (pair.second)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mouse_selection.selections.cend() ==
|
//Add the item to selections container.
|
||||||
std::find(mouse_selection.selections.cbegin(), mouse_selection.selections.cend(), pair.first))
|
if(!mouse_selection.is_selected(pair.first))
|
||||||
{
|
|
||||||
mouse_selection.selections.push_back(pair.first);
|
mouse_selection.selections.push_back(pair.first);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Deselects the items which are in mouse_selection.selections but not in selections.
|
||||||
|
//Eq to mouse_selection.selections = selections
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
for (auto i = mouse_selection.selections.cbegin(); i != mouse_selection.selections.cend();)
|
for (auto i = mouse_selection.selections.cbegin(); i != mouse_selection.selections.cend();)
|
||||||
#else
|
#else
|
||||||
for(auto i = mouse_selection.selections.begin(); i != mouse_selection.selections.end();)
|
for(auto i = mouse_selection.selections.begin(); i != mouse_selection.selections.end();)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
auto & selpos = *i;
|
auto & selpos = *i;
|
||||||
@ -2209,30 +2232,45 @@ namespace nana
|
|||||||
else
|
else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel_selections = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancel_selections)
|
//Restores an already selected item if it is not in selections.
|
||||||
|
for (auto& abs_pos : mouse_selection.already_selected)
|
||||||
{
|
{
|
||||||
if (!mouse_selection.already_selected.empty())
|
if (selections.cend() == std::find_if(selections.cbegin(), selections.cend(), [abs_pos](const std::pair<index_pair, bool>& rhs) {
|
||||||
|
return (abs_pos == rhs.first);
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
for (auto & pos : mouse_selection.selections)
|
item_proxy m{ this, abs_pos };
|
||||||
item_proxy(this, pos).select(false);
|
if (!m.selected())
|
||||||
|
|
||||||
//Don't restore the already selections if it is reverse selection(pressing shift). Behaves like Windows Explorer.
|
|
||||||
if (!mouse_selection.reverse_selection)
|
|
||||||
{
|
{
|
||||||
for (auto & abs_pos : mouse_selection.already_selected)
|
m.select(true);
|
||||||
item_proxy(this, abs_pos).select(true);
|
//Add the item to selections container.
|
||||||
|
if(!mouse_selection.is_selected(abs_pos))
|
||||||
|
mouse_selection.selections.push_back(abs_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
lister.select_for_all(false);
|
|
||||||
|
|
||||||
mouse_selection.selections.clear();
|
//Deselects the item which is not in already_selected and selections but in mouse_selection.selections
|
||||||
|
for(auto i = mouse_selection.selections.cbegin(); i != mouse_selection.selections.cend();)
|
||||||
|
{
|
||||||
|
auto abs_pos = *i;
|
||||||
|
|
||||||
|
bool is_box_selected = (selections.cend() != std::find_if(selections.cbegin(), selections.cend(), [abs_pos](const std::pair<index_pair, bool>& rhs) {
|
||||||
|
return (abs_pos == rhs.first);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (is_box_selected || mouse_selection.is_already_selected(abs_pos))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_proxy{ this, abs_pos }.select(false);
|
||||||
|
i = mouse_selection.selections.erase(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4374,7 +4412,7 @@ namespace nana
|
|||||||
if (arg.is_left_button() && (!lister.single_status(true)))
|
if (arg.is_left_button() && (!lister.single_status(true)))
|
||||||
essence_->start_mouse_selection(arg);
|
essence_->start_mouse_selection(arg);
|
||||||
|
|
||||||
//Deselection of all items is deferred to the mouse up event when ctrl or shift is not pressed
|
//Deselecting all items is deferred to the mouse up event when ctrl or shift is not pressed
|
||||||
//Pressing ctrl or shift is to selects other items without deselecting current selections.
|
//Pressing ctrl or shift is to selects other items without deselecting current selections.
|
||||||
if (!(arg.ctrl || arg.shift))
|
if (!(arg.ctrl || arg.shift))
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user