Add possibility to write math expression in number textboxes (fix #1762)

This commit is contained in:
David Capello 2018-06-28 13:33:13 -03:00
parent aa8d4dfc11
commit f595ceea7f
32 changed files with 337 additions and 172 deletions

3
.gitmodules vendored
View File

@ -60,3 +60,6 @@
[submodule "third_party/fmt"]
path = third_party/fmt
url = https://github.com/aseprite/fmt.git
[submodule "third_party/tinyexpr"]
path = third_party/tinyexpr
url = https://github.com/aseprite/tinyexpr.git

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="canvas_size" text="@.title">
<vbox>
@ -7,9 +7,9 @@
<hbox>
<grid columns="2">
<label text="@.width" />
<entry text="0" id="width" maxsize="32" maxwidth="64" suffix="px" magnet="true" />
<expr text="0" id="width" suffix="px" magnet="true" />
<label text="@.height" />
<entry text="0" id="height" maxsize="32" maxwidth="64" suffix="px" />
<expr text="0" id="height" suffix="px" />
<hbox filler="true" cell_hspan="2" />
</grid>
<buttonset columns="3" id="dir">
@ -28,16 +28,16 @@
<separator text="@.borders" left="true" horizontal="true" />
<grid columns="4">
<label text="@.left" />
<entry text="0" id="left" maxsize="32" maxwidth="64" suffix="px" tooltip="@.left_tooltip" />
<expr text="0" id="left" suffix="px" tooltip="@.left_tooltip" />
<label text="@.top" />
<entry text="0" id="top" maxsize="32" maxwidth="64" suffix="px" tooltip="@.top_tooltip" />
<expr text="0" id="top" suffix="px" tooltip="@.top_tooltip" />
<label text="@.right" />
<entry text="0" id="right" maxsize="32" maxwidth="64" suffix="px" tooltip="@.right_tooltip" />
<expr text="0" id="right" suffix="px" tooltip="@.right_tooltip" />
<label text="@.bottom" />
<entry text="0" id="bottom" maxsize="32" maxwidth="64" suffix="px" tooltip="@.bottom_tooltip" />
<expr text="0" id="bottom" suffix="px" tooltip="@.bottom_tooltip" />
</grid>
<separator horizontal="true" />

View File

@ -1,15 +1,15 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="color_curve_point" text="@.title">
<vbox>
<hbox expansive="true">
<grid columns="2">
<label text="@.x" />
<entry maxsize="32" id="x" magnet="true" />
<expr id="x" magnet="true" />
<label text="@.y" />
<entry maxsize="32" id="y" />
<expr id="y" />
</grid>
</hbox>
<hbox homogeneous="true">

View File

@ -1,10 +1,12 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<grid columns="2" id="controls">
<label text="@despeckle.width" />
<entry id="width" maxsize="4" cell_align="horizontal" />
<label text="@despeckle.height" />
<entry id="height" maxsize="4" cell_align="horizontal" />
<hbox id="despeckle">
<grid columns="2">
<label text="@.width" />
<expr id="width" cell_align="horizontal" />
<label text="@.height" />
<expr id="height" cell_align="horizontal" />
</grid>
</hbox>
</gui>

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2017 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="export_sprite_sheet" text="@.title">
<grid columns="4">
@ -7,11 +7,11 @@
<combobox id="sheet_type" cell_hspan="3" />
<label id="columns_label" text="@.columns" />
<entry id="columns" text="" maxsize="4" />
<expr id="columns" text="" />
<boxfiller cell_hspan="2" />
<label id="rows_label" text="@.rows" />
<entry id="rows" text="" maxsize="4" />
<expr id="rows" text="" />
<boxfiller cell_hspan="2" />
<hbox />
@ -21,11 +21,11 @@
</vbox>
<grid columns="2" id="padding_container" cell_hspan="2">
<label text="@.border" />
<entry id="border_padding" text="0" maxsize="4" />
<expr id="border_padding" text="0" />
<label text="@.shape" />
<entry id="shape_padding" text="0" maxsize="4" />
<expr id="shape_padding" text="0" />
<label text="@.inner" />
<entry id="inner_padding" text="0" maxsize="4" />
<expr id="inner_padding" text="0" />
</grid>
<label id="fit_width_label" text="@.width" />

View File

@ -1,23 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<gui>
<window id="frame_properties" text="@.title">
<grid columns="3">
<label text="@.frame_number" />
<label text="" id="frame" />
<box cell_align="horizontal" />
<label text="@.duration" />
<entry maxsize="10" id="frlen" magnet="true" />
<box cell_align="horizontal" />
<separator horizontal="true" cell_hspan="3" />
<box horizontal="true" homogeneous="true" cell_hspan="3" cell_align="right">
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
<button text="@general.cancel" closewindow="true" />
</box>
</grid>
</window>
</gui>
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="frame_properties" text="@.title">
<grid columns="3">
<label text="@.frame_number" />
<label text="" id="frame" />
<box cell_align="horizontal" />
<label text="@.duration" />
<expr id="frlen" magnet="true" />
<box cell_align="horizontal" />
<separator horizontal="true" cell_hspan="3" />
<box horizontal="true" homogeneous="true" cell_hspan="3" cell_align="right">
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
<button text="@general.cancel" closewindow="true" />
</box>
</grid>
</window>
</gui>

View File

@ -1,30 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2015-2017 by David Capello -->
<gui>
<window id="frame_tag_properties" text="@.title">
<grid columns="2">
<label text="@.name" />
<entry maxsize="256" id="name" magnet="true" />
<label text="@.from" />
<entry maxsize="10" id="from" />
<label text="@.to" />
<entry maxsize="10" id="to" />
<label text="@.color" />
<colorpicker id="color" simple="true" />
<label text="@.ani_dir" />
<combobox id="anidir" />
<separator horizontal="true" cell_hspan="2" />
<box horizontal="true" homogeneous="true" cell_hspan="2" cell_align="right">
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
<button text="@general.cancel" closewindow="true" />
</box>
</grid>
</window>
</gui>
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2015-2018 by David Capello -->
<gui>
<window id="frame_tag_properties" text="@.title">
<grid columns="2">
<label text="@.name" />
<entry maxsize="256" id="name" magnet="true" />
<label text="@.from" />
<expr id="from" />
<label text="@.to" />
<expr id="to" />
<label text="@.color" />
<colorpicker id="color" simple="true" />
<label text="@.ani_dir" />
<combobox id="anidir" />
<separator horizontal="true" cell_hspan="2" />
<box horizontal="true" homogeneous="true" cell_hspan="2" cell_align="right">
<button text="@general.ok" closewindow="true" id="ok" magnet="true" minwidth="60" />
<button text="@general.cancel" closewindow="true" />
</box>
</grid>
</window>
</gui>

View File

@ -1,20 +1,20 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="grid_settings" text="@.title">
<grid columns="4">
<label text="@.x" />
<entry id="grid_x" text="" maxsize="4" magnet="true" />
<expr id="grid_x" text="" magnet="true" />
<label text="@.y" />
<entry id="grid_y" text="" maxsize="4" />
<expr id="grid_y" text="" />
<label text="@.width" />
<entry id="grid_w" text="" maxsize="4" />
<expr id="grid_w" text="" />
<label text="@.height" />
<entry id="grid_h" text="" maxsize="4" />
<expr id="grid_h" text="" />
<separator horizontal="true" cell_hspan="4" />

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="import_sprite_sheet" text="@.title">
<grid columns="4">
@ -9,16 +9,16 @@
<combobox id="sheet_type" cell_hspan="3" />
<label text="@.x" />
<entry id="x" text="0" maxsize="4" />
<expr id="x" text="0" />
<label text="@.y" />
<entry id="y" text="0" maxsize="4" />
<expr id="y" text="0" />
<label text="@.width" />
<entry id="width" text="16" maxsize="4" />
<expr id="width" text="16" />
<label text="@.height" />
<entry id="height" text="16" maxsize="4" />
<expr id="height" text="16" />
<check id="partial_tiles" text="@.partial_tiles" cell_hspan="4" />

View File

@ -1,12 +1,12 @@
<!-- Aseprite -->
<!-- Copyright (C) 2015-2016 by David Capello -->
<!-- Copyright (C) 2015-2018 by David Capello -->
<gui>
<window id="modify_selection" text="@.title">
<vbox>
<grid columns="2">
<label id="by_label" text="" />
<entry id="quantity" expansive="true" maxsize="4" magnet="true" suffix="px" />
<expr id="quantity" expansive="true" magnet="true" suffix="px" />
<hbox />
<vbox>

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="new_sprite" text="@.title">
<box vertical="true">
@ -7,9 +7,9 @@
<separator text="@.size" left="true" horizontal="true" />
<grid columns="2">
<label text="@.width" />
<entry id="width" maxsize="8" magnet="true" cell_align="horizontal" suffix="px" />
<expr id="width" magnet="true" cell_align="horizontal" suffix="px" />
<label text="@.height" />
<entry id="height" maxsize="8" cell_align="horizontal" suffix="px" />
<expr id="height" cell_align="horizontal" suffix="px" />
</grid>
<separator text="@.color_mode" left="true" horizontal="true" />

View File

@ -151,7 +151,7 @@
pref="general.rewind_on_stop" />
<hbox>
<label text="@.default_first_frame" />
<entry id="first_frame" maxsize="3" />
<expr id="first_frame" />
</hbox>
</vbox>
@ -231,15 +231,15 @@
<grid columns="5">
<label text="@.grid_x" />
<entry id="grid_x" text="" maxsize="4" />
<expr id="grid_x" text="" />
<label text="@.grid_y" />
<entry id="grid_y" text="" maxsize="4" />
<expr id="grid_y" text="" />
<hbox />
<label text="@.grid_width" />
<entry id="grid_w" text="" maxsize="4" />
<expr id="grid_w" text="" />
<label text="@.grid_height" />
<entry id="grid_h" text="" maxsize="4" />
<expr id="grid_h" text="" />
<hbox />
<label text="@.grid_color" />
@ -293,7 +293,7 @@
<separator text="@.section_undo" horizontal="true" />
<hbox>
<check id="limit_undo" text="@.undo_size_limit" />
<entry id="undo_size_limit" maxsize="6" tooltip="@.undo_size_limit_tooltip" />
<expr id="undo_size_limit" tooltip="@.undo_size_limit_tooltip" />
<label text="@.undo_mb" />
</hbox>

View File

@ -1,10 +1,10 @@
<!-- Aseprite -->
<!-- Copyright (C) 2015-2016 by David Capello -->
<!-- Copyright (C) 2015-2018 by David Capello -->
<gui>
<window id="palette_from_sprite" text="@.title">
<grid columns="2">
<radio id="new_palette" text="@.new_palette" group="1" />
<entry expansive="true" maxsize="4" id="ncolors" magnet="true" />
<expr expansive="true" id="ncolors" magnet="true" />
<radio id="current_palette" text="@.replace_palette" group="1" cell_hspan="2" />
<radio id="current_range" text="@.replace_range" group="1" cell_hspan="2" />
<check id="alpha_channel" text="@.alpha_channel" cell_hspan="2" />

View File

@ -1,10 +1,10 @@
<!-- Aseprite -->
<!-- Copyright (C) 2015-2016 by David Capello -->
<!-- Copyright (C) 2015-2018 by David Capello -->
<gui>
<window id="palette_size" text="@.title">
<grid columns="3">
<label text="@.number_of_colors" />
<entry expansive="true" maxsize="4" id="colors" magnet="true" />
<expr expansive="true" id="colors" magnet="true" />
<box cell_align="horizontal" />
<separator horizontal="true" cell_hspan="3" />

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2015-2016 by David Capello -->
<!-- Copyright (C) 2015-2018 by David Capello -->
<gui>
<window id="paste_text" text="@.title">
<grid columns="2">
@ -7,7 +7,7 @@
<entry expansive="true" maxsize="256" id="user_text" magnet="true" cell_align="horizontal" />
<label text="@.font_size" />
<entry id="font_size" maxsize="3" text="32" cell_align="horizontal" />
<expr id="font_size" text="32" cell_align="horizontal" />
<label text="@.font" />
<dropdownbutton minwidth="60" id="font_face" text="@.select_font" cell_align="horizontal" />

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Aseprite -->
<!-- Copyright (C) 2017 by David Capello -->
<!-- Copyright (C) 2017-2018 by David Capello -->
<gui>
<window id="slice_properties" text="@.title">
<grid columns="2">
@ -22,24 +22,24 @@
<label text="@.bounds" />
<hbox homogeneous="true">
<entry maxsize="8" id="bounds_x" />
<entry maxsize="8" id="bounds_y" />
<entry maxsize="8" id="bounds_w" />
<entry maxsize="8" id="bounds_h" />
<expr id="bounds_x" />
<expr id="bounds_y" />
<expr id="bounds_w" />
<expr id="bounds_h" />
</hbox>
<check text="@.center" id="center" />
<hbox homogeneous="true">
<entry maxsize="8" id="center_x" text="0" />
<entry maxsize="8" id="center_y" text="0" />
<entry maxsize="8" id="center_w" text="0" />
<entry maxsize="8" id="center_h" text="0" />
<expr id="center_x" text="0" />
<expr id="center_y" text="0" />
<expr id="center_w" text="0" />
<expr id="center_h" text="0" />
</hbox>
<check text="@.pivot" id="pivot" />
<hbox>
<entry maxsize="8" id="pivot_x" text="0" />
<entry maxsize="8" id="pivot_y" text="0" />
<expr id="pivot_x" text="0" />
<expr id="pivot_y" text="0" />
</hbox>
<separator horizontal="true" cell_hspan="2" />

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2001-2016 by David Capello -->
<!-- Copyright (C) 2001-2018 by David Capello -->
<gui>
<window id="sprite_size" text="@.title">
<box vertical="true">
@ -12,8 +12,8 @@
<label text="@.height" />
</box>
<box vertical="true" homogeneous="true" expansive="true">
<entry expansive="true" id="width_px" suffix="px" maxsize="8" magnet="true" tooltip="@.width_px_tooltip" />
<entry expansive="true" id="height_px" suffix="px" maxsize="8" tooltip="@.height_px_tooltip" />
<expr expansive="true" id="width_px" suffix="px" magnet="true" tooltip="@.width_px_tooltip" />
<expr expansive="true" id="height_px" suffix="px" tooltip="@.height_px_tooltip" />
</box>
<check text="@.lock_ratio" id="lock_ratio" selected="true" />
</box>
@ -26,8 +26,10 @@
<label text="@.height" />
</box>
<box vertical="true" homogeneous="true" expansive="true">
<entry expansive="true" text="100" suffix="%" id="width_perc" maxsize="8" magnet="true" tooltip="@.width_perc_tooltip" />
<entry expansive="true" text="100" suffix="%" id="height_perc" maxsize="8" tooltip="@.height_perc_tooltip" />
<expr expansive="true" text="100" suffix="%" id="width_perc" magnet="true" tooltip="@.width_perc_tooltip"
decimals="4" />
<expr expansive="true" text="100" suffix="%" id="height_perc" tooltip="@.height_perc_tooltip"
decimals="4" />
</box>
<box horizontal="true" width="64" />
</box>

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2014-2017 by David Capello -->
<!-- Copyright (C) 2014-2018 by David Capello -->
<gui>
<vbox id="timeline_conf">
<hbox>
@ -17,7 +17,7 @@
<separator text="@.frame_header" left="true" horizontal="true" />
<hbox>
<label text="@.first_frame" />
<entry id="first_frame" maxsize="3" />
<expr id="first_frame" />
</hbox>
<hbox>

View File

@ -1054,6 +1054,30 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
# [tinyexpr](https://github.com/codeplea/tinyexpr)
```
zlib License
Copyright (C) 2015, 2016 Lewis Van Winkle
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgement in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
```
# [tinyxml](http://www.grinninglizard.com/tinyxml/)
```

View File

@ -347,6 +347,7 @@ if(ENABLE_UI)
ui/editor/transform_handles.cpp
ui/editor/zooming_state.cpp
ui/export_file_window.cpp
ui/expr_entry.cpp
ui/file_list.cpp
ui/file_list_view.cpp
ui/file_selector.cpp
@ -588,7 +589,8 @@ target_link_libraries(app-lib
${HARFBUZZ_LIBRARIES}
json11
archive_static
fmt)
fmt
tinyexpr)
if(ENABLE_SCRIPTING)
target_link_libraries(app-lib script-lib)

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -23,6 +23,8 @@
#include "doc/mask.h"
#include "ui/window.h"
#include "grid_settings.xml.h"
namespace app {
using namespace ui;
@ -102,28 +104,22 @@ bool GridSettingsCommand::onEnabled(Context* context)
void GridSettingsCommand::onExecute(Context* context)
{
base::UniquePtr<Window> window(app::load_widget<Window>("grid_settings.xml", "grid_settings"));
Widget* button_ok = app::find_widget<Widget>(window, "ok");
Widget* grid_x = app::find_widget<Widget>(window, "grid_x");
Widget* grid_y = app::find_widget<Widget>(window, "grid_y");
Widget* grid_w = app::find_widget<Widget>(window, "grid_w");
Widget* grid_h = app::find_widget<Widget>(window, "grid_h");
gen::GridSettings window;
DocumentPreferences& docPref = Preferences::instance().document(context->activeDocument());
Rect bounds = docPref.grid.bounds();
grid_x->setTextf("%d", bounds.x);
grid_y->setTextf("%d", bounds.y);
grid_w->setTextf("%d", bounds.w);
grid_h->setTextf("%d", bounds.h);
window.gridX()->setTextf("%d", bounds.x);
window.gridY()->setTextf("%d", bounds.y);
window.gridW()->setTextf("%d", bounds.w);
window.gridH()->setTextf("%d", bounds.h);
window.openWindowInForeground();
window->openWindowInForeground();
if (window->closer() == button_ok) {
bounds.x = grid_x->textInt();
bounds.y = grid_y->textInt();
bounds.w = grid_w->textInt();
bounds.h = grid_h->textInt();
if (window.closer() == window.ok()) {
bounds.x = window.gridX()->textInt();
bounds.y = window.gridY()->textInt();
bounds.w = window.gridW()->textInt();
bounds.h = window.gridH()->textInt();
bounds.w = MAX(bounds.w, 1);
bounds.h = MAX(bounds.h, 1);

View File

@ -33,7 +33,7 @@
#include "sprite_size.xml.h"
#define PERC_FORMAT "%.1f"
#define PERC_FORMAT "%.4g"
namespace app {

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -28,6 +28,8 @@
#include "ui/widget.h"
#include "ui/window.h"
#include "despeckle.xml.h"
#include <stdio.h>
namespace app {
@ -44,9 +46,9 @@ public:
WithTiledCheckBox,
filter.getTiledMode())
, m_filter(filter)
, m_controlsWidget(app::load_widget<ui::Widget>("despeckle.xml", "controls"))
, m_widthEntry(app::find_widget<ui::Entry>(m_controlsWidget, "width"))
, m_heightEntry(app::find_widget<ui::Entry>(m_controlsWidget, "height"))
, m_controlsWidget(new gen::Despeckle)
, m_widthEntry(m_controlsWidget->width())
, m_heightEntry(m_controlsWidget->height())
{
getContainer()->addChild(m_controlsWidget);
@ -58,14 +60,13 @@ public:
}
private:
void onSizeChange()
{
void onSizeChange() {
gfx::Size newSize(m_widthEntry->textInt(),
m_heightEntry->textInt());
// Avoid negative numbers
newSize.w = MAX(1, newSize.w);
newSize.h = MAX(1, newSize.h);
newSize.w = MID(1, newSize.w, 100);
newSize.h = MID(1, newSize.h, 100);
m_filter.setSize(newSize.w, newSize.h);
restartPreview();
@ -77,9 +78,9 @@ private:
}
MedianFilter& m_filter;
base::UniquePtr<ui::Widget> m_controlsWidget;
ui::Entry* m_widthEntry;
ui::Entry* m_heightEntry;
base::UniquePtr<gen::Despeckle> m_controlsWidget;
ExprEntry* m_widthEntry;
ExprEntry* m_heightEntry;
};
//////////////////////////////////////////////////////////////////////

View File

@ -267,8 +267,8 @@ bool ColorCurveEditor::editNodeManually(gfx::Point& viewPt)
window.openWindowInForeground();
if (window.closer() == window.ok()) {
viewPt.x = int(window.x()->textDouble());
viewPt.y = int(window.y()->textDouble());
viewPt.x = window.x()->textInt();
viewPt.y = window.y()->textInt();
viewPt.x = MID(0, viewPt.x, 255);
viewPt.y = MID(0, viewPt.y, 255);
return true;

74
src/app/ui/expr_entry.cpp Normal file
View File

@ -0,0 +1,74 @@
// Aseprite
// Copyright (C) 2018 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/expr_entry.h"
#include "ui/message.h"
#include "tinyexpr.h"
#include <cmath>
#include <cstdio>
namespace app {
ExprEntry::ExprEntry()
: ui::Entry(1024, "")
, m_decimals(0)
{
}
bool ExprEntry::onProcessMessage(ui::Message* msg)
{
switch (msg->type()) {
case ui::kFocusLeaveMessage: {
char buf[256];
if (m_decimals == 0) {
std::snprintf(buf, sizeof(buf), "%d", onGetTextInt());
}
else {
std::snprintf(buf, sizeof(buf), "%.*g",
m_decimals, onGetTextDouble());
}
if (text() != buf)
setText(buf);
break;
}
}
return ui::Entry::onProcessMessage(msg);
}
void ExprEntry::onChange()
{
Entry::onChange();
// TODO show expression errors?
}
int ExprEntry::onGetTextInt() const
{
int err = 0;
double v = te_interp(text().c_str(), &err);
if (std::isnan(v))
return Entry::onGetTextInt();
else
return int(v);
}
double ExprEntry::onGetTextDouble() const
{
int err = 0;
double v = te_interp(text().c_str(), &err);
if (std::isnan(v))
return Entry::onGetTextDouble();
else
return v;
}
} // namespace app

35
src/app/ui/expr_entry.h Normal file
View File

@ -0,0 +1,35 @@
// Aseprite
// Copyright (C) 2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef APP_UI_EXPR_ENTRY_H_INCLUDED
#define APP_UI_EXPR_ENTRY_H_INCLUDED
#pragma once
#include "ui/entry.h"
namespace app {
// Support math expressions.
class ExprEntry : public ui::Entry {
public:
ExprEntry();
void setDecimals(int decimals) {
m_decimals = decimals;
}
protected:
bool onProcessMessage(ui::Message* msg) override;
void onChange() override;
int onGetTextInt() const override;
double onGetTextDouble() const override;
int m_decimals;
};
} // namespace app
#endif

View File

@ -19,6 +19,7 @@
#include "app/ui/button_set.h"
#include "app/ui/color_button.h"
#include "app/ui/drop_down_button.h"
#include "app/ui/expr_entry.h"
#include "app/ui/icon_button.h"
#include "app/ui/search_entry.h"
#include "app/ui/skin/skin_theme.h"
@ -229,23 +230,28 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
if (editable)
((ComboBox*)widget)->setEditable(true);
}
else if (elem_name == "entry") {
else if (elem_name == "entry" ||
elem_name == "expr") {
const char* maxsize = elem->Attribute("maxsize");
const char* suffix = elem->Attribute("suffix");
if (maxsize != NULL) {
bool readonly = bool_attr_is_true(elem, "readonly");
widget = new Entry(strtol(maxsize, NULL, 10), "");
if (readonly)
((Entry*)widget)->setReadOnly(true);
if (suffix)
((Entry*)widget)->setSuffix(suffix);
}
else
if (elem_name == "entry" && !maxsize)
throw std::runtime_error("<entry> element found without 'maxsize' attribute");
const char* suffix = elem->Attribute("suffix");
const char* decimals = elem->Attribute("decimals");
const bool readonly = bool_attr_is_true(elem, "readonly");
widget = (elem_name == "expr" ?
new ExprEntry:
new Entry(strtol(maxsize, nullptr, 10), ""));
if (readonly)
((Entry*)widget)->setReadOnly(true);
if (suffix)
((Entry*)widget)->setSuffix(suffix);
if (elem_name == "expr" && decimals)
((ExprEntry*)widget)->setDecimals(strtol(decimals, nullptr, 10));
}
else if (elem_name == "grid") {
const char *columns = elem->Attribute("columns");

View File

@ -107,6 +107,9 @@ static Item convert_to_item(TiXmlElement* elem)
if (name == "entry")
return item.typeIncl("ui::Entry",
"ui/entry.h");
if (name == "expr")
return item.typeIncl("app::ExprEntry",
"app/ui/expr_entry.h");
if (name == "grid")
return item.typeIncl("ui::Grid",
"ui/grid.h");

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -122,12 +122,12 @@ void Widget::initTheme()
int Widget::textInt() const
{
return strtol(m_text.c_str(), NULL, 10);
return onGetTextInt();
}
double Widget::textDouble() const
{
return strtod(m_text.c_str(), NULL);
return onGetTextDouble();
}
void Widget::setText(const std::string& text)
@ -1583,6 +1583,16 @@ void Widget::onSetBgColor()
invalidate();
}
int Widget::onGetTextInt() const
{
return std::strtol(m_text.c_str(), nullptr, 10);
}
double Widget::onGetTextDouble() const
{
return std::strtod(m_text.c_str(), nullptr);
}
void Widget::offsetWidgets(int dx, int dy)
{
m_updateRegion.offset(dx, dy);

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2017 David Capello
// Copyright (C) 2001-2018 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -389,6 +389,8 @@ namespace ui {
virtual void onSelect(bool selected);
virtual void onSetText();
virtual void onSetBgColor();
virtual int onGetTextInt() const;
virtual double onGetTextDouble() const;
private:
void removeChild(WidgetsList::iterator& it);

View File

@ -169,3 +169,7 @@ add_library(mujs
mujs/utf.c
mujs/utftype.c)
target_include_directories(mujs PUBLIC .)
# tinyexpr
add_library(tinyexpr tinyexpr/tinyexpr.c)
target_include_directories(tinyexpr PUBLIC tinyexpr)

1
third_party/tinyexpr vendored Submodule

@ -0,0 +1 @@
Subproject commit ffb0d41b13e5f8d318db95feb071c220c134fe70