Simplify Workspace implementation removing the possibility to split views/tabs

It's confusing to see two tabs when we split the view. In the future we
should be able to move tabs to create a split view.
This commit is contained in:
David Capello 2015-03-04 17:23:40 -03:00
parent b7f69186bb
commit 200e612670
9 changed files with 28 additions and 429 deletions

View File

@ -87,9 +87,6 @@
<key command="InvertMask" shortcut="Ctrl+Shift+I" mac="Cmd+Shift+I" />
<!-- View -->
<key command="Refresh" shortcut="F5" />
<key command="MakeUniqueEditor" shortcut="Ctrl+1" mac="Cmd+1" />
<key command="SplitEditorVertically" shortcut="Ctrl+2" mac="Cmd+2" />
<key command="SplitEditorHorizontally" shortcut="Ctrl+3" mac="Cmd+3" />
<key command="TogglePreview" shortcut="F7" />
<key command="FullscreenPreview" shortcut="F8" />
<key command="ShowGrid" shortcut="Shift+G" />
@ -558,10 +555,6 @@
<item command="SaveMask" text="&amp;Save to MSK file" />
</menu>
<menu text="&amp;View">
<item command="MakeUniqueEditor" text="Make &amp;Unique" />
<item command="SplitEditorVertically" text="Split &amp;Vertically" />
<item command="SplitEditorHorizontally" text="Split &amp;Horizontally" />
<separator />
<item command="ShowPixelGrid" text="Show &amp;Pixel Grid" />
<item command="ShowGrid" text="Show &amp;Grid" />
<item command="SnapToGrid" text="&amp;Snap to Grid" />

View File

@ -190,7 +190,6 @@ add_library(app-lib
commands/cmd_scroll.cpp
commands/cmd_set_loop_section.cpp
commands/cmd_set_palette.cpp
commands/cmd_sprite_editor.cpp
commands/cmd_sprite_properties.cpp
commands/cmd_sprite_size.cpp
commands/cmd_switch_colors.cpp
@ -332,7 +331,6 @@ add_library(app-lib
ui/timeline.cpp
ui/toolbar.cpp
ui/workspace.cpp
ui/workspace_part.cpp
ui_context.cpp
util/autocrop.cpp
util/boundary.cpp

View File

@ -1,104 +0,0 @@
// Aseprite
// Copyright (C) 2001-2015 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
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/app.h"
#include "app/commands/command.h"
#include "app/ui/main_window.h"
#include "app/ui/workspace.h"
#include "ui/base.h"
namespace app {
class MakeUniqueEditorCommand : public Command {
public:
MakeUniqueEditorCommand();
Command* clone() const override { return new MakeUniqueEditorCommand(*this); }
protected:
void onExecute(Context* context);
};
MakeUniqueEditorCommand::MakeUniqueEditorCommand()
: Command("MakeUniqueEditor",
"Make Unique Editor",
CmdUIOnlyFlag)
{
}
void MakeUniqueEditorCommand::onExecute(Context* context)
{
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->activeView() != NULL)
workspace->makeUnique(workspace->activeView());
}
class SplitEditorHorizontallyCommand : public Command {
public:
SplitEditorHorizontallyCommand();
Command* clone() const override { return new SplitEditorHorizontallyCommand(*this); }
protected:
void onExecute(Context* context);
};
SplitEditorHorizontallyCommand::SplitEditorHorizontallyCommand()
: Command("SplitEditorHorizontally",
"Split Editor Horizontally",
CmdUIOnlyFlag)
{
}
void SplitEditorHorizontallyCommand::onExecute(Context* context)
{
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->activeView() != NULL)
workspace->splitView(workspace->activeView(), JI_HORIZONTAL);
}
class SplitEditorVerticallyCommand : public Command {
public:
SplitEditorVerticallyCommand();
Command* clone() const override { return new SplitEditorVerticallyCommand(*this); }
protected:
void onExecute(Context* context);
};
SplitEditorVerticallyCommand::SplitEditorVerticallyCommand()
: Command("SplitEditorVertically",
"Split Editor Vertically",
CmdUIOnlyFlag)
{
}
void SplitEditorVerticallyCommand::onExecute(Context* context)
{
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
if (workspace->activeView() != NULL)
workspace->splitView(workspace->activeView(), JI_VERTICAL);
}
Command* CommandFactory::createMakeUniqueEditorCommand()
{
return new MakeUniqueEditorCommand;
}
Command* CommandFactory::createSplitEditorHorizontallyCommand()
{
return new SplitEditorHorizontallyCommand;
}
Command* CommandFactory::createSplitEditorVerticallyCommand()
{
return new SplitEditorVerticallyCommand;
}
} // namespace app

View File

@ -59,7 +59,6 @@ FOR_EACH_COMMAND(LayerProperties)
FOR_EACH_COMMAND(LayerVisibility)
FOR_EACH_COMMAND(LoadMask)
FOR_EACH_COMMAND(LoadPalette)
FOR_EACH_COMMAND(MakeUniqueEditor)
FOR_EACH_COMMAND(MaskAll)
FOR_EACH_COMMAND(MaskByColor)
FOR_EACH_COMMAND(MaskContent)
@ -98,8 +97,6 @@ FOR_EACH_COMMAND(ShowGrid)
FOR_EACH_COMMAND(ShowOnionSkin)
FOR_EACH_COMMAND(ShowPixelGrid)
FOR_EACH_COMMAND(SnapToGrid)
FOR_EACH_COMMAND(SplitEditorHorizontally)
FOR_EACH_COMMAND(SplitEditorVertically)
FOR_EACH_COMMAND(SpriteProperties)
FOR_EACH_COMMAND(SpriteSize)
FOR_EACH_COMMAND(SwitchColors)

View File

@ -201,7 +201,7 @@ void Tabs::selectPreviousTab()
TabView* Tabs::getSelectedTab()
{
if (m_selected != NULL)
if (m_selected)
return m_selected->view;
else
return NULL;

View File

@ -13,11 +13,10 @@
#include "app/app.h"
#include "app/ui/main_window.h"
#include "app/ui/tabs.h"
#include "app/ui/workspace_part.h"
#include "app/ui/workspace_view.h"
#include "app/ui/skin/skin_theme.h"
#include "ui/splitter.h"
#include "app/ui/tabs.h"
#include "app/ui/workspace_view.h"
#include "base/remove_from_container.h"
#include <algorithm>
#include <queue>
@ -28,13 +27,11 @@ using namespace app::skin;
using namespace ui;
Workspace::Workspace()
: Box(JI_VERTICAL)
, m_activePart(new WorkspacePart)
: Widget(kGenericWidget)
, m_activeView(nullptr)
{
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
setBgColor(theme->colors.workspace());
addChild(m_activePart);
}
Workspace::~Workspace()
@ -47,32 +44,24 @@ void Workspace::addView(WorkspaceView* view)
{
m_views.push_back(view);
m_activePart->addView(view);
App::instance()->getMainWindow()->getTabsBar()->addTab(dynamic_cast<TabView*>(view));
ActiveViewChanged(); // Fire ActiveViewChanged event
setActiveView(view);
}
void Workspace::removeView(WorkspaceView* view)
{
WorkspaceViews::iterator it = std::find(m_views.begin(), m_views.end(), view);
ASSERT(it != m_views.end());
m_views.erase(it);
base::remove_from_container(m_views, view);
WorkspacePart* part = getPartByView(view);
ASSERT(part != NULL);
part->removeView(view);
Widget* content = view->getContentWidget();
if (content->getParent())
content->getParent()->removeChild(content);
// Remove related tab
Tabs* tabs = App::instance()->getMainWindow()->getTabsBar();
tabs->removeTab(dynamic_cast<TabView*>(view));
TabView* tabView = tabs->getSelectedTab();
if (tabView)
setActiveView(dynamic_cast<WorkspaceView*>(tabView));
ActiveViewChanged(); // Fire ActiveViewChanged event
setActiveView(dynamic_cast<WorkspaceView*>(tabView));
}
bool Workspace::closeView(WorkspaceView* view)
@ -82,165 +71,25 @@ bool Workspace::closeView(WorkspaceView* view)
WorkspaceView* Workspace::activeView()
{
ASSERT(m_activePart != NULL);
return m_activePart->activeView();
return m_activeView;
}
void Workspace::setActiveView(WorkspaceView* view)
{
ASSERT(view != NULL);
m_activeView = view;
WorkspacePart* viewPart =
static_cast<WorkspacePart*>(view->getContentWidget()->getParent());
viewPart->setActiveView(view);
m_activePart = viewPart;
ActiveViewChanged(); // Fire ActiveViewChanged event
}
void Workspace::splitView(WorkspaceView* view, int orientation)
{
// Try to clone the workspace view.
WorkspaceView* newView = view->cloneWorkspaceView();
if (newView == NULL)
return;
// Get the part where the view-to-clone is located because we need
// to split this part.
WorkspacePart* viewPart =
static_cast<WorkspacePart*>(view->getContentWidget()->getParent());
// Create a new splitter to add new WorkspacePart on it: the given
// "viewPart" and a new part named "newPart".
Splitter* splitter = new Splitter(Splitter::ByPercentage, orientation);
splitter->setExpansive(true);
// Create the new part to contain the cloned view (see below, "newView").
WorkspacePart* newPart = new WorkspacePart();
// Replace the "viewPart" with the "splitter".
Widget* parent = viewPart->getParent();
parent->replaceChild(viewPart, splitter);
splitter->addChild(viewPart);
splitter->addChild(newPart);
// The new part is the active one.
m_activePart = newPart;
// Add the cloned view to the active part (newPart)
// using Workspace::addView().
addView(newView);
setActiveView(newView);
removeAllChildren();
if (view)
addChild(view->getContentWidget());
layout();
newView->onClonedFrom(view);
ActiveViewChanged(); // Fire ActiveViewChanged event
}
WorkspacePart* Workspace::destroyPart(WorkspacePart* part)
void Workspace::onPaint(PaintEvent& ev)
{
ASSERT(part != NULL);
ASSERT(part->getViewCount() == 0);
Widget* splitter = part->getParent();
ASSERT(splitter != this);
ASSERT(splitter->getChildren().size() == 2);
splitter->removeChild(part);
delete part;
ASSERT(splitter->getChildren().size() == 1);
Widget* otherWidget = splitter->getFirstChild();
WorkspacePart* otherPart = dynamic_cast<WorkspacePart*>(otherWidget);
if (otherPart == NULL) {
Widget* widget = otherWidget;
for (;;) {
otherPart = widget->findFirstChildByType<WorkspacePart>();
if (otherPart != NULL)
break;
widget = widget->getFirstChild();
}
}
ASSERT(otherPart != NULL);
splitter->removeChild(otherWidget);
splitter->getParent()->replaceChild(splitter, otherWidget);
delete splitter;
layout();
return otherPart;
}
void Workspace::makeUnique(WorkspaceView* view)
{
WorkspaceParts parts;
enumAllParts(parts);
for (WorkspaceParts::iterator it=parts.begin(), end=parts.end(); it != end; ++it) {
WorkspacePart* part = *it;
if (part->getParent() != this) {
while (part->activeView())
part->removeView(part->activeView());
}
}
for (WorkspaceParts::iterator it=parts.begin(), end=parts.end(); it != end; ++it) {
WorkspacePart* part = *it;
if (part->getParent() != this)
destroyPart(part);
}
WorkspacePart* uniquePart = dynamic_cast<WorkspacePart*>(getFirstChild());
ASSERT(uniquePart != NULL);
m_activePart = uniquePart;
for (WorkspaceViews::iterator it=m_views.begin(), end=m_views.end(); it != end; ++it) {
WorkspaceView* v = *it;
if (!v->getContentWidget()->getParent())
uniquePart->addView(v);
}
setActiveView(view);
}
WorkspacePart* Workspace::getPartByView(WorkspaceView* view)
{
WorkspaceParts parts;
enumAllParts(parts);
for (WorkspaceParts::iterator it=parts.begin(), end=parts.end(); it != end; ++it) {
WorkspacePart* part = *it;
if (part->hasView(view))
return part;
}
return NULL;
}
void Workspace::enumAllParts(WorkspaceParts& parts)
{
std::queue<Widget*> remaining;
remaining.push(getFirstChild());
while (!remaining.empty()) {
Widget* widget = remaining.front();
remaining.pop();
ASSERT(widget != NULL);
WorkspacePart* part = dynamic_cast<WorkspacePart*>(widget);
if (part) {
parts.push_back(part);
}
else {
UI_FOREACH_WIDGET(widget->getChildren(), it) {
remaining.push(*it);
}
}
}
ev.getGraphics()->fillRect(getBgColor(), getClientBounds());
}
} // namespace app

View File

@ -11,13 +11,14 @@
#include "app/ui/workspace_views.h"
#include "base/signal.h"
#include "ui/box.h"
#include "ui/widget.h"
#include <map>
#include <vector>
namespace app {
class WorkspacePart;
class Workspace : public ui::Box {
class Workspace : public ui::Widget {
public:
typedef WorkspaceViews::iterator iterator;
@ -37,21 +38,14 @@ namespace app {
WorkspaceView* activeView();
void setActiveView(WorkspaceView* view);
void splitView(WorkspaceView* view, int orientation);
void makeUnique(WorkspaceView* view);
Signal0<void> ActiveViewChanged;
protected:
void onPaint(ui::PaintEvent& ev) override;
private:
typedef std::vector<WorkspacePart*> WorkspaceParts;
WorkspacePart* destroyPart(WorkspacePart* part);
WorkspacePart* getPartByView(WorkspaceView* view);
void enumAllParts(WorkspaceParts& parts);
// All views of all parts.
WorkspaceViews m_views;
WorkspacePart* m_activePart;
WorkspaceView* m_activeView;
};
} // namespace app

View File

@ -1,88 +0,0 @@
// Aseprite
// Copyright (C) 2001-2015 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
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/ui/workspace_part.h"
#include "app/ui/workspace_view.h"
#include "app/ui/skin/skin_theme.h"
#include <algorithm>
namespace app {
using namespace app::skin;
using namespace ui;
WorkspacePart::WorkspacePart()
: Box(JI_VERTICAL)
, m_activeView(NULL)
{
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
setBgColor(theme->colors.workspace());
setExpansive(true);
}
WorkspacePart::~WorkspacePart()
{
}
void WorkspacePart::addView(WorkspaceView* view)
{
m_views.push_back(view);
addChild(view->getContentWidget());
setActiveView(view);
}
void WorkspacePart::removeView(WorkspaceView* view)
{
WorkspaceViews::iterator it = std::find(m_views.begin(), m_views.end(), view);
ASSERT(it != m_views.end());
it = m_views.erase(it);
removeChild(view->getContentWidget());
setActiveView(
(it != m_views.end() ?
*it : (!m_views.empty() ? m_views.back(): nullptr)));
}
void WorkspacePart::setActiveView(WorkspaceView* view)
{
m_activeView = view;
Widget* newContent = (view ? view->getContentWidget(): NULL);
WidgetsList children = getChildren();
UI_FOREACH_WIDGET(children, it) {
if ((*it) != newContent)
(*it)->setVisible(false);
}
if (newContent) {
newContent->setExpansive(true);
newContent->setVisible(true);
newContent->requestFocus();
}
if (m_activeView)
m_activeView->onWorkspaceViewSelected();
layout();
}
bool WorkspacePart::hasView(WorkspaceView* view)
{
return (std::find(m_views.begin(), m_views.end(), view) != m_views.end());
}
} // namespace app

View File

@ -1,40 +0,0 @@
// Aseprite
// Copyright (C) 2001-2015 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
// published by the Free Software Foundation.
#ifndef APP_UI_WORKSPACE_PART_H_INCLUDED
#define APP_UI_WORKSPACE_PART_H_INCLUDED
#pragma once
#include "app/ui/workspace_views.h"
#include "ui/box.h"
#include <vector>
namespace app {
class WorkspacePart : public ui::Box {
public:
WorkspacePart();
~WorkspacePart();
size_t getViewCount() { return m_views.size(); }
void addView(WorkspaceView* view);
void removeView(WorkspaceView* view);
WorkspaceView* activeView() { return m_activeView; }
void setActiveView(WorkspaceView* view);
bool hasView(WorkspaceView* view);
private:
WorkspaceView* m_activeView;
WorkspaceViews m_views;
};
} // namespace app
#endif