Commit 2d977c95 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Implement Opacity slider in the geometry tab of the Default tool

parent 2d71cba0
......@@ -23,7 +23,8 @@ namespace KisCommandUtils {
enum CommandId {
MoveShapeId = 9999,
ResizeShapeId,
TransformShapeId
TransformShapeId,
ChangeShapeTransparencyId
};
}
......
......@@ -768,6 +768,9 @@ void KoShape::setTransparency(qreal transparency)
{
Q_D(KoShape);
d->transparency = qBound<qreal>(0.0, transparency, 1.0);
d->shapeChanged(TransparencyChanged);
notifyChanged();
}
qreal KoShape::transparency(bool recursive) const
......
......@@ -129,7 +129,8 @@ public:
TextRunAroundChanged, ///< used after a setTextRunAroundSide()
ChildChanged, ///< a child of a container was changed/removed. This is propagated to all parents
ConnectionPointChanged, ///< a connection point has changed
ClipPathChanged ///< the shapes clip path has changed
ClipPathChanged, ///< the shapes clip path has changed
TransparencyChanged ///< the shapetransparency value has changed
};
/// The behavior text should do when intersecting this shape.
......
......@@ -21,6 +21,7 @@
#include "KoShape.h"
#include <klocalizedstring.h>
#include "kis_command_ids.h"
class Q_DECL_HIDDEN KoShapeTransparencyCommand::Private
{
......@@ -98,3 +99,20 @@ void KoShapeTransparencyCommand::undo()
++transparencyIt;
}
}
int KoShapeTransparencyCommand::id() const
{
return KisCommandUtils::ChangeShapeTransparencyId;
}
bool KoShapeTransparencyCommand::mergeWith(const KUndo2Command *command)
{
const KoShapeTransparencyCommand *other = dynamic_cast<const KoShapeTransparencyCommand*>(command);
if (!other || other->d->shapes != d->shapes) {
return false;
}
d->newTransparencies = other->d->newTransparencies;
return true;
}
......@@ -57,9 +57,13 @@ public:
virtual ~KoShapeTransparencyCommand();
/// redo the command
void redo();
void redo() override;
/// revert the actions done in redo
void undo();
void undo() override;
int id() const override;
bool mergeWith(const KUndo2Command *command) override;
private:
class Private;
Private * const d;
......
......@@ -34,6 +34,7 @@
#include <commands/KoShapeSizeCommand.h>
#include <commands/KoShapeTransformCommand.h>
#include <commands/KoShapeKeepAspectRatioCommand.h>
#include <commands/KoShapeTransparencyCommand.h>
#include "SelectionDecorator.h"
#include <KoShapeGroup.h>
......@@ -52,6 +53,8 @@
#include "kis_aspect_ratio_locker.h"
#include "kis_debug.h"
#include "kis_acyclic_signal_connector.h"
#include "kis_signal_compressor.h"
#include "kis_signals_blocker.h"
DefaultToolGeometryWidget::DefaultToolGeometryWidget(KoInteractionTool *tool, QWidget *parent)
......@@ -81,10 +84,12 @@ DefaultToolGeometryWidget::DefaultToolGeometryWidget(KoInteractionTool *tool, QW
connect(selection, SIGNAL(selectionChanged()), this, SLOT(slotUpdatePositionBoxes()));
connect(selection, SIGNAL(selectionChanged()), this, SLOT(slotUpdateSizeBoxes()));
connect(selection, SIGNAL(selectionChanged()), this, SLOT(slotUpdateCheckboxes()));
connect(selection, SIGNAL(selectionChanged()), this, SLOT(slotUpdateOpacitySlider()));
KoShapeManager *manager = m_tool->canvas()->shapeManager();
connect(manager, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdatePositionBoxes()));
connect(manager, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdateSizeBoxes()));
connect(manager, SIGNAL(selectionContentChanged()), this, SLOT(slotUpdateOpacitySlider()));
connect(chkGlobalCoordinates, SIGNAL(toggled(bool)), SLOT(slotUpdateSizeBoxes()));
......@@ -103,6 +108,21 @@ DefaultToolGeometryWidget::DefaultToolGeometryWidget(KoInteractionTool *tool, QW
// Connect anchor point selector
connect(positionSelector, SIGNAL(valueChanged(KoFlake::AnchorPosition)), SLOT(slotAnchorPointChanged()));
dblOpacity->setRange(0.0, 1.0, 2);
dblOpacity->setSingleStep(0.01);
dblOpacity->setFastSliderStep(0.1);
{
KisSignalCompressor *opacityCompressor =
new KisSignalCompressor(100, KisSignalCompressor::FIRST_ACTIVE, this);
connect(dblOpacity, SIGNAL(valueChanged(qreal)), opacityCompressor, SLOT(start()));
connect(opacityCompressor, SIGNAL(timeout()), SLOT(slotOpacitySliderChanged()));
// cold init
slotUpdateOpacitySlider();
}
}
DefaultToolGeometryWidget::~DefaultToolGeometryWidget()
......@@ -236,6 +256,77 @@ void DefaultToolGeometryWidget::slotUpdateAspectButton()
aspectButton->setKeepAspectRatio(hasKeepAspectRatio);
}
namespace {
qreal calculateCommonShapeTransparency(const QList<KoShape*> &shapes)
{
qreal commonTransparency = -1.0;
Q_FOREACH (KoShape *shape, shapes) {
if (commonTransparency < 0) {
commonTransparency = shape->transparency();
} else if (!qFuzzyCompare(commonTransparency, shape->transparency())) {
commonTransparency = -1.0;
break;
}
}
return commonTransparency;
}
}
void DefaultToolGeometryWidget::slotOpacitySliderChanged()
{
static const qreal eps = 1e-3;
KoSelection *selection = m_tool->canvas()->shapeManager()->selection();
QList<KoShape*> shapes = selection->selectedEditableShapes();
if (shapes.isEmpty()) return;
const qreal newTransparency = 1.0 - dblOpacity->value();
const qreal commonTransparency = calculateCommonShapeTransparency(shapes);
if (qAbs(commonTransparency - newTransparency) < eps) {
return;
}
KUndo2Command *cmd =
new KoShapeTransparencyCommand(shapes, newTransparency);
m_tool->canvas()->addCommand(cmd);
}
void DefaultToolGeometryWidget::slotUpdateOpacitySlider()
{
if (!isVisible()) return;
const QString opacityNormalPrefix = i18n("Opacity: ");
const QString opacityVariesPrefix = i18n("Opacity [*varies*]: ");
KoSelection *selection = m_tool->canvas()->shapeManager()->selection();
QList<KoShape*> shapes = selection->selectedEditableShapes();
if (shapes.isEmpty()) {
KisSignalsBlocker b(dblOpacity);
dblOpacity->setEnabled(false);
dblOpacity->setValue(1.0);
dblOpacity->setPrefix(opacityNormalPrefix);
} else {
const qreal commonTransparency = calculateCommonShapeTransparency(shapes);
dblOpacity->setEnabled(true);
if (commonTransparency >= 0.0) {
KisSignalsBlocker b(dblOpacity);
dblOpacity->setValue(1.0 - commonTransparency);
dblOpacity->setPrefix(opacityNormalPrefix);
} else {
KisSignalsBlocker b(dblOpacity);
dblOpacity->setValue(1.0);
dblOpacity->setPrefix(opacityVariesPrefix);
}
}
}
void DefaultToolGeometryWidget::slotUpdateSizeBoxes()
{
const bool useGlobalSize = chkGlobalCoordinates->isChecked();
......
......@@ -55,6 +55,9 @@ private Q_SLOTS:
void slotAspectButtonToggled();
void slotUpdateAspectButton();
void slotOpacitySliderChanged();
void slotUpdateOpacitySlider();
private:
KoInteractionTool *m_tool;
QScopedPointer<KisAspectRatioLocker> m_sizeAspectLocker;
......
......@@ -6,29 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
<width>245</width>
<height>178</height>
<width>305</width>
<height>303</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
......@@ -202,15 +187,28 @@
</layout>
</item>
<item>
<widget class="QWidget" name="SpecialSpacer" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="KisDoubleSliderSpinBox" name="dblOpacity" native="true"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
......@@ -231,6 +229,12 @@
<header>KoAnchorSelectionWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KisDoubleSliderSpinBox</class>
<extends>QWidget</extends>
<header location="global">kis_slider_spin_box.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>positionXSpinBox</tabstop>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment