for (auto &r : _view)
r->drag_release();
- if (!_dragging)
+ if (_dragging)
+ _view.restack_all_row_items();
+ else
{
if (!ctrl_pressed) {
for (shared_ptr<RowItem> r : _view)
r->select();
}
+ item_owner->restack_items();
+ for (const auto &r : *item_owner)
+ r->animate_to_layout_v_offset();
signals_moved();
update();
RowItem::RowItem() :
_owner(NULL),
_layout_v_offset(0),
- _visual_v_offset(0)
+ _visual_v_offset(0),
+ _v_offset_animation(this, "visual_v_offset")
{
}
void RowItem::force_to_v_offset(int v_offset)
{
+ _v_offset_animation.stop();
_layout_v_offset = _visual_v_offset = v_offset;
}
+void RowItem::animate_to_layout_v_offset()
+{
+ if (_visual_v_offset == _layout_v_offset ||
+ (_v_offset_animation.endValue() == _layout_v_offset &&
+ _v_offset_animation.state() == QAbstractAnimation::Running))
+ return;
+
+ _v_offset_animation.setDuration(100);
+ _v_offset_animation.setStartValue(_visual_v_offset);
+ _v_offset_animation.setEndValue(_layout_v_offset);
+ _v_offset_animation.setEasingCurve(QEasingCurve::OutQuad);
+ _v_offset_animation.start();
+}
+
RowItemOwner* RowItem::owner() const
{
return _owner;
void RowItem::set_owner(RowItemOwner *owner)
{
assert(_owner || owner);
+ _v_offset_animation.stop();
+
+ if (_owner) {
+ const int owner_offset = _owner->owner_visual_v_offset();
+ _layout_v_offset += owner_offset;
+ _visual_v_offset += owner_offset;
+ }
- if (_owner)
- _visual_v_offset += _owner->owner_v_offset();
_owner = owner;
- if (_owner)
- _visual_v_offset -= _owner->owner_v_offset();
+
+ if (_owner) {
+ const int owner_offset = _owner->owner_visual_v_offset();
+ _layout_v_offset -= owner_offset;
+ _visual_v_offset -= owner_offset;
+ }
}
int RowItem::get_visual_y() const
{
assert(_owner);
- return _visual_v_offset + _owner->owner_v_offset();
+ return _visual_v_offset + _owner->owner_visual_v_offset();
}
QPoint RowItem::point() const
#include <memory>
+#include <QPropertyAnimation>
+
#include "selectableitem.h"
namespace pv {
public std::enable_shared_from_this<pv::view::RowItem>
{
Q_OBJECT
+ Q_PROPERTY(int visual_v_offset
+ READ visual_v_offset
+ WRITE set_visual_v_offset)
public:
/**
*/
void force_to_v_offset(int v_offset);
+ /**
+ * Begins an animation that will animate the visual offset toward
+ * the layout offset.
+ */
+ void animate_to_layout_v_offset();
+
/**
* Gets the owner this trace in the view trace hierachy.
*/
int _layout_v_offset;
int _visual_v_offset;
+
+private:
+ QPropertyAnimation _v_offset_animation;
};
} // namespace view
return extents;
}
+void RowItemOwner::restack_items()
+{
+}
+
} // view
} // pv
*/
virtual const pv::view::View* view() const = 0;
- virtual int owner_v_offset() const = 0;
+ virtual int owner_visual_v_offset() const = 0;
/**
* Returns the number of nested parents that this row item owner has.
*/
std::pair<int, int> v_extents() const;
+ virtual void restack_items();
+
public:
virtual void appearance_changed(bool label, bool content) = 0;
{
QRectF rect;
for (const shared_ptr<RowItem> r : child_items())
- if (r)
+ if (r && r->enabled())
rect = rect.united(r->label_rect(right));
return QRectF(rect.x() - Width - Padding, rect.y(),
return NULL;
}
-int TraceGroup::owner_v_offset() const
+int TraceGroup::owner_visual_v_offset() const
{
- return _owner ? layout_v_offset() + _owner->owner_v_offset() : 0;
+ return _owner ? visual_v_offset() + _owner->owner_visual_v_offset() : 0;
+}
+
+void TraceGroup::restack_items()
+{
+ vector< shared_ptr<RowItem> > items(
+ child_items().begin(), child_items().end());
+
+ // Sort by the centre line of the extents
+ stable_sort(items.begin(), items.end(),
+ [](const shared_ptr<RowItem> &a, const shared_ptr<RowItem> &b) {
+ const auto aext = a->v_extents();
+ const auto bext = b->v_extents();
+ return a->layout_v_offset() +
+ (aext.first + aext.second) / 2 <
+ b->layout_v_offset() +
+ (bext.first + bext.second) / 2;
+ });
+
+ int total_offset = 0;
+ for (shared_ptr<RowItem> r : items) {
+ const pair<int, int> extents = r->v_extents();
+ if (extents.first == 0 && extents.second == 0)
+ continue;
+
+ // We position disabled traces, so that they are close to the
+ // animation target positon should they be re-enabled
+ if (r->enabled())
+ total_offset += -extents.first;
+
+ if (!r->dragging())
+ r->set_layout_v_offset(total_offset);
+
+ if (r->enabled())
+ total_offset += extents.second;
+ }
}
unsigned int TraceGroup::depth() const
/**
* Returns the total vertical offset of this trace and all it's owners
*/
- int owner_v_offset() const;
+ int owner_visual_v_offset() const;
+
+ void restack_items();
/**
* Returns the number of nested parents that this row item owner has.
#include <climits>
#include <cmath>
#include <mutex>
+#include <unordered_set>
#include <QEvent>
#include <QMouseEvent>
using std::pair;
using std::set;
using std::shared_ptr;
+using std::unordered_set;
using std::vector;
using std::weak_ptr;
return _offset;
}
-int View::owner_v_offset() const
+int View::owner_visual_v_offset() const
{
return -_v_offset;
}
{
assert(_viewport);
_viewport->update();
+ _header->update();
+}
+
+void View::restack_all_row_items()
+{
+ // Make a set of owners
+ unordered_set< RowItemOwner* > owners;
+ for (const auto &r : *this)
+ owners.insert(r->owner());
+
+ // Make a list that is sorted from deepest first
+ vector< RowItemOwner* > sorted_owners(owners.begin(), owners.end());
+ sort(sorted_owners.begin(), sorted_owners.end(),
+ [](const RowItemOwner* a, const RowItemOwner *b) {
+ return a->depth() > b->depth(); });
+
+ // Restack the items recursively
+ for (auto &o : sorted_owners)
+ o->restack_items();
+
+ // Animate the items to their destination
+ for (const auto &r : *this)
+ r->animate_to_layout_v_offset();
}
void View::get_scroll_layout(double &length, double &offset) const
{
if (_sticky_events & SelectableItemHExtentsChanged)
update_layout();
- if (_sticky_events & SelectableItemVExtentsChanged) {
- _viewport->update();
- _header->update();
- }
+ if (_sticky_events & SelectableItemVExtentsChanged)
+ restack_all_row_items();
// Clear the sticky events
_sticky_events = 0;
* seconds.
*/
double offset() const;
- int owner_v_offset() const;
+ int owner_visual_v_offset() const;
/**
* Returns the number of nested parents that this row item owner has.
void update_viewport();
+ void restack_all_row_items();
+
Q_SIGNALS:
void hover_point_changed();