Add a visual icon when the program is saving backup data (fix #1114)

This commit is contained in:
David Capello 2016-11-07 16:32:54 -03:00
parent 6ba53c4e12
commit 69b52498a2
11 changed files with 191 additions and 7 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -413,6 +413,8 @@
<part id="icon_key" x="208" y="264" w="8" h="8" /> <part id="icon_key" x="208" y="264" w="8" h="8" />
<part id="icon_distance" x="216" y="264" w="8" h="8" /> <part id="icon_distance" x="216" y="264" w="8" h="8" />
<part id="icon_grid" x="224" y="264" w="8" h="8" /> <part id="icon_grid" x="224" y="264" w="8" h="8" />
<part id="icon_save" x="232" y="264" w="8" h="8" />
<part id="icon_save_small" x="240" y="264" w="8" h="8" />
</parts> </parts>
<stylesheet> <stylesheet>

View File

@ -350,6 +350,7 @@ add_library(app-lib
transformation.cpp transformation.cpp
ui/ani_controls.cpp ui/ani_controls.cpp
ui/app_menuitem.cpp ui/app_menuitem.cpp
ui/backup_indicator.cpp
ui/brush_popup.cpp ui/brush_popup.cpp
ui/button_set.cpp ui/button_set.cpp
ui/color_bar.cpp ui/color_bar.cpp

View File

@ -40,6 +40,7 @@
#include "app/shell.h" #include "app/shell.h"
#include "app/tools/active_tool.h" #include "app/tools/active_tool.h"
#include "app/tools/tool_box.h" #include "app/tools/tool_box.h"
#include "app/ui/backup_indicator.h"
#include "app/ui/color_bar.h" #include "app/ui/color_bar.h"
#include "app/ui/document_view.h" #include "app/ui/document_view.h"
#include "app/ui/editor/editor.h" #include "app/ui/editor/editor.h"
@ -56,6 +57,7 @@
#include "base/convert_to.h" #include "base/convert_to.h"
#include "base/exception.h" #include "base/exception.h"
#include "base/fs.h" #include "base/fs.h"
#include "base/scoped_lock.h"
#include "base/split_string.h" #include "base/split_string.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "doc/document_observer.h" #include "doc/document_observer.h"
@ -148,6 +150,7 @@ App::App()
, m_isGui(false) , m_isGui(false)
, m_isShell(false) , m_isShell(false)
, m_exporter(NULL) , m_exporter(NULL)
, m_backupIndicator(nullptr)
{ {
ASSERT(m_instance == NULL); ASSERT(m_instance == NULL);
m_instance = this; m_instance = this;
@ -750,6 +753,11 @@ App::~App()
// Save brushes // Save brushes
m_brushes.reset(nullptr); m_brushes.reset(nullptr);
if (m_backupIndicator) {
delete m_backupIndicator;
m_backupIndicator = nullptr;
}
delete m_legacy; delete m_legacy;
delete m_modules; delete m_modules;
delete m_coreModules; delete m_coreModules;
@ -842,6 +850,20 @@ void App::showNotification(INotificationDelegate* del)
m_mainWindow->showNotification(del); m_mainWindow->showNotification(del);
} }
void App::showBackupNotification(bool state)
{
base::scoped_lock lock(m_backupIndicatorMutex);
if (state) {
if (!m_backupIndicator)
m_backupIndicator = new BackupIndicator;
m_backupIndicator->start();
}
else {
if (m_backupIndicator)
m_backupIndicator->stop();
}
}
void App::updateDisplayTitleBar() void App::updateDisplayTitleBar()
{ {
std::string defaultTitle = PACKAGE " v" VERSION; std::string defaultTitle = PACKAGE " v" VERSION;

View File

@ -9,6 +9,7 @@
#pragma once #pragma once
#include "app/app_brushes.h" #include "app/app_brushes.h"
#include "base/mutex.h"
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "doc/pixel_format.h" #include "doc/pixel_format.h"
#include "obs/signal.h" #include "obs/signal.h"
@ -27,6 +28,7 @@ namespace ui {
namespace app { namespace app {
class AppOptions; class AppOptions;
class BackupIndicator;
class ContextBar; class ContextBar;
class Document; class Document;
class DocumentExporter; class DocumentExporter;
@ -83,6 +85,8 @@ namespace app {
} }
void showNotification(INotificationDelegate* del); void showNotification(INotificationDelegate* del);
// This can be called from a non-UI thread.
void showBackupNotification(bool state);
void updateDisplayTitleBar(); void updateDisplayTitleBar();
InputChain& inputChain(); InputChain& inputChain();
@ -108,6 +112,8 @@ namespace app {
FileList m_files; FileList m_files;
base::UniquePtr<DocumentExporter> m_exporter; base::UniquePtr<DocumentExporter> m_exporter;
base::UniquePtr<AppBrushes> m_brushes; base::UniquePtr<AppBrushes> m_brushes;
BackupIndicator* m_backupIndicator;
base::mutex m_backupIndicatorMutex;
}; };
void app_refresh_screen(); void app_refresh_screen();

View File

@ -23,6 +23,24 @@
namespace app { namespace app {
namespace crash { namespace crash {
namespace {
class SwitchBackupIcon {
public:
SwitchBackupIcon() {
App* app = App::instance();
if (app)
app->showBackupNotification(true);
}
~SwitchBackupIcon() {
App* app = App::instance();
if (app)
app->showBackupNotification(false);
}
};
}
BackupObserver::BackupObserver(Session* session, doc::Context* ctx) BackupObserver::BackupObserver(Session* session, doc::Context* ctx)
: m_session(session) : m_session(session)
, m_ctx(ctx) , m_ctx(ctx)
@ -66,7 +84,7 @@ void BackupObserver::backgroundThread()
{ {
int normalPeriod = 60*Preferences::instance().general.dataRecoveryPeriod(); int normalPeriod = 60*Preferences::instance().general.dataRecoveryPeriod();
int lockedPeriod = 10; int lockedPeriod = 10;
#if 0 // Just for testing purposes #if 1 // Just for testing purposes
normalPeriod = 5; normalPeriod = 5;
lockedPeriod = 5; lockedPeriod = 5;
#endif #endif
@ -79,6 +97,7 @@ void BackupObserver::backgroundThread()
if (seconds >= waitUntil) { if (seconds >= waitUntil) {
TRACE("RECO: Start backup process for %d documents\n", m_documents.size()); TRACE("RECO: Start backup process for %d documents\n", m_documents.size());
SwitchBackupIcon icon;
base::scoped_lock hold(m_mutex); base::scoped_lock hold(m_mutex);
base::Chrono chrono; base::Chrono chrono;
bool somethingLocked = false; bool somethingLocked = false;

View File

@ -0,0 +1,58 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/ui/backup_indicator.h"
#include "app/ui/status_bar.h"
#include "base/bind.h"
#include "ui/manager.h"
namespace app {
BackupIndicator::BackupIndicator()
: m_timer(100)
, m_small(false)
, m_running(false)
{
m_timer.Tick.connect(base::Bind<void>(&BackupIndicator::onTick, this));
}
BackupIndicator::~BackupIndicator()
{
m_timer.stop();
}
void BackupIndicator::start()
{
m_running = true;
m_timer.start();
}
void BackupIndicator::stop()
{
m_running = false;
}
void BackupIndicator::onTick()
{
if (!m_running) {
StatusBar::instance()->showBackupIcon(StatusBar::BackupIcon::None);
m_timer.stop();
return;
}
StatusBar::instance()->showBackupIcon(
m_small ? StatusBar::BackupIcon::Small:
StatusBar::BackupIcon::Normal);
m_small = !m_small;
}
} // namespace app

View File

@ -0,0 +1,33 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_UI_BACKUP_INDICATOR_H_INCLUDED
#define APP_UI_BACKUP_INDICATOR_H_INCLUDED
#pragma once
#include "ui/timer.h"
namespace app {
class BackupIndicator {
public:
BackupIndicator();
~BackupIndicator();
void start();
void stop();
private:
void onTick();
ui::Timer m_timer;
bool m_small;
bool m_running;
};
} // namespace app
#endif

View File

@ -182,7 +182,16 @@ class StatusBar::Indicators : public HBox {
public: public:
Indicators() { Indicators() : m_backupIcon(BackupIcon::None) {
m_leftArea.setBorder(gfx::Border(0));
m_leftArea.setVisible(true);
m_leftArea.setExpansive(true);
m_rightArea.setBorder(gfx::Border(0));
m_rightArea.setVisible(false);
addChild(&m_leftArea);
addChild(&m_rightArea);
} }
void startIndicators() { void startIndicators() {
@ -210,7 +219,7 @@ public:
auto indicator = new TextIndicator(text); auto indicator = new TextIndicator(text);
m_indicators.push_back(indicator); m_indicators.push_back(indicator);
m_iterator = m_indicators.end(); m_iterator = m_indicators.end();
addChild(indicator); m_leftArea.addChild(indicator);
} }
void addIconIndicator(she::Surface* icon, bool colored) { void addIconIndicator(she::Surface* icon, bool colored) {
@ -228,7 +237,7 @@ public:
auto indicator = new IconIndicator(icon, colored); auto indicator = new IconIndicator(icon, colored);
m_indicators.push_back(indicator); m_indicators.push_back(indicator);
m_iterator = m_indicators.end(); m_iterator = m_indicators.end();
addChild(indicator); m_leftArea.addChild(indicator);
} }
void addColorIndicator(const app::Color& color) { void addColorIndicator(const app::Color& color) {
@ -246,7 +255,29 @@ public:
auto indicator = new ColorIndicator(color); auto indicator = new ColorIndicator(color);
m_indicators.push_back(indicator); m_indicators.push_back(indicator);
m_iterator = m_indicators.end(); m_iterator = m_indicators.end();
addChild(indicator); m_leftArea.addChild(indicator);
}
void showBackupIcon(BackupIcon icon) {
m_backupIcon = icon;
if (m_backupIcon != BackupIcon::None) {
she::Surface* icon =
(m_backupIcon == BackupIcon::Normal ?
SkinTheme::instance()->parts.iconSave()->bitmap(0):
SkinTheme::instance()->parts.iconSaveSmall()->bitmap(0));
m_rightArea.setVisible(true);
if (m_rightArea.children().empty()) {
m_rightArea.addChild(new IconIndicator(icon, true));
}
else {
((IconIndicator*)m_rightArea.lastChild())->updateIndicator(icon, true);
}
}
else {
m_rightArea.setVisible(false);
}
layout();
} }
private: private:
@ -255,7 +286,7 @@ private:
auto end = m_indicators.end(); auto end = m_indicators.end();
for (; it != end; ++it) { for (; it != end; ++it) {
auto indicator = *it; auto indicator = *it;
removeChild(indicator); m_leftArea.removeChild(indicator);
delete indicator; delete indicator;
} }
m_indicators.erase(m_iterator, end); m_indicators.erase(m_iterator, end);
@ -263,6 +294,9 @@ private:
std::vector<Indicator*> m_indicators; std::vector<Indicator*> m_indicators;
std::vector<Indicator*>::iterator m_iterator; std::vector<Indicator*>::iterator m_iterator;
BackupIcon m_backupIcon;
HBox m_leftArea;
HBox m_rightArea;
}; };
class StatusBar::IndicatorsGeneration { class StatusBar::IndicatorsGeneration {
@ -572,6 +606,11 @@ void StatusBar::updateFromEditor(Editor* editor)
m_zoomEntry->setZoom(editor->zoom()); m_zoomEntry->setZoom(editor->zoom());
} }
void StatusBar::showBackupIcon(BackupIcon icon)
{
m_indicators->showBackupIcon(icon);
}
bool StatusBar::setStatusText(int msecs, const char *format, ...) bool StatusBar::setStatusText(int msecs, const char *format, ...)
{ {
if ((base::current_tick() > m_timeout) || (msecs > 0)) { if ((base::current_tick() > m_timeout) || (msecs > 0)) {

View File

@ -51,6 +51,8 @@ namespace app {
public: public:
static StatusBar* instance() { return m_instance; } static StatusBar* instance() { return m_instance; }
enum BackupIcon { None, Normal, Small };
StatusBar(); StatusBar();
~StatusBar(); ~StatusBar();
@ -65,6 +67,8 @@ namespace app {
// Used by AppEditor to update the zoom level in the status bar. // Used by AppEditor to update the zoom level in the status bar.
void updateFromEditor(Editor* editor); void updateFromEditor(Editor* editor);
void showBackupIcon(BackupIcon icon);
protected: protected:
void onResize(ui::ResizeEvent& ev) override; void onResize(ui::ResizeEvent& ev) override;

@ -1 +1 @@
Subproject commit 83dfe27536785acedb258e55ac762486d95e2ab0 Subproject commit 27fa7f6a4bc7f686da49e6e895ff7dde864b88ad