You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
8.1KB

  1. //
  2. // "$Id: Fl_Spinner.H 8339 2011-01-30 12:50:19Z ianmacarthur $"
  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_EXPORT Fl_Spinner : public Fl_Group {
  46. double value_; // Current value
  47. double minimum_; // Minimum value
  48. double maximum_; // Maximum value
  49. double step_; // Amount to add/subtract for up/down
  50. const char *format_; // Format string
  51. Fl_Input input_; // Input field for the value
  52. Fl_Repeat_Button
  53. up_button_, // Up button
  54. down_button_; // Down button
  55. static void sb_cb(Fl_Widget *w, Fl_Spinner *sb) {
  56. double v; // New value
  57. if (w == &(sb->input_)) {
  58. // Something changed in the input field...
  59. v = atof(sb->input_.value());
  60. if (v < sb->minimum_) {
  61. sb->value_ = sb->minimum_;
  62. sb->update();
  63. } else if (v > sb->maximum_) {
  64. sb->value_ = sb->maximum_;
  65. sb->update();
  66. } else sb->value_ = v;
  67. } else if (w == &(sb->up_button_)) {
  68. // Up button pressed...
  69. v = sb->value_ + sb->step_;
  70. if (v > sb->maximum_) sb->value_ = sb->minimum_;
  71. else sb->value_ = v;
  72. sb->update();
  73. } else if (w == &(sb->down_button_)) {
  74. // Down button pressed...
  75. v = sb->value_ - sb->step_;
  76. if (v < sb->minimum_) sb->value_ = sb->maximum_;
  77. else sb->value_ = v;
  78. sb->update();
  79. }
  80. sb->do_callback();
  81. }
  82. void update() {
  83. char s[255]; // Value string
  84. if (format_[0]=='%'&&format_[1]=='.'&&format_[2]=='*') { // precision argument
  85. // this code block is a simplified version of
  86. // Fl_Valuator::format() and works well (but looks ugly)
  87. int c = 0;
  88. char temp[64], *sp = temp;
  89. sprintf(temp, "%.12f", step_);
  90. while (*sp) sp++;
  91. sp--;
  92. while (sp>temp && *sp=='0') sp--;
  93. while (sp>temp && (*sp>='0' && *sp<='9')) { sp--; c++; }
  94. sprintf(s, format_, c, value_);
  95. } else {
  96. sprintf(s, format_, value_);
  97. }
  98. input_.value(s);
  99. }
  100. public:
  101. /**
  102. Creates a new Fl_Spinner widget using the given position, size,
  103. and label string.
  104. <P>Inherited destructor Destroys the widget and any value associated with it.
  105. */
  106. Fl_Spinner(int X, int Y, int W, int H, const char *L = 0)
  107. : Fl_Group(X, Y, W, H, L),
  108. input_(X, Y, W - H / 2 - 2, H),
  109. up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, "@-42<"),
  110. down_button_(X + W - H / 2 - 2, Y + H - H / 2,
  111. H / 2 + 2, H / 2, "@-42>") {
  112. end();
  113. value_ = 1.0;
  114. minimum_ = 1.0;
  115. maximum_ = 100.0;
  116. step_ = 1.0;
  117. format_ = "%g";
  118. align(FL_ALIGN_LEFT);
  119. input_.value("1");
  120. input_.type(FL_INT_INPUT);
  121. input_.when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE);
  122. input_.callback((Fl_Callback *)sb_cb, this);
  123. up_button_.callback((Fl_Callback *)sb_cb, this);
  124. down_button_.callback((Fl_Callback *)sb_cb, this);
  125. }
  126. /** Sets or returns the format string for the value. */
  127. const char *format() { return (format_); }
  128. /** Sets or returns the format string for the value. */
  129. void format(const char *f) { format_ = f; update(); }
  130. int handle(int event) {
  131. switch (event) {
  132. case FL_KEYDOWN :
  133. case FL_SHORTCUT :
  134. if (Fl::event_key() == FL_Up) {
  135. up_button_.do_callback();
  136. return 1;
  137. } else if (Fl::event_key() == FL_Down) {
  138. down_button_.do_callback();
  139. return 1;
  140. } else return 0;
  141. case FL_FOCUS :
  142. if (input_.take_focus()) return 1;
  143. else return 0;
  144. }
  145. return Fl_Group::handle(event);
  146. }
  147. /** Speling mistakes retained for source compatibility \deprecated */
  148. double maxinum() const { return (maximum_); }
  149. /** Gets the maximum value of the widget. */
  150. double maximum() const { return (maximum_); }
  151. /** Sets the maximum value of the widget. */
  152. void maximum(double m) { maximum_ = m; }
  153. /** Speling mistakes retained for source compatibility \deprecated */
  154. double mininum() const { return (minimum_); }
  155. /** Gets the minimum value of the widget. */
  156. double minimum() const { return (minimum_); }
  157. /** Sets the minimum value of the widget. */
  158. void minimum(double m) { minimum_ = m; }
  159. /** Sets the minimum and maximum values for the widget. */
  160. void range(double a, double b) { minimum_ = a; maximum_ = b; }
  161. void resize(int X, int Y, int W, int H) {
  162. Fl_Group::resize(X,Y,W,H);
  163. input_.resize(X, Y, W - H / 2 - 2, H);
  164. up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2);
  165. down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2,
  166. H / 2 + 2, H / 2);
  167. }
  168. /**
  169. Sets or returns the amount to change the value when the user clicks a button.
  170. Before setting step to a non-integer value, the spinner
  171. type() should be changed to floating point.
  172. */
  173. double step() const { return (step_); }
  174. /** See double Fl_Spinner::step() const */
  175. void step(double s) {
  176. step_ = s;
  177. if (step_ != (int)step_) input_.type(FL_FLOAT_INPUT);
  178. else input_.type(FL_INT_INPUT);
  179. update();
  180. }
  181. /** Gets the color of the text in the input field. */
  182. Fl_Color textcolor() const {
  183. return (input_.textcolor());
  184. }
  185. /** Sets the color of the text in the input field. */
  186. void textcolor(Fl_Color c) {
  187. input_.textcolor(c);
  188. }
  189. /** Gets the font of the text in the input field. */
  190. Fl_Font textfont() const {
  191. return (input_.textfont());
  192. }
  193. /** Sets the font of the text in the input field. */
  194. void textfont(Fl_Font f) {
  195. input_.textfont(f);
  196. }
  197. /** Gets the size of the text in the input field. */
  198. Fl_Fontsize textsize() const {
  199. return (input_.textsize());
  200. }
  201. /** Sets the size of the text in the input field. */
  202. void textsize(Fl_Fontsize s) {
  203. input_.textsize(s);
  204. }
  205. /** Gets the numeric representation in the input field.
  206. \see Fl_Spinner::type(uchar)
  207. */
  208. uchar type() const { return (input_.type()); }
  209. /** Sets the numeric representation in the input field.
  210. Valid values are FL_INT_INPUT and FL_FLOAT_INPUT.
  211. Also changes the format() template.
  212. Setting a new spinner type via a superclass pointer will not work.
  213. \note type is not a virtual function.
  214. */
  215. void type(uchar v) {
  216. if (v==FL_FLOAT_INPUT) {
  217. format("%.*f");
  218. } else {
  219. format("%.0f");
  220. }
  221. input_.type(v);
  222. }
  223. /** Gets the current value of the widget. */
  224. double value() const { return (value_); }
  225. /**
  226. Sets the current value of the widget.
  227. Before setting value to a non-integer value, the spinner
  228. type() should be changed to floating point.
  229. */
  230. void value(double v) { value_ = v; update(); }
  231. };
  232. #endif // !Fl_Spinner_H
  233. //
  234. // End of "$Id: Fl_Spinner.H 8339 2011-01-30 12:50:19Z ianmacarthur $".
  235. //