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.

372 lines
8.3KB

  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. int
  33. Fl_Panzoomer::x_value ( int pos, int size, int first, int total )
  34. {
  35. if ( pos + size > first + total )
  36. total = pos+size-first;
  37. if ( (int)_xmin == first &&
  38. (int)_xmax == total &&
  39. (int)_xpos == pos &&
  40. (int)_xsize == size )
  41. return pos;
  42. damage( FL_DAMAGE_USER1 );
  43. _xmin = first;
  44. _xmax = total;
  45. _xpos = pos;
  46. _xsize = size;
  47. return pos;
  48. }
  49. int
  50. Fl_Panzoomer::y_value ( int pos, int size, int first, int total )
  51. {
  52. if ( pos + size > first + total )
  53. total = pos+size-first;
  54. if ( (int)_ymin == first &&
  55. (int)_ymax == total &&
  56. (int)_ypos == pos &&
  57. (int)_ysize == size )
  58. return pos;
  59. damage( FL_DAMAGE_USER1 );
  60. _ymin = first;
  61. _ymax = total;
  62. _ypos = pos;
  63. _ysize = size;
  64. return pos;
  65. }
  66. void
  67. Fl_Panzoomer::x_value ( double v )
  68. {
  69. if ( _xpos == v )
  70. return;
  71. _xpos = v;
  72. if ( _xpos < _xmin )
  73. _xpos = _xmin;
  74. else if ( _xpos > _xmax - _xsize)
  75. _xpos = _xmax - _xsize;
  76. damage( FL_DAMAGE_USER1 );
  77. }
  78. void
  79. Fl_Panzoomer::y_value ( double v )
  80. {
  81. if ( _ypos == v )
  82. return;
  83. _ypos = v;
  84. if ( _ypos < _ymin )
  85. _ypos = _ymin;
  86. else if ( _ypos > _ymax - _ysize )
  87. _ypos = _ymax - _ysize;
  88. damage( FL_DAMAGE_USER1 );
  89. }
  90. void
  91. Fl_Panzoomer::zoom ( int v )
  92. {
  93. int z = _zoom;
  94. _zoom = v;
  95. if ( _zoom > _zoom_max )
  96. _zoom = _zoom_max;
  97. else
  98. if ( _zoom < _zoom_min )
  99. _zoom = _zoom_min;
  100. if ( z != _zoom )
  101. {
  102. _zoom_changed = true;
  103. do_callback();
  104. _zoom_changed = false;
  105. }
  106. }
  107. void
  108. Fl_Panzoomer::draw ( void )
  109. {
  110. draw(x(),y(),w(),h());
  111. }
  112. void
  113. Fl_Panzoomer::draw ( int X, int Y, int W, int H )
  114. {
  115. fl_draw_box( box(), X,Y,W,H,color());
  116. X += Fl::box_dx( box() );
  117. Y += Fl::box_dy( box() );
  118. W -= Fl::box_dw( box() );
  119. H -= Fl::box_dh( box() );
  120. fl_push_clip( X,Y,W,H );
  121. draw_background( X,Y,W,H );
  122. draw_cursor( X,Y,W,H );
  123. fl_pop_clip();
  124. draw_label();
  125. }
  126. void
  127. Fl_Panzoomer::draw_background ( int X, int Y, int W, int H )
  128. {
  129. }
  130. void
  131. Fl_Panzoomer::draw_cursor ( int X, int Y, int W, int H )
  132. {
  133. int cx,cy,cw,ch;
  134. cx = X; cy = Y; cw = W; ch = H;
  135. cursor_bounds( cx,cy,cw,ch );
  136. fl_rectf( cx,cy,cw,ch,
  137. fl_color_add_alpha( FL_WHITE, 50 ));
  138. fl_rect( cx,cy,cw,ch,
  139. fl_color_add_alpha( FL_WHITE, 80 ));
  140. }
  141. void
  142. Fl_Panzoomer::cursor_bounds ( int &cx, int &cy, int &cw, int &ch ) const
  143. {
  144. int X,Y,W,H;
  145. X = cx;
  146. Y = cy;
  147. W = cw;
  148. H = ch;
  149. double hval;
  150. if ( _xmin == _xmax )
  151. hval = 0.5;
  152. else
  153. {
  154. hval = (_xpos-_xmin)/(_xmax-_xmin);
  155. if (hval > 1.0) hval = 1.0;
  156. else if (hval < 0.0) hval = 0.0;
  157. }
  158. double vval;
  159. if ( _ymin == _ymax )
  160. vval = 0.5;
  161. else
  162. {
  163. vval = (_ypos-_ymin)/(_ymax-_ymin);
  164. if (vval > 1.0) vval = 1.0;
  165. else if (vval < 0.0) vval = 0.0;
  166. }
  167. cx = X + (hval) * W + .5;
  168. cy = _ymax ? Y + (vval) * H + .5 : Y;
  169. cw = W * (_xsize/_xmax);
  170. ch = _ymax ? H * (_ysize/_ymax) : H;
  171. }
  172. int
  173. Fl_Panzoomer::handle ( int m )
  174. {
  175. return handle( m, x(),y(),w(),h());
  176. }
  177. int
  178. Fl_Panzoomer::handle ( int m, int X, int Y, int W, int H )
  179. {
  180. static int xoffset;
  181. static int yoffset;
  182. static bool drag;
  183. X += Fl::box_dx( box() );
  184. Y += Fl::box_dy( box() );
  185. W -= Fl::box_dw( box() );
  186. H -= Fl::box_dh( box() );
  187. switch ( m )
  188. {
  189. case FL_ENTER:
  190. case FL_LEAVE:
  191. return 1;
  192. case FL_PUSH:
  193. {
  194. int cx,cy,cw,ch;
  195. cx = X; cy = Y; cw = W; ch = H;
  196. cursor_bounds( cx,cy,cw,ch );
  197. xoffset = Fl::event_x() - cx;
  198. yoffset = Fl::event_y() - cy;
  199. if ( Fl::event_inside( cx,cy,cw,ch ) &&
  200. Fl::event_button1() )
  201. drag = true;
  202. return 1;
  203. }
  204. case FL_DRAG:
  205. {
  206. int cx,cy,cw,ch;
  207. cx = X; cy = Y; cw = W; ch = H;
  208. cursor_bounds( cx,cy,cw,ch );
  209. if ( drag )
  210. {
  211. x_value((((double)Fl::event_x() - X - xoffset) / W) * _xmax);
  212. y_value( (((double)Fl::event_y() - Y - yoffset) / H) * _ymax );
  213. if ( when() & FL_WHEN_CHANGED )
  214. do_callback();
  215. }
  216. damage( FL_DAMAGE_USER1 );
  217. return 1;
  218. break;
  219. }
  220. case FL_MOUSEWHEEL:
  221. {
  222. const int dy = Fl::event_dy();
  223. const int dx = Fl::event_dx();
  224. if ( dy && Fl::event_ctrl() )
  225. {
  226. zoom( _zoom + dy );
  227. damage( FL_DAMAGE_USER1 );
  228. return 1;
  229. }
  230. if ( !Fl::event_alt() && !Fl::event_shift())
  231. {
  232. if ( dy )
  233. y_value( _ypos + ( (double)dy*5 / H ) * _ymax );
  234. if ( dx )
  235. x_value( _xpos + ( (double)dx*5 / W ) * _xmax );
  236. if ( when() & FL_WHEN_CHANGED )
  237. do_callback();
  238. damage( FL_DAMAGE_USER1 );
  239. return 1;
  240. }
  241. return 0;
  242. break;
  243. }
  244. case FL_RELEASE:
  245. {
  246. if ( drag )
  247. {
  248. drag = false;
  249. if ( when() & FL_WHEN_RELEASE )
  250. do_callback();
  251. }
  252. return 1;
  253. }
  254. case FL_KEYBOARD:
  255. {
  256. if ( Fl::event_shift() || Fl::event_ctrl() || Fl::event_alt() )
  257. return 0;
  258. double xv = _xpos;
  259. double yv = _ypos;
  260. /* FIXME: hack */
  261. int xls = _xsize / 50;
  262. int yls = _ysize / 50;
  263. switch ( Fl::event_key() )
  264. {
  265. case FL_Up:
  266. yv -= yls;
  267. break;
  268. case FL_Down:
  269. yv += yls;
  270. break;
  271. case FL_Left:
  272. xv -= xls;
  273. break;
  274. case FL_Right:
  275. xv += xls;
  276. break;
  277. default:
  278. return 0;
  279. }
  280. x_value( xv );
  281. y_value( yv );
  282. do_callback();
  283. redraw();
  284. return 1;
  285. break;
  286. }
  287. }
  288. return 0;
  289. }