diff options
| author | Matthias Melcher <github@matthiasm.com> | 2022-02-13 22:01:16 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-13 22:01:16 +0100 |
| commit | 8c3778e13feebced373497a3e4060ae065cf65b7 (patch) | |
| tree | 96ba807115e42e5f3cd35156343ccf5f700e5559 /fluid/Shortcut_Button.cxx | |
| parent | f196ffbb528f9ec5030697bc03fb956f79c9563e (diff) | |
Better Fluid Widget dimension controls (#394)
* Size and position widgets can evaluate basic math.
* Allowing x, y, w, and h as variables for formulas.
Also supporting 'i' as a counting index when selecting multiple
widgets, so setting Y: to i*25+10 arranges all selected widgets
vertically.
* Additional variables cx, etc. for children box
cx, cy, cw, ch
Diffstat (limited to 'fluid/Shortcut_Button.cxx')
| -rw-r--r-- | fluid/Shortcut_Button.cxx | 147 |
1 files changed, 129 insertions, 18 deletions
diff --git a/fluid/Shortcut_Button.cxx b/fluid/Shortcut_Button.cxx index cb18aa2cc..72e4470a9 100644 --- a/fluid/Shortcut_Button.cxx +++ b/fluid/Shortcut_Button.cxx @@ -14,23 +14,6 @@ // https://www.fltk.org/bugs.php // -/// \defgroup fl_type Basic Node for all Widgets and Functions -/// \{ - -/** \class Fl_Type -Each object described by Fluid is one of these objects. They -are all stored in a double-linked list. - -The "type" of the object is covered by the virtual functions. -There will probably be a lot of these virtual functions. - -The type browser is also a list of these objects, but they -are "factory" instances, not "real" ones. These objects exist -only so the "make" method can be called on them. They are -not in the linked list and are not written to files or -copied or otherwise examined. -*/ - #include "Shortcut_Button.h" #include "fluid.h" @@ -194,4 +177,132 @@ int Widget_Bin_Window_Button::handle(int inEvent) return Fl_Button::handle(inEvent); } -/// \} +/** \class Fluid_Coord_Input + An Input field for widget coordinates and sizes. + This widget adds basic math capability to the text input field. + */ + +Fluid_Coord_Input::Fluid_Coord_Input(int x, int y, int w, int h, const char *l) : +Fl_Input(x, y, w, h, l), +user_callback_(0L), +vars_(0L), +vars_user_data_(0L) +{ + Fl_Input::callback((Fl_Callback*)callback_handler_cb); +} + +void Fluid_Coord_Input::callback_handler_cb(Fluid_Coord_Input *This, void *v) { + This->callback_handler(v); +} + +void Fluid_Coord_Input::callback_handler(void *v) { + if (user_callback_) + (*user_callback_)(this, v); + value( value() ); +} + +int Fluid_Coord_Input::eval_var(uchar *&s) const { + if (!vars_) + return 0; + // find the end of the variable name + uchar *v = s; + while (isalpha(*s)) s++; + int n = (int)(s-v); + // find the variable in the list + for (Fluid_Coord_Input_Vars *vars = vars_; vars->name_; vars++) { + if (strncmp((char*)v, vars->name_, n)==0 && vars->name_[n]==0) + return vars->callback_(this, vars_user_data_); + } + return 0; +} + +/** + Evaluate a textual function into an integer. + \param s remaining text in this function + \param prio priority of current operation + \param flags + \return the value so far + */ +int Fluid_Coord_Input::eval(uchar *&s, int prio) const { + int v =0, sgn = 1; + uchar c = *s++; + + // check for unary operator + if (c=='-') { sgn = -1; c = *s++; } + else if (c=='+') { sgn = 1; c = *s++; } + + if (c>='0' && c<='9') { + // numeric value + while (c>='0' && c<='9') { + v = v*10 + (c-'0'); + c = *s++; + } + } else if (isalpha(c)) { + v = eval_var(--s); + c = *s++; + } else if (c=='(') { + // opening bracket + v = eval(s, 5); + } else { + return sgn*v; // syntax error + } + if (sgn==-1) v = -v; + + // Now evaluate all following binary operators + for (;;) { + if (c==0) { + return v; + } else if (c=='+' || c=='-') { + if (prio<=4) { s--; return v; } + if (c=='+') { v += eval(s, 4); } + else if (c=='-') { v -= eval(s, 4); } + } else if (c=='*' || c=='/') { + if (prio<=3) { s--; return v; } + if (c=='*') { v *= eval(s, 3); } + else if (c=='/') { v /= eval(s, 3); } + } else if (c==')') { + return v; + } else { + return v; // syntax error + } + c = *s++; + } + return v; +} + +int Fluid_Coord_Input::eval(const char *s) const +{ + // duplicate the text, so we can modify it + uchar *buf = (uchar*)strdup(s); + uchar *src = buf, *dst = buf; + // remove all whitespace to make the parser easier + for (;;) { + uchar c = *src++; + if (c==' ' || c=='\t') continue; + *dst++ = c; + if (c==0) break; + } + src = buf; + // now jump into the recursion + int ret = eval(src, 5); + ::free(buf); + return ret; +} + + +int Fluid_Coord_Input::value() const { + +// int v = 0; +// v = eval("2+5+10"); +// v = eval("2*5+20"); // 30 +// v = eval("2+5*20"); // 102 +// v = eval("(2+5)*20"); // 140 +// v = eval("2*(2+5)*20"); // 140 + return eval(text()); +} + +void Fluid_Coord_Input::value(int v) { + char buf[32]; + fl_snprintf(buf, sizeof(buf), "%d", v); + text(buf); +} |
