Skip to content

Commit

Permalink
Refactored ImageLayer and ObjectGroup undo commands
Browse files Browse the repository at this point in the history
The undo commands affecting ImageLayer and ObjectGroup properties are
now based on the "ChangeValue" command as well.

The "ChangeValue" command was improved to be able to change the value of
multiple objects at once, which also resolves the problem where toggling
for example the visibility of a set of layers on and off would fail to
mark the undo command as obsolete.

Part of issue #3103
  • Loading branch information
bjorn committed Jan 26, 2022
1 parent 93eb250 commit 5eaad3e
Show file tree
Hide file tree
Showing 24 changed files with 602 additions and 555 deletions.
22 changes: 20 additions & 2 deletions src/tiled/changeevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#pragma once

#include "imagelayer.h"
#include "map.h"
#include "mapobject.h"
#include "wangset.h"
Expand All @@ -38,6 +39,7 @@ class ChangeEvent
MapChanged,
LayerChanged,
TileLayerChanged,
ImageLayerChanged,
MapObjectAboutToBeAdded,
MapObjectAboutToBeRemoved,
MapObjectAdded,
Expand Down Expand Up @@ -111,14 +113,30 @@ class TileLayerChangeEvent : public LayerChangeEvent
{
public:
enum TileLayerProperty {
SizeProperty = 1 << 5,
SizeProperty = 1 << 7,
};

TileLayerChangeEvent(TileLayer *tileLayer, int properties)
: LayerChangeEvent(TileLayerChanged, tileLayer, properties)
{}

TileLayer *tileLayer() { return static_cast<TileLayer*>(layer); }
TileLayer *tileLayer() const { return static_cast<TileLayer*>(layer); }
};

class ImageLayerChangeEvent : public LayerChangeEvent
{
public:
enum TileLayerProperty {
TransparentColorProperty = 1 << 7,
ImageSourceProperty = 1 << 8,
RepeatProperty = 1 << 9,
};

ImageLayerChangeEvent(ImageLayer *imageLayer, int properties)
: LayerChangeEvent(ImageLayerChanged, imageLayer, properties)
{}

ImageLayer *imageLayer() const { return static_cast<ImageLayer*>(layer); }
};

class ObjectGroupChangeEvent : public ChangeEvent
Expand Down
159 changes: 80 additions & 79 deletions src/tiled/changeimagelayerproperty.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* changeimagelayerproperty.cpp
* Copyright 2010, Jeff Bland <jksb@member.fsf.org>
* Copyright 2010, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
* Copyright 2011, Gregory Nickonov <gregory@nickonov.ru>
* Copyright 2010-2022, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
*
* This file is part of Tiled.
*
Expand All @@ -22,102 +22,103 @@

#include "changeimagelayerproperty.h"

#include "mapdocument.h"
#include "changeevents.h"
#include "document.h"
#include "imagelayer.h"

#include <QCoreApplication>

using namespace Tiled;

ChangeImageLayerProperty::ChangeImageLayerProperty(
MapDocument *mapDocument,
ImageLayer *imageLayer,
const QColor transparentColor)
: QUndoCommand(QCoreApplication::translate("Undo Commands",
"Change Image Layer Transparent Color"))
, mMapDocument(mapDocument)
, mImageLayer(imageLayer)
, mProperty(TransparentColorProperty)
, mTransparentColor(transparentColor)
namespace Tiled {

ChangeImageLayerTransparentColor::ChangeImageLayerTransparentColor(Document *document,
QList<ImageLayer *> imageLayers,
const QColor &newColor)
: ChangeValue<ImageLayer, QColor>(document, std::move(imageLayers), newColor)
{
setText(QCoreApplication::translate("Undo Commands",
"Change Object Layer Transparent Color"));
}

QColor ChangeImageLayerTransparentColor::getValue(const ImageLayer *imageLayer) const
{
return imageLayer->transparentColor();
}

void ChangeImageLayerTransparentColor::setValue(ImageLayer *imageLayer, const QColor &value) const
{
imageLayer->setTransparentColor(value);

if (imageLayer->imageSource().isEmpty())
imageLayer->resetImage();
else
imageLayer->loadFromImage(imageLayer->imageSource());

emit document()->changed(ImageLayerChangeEvent(imageLayer, ImageLayerChangeEvent::TransparentColorProperty));
}


ChangeImageLayerImageSource::ChangeImageLayerImageSource(Document *document, QList<ImageLayer *> imageLayers, const QUrl &imageSource)
: ChangeValue<ImageLayer, QUrl>(document, std::move(imageLayers), imageSource)
{
setText(QCoreApplication::translate("Undo Commands",
"Change Object Layer Image Source"));
}

ChangeImageLayerProperty::ChangeImageLayerProperty(
MapDocument *mapDocument,
ImageLayer *imageLayer,
const QUrl &imageSource)
: QUndoCommand(QCoreApplication::translate("Undo Commands",
"Change Image Layer Image Source"))
, mMapDocument(mapDocument)
, mImageLayer(imageLayer)
, mProperty(ImageSourceProperty)
, mImageSource(imageSource)
QUrl ChangeImageLayerImageSource::getValue(const ImageLayer *imageLayer) const
{
return imageLayer->imageSource();
}

ChangeImageLayerProperty::ChangeImageLayerProperty(
MapDocument *mapDocument,
ImageLayer *imageLayer,
ChangeImageLayerProperty::Property property,
bool repeat)
: QUndoCommand(QCoreApplication::translate("Undo Commands",
"Change Image Layer Repeat Property"))
, mMapDocument(mapDocument)
, mImageLayer(imageLayer)
, mProperty(property)
, mRepeat(repeat)
void ChangeImageLayerImageSource::setValue(ImageLayer *imageLayer, const QUrl &value) const
{
if (value.isEmpty())
imageLayer->resetImage();
else
imageLayer->loadFromImage(value);

emit document()->changed(ImageLayerChangeEvent(imageLayer, ImageLayerChangeEvent::ImageSourceProperty));
}

void ChangeImageLayerProperty::redo()

ChangeImageLayerRepeatX::ChangeImageLayerRepeatX(Document *document,
QList<ImageLayer *> imageLayers,
bool repeatX)
: ChangeValue<ImageLayer, bool>(document, std::move(imageLayers), repeatX)
{
swap();
setText(QCoreApplication::translate("Undo Commands",
"Change Image Layer Repeat"));
}

void ChangeImageLayerProperty::undo()
bool ChangeImageLayerRepeatX::getValue(const ImageLayer *imageLayer) const
{
swap();
return imageLayer->repeatX();
}

void ChangeImageLayerProperty::swap()
void ChangeImageLayerRepeatX::setValue(ImageLayer *imageLayer, const bool &value) const
{
switch (mProperty) {
case TransparentColorProperty: {
const QColor color = mImageLayer->transparentColor();
mImageLayer->setTransparentColor(mTransparentColor);
mTransparentColor = color;

if (mImageSource.isEmpty())
mImageLayer->resetImage();
else
mImageLayer->loadFromImage(mImageSource);

break;
}
case ImageSourceProperty: {
const QUrl source = mImageLayer->imageSource();

if (mImageSource.isEmpty())
mImageLayer->resetImage();
else
mImageLayer->loadFromImage(mImageSource);

mImageSource = source;
break;
}
case RepeatXProperty: {
const bool repeatX = mImageLayer->repeatX();
mImageLayer->setRepeatX(mRepeat);
mRepeat = repeatX;
break;
}
case RepeatYProperty: {
const bool repeatY = mImageLayer->repeatY();
mImageLayer->setRepeatY(mRepeat);
mRepeat = repeatY;
break;
}
}

emit mMapDocument->imageLayerChanged(mImageLayer);
imageLayer->setRepeatX(value);
emit document()->changed(ImageLayerChangeEvent(imageLayer, ImageLayerChangeEvent::RepeatProperty));
}


ChangeImageLayerRepeatY::ChangeImageLayerRepeatY(Document *document,
QList<ImageLayer *> imageLayers,
bool repeatY)
: ChangeValue<ImageLayer, bool>(document, std::move(imageLayers), repeatY)
{
setText(QCoreApplication::translate("Undo Commands",
"Change Image Layer Repeat"));
}

bool ChangeImageLayerRepeatY::getValue(const ImageLayer *imageLayer) const
{
return imageLayer->repeatY();
}

void ChangeImageLayerRepeatY::setValue(ImageLayer *imageLayer, const bool &value) const
{
imageLayer->setRepeatY(value);
emit document()->changed(ImageLayerChangeEvent(imageLayer, ImageLayerChangeEvent::RepeatProperty));
}

} // namespace Tiled
109 changes: 49 additions & 60 deletions src/tiled/changeimagelayerproperty.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* changeimagelayerproperty.h
* Copyright 2010, Jeff Bland <jksb@member.fsf.org>
* Copyright 2010, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
* Copyright 2011, Gregory Nickonov <gregory@nickonov.ru>
* Copyright 2010-2022, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
*
* This file is part of Tiled.
*
Expand All @@ -22,77 +22,66 @@

#pragma once

#include "changevalue.h"
#include "undocommands.h"

#include <QColor>
#include <QUndoCommand>
#include <QUrl>

namespace Tiled {

class ImageLayer;

class MapDocument;
class ChangeImageLayerTransparentColor : public ChangeValue<ImageLayer, QColor>
{
public:
ChangeImageLayerTransparentColor(Document *document,
QList<ImageLayer *> imageLayers,
const QColor &newColor);

private:
QColor getValue(const ImageLayer *imageLayer) const override;
void setValue(ImageLayer *imageLayer, const QColor &value) const override;
};

class ChangeImageLayerImageSource : public ChangeValue<ImageLayer, QUrl>
{
public:
ChangeImageLayerImageSource(Document *document,
QList<ImageLayer *> imageLayers,
const QUrl &imageSource);

private:
QUrl getValue(const ImageLayer *imageLayer) const override;
void setValue(ImageLayer *imageLayer, const QUrl &value) const override;
};

class ChangeImageLayerRepeatX : public ChangeValue<ImageLayer, bool>
{
public:
ChangeImageLayerRepeatX(Document *document,
QList<ImageLayer *> imageLayers,
bool repeatX);

class ChangeImageLayerProperty : public QUndoCommand
int id() const override { return Cmd_ChangeImageLayerRepeatX; }

private:
bool getValue(const ImageLayer *imageLayer) const override;
void setValue(ImageLayer *imageLayer, const bool &value) const override;
};

class ChangeImageLayerRepeatY : public ChangeValue<ImageLayer, bool>
{
public:
enum Property {
TransparentColorProperty,
ImageSourceProperty,
RepeatXProperty,
RepeatYProperty
};

/**
* Constructs a command that changes the transparent color.
*
* @param mapDocument the map document of the image layer's map
* @param imageLayer the image layer to modify
* @param transparentColor the new transparent color to apply
*/
ChangeImageLayerProperty(MapDocument *mapDocument,
ImageLayer *imageLayer,
const QColor transparentColor);

/**
* Constructs a command that changes the image source.
*
* @param mapDocument the map document of the image layer's map
* @param imageLayer the image layer to modify
* @param repeat the new image source to apply
*/
ChangeImageLayerProperty(MapDocument *mapDocument,
ImageLayer *imageLayer,
const QUrl &imageSource);

/**
* Constructs a command that changes the repetition along an axis.
*
* Can only be used for the properties RepeatXProperty and RepeatYProperty.
*
* @param mapDocument the map document of the image layer's map
* @param imageLayer the image layer to modify
* @param property the image layer property to modify
* @param repeat the new repetition along an axis to apply
*/
ChangeImageLayerProperty(MapDocument *mapDocument,
ImageLayer *imageLayer,
ChangeImageLayerProperty::Property property,
bool repeat);

void undo() override;
void redo() override;
ChangeImageLayerRepeatY(Document *document,
QList<ImageLayer *> imageLayers,
bool repeatY);

int id() const override { return Cmd_ChangeImageLayerRepeatY; }

private:
void swap();

MapDocument *mMapDocument;
ImageLayer *mImageLayer;
Property mProperty;
QUrl mImageSource;
union {
QColor mTransparentColor;
bool mRepeat;
};
bool getValue(const ImageLayer *imageLayer) const override;
void setValue(ImageLayer *imageLayer, const bool &value) const override;
};

} // namespace Tiled
Loading

0 comments on commit 5eaad3e

Please sign in to comment.