Huge ui::scroller changes: support asymmetric shaping, remove sticking feature
This commit is contained in:
parent
c928b88062
commit
874d4bd5c8
3 changed files with 104 additions and 35 deletions
|
|
@ -32,6 +32,11 @@ namespace psemek::ui
|
|||
void reshape(geom::box<float, 2> const & bbox) override;
|
||||
|
||||
geom::box<float, 2> size_constraints() const override;
|
||||
geom::interval<float> width_constraints(float height) const override;
|
||||
geom::interval<float> height_constraints(float width) const override;
|
||||
|
||||
virtual float position(direction dir) const;
|
||||
virtual void set_position(direction dir, float position, bool animate);
|
||||
|
||||
void update(float dt) override;
|
||||
|
||||
|
|
@ -67,9 +72,6 @@ namespace psemek::ui
|
|||
bool horizontal_ = false;
|
||||
bool vertical_ = true;
|
||||
|
||||
bool horizontal_stick_ = false;
|
||||
bool vertical_stick_ = false;
|
||||
|
||||
geom::vector<float, 2> shift_{0.f, 0.f};
|
||||
geom::vector<float, 2> shift_tgt_{0.f, 0.f};
|
||||
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ namespace psemek::ui
|
|||
contents_str += entry.path.filename().string() + "[/link]\n";
|
||||
}
|
||||
directory_view->set_tagged_text(std::move(contents_str));
|
||||
directory_view_scroller->set_position(scroller::direction::vertical, 0.f, false);
|
||||
|
||||
directory_view->on_link_click([=, entries = std::move(entries)](std::string_view const & value){
|
||||
int index = util::from_string<int>(std::string{value});
|
||||
|
|
|
|||
|
|
@ -213,31 +213,22 @@ namespace psemek::ui
|
|||
if (vertical_scroll())
|
||||
child_bbox[0].max -= width() * *st->scale;
|
||||
|
||||
if (horizontal_scroll())
|
||||
if (width_first())
|
||||
{
|
||||
horizontal_stick_ |= child_bbox[0].length() > child_constraints[0].min;
|
||||
|
||||
if (horizontal_stick_)
|
||||
{
|
||||
shift_tgt_[0] = std::min(child_bbox[0].length() - child_constraints[0].min, 0.f);
|
||||
shift_[0] = shift_tgt_[0];
|
||||
}
|
||||
child_bbox[0].min += shift_[0];
|
||||
child_constraints[1] = child_->height_constraints(child_bbox[0].length());
|
||||
child_bbox[1].max = child_bbox[1].min + child_constraints[1].min;
|
||||
}
|
||||
else
|
||||
{
|
||||
child_constraints[0] = child_->width_constraints(child_bbox[1].length());
|
||||
child_bbox[0].max = child_bbox[0].min + child_constraints[0].min;
|
||||
}
|
||||
|
||||
if (vertical_scroll())
|
||||
{
|
||||
vertical_stick_ |= child_bbox[1].length() > child_constraints[1].min;
|
||||
if (horizontal_scroll())
|
||||
child_bbox[0] += shift_[0];
|
||||
|
||||
if (vertical_stick_)
|
||||
{
|
||||
shift_tgt_[1] = std::min(child_bbox[1].length() - child_constraints[1].min, 0.f);
|
||||
shift_[1] = shift_tgt_[1];
|
||||
}
|
||||
child_bbox[1].min += shift_[1];
|
||||
child_bbox[1].max = child_bbox[1].min + child_constraints[1].min;
|
||||
}
|
||||
if (vertical_scroll())
|
||||
child_bbox[1] += shift_[1];
|
||||
|
||||
child_->reshape(child_bbox);
|
||||
}
|
||||
|
|
@ -253,14 +244,11 @@ namespace psemek::ui
|
|||
{
|
||||
auto child_constraints = child_->size_constraints();
|
||||
|
||||
result[0].min = child_constraints[0].min;
|
||||
result[1].min = child_constraints[1].min;
|
||||
|
||||
if (!horizontal_scroll())
|
||||
result[0].max = child_constraints[0].max;
|
||||
result[0] = child_constraints[0];
|
||||
|
||||
if (!vertical_scroll())
|
||||
result[1].max = child_constraints[1].max;
|
||||
result[1] = child_constraints[1];
|
||||
}
|
||||
|
||||
auto st = merged_own_style();
|
||||
|
|
@ -273,6 +261,78 @@ namespace psemek::ui
|
|||
return result;
|
||||
}
|
||||
|
||||
geom::interval<float> scroller::width_constraints(float height) const
|
||||
{
|
||||
geom::interval<float> result = {0.f, std::numeric_limits<float>::infinity()};
|
||||
|
||||
auto st = merged_own_style();
|
||||
|
||||
if (child_ && !horizontal_scroll())
|
||||
result = child_->width_constraints(height - width() * *st->scale);
|
||||
|
||||
if (vertical_scroll())
|
||||
result += width() * *st->scale;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
geom::interval<float> scroller::height_constraints(float width) const
|
||||
{
|
||||
geom::interval<float> result = {0.f, std::numeric_limits<float>::infinity()};
|
||||
|
||||
auto st = merged_own_style();
|
||||
|
||||
if (child_ && !horizontal_scroll())
|
||||
result = child_->height_constraints(width - this->width() * *st->scale);
|
||||
|
||||
if (horizontal_scroll())
|
||||
result += this->width() * *st->scale;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float scroller::position(direction dir) const
|
||||
{
|
||||
if (!child_) return 0.f;
|
||||
|
||||
auto child_box = child_->shape().bbox();
|
||||
auto st = merged_own_style();
|
||||
auto child_area = shape_.box.dimensions();
|
||||
|
||||
if (horizontal_scroll())
|
||||
child_area[1] -= width() * *st->scale;
|
||||
if (vertical_scroll())
|
||||
child_area[0] -= width() * *st->scale;
|
||||
|
||||
if (dir == direction::horizontal)
|
||||
return -shift_[0] / (child_box[0].length() - child_area[0]);
|
||||
else
|
||||
return -shift_[1] / (child_box[1].length() - child_area[1]);
|
||||
}
|
||||
|
||||
void scroller::set_position(direction dir, float position, bool animate)
|
||||
{
|
||||
if (dir == direction::horizontal && !horizontal_scroll())
|
||||
return;
|
||||
if (dir == direction::vertical && !vertical_scroll())
|
||||
return;
|
||||
|
||||
int dim = (dir == direction::horizontal) ? 0 : 1;
|
||||
|
||||
auto child_box = child_->shape().bbox();
|
||||
auto st = merged_own_style();
|
||||
auto child_area = shape_.box.dimensions();
|
||||
|
||||
if (horizontal_scroll())
|
||||
child_area[1] -= width() * *st->scale;
|
||||
if (vertical_scroll())
|
||||
child_area[0] -= width() * *st->scale;
|
||||
|
||||
shift_tgt_[dim] = position * (child_area[dim] - child_box[dim].length());
|
||||
if (!animate)
|
||||
shift_[dim] = shift_tgt_[dim];
|
||||
}
|
||||
|
||||
void scroller::update(float dt)
|
||||
{
|
||||
shift_ += (shift_tgt_ - shift_) * std::min(25.f * dt, 1.f);
|
||||
|
|
@ -288,7 +348,7 @@ namespace psemek::ui
|
|||
if (horizontal_scroll())
|
||||
box[1].max -= w;
|
||||
if (vertical_scroll())
|
||||
box[0].max -= w;
|
||||
box[0].max -= w;
|
||||
|
||||
p.begin_stencil();
|
||||
p.draw_rect(box, {0, 0, 0, 255});
|
||||
|
|
@ -353,18 +413,24 @@ namespace psemek::ui
|
|||
if (!child_)
|
||||
return;
|
||||
|
||||
auto c = child_->size_constraints();
|
||||
geom::vector<float, 2> min = child_->shape().bbox().dimensions();
|
||||
|
||||
geom::vector<float, 2> min;
|
||||
min[0] = shape_.box[0].length() - c[0].min;
|
||||
min[1] = shape_.box[1].length() - c[1].min;
|
||||
auto st = merged_own_style();
|
||||
auto child_area = shape_.box.dimensions();
|
||||
|
||||
if (horizontal_scroll())
|
||||
child_area[1] -= width() * *st->scale;
|
||||
if (vertical_scroll())
|
||||
child_area[0] -= width() * *st->scale;
|
||||
|
||||
min[0] = child_area[0] - min[0];
|
||||
min[1] = child_area[1] - min[1];
|
||||
|
||||
// Can't use clamp since the order of min & max matters
|
||||
shift_tgt_[0] = std::max(shift_tgt_[0], min[0]);
|
||||
horizontal_stick_ = (shift_tgt_[0] == min[0]) || (min[0] > 0.f);
|
||||
shift_tgt_[0] = std::min(shift_tgt_[0], 0.f);
|
||||
|
||||
shift_tgt_[1] = std::max(shift_tgt_[1], min[1]);
|
||||
vertical_stick_ = (shift_tgt_[1] == min[1]) || (min[1] > 0.f);
|
||||
shift_tgt_[1] = std::min(shift_tgt_[1], 0.f);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue