summaryrefslogtreecommitdiff
path: root/fluid/Shortcut_Button.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2022-02-13 22:01:16 +0100
committerGitHub <noreply@github.com>2022-02-13 22:01:16 +0100
commit8c3778e13feebced373497a3e4060ae065cf65b7 (patch)
tree96ba807115e42e5f3cd35156343ccf5f700e5559 /fluid/Shortcut_Button.cxx
parentf196ffbb528f9ec5030697bc03fb956f79c9563e (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.cxx147
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);
+}