PageRenderTime 26ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/src/spec/xcorf/slider.c

https://github.com/pkgw/carma-miriad
C | 614 lines | 435 code | 119 blank | 60 comment | 69 complexity | d94223d14740d7c9189e19b7c57a2301 MD5 | raw file
  1. #include "xcorf.h"
  2. #include <Xm/DrawingA.h>
  3. typedef struct {
  4. double value; /* LO1 in GHz. */
  5. double minimum; /* The left extreme value in GHz. */
  6. double maximum; /* The right extreme value in GHz. */
  7. double slider_size; /* (2*SBMAX) in GHz. */
  8. double slider_bucket; /* LO2 in GHz. */
  9. double aspect_x; /* The scale factor in pixels/GHz. */
  10. double step; /* The major tick step size in GHz. */
  11. int numTicks; /* The number of tick marks between each major step. */
  12. short slider_x; /* The left edge of the slider in pixels. */
  13. short slider_y; /* The top edge of the slider in pixels. */
  14. short slider_width; /* The width of the slider in pixels. */
  15. short slider_height; /* The height of the slider in pixels. */
  16. short slider_gap; /* The value of LO2 in pixels. */
  17. short slider_area_x; /* Left edge of the slider area in pixels. */
  18. short slider_area_y; /* Top edge of the slider area in pixels. */
  19. short slider_area_width; /* The width of slider area in pixels. */
  20. short slider_area_height; /* The height of slider area in pixels. */
  21. Dimension shadowThickness;
  22. Drawable pixmap;
  23. GC foreground_GC;
  24. GC top_shadow_GC;
  25. GC bottom_shadow_GC;
  26. Widget widget;
  27. struct {
  28. Boolean inMotion; /* Slider motion in progress. */
  29. Position dx; /* Initial position of slider. */
  30. Position x; /* Current location. */
  31. } tmp;
  32. } SLIDER;
  33. static SLIDER *slider = (SLIDER *)NULL;
  34. /***********************************************************************/
  35. #ifdef __STDC__
  36. static void calcSliderRect(void)
  37. #else
  38. static void calcSliderRect()
  39. #endif /*__STDC__*/
  40. {
  41. int minSliderWidth = 6;
  42. int minSliderHeight = 1;
  43. int hitTheWall = 0;
  44. double range, trueSize, factor, slideSize, bucket, offset;
  45. trueSize = slider->slider_area_width;
  46. /* Total number of user units displayed */
  47. range = slider->maximum - slider->minimum;
  48. /* A niave notion of pixels per user unit */
  49. factor = trueSize / range;
  50. /* A naive notion of the size of the slider in pixels */
  51. slideSize = slider->slider_size * factor;
  52. bucket = slider->slider_bucket * factor;
  53. /* Don't let the slider get too small */
  54. slider->slider_width = (int)(slideSize + 0.5);
  55. if (slider->slider_width <= minSliderWidth)
  56. slider->slider_width = hitTheWall = minSliderWidth;
  57. slider->slider_height = slider->slider_area_height;
  58. if (slider->slider_height < minSliderHeight)
  59. slider->slider_height = minSliderHeight;
  60. slider->slider_gap = (int)(bucket + 0.5);
  61. if (slider->slider_gap > (slider->slider_width / 2))
  62. slider->slider_gap = (slider->slider_width / 2);
  63. if (hitTheWall > 0) {
  64. /*
  65. * The slider has not been allowed to take on its true
  66. * proportionate size (it would have been too small). This
  67. * breaks proportionality of the slider and the conversion
  68. * between pixels and user units.
  69. *
  70. * The factor needs to be tweaked in this case.
  71. */
  72. trueSize -= hitTheWall; /* actual pixels available */
  73. range -= slider->slider_size; /* actual range */
  74. if (range == 0) range = 1;
  75. factor = trueSize / range;
  76. }
  77. /* Many parentheses to explicitly control type conversion. */
  78. offset = slider->value - (slider->slider_size / 2) - slider->minimum;
  79. slider->slider_x = ((int)((offset * factor) + 0.5)) + slider->slider_area_x;
  80. slider->slider_y = slider->slider_area_y;
  81. /*
  82. * One final adjustment (of questionable value--preserved
  83. * for visual backward compatibility).
  84. */
  85. if ((slider->slider_x + slider->slider_width) > (slider->slider_area_x
  86. + slider->slider_area_width)) {
  87. slider->slider_x = slider->slider_area_x
  88. + slider->slider_area_width - slider->slider_width;
  89. }
  90. slider->aspect_x = factor;
  91. computeStepSize((Dimension)slider->slider_area_width,
  92. slider->minimum, slider->maximum, &slider->step, &slider->numTicks);
  93. return;
  94. }
  95. /*
  96. * Draw the slider graphic (shadowed rectangle) into the pixmap.
  97. */
  98. /***********************************************************************/
  99. #ifdef __STDC__
  100. static void drawSliderPixmap(Widget w)
  101. #else
  102. static void drawSliderPixmap(w)
  103. Widget w;
  104. #endif /*__STDC__*/
  105. {
  106. register int xpos;
  107. register int slider_width = slider->slider_width;
  108. register int slider_height = slider->slider_height;
  109. register Dimension shadowThickness = slider->shadowThickness;
  110. register Drawable sliderPixmap = slider->pixmap;
  111. XFillRectangle(XtDisplay(w), sliderPixmap, slider->foreground_GC,
  112. 0, 0, slider_width, slider_height);
  113. (void)_XmDrawShadows(XtDisplay(w), sliderPixmap,
  114. slider->top_shadow_GC, slider->bottom_shadow_GC,
  115. 0, 0, slider_width, slider_height, shadowThickness,
  116. XmSHADOW_OUT);
  117. /* Draw a line in the middle. */
  118. xpos = (slider_width / 2) - 1;
  119. XDrawLine(XtDisplay(w), sliderPixmap, slider->bottom_shadow_GC,
  120. xpos, ((slider_height / 2) + 1), xpos, (slider_height - 2));
  121. xpos = slider_width / 2;
  122. XDrawLine(XtDisplay(w), sliderPixmap, slider->top_shadow_GC,
  123. xpos, ((slider_height / 2) + 1), xpos, (slider_height - 2));
  124. /* Now, draw a line on the inside of each bucket. */
  125. xpos = (slider_width / 2) - slider->slider_gap - 1;
  126. XDrawLine(XtDisplay(w), sliderPixmap, slider->bottom_shadow_GC,
  127. xpos, 1, xpos, (slider_height - 2));
  128. xpos = (slider_width / 2) - slider->slider_gap;
  129. XDrawLine(XtDisplay(w), sliderPixmap, slider->top_shadow_GC,
  130. xpos, 1, xpos, (slider_height - 2));
  131. xpos = (slider_width / 2) + slider->slider_gap - 1;
  132. XDrawLine(XtDisplay(w), sliderPixmap, slider->bottom_shadow_GC,
  133. xpos, 1, xpos, (slider_height - 2));
  134. xpos = (slider_width / 2) + slider->slider_gap;
  135. XDrawLine(XtDisplay(w), sliderPixmap, slider->top_shadow_GC,
  136. xpos, 1, xpos, (slider_height - 2));
  137. return;
  138. }
  139. /***********************************************************************/
  140. #ifdef __STDC__
  141. GC getForegroundGC(Widget w, Pixel fg)
  142. #else
  143. GC getForegroundGC(w, fg)
  144. Widget w;
  145. Pixel fg;
  146. #endif /*__STDC__*/
  147. {
  148. XGCValues values;
  149. XtGCMask valueMask;
  150. valueMask = GCForeground | GCGraphicsExposures;
  151. values.foreground = fg;
  152. values.graphics_exposures = False;
  153. return(XtGetGC(w, valueMask, &values));
  154. }
  155. /* Get the graphics context used for drawing the top shadow. */
  156. /***********************************************************************/
  157. #ifdef __STDC__
  158. GC getShadowGC(Widget w, Pixel fg, Pixel bg, Pixmap pix)
  159. #else
  160. GC getShadowGC(w, fg, bg, pix)
  161. Widget w;
  162. Pixel fg;
  163. Pixel bg;
  164. Pixmap pix;
  165. #endif /*__STDC__*/
  166. {
  167. XGCValues values;
  168. XtGCMask valueMask;
  169. valueMask = GCForeground | GCBackground;
  170. values.foreground = fg;
  171. values.background = bg;
  172. if ((pix != None) && (pix != XmUNSPECIFIED_PIXMAP)) {
  173. valueMask |= GCFillStyle | GCTile;
  174. values.fill_style = FillTiled;
  175. values.tile = pix;
  176. }
  177. return(XtGetGC(w, valueMask, &values));
  178. }
  179. /***********************************************************************/
  180. #ifdef __STDC__
  181. static void createSlider(Widget w)
  182. #else
  183. static void createSlider(w)
  184. Widget w;
  185. #endif /*__STDC__*/
  186. {
  187. Arg arg[10];
  188. Cardinal i;
  189. Pixel background, foreground, top_shadow_color, bottom_shadow_color;
  190. Pixmap top_shadow_pixmap, bottom_shadow_pixmap;
  191. slider = XtNew(SLIDER);
  192. i = 0;
  193. XtSetArg(arg[i], XmNbackground, &background); i++;
  194. XtSetArg(arg[i], XmNforeground, &foreground); i++;
  195. XtSetArg(arg[i], XmNtopShadowColor, &top_shadow_color); i++;
  196. XtSetArg(arg[i], XmNbottomShadowColor, &bottom_shadow_color); i++;
  197. XtSetArg(arg[i], XmNtopShadowPixmap, &top_shadow_pixmap); i++;
  198. XtSetArg(arg[i], XmNbottomShadowPixmap, &bottom_shadow_pixmap); i++;
  199. XtGetValues(w, arg, i);
  200. slider->widget = w;
  201. slider->foreground_GC = getForegroundGC(w, background);
  202. slider->top_shadow_GC = getShadowGC(w,
  203. top_shadow_color, foreground, top_shadow_pixmap);
  204. slider->bottom_shadow_GC = getShadowGC(w,
  205. bottom_shadow_color, foreground, bottom_shadow_pixmap);
  206. slider->pixmap = None;
  207. slider->slider_size = (SBMAX + SBMAX) / 1000.0; /* (MHz -> GHz). */
  208. slider->slider_bucket = LO2 / 1000.0; /* (MHz -> GHz). */
  209. slider->aspect_x = 1.0;
  210. slider->tmp.inMotion = False;
  211. return;
  212. }
  213. /*
  214. * Process resizes on the widget by destroying and recreating the
  215. * slider pixmap. Also draws the correct sized slider onto the pixmap.
  216. */
  217. /***********************************************************************/
  218. #ifdef __STDC__
  219. void resizeSlider(Widget w)
  220. #else
  221. void resizeSlider(w)
  222. Widget w;
  223. #endif /*__STDC__*/
  224. {
  225. int depth;
  226. Arg arg[10];
  227. Cardinal i;
  228. Dimension ht, st;
  229. Dimension width, height;
  230. ht = 2; /* primitive.highlight_thickness */
  231. i = 0;
  232. XtSetArg(arg[i], XmNshadowThickness, (XtArgVal)&st); i++;
  233. XtSetArg(arg[i], XmNwidth, (XtArgVal)&width); i++;
  234. XtSetArg(arg[i], XmNheight, (XtArgVal)&height); i++;
  235. XtSetArg(arg[i], XmNdepth, (XtArgVal)&depth); i++;
  236. XtGetValues(w, arg, i);
  237. height /= 2;
  238. slider->shadowThickness = st;
  239. slider->slider_area_x = ht + st;
  240. slider->slider_area_width = width - (2 * (ht + st));
  241. if ((Dimension)(2 * (ht + st)) > height)
  242. slider->slider_area_y = height / 2;
  243. else
  244. slider->slider_area_y = height + ht + st;
  245. slider->slider_area_height = height - (2 * (ht + st));
  246. if (slider->slider_area_width <= 0)
  247. slider->slider_area_width = 1;
  248. if (slider->slider_area_height <= 0)
  249. slider->slider_area_height = 1;
  250. if (slider->pixmap != None)
  251. XFreePixmap(XtDisplay(w), slider->pixmap);
  252. slider->pixmap = XCreatePixmap(XtDisplay(w),
  253. RootWindowOfScreen(XtScreen(w)), slider->slider_area_width,
  254. slider->slider_area_height, depth);
  255. resizeSliderRuler(w, (Dimension)slider->slider_area_x,
  256. (Dimension)slider->slider_area_width, height);
  257. calcSliderRect();
  258. drawSliderPixmap(w);
  259. return;
  260. }
  261. /* General redisplay function called on exposure events. */
  262. /***********************************************************************/
  263. #ifdef __STDC__
  264. void redisplaySlider(Widget w)
  265. #else
  266. void redisplaySlider(w)
  267. Widget w;
  268. #endif /*__STDC__*/
  269. {
  270. calcSliderRect();
  271. if (slider->pixmap != None)
  272. drawSliderPixmap(w);
  273. redrawSliderRuler(w, slider->minimum, slider->maximum, slider->step,
  274. slider->numTicks);
  275. /* Dump the pixmap that contains the slider graphics. */
  276. if (slider->pixmap != None)
  277. XCopyArea(XtDisplay(w), slider->pixmap, XtWindow(w),
  278. slider->foreground_GC, 0, 0, slider->slider_width,
  279. slider->slider_height, slider->slider_x, slider->slider_y);
  280. return;
  281. }
  282. /*
  283. * Clear the through area at the current slider position,
  284. * recompute the slider coordinates and redraw the slider
  285. * the window by copying from the pixmap graphics.
  286. */
  287. /***********************************************************************/
  288. #ifdef __STDC__
  289. void redrawSliderWindow(Widget w)
  290. #else
  291. void redrawSliderWindow(w)
  292. Widget w;
  293. #endif /*__STDC__*/
  294. {
  295. if (XtIsRealized(w))
  296. XClearArea(XtDisplay(w), XtWindow(w),
  297. (int)slider->slider_area_x, (int)slider->slider_area_y,
  298. (unsigned int)slider->slider_area_width,
  299. (unsigned int)slider->slider_area_height, (Bool)FALSE);
  300. calcSliderRect();
  301. /* Dump the pixmap that contains the slider graphics. */
  302. if ((XtIsRealized(w)) && (slider->pixmap != None))
  303. XCopyArea(XtDisplay(w), slider->pixmap, XtWindow(w),
  304. slider->foreground_GC, 0, 0, slider->slider_width,
  305. slider->slider_height, slider->slider_x, slider->slider_y);
  306. return;
  307. }
  308. /***********************************************************************/
  309. #ifdef __STDC__
  310. void setSliderRange(Widget w, double low, double high)
  311. #else
  312. void setSliderRange(w, low, high)
  313. Widget w;
  314. double low, high;
  315. #endif /*__STDC__*/
  316. {
  317. double offset;
  318. if (slider == (SLIDER *)NULL) {
  319. createSlider(w);
  320. slider->value = (low + high) / 2;
  321. }
  322. if ((high - low) < slider->slider_size)
  323. high = low + slider->slider_size;
  324. slider->minimum = low; /* Minimum window Frequency (GHz). */
  325. slider->maximum = high; /* Maximum window Frequency (GHz). */
  326. /* Truncate and redraw as appropriate. */
  327. offset = slider->value - (slider->slider_size / 2); /* Left edge. */
  328. if (offset >= (slider->maximum - slider->slider_size))
  329. offset = slider->maximum - slider->slider_size;
  330. if (offset <= slider->minimum)
  331. offset = slider->minimum;
  332. offset += (slider->slider_size / 2); /* Reset position to middle. */
  333. slider->value = offset;
  334. redisplaySlider(w);
  335. return;
  336. }
  337. /***********************************************************************/
  338. #ifdef __STDC__
  339. void adjustSliderRange(Boolean increase)
  340. #else
  341. void adjustSliderRange(increase)
  342. Boolean increase;
  343. #endif /*__STDC__*/
  344. {
  345. double low, high, offset;
  346. if (slider == (SLIDER *)NULL)
  347. return;
  348. low = slider->minimum;
  349. high = slider->maximum;
  350. offset = high - low;
  351. if (increase == True)
  352. offset *= 2;
  353. else
  354. offset /= 2;
  355. /* Limit requests that are too small or too large. */
  356. if (offset < (2 * slider->slider_size))
  357. offset = 2 * slider->slider_size;
  358. else if (offset > (Global->freqmax - Global->freqmin))
  359. offset = (Global->freqmax - Global->freqmin);
  360. /*
  361. * Try to center this new range around the slider's current
  362. * value. Also, truncate with respect to the Global limits,
  363. * as appropriate.
  364. */
  365. slider->minimum = slider->value - (offset / 2);
  366. if (slider->minimum < Global->freqmin)
  367. slider->minimum = Global->freqmin;
  368. slider->maximum = slider->minimum + offset;
  369. if (slider->maximum > Global->freqmax) {
  370. slider->maximum = Global->freqmax;
  371. slider->minimum = slider->maximum - offset;
  372. if (slider->minimum < Global->freqmin)
  373. slider->minimum = Global->freqmin;
  374. }
  375. redisplaySlider(slider->widget);
  376. return;
  377. }
  378. /*
  379. * The input value is the slider value in GHz. It represents LO1, or
  380. * the center of the slider.
  381. */
  382. /***********************************************************************/
  383. #ifdef __STDC__
  384. void setSliderValue(double value)
  385. #else
  386. void setSliderValue(value)
  387. double value;
  388. #endif /*__STDC__*/
  389. {
  390. double offset, range;
  391. Boolean adjust;
  392. if (slider == (SLIDER *)NULL)
  393. return;
  394. if (value == slider->value) /* No change needed. */
  395. return;
  396. slider->value = value;
  397. offset = slider->value - (slider->slider_size / 2); /* Left edge. */
  398. range = slider->maximum - slider->minimum;
  399. adjust = False;
  400. if (offset > (slider->maximum - slider->slider_size)) {
  401. slider->maximum = offset + slider->slider_size;
  402. slider->minimum = slider->maximum - range;
  403. adjust = True;
  404. } else if (offset < slider->minimum) {
  405. slider->minimum = offset;
  406. slider->maximum = slider->minimum + range;
  407. adjust = True;
  408. }
  409. if (adjust == True)
  410. setSliderRange(slider->widget, slider->minimum, slider->maximum);
  411. else
  412. redrawSliderWindow(slider->widget);
  413. setDrawingValue(False, slider->value);
  414. setDrawingValue(True, slider->value);
  415. return;
  416. }
  417. /***********************************************************************/
  418. #ifdef __STDC__
  419. void sliderStart(Widget w, int xpos)
  420. #else
  421. void sliderStart(w, xpos)
  422. Widget w;
  423. int xpos;
  424. #endif /*__STDC__*/
  425. {
  426. if ((!XtIsRealized(w)) || (slider == (SLIDER *)NULL))
  427. return;
  428. slider->tmp.inMotion = True;
  429. slider->tmp.dx = (Position)xpos - slider->slider_x;
  430. slider->tmp.x = slider->slider_x;
  431. return;
  432. }
  433. /***********************************************************************/
  434. #ifdef __STDC__
  435. void sliderStop(Widget w, int xpos)
  436. #else
  437. void sliderStop(w, xpos)
  438. Widget w;
  439. int xpos;
  440. #endif /*__STDC__*/
  441. {
  442. int maxx;
  443. double value;
  444. if ((!XtIsRealized(w)) || (slider == (SLIDER *)NULL))
  445. return;
  446. slider->tmp.x = (Position)xpos - slider->tmp.dx;
  447. if (slider->tmp.x < 0)
  448. slider->tmp.x = 0;
  449. maxx = slider->slider_area_x + slider->slider_area_width;
  450. maxx -= slider->slider_width;
  451. if (slider->tmp.x > (Position)maxx)
  452. slider->tmp.x = (Position)maxx;
  453. value = (slider->tmp.x - slider->slider_area_x) / slider->aspect_x;
  454. value += slider->minimum;
  455. if (value < slider->minimum)
  456. value = slider->minimum;
  457. else if (value > (slider->maximum - slider->slider_size))
  458. value = slider->maximum - slider->slider_size;
  459. value += (slider->slider_size / 2); /* Move to LO1 position. */
  460. setLO1(value);
  461. slider->tmp.inMotion = False;
  462. return;
  463. }
  464. /***********************************************************************/
  465. #ifdef __STDC__
  466. void sliderMove(Widget w, int xpos)
  467. #else
  468. void sliderMove(w, xpos)
  469. Widget w;
  470. int xpos;
  471. #endif /*__STDC__*/
  472. {
  473. int maxx;
  474. double value;
  475. if ((!XtIsRealized(w)) || (slider == (SLIDER *)NULL))
  476. return;
  477. if (slider->tmp.inMotion != True)
  478. return;
  479. slider->tmp.x = (Position)xpos - slider->tmp.dx;
  480. if (slider->tmp.x < slider->slider_area_x)
  481. slider->tmp.x = slider->slider_area_x;
  482. maxx = slider->slider_area_x + slider->slider_area_width;
  483. maxx -= slider->slider_width;
  484. if (slider->tmp.x > (Position)maxx)
  485. slider->tmp.x = (Position)maxx;
  486. value = (slider->tmp.x - slider->slider_area_x) / slider->aspect_x;
  487. value += slider->minimum;
  488. if (value < slider->minimum)
  489. value = slider->minimum;
  490. else if (value > (slider->maximum - slider->slider_size))
  491. value = slider->maximum - slider->slider_size;
  492. value += (slider->slider_size / 2); /* Move to LO1 position. */
  493. setLO1(value);
  494. return;
  495. }