Skip to content

Commit

Permalink
QtWidgets: spinbox semantics for ordinal properties
Browse files Browse the repository at this point in the history
* added new draggable spinbox widget (ValueDragSpinBox) for int and double based on ValueDragger
  • Loading branch information
martinfalk committed Sep 7, 2018
1 parent 6d0e737 commit c2999d4
Show file tree
Hide file tree
Showing 14 changed files with 1,334 additions and 38 deletions.
10 changes: 10 additions & 0 deletions modules/qtwidgets/CMakeLists.txt
Expand Up @@ -23,7 +23,10 @@ set(MOC_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ordinaleditorwidget.h
${CMAKE_CURRENT_SOURCE_DIR}/processors/processordockwidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/processors/processorwidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/doublevaluedragspinbox.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/ordinalspinboxwidget.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/stringmultilinepropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/valuedragspinbox.h
${CMAKE_CURRENT_SOURCE_DIR}/propertylistwidget.h
${CMAKE_CURRENT_SOURCE_DIR}/rangesliderqt.h
${CMAKE_CURRENT_SOURCE_DIR}/sliderwidgetqt.h
Expand Down Expand Up @@ -53,6 +56,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/properties/eventpropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/filepropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/fontsizepropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/indicatorwidget.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/isotfpropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/isovaluepropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/lightpropertywidgetqt.h
Expand All @@ -70,6 +74,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/properties/texteditorwidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/tfprimitivesetwidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/tfpropertywidgetqt.h
${CMAKE_CURRENT_SOURCE_DIR}/properties/valuedragger.h
${CMAKE_CURRENT_SOURCE_DIR}/qstringhelper.h
${CMAKE_CURRENT_SOURCE_DIR}/qtwidgetsmodule.h
${CMAKE_CURRENT_SOURCE_DIR}/qtwidgetsmoduledefine.h
Expand Down Expand Up @@ -115,10 +120,12 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/properties/collapsiblegroupboxwidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/colorpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/compositepropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/doublevaluedragspinbox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/eventpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/filepropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/fontsizepropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/glslsyntaxhighlighter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/indicatorwidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/isotfpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/isovaluepropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/lightpropertywidgetqt.cpp
Expand All @@ -128,6 +135,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/properties/ordinalminmaxpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/ordinalminmaxtextpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/ordinalpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/ordinalspinboxwidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/propertyeditorwidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/propertysettingswidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/propertywidgetqt.cpp
Expand All @@ -138,6 +146,8 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/properties/texteditorwidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/tfprimitivesetwidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/tfpropertywidgetqt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/valuedragger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/properties/valuedragspinbox.cpp
${CMAKE_CURRENT_SOURCE_DIR}/propertylistwidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qtwidgetsmodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qtwidgetssettings.cpp
Expand Down
124 changes: 124 additions & 0 deletions modules/qtwidgets/properties/doublevaluedragspinbox.cpp
@@ -0,0 +1,124 @@
/*********************************************************************************
*
* Inviwo - Interactive Visualization Workshop
*
* Copyright (c) 2018 Inviwo Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************/

#include <modules/qtwidgets/properties/doublevaluedragspinbox.h>
#include <modules/qtwidgets/properties/valuedragger.h>
#include <modules/qtwidgets/customdoublespinboxqt.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QHBoxLayout>
#include <warn/pop>

namespace inviwo {

DoubleValueDragSpinBox::DoubleValueDragSpinBox(QWidget *parent)
: QWidget(parent)
, spinBox_(new CustomDoubleSpinBoxQt())
, valueDragger_(new ValueDragger<double>(spinBox_)) {
setObjectName("valueDragSpinBox");
auto layout = new QHBoxLayout();
layout->setSpacing(2);
layout->setMargin(0);
layout->addWidget(valueDragger_);
layout->addWidget(spinBox_);

setLayout(layout);

spinBox_->setButtonSymbols(QAbstractSpinBox::NoButtons);

connect(spinBox_, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this,
static_cast<void (DoubleValueDragSpinBox::*)(double)>(
&DoubleValueDragSpinBox::valueChanged));
connect(spinBox_,
static_cast<void (QDoubleSpinBox::*)(const QString &)>(&QDoubleSpinBox::valueChanged),
this,
static_cast<void (DoubleValueDragSpinBox::*)(const QString &)>(
&DoubleValueDragSpinBox::valueChanged));
connect(spinBox_, &QSpinBox::editingFinished, this, &DoubleValueDragSpinBox::editingFinished);
}

void DoubleValueDragSpinBox::setReadOnly(bool r) { spinBox_->setReadOnly(r); }

bool DoubleValueDragSpinBox::isReadOnly() const { return spinBox_->isReadOnly(); }

void DoubleValueDragSpinBox::setSpecialValueText(const QString &txt) {
spinBox_->setSpecialValueText(txt);
}

QString DoubleValueDragSpinBox::specialValueText() const { return spinBox_->specialValueText(); }

void DoubleValueDragSpinBox::setWrapping(bool w) { spinBox_->setWrapping(w); }

bool DoubleValueDragSpinBox::wrapping() const { return spinBox_->wrapping(); }

QString DoubleValueDragSpinBox::text() const { return spinBox_->text(); }

QString DoubleValueDragSpinBox::cleanText() const { return spinBox_->cleanText(); }

int DoubleValueDragSpinBox::decimals() const { return spinBox_->decimals(); }

double DoubleValueDragSpinBox::maximum() const { return spinBox_->maximum(); }

double DoubleValueDragSpinBox::minimum() const { return spinBox_->minimum(); }

QString DoubleValueDragSpinBox::prefix() const { return spinBox_->prefix(); }

void DoubleValueDragSpinBox::setDecimals(int prec) { spinBox_->setDecimals(prec); }

void DoubleValueDragSpinBox::setMaximum(double max) { spinBox_->setMaximum(max); }

void DoubleValueDragSpinBox::setMinimum(double min) { spinBox_->setMinimum(min); }

void DoubleValueDragSpinBox::setPrefix(const QString &prefix) { spinBox_->setPrefix(prefix); }

void DoubleValueDragSpinBox::setRange(double minimum, double maximum) {
spinBox_->setRange(minimum, maximum);
}

void DoubleValueDragSpinBox::setSingleStep(double val) { spinBox_->setSingleStep(val); }

void DoubleValueDragSpinBox::setSuffix(const QString &suffix) { spinBox_->setSuffix(suffix); }

double DoubleValueDragSpinBox::singleStep() const { return spinBox_->singleStep(); }

QString DoubleValueDragSpinBox::suffix() const { return spinBox_->suffix(); }

double DoubleValueDragSpinBox::value() const { return spinBox_->value(); }

void DoubleValueDragSpinBox::setValue(double value) { spinBox_->setValue(value); }

void DoubleValueDragSpinBox::selectAll() { spinBox_->selectAll(); }

void DoubleValueDragSpinBox::stepDown() { spinBox_->stepDown(); }

void DoubleValueDragSpinBox::stepUp() { spinBox_->stepUp(); }

} // namespace inviwo
102 changes: 102 additions & 0 deletions modules/qtwidgets/properties/doublevaluedragspinbox.h
@@ -0,0 +1,102 @@
/*********************************************************************************
*
* Inviwo - Interactive Visualization Workshop
*
* Copyright (c) 2018 Inviwo Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************/

#ifndef IVW_DOUBLEVALUEDRAGSPINBOX_H
#define IVW_DOUBLEVALUEDRAGSPINBOX_H

#include <modules/qtwidgets/qtwidgetsmoduledefine.h>
#include <inviwo/core/common/inviwo.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QWidget>
#include <warn/pop>

namespace inviwo {

class CustomDoubleSpinBoxQt;

template <typename T>
class ValueDragger;

class IVW_MODULE_QTWIDGETS_API DoubleValueDragSpinBox : public QWidget {
#include <warn/push>
#include <warn/ignore/all>
Q_OBJECT
#include <warn/pop>
public:
explicit DoubleValueDragSpinBox(QWidget *parent = nullptr);
virtual ~DoubleValueDragSpinBox() override = default;

void setReadOnly(bool r);
bool isReadOnly() const;

void setSpecialValueText(const QString &txt);
QString specialValueText() const;

void setWrapping(bool w);
bool wrapping() const;

QString text() const;

QString cleanText() const;
int decimals() const;
double maximum() const;
double minimum() const;
QString prefix() const;
void setDecimals(int prec);
void setMaximum(double max);
void setMinimum(double min);
void setPrefix(const QString &prefix);
void setRange(double minimum, double maximum);
void setSingleStep(double val);
void setSuffix(const QString &suffix);
double singleStep() const;
QString suffix() const;
double value() const;

signals:
void valueChanged(double d);
void valueChanged(const QString &text);
void editingFinished();

public slots:
void setValue(double value);
void selectAll();
void stepDown();
void stepUp();

private:
CustomDoubleSpinBoxQt *spinBox_;
ValueDragger<double> *valueDragger_;
};

} // namespace inviwo

#endif // IVW_DOUBLEVALUEDRAGSPINBOX_H
106 changes: 106 additions & 0 deletions modules/qtwidgets/properties/indicatorwidget.cpp
@@ -0,0 +1,106 @@
/*********************************************************************************
*
* Inviwo - Interactive Visualization Workshop
*
* Copyright (c) 2018 Inviwo Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************/

#include <modules/qtwidgets/properties/indicatorwidget.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QPaintEvent>
#include <QPainter>
#include <warn/pop>

namespace inviwo {

IndicatorWidget::IndicatorWidget(QWidget *parent)
: QWidget(parent, Qt::Window | Qt::FramelessWindowHint) {
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
setWindowOpacity(0.7);
}

void IndicatorWidget::setBasePoint(QPoint p) {
basePoint_ = p;
set(basePoint_, 0);
}

void IndicatorWidget::setLength(int len) {
length_ = len;
set(basePoint_, len);
}

void IndicatorWidget::set(QPoint base, int len) {
QRect r(base, QSize(0, -len));
r = r.normalized();
auto l = handleWidth_ / 2 + 1;
r.adjust(-l, -l, l, l);
handleRect_ = QRect(QPoint(-handleWidth_ / 2, -handleWidth_ / 2 + std::abs(len)),
QSize(handleWidth_, handleWidth_));
int sign = (len > 0) ? 1 : -1;

if (std::abs(len) > grooveWidth_) {
grooveRect_ =
QRect(QPoint(-grooveWidth_ / 2, -grooveWidth_ / 2), QSize(grooveWidth_, std::abs(len)));
} else {
grooveRect_ = QRect();
}

painterTransform_ =
QTransform::fromScale(1.0, -sign).translate(l, -sign * l - std::max(len, 0));

setGeometry(r);
}

void IndicatorWidget::paintEvent(QPaintEvent *e) {
QPainter p(this);
p.setRenderHints(QPainter::Antialiasing);

p.setClipRegion(e->region());

QPen pen(QColor("#1e70a8").darker(150), 1.0);
p.setPen(pen);

QRect handle;
QRect groove;

p.setTransform(painterTransform_);

if (grooveRect_.isValid()) {
p.setBrush(QColor("#1e70a8"));

auto radius = grooveWidth_ * 0.5;
p.drawRoundedRect(grooveRect_, radius, radius, Qt::AbsoluteSize);
}

// draw circle on top
p.setPen(QPen(QColor("#c8ccd0").darker(200), 1.0));
p.setBrush(QColor("#c8ccd0").lighter(130));
p.drawEllipse(handleRect_);
}

} // namespace inviwo

0 comments on commit c2999d4

Please sign in to comment.