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.

313 lines
7.2KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2012 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #include <FL/Fl.H>
  19. #include <FL/fl_draw.H>
  20. #include <FL/Fl_Panzoomer.H>
  21. Fl_Panzoomer::Fl_Panzoomer ( int X, int Y, int W, int H, const char *L ) :
  22. Fl_Valuator( X,Y,W,H,L )
  23. {
  24. _zoom = 1;
  25. _zoom_min = 0;
  26. _zoom_max = 4;
  27. _zoom_changed = false;
  28. _ymin = _ymax = _xmin = _xmax = _ysize = _xsize =
  29. _xpos = _ypos = 0;
  30. step( 1 );
  31. }
  32. void
  33. Fl_Panzoomer::x_value ( double v ) {
  34. if ( _xpos == v )
  35. return;
  36. _xpos = v;
  37. if ( _xpos < _xmin )
  38. _xpos = _xmin;
  39. else if ( _xpos > _xmax - _xsize)
  40. _xpos = _xmax - _xsize;
  41. damage( FL_DAMAGE_USER1 );
  42. }
  43. void
  44. Fl_Panzoomer::y_value ( double v ) {
  45. if ( _ypos == v )
  46. return;
  47. _ypos = v;
  48. if ( _ypos < _ymin )
  49. _ypos = _ymin;
  50. else if ( _ypos > _ymax - _ysize )
  51. _ypos = _ymax - _ysize;
  52. damage( FL_DAMAGE_USER1 );
  53. }
  54. void
  55. Fl_Panzoomer::zoom ( int v )
  56. {
  57. int z = _zoom;
  58. _zoom = v;
  59. if ( _zoom > _zoom_max )
  60. _zoom = _zoom_max;
  61. else
  62. if ( _zoom < _zoom_min )
  63. _zoom = _zoom_min;
  64. if ( z != _zoom )
  65. {
  66. _zoom_changed = true;
  67. do_callback();
  68. _zoom_changed = false;
  69. }
  70. }
  71. void
  72. Fl_Panzoomer::draw ( void )
  73. {
  74. draw(x(),y(),w(),h());
  75. }
  76. void
  77. Fl_Panzoomer::draw ( int X, int Y, int W, int H )
  78. {
  79. fl_draw_box( box(), X,Y,W,H,color());
  80. X += Fl::box_dx( box() );
  81. Y += Fl::box_dy( box() );
  82. W -= Fl::box_dw( box() );
  83. H -= Fl::box_dh( box() );
  84. fl_push_clip( X,Y,W,H );
  85. draw_background( X,Y,W,H );
  86. draw_cursor( X,Y,W,H );
  87. fl_pop_clip();
  88. draw_label();
  89. }
  90. void
  91. Fl_Panzoomer::draw_background ( int X, int Y, int W, int H )
  92. {
  93. }
  94. void
  95. Fl_Panzoomer::draw_cursor ( int X, int Y, int W, int H )
  96. {
  97. int cx,cy,cw,ch;
  98. cx = X; cy = Y; cw = W; ch = H;
  99. cursor_bounds( cx,cy,cw,ch );
  100. fl_rectf( cx,cy,cw,ch,
  101. fl_color_add_alpha( FL_WHITE, 50 ));
  102. fl_rect( cx,cy,cw,ch,
  103. fl_color_add_alpha( FL_WHITE, 80 ));
  104. }
  105. void
  106. Fl_Panzoomer::cursor_bounds ( int &cx, int &cy, int &cw, int &ch ) const
  107. {
  108. int X,Y,W,H;
  109. X = cx;
  110. Y = cy;
  111. W = cw;
  112. H = ch;
  113. double hval;
  114. if ( _xmin == _xmax )
  115. hval = 0.5;
  116. else
  117. {
  118. hval = (_xpos-_xmin)/(_xmax-_xmin);
  119. if (hval > 1.0) hval = 1.0;
  120. else if (hval < 0.0) hval = 0.0;
  121. }
  122. double vval;
  123. if ( _ymin == _ymax )
  124. vval = 0.5;
  125. else
  126. {
  127. vval = (_ypos-_ymin)/(_ymax-_ymin);
  128. if (vval > 1.0) vval = 1.0;
  129. else if (vval < 0.0) vval = 0.0;
  130. }
  131. cx = X + (hval) * W + .5;
  132. cy = _ymax ? Y + (vval) * H + .5 : Y;
  133. cw = W * (_xsize/_xmax);
  134. ch = _ymax ? H * (_ysize/_ymax) : H;
  135. }
  136. int
  137. Fl_Panzoomer::handle ( int m )
  138. {
  139. return handle( m, x(),y(),w(),h());
  140. }
  141. int
  142. Fl_Panzoomer::handle ( int m, int X, int Y, int W, int H )
  143. {
  144. static int xoffset;
  145. static int yoffset;
  146. static bool drag;
  147. X += Fl::box_dx( box() );
  148. Y += Fl::box_dy( box() );
  149. W -= Fl::box_dw( box() );
  150. H -= Fl::box_dh( box() );
  151. switch ( m )
  152. {
  153. case FL_ENTER:
  154. case FL_LEAVE:
  155. return 1;
  156. case FL_PUSH:
  157. {
  158. int cx,cy,cw,ch;
  159. cx = X; cy = Y; cw = W; ch = H;
  160. cursor_bounds( cx,cy,cw,ch );
  161. xoffset = Fl::event_x() - cx;
  162. yoffset = Fl::event_y() - cy;
  163. if ( Fl::event_inside( cx,cy,cw,ch ) &&
  164. Fl::event_button1() )
  165. drag = true;
  166. return 1;
  167. }
  168. case FL_DRAG:
  169. {
  170. int cx,cy,cw,ch;
  171. cx = X; cy = Y; cw = W; ch = H;
  172. cursor_bounds( cx,cy,cw,ch );
  173. if ( drag )
  174. {
  175. x_value((((double)Fl::event_x() - X - xoffset) / W) * _xmax);
  176. y_value( (((double)Fl::event_y() - Y - yoffset) / H) * _ymax );
  177. if ( when() & FL_WHEN_CHANGED )
  178. do_callback();
  179. }
  180. return 1;
  181. break;
  182. }
  183. case FL_MOUSEWHEEL:
  184. {
  185. int d = Fl::event_dy();
  186. if ( Fl::event_ctrl() )
  187. {
  188. zoom( _zoom + d );
  189. return 1;
  190. }
  191. else if (!Fl::event_alt() && !Fl::event_shift())
  192. {
  193. y_value( _ypos + ( (double)d*5 / H ) * _ymax );
  194. if ( when() & FL_WHEN_CHANGED )
  195. do_callback();
  196. return 1;
  197. }
  198. return 0;
  199. break;
  200. }
  201. case FL_RELEASE:
  202. {
  203. if ( drag )
  204. {
  205. drag = false;
  206. if ( when() & FL_WHEN_RELEASE )
  207. do_callback();
  208. }
  209. return 1;
  210. }
  211. case FL_KEYBOARD:
  212. {
  213. if ( Fl::event_shift() || Fl::event_ctrl() || Fl::event_alt() )
  214. return 0;
  215. double xv = _xpos;
  216. double yv = _ypos;
  217. /* FIXME: hack */
  218. int xls = _xsize / 50;
  219. int yls = _ysize / 50;
  220. switch ( Fl::event_key() )
  221. {
  222. case FL_Up:
  223. yv -= yls;
  224. break;
  225. case FL_Down:
  226. yv += yls;
  227. break;
  228. case FL_Left:
  229. xv -= xls;
  230. break;
  231. case FL_Right:
  232. xv += xls;
  233. break;
  234. default:
  235. return 0;
  236. }
  237. x_value( xv );
  238. y_value( yv );
  239. do_callback();
  240. redraw();
  241. return 1;
  242. break;
  243. }
  244. }
  245. return 0;
  246. }