adjust dockpanes when a dockpane is floating/docking

This commit is contained in:
Jinhao 2015-09-01 03:49:38 +08:00
parent c4af5dafce
commit ebd8da13f0
4 changed files with 199 additions and 22 deletions

View File

@ -337,8 +337,6 @@ namespace nana
namespace nana
{
namespace ng
{
namespace drawerbase
{
namespace tabbar_lite
@ -352,7 +350,7 @@ namespace nana
driver();
~driver();
model* get_model();
model* get_model() const throw();
private:
//Overrides drawer_trigger's method
void attached(widget_reference, graph_reference) override;
@ -373,11 +371,15 @@ namespace nana
tabbar_lite() = default;
tabbar_lite(window, bool visible = true, const::nana::rectangle& = {});
public: //capacity
std::size_t length() const;
public: //modifiers
void attach(std::size_t pos, window);
void push_back(std::string text, ::nana::any par = {});
void push_front(std::string text, ::nana::any par = {});
};
}
}
#endif

View File

@ -1602,16 +1602,83 @@ namespace nana
}
private:
//Implement dock_notifier_interface
/*
static div_dockpane* _m_left(div_dockpane* dockpn)
{
for (auto & dv : dockpn->div_owner->children)
{
if (dv->div_next == dockpn)
return static_cast<div_dockpane*>(dv.get());
}
return nullptr;
}
::nana::size _m_calc_space_if_remove(div_dockpane* dockpn)
{
div_owner->field_area;
auto left = _m_left(dockpn);
while (left && !left->display)
left = _m_left(left);
auto right = dockpn->div_next;
while (right && !right->display)
right = right->div_next;
}
*/
void notify_float() override
{
set_display(false);
/*
this->width_percent = field_area.width / div_owner->field_area.width * 100.0;
this->height_percent = field_area.height / div_owner->field_area.height * 100.0;
//Re-layout the siblings
double other_px = this->div_owner->field_area.height - this->field_area.height;
for (auto& div : this->div_owner->children)
{
if (!div->display)
continue;
//deprecated
//auto wgt_percent = div->field_area.height / other_px;
//div->weight.assign_percent(wgt_percent * 100.0);
//???? other_px issue, have
auto dockpn = dynamic_cast<div_dockpane*>(div.get());
dockpn->width_percent = div->field_area.width / other_px * 100.0;
dockpn->height_percent = div->field_area.height / other_px * 100.0;
}
this->weight.assign_percent((double(field_area.height) / this->div_owner->field_area.height) * 100.0);
*/
impl_ptr_->collocate();
}
void notify_dock() override
{
indicator_.docker.reset();
/*
//Re-layout the siblings
auto px = this->weight.get_value(div_owner->field_area.height);
double other_px = this->div_owner->field_area.height - px;
this->weight.assign_percent(px / div_owner->field_area.height * 100);
for (auto& div : this->div_owner->children)
{
if (!div->display)
continue;
auto px = div->weight.get_value(static_cast<int>(other_px));
div->weight.assign_percent(px / div_owner->field_area.height * 100);
}
*/
set_display(true);
impl_ptr_->collocate();
}
@ -1744,6 +1811,8 @@ namespace nana
}
public:
field_dock * dockable_field{ nullptr };
double width_percent{ -1 }; //[-1, 100] it's invalid if it is less than zero
double height_percent{ -1 }; //[-1, 100]
private:
implement * impl_ptr_;
bool created_{ false };
@ -1751,7 +1820,7 @@ namespace nana
struct indicator_tag
{
paint::graphics graph;
//panel<true> widget;
//panel<true> widget; //deprecated
rectangle r;
std::unique_ptr<panel<true>> dock_area;
std::unique_ptr<form> docker;
@ -1766,6 +1835,19 @@ namespace nana
: division(kind::dock, std::move(name))
{}
division* front() const
{
auto i = children.cbegin();
for (auto i = children.cbegin(); i != children.cend(); ++i)
{
if (i->get()->display)
return i->get();
}
return nullptr;
}
void collocate(window wd) override
{
auto area = this->margin_area();
@ -1773,20 +1855,30 @@ namespace nana
unsigned vert_count = 0, horz_count = 0;
unsigned vert_weight = 0, horz_weight = 0;
bool prev_attr = _m_is_vert(children.front()->dir);
bool prev_attr = _m_is_vert(front()->dir);
(prev_attr ? horz_count : vert_count) = 1;
for (auto & child : children)
{
auto is_vert = _m_is_vert(child->dir);
if (!child->display)
continue;
if (child->weight.is_not_none())
auto child_dv = dynamic_cast<div_dockpane*>(child.get());
const auto is_vert = _m_is_vert(child->dir);
/*
if (is_vert)
{
if (is_vert)
vert_weight += static_cast<unsigned>(child->weight.get_value(area.height));
else
horz_weight += static_cast<unsigned>(child->weight.get_value(area.width));
if (child_dv->height_percent >= 0)
vert_weight += static_cast<unsigned>(child_dv->height_percent * area.height);
}
else
{
if (child_dv->width_percent >= 0)
horz_weight += static_cast<unsigned>(child_dv->width_percent * area.width);
}
*/
if (is_vert == prev_attr)
{
@ -1819,12 +1911,36 @@ namespace nana
for (auto & child : children)
{
if (!child->display)
continue;
auto child_dv = dynamic_cast<div_dockpane*>(child.get());
double weight;
/* //deprecated
if (child->weight.is_not_none())
weight = child->weight.get_value(_m_is_vert(child->dir) ? area.height : area.height);
else
weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w);
if (_m_is_vert(child->dir))
{
if (child_dv->height_percent >= 0)
weight = child_dv->height_percent * area.height;
else
weight = auto_vert_w;
}
else
{
if (child_dv->width_percent >= 0)
weight = child_dv->width_percent * area.width;
else
weight = auto_horz_w;
}
*/
weight = (_m_is_vert(child->dir) ? auto_vert_w : auto_horz_w);
::nana::rectangle child_r;
switch (child->dir)
{
@ -2216,7 +2332,12 @@ namespace nana
std::vector<std::unique_ptr<division>> adjusted_children;
for (auto & child : children)
{
adjusted_children.emplace_back(new div_dockpane(std::move(child->name), this, child->dir));
//ignores weight if it is a dockpane
//internally, width_percent/height_percent are employed for weight
auto dockpn = new div_dockpane(std::move(child->name), this, child->dir);
dockpn->div_next = child->div_next;
dockpn->div_owner = child->div_owner;
adjusted_children.emplace_back(dockpn);
}
children.swap(adjusted_children);

View File

@ -198,7 +198,7 @@ namespace nana
});
if (panels_.size() > 1)
tabbar_.reset(new tabbar<int>(*this));
tabbar_.reset(new tabbar_lite(*this));
std::size_t pos = 0;
for (auto & pn : panels_)
@ -208,8 +208,10 @@ namespace nana
pn.widget_ptr = pn.factory_fn(*this);
if (tabbar_)
{
tabbar_->push_back(pn.widget_ptr->caption());
tabbar_->relate(pos++, pn.widget_ptr->handle());
tabbar_->push_back(::nana::charset(pn.widget_ptr->caption()));
tabbar_->attach(pos++, pn.widget_ptr->handle());
//tabbar_->push_back(pn.widget_ptr->caption());
//tabbar_->relate(pos++, pn.widget_ptr->handle());
}
}
}
@ -262,7 +264,7 @@ namespace nana
std::unique_ptr<form> container_;
dockarea_caption caption_;
std::deque<panel> panels_;
std::unique_ptr<tabbar<int>> tabbar_;
std::unique_ptr<tabbar_lite> tabbar_;
struct moves
{

View File

@ -1275,8 +1275,6 @@ namespace nana
#include <forward_list>
namespace nana
{
namespace ng
{
namespace drawerbase
{
namespace tabbar_lite
@ -1286,6 +1284,7 @@ namespace nana
::std::string text;
::nana::any value;
::std::pair<int, int> pos_ends;
::nana::window attached_window{ nullptr };
item(std::string t, ::nana::any v)
: text(std::move(t)), value(std::move(v))
@ -1361,6 +1360,23 @@ namespace nana
return items_;
}
void show_attached_window()
{
if (indexes_.active_pos != npos)
{
auto i = items_.cbegin();
std::advance(i, indexes_.active_pos);
API::show_window(i->attached_window, true);
std::size_t pos = 0;
for (auto & m : items_)
{
if (pos++ != indexes_.active_pos)
API::show_window(m.attached_window, false);
}
}
}
bool track_pointer(const point& pos)
{
std::size_t item_pos = 0;
@ -1476,7 +1492,7 @@ namespace nana
delete model_;
}
model* driver::get_model()
model* driver::get_model() const throw()
{
return model_;
}
@ -1514,10 +1530,12 @@ namespace nana
void driver::mouse_down(graph_reference graph, const arg_mouse&)
{
auto & indexes = model_->get_indexes();
if (indexes.hovered_pos == model_->npos)
if ((indexes.hovered_pos == model_->npos) || (indexes.active_pos == indexes.hovered_pos))
return;
indexes.active_pos = indexes.hovered_pos;
model_->show_attached_window();
refresh(graph);
API::lazy_refresh();
}
@ -1532,6 +1550,41 @@ namespace nana
this->create(parent_wd, r, visible);
}
//capacity
std::size_t tabbar_lite::length() const
{
auto& items = get_drawer_trigger().get_model()->items();
internal_scope_guard lock;
std::size_t off = 0;
auto i = items.cbegin(), end = items.cend();
while (i != end)
{
++i;
++off;
}
return off;
}
//modifiers
void tabbar_lite::attach(std::size_t pos_set, window wd)
{
auto model = get_drawer_trigger().get_model();
internal_scope_guard lock;
for (auto & m : model->items())
{
if (0 == pos_set--)
{
m.attached_window = wd;
model->show_attached_window();
return;
}
}
throw std::out_of_range("invalid position of tabbar_lite");
}
void tabbar_lite::push_back(std::string text, ::nana::any any)
{
auto & items = get_drawer_trigger().get_model()->items();
@ -1561,5 +1614,4 @@ namespace nana
API::refresh_window(handle());
}
//end class tabbar
}
}//end namespace nana