GUI2/Tree View: added interface for moving nodes between parent nodes
This commit is contained in:
parent
d5972c6f43
commit
fa7c967c0a
5 changed files with 61 additions and 21 deletions
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue