Code

Cleanup of device internal handling and API.
[inkscape.git] / src / ui / dialog / tracedialog.cpp
index fad7cb315e61dacabbbf48847b3760985af4a927..f6dd6cb2826c0fe58d67a4b6fc2d8418b57ada23 100644 (file)
@@ -1,12 +1,12 @@
-/*
- * A simple dialog for setting the parameters for autotracing a
- * bitmap <image> into an svg <path>
- *
- * Authors:
- *   Bob Jamison
+/** @file
+ * @brief Bitmap tracing settings dialog - implementation
+ */
+/* Authors:
+ *   Bob Jamison <rjamison@titan.com>
+ *   Stéphane Gimenez <dev@gim.name>
  *   Other dudes from The Inkscape Organization
  *
- * Copyright (C) 2004, 2005 Authors
+ * Copyright (C) 2004-2006 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -22,7 +22,7 @@
 #include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
 #include <glibmm/i18n.h>
 
-
+#include "desktop.h"
 
 #include "tracedialog.h"
 #include "trace/potrace/inkscape-potrace.h"
@@ -79,87 +79,125 @@ class TraceDialogImpl : public TraceDialog
      */
     void abort();
 
-    void potracePreviewCallback();
+    void previewCallback();
 
-    Gtk::Notebook   notebook;
-    Gtk::Tooltips   tips;
+    //############ General items
 
-    //########## Potrace items
-    Gtk::VBox             potraceBox;
-    Gtk::RadioButtonGroup potraceGroup;
-    Gtk::CheckButton      potraceInvertButton;
-    Gtk::HBox             potraceInvertBox;
-    Gtk::Button           *potraceOkButton;
-    Gtk::Button           *potraceCancelButton;
+    Gtk::HBox             mainHBox;
+    Gtk::Tooltips         tips;
 
-    //brightness
-    Gtk::Frame            potraceBrightnessFrame;
-    Gtk::VBox             potraceBrightnessVBox;
-    Gtk::HBox             potraceBrightnessBox;
-    Gtk::RadioButton      potraceBrightnessRadioButton;
-    Gtk::Label            potraceBrightnessSpinnerLabel;
-    Gtk::SpinButton       potraceBrightnessSpinner;
+    Gtk::Button           *mainOkButton;
+    Gtk::Button           *mainCancelButton;
 
+    //######## Left pannel
 
-    //edge detection
-    Gtk::Frame            potraceCannyFrame;
-    Gtk::HBox             potraceCannyBox;
-    Gtk::VBox             potraceCannyVBox;
-    Gtk::RadioButton      potraceCannyRadioButton;
-    //Gtk::HSeparator     potraceCannySeparator;
-    //Gtk::Label          potraceCannyLoSpinnerLabel;
-    //Gtk::SpinButton     potraceCannyLoSpinner;
-    Gtk::Label            potraceCannyHiSpinnerLabel;
-    Gtk::SpinButton       potraceCannyHiSpinner;
+    Gtk::VBox             leftVBox;
 
-    //quantization
-    Gtk::Frame            potraceQuantFrame;
-    Gtk::HBox             potraceQuantBox;
-    Gtk::VBox             potraceQuantVBox;
-    Gtk::RadioButton      potraceQuantRadioButton;
-    Gtk::Label            potraceQuantNrColorLabel;
-    Gtk::SpinButton       potraceQuantNrColorSpinner;
+    //#### Notebook
 
-    //multiple path scanning
-    Gtk::Frame            potraceMultiScanFrame;
-    Gtk::VBox             potraceMultiScanVBox;
+    Gtk::Notebook         notebook;
 
-    Gtk::HBox             potraceMultiScanHBox1;
-    Gtk::RadioButton      potraceMultiScanBrightnessRadioButton;
-    Gtk::SpinButton       potraceMultiScanNrColorSpinner;
+    //## Modes
 
-    Gtk::HBox             potraceMultiScanHBox2;
-    Gtk::RadioButton      potraceMultiScanColorRadioButton;
-    Gtk::CheckButton      potraceMultiScanStackButton;
+    Gtk::VBox             modePageBox;
+    Gtk::RadioButtonGroup modeGroup;
 
-    Gtk::HBox             potraceMultiScanHBox3;
-    Gtk::RadioButton      potraceMultiScanMonoRadioButton;
-    Gtk::Label            potraceMultiScanNrColorLabel;
+    //# Single scan mode
+    //brightness
+    Gtk::Frame            modeBrightnessFrame;
+    Gtk::VBox             modeBrightnessVBox;
+    Gtk::HBox             modeBrightnessBox;
+    Gtk::RadioButton      modeBrightnessRadioButton;
+    Gtk::Label            modeBrightnessSpinnerLabel;
+    Gtk::SpinButton       modeBrightnessSpinner;
+    //edge detection
+    Gtk::Frame            modeCannyFrame;
+    Gtk::HBox             modeCannyBox;
+    Gtk::VBox             modeCannyVBox;
+    Gtk::RadioButton      modeCannyRadioButton;
+    //Gtk::HSeparator     modeCannySeparator;
+    //Gtk::Label          modeCannyLoSpinnerLabel;
+    //Gtk::SpinButton     modeCannyLoSpinner;
+    Gtk::Label            modeCannyHiSpinnerLabel;
+    Gtk::SpinButton       modeCannyHiSpinner;
+    //quantization
+    Gtk::Frame            modeQuantFrame;
+    Gtk::HBox             modeQuantBox;
+    Gtk::VBox             modeQuantVBox;
+    Gtk::RadioButton      modeQuantRadioButton;
+    Gtk::Label            modeQuantNrColorLabel;
+    Gtk::SpinButton       modeQuantNrColorSpinner;
+    //params
+    Gtk::CheckButton      modeInvertButton;
+    Gtk::HBox             modeInvertBox;
+
+    //# Multiple path scanning mode
+    Gtk::Frame            modeMultiScanFrame;
+    Gtk::VBox             modeMultiScanVBox;
+    //brightness
+    Gtk::HBox             modeMultiScanHBox1;
+    Gtk::RadioButton      modeMultiScanBrightnessRadioButton;
+    Gtk::SpinButton       modeMultiScanNrColorSpinner;
+    //colors
+    Gtk::HBox             modeMultiScanHBox2;
+    Gtk::RadioButton      modeMultiScanColorRadioButton;
+    //grays
+    Gtk::HBox             modeMultiScanHBox3;
+    Gtk::RadioButton      modeMultiScanMonoRadioButton;
+    Gtk::Label            modeMultiScanNrColorLabel;
+    //params
+    Gtk::HBox             modeMultiScanHBox4;
+    Gtk::CheckButton      modeMultiScanStackButton;
+    Gtk::CheckButton      modeMultiScanSmoothButton;
+    Gtk::CheckButton      modeMultiScanBackgroundButton;
+
+    //## Options
+
+    Gtk::VBox             optionsPageBox;
+
+    // potrace parameters
+
+    Gtk::Frame            optionsFrame;
+    Gtk::VBox             optionsVBox;
+    Gtk::HBox             optionsSpecklesBox;
+    Gtk::CheckButton      optionsSpecklesButton;
+    Gtk::Label            optionsSpecklesSizeLabel;
+    Gtk::SpinButton       optionsSpecklesSizeSpinner;
+    Gtk::HBox             optionsCornersBox;
+    Gtk::CheckButton      optionsCornersButton;
+    Gtk::Label            optionsCornersThresholdLabel;
+    Gtk::SpinButton       optionsCornersThresholdSpinner;
+    Gtk::HBox             optionsOptimBox;
+    Gtk::CheckButton      optionsOptimButton;
+    Gtk::Label            optionsOptimToleranceLabel;
+    Gtk::SpinButton       optionsOptimToleranceSpinner;
+
+
+    //#### Credits
 
-    Gtk::CheckButton      potraceMultiScanSmoothButton;
+    Gtk::VBox             potraceCreditsVBox;
+    Gtk::Label            potraceCreditsLabel;
 
+    //######## Right pannel
 
-    //preview
-    Gtk::Frame            potracePreviewFrame;
-    Gtk::HBox             potracePreviewBox;
-    Gtk::Button           potracePreviewButton;
-    Gtk::Image            potracePreviewImage;
+    Gtk::VBox             rightVBox;
 
-    //credits
-    Gtk::Frame            potraceCreditsFrame;
-    Gtk::VBox             potraceCreditsVBox;
-    Gtk::Label            potraceCreditsLabel;
+    //#### SIOX selection
 
-    //########## Other items
-    Gtk::VBox             otherBox;
+    Gtk::HBox             sioxBox;
+    Gtk::CheckButton      sioxButton;
 
+    //#### Preview
 
+    Gtk::Frame            previewFrame;
+    Gtk::VBox             previewVBox;
+    Gtk::Button           previewButton;
+    Gtk::Image            previewImage;
 
 };
 
 
 
-
 //#########################################################################
 //## E V E N T S
 //#########################################################################
@@ -170,89 +208,119 @@ class TraceDialogImpl : public TraceDialog
  */
 void TraceDialogImpl::potraceProcess(bool do_i_trace)
 {
+    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+    if (desktop)
+        desktop->setWaitingCursor();
+
     //##### Get the tracer and engine
     Inkscape::Trace::Potrace::PotraceTracingEngine pte;
 
     /* inversion */
-    bool invert = potraceInvertButton.get_active();
+    bool invert = modeInvertButton.get_active();
     pte.setInvert(invert);
 
-    //##### Get the single-scan settings
-    /* which one? */
-    if (potraceBrightnessRadioButton.get_active())
+    //##### Get the preprocessor settings
+    /* siox -- performed by Tracer, and before any of the others */
+    if (sioxButton.get_active())
+        tracer.enableSiox(true);
+    else
+        tracer.enableSiox(false);
+
+    /* one of the following */
+    if (modeBrightnessRadioButton.get_active())
         pte.setTraceType(Inkscape::Trace::Potrace::TRACE_BRIGHTNESS);
-    else if (potraceMultiScanBrightnessRadioButton.get_active())
+    else if (modeMultiScanBrightnessRadioButton.get_active())
         pte.setTraceType(Inkscape::Trace::Potrace::TRACE_BRIGHTNESS_MULTI);
-    else if (potraceCannyRadioButton.get_active())
+    else if (modeCannyRadioButton.get_active())
         pte.setTraceType(Inkscape::Trace::Potrace::TRACE_CANNY);
-    else if (potraceQuantRadioButton.get_active())
+    else if (modeQuantRadioButton.get_active())
         pte.setTraceType(Inkscape::Trace::Potrace::TRACE_QUANT);
-    else if (potraceMultiScanColorRadioButton.get_active())
+    else if (modeMultiScanColorRadioButton.get_active())
         {
         pte.setTraceType(Inkscape::Trace::Potrace::TRACE_QUANT_COLOR);
         pte.setInvert(false);
         }
-    else if (potraceMultiScanMonoRadioButton.get_active())
+    else if (modeMultiScanMonoRadioButton.get_active())
         {
         pte.setTraceType(Inkscape::Trace::Potrace::TRACE_QUANT_MONO);
         pte.setInvert(false);
         }
 
+    /* params */
+    int paramsSpecklesSize =
+      optionsSpecklesButton.get_active() ?
+      optionsSpecklesSizeSpinner.get_value_as_int() :
+      0;
+    pte.setParamsTurdSize(paramsSpecklesSize);
+    double paramsCornersThreshold =
+      optionsCornersButton.get_active() ?
+      optionsCornersThresholdSpinner.get_value() :
+      0.;
+    pte.setParamsAlphaMax(paramsCornersThreshold);
+    bool paramsOptim = optionsOptimButton.get_active();
+    pte.setParamsOptiCurve(paramsOptim);
+    double paramsOptimTolerance = optionsOptimToleranceSpinner.get_value();
+    pte.setParamsOptTolerance(paramsOptimTolerance);
+
+    //##### Get the single-scan settings
     /* brightness */
-    double brightnessThreshold = potraceBrightnessSpinner.get_value();
+    double brightnessThreshold = modeBrightnessSpinner.get_value();
     pte.setBrightnessThreshold(brightnessThreshold);
-
     /* canny */
-    double cannyHighThreshold = potraceCannyHiSpinner.get_value();
+    double cannyHighThreshold = modeCannyHiSpinner.get_value();
     pte.setCannyHighThreshold(cannyHighThreshold);
-
     /* quantization */
-    int quantNrColors = potraceQuantNrColorSpinner.get_value_as_int();
+    int quantNrColors = modeQuantNrColorSpinner.get_value_as_int();
     pte.setQuantizationNrColors(quantNrColors);
 
     //##### Get multiple-scan settings
-    int multiScanNrColors = potraceMultiScanNrColorSpinner.get_value_as_int();
+    int multiScanNrColors = modeMultiScanNrColorSpinner.get_value_as_int();
     pte.setMultiScanNrColors(multiScanNrColors);
-    bool do_i_stack = potraceMultiScanStackButton.get_active();
+    bool do_i_stack = modeMultiScanStackButton.get_active();
     pte.setMultiScanStack(do_i_stack);
-    bool do_i_smooth = potraceMultiScanSmoothButton.get_active();
+    bool do_i_smooth = modeMultiScanSmoothButton.get_active();
     pte.setMultiScanSmooth(do_i_smooth);
+    bool do_i_remove_background = modeMultiScanBackgroundButton.get_active();
+    pte.setMultiScanRemoveBackground(do_i_remove_background);
 
     //##### Get intermediate bitmap image
-    GdkPixbuf *pixbuf = tracer.getSelectedImage();
+    Glib::RefPtr<Gdk::Pixbuf> pixbuf = tracer.getSelectedImage();
     if (pixbuf)
          {
-         GdkPixbuf *preview = pte.preview(pixbuf);
+         Glib::RefPtr<Gdk::Pixbuf> preview = pte.preview(pixbuf);
          if (preview)
              {
-             Glib::RefPtr<Gdk::Pixbuf> thePreview = Glib::wrap(preview);
-             int width  = thePreview->get_width();
-             int height = thePreview->get_height();
-             double scaleFactor = 100.0 / (double)height;
+             int width  = preview->get_width();
+             int height = preview->get_height();
+             double scaleFX = 200.0 / (double)width;
+             double scaleFY = 200.0 / (double)height;
+             double scaleFactor = scaleFX > scaleFY ? scaleFY : scaleFX;
              int newWidth  = (int) (((double)width)  * scaleFactor);
              int newHeight = (int) (((double)height) * scaleFactor);
              Glib::RefPtr<Gdk::Pixbuf> scaledPreview =
-                    thePreview->scale_simple(newWidth, newHeight,
+                    preview->scale_simple(newWidth, newHeight,
                        Gdk::INTERP_NEAREST);
              //g_object_unref(preview);
-             potracePreviewImage.set(scaledPreview);
+             previewImage.set(scaledPreview);
              }
          }
 
     //##### Convert
     if (do_i_trace)
         {
-        if (potraceCancelButton)
-            potraceCancelButton->set_sensitive(true);
-        if (potraceOkButton)
-            potraceOkButton->set_sensitive(false);
+        if (mainCancelButton)
+            mainCancelButton->set_sensitive(true);
+        if (mainOkButton)
+            mainOkButton->set_sensitive(false);
         tracer.trace(&pte);
-        if (potraceCancelButton)
-            potraceCancelButton->set_sensitive(false);
-        if (potraceOkButton)
-            potraceOkButton->set_sensitive(true);
+        if (mainCancelButton)
+            mainCancelButton->set_sensitive(false);
+        if (mainOkButton)
+            mainOkButton->set_sensitive(true);
         }
 
+    if (desktop)
+        desktop->clearWaitingCursor();
 }
 
 
@@ -261,11 +329,17 @@ void TraceDialogImpl::potraceProcess(bool do_i_trace)
  */
 void TraceDialogImpl::abort()
 {
-    //### Do some GUI thing
+    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+    if (desktop)
+        desktop->setWaitingCursor();
+
+    if (mainCancelButton)
+        mainCancelButton->set_sensitive(false);
+    if (mainOkButton)
+        mainOkButton->set_sensitive(true);
 
     //### Make the abort() call to the tracer
     tracer.abort();
-
 }
 
 
@@ -277,7 +351,7 @@ void TraceDialogImpl::abort()
 /**
  * Callback from the Preview button.  Can be called from elsewhere.
  */
-void TraceDialogImpl::potracePreviewCallback()
+void TraceDialogImpl::previewCallback()
 {
     potraceProcess(false);
 }
@@ -287,16 +361,10 @@ void TraceDialogImpl::potracePreviewCallback()
  */
 void TraceDialogImpl::responseCallback(int response_id)
 {
-
     if (response_id == GTK_RESPONSE_OK)
         {
-        int panelNr = notebook.get_current_page();
-        //g_message("selected panel:%d\n", panelNr);
-
-        if (panelNr == 0)
-            {
+            // for now, we assume potrace, as it's the only one we have
             potraceProcess(true);
-            }
         }
     else if (response_id == GTK_RESPONSE_CANCEL)
         {
@@ -308,231 +376,326 @@ void TraceDialogImpl::responseCallback(int response_id)
         return;
         }
 
-
-
 }
 
 
 
-
 //#########################################################################
 //## C O N S T R U C T O R    /    D E S T R U C T O R
 //#########################################################################
 /**
  * Constructor
  */
-TraceDialogImpl::TraceDialogImpl()
+TraceDialogImpl::TraceDialogImpl() :
+    TraceDialog()
 {
 
-    Gtk::VBox *mainVBox = get_vbox();
+    Gtk::Box *contents = _getContents();
+
+#define MARGIN 2
+    //#### begin left panel
+
+    //### begin notebook
+
+    //## begin mode page
 
-#define MARGIN 4
+    //# begin single scan
 
-    //##Set up the Potrace panel
+    // brightness
 
-    /*#### brightness ####*/
-    potraceBrightnessRadioButton.set_label(_("Brightness"));
-    potraceGroup = potraceBrightnessRadioButton.get_group();
-    potraceBrightnessBox.pack_start(potraceBrightnessRadioButton, false, false, MARGIN);
-    tips.set_tip(potraceBrightnessRadioButton, _("Trace by a given brightness level"));
+    modeBrightnessRadioButton.set_label(_("Brightness cutoff"));
+    modeGroup = modeBrightnessRadioButton.get_group();
+    modeBrightnessBox.pack_start(modeBrightnessRadioButton, false, false, MARGIN);
+    tips.set_tip(modeBrightnessRadioButton,
+                 _("Trace by a given brightness level"));
 
-    potraceBrightnessSpinner.set_digits(3);
-    potraceBrightnessSpinner.set_increments(0.01, 0.1);
-    potraceBrightnessSpinner.set_range(0.0, 1.0);
-    potraceBrightnessSpinner.set_value(0.45);
-    potraceBrightnessBox.pack_end(potraceBrightnessSpinner, false, false, MARGIN);
-    tips.set_tip(potraceBrightnessSpinner, _("Brightness cutoff for black/white"));
+    modeBrightnessSpinner.set_digits(3);
+    modeBrightnessSpinner.set_increments(0.01, 0);
+    modeBrightnessSpinner.set_range(0.0, 1.0);
+    modeBrightnessSpinner.set_value(0.45);
+    modeBrightnessBox.pack_end(modeBrightnessSpinner, false, false, MARGIN);
+    tips.set_tip(modeBrightnessSpinner,
+                 _("Brightness cutoff for black/white"));
 
-    potraceBrightnessSpinnerLabel.set_label(_("Threshold:"));
-    potraceBrightnessBox.pack_end(potraceBrightnessSpinnerLabel, false, false, MARGIN);
+    modeBrightnessSpinnerLabel.set_label(_("Threshold:"));
+    modeBrightnessBox.pack_end(modeBrightnessSpinnerLabel, false, false, MARGIN);
 
-    potraceBrightnessVBox.pack_start(potraceBrightnessBox, false, false, MARGIN);
+    modeBrightnessVBox.pack_start(modeBrightnessBox, false, false, MARGIN);
 
-    potraceBrightnessFrame.set_label(_("Image Brightness"));
-    //potraceBrightnessFrame.set_shadow_type(Gtk::SHADOW_NONE);
-    potraceBrightnessFrame.add(potraceBrightnessVBox);
-    potraceBox.pack_start(potraceBrightnessFrame, false, false, 0);
+    modeBrightnessFrame.set_label(_("Single scan: creates a path"));
 
-    /*#### canny edge detection ####*/
+    // canny edge detection
     // TRANSLATORS: "Canny" is the name of the inventor of this edge detection method
-    potraceCannyRadioButton.set_label(_("Optimal Edge Detection (Canny)"));
-    potraceCannyRadioButton.set_group(potraceGroup);
-    potraceCannyBox.pack_start(potraceCannyRadioButton, false, false, MARGIN);
-    tips.set_tip(potraceCannyRadioButton, _("Trace with edge detection by J. Canny's algorithm"));
+
+    modeCannyRadioButton.set_label(_("Edge detection"));
+    modeCannyRadioButton.set_group(modeGroup);
+    modeCannyBox.pack_start(modeCannyRadioButton, false, false, MARGIN);
+    tips.set_tip(modeCannyRadioButton,
+                 _("Trace with optimal edge detection by J. Canny's algorithm"));
     /*
-    potraceCannyBox.pack_start(potraceCannySeparator);
-    potraceCannyLoSpinnerLabel.set_label(_("Low"));
-    potraceCannyBox.pack_start(potraceCannyLoSpinnerLabel);
-    potraceCannyLoSpinner.set_digits(5);
-    potraceCannyLoSpinner.set_increments(0.01, 0.1);
-    potraceCannyLoSpinner.set_range(0.0, 1.0);
-    potraceCannyLoSpinner.set_value(0.1);
-    potraceCannyBox.pack_start(potraceCannyLoSpinner);
+    modeCannyBox.pack_start(modeCannySeparator);
+    modeCannyLoSpinnerLabel.set_label(_("Low"));
+    modeCannyBox.pack_start(modeCannyLoSpinnerLabel);
+    modeCannyLoSpinner.set_digits(5);
+    modeCannyLoSpinner.set_increments(0.01, 0);
+    modeCannyLoSpinner.set_range(0.0, 1.0);
+    modeCannyLoSpinner.set_value(0.1);
+    modeCannyBox.pack_start(modeCannyLoSpinner);
     */
-    potraceCannyHiSpinner.set_digits(3);
-    potraceCannyHiSpinner.set_increments(0.01, 0.1);
-    potraceCannyHiSpinner.set_range(0.0, 1.0);
-    potraceCannyHiSpinner.set_value(0.65);
-    potraceCannyBox.pack_end(potraceCannyHiSpinner, false, false, MARGIN);
-    tips.set_tip(potraceCannyHiSpinner, _("Brightness cutoff for adjacent pixels (determines edge thickness)"));
-
-    potraceCannyHiSpinnerLabel.set_label(_("Threshold:"));
-    potraceCannyBox.pack_end(potraceCannyHiSpinnerLabel, false, false, MARGIN);
-
-    potraceCannyVBox.pack_start(potraceCannyBox, false, false, MARGIN);
-
-    potraceCannyFrame.set_label(_("Edge Detection"));
-    //potraceCannyFrame.set_shadow_type(Gtk::SHADOW_NONE);
-    potraceCannyFrame.add(potraceCannyVBox);
-    potraceBox.pack_start(potraceCannyFrame, false, false, 0);
-
-    /*#### quantization ####*/
-    // TRANSLATORS: Color Quantization: the process of reducing the number of colors
-    //  in an image by selecting an optimized set of representative colors and then
-    //  re-applying this reduced set to the original image.
-    potraceQuantRadioButton.set_label(_("Color Quantization"));
-    potraceQuantRadioButton.set_group(potraceGroup);
-    potraceQuantBox.pack_start(potraceQuantRadioButton, false, false, MARGIN);
-    tips.set_tip(potraceQuantRadioButton, _("Trace along the boundaries of reduced colors"));
-
-    potraceQuantNrColorSpinner.set_digits(2);
-    potraceQuantNrColorSpinner.set_increments(1.0, 4.0);
-    potraceQuantNrColorSpinner.set_range(2.0, 64.0);
-    potraceQuantNrColorSpinner.set_value(8.0);
-    potraceQuantBox.pack_end(potraceQuantNrColorSpinner, false, false, MARGIN);
-    tips.set_tip(potraceQuantNrColorSpinner, _("The number of reduced colors"));
-
-    potraceQuantNrColorLabel.set_label(_("Colors:"));
-    potraceQuantBox.pack_end(potraceQuantNrColorLabel, false, false, MARGIN);
-
-    potraceQuantVBox.pack_start(potraceQuantBox, false, false, MARGIN);
-
-    potraceQuantFrame.set_label(_("Quantization / Reduction"));
-    //potraceQuantFrame.set_shadow_type(Gtk::SHADOW_NONE);
-    potraceQuantFrame.add(potraceQuantVBox);
-    potraceBox.pack_start(potraceQuantFrame, false, false, 0);
-
-    /*#### Multiple scanning####*/
-    //----Hbox1
-    potraceMultiScanBrightnessRadioButton.set_label(_("Brightness"));
-    potraceMultiScanBrightnessRadioButton.set_group(potraceGroup);
-    potraceMultiScanHBox1.pack_start(potraceMultiScanBrightnessRadioButton, false, false, MARGIN);
-    tips.set_tip(potraceMultiScanBrightnessRadioButton, _("Trace the given number of brightness levels"));
-
-    potraceMultiScanNrColorSpinner.set_digits(2);
-    potraceMultiScanNrColorSpinner.set_increments(1.0, 4.0);
-    potraceMultiScanNrColorSpinner.set_range(2.0, 256.0);
-    potraceMultiScanNrColorSpinner.set_value(8.0);
-    potraceMultiScanHBox1.pack_end(potraceMultiScanNrColorSpinner, false, false, MARGIN);
-    potraceMultiScanNrColorLabel.set_label(_("Scans:"));
-    potraceMultiScanHBox1.pack_end(potraceMultiScanNrColorLabel, false, false, MARGIN);
-    tips.set_tip(potraceMultiScanNrColorSpinner, _("The desired number of scans"));
-
-    potraceMultiScanVBox.pack_start(potraceMultiScanHBox1, false, false, MARGIN);
-
-    //----Hbox2
-    potraceMultiScanColorRadioButton.set_label(_("Color"));
-    potraceMultiScanColorRadioButton.set_group(potraceGroup);
-    potraceMultiScanHBox2.pack_start(potraceMultiScanColorRadioButton, false, false, MARGIN);
-    tips.set_tip(potraceMultiScanColorRadioButton, _("Trace the given number of reduced colors"));
-
-
-    potraceMultiScanVBox.pack_start(potraceMultiScanHBox2, false, false, MARGIN);
-
-    //---Hbox3
-    potraceMultiScanMonoRadioButton.set_label(_("Monochrome"));
-    potraceMultiScanMonoRadioButton.set_group(potraceGroup);
-    potraceMultiScanHBox3.pack_start(potraceMultiScanMonoRadioButton, false, false, MARGIN);
-    tips.set_tip(potraceMultiScanMonoRadioButton, _("Same as Color, but convert result to grayscale"));
-
-    // TRANSLATORS: "Stack" is a verb here
-    potraceMultiScanStackButton.set_label(_("Stack"));
-    potraceMultiScanStackButton.set_active(true);
-    potraceMultiScanHBox3.pack_end(potraceMultiScanStackButton, false, false, MARGIN);
-    tips.set_tip(potraceMultiScanStackButton, _("Stack scans vertically (no gaps) or tile horizontally (usually with gaps)"));
+    modeCannyHiSpinner.set_digits(3);
+    modeCannyHiSpinner.set_increments(0.01, 0);
+    modeCannyHiSpinner.set_range(0.0, 1.0);
+    modeCannyHiSpinner.set_value(0.65);
+    modeCannyBox.pack_end(modeCannyHiSpinner, false, false, MARGIN);
+    tips.set_tip(modeCannyHiSpinner,
+                 _("Brightness cutoff for adjacent pixels (determines edge thickness)"));
+
+    modeCannyHiSpinnerLabel.set_label(_("Threshold:"));
+    modeCannyBox.pack_end(modeCannyHiSpinnerLabel, false, false, MARGIN);
+
+    modeBrightnessVBox.pack_start(modeCannyBox, false, false, MARGIN);
+
+    // quantization
+    // TRANSLATORS: Color Quantization: the process of reducing the number
+    // of colors in an image by selecting an optimized set of representative
+    // colors and then re-applying this reduced set to the original image.
+
+    modeQuantRadioButton.set_label(_("Color quantization"));
+    modeQuantRadioButton.set_group(modeGroup);
+    modeQuantBox.pack_start(modeQuantRadioButton, false, false, MARGIN);
+    tips.set_tip(modeQuantRadioButton,
+                 _("Trace along the boundaries of reduced colors"));
+
+    modeQuantNrColorSpinner.set_digits(0);
+    modeQuantNrColorSpinner.set_increments(1.0, 0);
+    modeQuantNrColorSpinner.set_range(2.0, 64.0);
+    modeQuantNrColorSpinner.set_value(8.0);
+    modeQuantBox.pack_end(modeQuantNrColorSpinner, false, false, MARGIN);
+    tips.set_tip(modeQuantNrColorSpinner,
+                 _("The number of reduced colors"));
+
+    modeQuantNrColorLabel.set_label(_("Colors:"));
+    modeQuantBox.pack_end(modeQuantNrColorLabel, false, false, MARGIN);
+
+    modeBrightnessVBox.pack_start(modeQuantBox, false, false, MARGIN);
+
+    // swap black and white
+    modeInvertButton.set_label(_("Invert image"));
+    modeInvertButton.set_active(false);
+    modeInvertBox.pack_start(modeInvertButton, false, false, MARGIN);
+    modeBrightnessVBox.pack_start(modeInvertBox, false, false, MARGIN);
+    tips.set_tip(modeInvertButton,
+                 _("Invert black and white regions"));
+
+    modeBrightnessFrame.add(modeBrightnessVBox);
+    modePageBox.pack_start(modeBrightnessFrame, false, false, 0);
+
+    //# end single scan
+
+    //# begin multiple scan
+
+    modeMultiScanBrightnessRadioButton.set_label(_("Brightness steps"));
+    modeMultiScanBrightnessRadioButton.set_group(modeGroup);
+    modeMultiScanHBox1.pack_start(modeMultiScanBrightnessRadioButton, false, false, MARGIN);
+    tips.set_tip(modeMultiScanBrightnessRadioButton,
+                 _("Trace the given number of brightness levels"));
+
+    modeMultiScanNrColorSpinner.set_digits(0);
+    modeMultiScanNrColorSpinner.set_increments(1.0, 0);
+    modeMultiScanNrColorSpinner.set_range(2.0, 256.0);
+    modeMultiScanNrColorSpinner.set_value(8.0);
+    modeMultiScanHBox1.pack_end(modeMultiScanNrColorSpinner, false, false, MARGIN);
+    modeMultiScanNrColorLabel.set_label(_("Scans:"));
+    modeMultiScanHBox1.pack_end(modeMultiScanNrColorLabel, false, false, MARGIN);
+    tips.set_tip(modeMultiScanNrColorSpinner,
+                 _("The desired number of scans"));
+
+    modeMultiScanVBox.pack_start(modeMultiScanHBox1, false, false, MARGIN);
+
+    modeMultiScanColorRadioButton.set_label(_("Colors"));
+    modeMultiScanColorRadioButton.set_group(modeGroup);
+    modeMultiScanHBox2.pack_start(modeMultiScanColorRadioButton, false, false, MARGIN);
+    tips.set_tip(modeMultiScanColorRadioButton,
+                 _("Trace the given number of reduced colors"));
+
+    modeMultiScanVBox.pack_start(modeMultiScanHBox2, false, false, MARGIN);
+
+    modeMultiScanMonoRadioButton.set_label(_("Grays"));
+    modeMultiScanMonoRadioButton.set_group(modeGroup);
+    modeMultiScanHBox3.pack_start(modeMultiScanMonoRadioButton, false, false, MARGIN);
+    tips.set_tip(modeMultiScanMonoRadioButton,
+                 _("Same as Colors, but the result is converted to grayscale"));
+
+    modeMultiScanVBox.pack_start(modeMultiScanHBox3, false, false, MARGIN);
 
     // TRANSLATORS: "Smooth" is a verb here
-    potraceMultiScanSmoothButton.set_label(_("Smooth"));
-    potraceMultiScanSmoothButton.set_active(true);
-    potraceMultiScanHBox3.pack_end(potraceMultiScanSmoothButton, false, false, MARGIN);
-    tips.set_tip(potraceMultiScanSmoothButton, _("Apply Gaussian blur to the bitmap before tracing"));
-
-    potraceMultiScanVBox.pack_start(potraceMultiScanHBox3, false, false, MARGIN);
-
-    potraceMultiScanFrame.set_label(_("Multiple Scanning"));
-    //potraceQuantFrame.set_shadow_type(Gtk::SHADOW_NONE);
-    potraceMultiScanFrame.add(potraceMultiScanVBox);
-    potraceBox.pack_start(potraceMultiScanFrame, false, false, 0);
-
-    /*#### Preview ####*/
-    potracePreviewButton.set_label(_("Preview"));
-    potracePreviewButton.signal_clicked().connect(
-         sigc::mem_fun(*this, &TraceDialogImpl::potracePreviewCallback) );
-    potracePreviewBox.pack_end(potracePreviewButton, false, false, 0);//do not expand
-    tips.set_tip(potracePreviewButton, _("Preview the result without actual tracing"));
-
-
-    potracePreviewImage.set_size_request(100,100);
-    //potracePreviewImage.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
-    potracePreviewBox.pack_start(potracePreviewImage, true, true, 0);
-    potracePreviewFrame.set_label(_("Preview")); // I guess it's correct to call the "intermediate bitmap" a preview of the trace
-    //potracePreviewFrame.set_shadow_type(Gtk::SHADOW_NONE);
-    potracePreviewFrame.add(potracePreviewBox);
-    potraceBox.pack_start(potracePreviewFrame, true, true, 0);
-
-    /*#### swap black and white ####*/
-    potraceInvertButton.set_label(_("Invert"));
-    potraceInvertButton.set_active(false);
-    potraceInvertBox.pack_end(potraceInvertButton, false, false, MARGIN);
-    potraceBox.pack_start(potraceInvertBox, false, false, MARGIN);
-    tips.set_tip(potraceInvertButton, _("Invert black and white regions for single traces"));
-
-    /*#### Credits ####*/
-    potraceCreditsLabel.set_text(
-                                                        _("Thanks to Peter Selinger, http://potrace.sourceforge.net")
-                         );
+    modeMultiScanSmoothButton.set_label(_("Smooth"));
+    modeMultiScanSmoothButton.set_active(true);
+    modeMultiScanHBox4.pack_start(modeMultiScanSmoothButton, false, false, MARGIN);
+    tips.set_tip(modeMultiScanSmoothButton,
+                 _("Apply Gaussian blur to the bitmap before tracing"));
+
+    // TRANSLATORS: "Stack" is a verb here
+    modeMultiScanStackButton.set_label(_("Stack scans"));
+    modeMultiScanStackButton.set_active(true);
+    modeMultiScanHBox4.pack_start(modeMultiScanStackButton, false, false, MARGIN);
+    tips.set_tip(modeMultiScanStackButton, _("Stack scans on top of one another (no gaps) instead of tiling (usually with gaps)"));
+
+
+    modeMultiScanBackgroundButton.set_label(_("Remove background"));
+    modeMultiScanBackgroundButton.set_active(false);
+    modeMultiScanHBox4.pack_start(modeMultiScanBackgroundButton, false, false, MARGIN);
+    // TRANSLATORS: "Layer" refers to one of the stacked paths in the multiscan
+    tips.set_tip(modeMultiScanBackgroundButton,
+                 _("Remove bottom (background) layer when done"));
+
+    modeMultiScanVBox.pack_start(modeMultiScanHBox4, false, false, MARGIN);
+
+    modeMultiScanFrame.set_label(_("Multiple scans: creates a group of paths"));
+    //modeQuantFrame.set_shadow_type(Gtk::SHADOW_NONE);
+    modeMultiScanFrame.add(modeMultiScanVBox);
+    modePageBox.pack_start(modeMultiScanFrame, false, false, 0);
+
+    //# end multiple scan
+
+    //## end mode page
+
+    notebook.append_page(modePageBox, _("Mode"));
+
+    //## begin option page
+
+    //# potrace parameters
+
+    optionsSpecklesButton.set_label(_("Suppress speckles"));
+    tips.set_tip(optionsSpecklesButton,
+                 _("Ignore small spots (speckles) in the bitmap"));
+    optionsSpecklesButton.set_active(true);
+    optionsSpecklesBox.pack_start(optionsSpecklesButton, false, false, MARGIN);
+    optionsSpecklesSizeSpinner.set_digits(0);
+    optionsSpecklesSizeSpinner.set_increments(1, 0);
+    optionsSpecklesSizeSpinner.set_range(0, 1000);
+    optionsSpecklesSizeSpinner.set_value(2);
+    tips.set_tip(optionsSpecklesSizeSpinner,
+                 _("Speckles of up to this many pixels will be suppressed"));
+    optionsSpecklesBox.pack_end(optionsSpecklesSizeSpinner, false, false, MARGIN);
+    optionsSpecklesSizeLabel.set_label(_("Size:"));
+    optionsSpecklesBox.pack_end(optionsSpecklesSizeLabel, false, false, MARGIN);
+
+    optionsCornersButton.set_label(_("Smooth corners"));
+    tips.set_tip(optionsCornersButton,
+                 _("Smooth out sharp corners of the trace"));
+    optionsCornersButton.set_active(true);
+    optionsCornersBox.pack_start(optionsCornersButton, false, false, MARGIN);
+    optionsCornersThresholdSpinner.set_digits(2);
+    optionsCornersThresholdSpinner.set_increments(0.01, 0);
+    optionsCornersThresholdSpinner.set_range(0.0, 1.34);
+    optionsCornersThresholdSpinner.set_value(1.0);
+    optionsCornersBox.pack_end(optionsCornersThresholdSpinner, false, false, MARGIN);
+    tips.set_tip(optionsCornersThresholdSpinner,
+                 _("Increase this to smooth corners more"));
+    optionsCornersThresholdLabel.set_label(_("Threshold:"));
+    optionsCornersBox.pack_end(optionsCornersThresholdLabel, false, false, MARGIN);
+
+    optionsOptimButton.set_label(_("Optimize paths"));
+    optionsOptimButton.set_active(true);
+    tips.set_tip(optionsOptimButton,
+                 _("Try to optimize paths by joining adjacent Bezier curve segments"));
+    optionsOptimBox.pack_start(optionsOptimButton, false, false, MARGIN);
+    optionsOptimToleranceSpinner.set_digits(2);
+    optionsOptimToleranceSpinner.set_increments(0.05, 0);
+    optionsOptimToleranceSpinner.set_range(0.0, 5.0);
+    optionsOptimToleranceSpinner.set_value(0.2);
+    optionsOptimBox.pack_end(optionsOptimToleranceSpinner, false, false, MARGIN);
+    tips.set_tip(optionsOptimToleranceSpinner,
+                 _("Increase this to reduce the number of nodes in the trace by more aggressive optimization"));
+    optionsOptimToleranceLabel.set_label(_("Tolerance:"));
+    optionsOptimBox.pack_end(optionsOptimToleranceLabel, false, false, MARGIN);
+
+    optionsVBox.pack_start(optionsSpecklesBox, false, false, MARGIN);
+    optionsVBox.pack_start(optionsCornersBox, false, false, MARGIN);
+    optionsVBox.pack_start(optionsOptimBox, false, false, MARGIN);
+    optionsFrame.set_label(_("Options"));
+    optionsFrame.add(optionsVBox);
+    optionsPageBox.pack_start(optionsFrame, false, false, 0);
+
+    //## end option page
+
+    notebook.append_page(optionsPageBox, _("Options"));
+
+    //### credits
+
+    potraceCreditsLabel.set_text(_("Inkscape bitmap tracing\nis based on Potrace,\ncreated by Peter Selinger\n\nhttp://potrace.sourceforge.net"));
     potraceCreditsVBox.pack_start(potraceCreditsLabel, false, false, MARGIN);
-    potraceCreditsFrame.set_label(_("Credits"));
-    potraceCreditsFrame.set_shadow_type(Gtk::SHADOW_NONE);
-    potraceCreditsFrame.add(potraceCreditsVBox);
-    potraceBox.pack_start(potraceCreditsFrame, false, false, 0);
 
-    /*done */
-    // TRANSLATORS: Potrace is an application for transforming bitmaps into
-    //  vector graphics (http://potrace.sourceforge.net/)
-    notebook.append_page(potraceBox, _("Potrace"));
+    notebook.append_page(potraceCreditsVBox, _("Credits"));
+
+    //### end notebook
+
+    leftVBox.pack_start(notebook, true, true, MARGIN);
+
+    //#### end left panel
+
+    mainHBox.pack_start(leftVBox);
+
+    //#### begin right panel
 
-    //##Set up the Other panel
-    // This may be reenabled when we have another tracer; now an empty tab is confusing so I'm disabling it
-    //    notebook.append_page(otherBox, _("Other"));
+    //## SIOX
 
-    //##Put the notebook on the dialog
-    mainVBox->pack_start(notebook);
+    sioxButton.set_label(_("SIOX foreground selection"));
+    sioxBox.pack_start(sioxButton, false, false, MARGIN);
+    tips.set_tip(sioxButton,
+                 _("Cover the area you want to select as the foreground"));
+    rightVBox.pack_start(sioxBox, false, false, 0);
+
+    //## preview
+
+    previewButton.set_label(_("Update"));
+    previewButton.signal_clicked().connect(
+         sigc::mem_fun(*this, &TraceDialogImpl::previewCallback) );
+    previewVBox.pack_end(previewButton, false, false, 0);
+    // I guess it's correct to call the "intermediate bitmap" a preview of the trace
+    tips.set_tip(previewButton,
+                 _("Preview the intermediate bitmap with the current settings, without actual tracing"));
+    previewImage.set_size_request(200,200);
+    //previewImage.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
+    previewVBox.pack_start(previewImage, true, true, 0);
+    previewFrame.set_label(_("Preview"));
+    //previewFrame.set_shadow_type(Gtk::SHADOW_NONE);
+    previewFrame.add(previewVBox);
+
+    rightVBox.pack_start(previewFrame, true, true, MARGIN);
+
+    //#### end right panel
+
+    mainHBox.pack_start(rightVBox);
+
+    //#### Global stuff
+
+    contents->pack_start(mainHBox);
 
     //## The OK button
-    potraceCancelButton = add_button(Gtk::Stock::STOP, GTK_RESPONSE_CANCEL);
-    if (potraceCancelButton)
-        {
-        tips.set_tip((*potraceCancelButton), _("Abort a trace in progress"));
-        potraceCancelButton->set_sensitive(false);
-        }
-    potraceOkButton     = add_button(Gtk::Stock::OK,   GTK_RESPONSE_OK);
-    tips.set_tip((*potraceOkButton), _("Execute the trace"));
+    mainCancelButton = addResponseButton(Gtk::Stock::STOP, GTK_RESPONSE_CANCEL);
+    if (mainCancelButton) {
+       tips.set_tip((*mainCancelButton), _("Abort a trace in progress"));
+       mainCancelButton->set_sensitive(false);
+    }
+    mainOkButton = addResponseButton(Gtk::Stock::OK, GTK_RESPONSE_OK);
+    tips.set_tip((*mainOkButton), _("Execute the trace"));
 
     show_all_children();
 
     //## Connect the signal
-    signal_response().connect(
-         sigc::mem_fun(*this, &TraceDialogImpl::responseCallback) );
+    signalResponse().connect(
+       sigc::mem_fun(*this, &TraceDialogImpl::responseCallback));
 }
 
 /**
  * Factory method.  Use this to create a new TraceDialog
  */
-TraceDialog *TraceDialog::create()
+TraceDialog &TraceDialog::getInstance()
 {
     TraceDialog *dialog = new TraceDialogImpl();
-    return dialog;
+    return *dialog;
 }
 
 
@@ -542,14 +705,9 @@ TraceDialog *TraceDialog::create()
 TraceDialogImpl::~TraceDialogImpl()
 {
 
-
 }
 
 
-
-
-
-
 } //namespace Dialog
 } //namespace UI
 } //namespace Inkscape