Fix crashes saving sprites with '%' char in their filename

To fix this we changed the way StatusBar text is handled (we are using
fmt::format() in StatusBar instead of printf-like ... args now).
This commit is contained in:
David Capello 2020-05-08 17:39:55 -03:00
parent 6e4b96f548
commit 46f4002368
22 changed files with 165 additions and 139 deletions

View File

@ -101,7 +101,7 @@ void FlipCommand::onExecute(Context* ctx)
if (cels.empty()) {
StatusBar::instance()->showTip(
1000, Strings::statusbar_tips_all_layers_are_locked().c_str());
1000, Strings::statusbar_tips_all_layers_are_locked());
return;
}
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
@ -18,6 +19,7 @@
#include "app/ui/timeline/timeline.h"
#include "doc/layer.h"
#include "doc/sprite.h"
#include "fmt/format.h"
namespace app {
@ -73,9 +75,9 @@ protected:
void updateStatusBar(Site& site) {
if (site.layer() != NULL)
StatusBar::instance()->setStatusText(
1000, "%s '%s' selected",
(site.layer()->isGroup() ? "Group": "Layer"),
site.layer()->name().c_str());
1000, fmt::format("{} '{}' selected",
(site.layer()->isGroup() ? "Group": "Layer"),
site.layer()->name()));
}
private:

View File

@ -175,7 +175,7 @@ void NewBrushCommand::createBrush(const Site& site, const Mask* mask)
std::string tooltip;
tooltip += "Shortcut: ";
tooltip += key->accels().front().toString();
StatusBar::instance()->showTip(2000, tooltip.c_str());
StatusBar::instance()->showTip(2000, tooltip);
}
}

View File

@ -172,10 +172,10 @@ void NewFrameCommand::onExecute(Context* context)
if (context->isUIAvailable()) {
update_screen_for_document(document);
StatusBar::instance()
->showTip(1000, "New frame %d/%d",
(int)context->activeSite().frame()+1,
(int)sprite->totalFrames());
StatusBar::instance()->showTip(
1000, fmt::format("New frame {}/{}",
(int)context->activeSite().frame()+1,
(int)sprite->totalFrames()));
App::instance()->mainWindow()->popTimeline();
}

View File

@ -421,9 +421,9 @@ void NewLayerCommand::onExecute(Context* context)
StatusBar::instance()->invalidate();
StatusBar::instance()->showTip(
1000, "%s '%s' created",
layerPrefix().c_str(),
name.c_str());
1000, fmt::format("{} '{}' created",
layerPrefix(),
name));
App::instance()->mainWindow()->popTimeline();
}

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
@ -11,6 +12,7 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/ui/status_bar.h"
#include "fmt/format.h"
#include "ui/scale.h"
#include "ui/system.h"
#include "ui/theme.h"
@ -47,12 +49,12 @@ void RefreshCommand::onExecute(Context* context)
{
PROCESS_MEMORY_COUNTERS pmc;
if (::GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
StatusBar::instance()
->showTip(1000,
"Current memory: %.16g KB (%lu)\n"
"Peak of memory: %.16g KB (%lu)",
pmc.WorkingSetSize / 1024.0, pmc.WorkingSetSize,
pmc.PeakWorkingSetSize / 1024.0, pmc.PeakWorkingSetSize);
StatusBar::instance()->showTip(
1000,
fmt::format("Current memory: {:.2f} MB ({})\n"
"Peak of memory: {:.2f} MB ({})",
pmc.WorkingSetSize / 1024.0 / 1024.0, pmc.WorkingSetSize,
pmc.PeakWorkingSetSize / 1024.0 / 1024.0, pmc.PeakWorkingSetSize));
}
}
#endif

View File

@ -1,4 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -18,6 +19,7 @@
#include "app/ui/status_bar.h"
#include "doc/layer.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "ui/alert.h"
#include "ui/widget.h"
@ -95,7 +97,7 @@ void RemoveLayerCommand::onExecute(Context* context)
StatusBar::instance()->invalidate();
if (!layerName.empty())
StatusBar::instance()->showTip(1000, "Layer '%s' removed", layerName.c_str());
StatusBar::instance()->showTip(1000, fmt::format("Layer '{}' removed", layerName));
else
StatusBar::instance()->showTip(1000, "Layers removed");
}

View File

@ -21,6 +21,7 @@
#include "doc/selected_objects.h"
#include "doc/slice.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "ui/alert.h"
#include "ui/widget.h"
@ -121,10 +122,10 @@ void RemoveSliceCommand::onExecute(Context* context)
StatusBar::instance()->invalidate();
if (!sliceName.empty())
StatusBar::instance()->showTip(
1000, "Slice '%s' removed", sliceName.c_str());
1000, fmt::format("Slice '{}' removed", sliceName));
else
StatusBar::instance()->showTip(
1000, "%d slice(s) removed", slicesToDelete.size());
1000, fmt::format("{} slice(s) removed", slicesToDelete.size()));
}
Command* CommandFactory::createRemoveSliceCommand()

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -223,7 +223,7 @@ void RotateCommand::onExecute(Context* context)
if (cels.empty()) {
StatusBar::instance()->showTip(
1000, Strings::statusbar_tips_all_layers_are_locked().c_str());
1000, Strings::statusbar_tips_all_layers_are_locked());
return;
}
}

View File

@ -248,9 +248,9 @@ void SaveFileBaseCommand::saveDocumentInBackground(
document->incrementVersion();
}
#ifdef ENABLE_UI
StatusBar::instance()
->setStatusText(2000, "File <%s> saved.",
base::get_file_name(filename).c_str());
StatusBar::instance()->setStatusText(
2000, fmt::format("File <{}> saved.",
base::get_file_name(filename)));
#endif
}
}

View File

@ -116,9 +116,9 @@ void UndoCommand::onExecute(Context* context)
else
msg = "Redid " + undo->nextRedoLabel();
if (Preferences::instance().undo.showTooltip())
statusbar->showTip(1000, msg.c_str());
statusbar->showTip(1000, msg);
else
statusbar->setStatusText(0, msg.c_str());
statusbar->setStatusText(0, msg);
}
#endif // ENABLE_UI

View File

@ -327,9 +327,9 @@ bool DocView::onCloseView(Workspace* workspace, bool quitting)
DocDestroyer destroyer(
static_cast<app::Context*>(m_document->context()), m_document, 500);
StatusBar::instance()
->setStatusText(0, "Sprite '%s' closed.",
m_document->name().c_str());
StatusBar::instance()->setStatusText(
0, fmt::format("Sprite '{}' closed.",
m_document->name()));
// Just close the document (so we can reopen it with
// ReopenClosedFile command).

View File

@ -28,6 +28,7 @@
#include "doc/layer.h"
#include "doc/mask.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "ui/message.h"
#include <algorithm>
@ -289,29 +290,31 @@ bool MovingCelState::onUpdateStatusBar(Editor* editor)
if (m_hasReference) {
if (m_scaled && m_cel) {
StatusBar::instance()->setStatusText
(0,
":pos: %.2f %.2f :offset: %.2f %.2f :size: %.2f%% %.2f%%",
pos.x, pos.y,
m_celOffset.x, m_celOffset.y,
100.0*m_celScale.w*m_celMainSize.w/m_cel->image()->width(),
100.0*m_celScale.h*m_celMainSize.h/m_cel->image()->height());
StatusBar::instance()->setStatusText(
0,
fmt::format(
":pos: {:.2f} {:.2f} :offset: {:.2f} {:.2f} :size: {:.2f}% {:.2f}%",
pos.x, pos.y,
m_celOffset.x, m_celOffset.y,
100.0*m_celScale.w*m_celMainSize.w/m_cel->image()->width(),
100.0*m_celScale.h*m_celMainSize.h/m_cel->image()->height()));
}
else {
StatusBar::instance()->setStatusText
(0,
":pos: %.2f %.2f :offset: %.2f %.2f",
pos.x, pos.y,
m_celOffset.x, m_celOffset.y);
StatusBar::instance()->setStatusText(
0,
fmt::format(
":pos: {:.2f} {:.2f} :offset: {:.2f} {:.2f}",
pos.x, pos.y,
m_celOffset.x, m_celOffset.y));
}
}
else {
gfx::Point intOffset = intCelOffset();
StatusBar::instance()->setStatusText
(0,
":pos: %3d %3d :offset: %3d %3d",
int(pos.x), int(pos.y),
intOffset.x, intOffset.y);
StatusBar::instance()->setStatusText(
0,
fmt::format(":pos: {:3d} {:3d} :offset: {:3d} {:3d}",
int(pos.x), int(pos.y),
intOffset.x, intOffset.y));
}
return true;

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -41,6 +41,7 @@
#include "doc/algorithm/flip_image.h"
#include "doc/mask.h"
#include "doc/sprite.h"
#include "fmt/format.h"
#include "gfx/rect.h"
#include "ui/manager.h"
#include "ui/message.h"
@ -491,19 +492,21 @@ bool MovingPixelsState::onUpdateStatusBar(Editor* editor)
int w = int(transform.bounds().w);
int h = int(transform.bounds().h);
int gcd = base::gcd(w, h);
StatusBar::instance()->setStatusText
(100, ":pos: %d %d :size: %3d %3d :selsize: %d %d [%.02f%% %.02f%%] :angle: %.1f :aspect_ratio: %d:%d",
int(transform.bounds().x),
int(transform.bounds().y),
imageSize.w,
imageSize.h,
w,
h,
(double)w*100.0/imageSize.w,
(double)h*100.0/imageSize.h,
180.0 * transform.angle() / PI,
w/gcd,
h/gcd);
StatusBar::instance()->setStatusText(
100,
fmt::format(
":pos: {} {} :size: {:3d} {:3d} :selsize: {} {} [{:.02f}% {:.02f}%] :angle: {:.1f} :aspect_ratio: {}:{}",
int(transform.bounds().x),
int(transform.bounds().y),
imageSize.w,
imageSize.h,
w,
h,
(double)w*100.0/imageSize.w,
(double)h*100.0/imageSize.h,
180.0 * transform.angle() / PI,
w/gcd,
h/gcd));
return true;
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2017-2018 David Capello
//
// This program is distributed under the terms of
@ -20,6 +20,7 @@
#include "app/ui_context.h"
#include "app/ui_context.h"
#include "doc/mask.h"
#include "fmt/format.h"
#include "ui/message.h"
namespace app {
@ -132,11 +133,13 @@ bool MovingSelectionState::onUpdateStatusBar(Editor* editor)
{
const gfx::Rect bounds = editor->document()->mask()->bounds();
StatusBar::instance()->setStatusText
(100, ":pos: %d %d :size: %3d %3d :offset: %d %d",
bounds.x, bounds.y,
bounds.w, bounds.h,
m_delta.x, m_delta.y);
StatusBar::instance()->setStatusText(
100,
fmt::format(
":pos: {} {} :size: {:3d} {:3d} :offset: {} {}",
bounds.x, bounds.y,
bounds.w, bounds.h,
m_delta.x, m_delta.y));
return true;
}

View File

@ -14,6 +14,7 @@
#include "app/ui/editor/editor.h"
#include "app/ui/status_bar.h"
#include "base/clamp.h"
#include "fmt/format.h"
#include "ui/message.h"
#include <cmath>
@ -70,13 +71,15 @@ bool MovingSymmetryState::onMouseMove(Editor* editor, MouseMessage* msg)
bool MovingSymmetryState::onUpdateStatusBar(Editor* editor)
{
if (m_symmetryMode == app::gen::SymmetryMode::HORIZONTAL)
StatusBar::instance()->setStatusText
(0, "Left %3.1f Right %3.1f", m_symmetryAxis(),
double(editor->sprite()->width()) - m_symmetryAxis());
StatusBar::instance()->setStatusText(
0, fmt::format("Left {:3.1f} Right {:3.1f}",
m_symmetryAxis(),
double(editor->sprite()->width()) - m_symmetryAxis()));
else
StatusBar::instance()->setStatusText
(0, "Top %3.1f Bottom %3.1f", m_symmetryAxis(),
double(editor->sprite()->height()) - m_symmetryAxis());
StatusBar::instance()->setStatusText(
0, fmt::format("Top {:3.1f} Bottom {:3.1f}",
m_symmetryAxis(),
double(editor->sprite()->height()) - m_symmetryAxis()));
return true;
}

View File

@ -56,6 +56,7 @@
#include "doc/slice.h"
#include "doc/sprite.h"
#include "fixmath/fixmath.h"
#include "fmt/format.h"
#include "gfx/rect.h"
#include "os/surface.h"
#include "os/system.h"
@ -190,12 +191,12 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
"The background layer cannot be moved");
}
else if (!layer->isVisibleHierarchy()) {
StatusBar::instance()->showTip(1000,
"Layer '%s' is hidden", layer->name().c_str());
StatusBar::instance()->showTip(
1000, fmt::format("Layer '{}' is hidden", layer->name()));
}
else if (!layer->isMovable() || !layer->isEditableHierarchy()) {
StatusBar::instance()->showTip(1000,
"Layer '%s' is locked", layer->name().c_str());
StatusBar::instance()->showTip(
1000, fmt::format("Layer '{}' is locked", layer->name()));
}
else {
MovingCelCollect collect(editor, layer);
@ -299,8 +300,8 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
Image* image = site.image(&x, &y, &opacity);
if (layer && image) {
if (!layer->isEditableHierarchy()) {
StatusBar::instance()->showTip(1000,
"Layer '%s' is locked", layer->name().c_str());
StatusBar::instance()->showTip(
1000, fmt::format("Layer '{}' is locked", layer->name()));
return true;
}
@ -320,8 +321,8 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
// Move selected pixels
if (layer && editor->canStartMovingSelectionPixels() && msg->left()) {
if (!layer->isEditableHierarchy()) {
StatusBar::instance()->showTip(1000,
"Layer '%s' is locked", layer->name().c_str());
StatusBar::instance()->showTip(
1000, fmt::format("Layer '{}' is locked", layer->name()));
return true;
}
@ -741,8 +742,8 @@ void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleT
Layer* layer = editor->layer();
if (layer && layer->isReference()) {
StatusBar::instance()->showTip(
1000, "Layer '%s' is reference, cannot be transformed",
layer->name().c_str());
1000, fmt::format("Layer '{}' is reference, cannot be transformed",
layer->name()));
return;
}

View File

@ -717,19 +717,19 @@ tools::ToolLoop* create_tool_loop(
}
else if (!layer->isVisibleHierarchy()) {
StatusBar::instance()->showTip(
1000, "Layer '%s' is hidden", layer->name().c_str());
1000, fmt::format("Layer '{}' is hidden", layer->name()));
return nullptr;
}
// If the active layer is read-only.
else if (!layer->isEditableHierarchy()) {
StatusBar::instance()->showTip(
1000, "Layer '%s' is locked", layer->name().c_str());
1000, fmt::format("Layer '{}' is locked", layer->name()));
return nullptr;
}
// If the active layer is reference.
else if (layer->isReference()) {
StatusBar::instance()->showTip(
1000, "Layer '%s' is reference, cannot be modified", layer->name().c_str());
1000, fmt::format("Layer '{}' is reference, cannot be modified", layer->name()));
return nullptr;
}
}

View File

@ -29,6 +29,7 @@
#include "doc/image.h"
#include "doc/palette.h"
#include "doc/remap.h"
#include "fmt/format.h"
#include "gfx/color.h"
#include "gfx/point.h"
#include "os/font.h"
@ -935,9 +936,11 @@ void PaletteView::setStatusBar()
std::max(palSize, destIndex + picks));
statusBar->setStatusText(
0, "%s to %d - New Palette Size %d",
(m_copy ? "Copy": "Move"),
destIndex, newPalSize);
0,
fmt::format("{} to {} - New Palette Size {}",
(m_copy ? "Copy": "Move"),
destIndex,
newPalSize));
}
else {
statusBar->showDefaultText();
@ -950,8 +953,8 @@ void PaletteView::setStatusBar()
m_hot.part == Hit::RESIZE_HANDLE) {
int newPalSize = std::max(1, m_hot.color);
statusBar->setStatusText(
0, "New Palette Size %d",
newPalSize);
0, fmt::format("New Palette Size {}",
newPalSize));
}
else {
statusBar->showDefaultText();

View File

@ -609,7 +609,7 @@ void StatusBar::onSelectedToolChange(tools::Tool* tool)
void StatusBar::clearText()
{
setStatusText(1, "");
setStatusText(1, std::string());
}
// TODO Workspace views should have a method to set the default status
@ -621,8 +621,8 @@ void StatusBar::showDefaultText()
showDefaultText(current_editor->document());
}
else if (App::instance()->mainWindow()->isHomeSelected()) {
setStatusText(0, "-- %s %s by David & Gaspar Capello -- Igara Studio --",
get_app_name(), get_app_version());
setStatusText(0, fmt::format("-- {} {} by David & Gaspar Capello -- Igara Studio --",
get_app_name(), get_app_version()));
}
else {
clearText();
@ -647,7 +647,7 @@ void StatusBar::showDefaultText(Doc* doc)
buf += fmt::format(" ({})", path);
}
setStatusText(1, buf.c_str());
setStatusText(1, buf);
}
}
@ -662,14 +662,9 @@ void StatusBar::showBackupIcon(BackupIcon icon)
m_indicators->showBackupIcon(icon);
}
bool StatusBar::setStatusText(int msecs, const char* format, ...)
bool StatusBar::setStatusText(int msecs, const std::string& msg)
{
if ((base::current_tick() > m_timeout) || (msecs > 0)) {
std::va_list ap;
va_start(ap, format);
std::string msg = base::string_vprintf(format, ap);
va_end(ap);
IndicatorsGeneration(m_indicators).add(msg.c_str());
m_timeout = base::current_tick() + msecs;
return true;
@ -678,13 +673,8 @@ bool StatusBar::setStatusText(int msecs, const char* format, ...)
return false;
}
void StatusBar::showTip(int msecs, const char* format, ...)
void StatusBar::showTip(int msecs, const std::string& msg)
{
std::va_list ap;
va_start(ap, format);
std::string msg = base::string_vprintf(format, ap);
va_end(ap);
if (m_tipwindow == NULL) {
m_tipwindow = new CustomizedTipWindow(msg);
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018 Igara Studio S.A.
// Copyright (C) 2018-2020 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -57,8 +57,8 @@ namespace app {
void showDefaultText();
void showDefaultText(Doc* document);
bool setStatusText(int msecs, const char* format, ...);
void showTip(int msecs, const char* format, ...);
bool setStatusText(int msecs, const std::string& text);
void showTip(int msecs, const std::string& msg);
void showColor(int msecs, const char* text, const Color& color);
void showTool(int msecs, tools::Tool* tool);
void showSnapToGridWarning(bool state);

View File

@ -50,6 +50,7 @@
#include "base/memory.h"
#include "base/scoped_value.h"
#include "doc/doc.h"
#include "fmt/format.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "os/font.h"
@ -3267,17 +3268,19 @@ void Timeline::updateStatusBar(ui::Message* msg)
switch (m_range.type()) {
case Range::kCels:
sb->setStatusText(0, "%s cels", verb);
break;
sb->setStatusText(0, fmt::format("{} cels", verb));
return;
case Range::kFrames:
if (validFrame(m_hot.frame)) {
if (m_dropTarget.hhit == DropTarget::Before) {
sb->setStatusText(0, "%s before frame %d", verb, int(m_dropRange.firstFrame()+1));
sb->setStatusText(0, fmt::format("{} before frame {}",
verb, int(m_dropRange.firstFrame()+1)));
return;
}
else if (m_dropTarget.hhit == DropTarget::After) {
sb->setStatusText(0, "%s after frame %d", verb, int(m_dropRange.lastFrame()+1));
sb->setStatusText(0, fmt::format("{} after frame {}",
verb, int(m_dropRange.lastFrame()+1)));
return;
}
}
@ -3291,7 +3294,7 @@ void Timeline::updateStatusBar(ui::Message* msg)
break;
if (m_dropTarget.vhit == DropTarget::VeryBottom) {
sb->setStatusText(0, "%s at the very bottom", verb);
sb->setStatusText(0, fmt::format("{} at the very bottom", verb));
return;
}
@ -3306,13 +3309,16 @@ void Timeline::updateStatusBar(ui::Message* msg)
if (layer) {
switch (m_dropTarget.vhit) {
case DropTarget::Bottom:
sb->setStatusText(0, "%s at bottom of layer %s", verb, layer->name().c_str());
sb->setStatusText(0, fmt::format("{} below layer '{}'",
verb, layer->name()));
return;
case DropTarget::Top:
sb->setStatusText(0, "%s at top of layer %s", verb, layer->name().c_str());
sb->setStatusText(0, fmt::format("{} above layer '{}'",
verb, layer->name()));
return;
case DropTarget::FirstChild:
sb->setStatusText(0, "%s as first child of layer %s", verb, layer->name().c_str());
sb->setStatusText(0, fmt::format("{} as first child of group '{}'",
verb, layer->name()));
return;
}
}
@ -3328,37 +3334,41 @@ void Timeline::updateStatusBar(ui::Message* msg)
switch (m_hot.part) {
case PART_HEADER_ONIONSKIN: {
sb->setStatusText(0, "Onionskin is %s",
docPref().onionskin.active() ? "enabled": "disabled");
sb->setStatusText(0, fmt::format("Onionskin is {}",
docPref().onionskin.active()
? "enabled": "disabled"));
return;
}
case PART_ROW_TEXT:
if (layer != NULL) {
sb->setStatusText(
0, "%s '%s' [%s%s]",
layer->isReference() ? "Reference layer": "Layer",
layer->name().c_str(),
layer->isVisible() ? "visible": "hidden",
layer->isEditable() ? "": " locked");
0, fmt::format("{} '{}' [{}{}]",
layer->isReference() ? "Reference layer": "Layer",
layer->name(),
layer->isVisible() ? "visible": "hidden",
layer->isEditable() ? "": " locked"));
return;
}
break;
case PART_ROW_EYE_ICON:
if (layer != NULL) {
sb->setStatusText(0, "Layer '%s' is %s",
layer->name().c_str(),
layer->isVisible() ? "visible": "hidden");
sb->setStatusText(
0, fmt::format("Layer '{}' is {}",
layer->name(),
layer->isVisible() ? "visible": "hidden"));
return;
}
break;
case PART_ROW_PADLOCK_ICON:
if (layer != NULL) {
sb->setStatusText(0, "Layer '%s' is %s",
layer->name().c_str(),
layer->isEditable() ? "unlocked (editable)": "locked (read-only)");
sb->setStatusText(
0, fmt::format("Layer '{}' is {}",
layer->name(),
layer->isEditable() ? "unlocked (editable)":
"locked (read-only)"));
return;
}
break;
@ -3366,12 +3376,16 @@ void Timeline::updateStatusBar(ui::Message* msg)
case PART_ROW_CONTINUOUS_ICON:
if (layer) {
if (layer->isImage())
sb->setStatusText(0, "Layer '%s' is %s (%s)",
layer->name().c_str(),
layer->isContinuous() ? "continuous": "discontinuous",
layer->isContinuous() ? "prefer linked cels/frames": "prefer individual cels/frames");
sb->setStatusText(
0, fmt::format("Layer '{}' is {} ({})",
layer->name(),
layer->isContinuous() ? "continuous":
"discontinuous",
layer->isContinuous() ? "prefer linked cels/frames":
"prefer individual cels/frames"));
else if (layer->isGroup())
sb->setStatusText(0, "Group '%s'", layer->name().c_str());
sb->setStatusText(
0, fmt::format("Group '{}'", layer->name()));
return;
}
break;
@ -3455,8 +3469,7 @@ void Timeline::updateStatusBarForFrame(const frame_t frame,
}
}
StatusBar::instance()
->setStatusText(0, buf);
StatusBar::instance()->setStatusText(0, buf);
}
void Timeline::showCel(layer_t layer, frame_t frame)