GUI2/Tree View: added interface for moving nodes between parent nodes

This commit is contained in:
Charles Dang 2018-07-14 06:29:51 +11:00
parent d5972c6f43
commit fa7c967c0a
5 changed files with 61 additions and 21 deletions

View file

@ -129,7 +129,7 @@ int mp_options_helper::remove_nodes_for_type(const std::string& type)
// Remove each node in reverse, so that in the end we have the position of the first node removed
for(auto i = type_node_vector.rbegin(); i != type_node_vector.rend(); i++) {
position = options_tree_.remove_node(*i);
position = options_tree_.remove_node(*i).second;
}
type_node_vector.clear();

View file

@ -19,7 +19,6 @@
#include "gui/core/log.hpp"
#include "gui/core/window_builder/helper.hpp"
#include "gui/core/register_widget.hpp"
#include "gui/widgets/tree_view_node.hpp"
#include "gui/widgets/window.hpp"
#include "gettext.hpp"
#include "wml_exception.hpp"
@ -66,7 +65,7 @@ tree_view_node& tree_view::add_node(
return get_root_node().add_child(id, data, index);
}
int tree_view::remove_node(tree_view_node* node)
std::pair<tree_view_node::ptr_t, int> tree_view::remove_node(tree_view_node* node)
{
assert(node && node != root_node_.get() && node->parent_node_);
const point node_size = node->get_size();
@ -79,6 +78,9 @@ int tree_view::remove_node(tree_view_node* node)
assert(node_itor != siblings.end());
auto old_node = std::move(*node_itor);
old_node->parent_node_ = nullptr;
const int position = std::distance(siblings.begin(), node_itor);
siblings.erase(node_itor);
@ -88,7 +90,7 @@ int tree_view::remove_node(tree_view_node* node)
resize_content(0, -node_size.y);
}
return position;
return std::make_pair(std::move(old_node), position);
}
void tree_view::clear()

View file

@ -15,6 +15,7 @@
#pragma once
#include "gui/widgets/scrollbar_container.hpp"
#include "gui/widgets/tree_view_node.hpp"
namespace gui2
{
@ -59,7 +60,15 @@ public:
const std::map<std::string /* widget id */, string_map>& data,
const int index = -1);
int remove_node(tree_view_node* tree_view_node);
/**
* Removes the given node as a child of its parent node.
*
* @param node A pointer to the node to remove.
*
* @returns A pair consisting of a smart pointer managing the removed
* node, and its position before removal.
*/
std::pair<tree_view_node::ptr_t, int> remove_node(tree_view_node* node);
void clear();

View file

@ -127,10 +127,7 @@ void tree_view_node::clear_before_destruct()
}
}
tree_view_node& tree_view_node::add_child(
const std::string& id,
const std::map<std::string /* widget id */, string_map>& data,
const int index)
tree_view_node& tree_view_node::add_child_impl(ptr_t&& new_node, const int index)
{
auto itor = children_.end();
@ -138,14 +135,22 @@ tree_view_node& tree_view_node::add_child(
itor = children_.begin() + index;
}
itor = children_.emplace(itor, new tree_view_node(id, this, get_tree_view(), data));
tree_view_node& node = **children_.insert(itor, std::move(new_node));
// NOTE: we currently don't support moving nodes between different trees, so this
// just ensures that wasn't tried. Remove this if we implement support for that.
assert(node.tree_view_ == tree_view_);
// Safety check. Might only fail if someone accidentally removed the parent_node_
// setter in add_child().
assert(node.parent_node_ == this);
if(is_folded() /*|| is_root_node()*/) {
return **itor;
return node;
}
if(get_tree_view().get_size() == point()) {
return **itor;
return node;
}
assert(get_tree_view().content_grid());
@ -153,7 +158,7 @@ tree_view_node& tree_view_node::add_child(
// Calculate width modification.
// This increases tree width if the width of the new node is greater than the current width.
point best_size = (*itor)->get_best_size();
point best_size = node.get_best_size();
best_size.x += get_indentation_level() * get_tree_view().indentation_step_size_;
const int width_modification = best_size.x > current_size.x
@ -165,7 +170,7 @@ tree_view_node& tree_view_node::add_child(
// is larger than its current size. This prevents the scrollbar being reserved even when there's obviously
// enough visual space.
// Throw away cached best size to force a recomputation.
// Throw away cached best size to force a recalculation.
get_tree_view().layout_initialize(false);
const point tree_best_size = get_tree_view().get_best_size();
@ -177,9 +182,9 @@ tree_view_node& tree_view_node::add_child(
assert(height_modification >= 0);
// Request new size.
get_tree_view().resize_content(width_modification, height_modification, -1, (*itor)->calculate_ypos());
get_tree_view().resize_content(width_modification, height_modification, -1, node.calculate_ypos());
return **itor;
return node;
}
unsigned tree_view_node::get_indentation_level() const

View file

@ -52,7 +52,7 @@ public:
~tree_view_node();
/**
* Adds a child item to the list of child nodes.
* Constructs a new child node.
*
* @param id The id of the node definition to use for the
* new node.
@ -66,10 +66,26 @@ public:
* @param index The item before which to add the new item,
* 0 == begin, -1 == end.
*/
tree_view_node&
add_child(const std::string& id,
const std::map<std::string /* widget id */, string_map>& data,
const int index = -1);
tree_view_node& add_child(const std::string& id,
const std::map<std::string /* widget id */, string_map>& data,
const int index = -1)
{
ptr_t new_node(new tree_view_node(id, this, get_tree_view(), data));
return add_child_impl(std::move(new_node), index);
}
/**
* Adds a previously-constructed node as a child of this node at the given position.
*
* @param new_node A smart pointer to the node object to insert.
* @param index The item before which to add the new item,
* 0 == begin, -1 == end.
*/
tree_view_node& add_child(ptr_t new_node, const int index = -1)
{
new_node->parent_node_ = this;
return add_child_impl(std::move(new_node), index);
}
/**
* Adds a sibbling for a node at the end of the list.
@ -92,12 +108,20 @@ public:
return parent_node().add_child(id, data);
}
private:
/** Implementation detail for @ref add_child. */
tree_view_node& add_child_impl(ptr_t&& new_node, const int index);
public:
/**
* Is this node the root node?
*
* When the parent tree view is created it adds one special node, the root
* node. This node has no parent node and some other special features so
* several code paths need to check whether they are the parent node.
*
* This also returns true for a detecthed node returned with @ref tree_view::
* remove_node.
*/
bool is_root_node() const
{