mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
259 lines
5.7 KiB
C++
259 lines
5.7 KiB
C++
// Aseprite UI Library
|
|
// Copyright (C) 2019-2020 Igara Studio S.A.
|
|
// Copyright (C) 2001-2018 David Capello
|
|
//
|
|
// This file is released under the terms of the MIT license.
|
|
// Read LICENSE.txt for more information.
|
|
|
|
/***********************************************************************
|
|
|
|
Alert format:
|
|
------------
|
|
|
|
"Title Text"
|
|
"==Centre line of text"
|
|
"--"
|
|
"<<Left line of text"
|
|
">>Right line of text"
|
|
"||My &Button||&Your Button||&He Button"
|
|
|
|
.-----------------------------------------.
|
|
| My Message |
|
|
+=========================================+
|
|
| Centre line of text |
|
|
| --------------------------------------- |
|
|
| Left line of text |
|
|
| Right line of text |
|
|
| |
|
|
| [My Button] [Your Button] [Him Button] |
|
|
`-----~---------~-------------~-----------'
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "ui/alert.h"
|
|
|
|
#include "base/clamp.h"
|
|
#include "base/string.h"
|
|
#include "ui/box.h"
|
|
#include "ui/button.h"
|
|
#include "ui/grid.h"
|
|
#include "ui/label.h"
|
|
#include "ui/scale.h"
|
|
#include "ui/separator.h"
|
|
#include "ui/slider.h"
|
|
#include "ui/theme.h"
|
|
|
|
#include <cstdio>
|
|
|
|
namespace ui {
|
|
|
|
Alert::Alert()
|
|
: Window(WithTitleBar)
|
|
, m_progress(nullptr)
|
|
, m_progressPlaceholder(nullptr)
|
|
{
|
|
auto box1 = new Box(VERTICAL);
|
|
auto box2 = new Box(VERTICAL);
|
|
auto grid = new Grid(1, false);
|
|
auto box3 = new Box(HORIZONTAL | HOMOGENEOUS);
|
|
|
|
// To identify by the user
|
|
box2->setId("labels");
|
|
box3->setId("buttons");
|
|
m_labelsPlaceholder = box2;
|
|
m_buttonsPlaceholder = box3;
|
|
|
|
// Pseudo separators (only to fill blank space)
|
|
auto box4 = new Box(0);
|
|
auto box5 = new Box(0);
|
|
m_progressPlaceholder = new Box(0);
|
|
|
|
box4->setExpansive(true);
|
|
box5->setExpansive(true);
|
|
box4->noBorderNoChildSpacing();
|
|
box5->noBorderNoChildSpacing();
|
|
m_progressPlaceholder->noBorderNoChildSpacing();
|
|
|
|
// Setup parent <-> children relationship
|
|
|
|
addChild(box1);
|
|
|
|
box1->addChild(box4); // Filler
|
|
box1->addChild(box2); // Labels
|
|
box1->addChild(m_progressPlaceholder);
|
|
box1->addChild(box5); // Filler
|
|
box1->addChild(grid); // Buttons
|
|
|
|
grid->addChildInCell(box3, 1, 1, CENTER | BOTTOM | HORIZONTAL);
|
|
}
|
|
|
|
void Alert::setTitle(const std::string& title)
|
|
{
|
|
setText(title);
|
|
}
|
|
|
|
void Alert::addLabel(const std::string& text, const int align)
|
|
{
|
|
auto label = new Label(text);
|
|
label->setAlign(align);
|
|
m_labelsPlaceholder->addChild(label);
|
|
}
|
|
|
|
void Alert::addSeparator()
|
|
{
|
|
auto sep = new Separator("", HORIZONTAL);
|
|
m_labelsPlaceholder->addChild(sep);
|
|
}
|
|
|
|
void Alert::addButton(const std::string& text)
|
|
{
|
|
auto button = new Button(text);
|
|
button->processMnemonicFromText();
|
|
button->setMinSize(gfx::Size(60*guiscale(), 0));
|
|
m_buttons.push_back(button);
|
|
|
|
char id[256];
|
|
sprintf(id, "button-%lu", m_buttons.size());
|
|
button->setId(id);
|
|
button->Click.connect([this, button]{ closeWindow(button); });
|
|
|
|
m_buttonsPlaceholder->addChild(button);
|
|
}
|
|
|
|
void Alert::addProgress()
|
|
{
|
|
ASSERT(!m_progress);
|
|
m_progress = new Slider(0, 100, 0);
|
|
m_progress->setReadOnly(true);
|
|
m_progressPlaceholder->addChild(m_progress);
|
|
m_progressPlaceholder->setVisible(true);
|
|
}
|
|
|
|
CheckBox* Alert::addCheckBox(const std::string& text)
|
|
{
|
|
auto checkBox = new CheckBox(text);
|
|
m_progressPlaceholder->addChild(checkBox);
|
|
m_progressPlaceholder->setVisible(true);
|
|
return checkBox;
|
|
}
|
|
|
|
void Alert::setProgress(double progress)
|
|
{
|
|
ASSERT(m_progress);
|
|
m_progress->setValue(int(base::clamp(progress * 100.0, 0.0, 100.0)));
|
|
}
|
|
|
|
// static
|
|
AlertPtr Alert::create(const std::string& _msg)
|
|
{
|
|
std::string msg(_msg);
|
|
|
|
// Create the alert window
|
|
AlertPtr window(new Alert);
|
|
window->processString(msg);
|
|
return window;
|
|
}
|
|
|
|
// static
|
|
int Alert::show(const std::string& _msg)
|
|
{
|
|
std::string msg(_msg);
|
|
|
|
// Create the alert window
|
|
AlertPtr window(new Alert);
|
|
window->processString(msg);
|
|
return window->show();
|
|
}
|
|
|
|
int Alert::show()
|
|
{
|
|
// Default button is the first one (Enter default option, Esc should
|
|
// act like the last button)
|
|
if (!m_buttons.empty())
|
|
m_buttons[0]->setFocusMagnet(true);
|
|
|
|
// Open it
|
|
openWindowInForeground();
|
|
|
|
// Check the closer
|
|
int ret = 0;
|
|
if (Widget* closer = this->closer()) {
|
|
for (int i=0; i<(int)m_buttons.size(); ++i) {
|
|
if (closer == m_buttons[i]) {
|
|
ret = i+1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// And return it
|
|
return ret;
|
|
}
|
|
|
|
void Alert::processString(std::string& buf)
|
|
{
|
|
bool title = true;
|
|
bool label = false;
|
|
bool separator = false;
|
|
bool button = false;
|
|
int align = 0;
|
|
|
|
// Process buffer
|
|
int c = 0;
|
|
int beg = 0;
|
|
for (;;) {
|
|
// Ignore characters
|
|
if (buf[c] == '\n' ||
|
|
buf[c] == '\r') {
|
|
buf.erase(c, 1);
|
|
continue;
|
|
}
|
|
|
|
if ((!buf[c]) ||
|
|
((buf[c] == buf[c+1]) &&
|
|
((buf[c] == '<') ||
|
|
(buf[c] == '=') ||
|
|
(buf[c] == '>') ||
|
|
(buf[c] == '-') ||
|
|
(buf[c] == '|')))) {
|
|
if (title || label || separator || button) {
|
|
std::string item = buf.substr(beg, c-beg);
|
|
|
|
if (title)
|
|
setTitle(item);
|
|
else if (label)
|
|
addLabel(item, align);
|
|
else if (separator)
|
|
addSeparator();
|
|
else if (button)
|
|
addButton(item);
|
|
}
|
|
|
|
// Done
|
|
if (!buf[c])
|
|
break;
|
|
// Next widget
|
|
else {
|
|
title = label = separator = button = false;
|
|
beg = c+2;
|
|
align = 0;
|
|
|
|
switch (buf[c]) {
|
|
case '<': label=true; align=LEFT; break;
|
|
case '=': label=true; align=CENTER; break;
|
|
case '>': label=true; align=RIGHT; break;
|
|
case '-': separator=true; break;
|
|
case '|': button=true; break;
|
|
}
|
|
++c;
|
|
}
|
|
}
|
|
++c;
|
|
}
|
|
}
|
|
|
|
} // namespace ui
|