code refine
This commit is contained in:
parent
3e5c4133ce
commit
f43d54d7e2
@ -15,7 +15,6 @@
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
#include <nana/deploy.hpp>
|
||||
@ -57,7 +56,7 @@ namespace nana
|
||||
enum class token
|
||||
{
|
||||
div_start, div_end, splitter,
|
||||
identifier, dock, fit, vert, grid, number, array, reparray,
|
||||
identifier, dock, fit, fit_s, vert, grid, number, array, reparray,
|
||||
weight, gap, margin, arrange, variable, repeated, min_px, max_px, left, right, top, bottom, undisplayed, invisible,
|
||||
collapse, parameters,
|
||||
equal,
|
||||
@ -73,7 +72,7 @@ namespace nana
|
||||
return idstr_;
|
||||
}
|
||||
|
||||
number_t number() const
|
||||
const number_t& number() const
|
||||
{
|
||||
return number_;
|
||||
}
|
||||
@ -98,11 +97,6 @@ namespace nana
|
||||
return (sp_ - divstr_);
|
||||
}
|
||||
|
||||
std::string pos_str() const
|
||||
{
|
||||
return std::to_string(pos());
|
||||
}
|
||||
|
||||
token read()
|
||||
{
|
||||
sp_ = _m_eat_whitespace(sp_);
|
||||
@ -255,6 +249,8 @@ namespace nana
|
||||
return token::dock;
|
||||
else if ("fit" == idstr_)
|
||||
return token::fit;
|
||||
else if ("fit_s" == idstr_)
|
||||
return token::fit_s;
|
||||
else if ("vertical" == idstr_ || "vert" == idstr_)
|
||||
return token::vert;
|
||||
else if ("variable" == idstr_ || "repeated" == idstr_)
|
||||
@ -434,6 +430,16 @@ namespace nana
|
||||
}; //end class tokenizer
|
||||
}
|
||||
|
||||
static bool is_vert_dir(::nana::direction dir)
|
||||
{
|
||||
return (dir == ::nana::direction::north || dir == ::nana::direction::south);
|
||||
}
|
||||
|
||||
static int horz_point(bool vert, const point& pos)
|
||||
{
|
||||
return (vert ? pos.y : pos.x);
|
||||
}
|
||||
|
||||
|
||||
static bool is_idchar(int ch) noexcept
|
||||
{
|
||||
@ -640,18 +646,31 @@ namespace nana
|
||||
return nullptr;
|
||||
}
|
||||
private:
|
||||
//Listen to destroy of a window
|
||||
//It will delete the element and recollocate when the window destroyed.
|
||||
event_handle _m_make_destroy(window wd)
|
||||
void _m_insert_widget(window wd, bool to_fasten)
|
||||
{
|
||||
return API::events(wd).destroy.connect([this, wd](const arg_destroy&)
|
||||
if (API::empty_window(wd))
|
||||
throw std::invalid_argument("Place: An invalid window handle.");
|
||||
|
||||
if (API::get_parent_window(wd) != place_ptr_->window_handle())
|
||||
throw std::invalid_argument("Place: the window is not a child of place bind window");
|
||||
|
||||
//Listen to destroy of a window
|
||||
//It will delete the element and recollocate when the window destroyed.
|
||||
auto evt = API::events(wd).destroy.connect([this, to_fasten](const arg_destroy& arg)
|
||||
{
|
||||
if (erase_element(elements, wd))
|
||||
if (!to_fasten)
|
||||
{
|
||||
if (!API::is_destroying(API::get_parent_window(wd)))
|
||||
place_ptr_->collocate();
|
||||
if (erase_element(elements, arg.window_handle))
|
||||
{
|
||||
if (!API::is_destroying(API::get_parent_window(arg.window_handle)))
|
||||
place_ptr_->collocate();
|
||||
}
|
||||
}
|
||||
else
|
||||
erase_element(fastened, arg.window_handle);
|
||||
});
|
||||
|
||||
(to_fasten ? &fastened : &elements)->emplace_back(wd, evt);
|
||||
}
|
||||
|
||||
field_interface& operator<<(const char* label_text) override
|
||||
@ -666,33 +685,13 @@ namespace nana
|
||||
|
||||
field_interface& operator<<(window wd) override
|
||||
{
|
||||
if (API::empty_window(wd))
|
||||
throw std::invalid_argument("Place: An invalid window handle.");
|
||||
|
||||
if (API::get_parent_window(wd) != place_ptr_->window_handle())
|
||||
throw std::invalid_argument("Place: the window is not a child of place bind window");
|
||||
|
||||
auto evt = _m_make_destroy(wd);
|
||||
elements.emplace_back(wd, evt);
|
||||
_m_insert_widget(wd, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
field_interface& fasten(window wd) override
|
||||
{
|
||||
if (API::empty_window(wd))
|
||||
throw std::invalid_argument("Place: An invalid window handle.");
|
||||
|
||||
if (API::get_parent_window(wd) != place_ptr_->window_handle())
|
||||
throw std::invalid_argument("Place: the window is not a child of place bind window");
|
||||
|
||||
//Listen to destroy of a window. The deleting a fastened window
|
||||
//does not change the layout.
|
||||
auto evt = API::events(wd).destroy.connect([this](const arg_destroy& arg)
|
||||
{
|
||||
erase_element(fastened, arg.window_handle);
|
||||
});
|
||||
|
||||
fastened.emplace_back(wd, evt);
|
||||
_m_insert_widget(wd, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -719,6 +718,12 @@ namespace nana
|
||||
};//end class field_dock
|
||||
|
||||
|
||||
enum class fit_policy
|
||||
{
|
||||
none, //Doesn't fit the content
|
||||
both, //Fits both width and height of content
|
||||
single //Fits only width or height of content
|
||||
};
|
||||
|
||||
class place::implement::division
|
||||
{
|
||||
@ -773,7 +778,7 @@ namespace nana
|
||||
{
|
||||
auto child_floor = child->calc_weight_floor();
|
||||
|
||||
if(child->weight.kind_of() == number_t::kind::percent)
|
||||
if(child->is_percent())
|
||||
{
|
||||
ratio += child->weight.real();
|
||||
}
|
||||
@ -785,24 +790,23 @@ namespace nana
|
||||
}
|
||||
|
||||
auto const vert = (this->div_owner && (this->div_owner->kind_of_division == kind::vertical_arrange));
|
||||
|
||||
double& fv = (vert ? floor.second : floor.first);
|
||||
|
||||
if(ratio > 0.001)
|
||||
{
|
||||
if(fv > 0)
|
||||
fv = fv / ratio;
|
||||
}
|
||||
if((ratio > 0.001) && (fv > 0))
|
||||
fv /= ratio;
|
||||
|
||||
if (!this->weight.empty())
|
||||
{
|
||||
if (this->weight.kind_of() != number_t::kind::percent)
|
||||
if(!this->is_percent())
|
||||
fv = this->weight.real();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->fit_content)
|
||||
if (fit_policy::none != this->fit)
|
||||
{
|
||||
unsigned limited_px = 0;
|
||||
bool limit_width = false;
|
||||
|
||||
std::size_t fit_count = 0;
|
||||
unsigned max_value = 0;
|
||||
for (auto & elm : this->field->elements)
|
||||
@ -812,17 +816,11 @@ namespace nana
|
||||
{
|
||||
++fit_count;
|
||||
if (vert)
|
||||
{
|
||||
floor.second += extent->second.height;
|
||||
if (extent->second.width > max_value)
|
||||
max_value = extent->second.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
floor.first += extent->second.width;
|
||||
if (extent->second.height > max_value)
|
||||
max_value = extent->second.height;
|
||||
}
|
||||
|
||||
max_value = (std::max)(max_value, (vert ? extent->second.width : extent->second.height));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1006,7 +1004,7 @@ namespace nana
|
||||
kind kind_of_division;
|
||||
bool display{ true };
|
||||
bool visible{ true };
|
||||
bool fit_content{ false };
|
||||
fit_policy fit{ fit_policy::none };
|
||||
::nana::direction dir{::nana::direction::west};
|
||||
std::string name;
|
||||
std::vector<std::unique_ptr<division>> children;
|
||||
@ -1109,27 +1107,21 @@ namespace nana
|
||||
|
||||
bool moved = false;
|
||||
unsigned px = 0;
|
||||
if (this->fit_content)
|
||||
|
||||
auto move_r = element_r.result();
|
||||
if (fit_policy::both == this->fit)
|
||||
{
|
||||
auto extent = API::content_extent(el.handle, 0, false);
|
||||
if (extent)
|
||||
{
|
||||
auto r = element_r.result();
|
||||
r.dimension(extent->second);
|
||||
move_r.dimension(extent->second);
|
||||
|
||||
if (vert)
|
||||
{
|
||||
if (area_margined.width > r.width)
|
||||
r.x += (area_margined.width - r.width) / 2;
|
||||
}
|
||||
move_r.x += place_parts::differ(area_margined.width, move_r.width) / 2;
|
||||
else
|
||||
{
|
||||
if (area_margined.height > r.height)
|
||||
r.y += (area_margined.height - r.height) / 2;
|
||||
}
|
||||
move_r.y += place_parts::differ(area_margined.height, move_r.height) / 2;
|
||||
|
||||
API::move_window(el.handle, r);
|
||||
px = (vert ? r.height : r.width);
|
||||
px = (vert ? move_r.height : move_r.width);
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
@ -1138,9 +1130,11 @@ namespace nana
|
||||
{
|
||||
px = calc_number(arrange_.at(index), area_px, adjustable_px, precise_px);
|
||||
element_r.w_ref() = px;
|
||||
API::move_window(el.handle, element_r.result());
|
||||
move_r = element_r.result();
|
||||
}
|
||||
|
||||
API::move_window(el.handle, move_r);
|
||||
|
||||
if (index + 1 < field->elements.size())
|
||||
position += (px + calc_number(gap.at(index), area_px, 0, precise_px));
|
||||
|
||||
@ -1260,7 +1254,7 @@ namespace nana
|
||||
return reached_mins;
|
||||
}
|
||||
|
||||
double _m_revise_adjustable(std::pair<unsigned, std::size_t>& fa, unsigned area_px) noexcept
|
||||
double _m_revise_adjustable(std::pair<unsigned, std::size_t>& fa, unsigned area_px)
|
||||
{
|
||||
if (fa.first >= area_px || 0 == fa.second)
|
||||
return 0;
|
||||
@ -1402,126 +1396,120 @@ namespace nana
|
||||
if (!field || !(visible && display))
|
||||
return;
|
||||
|
||||
auto area = margin_area();
|
||||
|
||||
unsigned gap_size = 0;
|
||||
auto gap_number = gap.at(0);
|
||||
if (!gap_number.empty())
|
||||
gap_size = static_cast<unsigned>(gap_number.get_value(area.width));
|
||||
|
||||
//When the amount pixels of gaps is out of the area bound.
|
||||
if ((gap_size * dimension.first >= area.width) || (gap_size * dimension.second >= area.height))
|
||||
{
|
||||
for (auto & el : field->elements)
|
||||
API::window_size(el.handle, size{ 0, 0 });
|
||||
return;
|
||||
}
|
||||
auto const area = margin_area();
|
||||
auto const gap_size = static_cast<unsigned>(gap.at(0).get_value(area.width)); //gap_size is 0 if gap isn't specified
|
||||
|
||||
auto i = field->elements.cbegin();
|
||||
auto const end = field->elements.cend();
|
||||
if (dimension.first <= 1 && dimension.second <= 1)
|
||||
|
||||
//The total gaps must not beyond the bound of the area.
|
||||
if ((gap_size * dimension.first < area.width) && (gap_size * dimension.second < area.height))
|
||||
{
|
||||
auto n_of_wd = field->elements.size();
|
||||
std::size_t edge;
|
||||
switch (n_of_wd)
|
||||
if (dimension.first <= 1 && dimension.second <= 1)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
edge = 1; break;
|
||||
case 2: case 3: case 4:
|
||||
edge = 2; break;
|
||||
default:
|
||||
edge = static_cast<std::size_t>(std::sqrt(n_of_wd));
|
||||
if ((edge * edge) < n_of_wd) ++edge;
|
||||
}
|
||||
|
||||
double y = area.y;
|
||||
double block_w = area.width / double(edge);
|
||||
double block_h = area.height / double((n_of_wd / edge) + (n_of_wd % edge ? 1 : 0));
|
||||
unsigned uns_block_w = static_cast<unsigned>(block_w);
|
||||
unsigned uns_block_h = static_cast<unsigned>(block_h);
|
||||
unsigned height = (uns_block_h > gap_size ? uns_block_h - gap_size : uns_block_h);
|
||||
|
||||
std::size_t arr_pos = 0;
|
||||
for (std::size_t u = 0; (u < edge && i != end); ++u)
|
||||
{
|
||||
double x = area.x;
|
||||
for (std::size_t v = 0; (v < edge && i != end); ++v, ++i)
|
||||
auto n_of_wd = field->elements.size();
|
||||
std::size_t edge;
|
||||
switch (n_of_wd)
|
||||
{
|
||||
unsigned value = 0;
|
||||
auto arr = arrange_.at(arr_pos++);
|
||||
|
||||
if (arr.empty())
|
||||
value = static_cast<decltype(value)>(block_w);
|
||||
else
|
||||
value = static_cast<decltype(value)>(arr.get_value(static_cast<int>(area.width)));
|
||||
|
||||
unsigned width = (value > uns_block_w ? uns_block_w : value);
|
||||
if (width > gap_size) width -= gap_size;
|
||||
API::move_window(i->handle, rectangle{ static_cast<int>(x), static_cast<int>(y), width, height });
|
||||
x += block_w;
|
||||
}
|
||||
y += block_h;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double block_w = int(area.width - gap_size * (dimension.first - 1)) / double(dimension.first);
|
||||
double block_h = int(area.height - gap_size * (dimension.second - 1)) / double(dimension.second);
|
||||
|
||||
std::unique_ptr<char[]> table_ptr{ new char[dimension.first * dimension.second] };
|
||||
char *table = table_ptr.get();
|
||||
std::memset(table, 0, dimension.first * dimension.second);
|
||||
|
||||
std::size_t lbp = 0;
|
||||
|
||||
double precise_h = 0;
|
||||
for (std::size_t u = 0; (u < dimension.second && i != end); ++u)
|
||||
{
|
||||
auto const block_height_px = static_cast<unsigned>(block_h + precise_h);
|
||||
precise_h = (block_h + precise_h) - block_height_px;
|
||||
|
||||
double precise_w = 0;
|
||||
for (std::size_t v = 0; (v < dimension.first && i != end); ++v)
|
||||
{
|
||||
if (table[v + lbp])
|
||||
{
|
||||
precise_w += block_w;
|
||||
precise_w -= static_cast<int>(precise_w);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> room{ 1, 1 };
|
||||
_m_find_collapse(static_cast<int>(v), static_cast<int>(u), room);
|
||||
|
||||
int pos_x = area.x + static_cast<int>(v * (block_w + gap_size));
|
||||
int pos_y = area.y + static_cast<int>(u * (block_h + gap_size));
|
||||
|
||||
unsigned result_h;
|
||||
if (room.first <= 1 && room.second <= 1)
|
||||
{
|
||||
precise_w += block_w;
|
||||
result_h = block_height_px;
|
||||
table[v + lbp] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
precise_w += block_w * room.first + (room.first - 1) * gap_size;
|
||||
result_h = static_cast<unsigned>(block_h * room.second + precise_h + (room.second - 1) * gap_size);
|
||||
|
||||
for (unsigned y = 0; y < room.second; ++y)
|
||||
for (unsigned x = 0; x < room.first; ++x)
|
||||
table[v + x + lbp + y * dimension.first] = 1;
|
||||
}
|
||||
|
||||
unsigned result_w = static_cast<unsigned>(precise_w);
|
||||
precise_w -= result_w;
|
||||
|
||||
API::move_window(i->handle, rectangle{ pos_x, pos_y, result_w, result_h });
|
||||
++i;
|
||||
case 0:
|
||||
case 1:
|
||||
edge = 1; break;
|
||||
case 2: case 3: case 4:
|
||||
edge = 2; break;
|
||||
default:
|
||||
edge = static_cast<std::size_t>(std::sqrt(n_of_wd));
|
||||
if ((edge * edge) < n_of_wd) ++edge;
|
||||
}
|
||||
|
||||
lbp += dimension.first;
|
||||
double y = area.y;
|
||||
const double block_w = area.width / double(edge);
|
||||
const double block_h = area.height / double((n_of_wd / edge) + (n_of_wd % edge ? 1 : 0));
|
||||
const unsigned uns_block_w = static_cast<unsigned>(block_w);
|
||||
const unsigned uns_block_h = static_cast<unsigned>(block_h);
|
||||
const unsigned height = (uns_block_h > gap_size ? uns_block_h - gap_size : uns_block_h);
|
||||
|
||||
std::size_t arr_pos = 0;
|
||||
for (std::size_t u = 0; (u < edge && i != end); ++u)
|
||||
{
|
||||
double x = area.x;
|
||||
for (std::size_t v = 0; (v < edge && i != end); ++v, ++i)
|
||||
{
|
||||
unsigned value = 0;
|
||||
auto arr = arrange_.at(arr_pos++);
|
||||
|
||||
if (arr.empty())
|
||||
value = static_cast<decltype(value)>(block_w);
|
||||
else
|
||||
value = static_cast<decltype(value)>(arr.get_value(static_cast<int>(area.width)));
|
||||
|
||||
unsigned width = (value > uns_block_w ? uns_block_w : value);
|
||||
if (width > gap_size) width -= gap_size;
|
||||
API::move_window(i->handle, rectangle{ static_cast<int>(x), static_cast<int>(y), width, height });
|
||||
x += block_w;
|
||||
}
|
||||
y += block_h;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const double block_w = int(area.width - gap_size * (dimension.first - 1)) / double(dimension.first);
|
||||
const double block_h = int(area.height - gap_size * (dimension.second - 1)) / double(dimension.second);
|
||||
|
||||
std::unique_ptr<char[]> table_ptr{ new char[dimension.first * dimension.second] };
|
||||
char *table = table_ptr.get();
|
||||
std::memset(table, 0, dimension.first * dimension.second);
|
||||
|
||||
std::size_t lbp = 0;
|
||||
|
||||
double precise_h = 0;
|
||||
for (std::size_t u = 0; (u < dimension.second && i != end); ++u)
|
||||
{
|
||||
auto const block_height_px = static_cast<unsigned>(block_h + precise_h);
|
||||
precise_h = (block_h + precise_h) - block_height_px;
|
||||
|
||||
double precise_w = 0;
|
||||
for (std::size_t v = 0; (v < dimension.first && i != end); ++v)
|
||||
{
|
||||
auto const epos = v + lbp;
|
||||
if (table[epos])
|
||||
{
|
||||
precise_w += block_w;
|
||||
precise_w -= static_cast<int>(precise_w);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> room{ 1, 1 };
|
||||
_m_find_collapse(static_cast<int>(v), static_cast<int>(u), room);
|
||||
|
||||
const int pos_x = area.x + static_cast<int>(v * (block_w + gap_size));
|
||||
const int pos_y = area.y + static_cast<int>(u * (block_h + gap_size));
|
||||
|
||||
unsigned result_h;
|
||||
if (room.first <= 1 && room.second <= 1)
|
||||
{
|
||||
precise_w += block_w;
|
||||
result_h = block_height_px;
|
||||
table[epos] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
precise_w += block_w * room.first + (room.first - 1) * gap_size;
|
||||
result_h = static_cast<unsigned>(block_h * room.second + precise_h + (room.second - 1) * gap_size);
|
||||
|
||||
for (unsigned y = 0; y < room.second; ++y)
|
||||
for (unsigned x = 0; x < room.first; ++x)
|
||||
table[epos + x + y * dimension.first] = 1;
|
||||
}
|
||||
|
||||
unsigned result_w = static_cast<unsigned>(precise_w);
|
||||
precise_w -= result_w;
|
||||
|
||||
API::move_window(i->handle, rectangle{ pos_x, pos_y, result_w, result_h });
|
||||
++i;
|
||||
}
|
||||
|
||||
lbp += dimension.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1598,6 +1586,9 @@ namespace nana
|
||||
if ((false == arg.left_button) && (mouse::left_button != arg.button))
|
||||
return;
|
||||
|
||||
auto const leaf_left = _m_leaf(true);
|
||||
auto const leaf_right = _m_leaf(false);
|
||||
|
||||
if (event_code::mouse_down == arg.evt_code)
|
||||
{
|
||||
begin_point_ = splitter_.pos();
|
||||
@ -1605,8 +1596,8 @@ namespace nana
|
||||
auto px_ptr = &nana::rectangle::width;
|
||||
|
||||
//Use field_area of leaf, not margin_area. Otherwise splitter would be at wrong position
|
||||
auto area_left = _m_leaf_left()->field_area;
|
||||
auto area_right = _m_leaf_right()->field_area;
|
||||
auto const area_left = leaf_left->field_area;
|
||||
auto const area_right = leaf_right->field_area;
|
||||
|
||||
if (nana::cursor::size_we != splitter_cursor_)
|
||||
{
|
||||
@ -1635,29 +1626,29 @@ namespace nana
|
||||
if(!grabbed_)
|
||||
return;
|
||||
|
||||
const bool vert = (::nana::cursor::size_we != splitter_cursor_);
|
||||
auto area_px = rectangle_rotator(vert, div_owner->margin_area()).w();
|
||||
int delta = (vert ? splitter_.pos().y - begin_point_.y : splitter_.pos().x - begin_point_.x);
|
||||
auto const vert = (::nana::cursor::size_we != splitter_cursor_);
|
||||
auto const delta = horz_point(vert, splitter_.pos() - begin_point_);
|
||||
|
||||
const auto total_pixels = static_cast<int>(left_pixels_ + right_pixels_);
|
||||
|
||||
auto left_px = std::clamp(static_cast<int>(left_pixels_) + delta, 0, total_pixels);
|
||||
|
||||
auto area_px = rectangle_rotator(vert, div_owner->margin_area()).w();
|
||||
double imd_rate = 100.0 / area_px;
|
||||
left_px = static_cast<int>(limit_px(_m_leaf_left(), left_px, area_px));
|
||||
_m_leaf_left()->weight.assign_percent(imd_rate * left_px);
|
||||
left_px = static_cast<int>(limit_px(leaf_left, left_px, area_px));
|
||||
leaf_left->weight.assign_percent(imd_rate * left_px);
|
||||
|
||||
auto right_px = std::clamp(static_cast<int>(right_pixels_) - delta, 0, total_pixels);
|
||||
|
||||
right_px = static_cast<int>(limit_px(_m_leaf_right(), right_px, area_px));
|
||||
_m_leaf_right()->weight.assign_percent(imd_rate * right_px);
|
||||
right_px = static_cast<int>(limit_px(leaf_right, right_px, area_px));
|
||||
leaf_right->weight.assign_percent(imd_rate * right_px);
|
||||
|
||||
pause_move_collocate_ = true;
|
||||
div_owner->collocate(splitter_.parent());
|
||||
|
||||
//After the collocating, the splitter keeps the calculated weight of left division,
|
||||
//and clear the weight of right division.
|
||||
_m_leaf_right()->weight.reset();
|
||||
leaf_right->weight.reset();
|
||||
|
||||
pause_move_collocate_ = false;
|
||||
}
|
||||
@ -1675,8 +1666,8 @@ namespace nana
|
||||
{
|
||||
const bool vert = (::nana::cursor::size_we != splitter_cursor_);
|
||||
|
||||
auto leaf_left = _m_leaf_left();
|
||||
auto leaf_right = _m_leaf_right();
|
||||
auto leaf_left = _m_leaf(true);
|
||||
auto leaf_right = _m_leaf(false);
|
||||
rectangle_rotator left(vert, leaf_left->field_area);
|
||||
rectangle_rotator right(vert, leaf_right->field_area);
|
||||
auto area_px = right.right() - left.x();
|
||||
@ -1806,16 +1797,19 @@ namespace nana
|
||||
|
||||
void _m_update_div(std::string& div)
|
||||
{
|
||||
auto const leaf_left = _m_leaf(true);
|
||||
auto const leaf_right = _m_leaf(false);
|
||||
|
||||
std::string name;
|
||||
bool left = true;
|
||||
|
||||
//Search a name recursively from a specified leaf field.
|
||||
//It returns the depth from the leaf div to the div which has a name.
|
||||
auto depth = _m_search_name(_m_leaf_left(), name);
|
||||
auto depth = _m_search_name(leaf_left, name);
|
||||
if (-1 == depth)
|
||||
{
|
||||
left = false;
|
||||
depth = _m_search_name(_m_leaf_right(), name);
|
||||
depth = _m_search_name(leaf_right, name);
|
||||
if (-1 == depth)
|
||||
return;
|
||||
}
|
||||
@ -1839,8 +1833,8 @@ namespace nana
|
||||
|
||||
const bool vert = (::nana::cursor::size_we != splitter_cursor_);
|
||||
|
||||
rectangle_rotator r_left(vert, _m_leaf_left()->field_area);
|
||||
rectangle_rotator r_right(vert, _m_leaf_right()->field_area);
|
||||
rectangle_rotator r_left(vert, leaf_left->field_area);
|
||||
rectangle_rotator r_right(vert, leaf_right->field_area);
|
||||
rectangle_rotator r_owner(vert, this->div_owner->field_area);
|
||||
|
||||
double percent = double((left ? r_left : r_right).w()) / double(r_owner.w());
|
||||
@ -1866,14 +1860,9 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
division * _m_leaf_left() const
|
||||
division * _m_leaf(bool left) const noexcept
|
||||
{
|
||||
return previous();
|
||||
}
|
||||
|
||||
division * _m_leaf_right() const
|
||||
{
|
||||
return div_next;
|
||||
return (left ? previous() : div_next);
|
||||
}
|
||||
|
||||
rectangle_rotator _m_update_splitter_range()
|
||||
@ -1882,8 +1871,8 @@ namespace nana
|
||||
|
||||
rectangle_rotator area(vert, div_owner->margin_area());
|
||||
|
||||
auto leaf_left = _m_leaf_left();
|
||||
auto leaf_right = _m_leaf_right();
|
||||
auto leaf_left = _m_leaf(true);
|
||||
auto leaf_right = _m_leaf(false);
|
||||
|
||||
rectangle_rotator left(vert, leaf_left->field_area);
|
||||
rectangle_rotator right(vert, leaf_right->field_area);
|
||||
@ -1982,7 +1971,7 @@ namespace nana
|
||||
|
||||
void notify_move() override
|
||||
{
|
||||
if (!_m_indicator())
|
||||
if (!_m_hit_test(false)) //hit test on indicator
|
||||
{
|
||||
indicator_.docker.reset();
|
||||
return;
|
||||
@ -2019,7 +2008,7 @@ namespace nana
|
||||
});
|
||||
}
|
||||
|
||||
if (_m_dockable())
|
||||
if (_m_hit_test(true)) //hit test on docker
|
||||
{
|
||||
if (!indicator_.dock_area)
|
||||
{
|
||||
@ -2078,7 +2067,8 @@ namespace nana
|
||||
|
||||
void notify_move_stopped() override
|
||||
{
|
||||
if (_m_dockable() && dockable_field && dockable_field->dockarea)
|
||||
//hit test on docker
|
||||
if (_m_hit_test(true) && dockable_field && dockable_field->dockarea)
|
||||
dockable_field->dockarea->dock();
|
||||
|
||||
indicator_.docker.reset();
|
||||
@ -2101,25 +2091,22 @@ namespace nana
|
||||
API::close_window(window_handle);
|
||||
}
|
||||
private:
|
||||
bool _m_indicator() const
|
||||
bool _m_hit_test(bool try_docker) const
|
||||
{
|
||||
::nana::point pos;
|
||||
API::calc_screen_point(impl_ptr_->window_handle, pos);
|
||||
window handle = nullptr;
|
||||
if (try_docker)
|
||||
{
|
||||
if (!indicator_.docker)
|
||||
return false;
|
||||
|
||||
rectangle r{ pos, API::window_size(impl_ptr_->window_handle) };
|
||||
return r.is_hit(API::cursor_position());
|
||||
}
|
||||
handle = indicator_.docker->handle(); //hit test for docker
|
||||
}
|
||||
else
|
||||
handle = impl_ptr_->window_handle; //hit test for indicator
|
||||
|
||||
bool _m_dockable() const
|
||||
{
|
||||
if (!indicator_.docker)
|
||||
return false;
|
||||
|
||||
::nana::point pos;
|
||||
API::calc_screen_point(indicator_.docker->handle(), pos);
|
||||
|
||||
rectangle r{ pos, API::window_size(indicator_.docker->handle()) };
|
||||
return r.is_hit(API::cursor_position());
|
||||
point pos;
|
||||
API::calc_screen_point(handle, pos);
|
||||
return rectangle{ pos, API::window_size(handle) }.is_hit(API::cursor_position());
|
||||
}
|
||||
public:
|
||||
field_dock * dockable_field{ nullptr };
|
||||
@ -2149,25 +2136,21 @@ namespace nana
|
||||
: panel<true>(wd, true), dir_(dir), dock_dv_(dock_dv), pane_dv_(pane_dv)
|
||||
{
|
||||
this->bgcolor(colors::alice_blue);
|
||||
this->cursor(_m_is_vert(dir_) ? ::nana::cursor::size_ns : ::nana::cursor::size_we);
|
||||
|
||||
this->cursor(is_vert_dir(dir_) ? ::nana::cursor::size_ns : ::nana::cursor::size_we);
|
||||
|
||||
auto grab_fn = [this, wd](const arg_mouse& arg)
|
||||
{
|
||||
auto const is_vert = is_vert_dir(dir_);
|
||||
|
||||
if (event_code::mouse_down == arg.evt_code) //press mouse button
|
||||
{
|
||||
if (arg.button != ::nana::mouse::left_button)
|
||||
return;
|
||||
|
||||
bool is_vert = _m_is_vert(dir_);
|
||||
|
||||
this->set_capture(true);
|
||||
|
||||
auto basepos = API::cursor_position();
|
||||
base_pos_.x = (is_vert ? basepos.y : basepos.x);
|
||||
|
||||
basepos = this->pos();
|
||||
base_pos_.y = (is_vert ? basepos.y : basepos.x);
|
||||
base_pos_.x = horz_point(is_vert, API::cursor_position());
|
||||
base_pos_.y = horz_point(is_vert, this->pos());
|
||||
|
||||
base_px_ = (is_vert ? pane_dv_->field_area.height : pane_dv_->field_area.width);
|
||||
}
|
||||
@ -2176,8 +2159,7 @@ namespace nana
|
||||
if (!arg.is_left_button())
|
||||
return;
|
||||
|
||||
auto now_pos = API::cursor_position();
|
||||
int delta = (_m_is_vert(dir_) ? now_pos.y : now_pos.x) - base_pos_.x;
|
||||
auto delta = horz_point(is_vert, API::cursor_position()) - base_pos_.x;
|
||||
int new_pos = base_pos_.y + delta;
|
||||
if (new_pos < range_.x)
|
||||
{
|
||||
@ -2190,8 +2172,8 @@ namespace nana
|
||||
delta = new_pos - base_pos_.y;
|
||||
}
|
||||
|
||||
now_pos = this->pos();
|
||||
if (_m_is_vert(dir_))
|
||||
auto now_pos = this->pos();
|
||||
if (is_vert)
|
||||
now_pos.y = new_pos;
|
||||
else
|
||||
now_pos.x = new_pos;
|
||||
@ -2218,7 +2200,7 @@ namespace nana
|
||||
break;
|
||||
}
|
||||
|
||||
auto dock_px = (_m_is_vert(dir_) ? dock_dv_->field_area.height : dock_dv_->field_area.width);
|
||||
auto dock_px = (is_vert ? dock_dv_->field_area.height : dock_dv_->field_area.width);
|
||||
|
||||
pane_dv_->weight.assign_percent(double(px) / double(dock_px) * 100);
|
||||
|
||||
@ -2278,7 +2260,7 @@ namespace nana
|
||||
if (!child->display)
|
||||
continue;
|
||||
|
||||
const auto is_vert = _m_is_vert(child->dir);
|
||||
const auto is_vert = is_vert_dir(child->dir);
|
||||
if (is_first)
|
||||
{
|
||||
is_first = false;
|
||||
@ -2318,7 +2300,7 @@ namespace nana
|
||||
}
|
||||
|
||||
auto child_dv = dynamic_cast<div_dockpane*>(child.get());
|
||||
const bool is_vert = _m_is_vert(child->dir);
|
||||
const bool is_vert = is_vert_dir(child->dir);
|
||||
|
||||
auto room_px = (is_vert ? room.height : room.width);
|
||||
|
||||
@ -2429,11 +2411,6 @@ namespace nana
|
||||
}
|
||||
}
|
||||
private:
|
||||
static bool _m_is_vert(::nana::direction dir)
|
||||
{
|
||||
return (dir == ::nana::direction::north || dir == ::nana::direction::south);
|
||||
}
|
||||
|
||||
static div_dockpane* _m_right(division* dv)
|
||||
{
|
||||
dv = dv->div_next;
|
||||
@ -2521,7 +2498,6 @@ namespace nana
|
||||
static int get_parameter(place_parts::tokenizer& tknizer, std::size_t pos)
|
||||
{
|
||||
auto & arg = tknizer.parameters()[pos];
|
||||
//auto & arg = params[pos];
|
||||
|
||||
if (arg.kind_of() == number_t::kind::integer)
|
||||
return arg.integer();
|
||||
@ -2538,7 +2514,7 @@ namespace nana
|
||||
|
||||
std::unique_ptr<division> div;
|
||||
token div_type = token::eof;
|
||||
bool fit_content = false;
|
||||
auto fit = fit_policy::none;
|
||||
|
||||
//These variables stand for the new division's attributes
|
||||
std::string name;
|
||||
@ -2559,12 +2535,15 @@ namespace nana
|
||||
{
|
||||
case token::dock:
|
||||
if (token::eof != div_type && token::dock != div_type)
|
||||
throw std::invalid_argument("nana.place: conflict of div type at " + tknizer.pos_str());
|
||||
throw std::invalid_argument("nana.place: conflict of div type at " + std::to_string(tknizer.pos()));
|
||||
|
||||
div_type = token::dock;
|
||||
break;
|
||||
case token::fit:
|
||||
fit_content = true;
|
||||
fit = fit_policy::both;
|
||||
break;
|
||||
case token::fit_s:
|
||||
fit = fit_policy::single;
|
||||
break;
|
||||
case token::splitter:
|
||||
//Ignore the splitter when there is not a division.
|
||||
@ -2666,7 +2645,7 @@ namespace nana
|
||||
switch (tknizer.read())
|
||||
{
|
||||
case token::number:
|
||||
margin.set_value(tknizer.number());
|
||||
margin.push(tknizer.number(), true);
|
||||
break;
|
||||
case token::array:
|
||||
margin.set_array(tknizer.array());
|
||||
@ -2829,7 +2808,7 @@ namespace nana
|
||||
|
||||
div->display = !undisplayed;
|
||||
div->visible = !(undisplayed || invisible);
|
||||
div->fit_content = fit_content;
|
||||
div->fit = fit;
|
||||
return div;
|
||||
}
|
||||
|
||||
@ -2891,20 +2870,20 @@ namespace nana
|
||||
if (i != docks.end())
|
||||
{
|
||||
docks_to_be_closed.erase(div->name);
|
||||
auto pane = dynamic_cast<div_dockpane*>(div);
|
||||
pane->dockable_field = i->second;
|
||||
|
||||
auto old_pane = pane->dockable_field->attached;
|
||||
if (old_pane)
|
||||
auto const pane = dynamic_cast<div_dockpane*>(div);
|
||||
auto fd_dock = pane->dockable_field;
|
||||
fd_dock = i->second;
|
||||
|
||||
if (fd_dock->attached)
|
||||
{
|
||||
//old div_dockpane will be deleted
|
||||
old_pane->dockable_field = nullptr;
|
||||
div->display = old_pane->display;
|
||||
fd_dock->attached->dockable_field = nullptr;
|
||||
div->display = fd_dock->attached->display;
|
||||
}
|
||||
pane->dockable_field->attached = pane;
|
||||
|
||||
if (pane->dockable_field->dockarea)
|
||||
pane->dockable_field->dockarea->set_notifier(pane);
|
||||
fd_dock->attached = pane;
|
||||
if (fd_dock->dockarea)
|
||||
fd_dock->dockarea->set_notifier(pane);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -3035,7 +3014,6 @@ namespace nana
|
||||
throw std::invalid_argument(what);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<implement::division>* replaced = nullptr;
|
||||
|
||||
implement::division * div_owner = div_ptr->div_owner;
|
||||
|
@ -29,21 +29,16 @@ namespace nana
|
||||
virtual ~splitter_interface(){}
|
||||
};
|
||||
|
||||
class splitter_dtrigger
|
||||
: public drawer_trigger
|
||||
{
|
||||
};
|
||||
|
||||
template<bool IsLite>
|
||||
class splitter
|
||||
: public widget_object <typename std::conditional<IsLite, category::lite_widget_tag, category::widget_tag>::type, splitter_dtrigger>,
|
||||
: public widget_object <typename std::conditional<IsLite, category::lite_widget_tag, category::widget_tag>::type, drawer_trigger>,
|
||||
public splitter_interface
|
||||
{
|
||||
private:
|
||||
void _m_complete_creation() override
|
||||
{
|
||||
this->caption("place-splitter");
|
||||
widget_object <typename std::conditional<IsLite, category::lite_widget_tag, category::widget_tag>::type, splitter_dtrigger>::_m_complete_creation();
|
||||
widget_object <typename std::conditional<IsLite, category::lite_widget_tag, category::widget_tag>::type, drawer_trigger>::_m_complete_creation();
|
||||
}
|
||||
};
|
||||
|
||||
@ -92,7 +87,7 @@ namespace nana
|
||||
{
|
||||
color xclr = colors::red;
|
||||
|
||||
if(x_state_ == ::nana::mouse_action::pressed)
|
||||
if(x_state_ == ::nana::mouse_action::pressed)
|
||||
xclr = xclr.blend(colors::white, 0.8);
|
||||
|
||||
graph.rectangle(r, true, xclr);
|
||||
@ -144,11 +139,8 @@ namespace nana
|
||||
private:
|
||||
::nana::rectangle _m_button_area() const
|
||||
{
|
||||
::nana::rectangle r{API::window_size(window_handle_)};
|
||||
|
||||
r.x = r.right() - 20;
|
||||
r.width = 20;
|
||||
return r;
|
||||
auto sz = API::window_size(window_handle_);
|
||||
return{static_cast<int>(sz.width) - 20, 0, 20, sz.height};
|
||||
}
|
||||
public:
|
||||
window window_handle_;
|
||||
@ -161,12 +153,17 @@ namespace nana
|
||||
};
|
||||
|
||||
class dockarea_caption
|
||||
: public widget_object < category::widget_tag, dockcaption_dtrigger >
|
||||
: public widget_object<category::widget_tag, dockcaption_dtrigger>
|
||||
{
|
||||
public:
|
||||
using widget_object<category::widget_tag, dockcaption_dtrigger>::get_drawer_trigger;
|
||||
};
|
||||
|
||||
static unsigned differ(unsigned x, unsigned y) noexcept
|
||||
{
|
||||
return (x > y ? x - y : 0);
|
||||
}
|
||||
|
||||
class dockarea
|
||||
: public widget_object <category::lite_widget_tag, drawer_trigger>
|
||||
{
|
||||
@ -183,6 +180,7 @@ namespace nana
|
||||
{
|
||||
notifier_ = notifier;
|
||||
}
|
||||
|
||||
void create(window parent)
|
||||
{
|
||||
host_window_ = parent;
|
||||
@ -191,17 +189,14 @@ namespace nana
|
||||
caption_.create(*this, true);
|
||||
caption_.get_drawer_trigger().on_close([this]
|
||||
{
|
||||
bool destroy_dockarea = true;
|
||||
|
||||
if (tabbar_)
|
||||
{
|
||||
tabbar_->erase(tabbar_->selected());
|
||||
|
||||
destroy_dockarea = (0 == tabbar_->length());
|
||||
if (tabbar_->length())
|
||||
return;
|
||||
}
|
||||
|
||||
if (destroy_dockarea)
|
||||
notifier_->request_close();
|
||||
notifier_->request_close();
|
||||
});
|
||||
|
||||
this->events().resized.connect([this](const arg_resized& arg)
|
||||
@ -331,14 +326,11 @@ namespace nana
|
||||
private:
|
||||
widget* _m_add_pane(factory & fn)
|
||||
{
|
||||
rectangle r{ point(), this->size() };
|
||||
rectangle r{ this->size() };
|
||||
|
||||
//get a rectangle excluding caption
|
||||
r.y = 20;
|
||||
if (r.height > 20)
|
||||
r.height -= 20;
|
||||
else
|
||||
r.height = 0;
|
||||
r.height = differ(r.height, 20);
|
||||
|
||||
if (!tabbar_)
|
||||
{
|
||||
@ -434,17 +426,8 @@ namespace nana
|
||||
|
||||
bool is_negative() const
|
||||
{
|
||||
switch (kind_)
|
||||
{
|
||||
case kind::integer:
|
||||
return (value_.integer < 0);
|
||||
case kind::real:
|
||||
case kind::percent:
|
||||
return (value_.real < 0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
return (((kind::integer == kind_) && (value_.integer < 0)) ||
|
||||
((kind::real == kind_ || kind::percent == kind_) && (value_.real < 0)));
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
@ -532,15 +515,12 @@ namespace nana
|
||||
all_edges_ = true;
|
||||
margins_.clear();
|
||||
}
|
||||
|
||||
void push(const number_t& v)
|
||||
|
||||
void push(const number_t& v, bool reset = false)
|
||||
{
|
||||
margins_.emplace_back(v);
|
||||
}
|
||||
if (reset)
|
||||
clear();
|
||||
|
||||
void set_value(const number_t& v)
|
||||
{
|
||||
clear();
|
||||
margins_.emplace_back(v);
|
||||
}
|
||||
|
||||
@ -559,12 +539,11 @@ namespace nana
|
||||
if (all_edges_)
|
||||
{
|
||||
auto px = static_cast<int>(margins_.back().get_value(static_cast<int>(r.width)));
|
||||
const auto dbl_px = static_cast<unsigned>(px << 1);
|
||||
r.x += px;
|
||||
r.width = (r.width < dbl_px ? 0 : r.width - dbl_px);
|
||||
r.width = differ(r.width, (static_cast<unsigned>(px) << 1));
|
||||
|
||||
r.y += px;
|
||||
r.height = (r.height < dbl_px ? 0 : r.height - dbl_px);
|
||||
r.height = differ(r.height, (static_cast<unsigned>(px) << 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -587,49 +566,44 @@ namespace nana
|
||||
ib = 2;
|
||||
}
|
||||
|
||||
typedef decltype(r.height) px_type;
|
||||
auto calc = [](px_type a, px_type b)
|
||||
{
|
||||
return (a > b ? a - b : 0);
|
||||
};
|
||||
using px_type = decltype(r.height);
|
||||
|
||||
if (0 == it) //top
|
||||
{
|
||||
auto px = static_cast<int>(margins_[it].get_value(static_cast<int>(field_area.height)));
|
||||
r.y += px;
|
||||
r.height = calc(r.height, static_cast<px_type>(px));
|
||||
r.height = differ(r.height, static_cast<px_type>(px));
|
||||
}
|
||||
|
||||
if (-1 != ib) //bottom
|
||||
{
|
||||
auto px = static_cast<int>(margins_[ib].get_value(static_cast<int>(field_area.height)));
|
||||
r.height = calc(r.height, static_cast<px_type>(px));
|
||||
r.height = differ(r.height, static_cast<px_type>(px));
|
||||
}
|
||||
|
||||
if (-1 != il) //left
|
||||
{
|
||||
auto px = static_cast<px_type>(margins_[il].get_value(static_cast<int>(field_area.width)));
|
||||
r.x += px;
|
||||
r.width = calc(r.width, static_cast<px_type>(px));
|
||||
r.width = differ(r.width, static_cast<px_type>(px));
|
||||
}
|
||||
|
||||
if (-1 != ir) //right
|
||||
{
|
||||
auto px = static_cast<int>(margins_[ir].get_value(static_cast<int>(field_area.width)));
|
||||
r.width = calc(r.width, static_cast<px_type>(px));
|
||||
r.width = differ(r.width, static_cast<px_type>(px));
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
private:
|
||||
bool all_edges_ = true;
|
||||
bool all_edges_{ true };
|
||||
std::vector<number_t> margins_;
|
||||
};//end class margin
|
||||
|
||||
class repeated_array
|
||||
{
|
||||
public:
|
||||
|
||||
//A workaround for VC2013, becuase it does not generated an implicit declared move-constructor as defaulted.
|
||||
repeated_array() = default;
|
||||
|
||||
@ -678,15 +652,10 @@ namespace nana
|
||||
|
||||
number_t at(std::size_t pos) const
|
||||
{
|
||||
if (values_.empty())
|
||||
return{};
|
||||
if (values_.size() && (repeated_ || pos < values_.size()))
|
||||
return values_[pos % values_.size()];
|
||||
|
||||
if (repeated_)
|
||||
pos %= values_.size();
|
||||
else if (pos >= values_.size())
|
||||
return{};
|
||||
|
||||
return values_[pos];
|
||||
return{};
|
||||
}
|
||||
private:
|
||||
bool repeated_ = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user