improve place fit when margin is given

This commit is contained in:
Jinhao 2017-04-29 11:24:35 +08:00
parent 58cb215f7b
commit 0511a300d6
2 changed files with 152 additions and 72 deletions

View File

@ -807,80 +807,107 @@ namespace nana
if((ratio > 0.001) && (fv > 0))
fv /= ratio;
int set_weight = 0;
if ((fit_policy::none != this->fit) && this->field)
{
std::size_t fit_count = 0;
unsigned max_value = 0;
auto const fit_horz = (fit_policy::vert == this->fit);
std::size_t pos = 0;
for (auto & elm : this->field->elements)
{
++pos;
unsigned edge_px = 0;
if (fit_policy::both != this->fit)
{
auto fit_val = this->fit_parameters.at(pos - 1);
if (fit_val.empty())
continue;
edge_px = fit_val.integer();
}
auto extent = API::content_extent(elm.handle, edge_px, fit_horz);
if (extent)
{
run_.fit_extents[elm.handle] = extent->second;
++fit_count;
if (vert_fields)
floor.second += extent->second.height;
else
floor.first += extent->second.width;
max_value = (std::max)(max_value, (vert_fields ? extent->second.width : extent->second.height));
if (0 == set_weight)
set_weight = 1;
}
else
set_weight = -1;
}
if (max_value)
{
if (vert_fields)
floor.first = max_value;
else
floor.second = max_value;
}
//reverse deduction with gap
if (fit_count > 1)
{
double percent = 0;
for (std::size_t i = 0; i < fit_count - 1; ++i)
{
auto gap_value = gap.at(i);
if (gap_value.kind_of() == number_t::kind::percent)
{
percent += gap_value.real();
}
else
{
double precise_px = 0;
fv += calc_number(gap_value, 100, 0, precise_px);
}
}
fv *= (1 + percent);
}
//reverse deduction with margin
double margin_per = _m_extend_with_margin(0, floor.second);
margin_per += _m_extend_with_margin(2, floor.second);
if (margin_per < 1)
floor.second /= (1 - margin_per);
margin_per = _m_extend_with_margin(1, floor.first);
margin_per += _m_extend_with_margin(3, floor.first);
if (margin_per < 1)
floor.first /= (1 - margin_per);
}
if (!this->weight.empty())
{
if(!this->is_percent())
fv = this->weight.real();
}
else
{
if (fit_policy::none != this->fit)
if (!this->is_percent())
{
std::size_t fit_count = 0;
unsigned max_value = 0;
auto const fit_horz = (fit_policy::vert == this->fit);
std::size_t pos = 0;
for (auto & elm : this->field->elements)
{
++pos;
unsigned edge_px = 0;
if (fit_policy::both != this->fit)
{
auto fit_val = this->fit_parameters.at(pos - 1);
if (fit_val.empty())
continue;
edge_px = fit_val.integer();
}
auto extent = API::content_extent(elm.handle, edge_px, fit_horz);
if (extent)
{
run_.fit_extents[elm.handle] = extent->second;
++fit_count;
if (vert_fields)
floor.second += extent->second.height;
else
floor.first += extent->second.width;
max_value = (std::max)(max_value, (vert_fields ? extent->second.width : extent->second.height));
}
}
if (max_value)
{
if (vert_fields)
floor.first = max_value;
else
floor.second = max_value;
}
if (fit_count > 1)
{
double percent = 0;
for (std::size_t i = 0; i < fit_count - 1; ++i)
{
auto gap_value = gap.at(i);
if (gap_value.kind_of() == number_t::kind::percent)
{
percent += gap_value.real();
}
else
{
double precise_px = 0;
fv += calc_number(gap_value, 100, 0, precise_px);
}
}
fv *= (1 + percent);
}
//Cancel to set weight
if (fv <= this->weight.real())
set_weight = -1;
}
run_.weight_floor = floor;
}
if (1 == set_weight)
this->weight.assign(static_cast<int>(fv));
run_.weight_floor = floor;
}
return floor;
@ -1014,6 +1041,19 @@ namespace nana
return nullptr;
}
public:
double _m_extend_with_margin(std::size_t edge, double & extended)
{
auto margin_edge = margin.get_edge(edge);
if (!margin_edge.empty())
{
if (margin_edge.kind_of() != number_t::kind::percent)
extended += margin_edge.real();
else
return margin_edge.real();
}
return 0;
}
static void _m_visible_for_child(division * div, bool vsb) noexcept
{
for (auto & child : div->children)
@ -1104,7 +1144,9 @@ namespace nana
child_px = npx;
}
else
{
child_px = static_cast<unsigned>(child->weight.integer());
}
//Use 'endpos' to calc width is to avoid deviation
int endpos = static_cast<int>(position + child_px);
@ -2813,10 +2855,9 @@ namespace nana
if ((!max_px.empty()) && (!weight.empty()) && (weight.get_value(100) > max_px.get_value(100)))
weight.reset();
if(!weight.empty())
if (!weight.empty())
div->weight = weight;
div->gap = std::move(gap);
//attach the field to the division

View File

@ -591,6 +591,45 @@ namespace nana
margins_ = v;
}
number_t get_edge(std::size_t edge) const
{
int il{ -1 }, ir{ -1 }, it{ -1 }, ib{ -1 }; //index of four corners in margin
switch (margins_.size())
{
case 0: break;
case 1: //top
il = ir = it = ib = 0;
break;
case 2://top,bottom and left,right
it = ib = 0;
il = ir = 1;
break;
default:
il = 3; //left
case 3: //top, right, bottom
it = 0;
ir = 1;
ib = 2;
}
int pos = 0;
switch (edge)
{
case 0: //top
pos = it; break;
case 1: //right
pos = ir; break;
case 2: //bottom
pos = ib; break;
case 3: //left
pos = il; break;
default:
return number_t{};
}
return (-1 == pos ? number_t{} : margins_[pos]);
}
nana::rectangle area(const ::nana::rectangle& field_area) const
{
if (margins_.empty())
@ -613,7 +652,7 @@ namespace nana
{
case 0: break;
case 1: //top
it = 0;
il = ir = it = ib = 0;
break;
case 2://top,bottom and left,right
it = ib = 0;