lua: add app.alert() function

This commit is contained in:
David Capello 2018-09-07 16:42:58 -03:00
parent ef23e1b307
commit f604ac95dd
3 changed files with 160 additions and 72 deletions

View File

@ -13,12 +13,14 @@
#include "app/commands/params.h"
#include "app/context.h"
#include "app/doc.h"
#include "app/i18n/strings.h"
#include "app/pref/preferences.h"
#include "app/script/engine.h"
#include "app/script/luacpp.h"
#include "app/site.h"
#include "app/site.h"
#include "app/tx.h"
#include "ui/alert.h"
#include <iostream>
@ -94,6 +96,73 @@ int App_redo(lua_State* L)
return 0;
}
int App_alert(lua_State* L)
{
#ifdef ENABLE_UI
app::Context* ctx = App::instance()->context();
if (!ctx || !ctx->isUIAvailable())
return 0; // No UI to show the alert
// app.alert("text...")
else if (lua_isstring(L, 1)) {
ui::AlertPtr alert(new ui::Alert);
alert->addLabel(lua_tostring(L, 1), ui::CENTER);
alert->addButton(Strings::general_ok());
lua_pushinteger(L, alert->show());
return 1;
}
// app.alert{ ... }
else if (lua_istable(L, 1)) {
ui::AlertPtr alert(new ui::Alert);
int type = lua_getfield(L, 1, "title");
if (type != LUA_TNIL)
alert->setTitle(lua_tostring(L, -1));
lua_pop(L, 1);
type = lua_getfield(L, 1, "text");
if (type == LUA_TTABLE) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
const char* v = luaL_tolstring(L, -1, nullptr);
if (v)
alert->addLabel(v, ui::LEFT);
lua_pop(L, 2);
}
}
else if (type == LUA_TSTRING) {
alert->addLabel(lua_tostring(L, -1), ui::LEFT);
}
lua_pop(L, 1);
int nbuttons = 0;
type = lua_getfield(L, 1, "buttons");
if (type == LUA_TTABLE) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
const char* v = luaL_tolstring(L, -1, nullptr);
if (v) {
alert->addButton(v);
++nbuttons;
}
lua_pop(L, 2);
}
}
else if (type == LUA_TSTRING) {
alert->addButton(lua_tostring(L, -1));
++nbuttons;
}
lua_pop(L, 1);
if (nbuttons == 0)
alert->addButton(Strings::general_ok());
lua_pushinteger(L, alert->show());
return 1;
}
#endif
return 0;
}
int App_get_activeSprite(lua_State* L)
{
app::Context* ctx = App::instance()->context();
@ -167,6 +236,7 @@ const luaL_Reg App_methods[] = {
{ "transaction", App_transaction },
{ "undo", App_undo },
{ "redo", App_redo },
{ "alert", App_alert },
{ nullptr, nullptr }
};

View File

@ -54,7 +54,72 @@ Alert::Alert()
, m_progress(nullptr)
, m_progressPlaceholder(nullptr)
{
// Do nothing
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(base::Bind<void>(&Window::closeWindow, this, button));
m_buttonsPlaceholder->addChild(button);
}
void Alert::addProgress()
@ -86,7 +151,7 @@ AlertPtr Alert::create(const std::string& _msg)
std::string msg(_msg);
// Create the alert window
AlertPtr window(new Alert());
AlertPtr window(new Alert);
window->processString(msg);
return window;
}
@ -97,13 +162,18 @@ int Alert::show(const std::string& _msg)
std::string msg(_msg);
// Create the alert window
AlertPtr window(new Alert());
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();
@ -129,11 +199,10 @@ void Alert::processString(std::string& buf)
bool separator = false;
bool button = false;
int align = 0;
int c, beg;
// Process buffer
c = 0;
beg = 0;
int c = 0;
int beg = 0;
for (;;) {
// Ignore characters
if (buf[c] == '\n' ||
@ -152,28 +221,14 @@ void Alert::processString(std::string& buf)
if (title || label || separator || button) {
std::string item = buf.substr(beg, c-beg);
if (title) {
setText(item);
}
else if (label) {
Label* label = new Label(item);
label->setAlign(align);
m_labels.push_back(label);
}
else if (separator) {
m_labels.push_back(new Separator("", HORIZONTAL));
}
else if (button) {
char buttonId[256];
Button* button_widget = new Button(item);
button_widget->processMnemonicFromText();
button_widget->setMinSize(gfx::Size(60*guiscale(), 0));
m_buttons.push_back(button_widget);
sprintf(buttonId, "button-%lu", m_buttons.size());
button_widget->setId(buttonId);
button_widget->Click.connect(base::Bind<void>(&Window::closeWindow, this, button_widget));
}
if (title)
setTitle(item);
else if (label)
addLabel(item, align);
else if (separator)
addSeparator();
else if (button)
addButton(item);
}
// Done
@ -197,49 +252,6 @@ void Alert::processString(std::string& buf)
}
++c;
}
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");
// 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);
for (auto it=m_labels.begin(); it!=m_labels.end(); ++it)
box2->addChild(*it);
for (auto it=m_buttons.begin(); it!=m_buttons.end(); ++it)
box3->addChild(*it);
// 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);
}
} // namespace ui

View File

@ -27,6 +27,11 @@ namespace ui {
public:
Alert();
void setTitle(const std::string& title);
void addLabel(const std::string& text, const int align);
void addSeparator();
void addButton(const std::string& text);
void addProgress();
void setProgress(double progress);
@ -41,8 +46,9 @@ namespace ui {
void processString(std::string& buf);
Slider* m_progress;
Box* m_labelsPlaceholder;
Box* m_buttonsPlaceholder;
Box* m_progressPlaceholder;
std::vector<Widget*> m_labels;
std::vector<Widget*> m_buttons;
};