/********************************************************************** PIKA - Photo and Image Kooker Application Copyright (C) 1995 Spencer Kimball and Peter Mattis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "config.h" #include #include #include #include #include #include #include "fractal-explorer.h" #include "fractal-explorer-dialogs.h" #include "libpika/stdplugins-intl.h" #define ZOOM_UNDO_SIZE 100 static gint n_gradient_samples = 0; static gdouble *gradient_samples = NULL; static PikaGradient *gradient = NULL; static gboolean ready_now = FALSE; static gchar *tpath = NULL; static GtkWidget *cmap_preview; static GtkWidget *maindlg; static explorer_vals_t zooms[ZOOM_UNDO_SIZE]; static gint zoomindex = 0; static gint zoommax = 0; static gint oldxpos = -1; static gint oldypos = -1; static gdouble x_press = -1.0; static gdouble y_press = -1.0; static explorer_vals_t standardvals = { 0, -2.0, 2.0, -1.5, 1.5, 50.0, -0.75, -0.2, 0, 1.0, 1.0, 1.0, 1, 1, 0, 0, 0, 0, 1, 256, 0 }; /********************************************************************** FORWARD DECLARATIONS *********************************************************************/ static void update_preview (PikaProcedureConfig *config); static void load_file_chooser_response (GtkFileChooser *chooser, gint response_id, gpointer data); static void save_file_chooser_response (GtkFileChooser *chooser, gint response_id, gpointer data); static void create_load_file_chooser (GtkWidget *widget, GtkWidget *dialog); static void create_save_file_chooser (GtkWidget *widget, GtkWidget *dialog); static void cmap_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation, PikaProcedureConfig *config); /********************************************************************** CALLBACKS *********************************************************************/ static void update_preview (PikaProcedureConfig *config) { set_cmap_preview (config); dialog_update_preview (config); } static void dialog_redraw_callback (GtkWidget *widget, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; gint alwaysprev = wvals.alwayspreview; wvals.alwayspreview = TRUE; set_cmap_preview (config); dialog_update_preview (config); wvals.alwayspreview = alwaysprev; } static void dialog_undo_zoom_callback (GtkWidget *widget, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; if (zoomindex > 0) { g_object_get (config, "xmin", &wvals.xmin, "xmax", &wvals.xmax, "ymin", &wvals.ymin, "ymax", &wvals.ymax, NULL); zooms[zoomindex] = wvals; zoomindex--; wvals = zooms[zoomindex]; g_object_set (config, "xmin", wvals.xmin, "xmax", wvals.xmax, "ymin", wvals.ymin, "ymax", wvals.ymax, NULL); set_cmap_preview (config); dialog_update_preview (config); } } static void dialog_redo_zoom_callback (GtkWidget *widget, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; if (zoomindex < zoommax) { zoomindex++; wvals = zooms[zoomindex]; g_object_set (config, "xmin", wvals.xmin, "xmax", wvals.xmax, "ymin", wvals.ymin, "ymax", wvals.ymax, NULL); set_cmap_preview (config); dialog_update_preview (config); } } static void dialog_step_in_callback (GtkWidget *widget, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; gdouble xdifferenz; gdouble ydifferenz; gdouble xmin; gdouble xmax; gdouble ymin; gdouble ymax; g_object_get (config, "xmin", &xmin, "xmax", &xmax, "ymin", &ymin, "ymax", &ymax, NULL); if (zoomindex < ZOOM_UNDO_SIZE - 1) { g_object_get (config, "xmin", &wvals.xmin, "xmax", &wvals.xmax, "ymin", &wvals.ymin, "ymax", &wvals.ymax, NULL); zooms[zoomindex] = wvals; zoomindex++; } zoommax = zoomindex; xdifferenz = xmax - xmin; ydifferenz = ymax - ymin; xmin += 1.0 / 6.0 * xdifferenz; ymin += 1.0 / 6.0 * ydifferenz; xmax -= 1.0 / 6.0 * xdifferenz; ymax -= 1.0 / 6.0 * ydifferenz; wvals.xmin = xmin; wvals.xmax = xmax; wvals.ymin = ymin; wvals.ymax = ymax; zooms[zoomindex] = wvals; g_object_set (config, "xmin", xmin, "xmax", xmax, "ymin", ymin, "ymax", ymax, NULL); set_cmap_preview (config); dialog_update_preview (config); } static void dialog_step_out_callback (GtkWidget *widget, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; gdouble xdifferenz; gdouble ydifferenz; gdouble xmin; gdouble xmax; gdouble ymin; gdouble ymax; g_object_get (config, "xmin", &xmin, "xmax", &xmax, "ymin", &ymin, "ymax", &ymax, NULL); if (zoomindex < ZOOM_UNDO_SIZE - 1) { g_object_get (config, "xmin", &wvals.xmin, "xmax", &wvals.xmax, "ymin", &wvals.ymin, "ymax", &wvals.ymax, NULL); zooms[zoomindex] = wvals; zoomindex++; } zoommax = zoomindex; xdifferenz = xmax - xmin; ydifferenz = ymax - ymin; xmin -= 1.0 / 4.0 * xdifferenz; ymin -= 1.0 / 4.0 * ydifferenz; xmax += 1.0 / 4.0 * xdifferenz; ymax += 1.0 / 4.0 * ydifferenz; wvals.xmin = xmin; wvals.xmax = xmax; wvals.ymin = ymin; wvals.ymax = ymax; zooms[zoomindex] = wvals; g_object_set (config, "xmin", xmin, "xmax", xmax, "ymin", ymin, "ymax", ymax, NULL); set_cmap_preview (config); dialog_update_preview (config); } static void explorer_toggle_update (GtkWidget *widget, gpointer data) { pika_toggle_button_update (widget, data); set_cmap_preview (wvals.config); dialog_update_preview (wvals.config); } static void explorer_radio_update (GtkWidget *widget, gpointer data) { gboolean c_sensitive; gint fractal_type; fractal_type = pika_procedure_config_get_choice_id (wvals.config, "fractal-type"); switch (fractal_type) { case TYPE_MANDELBROT: case TYPE_SIERPINSKI: c_sensitive = FALSE; break; default: c_sensitive = TRUE; break; } pika_procedure_dialog_set_sensitive (PIKA_PROCEDURE_DIALOG (maindlg), "cx", c_sensitive, NULL, NULL, FALSE); pika_procedure_dialog_set_sensitive (PIKA_PROCEDURE_DIALOG (maindlg), "cy", c_sensitive, NULL, NULL, FALSE); set_cmap_preview (wvals.config); dialog_update_preview (wvals.config); } static void explorer_number_of_colors_callback (PikaProcedureConfig *config) { gint n_colors; g_object_get (config, "n-colors", &n_colors, NULL); g_free (gradient_samples); if (! gradient) gradient = pika_context_get_gradient (); pika_gradient_get_uniform_samples (gradient, n_colors, FALSE, &n_gradient_samples, &gradient_samples); set_cmap_preview (config); dialog_update_preview (config); } /* Same signature as all PikaResourceSelectButton */ static void explorer_gradient_select_callback (gpointer data, /* config */ PikaGradient *gradient, gboolean dialog_closing) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; gint n_colors; gint color_mode; g_object_get (config, "n-colors", &n_colors, "color-mode", &color_mode, NULL); g_free (gradient_samples); pika_gradient_get_uniform_samples (gradient, n_colors, FALSE, &n_gradient_samples, &gradient_samples); if (color_mode == 1) { set_cmap_preview (config); dialog_update_preview (config); } } static void preview_draw_crosshair (gint px, gint py) { gint x, y; guchar *p_ul; p_ul = wint.wimage + 3 * (preview_width * py + 0); for (x = 0; x < preview_width; x++) { p_ul[0] ^= 254; p_ul[1] ^= 254; p_ul[2] ^= 254; p_ul += 3; } p_ul = wint.wimage + 3 * (preview_width * 0 + px); for (y = 0; y < preview_height; y++) { p_ul[0] ^= 254; p_ul[1] ^= 254; p_ul[2] ^= 254; p_ul += 3 * preview_width; } } static void preview_redraw (void) { pika_preview_area_draw (PIKA_PREVIEW_AREA (wint.preview), 0, 0, preview_width, preview_height, PIKA_RGB_IMAGE, wint.wimage, preview_width * 3); gtk_widget_queue_draw (wint.preview); } static gboolean preview_button_press_event (GtkWidget *widget, GdkEventButton *event) { if (event->button == 1) { x_press = event->x; y_press = event->y; xbild = preview_width; ybild = preview_height; xdiff = (xmax - xmin) / xbild; ydiff = (ymax - ymin) / ybild; preview_draw_crosshair (x_press, y_press); preview_redraw (); } return TRUE; } static gboolean preview_motion_notify_event (GtkWidget *widget, GdkEventButton *event) { if (oldypos != -1) { preview_draw_crosshair (oldxpos, oldypos); } oldxpos = event->x; oldypos = event->y; if ((oldxpos >= 0.0) && (oldypos >= 0.0) && (oldxpos < preview_width) && (oldypos < preview_height)) { preview_draw_crosshair (oldxpos, oldypos); } else { oldypos = -1; oldxpos = -1; } preview_redraw (); return TRUE; } static gboolean preview_leave_notify_event (GtkWidget *widget, GdkEventButton *event) { if (oldypos != -1) { preview_draw_crosshair (oldxpos, oldypos); } oldxpos = -1; oldypos = -1; preview_redraw (); gdk_window_set_cursor (gtk_widget_get_window (maindlg), NULL); return TRUE; } static gboolean preview_enter_notify_event (GtkWidget *widget, GdkEventButton *event) { static GdkCursor *cursor = NULL; if (! cursor) { GdkDisplay *display = gtk_widget_get_display (maindlg); cursor = gdk_cursor_new_for_display (display, GDK_TCROSS); } gdk_window_set_cursor (gtk_widget_get_window (maindlg), cursor); return TRUE; } static gboolean preview_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; gdouble l_xmin; gdouble l_xmax; gdouble l_ymin; gdouble l_ymax; gdouble xmin; gdouble xmax; gdouble ymin; gdouble ymax; g_object_get (config, "xmin", &xmin, "xmax", &xmax, "ymin", &ymin, "ymax", &ymax, NULL); if (event->button == 1) { gdouble x_release, y_release; x_release = event->x; y_release = event->y; if ((x_press >= 0.0) && (y_press >= 0.0) && (x_release >= 0.0) && (y_release >= 0.0) && (x_press < preview_width) && (y_press < preview_height) && (x_release < preview_width) && (y_release < preview_height)) { l_xmin = (xmin + (xmax -xmin) * (x_press / preview_width)); l_xmax = (xmin + (xmax - xmin) * (x_release / preview_width)); l_ymin = (ymin + (ymax - ymin) * (y_press / preview_height)); l_ymax = (ymin + (ymax - ymin) * (y_release / preview_height)); if (zoomindex < ZOOM_UNDO_SIZE - 1) { wvals.xmin = l_xmin; wvals.xmax = l_xmax; wvals.ymin = l_ymin; wvals.ymax = l_ymax; zooms[zoomindex] = wvals; zoomindex++; } zoommax = zoomindex; g_object_set (config, "xmin", l_xmin, "xmax", l_xmax, "ymin", l_ymin, "ymax", l_ymax, NULL); dialog_update_preview (config); oldypos = oldxpos = -1; } } return TRUE; } /********************************************************************** FUNCTION: explorer_dialog *********************************************************************/ gint explorer_dialog (PikaProcedure *procedure, PikaProcedureConfig *config) { GtkWidget *dialog; GtkWidget *top_hbox; GtkWidget *left_vbox; GtkWidget *vbox; GtkWidget *bbox; GtkWidget *frame; GtkWidget *toggle; GtkWidget *hbox; GtkWidget *button; GtkWidget *gradient_button; gchar *path; PikaGradient *gradient; GtkListStore *store; gint n_colors; pika_ui_init (PLUG_IN_BINARY); path = pika_pikarc_query ("fractalexplorer-path"); if (path) { fractalexplorer_path = g_filename_from_utf8 (path, -1, NULL, NULL, NULL); g_free (path); } else { GFile *pikarc = pika_directory_file ("pikarc", NULL); gchar *full_path = pika_config_build_data_path ("fractalexplorer"); gchar *esc_path = g_strescape (full_path, NULL); g_free (full_path); g_message (_("No %s in pikarc:\n" "You need to add an entry like\n" "(%s \"%s\")\n" "to your %s file."), "fractalexplorer-path", "fractalexplorer-path", esc_path, pika_file_get_utf8_name (pikarc)); g_object_unref (pikarc); g_free (esc_path); } wint.wimage = g_new (guchar, preview_width * preview_height * 3); dialog = maindlg = pika_procedure_dialog_new (procedure, PIKA_PROCEDURE_CONFIG (config), _("Fractal Explorer")); top_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_widget_set_vexpand (top_hbox, FALSE); gtk_container_set_border_width (GTK_CONTAINER (top_hbox), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), top_hbox, FALSE, FALSE, 0); gtk_widget_show (top_hbox); left_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_widget_show (left_vbox); /* Preview */ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start (GTK_BOX (left_vbox), vbox, FALSE, FALSE, 0); gtk_widget_show (vbox); frame = gtk_frame_new (NULL); gtk_widget_set_halign (frame, GTK_ALIGN_START); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); wint.preview = pika_preview_area_new (); gtk_widget_set_size_request (wint.preview, preview_width, preview_height); gtk_container_add (GTK_CONTAINER (frame), wint.preview); g_signal_connect (wint.preview, "button-press-event", G_CALLBACK (preview_button_press_event), NULL); g_signal_connect (wint.preview, "button-release-event", G_CALLBACK (preview_button_release_event), config); g_signal_connect (wint.preview, "motion-notify-event", G_CALLBACK (preview_motion_notify_event), NULL); g_signal_connect (wint.preview, "leave-notify-event", G_CALLBACK (preview_leave_notify_event), NULL); g_signal_connect (wint.preview, "enter-notify-event", G_CALLBACK (preview_enter_notify_event), NULL); gtk_widget_set_events (wint.preview, (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK)); gtk_widget_show (wint.preview); toggle = gtk_check_button_new_with_mnemonic (_("Re_altime preview")); gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); g_signal_connect (toggle, "toggled", G_CALLBACK (explorer_toggle_update), &wvals.alwayspreview); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.alwayspreview); gtk_widget_show (toggle); pika_help_set_help_data (toggle, _("If enabled the preview will " "be redrawn automatically"), NULL); button = gtk_button_new_with_mnemonic (_("R_edraw preview")); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); g_signal_connect (button, "clicked", G_CALLBACK (dialog_redraw_callback), config); gtk_widget_show (button); /* Zoom Options */ frame = pika_frame_new (_("Zoom")); gtk_box_pack_start (GTK_BOX (left_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_widget_show (vbox); bbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_set_homogeneous (GTK_BOX (bbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); gtk_widget_show (bbox); button = gtk_button_new_with_mnemonic (_("Zoom _In")); gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0); gtk_widget_show (button); g_signal_connect (button, "clicked", G_CALLBACK (dialog_step_in_callback), config); button = gtk_button_new_with_mnemonic (_("Zoom _Out")); gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0); gtk_widget_show (button); g_signal_connect (button, "clicked", G_CALLBACK (dialog_step_out_callback), config); bbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_set_homogeneous (GTK_BOX (bbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); gtk_widget_show (bbox); button = gtk_button_new_with_mnemonic (_("_Undo")); gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0); gtk_widget_show (button); pika_help_set_help_data (button, _("Undo last zoom change"), NULL); g_signal_connect (button, "clicked", G_CALLBACK (dialog_undo_zoom_callback), config); button = gtk_button_new_with_mnemonic (_("_Redo")); gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0); gtk_widget_show (button); pika_help_set_help_data (button, _("Redo last zoom change"), NULL); g_signal_connect (button, "clicked", G_CALLBACK (dialog_redo_zoom_callback), config); /* Create notebook */ pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "parameter-tab", _("_Parameters"), FALSE, TRUE); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "color-tab", _("_Colors"), FALSE, TRUE); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "fractal-tab", _("_Fractals"), FALSE, TRUE); /* "Parameters" page */ pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "xmin", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "xmax", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "ymin", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "ymax", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "iter", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "cx", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "cy", 1.0); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "parameter-input-label", _("Fractal Parameters"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "parameter-input-box", "xmin", "xmax", "ymin", "ymax", "iter", "cx", "cy", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "parameter-input-frame", "parameter-input-label", FALSE, "parameter-input-box"); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "parameter-type-label", _("Fractal Type"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "parameter-type-box", "fractal-type", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "parameter-type-frame", "parameter-type-label", FALSE, "parameter-type-box"); vbox = pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "parameter-box", "parameter-input-frame", "parameter-type-frame", NULL); bbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_widget_set_margin_top (bbox, 12); gtk_box_set_homogeneous (GTK_BOX (bbox), TRUE); gtk_box_pack_start (GTK_BOX (vbox), bbox, TRUE, TRUE, 2); gtk_box_reorder_child (GTK_BOX (vbox), bbox, 1); gtk_widget_set_visible (bbox, TRUE); button = gtk_button_new_with_mnemonic (_("_Open")); gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0); g_signal_connect (button, "clicked", G_CALLBACK (create_load_file_chooser), dialog); gtk_widget_set_visible (button, TRUE); pika_help_set_help_data (button, _("Load a fractal from file"), NULL); button = gtk_button_new_with_mnemonic (_("_Save")); gtk_box_pack_start (GTK_BOX (bbox), button, TRUE, TRUE, 0); g_signal_connect (button, "clicked", G_CALLBACK (create_save_file_chooser), dialog); gtk_widget_set_visible (button, TRUE); pika_help_set_help_data (button, _("Save active fractal to file"), NULL); g_signal_connect (config, "notify::xmin", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::xmax", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::ymin", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::ymax", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::iter", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::cx", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::cy", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::fractal-type", G_CALLBACK (explorer_radio_update), config); explorer_radio_update (NULL, NULL); /* Colors Page */ pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "n-colors", 1.0); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "num-colors-label", _("Number of Colors"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "num-colors-box", "n-colors", "use-loglog-smoothing", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "num-colors-frame", "num-colors-label", FALSE, "num-colors-box"); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "red-stretch", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "green-stretch", 1.0); pika_procedure_dialog_get_scale_entry (PIKA_PROCEDURE_DIALOG (dialog), "blue-stretch", 1.0); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "color-density-label", _("Color Density"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "color-density-box", "red-stretch", "green-stretch", "blue-stretch", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "color-density-frame", "color-density-label", FALSE, "color-density-box"); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "color-function-label", _("Color Function"), FALSE, FALSE); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "red-function-label", _("Red"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "red-function-box", "red-mode", "red-invert", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "red-function-frame", "red-function-label", FALSE, "red-function-box"); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "green-function-label", _("Green"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "green-function-box", "green-mode", "green-invert", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "green-function-frame", "green-function-label", FALSE, "green-function-box"); pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "blue-function-label", _("Blue"), FALSE, FALSE); pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "blue-function-box", "blue-mode", "blue-invert", NULL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "blue-function-frame", "blue-function-label", FALSE, "blue-function-box"); hbox = pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "function-hbox", "red-function-frame", "green-function-frame", "blue-function-frame", NULL); gtk_orientable_set_orientation (GTK_ORIENTABLE (hbox), GTK_ORIENTATION_HORIZONTAL); pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog), "color-function-frame", "color-function-label", FALSE, "function-hbox"); store = pika_int_store_new (_("As specified above"), 0, _("Apply active gradient to final image"), 1, NULL); pika_procedure_dialog_get_int_radio (PIKA_PROCEDURE_DIALOG (dialog), "color-mode", PIKA_INT_STORE (store)); hbox = pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "color-mode-hbox", "color-mode", NULL); gtk_orientable_set_orientation (GTK_ORIENTABLE (hbox), GTK_ORIENTATION_HORIZONTAL); g_object_get (config, "n-colors", &n_colors, NULL); gradient = pika_context_get_gradient (); pika_gradient_get_uniform_samples (gradient, n_colors, FALSE, &n_gradient_samples, &gradient_samples); gradient_button = pika_gradient_chooser_new (_("FractalExplorer Gradient"), NULL, PIKA_RESOURCE (gradient)); g_signal_connect (gradient_button, "resource-set", G_CALLBACK (explorer_gradient_select_callback), config); gtk_box_pack_start (GTK_BOX (hbox), gradient_button, TRUE, TRUE, 0); gtk_widget_set_visible (gradient_button, TRUE); vbox = pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "color-box", "num-colors-frame", "color-density-frame", "color-function-frame", "color-mode-hbox", NULL); cmap_preview = pika_preview_area_new (); gtk_widget_set_halign (cmap_preview, GTK_ALIGN_CENTER); gtk_widget_set_valign (cmap_preview, GTK_ALIGN_CENTER); gtk_widget_set_size_request (cmap_preview, 32, 32); gtk_box_pack_start (GTK_BOX (vbox), cmap_preview, TRUE, TRUE, 0); g_signal_connect (cmap_preview, "size-allocate", G_CALLBACK (cmap_preview_size_allocate), config); gtk_widget_set_visible (cmap_preview, TRUE); g_signal_connect (config, "notify::n-colors", G_CALLBACK (explorer_number_of_colors_callback), config); g_signal_connect (config, "notify::use-loglog-smoothing", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::red-stretch", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::blue-stretch", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::green-stretch", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::red-mode", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::green-mode", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::blue-mode", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::red-invert", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::green-invert", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::blue-invert", G_CALLBACK (update_preview), config); g_signal_connect (config, "notify::color-mode", G_CALLBACK (update_preview), config); /* Fractal Presets */ pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog), "preset-label", _("Presets"), FALSE, FALSE); vbox = pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "fractal-box", "preset-label", NULL); frame = add_objects_list (); gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 2); gtk_widget_set_visible (frame, TRUE); /* Creating layout */ pika_procedure_dialog_fill_notebook (PIKA_PROCEDURE_DIALOG (dialog), "main-notebook", "parameter-tab", "parameter-box", "color-tab", "color-box", "fractal-tab", "fractal-box", NULL); top_hbox = pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog), "top-hbox", "main-notebook", NULL); gtk_orientable_set_orientation (GTK_ORIENTABLE (top_hbox), GTK_ORIENTATION_HORIZONTAL); gtk_widget_set_vexpand (top_hbox, FALSE); gtk_container_set_border_width (GTK_CONTAINER (top_hbox), 12); gtk_box_pack_start (GTK_BOX (top_hbox), left_vbox, FALSE, FALSE, 0); gtk_box_reorder_child (GTK_BOX (top_hbox), left_vbox, 0); pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), "top-hbox", NULL); gtk_widget_show (dialog); ready_now = TRUE; set_cmap_preview (config); dialog_update_preview (config); wint.run = pika_procedure_dialog_run (PIKA_PROCEDURE_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (wint.wimage); return wint.run; } /********************************************************************** FUNCTION: dialog_update_preview *********************************************************************/ void dialog_update_preview (PikaProcedureConfig *config) { gint ycoord; guchar *p_ul; if (NULL == wint.preview) return; if (ready_now && wvals.alwayspreview) { g_object_get (config, "xmin", &xmin, "xmax", &xmax, "ymin", &ymin, "ymax", &ymax, NULL); xbild = preview_width; ybild = preview_height; xdiff = (xmax - xmin) / xbild; ydiff = (ymax - ymin) / ybild; p_ul = wint.wimage; for (ycoord = 0; ycoord < preview_height; ycoord++) { explorer_render_row (NULL, p_ul, ycoord, preview_width, 3, config); p_ul += preview_width * 3; } preview_redraw (); } } /********************************************************************** FUNCTION: cmap_preview_size_allocate() *********************************************************************/ static void cmap_preview_size_allocate (GtkWidget *widget, GtkAllocation *allocation, PikaProcedureConfig *config) { gint i; gint x; gint y; gint j; gint n_colors; guchar *b; PikaPreviewArea *preview = PIKA_PREVIEW_AREA (widget); g_object_get (config, "n-colors", &n_colors, NULL); b = g_new (guchar, allocation->width * allocation->height * 3); for (y = 0; y < allocation->height; y++) { for (x = 0; x < allocation->width; x++) { i = x + (y / 4) * allocation->width; if (i > n_colors) { for (j = 0; j < 3; j++) b[(y*allocation->width + x) * 3 + j] = 0; } else { b[(y*allocation->width + x) * 3] = colormap[i].r; b[(y*allocation->width + x) * 3 + 1] = colormap[i].g; b[(y*allocation->width + x) * 3 + 2] = colormap[i].b; } } } pika_preview_area_draw (preview, 0, 0, allocation->width, allocation->height, PIKA_RGB_IMAGE, b, allocation->width*3); gtk_widget_queue_draw (cmap_preview); g_free (b); } /********************************************************************** FUNCTION: set_cmap_preview() *********************************************************************/ void set_cmap_preview (PikaProcedureConfig *config) { gint xsize; gint ysize; gint n_colors; g_object_get (config, "n-colors", &n_colors, NULL); if (NULL == cmap_preview) return; make_color_map (config); for (ysize = 1; ysize * ysize * ysize < n_colors; ysize++) /**/; xsize = n_colors / ysize; while (xsize * ysize < n_colors) xsize++; gtk_widget_set_size_request (cmap_preview, xsize, ysize * 4); } /********************************************************************** FUNCTION: make_color_map() *********************************************************************/ void make_color_map (PikaProcedureConfig *config) { gint i; gint r; gint gr; gint bl; gdouble redstretch; gdouble greenstretch; gdouble bluestretch; gdouble pi = atan (1) * 4; gint n_colors; gint color_mode; gint red_mode; gint green_mode; gint blue_mode; gboolean red_invert; gboolean green_invert; gboolean blue_invert; g_object_get (config, "n-colors", &n_colors, "red-stretch", &redstretch, "green-stretch", &greenstretch, "blue-stretch", &bluestretch, "color-mode", &color_mode, "red-invert", &red_invert, "green-invert", &green_invert, "blue-invert", &blue_invert, NULL); red_mode = pika_procedure_config_get_choice_id (config, "red-mode"); green_mode = pika_procedure_config_get_choice_id (config, "green-mode"); blue_mode = pika_procedure_config_get_choice_id (config, "blue-mode"); /* get gradient samples if they don't exist -- fixes gradient color * mode for noninteractive use (bug #103470). */ if (gradient_samples == NULL) { PikaGradient *gradient = pika_context_get_gradient (); pika_gradient_get_uniform_samples (gradient, n_colors, FALSE, &n_gradient_samples, &gradient_samples); } redstretch *= 127.5; greenstretch *= 127.5; bluestretch *= 127.5; for (i = 0; i < n_colors; i++) if (color_mode == 1) { colormap[i].r = (guchar)(gradient_samples[i * 4] * 255.9); colormap[i].g = (guchar)(gradient_samples[i * 4 + 1] * 255.9); colormap[i].b = (guchar)(gradient_samples[i * 4 + 2] * 255.9); } else { double x = (i*2.0) / n_colors; r = gr = bl = 0; switch (red_mode) { case SINUS: r = (int) redstretch *(1.0 + sin((x - 1) * pi)); break; case COSINUS: r = (int) redstretch *(1.0 + cos((x - 1) * pi)); break; case NONE: r = (int)(redstretch *(x)); break; default: break; } switch (green_mode) { case SINUS: gr = (int) greenstretch *(1.0 + sin((x - 1) * pi)); break; case COSINUS: gr = (int) greenstretch *(1.0 + cos((x - 1) * pi)); break; case NONE: gr = (int)(greenstretch *(x)); break; default: break; } switch (blue_mode) { case SINUS: bl = (int) bluestretch * (1.0 + sin ((x - 1) * pi)); break; case COSINUS: bl = (int) bluestretch * (1.0 + cos ((x - 1) * pi)); break; case NONE: bl = (int) (bluestretch * x); break; default: break; } r = MIN (r, 255); gr = MIN (gr, 255); bl = MIN (bl, 255); if (red_invert) r = 255 - r; if (green_invert) gr = 255 - gr; if (green_invert) bl = 255 - bl; colormap[i].r = r; colormap[i].g = gr; colormap[i].b = bl; } } /********************************************************************** FUNCTION: save_options *********************************************************************/ static void save_options (FILE * fp) { gchar buf[64]; gint fractal_type; gint red_mode; gint green_mode; gint blue_mode; gint xmin; gint xmax; gint ymin; gint ymax; gint iter; gint cx; gint cy; gdouble red_stretch; gdouble green_stretch; gdouble blue_stretch; gboolean red_invert; gboolean green_invert; gboolean blue_invert; gint color_mode; g_object_get (wvals.config, "xmin", &xmin, "xmax", &xmax, "ymin", &ymin, "ymax", &ymax, "iter", &iter, "cx", &cx, "cy", &cy, "red-stretch", &red_stretch, "green-stretch", &green_stretch, "blue-stretch", &blue_stretch, "color-mode", &color_mode, "red_invert", &red_invert, "green_invert", &green_invert, "blue_invert", &blue_invert, NULL); fractal_type = pika_procedure_config_get_choice_id (wvals.config, "fractal-type"); red_mode = pika_procedure_config_get_choice_id (wvals.config, "red-mode"); green_mode = pika_procedure_config_get_choice_id (wvals.config, "green-mode"); blue_mode = pika_procedure_config_get_choice_id (wvals.config, "blue-mode"); /* Save options */ fprintf (fp, "fractaltype: %i\n", fractal_type); g_ascii_dtostr (buf, sizeof (buf), xmin); fprintf (fp, "xmin: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), xmax); fprintf (fp, "xmax: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), ymin); fprintf (fp, "ymin: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), ymax); fprintf (fp, "ymax: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), iter); fprintf (fp, "iter: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), cx); fprintf (fp, "cx: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), cy); fprintf (fp, "cy: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), red_stretch * 128.0); fprintf (fp, "redstretch: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), green_stretch * 128.0); fprintf (fp, "greenstretch: %s\n", buf); g_ascii_dtostr (buf, sizeof (buf), blue_stretch * 128.0); fprintf (fp, "bluestretch: %s\n", buf); fprintf (fp, "redmode: %i\n", red_mode); fprintf (fp, "greenmode: %i\n", green_mode); fprintf (fp, "bluemode: %i\n", blue_mode); fprintf (fp, "redinvert: %i\n", red_invert); fprintf (fp, "greeninvert: %i\n", green_invert); fprintf (fp, "blueinvert: %i\n", blue_invert); fprintf (fp, "colormode: %i\n", color_mode); fputs ("#**********************************************************************\n", fp); fprintf(fp, "\n"); fputs ("#**********************************************************************\n", fp); } static void save_callback (void) { FILE *fp; const gchar *savename = filename; fp = g_fopen (savename, "wt+"); if (!fp) { g_message (_("Could not open '%s' for writing: %s"), pika_filename_to_utf8 (savename), g_strerror (errno)); return; } /* Write header out */ fputs (FRACTAL_HEADER, fp); fputs ("#**********************************************************************\n", fp); fputs ("# This is a data file for the Fractal Explorer plug-in for PIKA *\n", fp); fputs ("#**********************************************************************\n", fp); save_options (fp); if (ferror (fp)) g_message (_("Could not write '%s': %s"), pika_filename_to_utf8 (savename), g_strerror (ferror (fp))); fclose (fp); } static void save_file_chooser_response (GtkFileChooser *chooser, gint response_id, gpointer data) { if (response_id == GTK_RESPONSE_OK) { filename = gtk_file_chooser_get_filename (chooser); save_callback (); } gtk_widget_destroy (GTK_WIDGET (chooser)); } static void file_chooser_set_default_folder (GtkFileChooser *chooser) { GList *path_list; gchar *dir; if (! fractalexplorer_path) return; path_list = pika_path_parse (fractalexplorer_path, 256, FALSE, NULL); dir = pika_path_get_user_writable_dir (path_list); if (! dir) dir = g_strdup (pika_directory ()); gtk_file_chooser_set_current_folder (chooser, dir); g_free (dir); pika_path_free (path_list); } static void load_file_chooser_response (GtkFileChooser *chooser, gint response_id, gpointer data) { PikaProcedureConfig *config = (PikaProcedureConfig *) data; if (response_id == GTK_RESPONSE_OK) { filename = gtk_file_chooser_get_filename (chooser); if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { explorer_load (); } gtk_widget_show (maindlg); set_cmap_preview (config); dialog_update_preview (config); } gtk_widget_destroy (GTK_WIDGET (chooser)); } static void create_load_file_chooser (GtkWidget *widget, GtkWidget *dialog) { static GtkWidget *window = NULL; PikaProcedureConfig *config; g_object_get (PIKA_PROCEDURE_DIALOG (dialog), "config", &config, NULL); if (!window) { window = gtk_file_chooser_dialog_new (_("Load Fractal Parameters"), GTK_WINDOW (dialog), GTK_FILE_CHOOSER_ACTION_OPEN, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_Open"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK); pika_dialog_set_alternative_button_order (GTK_DIALOG (window), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); file_chooser_set_default_folder (GTK_FILE_CHOOSER (window)); g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); g_signal_connect (window, "response", G_CALLBACK (load_file_chooser_response), config); } gtk_window_present (GTK_WINDOW (window)); } static void create_save_file_chooser (GtkWidget *widget, GtkWidget *dialog) { static GtkWidget *window = NULL; if (! window) { window = gtk_file_chooser_dialog_new (_("Save Fractal Parameters"), GTK_WINDOW (dialog), GTK_FILE_CHOOSER_ACTION_SAVE, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_Save"), GTK_RESPONSE_OK, NULL); pika_dialog_set_alternative_button_order (GTK_DIALOG (window), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_OK); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (window), TRUE); g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); g_signal_connect (window, "response", G_CALLBACK (save_file_chooser_response), window); } if (tpath) { gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (window), tpath); } else { file_chooser_set_default_folder (GTK_FILE_CHOOSER (window)); } gtk_window_present (GTK_WINDOW (window)); } gchar* get_line (gchar *buf, gint s, FILE *from, gint init) { gint slen; gchar *ret; if (init) line_no = 1; else line_no++; do { ret = fgets (buf, s, from); } while (!ferror (from) && buf[0] == '#'); slen = strlen (buf); /* The last newline is a pain */ if (slen > 0) buf[slen - 1] = '\0'; if (ferror (from)) { g_warning ("Error reading file"); return NULL; } return ret; } gint load_options (fractalexplorerOBJ *xxx, FILE *fp) { gchar load_buf[MAX_LOAD_LINE]; gchar str_buf[MAX_LOAD_LINE]; gchar opt_buf[MAX_LOAD_LINE]; /* default values */ xxx->opts = standardvals; xxx->opts.gradinvert = FALSE; get_line (load_buf, MAX_LOAD_LINE, fp, 0); while (!feof (fp) && strcmp (load_buf, "")) { /* Get option name */ sscanf (load_buf, "%255s %255s", str_buf, opt_buf); if (!strcmp (str_buf, "fractaltype:")) { gint sp = 0; sp = atoi (opt_buf); if (sp < 0) return -1; xxx->opts.fractaltype = sp; } else if (!strcmp (str_buf, "xmin:")) { xxx->opts.xmin = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp (str_buf, "xmax:")) { xxx->opts.xmax = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp(str_buf, "ymin:")) { xxx->opts.ymin = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp (str_buf, "ymax:")) { xxx->opts.ymax = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp(str_buf, "redstretch:")) { gdouble sp = g_ascii_strtod (opt_buf, NULL); xxx->opts.redstretch = sp / 128.0; } else if (!strcmp(str_buf, "greenstretch:")) { gdouble sp = g_ascii_strtod (opt_buf, NULL); xxx->opts.greenstretch = sp / 128.0; } else if (!strcmp (str_buf, "bluestretch:")) { gdouble sp = g_ascii_strtod (opt_buf, NULL); xxx->opts.bluestretch = sp / 128.0; } else if (!strcmp (str_buf, "iter:")) { xxx->opts.iter = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp(str_buf, "cx:")) { xxx->opts.cx = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp (str_buf, "cy:")) { xxx->opts.cy = g_ascii_strtod (opt_buf, NULL); } else if (!strcmp(str_buf, "redmode:")) { xxx->opts.redmode = atoi (opt_buf); } else if (!strcmp(str_buf, "greenmode:")) { xxx->opts.greenmode = atoi (opt_buf); } else if (!strcmp(str_buf, "bluemode:")) { xxx->opts.bluemode = atoi (opt_buf); } else if (!strcmp (str_buf, "redinvert:")) { xxx->opts.redinvert = atoi (opt_buf); } else if (!strcmp (str_buf, "greeninvert:")) { xxx->opts.greeninvert = atoi (opt_buf); } else if (!strcmp(str_buf, "blueinvert:")) { xxx->opts.blueinvert = atoi (opt_buf); } else if (!strcmp (str_buf, "colormode:")) { xxx->opts.colormode = atoi (opt_buf); } get_line (load_buf, MAX_LOAD_LINE, fp, 0); } return 0; } void explorer_load (void) { FILE *fp; gchar load_buf[MAX_LOAD_LINE]; g_assert (filename != NULL); fp = g_fopen (filename, "rt"); if (!fp) { g_message (_("Could not open '%s' for reading: %s"), pika_filename_to_utf8 (filename), g_strerror (errno)); return; } get_line (load_buf, MAX_LOAD_LINE, fp, 1); if (strncmp (FRACTAL_HEADER, load_buf, strlen (load_buf))) { g_message (_("'%s' is not a FractalExplorer file"), pika_filename_to_utf8 (filename)); fclose (fp); return; } if (load_options (current_obj, fp)) { g_message (_("'%s' is corrupt. Line %d Option section incorrect"), pika_filename_to_utf8 (filename), line_no); fclose (fp); return; } g_object_set (wvals.config, "xmin", current_obj->opts.xmin, "xmax", current_obj->opts.xmax, "ymin", current_obj->opts.ymin, "ymax", current_obj->opts.ymax, "iter", current_obj->opts.iter, "cx", current_obj->opts.cx, "cy", current_obj->opts.cy, "red-stretch", current_obj->opts.redstretch, "green-stretch", current_obj->opts.greenstretch, "blue-stretch", current_obj->opts.bluestretch, "color-mode", current_obj->opts.colormode, "red-invert", current_obj->opts.redinvert, "green-invert", current_obj->opts.greeninvert, "blue-invert", current_obj->opts.blueinvert, NULL); switch (current_obj->opts.fractaltype) { case 0: g_object_set (wvals.config, "fractal-type", "mandelbrot", NULL); break; case 1: g_object_set (wvals.config, "fractal-type", "julia", NULL); break; case 2: g_object_set (wvals.config, "fractal-type", "barnsley-1", NULL); break; case 3: g_object_set (wvals.config, "fractal-type", "barnsley-2", NULL); break; case 4: g_object_set (wvals.config, "fractal-type", "barnsley-3", NULL); break; case 5: g_object_set (wvals.config, "fractal-type", "spider", NULL); break; case 6: g_object_set (wvals.config, "fractal-type", "man-o-war", NULL); break; case 7: g_object_set (wvals.config, "fractal-type", "lambda", NULL); break; case 8: g_object_set (wvals.config, "fractal-type", "sierpinski", NULL); break; default: break; } switch (current_obj->opts.redmode) { case 0: g_object_set (wvals.config, "red-mode", "red-sin", NULL); break; case 1: g_object_set (wvals.config, "red-mode", "red-cos", NULL); break; case 2: g_object_set (wvals.config, "red-mode", "red-none", NULL); break; default: break; } switch (current_obj->opts.greenmode) { case 0: g_object_set (wvals.config, "green-mode", "green-sin", NULL); break; case 1: g_object_set (wvals.config, "green-mode", "green-cos", NULL); break; case 2: g_object_set (wvals.config, "green-mode", "green-none", NULL); break; default: break; } switch (current_obj->opts.bluemode) { case 0: g_object_set (wvals.config, "blue-mode", "blue-sin", NULL); break; case 1: g_object_set (wvals.config, "blue-mode", "blue-cos", NULL); break; case 2: g_object_set (wvals.config, "blue-mode", "blue-none", NULL); break; default: break; } fclose (fp); }