diff --git a/libs/flake/KoShapeFillWrapper.h b/libs/flake/KoShapeFillWrapper.h --- a/libs/flake/KoShapeFillWrapper.h +++ b/libs/flake/KoShapeFillWrapper.h @@ -46,6 +46,7 @@ QTransform gradientTransform() const; KUndo2Command* setColor(const QColor &color); + KUndo2Command* setLineWidth(const float &lineWidth); KUndo2Command* setGradient(const QGradient *gradient, const QTransform &transform); KUndo2Command* applyGradient(const QGradient *gradient); diff --git a/libs/flake/KoShapeFillWrapper.cpp b/libs/flake/KoShapeFillWrapper.cpp --- a/libs/flake/KoShapeFillWrapper.cpp +++ b/libs/flake/KoShapeFillWrapper.cpp @@ -86,6 +86,11 @@ KoShapeStrokeSP stroke = qSharedPointerDynamicCast(shape->stroke()); if (!stroke) return Type::None; + // strokes without any width are none + if (stroke->lineWidth() == 0.0) { + return Type::None; + } + // TODO: patterns are not supported yet! return stroke->lineBrush().gradient() ? Type::Gradient : Type::Solid; } @@ -238,9 +243,16 @@ KoShape *shape = m_d->shapes.first(); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(shape, KoFlake::None); - return m_d->fillVariant == KoFlake::Fill ? - ShapeBackgroundFetchPolicy::type(shape) : - ShapeStrokeFillFetchPolicy::type(shape); + KoFlake::FillType fillType; + if (m_d->fillVariant == KoFlake::Fill) { + // fill property of vector object + fillType = ShapeBackgroundFetchPolicy::type(shape); + } else { + // stroke property of vector object + fillType = ShapeStrokeFillFetchPolicy::type(shape); + } + + return fillType; } QColor KoShapeFillWrapper::color() const @@ -310,6 +322,27 @@ return command; } +KUndo2Command *KoShapeFillWrapper::setLineWidth(const float &lineWidth) +{ + KUndo2Command *command = 0; + + float applyLineWidth = lineWidth; + if (m_d->fillVariant == KoFlake::Fill) { + // background section doesn't have a line width, so set to 0 + applyLineWidth = 0.0; + } + + command = KoFlake::modifyShapesStrokes(m_d->shapes, [lineWidth](KoShapeStrokeSP stroke) { + stroke->setColor(Qt::transparent); + stroke->setLineWidth(lineWidth); + + }); + + return command; + +} + + KUndo2Command *KoShapeFillWrapper::setGradient(const QGradient *gradient, const QTransform &transform) { KUndo2Command *command = 0; diff --git a/libs/ui/widgets/KoFillConfigWidget.h b/libs/ui/widgets/KoFillConfigWidget.h --- a/libs/ui/widgets/KoFillConfigWidget.h +++ b/libs/ui/widgets/KoFillConfigWidget.h @@ -75,6 +75,7 @@ void styleButtonPressed(int buttonId); void noColorSelected(); + void shapeChanged(); /// apply color changes to the selected shape void colorChanged(); @@ -82,7 +83,7 @@ /// the pattern of the fill changed, apply the changes void patternChanged(QSharedPointer background); - void shapeChanged(); + void slotUpdateFillTitle(); @@ -104,9 +105,6 @@ void sigInternalRequestColorToResourceManager(); private: - /// update the widget with the KoShape background - void updateWidget(KoShape *shape); - void uploadNewGradientBackground(const QGradient *gradient); void setNewGradientBackgroundToShape(); void updateGradientSaveButtonAvailability(); @@ -114,7 +112,8 @@ void updateWidgetComponentVisbility(); - bool checkNewFillModeIsSame(const KoShapeFillWrapper &w) const; + /// update the widget with the KoShape background + void updateFillIndexFromShape(KoShape *shape); class Private; Private * const d; diff --git a/libs/ui/widgets/KoFillConfigWidget.cpp b/libs/ui/widgets/KoFillConfigWidget.cpp --- a/libs/ui/widgets/KoFillConfigWidget.cpp +++ b/libs/ui/widgets/KoFillConfigWidget.cpp @@ -178,6 +178,7 @@ : canvas(0), colorChangedCompressor(100, KisSignalCompressor::FIRST_ACTIVE), gradientChangedCompressor(100, KisSignalCompressor::FIRST_ACTIVE), + shapeChangedCompressor(200,KisSignalCompressor::FIRST_ACTIVE), fillVariant(_fillVariant), noSelectionTrackingMode(false) { @@ -197,8 +198,12 @@ QSharedPointer activeGradient; KisSignalCompressor gradientChangedCompressor; + KisSignalCompressor shapeChangedCompressor; KoFlake::FillVariant fillVariant; + + QList previousShapeSelected;/// container to see if the selection has actually changed + bool noSelectionTrackingMode; Ui_KoFillConfigWidget *ui; @@ -215,11 +220,15 @@ if (trackShapeSelection) { d->shapeChangedAcyclicConnector.connectBackwardVoid( d->canvas->selectedShapesProxy(), SIGNAL(selectionChanged()), - this, SLOT(shapeChanged())); + &d->shapeChangedCompressor, SLOT(start())); d->shapeChangedAcyclicConnector.connectBackwardVoid( d->canvas->selectedShapesProxy(), SIGNAL(selectionContentChanged()), - this, SLOT(shapeChanged())); + &d->shapeChangedCompressor, SLOT(start())); + + + connect(&d->shapeChangedCompressor, SIGNAL(timeout()), this, SLOT(shapeChanged())); + } d->resourceManagerAcyclicConnector.connectBackwardResourcePair( @@ -328,7 +337,7 @@ d->deactivationLocks.clear(); if (!d->noSelectionTrackingMode) { - shapeChanged(); + d->shapeChangedCompressor.start(); } else { loadCurrentFillFromResourceServer(); } @@ -345,14 +354,14 @@ void KoFillConfigWidget::forceUpdateOnSelectionChanged() { - shapeChanged(); + d->shapeChangedCompressor.start(); } void KoFillConfigWidget::setNoSelectionTrackingMode(bool value) { d->noSelectionTrackingMode = value; if (!d->noSelectionTrackingMode) { - shapeChanged(); + d->shapeChangedCompressor.start(); } } @@ -477,6 +486,15 @@ d->canvas->addCommand(command); } + + if (d->fillVariant == KoFlake::StrokeFill) { + KUndo2Command *lineCommand = wrapper.setLineWidth(0.0); + if (lineCommand) { + d->canvas->addCommand(lineCommand); + } + } + + emit sigFillChanged(); } @@ -722,86 +740,68 @@ QList shapes = currentShapes(); + // check to see if the shape actually changed...or is still the same shape + if (d->previousShapeSelected == shapes) { + return; + } else { + d->previousShapeSelected = shapes; + } + + if (shapes.isEmpty() || (shapes.size() > 1 && KoShapeFillWrapper(shapes, d->fillVariant).isMixedFill())) { Q_FOREACH (QAbstractButton *button, d->group->buttons()) { button->setEnabled(!shapes.isEmpty()); } - - d->group->button(None)->setChecked(true); - d->selectedFillIndex = None; - } else { + // only one vector object selected Q_FOREACH (QAbstractButton *button, d->group->buttons()) { button->setEnabled(true); } + // update active index of shape KoShape *shape = shapes.first(); - updateWidget(shape); + updateFillIndexFromShape(shape); } -} -bool KoFillConfigWidget::checkNewFillModeIsSame(const KoShapeFillWrapper &w) const -{ - bool retval = false; - switch (w.type()) { - case KoFlake::None: - retval = d->selectedFillIndex == None; - break; - case KoFlake::Solid: - retval = d->selectedFillIndex == Solid && w.color() == d->colorAction->currentColor(); - break; - case KoFlake::Gradient: { - QScopedPointer newGradient(KoStopGradient::fromQGradient(w.gradient())); - - retval = d->selectedFillIndex == Gradient && *newGradient == *d->activeGradient; - break; - } - case KoFlake::Pattern: - // TODO: not implemented - retval = d->selectedFillIndex == Pattern && false; - break; - } + // updates the UI + d->group->button(d->selectedFillIndex)->setChecked(true); + styleButtonPressed(d->selectedFillIndex); + slotUpdateFillTitle(); + updateWidgetComponentVisbility(); - return retval; } -void KoFillConfigWidget::updateWidget(KoShape *shape) +void KoFillConfigWidget::updateFillIndexFromShape(KoShape *shape) { KIS_SAFE_ASSERT_RECOVER_RETURN(shape); - StyleButton newActiveButton = None; KoShapeFillWrapper wrapper(shape, d->fillVariant); - if (checkNewFillModeIsSame(wrapper)) return; - switch (wrapper.type()) { - case KoFlake::None: - break; - case KoFlake::Solid: { - QColor color = wrapper.color(); - if (color.alpha() > 0) { - newActiveButton = KoFillConfigWidget::Solid; - d->colorAction->setCurrentColor(wrapper.color()); + case KoFlake::None: + d->selectedFillIndex = KoFillConfigWidget::None; + break; + case KoFlake::Solid: { + d->selectedFillIndex = KoFillConfigWidget::Solid; + QColor color = wrapper.color(); + if (color.alpha() > 0) { + d->colorAction->setCurrentColor(wrapper.color()); + } + break; } - break; - } - case KoFlake::Gradient: - newActiveButton = KoFillConfigWidget::Gradient; - uploadNewGradientBackground(wrapper.gradient()); - updateGradientSaveButtonAvailability(); - break; - case KoFlake::Pattern: - newActiveButton = KoFillConfigWidget::Pattern; - break; + case KoFlake::Gradient: + d->selectedFillIndex = KoFillConfigWidget::Gradient; + uploadNewGradientBackground(wrapper.gradient()); + updateGradientSaveButtonAvailability(); + break; + case KoFlake::Pattern: + d->selectedFillIndex = KoFillConfigWidget::Pattern; + break; } - d->group->button(newActiveButton)->setChecked(true); - - d->selectedFillIndex = newActiveButton; - updateWidgetComponentVisbility(); } @@ -824,6 +824,11 @@ d->ui->soldStrokeColorLabel->setVisible(false); d->ui->presetLabel->setVisible(false); + // keep options hidden if no vector shapes are selected + if(currentShapes().isEmpty()) { + return; + } + switch (d->selectedFillIndex) { case KoFillConfigWidget::None: break; diff --git a/libs/ui/widgets/KoStrokeConfigWidget.cpp b/libs/ui/widgets/KoStrokeConfigWidget.cpp --- a/libs/ui/widgets/KoStrokeConfigWidget.cpp +++ b/libs/ui/widgets/KoStrokeConfigWidget.cpp @@ -69,6 +69,7 @@ #include #include "kis_canvas_resource_provider.h" #include "kis_acyclic_signal_connector.h" +#include // Krita #include "kis_double_parse_unit_spin_box.h" @@ -169,7 +170,8 @@ active(true), allowLocalUnitManagement(true), fillConfigWidget(0), - noSelectionTrackingMode(false) + noSelectionTrackingMode(false), + selectionChangedCompressor(200, KisSignalCompressor::FIRST_ACTIVE) { } @@ -193,6 +195,8 @@ KisAcyclicSignalConnector shapeChangedAcyclicConnector; KisAcyclicSignalConnector resourceManagerAcyclicConnector; + KisSignalCompressor selectionChangedCompressor; + std::vector deactivationLocks; @@ -213,11 +217,13 @@ { // connect the canvas d->shapeChangedAcyclicConnector.connectBackwardVoid( canvas->selectedShapesProxy(), SIGNAL(selectionChanged()), - this, SLOT(selectionChanged())); + &d->selectionChangedCompressor, SLOT(start())); d->shapeChangedAcyclicConnector.connectBackwardVoid( canvas->selectedShapesProxy(), SIGNAL(selectionContentChanged()), - this, SLOT(selectionChanged())); + &d->selectionChangedCompressor, SLOT(start())); + + connect(&d->selectionChangedCompressor, SIGNAL(timeout()), this, SLOT(selectionChanged())); d->resourceManagerAcyclicConnector.connectBackwardResourcePair( canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), @@ -226,10 +232,9 @@ d->canvas = canvas; } - { - d->fillConfigWidget = new KoFillConfigWidget(canvas, KoFlake::StrokeFill, false, this); + d->fillConfigWidget = new KoFillConfigWidget(canvas, KoFlake::StrokeFill, true, this); d->fillConfigWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); d->ui->fillConfigWidgetLayout->addWidget(d->fillConfigWidget); connect(d->fillConfigWidget, SIGNAL(sigFillChanged()), SIGNAL(sigStrokeChanged())); @@ -239,7 +244,7 @@ d->ui->thicknessLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // set min/max/step and value in points, then set actual unit - d->ui->lineWidth->setMinMaxStep(0.0, 1000.0, 0.5); + d->ui->lineWidth->setMinMaxStep(0.5, 1000.0, 0.5); // if someone wants 0, just set to "none" on UI d->ui->lineWidth->setDecimals(2); d->ui->lineWidth->setUnit(KoUnit(KoUnit::Point)); d->ui->lineWidth->setToolTip(i18n("Set line width of actual selection")); @@ -322,7 +327,7 @@ } } - selectionChanged(); + d->selectionChangedCompressor.start(); d->fillConfigWidget->activate(); deactivate(); @@ -338,7 +343,7 @@ d->fillConfigWidget->setNoSelectionTrackingMode(value); d->noSelectionTrackingMode = value; if (!d->noSelectionTrackingMode) { - selectionChanged(); + d->selectionChangedCompressor.start(); } } @@ -465,7 +470,8 @@ d->fillConfigWidget->activate(); if (!d->noSelectionTrackingMode) { - selectionChanged(); + // selectionChanged(); + d->selectionChangedCompressor.start(); } else { loadCurrentStrokeFillFromResourceServer(); } @@ -668,11 +674,11 @@ // we need to linearize update order, and force the child widget to update // before we start doing it - d->fillConfigWidget->forceUpdateOnSelectionChanged(); - QList shapes = selection->selectedEditableShapes(); + d->fillConfigWidget->forceUpdateOnSelectionChanged(); // calls shapeChanged() logic + KoShape *shape = !shapes.isEmpty() ? shapes.first() : 0; const KoShapeStrokeSP stroke = shape ? qSharedPointerDynamicCast(shape->stroke()) : KoShapeStrokeSP(); @@ -781,7 +787,7 @@ case KoCanvasResourceProvider::Unit: // we request the whole selection to reload because the // unit of the stroke width depends on the selected shape - selectionChanged(); + d->selectionChangedCompressor.start(); break; case KisCanvasResourceProvider::Size: if (d->noSelectionTrackingMode) {