home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / rcm / rcm_callback.c next >
Encoding:
C/C++ Source or Header  |  2000-11-19  |  23.2 KB  |  821 lines

  1. /*
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This is a plug-in for the GIMP.
  5.  *
  6.  * Colormap-Rotation plug-in. Exchanges two color ranges.
  7.  *
  8.  * Copyright (C) 1999 Sven Anders (anderss@fmi.uni-passau.de)
  9.  *                    Based on code from Pavel Grinfeld (pavel@ml.com)
  10.  *
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25.  */
  26.  
  27. /*---------------------------------------------------------------------------
  28.  * Change log:
  29.  * 
  30.  * Version 2.0, 04 April 1999.
  31.  *  Nearly complete rewrite, made plug-in stable.
  32.  *  (Works with GIMP 1.1 and GTK+ 1.2)
  33.  *
  34.  * Version 1.0, 27 March 1997.
  35.  *  Initial (unstable) release by Pavel Grinfeld
  36.  *
  37.  *---------------------------------------------------------------------------*/
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <math.h>
  42.  
  43. #include "config.h"
  44. #include <gtk/gtk.h>
  45. #include "libgimp/gimp.h"
  46. #include "libgimp/stdplugins-intl.h"
  47.  
  48. #include "rcm.h"
  49. #include "rcm_misc.h"
  50. #include "rcm_gdk.h"
  51. #include "rcm_dialog.h"
  52. #include "rcm_callback.h"
  53.  
  54. #include "pixmaps/rcm_ccw.xpm"
  55. #include "pixmaps/rcm_cw.xpm"
  56.  
  57.  
  58. /*---------------------------------------------------------------------------*/
  59. /* Misc functions */
  60. /*---------------------------------------------------------------------------*/
  61.  
  62. float 
  63. rcm_units_factor (gint units)
  64. {
  65.   switch (units)
  66.   {
  67.     case DEGREES:         return 180.0 / G_PI;
  68.     case RADIANS:         return 1.0;
  69.     case RADIANS_OVER_PI: return 1.0 / G_PI;
  70.     default:              return -1;
  71.   }
  72. }
  73.  
  74. gchar *
  75. rcm_units_string (gint units)
  76. {
  77.   switch (units)
  78.   {
  79.     case DEGREES:         return "deg";
  80.     case RADIANS:         return "rad";
  81.     case RADIANS_OVER_PI: return "rad/pi";
  82.     default:              return "(???)";
  83.   }
  84. }
  85.  
  86. void 
  87. rcm_set_pixmap (GtkWidget **widget, 
  88.         GtkWidget  *parent, 
  89.         GtkWidget  *label_box, 
  90.         char      **pixmap_data)
  91. {
  92.   GdkPixmap *pixmap;
  93.   GdkBitmap *mask;
  94.   GtkStyle  *style;
  95.  
  96.   /* create pixmap */
  97.  
  98.   style = gtk_widget_get_style(parent);
  99.   pixmap = gdk_pixmap_create_from_xpm_d(parent->window, &mask,
  100.                     &style->bg[GTK_STATE_NORMAL], pixmap_data);
  101.  
  102.   if (*widget != NULL)
  103.   {
  104.     gtk_widget_destroy(*widget);
  105.   }
  106.  
  107.   *widget = gtk_pixmap_new(pixmap, mask);
  108.  
  109.   gtk_box_pack_start(GTK_BOX(label_box), *widget, FALSE, FALSE, 3);
  110.  
  111.   gtk_widget_show(*widget);
  112. }
  113.  
  114. /*---------------------------------------------------------------------------*/
  115. /* Ok Button */
  116. /*---------------------------------------------------------------------------*/
  117.  
  118. void 
  119. rcm_ok_callback (GtkWidget *widget,
  120.          gpointer   data)
  121. {
  122.   Current.Success = 1;
  123.  
  124.   gtk_widget_destroy (GTK_WIDGET (data));
  125. }
  126.  
  127. /*---------------------------------------------------------------------------*/
  128. /* Circle buttons */
  129. /*---------------------------------------------------------------------------*/
  130.  
  131. void 
  132. rcm_360_degrees (GtkWidget *button, 
  133.          RcmCircle *circle)
  134. {
  135.   circle->action_flag = DO_NOTHING;
  136.   gtk_widget_draw(circle->preview, NULL);
  137.   circle->angle->beta = circle->angle->alpha-circle->angle->cw_ccw * 0.001;
  138.   rcm_draw_arrows(circle->preview->window, circle->preview->style->black_gc, circle->angle);
  139.   circle->action_flag = VIRGIN;
  140.   rcm_render_preview(Current.Bna->after, CURRENT);
  141. }
  142.  
  143. void 
  144. rcm_cw_ccw (GtkWidget *button, 
  145.         RcmCircle *circle)
  146. {
  147.   circle->angle->cw_ccw *= -1;
  148.  
  149.   rcm_set_pixmap(&circle->cw_ccw_pixmap, circle->cw_ccw_button->parent,
  150.          circle->cw_ccw_box, (circle->angle->cw_ccw>0) ? rcm_cw_xpm : rcm_ccw_xpm);
  151.  
  152.   gtk_label_set_text (GTK_LABEL (circle->cw_ccw_label),
  153.               (circle->angle->cw_ccw>0) ?
  154.               _("Switch to clockwise") : _("Switch to c/clockwise"));
  155.  
  156.   rcm_a_to_b(button, circle);
  157. }
  158.  
  159. void 
  160. rcm_a_to_b (GtkWidget *button, 
  161.         RcmCircle *circle)
  162. {
  163.   circle->action_flag = DO_NOTHING;
  164.   gtk_widget_draw(circle->preview, NULL);
  165.  
  166.   SWAP(circle->angle->alpha, circle->angle->beta);
  167.  
  168.   rcm_draw_arrows(circle->preview->window, circle->preview->style->black_gc,
  169.           circle->angle);
  170.  
  171.   circle->action_flag = VIRGIN;
  172.   rcm_render_preview(Current.Bna->after, CURRENT);
  173. }
  174.  
  175. /*---------------------------------------------------------------------------*/
  176. /* Misc: units buttons */
  177. /*---------------------------------------------------------------------------*/
  178.  
  179. static void 
  180. rcm_spinbutton_to_degrees (GtkWidget *button, 
  181.                float      value, 
  182.                GtkWidget *label)
  183. {
  184.   GtkAdjustment *adj;
  185.  
  186.   adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(button));
  187.   adj->value = value * rcm_units_factor(Current.Units);
  188.   adj->upper = 360.0;
  189.   adj->step_increment = 0.01;
  190.   adj->page_increment = 1.0;
  191.   gtk_spin_button_set_digits(GTK_SPIN_BUTTON(button), 2);
  192.  
  193.   gtk_label_set_text (GTK_LABEL(label), rcm_units_string(Current.Units));
  194. }
  195.  
  196. void 
  197. rcm_switch_to_degrees (GtkWidget *button, 
  198.                gpointer  *value)
  199. {
  200.   if (GTK_TOGGLE_BUTTON(button)->active)
  201.   {
  202.     Current.Units = DEGREES;
  203.  
  204.     rcm_spinbutton_to_degrees(Current.From->alpha_entry, 
  205.                   Current.From->angle->alpha,
  206.                   Current.From->alpha_units_label);
  207.  
  208.     rcm_spinbutton_to_degrees(Current.From->beta_entry, 
  209.                   Current.From->angle->beta,
  210.                   Current.From->beta_units_label);
  211.  
  212.     rcm_spinbutton_to_degrees(Current.To->alpha_entry, 
  213.                   Current.To->angle->alpha,
  214.                   Current.To->alpha_units_label);
  215.  
  216.     rcm_spinbutton_to_degrees(Current.To->beta_entry, 
  217.                   Current.To->angle->beta,
  218.                   Current.To->beta_units_label);
  219.  
  220.     rcm_spinbutton_to_degrees(Current.Gray->hue_entry, 
  221.                   Current.Gray->hue,
  222.                   Current.Gray->hue_units_label);
  223.  
  224.     Current.From->action_flag = VIRGIN;
  225.     Current.To->action_flag   = VIRGIN;
  226.     Current.Gray->action_flag = VIRGIN;
  227.   }
  228. }
  229.  
  230. /*---------------------------------------------------------------------------*/
  231.  
  232. static void 
  233. rcm_spinbutton_to_radians (GtkWidget *button, 
  234.                float      value, 
  235.                GtkWidget *label)
  236. {
  237.   GtkAdjustment *adj;
  238.  
  239.   adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(button));
  240.   adj->value = value * rcm_units_factor(Current.Units);
  241.   adj->upper = TP; 
  242.   adj->step_increment = 0.0001; 
  243.   adj->page_increment = 0.001;
  244.   gtk_spin_button_set_digits(GTK_SPIN_BUTTON(button), 4);
  245.  
  246.   gtk_label_set_text (GTK_LABEL(label), rcm_units_string(Current.Units));
  247. }
  248.  
  249. void 
  250. rcm_switch_to_radians (GtkWidget *button, 
  251.                gpointer  *value)
  252. {
  253.   if (GTK_TOGGLE_BUTTON(button)->active) 
  254.   {
  255.     Current.Units = RADIANS;
  256.  
  257.     rcm_spinbutton_to_radians(Current.From->alpha_entry, 
  258.                   Current.From->angle->alpha,
  259.                   Current.From->alpha_units_label);
  260.  
  261.     rcm_spinbutton_to_radians(Current.From->beta_entry, 
  262.                   Current.From->angle->beta,
  263.                   Current.From->beta_units_label);
  264.  
  265.     rcm_spinbutton_to_radians(Current.To->alpha_entry, 
  266.                   Current.To->angle->alpha,
  267.                   Current.To->alpha_units_label);
  268.  
  269.     rcm_spinbutton_to_radians(Current.To->beta_entry, 
  270.                   Current.To->angle->beta,
  271.                   Current.To->beta_units_label);
  272.  
  273.     rcm_spinbutton_to_radians(Current.Gray->hue_entry, 
  274.                   Current.Gray->hue,
  275.                   Current.Gray->hue_units_label);
  276.  
  277.     Current.From->action_flag = VIRGIN;
  278.     Current.To->action_flag   = VIRGIN;
  279.     Current.Gray->action_flag = VIRGIN;
  280.   }
  281. }
  282.  
  283. /*---------------------------------------------------------------------------*/
  284.  
  285. static void 
  286. rcm_spinbutton_to_radians_over_PI (GtkWidget *button, 
  287.                    float      value, 
  288.                    GtkWidget *label)
  289. {
  290.   GtkAdjustment *adj;
  291.  
  292.   adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(button));
  293.   adj->value = value * rcm_units_factor(Current.Units);
  294.   adj->upper = 2.0;
  295.   adj->step_increment = 0.0001;
  296.   adj->page_increment = 0.001;
  297.   gtk_spin_button_set_digits(GTK_SPIN_BUTTON(button), 4);
  298.  
  299.   gtk_label_set_text (GTK_LABEL(label), rcm_units_string(Current.Units));
  300. }
  301.  
  302. void 
  303. rcm_switch_to_radians_over_PI (GtkWidget *button, 
  304.                    gpointer  *value)
  305. {
  306.   if (GTK_TOGGLE_BUTTON(button)->active)
  307.   { 
  308.     Current.Units = RADIANS_OVER_PI;
  309.  
  310.     rcm_spinbutton_to_radians_over_PI(Current.From->alpha_entry, 
  311.                       Current.From->angle->alpha,
  312.                       Current.From->alpha_units_label);
  313.  
  314.     rcm_spinbutton_to_radians_over_PI(Current.From->beta_entry, 
  315.                       Current.From->angle->beta,
  316.                       Current.From->beta_units_label);
  317.  
  318.     rcm_spinbutton_to_radians_over_PI(Current.To->alpha_entry, 
  319.                       Current.To->angle->alpha,
  320.                       Current.To->alpha_units_label);
  321.  
  322.     rcm_spinbutton_to_radians_over_PI(Current.To->beta_entry, 
  323.                       Current.To->angle->beta,
  324.                       Current.To->beta_units_label);
  325.  
  326.     rcm_spinbutton_to_radians_over_PI(Current.Gray->hue_entry, 
  327.                       Current.Gray->hue,
  328.                       Current.Gray->hue_units_label);
  329.  
  330.     Current.From->action_flag = VIRGIN;
  331.     Current.To->action_flag   = VIRGIN;
  332.     Current.Gray->action_flag = VIRGIN;
  333.   }
  334. }
  335.  
  336. /*---------------------------------------------------------------------------*/
  337. /* Misc: Gray: mode buttons */
  338. /*---------------------------------------------------------------------------*/
  339.  
  340. void 
  341. rcm_switch_to_gray_to (GtkWidget *button, 
  342.                gpointer  *value)
  343. {
  344.   if (!GTK_TOGGLE_BUTTON(button)->active) return;
  345.  
  346.   Current.Gray_to_from = GRAY_TO;
  347.   rcm_render_preview(Current.Bna->after, CURRENT);
  348. }
  349.  
  350. void 
  351. rcm_switch_to_gray_from (GtkWidget *button, 
  352.              gpointer  *value)
  353. {
  354.   if (!(GTK_TOGGLE_BUTTON(button)->active)) return;
  355.  
  356.   Current.Gray_to_from = GRAY_FROM;
  357.   rcm_render_preview(Current.Bna->after, CURRENT);
  358. }
  359.  
  360. /*---------------------------------------------------------------------------*/
  361. /* Misc: Preview buttons */
  362. /*---------------------------------------------------------------------------*/
  363.  
  364. void 
  365. rcm_preview_as_you_drag (GtkWidget *button, 
  366.              gpointer  *value)
  367. {
  368.   if (GTK_TOGGLE_BUTTON(button)->active) 
  369.     Current.RealTime = TRUE;
  370.   else
  371.     Current.RealTime = FALSE;
  372. }
  373.  
  374. /*---------------------------------------------------------------------------*/
  375.  
  376. static void 
  377. rcm_change_preview (void)
  378. {
  379.   /* must hide and show or resize would not work ... */
  380.  
  381.   gtk_widget_hide(Current.Bna->before);
  382.   gtk_widget_hide(Current.Bna->after);
  383.  
  384.   gtk_preview_size(GTK_PREVIEW(Current.Bna->before),
  385.            Current.reduced->width, Current.reduced->height);
  386.  
  387.   gtk_preview_size(GTK_PREVIEW(Current.Bna->after),
  388.            Current.reduced->width, Current.reduced->height);
  389.  
  390.   rcm_render_preview(Current.Bna->before, ORIGINAL);
  391.   rcm_render_preview(Current.Bna->after, CURRENT);
  392.  
  393.   gtk_widget_draw(Current.Bna->before, NULL);
  394.   gtk_widget_draw(Current.Bna->after, NULL);
  395.  
  396.   gtk_widget_show(Current.Bna->before);
  397.   gtk_widget_show(Current.Bna->after);
  398. }
  399.  
  400. /*---------------------------------------------------------------------------*/
  401.  
  402. void 
  403. rcm_selection_in_context (GtkWidget *button, 
  404.               gpointer  *value)
  405. {
  406.   Current.reduced = rcm_reduce_image(Current.drawable, Current.mask,
  407.                      MAX_PREVIEW_SIZE, SELECTION_IN_CONTEXT);
  408.   rcm_change_preview();
  409. }
  410.  
  411. void 
  412. rcm_selection (GtkWidget *button, 
  413.            gpointer  *value)
  414. {
  415.   Current.reduced = rcm_reduce_image(Current.drawable, Current.mask,
  416.                      MAX_PREVIEW_SIZE, SELECTION);
  417.   rcm_change_preview();
  418. }
  419.  
  420. void 
  421. rcm_entire_image (GtkWidget *button, 
  422.           gpointer  *value)
  423. {
  424.   Current.reduced = rcm_reduce_image(Current.drawable, Current.mask,
  425.                      MAX_PREVIEW_SIZE, ENTIRE_IMAGE);
  426.   rcm_change_preview();  
  427. }
  428.  
  429.  
  430. /*---------------------------------------------------------------------------*/
  431. /* Circle events */
  432. /*---------------------------------------------------------------------------*/
  433.  
  434. gint 
  435. rcm_expose_event (GtkWidget *widget, 
  436.           GdkEvent  *event, 
  437.           RcmCircle *circle)
  438. {
  439.   switch (circle->action_flag)
  440.   {
  441.     case DO_NOTHING: return 0;
  442.  
  443.     case VIRGIN:     rcm_draw_arrows(widget->window, widget->style->black_gc,
  444.                      circle->angle);
  445.                      break;
  446.  
  447.     default:         if (Current.RealTime)
  448.                        rcm_render_preview(Current.Bna->after,CURRENT);
  449.              break;
  450.   }
  451.   return 1;
  452. }
  453.  
  454. /*---------------------------------------------------------------------------*/
  455.  
  456. gint 
  457. rcm_button_press_event (GtkWidget *widget, 
  458.             GdkEvent  *event, 
  459.             RcmCircle *circle)
  460. {
  461.   float clicked_angle;
  462.   float *alpha;
  463.   float *beta;
  464.   GdkEventButton *bevent;
  465.  
  466.   alpha = &(circle->angle->alpha);
  467.   beta = &(circle->angle->beta);
  468.   bevent = (GdkEventButton *) event;
  469.  
  470.   circle->action_flag = DRAG_START;
  471.   clicked_angle = angle_mod_2PI(arctg(CENTER-bevent->y, bevent->x-CENTER));
  472.   circle->prev_clicked = clicked_angle;
  473.   
  474.   if ((sqrt (SQR (bevent->y-CENTER) + SQR (bevent->x-CENTER)) > RADIUS * EACH_OR_BOTH) &&
  475.       (min_prox (*alpha, *beta, clicked_angle) < G_PI / 12))
  476.   {
  477.     circle->mode = EACH;
  478.     circle->target = closest(alpha, beta, clicked_angle);
  479.     
  480.     if (*(circle->target) != clicked_angle)
  481.     {
  482.       *(circle->target) = clicked_angle; 
  483.       gtk_widget_draw(circle->preview, NULL);
  484.       rcm_draw_arrows(widget->window, widget->style->black_gc, circle->angle);
  485.       
  486.       gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->alpha_entry),
  487.                 circle->angle->alpha * rcm_units_factor(Current.Units));
  488.  
  489.       gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->beta_entry),
  490.                 circle->angle->beta * rcm_units_factor(Current.Units));
  491.  
  492.       if (Current.RealTime)
  493.     rcm_render_preview(Current.Bna->after, CURRENT);
  494.     }
  495.   }
  496.   else 
  497.     circle->mode = BOTH;
  498.  
  499.   return 1;
  500. }
  501.  
  502. /*---------------------------------------------------------------------------*/
  503.  
  504. gint 
  505. rcm_release_event (GtkWidget *widget, 
  506.            GdkEvent  *event,  
  507.            RcmCircle *circle)
  508. {
  509.   if (circle->action_flag == DRAGING)
  510.     rcm_draw_arrows(widget->window, widget->style->black_gc, circle->angle); 
  511.   circle->action_flag = VIRGIN;
  512.   
  513.   if (!(Current.RealTime))
  514.       rcm_render_preview(Current.Bna->after,CURRENT);
  515.  
  516.   return 1;
  517. }
  518.  
  519. /*---------------------------------------------------------------------------*/
  520.  
  521. gint 
  522. rcm_motion_notify_event (GtkWidget *widget, 
  523.              GdkEvent  *event, 
  524.              RcmCircle *circle)
  525.   gint x, y;
  526.   float clicked_angle, delta;
  527.   float *alpha, *beta;
  528.   int  cw_ccw;
  529.   GdkGCValues values;
  530.  
  531.   alpha = &(circle->angle->alpha);
  532.   beta  = &(circle->angle->beta);
  533.   cw_ccw = circle->angle->cw_ccw;
  534.   delta = angle_mod_2PI(cw_ccw * (*beta - *alpha));
  535.  
  536.   values.foreground = Current.From->preview->style->white;
  537.   values.function = GDK_XOR;
  538.   xor_gc = gdk_gc_new_with_values (Current.From->preview->window,
  539.                    &values, GDK_GC_FOREGROUND | GDK_GC_FUNCTION);
  540.  
  541.   gdk_window_get_pointer(widget->window, &x, &y, NULL);
  542.   clicked_angle = angle_mod_2PI(arctg(CENTER-y, x-CENTER));
  543.   
  544.   delta = clicked_angle - circle->prev_clicked;
  545.   circle->prev_clicked = clicked_angle;
  546.   
  547.   if (delta)
  548.   {
  549.     if (circle->action_flag == DRAG_START)
  550.     {
  551.       gtk_widget_draw(circle->preview, NULL);
  552.       circle->action_flag = DRAGING;
  553.     }
  554.     else 
  555.       rcm_draw_arrows(widget->window, xor_gc, circle->angle);  /* erase! */
  556.     
  557.     if (circle->mode==EACH)
  558.       *(circle->target)=clicked_angle;
  559.     else {
  560.       circle->angle->alpha=angle_mod_2PI(circle->angle->alpha + delta);
  561.       circle->angle->beta =angle_mod_2PI(circle->angle->beta  + delta);
  562.     }
  563.     
  564.     rcm_draw_arrows(widget->window, xor_gc, circle->angle); 
  565.     
  566.     gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->alpha_entry),
  567.               circle->angle->alpha * rcm_units_factor(Current.Units));
  568.  
  569.     gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->beta_entry),
  570.               circle->angle->beta * rcm_units_factor(Current.Units));
  571.     
  572.     if (Current.RealTime)
  573.       rcm_render_preview(Current.Bna->after, CURRENT);
  574.   }
  575.  
  576.   return 1;
  577. }
  578.  
  579. /*---------------------------------------------------------------------------*/
  580. /* Gray circle events */
  581. /*---------------------------------------------------------------------------*/
  582.  
  583. gint rcm_gray_expose_event (GtkWidget *widget, 
  584.                 GdkEvent  *event, 
  585.                 RcmGray   *circle)
  586. {
  587.   if (circle->action_flag == VIRGIN)
  588.   {
  589.     rcm_draw_little_circle(widget->window, widget->style->black_gc,
  590.                circle->hue, circle->satur);
  591.  
  592.     rcm_draw_large_circle(widget->window, widget->style->black_gc, circle->gray_sat);
  593.   }
  594.   else if (Current.RealTime)
  595.     rcm_render_preview(Current.Bna->after, CURRENT);
  596.  
  597.   return 1;
  598. }
  599.  
  600. /*---------------------------------------------------------------------------*/
  601.  
  602. gint 
  603. rcm_gray_button_press_event (GtkWidget *widget, 
  604.                  GdkEvent  *event, 
  605.                  RcmGray   *circle)
  606. {
  607.   GdkEventButton *bevent;
  608.   int x, y;
  609.  
  610.   bevent = (GdkEventButton *) event;
  611.   x = bevent->x - GRAY_CENTER - LITTLE_RADIUS;
  612.   y = GRAY_CENTER - bevent->y + LITTLE_RADIUS;
  613.  
  614.   circle->action_flag = DRAG_START;
  615.   circle->hue = angle_mod_2PI(arctg(y, x));
  616.   circle->satur = sqrt (SQR (x) + SQR (y)) / GRAY_RADIUS;
  617.   if (circle->satur > 1.0) circle->satur = 1;
  618.  
  619.   gtk_widget_draw(circle->preview, NULL);
  620.   rcm_draw_little_circle(widget->window, widget->style->black_gc,
  621.              circle->hue, circle->satur);
  622.   
  623.   rcm_draw_large_circle(circle->preview->window, circle->preview->style->black_gc,
  624.             circle->gray_sat);  
  625.   
  626.   gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->hue_entry),
  627.                   circle->hue * rcm_units_factor(Current.Units));
  628.  
  629.   gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->satur_entry), circle->satur);
  630.   
  631.   if (Current.RealTime)
  632.       rcm_render_preview(Current.Bna->after,CURRENT);
  633.  
  634.   return 1;
  635. }
  636.  
  637. /*---------------------------------------------------------------------------*/
  638.  
  639. gint 
  640. rcm_gray_release_event (GtkWidget *widget, 
  641.             GdkEvent  *event, 
  642.             RcmGray   *circle)
  643. {
  644.   if (circle->action_flag == DRAGING)
  645.     rcm_draw_little_circle(widget->window,
  646.                widget->style->black_gc,
  647.                circle->hue,
  648.                circle->satur);
  649.  
  650.   circle->action_flag = VIRGIN;
  651.   
  652.   if (!(Current.RealTime)) rcm_render_preview(Current.Bna->after, CURRENT);
  653.  
  654.   return 1;
  655. }
  656.  
  657. /*---------------------------------------------------------------------------*/
  658.  
  659. gint 
  660. rcm_gray_motion_notify_event (GtkWidget *widget, 
  661.                   GdkEvent  *event, 
  662.                   RcmGray   *circle)
  663.   gint x, y;
  664.   GdkGCValues values;
  665.   
  666.   values.foreground = Current.From->preview->style->white;
  667.   values.function = GDK_XOR;
  668.   xor_gc = gdk_gc_new_with_values (Current.From->preview->window,
  669.                    &values, GDK_GC_FOREGROUND | GDK_GC_FUNCTION);
  670.   
  671.   if (circle->action_flag == DRAG_START)
  672.   {
  673.     gtk_widget_draw(circle->preview, NULL);
  674.     rcm_draw_large_circle(circle->preview->window, circle->preview->style->black_gc,
  675.               circle->gray_sat);
  676.  
  677.     circle->action_flag = DRAGING;
  678.   }
  679.   else 
  680.     rcm_draw_little_circle(widget->window, xor_gc,
  681.                circle->hue, circle->satur); /* erase */
  682.  
  683.   gdk_window_get_pointer(widget->window, &x, &y, NULL);
  684.  
  685.   x = x - GRAY_CENTER - LITTLE_RADIUS;
  686.   y = GRAY_CENTER - y + LITTLE_RADIUS;
  687.  
  688.   circle->hue = angle_mod_2PI (arctg (y, x));
  689.   circle->satur = sqrt (SQR (x) + SQR (y)) / GRAY_RADIUS;
  690.   if (circle->satur > 1.0) circle->satur = 1;
  691.  
  692.   rcm_draw_little_circle(widget->window, xor_gc, circle->hue, circle->satur);
  693.  
  694.   gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->hue_entry),
  695.                 circle->hue * rcm_units_factor(Current.Units));
  696.  
  697.   gtk_spin_button_set_value(GTK_SPIN_BUTTON(circle->satur_entry), circle->satur);
  698.  
  699.   if (Current.RealTime) rcm_render_preview(Current.Bna->after, CURRENT);
  700.  
  701.   return 1;
  702. }
  703.  
  704. /*---------------------------------------------------------------------------*/
  705. /* Spinbuttons */
  706. /*---------------------------------------------------------------------------*/
  707.  
  708. void 
  709. rcm_set_alpha (GtkWidget *entry, 
  710.            gpointer   data)
  711. {
  712.   RcmCircle *circle;
  713.  
  714.   circle = (RcmCircle *) data;
  715.   if (circle->action_flag != VIRGIN) return;
  716.  
  717.   circle->angle->alpha = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(entry)) /
  718.                                                       rcm_units_factor(Current.Units);
  719.  
  720.   gtk_widget_draw(circle->preview, NULL);
  721.  
  722.   rcm_draw_arrows(circle->preview->window, circle->preview->style->black_gc,
  723.           circle->angle); 
  724.  
  725.   rcm_render_preview(Current.Bna->after, CURRENT);
  726. }
  727.  
  728. /*---------------------------------------------------------------------------*/
  729.  
  730. void 
  731. rcm_set_beta (GtkWidget *entry, 
  732.           gpointer   data)
  733. {
  734.   RcmCircle *circle;
  735.  
  736.   circle=(RcmCircle *) data;
  737.   if (circle->action_flag != VIRGIN) return;
  738.  
  739.   circle->angle->beta = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(entry)) /
  740.                                                      rcm_units_factor(Current.Units);
  741.  
  742.   gtk_widget_draw(circle->preview, NULL);
  743.  
  744.   rcm_draw_arrows(circle->preview->window, circle->preview->style->black_gc,
  745.           circle->angle);  
  746.  
  747.   rcm_render_preview(Current.Bna->after, CURRENT);
  748. }
  749.  
  750. /*---------------------------------------------------------------------------*/
  751.  
  752. void 
  753. rcm_set_hue (GtkWidget *entry, 
  754.          gpointer   data)
  755. {
  756.   RcmGray *circle;
  757.  
  758.   circle = (RcmGray *) data;
  759.   if (circle->action_flag != VIRGIN) return;
  760.  
  761.   circle->hue = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(entry)) /
  762.                                                    rcm_units_factor(Current.Units);
  763.  
  764.   gtk_widget_draw(circle->preview, NULL);
  765.  
  766.   rcm_draw_little_circle(circle->preview->window, circle->preview->style->black_gc,
  767.              circle->hue, circle->satur);  
  768.  
  769.   rcm_draw_large_circle(circle->preview->window, circle->preview->style->black_gc,
  770.             circle->gray_sat);  
  771.  
  772.   rcm_render_preview(Current.Bna->after, CURRENT);
  773. }
  774.  
  775. /*---------------------------------------------------------------------------*/
  776.  
  777. void 
  778. rcm_set_satur (GtkWidget *entry, 
  779.            gpointer   data)
  780. {
  781.   RcmGray *circle;
  782.  
  783.   circle=(RcmGray *) data;
  784.   if (circle->action_flag != VIRGIN) return;
  785.   
  786.   circle->satur = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(entry));
  787.  
  788.   gtk_widget_draw(circle->preview, NULL);
  789.   rcm_draw_little_circle(circle->preview->window, circle->preview->style->black_gc,
  790.              circle->hue, circle->satur);
  791.  
  792.   rcm_draw_large_circle(circle->preview->window, circle->preview->style->black_gc,
  793.             circle->gray_sat);  
  794.  
  795.   rcm_render_preview(Current.Bna->after, CURRENT);
  796. }
  797.  
  798. /*---------------------------------------------------------------------------*/
  799.  
  800. void 
  801. rcm_set_gray_sat (GtkWidget *entry, 
  802.           gpointer   data)
  803. {
  804.   RcmGray *circle;
  805.  
  806.   circle=(RcmGray *) data;
  807.  
  808.   circle->gray_sat = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(entry));
  809.  
  810.   gtk_widget_draw(circle->preview, NULL);
  811.  
  812.   rcm_draw_large_circle(circle->preview->window, circle->preview->style->black_gc,
  813.             circle->gray_sat);
  814.  
  815.   rcm_render_preview(Current.Bna->after, CURRENT);
  816. }
  817.  
  818. /*---------------------------------------------------------------------------*/
  819.