[glabels/vala] Initial implementation of barcode object.



commit 462e3f75432e9cf5a38bf15099b6b66a4a361192
Author: Jim Evins <evins snaught com>
Date:   Tue Sep 11 19:32:23 2012 -0400

    Initial implementation of barcode object.

 .gitignore                        |    3 +
 data/ui/object_editor.ui          |  422 +++++++++++++++++++++++++++++++--
 glabels/Makefile.am               |    8 +
 glabels/barcode_backends.vala     |  470 +++++++++++++++++++++++++++++++++++++
 glabels/barcode_style.vala        |   83 +++++++
 glabels/combo_util.vala           |   73 ++++++
 glabels/glabels.vala              |    2 +
 glabels/label_object.vala         |   12 +
 glabels/label_object_barcode.vala |  455 +++++++++++++++++++++++++++++++++++
 glabels/new_label_dialog.vala     |   21 +-
 glabels/object_editor.vala        |  300 +++++++++++++++++++++++-
 glabels/ui.vala                   |    7 +-
 glabels/view.vala                 |   28 ++-
 glabels/xml_label.vala            |  127 ++++++++++-
 libglbarcode/barcode.vala         |    3 +-
 15 files changed, 1975 insertions(+), 39 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 82a5daf..fb030de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ glabels-*.tar.gz
 
 /libglbarcode/demo/*.c
 /libglbarcode/demo/*.h
+/libglbarcode/demo/*.stamp
 /libglbarcode/demo/glbarcode
 
 /glabels/*.c
@@ -136,3 +137,5 @@ glabels-*.tar.gz
 *.orig
 *.rej
 gmon.out
+core
+*.safe
\ No newline at end of file
diff --git a/data/ui/object_editor.ui b/data/ui/object_editor.ui
index 768e4f4..c0077a9 100644
--- a/data/ui/object_editor.ui
+++ b/data/ui/object_editor.ui
@@ -1,6 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkAdjustment" id="bc_digits_adjustment">
+    <property name="lower">1</property>
+    <property name="upper">100</property>
+    <property name="value">10</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkAdjustment" id="font_size_adjustment">
     <property name="lower">1</property>
     <property name="upper">100</property>
@@ -32,6 +39,16 @@
     <property name="step_increment">0.25</property>
     <property name="page_increment">1</property>
   </object>
+  <object class="GtkAdjustment" id="pos_x_adjustment">
+    <property name="upper">100</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">1</property>
+  </object>
+  <object class="GtkAdjustment" id="pos_y_adjustment">
+    <property name="upper">100</property>
+    <property name="step_increment">0.01</property>
+    <property name="page_increment">1</property>
+  </object>
   <object class="GtkAdjustment" id="shadow_opacity_adjustment">
     <property name="upper">100</property>
     <property name="value">1</property>
@@ -765,6 +782,385 @@
               </packing>
             </child>
             <child>
+              <object class="GtkBox" id="bc_page_box">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="border_width">6</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkFrame" id="frame3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment11">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkGrid" id="grid8">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="border_width">3</property>
+                            <property name="row_spacing">6</property>
+                            <property name="column_spacing">9</property>
+                            <child>
+                              <object class="GtkLabel" id="label23">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="label" translatable="yes">Type:</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label26">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="halign">start</property>
+                                <property name="label" translatable="yes">Color:</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">3</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="box2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="spacing">3</property>
+                                <child>
+                                  <object class="GtkComboBoxText" id="bc_type_combo">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="hexpand">True</property>
+                                    <property name="entry_text_column">0</property>
+                                    <property name="id_column">1</property>
+                                    <items>
+                                      <item translatable="yes">Code 39</item>
+                                    </items>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">0</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="box14">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="spacing">3</property>
+                                <child>
+                                  <object class="GtkBox" id="bc_color_box">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">3</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="bc_show_text_check">
+                                <property name="label" translatable="yes">Show text</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="xalign">0</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">1</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="bc_checksum_check">
+                                <property name="label" translatable="yes">Checksum</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="xalign">0</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">2</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <placeholder/>
+                            </child>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label27">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Style&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment12">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkGrid" id="grid10">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="valign">start</property>
+                            <property name="hexpand">True</property>
+                            <property name="row_spacing">6</property>
+                            <property name="column_spacing">12</property>
+                            <child>
+                              <object class="GtkRadioButton" id="bc_literal_radio">
+                                <property name="label" translatable="yes">Literal:</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="valign">start</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="xalign">0</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="bc_key_radio">
+                                <property name="label" translatable="yes">Key:</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="xalign">0</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">bc_literal_radio</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">1</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox" id="bc_key_box">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="hexpand">True</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">1</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkScrolledWindow" id="scrolledwindow3">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="vexpand">True</property>
+                                <property name="shadow_type">in</property>
+                                <child>
+                                  <object class="GtkTextView" id="bc_data_textview">
+                                    <property name="width_request">232</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="vexpand">True</property>
+                                  </object>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">0</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <placeholder/>
+                            </child>
+                            <child>
+                              <object class="GtkGrid" id="bc_key_grid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="row_spacing">3</property>
+                                <property name="column_spacing">6</property>
+                                <child>
+                                  <object class="GtkLabel" id="label24">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">format:</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                    <property name="width">1</property>
+                                    <property name="height">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label25">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">digits:</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">1</property>
+                                    <property name="width">1</property>
+                                    <property name="height">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="bc_format_label">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">0123456789</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="top_attach">0</property>
+                                    <property name="width">1</property>
+                                    <property name="height">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkSpinButton" id="bc_digits_spin">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">â</property>
+                                    <property name="adjustment">bc_digits_adjustment</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="top_attach">1</property>
+                                    <property name="width">1</property>
+                                    <property name="height">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="top_attach">2</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label30">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Data&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child type="tab">
+              <object class="GtkLabel" id="label22">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Barcode</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkBox" id="image_page_box">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -883,7 +1279,7 @@
                 </child>
               </object>
               <packing>
-                <property name="position">1</property>
+                <property name="position">2</property>
               </packing>
             </child>
             <child type="tab">
@@ -893,7 +1289,7 @@
                 <property name="label" translatable="yes">Image</property>
               </object>
               <packing>
-                <property name="position">1</property>
+                <property name="position">2</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>
@@ -1086,7 +1482,7 @@
                 </child>
               </object>
               <packing>
-                <property name="position">2</property>
+                <property name="position">3</property>
               </packing>
             </child>
             <child type="tab">
@@ -1097,7 +1493,7 @@
                 <property name="label" translatable="yes">Line/Fill</property>
               </object>
               <packing>
-                <property name="position">2</property>
+                <property name="position">3</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>
@@ -1543,7 +1939,7 @@
                 </child>
               </object>
               <packing>
-                <property name="position">3</property>
+                <property name="position">4</property>
               </packing>
             </child>
             <child type="tab">
@@ -1554,7 +1950,7 @@
                 <property name="label" translatable="yes">Position/Size</property>
               </object>
               <packing>
-                <property name="position">3</property>
+                <property name="position">4</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>
@@ -1775,7 +2171,7 @@
                 </child>
               </object>
               <packing>
-                <property name="position">4</property>
+                <property name="position">5</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>
@@ -1787,7 +2183,7 @@
                 <property name="label" translatable="yes">Shadow</property>
               </object>
               <packing>
-                <property name="position">4</property>
+                <property name="position">5</property>
                 <property name="tab_fill">False</property>
               </packing>
             </child>
@@ -1834,16 +2230,6 @@
       <widget name="shadow_page_box"/>
     </widgets>
   </object>
-  <object class="GtkAdjustment" id="pos_x_adjustment">
-    <property name="upper">100</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">1</property>
-  </object>
-  <object class="GtkAdjustment" id="pos_y_adjustment">
-    <property name="upper">100</property>
-    <property name="step_increment">0.01</property>
-    <property name="page_increment">1</property>
-  </object>
   <object class="GtkSizeGroup" id="width_sizegroup">
     <widgets>
       <widget name="notebook"/>
diff --git a/glabels/Makefile.am b/glabels/Makefile.am
index ad12464..0b37d6d 100644
--- a/glabels/Makefile.am
+++ b/glabels/Makefile.am
@@ -9,6 +9,8 @@ bin_PROGRAMS = glabels-4
 glabels_4_SOURCES = \
 	TMP_gdk_pixdata.vapi \
 	glabels.vala \
+	barcode_backends.vala \
+	barcode_style.vala \
 	color.vala \
 	color_button.vala \
 	color_history.vala \
@@ -16,6 +18,7 @@ glabels_4_SOURCES = \
 	color_menu_item.vala \
 	color_node.vala \
 	color_swatch.vala \
+	combo_util.vala \
 	cursor.vapi \
 	enum_util.vala \
 	field_button.vala \
@@ -33,6 +36,7 @@ glabels_4_SOURCES = \
 	handle.vala \
 	label.vala \
 	label_object.vala \
+	label_object_barcode.vala \
 	label_object_box.vala \
 	label_object_ellipse.vala \
 	label_object_image.vala \
@@ -80,6 +84,7 @@ INCLUDES = \
 	-include config.h \
 	$(GLABELS_CFLAGS) \
 	-I../libglabels \
+	-I../libglbarcode \
 	-DLOCALEDIR=\""$(localedir)"\" \
 	-DDATADIR=\""$(datadir)"\" \
 	-DGLABELS_BRANCH=\""$(GLABELS_BRANCH)"\" \
@@ -88,6 +93,7 @@ INCLUDES = \
 VALAFLAGS = \
 	--vapidir=$(srcdir)/../vapi \
 	--vapidir=$(srcdir)/../libglabels \
+	--vapidir=$(srcdir)/../libglbarcode \
 	--pkg config \
 	--pkg posix \
 	--pkg gtk+-3.0 \
@@ -95,11 +101,13 @@ VALAFLAGS = \
 	--pkg gee-1.0 \
 	--pkg librsvg-2.0 \
 	--pkg libglabels-4 \
+	--pkg libglbarcode-4 \
 	$(NULL)
 
 
 glabels_4_LDADD = \
 	-L../libglabels -lglabels-4.0 \
+	-L../libglbarcode -lglbarcode-4.0 \
 	$(GLABELS_LIBS) \
 	$(NULL)
 
diff --git a/glabels/barcode_backends.vala b/glabels/barcode_backends.vala
new file mode 100644
index 0000000..598044e
--- /dev/null
+++ b/glabels/barcode_backends.vala
@@ -0,0 +1,470 @@
+/*  barcode_backends.vala
+ *
+ *  Copyright (C) 2012  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/>.
+ */
+
+
+using GLib;
+
+namespace glabels
+{
+
+	public class BarcodeBackends
+	{
+
+		private const string DEFAULT_ID = "Code39";
+		private const string DEFAULT_NAME = _("Code 39");
+
+		private static bool initialized = false;
+		private static HashTable<string,BarcodeStyle> id_map;
+		private static HashTable<string,BarcodeStyle> name_map;
+
+
+		static construct
+		{
+			id_map   = new HashTable<string,BarcodeStyle>( str_hash, str_equal );
+			name_map = new HashTable<string,BarcodeStyle>( str_hash, str_equal );
+
+			register( "POSTNET", _("POSTNET (any)"),
+			          false, false, true, false, "12345-6789-12", false, 11 );
+
+			register( "POSTNET-5", _("POSTNET-5 (ZIP only)"),
+			          false, false, true, false, "12345", false, 5 );
+
+			register( "POSTNET-9", _("POSTNET-9 (ZIP+4)"),
+			          false, false, true, false, "12345-6789", false, 9 );
+
+			register( "POSTNET-11", _("POSTNET-11 (DPBC)"),
+			          false, false, true, false, "12345-6789-12", false, 11 );
+
+			register( "CEPNET", _("CEPNET"),
+			          false, false, true, false, "12345-678", false, 8 );
+
+			register( "ONECODE", _("One Code"),
+			          false, false, true, false, "12345678901234567890", false, 20 );
+
+			register( "Code39", _("Code 39"),
+			          true, true, true, true, "1234567890", true, 10 );
+
+			register( "Code39Ext", _("Code 39 Extended"),
+			          true, true, true, true, "1234567890", true, 10 );
+
+#if HAVE_LIBBARCODE
+
+			register( "gnu-barcode:EAN", _("GNU-Barcode : EAN (any)"),
+			          true, true, true, false, "000000000000 00000", false, 17 );
+
+			register( "gnu-barcode:EAN-8", _("GNU-Barcode : EAN-8"),
+			          true, true, true, false, "0000000", false, 7 );
+
+			register( "gnu-barcode:EAN-8+2", _("GNU-Barcode : EAN-8 +2"),
+			          true, true, true, false, "0000000 00", false, 9 );
+
+			register( "gnu-barcode:EAN-8+5", _("GNU-Barcode : EAN-8 +5"),
+			          true, true, true, false, "0000000 00000", false, 12 );
+
+			register( "gnu-barcode:EAN-13", _("GNU-Barcode : EAN-13"),
+			          true, true, true, false, "000000000000", false, 12 );
+
+			register( "gnu-barcode:EAN-13+2", _("GNU-Barcode : EAN-13 +2"),
+			          true, true, true, false, "000000000000 00", false, 14 );
+
+			register( "gnu-barcode:EAN-13+5", _("GNU-Barcode : EAN-13 +5"),
+			          true, true, true, false, "000000000000 00000", false, 17 );
+
+			register( "gnu-barcode:UPC", _("GNU-Barcode : UPC (UPC-A or UPC-E)"),
+			          true, true, true, false, "00000000000 00000", false, 16 );
+
+			register( "gnu-barcode:UPC-A", _("GNU-Barcode : UPC-A"),
+			          true, true, true, false, "00000000000", false, 11 );
+
+			register( "gnu-barcode:UPC-A+2", _("GNU-Barcode : UPC-A +2"),
+			          true, true, true, false, "00000000000 00", false, 13 );
+
+			register( "gnu-barcode:UPC-A+5", _("GNU-Barcode : UPC-A +5"),
+			          true, true, true, false, "00000000000 00000", false, 16 );
+
+			register( "gnu-barcode:UPC-E", _("GNU-Barcode : UPC-E"),
+			          true, true, true, false, "000000", false, 6 );
+
+			register( "gnu-barcode:UPC-E+2", _("GNU-Barcode : UPC-E +2"),
+			          true, true, true, false, "000000 00", false, 8 );
+
+			register( "gnu-barcode:UPC-E+5", _("GNU-Barcode : UPC-E +5"),
+			          true, true, true, false, "000000 00000", false, 11 );
+
+			register( "gnu-barcode:ISBN", _("GNU-Barcode : ISBN"),
+			          true, true, true, true, "0-00000-000-0", false, 10 );
+
+			register( "gnu-barcode:ISBN+5", _("GNU-Barcode : ISBN +5"),
+			          true, true, true, true, "0-00000-000-0 00000", false, 15 );
+
+			register( "gnu-barcode:Code39", _("GNU-Barcode : Code 39"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:Code128", _("GNU-Barcode : Code 128"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:Code128C", _("GNU-Barcode : Code 128C"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "gnu-barcode:Code128B", _("GNU-Barcode : Code 128B"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:I25", _("GNU-Barcode : Interleaved 2 of 5"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:CBR", _("GNU-Barcode : Codabar"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:MSI", _("GNU-Barcode : MSI"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:PLS", _("GNU-Barcode : Plessey"),
+			          true, true, true, true, "0000000000", true, 10 );
+
+			register( "gnu-barcode:Code93", _("GNU-Barcode : Code 93"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+#endif
+
+#if HAVE_LIBZINT
+
+			register( "zint:AUSP", _("zint : Australia Post Standard"),
+			          false, false, true, false, "12345678901234567890123", true, 23 );
+
+			register( "zint:AUSRP", _("zint : Australia Post Reply Paid"),
+			          false, false, true, false, "12345678", true, 8 );
+
+			register( "zint:AUSRT", _("zint : Australia Post Route Code"),
+			          false, false, true, false, "12345678", true, 8 );
+
+			register( "zint:AUSRD", _("zint : Australia Post Redirect"),
+			          false, false, true, false, "12345678", true, 8 );
+
+			register( "zint:AZTEC", _("zint : Aztec Code"),
+			          false, false, true, false, "1234567890", true, 10 );
+          
+			register( "zint:AZRUN", _("zint : Aztec Rune"),
+			          false, false, true, false, "255", true, 3 );
+
+			register( "zint:CBR", _("zint : Codabar"),
+			          true, true, true, false, "ABCDABCDAB", true, 10 );
+
+			register( "zint:Code1", _("zint : Code One"), 
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:Code11", _("zint : Code 11"),
+			          true, true, true, false, "0000000000", true, 10 );
+          
+			register( "zint:C16K", _("zint : Code 16K"),
+			          false, false, true, false, "0000000000", true, 10 );
+          
+			register( "zint:C25M", _("zint : Code 2 of 5 Matrix"), 
+			          true, true, true, false, "0000000000", true, 10 );
+          
+			register( "zint:C25I", _("zint : Code 2 of 5 IATA"), 
+			          true, true, true, false, "0000000000", true, 10 );
+          
+			register( "zint:C25DL", _("zint : Code 2 of 5 Data Logic"), 
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:Code32", _("zint : Code 32 (Italian Pharmacode)"), 
+			          true, true, true, false, "12345678", true, 8 );
+
+			register( "zint:Code39", _("zint : Code 39"),
+			          true, true, false, false, "0000000000", true, 10 );
+          
+			register( "zint:Code39E", _("zint : Code 39 Extended"), 
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:Code49", _("zint : Code 49"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:Code93", _("zint : Code 93"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:Code128", _("zint : Code 128"),
+			          true, true, true, false, "0000000000", true, 10 );
+          
+			register( "zint:Code128B", _("zint : Code 128 (Mode C supression)"),
+			          true, true, true, false, "0000000000", true, 10 );
+          
+			register( "zint:DAFT", _("zint : DAFT Code"),
+			          false, false, false, false, "DAFTDAFTDAFTDAFT", true, 16 );
+
+			register( "zint:DMTX", _("zint : Data Matrix"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:DPL", _("zint : Deutsche Post Leitcode"),
+			          true, true, true, false, "1234567890123", true, 13 );
+          
+			register( "zint:DPI", _("zint : Deutsche Post Identcode"),
+			          true, true, true, false, "12345678901", true, 11 );
+          
+			register( "zint:KIX", _("zint : Dutch Post KIX Code"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:EAN", _("zint : EAN"),
+			          true, true, true, false, "1234567890123", false, 13 );
+
+			register( "zint:GMTX", _("zint : Grid Matrix"), 
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:GS1-128", _("zint : GS1-128"),
+			          true, true, true, false, "[01]12345678901234", false, 18 );
+
+			register( "zint:RSS14", _("zint : GS1 DataBar-14"),
+			          true, true, true, false, "1234567890123", true, 13 );
+          
+			register( "zint:RSSLTD", "GS1 DataBar-14 Limited", 
+			          true, true, true, false, "1234567890123", true, 13 );
+          
+			register( "zint:RSSEXP", "GS1 DataBar Extended", 
+			          true, true, true, false, "[01]12345678901234", false, 18 );
+          
+			register( "zint:RSSS", _("zint : GS1 DataBar-14 Stacked"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:RSSSO", _("zint : GS1 DataBar-14 Stacked Omni."),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:RSSSE", _("zint : GS1 DataBar Extended Stacked"),
+			          false, false, true, false, "[01]12345678901234", false, 18 );
+
+			register( "zint:HIBC128", _("zint : HIBC Code 128"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:HIBC39", _("zint : HIBC Code 39"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:HIBCDM", _("zint : HIBC Data Matrix"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:HIBCQR", _("zint : HIBC QR Code"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:HIBCPDF", _("zint : HIBC PDF417"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:HIBCMPDF", _("zint : HIBC Micro PDF417"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:HIBCAZ", _("zint : HIBC Aztec Code"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:I25", _("zint : Interleaved 2 of 5"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:ISBN", _("zint : ISBN"),
+			          true, true, true, false, "123456789", false, 9 );
+
+			register( "zint:ITF14", _("zint : ITF-14"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:JAPAN", _("zint : Japanese Postal"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:KOREA", _("zint : Korean Postal"),
+			          true, true, true, false, "123456", false, 6 );
+
+			register( "zint:LOGM", _("zint : LOGMARS"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:MAXI", _("zint : Maxicode"),
+			          false, false, false, false, "0000000000", true, 10 );
+
+			register( "zint:MPDF", _("zint : Micro PDF417"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:MQR", _("zint : Micro QR Code"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:MSI", _("zint : MSI Plessey"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:NVE", _("zint : NVE-18"),
+			          true, true, true, false, "12345678901234567", false, 17 );
+
+			register( "zint:PDF", _("zint : PDF417"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:PDFT", _("zint : PDF417 Truncated"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:PLAN", _("zint : PLANET"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:POSTNET", _("zint : PostNet"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:PHARMA", _("zint : Pharmacode"),
+			          false, false, true, false, "123456", false, 6 );
+
+			register( "zint:PHARMA2", _("zint : Pharmacode 2-track"),
+			          false, false, true, false, "12345678", false, 8 );
+
+			register( "zint:PZN", _("zint : Pharmazentral Nummer (PZN)"),
+			          true, true, true, false, "123456", false, 6 );
+
+			register( "zint:QR", _("zint : QR Code"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:RM4", _("zint : Royal Mail 4-State"),
+			          false, false, true, false, "0000000000", true, 10 );
+
+			register( "zint:TELE", _("zint : Telepen"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:TELEX", _("zint : Telepen Numeric"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+			register( "zint:UPC-A", _("zint : UPC-A"), 
+			          true, true, true, false, "12345678901", false, 11 );
+          
+			register( "zint:UPC-E", _("zint : UPC-E"), 
+			          true, true, true, false, "1234567", false, 7 );
+          
+			register( "zint:USPS", _("zint : USPS One Code"),
+			          false, false, true, false, "12345678901234567890", true, 20 );
+
+			register( "zint:PLS", _("zint : UK Plessey"),
+			          true, true, true, false, "0000000000", true, 10 );
+
+#endif
+
+#if HAVE_LIBIEC16022
+
+			register( "iec16022:IEC16022", _("IEC16022 : IEC16022 (DataMatrix)"),
+			          false, false, true, false, "12345678", true, 8 );
+
+#endif
+
+#if HAVE_LIBQRENCODE
+
+			register( "qrencode:IEC18004", _("qrencode : IEC18004 (QRCode)"),
+			          false, false, true, false, "12345678", true, 8 );
+
+#endif
+
+			initialized = true;
+		}
+
+
+		public static void init()
+		{
+			if ( !initialized )
+			{
+				new BarcodeBackends();
+			}
+			else
+			{
+				message( "BarcodeBackends already initialized.\n" );
+			}
+		}
+
+
+		private static void register ( string id,
+		                               string name,
+		                               bool   can_text,
+		                               bool   text_optional,
+		                               bool   can_checksum,
+		                               bool   checksum_optional,
+		                               string default_digits,
+		                               bool   can_freeform,
+		                               int    prefered_n )
+		{
+			BarcodeStyle style = new BarcodeStyle( id, name,
+			                                       can_text, text_optional, can_checksum, checksum_optional,
+			                                       default_digits, can_freeform, prefered_n );
+
+			id_map.insert( id, style );
+			name_map.insert( name, style );
+		}
+
+
+		public static BarcodeStyle? lookup_style_from_name( string name )
+		{
+			if ( name_map.contains( name ) )
+			{
+				return name_map.lookup( name );
+			}
+			else
+			{
+				return id_map.lookup( DEFAULT_ID );
+			}
+		}
+
+
+		public static BarcodeStyle? lookup_style_from_id( string id )
+		{
+			if ( id_map.contains( id ) )
+			{
+				return id_map.lookup( id );
+			}
+			else
+			{
+				return id_map.lookup( DEFAULT_ID );
+			}
+		}
+
+
+		public static string id_to_name( string id )
+		{
+			BarcodeStyle? style = lookup_style_from_id( id );
+
+			if ( style != null )
+			{
+				return style.name;
+			}
+			else
+			{
+				return DEFAULT_NAME;
+			}
+		}
+
+
+		public static string name_to_id( string name )
+		{
+			BarcodeStyle? style = lookup_style_from_name( name );
+
+			if ( style != null )
+			{
+				return style.id;
+			}
+			else
+			{
+				return DEFAULT_ID;
+			}
+		}
+
+
+		public static List<weak string> get_name_list()
+		{
+			List<weak string> list = name_map.get_keys();
+			list.sort( strcmp );
+			return list;
+		}
+
+	}
+
+}
+
+
+
+
diff --git a/glabels/barcode_style.vala b/glabels/barcode_style.vala
new file mode 100644
index 0000000..f69e681
--- /dev/null
+++ b/glabels/barcode_style.vala
@@ -0,0 +1,83 @@
+/*  barcode_style.vala
+ *
+ *  Copyright (C) 2012  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/>.
+ */
+
+
+using GLib;
+
+namespace glabels
+{
+
+	public class BarcodeStyle
+	{
+
+		public string id                { get; private set; }
+		public string name              { get; private set; }
+		public bool   can_text          { get; private set; }
+		public bool   text_optional     { get; private set; }
+		public bool   can_checksum      { get; private set; }
+		public bool   checksum_optional { get; private set; }
+		public string default_digits    { get; private set; }
+		public bool   can_freeform      { get; private set; }
+		public int    prefered_n        { get; private set; }
+
+
+		public BarcodeStyle ( string id,
+		                      string name,
+		                      bool   can_text,
+		                      bool   text_optional,
+		                      bool   can_checksum,
+		                      bool   checksum_optional,
+		                      string default_digits,
+		                      bool   can_freeform,
+		                      int    prefered_n )
+		{
+			this.id                = id;
+			this.name              = name;
+			this.can_text          = can_text;
+			this.text_optional     = text_optional;
+			this.can_checksum      = can_checksum;
+			this.checksum_optional = checksum_optional;
+			this.default_digits    = default_digits;
+			this.can_freeform      = can_freeform;
+			this.prefered_n        = prefered_n;
+		}
+
+
+		public string get_example_digits( int n )
+		{
+			if ( can_freeform )
+			{
+				return string.nfill( int.max(n,1), '0' );
+			}
+			else
+			{
+				return default_digits;
+			}
+		}
+
+
+	}
+
+
+}
+
+
+
+
diff --git a/glabels/combo_util.vala b/glabels/combo_util.vala
new file mode 100644
index 0000000..8b6a3ad
--- /dev/null
+++ b/glabels/combo_util.vala
@@ -0,0 +1,73 @@
+/*  combo_util.vala
+ *
+ *  Copyright (C) 2012  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/>.
+ */
+
+
+using GLib;
+
+namespace glabels
+{
+
+	namespace ComboUtil
+	{
+
+		public void load_strings( Gtk.ComboBoxText combo,
+		                          List<string>     list )
+		{
+			combo.remove_all();
+
+			foreach ( string s in list )
+			{
+				combo.append_text( s );
+			}
+		}
+
+
+		public void set_active_text( Gtk.ComboBoxText combo,
+		                             string           text )
+		{
+			Gtk.TreeModel model = combo.get_model();
+
+			Gtk.TreeIter iter;
+
+			if ( model.get_iter_first( out iter ) )
+			{
+				do
+				{
+					string model_text = "";
+
+					model.get( iter, 0, ref model_text, -1 );
+					if ( model_text == text )
+					{
+						combo.set_active_iter( iter );
+						return;
+					}
+				}
+				while ( model.iter_next( ref iter ) );
+			}
+
+			combo.set_active( -1 );
+		}
+
+	}
+
+}
+
+
+
diff --git a/glabels/glabels.vala b/glabels/glabels.vala
index ca05103..b92d11c 100644
--- a/glabels/glabels.vala
+++ b/glabels/glabels.vala
@@ -56,6 +56,8 @@ namespace glabels
 			libglabels.Db.init();
 			libglabels.XmlUtil.init();
 			libglabels.XmlUtil.default_units = libglabels.Units.inch();
+			glbarcode.Factory.init();
+			BarcodeBackends.init();
 
 			Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default();
 			icon_theme.append_search_path( Path.build_filename( Config.DATADIR, Config.GLABELS_BRANCH, "icons", null ) );
diff --git a/glabels/label_object.vala b/glabels/label_object.vala
index 469fc86..0ca8ffa 100644
--- a/glabels/label_object.vala
+++ b/glabels/label_object.vala
@@ -170,6 +170,18 @@ namespace glabels
 
 
 		/**
+		 * Barcode parameters interface
+		 */
+		public virtual TextNode        bc_data_node        { get; set; }
+		public virtual string          bc_type             { get; set; }
+		public virtual bool            bc_text_flag        { get; set; }
+		public virtual bool            bc_checksum_flag    { get; set; }
+		public virtual int             bc_format_digits    { get; set; }
+		public virtual ColorNode       bc_color_node       { get; set; }
+		public virtual BarcodeStyle    bc_style            { get; set; }
+
+
+		/**
 		 * Shadow state
 		 */
 		public bool shadow_state
diff --git a/glabels/label_object_barcode.vala b/glabels/label_object_barcode.vala
new file mode 100644
index 0000000..c56a153
--- /dev/null
+++ b/glabels/label_object_barcode.vala
@@ -0,0 +1,455 @@
+/*  label_object_barcode.vala
+ *
+ *  Copyright (C) 2012  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/>.
+ */
+
+
+using GLib;
+
+namespace glabels
+{
+
+	public class LabelObjectBarcode : LabelObject
+	{
+
+		private const double FONT_SCALE = (72.0/96.0);
+		private const double SELECTION_SLOP_PIXELS = 4.0;
+		private const double TEXT_MARGIN = 3.0;
+
+
+		private glbarcode.Barcode? cached_bc;
+
+
+		public LabelObjectBarcode.with_parent( Label parent )
+		{
+			this();
+			parent.add_object( this );
+		}
+
+
+		/**
+		 * Width of bounding box
+		 */
+		public override double w
+		{
+			get { return _w; }
+
+			set
+			{
+				if ( _w != value )
+				{
+					_w = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private double _w;
+
+
+		/**
+		 * Height of bounding box
+		 */
+		public override double h
+		{
+			get { return _h; }
+
+			set
+			{
+				if ( _h != value )
+				{
+					_h = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private double _h;
+
+
+		/**
+		 * Barcode data
+		 */
+		public override TextNode bc_data_node
+		{
+			get { return _bc_data_node; }
+
+			set
+			{
+				if ( _bc_data_node != value )
+				{
+					_bc_data_node = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private TextNode _bc_data_node;
+
+
+		/**
+		 * Barcode type
+		 */
+		public override string bc_type
+		{
+			get { return _bc_type; }
+
+			set
+			{
+				if ( _bc_type != value )
+				{
+					_bc_type = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+
+		}
+		private string _bc_type;
+
+
+		/**
+		 * Barcode show text flag
+		 */
+		public override bool bc_text_flag
+		{
+			get { return _bc_text_flag; }
+
+			set
+			{
+				if ( _bc_text_flag != value )
+				{
+					_bc_text_flag = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private bool _bc_text_flag;
+
+
+		/**
+		 * Barcode checksum flag
+		 */
+		public override bool bc_checksum_flag
+		{
+			get { return _bc_checksum_flag; }
+
+			set
+			{
+				if ( _bc_checksum_flag != value )
+				{
+					_bc_checksum_flag = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private bool _bc_checksum_flag;
+
+
+		/**
+		 * Barcode format digits
+		 */
+		public override int bc_format_digits
+		{
+			get { return _bc_format_digits; }
+
+			set
+			{
+				if ( _bc_format_digits != value )
+				{
+					_bc_format_digits = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private int _bc_format_digits;
+
+
+		/**
+		 * Barcode color node
+		 */
+		public override ColorNode bc_color_node
+		{
+			get { return _bc_color_node; }
+
+			set
+			{
+				if ( _bc_color_node != value )
+				{
+					_bc_color_node = value;
+					update_cached_barcode();
+					changed();
+				}
+			}
+		}
+		private ColorNode _bc_color_node;
+
+
+		/**
+		 * Style information
+		 */
+		public override BarcodeStyle bc_style { get; private set; }
+
+
+		public LabelObjectBarcode()
+		{
+			handles.append( new HandleSouthEast( this ) );
+			handles.append( new HandleSouthWest( this ) );
+			handles.append( new HandleNorthEast( this ) );
+			handles.append( new HandleNorthWest( this ) );
+			handles.append( new HandleEast( this ) );
+			handles.append( new HandleSouth( this ) );
+			handles.append( new HandleWest( this ) );
+			handles.append( new HandleNorth( this ) );
+
+			outline = new Outline( this );
+
+			Prefs prefs = new Prefs();
+
+			_bc_style              = BarcodeBackends.lookup_style_from_id( "Code39" );
+			_bc_type               = _bc_style.id;
+			_bc_text_flag          = _bc_style.can_text;
+			_bc_checksum_flag      = _bc_style.can_checksum;
+			_bc_format_digits      = _bc_style.prefered_n;
+
+			_bc_data_node          = new TextNode( false, _bc_style.default_digits );
+
+			_bc_color_node         = ColorNode.from_color( prefs.default_line_color );
+
+			update_cached_barcode();
+		}
+
+
+		public override LabelObject dup()
+		{
+			LabelObjectBarcode copy = new LabelObjectBarcode();
+
+			copy.set_common_properties_from_object( this );
+
+			return copy;
+		}
+
+
+		public override void draw_object( Cairo.Context cr, bool in_editor, MergeRecord? record )
+		{
+			Color bc_color = bc_color_node.expand( record );
+
+			if ( in_editor && line_color_node.field_flag )
+			{
+				bc_color = Color.from_rgba( 0, 0, 0, 0.5 );
+			}
+
+			cr.set_source_rgba( bc_color.r, bc_color.g, bc_color.b, bc_color.a );
+
+			if ( !in_editor && bc_data_node.field_flag )
+			{
+
+				string text = bc_data_node.expand( record );
+				glbarcode.Barcode bc = glbarcode.Factory.create_barcode( bc_type, bc_text_flag, bc_checksum_flag, w, h, text );
+
+				if ( bc != null )
+				{
+					bc.render( new glbarcode.CairoRenderer( cr ) );
+				}
+
+			}
+			else
+			{
+
+				if ( cached_bc == null )
+				{
+					create_alt_msg_path( cr, _("Invalid barcode type") );
+					cr.fill();
+				}
+				else
+				{
+					if ( cached_bc.is_empty )
+					{
+						create_alt_msg_path( cr, _("Barcode data empty") );
+						cr.fill();
+					}
+					else if ( !cached_bc.is_data_valid )
+					{
+						create_alt_msg_path( cr, _("Invalid barcode data") );
+						cr.fill();
+					}
+					else
+					{
+						cached_bc.render( new glbarcode.CairoRenderer( cr ) );
+					}
+				}
+
+			}
+		}
+
+
+		public override void draw_shadow( Cairo.Context cr, bool in_editor, MergeRecord? record )
+		{
+			/* Shadows unsupported for barcodes.  Shadows would likely make the barcode unreadable. */
+		}
+
+
+		public override bool is_object_located_at( Cairo.Context cr, double x, double y )
+		{
+			if ( (x >= 0) && (x <= w) && (y >= 0) && (y <= h) )
+			{
+
+				if ( cached_bc == null )
+				{
+					create_alt_msg_path( cr, _("Invalid barcode type") );
+				}
+				else
+				{
+					if ( cached_bc.is_empty )
+					{
+						create_alt_msg_path( cr, _("Barcode data empty") );
+					}
+					else if ( !cached_bc.is_data_valid )
+					{
+						create_alt_msg_path( cr, _("Invalid barcode data") );
+					}
+					else
+					{
+						cached_bc.render( new glbarcode.CairoRenderer( cr, false ) );
+					}
+				}
+
+				if ( cr.in_fill( x, y ) )
+				{
+					return true;
+				}
+
+
+				double scale_x = 1.0;
+				double scale_y = 1.0;
+				cr.device_to_user_distance( ref scale_x, ref scale_y );
+
+				cr.set_line_width( 2*SELECTION_SLOP_PIXELS*scale_x );
+
+				if ( cr.in_stroke( x, y ) )
+				{
+					return true;
+				}
+
+			}
+
+			return false;
+		}
+
+
+		private void create_alt_msg_path( Cairo.Context cr, string msg )
+		{
+			cr.save();
+
+			Pango.Layout layout = Pango.cairo_create_layout( cr );
+
+			Cairo.FontOptions font_options = new Cairo.FontOptions();
+			font_options.set_hint_metrics( Cairo.HintMetrics.OFF );
+			Pango.Context context = layout.get_context();
+			Pango.cairo_context_set_font_options( context, font_options );
+
+			Pango.FontDescription desc = new Pango.FontDescription();
+			desc.set_family( "Sans" );
+			desc.set_weight( Pango.Weight.NORMAL );
+			desc.set_size( (int)(12 * FONT_SCALE * Pango.SCALE) );
+			desc.set_style( Pango.Style.NORMAL );
+			layout.set_font_description( desc );
+
+			layout.set_text( msg, -1 );
+
+			cr.move_to( TEXT_MARGIN, 0 );
+			Pango.cairo_layout_path( cr, layout );
+
+			cr.restore();
+		}
+
+
+		private void update_cached_barcode()
+		{
+			string data;
+
+			_bc_style = BarcodeBackends.lookup_style_from_id( bc_type );
+
+			if ( bc_data_node.field_flag )
+			{
+				data = _bc_style.get_example_digits( bc_format_digits );
+			}
+			else
+			{
+				data = bc_data_node.expand( null );
+			}
+
+			cached_bc = glbarcode.Factory.create_barcode( bc_type, bc_text_flag, bc_checksum_flag, w, h, data );
+
+			if ( (cached_bc == null) || !cached_bc.is_data_valid )
+			{
+				/* Try again with default digits, but don't save -- just extract size. */
+				data = _bc_style.get_example_digits( bc_format_digits );
+
+				glbarcode.Barcode bc = glbarcode.Factory.create_barcode( bc_type, bc_text_flag, bc_checksum_flag, w, h, data );
+
+				if ( bc != null )
+				{
+					w = bc.w;
+					h = bc.h;
+				}
+				else
+				{
+					/* If we still can't render, just set a default size. */
+					w = 144;
+					h = 72;
+				}
+
+			}
+			else
+			{
+				w = cached_bc.w;
+				h = cached_bc.h;
+			}
+
+			if ( !_bc_style.can_text )
+			{
+				_bc_text_flag = false;
+			}
+			else if ( !_bc_style.text_optional )
+			{
+				_bc_text_flag = true;
+			}
+
+			if ( !_bc_style.can_checksum )
+			{
+				_bc_checksum_flag = false;
+			}
+			else if ( !_bc_style.checksum_optional )
+			{
+				_bc_checksum_flag = true;
+			}
+
+			if ( !_bc_style.can_freeform )
+			{
+				_bc_format_digits = _bc_style.prefered_n;
+			}
+
+		}
+
+	}
+
+}
diff --git a/glabels/new_label_dialog.vala b/glabels/new_label_dialog.vala
index 762ec70..588f957 100644
--- a/glabels/new_label_dialog.vala
+++ b/glabels/new_label_dialog.vala
@@ -193,18 +193,21 @@ namespace glabels
 			{
 				libglabels.Template template = libglabels.Db.lookup_template_from_name( name );
 
-				Gtk.TreeIter iter;
-				recent_model.append( out iter );
+				if ( template != null )
+				{
+					Gtk.TreeIter iter;
+					recent_model.append( out iter );
 
-				string tooltip = build_tooltip( template );
+					string tooltip = build_tooltip( template );
 
-				recent_model.set( iter,
-				                  0, template.name,
-				                  1, template.preview_pixbuf,
-				                  2, tooltip,
-				                  -1);
+					recent_model.set( iter,
+					                  0, template.name,
+					                  1, template.preview_pixbuf,
+					                  2, tooltip,
+					                  -1);
 
-				recent_info_bar.hide();
+					recent_info_bar.hide();
+				}
 			}
 
 			template_history.changed.connect( on_template_history_changed );
diff --git a/glabels/object_editor.vala b/glabels/object_editor.vala
index 472b17a..f96f181 100644
--- a/glabels/object_editor.vala
+++ b/glabels/object_editor.vala
@@ -41,6 +41,7 @@ namespace glabels
 
 		private Gtk.Box          text_page_box;
 		private Gtk.Box          image_page_box;
+		private Gtk.Box          bc_page_box;
 		private Gtk.Box          line_fill_page_box;
 		private Gtk.Box          pos_size_page_box;
 		private Gtk.Box          shadow_page_box;
@@ -70,6 +71,21 @@ namespace glabels
 		private Gtk.Box          image_key_box;
 		private FieldButton      image_key_button;
 
+		private Gtk.ComboBoxText bc_type_combo;
+		private Gtk.CheckButton  bc_show_text_check;
+		private Gtk.CheckButton  bc_checksum_check;
+		private Gtk.Box          bc_color_box;
+		private ColorButton      bc_color_button;
+		private Gtk.RadioButton  bc_literal_radio;
+		private Gtk.RadioButton  bc_key_radio;
+		private Gtk.TextView     bc_data_textview;
+		private Gtk.TextBuffer   bc_data_textbuffer;
+		private Gtk.Box          bc_key_box;
+		private FieldButton      bc_key_button;
+		private Gtk.Grid         bc_key_grid;
+		private Gtk.Label        bc_format_label;
+		private Gtk.SpinButton   bc_digits_spin;
+
 		private Gtk.SpinButton   line_width_spin;
 		private Gtk.Box          line_color_box;
 		private ColorButton      line_color_button;
@@ -126,6 +142,14 @@ namespace glabels
 		private ulong sigid_image_filebutton_selection_changed;
 		private ulong sigid_image_key_button_changed;
 
+		private ulong sigid_bc_type_combo_changed;
+		private ulong sigid_bc_show_text_check_toggled;
+		private ulong sigid_bc_checksum_check_toggled;
+		private ulong sigid_bc_color_button_changed;
+		private ulong sigid_bc_data_textbuffer_changed;
+		private ulong sigid_bc_key_button_changed;
+		private ulong sigid_bc_digits_spin_changed;
+
 		private ulong sigid_line_width_spin_changed;
 		private ulong sigid_line_color_button_changed;
 
@@ -158,6 +182,7 @@ namespace glabels
 				string[] objects = { "object_editor_vbox",
 				                     "font_size_adjustment", "line_spacing_adjustment",
 				                     "line_width_adjustment",
+				                     "bc_digits_adjustment",
 				                     "size_w_adjustment", "size_h_adjustment",
 				                     "line_length_adjustment", "line_angle_adjustment",
 				                     "pos_x_adjustment", "pos_y_adjustment",
@@ -187,7 +212,8 @@ namespace glabels
 
 			/* Notebook pages. */
 			text_page_box      = builder.get_object( "text_page_box" )      as Gtk.Box;
-			image_page_box     = builder.get_object( "image_page_box" )      as Gtk.Box;
+			image_page_box     = builder.get_object( "image_page_box" )     as Gtk.Box;
+			bc_page_box        = builder.get_object( "bc_page_box" )        as Gtk.Box;
 			line_fill_page_box = builder.get_object( "line_fill_page_box" ) as Gtk.Box;
 			pos_size_page_box  = builder.get_object( "pos_size_page_box" )  as Gtk.Box;
 			shadow_page_box    = builder.get_object( "shadow_page_box" )    as Gtk.Box;
@@ -263,6 +289,41 @@ namespace glabels
 			sigid_image_key_button_changed = image_key_button.changed.connect( on_image_key_button_changed );
 
 
+			/* Barcode widgets. */
+			bc_type_combo           = builder.get_object( "bc_type_combo" )           as Gtk.ComboBoxText;
+			bc_show_text_check      = builder.get_object( "bc_show_text_check" )      as Gtk.CheckButton;
+			bc_checksum_check       = builder.get_object( "bc_checksum_check" )       as Gtk.CheckButton;
+			bc_color_box            = builder.get_object( "bc_color_box" )            as Gtk.Box;
+			bc_literal_radio        = builder.get_object( "bc_literal_radio" )        as Gtk.RadioButton;
+			bc_key_radio            = builder.get_object( "bc_key_radio" )            as Gtk.RadioButton;
+			bc_data_textview        = builder.get_object( "bc_data_textview" )        as Gtk.TextView;
+			bc_key_box              = builder.get_object( "bc_key_box" )              as Gtk.Box;
+			bc_key_grid             = builder.get_object( "bc_key_grid" )             as Gtk.Grid;
+			bc_format_label         = builder.get_object( "bc_format_label" )         as Gtk.Label;
+			bc_digits_spin          = builder.get_object( "bc_digits_spin" )          as Gtk.SpinButton;
+
+			bc_color_button = new ColorButton( _("Default"), Color.black(), Color.black() );
+			bc_color_box.pack_start( bc_color_button, true, true, 0 );
+
+			bc_data_textbuffer = new Gtk.TextBuffer( null );
+			bc_data_textview.set_buffer( bc_data_textbuffer );
+
+			bc_key_button = new FieldButton( null );
+			bc_key_box.pack_start( bc_key_button, true, true, 0 );
+
+			ComboUtil.load_strings( bc_type_combo, BarcodeBackends.get_name_list() );
+
+			sigid_bc_type_combo_changed = bc_type_combo.changed.connect( on_bc_type_combo_changed );
+			sigid_bc_show_text_check_toggled =
+				bc_show_text_check.toggled.connect( on_bc_show_text_check_toggled );
+			sigid_bc_checksum_check_toggled =
+				bc_checksum_check.toggled.connect( on_bc_checksum_check_toggled );
+			sigid_bc_color_button_changed = bc_color_button.color_changed.connect( on_bc_color_button_changed );
+			sigid_bc_data_textbuffer_changed = bc_data_textbuffer.changed.connect( on_bc_data_textbuffer_changed );
+			sigid_bc_key_button_changed = bc_key_button.changed.connect( on_bc_key_button_changed );
+			sigid_bc_digits_spin_changed = bc_digits_spin.value_changed.connect( on_bc_digits_spin_changed );
+
+
 			/* Line widgets. */
 			line_width_spin         = builder.get_object( "line_width_spin" )         as Gtk.SpinButton;
 			line_color_box          = builder.get_object( "line_color_box" )          as Gtk.Box;
@@ -429,6 +490,7 @@ namespace glabels
 
 					text_page_box.show_all();
 					image_page_box.hide();
+					bc_page_box.hide();
 					line_fill_page_box.hide();
 					pos_size_page_box.show_all();
 					shadow_page_box.show_all();
@@ -443,6 +505,7 @@ namespace glabels
 
 					text_page_box.hide();
 					image_page_box.hide();
+					bc_page_box.hide();
 					line_fill_page_box.show_all();
 					pos_size_page_box.show_all();
 					shadow_page_box.show_all();
@@ -457,6 +520,7 @@ namespace glabels
 
 					text_page_box.hide();
 					image_page_box.hide();
+					bc_page_box.hide();
 					line_fill_page_box.show_all();
 					pos_size_page_box.show_all();
 					shadow_page_box.show_all();
@@ -471,6 +535,7 @@ namespace glabels
 
 					text_page_box.hide();
 					image_page_box.hide();
+					bc_page_box.hide();
 					line_fill_page_box.show_all();
 					pos_size_page_box.show_all();
 					shadow_page_box.show_all();
@@ -486,6 +551,7 @@ namespace glabels
 
 					text_page_box.hide();
 					image_page_box.show_all();
+					bc_page_box.hide();
 					line_fill_page_box.hide();
 					pos_size_page_box.show_all();
 					shadow_page_box.show_all();
@@ -493,6 +559,22 @@ namespace glabels
 					line_size_frame.hide();
 					size_reset_image_button.hide();
 				}
+				else if ( object is LabelObjectBarcode )
+				{
+					title_image.set_from_icon_name( "glabels-barcode", Gtk.IconSize.LARGE_TOOLBAR );
+					title_label.set_text( "<b>%s</b>".printf( _("Barcode object properties") ) );
+
+					text_page_box.hide();
+					image_page_box.hide();
+					bc_page_box.show_all();
+					line_fill_page_box.hide();
+					pos_size_page_box.show_all();
+					shadow_page_box.hide();
+
+					line_size_frame.hide();
+					size_aspect_check.hide();
+					size_reset_image_button.hide();
+				}
 				else
 				{
 					assert_not_reached();
@@ -510,6 +592,13 @@ namespace glabels
 				load_text_textview();
 				load_image_filebutton();
 				load_image_key_button();
+				load_bc_type_combo();
+				load_bc_show_text_check();
+				load_bc_checksum_check();
+				load_bc_color_button();
+				load_bc_data_textbuffer();
+				load_bc_key_button();
+				load_bc_digits_spin();
 				load_line_width_spin();
 				load_line_color_button();
 				load_fill_color_button();
@@ -577,12 +666,17 @@ namespace glabels
 				text_color_button.clear_keys();
 				text_insert_field_button.clear_keys();
 				image_key_button.clear_keys();
+				bc_key_button.clear_keys();
 				line_color_button.clear_keys();
 				fill_color_button.clear_keys();
 				shadow_color_button.clear_keys();
 
 				image_file_radio.set_active( true );
 				image_key_radio.set_sensitive( false );
+
+				bc_literal_radio.set_active( true );
+				bc_key_radio.set_sensitive( false );
+				bc_key_grid.set_sensitive( false );
 			}
 			else
 			{
@@ -595,6 +689,8 @@ namespace glabels
 				shadow_color_button.set_keys( key_list );
 
 				image_key_radio.set_sensitive( true );
+				bc_key_radio.set_sensitive( true );
+				bc_key_grid.set_sensitive( true );
 			}
 		}
 
@@ -617,6 +713,13 @@ namespace glabels
 			{
 				load_size_w_spin();
 				load_size_h_spin();
+
+				if ( object is LabelObjectBarcode )
+				{
+					load_bc_show_text_check();
+					load_bc_checksum_check();
+					load_bc_digits_spin();
+				}
 			}
 		}
 
@@ -1067,6 +1170,201 @@ namespace glabels
 			}
 		}
 
+
+		/******************************
+		 * bc_type_combo
+		 ******************************/
+		private void on_bc_type_combo_changed()
+		{
+			if ( object != null )
+			{
+				object.bc_type = BarcodeBackends.name_to_id( bc_type_combo.get_active_text() );
+			}
+		}
+
+		private void load_bc_type_combo()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				GLib.SignalHandler.block( (void*)bc_type_combo, sigid_bc_type_combo_changed );
+
+				ComboUtil.set_active_text( bc_type_combo,
+				                           BarcodeBackends.id_to_name( object.bc_type ) );
+
+				GLib.SignalHandler.unblock( (void*)bc_type_combo, sigid_bc_type_combo_changed );
+			}
+		}
+
+
+		/******************************
+		 * bc_show_text_check
+		 ******************************/
+		private void on_bc_show_text_check_toggled()
+		{
+			if ( object != null )
+			{
+				object.bc_text_flag = bc_show_text_check.get_active();
+			}
+		}
+
+		private void load_bc_show_text_check()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				GLib.SignalHandler.block( (void*)bc_show_text_check, sigid_bc_show_text_check_toggled );
+
+				bc_show_text_check.set_sensitive( object.bc_style.text_optional );
+				bc_show_text_check.set_active( object.bc_text_flag );
+
+				GLib.SignalHandler.unblock( (void*)bc_show_text_check, sigid_bc_show_text_check_toggled );
+			}
+		}
+
+
+		/******************************
+		 * bc_checksum_check
+		 ******************************/
+		private void on_bc_checksum_check_toggled()
+		{
+			if ( object != null )
+			{
+				object.bc_checksum_flag = bc_checksum_check.get_active();
+			}
+		}
+
+		private void load_bc_checksum_check()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				GLib.SignalHandler.block( (void*)bc_checksum_check, sigid_bc_checksum_check_toggled );
+
+				bc_checksum_check.set_sensitive( object.bc_style.checksum_optional );
+				bc_checksum_check.set_active( object.bc_checksum_flag );
+
+				GLib.SignalHandler.unblock( (void*)bc_checksum_check, sigid_bc_checksum_check_toggled );
+			}
+		}
+
+
+		/******************************
+		 * bc_color_button
+		 ******************************/
+		private void on_bc_color_button_changed()
+		{
+			if ( object != null )
+			{
+				bool is_default;
+
+				object.bc_color_node = bc_color_button.get_color_node( out is_default );
+			}
+		}
+
+
+		private void load_bc_color_button()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				GLib.SignalHandler.block( (void*)bc_color_button, sigid_bc_color_button_changed );
+
+				bc_color_button.set_color_node( object.bc_color_node );
+
+				GLib.SignalHandler.unblock( (void*)bc_color_button, sigid_bc_color_button_changed );
+			}
+		}
+
+
+		/******************************
+		 * bc_data_textbuffer
+		 ******************************/
+		private void on_bc_data_textbuffer_changed()
+		{
+			if ( object != null )
+			{
+				Gtk.TextIter start, end;
+
+				bc_data_textbuffer.get_bounds( out start, out end );
+
+				object.bc_data_node = new TextNode( false, bc_data_textbuffer.get_text( start, end, false ) );
+			}
+		}
+
+
+		private void load_bc_data_textbuffer()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				if ( !object.bc_data_node.field_flag )
+				{
+					bc_literal_radio.set_active( true );
+
+					GLib.SignalHandler.block( (void*)bc_data_textbuffer, sigid_bc_data_textbuffer_changed );
+
+					bc_data_textbuffer.set_text( object.bc_data_node.data );
+
+					GLib.SignalHandler.unblock( (void*)bc_data_textbuffer, sigid_bc_data_textbuffer_changed );
+				}
+			}
+		}
+
+
+		/******************************
+		 * bc_key_button
+		 ******************************/
+		private void on_bc_key_button_changed()
+		{
+			if ( object != null )
+			{
+				object.bc_data_node = new TextNode( true, bc_key_button.get_key() );
+			}
+		}
+
+		private void load_bc_key_button()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				if ( object.bc_data_node.field_flag )
+				{
+					bc_key_radio.set_active( true );
+
+					GLib.SignalHandler.block( (void*)bc_key_button, sigid_bc_key_button_changed );
+
+					bc_key_button.set_key( object.bc_data_node.data );
+
+					GLib.SignalHandler.unblock( (void*)bc_key_button, sigid_bc_key_button_changed );
+				}
+			}
+		}
+
+
+		/******************************
+		 * bc_digits_spin
+		 ******************************/
+		private void on_bc_digits_spin_changed()
+		{
+			if ( object != null )
+			{
+				object.bc_format_digits = bc_digits_spin.get_value_as_int();
+
+				/* TODO: load format label. */
+			}
+		}
+
+
+		private void load_bc_digits_spin()
+		{
+			if ( (object != null) && object is LabelObjectBarcode )
+			{
+				GLib.SignalHandler.block( (void*)bc_digits_spin, sigid_bc_digits_spin_changed );
+
+				bc_digits_spin.set_value( object.bc_format_digits );
+
+				/* TODO: load format label. */
+
+				GLib.SignalHandler.unblock( (void*)bc_digits_spin, sigid_bc_digits_spin_changed );
+			}
+		}
+
+
 		/******************************
 		 * line_width_spin
 		 ******************************/
diff --git a/glabels/ui.vala b/glabels/ui.vala
index 973ed4a..44e34cf 100644
--- a/glabels/ui.vala
+++ b/glabels/ui.vala
@@ -1182,12 +1182,7 @@ namespace glabels
 
 		private void on_objects_create_barcode( Gtk.Action action )
 		{
-			/*
-			if (window->view != NULL) {
-				gl_view_object_create_mode (GL_VIEW(window->view),
-				                            GL_LABEL_OBJECT_BARCODE);
-			}
-			*/
+			window.view.create_barcode_mode();
 		}
 
 
diff --git a/glabels/view.vala b/glabels/view.vala
index a22cbf4..41bc4d7 100644
--- a/glabels/view.vala
+++ b/glabels/view.vala
@@ -473,6 +473,28 @@ namespace glabels
 		}
 
 
+		public void create_barcode_mode()
+		{
+			Gdk.Window window = canvas.get_window();
+
+			try
+			{
+				Gdk.Pixbuf pixbuf = Gdk.Pixbuf.from_pixdata( Cursor.barcode_pixdata, false );
+				Gdk.Cursor cursor = new Gdk.Cursor.from_pixbuf( Gdk.Display.get_default(),
+				                                                pixbuf, CURSOR_X_HOTSPOT, CURSOR_Y_HOTSPOT );
+				window.set_cursor( cursor );
+			}
+			catch ( Error err )
+			{
+				error( "%s\n", err.message );
+			}
+
+			in_object_create_mode = true;
+			create_object_type    = CreateType.BARCODE;
+			state                 = State.IDLE;
+		}
+
+
 		private void on_prefs_changed()
 		{
 			grid_spacing = UnitsUtil.get_grid_size( prefs.units );
@@ -941,7 +963,9 @@ namespace glabels
 						                        double.max( y, create_y0 ) - double.min( y, create_y0 ) );
 						break;
 					case CreateType.BARCODE:
-						/* TODO */
+						create_object.set_position( double.min( x, create_x0 ), double.min( y, create_y0 ) );
+						create_object.set_size( double.max( x, create_x0 ) - double.min( x, create_x0 ),
+						                        double.max( y, create_y0 ) - double.min( y, create_y0 ) );
 						break;
 					default:
 						warning( "Invalid create type." );   /* Should not happen! */
@@ -1067,7 +1091,7 @@ namespace glabels
 							create_object = new LabelObjectText()    as LabelObject;
 							break;
 						case CreateType.BARCODE:
-							/* TODO */
+							create_object = new LabelObjectBarcode() as LabelObject;
 							break;
 						default:
 							warning( "Invalid create type." );   /* Should not happen! */
diff --git a/glabels/xml_label.vala b/glabels/xml_label.vala
index edb253a..b81f26f 100644
--- a/glabels/xml_label.vala
+++ b/glabels/xml_label.vala
@@ -202,7 +202,7 @@ namespace glabels
 					break;
 
 				case "Object-barcode":
-					/* TODO. */
+					parse_object_barcode_node( child, label );
 					break;
 
 				case "Object-text":
@@ -374,6 +374,67 @@ namespace glabels
 		}
 
 
+		private void parse_object_barcode_node( Xml.Node node,
+		                                        Label    label )
+		{
+			LabelObjectBarcode object = new LabelObjectBarcode.with_parent( label );
+
+		
+			/* position attrs */
+			object.x0 = XmlUtil.get_prop_length( node, "x", 0.0 );
+			object.y0 = XmlUtil.get_prop_length( node, "y", 0.0 );
+
+			/* size attrs */
+			object.w = XmlUtil.get_prop_length( node, "w", 0 );
+			object.h = XmlUtil.get_prop_length( node, "h", 0 );
+
+			/* style attrs */
+			string backend_id = XmlUtil.get_prop_string( node, "backend", null );
+			string style_id   = XmlUtil.get_prop_string( node, "style", "Code39" );
+			if ( (backend_id != null) && (backend_id != "built-in") )
+			{
+				object.bc_type = "%s:%s".printf( backend_id, style_id );
+			}
+			else
+			{
+				object.bc_type = style_id;
+			}
+			object.bc_text_flag     = XmlUtil.get_prop_bool( node, "text", false );
+			object.bc_checksum_flag = XmlUtil.get_prop_bool( node, "checksum", true );
+			object.bc_format_digits = XmlUtil.get_prop_int(  node, "format", 10 );
+					
+			/* color attrs */
+			{
+				string key        = XmlUtil.get_prop_string( node, "color_field", null );
+				bool   field_flag = key != null;
+				Color  color      = Color.from_legacy_color( XmlUtil.get_prop_uint( node, "color", 0 ) );
+				object.bc_color_node = ColorNode( field_flag, color, key );
+			}
+
+			/* data attrs */
+			string data = XmlUtil.get_prop_string( node, "data", null );
+			if ( data != null )
+			{
+				object.bc_data_node = new TextNode( false, data );
+			}
+			else
+			{
+				string field = XmlUtil.get_prop_string( node, "field", null );
+				if ( field != null )
+				{
+					object.bc_data_node = new TextNode( true, field );
+				}
+				else
+				{
+					message( "Missing Object-barcode data or field attr." );
+				}
+			}
+	
+			/* affine attrs */
+			parse_affine_attrs( node, object );
+		}
+
+
 		private void parse_object_text_node( Xml.Node node,
 		                                     Label    label )
 		{
@@ -697,11 +758,15 @@ namespace glabels
 				{
 					create_object_image_node( node, ns, object as LabelObjectImage );
 				}
+				else if ( object is LabelObjectBarcode )
+				{
+					create_object_barcode_node( node, ns, object as LabelObjectBarcode );
+				}
 				else if ( object is LabelObjectText )
 				{
 					create_object_text_node( node, ns, object as LabelObjectText );
 				}
-				else /* TODO: other object types. */
+				else
 				{
 					message( "Unknown label object." );
 				}
@@ -860,6 +925,64 @@ namespace glabels
 		}
 
 
+		private void create_object_barcode_node( Xml.Node        parent,
+		                                         Xml.Ns          ns,
+		                                         LabelObjectBarcode object )
+		{
+			unowned Xml.Node *node = parent.new_child( ns, "Object-barcode" );
+
+			/* position attrs */
+			XmlUtil.set_prop_length( node, "x", object.x0 );
+			XmlUtil.set_prop_length( node, "y", object.y0 );
+
+			/* size attrs */
+			XmlUtil.set_prop_length( node, "w", object.w );
+			XmlUtil.set_prop_length( node, "h", object.h );
+
+			/* style attrs */
+			if ( object.bc_type.contains( ":" ) )
+			{
+				string[] token = object.bc_type.split( ":", 2 );
+				XmlUtil.set_prop_string( node, "backend", token[0] );
+				XmlUtil.set_prop_string( node, "style",   token[1] );
+			}
+			else
+			{
+				XmlUtil.set_prop_string( node, "backend", "built-in" );
+				XmlUtil.set_prop_string( node, "style",   object.bc_type );
+			}
+			XmlUtil.set_prop_bool( node, "text",     object.bc_text_flag );
+			XmlUtil.set_prop_bool( node, "checksum", object.bc_text_flag );
+
+			/* data attrs */
+			if ( object.bc_data_node.field_flag )
+			{
+				XmlUtil.set_prop_string( node, "field",  object.bc_data_node.data );
+				XmlUtil.set_prop_int(    node, "format", object.bc_format_digits );
+			}
+			else
+			{
+				XmlUtil.set_prop_string( node, "data",  object.bc_data_node.data );
+			}
+
+			/* color attrs */
+			if ( object.bc_color_node.field_flag )
+			{
+				XmlUtil.set_prop_string( node, "color_field", object.bc_color_node.key );
+			}
+			else
+			{
+				XmlUtil.set_prop_uint_hex( node, "color", object.bc_color_node.color.to_legacy_color() );
+			}
+
+			/* affine attrs */
+			create_affine_attrs( node, object );
+
+			/* shadow attrs */
+			create_shadow_attrs( node, object );
+		}
+
+
 		private void create_object_text_node( Xml.Node        parent,
 		                                      Xml.Ns          ns,
 		                                      LabelObjectText object )
diff --git a/libglbarcode/barcode.vala b/libglbarcode/barcode.vala
index 683d9ad..9693296 100644
--- a/libglbarcode/barcode.vala
+++ b/libglbarcode/barcode.vala
@@ -63,7 +63,8 @@ namespace glbarcode
 		{
 			if ( (data == null) || (data == "") )
 			{
-				is_empty = true;
+				is_empty      = true;
+				is_data_valid = false;
 			}
 			else
 			{



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