Fl_Spinner.H 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. //
  2. // "$Id: Fl_Spinner.H 7903 2010-11-28 21:06:39Z matt $"
  3. //
  4. // Spinner widget for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems on the following page:
  24. //
  25. // http://www.fltk.org/str.php
  26. //
  27. /* \file
  28. Fl_Spinner widget . */
  29. #ifndef Fl_Spinner_H
  30. # define Fl_Spinner_H
  31. //
  32. // Include necessary headers...
  33. //
  34. # include <FL/Enumerations.H>
  35. # include <FL/Fl_Group.H>
  36. # include <FL/Fl_Input.H>
  37. # include <FL/Fl_Repeat_Button.H>
  38. # include <stdio.h>
  39. # include <stdlib.h>
  40. /**
  41. This widget is a combination of the input
  42. widget and repeat buttons. The user can either type into the
  43. input area or use the buttons to change the value.
  44. */
  45. class Fl_Spinner : public Fl_Group
  46. {
  47. double value_; // Current value
  48. double minimum_; // Minimum value
  49. double maximum_; // Maximum value
  50. double step_; // Amount to add/subtract for up/down
  51. const char *format_; // Format string
  52. Fl_Input input_; // Input field for the value
  53. Fl_Repeat_Button
  54. up_button_, // Up button
  55. down_button_; // Down button
  56. static void sb_cb(Fl_Widget *w, Fl_Spinner *sb) {
  57. double v; // New value
  58. if (w == &(sb->input_)) {
  59. // Something changed in the input field...
  60. v = atof(sb->input_.value());
  61. if (v < sb->minimum_) {
  62. sb->value_ = sb->minimum_;
  63. sb->update();
  64. } else if (v > sb->maximum_) {
  65. sb->value_ = sb->maximum_;
  66. sb->update();
  67. } else sb->value_ = v;
  68. } else if (w == &(sb->up_button_)) {
  69. // Up button pressed...
  70. v = sb->value_ + sb->step_;
  71. if (v > sb->maximum_) sb->value_ = sb->minimum_;
  72. else sb->value_ = v;
  73. sb->update();
  74. } else if (w == &(sb->down_button_)) {
  75. // Down button pressed...
  76. v = sb->value_ - sb->step_;
  77. if (v < sb->minimum_) sb->value_ = sb->maximum_;
  78. else sb->value_ = v;
  79. sb->update();
  80. }
  81. sb->do_callback();
  82. }
  83. void update() {
  84. char s[255]; // Value string
  85. if (format_[0]=='%'&&format_[1]=='.'&&format_[2]=='*') { // precision argument
  86. // this code block is a simplified version of
  87. // Fl_Valuator::format() and works well (but looks ugly)
  88. int c = 0;
  89. char temp[64], *sp = temp;
  90. sprintf(temp, "%.12f", step_);
  91. while (*sp) sp++;
  92. sp--;
  93. while (sp>temp && *sp=='0') sp--;
  94. while (sp>temp && (*sp>='0' && *sp<='9')) { sp--; c++; }
  95. sprintf(s, format_, c, value_);
  96. } else {
  97. sprintf(s, format_, value_);
  98. }
  99. input_.value(s);
  100. }
  101. public:
  102. /**
  103. Creates a new Fl_Spinner widget using the given position, size,
  104. and label string.
  105. <P>Inherited destructor Destroys the widget and any value associated with it.
  106. */
  107. Fl_Spinner(int X, int Y, int W, int H, const char *L = 0)
  108. : Fl_Group(X, Y, W, H, L),
  109. input_(X, Y, W - H / 2 - 2, H),
  110. up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, "@-42<"),
  111. down_button_(X + W - H / 2 - 2, Y + H - H / 2,
  112. H / 2 + 2, H / 2, "@-42>") {
  113. end();
  114. value_ = 1.0;
  115. minimum_ = 1.0;
  116. maximum_ = 100.0;
  117. step_ = 1.0;
  118. format_ = "%g";
  119. align(FL_ALIGN_LEFT);
  120. input_.value("1");
  121. input_.type(FL_INT_INPUT);
  122. input_.when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE);
  123. input_.callback((Fl_Callback *)sb_cb, this);
  124. up_button_.callback((Fl_Callback *)sb_cb, this);
  125. down_button_.callback((Fl_Callback *)sb_cb, this);
  126. }
  127. /** Sets or returns the format string for the value. */
  128. const char *format() { return (format_); }
  129. /** Sets or returns the format string for the value. */
  130. void format(const char *f) { format_ = f; update(); }
  131. int handle(int event) {
  132. switch (event) {
  133. case FL_KEYDOWN :
  134. case FL_SHORTCUT :
  135. if (Fl::event_key() == FL_Up) {
  136. up_button_.do_callback();
  137. return 1;
  138. } else if (Fl::event_key() == FL_Down) {
  139. down_button_.do_callback();
  140. return 1;
  141. } else return 0;
  142. case FL_FOCUS :
  143. if (input_.take_focus()) return 1;
  144. else return 0;
  145. }
  146. return Fl_Group::handle(event);
  147. }
  148. /** Speling mistakes retained for source compatibility \deprecated */
  149. double maxinum() const { return (maximum_); }
  150. /** Gets the maximum value of the widget. */
  151. double maximum() const { return (maximum_); }
  152. /** Sets the maximum value of the widget. */
  153. void maximum(double m) { maximum_ = m; }
  154. /** Speling mistakes retained for source compatibility \deprecated */
  155. double mininum() const { return (minimum_); }
  156. /** Gets the minimum value of the widget. */
  157. double minimum() const { return (minimum_); }
  158. /** Sets the minimum value of the widget. */
  159. void minimum(double m) { minimum_ = m; }
  160. /** Sets the minimum and maximum values for the widget. */
  161. void range(double a, double b) { minimum_ = a; maximum_ = b; }
  162. void resize(int X, int Y, int W, int H) {
  163. Fl_Group::resize(X,Y,W,H);
  164. input_.resize(X, Y, W - H / 2 - 2, H);
  165. up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2);
  166. down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2,
  167. H / 2 + 2, H / 2);
  168. }
  169. /**
  170. Sets or returns the amount to change the value when the user clicks a button.
  171. Before setting step to a non-integer value, the spinner
  172. type() should be changed to floating point.
  173. */
  174. double step() const { return (step_); }
  175. /** See double Fl_Spinner::step() const */
  176. void step(double s) {
  177. step_ = s;
  178. if (step_ != (int)step_) input_.type(FL_FLOAT_INPUT);
  179. else input_.type(FL_INT_INPUT);
  180. update();
  181. }
  182. /** Gets the color of the text in the input field. */
  183. Fl_Color textcolor() const {
  184. return (input_.textcolor());
  185. }
  186. /** Sets the color of the text in the input field. */
  187. void textcolor(Fl_Color c) {
  188. input_.textcolor(c);
  189. }
  190. /** Gets the font of the text in the input field. */
  191. Fl_Font textfont() const {
  192. return (input_.textfont());
  193. }
  194. /** Sets the font of the text in the input field. */
  195. void textfont(Fl_Font f) {
  196. input_.textfont(f);
  197. }
  198. /** Gets the size of the text in the input field. */
  199. Fl_Fontsize textsize() const {
  200. return (input_.textsize());
  201. }
  202. /** Sets the size of the text in the input field. */
  203. void textsize(Fl_Fontsize s) {
  204. input_.textsize(s);
  205. }
  206. /** Sets or Gets the numeric representation in the input field.
  207. Valid values are FL_INT_INPUT and FL_FLOAT_INPUT.
  208. The first form also changes the format() template.
  209. Setting a new spinner type via a superclass pointer will not work.
  210. \note type is not a virtual function.
  211. */
  212. uchar type() const { return (input_.type()); }
  213. /** See uchar Fl_Spinner::type() const */
  214. void type(uchar v) {
  215. if (v==FL_FLOAT_INPUT) {
  216. format("%.*f");
  217. } else {
  218. format("%.0f");
  219. }
  220. input_.type(v);
  221. }
  222. /** Gets the current value of the widget. */
  223. double value() const { return (value_); }
  224. /**
  225. Sets the current value of the widget.
  226. Before setting value to a non-integer value, the spinner
  227. type() should be changed to floating point.
  228. */
  229. void value(double v) { value_ = v; update(); }
  230. };
  231. #endif // !Fl_Spinner_H
  232. //
  233. // End of "$Id: Fl_Spinner.H 7903 2010-11-28 21:06:39Z matt $".
  234. //