Base selection on Excel behaviour

-- sqref is a block of selected cells containing the active_cell (normally is just == active_cell)
-- active cell is the selected vell in this selection/view/pane
-- inactive selections use the top-left cell as the active_cell
This commit is contained in:
Crzyrndm 2018-06-16 20:51:27 +12:00
parent 6f13002ac6
commit fc7c69a724
3 changed files with 56 additions and 39 deletions

View File

@ -36,6 +36,27 @@ namespace xlnt {
class XLNT_API selection class XLNT_API selection
{ {
public: public:
/// <summary>
/// default ctor
/// </summary>
explicit selection() = default;
/// <summary>
/// ctor when no range selected
/// sqref == active_cell
/// </summary>
explicit selection(pane_corner quadrant, cell_reference active_cell)
: active_cell_(active_cell), sqref_(range_reference(active_cell, active_cell)), pane_(quadrant)
{}
/// <summary>
/// ctor with selected range
/// sqref must contain active_cell
/// </summary>
explicit selection(pane_corner quadrant, cell_reference active_cell, range_reference selected)
: active_cell_(active_cell), sqref_(selected), pane_(quadrant)
{}
/// <summary> /// <summary>
/// Returns true if this selection has a defined active cell. /// Returns true if this selection has a defined active cell.
/// </summary> /// </summary>
@ -121,17 +142,18 @@ public:
private: private:
/// <summary> /// <summary>
/// The active cell /// The last selected cell in the selection
/// </summary> /// </summary>
optional<cell_reference> active_cell_; optional<cell_reference> active_cell_;
/// <summary> /// <summary>
/// The range /// The last selected block in the selection
/// contains active_cell_, normally == to active_cell_
/// </summary> /// </summary>
optional<range_reference> sqref_; optional<range_reference> sqref_;
/// <summary> /// <summary>
/// The quadrant /// The corner of the worksheet that this selection extends to
/// </summary> /// </summary>
pane_corner pane_; pane_corner pane_;
}; };

View File

@ -310,42 +310,23 @@ void worksheet::freeze_panes(const cell_reference &ref)
primary_view.pane().state = pane_state::frozen; primary_view.pane().state = pane_state::frozen;
primary_view.clear_selections(); primary_view.clear_selections();
primary_view.add_selection(selection());
primary_view.add_selection(selection());
if (ref.column() == "A") // no column is frozen if (ref.column() == "A") // no column is frozen
{ {
primary_view.selection(0).pane(pane_corner::bottom_left); primary_view.add_selection(selection(pane_corner::bottom_left, ref));
primary_view.selection(0).sqref("A1");
primary_view.selection(0).active_cell(ref.make_offset(0, -1)); // cell above
primary_view.selection(1).pane(pane_corner::bottom_right);
primary_view.selection(1).sqref("A1");
primary_view.selection(1).active_cell(ref);
primary_view.pane().active_pane = pane_corner::bottom_left; primary_view.pane().active_pane = pane_corner::bottom_left;
primary_view.pane().y_split = ref.row() - 1; primary_view.pane().y_split = ref.row() - 1;
} }
else if (ref.row() == 1) // no row is frozen else if (ref.row() == 1) // no row is frozen
{ {
primary_view.selection(0).pane(pane_corner::top_right); primary_view.add_selection(selection(pane_corner::top_right, ref));
primary_view.selection(0).sqref("A1");
primary_view.selection(0).active_cell(ref.make_offset(-1, 0)); // cell to the left
primary_view.selection(1).pane(pane_corner::bottom_right);
primary_view.selection(1).sqref("A1");
primary_view.selection(1).active_cell(ref);
primary_view.pane().active_pane = pane_corner::top_right; primary_view.pane().active_pane = pane_corner::top_right;
primary_view.pane().x_split = ref.column_index() - 1; primary_view.pane().x_split = ref.column_index() - 1;
} }
else // column and row is frozen else // column and row is frozen
{ {
primary_view.add_selection(selection()); primary_view.add_selection(selection(pane_corner::top_right, cell_reference(ref.column(), 1)));
primary_view.selection(0).pane(pane_corner::top_right); primary_view.add_selection(selection(pane_corner::bottom_left, cell_reference(1, ref.row())));
primary_view.selection(0).sqref("A1"); primary_view.add_selection(selection(pane_corner::bottom_right, ref));
primary_view.selection(0).active_cell(ref.make_offset(0, -1)); // cell above
primary_view.selection(1).pane(pane_corner::bottom_left);
primary_view.selection(1).sqref("A1");
primary_view.selection(1).active_cell(ref.make_offset(-1, 0)); // cell to the left
primary_view.selection(2).pane(pane_corner::bottom_right);
primary_view.selection(2).sqref("A1");
primary_view.selection(2).active_cell(ref);
primary_view.pane().active_pane = pane_corner::bottom_right; primary_view.pane().active_pane = pane_corner::bottom_right;
primary_view.pane().x_split = ref.column_index() - 1; primary_view.pane().x_split = ref.column_index() - 1;
primary_view.pane().y_split = ref.row() - 1; primary_view.pane().y_split = ref.row() - 1;
@ -373,11 +354,12 @@ void worksheet::active_cell(const cell_reference &ref)
if (!primary_view.has_selections()) if (!primary_view.has_selections())
{ {
primary_view.add_selection(selection()); primary_view.add_selection(selection(pane_corner::bottom_right, ref));
}
else
{
primary_view.selection(0).active_cell(ref);
} }
auto &primary_selection = primary_view.selection(0);
primary_selection.active_cell(ref);
} }
bool worksheet::has_active_cell() const bool worksheet::has_active_cell() const

View File

@ -492,10 +492,13 @@ public:
ws.freeze_panes("A4"); ws.freeze_panes("A4");
auto view = ws.view(); auto view = ws.view();
xlnt_assert_equals(view.selections().size(), 2); xlnt_assert_equals(view.selections().size(), 1);
xlnt_assert_equals(view.selections()[0].active_cell(), "A3"); // pane is the corner of the worksheet that this selection extends to
// active cell is the last selected cell in the selection
// sqref is the last selected block in the selection
xlnt_assert_equals(view.selections()[0].pane(), xlnt::pane_corner::bottom_left); xlnt_assert_equals(view.selections()[0].pane(), xlnt::pane_corner::bottom_left);
xlnt_assert_equals(view.selections()[0].sqref(), "A1"); // TODO: document sqref and clarify whether 'A1' is the intended value here xlnt_assert_equals(view.selections()[0].active_cell(), "A4");
xlnt_assert_equals(view.selections()[0].sqref(), "A4");
xlnt_assert_equals(view.pane().active_pane, xlnt::pane_corner::bottom_left); xlnt_assert_equals(view.pane().active_pane, xlnt::pane_corner::bottom_left);
xlnt_assert_equals(view.pane().state, xlnt::pane_state::frozen); xlnt_assert_equals(view.pane().state, xlnt::pane_state::frozen);
xlnt_assert_equals(view.pane().top_left_cell.get(), "A4"); xlnt_assert_equals(view.pane().top_left_cell.get(), "A4");
@ -509,10 +512,13 @@ public:
ws.freeze_panes("D1"); ws.freeze_panes("D1");
auto view = ws.view(); auto view = ws.view();
xlnt_assert_equals(view.selections().size(), 2); xlnt_assert_equals(view.selections().size(), 1);
xlnt_assert_equals(view.selections()[0].active_cell(), "C1"); // pane is the corner of the worksheet that this selection extends to
// active cell is the last selected cell in the selection
// sqref is the last selected block in the selection
xlnt_assert_equals(view.selections()[0].pane(), xlnt::pane_corner::top_right); xlnt_assert_equals(view.selections()[0].pane(), xlnt::pane_corner::top_right);
xlnt_assert_equals(view.selections()[0].sqref(), "A1"); // TODO: document sqref and clarify whether 'A1' is the intended value here xlnt_assert_equals(view.selections()[0].active_cell(), "D1");
xlnt_assert_equals(view.selections()[0].sqref(), "D1");
xlnt_assert_equals(view.pane().active_pane, xlnt::pane_corner::top_right); xlnt_assert_equals(view.pane().active_pane, xlnt::pane_corner::top_right);
xlnt_assert_equals(view.pane().state, xlnt::pane_state::frozen); xlnt_assert_equals(view.pane().state, xlnt::pane_state::frozen);
xlnt_assert_equals(view.pane().top_left_cell.get(), "D1"); xlnt_assert_equals(view.pane().top_left_cell.get(), "D1");
@ -527,11 +533,18 @@ public:
auto view = ws.view(); auto view = ws.view();
xlnt_assert_equals(view.selections().size(), 3); xlnt_assert_equals(view.selections().size(), 3);
// pane is the corner of the worksheet that this selection extends to
// active cell is the last selected cell in the selection
// sqref is the last selected block in the selection
xlnt_assert_equals(view.selections()[0].pane(), xlnt::pane_corner::top_right); xlnt_assert_equals(view.selections()[0].pane(), xlnt::pane_corner::top_right);
xlnt_assert_equals(view.selections()[0].active_cell(), "D1");
xlnt_assert_equals(view.selections()[0].sqref(), "D1");
xlnt_assert_equals(view.selections()[1].pane(), xlnt::pane_corner::bottom_left); xlnt_assert_equals(view.selections()[1].pane(), xlnt::pane_corner::bottom_left);
xlnt_assert_equals(view.selections()[2].active_cell(), "D4"); xlnt_assert_equals(view.selections()[1].active_cell(), "A4");
xlnt_assert_equals(view.selections()[1].sqref(), "A4");
xlnt_assert_equals(view.selections()[2].pane(), xlnt::pane_corner::bottom_right); xlnt_assert_equals(view.selections()[2].pane(), xlnt::pane_corner::bottom_right);
xlnt_assert_equals(view.selections()[2].sqref(), "A1"); // TODO: document sqref and clarify whether 'A1' is the intended value here xlnt_assert_equals(view.selections()[2].active_cell(), "D4");
xlnt_assert_equals(view.selections()[2].sqref(), "D4");
xlnt_assert_equals(view.pane().active_pane, xlnt::pane_corner::bottom_right); xlnt_assert_equals(view.pane().active_pane, xlnt::pane_corner::bottom_right);
xlnt_assert_equals(view.pane().state, xlnt::pane_state::frozen); xlnt_assert_equals(view.pane().state, xlnt::pane_state::frozen);
xlnt_assert_equals(view.pane().top_left_cell.get(), "D4"); xlnt_assert_equals(view.pane().top_left_cell.get(), "D4");