Logo Search packages:      
Sourcecode: papaya version File versions  Download package

Fade.cpp

#include "papaya/system.h"
#include "mudclient.h"

#include "PapayaList.h"
#include "Fade.h"

Fade::Fade(gboolean three, char * min, char * mid, char * max) {
  min_edit = NULL;
  mid_edit = NULL;
  max_edit = NULL;
  pixmap = NULL;
  update_preview = FALSE;
  editor_toplevel = NULL;
  preview = NULL;
  reset(three, min, mid, max);
}

void Fade::reset(gboolean three, char * min, char * mid, char *max) {
  if (!min || !parseColour(&minimum, min)) {
    minimum.red   = 0xFFFF;
    minimum.green = 0x0000;
    minimum.blue  = 0x0000;
  }

  if (!mid || !parseColour(&middle, mid)) {
    middle.red    = 0xFFFF;
    middle.green  = 0xFFFF;
    middle.blue   = 0x0000;
  }

  if (!max || !parseColour(&maximum, max)) {
    maximum.red   = 0x0000;
    maximum.green = 0xFFFF;
    maximum.blue  = 0x0000;
  }

  // Clean up potential user-data
  if (three)
    use_three = TRUE;
  else
    use_three = FALSE;
}

Fade::~Fade() {
  return;
}

gboolean Fade::parseColour(GdkColor * colour, char * colour_string) {
  int r, g, b;
  if (colour_string && colour_string[0] != '\0') {
    if (sscanf(colour_string, "%d,%d,%d", &r, &g, &b) == 3) {
      colour->red = r;
      colour->green = g;
      colour->blue = b;
      return TRUE;
    } else
      debug(_("Fade: failed to parse \"%s\"\n"), colour_string);
  } else
    debug(_("Fade: No colour string given - defaulting.\n"));

  // Default
  colour->red   = 0x0000;
  colour->green = 0x0000;
  colour->blue  = 0x0000;

  return FALSE;
}

GtkWidget * Fade::getEditor() {
  GtkWidget * table;
  GtkWidget * label_box;
  GtkWidget * label;
  GtkWidget * ce_box;
  GtkWidget * pad;

  if (editor_toplevel)
    return NULL;

  editor_toplevel = gtk_frame_new (_("Colour Fade Settings"));
  gtk_container_set_border_width(GTK_CONTAINER(editor_toplevel), 3);

  table = gtk_table_new (4, 3, TRUE);
  gtk_widget_show (table);
  gtk_container_set_border_width(GTK_CONTAINER(table), 3);
  gtk_container_add (GTK_CONTAINER (editor_toplevel), table);

  label_box = gtk_hbox_new(TRUE, 0);
  gtk_widget_show(label_box);
  gtk_table_attach (GTK_TABLE (table), label_box, 0, 3, 0, 1,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (GTK_FILL), 0, 0);

  label = gtk_label_new (_("Min Colour"));
  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_widget_show (label);
  gtk_box_pack_start(GTK_BOX(label_box), label, TRUE, TRUE, 0);

  label = gtk_label_new (_("Middle Colour"));
  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
  gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
  gtk_widget_show (label);
  gtk_box_pack_start(GTK_BOX(label_box), label, TRUE, TRUE, 0);

  label = gtk_label_new (_("Max Colour"));
  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
  gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
  gtk_widget_show (label);
  gtk_box_pack_start(GTK_BOX(label_box), label, TRUE, TRUE, 0);

  ce_box = gtk_hbox_new(FALSE, 0);
  gtk_widget_show(ce_box);
  gtk_table_attach (GTK_TABLE (table), ce_box, 0, 3, 1, 2,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (GTK_FILL), 0, 0);

  min_edit = new ColourEditor(minimum.red, minimum.green, minimum.blue,
                              ce_change_callback, this);
  gtk_box_pack_start(GTK_BOX(ce_box), min_edit->getPreview(), FALSE, FALSE, 0);

  pad = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(pad), GTK_SHADOW_NONE);
  gtk_widget_show(pad);
  gtk_box_pack_start(GTK_BOX(ce_box), pad, TRUE, TRUE, 0);

  mid_edit = new ColourEditor(middle.red, middle.green, middle.blue,
                              ce_change_callback, this);
  gtk_box_pack_start(GTK_BOX(ce_box), mid_edit->getPreview(), FALSE, FALSE, 0);

  pad = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(pad), GTK_SHADOW_NONE);
  gtk_widget_show(pad);
  gtk_box_pack_start(GTK_BOX(ce_box), pad, TRUE, TRUE, 0);

  max_edit = new ColourEditor(maximum.red, maximum.green, maximum.blue,
                              ce_change_callback, this);
  gtk_box_pack_start(GTK_BOX(ce_box), max_edit->getPreview(), FALSE, FALSE, 0);

  preview = gtk_drawing_area_new();
  gtk_widget_show(preview);

  g_signal_connect_data(G_OBJECT(preview), "expose_event",
                              GTK_SIGNAL_FUNC(fade_preview_expose), this,
                              NULL, (GConnectFlags)0);
  g_signal_connect_data(G_OBJECT(preview), "configure_event",
                              GTK_SIGNAL_FUNC(fade_preview_conf), this,
                              NULL, (GConnectFlags)0);

  gtk_table_attach (GTK_TABLE (table), preview, 0, 3, 2, 3,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (GTK_FILL), 0, 0);

  three_choice = gtk_check_button_new_with_label(_("Use median shade"));
  gtk_widget_ref(three_choice);
  gtk_widget_show(three_choice);
  gtk_table_attach (GTK_TABLE (table), three_choice, 0, 1, 3, 4,
                    (GtkAttachOptions) (0),
                    (GtkAttachOptions) (0), 0, 0);
  if (use_three)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (three_choice), TRUE);
  else
    mid_edit->setSensitive(FALSE);

  // Order seems to be important with this statement :)
  g_signal_connect_data(G_OBJECT(three_choice), "toggled",
                                    GTK_SIGNAL_FUNC(fade_swap_three), this,
                                    NULL, (GConnectFlags)0);
  return editor_toplevel;
}

// Thanks to Mtf of Turf for these macros
#define TRI_SHADE_HIGH(min, max, level, max_level) \
  (min+(max-min)*(level-((max_level%2!=0)?1:0)-max_level/2)/(max_level/2))

#define TRI_SHADE_LOW(min, max, level, max_level) \
  (min+(max-min)*level/(max_level/2))

#define TWO_SHADE_FADE(min, max, level, max_level) \
  (min+(max-min)*level/max_level)

GdkColor * Fade::getShade(gboolean three, GdkColor * smin, GdkColor * smid,
                          GdkColor * smax, int level, int max_level) {

  // <= 1, we divide by 2 and then again, so 1 won't work!
  if (max_level <= 1) {
    if (level == 1)
      level = 2;
    max_level = 2;
  } else if (level <= 0)
    level = 0;
  else if (level > max_level)
    level = max_level;

  if ( three ) {
    if ( level > max_level/2) {
      shade.red   = TRI_SHADE_HIGH(smid->red,   smax->red,   level, max_level);
      shade.green = TRI_SHADE_HIGH(smid->green, smax->green, level, max_level);
      shade.blue  = TRI_SHADE_HIGH(smid->blue,  smax->blue,  level, max_level);
    } else {
      shade.red   = TRI_SHADE_LOW(smin->red,   smid->red,   level, max_level);
      shade.green = TRI_SHADE_LOW(smin->green, smid->green, level, max_level);
      shade.blue  = TRI_SHADE_LOW(smin->blue,  smid->blue,  level, max_level);
    }
  } else {
    shade.red   = TWO_SHADE_FADE(smin->red,   smax->red,    level, max_level);
    shade.green = TWO_SHADE_FADE(smin->green, smax->green,  level, max_level);
    shade.blue  = TWO_SHADE_FADE(smin->blue,  smax->blue,   level, max_level);
  }

  return &shade;
}

GdkColor * Fade::getShade(int level, int max_level) {

  getShade(use_three, &minimum, &middle, &maximum, level, max_level);

  return &shade;
}

void Fade::finalise_widgets() {
  editor_toplevel = NULL;
  preview = NULL;

  if (pixmap)
    gdk_pixmap_unref(pixmap);
  pixmap = NULL;
}

void Fade::copyColoursFromEditors(GdkColor * min, GdkColor * mid, GdkColor * max) {
  min->red    = min_edit->getRed();
  min->green  = min_edit->getGreen();
  min->blue   = min_edit->getBlue();

  mid->red    = mid_edit->getRed();
  mid->green  = mid_edit->getGreen();
  mid->blue   = mid_edit->getBlue();

  max->red    = max_edit->getRed();
  max->green  = max_edit->getGreen();
  max->blue   = max_edit->getBlue();
}

void Fade::onPrefsOk() {

  copyColoursFromEditors(&minimum, &middle, &maximum);

  use_three = (GTK_TOGGLE_BUTTON(three_choice)->active);

  finalise_widgets();
}

void Fade::onPrefsApply() {
  copyColoursFromEditors(&minimum, &middle, &maximum);

  use_three = (GTK_TOGGLE_BUTTON(three_choice)->active);
}

void Fade::onPrefsCancel() {
  finalise_widgets();
}

char * Fade::stringMinColour() {
  char buffer[50];

  sprintf(buffer, "%d,%d,%d", minimum.red, minimum.green, minimum.blue);

  return strdup(buffer);
}

char * Fade::stringMidColour() {
  char buffer[50];

  sprintf(buffer, "%d,%d,%d", middle.red, middle.green, middle.blue);

  return strdup(buffer);
}

char * Fade::stringMaxColour() {
  char buffer[50];

  sprintf(buffer, "%d,%d,%d", maximum.red, maximum.green, maximum.blue);

  return strdup(buffer);
}

char * Fade::stringUseThree() {
  char buffer[50];

  sprintf(buffer, "%d", use_three);

  return strdup(buffer);
}

gboolean fade_preview_expose(GtkWidget * widget, GdkEventExpose * event, gpointer data) {

  Fade * fade = (Fade *) data;

  if (!fade->preview)
    return FALSE;

  if (!fade->pixmap)
    fade_preview_conf(fade->preview, NULL, data);

  if (fade->update_preview) {
    fade->update_preview = FALSE;
    fade->updatePreview();
  }

  if (event)
    gdk_draw_pixmap(fade->preview->window,
                    fade->preview->style->fg_gc[GTK_WIDGET_STATE(widget)],
                    fade->pixmap,
                    event->area.x,
                    event->area.y,
                    event->area.x,
                    event->area.y,
                    event->area.width,
                    event->area.height);
  else
    gdk_draw_pixmap(fade->preview->window,
                fade->preview->style->fg_gc[GTK_WIDGET_STATE(fade->preview)],
                fade->pixmap,
                0, 0, 0, 0,
                fade->preview->allocation.width,
                fade->preview->allocation.height);

  return TRUE;
}

gboolean fade_preview_conf(GtkWidget * widget, GdkEventConfigure * event, gpointer data) {
  Fade * fade = (Fade *) data;

  if (!widget)
        return FALSE;

  if (fade->pixmap)
    gdk_pixmap_unref(fade->pixmap);

  fade->pixmap = gdk_pixmap_new(widget->window,
                                widget->allocation.width,
                                widget->allocation.height, -1);

  fade->update_preview = TRUE;

  return TRUE;
}

gboolean fade_swap_three(GtkWidget *widget, gpointer data) {
  Fade * fade = (Fade *) data;

  if (fade->preview != NULL) {
    fade->update_preview = TRUE;
    fade_preview_expose(NULL, NULL, data);
  }

  if (GTK_TOGGLE_BUTTON(widget)->active)
    fade->mid_edit->setSensitive(TRUE);
  else
    fade->mid_edit->setSensitive(FALSE);

  return TRUE;
}

void Fade::updatePreview() {
  int bottom = preview->allocation.height;
  int column = 0;
  int width = preview->allocation.width;

  GdkGC * gc = gdk_gc_new(preview->window);
  GdkColor * colour;
  GdkColor min_proto;
  GdkColor mid_proto;
  GdkColor max_proto;

  copyColoursFromEditors(&min_proto, &mid_proto, &max_proto);

  gdk_gc_copy(gc,preview->style->white_gc);

  gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0,
                     preview->allocation.width, preview->allocation.height);

  for (; column <= width; ++column) {
    colour = getShade((GTK_TOGGLE_BUTTON(three_choice)->active),
                      &min_proto, &mid_proto,
                      &max_proto, column, width);

    if (!gdk_colormap_alloc_color(gdk_colormap_get_system(), colour, FALSE, TRUE)) {
      debug(_("fade preview: couldn't allocate colour.\n"));
    }

    gdk_gc_set_foreground(gc, colour);
    gdk_gc_set_background(gc, colour);

    gdk_draw_line(pixmap, gc, column, 0, column, bottom);
  }

  gdk_gc_destroy(gc);
}

void ce_change_callback(ColourEditor *ce, gpointer data) {
  if (((Fade *)data)->preview != NULL) {
    ((Fade *)data)->update_preview = TRUE;
    fade_preview_expose(NULL, NULL, data);
  }
}

Generated by  Doxygen 1.6.0   Back to index