From d1cee66cd6afcf21eecdcf598375bb705cbc700a Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Tue, 22 Mar 2022 17:20:44 -0400 Subject: [PATCH 1/3] Add `leaves_only` support to `to_arrow()` --- .../src/cpp/context_grouped_pkey.cpp | 4 +- cpp/perspective/src/cpp/context_one.cpp | 20 +++++- cpp/perspective/src/cpp/context_two.cpp | 22 ++++++- cpp/perspective/src/cpp/data_slice.cpp | 12 ++++ cpp/perspective/src/cpp/emscripten.cpp | 19 +++--- cpp/perspective/src/cpp/traversal.cpp | 63 +++++++++++++------ .../src/cpp/tree_context_common.cpp | 2 +- cpp/perspective/src/cpp/view.cpp | 61 +++++++++++++++++- .../src/include/perspective/context_one.h | 3 + .../src/include/perspective/context_two.h | 3 + .../src/include/perspective/context_unit.h | 2 + .../src/include/perspective/traversal.h | 16 +++-- .../src/include/perspective/view.h | 4 +- packages/perspective/src/js/perspective.js | 31 ++++++--- 14 files changed, 215 insertions(+), 47 deletions(-) diff --git a/cpp/perspective/src/cpp/context_grouped_pkey.cpp b/cpp/perspective/src/cpp/context_grouped_pkey.cpp index 433bc0aaa1..b31ab88dfb 100644 --- a/cpp/perspective/src/cpp/context_grouped_pkey.cpp +++ b/cpp/perspective/src/cpp/context_grouped_pkey.cpp @@ -297,7 +297,7 @@ t_ctx_grouped_pkey::sort_by(const std::vector& sortby) { if (m_sortby.empty()) { return; } - m_traversal->sort_by(m_config, sortby, *this); + m_traversal->sort_by(sortby, *this); } void @@ -642,7 +642,7 @@ t_ctx_grouped_pkey::rebuild() { set_expansion_state(expansion_state); if (!m_sortby.empty()) { - m_traversal->sort_by(m_config, m_sortby, *this); + m_traversal->sort_by(m_sortby, *this); } } diff --git a/cpp/perspective/src/cpp/context_one.cpp b/cpp/perspective/src/cpp/context_one.cpp index 0e28795f0e..0dd8cb2ccd 100644 --- a/cpp/perspective/src/cpp/context_one.cpp +++ b/cpp/perspective/src/cpp/context_one.cpp @@ -360,7 +360,7 @@ t_ctx1::sort_by(const std::vector& sortby) { if (m_sortby.empty()) { return; } - m_traversal->sort_by(m_config, sortby, *(m_tree.get())); + m_traversal->sort_by(sortby, *(m_tree.get())); } void @@ -519,6 +519,24 @@ t_ctx1::reset_step_state() { } } +std::shared_ptr +t_ctx1::set_is_leaves_only() { + auto trav = m_traversal; + m_traversal = std::make_shared(m_tree); + m_traversal->set_is_leaves_only(true); + if (!m_sortby.empty()) { + m_traversal->sort_by(m_sortby, *(m_tree.get())); + } + + m_traversal->set_depth(m_sortby, m_config.get_num_rpivots() - 1); + return trav; +} + +void +t_ctx1::clear_is_leaves_only(std::shared_ptr trav) { + m_traversal = trav; +} + t_index t_ctx1::sidedness() const { return 1; diff --git a/cpp/perspective/src/cpp/context_two.cpp b/cpp/perspective/src/cpp/context_two.cpp index 6945427628..7d9bd2fcc7 100644 --- a/cpp/perspective/src/cpp/context_two.cpp +++ b/cpp/perspective/src/cpp/context_two.cpp @@ -482,7 +482,7 @@ void t_ctx2::column_sort_by(const std::vector& sortby) { PSP_TRACE_SENTINEL(); PSP_VERBOSE_ASSERT(m_init, "touching uninited object"); - m_ctraversal->sort_by(m_config, sortby, *(ctree().get())); + m_ctraversal->sort_by(sortby, *(ctree().get())); } void @@ -493,7 +493,7 @@ t_ctx2::sort_by(const std::vector& sortby) { if (m_sortby.empty()) { return; } - m_rtraversal->sort_by(m_config, sortby, *(rtree().get()), this); + m_rtraversal->sort_by(sortby, *(rtree().get()), this); } void @@ -503,6 +503,24 @@ t_ctx2::reset_sortby() { m_sortby = std::vector(); } +std::shared_ptr +t_ctx2::set_is_leaves_only() { + auto trav = m_rtraversal; + m_rtraversal = std::make_shared(rtree()); + m_rtraversal->set_is_leaves_only(true); + if (!m_sortby.empty()) { + m_rtraversal->sort_by(m_sortby, *(rtree().get()), this); + } + + m_rtraversal->set_depth(m_sortby, m_config.get_num_rpivots() - 1); + return trav; +} + +void +t_ctx2::clear_is_leaves_only(std::shared_ptr trav) { + m_rtraversal = trav; +} + void t_ctx2::notify(const t_data_table& flattened) { for (t_uindex tree_idx = 0, loop_end = m_trees.size(); tree_idx < loop_end; diff --git a/cpp/perspective/src/cpp/data_slice.cpp b/cpp/perspective/src/cpp/data_slice.cpp index 636116d841..e17a271cf8 100644 --- a/cpp/perspective/src/cpp/data_slice.cpp +++ b/cpp/perspective/src/cpp/data_slice.cpp @@ -28,6 +28,12 @@ t_data_slice::t_data_slice(std::shared_ptr ctx, , m_slice(slice) , m_column_names(column_names) { m_stride = m_end_col - m_start_col; + t_uindex ctx_nrows = m_ctx->get_row_count(); + t_uindex ncols = m_ctx->get_column_count(); + auto ext = sanitize_get_data_extents( + ctx_nrows, ncols, start_row, end_row, start_col, end_col); + m_start_row = ext.m_srow; + m_end_row = ext.m_erow; } template @@ -48,6 +54,12 @@ t_data_slice::t_data_slice(std::shared_ptr ctx, , m_column_names(column_names) , m_column_indices(column_indices) { m_stride = m_end_col - m_start_col; + t_uindex ctx_nrows = m_ctx->get_row_count(); + t_uindex ncols = m_ctx->get_column_count(); + auto ext = sanitize_get_data_extents( + ctx_nrows, ncols, start_row, end_row, start_col, end_col); + m_start_row = ext.m_srow; + m_end_row = ext.m_erow; } template diff --git a/cpp/perspective/src/cpp/emscripten.cpp b/cpp/perspective/src/cpp/emscripten.cpp index de4af44f4a..90f397c99f 100644 --- a/cpp/perspective/src/cpp/emscripten.cpp +++ b/cpp/perspective/src/cpp/emscripten.cpp @@ -203,9 +203,10 @@ namespace binding { template t_val to_arrow(std::shared_ptr> view, std::int32_t start_row, - std::int32_t end_row, std::int32_t start_col, std::int32_t end_col) { - std::shared_ptr s - = view->to_arrow(start_row, end_row, start_col, end_col, true); + std::int32_t end_row, std::int32_t start_col, std::int32_t end_col, + bool is_leaves_only) { + std::shared_ptr s = view->to_arrow( + start_row, end_row, start_col, end_col, true, is_leaves_only); return str_to_arraybuffer(s)["buffer"]; } @@ -1922,7 +1923,8 @@ EMSCRIPTEN_BINDINGS(perspective) { .function("get_sort", &View::get_sort) .function("get_step_delta", &View::get_step_delta) .function("get_column_dtype", &View::get_column_dtype) - .function("is_column_only", &View::is_column_only); + .function("is_column_only", &View::is_column_only) + .function("set_separator", &View::set_separator); class_>("View_ctx0") .constructor, std::shared_ptr, @@ -1948,7 +1950,8 @@ EMSCRIPTEN_BINDINGS(perspective) { .function("get_sort", &View::get_sort) .function("get_step_delta", &View::get_step_delta) .function("get_column_dtype", &View::get_column_dtype) - .function("is_column_only", &View::is_column_only); + .function("is_column_only", &View::is_column_only) + .function("set_separator", &View::set_separator); class_>("View_ctx1") .constructor, std::shared_ptr, @@ -1977,7 +1980,8 @@ EMSCRIPTEN_BINDINGS(perspective) { .function("get_sort", &View::get_sort) .function("get_step_delta", &View::get_step_delta) .function("get_column_dtype", &View::get_column_dtype) - .function("is_column_only", &View::is_column_only); + .function("is_column_only", &View::is_column_only) + .function("set_separator", &View::set_separator); class_>("View_ctx2") .constructor, std::shared_ptr, @@ -2007,7 +2011,8 @@ EMSCRIPTEN_BINDINGS(perspective) { .function("get_row_path", &View::get_row_path) .function("get_step_delta", &View::get_step_delta) .function("get_column_dtype", &View::get_column_dtype) - .function("is_column_only", &View::is_column_only); + .function("is_column_only", &View::is_column_only) + .function("set_separator", &View::set_separator); /****************************************************************************** * diff --git a/cpp/perspective/src/cpp/traversal.cpp b/cpp/perspective/src/cpp/traversal.cpp index 991ab19b21..c72b45d031 100644 --- a/cpp/perspective/src/cpp/traversal.cpp +++ b/cpp/perspective/src/cpp/traversal.cpp @@ -32,7 +32,8 @@ t_vdnode::t_vdnode(bool expanded, bool has_children) , m_has_children(has_children) {} t_traversal::t_traversal(std::shared_ptr tree) - : m_tree(tree) { + : m_tree(tree) + , m_is_leaves_only(false) { t_stnode_vec rchildren; tree->get_child_nodes(0, rchildren); populate_root_children(rchildren); @@ -174,14 +175,22 @@ t_traversal::expand_node( count += 1; } - // Update node being expanded - exp_tvnode.m_expanded = !sorted_idx.empty(); - exp_tvnode.m_ndesc += n_changed; - exp_tvnode.m_nchild = n_changed; - // insert children of node into the traversal - m_nodes->insert( - m_nodes->begin() + exp_idx + 1, children.begin(), children.end()); + if (m_is_leaves_only) { + if (children.size() > 0) { + m_nodes->erase(m_nodes->begin() + exp_idx); + m_nodes->insert( + m_nodes->begin() + exp_idx, children.begin(), children.end()); + } + } else { + // Update node being expanded + exp_tvnode.m_expanded = !sorted_idx.empty(); + exp_tvnode.m_ndesc += n_changed; + exp_tvnode.m_nchild = n_changed; + + m_nodes->insert( + m_nodes->begin() + exp_idx + 1, children.begin(), children.end()); + } // update ancestors about their new descendents update_ancestors(exp_idx, n_changed); @@ -280,7 +289,6 @@ t_traversal::update_sucessors(t_index nidx, t_index n_changed) { while (c_node->m_depth > 0) { t_index pidx = nidx - c_node->m_rel_pidx; - const t_tvnode& p_node = (*m_nodes)[pidx]; t_index p_nchild = p_node.m_nchild; @@ -289,7 +297,7 @@ t_traversal::update_sucessors(t_index nidx, t_index n_changed) { for (int i = 0; i < p_nchild; i++) { t_index curr_cidx = pidx + coffset; t_tvnode& child_node = (*m_nodes)[curr_cidx]; - if (curr_cidx > nidx) { + if (!m_is_leaves_only && curr_cidx > nidx) { child_node.m_rel_pidx += n_changed; } if (child_node.m_expanded) { @@ -312,7 +320,11 @@ t_traversal::get_tree_index(t_index idx) const { t_uindex t_traversal::size() const { - return m_nodes->size(); + if (m_is_leaves_only) { + return m_nodes->size() - 1; + } else { + return m_nodes->size(); + } } t_depth @@ -467,12 +479,17 @@ t_traversal::get_leaves(std::vector& out_data) const { } void -t_traversal::get_child_indices( - t_index nidx, std::vector>& out_data) const { +t_traversal::get_child_indices(t_index nidx, + std::vector>& out_data, t_index count) const { const t_tvnode& tvnode = (*m_nodes)[nidx]; - t_index nchild = tvnode.m_nchild; - t_index coffset = 1; + t_index nchild; + if (count >= 0) { + nchild = count; + } else { + nchild = tvnode.m_nchild; + } + t_index coffset = m_is_leaves_only && nidx > 0 ? 0 : 1; for (int i = 0; i < nchild; i++) { t_index curr_cidx = nidx + coffset; const t_tvnode& child_node = (*m_nodes)[curr_cidx]; @@ -506,7 +523,7 @@ t_traversal::get_num_tree_leaves(t_index idx) const { void t_traversal::post_order(t_index nidx, std::vector& out_vec) { std::vector> children; - get_child_indices(nidx, children); + get_child_indices(nidx, children, -1); for (t_index idx = 0, loop_end = children.size(); idx < loop_end; ++idx) { post_order(children[idx].first, out_vec); @@ -526,9 +543,14 @@ t_traversal::set_depth( while (pending.size() > 0) { t_index curidx = pending.back(); pending.pop_back(); - n_changed += expand_node(sortby, curidx, ctx2); + t_index _n_changed = expand_node(sortby, curidx, ctx2); + n_changed += _n_changed; std::vector> children; - get_child_indices(curidx, children); + if (m_is_leaves_only && curidx != 0) { + get_child_indices(curidx, children, _n_changed); + } else { + get_child_indices(curidx, children, -1); + } std::vector collapse; for (t_index idx = 0, loop_end = children.size(); idx < loop_end; ++idx) { @@ -668,6 +690,11 @@ t_traversal::drop_tree_indices(const std::vector& indices) { } } +void +t_traversal::set_is_leaves_only(bool is_leaves_only) { + m_is_leaves_only = is_leaves_only; +} + bool t_traversal::is_valid_idx(t_index idx) const { return idx > 0 && idx < t_index(size()); diff --git a/cpp/perspective/src/cpp/tree_context_common.cpp b/cpp/perspective/src/cpp/tree_context_common.cpp index ffb8e3b54c..8042f12329 100644 --- a/cpp/perspective/src/cpp/tree_context_common.cpp +++ b/cpp/perspective/src/cpp/tree_context_common.cpp @@ -205,7 +205,7 @@ ctx_get_flattened_tree(t_index idx, t_depth stop_depth, t_traversal& trav, t_index ptidx = trav.get_tree_index(idx); trav.set_depth(sortby, stop_depth); if (!sortby.empty()) { - trav.sort_by(config, sortby, *(trav.get_tree())); + trav.sort_by(sortby, *(trav.get_tree())); } t_index new_tvidx = trav.tree_index_lookup(ptidx, idx); return trav.get_flattened_tree(new_tvidx, stop_depth); diff --git a/cpp/perspective/src/cpp/view.cpp b/cpp/perspective/src/cpp/view.cpp index d3675b75b9..084787aa82 100644 --- a/cpp/perspective/src/cpp/view.cpp +++ b/cpp/perspective/src/cpp/view.cpp @@ -531,12 +531,65 @@ View::get_data(t_uindex start_row, t_uindex end_row, t_uindex start_col, template std::shared_ptr View::to_arrow(std::int32_t start_row, std::int32_t end_row, - std::int32_t start_col, std::int32_t end_col, bool emit_group_by) const { + std::int32_t start_col, std::int32_t end_col, bool emit_group_by, + bool is_leaves_only) const { std::shared_ptr> data_slice = get_data(start_row, end_row, start_col, end_col); return data_slice_to_arrow(data_slice, emit_group_by); }; +template <> +std::shared_ptr +View::to_arrow(std::int32_t start_row, std::int32_t end_row, + std::int32_t start_col, std::int32_t end_col, bool emit_group_by, + bool is_leaves_only) const { + std::shared_ptr guard; + if (is_leaves_only) { + guard = m_ctx->set_is_leaves_only(); + start_row += 1; + } + + std::shared_ptr> data_slice + = get_data(start_row, end_row, start_col, end_col); + auto arr = data_slice_to_arrow(data_slice, emit_group_by); + if (is_leaves_only) { + m_ctx->clear_is_leaves_only(guard); + } + + return arr; +}; + +template <> +std::shared_ptr +View::to_arrow(std::int32_t start_row, std::int32_t end_row, + std::int32_t start_col, std::int32_t end_col, bool emit_group_by, + bool is_leaves_only) const { + std::shared_ptr guard; + if (is_leaves_only) { + guard = m_ctx->set_is_leaves_only(); + start_row += 1; + } + + std::shared_ptr> data_slice + = get_data(start_row, end_row, start_col, end_col); + auto arr = data_slice_to_arrow(data_slice, emit_group_by); + if (is_leaves_only) { + m_ctx->clear_is_leaves_only(guard); + } + + return arr; +}; + +// template <> +// std::shared_ptr +// View::to_arrow(std::int32_t start_row, std::int32_t end_row, +// std::int32_t start_col, std::int32_t end_col, bool emit_group_by, +// bool is_leaves_only) const { +// std::shared_ptr> data_slice +// = get_data(start_row, end_row, start_col, end_col); +// return data_slice_to_arrow(data_slice, emit_group_by); +// }; + template std::shared_ptr View::to_csv(std::int32_t start_row, std::int32_t end_row, @@ -1312,6 +1365,12 @@ View::get_event_loop_thread_id() const { }; #endif +template +void +View::set_separator(std::string sep) { + m_separator = sep; +} + /****************************************************************************** * * Private diff --git a/cpp/perspective/src/include/perspective/context_one.h b/cpp/perspective/src/include/perspective/context_one.h index d284a7b057..d88fb0d77f 100644 --- a/cpp/perspective/src/include/perspective/context_one.h +++ b/cpp/perspective/src/include/perspective/context_one.h @@ -50,6 +50,9 @@ class PERSPECTIVE_EXPORT t_ctx1 : public t_ctxbase { using t_ctxbase::get_data; + std::shared_ptr set_is_leaves_only(); + void clear_is_leaves_only(std::shared_ptr trav); + private: std::shared_ptr m_traversal; std::shared_ptr m_tree; diff --git a/cpp/perspective/src/include/perspective/context_two.h b/cpp/perspective/src/include/perspective/context_two.h index c567da1c28..215993e2bd 100644 --- a/cpp/perspective/src/include/perspective/context_two.h +++ b/cpp/perspective/src/include/perspective/context_two.h @@ -58,6 +58,9 @@ class PERSPECTIVE_EXPORT t_ctx2 : public t_ctxbase { using t_ctxbase::get_data; + std::shared_ptr set_is_leaves_only(); + void clear_is_leaves_only(std::shared_ptr trav); + protected: std::vector resolve_cells( const std::vector>& cells) const; diff --git a/cpp/perspective/src/include/perspective/context_unit.h b/cpp/perspective/src/include/perspective/context_unit.h index 976f367e64..84a9c249e9 100644 --- a/cpp/perspective/src/include/perspective/context_unit.h +++ b/cpp/perspective/src/include/perspective/context_unit.h @@ -116,6 +116,8 @@ class PERSPECTIVE_EXPORT t_ctxunit : public t_ctxbase { const tsl::hopscotch_set& get_delta_pkeys() const; + void set_is_leaves_only(bool is_leaves_only); + // Unity api std::vector unity_get_row_data(t_uindex idx) const; std::vector unity_get_row_path(t_uindex idx) const; diff --git a/cpp/perspective/src/include/perspective/traversal.h b/cpp/perspective/src/include/perspective/traversal.h index bdb13566d2..8f9be5c56b 100644 --- a/cpp/perspective/src/include/perspective/traversal.h +++ b/cpp/perspective/src/include/perspective/traversal.h @@ -75,11 +75,12 @@ class t_traversal { void get_leaves(std::vector& out_data) const; template - void sort_by(const t_config& config, const std::vector& sortby, - const SRC_T& src, t_ctx2* ctx2 = nullptr); + void sort_by(const std::vector& sortby, const SRC_T& src, + t_ctx2* ctx2 = nullptr); - void get_child_indices( - t_index nidx, std::vector>& out_data) const; + void get_child_indices(t_index nidx, + std::vector>& out_data, + t_index count) const; void print_stats(); @@ -112,9 +113,12 @@ class t_traversal { void populate_root_children(const t_stnode_vec& rchildren); void populate_root_children(std::shared_ptr tree); + void set_is_leaves_only(bool is_leaves_only); + private: std::shared_ptr m_tree; std::shared_ptr> m_nodes; + bool m_is_leaves_only; }; /** @@ -128,7 +132,7 @@ class t_traversal { */ template void -t_traversal::sort_by(const t_config& config, +t_traversal::sort_by( const std::vector& sortby, const SRC_T& src, t_ctx2* ctx2) { std::vector new_nodes(m_nodes->size()); @@ -162,7 +166,7 @@ t_traversal::sort_by(const t_config& config, const t_tvnode& head = (*m_nodes)[h_ctvidx]; std::vector> h_children; - get_child_indices(h_ctvidx, h_children); + get_child_indices(h_ctvidx, h_children, -1); if (!h_children.empty()) { // Get sorted indices diff --git a/cpp/perspective/src/include/perspective/view.h b/cpp/perspective/src/include/perspective/view.h index 8ba822a08d..f1b7930990 100644 --- a/cpp/perspective/src/include/perspective/view.h +++ b/cpp/perspective/src/include/perspective/view.h @@ -153,7 +153,7 @@ class PERSPECTIVE_EXPORT View { */ std::shared_ptr to_arrow(std::int32_t start_row, std::int32_t end_row, std::int32_t start_col, std::int32_t end_col, - bool emit_group_by) const; + bool emit_group_by, bool is_leaves_only) const; /** * @brief Serializes the `View`'s data into the Apache Arrow format @@ -246,6 +246,8 @@ class PERSPECTIVE_EXPORT View { */ std::shared_ptr> get_row_delta() const; + void set_separator(std::string sep); + // Getters std::shared_ptr get_context() const; std::vector get_row_pivots() const; diff --git a/packages/perspective/src/js/perspective.js b/packages/perspective/src/js/perspective.js index a4117a63d5..a1622fc8b3 100644 --- a/packages/perspective/src/js/perspective.js +++ b/packages/perspective/src/js/perspective.js @@ -901,39 +901,54 @@ export default function (Module) { const end_col = options.end_col; const sides = this.sides(); + if (options.separator) { + this._View.set_separator(options.separator); + } + + let arrow; if (this.is_unit_context) { - return __MODULE__.to_arrow_unit( + arrow = __MODULE__.to_arrow_unit( this._View, start_row, end_row, start_col, - end_col + end_col, + !!options.leaves_only ); } else if (sides === 0) { - return __MODULE__.to_arrow_zero( + arrow = __MODULE__.to_arrow_zero( this._View, start_row, end_row, start_col, - end_col + end_col, + !!options.leaves_only ); } else if (sides === 1) { - return __MODULE__.to_arrow_one( + arrow = __MODULE__.to_arrow_one( this._View, start_row, end_row, start_col, - end_col + end_col, + !!options.leaves_only ); } else if (sides === 2) { - return __MODULE__.to_arrow_two( + arrow = __MODULE__.to_arrow_two( this._View, start_row, end_row, start_col, - end_col + end_col, + !!options.leaves_only ); } + + if (options.separator) { + this._View.set_separator("|"); + } + + return arrow; }; /** From fa202700dec37f4231d2661251c655070c21ffa6 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Wed, 6 Apr 2022 19:06:15 -0400 Subject: [PATCH 2/3] WIP --- .../src/js/workspace/commands.js | 62 +++++++++++++++++++ .../src/js/workspace/widget.js | 5 +- .../src/js/workspace/workspace.js | 1 + 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/packages/perspective-workspace/src/js/workspace/commands.js b/packages/perspective-workspace/src/js/workspace/commands.js index a4b12b270c..59d2b77055 100644 --- a/packages/perspective-workspace/src/js/workspace/commands.js +++ b/packages/perspective-workspace/src/js/workspace/commands.js @@ -10,6 +10,10 @@ import {CommandRegistry} from "@lumino/commands/src"; import {MODE} from "./workspace"; +import perspective from "@finos/perspective"; + +const worker = perspective.shared_worker(); + export const createCommands = (workspace, indicator) => { const commands = new CommandRegistry(); @@ -115,6 +119,64 @@ export const createCommands = (workspace, indicator) => { mnemonic: 0, }); + commands.addCommand("workspace:flatten", { + execute: async (args) => { + const view = await args.widget.viewer.getView(); + const arrow = await view.to_arrow({ + separator: ", ", + leaves_only: true, + }); + + const table = await worker.table(arrow); + const {group_by} = await args.widget.viewer.save(); + const columns = await table.columns(); + const new_group_by = columns.slice(0, group_by.length); + const new_config = { + table: "a", + group_by: new_group_by, + split_by: [], + filter: [], + sort: [], + columns: columns.slice(group_by.length), + }; + + workspace.addTable("a", Promise.resolve(table)); + + if (workspace.dockpanel.mode === "single-document") { + workspace.toggleSingleDocument(widget); + } + // const config = await widget.save(); + new_config.name = new_config.name + ? `${new_config.name} (flat)` + : ""; + + const duplicate = workspace._createWidgetAndNode({ + config: new_config, + }); + // if (config.linked) { + // workspace._linkWidget(duplicate); + // } + + // if (widget.master) { + // const index = workspace.masterPanel.widgets.indexOf(widget) + 1; + // workspace.masterPanel.insertWidget(index, duplicate); + // } else { + workspace.dockpanel.addWidget(duplicate, { + mode: "split-right", + ref: args.widget, + }); + // } + + await duplicate.task; + + // args.widget.viewer.load(table); + // args.widget.viewer.restore(new_config); + }, + iconClass: "menu-reset", + label: "Flatten", + mnemonic: 0, + }); + commands.addCommand("workspace:link", { execute: (args) => workspace.toggleLink(args.widget), isVisible: () => workspace.mode === MODE.LINKED, diff --git a/packages/perspective-workspace/src/js/workspace/widget.js b/packages/perspective-workspace/src/js/workspace/widget.js index ee91c240a9..45d967ba17 100644 --- a/packages/perspective-workspace/src/js/workspace/widget.js +++ b/packages/perspective-workspace/src/js/workspace/widget.js @@ -103,7 +103,10 @@ export class PerspectiveViewerWidget extends Widget { this.viewer.setAttribute("editable", editable); } - const restore_config = () => this.viewer.restore({...viewerConfig}); + const restore_config = async () => { + await this.viewer.restore({...viewerConfig}); + this._restore_config = undefined; + }; if (this._is_table_loaded) { return restore_config(); diff --git a/packages/perspective-workspace/src/js/workspace/workspace.js b/packages/perspective-workspace/src/js/workspace/workspace.js index ed4afe13d0..e9204b511b 100644 --- a/packages/perspective-workspace/src/js/workspace/workspace.js +++ b/packages/perspective-workspace/src/js/workspace/workspace.js @@ -748,6 +748,7 @@ export class PerspectiveWorkspace extends SplitPanel { command: "workspace:minimize", args: {widget}, }); + contextMenu.addItem({command: "workspace:flatten", args: {widget}}); contextMenu.addItem({ command: "workspace:duplicate", args: {widget}, From c77b66411aac56c0f56a107bbdb61739abc4723b Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Wed, 6 Apr 2022 19:26:12 -0400 Subject: [PATCH 3/3] WIP --- cpp/perspective/src/cpp/view.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/cpp/perspective/src/cpp/view.cpp b/cpp/perspective/src/cpp/view.cpp index 084787aa82..43c2e54858 100644 --- a/cpp/perspective/src/cpp/view.cpp +++ b/cpp/perspective/src/cpp/view.cpp @@ -453,10 +453,8 @@ View::get_data(t_uindex start_row, t_uindex end_row, t_uindex start_col, std::vector> cols; bool is_sorted = m_sort.size() > 0; - if (is_column_only()) { - start_row += m_row_offset; - end_row += m_row_offset; - } + start_row += m_row_offset; + end_row += m_row_offset; if (is_sorted) { /** @@ -546,7 +544,6 @@ View::to_arrow(std::int32_t start_row, std::int32_t end_row, std::shared_ptr guard; if (is_leaves_only) { guard = m_ctx->set_is_leaves_only(); - start_row += 1; } std::shared_ptr> data_slice @@ -567,7 +564,6 @@ View::to_arrow(std::int32_t start_row, std::int32_t end_row, std::shared_ptr guard; if (is_leaves_only) { guard = m_ctx->set_is_leaves_only(); - start_row += 1; } std::shared_ptr> data_slice @@ -580,16 +576,6 @@ View::to_arrow(std::int32_t start_row, std::int32_t end_row, return arr; }; -// template <> -// std::shared_ptr -// View::to_arrow(std::int32_t start_row, std::int32_t end_row, -// std::int32_t start_col, std::int32_t end_col, bool emit_group_by, -// bool is_leaves_only) const { -// std::shared_ptr> data_slice -// = get_data(start_row, end_row, start_col, end_col); -// return data_slice_to_arrow(data_slice, emit_group_by); -// }; - template std::shared_ptr View::to_csv(std::int32_t start_row, std::int32_t end_row,