diff options
Diffstat (limited to 'spline/spline-widget.cpp')
-rw-r--r-- | spline/spline-widget.cpp | 208 |
1 files changed, 114 insertions, 94 deletions
diff --git a/spline/spline-widget.cpp b/spline/spline-widget.cpp index 64f9f156..d329d8e2 100644 --- a/spline/spline-widget.cpp +++ b/spline/spline-widget.cpp @@ -1,10 +1,3 @@ -/* Copyright (c) 2012-2016 Stanislaw Halik <sthalik@misaki.pl> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ - #include "spline-widget.hpp" #include "compat/math.hpp" #include "compat/macros.hpp" @@ -19,7 +12,7 @@ #include <QDebug> -using namespace spline_detail; +namespace spline_detail { spline_widget::spline_widget(QWidget *parent) : QWidget(parent) { @@ -31,28 +24,31 @@ spline_widget::spline_widget(QWidget *parent) : QWidget(parent) spline_widget::~spline_widget() { if (connection) + { QObject::disconnect(connection); + connection = {}; + } } -void spline_widget::setConfig(base_spline* spl) +void spline_widget::set_config(base_spline* spl) { if (connection) { QObject::disconnect(connection); - connection = QMetaObject::Connection(); + connection = {}; } - _config = spl; + config = spl; if (spl) { - update_range(); - - std::shared_ptr<base_spline::base_settings> s = spl->get_settings(); - connection = connect(s.get(), &base_spline::base_settings::recomputed, + std::shared_ptr<base_settings> s = spl->get_settings(); + connection = connect(s.get(), &base_settings::recomputed, this, [this] { reload_spline(); }, Qt::QueuedConnection); } + + reload_spline(); } QColor spline_widget::colorBezier() const @@ -68,37 +64,39 @@ void spline_widget::setColorBezier(QColor const& color) void spline_widget::force_redraw() { - _background = QPixmap(); + background_img = {}; repaint(); } void spline_widget::set_preview_only(bool val) { - _preview_only = val; + preview_only = val; } bool spline_widget::is_preview_only() const { - return _preview_only; + return preview_only; } void spline_widget::drawBackground() { - QPainter painter(&_background); + QPainter painter(&background_img); painter.fillRect(rect(), widget_bg_color); { QColor bg_color(112, 154, 209); - if (!isEnabled() && !_preview_only) + if (!isEnabled() && !preview_only) bg_color = QColor(176,176,180); painter.fillRect(pixel_bounds, bg_color); } QFont font; font.setPointSize(8); + font.setStyleHint(QFont::Monospace, QFont::PreferAntialias); painter.setFont(font); - QFontMetricsF metrics(font); + const QFontMetricsF metrics(font); + const double height = metrics.height(); QColor color__(176, 190, 209, 127); @@ -107,11 +105,11 @@ void spline_widget::drawBackground() const QPen pen(color__, 1, Qt::SolidLine, Qt::FlatCap); - const int ystep = _y_step, xstep = _x_step; - const double maxx = _config->max_input(); - const double maxy = _config->max_output(); + const int ystep = (int)std::ceil(y_step_), xstep = (int)std::ceil(x_step_); + const double maxx = config->max_input(); + const double maxy = config->max_output(); - // horizontal grid + // vertical grid for (int i = 0; i <= maxy; i += ystep) { const double y = pixel_bounds.height() - i * c.y() + pixel_bounds.y(); @@ -120,13 +118,13 @@ void spline_widget::drawBackground() QPointF(pixel_bounds.x() + pixel_bounds.width(), y), pen); painter.drawText(QRectF(10, - y - metrics.height()/2., + y - height/2, pixel_bounds.left(), - metrics.height()), + height), QString::number(i)); } - // vertical grid + // horizontal grid for (int i = 0; i <= maxx; i += xstep) { const double x = pixel_bounds.x() + i * c.x(); @@ -134,21 +132,29 @@ void spline_widget::drawBackground() QPointF(x, pixel_bounds.y()), QPointF(x, pixel_bounds.y() + pixel_bounds.height()), pen); + const QString text = QString::number(i); - painter.drawText(QRectF(x - metrics.width(text)/2., - pixel_bounds.height() + 10 + metrics.height(), - metrics.width(text), - metrics.height()), + + const double width = +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + metrics.horizontalAdvance(text); +#else + metrics.width(text); +#endif + + painter.drawText(QRectF{x - width/2, + pixel_bounds.height() + 10 + height, + width, height}, text); } } void spline_widget::drawFunction() { - QPainter painter(&_function); + QPainter painter(&spline_img); painter.setRenderHint(QPainter::Antialiasing, true); - const points_t points = _config->get_points(); + const points_t& points = config->get_points(); if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) @@ -156,7 +162,7 @@ void spline_widget::drawFunction() const QPen pen(Qt::white, 1, Qt::SolidLine, Qt::FlatCap); const QPointF prev_ = point_to_pixel({}); QPointF prev(iround(prev_.x()), iround(prev_.y())); - for (auto point : points) + for (const auto& point : points) { const QPointF tmp = point_to_pixel(point); drawLine(painter, prev, tmp, pen); @@ -165,7 +171,7 @@ void spline_widget::drawFunction() } const QColor color_ = progn( - if (!isEnabled() && !_preview_only) + if (!isEnabled() && !preview_only) { QColor color(spline_color); const int avg = int(float(color.red() + color.green() + color.blue())/3); @@ -187,7 +193,7 @@ void spline_widget::drawFunction() const double dpr = devicePixelRatioF(); const double line_length_pixels = std::fmax(1, 2 * dpr); const double step = std::fmax(.1, line_length_pixels / c.x()); - const double maxx = _config->max_input(); + const double maxx = config->max_input(); //#define USE_CUBIC_SPLINE #if defined USE_CUBIC_SPLINE @@ -205,9 +211,9 @@ void spline_widget::drawFunction() for (double k = 0; k < maxx; k += step*3) // NOLINT { - const auto next_1 = (double) _config->get_value_no_save(k + step*1); - const auto next_2 = (double) _config->get_value_no_save(k + step*2); - const auto next_3 = (double) _config->get_value_no_save(k + step*3); + const auto next_1 = config->get_value_no_save(k + step*1); + const auto next_2 = config->get_value_no_save(k + step*2); + const auto next_3 = config->get_value_no_save(k + step*3); QPointF b(clamp(point_to_pixel({k + step*1, next_1}))), c(clamp(point_to_pixel({k + step*2, next_2}))), @@ -221,14 +227,14 @@ void spline_widget::drawFunction() QPointF prev = point_to_pixel({}); for (double i = 0; i < maxx; i += step) // NOLINT { - const auto val = (double) _config->get_value_no_save(i); + const auto val = config->get_value_no_save(i); const QPointF cur = point_to_pixel({i, val}); painter.drawLine(prev, cur); prev = cur; } { - const double maxx = _config->max_input(); - const double maxy = double(_config->get_value_no_save(maxx)); + const double maxx = config->max_input(); + const double maxy = config->get_value_no_save(maxx); painter.drawLine(prev, point_to_pixel({ maxx, maxy })); } #endif @@ -242,7 +248,7 @@ void spline_widget::drawFunction() painter.fillRect(r2, widget_bg_color); const int alpha = !isEnabled() ? 64 : 120; - if (!_preview_only) + if (!preview_only) { for (auto const& point : points) { @@ -256,7 +262,7 @@ void spline_widget::drawFunction() void spline_widget::paintEvent(QPaintEvent *e) { - if (!_config) + if (!config) return; QPainter p(this); @@ -265,28 +271,30 @@ void spline_widget::paintEvent(QPaintEvent *e) const int W = iround(width() * dpr); const int H = iround(height() * dpr); - if (_background.size() != QSize(W, H)) + if (background_img.size() != QSize(W, H)) { - _background = QPixmap(W, H); - _background.setDevicePixelRatio(dpr); - _draw_function = true; + update_range(); + + background_img = { W, H }; + background_img.setDevicePixelRatio(dpr); drawBackground(); + draw_function = true; } - if (_draw_function) + if (draw_function) { - _draw_function = false; - _function = _background; + draw_function = false; + spline_img = background_img; drawFunction(); } - p.drawPixmap(e->rect(), _function); + p.drawPixmap(e->rect(), spline_img); // If the Tracker is active, the 'Last Point' it requested is recorded. // Show that point on the graph, with some lines to assist. // This new feature is very handy for tweaking the curves! QPointF last; - if (_config->get_last_value(last) && isEnabled()) + if (config->get_last_value(last) && isEnabled()) drawPoint(p, point_to_pixel(last), QColor(255, 0, 0, 120)); } @@ -312,14 +320,14 @@ void spline_widget::drawLine(QPainter& painter, const QPointF& start, const QPoi void spline_widget::mousePressEvent(QMouseEvent *e) { - if (!_config || !isEnabled() || !is_in_bounds(e->localPos()) || _preview_only) + if (!config || !isEnabled() || !is_in_bounds(e->localPos()) || preview_only) return; const double min_dist = min_pt_distance(); moving_control_point_idx = -1; - points_t points = _config->get_points(); + const points_t& points = config->get_points(); if (e->button() == Qt::LeftButton) { @@ -352,50 +360,50 @@ void spline_widget::mousePressEvent(QMouseEvent *e) if (!too_close) { - _config->add_point(pixel_to_point(e->localPos())); + config->add_point(pixel_to_point(e->localPos())); show_tooltip(e->pos()); } } - _draw_function = true; + draw_function = true; } if (e->button() == Qt::RightButton) { - if (_config) + if (config) { for (int i = 0; i < points.size(); i++) { if (point_within_pixel(points[i], e->localPos())) { - _config->remove_point(i); - _draw_function = true; + config->remove_point(i); + draw_function = true; break; } } } } - if (_draw_function) + if (draw_function) repaint(); } void spline_widget::mouseMoveEvent(QMouseEvent *e) { - if (_preview_only && _config) + if (preview_only && config) { show_tooltip(e->pos()); return; } - if (!_config || !isEnabled() || !isActiveWindow()) + if (!config || !isEnabled() || !isActiveWindow()) { QToolTip::hideText(); return; } const int i = moving_control_point_idx; - const points_t points = _config->get_points(); + const points_t& points = config->get_points(); const int sz = points.size(); if (i >= 0 && i < sz) @@ -428,8 +436,8 @@ void spline_widget::mouseMoveEvent(QMouseEvent *e) if ((!has_prev || check_prev()) && (!has_next || check_next())) { - _config->move_point(i, new_pt); - _draw_function = true; + config->move_point(i, new_pt); + draw_function = true; repaint(); } } @@ -456,7 +464,7 @@ void spline_widget::mouseMoveEvent(QMouseEvent *e) void spline_widget::mouseReleaseEvent(QMouseEvent *e) { - if (!_config || !isEnabled() || !isActiveWindow() || _preview_only) + if (!config || !isEnabled() || !isActiveWindow() || preview_only) return; const bool redraw = moving_control_point_idx != -1; @@ -479,7 +487,7 @@ void spline_widget::mouseReleaseEvent(QMouseEvent *e) if (redraw) { - _draw_function = true; + draw_function = true; repaint(); } } @@ -487,7 +495,7 @@ void spline_widget::mouseReleaseEvent(QMouseEvent *e) void spline_widget::reload_spline() { // don't recompute here as the value's about to be recomputed in the callee - update_range(); + background_img = {}; update(); } @@ -504,8 +512,8 @@ void spline_widget::show_tooltip(const QPoint& pos, const QPointF& value_) double x = value.x(), y = value.y(); - if (_preview_only) - y = _config->get_value_no_save(x); + if (preview_only) + y = config->get_value_no_save(x); const int x_ = iround(x), y_ = iround(y); @@ -514,16 +522,13 @@ void spline_widget::show_tooltip(const QPoint& pos, const QPointF& value_) if (std::fabs(y_ - y) < 1e-3) y = y_; - // the style on OSX has different offsets - static const bool is_fusion = + // the native OSX style doesn't look right otherwise #if defined __APPLE__ - true; + constexpr int off_x = 0, off_y = 0; #else - false; + constexpr int off_x = 25, off_y = 15; #endif - const int off_x = (is_fusion ? 25 : 0), off_y = (is_fusion ? 15 : 0); - const QPoint pix(pos.x() + off_x, pos.y() + off_y); QToolTip::showText(mapToGlobal(pix), @@ -535,8 +540,8 @@ void spline_widget::show_tooltip(const QPoint& pos, const QPointF& value_) bool spline_widget::is_in_bounds(const QPointF& pos) const { - const int grace = point_size_in_pixels * 3; - const int bottom_grace = int(point_size_in_pixels * 1.5); + const int grace = (int)std::ceil(point_size_in_pixels * 3); + const int bottom_grace = (int)std::ceil(point_size_in_pixels * 1.5); return (pos.x() + grace > pixel_bounds.left() && pos.x() - grace < pixel_bounds.right() && pos.y() + grace > pixel_bounds.top() && @@ -545,21 +550,22 @@ bool spline_widget::is_in_bounds(const QPointF& pos) const void spline_widget::update_range() { - if (!_config) + if (!config) return; const int w = width(), h = height(); const int mwl = 40, mhl = 20; const int mwr = 15, mhr = 35; - pixel_bounds = QRect(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr)); - c = { pixel_bounds.width() / _config->max_input(), pixel_bounds.height() / _config->max_output() }; - _draw_function = true; - - _background = QPixmap(); - _function = QPixmap(); + pixel_bounds = { mwl, mhl, (w - mwl - mwr), (h - mhl - mhr) }; + c = { + pixel_bounds.width() / std::fmax(1, config->max_input()), + pixel_bounds.height() / std::fmax(1, config->max_output()) + }; - repaint(); + draw_function = true; + background_img = {}; + spline_img = {}; } bool spline_widget::point_within_pixel(const QPointF& pt, const QPointF& pixel) @@ -573,7 +579,7 @@ void spline_widget::focusOutEvent(QFocusEvent* e) if (moving_control_point_idx != -1) QToolTip::hideText(); moving_control_point_idx = -1; - _draw_function = true; + draw_function = true; lower(); setCursor(Qt::ArrowCursor); e->accept(); @@ -604,8 +610,8 @@ QPointF spline_widget::pixel_to_point(const QPointF& point) if (snap_y > 0) y = snap(y, snap_y); - x = clamp(x, 0, _config->max_input()); - y = clamp(y, 0, _config->max_output()); + x = clamp(x, 0, config->max_input()); + y = clamp(y, 0, config->max_output()); return { x, y }; } @@ -620,19 +626,19 @@ QPointF spline_widget::point_to_pixel(const QPointF& point) void spline_widget::resizeEvent(QResizeEvent *) { - update_range(); + reload_spline(); } bool spline_widget::is_on_pt(const QPointF& pos, int* pt) { - if (!_config) + if (!config) { if (pt) *pt = -1; return false; } - const points_t points = _config->get_points(); + const points_t& points = config->get_points(); for (int i = 0; i < points.size(); i++) { @@ -648,3 +654,17 @@ bool spline_widget::is_on_pt(const QPointF& pos, int* pt) *pt = -1; return false; } + +void spline_widget::changeEvent(QEvent* e) +{ + switch (e->type()) + { + case QEvent::EnabledChange: + background_img = {}; spline_img = {}; + update(); + break; + default: + break; + } +} +} // ns spline_detail |