[widget] propagate new TimeVal on horizontal drag

This commit is contained in:
thibaud keller 2025-01-22 23:14:58 +00:00
parent 590815e7dc
commit 9a2ce69dee
10 changed files with 198 additions and 72 deletions

View file

@ -54,6 +54,20 @@ void EventWidget::set_span_recursive()
static_cast<StateWidget*>(s.get())->set_y();
}
void EventWidget::time_propagate(const TimeVal& t)
{
model.setDate(t);
// FIXME : call scneario->time_propagate with StateModel
// is tehre a beter way to find connected intervals ?
for (auto& s : bugui::container_widget::children)
{
scenario->time_propagate(
static_cast<StateWidget*>(s.get())->get_model(),
t);
}
}
void EventWidget::paint(bugui::painter& painter) const
{
if (!press && m_height == 0) return;

View file

@ -20,6 +20,7 @@ struct EventWidget final : ScenarioComponentSpec<
void set_y();
void set_span_recursive();
void time_propagate(const TimeVal& t);
private:
void on_state_added(Scenario::StateModel& state);

View file

@ -1,7 +1,9 @@
#include <widgets/container_widget.hpp>
#include <Scenario/Document/Interval/IntervalDurations.hpp>
#include "IntervalWidget.hpp"
#include "Hardware/Widgets/ScenarioWidget.hpp"
#include "ScenarioWidget.hpp"
namespace Hardware
{
@ -38,6 +40,19 @@ void IntervalWidget::change_next(const Scenario::StateModel& state)
scenario->change_next(model);
}
void IntervalWidget::time_propagate(const TimeVal& t)
{
model.translate(t - model.date());
scenario->time_propagate(model,
model.date() + model.duration.defaultDuration());
}
void IntervalWidget::set_duration(const TimeVal& t)
{
Scenario::IntervalDurations::Algorithms::changeAllDurations(
model, t - model.date());
}
bool IntervalWidget::contains(int px, int py) const
{
// ignore first and last cell

View file

@ -19,6 +19,8 @@ struct IntervalWidget final : ScenarioComponentSpec<Scenario::IntervalModel>
void change_previous(const Scenario::StateModel& state);
void change_next(const Scenario::StateModel& state);
void time_propagate(const TimeVal& t);
void set_duration(const TimeVal& t);
private:
bool contains(int px, int py) const override;

View file

@ -65,14 +65,81 @@ void ScenarioWidget::on_time_sync_removed(const Scenario::TimeSyncModel& timeSyn
void ScenarioWidget::recursive_change(const Scenario::StateModel& state)
{
change_next(state);
change_previous(state);
change_next(state);
}
void ScenarioWidget::recursive_change(const Scenario::IntervalModel& interval)
{
change_next(interval);
change_previous(interval);
change_next(interval);
}
void ScenarioWidget::time_propagate(const Scenario::StateModel& state, const TimeVal& t)
{
auto interval{state.previousInterval()};
if (interval.has_value())
{
auto& v{interval.value()};
for (const auto& c : children)
{
ScenarioComponent<>* s{static_cast<ScenarioComponent<>*>(c.get())};
if (s->this_model(v))
{
static_cast<IntervalWidget*>(s)->set_duration(t);
break;
}
}
}
interval = state.nextInterval();
if (interval.has_value())
{
auto& v{interval.value()};
for (const auto& c : children)
{
ScenarioComponent<>* s{static_cast<ScenarioComponent<>*>(c.get())};
if (s->this_model(v))
{
static_cast<IntervalWidget*>(s)->time_propagate(t);
break;
}
}
}
}
void ScenarioWidget::time_propagate(const Scenario::IntervalModel& interval, const TimeVal& t)
{
auto& es{interval.endState()};
for (const auto& s : states_proxy)
{
if (s->this_model(es))
{
s->time_propagate(t);
break;
}
}
}
void ScenarioWidget::change_previous(const Scenario::IntervalModel& interval)
{
auto& es{interval.startState()};
for (const auto& s : states_proxy)
{
if (s->this_model(es))
{
s->change_previous(interval);
break;
}
}
}
void ScenarioWidget::change_next(const Scenario::IntervalModel& interval)
@ -89,6 +156,27 @@ void ScenarioWidget::change_next(const Scenario::IntervalModel& interval)
}
}
void ScenarioWidget::change_previous(const Scenario::StateModel& state)
{
auto& pi{state.previousInterval()};
if (pi)
{
auto& v{pi.value()};
for (const auto& c : children)
{
ScenarioComponent<>* s{static_cast<ScenarioComponent<>*>(c.get())};
if (s->this_model(v))
{
static_cast<IntervalWidget*>(s)->change_previous(state);
break;
}
}
}
}
void ScenarioWidget::change_next(const Scenario::StateModel& state)
{
auto& ni{state.nextInterval()};
@ -110,39 +198,4 @@ void ScenarioWidget::change_next(const Scenario::StateModel& state)
}
}
void ScenarioWidget::change_previous(const Scenario::IntervalModel& interval)
{
auto& es{interval.startState()};
for (const auto& s : states_proxy)
{
if (s->this_model(es))
{
s->change_previous(interval);
break;
}
}
}
void ScenarioWidget::change_previous(const Scenario::StateModel& state)
{
auto& ni{state.previousInterval()};
if (ni)
{
auto& v{ni.value()};
for (const auto& c : children)
{
ScenarioComponent<>* s{static_cast<ScenarioComponent<>*>(c.get())};
if (s->this_model(v))
{
static_cast<IntervalWidget*>(s)->change_previous(state);
break;
}
}
}
}
} // namespace Hardware

View file

@ -32,10 +32,13 @@ public:
void recursive_change(const Scenario::IntervalModel& interval);
void change_previous(const Scenario::IntervalModel& interval);
void change_previous(const Scenario::StateModel& state);
void change_next(const Scenario::IntervalModel& interval);
void change_previous(const Scenario::StateModel& state);
void change_next(const Scenario::StateModel& state);
void time_propagate(const Scenario::StateModel& state, const TimeVal& t);
void time_propagate(const Scenario::IntervalModel& interval, const TimeVal& t);
bool changing{false};
private:

View file

@ -1,6 +1,7 @@
#include <Scenario/Document/State/StateModel.hpp>
#include "ScenarioWidget.hpp"
#include "TimeSyncWidget.hpp"
#include "EventWidget.hpp"
#include "StateWidget.hpp"
@ -34,6 +35,24 @@ StateWidget::~StateWidget()
scenario->remove_proxy(this);
}
void StateWidget::set_absolute_y()
{
m_absolute_y = model.heightPercentage() * scenario->height();
}
void StateWidget::set_y()
{
m_y = m_absolute_y -
bugui::base_widget::parent->y() -
bugui::base_widget::parent->get_parent()->y();
}
void StateWidget::set_span_recursive()
{
static_cast<EventWidget*>(bugui::base_widget::parent)
->set_span_recursive();
}
void StateWidget::change_previous(const Scenario::IntervalModel& interval)
{
model.setHeightPercentage(interval.heightPercentage());
@ -49,6 +68,13 @@ void StateWidget::change_next(const Scenario::IntervalModel& interval)
scenario->change_next(model);
}
void StateWidget::time_propagate(const TimeVal& t)
{
static_cast<TimeSyncWidget*>(
bugui::base_widget::parent->get_parent())
->time_propagate(t);
}
void StateWidget::paint(bugui::painter& painter) const
{
const auto col{model.metadata().getColor().getBrush().color()};
@ -79,38 +105,40 @@ void StateWidget::on_double_press(int x, int y)
void StateWidget::on_drag(int from_x, int from_y, int to_x, int to_y)
{
double new_height{model.heightPercentage() +
to_y / static_cast<double>(scenario->height())};
bool update{false};
// prevent dragging out of scenario
if (new_height >= 0 && new_height <= 1)
// handle vertical drag
if (from_y != to_y)
{
double new_height{model.heightPercentage() +
to_y / static_cast<double>(scenario->height())};
// prevent dragging out of scenario
if (new_height >= 0 && new_height <= 1)
{
scenario->changing = true;
model.setHeightPercentage(new_height);
scenario->recursive_change(model);
set_absolute_y();
set_span_recursive();
scenario->changing = false;
update = true;
}
}
if (from_x != to_x)
{
scenario->changing = true;
model.setHeightPercentage(new_height);
scenario->recursive_change(model);
set_absolute_y();
set_span_recursive();
scenario->update();
TimeSyncWidget* sync{static_cast<TimeSyncWidget*>(
bugui::base_widget::parent->get_parent())};
auto d{sync->get_model().date()};
d.setMSecs(d.msec() + to_x * 1000);
sync->time_propagate(d);
scenario->changing = false;
update = true;
}
}
void StateWidget::set_absolute_y()
{
m_absolute_y = model.heightPercentage() * scenario->height();
}
void StateWidget::set_y()
{
m_y = m_absolute_y -
bugui::base_widget::parent->y() -
bugui::base_widget::parent->get_parent()->y();
}
void StateWidget::set_span_recursive()
{
static_cast<EventWidget*>(bugui::base_widget::parent)
->set_span_recursive();
if (update) scenario->update();
}
} // namespace Hardware

View file

@ -19,6 +19,7 @@ struct StateWidget final : ScenarioComponentSpec<Scenario::StateModel>
void set_y();
void change_previous(const Scenario::IntervalModel& interval);
void change_next(const Scenario::IntervalModel& interval);
void time_propagate(const TimeVal& t);
private:
W_OBJECT(StateWidget)
@ -36,6 +37,7 @@ private:
void on_drag(int from_x, int from_y, int to_x, int to_y) override;
void set_absolute_y();
int m_absolute_y;
int m_y;
};

View file

@ -24,7 +24,12 @@ TimeSyncWidget::TimeSyncWidget(Scenario::TimeSyncModel& timeSync,
connect(&model,
&Scenario::TimeSyncModel::dateChanged,
this,
[scenario] (const TimeVal&) { scenario->update(); });
[scenario] (const TimeVal&)
{
if (scenario->changing) return;
scenario->update();
});
}
TimeSyncWidget::~TimeSyncWidget()
@ -58,6 +63,14 @@ void TimeSyncWidget::set_span()
static_cast<EventWidget*>(e.get())->set_y();
}
void TimeSyncWidget::time_propagate(const TimeVal& t)
{
model.setDate(t);
for (auto& s : bugui::container_widget::children)
static_cast<EventWidget*>(s.get())->time_propagate(t);
}
void TimeSyncWidget::on_state_added(Scenario::EventModel& event)
{
if (event.timeSync() != model.id()) return;
@ -98,11 +111,6 @@ bool TimeSyncWidget::contains(int px, int py) const
return false;
}
void TimeSyncWidget::on_press(int x, int y, bool pressed)
{
press = pressed;
}
} // namespace Hardware
#include <wobjectimpl.h>

View file

@ -23,6 +23,7 @@ struct TimeSyncWidget final : ScenarioComponentSpec<
int height() const override { return m_height; }
void set_span();
void time_propagate(const TimeVal& t);
private:
W_OBJECT(TimeSyncWidget)
@ -33,7 +34,6 @@ private:
bool contains(int px, int py) const override;
void paint(bugui::painter& painter) const override;
void on_press(int x, int y, bool pressed) override;
bool press{false};