| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /*
- * Copyright (c) 2012-2026 Daniele Bartolini et al.
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
- namespace Crown
- {
- public class InputDouble : InputField
- {
- public bool _inconsistent;
- public double _min;
- public double _max;
- public double _value;
- public int _preview_decimals;
- public int _edit_decimals;
- public Gtk.Entry _entry;
- public Gtk.GestureMultiPress _gesture_click;
- public Gtk.EventControllerScroll _controller_scroll;
- public override void set_inconsistent(bool inconsistent)
- {
- if (_inconsistent != inconsistent) {
- _inconsistent = inconsistent;
- if (_inconsistent) {
- _entry.text = INCONSISTENT_LABEL;
- } else {
- set_value_safe(string_to_double(_entry.text, _value));
- }
- }
- }
- public override bool is_inconsistent()
- {
- return _inconsistent;
- }
- public override GLib.Value union_value()
- {
- return this.value;
- }
- public override void set_union_value(GLib.Value v)
- {
- this.value = (double)v;
- }
- public double value
- {
- get
- {
- return _value;
- }
- set
- {
- set_value_safe(value);
- }
- }
- public InputDouble(double val, double min, double max, int preview_decimals = 4, int edit_decimals = 5)
- {
- _entry = new Gtk.Entry();
- _entry.input_purpose = Gtk.InputPurpose.NUMBER;
- _entry.set_width_chars(1);
- _entry.activate.connect(on_activate);
- _entry.focus_in_event.connect(on_focus_in);
- _entry.focus_out_event.connect(on_focus_out);
- _inconsistent = false;
- _min = min;
- _max = max;
- _preview_decimals = preview_decimals;
- _edit_decimals = edit_decimals;
- set_value_safe(val);
- _gesture_click = new Gtk.GestureMultiPress(_entry);
- _gesture_click.pressed.connect(on_button_pressed);
- _gesture_click.released.connect(on_button_released);
- #if CROWN_GTK3
- _entry.scroll_event.connect(() => {
- GLib.Signal.stop_emission_by_name(_entry, "scroll-event");
- return Gdk.EVENT_PROPAGATE;
- });
- #else
- _controller_scroll = new Gtk.EventControllerScroll(_entry, Gtk.EventControllerScrollFlags.BOTH_AXES);
- _controller_scroll.set_propagation_phase(Gtk.PropagationPhase.CAPTURE);
- _controller_scroll.scroll.connect(() => {
- // Do nothing, just consume the event to stop
- // the annoying scroll default behavior.
- });
- #endif
- this.add(_entry);
- }
- public void on_button_pressed(int n_press, double x, double y)
- {
- _entry.grab_focus();
- }
- public void on_button_released(int n_press, double x, double y)
- {
- uint button = _gesture_click.get_current_button();
- if (button == Gdk.BUTTON_PRIMARY && _entry.has_focus) {
- if (_inconsistent)
- _entry.text = "";
- else
- _entry.text = print_max_decimals(_value, _edit_decimals);
- GLib.Idle.add(() => {
- _entry.set_position(-1);
- _entry.select_region(0, -1);
- return GLib.Source.REMOVE;
- });
- }
- }
- public void on_activate()
- {
- _entry.select_region(0, 0);
- _entry.set_position(-1);
- if (_entry.text != print_max_decimals(_value, _edit_decimals))
- set_value_safe(string_to_double(_entry.text, _value));
- else
- _entry.text = print_max_decimals(_value, _preview_decimals);
- }
- public bool on_focus_in(Gdk.EventFocus ev)
- {
- var app = (LevelEditorApplication)GLib.Application.get_default();
- app.entry_any_focus_in(_entry);
- if (_inconsistent)
- _entry.text = "";
- else
- _entry.text = print_max_decimals(_value, _edit_decimals);
- _entry.set_position(-1);
- _entry.select_region(0, -1);
- return Gdk.EVENT_PROPAGATE;
- }
- public bool on_focus_out(Gdk.EventFocus ef)
- {
- var app = (LevelEditorApplication)GLib.Application.get_default();
- app.entry_any_focus_out(_entry);
- if (_inconsistent) {
- if (_entry.text != "") {
- set_value_safe(string_to_double(_entry.text, _value));
- } else {
- _entry.text = INCONSISTENT_LABEL;
- }
- } else {
- if (_entry.text != print_max_decimals(_value, _edit_decimals))
- set_value_safe(string_to_double(_entry.text, _value));
- else
- _entry.text = print_max_decimals(_value, _preview_decimals);
- }
- _entry.select_region(0, 0);
- return Gdk.EVENT_PROPAGATE;
- }
- public void set_value_safe(double val)
- {
- double clamped = val.clamp(_min, _max);
- // Convert to text for displaying.
- _entry.text = print_max_decimals(clamped, _preview_decimals);
- _inconsistent = false;
- // Notify value changed.
- if (_value != clamped) {
- _value = clamped;
- value_changed(this);
- }
- }
- /// Returns @a str as double or @a deffault if conversion fails.
- public double string_to_double(string str, double deffault)
- {
- TinyExpr.Variable vars[] =
- {
- { "x", &_value }
- };
- int err;
- TinyExpr.Expr expr = TinyExpr.compile(str, vars, out err);
- return err == 0 ? TinyExpr.eval(expr) : deffault;
- }
- public void set_min(double min)
- {
- _min = min;
- set_value_safe(_value);
- }
- public void set_max(double max)
- {
- _max = max;
- set_value_safe(_value);
- }
- }
- } /* namespace Crown */
|