fix issues that occur when expands/shrinks treebox
This commit is contained in:
@@ -37,7 +37,7 @@ namespace nana
|
||||
{
|
||||
enum class component
|
||||
{
|
||||
begin, expender = begin, crook, icon, text, bground, end
|
||||
begin, expander = begin, crook, icon, text, bground, end
|
||||
};
|
||||
|
||||
struct node_image_tag
|
||||
@@ -120,9 +120,6 @@ namespace nana
|
||||
|
||||
void check(node_type*, checkstate);
|
||||
|
||||
const tree_cont_type & tree() const;
|
||||
tree_cont_type & tree();
|
||||
|
||||
void renderer(::nana::pat::cloneable<renderer_interface>&&);
|
||||
const ::nana::pat::cloneable<renderer_interface>& renderer() const;
|
||||
void placer(::nana::pat::cloneable<compset_placer_interface>&&);
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace nana
|
||||
template<typename Renderer>
|
||||
struct trigger::basic_implement
|
||||
{
|
||||
typedef trigger::node_type node_type;
|
||||
using node_type = trigger::node_type;
|
||||
|
||||
struct rep_tag
|
||||
{
|
||||
@@ -215,7 +215,6 @@ namespace nana
|
||||
{
|
||||
nana::upoint border;
|
||||
nana::scroll<true> scroll;
|
||||
std::size_t prev_first_value;
|
||||
|
||||
mutable std::map<std::string, node_image_tag> image_table;
|
||||
|
||||
@@ -234,9 +233,9 @@ namespace nana
|
||||
{
|
||||
tooltip_window * tooltip;
|
||||
component comp_pointed;
|
||||
tree_cont_type::node_type * pointed;
|
||||
tree_cont_type::node_type * selected;
|
||||
tree_cont_type::node_type * event_node;
|
||||
node_type * pointed;
|
||||
node_type * selected;
|
||||
node_type * pressed_node;
|
||||
}node_state;
|
||||
|
||||
struct track_node_tag
|
||||
@@ -259,7 +258,6 @@ namespace nana
|
||||
data.widget_ptr = nullptr;
|
||||
data.stop_drawing = false;
|
||||
|
||||
shape.prev_first_value = 0;
|
||||
shape.first = nullptr;
|
||||
shape.indent_pixels = 10;
|
||||
shape.offset_x = 0;
|
||||
@@ -270,7 +268,7 @@ namespace nana
|
||||
node_state.comp_pointed = component::end;
|
||||
node_state.pointed = nullptr;
|
||||
node_state.selected = nullptr;
|
||||
node_state.event_node = nullptr;
|
||||
node_state.pressed_node = nullptr;
|
||||
|
||||
track_node.key_time = 0;
|
||||
|
||||
@@ -321,9 +319,6 @@ namespace nana
|
||||
if (node->is_ancestor_of(node_state.selected))
|
||||
node_state.selected = nullptr;
|
||||
|
||||
if (node->is_ancestor_of(node_state.event_node))
|
||||
node_state.event_node = nullptr;
|
||||
|
||||
if (perf_clear)
|
||||
{
|
||||
if (node->child)
|
||||
@@ -338,16 +333,15 @@ namespace nana
|
||||
return true;
|
||||
}
|
||||
|
||||
bool draw(bool reset_scroll, bool ignore_update = false)
|
||||
bool draw(bool reset_scroll, bool ignore_update = false, bool ignore_auto_draw = false)
|
||||
{
|
||||
if(data.graph && (false == data.stop_drawing))
|
||||
{
|
||||
if (reset_scroll)
|
||||
show_scroll();
|
||||
|
||||
if (attr.auto_draw)
|
||||
if (attr.auto_draw || ignore_auto_draw)
|
||||
{
|
||||
|
||||
//Draw background
|
||||
data.graph->rectangle(true, data.widget_ptr->bgcolor());
|
||||
|
||||
@@ -448,35 +442,49 @@ namespace nana
|
||||
{
|
||||
if(!node) return false;
|
||||
|
||||
auto & tree_container = attr.tree_cont;
|
||||
auto & tree = attr.tree_cont;
|
||||
|
||||
auto const first_pos = tree.distance_if(shape.first, pred_allow_child{});
|
||||
auto const node_pos = tree.distance_if(node, pred_allow_child{});
|
||||
auto const max_allow = max_allowed();
|
||||
switch(reason)
|
||||
{
|
||||
case 0:
|
||||
//adjust if the node expanded and the number of its children are over the max number allowed
|
||||
if(shape.first != node)
|
||||
if (node->value.second.expanded)
|
||||
{
|
||||
unsigned child_size = tree_container.child_size_if(*node, pred_allow_child());
|
||||
const std::size_t max_allow = max_allowed();
|
||||
|
||||
if(child_size < max_allow)
|
||||
//adjust if the number of its children are over the max number allowed
|
||||
if (shape.first != node)
|
||||
{
|
||||
unsigned off1 = tree_container.distance_if(shape.first, pred_allow_child());
|
||||
unsigned off2 = tree_container.distance_if(node, pred_allow_child());
|
||||
const unsigned size = off2 - off1 + child_size + 1;
|
||||
if(size > max_allow)
|
||||
shape.first = tree_container.advance_if(shape.first, size - max_allow, pred_allow_child());
|
||||
auto child_size = tree.child_size_if(*node, pred_allow_child());
|
||||
if (child_size < max_allow)
|
||||
{
|
||||
auto const size = node_pos - first_pos + child_size + 1;
|
||||
if (size > max_allow)
|
||||
shape.first = tree.advance_if(shape.first, size - max_allow, pred_allow_child{});
|
||||
}
|
||||
else
|
||||
shape.first = node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//The node is shrank
|
||||
auto visual_size = visual_item_size();
|
||||
if (visual_size > max_allow)
|
||||
{
|
||||
if (first_pos + max_allow > visual_size)
|
||||
shape.first = tree.advance_if(nullptr, visual_size - max_allow, pred_allow_child{});
|
||||
}
|
||||
else
|
||||
shape.first = nullptr;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
//param is the begin pos of an item in absolute.
|
||||
{
|
||||
int beg = static_cast<int>(tree_container.indent_size(node) * shape.indent_pixels) - shape.offset_x;
|
||||
int beg = static_cast<int>(tree.indent_size(node) * shape.indent_pixels) - shape.offset_x;
|
||||
int end = beg + static_cast<int>(node_w_pixels(node));
|
||||
|
||||
bool take_adjust = false;
|
||||
@@ -499,16 +507,14 @@ namespace nana
|
||||
case 4:
|
||||
if(shape.first != node)
|
||||
{
|
||||
unsigned off_first = tree_container.distance_if(shape.first, pred_allow_child());
|
||||
unsigned off_node = tree_container.distance_if(node, pred_allow_child());
|
||||
if(off_node < off_first)
|
||||
if (node_pos < first_pos)
|
||||
{
|
||||
shape.first = node;
|
||||
return true;
|
||||
}
|
||||
else if(off_node - off_first > max_allowed())
|
||||
else if (node_pos - first_pos > max_allow)
|
||||
{
|
||||
shape.first = tree_container.advance_if(0, off_node - max_allowed() + 1, pred_allow_child());
|
||||
shape.first = tree.advance_if(nullptr, node_pos - max_allow + 1, pred_allow_child{});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -603,44 +609,24 @@ namespace nana
|
||||
{
|
||||
if(scroll.empty())
|
||||
{
|
||||
shape.prev_first_value = 0;
|
||||
scroll.create(*data.widget_ptr, nana::rectangle(data.graph->width() - 16, 0, 16, data.graph->height()));
|
||||
|
||||
auto fn = [this](const arg_mouse& arg){
|
||||
this->event_scrollbar(arg);
|
||||
};
|
||||
auto & events = scroll.events();
|
||||
events.mouse_down(fn);
|
||||
events.mouse_move(fn);
|
||||
events.mouse_wheel(fn);
|
||||
scroll.events().value_changed.connect_unignorable([this](const arg_scroll& arg)
|
||||
{
|
||||
adjust.scroll_timestamp = nana::system::timestamp();
|
||||
adjust.timer.start();
|
||||
|
||||
shape.first = attr.tree_cont.advance_if(nullptr, shape.scroll.value(), pred_allow_child{});
|
||||
draw(false, false, true);
|
||||
});
|
||||
}
|
||||
|
||||
scroll.amount(visual_items);
|
||||
scroll.range(max_allow);
|
||||
}
|
||||
|
||||
scroll.value(attr.tree_cont.distance_if(shape.first, pred_allow_child()));
|
||||
}
|
||||
|
||||
void event_scrollbar(const arg_mouse& arg)
|
||||
{
|
||||
if((event_code::mouse_wheel == arg.evt_code) || arg.is_left_button())
|
||||
{
|
||||
if(shape.prev_first_value != shape.scroll.value())
|
||||
{
|
||||
shape.prev_first_value = shape.scroll.value();
|
||||
adjust.scroll_timestamp = nana::system::timestamp();
|
||||
adjust.timer.start();
|
||||
|
||||
shape.first = attr.tree_cont.advance_if(nullptr, shape.prev_first_value, pred_allow_child());
|
||||
|
||||
if(arg.window_handle == shape.scroll.handle())
|
||||
{
|
||||
draw(false);
|
||||
API::update_window(data.widget_ptr->handle());
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pos = attr.tree_cont.distance_if(shape.first, pred_allow_child{});
|
||||
scroll.value(pos);
|
||||
}
|
||||
|
||||
std::size_t visual_item_size() const
|
||||
@@ -702,11 +688,10 @@ namespace nana
|
||||
attr.tree_cont.template for_each<item_locator&>(shape.first, nl);
|
||||
|
||||
bool redraw = false;
|
||||
node_state.event_node = nl.node();
|
||||
|
||||
if(nl.node() && (nl.what() != component::end))
|
||||
auto const node = nl.node();
|
||||
if (node && (nl.what() != component::end))
|
||||
{
|
||||
if((nl.what() != node_state.comp_pointed || nl.node() != node_state.pointed))
|
||||
if ((nl.what() != node_state.comp_pointed) || (node != node_state.pointed))
|
||||
{
|
||||
node_state.comp_pointed = nl.what();
|
||||
|
||||
@@ -715,12 +700,11 @@ namespace nana
|
||||
item_proxy iprx(data.trigger_ptr, node_state.pointed);
|
||||
data.widget_ptr->events().hovered.emit(::nana::arg_treebox{ *data.widget_ptr, iprx, false }, data.widget_ptr->handle());
|
||||
|
||||
if (nl.node() != node_state.pointed)
|
||||
if (node != node_state.pointed)
|
||||
close_tooltip_window();
|
||||
}
|
||||
|
||||
|
||||
node_state.pointed = nl.node();
|
||||
node_state.pointed = node;
|
||||
item_proxy iprx(data.trigger_ptr, node_state.pointed);
|
||||
data.widget_ptr->events().hovered.emit(::nana::arg_treebox{ *data.widget_ptr, iprx, true }, data.widget_ptr->handle());
|
||||
|
||||
@@ -781,11 +765,11 @@ namespace nana
|
||||
};
|
||||
|
||||
auto & events = node_state.tooltip->events();
|
||||
events.mouse_leave(fn);
|
||||
events.mouse_move(fn);
|
||||
events.mouse_down.connect(fn);
|
||||
events.mouse_up.connect(fn);
|
||||
events.dbl_click.connect(fn);
|
||||
events.mouse_leave.connect_unignorable(fn);
|
||||
events.mouse_move.connect_unignorable(fn);
|
||||
events.mouse_down.connect_unignorable(fn);
|
||||
events.mouse_up.connect_unignorable(fn);
|
||||
events.dbl_click.connect_unignorable(fn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1170,7 +1154,7 @@ namespace nana
|
||||
{
|
||||
switch(comp)
|
||||
{
|
||||
case component_t::expender:
|
||||
case component_t::expander:
|
||||
if(attr.has_children)
|
||||
{
|
||||
r->width = item_offset;
|
||||
@@ -1259,7 +1243,7 @@ namespace nana
|
||||
void expander(graph_reference graph, const compset_interface * compset) const override
|
||||
{
|
||||
comp_attribute_t attr;
|
||||
if(compset->comp_attribute(component::expender, attr))
|
||||
if(compset->comp_attribute(component::expander, attr))
|
||||
{
|
||||
facade<element::arrow> arrow("solid_triangle");
|
||||
arrow.direction(direction::southeast);
|
||||
@@ -1374,7 +1358,7 @@ namespace nana
|
||||
{
|
||||
node_ = &node;
|
||||
what_ = static_cast<component>(comp);
|
||||
if (component::expender == what_ && (false == node_attr_.has_children))
|
||||
if (component::expander == what_ && (false == node_attr_.has_children))
|
||||
what_ = component::end;
|
||||
|
||||
if (component::text == what_)
|
||||
@@ -1667,16 +1651,6 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
auto trigger::tree() -> tree_cont_type &
|
||||
{
|
||||
return impl_->attr.tree_cont;
|
||||
}
|
||||
|
||||
auto trigger::tree() const -> tree_cont_type const &
|
||||
{
|
||||
return impl_->attr.tree_cont;
|
||||
}
|
||||
|
||||
void trigger::renderer(::nana::pat::cloneable<renderer_interface>&& r)
|
||||
{
|
||||
impl_->data.renderer = std::move(r);
|
||||
@@ -1726,7 +1700,7 @@ namespace nana
|
||||
|
||||
void trigger::selected(node_type* node)
|
||||
{
|
||||
if(tree().verify(node) && impl_->set_selected(node))
|
||||
if(impl_->attr.tree_cont.verify(node) && impl_->set_selected(node))
|
||||
impl_->draw(true);
|
||||
}
|
||||
|
||||
@@ -1750,7 +1724,7 @@ namespace nana
|
||||
|
||||
void trigger::node_icon(node_type* node, const std::string& id)
|
||||
{
|
||||
if(tree().verify(node))
|
||||
if(impl_->attr.tree_cont.verify(node))
|
||||
{
|
||||
node->value.second.img_idstr = id;
|
||||
auto i = impl_->shape.image_table.find(id);
|
||||
@@ -1768,7 +1742,7 @@ namespace nana
|
||||
|
||||
bool trigger::rename(node_type *node, const char* key, const char* name)
|
||||
{
|
||||
if((key || name ) && tree().verify(node))
|
||||
if((key || name ) && impl_->attr.tree_cont.verify(node))
|
||||
{
|
||||
if(key && (key != node->value.first))
|
||||
{
|
||||
@@ -1813,12 +1787,21 @@ namespace nana
|
||||
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
|
||||
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
|
||||
|
||||
if(nl.node() && (nl.what() == component::text || nl.what() == component::icon))
|
||||
auto const node = nl.node();
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
auto & node_state = impl_->node_state;
|
||||
switch (nl.what())
|
||||
{
|
||||
impl_->node_state.event_node = nl.node();
|
||||
impl_->set_expanded(impl_->node_state.event_node, !impl_->node_state.event_node->value.second.expanded);
|
||||
impl_->draw(true);
|
||||
case component::icon:
|
||||
case component::text:
|
||||
impl_->set_expanded(node, !node->value.second.expanded);
|
||||
impl_->draw(true, true, false);
|
||||
API::dev::lazy_refresh();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1833,26 +1816,19 @@ namespace nana
|
||||
bool has_redraw = false;
|
||||
|
||||
auto & node_state = impl_->node_state;
|
||||
node_state.event_node = nullptr;
|
||||
node_state.pressed_node = nl.node();
|
||||
|
||||
if(nl.node())
|
||||
if (node_state.pressed_node && (component::expander == nl.what()))
|
||||
{
|
||||
node_state.event_node = nl.node();
|
||||
if(nl.what() != component::end)
|
||||
{
|
||||
if(nl.what() == component::expender)
|
||||
{
|
||||
if(impl_->set_expanded(node_state.event_node, !node_state.event_node->value.second.expanded))
|
||||
impl_->make_adjust(node_state.event_node, 0);
|
||||
if(impl_->set_expanded(node_state.pressed_node, !node_state.pressed_node->value.second.expanded))
|
||||
impl_->make_adjust(node_state.pressed_node, 0);
|
||||
|
||||
has_redraw = true; //btw, don't select the node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!has_redraw) && (node_state.selected != node_state.event_node))
|
||||
if ((!has_redraw) && (node_state.selected != node_state.pressed_node))
|
||||
{
|
||||
impl_->set_selected(node_state.event_node);
|
||||
impl_->set_selected(node_state.pressed_node);
|
||||
has_redraw = true;
|
||||
}
|
||||
|
||||
@@ -1871,13 +1847,18 @@ namespace nana
|
||||
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
|
||||
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
|
||||
|
||||
auto const pressed_node = impl_->node_state.pressed_node;
|
||||
impl_->node_state.pressed_node = nullptr;
|
||||
|
||||
if(!nl.node())
|
||||
return;
|
||||
|
||||
if((impl_->node_state.selected != nl.node()) && nl.item_body())
|
||||
if (pressed_node == nl.node())
|
||||
{
|
||||
if ((impl_->node_state.selected != nl.node()) && nl.item_body())
|
||||
{
|
||||
impl_->set_selected(nl.node());
|
||||
if(impl_->make_adjust(impl_->node_state.selected, 1))
|
||||
if (impl_->make_adjust(impl_->node_state.selected, 1))
|
||||
impl_->adjust.scroll_timestamp = 1;
|
||||
}
|
||||
else if (nl.what() == component::crook)
|
||||
@@ -1890,6 +1871,9 @@ namespace nana
|
||||
}
|
||||
else
|
||||
return; //Do not refresh
|
||||
}
|
||||
else
|
||||
return; //Don't refresh
|
||||
|
||||
impl_->draw(true);
|
||||
API::dev::lazy_refresh();
|
||||
@@ -1906,18 +1890,19 @@ namespace nana
|
||||
|
||||
void trigger::mouse_wheel(graph_reference, const arg_wheel& arg)
|
||||
{
|
||||
auto & shape = impl_->shape;
|
||||
std::size_t prev = shape.prev_first_value;
|
||||
auto & scroll = impl_->shape.scroll;
|
||||
if (scroll.empty())
|
||||
return;
|
||||
|
||||
shape.scroll.make_step(!arg.upwards);
|
||||
auto const value_before = scroll.value();
|
||||
|
||||
impl_->event_scrollbar(arg);
|
||||
scroll.make_step(!arg.upwards);
|
||||
|
||||
if(prev != shape.prev_first_value)
|
||||
if (value_before != scroll.value())
|
||||
{
|
||||
impl_->track_mouse(arg.pos.x, arg.pos.y);
|
||||
|
||||
impl_->draw(false);
|
||||
impl_->draw(false, true, true);
|
||||
API::dev::lazy_refresh();
|
||||
}
|
||||
}
|
||||
@@ -2162,7 +2147,7 @@ namespace nana
|
||||
auto treebox::find(const std::string& keypath) -> item_proxy
|
||||
{
|
||||
auto * trg = &get_drawer_trigger();
|
||||
return item_proxy(trg, trg->tree().find(keypath));
|
||||
return item_proxy(trg, trg->impl()->attr.tree_cont.find(keypath));
|
||||
}
|
||||
|
||||
treebox::item_proxy treebox::insert(const std::string& path_key, std::string title)
|
||||
@@ -2192,7 +2177,7 @@ namespace nana
|
||||
|
||||
std::string treebox::make_key_path(item_proxy i, const std::string& splitter) const
|
||||
{
|
||||
auto & tree = get_drawer_trigger().tree();
|
||||
auto & tree = get_drawer_trigger().impl()->attr.tree_cont;
|
||||
auto pnode = i._m_node();
|
||||
if(tree.verify(pnode))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user