[glabels] Created new "New label dialog"
- From: Jim Evins <jimevins src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glabels] Created new "New label dialog"
- Date: Thu, 11 Mar 2010 03:44:24 +0000 (UTC)
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"><b>Select media</b></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"><b>Information</b></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"><b>Preview</b></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]