From f971ccff4b39d7e935f66a2c2fafbca15b0dfd17 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Mon, 4 Jan 2016 22:05:01 +0000 Subject: [PATCH] Workout Editor Smart Guides .. just a simple indicator in the x-axis for now when points are selected. may extend to the y-axis as well. .. lots more to come on smart guides but needs a lot of thought and play time. --- src/WorkoutWidgetItems.cpp | 120 +++++++++++++++++++++++++++++++++++++ src/WorkoutWidgetItems.h | 20 +++++++ src/WorkoutWindow.cpp | 3 + src/WorkoutWindow.h | 2 + 4 files changed, 145 insertions(+) diff --git a/src/WorkoutWidgetItems.cpp b/src/WorkoutWidgetItems.cpp index def3d810d..75c33c395 100644 --- a/src/WorkoutWidgetItems.cpp +++ b/src/WorkoutWidgetItems.cpp @@ -393,6 +393,126 @@ WWMMPCurve::paint(QPainter *painter) } } +void +WWSmartGuide::paint(QPainter *painter) +{ + QPointF tl(-1,-1); + QPointF br(-1,-1); + + // get the boundary of the selection + int selected=0; + foreach(WWPoint *p, workoutWidget()->points()) { + + // don't show guides whilst selecting, too noisy + if (!p->selected) continue; + + selected++; + + // top left + if (tl.x() == -1 || tl.x() > p->x) tl.setX(p->x); + if (tl.y() == -1 || tl.y() < p->y) tl.setY(p->y); + + // bottom right + if (br.x() == -1 || br.x() < p->x) br.setX(p->x); + if (br.y() == -1 || br.y() > p->y) br.setY(p->y); + } + + // set the boundary + QRectF boundary (workoutWidget()->transform(tl.x(), tl.y()), + workoutWidget()->transform(br.x(), br.y())); + + if (selected > 0) { + + // for now just paint the boundary tics on the x-axis + QPen linePen(GColor(CPLOTMARKER)); + linePen.setWidthF(0); + painter->setPen(linePen); + + QRectF bottom = workoutWidget()->bottom(); + + // top line width indicators + painter->drawLine(boundary.bottomLeft().x(), workoutWidget()->bottom().y(), + boundary.bottomLeft().x(), workoutWidget()->bottom().y()+bottom.height()); + + painter->drawLine(boundary.bottomRight().x(), bottom.y(), + boundary.bottomRight().x(), bottom.y()+bottom.height()); + + // now the text - but only if we have a gap! + if (br.x() > tl.x()) { + QFontMetrics fontMetrics(workoutWidget()->markerFont); + painter->setFont(workoutWidget()->markerFont); + + // paint time at very bottom of bottom in the middle + // of the elongated tic marks + QString text = time_to_string(br.x()-tl.x()); + QRect bound = fontMetrics.boundingRect(text); + QPoint here(boundary.center().x()-(bound.width()/2), bottom.bottom()); + + painter->drawText(here, text); + } + + // find next and previous points, so we can mark them too + // this is useful when shifting left and right + int prev=-1, next=-1; + for(int i=0; i < workoutWidget()->points().count(); i++) { + WWPoint *p = workoutWidget()->points()[i]; + if (p->x < tl.x()) prev=i; // to left + if (p->x > br.x()) { + next=i; + break; + } + } + + // in seconds + int left = prev >= 0 ? workoutWidget()->points()[prev]->x : 0; + int right = next >= 0 ? workoutWidget()->points()[next]->x : workoutWidget()->maxX(); + + // in plot coordinates + QPointF leftpx = workoutWidget()->transform(left,0); + QPointF rightpx = workoutWidget()->transform(right,0); + leftpx.setY(bottom.y()); + rightpx.setY(bottom.y()); + + // left indicator + painter->drawLine(leftpx, leftpx + QPointF(0, bottom.height())); + painter->drawLine(rightpx, rightpx + QPointF(0, bottom.height())); + + // now the left text - but only if we have a gap! + if (left < tl.x()) { + QFontMetrics fontMetrics(workoutWidget()->markerFont); + painter->setFont(workoutWidget()->markerFont); + + // paint time at very bottom of bottom in the middle + // of the elongated tic marks + QString text = time_to_string(tl.x() - left); + QRect bound = fontMetrics.boundingRect(text); + QPointF here(leftpx.x() + ((boundary.left() - leftpx.x())/2) - (bound.width()/2), bottom.bottom()); + + painter->drawText(here, text); + } + + // now the right text - but only if we have a gap! + if (right > br.x()) { + QFontMetrics fontMetrics(workoutWidget()->markerFont); + painter->setFont(workoutWidget()->markerFont); + + // paint time at very bottom of bottom in the middle + // of the elongated tic marks + QString text = time_to_string(right - br.x()); + QRect bound = fontMetrics.boundingRect(text); + QPointF here(boundary.right() + ((rightpx.x()-boundary.right())/2) - (bound.width()/2), bottom.bottom()); + painter->drawText(here, text); + } + +#if 0 // doesn't add much + // side line width indicators + painter->drawLine(boundary.topLeft()-QPointF(10,0), boundary.topLeft()-QPointF(30,0)); + painter->drawLine(boundary.bottomLeft()-QPointF(10,0), boundary.bottomLeft()-QPointF(30,0)); + painter->drawLine(boundary.bottomLeft()-QPointF(20,0), boundary.topLeft()-QPointF(20,0)); +#endif + } +} + // // COMMANDS // diff --git a/src/WorkoutWidgetItems.h b/src/WorkoutWidgetItems.h index 00f811dd4..c605f8c5b 100644 --- a/src/WorkoutWidgetItems.h +++ b/src/WorkoutWidgetItems.h @@ -40,6 +40,7 @@ #define GCWW_BCURSOR 7 // interval "block" cursor #define GCWW_BRECT 8 // block selection #define GCWW_MMPCURVE 9 +#define GCWW_SGUIDE 10 // smart guides appear as we drag // // ITEMS @@ -163,6 +164,25 @@ class WWRect : public WorkoutWidgetItem { }; +// flash up guide lines when things align when the user is creating +// moving or dragging points or blocks around +class WWSmartGuide : public WorkoutWidgetItem { + + public: + + WWSmartGuide(WorkoutWidget *w) : WorkoutWidgetItem(w) { w->addItem(this); } + + // Reimplement in children + int type() { return GCWW_SGUIDE; } + + void paint(QPainter *painter); + + // locate me on the parent widget in paint coordinates + // should not be selectable (!!) + QRectF bounding() { return QRectF(); } +}; + +// highlight as we hover over blocks class WWBlockCursor : public WorkoutWidgetItem { public: diff --git a/src/WorkoutWindow.cpp b/src/WorkoutWindow.cpp index e31e64462..b7ebe4bfc 100644 --- a/src/WorkoutWindow.cpp +++ b/src/WorkoutWindow.cpp @@ -58,6 +58,9 @@ WorkoutWindow::WorkoutWindow(Context *context) : // selection tool rect = new WWRect(workout); + // guides always on top! + guide = new WWSmartGuide(workout); + // setup the toolbar toolbar = new QToolBar(this); toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); diff --git a/src/WorkoutWindow.h b/src/WorkoutWindow.h index b40e233f9..7553cc476 100644 --- a/src/WorkoutWindow.h +++ b/src/WorkoutWindow.h @@ -44,6 +44,7 @@ class WWRect; class WWBlockCursor; class WWBlockSelection; class WWMMPCurve; +class WWSmartGuide; class WorkoutWindow : public GcWindow { @@ -87,6 +88,7 @@ class WorkoutWindow : public GcWindow WWBlockCursor *bcursor; WWBlockSelection *brect; WWMMPCurve *mmp; + WWSmartGuide *guide; bool active; };