[glabels] Created new "New label dialog"



commit 44ad3d257b9594674604fa82215e72759b40de11
Author: Jim Evins <evins snaught com>
Date:   Wed Mar 10 22:38:28 2010 -0500

    Created new "New label dialog"
    
    Created a new re-designed "New label dialog."  The dialog now shows meta-data
    for the selected template, including hyperlinks to vendor and product
    websites, if available.  The new dialog is more compact and thus should
    be usable on small displays such as netbooks (probably not hand-helds).
    
    The menu is somewhat clumbsy to navigate still -- will need to reorganize
    to make navigation easier and more intuitive.

 data/builder/Makefile.am              |    2 +-
 data/builder/media-select.builder     |  229 --------
 data/builder/new-label-dialog.builder |  362 +++++++++++++
 libglabels/db.c                       |   75 +++-
 libglabels/db.h                       |    4 +
 libglabels/str.c                      |   41 ++-
 libglabels/str.h                      |   10 +-
 libglabels/template.c                 |  232 ++++++++-
 libglabels/template.h                 |   31 +-
 src/Makefile.am                       |    8 +-
 src/media-combo-menu-item.c           |  178 +++++++
 src/media-combo-menu-item.h           |   75 +++
 src/media-combo-menu.c                |  332 ++++++++++++
 src/media-combo-menu.h                |   83 +++
 src/media-combo.c                     |  345 ++++++++++++
 src/media-combo.h                     |   84 +++
 src/media-select.c                    |  937 ---------------------------------
 src/media-select.h                    |   87 ---
 src/mini-preview.c                    |   90 +++-
 src/mini-preview.h                    |    6 +
 src/new-label-dialog.c                |  342 +++++++++---
 src/rotate-label-button.c             |   10 +-
 src/str-util.c                        |   37 --
 src/str-util.h                        |    2 -
 24 files changed, 2196 insertions(+), 1406 deletions(-)
---
diff --git a/data/builder/Makefile.am b/data/builder/Makefile.am
index a4cf3f3..4b48a69 100644
--- a/data/builder/Makefile.am
+++ b/data/builder/Makefile.am
@@ -5,7 +5,7 @@ builderdir = $(datadir)/$(GLABELS_BRANCH)/builder/
 builder_DATA = \
 	property-bar.builder		\
 	print-op-dialog-custom-widget.builder	\
-	media-select.builder		\
+	new-label-dialog.builder	\
 	merge-properties-dialog.builder	\
 	template-designer.builder	\
 	prefs-dialog.builder		\
diff --git a/data/builder/new-label-dialog.builder b/data/builder/new-label-dialog.builder
new file mode 100644
index 0000000..9cb16a5
--- /dev/null
+++ b/data/builder/new-label-dialog.builder
@@ -0,0 +1,362 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="window1">
+    <child>
+      <object class="GtkHBox" id="new_label_dialog_hbox">
+        <property name="visible">True</property>
+        <property name="border_width">6</property>
+        <property name="spacing">18</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkTable" id="table2">
+                        <property name="visible">True</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">12</property>
+                        <property name="row_spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="label6">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Template:</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="combo_hbox">
+                            <property name="visible">True</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label12">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="label" translatable="yes">Orientation:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="rotate_hbox">
+                            <property name="visible">True</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label9">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Select media&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame2">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment2">
+                    <property name="visible">True</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkTable" id="table1">
+                        <property name="visible">True</property>
+                        <property name="n_rows">7</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">12</property>
+                        <property name="row_spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Description:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label2">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Page size:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label3">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Label size:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label4">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Layout:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label7">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="label" translatable="yes">Similar products:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="desc_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="page_size_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label_size_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="layout_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label5">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Vendor:</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="vendor_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label8">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Part #:</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="part_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="scrolledwindow1">
+                            <property name="height_request">77</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkViewport" id="viewport1">
+                                <property name="visible">True</property>
+                                <property name="resize_mode">queue</property>
+                                <property name="shadow_type">none</property>
+                                <child>
+                                  <object class="GtkLabel" id="similar_label">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="yalign">0</property>
+                                    <property name="label" translatable="yes">1
+2
+3
+4</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label10">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Information&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame3">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <object class="GtkAlignment" id="alignment3">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkVBox" id="preview_vbox">
+                    <property name="visible">True</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label11">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;b&gt;Preview&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/libglabels/db.c b/libglabels/db.c
index b43ff6b..af2adca 100644
--- a/libglabels/db.c
+++ b/libglabels/db.c
@@ -1149,7 +1149,7 @@ read_vendor_files_from_dir (GList      *vendors,
 
 		if (extension != NULL) {
 
-			if ( ASCII_EQUAL (filename, "vendor-sizes.xml") )
+			if ( ASCII_EQUAL (filename, "vendors.xml") )
                         {
 
 				full_filename =
@@ -1556,6 +1556,77 @@ lgl_db_get_template_name_list_all (const gchar *brand,
 
 
 /**
+ * lgl_db_get_similar_template_name_list:
+ * @name:     Name of template under test.
+ *
+ * Get a list of all valid names and aliases of templates in the template database that
+ * have the same size and layout characteristics as the given template.
+ *
+ * Returns: a list of template names and aliases.
+ */
+GList *
+lgl_db_get_similar_template_name_list (const gchar  *name)
+{
+	GList            *p_tmplt, *p_alias;
+	lglTemplate      *template1;
+	lglTemplate      *template2;
+	lglTemplateAlias *alias;
+        gchar            *name2;
+	GList            *names = NULL;
+
+	if (!templates)
+        {
+		lgl_db_init ();
+	}
+
+        if ( !name )
+        {
+                return NULL;
+        }
+
+        template1 = lgl_db_lookup_template_from_name (name);
+        if ( !template1 )
+        {
+                return NULL;
+        }
+
+        for (p_alias = template1->aliases; p_alias != NULL; p_alias = p_alias->next)
+        {
+                alias = (lglTemplateAlias *)p_alias->data;
+
+                name2 = g_strdup_printf ("%s %s", alias->brand, alias->part);
+                if ( !UTF8_EQUAL (name2, name) )
+                {
+                        names = g_list_insert_sorted (names, name2,
+                                                      (GCompareFunc)lgl_str_part_name_cmp);
+                }
+        }
+
+	for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+        {
+		template2 = (lglTemplate *) p_tmplt->data;
+
+                if ( lgl_template_are_templates_identical (template1, template2) )
+                {
+			for (p_alias = template2->aliases; p_alias != NULL; p_alias = p_alias->next)
+                        {
+                                alias = (lglTemplateAlias *)p_alias->data;
+
+                                name2 = g_strdup_printf ("%s %s", alias->brand, alias->part);
+                                if ( !UTF8_EQUAL (name2, name) )
+                                {
+                                        names = g_list_insert_sorted (names, name2,
+                                                                      (GCompareFunc)lgl_str_part_name_cmp);
+                                }
+			}
+		}
+	}
+
+	return names;
+}
+
+
+/**
  * lgl_db_free_template_name_list:
  * @names: List of template name strings to be freed.
  *
@@ -1819,7 +1890,7 @@ template_full_page (const gchar *paper_id)
 	}
 
 	part = g_strdup_printf ("%s-Full-Page", paper->id);
-	desc = g_strdup_printf (_("Generic %s full page template"), paper->name);
+	desc = g_strdup_printf (_("%s full page label"), paper->name);
 
 	template = lgl_template_new ("Generic", part, desc,
                                      paper_id, paper->width, paper->height);
diff --git a/libglabels/db.h b/libglabels/db.h
index 3fd9f3a..343573e 100644
--- a/libglabels/db.h
+++ b/libglabels/db.h
@@ -130,6 +130,8 @@ GList         *lgl_db_get_template_name_list_all     (const gchar         *brand
                                                       const gchar         *paper_id,
                                                       const gchar         *category_id);
 
+GList         *lgl_db_get_similar_template_name_list (const gchar         *name);
+
 void           lgl_db_free_template_name_list        (GList               *names);
 
 lglTemplate   *lgl_db_lookup_template_from_name      (const gchar         *name);
@@ -149,6 +151,8 @@ void           lgl_db_print_known_templates          (void);
 
 void           lgl_db_print_aliases                  (const lglTemplate    *template);
 
+void           lgl_db_print_known_vendors            (void);
+
 
 
 G_END_DECLS
diff --git a/libglabels/str.c b/libglabels/str.c
index e93a991..0f0339b 100644
--- a/libglabels/str.c
+++ b/libglabels/str.c
@@ -18,11 +18,15 @@
  *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-//#include <config.h>
+#include <config.h>
 
 #include "str.h"
 
 #include <string.h>
+#include <math.h>
+
+#define FRAC_EPSILON 0.00005
+
 
 /*===========================================*/
 /* Private types                             */
@@ -217,6 +221,41 @@ span_non_digits (gchar **p)
 }
 
 
+/****************************************************************************/
+/* Create fractional representation of number, if possible.                 */
+/****************************************************************************/
+gchar *
+lgl_str_format_fraction (gdouble x)
+{
+	static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. };
+	gint i;
+	gdouble product, remainder;
+	gint n, d;
+
+	for ( i=0; denom[i] != 0.0; i++ ) {
+		product = x * denom[i];
+		remainder = fabs(product - ((gint)(product+0.5)));
+		if ( remainder < FRAC_EPSILON ) break;
+	}
+
+	if ( denom[i] == 0.0 ) {
+		/* None of our denominators work. */
+		return g_strdup_printf ("%.5g", x);
+	}
+	if ( denom[i] == 1.0 ) {
+		/* Simple integer. */
+		return g_strdup_printf ("%d", (gint)x);
+	}
+	n = (gint)( x * denom[i] + 0.5 );
+	d = (gint)denom[i];
+	if ( n > d ) {
+		return g_strdup_printf ("%d_%d/%d", (n/d), (n%d), d);
+	} else {
+		return g_strdup_printf ("%d/%d", (n%d), d);
+	}
+}
+
+
 
 /*
  * Local Variables:       -- emacs
diff --git a/libglabels/str.h b/libglabels/str.h
index 2675029..b22f13b 100644
--- a/libglabels/str.h
+++ b/libglabels/str.h
@@ -25,11 +25,13 @@
 
 G_BEGIN_DECLS
 
-gint  lgl_str_utf8_casecmp  (const gchar *s1,
-                             const gchar *s2);
+gint   lgl_str_utf8_casecmp    (const gchar *s1,
+                                const gchar *s2);
 
-gint  lgl_str_part_name_cmp (const gchar *s1,
-                             const gchar *s2);
+gint   lgl_str_part_name_cmp   (const gchar *s1,
+                                const gchar *s2);
+
+gchar *lgl_str_format_fraction (gdouble      x);
 
 G_END_DECLS
 
diff --git a/libglabels/template.c b/libglabels/template.c
index 0af4e5d..50271fb 100644
--- a/libglabels/template.c
+++ b/libglabels/template.c
@@ -180,7 +180,7 @@ lgl_template_get_name (const lglTemplate  *template)
  * This function tests if the given templates match.  This is a simple test that only tests
  * the brand and part name/number. It does not test if they are actually identical.
  *
- * Returns:  TRUE if the two template matche.
+ * Returns:  TRUE if the two templates match.
  *
  */
 gboolean
@@ -284,6 +284,108 @@ lgl_template_does_category_match  (const lglTemplate  *template,
 
 
 /**
+ * lgl_template_are_templates_identical:
+ *   @template1:  Pointer to 1st template structure to test
+ *   @template2:  Pointer to 2nd template structure to test
+ *
+ * This function tests if the given templates have identical size and layout properties.
+ *
+ * Returns:  TRUE if the two templates are identical.
+ *
+ */
+gboolean
+lgl_template_are_templates_identical (const lglTemplate   *template1,
+                                      const lglTemplate   *template2)
+{
+        lglTemplateFrame  *frame1;
+        lglTemplateFrame  *frame2;
+        GList             *p1;
+        GList             *p2;
+        lglTemplateLayout *layout1;
+        lglTemplateLayout *layout2;
+        gboolean           match_found;
+
+
+        if (!UTF8_EQUAL (template1->paper_id, template2->paper_id) ||
+            (template1->page_width  != template2->page_width)      ||
+            (template1->page_height != template2->page_height))
+        {
+                return FALSE;
+        }
+
+        frame1 = (lglTemplateFrame *)template1->frames->data;
+        frame2 = (lglTemplateFrame *)template2->frames->data;
+
+        if ( frame1->shape != frame2->shape )
+        {
+                return FALSE;
+        }
+
+        switch ( frame1->shape )
+        {
+
+        case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+                if ((frame1->rect.w != frame2->rect.w) ||
+                    (frame1->rect.h != frame2->rect.h))
+                {
+                        return FALSE;
+                }
+                break;
+
+        case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+                if ((frame1->ellipse.w != frame2->ellipse.w) ||
+                    (frame1->ellipse.h != frame2->ellipse.h))
+                {
+                        return FALSE;
+                }
+                break;
+
+        case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+                if ((frame1->round.r != frame2->round.r))
+                {
+                        return FALSE;
+                }
+                break;
+
+        case LGL_TEMPLATE_FRAME_SHAPE_CD:
+                if ((frame1->cd.r1 != frame2->cd.r1) ||
+                    (frame1->cd.r2 != frame2->cd.r2))
+                {
+                        return FALSE;
+                }
+        }
+
+        for ( p1 = frame1->all.layouts; p1; p1 = p1->next )
+        {
+                layout1 = (lglTemplateLayout *)p1->data;
+
+                match_found = FALSE;
+                for ( p2 = frame2->all.layouts; p2 && !match_found; p2 = p2->next )
+                {
+                        layout2 = (lglTemplateLayout *)p2->data;
+
+                        if ( (layout1->nx == layout2->nx) &&
+                             (layout1->ny == layout2->ny) &&
+                             (layout1->x0 == layout2->x0) &&
+                             (layout1->y0 == layout2->y0) &&
+                             (layout1->dx == layout2->dx) &&
+                             (layout1->dy == layout2->dy) )
+                        {
+                                match_found = TRUE;
+                        }
+
+                }
+                if ( !match_found )
+                {
+                        return FALSE;
+                }
+        }
+
+        return TRUE;
+}
+
+
+/**
  * lgl_template_alias_new:
  *   @brand:        Alias brand
  *   @part:         Alias part name/number
@@ -589,6 +691,134 @@ lgl_template_frame_get_n_labels (const lglTemplateFrame *frame)
 
 
 /**
+ * lgl_template_frame_get_layout_description
+ * @frame: #lglTemplateFrame structure to query
+ *
+ * Get a description of the label layout including number of labels per sheet.
+ *
+ * Returns: a newly allocation description string.
+ *
+ */
+gchar *
+lgl_template_frame_get_layout_description (const lglTemplateFrame *frame)
+{
+        gint                    n_labels;
+        gchar                  *string;
+        lglTemplateLayout      *layout;
+
+        n_labels = lgl_template_frame_get_n_labels (frame);
+
+        if ( frame->all.layouts && (frame->all.layouts->next == NULL) )
+        {
+                layout = (lglTemplateLayout *)frame->all.layouts->data;
+                string = g_strdup_printf ("%d Ã? %d (%d %s)", layout->nx, layout->ny, n_labels, _("per sheet"));
+        }
+        else
+        {
+                string = g_strdup_printf (_("%d %s"), n_labels, _("per sheet"));
+        }
+
+        return string;
+}
+
+
+/**
+ * lgl_template_frame_get_size_description
+ * @frame: #lglTemplateFrame structure to query
+ * @units: #lglUnits
+ *
+ * Get a description of the label size.
+ *
+ * Returns: a newly allocation description string.
+ *
+ */
+gchar *
+lgl_template_frame_get_size_description (const lglTemplateFrame *frame,
+                                         lglUnits                units)
+{
+        const gchar               *units_string;
+        gdouble                    units_per_point;
+        gchar                     *string = NULL;
+
+        units_string    = lgl_units_get_name (units);
+        units_per_point = lgl_units_get_units_per_point (units);
+
+        switch (frame->shape) {
+        case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+                if ( units == LGL_UNITS_INCH ) {
+                        gchar *xstr, *ystr;
+
+                        xstr = lgl_str_format_fraction (frame->rect.w*units_per_point);
+                        ystr = lgl_str_format_fraction (frame->rect.h*units_per_point);
+                        string = g_strdup_printf ("%s Ã? %s %s",
+                                                  xstr, ystr, units_string);
+                        g_free (xstr);
+                        g_free (ystr);
+                } else {
+                        string = g_strdup_printf ("%.5g Ã? %.5g %s",
+                                                  frame->rect.w*units_per_point,
+                                                  frame->rect.h*units_per_point,
+                                                  units_string);
+                }
+                break;
+        case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+                if ( units == LGL_UNITS_INCH ) {
+                        gchar *xstr, *ystr;
+
+                        xstr = lgl_str_format_fraction (frame->ellipse.w*units_per_point);
+                        ystr = lgl_str_format_fraction (frame->ellipse.h*units_per_point);
+                        string = g_strdup_printf ("%s Ã? %s %s",
+                                                  xstr, ystr, units_string);
+                        g_free (xstr);
+                        g_free (ystr);
+                } else {
+                        string = g_strdup_printf ("%.5g Ã? %.5g %s",
+                                                  frame->ellipse.w*units_per_point,
+                                                  frame->ellipse.h*units_per_point,
+                                                  units_string);
+                }
+                break;
+        case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+                if ( units == LGL_UNITS_INCH ) {
+                        gchar *dstr;
+
+                        dstr = lgl_str_format_fraction (2.0*frame->round.r*units_per_point);
+                        string = g_strdup_printf ("%s %s %s",
+                                                  dstr, units_string,
+                                                  _("diameter"));
+                        g_free (dstr);
+                } else {
+                        string = g_strdup_printf ("%.5g %s %s",
+                                                  2.0*frame->round.r*units_per_point,
+                                                  units_string,
+                                                  _("diameter"));
+                }
+                break;
+        case LGL_TEMPLATE_FRAME_SHAPE_CD:
+                if ( units == LGL_UNITS_INCH ) {
+                        gchar *dstr;
+
+                        dstr = lgl_str_format_fraction (2.0*frame->cd.r1*units_per_point);
+                        string = g_strdup_printf ("%s %s %s",
+                                                  dstr, units_string,
+                                                  _("diameter"));
+                        g_free (dstr);
+                } else {
+                        string = g_strdup_printf ("%.5g %s %s",
+                                                  2.0*frame->cd.r1*units_per_point,
+                                                  units_string,
+                                                  _("diameter"));
+                }
+                break;
+        default:
+                break;
+        }
+
+        return string;
+}
+
+
+/**
  * lgl_template_frame_get_origins:
  * @frame: #lglTemplateFrame structure to query
  *
diff --git a/libglabels/template.h b/libglabels/template.h
index 6adfa83..a3c0111 100644
--- a/libglabels/template.h
+++ b/libglabels/template.h
@@ -22,6 +22,7 @@
 #define __LGL_TEMPLATE_H__
 
 #include <glib.h>
+#include "units.h"
 
 G_BEGIN_DECLS
 
@@ -285,19 +286,24 @@ struct _lglTemplateOrigin {
 /* 
  * Template query functions
  */
-gchar                     *lgl_template_get_name             (const lglTemplate   *template);
+gchar                     *lgl_template_get_name                (const lglTemplate   *template);
 
-gboolean                   lgl_template_do_templates_match   (const lglTemplate   *template1,
-                                                              const lglTemplate   *template2);
+gboolean                   lgl_template_do_templates_match      (const lglTemplate   *template1,
+                                                                 const lglTemplate   *template2);
 
-gboolean                   lgl_template_does_brand_match     (const lglTemplate   *template,
-                                                              const gchar         *brand);
+gboolean                   lgl_template_does_brand_match        (const lglTemplate   *template,
+                                                                 const gchar         *brand);
+
+gboolean                   lgl_template_does_page_size_match    (const lglTemplate   *template,
+                                                                 const gchar         *paper_id);
+
+gboolean                   lgl_template_does_category_match     (const lglTemplate   *template,
+                                                                 const gchar         *category_id);
+
+gboolean                   lgl_template_are_templates_identical (const lglTemplate   *template1,
+                                                                 const lglTemplate   *template2);
 
-gboolean                   lgl_template_does_page_size_match (const lglTemplate   *template,
-                                                              const gchar         *paper_id);
 
-gboolean                   lgl_template_does_category_match  (const lglTemplate   *template,
-                                                              const gchar         *category_id);
 
 
 /*
@@ -311,6 +317,13 @@ gint                 lgl_template_frame_get_n_labels   (const lglTemplateFrame
 
 lglTemplateOrigin   *lgl_template_frame_get_origins    (const lglTemplateFrame    *frame);
 
+gchar               *lgl_template_frame_get_layout_description (const lglTemplateFrame *frame);
+
+gchar               *lgl_template_frame_get_size_description   (const lglTemplateFrame *frame,
+                                                                lglUnits                units);
+
+
+
 
 /*
  * Template Construction
diff --git a/src/Makefile.am b/src/Makefile.am
index cf0b81a..49e6e0e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -162,8 +162,12 @@ glabels_3_SOURCES = 			\
 	mini-preview-pixbuf.h		\
 	mini-preview-pixbuf-cache.c	\
 	mini-preview-pixbuf-cache.h	\
-	media-select.c			\
-	media-select.h			\
+	media-combo.c			\
+	media-combo.h			\
+	media-combo-menu.c		\
+	media-combo-menu.h		\
+	media-combo-menu-item.c		\
+	media-combo-menu-item.h		\
 	message-bar.c			\
 	message-bar.h			\
 	template-history.c		\
diff --git a/src/media-combo-menu-item.c b/src/media-combo-menu-item.c
new file mode 100644
index 0000000..0c3225f
--- /dev/null
+++ b/src/media-combo-menu-item.c
@@ -0,0 +1,178 @@
+/*
+ *  media-combo-menu-item.c
+ *  Copyright (C) 2010  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "media-combo-menu-item.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <libglabels/libglabels.h>
+#include "mini-preview-pixbuf-cache.h"
+#include "prefs.h"
+#include "str-util.h"
+#include "marshal.h"
+
+
+
+/*===========================================*/
+/* Private macros and constants.             */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private types                             */
+/*===========================================*/
+
+struct _glMediaComboMenuItemPrivate {
+
+        gchar *name;
+
+};
+
+
+/*===========================================*/
+/* Private globals                           */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Local function prototypes                 */
+/*===========================================*/
+
+static void   gl_media_combo_menu_item_finalize    (GObject                *object);
+
+
+/****************************************************************************/
+/* Boilerplate Object stuff.                                                */
+/****************************************************************************/
+G_DEFINE_TYPE (glMediaComboMenuItem, gl_media_combo_menu_item, GTK_TYPE_MENU_ITEM);
+
+
+/*****************************************************************************/
+/* Class Init Function.                                                      */
+/*****************************************************************************/
+static void
+gl_media_combo_menu_item_class_init (glMediaComboMenuItemClass *class)
+{
+	GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
+
+        gl_media_combo_menu_item_parent_class = g_type_class_peek_parent (class);
+
+	gobject_class->finalize = gl_media_combo_menu_item_finalize;
+}
+
+
+/*****************************************************************************/
+/* Object Instance Init Function.                                            */
+/*****************************************************************************/
+static void
+gl_media_combo_menu_item_init (glMediaComboMenuItem *this)
+{
+	this->priv = g_new0 (glMediaComboMenuItemPrivate, 1);
+}
+
+
+/*****************************************************************************/
+/* Finalize Method.                                                          */
+/*****************************************************************************/
+static void
+gl_media_combo_menu_item_finalize (GObject *object)
+{
+	glMediaComboMenuItem *this = GL_MEDIA_COMBO_MENU_ITEM (object);
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GL_IS_MEDIA_COMBO_MENU_ITEM (object));
+
+        g_free (this->priv->name);
+	g_free (this->priv);
+
+	G_OBJECT_CLASS (gl_media_combo_menu_item_parent_class)->finalize (object);
+}
+
+
+/*****************************************************************************/
+/** New Object Generator.                                                    */
+/*****************************************************************************/
+GtkWidget *
+gl_media_combo_menu_item_new (gchar *name)
+{
+	glMediaComboMenuItem *this;
+        GtkWidget            *hbox;
+        GtkWidget            *preview;
+        GtkWidget            *label;
+        GdkPixbuf            *pixbuf;
+        lglTemplate          *template;
+        lglTemplateFrame     *frame;
+        gchar                *size_string;
+        gchar                *layout_string;
+        gchar                *label_markup;
+
+	this = g_object_new (GL_TYPE_MEDIA_COMBO_MENU_ITEM, NULL);
+
+        this->priv->name = g_strdup (name);
+
+        hbox = gtk_hbox_new (FALSE, 6);
+        gtk_container_add (GTK_CONTAINER (this), hbox);
+
+        pixbuf = gl_mini_preview_pixbuf_cache_get_pixbuf (name);
+        preview = gtk_image_new_from_pixbuf (pixbuf);
+        gtk_box_pack_start (GTK_BOX (hbox), preview, FALSE, FALSE, 0);
+        g_object_unref (G_OBJECT (pixbuf));
+
+        template      = lgl_db_lookup_template_from_name (name);
+        frame         = (lglTemplateFrame *)template->frames->data;
+        size_string   = lgl_template_frame_get_size_description (frame, gl_prefs_model_get_units (gl_prefs));
+        layout_string = lgl_template_frame_get_layout_description (frame);
+        label_markup  = g_strdup_printf ("<b>%s: %s</b>\n%s\n%s",
+                                         name, template->description, size_string, layout_string);
+        g_free (size_string);
+        g_free (layout_string);
+        lgl_template_free (template);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label), label_markup);
+        g_free (label_markup);
+        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+	return GTK_WIDGET (this);
+}
+
+
+/*****************************************************************************/
+/* Get family.                                                               */
+/*****************************************************************************/
+gchar *
+gl_media_combo_menu_item_get_name (glMediaComboMenuItem *this)
+{
+        return g_strdup (this->priv->name);
+}
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/media-combo-menu-item.h b/src/media-combo-menu-item.h
new file mode 100644
index 0000000..4aa6ad4
--- /dev/null
+++ b/src/media-combo-menu-item.h
@@ -0,0 +1,75 @@
+/*
+ *  media-combo-menu-item.h
+ *  Copyright (C) 2010  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MEDIA_COMBO_MENU_ITEM_H__
+#define __MEDIA_COMBO_MENU_ITEM_H__
+
+
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define GL_TYPE_MEDIA_COMBO_MENU_ITEM (gl_media_combo_menu_item_get_type ())
+#define GL_MEDIA_COMBO_MENU_ITEM(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_MEDIA_COMBO_MENU_ITEM, glMediaComboMenuItem ))
+#define GL_MEDIA_COMBO_MENU_ITEM_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MEDIA_COMBO_MENU_ITEM, glMediaComboMenuItemClass))
+#define GL_IS_MEDIA_COMBO_MENU_ITEM(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MEDIA_COMBO_MENU_ITEM))
+#define GL_IS_MEDIA_COMBO_MENU_ITEM_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MEDIA_COMBO_MENU_ITEM))
+
+typedef struct _glMediaComboMenuItem        glMediaComboMenuItem;
+typedef struct _glMediaComboMenuItemPrivate glMediaComboMenuItemPrivate;
+typedef struct _glMediaComboMenuItemClass   glMediaComboMenuItemClass;
+
+struct _glMediaComboMenuItem {
+	GtkMenuItem            parent_widget;
+
+	glMediaComboMenuItemPrivate *priv;
+};
+
+struct _glMediaComboMenuItemClass {
+	GtkMenuItemClass       parent_class;
+};
+
+
+GType      gl_media_combo_menu_item_get_type   (void) G_GNUC_CONST;
+
+GtkWidget *gl_media_combo_menu_item_new        (gchar                *name);
+
+gchar     *gl_media_combo_menu_item_get_name   (glMediaComboMenuItem *this);
+
+
+G_END_DECLS
+
+#endif /* __MEDIA_COMBO_MENU_ITEM_H__ */
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/media-combo-menu.c b/src/media-combo-menu.c
new file mode 100644
index 0000000..4f117d5
--- /dev/null
+++ b/src/media-combo-menu.c
@@ -0,0 +1,332 @@
+/*
+ *  media-combo-menu.c
+ *  Copyright (C) 2010  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "media-combo-menu.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <libglabels/libglabels.h>
+#include "media-combo-menu-item.h"
+#include "template-history.h"
+#include "marshal.h"
+
+
+/*===========================================*/
+/* Private macros and constants.             */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private types                             */
+/*===========================================*/
+
+struct _glMediaComboMenuPrivate {
+
+        gchar     *media;
+
+        GtkWidget *recent_menu_item;
+        GtkWidget *recent_sub_menu;
+
+};
+
+enum {
+        MEDIA_CHANGED,
+        LAST_SIGNAL
+};
+
+
+/*===========================================*/
+/* Private globals                           */
+/*===========================================*/
+
+static guint signals[LAST_SIGNAL] = {0};
+
+
+/*===========================================*/
+/* Local function prototypes                 */
+/*===========================================*/
+
+static void       gl_media_combo_menu_finalize (GObject             *object);
+
+static void       menu_item_activate_cb        (glMediaComboMenuItem *item,
+                                                glMediaComboMenu     *this);
+
+static GtkWidget *new_brand_sub_menu           (glMediaComboMenu     *this,
+                                                const gchar          *paper_id,
+                                                const GList          *brand_list);
+
+static GtkWidget *new_part_sub_menu            (glMediaComboMenu     *this,
+                                                const GList          *part_list);
+
+static void       media_history_changed_cb     (glMediaComboMenu     *this);
+
+
+
+/****************************************************************************/
+/* Boilerplate Object stuff.                                                */
+/****************************************************************************/
+G_DEFINE_TYPE (glMediaComboMenu, gl_media_combo_menu, GTK_TYPE_MENU);
+
+
+/*****************************************************************************/
+/* Class Init Function.                                                      */
+/*****************************************************************************/
+static void
+gl_media_combo_menu_class_init (glMediaComboMenuClass *class)
+{
+	GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
+
+        gl_media_combo_menu_parent_class = g_type_class_peek_parent (class);
+
+	gobject_class->finalize = gl_media_combo_menu_finalize;
+
+        signals[MEDIA_CHANGED] =
+                g_signal_new ("media_changed",
+                              G_OBJECT_CLASS_TYPE (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (glMediaComboMenuClass, media_changed),
+                              NULL, NULL,
+                              gl_marshal_VOID__VOID,
+                              G_TYPE_NONE, 0);
+}
+
+
+/*****************************************************************************/
+/* Object Instance Init Function.                                            */
+/*****************************************************************************/
+static void
+gl_media_combo_menu_init (glMediaComboMenu *this)
+{
+        GtkWidget    *menu_item;
+        GtkWidget    *sub_menu;
+        const GList  *list;
+        GList        *paper_id_list, *p_id;
+        gchar        *paper_id, *paper_name;
+        GList        *brand_list;
+
+	this->priv = g_new0 (glMediaComboMenuPrivate, 1);
+
+
+        menu_item = gtk_menu_item_new_with_label (_("Recent templates"));
+        gtk_menu_shell_append (GTK_MENU_SHELL (this), menu_item);
+
+        list = gl_template_history_model_get_name_list (gl_template_history);
+        sub_menu = new_part_sub_menu (this, list);
+        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), sub_menu);
+        gtk_widget_set_sensitive (menu_item, list != NULL);
+
+        this->priv->recent_menu_item = menu_item;
+        this->priv->recent_sub_menu  = sub_menu;
+
+        menu_item = gtk_separator_menu_item_new ();
+        gtk_menu_shell_append (GTK_MENU_SHELL (this), menu_item);
+
+        paper_id_list = lgl_db_get_paper_id_list ();
+
+        for ( p_id = paper_id_list; p_id; p_id = p_id->next )
+        {
+                paper_id = p_id->data;
+                paper_name = lgl_db_lookup_paper_name_from_id (paper_id);
+
+                brand_list = lgl_db_get_brand_list (paper_id, NULL);
+                if ( brand_list )
+                {
+                        menu_item = gtk_menu_item_new_with_label (paper_name);
+                        gtk_menu_shell_append (GTK_MENU_SHELL (this), menu_item);
+
+                        sub_menu = new_brand_sub_menu (this, paper_id, brand_list);
+                        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), sub_menu);
+                }
+                lgl_db_free_brand_list ( brand_list );
+        }
+
+        lgl_db_free_paper_id_list (paper_id_list);
+
+        g_signal_connect_swapped (gl_template_history, "changed",
+                                  G_CALLBACK (media_history_changed_cb), this);
+
+}
+
+
+/*****************************************************************************/
+/* Finalize Method.                                                          */
+/*****************************************************************************/
+static void
+gl_media_combo_menu_finalize (GObject *object)
+{
+	glMediaComboMenu *this = GL_MEDIA_COMBO_MENU (object);
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GL_IS_MEDIA_COMBO_MENU (object));
+
+	g_free (this->priv);
+
+	G_OBJECT_CLASS (gl_media_combo_menu_parent_class)->finalize (object);
+}
+
+
+/*****************************************************************************/
+/** New Object Generator.                                                    */
+/*****************************************************************************/
+GtkWidget *
+gl_media_combo_menu_new (void)
+{
+	glMediaComboMenu *this;
+
+	this = g_object_new (gl_media_combo_menu_get_type (), NULL);
+
+	return GTK_WIDGET (this);
+}
+
+
+/*****************************************************************************/
+/* menu_item activate callback.                                              */
+/*****************************************************************************/
+static void menu_item_activate_cb (glMediaComboMenuItem *item,
+                                   glMediaComboMenu     *this)
+{
+        this->priv->media = gl_media_combo_menu_item_get_name (item);
+
+        g_signal_emit (this, signals[MEDIA_CHANGED], 0);
+
+        gtk_widget_hide (GTK_WIDGET (this));
+}
+
+
+/*****************************************************************************/
+/* Get media name.                                                           */
+/*****************************************************************************/
+gchar *
+gl_media_combo_menu_get_name (glMediaComboMenu *this)
+{
+        return g_strdup (this->priv->media);
+}
+
+
+/*****************************************************************************/
+/* Create a new brand sub menu from media list.                              */
+/*****************************************************************************/
+static GtkWidget *
+new_brand_sub_menu (glMediaComboMenu *this,
+                    const gchar      *paper_id,
+                    const GList      *brand_list)
+{
+        GtkWidget   *menu;
+        GtkWidget   *menu_item;
+        GtkWidget    *sub_menu;
+        GList       *p_brand;
+        gchar       *brand;
+        GList       *part_list;
+
+        menu = gtk_menu_new ();
+
+        for ( p_brand = (GList *)brand_list; p_brand; p_brand = p_brand->next )
+        {
+                brand = p_brand->data;
+
+                part_list = lgl_db_get_template_name_list_all (brand, paper_id, NULL);
+                if ( part_list )
+                {
+                        menu_item = gtk_menu_item_new_with_label (brand);
+                        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+                        sub_menu = new_part_sub_menu (this, part_list);
+                        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), sub_menu);
+                }
+                lgl_db_free_brand_list ( part_list );
+        }
+
+        gtk_widget_show (menu);
+
+        return menu;
+}
+
+
+/*****************************************************************************/
+/* Create a new part sub menu from part list.                                */
+/*****************************************************************************/
+static GtkWidget *
+new_part_sub_menu (glMediaComboMenu *this,
+                   const GList      *part_list)
+{
+        GtkWidget   *menu;
+        GtkWidget   *menu_item;
+        GList       *p;
+
+        menu = gtk_menu_new ();
+
+        for ( p = (GList *)part_list; p != NULL; p = p->next )
+        {
+                menu_item = gl_media_combo_menu_item_new (p->data);
+                gtk_widget_show_all (menu_item);
+                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+                g_signal_connect (menu_item, "activate",
+                                  G_CALLBACK (menu_item_activate_cb), this);
+        }
+
+        gtk_widget_show (menu);
+        return menu;
+}
+
+
+/*****************************************************************************/
+/* Media history changed callback.                                           */
+/*****************************************************************************/
+static void
+media_history_changed_cb (glMediaComboMenu     *this)
+{
+        GList *list;
+
+        /*
+         * Remove old sub menu
+         */
+        gtk_menu_item_set_submenu (GTK_MENU_ITEM (this->priv->recent_menu_item),
+                                   NULL);
+
+        /*
+         * Build new sub menu
+         */
+        list = gl_template_history_model_get_name_list (gl_template_history);
+        this->priv->recent_sub_menu = new_part_sub_menu (this, list);
+
+        /*
+         * Attach to top-level menu item
+         */
+        gtk_menu_item_set_submenu (GTK_MENU_ITEM (this->priv->recent_menu_item),
+                                   this->priv->recent_sub_menu);
+        gtk_widget_set_sensitive (this->priv->recent_menu_item, list != NULL);
+
+        gl_template_history_model_free_name_list (list);
+}
+
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/media-combo-menu.h b/src/media-combo-menu.h
new file mode 100644
index 0000000..5c83e58
--- /dev/null
+++ b/src/media-combo-menu.h
@@ -0,0 +1,83 @@
+/*
+ *  media-combo-menu.h
+ *  Copyright (C) 2010  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MEDIA_COMBO_MENU_H__
+#define __MEDIA_COMBO_MENU_H__
+
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define GL_TYPE_MEDIA_COMBO_MENU (gl_media_combo_menu_get_type ())
+#define GL_MEDIA_COMBO_MENU(obj) \
+        (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_MEDIA_COMBO_MENU, glMediaComboMenu ))
+#define GL_MEDIA_COMBO_MENU_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MEDIA_COMBO_MENU, glMediaComboMenuClass))
+#define GL_IS_MEDIA_COMBO_MENU(obj) \
+        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MEDIA_COMBO_MENU))
+#define GL_IS_MEDIA_COMBO_MENU_CLASS(klass) \
+        (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MEDIA_COMBO_MENU))
+
+typedef struct _glMediaComboMenu        glMediaComboMenu;
+typedef struct _glMediaComboMenuPrivate glMediaComboMenuPrivate;
+typedef struct _glMediaComboMenuClass   glMediaComboMenuClass;
+
+struct _glMediaComboMenu {
+	GtkMenu                  parent_widget;
+
+	glMediaComboMenuPrivate *priv;
+};
+
+struct _glMediaComboMenuClass {
+	GtkMenuClass             parent_class;
+
+        /*
+         * Signals
+         */
+        void (*media_changed) (glMediaComboMenu *object,
+                               gpointer          user_data);
+
+};
+
+
+GType      gl_media_combo_menu_get_type     (void) G_GNUC_CONST;
+
+GtkWidget *gl_media_combo_menu_new          (void);
+
+gchar     *gl_media_combo_menu_get_name     (glMediaComboMenu *this);
+
+
+G_END_DECLS
+
+
+#endif /* __MEDIA_COMBO_MENU_H__ */
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
+
diff --git a/src/media-combo.c b/src/media-combo.c
new file mode 100644
index 0000000..6c7104e
--- /dev/null
+++ b/src/media-combo.c
@@ -0,0 +1,345 @@
+/*
+ *  media-combo.c
+ *  Copyright (C) 2010  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "media-combo.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "media-combo-menu.h"
+#include "marshal.h"
+
+
+
+/*========================================================*/
+/* Private types.                                         */
+/*========================================================*/
+
+/** GL_MEDIA_COMBO Private fields */
+struct _glMediaComboPrivate {
+
+        gchar      *name;
+
+        GtkWidget  *label;
+
+        GtkWidget  *menu;
+};
+
+enum {
+        CHANGED,
+        LAST_SIGNAL
+};
+
+
+/*========================================================*/
+/* Private globals.                                       */
+/*========================================================*/
+
+static guint signals[LAST_SIGNAL] = {0};
+
+
+/*========================================================*/
+/* Private function prototypes.                           */
+/*========================================================*/
+
+static void gl_media_combo_finalize      (GObject             *object);
+
+static gboolean
+button_press_event_cb   (GtkWidget         *widget,
+                         GdkEventButton    *event,
+                         glMediaCombo      *this);
+
+static void
+menu_media_changed_cb   (glMediaComboMenu  *menu,
+                         glMediaCombo      *this);
+
+static void
+menu_selection_done_cb  (GtkMenuShell      *object,
+                         glMediaCombo      *this);
+
+
+/*****************************************************************************/
+/* Object infrastructure.                                                    */
+/*****************************************************************************/
+G_DEFINE_TYPE (glMediaCombo, gl_media_combo, GTK_TYPE_TOGGLE_BUTTON);
+
+
+/*****************************************************************************/
+/* Class Init Function.                                                      */
+/*****************************************************************************/
+static void
+gl_media_combo_class_init (glMediaComboClass *class)
+{
+        GObjectClass      *gobject_class = (GObjectClass *) class;
+
+        gl_media_combo_parent_class = g_type_class_peek_parent (class);
+
+        gobject_class->finalize = gl_media_combo_finalize;
+
+        signals[CHANGED] =
+                g_signal_new ("changed",
+                              G_OBJECT_CLASS_TYPE (gobject_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (glMediaComboClass, changed),
+                              NULL, NULL,
+                              gl_marshal_VOID__VOID,
+                              G_TYPE_NONE, 0);
+}
+
+
+/*****************************************************************************/
+/* Object Instance Init Function.                                            */
+/*****************************************************************************/
+static void
+gl_media_combo_init (glMediaCombo *this)
+{
+        GtkWidget *hbox;
+        GtkWidget *arrow;
+
+        this->priv = g_new0 (glMediaComboPrivate, 1);
+
+        hbox = gtk_hbox_new (FALSE, 3);
+        gtk_container_add (GTK_CONTAINER (this), hbox);
+        
+        this->priv->label = gtk_label_new ("");
+        gtk_misc_set_alignment (GTK_MISC (this->priv->label), 0.0, 0.5);
+	gtk_widget_set_size_request (this->priv->label, 180, -1);
+        gtk_box_pack_start (GTK_BOX (hbox), this->priv->label, TRUE, TRUE, 0);
+
+        arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
+        gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
+
+        g_signal_connect (this, "button_press_event",
+                          G_CALLBACK(button_press_event_cb), this);
+}
+
+
+/*****************************************************************************/
+/* Finalize Method.                                                          */
+/*****************************************************************************/
+static void
+gl_media_combo_finalize (GObject *object)
+{
+        glMediaCombo    *this;
+
+        g_return_if_fail (object && IS_GL_MEDIA_COMBO (object));
+        this = GL_MEDIA_COMBO (object);
+
+        g_free (this->priv->name);
+        g_object_ref_sink (this->priv->menu);
+        g_free (this->priv);
+
+        G_OBJECT_CLASS (gl_media_combo_parent_class)->finalize (object);
+}
+
+
+/*****************************************************************************/
+/** New Object Generator.                                                    */
+/*****************************************************************************/
+GtkWidget *
+gl_media_combo_new (void)
+{
+        glMediaCombo  *this;
+
+        this = g_object_new (TYPE_GL_MEDIA_COMBO, NULL);
+
+        this->priv->menu = gl_media_combo_menu_new ();
+
+        gtk_widget_show_all (this->priv->menu);
+
+        g_signal_connect (this->priv->menu, "media_changed",
+                          G_CALLBACK (menu_media_changed_cb), this);
+        g_signal_connect (this->priv->menu, "selection_done",
+                          G_CALLBACK (menu_selection_done_cb), this);
+
+        return GTK_WIDGET (this);
+}
+
+
+/*****************************************************************************/
+/* Set media name.                                                           */
+/*****************************************************************************/
+void
+gl_media_combo_set_name (glMediaCombo  *this,
+                         const gchar   *name)
+{
+
+        g_free (this->priv->name);
+        this->priv->name = g_strdup (name);
+
+        gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->name);
+}
+
+
+/*****************************************************************************/
+/* Get media name.                                                           */
+/*****************************************************************************/
+gchar *
+gl_media_combo_get_name (glMediaCombo  *this)
+{
+        return g_strdup (this->priv->name);
+}
+
+
+/*****************************************************************************/
+/* Menu positioning function.                                                */
+/*****************************************************************************/
+static void
+menu_position_function (GtkMenu       *menu,
+                        gint          *x,
+                        gint          *y,
+                        gboolean      *push_in,
+                        glMediaCombo  *this)
+{
+        GdkScreen          *screen;
+        gint                w_screen, h_screen;
+        GdkWindow          *window;
+        gint                x_window, y_window;
+        GtkAllocation       allocation;
+        gint                x_this, y_this, h_this;
+        GtkRequisition      menu_requisition;
+        gint                h_menu, w_menu;
+
+        /*
+         * Screen size
+         */
+        screen = gtk_widget_get_screen (GTK_WIDGET (this));
+        w_screen = gdk_screen_get_width (screen);
+        h_screen = gdk_screen_get_height (screen);
+
+        /*
+         * Absolute position of "this" window on screen.
+         */
+        window = gtk_widget_get_window (GTK_WIDGET (this));
+        gdk_window_get_origin (window, &x_window, &y_window);
+
+        /*
+         *  Position and size of "this" inside window
+         */
+        gtk_widget_get_allocation (GTK_WIDGET (this), &allocation);
+        x_this = allocation.x;
+        y_this = allocation.y;
+        h_this = allocation.height;
+
+        /*
+         * Size of menu.
+         */
+        gtk_widget_size_request (this->priv->menu, &menu_requisition);
+        h_menu = menu_requisition.height;
+        w_menu = menu_requisition.width;
+
+        /*
+         * Default position anchored to lower left corner of "this".
+         */
+        *x = x_window + x_this;
+        *y = y_window + y_this + h_this;
+                
+        /*
+         * Adjust vertical position if menu if extends past bottom of screen.
+         */
+        if ( (*y + h_menu) > h_screen )
+        {
+                *y = y_window + y_this - h_menu;
+
+                if ( *y < 0 )
+                {
+                        *y = h_screen - h_menu;
+                }
+        }
+
+        /*
+         * Adjust horizontal position if menu if extends past edge of screen.
+         */
+        if ( (*x + w_menu) > w_screen )
+        {
+                *x = w_screen - w_menu;
+        }
+
+
+        *push_in = TRUE;
+}
+
+
+/*****************************************************************************/
+/* Button "button_press_event" callback.                                     */
+/*****************************************************************************/
+static gboolean
+button_press_event_cb (GtkWidget      *widget,
+                       GdkEventButton *event,
+                       glMediaCombo   *this)
+{
+        switch (event->button)
+        {
+
+        case 1:
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), TRUE);
+
+                gtk_menu_popup (GTK_MENU (this->priv->menu),
+                                NULL, NULL,
+                                (GtkMenuPositionFunc)menu_position_function, this,
+                                event->button, event->time);
+                break;
+
+        default:
+                break;
+
+        }
+
+        return FALSE;
+}
+
+
+/*****************************************************************************/
+/* Menu "media changed" callback.                                            */
+/*****************************************************************************/
+static void
+menu_media_changed_cb (glMediaComboMenu     *menu,
+                       glMediaCombo         *this)
+{
+        this->priv->name = gl_media_combo_menu_get_name (menu);
+
+        gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->name);
+
+        g_signal_emit (this, signals[CHANGED], 0);
+}
+
+
+/*****************************************************************************/
+/* Menu "selection done" callback.                                           */
+/*****************************************************************************/
+static void
+menu_selection_done_cb (GtkMenuShell         *object,
+                        glMediaCombo         *this)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), FALSE);
+}
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/media-combo.h b/src/media-combo.h
new file mode 100644
index 0000000..c413d14
--- /dev/null
+++ b/src/media-combo.h
@@ -0,0 +1,84 @@
+/*
+ *  media-combo.h
+ *  Copyright (C) 2009  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GL_MEDIA_COMBO_H__
+#define __GL_MEDIA_COMBO_H__
+
+
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define TYPE_GL_MEDIA_COMBO              (gl_media_combo_get_type ())
+#define GL_MEDIA_COMBO(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_GL_MEDIA_COMBO, glMediaCombo))
+#define GL_MEDIA_COMBO_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_GL_MEDIA_COMBO, glMediaComboClass))
+#define IS_GL_MEDIA_COMBO(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_GL_MEDIA_COMBO))
+#define IS_GL_MEDIA_COMBO_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_GL_MEDIA_COMBO))
+#define GL_MEDIA_COMBO_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_GL_MEDIA_COMBO, glMediaComboClass))
+
+
+typedef struct _glMediaCombo          glMediaCombo;
+typedef struct _glMediaComboPrivate   glMediaComboPrivate;
+typedef struct _glMediaComboClass     glMediaComboClass;
+
+
+struct _glMediaCombo {
+        GtkToggleButton               parent;
+
+        glMediaComboPrivate          *priv;
+};
+
+struct _glMediaComboClass {
+        GtkToggleButtonClass          parent_class;
+
+        /*
+         * Signals
+         */
+        void (*changed) (glMediaCombo *object,
+                         gpointer     user_data);
+
+};
+
+
+GType            gl_media_combo_get_type          (void) G_GNUC_CONST;
+
+GtkWidget       *gl_media_combo_new               (void);
+
+void             gl_media_combo_set_name          (glMediaCombo   *this,
+                                                   const gchar    *name);
+
+gchar           *gl_media_combo_get_name          (glMediaCombo   *this);
+
+
+G_END_DECLS
+
+#endif /* __GL_COLOR_COMBO_H__ */
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/mini-preview.c b/src/mini-preview.c
index 2b7984e..abbc104 100644
--- a/src/mini-preview.c
+++ b/src/mini-preview.c
@@ -40,6 +40,8 @@
 #define MARGIN 2
 #define SHADOW_OFFSET 3
 
+#define ARROW_SCALE 0.35
+#define ARROW_RGBA_ARGS 1.0, 0.0, 0.0, 0.05
 
 /*===========================================*/
 /* Private types                             */
@@ -73,6 +75,9 @@ struct _glMiniPreviewPrivate {
 	gint            last_i;
 	gint            prev_i;
 
+        gboolean        draw_arrow_flag;
+        gboolean        rotate_flag;
+
         gboolean        update_scheduled_flag;
 
         glLabel        *label;
@@ -139,6 +144,11 @@ static void     draw_labels                    (glMiniPreview          *this,
 						cairo_t                *cr,
 						lglTemplate            *template,
 						gdouble                 line_width);
+static void     draw_arrow                     (glMiniPreview          *this,
+                                                cairo_t                *cr,
+                                                gdouble                 width,
+                                                gdouble                 height);
+
 static void     draw_rich_preview              (glMiniPreview          *this,
 						cairo_t                *cr);
 
@@ -398,6 +408,36 @@ gl_mini_preview_highlight_range (glMiniPreview *this,
 
 
 /****************************************************************************/
+/* Set draw arrow.                                                          */
+/****************************************************************************/
+void
+gl_mini_preview_set_draw_arrow (glMiniPreview     *this,
+                                gboolean           draw_arrow_flag)
+{
+        if ( draw_arrow_flag != this->priv->draw_arrow_flag )
+        {
+                this->priv->draw_arrow_flag = draw_arrow_flag;
+                redraw (this);
+        }
+}
+
+
+/****************************************************************************/
+/* Set rotate flag.                                                         */
+/****************************************************************************/
+void
+gl_mini_preview_set_rotate (glMiniPreview     *this,
+                            gboolean           rotate_flag)
+{
+        if ( rotate_flag != this->priv->rotate_flag )
+        {
+                this->priv->rotate_flag = rotate_flag;
+                redraw (this);
+        }
+}
+
+
+/****************************************************************************/
 /* Set label.                                                               */
 /****************************************************************************/
 void
@@ -858,7 +898,13 @@ draw (glMiniPreview  *this,
 			    template->page_width, template->page_height,
 			    1.0/scale);
 
-		draw_labels (this, cr, template, 1.0/scale);
+		draw_labels (this, cr, template, 2.0/scale);
+
+                if (this->priv->draw_arrow_flag)
+                {
+                        draw_arrow (this, cr,
+                                    template->page_width, template->page_height);
+                }
 
                 if (this->priv->label)
                 {
@@ -971,7 +1017,7 @@ draw_labels (glMiniPreview *this,
         if (this->priv->label)
         {
                 /* Outlines are more subtle when doing a rich preview. */
-                outline_color   = gl_color_set_opacity (base_color, 0.05);
+                outline_color   = gl_color_set_opacity (base_color, 0.25);
         }
         else
         {
@@ -1008,6 +1054,46 @@ draw_labels (glMiniPreview *this,
 
 
 /*--------------------------------------------------------------------------*/
+/* Draw arrow to indicate top of labels.                                    */
+/*--------------------------------------------------------------------------*/
+static void
+draw_arrow  (glMiniPreview      *this,
+             cairo_t            *cr,
+             gdouble             width,
+             gdouble             height)
+{
+        gdouble min;
+
+        cairo_save (cr);
+
+        min = MIN (width, height);
+
+        cairo_translate (cr, width/2, height/2);
+        cairo_scale (cr, 1, -1);
+        if ( this->priv->rotate_flag )
+        {
+                cairo_rotate (cr, -M_PI/2.0);
+        }
+
+        cairo_new_path (cr);
+        cairo_move_to (cr, 0, -min*ARROW_SCALE/2);
+        cairo_line_to (cr, 0, min*ARROW_SCALE);
+
+        cairo_new_sub_path (cr);
+        cairo_move_to (cr, -min*ARROW_SCALE/2, min*ARROW_SCALE/2);
+        cairo_line_to (cr, 0, min*ARROW_SCALE);
+        cairo_line_to (cr, min*ARROW_SCALE/2, min*ARROW_SCALE/2);
+
+        cairo_set_line_width (cr, 0.25*min*ARROW_SCALE);
+        cairo_set_source_rgba (cr, ARROW_RGBA_ARGS);
+
+        cairo_stroke (cr);
+
+        cairo_restore (cr);
+}
+
+
+/*--------------------------------------------------------------------------*/
 /* Draw rich preview using print renderers.                                 */
 /*--------------------------------------------------------------------------*/
 static void
diff --git a/src/mini-preview.h b/src/mini-preview.h
index caf77eb..d2d9210 100644
--- a/src/mini-preview.h
+++ b/src/mini-preview.h
@@ -83,6 +83,12 @@ void       gl_mini_preview_highlight_range     (glMiniPreview     *this,
                                                 gint               first_label,
                                                 gint               last_label);
 
+void       gl_mini_preview_set_draw_arrow      (glMiniPreview     *this,
+                                                gboolean           draw_arrow_flag);
+
+void       gl_mini_preview_set_rotate          (glMiniPreview     *this,
+                                                gboolean           rotate_flag);
+
 
 /*
  * If label is set, the preview will be rich.
diff --git a/src/new-label-dialog.c b/src/new-label-dialog.c
index f01d0fb..ffea6dc 100644
--- a/src/new-label-dialog.c
+++ b/src/new-label-dialog.c
@@ -26,21 +26,43 @@
 #include <gtk/gtk.h>
 
 #include "hig.h"
-#include "media-select.h"
+#include "builder-util.h"
+#include "prefs.h"
+#include "template-history.h"
+#include "mini-preview.h"
+#include "media-combo.h"
 #include "rotate-label-button.h"
 
 #include "debug.h"
 
 
+#define MINI_PREVIEW_MIN_HEIGHT 300
+#define MINI_PREVIEW_MIN_WIDTH  256
+
+
 /*===========================================*/
 /* Private data types                        */
 /*===========================================*/
 
 struct _glNewLabelDialogPrivate {
 
-	GtkWidget  *media_select;
-	GtkWidget  *rotate_label;
+        GtkBuilder *builder;
+
+	GtkWidget  *preview_vbox;
+        GtkWidget  *combo_hbox;
+	GtkWidget  *rotate_hbox;
 
+        GtkWidget  *desc_label;
+        GtkWidget  *page_size_label;
+        GtkWidget  *label_size_label;
+        GtkWidget  *layout_label;
+        GtkWidget  *vendor_label;
+        GtkWidget  *part_label;
+        GtkWidget  *similar_label;
+
+        GtkWidget  *preview;
+        GtkWidget  *combo;
+        GtkWidget  *rotate_button;
 };
 
 
@@ -55,8 +77,13 @@ struct _glNewLabelDialogPrivate {
 
 static void       gl_new_label_dialog_finalize        (GObject           *object);
 
-static void       template_changed_cb                 (glMediaSelect     *select,
-						       gpointer           data);
+static void       combo_changed_cb                    (glNewLabelDialog  *this);
+static void       rotate_toggled_cb                   (glNewLabelDialog  *this);
+
+static gchar     *get_default_name                    (void);
+
+static void       set_info                            (glNewLabelDialog  *this,
+                                                       const gchar       *name);
 
 
 /*****************************************************************************/
@@ -77,7 +104,7 @@ gl_new_label_dialog_class_init (glNewLabelDialogClass *class)
 	
   	gl_new_label_dialog_parent_class = g_type_class_peek_parent (class);
 
-  	object_class->finalize = gl_new_label_dialog_finalize;  	
+  	object_class->finalize = gl_new_label_dialog_finalize;
 }
 
 
@@ -85,59 +112,84 @@ gl_new_label_dialog_class_init (glNewLabelDialogClass *class)
 /* Object Instance Init Function.                                            */
 /*****************************************************************************/
 static void
-gl_new_label_dialog_init (glNewLabelDialog *dialog)
+gl_new_label_dialog_init (glNewLabelDialog *this)
 {
 	GtkWidget    *vbox;
-        GtkWidget    *label;
-	GtkWidget    *frame;
-	gchar        *name;
+        GtkBuilder   *builder;
+        gchar        *builder_filename;
+        static gchar *object_ids[] = { "new_label_dialog_hbox", NULL };
+        GError       *error = NULL;
+        GtkWidget    *new_label_dialog_hbox;
+        gchar        *name;
 
 	gl_debug (DEBUG_FILE, "START");
 
-	g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (dialog));
+	g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this));
 
-	dialog->priv = g_new0 (glNewLabelDialogPrivate, 1);
+	this->priv = g_new0 (glNewLabelDialogPrivate, 1);
 
-	gtk_container_set_border_width (GTK_CONTAINER (dialog), GL_HIG_PAD1);
+	gtk_container_set_border_width (GTK_CONTAINER (this), GL_HIG_PAD1);
 
-	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+	gtk_dialog_set_has_separator (GTK_DIALOG (this), FALSE);
+	gtk_dialog_add_buttons (GTK_DIALOG (this),
                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                 GTK_STOCK_OK, GTK_RESPONSE_OK,
                                 NULL);
-        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-	gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-
-        vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-
-        label = gtk_label_new (_("<b>Media type</b>"));
-        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-        frame = gtk_frame_new ("");
-        gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
-	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, GL_HIG_PAD1);
-
-	dialog->priv->media_select = gl_media_select_new ();
-        gtk_container_add (GTK_CONTAINER (frame), dialog->priv->media_select);
-
-        label = gtk_label_new (_("<b>Label orientation</b>"));
-        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-        frame = gtk_frame_new ("");
-        gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
-	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
-
-	dialog->priv->rotate_label = gl_rotate_label_button_new ();
-        gtk_container_add (GTK_CONTAINER (frame), dialog->priv->rotate_label);
-
-	/* Sync template name from media select with rotate widget. */
-	name = gl_media_select_get_name (GL_MEDIA_SELECT (dialog->priv->media_select));
-	gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label),
-                                                  name);
-
-	g_signal_connect (G_OBJECT (dialog->priv->media_select), "changed",
-			  G_CALLBACK (template_changed_cb), dialog);
+        gtk_dialog_set_default_response (GTK_DIALOG (this), GTK_RESPONSE_OK);
+	gtk_window_set_destroy_with_parent (GTK_WINDOW (this), TRUE);
+	gtk_window_set_modal (GTK_WINDOW (this), TRUE);
+
+        vbox = gtk_dialog_get_content_area (GTK_DIALOG (this));
+
+
+        builder = gtk_builder_new ();
+        builder_filename = g_build_filename (GLABELS_DATA_DIR, "builder", "new-label-dialog.builder", NULL);
+        gtk_builder_add_objects_from_file (builder, builder_filename, object_ids, &error);
+        g_free (builder_filename);
+	if (error) {
+		g_critical ("%s\n\ngLabels may not be installed correctly!", error->message);
+                g_error_free (error);
+		return;
+	}
+
+        gl_builder_util_get_widgets (builder,
+                                     "new_label_dialog_hbox",  &new_label_dialog_hbox,
+                                     "preview_vbox",           &this->priv->preview_vbox,
+                                     "combo_hbox",             &this->priv->combo_hbox,
+                                     "rotate_hbox",            &this->priv->rotate_hbox,
+                                     "desc_label",             &this->priv->desc_label,
+                                     "page_size_label",        &this->priv->page_size_label,
+                                     "label_size_label",       &this->priv->label_size_label,
+                                     "layout_label",           &this->priv->layout_label,
+                                     "vendor_label",           &this->priv->vendor_label,
+                                     "part_label",             &this->priv->part_label,
+                                     "similar_label",          &this->priv->similar_label,
+                                     NULL);
+
+        gtk_container_add (GTK_CONTAINER (vbox), new_label_dialog_hbox);
+        this->priv->builder = builder;
+
+        this->priv->preview = gl_mini_preview_new (MINI_PREVIEW_MIN_HEIGHT, MINI_PREVIEW_MIN_WIDTH);
+        gl_mini_preview_set_draw_arrow (GL_MINI_PREVIEW (this->priv->preview), TRUE);
+        gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), FALSE);
+        gtk_container_add (GTK_CONTAINER (this->priv->preview_vbox), this->priv->preview);
+
+        this->priv->combo = gl_media_combo_new ();
+        gtk_container_add (GTK_CONTAINER (this->priv->combo_hbox), this->priv->combo);
+
+        this->priv->rotate_button = gl_rotate_label_button_new ();
+        gtk_container_add (GTK_CONTAINER (this->priv->rotate_hbox), this->priv->rotate_button);
+
+	g_signal_connect_swapped (G_OBJECT (this->priv->combo), "changed",
+			  G_CALLBACK (combo_changed_cb), this);
+	g_signal_connect_swapped (G_OBJECT (this->priv->rotate_button), "changed",
+			  G_CALLBACK (rotate_toggled_cb), this);
+
+        name = get_default_name ();
+        gl_media_combo_set_name (GL_MEDIA_COMBO (this->priv->combo), name);
+        gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button), name);
+        g_free (name);
+        combo_changed_cb (this);
 
 	gl_debug (DEBUG_FILE, "END");
 }
@@ -149,15 +201,16 @@ gl_new_label_dialog_init (glNewLabelDialog *dialog)
 static void 
 gl_new_label_dialog_finalize (GObject *object)
 {
-	glNewLabelDialog* dialog = GL_NEW_LABEL_DIALOG (object);;
+	glNewLabelDialog* this = GL_NEW_LABEL_DIALOG (object);;
 	
 	gl_debug (DEBUG_FILE, "START");
 
 	g_return_if_fail (object != NULL);
-	g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (dialog));
-	g_return_if_fail (dialog->priv != NULL);
+	g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this));
+	g_return_if_fail (this->priv != NULL);
 
-	g_free (dialog->priv);
+        g_object_unref (G_OBJECT (this->priv->builder));
+	g_free (this->priv);
 
 	G_OBJECT_CLASS (gl_new_label_dialog_parent_class)->finalize (object);
 
@@ -172,38 +225,33 @@ gl_new_label_dialog_finalize (GObject *object)
 GtkWidget *
 gl_new_label_dialog_new (GtkWindow    *win)
 {
-	GtkWidget *dialog;
+	GtkWidget *this;
 
 	gl_debug (DEBUG_FILE, "");
 
-	dialog = GTK_WIDGET (g_object_new (GL_TYPE_NEW_LABEL_DIALOG, NULL));
+	this = GTK_WIDGET (g_object_new (GL_TYPE_NEW_LABEL_DIALOG, NULL));
 
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), win);
+	gtk_window_set_transient_for (GTK_WINDOW (this), win);
 
-	return dialog;
+	return this;
 }
 
 
 /*---------------------------------------------------------------------------*/
-/* PRIVATE.  New template changed callback.                                  */
+/* PRIVATE.  Template changed callback.                                      */
 /*---------------------------------------------------------------------------*/
 static void
-template_changed_cb (glMediaSelect *select,
-		     gpointer       data)
+combo_changed_cb (glNewLabelDialog  *this)
 {
-	glNewLabelDialog  *dialog = GL_NEW_LABEL_DIALOG (data);
 	gchar             *name;
 
 	gl_debug (DEBUG_FILE, "START");
 
-	name = gl_media_select_get_name (GL_MEDIA_SELECT (select));
+	name = gl_media_combo_get_name (GL_MEDIA_COMBO (this->priv->combo));
 
-	gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label),
-                                                  name);
-
-	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
-					   GTK_RESPONSE_OK,
-					   (name != NULL));
+	gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name);
+        gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button), name);
+        set_info (this, name);
 
 	g_free (name);
 
@@ -211,15 +259,144 @@ template_changed_cb (glMediaSelect *select,
 }
 
 
+/*---------------------------------------------------------------------------*/
+/* PRIVATE.  Rotate toggled callback.                                        */
+/*---------------------------------------------------------------------------*/
+static void
+rotate_toggled_cb (glNewLabelDialog  *this)
+{
+        gboolean state;
+
+	gl_debug (DEBUG_FILE, "START");
+
+        state = gl_rotate_label_button_get_state (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button));
+        gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state);
+
+	gl_debug (DEBUG_FILE, "END");
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE.  Get default template name.                                      */
+/*---------------------------------------------------------------------------*/
+static gchar *
+get_default_name (void)
+{
+        gchar *name = NULL;
+        GList *list;
+
+        list = gl_template_history_model_get_name_list (gl_template_history);
+
+        if ( list )
+        {
+                name = g_strdup (list->data);
+                gl_template_history_model_free_name_list (list);
+        }
+        else
+        {
+                gchar *page_size;
+
+                page_size = gl_prefs_model_get_default_page_size (gl_prefs);
+                list = lgl_db_get_template_name_list_all (NULL, page_size, NULL);
+                g_free (page_size);
+
+                if ( list )
+                {
+                        name = g_strdup (list->data);
+                        lgl_db_free_template_name_list (list);
+                }
+        }
+
+        return name;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE.  Set information labels.                                         */
+/*---------------------------------------------------------------------------*/
+static void
+set_info (glNewLabelDialog  *this,
+          const gchar       *name)
+{
+        lglTemplate          *template;
+        lglTemplateFrame     *frame;
+        lglVendor            *vendor;
+        lglUnits              units;
+        gchar                *page_size_string;
+        gchar                *label_size_string;
+        gchar                *layout_string;
+        GList                *list, *p;
+        GString              *list_string;
+
+        template = lgl_db_lookup_template_from_name (name);
+        frame    = template->frames->data;
+        vendor   = lgl_db_lookup_vendor_from_name (template->brand);
+
+        units    = gl_prefs_model_get_units (gl_prefs);
+
+        page_size_string  = lgl_db_lookup_paper_name_from_id (template->paper_id);
+        label_size_string = lgl_template_frame_get_size_description (frame, units);
+        layout_string     = lgl_template_frame_get_layout_description (frame);
+
+        gtk_label_set_text (GTK_LABEL (this->priv->desc_label),       template->description);
+        gtk_label_set_text (GTK_LABEL (this->priv->page_size_label),  page_size_string);
+        gtk_label_set_text (GTK_LABEL (this->priv->label_size_label), label_size_string);
+        gtk_label_set_text (GTK_LABEL (this->priv->layout_label),     layout_string);
+
+        if ( vendor && vendor->url )
+        {
+                gchar *markup;
+
+                markup = g_strdup_printf ("<a href='%s'>%s</a>", vendor->url, vendor->name);
+                gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), markup);
+                g_free (markup);
+        }
+        else
+        {
+                /* FIXME: Using set_markup instead of set_text to clear out previous link. */
+                gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), template->brand);
+        }
+
+        if ( template->product_url )
+        {
+                gchar *markup;
+
+                markup = g_strdup_printf ("<a href='%s'>%s</a>", template->product_url, template->part);
+                gtk_label_set_markup (GTK_LABEL (this->priv->part_label), markup);
+                g_free (markup);
+        }
+        else
+        {
+                /* FIXME: Using set_markup instead of set_text to clear out previous link. */
+                gtk_label_set_markup (GTK_LABEL (this->priv->part_label), template->part);
+        }
+
+        list = lgl_db_get_similar_template_name_list (name);
+        list_string = g_string_new ("");
+        for ( p = list; p; p = p->next )
+        {
+                g_string_append_printf (list_string, "%s\n", (char *)p->data);
+        }
+        gtk_label_set_text (GTK_LABEL (this->priv->similar_label), list_string->str);
+
+        lgl_db_free_template_name_list (list);
+        g_string_free (list_string, TRUE);
+
+        g_free (page_size_string);
+        g_free (label_size_string);
+        g_free (layout_string);
+}
+
+
 /*****************************************************************************/
 /* Get template name.                                                        */
 /*****************************************************************************/
 gchar *
-gl_new_label_dialog_get_template_name (glNewLabelDialog *dialog)
+gl_new_label_dialog_get_template_name (glNewLabelDialog *this)
 {
 	gchar *name;
 
-	name = gl_media_select_get_name (GL_MEDIA_SELECT (dialog->priv->media_select));
+	name = gl_media_combo_get_name (GL_MEDIA_COMBO (this->priv->combo));
 
 	return name;
 }
@@ -229,10 +406,12 @@ gl_new_label_dialog_get_template_name (glNewLabelDialog *dialog)
 /* Set template name.                                                        */
 /*****************************************************************************/
 void
-gl_new_label_dialog_set_template_name (glNewLabelDialog *dialog,
+gl_new_label_dialog_set_template_name (glNewLabelDialog *this,
 				       gchar            *name)
 {
-	gl_media_select_set_name (GL_MEDIA_SELECT (dialog->priv->media_select), name);
+	gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name);
+	gl_media_combo_set_name (GL_MEDIA_COMBO (this->priv->combo), name);
+        set_info (this, name);
 }
 
 
@@ -240,13 +419,10 @@ gl_new_label_dialog_set_template_name (glNewLabelDialog *dialog,
 /* Get current filter parameters.                                            */
 /*****************************************************************************/
 void
-gl_new_label_dialog_get_filter_parameters (glNewLabelDialog  *dialog,
+gl_new_label_dialog_get_filter_parameters (glNewLabelDialog  *this,
 					   gchar            **page_size_id,
 					   gchar            **category_id)
 {
-	gl_media_select_get_filter_parameters (
-		GL_MEDIA_SELECT (dialog->priv->media_select),
-		page_size_id, category_id);
 }
 
 
@@ -254,13 +430,10 @@ gl_new_label_dialog_get_filter_parameters (glNewLabelDialog  *dialog,
 /* Set current filter parameters.                                            */
 /*****************************************************************************/
 void
-gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *dialog,
+gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *this,
 					   const gchar      *page_size_id,
 					   const gchar      *category_id)
 {
-	gl_media_select_set_filter_parameters (
-		GL_MEDIA_SELECT (dialog->priv->media_select),
-		page_size_id, category_id);
 }
 
 
@@ -268,10 +441,9 @@ gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *dialog,
 /* Get rotate state.                                                         */
 /*****************************************************************************/
 gboolean
-gl_new_label_dialog_get_rotate_state (glNewLabelDialog *dialog)
+gl_new_label_dialog_get_rotate_state (glNewLabelDialog *this)
 {
-	return gl_rotate_label_button_get_state (
-		GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label));
+	return gl_rotate_label_button_get_state (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button));
 }
 
 
@@ -279,11 +451,11 @@ gl_new_label_dialog_get_rotate_state (glNewLabelDialog *dialog)
 /* Set rotate state.                                                         */
 /*****************************************************************************/
 void
-gl_new_label_dialog_set_rotate_state (glNewLabelDialog *dialog,
+gl_new_label_dialog_set_rotate_state (glNewLabelDialog *this,
 				      gboolean          state)
 {
-	gl_rotate_label_button_set_state (
-		GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label), state);
+        gl_rotate_label_button_set_state (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button), state);
+        gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state);
 }
 
 
diff --git a/src/rotate-label-button.c b/src/rotate-label-button.c
index d477edf..cf65db0 100644
--- a/src/rotate-label-button.c
+++ b/src/rotate-label-button.c
@@ -111,7 +111,7 @@ gl_rotate_label_button_init (glRotateLabelButton *this)
 
         this->priv = g_new0 (glRotateLabelButtonPrivate, 1);
 
-        gtk_container_set_border_width (GTK_CONTAINER (this), GL_HIG_PAD2);
+        gtk_box_set_spacing (GTK_BOX (this), GL_HIG_PAD2);
 
         this->priv->no_rotate_radio = gtk_radio_button_new (NULL);
         gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (this->priv->no_rotate_radio),
@@ -134,12 +134,8 @@ gl_rotate_label_button_init (glRotateLabelButton *this)
         gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
         gtk_container_add (GTK_CONTAINER (this->priv->rotate_radio), vbox);
 
-        gtk_box_pack_start (GTK_BOX (this),
-                            this->priv->no_rotate_radio,
-                            FALSE, FALSE, GL_HIG_PAD1);
-        gtk_box_pack_start (GTK_BOX (this),
-                            this->priv->rotate_radio,
-                            FALSE, FALSE, GL_HIG_PAD1);
+        gtk_box_pack_start (GTK_BOX (this), this->priv->no_rotate_radio, FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (this), this->priv->rotate_radio, FALSE, FALSE, 0);
         
         /* Connect signals to controls */
 	g_signal_connect (G_OBJECT (this->priv->no_rotate_radio),
diff --git a/src/str-util.c b/src/str-util.c
index d48ec00..6aa2dd1 100644
--- a/src/str-util.c
+++ b/src/str-util.c
@@ -25,43 +25,6 @@
 #include <string.h>
 #include <math.h>
 
-#define FRAC_EPSILON 0.00005
-
-
-/****************************************************************************/
-/* Create fractional representation of number, if possible.                 */
-/****************************************************************************/
-gchar *
-gl_str_util_fraction_to_string (gdouble x)
-{
-	static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. };
-	gint i;
-	gdouble product, remainder;
-	gint n, d;
-
-	for ( i=0; denom[i] != 0.0; i++ ) {
-		product = x * denom[i];
-		remainder = fabs(product - ((gint)(product+0.5)));
-		if ( remainder < FRAC_EPSILON ) break;
-	}
-
-	if ( denom[i] == 0.0 ) {
-		/* None of our denominators work. */
-		return g_strdup_printf ("%.5g", x);
-	}
-	if ( denom[i] == 1.0 ) {
-		/* Simple integer. */
-		return g_strdup_printf ("%d", (gint)x);
-	}
-	n = (gint)( x * denom[i] + 0.5 );
-	d = (gint)denom[i];
-	if ( n > d ) {
-		return g_strdup_printf ("%d_%d/%d", (n/d), (n%d), d);
-	} else {
-		return g_strdup_printf ("%d/%d", (n%d), d);
-	}
-}
-
 
 /****************************************************************************/
 /* Utilities to deal with PangoAlignment types.                             */
diff --git a/src/str-util.h b/src/str-util.h
index 0253392..76dda77 100644
--- a/src/str-util.h
+++ b/src/str-util.h
@@ -26,8 +26,6 @@
 
 G_BEGIN_DECLS
 
-gchar              *gl_str_util_fraction_to_string    (gdouble            x);
-
 const gchar        *gl_str_util_align_to_string       (PangoAlignment     align);
 PangoAlignment      gl_str_util_string_to_align       (const gchar       *string);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]