Move selected layers into the new group

If the Timeline has an active selected range of layers and the user
creates a new layer group, the selected layers will be be grouped as
children of the new layer 'group'.
This commit is contained in:
David Capello 2016-06-21 00:02:13 -03:00
parent 139b8f6d74
commit 0f77bf0712
13 changed files with 117 additions and 35 deletions

View File

@ -66,8 +66,7 @@ void AddLayer::onRedo()
void AddLayer::addLayer(Layer* group, Layer* newLayer, Layer* afterThis)
{
static_cast<LayerGroup*>(group)->addLayer(newLayer);
static_cast<LayerGroup*>(group)->stackLayer(newLayer, afterThis);
static_cast<LayerGroup*>(group)->insertLayer(newLayer, afterThis);
group->incrementVersion();
Document* doc = group->sprite()->document();

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -15,6 +15,7 @@
#include "app/cmd/set_layer_flags.h"
#include "app/cmd/set_layer_name.h"
#include "app/cmd/set_layer_opacity.h"
#include "doc/sprite.h"
namespace app {
namespace cmd {
@ -33,7 +34,7 @@ ConfigureBackground::ConfigureBackground(Layer* layer)
add(new cmd::SetLayerOpacity(static_cast<LayerImage*>(layer), 255));
}
add(new cmd::MoveLayer(layer, nullptr));
add(new cmd::MoveLayer(layer, layer->sprite()->root(), nullptr));
}
} // namespace cmd

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -21,29 +21,51 @@ namespace cmd {
using namespace doc;
MoveLayer::MoveLayer(Layer* layer, Layer* afterThis)
MoveLayer::MoveLayer(Layer* layer,
Layer* newParent,
Layer* afterThis)
: m_layer(layer)
, m_oldParent(layer->parent())
, m_oldAfterThis(layer->getPrevious())
, m_newAfterThis(afterThis)
, m_newParent(newParent)
, m_newAfterThis(afterThis == layer ? afterThis->getPrevious(): afterThis)
{
}
void MoveLayer::onExecute()
{
m_layer.layer()->parent()->stackLayer(
m_layer.layer(),
m_newAfterThis.layer());
Layer* layer = m_layer.layer();
Layer* afterThis = m_newAfterThis.layer();
LayerGroup* oldParent = static_cast<LayerGroup*>(m_oldParent.layer());
LayerGroup* newParent = static_cast<LayerGroup*>(m_newParent.layer());
ASSERT(layer);
ASSERT(oldParent);
ASSERT(newParent);
m_layer.layer()->parent()->incrementVersion();
oldParent->removeLayer(layer);
newParent->insertLayer(layer, afterThis);
if (oldParent != newParent)
oldParent->incrementVersion();
newParent->incrementVersion();
}
void MoveLayer::onUndo()
{
m_layer.layer()->parent()->stackLayer(
m_layer.layer(),
m_oldAfterThis.layer());
Layer* layer = m_layer.layer();
Layer* afterThis = m_oldAfterThis.layer();
LayerGroup* oldParent = static_cast<LayerGroup*>(m_oldParent.layer());
LayerGroup* newParent = static_cast<LayerGroup*>(m_newParent.layer());
ASSERT(layer);
ASSERT(oldParent);
ASSERT(newParent);
m_layer.layer()->parent()->incrementVersion();
newParent->removeLayer(layer);
oldParent->insertLayer(layer, afterThis);
if (oldParent != newParent)
oldParent->incrementVersion();
newParent->incrementVersion();
}
void MoveLayer::onFireNotifications()

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -18,7 +18,9 @@ namespace cmd {
class MoveLayer : public Cmd {
public:
MoveLayer(Layer* layer, Layer* afterThis);
MoveLayer(Layer* layer,
Layer* newParent,
Layer* afterThis);
protected:
void onExecute() override;
@ -30,8 +32,8 @@ namespace cmd {
private:
WithLayer m_layer;
WithLayer m_oldAfterThis;
WithLayer m_newAfterThis;
WithLayer m_oldParent, m_oldAfterThis;
WithLayer m_newParent, m_newAfterThis;
};
} // namespace cmd

View File

@ -50,11 +50,8 @@ protected:
int i = m_offset;
while (i-- > 0) {
layer = layer->getNextInWholeHierarchy();
if (!layer) {
layer = site.sprite()->root()->firstLayer();
while (layer->isBrowsable())
layer = static_cast<LayerGroup*>(layer)->firstLayer();
}
if (!layer)
layer = site.sprite()->firstBrowsableLayer();
}
}
else if (m_offset < 0) {

View File

@ -10,6 +10,7 @@
#endif
#include "app/app.h"
#include "app/cmd/move_layer.h"
#include "app/commands/command.h"
#include "app/commands/params.h"
#include "app/context_access.h"
@ -107,6 +108,7 @@ void NewLayerCommand::onExecute(Context* context)
LayerGroup* parent = sprite->root();
Layer* activeLayer = writer.layer();
SelectedLayers selLayers = writer.site()->selectedLayers();
if (activeLayer) {
if (activeLayer->isGroup() &&
activeLayer->isExpanded() &&
@ -131,11 +133,35 @@ void NewLayerCommand::onExecute(Context* context)
else
layer = api.newLayer(parent, name);
ASSERT(layer->parent());
// If "top" parameter is false, create the layer above the active
// one.
if (activeLayer && !m_top)
if (activeLayer && !m_top) {
api.restackLayerAfter(layer, activeLayer);
// Put all selected layers inside the group
if (m_group && writer.site()->inTimeline()) {
LayerGroup* commonParent = nullptr;
std::size_t sameParents = 0;
for (Layer* l : selLayers) {
if (!commonParent ||
commonParent == l->parent()) {
commonParent = l->parent();
++sameParents;
}
}
if (sameParents == selLayers.size()) {
for (Layer* newChild : convert_selected_layers_into_layer_list(selLayers)) {
transaction.execute(
new cmd::MoveLayer(newChild, layer,
static_cast<LayerGroup*>(layer)->lastLayer()));
}
}
}
}
transaction.commit();
}
update_screen_for_document(document);

View File

@ -425,7 +425,7 @@ void DocumentApi::removeLayer(Layer* layer)
void DocumentApi::restackLayerAfter(Layer* layer, Layer* afterThis)
{
m_transaction.execute(new cmd::MoveLayer(layer, afterThis));
m_transaction.execute(new cmd::MoveLayer(layer, layer->parent(), afterThis));
}
void DocumentApi::restackLayerBefore(Layer* layer, Layer* beforeThis)

View File

@ -378,16 +378,8 @@ void LayerGroup::removeLayer(Layer* layer)
layer->setParent(nullptr);
}
void LayerGroup::stackLayer(Layer* layer, Layer* after)
void LayerGroup::insertLayer(Layer* layer, Layer* after)
{
ASSERT(layer != after);
if (layer == after)
return;
auto it = std::find(m_layers.begin(), m_layers.end(), layer);
ASSERT(it != m_layers.end());
m_layers.erase(it);
if (after) {
auto after_it = std::find(m_layers.begin(), m_layers.end(), after);
ASSERT(after_it != m_layers.end());
@ -396,6 +388,18 @@ void LayerGroup::stackLayer(Layer* layer, Layer* after)
}
else
m_layers.insert(m_layers.begin(), layer);
layer->setParent(this);
}
void LayerGroup::stackLayer(Layer* layer, Layer* after)
{
ASSERT(layer != after);
if (layer == after)
return;
removeLayer(layer);
insertLayer(layer, after);
}
void LayerGroup::displaceFrames(frame_t fromThis, frame_t delta)

View File

@ -180,6 +180,7 @@ namespace doc {
void addLayer(Layer* layer);
void removeLayer(Layer* layer);
void insertLayer(Layer* layer, Layer* after);
void stackLayer(Layer* layer, Layer* after);
Layer* firstLayer() const { return (m_layers.empty() ? nullptr: m_layers.front()); }

View File

@ -11,6 +11,7 @@
#include "doc/selected_layers.h"
#include "doc/layer.h"
#include "doc/sprite.h"
namespace doc {
@ -43,4 +44,22 @@ void select_all_layers(LayerGroup* group, SelectedLayers& layers)
}
}
LayerList convert_selected_layers_into_layer_list(const SelectedLayers& layers)
{
LayerList output;
if (layers.empty())
return output;
for (Layer* layer = (*layers.begin())->sprite()->firstBrowsableLayer();
layer != nullptr;
layer = layer->getNextInWholeHierarchy()) {
if (layers.find(layer) != layers.end()) {
output.push_back(layer);
}
}
return output;
}
} // namespace doc

View File

@ -9,6 +9,7 @@
#pragma once
#include <set>
#include "layer_list.h"
namespace doc {
@ -19,6 +20,7 @@ namespace doc {
void remove_children_if_parent_is_selected(SelectedLayers& layers);
void select_all_layers(LayerGroup* group, SelectedLayers& layers);
LayerList convert_selected_layers_into_layer_list(const SelectedLayers& layers);
} // namespace doc

View File

@ -223,6 +223,14 @@ LayerIndex Sprite::firstLayer() const
return LayerIndex(0);
}
Layer* Sprite::firstBrowsableLayer() const
{
Layer* layer = root()->firstLayer();
while (layer->isBrowsable())
layer = static_cast<LayerGroup*>(layer)->firstLayer();
return layer;
}
LayerIndex Sprite::lastLayer() const
{
return LayerIndex(root()->layersCount()-1);

View File

@ -95,6 +95,7 @@ namespace doc {
LayerIndex countLayers() const;
LayerIndex firstLayer() const;
Layer* firstBrowsableLayer() const;
LayerIndex lastLayer() const;
Layer* layer(int layerIndex) const;