Rev 2110 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* field.cc
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "field.h"
#include "font.h"
#include "utils.h"
#include "input.h"
#include "utils.h"
#include "tcl_interp.h"
#include <string>
#include <sstream>
#include <list>
#include <cstdlib>
using namespace std;
extern int lmb;
extern int mousex, mouseyy;
char get_typed_char ();
extern tcl_interp interpreter;
extern char BUFFER [];
int field::handle_input () {
widget::handle_input ();
// locate mouse in field
if (lmb) {
if (lmb_clicked == 0) {
lmb_clicked = 1;
if (hittest (mousex, mouseyy)) {
calc_cursor ();
edited |= 0;
widget::focus = this;
if (SHIFT) set_text ("");
} else {
if (widget::focus == this) {
defocus (this);
lmb_clicked = 0;
return 1;
}
}
}
} else {
lmb_clicked = 0;
}
if (focus) { // can edit text
char c = get_typed_char ();
if (c != 0) {
edited = 1;
if (mode == pushback)
text.push_back (c);
else
text.insert (text.begin() + cursor, c);
++len;
++last;
++cursor;
calc_cursor ();
if (typing_lsnr) typing_lsnr->typing (*this);
}
if (keypressed (SDLK_ESCAPE)) { // abort editing
focus = 0;
defocus (this);
return 1;
} else
if (keypressed (SDLK_RETURN)) { // finished editing
focus = 0;
call_listener ();
defocus(this);
return 1;
}
else if (keypressedd (SDLK_LEFT)) { // move cursor left
mode = insert;
if (--cursor < 0) cursor = 0;
calc_cursor ();
} else if (keypressedd (SDLK_RIGHT)) { // move cursor right
mode = insert;
if (++cursor >= len) {
cursor = len;
mode = pushback;
}
calc_cursor ();
} else if (keypressedd (SDLK_BACKSPACE)) { // delete
if (cursor) {
--cursor;
--len;
if (--last < 0) {
last = 0;
len = 0;
mode = pushback;
}
string::iterator e = text.begin () + cursor;
if (e != text.end()) text.erase (e);
calc_cursor ();
if (typing_lsnr) typing_lsnr->typing (*this);
edited = 1;
}
}
}
return focus;
}
void field::set_text (const string& txt, int _edited) {
edited = _edited;
text = txt;
len = text.length ();
if (len == 0) {
last = 0;
cursor = 0;
} else {
last = len - 1;
cursor = len;
}
mode = pushback;
calc_cursor ();
}
void field::set_text (int i, int _edited) {
sprintf (BUFFER, "%d", i);
set_text (BUFFER, _edited);
}
void field::set_text (float f, int _edited) {
sprintf (BUFFER, fmts[fmt], f);
set_text (BUFFER, _edited);
}
void field::calc_cursor () {
string cstr (text.substr (0, cursor));
offset = get_char_width (cstr);
update ();
}
void field::update () {
const box<int>& e = extents;
set_extents (e.left, e.bottom, e.left + get_char_width (text) + 2 * fnt.charwidth.avg, e.bottom + fnt.charheight.max);
}
void field::draw_cursor (int x, int y) {
int cx = x + offset;
glBegin (GL_LINES);
glVertex2i (cx, y);
glVertex2i (cx, y + fnt.charheight.max);
glEnd ();
/*static int pts [4] = {0};
pts[0]=cx;pts[1]=y;
pts[2]=cx;pts[3]=y+fnt.charheight.max;
glVertexPointer (2, GL_INT, 0, pts);
glDrawArrays (GL_LINES, 0, 2);*/
}
void field::draw () {
draw_and_fill_bbox ();
int x = posx, y = posy;
x += fnt.charwidth.avg;
if (focus) draw_cursor (x, y);
draw_string (text, x, y);
}
void field::init () {
lmb_clicked = 0;
focus = 0;
edited = 0;
change_lsnr = 0;
typing_lsnr = 0;
type = "";
expr = 1;
fmt = dec3;
}
field::field () {
set_text ("");
init ();
}
field::field (int x, int y, const string& txt) {
set_text (txt);
set_pos (x, y);
init ();
}
field::operator float() const {
return ((float) atof (text.c_str()));
}
field::operator double() const {
return atof (text.c_str());
}
field::operator int() const {
return (atoi (text.c_str()));
}
field::operator short() const {
return ((short) atoi(text.c_str()));
}
int field::hittest (int x, int y) {
const box<int>& e = extents;
if (hover) { // in the box
focus = 1; // so got focus
int n = text.length ();
if (n == 0) {
cursor = 0;
mode = pushback;
return focus;
}
// locate cursor in text
//
int l = e.left + fnt.charwidth.avg, r;
if (x <= l) {
cursor = 0;
mode = insert;
return focus;
}
cursor = 0;
int r0 = l;
for (int i = 0; i < n; ++i) {
r = r0 + get_char_width (text.substr (0, i + 1));
if (inrange (l, x, r)) { // found!
int rn = r - fnt.spacing.ch;
int xl = x - l, xr = rn - x;
if (xl < xr) cursor = i; else cursor = i + 1;
if (cursor > last) {
cursor = len;
mode = pushback;
} else mode = insert;
return focus;
}
l = r;
}
cursor = len;
mode = pushback;
return focus;
}
focus = 0;
return focus;
}
void field::call_listener () {
if (edited) {
if (expr) {
sprintf (BUFFER, "eval-expr %s %s", text.c_str(), type.c_str());
interpreter (BUFFER);
if (interpreter.result_status == 0) {
set_text (interpreter.result, 1);
if (change_lsnr) change_lsnr->changed (*this);
}
} else {
if (change_lsnr) change_lsnr->changed (*this);
}
edited = 0;
}
}