kis_aspect_ratio_locker.cpp 7.38 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 *  Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kis_aspect_ratio_locker.h"

#include <QSpinBox>
22 23
#include <QDoubleSpinBox>

24 25 26
#include <KoAspectButton.h>

#include "kis_signals_blocker.h"
27 28 29
#include "kis_assert.h"
#include "kis_debug.h"
#include "kis_slider_spin_box.h"
30 31
#include "kis_int_parse_spin_box.h"
#include "kis_double_parse_spin_box.h"
32
#include "kis_double_parse_unit_spin_box.h"
33 34


35
struct SliderWrapper
36
{
37 38 39 40 41 42 43
    template <class Slider>
    SliderWrapper(Slider *slider)
        : m_slider(QVariant::fromValue(slider)),
          m_object(slider) {}

    void setValue(qreal value) {

44 45
        if (m_slider.canConvert<KisDoubleParseUnitSpinBox*>()) {
            m_slider.value<KisDoubleParseUnitSpinBox*>()->changeValue(value);
46

47 48
        } else if (m_slider.canConvert<KisDoubleParseSpinBox*>()) {
            m_slider.value<KisDoubleParseSpinBox*>()->setValue(value);
49 50 51

        } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) {
            m_slider.value<KisDoubleSliderSpinBox*>()->setValue(value);
Dmitry Kazakov's avatar
Dmitry Kazakov committed
52

53 54 55
        } else if (m_slider.canConvert<QDoubleSpinBox*>()) {
            m_slider.value<QDoubleSpinBox*>()->setValue(value);

Dmitry Kazakov's avatar
Dmitry Kazakov committed
56 57 58
        } else if (m_slider.canConvert<KisIntParseSpinBox*>()) {
            m_slider.value<KisIntParseSpinBox*>()->setValue(qRound(value));

59 60 61 62 63
        } else if (m_slider.canConvert<KisSliderSpinBox*>()) {
            m_slider.value<KisSliderSpinBox*>()->setValue(qRound(value));

        } else if (m_slider.canConvert<QSpinBox*>()) {
            m_slider.value<QSpinBox*>()->setValue(qRound(value));
64 65 66 67 68 69
        }
    }

    qreal value() const {
        qreal result = 0.0;

70 71
        if (m_slider.canConvert<KisDoubleParseUnitSpinBox*>()) {
            result = m_slider.value<KisDoubleParseUnitSpinBox*>()->value();
72

73 74
        } else if (m_slider.canConvert<KisDoubleParseSpinBox*>()) {
            result = m_slider.value<KisDoubleParseSpinBox*>()->value();
75 76 77

        } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) {
            result = m_slider.value<KisDoubleSliderSpinBox*>()->value();
Dmitry Kazakov's avatar
Dmitry Kazakov committed
78

79 80 81
        } else if (m_slider.canConvert<QDoubleSpinBox*>()) {
            result = m_slider.value<QDoubleSpinBox*>()->value();

Dmitry Kazakov's avatar
Dmitry Kazakov committed
82 83 84
        } else if (m_slider.canConvert<KisIntParseSpinBox*>()) {
            result = m_slider.value<KisIntParseSpinBox*>()->value();

85 86 87 88 89 90
        } else if (m_slider.canConvert<KisSliderSpinBox*>()) {
            result = m_slider.value<KisSliderSpinBox*>()->value();

        } else if (m_slider.canConvert<QSpinBox*>()) {
            result = m_slider.value<QSpinBox*>()->value();

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        }

        return result;
    }

    bool isDragging() const {
        bool result = false;

        if (m_slider.canConvert<KisSliderSpinBox*>()) {
            result = m_slider.value<KisSliderSpinBox*>()->isDragging();

        } else if (m_slider.canConvert<KisDoubleSliderSpinBox*>()) {
            result = m_slider.value<KisDoubleSliderSpinBox*>()->isDragging();
        }

        return result;
    }
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    QObject* object() const {
        return m_object;
    }

private:
    QVariant m_slider;
    QObject *m_object;
};

struct KisAspectRatioLocker::Private
{
    QScopedPointer<SliderWrapper> spinOne;
    QScopedPointer<SliderWrapper> spinTwo;
    KoAspectButton *aspectButton = 0;

    qreal aspectRatio = 1.0;
    bool blockUpdatesOnDrag = false;
126 127 128 129 130 131 132 133 134 135 136 137 138
};


KisAspectRatioLocker::KisAspectRatioLocker(QObject *parent)
    : QObject(parent),
      m_d(new Private)
{
}

KisAspectRatioLocker::~KisAspectRatioLocker()
{
}

139 140
template <class SpinBoxType>
void KisAspectRatioLocker::connectSpinBoxes(SpinBoxType *spinOne, SpinBoxType *spinTwo, KoAspectButton *aspectButton)
141
{
142 143
    m_d->spinOne.reset(new SliderWrapper(spinOne));
    m_d->spinTwo.reset(new SliderWrapper(spinTwo));
144 145
    m_d->aspectButton = aspectButton;

146 147 148 149 150 151 152 153
    if (QVariant::fromValue(spinOne->value()).type() == QVariant::Double) {
        connect(spinOne, SIGNAL(valueChanged(qreal)), SLOT(slotSpinOneChanged()));
        connect(spinTwo, SIGNAL(valueChanged(qreal)), SLOT(slotSpinTwoChanged()));
    } else {
        connect(spinOne, SIGNAL(valueChanged(int)), SLOT(slotSpinOneChanged()));
        connect(spinTwo, SIGNAL(valueChanged(int)), SLOT(slotSpinTwoChanged()));
    }

154 155 156 157
    connect(m_d->aspectButton, SIGNAL(keepAspectRatioChanged(bool)), SLOT(slotAspectButtonChanged()));
    slotAspectButtonChanged();
}

Dmitry Kazakov's avatar
Dmitry Kazakov committed
158 159 160 161 162 163
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(QSpinBox *spinOne, QSpinBox *spinTwo, KoAspectButton *aspectButton);
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(QDoubleSpinBox *spinOne, QDoubleSpinBox *spinTwo, KoAspectButton *aspectButton);
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisSliderSpinBox *spinOne, KisSliderSpinBox *spinTwo, KoAspectButton *aspectButton);
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisDoubleSliderSpinBox *spinOne, KisDoubleSliderSpinBox *spinTwo, KoAspectButton *aspectButton);
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisIntParseSpinBox *spinOne, KisIntParseSpinBox *spinTwo, KoAspectButton *aspectButton);
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisDoubleParseSpinBox *spinOne, KisDoubleParseSpinBox *spinTwo, KoAspectButton *aspectButton);
164
template KRITAUI_EXPORT void KisAspectRatioLocker::connectSpinBoxes(KisDoubleParseUnitSpinBox *spinOne, KisDoubleParseUnitSpinBox *spinTwo, KoAspectButton *aspectButton);
165

166 167 168
void KisAspectRatioLocker::slotSpinOneChanged()
{
    if (m_d->aspectButton->keepAspectRatio()) {
169 170 171 172 173 174
        KisSignalsBlocker b(m_d->spinTwo->object());
        m_d->spinTwo->setValue(m_d->aspectRatio * m_d->spinOne->value());
    }

    if (!m_d->blockUpdatesOnDrag || !m_d->spinOne->isDragging()) {
        emit sliderValueChanged();
175 176 177 178 179 180
    }
}

void KisAspectRatioLocker::slotSpinTwoChanged()
{
    if (m_d->aspectButton->keepAspectRatio()) {
181 182
        KisSignalsBlocker b(m_d->spinOne->object());
        m_d->spinOne->setValue(m_d->spinTwo->value() / m_d->aspectRatio);
183
    }
184

185 186 187
    if (!m_d->blockUpdatesOnDrag || !m_d->spinTwo->isDragging()) {
        emit sliderValueChanged();
    }
188 189 190 191 192 193 194 195 196 197 198 199
}

void KisAspectRatioLocker::slotAspectButtonChanged()
{
    if (m_d->aspectButton->keepAspectRatio() &&
        m_d->spinTwo->value() > 0 &&
        m_d->spinOne->value() > 0) {

        m_d->aspectRatio = qreal(m_d->spinTwo->value()) / m_d->spinOne->value();
    } else {
        m_d->aspectRatio = 1.0;
    }
200

201 202
    if (!m_d->spinTwo->isDragging()) {
        emit aspectButtonChanged();
203
        emit aspectButtonToggled(m_d->aspectButton->keepAspectRatio());
204 205 206 207 208 209
    }
}

void KisAspectRatioLocker::setBlockUpdateSignalOnDrag(bool value)
{
    m_d->blockUpdatesOnDrag = value;
210
}
211 212 213 214 215 216

void KisAspectRatioLocker::updateAspect()
{
    KisSignalsBlocker b(this);
    slotAspectButtonChanged();
}