2015-02-12 23:16:25 +08:00
|
|
|
// Aseprite
|
2016-02-12 08:09:31 +08:00
|
|
|
// Copyright (C) 2001-2016 David Capello
|
2015-02-12 23:16:25 +08:00
|
|
|
//
|
|
|
|
// 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.
|
2009-06-01 10:59:15 +08:00
|
|
|
|
2013-08-06 08:20:19 +08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2009-06-01 10:59:15 +08:00
|
|
|
#include "config.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "app/app.h"
|
2013-11-11 05:27:11 +08:00
|
|
|
#include "app/document.h"
|
|
|
|
#include "app/modules/editors.h"
|
2014-12-28 22:06:11 +08:00
|
|
|
#include "app/pref/preferences.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#include "app/ui/color_bar.h"
|
|
|
|
#include "app/ui/document_view.h"
|
|
|
|
#include "app/ui/editor/editor.h"
|
2015-05-10 06:55:33 +08:00
|
|
|
#include "app/ui/input_chain.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#include "app/ui/main_window.h"
|
2015-02-10 20:38:07 +08:00
|
|
|
#include "app/ui/preview_editor.h"
|
2015-04-07 13:29:33 +08:00
|
|
|
#include "app/ui/status_bar.h"
|
2013-11-11 05:27:11 +08:00
|
|
|
#include "app/ui/timeline.h"
|
2013-08-06 08:20:19 +08:00
|
|
|
#include "app/ui/workspace.h"
|
2015-04-03 02:43:50 +08:00
|
|
|
#include "app/ui/workspace_tabs.h"
|
2013-11-11 05:27:11 +08:00
|
|
|
#include "app/ui_context.h"
|
2011-03-23 08:11:25 +08:00
|
|
|
#include "base/mutex.h"
|
2015-04-21 03:27:09 +08:00
|
|
|
#include "doc/site.h"
|
2014-10-21 09:21:31 +08:00
|
|
|
#include "doc/sprite.h"
|
2009-06-01 10:59:15 +08:00
|
|
|
|
2013-08-06 08:20:19 +08:00
|
|
|
namespace app {
|
2009-06-01 10:59:15 +08:00
|
|
|
|
2015-04-21 03:27:09 +08:00
|
|
|
UIContext* UIContext::m_instance = nullptr;
|
2013-01-21 05:40:37 +08:00
|
|
|
|
2009-10-09 09:34:06 +08:00
|
|
|
UIContext::UIContext()
|
2015-05-19 03:53:25 +08:00
|
|
|
: m_lastSelectedDoc(nullptr)
|
2015-04-21 03:27:09 +08:00
|
|
|
, m_lastSelectedView(nullptr)
|
2009-06-01 10:59:15 +08:00
|
|
|
{
|
2015-05-19 03:53:25 +08:00
|
|
|
documents().addObserver(&Preferences::instance());
|
2014-09-09 10:08:06 +08:00
|
|
|
|
2010-08-04 10:33:44 +08:00
|
|
|
ASSERT(m_instance == NULL);
|
2009-10-09 09:34:06 +08:00
|
|
|
m_instance = this;
|
2009-06-01 10:59:15 +08:00
|
|
|
}
|
|
|
|
|
2009-10-09 09:34:06 +08:00
|
|
|
UIContext::~UIContext()
|
2009-06-01 10:59:15 +08:00
|
|
|
{
|
2010-08-04 10:33:44 +08:00
|
|
|
ASSERT(m_instance == this);
|
2009-10-09 09:34:06 +08:00
|
|
|
m_instance = NULL;
|
2014-07-29 11:53:24 +08:00
|
|
|
|
2015-05-19 03:53:25 +08:00
|
|
|
documents().removeObserver(&Preferences::instance());
|
2014-09-09 10:08:06 +08:00
|
|
|
|
2014-07-29 11:53:24 +08:00
|
|
|
// The context must be empty at this point. (It's to check if the UI
|
|
|
|
// is working correctly, i.e. closing all files when the user can
|
|
|
|
// take any action about it.)
|
|
|
|
ASSERT(documents().empty());
|
2009-06-01 10:59:15 +08:00
|
|
|
}
|
|
|
|
|
2015-05-19 04:04:31 +08:00
|
|
|
bool UIContext::isUIAvailable() const
|
2014-11-07 05:40:29 +08:00
|
|
|
{
|
|
|
|
return App::instance()->isGui();
|
|
|
|
}
|
|
|
|
|
2014-07-29 11:53:24 +08:00
|
|
|
DocumentView* UIContext::activeView() const
|
2013-01-21 05:40:37 +08:00
|
|
|
{
|
2015-05-19 04:04:31 +08:00
|
|
|
if (!isUIAvailable())
|
2015-10-27 04:51:32 +08:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
MainWindow* mainWindow = App::instance()->getMainWindow();
|
|
|
|
if (!mainWindow)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
Workspace* workspace = mainWindow->getWorkspace();
|
|
|
|
if (!workspace)
|
|
|
|
return nullptr;
|
2014-11-07 05:40:29 +08:00
|
|
|
|
2014-07-29 11:53:24 +08:00
|
|
|
WorkspaceView* view = workspace->activeView();
|
2013-03-28 08:19:35 +08:00
|
|
|
if (DocumentView* docView = dynamic_cast<DocumentView*>(view))
|
|
|
|
return docView;
|
|
|
|
else
|
2015-10-27 04:51:32 +08:00
|
|
|
return nullptr;
|
2013-01-21 05:40:37 +08:00
|
|
|
}
|
|
|
|
|
2013-08-06 08:20:19 +08:00
|
|
|
void UIContext::setActiveView(DocumentView* docView)
|
2013-01-21 05:40:37 +08:00
|
|
|
{
|
2015-05-10 06:55:33 +08:00
|
|
|
MainWindow* mainWin = App::instance()->getMainWindow();
|
|
|
|
|
|
|
|
// Prioritize workspace for user input.
|
|
|
|
App::instance()->inputChain().prioritize(mainWin->getWorkspace());
|
|
|
|
|
2015-04-07 03:12:28 +08:00
|
|
|
// Do nothing cases: 1) the view is already selected, or 2) the view
|
|
|
|
// is the a preview.
|
|
|
|
if (m_lastSelectedView == docView ||
|
|
|
|
(docView && docView->isPreview()))
|
2014-08-25 19:27:42 +08:00
|
|
|
return;
|
|
|
|
|
2015-02-10 20:38:07 +08:00
|
|
|
if (docView) {
|
|
|
|
mainWin->getTabsBar()->selectTab(docView);
|
2013-01-21 05:40:37 +08:00
|
|
|
|
2015-02-10 20:38:07 +08:00
|
|
|
if (mainWin->getWorkspace()->activeView() != docView)
|
|
|
|
mainWin->getWorkspace()->setActiveView(docView);
|
2013-03-28 08:19:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
current_editor = (docView ? docView->getEditor(): NULL);
|
2013-01-21 05:40:37 +08:00
|
|
|
|
|
|
|
if (current_editor)
|
|
|
|
current_editor->requestFocus();
|
|
|
|
|
2015-02-10 20:38:07 +08:00
|
|
|
mainWin->getPreviewEditor()->updateUsingEditor(current_editor);
|
|
|
|
mainWin->getTimeline()->updateUsingEditor(current_editor);
|
2013-02-21 06:54:00 +08:00
|
|
|
|
2013-03-12 07:29:45 +08:00
|
|
|
// Change the image-type of color bar.
|
|
|
|
ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());
|
|
|
|
|
2013-02-21 06:54:00 +08:00
|
|
|
// Restore the palette of the selected document.
|
2013-03-12 07:29:45 +08:00
|
|
|
app_refresh_screen();
|
|
|
|
|
|
|
|
// Change the main frame title.
|
2014-09-03 11:39:15 +08:00
|
|
|
App::instance()->updateDisplayTitleBar();
|
2014-08-25 19:27:42 +08:00
|
|
|
|
|
|
|
m_lastSelectedView = docView;
|
2015-05-05 23:58:50 +08:00
|
|
|
|
|
|
|
// TODO all the calls to functions like updateUsingEditor(),
|
|
|
|
// setPixelFormat(), app_refresh_screen(), updateDisplayTitleBar()
|
|
|
|
// Can be replaced with a ContextObserver listening to the
|
|
|
|
// onActiveSiteChange() event.
|
|
|
|
notifyActiveSiteChanged();
|
2013-01-21 05:40:37 +08:00
|
|
|
}
|
|
|
|
|
2015-04-21 03:27:09 +08:00
|
|
|
void UIContext::setActiveDocument(Document* document)
|
|
|
|
{
|
2015-05-05 23:58:50 +08:00
|
|
|
bool notify = (m_lastSelectedDoc != document);
|
2015-04-21 03:27:09 +08:00
|
|
|
m_lastSelectedDoc = document;
|
|
|
|
|
|
|
|
DocumentView* docView = getFirstDocumentView(document);
|
2015-05-05 23:58:50 +08:00
|
|
|
if (docView) { // The view can be null if we are in --batch mode
|
2015-04-21 03:27:09 +08:00
|
|
|
setActiveView(docView);
|
2015-05-05 23:58:50 +08:00
|
|
|
notify = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (notify)
|
|
|
|
notifyActiveSiteChanged();
|
2015-04-21 03:27:09 +08:00
|
|
|
}
|
|
|
|
|
2015-08-15 00:06:26 +08:00
|
|
|
DocumentView* UIContext::getFirstDocumentView(doc::Document* document) const
|
2014-12-01 08:06:29 +08:00
|
|
|
{
|
2015-05-01 04:02:57 +08:00
|
|
|
MainWindow* mainWindow = App::instance()->getMainWindow();
|
|
|
|
if (!mainWindow) // Main window can be null if we are in --batch mode
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
Workspace* workspace = mainWindow->getWorkspace();
|
2014-12-01 08:06:29 +08:00
|
|
|
|
2015-02-23 08:18:53 +08:00
|
|
|
for (WorkspaceView* view : *workspace) {
|
2014-12-01 08:06:29 +08:00
|
|
|
if (DocumentView* docView = dynamic_cast<DocumentView*>(view)) {
|
|
|
|
if (docView->getDocument() == document) {
|
|
|
|
return docView;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-01 04:02:57 +08:00
|
|
|
return nullptr;
|
2014-12-01 08:06:29 +08:00
|
|
|
}
|
|
|
|
|
2015-08-15 00:06:26 +08:00
|
|
|
DocumentViews UIContext::getAllDocumentViews(doc::Document* document) const
|
|
|
|
{
|
|
|
|
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
|
|
|
|
DocumentViews docViews;
|
|
|
|
|
|
|
|
for (WorkspaceView* view : *workspace) {
|
|
|
|
if (DocumentView* docView = dynamic_cast<DocumentView*>(view)) {
|
|
|
|
if (docView->getDocument() == document) {
|
|
|
|
docViews.push_back(docView);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return docViews;
|
|
|
|
}
|
|
|
|
|
2014-07-29 11:53:24 +08:00
|
|
|
Editor* UIContext::activeEditor()
|
2013-01-21 05:40:37 +08:00
|
|
|
{
|
2014-07-29 11:53:24 +08:00
|
|
|
DocumentView* view = activeView();
|
|
|
|
if (view)
|
|
|
|
return view->getEditor();
|
2013-01-21 05:40:37 +08:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-07-29 11:53:24 +08:00
|
|
|
void UIContext::onAddDocument(doc::Document* doc)
|
2009-06-01 10:59:15 +08:00
|
|
|
{
|
2015-04-21 03:27:09 +08:00
|
|
|
m_lastSelectedDoc = static_cast<app::Document*>(doc);
|
2009-06-01 10:59:15 +08:00
|
|
|
|
2013-12-09 07:19:32 +08:00
|
|
|
// We don't create views in batch mode.
|
|
|
|
if (!App::instance()->isGui())
|
|
|
|
return;
|
|
|
|
|
2013-01-21 05:40:37 +08:00
|
|
|
// Add a new view for this document
|
2016-02-12 08:09:31 +08:00
|
|
|
DocumentView* view = new DocumentView(
|
|
|
|
m_lastSelectedDoc,
|
|
|
|
DocumentView::Normal,
|
|
|
|
App::instance()->getMainWindow()->getPreviewEditor());
|
2013-01-21 05:40:37 +08:00
|
|
|
|
|
|
|
// Add a tab with the new view for the document
|
|
|
|
App::instance()->getMainWindow()->getWorkspace()->addView(view);
|
|
|
|
|
|
|
|
setActiveView(view);
|
|
|
|
view->getEditor()->setDefaultScroll();
|
2009-06-01 10:59:15 +08:00
|
|
|
}
|
|
|
|
|
2014-07-29 11:53:24 +08:00
|
|
|
void UIContext::onRemoveDocument(doc::Document* doc)
|
2009-06-01 10:59:15 +08:00
|
|
|
{
|
2015-04-21 03:27:09 +08:00
|
|
|
if (doc == m_lastSelectedDoc)
|
|
|
|
m_lastSelectedDoc = nullptr;
|
|
|
|
|
2014-11-07 08:04:32 +08:00
|
|
|
// We don't destroy views in batch mode.
|
2015-05-19 04:04:31 +08:00
|
|
|
if (isUIAvailable()) {
|
2015-04-07 12:21:31 +08:00
|
|
|
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
|
2009-06-01 10:59:15 +08:00
|
|
|
|
2015-08-15 00:06:26 +08:00
|
|
|
for (DocumentView* docView : getAllDocumentViews(doc)) {
|
2015-04-07 12:21:31 +08:00
|
|
|
workspace->removeView(docView);
|
|
|
|
delete docView;
|
|
|
|
}
|
2013-03-28 08:19:35 +08:00
|
|
|
}
|
2009-06-01 10:59:15 +08:00
|
|
|
}
|
|
|
|
|
2015-04-21 03:27:09 +08:00
|
|
|
void UIContext::onGetActiveSite(Site* site) const
|
2009-06-01 10:59:15 +08:00
|
|
|
{
|
2014-07-29 11:53:24 +08:00
|
|
|
DocumentView* view = activeView();
|
2014-11-07 08:04:32 +08:00
|
|
|
if (view) {
|
2015-04-21 03:27:09 +08:00
|
|
|
view->getSite(site);
|
2014-11-07 08:04:32 +08:00
|
|
|
}
|
2015-04-21 03:27:09 +08:00
|
|
|
// Default/dummy site (maybe for batch/command line mode)
|
2015-05-19 04:04:31 +08:00
|
|
|
else if (!isUIAvailable()) {
|
2015-05-05 03:24:56 +08:00
|
|
|
if (Document* doc = m_lastSelectedDoc) {
|
|
|
|
site->document(doc);
|
|
|
|
site->sprite(doc->sprite());
|
|
|
|
site->layer(doc->sprite()->indexToLayer(LayerIndex(0)));
|
|
|
|
site->frame(0);
|
|
|
|
}
|
2014-11-07 08:04:32 +08:00
|
|
|
}
|
2009-06-01 10:59:15 +08:00
|
|
|
}
|
2013-08-06 08:20:19 +08:00
|
|
|
|
|
|
|
} // namespace app
|