
- remove obsolete svn '$Id$' tags from all source files - update .fl files and generated files accordingly - replace 'http://www.fltk.org' URL's with 'https://...' - replace bug report URL 'str.php' with 'bugs.php' - remove trailing whitespace - fix other whitespace errors flagged by Git - add and/or fix missing or wrong standard headers - convert tabs to spaces in all source files The only relevant code changes are in the fluid/ folder where some .fl files and other source files were used to generate the '$Id' headers and footers.
213 lines
5.1 KiB
C++
213 lines
5.1 KiB
C++
//
|
|
// Spinner widget for the Fast Light Tool Kit (FLTK).
|
|
//
|
|
// Copyright 1998-2017 by Bill Spitzak and others.
|
|
//
|
|
// This library is free software. Distribution and use rights are outlined in
|
|
// the file "COPYING" which should have been included with this file. If this
|
|
// file is missing or damaged, see the license at:
|
|
//
|
|
// https://www.fltk.org/COPYING.php
|
|
//
|
|
// Please see the following page on how to report bugs and issues:
|
|
//
|
|
// https://www.fltk.org/bugs.php
|
|
//
|
|
|
|
/* \file
|
|
Fl_Spinner widget . */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <FL/Fl_Spinner.H>
|
|
|
|
/*
|
|
This widget is a combination of the input widget and repeat buttons.
|
|
|
|
The user can either type into the input area or use the buttons to
|
|
change the value.
|
|
*/
|
|
|
|
void Fl_Spinner::sb_cb(Fl_Widget *w, Fl_Spinner *sb) {
|
|
double v; // New value
|
|
|
|
if (w == &(sb->input_)) {
|
|
// Something changed in the input field...
|
|
v = atof(sb->input_.value());
|
|
|
|
if (v < sb->minimum_) {
|
|
sb->value_ = sb->minimum_;
|
|
sb->update();
|
|
} else if (v > sb->maximum_) {
|
|
sb->value_ = sb->maximum_;
|
|
sb->update();
|
|
} else sb->value_ = v;
|
|
} else if (w == &(sb->up_button_)) {
|
|
// Up button pressed...
|
|
v = sb->value_ + sb->step_;
|
|
if (v > sb->maximum_) {
|
|
if (sb->wrap_)
|
|
v = sb->minimum_;
|
|
else
|
|
v = sb->maximum_;
|
|
}
|
|
sb->value_ = v;
|
|
sb->update();
|
|
} else if (w == &(sb->down_button_)) {
|
|
// Down button pressed...
|
|
v = sb->value_ - sb->step_;
|
|
if (v < sb->minimum_) {
|
|
if (sb->wrap_)
|
|
v = sb->maximum_;
|
|
else
|
|
v = sb->minimum_;
|
|
}
|
|
sb->value_ = v;
|
|
sb->update();
|
|
}
|
|
|
|
sb->set_changed();
|
|
sb->do_callback();
|
|
}
|
|
|
|
void Fl_Spinner::update() {
|
|
char s[255]; // Value string
|
|
|
|
if (format_[0] == '%' && format_[1] == '.' && format_[2] == '*') { // precision argument
|
|
// this code block is a simplified version of
|
|
// Fl_Valuator::format() and works well (but looks ugly)
|
|
int c = 0;
|
|
char temp[64], *sp = temp;
|
|
sprintf(temp, "%.12f", step_);
|
|
while (*sp) sp++;
|
|
sp--;
|
|
while (sp > temp && *sp == '0') sp--;
|
|
while (sp > temp && (*sp >= '0' && *sp <= '9')) { sp--; c++; }
|
|
sprintf(s, format_, c, value_);
|
|
} else {
|
|
sprintf(s, format_, value_);
|
|
}
|
|
input_.value(s);
|
|
}
|
|
|
|
#define FL_UP_ARROW_TX "@-42<"
|
|
#define FL_DOWN_ARROW_TX "@-42>"
|
|
|
|
/**
|
|
Creates a new Fl_Spinner widget using the given position, size,
|
|
and label string.
|
|
|
|
The inherited destructor destroys the widget and any value associated with it.
|
|
*/
|
|
|
|
Fl_Spinner::Fl_Spinner(int X, int Y, int W, int H, const char *L)
|
|
: Fl_Group(X, Y, W, H, L),
|
|
input_(X, Y, W - H / 2 - 2, H),
|
|
up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, FL_UP_ARROW_TX),
|
|
down_button_(X + W - H / 2 - 2, Y + H - H / 2,
|
|
H / 2 + 2, H / 2, FL_DOWN_ARROW_TX)
|
|
{
|
|
end();
|
|
|
|
value_ = 1.0;
|
|
minimum_ = 1.0;
|
|
maximum_ = 100.0;
|
|
step_ = 1.0;
|
|
wrap_ = 1;
|
|
format_ = "%g";
|
|
|
|
align(FL_ALIGN_LEFT);
|
|
|
|
input_.value("1");
|
|
input_.type(FL_INT_INPUT);
|
|
input_.when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE);
|
|
input_.callback((Fl_Callback *)sb_cb, this);
|
|
|
|
up_button_.callback((Fl_Callback *)sb_cb, this);
|
|
|
|
down_button_.callback((Fl_Callback *)sb_cb, this);
|
|
}
|
|
|
|
int Fl_Spinner::handle(int event) {
|
|
|
|
switch (event) {
|
|
|
|
case FL_KEYDOWN:
|
|
case FL_SHORTCUT:
|
|
if (Fl::event_key() == FL_Up) {
|
|
up_button_.do_callback();
|
|
return 1;
|
|
} else if (Fl::event_key() == FL_Down) {
|
|
down_button_.do_callback();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
|
|
case FL_FOCUS:
|
|
if (input_.take_focus()) return 1;
|
|
return 0;
|
|
}
|
|
|
|
return Fl_Group::handle(event);
|
|
}
|
|
|
|
void Fl_Spinner::resize(int X, int Y, int W, int H) {
|
|
Fl_Group::resize(X,Y,W,H);
|
|
|
|
input_.resize(X, Y, W - H / 2 - 2, H);
|
|
up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2);
|
|
down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2,
|
|
H / 2 + 2, H / 2);
|
|
}
|
|
|
|
/**
|
|
Sets or returns the amount to change the value when the user clicks a button.
|
|
Before setting step to a non-integer value, the spinner
|
|
type() should be changed to floating point.
|
|
|
|
\see double Fl_Spinner::step() const
|
|
*/
|
|
|
|
void Fl_Spinner::step(double s) {
|
|
step_ = s;
|
|
if (step_ != (int)step_) input_.type(FL_FLOAT_INPUT);
|
|
else input_.type(FL_INT_INPUT);
|
|
update();
|
|
}
|
|
|
|
/** Sets the numeric representation in the input field.
|
|
|
|
Valid values are FL_INT_INPUT and FL_FLOAT_INPUT.
|
|
Also changes the format() template.
|
|
Setting a new spinner type via a superclass pointer will not work.
|
|
\note type() is not a virtual function.
|
|
*/
|
|
|
|
void Fl_Spinner::type(uchar v) {
|
|
if (v == FL_FLOAT_INPUT) {
|
|
format("%.*f");
|
|
} else {
|
|
format("%.0f");
|
|
}
|
|
input_.type(v);
|
|
}
|
|
|
|
|
|
/**
|
|
Handles events of Fl_Spinner's embedded input widget.
|
|
|
|
Works like Fl_Input::handle() but ignores FL_Up and FL_Down keys
|
|
so they can be handled by the parent widget (Fl_Spinner).
|
|
*/
|
|
int Fl_Spinner::Fl_Spinner_Input::handle(int event) {
|
|
if (event == FL_KEYBOARD) {
|
|
const int key = Fl::event_key();
|
|
if (key == FL_Up || key == FL_Down) {
|
|
Fl_Input::handle(FL_UNFOCUS); // sets and potentially clips the input value
|
|
return 0;
|
|
}
|
|
}
|
|
return Fl_Input::handle(event);
|
|
}
|