فهرست منبع

Removed legacy GTK files.

Juan Pablo Caram 9 سال پیش
والد
کامیت
2abc9a8faf

+ 0 - 46
FlatCAM_GTK/FCNoteBook.py

@@ -1,46 +0,0 @@
-from gi.repository import Gtk
-
-
-class FCNoteBook(Gtk.Notebook):
-
-    def __init__(self):
-        Gtk.Notebook.__init__(self, vexpand=True, vexpand_set=True, valign=1, expand=True)
-
-        ###############
-        ### Project ###
-        ###############
-        self.project_contents = Gtk.VBox(vexpand=True, valign=0, vexpand_set=True, expand=True)
-        sw1 = Gtk.ScrolledWindow(vexpand=True, valign=0, vexpand_set=True, expand=True)
-        sw1.add_with_viewport(self.project_contents)
-        self.project_page_num = self.append_page(sw1, Gtk.Label("Project"))
-
-        ################
-        ### Selected ###
-        ################
-        self.selected_contents = Gtk.VBox()
-        sw2 = Gtk.ScrolledWindow()
-        sw2.add_with_viewport(self.selected_contents)
-        self.selected_page_num = self.append_page(sw2, Gtk.Label("Selected"))
-
-        ###############
-        ### Options ###
-        ###############
-        self.options_contents_super = Gtk.VBox()
-        sw3 = Gtk.ScrolledWindow()
-        sw3.add_with_viewport(self.options_contents_super)
-        self.options_page_num = self.append_page(sw3, Gtk.Label("Options"))
-
-        hb = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
-        ico = Gtk.Image.new_from_file("share/gear32.png")
-        hb.pack_start(ico, expand=False, fill=False, padding=0)
-        self.combo_options = Gtk.ComboBoxText()
-        hb.pack_start(self.combo_options, expand=True, fill=True, padding=0)
-        self.options_contents_super.pack_start(hb, expand=False, fill=False, padding=0)
-        self.options_contents = Gtk.VBox()
-        self.options_contents_super.pack_start(self.options_contents, expand=False, fill=False, padding=0)
-
-        ############
-        ### Tool ###
-        ############
-        self.tool_contents = Gtk.VBox()
-        self.tool_page_num = self.append_page(self.tool_contents, Gtk.Label("Tool"))

+ 0 - 15
FlatCAM_GTK/FlatCAM.py

@@ -1,15 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-from gi.repository import Gtk
-
-from FlatCAM_GTK.FlatCAMApp import *
-
-
-app = App()
-Gtk.main()

+ 0 - 1402
FlatCAM_GTK/FlatCAM.ui

@@ -1,1402 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
-  <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkAboutDialog" id="aboutdialog">
-    <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="type_hint">dialog</property>
-    <property name="program_name">FlatCAM</property>
-    <property name="version">Version Alpha 5 (2014/05)</property>
-    <property name="copyright" translatable="yes">(c) 2014 Juan Pablo Caram</property>
-    <property name="comments" translatable="yes">2D Post-processing for Manufacturing specialized in 
-Printed Circuit Boards</property>
-    <property name="website">http://caram.cl/software/flatcam/</property>
-    <property name="website_label" translatable="yes">Caram.cl/software/flatcam</property>
-    <property name="license" translatable="yes">The MIT License (MIT)
-
-Copyright (c) 2014 Juan Pablo Caram
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.</property>
-    <property name="logo">share/flatcam_icon128.png</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="aboutdialog-vbox1">
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="aboutdialog-action_area1">
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <placeholder/>
-        </child>
-      </object>
-    </child>
-  </object>
-  <object class="GtkImage" id="image1">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-open</property>
-  </object>
-  <object class="GtkImage" id="image10">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-page-setup</property>
-  </object>
-  <object class="GtkImage" id="image16">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-info</property>
-  </object>
-  <object class="GtkImage" id="image17">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="pixbuf">share/clear_plot16.png</property>
-  </object>
-  <object class="GtkImage" id="image18">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="pixbuf">share/clear_plot16.png</property>
-  </object>
-  <object class="GtkImage" id="image19">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="pixbuf">share/replot16.png</property>
-  </object>
-  <object class="GtkImage" id="image2">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-open</property>
-  </object>
-  <object class="GtkImage" id="image20">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-open</property>
-  </object>
-  <object class="GtkImage" id="image21">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="pixbuf">share/bug16.png</property>
-  </object>
-  <object class="GtkImage" id="image3">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-open</property>
-  </object>
-  <object class="GtkImage" id="image4">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-save</property>
-  </object>
-  <object class="GtkImage" id="image5">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-jump-to</property>
-  </object>
-  <object class="GtkImage" id="image6">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-save</property>
-  </object>
-  <object class="GtkImage" id="image7">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-save-as</property>
-  </object>
-  <object class="GtkImage" id="image8">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-save-as</property>
-  </object>
-  <object class="GtkImage" id="image9">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="stock">gtk-open</property>
-  </object>
-  <object class="GtkOffscreenWindow" id="offscreenwindow_dblsided">
-    <property name="can_focus">False</property>
-    <child>
-      <object class="GtkScrolledWindow" id="sw_dblsided">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="hscrollbar_policy">never</property>
-        <property name="shadow_type">in</property>
-        <child>
-          <object class="GtkViewport" id="vp_dblsided">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <child>
-              <object class="GtkBox" id="box_dblsided">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">5</property>
-                <property name="margin_right">5</property>
-                <property name="margin_top">5</property>
-                <property name="margin_bottom">5</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkLabel" id="label53">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_bottom">6</property>
-                    <property name="ypad">3</property>
-                    <property name="label" translatable="yes">Double-Sided PCB Tool</property>
-                    <attributes>
-                      <attribute name="weight" value="semibold"/>
-                    </attributes>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkGrid" id="grid7">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="row_spacing">3</property>
-                    <property name="column_spacing">3</property>
-                    <child>
-                      <object class="GtkLabel" id="label84">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_markup" translatable="yes">The object that you want to flip around, 
-usually the Gerber object defining the 
-bottom copper layer. You can also flip
-an Excellon object in case you want to drill
-from the bottom side.</property>
-                        <property name="xalign">1</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Bottom Layer:</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="GtkComboBoxText" id="comboboxtext_bottomlayer">
-                        <property name="width_request">200</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="entry_text_column">0</property>
-                        <property name="id_column">1</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="GtkLabel" id="label85">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_markup" translatable="yes">&lt;b&gt;X&lt;/b&gt; flips from top to bottom,
-&lt;b&gt;Y&lt;/b&gt; flips from left to right.</property>
-                        <property name="xalign">1</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Mirror Axis:</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="box24">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">10</property>
-                        <child>
-                          <object class="GtkRadioButton" id="rb_mirror_x">
-                            <property name="label" translatable="yes">X</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="xalign">0</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="rb_mirror_y">
-                            <property name="label" translatable="yes">Y</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="xalign">0</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">rb_mirror_x</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </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="GtkLabel" id="label86">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_markup" translatable="yes">How the location of the axis
-is specified.</property>
-                        <property name="xalign">1</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Axis location:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">2</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="box25">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">10</property>
-                        <child>
-                          <object class="GtkRadioButton" id="rb_mirror_point">
-                            <property name="label" translatable="yes">Point</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="tooltip_markup" translatable="yes">The axis must pass through the
-specified point.</property>
-                            <property name="xalign">0</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                            <signal name="toggled" handler="on_toggle_pointbox" swapped="no"/>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="rb_mirror_box">
-                            <property name="label" translatable="yes">Box</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="tooltip_markup" translatable="yes">The axis cuts a box (some Geometry object
-in the project) exactly in the middle.</property>
-                            <property name="xalign">0</property>
-                            <property name="draw_indicator">True</property>
-                            <property name="group">rb_mirror_point</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">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>
-                    <child>
-                      <object class="GtkLabel" id="label87">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_markup" translatable="yes">&lt;b&gt;Point:&lt;/b&gt; Click on the desired point on the plot.
-This copies the point to the clipboard. Then paste it
-in the box by right-clicking and choosing paste, or
-hitting Control-v.
-
-&lt;b&gt;Box:&lt;/b&gt; Choose an object in the project
-that you want to use as a box for specifying
-the flipping axis. If the object is not a rectangle,
-a bounding box arounf the object is calculated.</property>
-                        <property name="xalign">1</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Point/Box:</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="box_pointbox">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <placeholder/>
-                        </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="GtkLabel" id="label89">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_markup" translatable="yes">List of coordinates where to drill alignment
-holes, in the format &lt;b&gt;(x1, y1), (x2, y2)&lt;/b&gt;, etc.
-You can click on the plot and paste each
-coordinate here.
-
-All &lt;b&gt;coordinates are duplicated&lt;/b&gt; and mirrored 
-automatically around the axis so drill pattens are 
-identical when flipping your board around.</property>
-                        <property name="xalign">1</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Algnmt holes:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">4</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="entry_dblsided_alignholes">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="invisible_char">●</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">4</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label90">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_markup" translatable="yes">Diameter of the drill for
-the aligment holes.</property>
-                        <property name="xalign">1</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Drill diam.:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">5</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="entry_dblsided_alignholediam">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="invisible_char">●</property>
-                        <property name="invisible_char_set">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">5</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox" id="box27">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">end</property>
-                    <property name="margin_top">6</property>
-                    <property name="margin_bottom">3</property>
-                    <child>
-                      <object class="GtkButton" id="button19">
-                        <property name="label" translatable="yes">Create Alignment Drill</property>
-                        <property name="width_request">120</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="tooltip_markup" translatable="yes">Creates an Excellon object with
-the specified holes and their
-mirror pairs.</property>
-                        <property name="halign">end</property>
-                        <signal name="activate" handler="on_create_aligndrill" swapped="no"/>
-                        <signal name="clicked" handler="on_create_aligndrill" swapped="no"/>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="padding">4</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="button18">
-                        <property name="label" translatable="yes">Mirror Object</property>
-                        <property name="width_request">120</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="tooltip_markup" translatable="yes">Mirrors the object specified in
-&lt;b&gt;Bottom Layer&lt;/b&gt; around the
-specified axis.</property>
-                        <property name="halign">end</property>
-                        <signal name="activate" handler="on_create_mirror" swapped="no"/>
-                        <signal name="clicked" handler="on_create_mirror" swapped="no"/>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="padding">4</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-            </child>
-          </object>
-        </child>
-      </object>
-    </child>
-  </object>
-  <object class="GtkWindow" id="window1">
-    <property name="width_request">600</property>
-    <property name="height_request">400</property>
-    <property name="can_focus">False</property>
-    <signal name="destroy" handler="on_closewindow" swapped="no"/>
-    <child>
-      <object class="GtkBox" id="box1">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <child>
-          <object class="GtkMenuBar" id="menubar1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <signal name="deactivate" handler="do_nothing" swapped="no"/>
-            <child>
-              <object class="GtkMenuItem" id="menuitem1">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_File</property>
-                <property name="use_underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu" id="menu1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem1">
-                        <property name="label">gtk-new</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_text" translatable="yes">New project. Clears all 
-objects and options.</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="on_file_new" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="open_recent">
-                        <property name="label" translatable="yes">Open recent</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image20</property>
-                        <property name="use_stock">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem6">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem2">
-                        <property name="label">Open Gerber</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_text" translatable="yes">Load a Gerber file and create 
-a Gerber Object in the current 
-project.</property>
-                        <property name="image">image2</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_fileopengerber" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem3">
-                        <property name="label">Open Excellon</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_text" translatable="yes">Load an Excellon file and create 
-an Excellon Object in the current 
-project.</property>
-                        <property name="image">image1</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_fileopenexcellon" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem4">
-                        <property name="label">Open G-Code</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_text" translatable="yes">Load a G-Code file and create 
-a CNCJob Object in the current 
-project.</property>
-                        <property name="image">image3</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_fileopengcode" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem11">
-                        <property name="label" translatable="yes">Open Project ...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image9</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_file_openproject" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem2">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem6">
-                        <property name="label" translatable="yes">Save Project</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image6</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_file_saveproject" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem7">
-                        <property name="label" translatable="yes">Save Project As ...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image7</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_file_saveprojectas" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem8">
-                        <property name="label" translatable="yes">Save a Project copy ...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image8</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_file_saveprojectcopy" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="menuitem5">
-                        <property name="label" translatable="yes">Save defaults</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_text" translatable="yes">Saves the application's default options to file.</property>
-                        <property name="image">image4</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_file_savedefaults" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem3">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem5">
-                        <property name="label">gtk-quit</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="on_filequit" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="menuitem2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Edit</property>
-                <property name="use_underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu" id="menu2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem9">
-                        <property name="label">gtk-delete</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="tooltip_text" translatable="yes">Deletes the selected object.</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="on_delete" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="menuitem14">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">View</property>
-                <property name="use_underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu" id="menu7">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem14">
-                        <property name="label" translatable="yes">Disable all plots</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image17</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_disable_all_plots" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem15">
-                        <property name="label" translatable="yes">Disable all plots but this one</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image18</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_disable_all_plots_not_current" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem16">
-                        <property name="label" translatable="yes">Enable all plots</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image19</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="enable_all_plots" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="menuitem3">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Options</property>
-                <property name="use_underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu" id="menu4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkImageMenuItem" id="menuitem6">
-                        <property name="label" translatable="yes">Transfer options</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image5</property>
-                        <property name="use_stock">False</property>
-                        <child type="submenu">
-                          <object class="GtkMenu" id="menu5">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkMenuItem" id="menuitem7">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">Make the application's default options 
-equal to the current project's default options.</property>
-                                <property name="label" translatable="yes">Project =&gt; App</property>
-                                <property name="use_underline">True</property>
-                                <signal name="activate" handler="on_options_project2app" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="menuitem8">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">Make the project's options equal to the 
-application's default options.</property>
-                                <property name="label" translatable="yes">App =&gt; Project</property>
-                                <property name="use_underline">True</property>
-                                <signal name="activate" handler="on_options_app2project" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="menuitem9">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">Make the current object's 
-options be project defaults.</property>
-                                <property name="label" translatable="yes">Object =&gt; Project</property>
-                                <property name="use_underline">True</property>
-                                <signal name="activate" handler="on_options_object2project" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="menuitem10">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">Make the current object's 
-options be application defaults.</property>
-                                <property name="label" translatable="yes">Object =&gt; App</property>
-                                <property name="use_underline">True</property>
-                                <signal name="activate" handler="on_options_object2app" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="menuitem12">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">Set the current object's options
-to project defaults.</property>
-                                <property name="label" translatable="yes">Project =&gt; Object</property>
-                                <property name="use_underline">True</property>
-                                <signal name="activate" handler="on_options_project2object" swapped="no"/>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkMenuItem" id="menuitem13">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="tooltip_text" translatable="yes">Set the current object's options
-to application defaults.</property>
-                                <property name="label" translatable="yes">App =&gt; Object</property>
-                                <property name="use_underline">True</property>
-                                <signal name="activate" handler="on_options_app2object" swapped="no"/>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="menuitem11">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Tools</property>
-                <property name="use_underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu" id="menu6">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem12">
-                        <property name="label" translatable="yes">Double-Sided PCB Tool</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image10</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_tools_doublesided" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkSeparatorMenuItem" id="separatormenuitem7">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem17">
-                        <property name="label" translatable="yes">List objects</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image21</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="on_debug_printlist" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuItem" id="menuitem4">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Help</property>
-                <property name="use_underline">True</property>
-                <child type="submenu">
-                  <object class="GtkMenu" id="menu3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem10">
-                        <property name="label">gtk-about</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="on_about" swapped="no"/>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem13">
-                        <property name="label" translatable="yes">Check for updates...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="image">image16</property>
-                        <property name="use_stock">False</property>
-                        <signal name="activate" handler="version_check" swapped="no"/>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkToolbar" id="toolbar_main">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="toolbar_style">icons</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkPaned" id="paned1">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <child>
-              <object class="GtkNotebook" id="notebook1">
-                <property name="width_request">250</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="margin_left">3</property>
-                <property name="margin_right">3</property>
-                <property name="margin_top">3</property>
-                <property name="margin_bottom">3</property>
-                <property name="scrollable">True</property>
-                <child>
-                  <object class="GtkBox" id="box_project">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="vexpand">True</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="tooltip_markup" translatable="yes">Objects in the project.</property>
-                    <property name="label" translatable="yes">Project</property>
-                  </object>
-                  <packing>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox" id="box_selected">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="vexpand">True</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkScrolledWindow" id="sw_selected">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="vexpand">True</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="shadow_type">in</property>
-                        <child>
-                          <object class="GtkViewport" id="vp_selected">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <placeholder/>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="tooltip_markup" translatable="yes">Options and action
-for the current object.</property>
-                    <property name="label" translatable="yes">Selected</property>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox" id="box_options">
-                    <property name="height_request">400</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="vexpand">True</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkScrolledWindow" id="scrolledwindow1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="vexpand">True</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="shadow_type">in</property>
-                        <child>
-                          <object class="GtkViewport" id="vp_options">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkBox" id="options_box_super">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="margin_left">5</property>
-                                <property name="margin_right">5</property>
-                                <property name="margin_bottom">5</property>
-                                <property name="vexpand">True</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkBox" id="box30">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <child>
-                                      <object class="GtkImage" id="image11">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="pixbuf">share/gear32.png</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkComboBoxText" id="combo_options">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="has_tooltip">True</property>
-                                        <property name="tooltip_markup" translatable="yes">Application defaults get transfered
-to every new project. Project options
-get inherited by new project objects.
-
-&lt;b&gt;Save&lt;/b&gt; application defaults
-by choosing &lt;i&gt;File + Save defaults&lt;/i&gt;.
-
-Project obtions are saved with the
-project.</property>
-                                        <property name="tooltip_text" translatable="yes">Application defaults get transfered
-to every new project. Project options
-get inherited by new project objects.
-
-Save application defaults
-by choosing File + Save defaults.
-
-Project obtions are saved with the
-project.</property>
-                                        <property name="margin_left">10</property>
-                                        <property name="margin_right">10</property>
-                                        <property name="margin_top">5</property>
-                                        <property name="margin_bottom">10</property>
-                                        <property name="entry_text_column">0</property>
-                                        <property name="id_column">1</property>
-                                        <items>
-                                          <item translatable="yes">PROJECT OPTIONS</item>
-                                          <item translatable="yes">APPLICATION DEFAULTS</item>
-                                        </items>
-                                        <signal name="changed" handler="on_options_combo_change" swapped="no"/>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">True</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="options_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">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label5">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="tooltip_markup" translatable="yes">Project and application
-defaults.</property>
-                    <property name="label" translatable="yes">Options</property>
-                  </object>
-                  <packing>
-                    <property name="position">2</property>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkBox" id="box_tool">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">3</property>
-                  </packing>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label88">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="tooltip_markup" translatable="yes">Active tool</property>
-                    <property name="label" translatable="yes">Tool</property>
-                  </object>
-                  <packing>
-                    <property name="position">3</property>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="resize">False</property>
-                <property name="shrink">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="box39">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkGrid" id="grid1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-              <packing>
-                <property name="resize">True</property>
-                <property name="shrink">True</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="box2">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin_left">3</property>
-            <property name="margin_right">3</property>
-            <property name="margin_top">3</property>
-            <property name="margin_bottom">3</property>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="hexpand">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">out</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="left_padding">12</property>
-                    <child>
-                      <object class="GtkLabel" id="label_status">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="hexpand">True</property>
-                        <property name="xalign">0</property>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label_item">
-                  <placeholder/>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label3">
-                <property name="width_request">140</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">5</property>
-                <property name="margin_right">5</property>
-                <property name="label" translatable="yes">X: 0.0    Y: 0.0</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label_units">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">6</property>
-                <property name="margin_right">6</property>
-                <property name="label" translatable="yes">[in]</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkProgressBar" id="progressbar">
-                <property name="width_request">50</property>
-                <property name="height_request">10</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">2</property>
-                <property name="margin_right">2</property>
-                <property name="margin_top">2</property>
-                <property name="margin_bottom">2</property>
-                <property name="text" translatable="yes">Idle</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">3</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">3</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>

+ 0 - 2478
FlatCAM_GTK/FlatCAMApp.py

@@ -1,2478 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-import threading
-import sys
-import urllib
-import random
-
-from gi.repository import Gtk, GdkPixbuf, GObject, Gdk, GLib
-
-
-
-
-
-
-# from shapely import speedups
-# Importing shapely speedups was causing the following errors:
-# 'C:\WinPython-32\python-2.7.6\Lib\site-packages\gnome\lib/gio/modules\
-# libgiognutls.dll': The specified module could not be found.
-# Failed to load module: C:\WinPython-32\python-2.7.6\Lib\site-packages\gnome\lib/gio/modules\libgiognutls.dll
-# 'C:\WinPython-32\python-2.7.6\Lib\site-packages\gnome\lib/gio/modules\
-# libgiolibproxy.dll': The specified module could not be found.
-# Failed to load module: C:\WinPython-32\python-2.7.6\Lib\site-packages\gnome\lib/gio/modules\libgiolibproxy.dll
-
-
-########################################
-##      Imports part of FlatCAM       ##
-########################################
-from FlatCAM_GTK.FlatCAMWorker import Worker
-from FlatCAM_GTK.ObjectCollection import *
-from FlatCAM_GTK.FlatCAMObj import *
-from FlatCAM_GTK.PlotCanvas import *
-from FlatCAM_GTK.FlatCAMGUI import *
-
-
-class GerberOptionsGroupUI(Gtk.VBox):
-    def __init__(self):
-        Gtk.VBox.__init__(self, spacing=3, margin=5, vexpand=False)
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        # Plot CB
-        self.plot_cb = FCCheckBox(label='Plot')
-        grid0.attach(self.plot_cb, 0, 0, 1, 1)
-
-        # Solid CB
-        self.solid_cb = FCCheckBox(label='Solid')
-        grid0.attach(self.solid_cb, 1, 0, 1, 1)
-
-        # Multicolored CB
-        self.multicolored_cb = FCCheckBox(label='Multicolored')
-        grid0.attach(self.multicolored_cb, 2, 0, 1, 1)
-
-        ## Isolation Routing
-        self.isolation_routing_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.isolation_routing_label.set_markup("<b>Isolation Routing:</b>")
-        self.pack_start(self.isolation_routing_label, expand=True, fill=False, padding=2)
-
-        grid = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid, expand=True, fill=False, padding=2)
-
-        l1 = Gtk.Label('Tool diam:', xalign=1)
-        grid.attach(l1, 0, 0, 1, 1)
-        self.iso_tool_dia_entry = LengthEntry()
-        grid.attach(self.iso_tool_dia_entry, 1, 0, 1, 1)
-
-        l2 = Gtk.Label('Width (# passes):', xalign=1)
-        grid.attach(l2, 0, 1, 1, 1)
-        self.iso_width_entry = IntEntry()
-        grid.attach(self.iso_width_entry, 1, 1, 1, 1)
-
-        l3 = Gtk.Label('Pass overlap:', xalign=1)
-        grid.attach(l3, 0, 2, 1, 1)
-        self.iso_overlap_entry = FloatEntry()
-        grid.attach(self.iso_overlap_entry, 1, 2, 1, 1)
-
-        ## Board cuttout
-        self.isolation_routing_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.isolation_routing_label.set_markup("<b>Board cutout:</b>")
-        self.pack_start(self.isolation_routing_label, expand=True, fill=False, padding=2)
-
-        grid2 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid2, expand=True, fill=False, padding=2)
-
-        l4 = Gtk.Label('Tool dia:', xalign=1)
-        grid2.attach(l4, 0, 0, 1, 1)
-        self.cutout_tooldia_entry = LengthEntry()
-        grid2.attach(self.cutout_tooldia_entry, 1, 0, 1, 1)
-
-        l5 = Gtk.Label('Margin:', xalign=1)
-        grid2.attach(l5, 0, 1, 1, 1)
-        self.cutout_margin_entry = LengthEntry()
-        grid2.attach(self.cutout_margin_entry, 1, 1, 1, 1)
-
-        l6 = Gtk.Label('Gap size:', xalign=1)
-        grid2.attach(l6, 0, 2, 1, 1)
-        self.cutout_gap_entry = LengthEntry()
-        grid2.attach(self.cutout_gap_entry, 1, 2, 1, 1)
-
-        l7 = Gtk.Label('Gaps:', xalign=1)
-        grid2.attach(l7, 0, 3, 1, 1)
-        self.gaps_radio = RadioSet([{'label': '2 (T/B)', 'value': 'tb'},
-                                    {'label': '2 (L/R)', 'value': 'lr'},
-                                    {'label': '4', 'value': '4'}])
-        grid2.attach(self.gaps_radio, 1, 3, 1, 1)
-
-        ## Non-copper regions
-        self.noncopper_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.noncopper_label.set_markup("<b>Non-copper regions:</b>")
-        self.pack_start(self.noncopper_label, expand=True, fill=False, padding=2)
-
-        grid3 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid3, expand=True, fill=False, padding=2)
-
-        l8 = Gtk.Label('Boundary margin:', xalign=1)
-        grid3.attach(l8, 0, 0, 1, 1)
-        self.noncopper_margin_entry = LengthEntry()
-        grid3.attach(self.noncopper_margin_entry, 1, 0, 1, 1)
-
-        self.noncopper_rounded_cb = FCCheckBox(label="Rounded corners")
-        grid3.attach(self.noncopper_rounded_cb, 0, 1, 2, 1)
-
-        ## Bounding box
-        self.boundingbox_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.boundingbox_label.set_markup('<b>Bounding Box:</b>')
-        self.pack_start(self.boundingbox_label, expand=True, fill=False, padding=2)
-
-        grid4 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid4, expand=True, fill=False, padding=2)
-
-        l9 = Gtk.Label('Boundary Margin:', xalign=1)
-        grid4.attach(l9, 0, 0, 1, 1)
-        self.bbmargin_entry = LengthEntry()
-        grid4.attach(self.bbmargin_entry, 1, 0, 1, 1)
-
-        self.bbrounded_cb = FCCheckBox(label="Rounded corners")
-        grid4.attach(self.bbrounded_cb, 0, 1, 2, 1)
-
-
-class ExcellonOptionsGroupUI(Gtk.VBox):
-    def __init__(self):
-        Gtk.VBox.__init__(self, spacing=3, margin=5, vexpand=False)
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        self.plot_cb = FCCheckBox(label='Plot')
-        grid0.attach(self.plot_cb, 0, 0, 1, 1)
-
-        self.solid_cb = FCCheckBox(label='Solid')
-        grid0.attach(self.solid_cb, 1, 0, 1, 1)
-
-        ## Create CNC Job
-        self.cncjob_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.cncjob_label.set_markup('<b>Create CNC Job</b>')
-        self.pack_start(self.cncjob_label, expand=True, fill=False, padding=2)
-
-        grid1 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid1, expand=True, fill=False, padding=2)
-
-        l1 = Gtk.Label('Cut Z:', xalign=1)
-        grid1.attach(l1, 0, 0, 1, 1)
-        self.cutz_entry = LengthEntry()
-        grid1.attach(self.cutz_entry, 1, 0, 1, 1)
-
-        l2 = Gtk.Label('Travel Z:', xalign=1)
-        grid1.attach(l2, 0, 1, 1, 1)
-        self.travelz_entry = LengthEntry()
-        grid1.attach(self.travelz_entry, 1, 1, 1, 1)
-
-        l3 = Gtk.Label('Feed rate:', xalign=1)
-        grid1.attach(l3, 0, 2, 1, 1)
-        self.feedrate_entry = LengthEntry()
-        grid1.attach(self.feedrate_entry, 1, 2, 1, 1)
-
-
-class GeometryOptionsGroupUI(Gtk.VBox):
-    def __init__(self):
-        Gtk.VBox.__init__(self, spacing=3, margin=5, vexpand=False)
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        # Plot CB
-        self.plot_cb = FCCheckBox(label='Plot')
-        grid0.attach(self.plot_cb, 0, 0, 1, 1)
-
-        ## Create CNC Job
-        self.cncjob_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.cncjob_label.set_markup('<b>Create CNC Job:</b>')
-        self.pack_start(self.cncjob_label, expand=True, fill=False, padding=2)
-
-        grid1 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid1, expand=True, fill=False, padding=2)
-
-        # Cut Z
-        l1 = Gtk.Label('Cut Z:', xalign=1)
-        grid1.attach(l1, 0, 0, 1, 1)
-        self.cutz_entry = LengthEntry()
-        grid1.attach(self.cutz_entry, 1, 0, 1, 1)
-
-        # Travel Z
-        l2 = Gtk.Label('Travel Z:', xalign=1)
-        grid1.attach(l2, 0, 1, 1, 1)
-        self.travelz_entry = LengthEntry()
-        grid1.attach(self.travelz_entry, 1, 1, 1, 1)
-
-        l3 = Gtk.Label('Feed rate:', xalign=1)
-        grid1.attach(l3, 0, 2, 1, 1)
-        self.cncfeedrate_entry = LengthEntry()
-        grid1.attach(self.cncfeedrate_entry, 1, 2, 1, 1)
-
-        l4 = Gtk.Label('Tool dia:', xalign=1)
-        grid1.attach(l4, 0, 3, 1, 1)
-        self.cnctooldia_entry = LengthEntry()
-        grid1.attach(self.cnctooldia_entry, 1, 3, 1, 1)
-
-        ## Paint Area
-        self.paint_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.paint_label.set_markup('<b>Paint Area:</b>')
-        self.pack_start(self.paint_label, expand=True, fill=False, padding=2)
-
-        grid2 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid2, expand=True, fill=False, padding=2)
-
-        # Tool dia
-        l5 = Gtk.Label('Tool dia:', xalign=1)
-        grid2.attach(l5, 0, 0, 1, 1)
-        self.painttooldia_entry = LengthEntry()
-        grid2.attach(self.painttooldia_entry, 1, 0, 1, 1)
-
-        # Overlap
-        l6 = Gtk.Label('Overlap:', xalign=1)
-        grid2.attach(l6, 0, 1, 1, 1)
-        self.paintoverlap_entry = LengthEntry()
-        grid2.attach(self.paintoverlap_entry, 1, 1, 1, 1)
-
-        # Margin
-        l7 = Gtk.Label('Margin:', xalign=1)
-        grid2.attach(l7, 0, 2, 1, 1)
-        self.paintmargin_entry = LengthEntry()
-        grid2.attach(self.paintmargin_entry, 1, 2, 1, 1)
-
-
-class CNCJobOptionsGroupUI(Gtk.VBox):
-    def __init__(self):
-        Gtk.VBox.__init__(self, spacing=3, margin=5, vexpand=False)
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        # Plot CB
-        self.plot_cb = FCCheckBox(label='Plot')
-        grid0.attach(self.plot_cb, 0, 0, 2, 1)
-
-        # Tool dia for plot
-        l1 = Gtk.Label('Tool dia:', xalign=1)
-        grid0.attach(l1, 0, 1, 1, 1)
-        self.tooldia_entry = LengthEntry()
-        grid0.attach(self.tooldia_entry, 1, 1, 1, 1)
-
-
-class GlobalOptionsUI(Gtk.VBox):
-    def __init__(self):
-        Gtk.VBox.__init__(self, spacing=3, margin=5, vexpand=False)
-
-        box1 = Gtk.Box()
-        self.pack_start(box1, expand=False, fill=False, padding=2)
-        l1 = Gtk.Label('Units:')
-        box1.pack_start(l1, expand=False, fill=False, padding=2)
-        self.units_radio = RadioSet([{'label': 'inch', 'value': 'IN'},
-                                     {'label': 'mm', 'value': 'MM'}])
-        box1.pack_start(self.units_radio, expand=False, fill=False, padding=2)
-
-        ####### Gerber #######
-        l2 = Gtk.Label(margin=5)
-        l2.set_markup('<b>Gerber Options</b>')
-        frame1 = Gtk.Frame(label_widget=l2)
-        self.pack_start(frame1, expand=False, fill=False, padding=2)
-        self.gerber_group = GerberOptionsGroupUI()
-        frame1.add(self.gerber_group)
-
-        ######## Excellon #########
-        l3 = Gtk.Label(margin=5)
-        l3.set_markup('<b>Excellon Options</b>')
-        frame2 = Gtk.Frame(label_widget=l3)
-        self.pack_start(frame2, expand=False, fill=False, padding=2)
-        self.excellon_group = ExcellonOptionsGroupUI()
-        frame2.add(self.excellon_group)
-
-        ########## Geometry ##########
-        l4 = Gtk.Label(margin=5)
-        l4.set_markup('<b>Geometry Options</b>')
-        frame3 = Gtk.Frame(label_widget=l4)
-        self.pack_start(frame3, expand=False, fill=False, padding=2)
-        self.geometry_group = GeometryOptionsGroupUI()
-        frame3.add(self.geometry_group)
-
-        ########## CNC ############
-        l5 = Gtk.Label(margin=5)
-        l5.set_markup('<b>CNC Job Options</b>')
-        frame4 = Gtk.Frame(label_widget=l5)
-        self.pack_start(frame4, expand=False, fill=False, padding=2)
-        self.cncjob_group = CNCJobOptionsGroupUI()
-        frame4.add(self.cncjob_group)
-
-
-########################################
-##                App                 ##
-########################################
-class App:
-    """
-    The main application class. The constructor starts the GUI.
-    """
-
-    log = logging.getLogger('base')
-    log.setLevel(logging.DEBUG)
-    #log.setLevel(logging.WARNING)
-    formatter = logging.Formatter('[%(levelname)s] %(message)s')
-    handler = logging.StreamHandler()
-    handler.setFormatter(formatter)
-    log.addHandler(handler)
-
-    version_url = "http://caram.cl/flatcam/VERSION"
-
-    def __init__(self):
-        """
-        Starts the application. Takes no parameters.
-
-        :return: app
-        :rtype: App
-        """
-
-        App.log.info("FlatCAM Starting...")
-
-        # if speedups.available:
-        #     App.log.info("Enabling geometry speedups...")
-        #     speedups.enable()
-
-        # Needed to interact with the GUI from other threads.
-        App.log.debug("GObject.threads_init()...")
-        GObject.threads_init()
-
-        #### GUI ####
-        # Glade init
-        # App.log.debug("Building GUI from Glade file...")
-        # self.gladefile = "FlatCAM.ui"
-        # self.builder = Gtk.Builder()
-        # self.builder.add_from_file(self.gladefile)
-        #
-        # # References to UI widgets
-        # self.window = self.builder.get_object("window1")
-        # self.position_label = self.builder.get_object("label3")
-        # self.grid = self.builder.get_object("grid1")
-        # self.notebook = self.builder.get_object("notebook1")
-        # self.info_label = self.builder.get_object("label_status")
-        # self.progress_bar = self.builder.get_object("progressbar")
-        # self.progress_bar.set_show_text(True)
-        # self.units_label = self.builder.get_object("label_units")
-        # self.toolbar = self.builder.get_object("toolbar_main")
-        #
-        # # White (transparent) background on the "Options" tab.
-        # self.builder.get_object("vp_options").override_background_color(Gtk.StateType.NORMAL,
-        #                                                                 Gdk.RGBA(1, 1, 1, 1))
-        # # Combo box to choose between project and application options.
-        # self.combo_options = self.builder.get_object("combo_options")
-        # self.combo_options.set_active(1)
-        self.ui = FlatCAMGUI()
-
-        #self.setup_project_list()  # The "Project" tab
-        self.setup_component_editor()  # The "Selected" tab
-
-        ## Setup the toolbar. Adds buttons.
-        self.setup_toolbar()
-
-        # App.log.debug("Connecting signals from builder...")
-        #### Event handling ####
-        # self.builder.connect_signals(self)
-        self.ui.menufileopengerber.connect('activate', self.on_fileopengerber)
-
-        #### Make plot area ####
-        self.plotcanvas = PlotCanvas(self.ui.plotarea)
-        self.plotcanvas.mpl_connect('button_press_event', self.on_click_over_plot)
-        self.plotcanvas.mpl_connect('motion_notify_event', self.on_mouse_move_over_plot)
-        self.plotcanvas.mpl_connect('key_press_event', self.on_key_over_plot)
-
-        #### DATA ####
-        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
-        self.setup_obj_classes()
-        self.mouse = None  # Mouse coordinates over plot
-        self.recent = []
-        self.collection = ObjectCollection()
-        # self.builder.get_object("box_project").pack_start(self.collection.view, False, False, 1)
-        self.ui.notebook.project_contents.pack_start(self.collection.view, False, False, 1)
-        # TODO: Do this different
-        self.collection.view.connect("row_activated", self.on_row_activated)
-
-        # Used to inhibit the on_options_update callback when
-        # the options are being changed by the program and not the user.
-        self.options_update_ignore = False
-
-        self.toggle_units_ignore = False
-
-        # self.options_box = self.builder.get_object('options_box')
-        ## Application defaults ##
-        self.defaults_form = GlobalOptionsUI()
-        self.defaults_form_fields = {
-            "units": self.defaults_form.units_radio,
-            "gerber_plot": self.defaults_form.gerber_group.plot_cb,
-            "gerber_solid": self.defaults_form.gerber_group.solid_cb,
-            "gerber_multicolored": self.defaults_form.gerber_group.multicolored_cb,
-            "gerber_isotooldia": self.defaults_form.gerber_group.iso_tool_dia_entry,
-            "gerber_isopasses": self.defaults_form.gerber_group.iso_width_entry,
-            "gerber_isooverlap": self.defaults_form.gerber_group.iso_overlap_entry,
-            "gerber_cutouttooldia": self.defaults_form.gerber_group.cutout_tooldia_entry,
-            "gerber_cutoutmargin": self.defaults_form.gerber_group.cutout_margin_entry,
-            "gerber_cutoutgapsize": self.defaults_form.gerber_group.cutout_gap_entry,
-            "gerber_gaps": self.defaults_form.gerber_group.gaps_radio,
-            "gerber_noncoppermargin": self.defaults_form.gerber_group.noncopper_margin_entry,
-            "gerber_noncopperrounded": self.defaults_form.gerber_group.noncopper_rounded_cb,
-            "gerber_bboxmargin": self.defaults_form.gerber_group.bbmargin_entry,
-            "gerber_bboxrounded": self.defaults_form.gerber_group.bbrounded_cb,
-            "excellon_plot": self.defaults_form.excellon_group.plot_cb,
-            "excellon_solid": self.defaults_form.excellon_group.solid_cb,
-            "excellon_drillz": self.defaults_form.excellon_group.cutz_entry,
-            "excellon_travelz": self.defaults_form.excellon_group.travelz_entry,
-            "excellon_feedrate": self.defaults_form.excellon_group.feedrate_entry,
-            "geometry_plot": self.defaults_form.geometry_group.plot_cb,
-            "geometry_cutz": self.defaults_form.geometry_group.cutz_entry,
-            "geometry_travelz": self.defaults_form.geometry_group.travelz_entry,
-            "geometry_feedrate": self.defaults_form.geometry_group.cncfeedrate_entry,
-            "geometry_cnctooldia": self.defaults_form.geometry_group.cnctooldia_entry,
-            "geometry_painttooldia": self.defaults_form.geometry_group.painttooldia_entry,
-            "geometry_paintoverlap": self.defaults_form.geometry_group.paintoverlap_entry,
-            "geometry_paintmargin": self.defaults_form.geometry_group.paintmargin_entry,
-            "cncjob_plot": self.defaults_form.cncjob_group.plot_cb,
-            "cncjob_tooldia": self.defaults_form.cncjob_group.tooldia_entry
-        }
-
-        self.defaults = {
-            "units": "IN",
-            "gerber_plot": True,
-            "gerber_solid": True,
-            "gerber_multicolored": False,
-            "gerber_isotooldia": 0.016,
-            "gerber_isopasses": 1,
-            "gerber_isooverlap": 0.15,
-            "gerber_cutouttooldia": 0.07,
-            "gerber_cutoutmargin": 0.1,
-            "gerber_cutoutgapsize": 0.15,
-            "gerber_gaps": "4",
-            "gerber_noncoppermargin": 0.0,
-            "gerber_noncopperrounded": False,
-            "gerber_bboxmargin": 0.0,
-            "gerber_bboxrounded": False,
-            "excellon_plot": True,
-            "excellon_solid": False,
-            "excellon_drillz": -0.1,
-            "excellon_travelz": 0.1,
-            "excellon_feedrate": 3.0,
-            "geometry_plot": True,
-            "geometry_cutz": -0.002,
-            "geometry_travelz": 0.1,
-            "geometry_feedrate": 3.0,
-            "geometry_cnctooldia": 0.016,
-            "geometry_painttooldia": 0.07,
-            "geometry_paintoverlap": 0.15,
-            "geometry_paintmargin": 0.0,
-            "cncjob_plot": True,
-            "cncjob_tooldia": 0.016
-        }
-        self.load_defaults()
-        self.defaults_write_form()
-
-        ## Current Project ##
-        self.options_form = GlobalOptionsUI()
-        self.options_form_fields = {
-            "units": self.options_form.units_radio,
-            "gerber_plot": self.options_form.gerber_group.plot_cb,
-            "gerber_solid": self.options_form.gerber_group.solid_cb,
-            "gerber_multicolored": self.options_form.gerber_group.multicolored_cb,
-            "gerber_isotooldia": self.options_form.gerber_group.iso_tool_dia_entry,
-            "gerber_isopasses": self.options_form.gerber_group.iso_width_entry,
-            "gerber_isooverlap": self.options_form.gerber_group.iso_overlap_entry,
-            "gerber_cutouttooldia": self.options_form.gerber_group.cutout_tooldia_entry,
-            "gerber_cutoutmargin": self.options_form.gerber_group.cutout_margin_entry,
-            "gerber_cutoutgapsize": self.options_form.gerber_group.cutout_gap_entry,
-            "gerber_gaps": self.options_form.gerber_group.gaps_radio,
-            "gerber_noncoppermargin": self.options_form.gerber_group.noncopper_margin_entry,
-            "gerber_noncopperrounded": self.options_form.gerber_group.noncopper_rounded_cb,
-            "gerber_bboxmargin": self.options_form.gerber_group.bbmargin_entry,
-            "gerber_bboxrounded": self.options_form.gerber_group.bbrounded_cb,
-            "excellon_plot": self.options_form.excellon_group.plot_cb,
-            "excellon_solid": self.options_form.excellon_group.solid_cb,
-            "excellon_drillz": self.options_form.excellon_group.cutz_entry,
-            "excellon_travelz": self.options_form.excellon_group.travelz_entry,
-            "excellon_feedrate": self.options_form.excellon_group.feedrate_entry,
-            "geometry_plot": self.options_form.geometry_group.plot_cb,
-            "geometry_cutz": self.options_form.geometry_group.cutz_entry,
-            "geometry_travelz": self.options_form.geometry_group.travelz_entry,
-            "geometry_feedrate": self.options_form.geometry_group.cncfeedrate_entry,
-            "geometry_cnctooldia": self.options_form.geometry_group.cnctooldia_entry,
-            "geometry_painttooldia": self.options_form.geometry_group.painttooldia_entry,
-            "geometry_paintoverlap": self.options_form.geometry_group.paintoverlap_entry,
-            "geometry_paintmargin": self.options_form.geometry_group.paintmargin_entry,
-            "cncjob_plot": self.options_form.cncjob_group.plot_cb,
-            "cncjob_tooldia": self.options_form.cncjob_group.tooldia_entry
-        }
-
-        # Project options
-        self.options = {
-            "units": "IN",
-            "gerber_plot": True,
-            "gerber_solid": True,
-            "gerber_multicolored": False,
-            "gerber_isotooldia": 0.016,
-            "gerber_isopasses": 1,
-            "gerber_isooverlap": 0.15,
-            "gerber_cutouttooldia": 0.07,
-            "gerber_cutoutmargin": 0.1,
-            "gerber_cutoutgapsize": 0.15,
-            "gerber_gaps": "4",
-            "gerber_noncoppermargin": 0.0,
-            "gerber_noncopperrounded": False,
-            "gerber_bboxmargin": 0.0,
-            "gerber_bboxrounded": False,
-            "excellon_plot": True,
-            "excellon_solid": False,
-            "excellon_drillz": -0.1,
-            "excellon_travelz": 0.1,
-            "excellon_feedrate": 3.0,
-            "geometry_plot": True,
-            "geometry_cutz": -0.002,
-            "geometry_travelz": 0.1,
-            "geometry_feedrate": 3.0,
-            "geometry_cnctooldia": 0.016,
-            "geometry_painttooldia": 0.07,
-            "geometry_paintoverlap": 0.15,
-            "geometry_paintmargin": 0.0,
-            "cncjob_plot": True,
-            "cncjob_tooldia": 0.016
-        }
-        self.options.update(self.defaults)  # Copy app defaults to project options
-        self.options_write_form()
-
-        self.project_filename = None
-
-        # Where we draw the options/defaults forms.
-        self.on_options_combo_change(None)
-        #self.options_box.pack_start(self.defaults_form, False, False, 1)
-
-        self.options_form.units_radio.group_toggle_fn = lambda x, y: self.on_toggle_units(x)
-
-        ## Event subscriptions ##
-
-        ## Tools ##
-        # self.measure = Measurement(self.builder.get_object("box39"), self.plotcanvas)
-        self.measure = Measurement(self.ui.plotarea_super, self.plotcanvas)
-        # Toolbar icon
-        # TODO: Where should I put this? Tool should have a method to add to toolbar?
-        meas_ico = Gtk.Image.new_from_file('share/measure32.png')
-        measure = Gtk.ToolButton.new(meas_ico, "")
-        measure.connect("clicked", self.measure.toggle_active)
-        measure.set_tooltip_markup("<b>Measure Tool:</b> Enable/disable tool.\n" +
-                                   "Click on point to set reference.\n" +
-                                   "(Click on plot and hit <b>m</b>)")
-        # self.toolbar.insert(measure, -1)
-        self.ui.toolbar.insert(measure, -1)
-
-        #### Initialization ####
-        # self.units_label.set_text("[" + self.options["units"] + "]")
-        self.ui.units_label.set_text("[" + self.options["units"] + "]")
-        self.setup_recent_items()
-
-        App.log.info("Starting Worker...")
-        self.worker = Worker()
-        self.worker.daemon = True
-        self.worker.start()
-
-        #### Check for updates ####
-        # Separate thread (Not worker)
-        self.version = 5
-        App.log.info("Checking for updates in backgroud (this is version %s)." % str(self.version))
-        t1 = threading.Thread(target=self.version_check)
-        t1.daemon = True
-        t1.start()
-
-        #### For debugging only ###
-        def somethreadfunc(app_obj):
-            App.log.info("Hello World!")
-
-        t = threading.Thread(target=somethreadfunc, args=(self,))
-        t.daemon = True
-        t.start()
-
-        ########################################
-        ##              START                 ##
-        ########################################
-        self.icon256 = GdkPixbuf.Pixbuf.new_from_file('share/flatcam_icon256.png')
-        self.icon48 = GdkPixbuf.Pixbuf.new_from_file('share/flatcam_icon48.png')
-        self.icon16 = GdkPixbuf.Pixbuf.new_from_file('share/flatcam_icon16.png')
-        Gtk.Window.set_default_icon_list([self.icon16, self.icon48, self.icon256])
-        # self.window.set_title("FlatCAM - Alpha 5")
-        # self.window.set_default_size(900, 600)
-        # self.window.show_all()
-        self.ui.show_all()
-
-        App.log.info("END of constructor. Releasing control.")
-
-    def message_dialog(self, title, message, kind="info"):
-        types = {"info": Gtk.MessageType.INFO,
-                 "warn": Gtk.MessageType.WARNING,
-                 "error": Gtk.MessageType.ERROR}
-        dlg = Gtk.MessageDialog(self.ui, 0, types[kind], Gtk.ButtonsType.OK, title)
-        dlg.format_secondary_text(message)
-
-        def lifecycle():
-            dlg.run()
-            dlg.destroy()
-
-        GLib.idle_add(lifecycle)
-
-    def question_dialog(self, title, message):
-        label = Gtk.Label(message)
-        dialog = Gtk.Dialog(title, self.window, 0,
-                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                             Gtk.STOCK_OK, Gtk.ResponseType.OK))
-        dialog.set_default_size(150, 100)
-        dialog.set_modal(True)
-        box = dialog.get_content_area()
-        box.set_border_width(10)
-        box.add(label)
-        dialog.show_all()
-        response = dialog.run()
-        dialog.destroy()
-        return response
-
-    def setup_toolbar(self):
-
-        # Zoom fit
-        # zf_ico = Gtk.Image.new_from_file('share/zoom_fit32.png')
-        # zoom_fit = Gtk.ToolButton.new(zf_ico, "")
-        # zoom_fit.connect("clicked", self.on_zoom_fit)
-        # zoom_fit.set_tooltip_markup("Zoom Fit.\n(Click on plot and hit <b>1</b>)")
-        # self.toolbar.insert(zoom_fit, -1)
-        self.ui.zoom_fit_btn.connect("clicked", self.on_zoom_fit)
-
-        # Zoom out
-        # zo_ico = Gtk.Image.new_from_file('share/zoom_out32.png')
-        # zoom_out = Gtk.ToolButton.new(zo_ico, "")
-        # zoom_out.connect("clicked", self.on_zoom_out)
-        # zoom_out.set_tooltip_markup("Zoom Out.\n(Click on plot and hit <b>2</b>)")
-        # self.toolbar.insert(zoom_out, -1)
-        self.ui.zoom_out_btn.connect("clicked", self.on_zoom_out)
-
-        # Zoom in
-        # zi_ico = Gtk.Image.new_from_file('share/zoom_in32.png')
-        # zoom_in = Gtk.ToolButton.new(zi_ico, "")
-        # zoom_in.connect("clicked", self.on_zoom_in)
-        # zoom_in.set_tooltip_markup("Zoom In.\n(Click on plot and hit <b>3</b>)")
-        # self.toolbar.insert(zoom_in, -1)
-        self.ui.zoom_in_btn.connect("clicked", self.on_zoom_in)
-
-        # Clear plot
-        # cp_ico = Gtk.Image.new_from_file('share/clear_plot32.png')
-        # clear_plot = Gtk.ToolButton.new(cp_ico, "")
-        # clear_plot.connect("clicked", self.on_clear_plots)
-        # clear_plot.set_tooltip_markup("Clear Plot")
-        # self.toolbar.insert(clear_plot, -1)
-        self.ui.clear_plot_btn.connect("clicked", self.on_clear_plots)
-
-        # Replot
-        # rp_ico = Gtk.Image.new_from_file('share/replot32.png')
-        # replot = Gtk.ToolButton.new(rp_ico, "")
-        # replot.connect("clicked", self.on_toolbar_replot)
-        # replot.set_tooltip_markup("Re-plot all")
-        # self.toolbar.insert(replot, -1)
-        self.ui.replot_btn.connect("clicked", self.on_toolbar_replot)
-
-        # Delete item
-        # del_ico = Gtk.Image.new_from_file('share/delete32.png')
-        # delete = Gtk.ToolButton.new(del_ico, "")
-        # delete.connect("clicked", self.on_delete)
-        # delete.set_tooltip_markup("Delete selected\nobject.")
-        # self.toolbar.insert(delete, -1)
-        self.ui.delete_btn.connect("clicked", self.on_delete)
-
-    def setup_obj_classes(self):
-        """
-        Sets up application specifics on the FlatCAMObj class.
-
-        :return: None
-        """
-        FlatCAMObj.app = self
-
-    def setup_component_editor(self):
-        """
-        Initial configuration of the component editor. Creates
-        a page titled "Selection" on the notebook on the left
-        side of the main window.
-
-        :return: None
-        """
-
-        # box_selected = self.builder.get_object("vp_selected")
-
-        # White background
-        # box_selected.override_background_color(Gtk.StateType.NORMAL,
-        #                                        Gdk.RGBA(1, 1, 1, 1))
-        self.ui.notebook.selected_contents.override_background_color(Gtk.StateType.NORMAL,
-                                                                     Gdk.RGBA(1, 1, 1, 1))
-
-        # Remove anything else in the box
-        box_children = self.ui.notebook.selected_contents.get_children()
-        for child in box_children:
-            self.ui.notebook.selected_contents.remove(child)
-
-        box1 = Gtk.Box(Gtk.Orientation.VERTICAL)
-        label1 = Gtk.Label("Choose an item from Project")
-        box1.pack_start(label1, True, False, 1)
-        self.ui.notebook.selected_contents.add(box1)
-        box1.show()
-        label1.show()
-
-    def setup_recent_items(self):
-
-        # TODO: Move this to constructor
-        icons = {
-            "gerber": "share/flatcam_icon16.png",
-            "excellon": "share/drill16.png",
-            "cncjob": "share/cnc16.png",
-            "project": "share/project16.png"
-        }
-
-        openers = {
-            'gerber': self.open_gerber,
-            'excellon': self.open_excellon,
-            'cncjob': self.open_gcode,
-            'project': self.open_project
-        }
-
-        # Closure needed to create callbacks in a loop.
-        # Otherwise late binding occurs.
-        def make_callback(func, fname):
-            def opener(*args):
-                self.worker.add_task(func, [fname])
-            return opener
-
-        try:
-            f = open('recent.json')
-        except IOError:
-            App.log.error("Failed to load recent item list.")
-            self.info("ERROR: Failed to load recent item list.")
-            return
-
-        try:
-            self.recent = json.load(f)
-        except:
-            App.log.error("Failed to parse recent item list.")
-            self.info("ERROR: Failed to parse recent item list.")
-            f.close()
-            return
-        f.close()
-
-        recent_menu = Gtk.Menu()
-        for recent in self.recent:
-            filename = recent['filename'].split('/')[-1].split('\\')[-1]
-            item = Gtk.ImageMenuItem.new_with_label(filename)
-            im = Gtk.Image.new_from_file(icons[recent["kind"]])
-            item.set_image(im)
-
-            o = make_callback(openers[recent["kind"]], recent['filename'])
-
-            item.connect('activate', o)
-            recent_menu.append(item)
-
-        # self.builder.get_object('open_recent').set_submenu(recent_menu)
-        self.ui.menufilerecent.set_submenu(recent_menu)
-        recent_menu.show_all()
-
-    def info(self, text):
-        """
-        Show text on the status bar. This method is thread safe.
-
-        :param text: Text to display.
-        :type text: str
-        :return: None
-        """
-        GLib.idle_add(lambda: self.ui.info_label.set_text(text))
-
-    def get_radio_value(self, radio_set):
-        """
-        Returns the radio_set[key] of the radiobutton
-        whose name is key is active.
-
-        :param radio_set: A dictionary containing widget_name: value pairs.
-        :type radio_set: dict
-        :return: radio_set[key]
-        """
-
-        for name in radio_set:
-            if self.builder.get_object(name).get_active():
-                return radio_set[name]
-
-    def plot_all(self):
-        """
-        Re-generates all plots from all objects.
-
-        :return: None
-        """
-        self.plotcanvas.clear()
-        self.set_progress_bar(0.1, "Re-plotting...")
-
-        def worker_task(app_obj):
-            percentage = 0.1
-            try:
-                delta = 0.9 / len(self.collection.get_list())
-            except ZeroDivisionError:
-                GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, ""))
-                return
-            for obj in self.collection.get_list():
-                obj.plot()
-                percentage += delta
-                GLib.idle_add(lambda: app_obj.set_progress_bar(percentage, "Re-plotting..."))
-
-            GLib.idle_add(app_obj.plotcanvas.auto_adjust_axes)
-            GLib.idle_add(lambda: self.on_zoom_fit(None))
-            GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, "Idle"))
-
-        # Send to worker
-        self.worker.add_task(worker_task, [self])
-
-    def get_eval(self, widget_name):
-        """
-        Runs eval() on the on the text entry of name 'widget_name'
-        and returns the results.
-
-        :param widget_name: Name of Gtk.Entry
-        :type widget_name: str
-        :return: Depends on contents of the entry text.
-        """
-
-        value = self.builder.get_object(widget_name).get_text()
-        if value == "":
-            value = "None"
-        try:
-            evald = eval(value)
-            return evald
-        except:
-            self.info("Could not evaluate: " + value)
-            return None
-
-    def new_object(self, kind, name, initialize, active=True, fit=True, plot=True):
-        """
-        Creates a new specalized FlatCAMObj and attaches it to the application,
-        this is, updates the GUI accordingly, any other records and plots it.
-        This method is thread-safe.
-
-        :param kind: The kind of object to create. One of 'gerber',
-         'excellon', 'cncjob' and 'geometry'.
-        :type kind: str
-        :param name: Name for the object.
-        :type name: str
-        :param initialize: Function to run after creation of the object
-         but before it is attached to the application. The function is
-         called with 2 parameters: the new object and the App instance.
-        :type initialize: function
-        :return: None
-        :rtype: None
-        """
-
-        App.log.debug("new_object()")
-
-        # This is ok here... NO.
-        # t = Gtk.TextView()
-        # print t
-
-        ### Check for existing name
-        if name in self.collection.get_names():
-            ## Create a new name
-            # Ends with number?
-            App.log.debug("new_object(): Object name exists, changing.")
-            match = re.search(r'(.*[^\d])?(\d+)$', name)
-            if match:  # Yes: Increment the number!
-                base = match.group(1) or ''
-                num = int(match.group(2))
-                name = base + str(num + 1)
-            else:  # No: add a number!
-                name += "_1"
-
-        # App dies here!
-        # t = Gtk.TextView()
-        # print t
-
-        # Create object
-        classdict = {
-            "gerber": FlatCAMGerber,
-            "excellon": FlatCAMExcellon,
-            "cncjob": FlatCAMCNCjob,
-            "geometry": FlatCAMGeometry
-        }
-        obj = classdict[kind](name)
-        obj.units = self.options["units"]  # TODO: The constructor should look at defaults.
-
-        # Set default options from self.options
-        for option in self.options:
-            if option.find(kind + "_") == 0:
-                oname = option[len(kind)+1:]
-                obj.options[oname] = self.options[option]
-
-        # Initialize as per user request
-        # User must take care to implement initialize
-        # in a thread-safe way as is is likely that we
-        # have been invoked in a separate thread.
-        initialize(obj, self)
-
-        # Check units and convert if necessary
-        if self.options["units"].upper() != obj.units.upper():
-            GLib.idle_add(lambda: self.info("Converting units to " + self.options["units"] + "."))
-            obj.convert_units(self.options["units"])
-
-        # Add to our records
-        self.collection.append(obj, active=active)
-
-        # Show object details now.
-        # GLib.idle_add(lambda: self.notebook.set_current_page(1))
-        GLib.idle_add(lambda: self.ui.notebook.set_current_page(1))
-
-        # Plot
-        # TODO: (Thread-safe?)
-        if plot:
-            obj.plot()
-
-        if fit:
-            GLib.idle_add(lambda: self.on_zoom_fit(None))
-
-        return obj
-
-    def set_progress_bar(self, percentage, text=""):
-        """
-        Sets the application's progress bar to a given frac_digits and text.
-
-        :param percentage: The frac_digits (0.0-1.0) of the progress.
-        :type percentage: float
-        :param text: Text to display on the progress bar.
-        :type text: str
-        :return: None
-        """
-        # self.progress_bar.set_text(text)
-        # self.progress_bar.set_fraction(percentage)
-        self.ui.progress_bar.set_text(text)
-        self.ui.progress_bar.set_fraction(percentage)
-        return False
-
-    def load_defaults(self):
-        """
-        Loads the aplication's default settings from defaults.json into
-        ``self.defaults``.
-
-        :return: None
-        """
-        try:
-            f = open("defaults.json")
-            options = f.read()
-            f.close()
-        except IOError:
-            App.log.error("Could not load defaults file.")
-            self.info("ERROR: Could not load defaults file.")
-            return
-
-        try:
-            defaults = json.loads(options)
-        except:
-            e = sys.exc_info()[0]
-            App.log.error(str(e))
-            self.info("ERROR: Failed to parse defaults file.")
-            return
-        self.defaults.update(defaults)
-
-    def defaults_read_form(self):
-        for option in self.defaults_form_fields:
-            self.defaults[option] = self.defaults_form_fields[option].get_value()
-
-    def options_read_form(self):
-        for option in self.options_form_fields:
-            self.options[option] = self.options_form_fields[option].get_value()
-
-    def defaults_write_form(self):
-        for option in self.defaults_form_fields:
-            self.defaults_form_fields[option].set_value(self.defaults[option])
-
-    def options_write_form(self):
-        for option in self.options_form_fields:
-            self.options_form_fields[option].set_value(self.options[option])
-
-    def save_project(self, filename):
-        """
-        Saves the current project to the specified file.
-
-        :param filename: Name of the file in which to save.
-        :type filename: str
-        :return: None
-        """
-
-        # Capture the latest changes
-        try:
-            self.collection.get_active().read_form()
-        except:
-            pass
-
-        # Serialize the whole project
-        d = {"objs": [obj.to_dict() for obj in self.collection.get_list()],
-             "options": self.options}
-
-        try:
-            f = open(filename, 'w')
-        except IOError:
-            App.log.error("ERROR: Failed to open file for saving:", filename)
-            return
-
-        try:
-            json.dump(d, f, default=to_dict)
-        except:
-            App.log.error("ERROR: File open but failed to write:", filename)
-            f.close()
-            return
-
-        f.close()
-
-    def open_project(self, filename):
-        """
-        Loads a project from the specified file.
-
-        :param filename:  Name of the file from which to load.
-        :type filename: str
-        :return: None
-        """
-        App.log.debug("Opening project: " + filename)
-
-        try:
-            f = open(filename, 'r')
-        except IOError:
-            App.log.error("Failed to open project file: %s" % filename)
-            self.info("ERROR: Failed to open project file: %s" % filename)
-            return
-
-        try:
-            d = json.load(f, object_hook=dict2obj)
-        except:
-            App.log.error("Failed to parse project file: %s" % filename)
-            self.info("ERROR: Failed to parse project file: %s" % filename)
-            f.close()
-            return
-
-        self.register_recent("project", filename)
-
-        # Clear the current project
-        self.on_file_new(None)
-
-        # Project options
-        self.options.update(d['options'])
-        self.project_filename = filename
-        GLib.idle_add(lambda: self.units_label.set_text(self.options["units"]))
-
-        # Re create objects
-        App.log.debug("Re-creating objects...")
-        for obj in d['objs']:
-            def obj_init(obj_inst, app_inst):
-                obj_inst.from_dict(obj)
-            App.log.debug(obj['kind'] + ":  " + obj['options']['name'])
-            self.new_object(obj['kind'], obj['options']['name'], obj_init, active=False, fit=False, plot=False)
-
-        self.plot_all()
-        self.info("Project loaded from: " + filename)
-        App.log.debug("Project loaded")
-
-    def populate_objects_combo(self, combo):
-        """
-        Populates a Gtk.Comboboxtext with the list of the object in the project.
-
-        :param combo: Name or instance of the comboboxtext.
-        :type combo: str or Gtk.ComboBoxText
-        :return: None
-        """
-        App.log.debug("Populating combo!")
-        if type(combo) == str:
-            combo = self.builder.get_object(combo)
-
-        combo.remove_all()
-        for name in self.collection.get_names():
-            combo.append_text(name)
-
-    def version_check(self, *args):
-        """
-        Checks for the latest version of the program. Alerts the
-        user if theirs is outdated. This method is meant to be run
-        in a saeparate thread.
-
-        :return: None
-        """
-
-        try:
-            f = urllib.urlopen(App.version_url)
-        except:
-            App.log.warning("Failed checking for latest version. Could not connect.")
-            GLib.idle_add(lambda: self.info("ERROR trying to check for latest version."))
-            return
-
-        try:
-            data = json.load(f)
-        except:
-            App.log.error("Could nor parse information about latest version.")
-            GLib.idle_add(lambda: self.info("ERROR trying to check for latest version."))
-            f.close()
-            return
-
-        f.close()
-
-        if self.version >= data["version"]:
-            GLib.idle_add(lambda: self.info("FlatCAM is up to date!"))
-            return
-
-        label = Gtk.Label("There is a newer version of FlatCAM\n" +
-                          "available for download:\n\n" +
-                          data["name"] + "\n\n" + data["message"])
-        dialog = Gtk.Dialog("Newer Version Available", self.window, 0,
-                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                             Gtk.STOCK_OK, Gtk.ResponseType.OK))
-        dialog.set_default_size(150, 100)
-        dialog.set_modal(True)
-        box = dialog.get_content_area()
-        box.set_border_width(10)
-        box.add(label)
-
-        def do_dialog():
-            dialog.show_all()
-            response = dialog.run()
-            dialog.destroy()
-
-        GLib.idle_add(lambda: do_dialog())
-
-        return
-
-    def do_nothing(self, param):
-        return
-
-    def disable_plots(self, except_current=False):
-        """
-        Disables all plots with exception of the current object if specified.
-
-        :param except_current: Wether to skip the current object.
-        :rtype except_current: boolean
-        :return: None
-        """
-        # TODO: This method is very similar to replot_all. Try to merge.
-
-        self.set_progress_bar(0.1, "Re-plotting...")
-
-        def worker_task(app_obj):
-            percentage = 0.1
-            try:
-                delta = 0.9 / len(self.collection.get_list())
-            except ZeroDivisionError:
-                GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, ""))
-                return
-            for obj in self.collection.get_list():
-                if obj != self.collection.get_active() or not except_current:
-                    obj.options['plot'] = False
-                    obj.plot()
-                percentage += delta
-                GLib.idle_add(lambda: app_obj.set_progress_bar(percentage, "Re-plotting..."))
-
-            GLib.idle_add(app_obj.plotcanvas.auto_adjust_axes)
-            GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, ""))
-
-        # Send to worker
-        self.worker.add_task(worker_task, [self])
-
-    def enable_all_plots(self, *args):
-        self.plotcanvas.clear()
-        self.set_progress_bar(0.1, "Re-plotting...")
-
-        def worker_task(app_obj):
-            percentage = 0.1
-            try:
-                delta = 0.9 / len(self.collection.get_list())
-            except ZeroDivisionError:
-                GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, ""))
-                return
-            for obj in self.collection.get_list():
-                obj.options['plot'] = True
-                obj.plot()
-                percentage += delta
-                GLib.idle_add(lambda: app_obj.set_progress_bar(percentage, "Re-plotting..."))
-
-            GLib.idle_add(app_obj.plotcanvas.auto_adjust_axes)
-            GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, ""))
-
-        # Send to worker
-        self.worker.add_task(worker_task, [self])
-
-    def register_recent(self, kind, filename):
-        record = {'kind': kind, 'filename': filename}
-
-        if record in self.recent:
-            return
-
-        self.recent.insert(0, record)
-
-        if len(self.recent) > 10:  # Limit reached
-            self.recent.pop()
-
-        try:
-            f = open('recent.json', 'w')
-        except IOError:
-            App.log.error("Failed to open recent items file for writing.")
-            self.info('Failed to open recent files file for writing.')
-            return
-
-        try:
-            json.dump(self.recent, f)
-        except:
-            App.log.error("Failed to write to recent items file.")
-            self.info('ERROR: Failed to write to recent items file.')
-            f.close()
-
-        f.close()
-
-    def open_gerber(self, filename):
-        """
-        Opens a Gerber file, parses it and creates a new object for
-        it in the program. Thread-safe.
-
-        :param filename: Gerber file filename
-        :type filename: str
-        :return: None
-        """
-
-        # Fails here
-        # t = Gtk.TextView()
-        # print t
-
-        GLib.idle_add(lambda: self.set_progress_bar(0.1, "Opening Gerber ..."))
-
-        # How the object should be initialized
-        def obj_init(gerber_obj, app_obj):
-            assert isinstance(gerber_obj, FlatCAMGerber)
-
-            # Opening the file happens here
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.2, "Parsing ..."))
-            gerber_obj.parse_file(filename)
-
-            # Further parsing
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.5, "Creating Geometry ..."))
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.6, "Plotting ..."))
-
-        # Object name
-        name = filename.split('/')[-1].split('\\')[-1]
-
-        self.new_object("gerber", name, obj_init)
-
-        # New object creation and file processing
-        # try:
-        #     self.new_object("gerber", name, obj_init)
-        # except:
-        #     e = sys.exc_info()
-        #     print "ERROR:", e[0]
-        #     traceback.print_exc()
-        #     self.message_dialog("Failed to create Gerber Object",
-        #                         "Attempting to create a FlatCAM Gerber Object from " +
-        #                         "Gerber file failed during processing:\n" +
-        #                         str(e[0]) + " " + str(e[1]), kind="error")
-        #     GLib.timeout_add_seconds(1, lambda: self.set_progress_bar(0.0, "Idle"))
-        #     self.collection.delete_active()
-        #     return
-
-        # Register recent file
-        self.register_recent("gerber", filename)
-
-        # GUI feedback
-        self.info("Opened: " + filename)
-        GLib.idle_add(lambda: self.set_progress_bar(1.0, "Done!"))
-        GLib.timeout_add_seconds(1, lambda: self.set_progress_bar(0.0, "Idle"))
-
-    def open_excellon(self, filename):
-        """
-        Opens an Excellon file, parses it and creates a new object for
-        it in the program. Thread-safe.
-
-        :param filename: Excellon file filename
-        :type filename: str
-        :return: None
-        """
-        GLib.idle_add(lambda: self.set_progress_bar(0.1, "Opening Excellon ..."))
-
-        # How the object should be initialized
-        def obj_init(excellon_obj, app_obj):
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.2, "Parsing ..."))
-            excellon_obj.parse_file(filename)
-            excellon_obj.create_geometry()
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.6, "Plotting ..."))
-
-        # Object name
-        name = filename.split('/')[-1].split('\\')[-1]
-
-        # New object creation and file processing
-        try:
-            self.new_object("excellon", name, obj_init)
-        except:
-            e = sys.exc_info()
-            App.log.error(str(e))
-            self.message_dialog("Failed to create Excellon Object",
-                                "Attempting to create a FlatCAM Excellon Object from " +
-                                "Excellon file failed during processing:\n" +
-                                str(e[0]) + " " + str(e[1]), kind="error")
-            GLib.timeout_add_seconds(1, lambda: self.set_progress_bar(0.0, "Idle"))
-            self.collection.delete_active()
-            return
-
-        # Register recent file
-        self.register_recent("excellon", filename)
-
-        # GUI feedback
-        self.info("Opened: " + filename)
-        GLib.idle_add(lambda: self.set_progress_bar(1.0, "Done!"))
-        GLib.timeout_add_seconds(1, lambda: self.set_progress_bar(0.0, ""))
-
-    def open_gcode(self, filename):
-        """
-        Opens a G-gcode file, parses it and creates a new object for
-        it in the program. Thread-safe.
-
-        :param filename: G-code file filename
-        :type filename: str
-        :return: None
-        """
-
-        # How the object should be initialized
-        def obj_init(job_obj, app_obj_):
-            """
-
-            :type app_obj_: App
-            """
-            assert isinstance(app_obj_, App)
-            GLib.idle_add(lambda: app_obj_.set_progress_bar(0.1, "Opening G-Code ..."))
-
-            f = open(filename)
-            gcode = f.read()
-            f.close()
-
-            job_obj.gcode = gcode
-
-            GLib.idle_add(lambda: app_obj_.set_progress_bar(0.2, "Parsing ..."))
-            job_obj.gcode_parse()
-
-            GLib.idle_add(lambda: app_obj_.set_progress_bar(0.6, "Creating geometry ..."))
-            job_obj.create_geometry()
-
-            GLib.idle_add(lambda: app_obj_.set_progress_bar(0.6, "Plotting ..."))
-
-        # Object name
-        name = filename.split('/')[-1].split('\\')[-1]
-
-        # New object creation and file processing
-        try:
-            self.new_object("cncjob", name, obj_init)
-        except:
-            e = sys.exc_info()
-            App.log.error(str(e))
-            self.message_dialog("Failed to create CNCJob Object",
-                                "Attempting to create a FlatCAM CNCJob Object from " +
-                                "G-Code file failed during processing:\n" +
-                                str(e[0]) + " " + str(e[1]), kind="error")
-            GLib.timeout_add_seconds(1, lambda: self.set_progress_bar(0.0, "Idle"))
-            self.collection.delete_active()
-            return
-
-        # Register recent file
-        self.register_recent("cncjob", filename)
-
-        # GUI feedback
-        self.info("Opened: " + filename)
-        GLib.idle_add(lambda: self.set_progress_bar(1.0, "Done!"))
-        GLib.timeout_add_seconds(1, lambda: self.set_progress_bar(0.0, ""))
-
-    ########################################
-    ##         EVENT HANDLERS             ##
-    ########################################
-    def on_debug_printlist(self, *args):
-        self.collection.print_list()
-
-    def on_disable_all_plots(self, widget):
-        self.disable_plots()
-
-    def on_disable_all_plots_not_current(self, widget):
-        self.disable_plots(except_current=True)
-
-    def on_about(self, widget):
-        """
-        Opens the 'About' dialog box.
-
-        :param widget: Ignored.
-        :return: None
-        """
-
-        about = self.builder.get_object("aboutdialog")
-        about.run()
-        about.hide()
-
-    def on_create_mirror(self, widget):
-        """
-        Creates a mirror image of an object to be used as a bottom layer.
-
-        :param widget: Ignored.
-        :return: None
-        """
-        # TODO: Move (some of) this to camlib!
-
-        # Object to mirror
-        obj_name = self.builder.get_object("comboboxtext_bottomlayer").get_active_text()
-        fcobj = self.collection.get_by_name(obj_name)
-
-        # For now, lets limit to Gerbers and Excellons.
-        # assert isinstance(gerb, FlatCAMGerber)
-        if not isinstance(fcobj, FlatCAMGerber) and not isinstance(fcobj, FlatCAMExcellon):
-            self.info("ERROR: Only Gerber and Excellon objects can be mirrored.")
-            return
-
-        # Mirror axis "X" or "Y
-        axis = self.get_radio_value({"rb_mirror_x": "X",
-                                     "rb_mirror_y": "Y"})
-        mode = self.get_radio_value({"rb_mirror_box": "box",
-                                     "rb_mirror_point": "point"})
-        if mode == "point":  # A single point defines the mirror axis
-            # TODO: Error handling
-            px, py = eval(self.point_entry.get_text())
-        else:  # The axis is the line dividing the box in the middle
-            name = self.box_combo.get_active_text()
-            bb_obj = self.collection.get_by_name(name)
-            xmin, ymin, xmax, ymax = bb_obj.bounds()
-            px = 0.5*(xmin+xmax)
-            py = 0.5*(ymin+ymax)
-
-        fcobj.mirror(axis, [px, py])
-        fcobj.plot()
-
-    def on_create_aligndrill(self, widget):
-        """
-        Creates alignment holes Excellon object. Creates mirror duplicates
-        of the specified holes around the specified axis.
-
-        :param widget: Ignored.
-        :return: None
-        """
-
-        # Mirror axis. Same as in on_create_mirror.
-        axis = self.get_radio_value({"rb_mirror_x": "X",
-                                     "rb_mirror_y": "Y"})
-        # TODO: Error handling
-        mode = self.get_radio_value({"rb_mirror_box": "box",
-                                     "rb_mirror_point": "point"})
-        if mode == "point":
-            px, py = eval(self.point_entry.get_text())
-        else:
-            name = self.box_combo.get_active_text()
-            bb_obj = self.collection.get_by_name(name)
-            xmin, ymin, xmax, ymax = bb_obj.bounds()
-            px = 0.5*(xmin+xmax)
-            py = 0.5*(ymin+ymax)
-        xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis]
-
-        # Tools
-        dia = self.get_eval("entry_dblsided_alignholediam")
-        tools = {"1": {"C": dia}}
-
-        # Parse hole list
-        # TODO: Better parsing
-        holes = self.builder.get_object("entry_dblsided_alignholes").get_text()
-        holes = eval("[" + holes + "]")
-        drills = []
-        for hole in holes:
-            point = Point(hole)
-            point_mirror = affinity.scale(point, xscale, yscale, origin=(px, py))
-            drills.append({"point": point, "tool": "1"})
-            drills.append({"point": point_mirror, "tool": "1"})
-
-        def obj_init(obj_inst, app_inst):
-            obj_inst.tools = tools
-            obj_inst.drills = drills
-            obj_inst.create_geometry()
-
-        self.new_object("excellon", "Alignment Drills", obj_init)
-
-    def on_toggle_pointbox(self, widget):
-        """
-        Callback for radio selection change between point and box in the
-        Double-sided PCB tool. Updates the UI accordingly.
-
-        :param widget: Ignored.
-        :return: None
-        """
-
-        # Where the entry or combo go
-        box = self.builder.get_object("box_pointbox")
-
-        # Clear contents
-        children = box.get_children()
-        for child in children:
-            box.remove(child)
-
-        choice = self.get_radio_value({"rb_mirror_point": "point",
-                                       "rb_mirror_box": "box"})
-
-        if choice == "point":
-            self.point_entry = Gtk.Entry()
-            self.builder.get_object("box_pointbox").pack_start(self.point_entry,
-                                                               False, False, 1)
-            self.point_entry.show()
-        else:
-            self.box_combo = Gtk.ComboBoxText()
-            self.builder.get_object("box_pointbox").pack_start(self.box_combo,
-                                                               False, False, 1)
-            self.populate_objects_combo(self.box_combo)
-            self.box_combo.show()
-
-    def on_tools_doublesided(self, param):
-        """
-        Callback for menu item Tools->Double Sided PCB Tool. Launches the
-        tool placing its UI in the "Tool" tab in the notebook.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        # Were are we drawing the UI
-        box_tool = self.builder.get_object("box_tool")
-
-        # Remove anything else in the box
-        box_children = box_tool.get_children()
-        for child in box_children:
-            box_tool.remove(child)
-
-        # Get the UI
-        osw = self.builder.get_object("offscreenwindow_dblsided")
-        sw = self.builder.get_object("sw_dblsided")
-        osw.remove(sw)
-        vp = self.builder.get_object("vp_dblsided")
-        vp.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(1, 1, 1, 1))
-
-        # Put in the UI
-        box_tool.pack_start(sw, True, True, 0)
-
-        # INITIALIZATION
-        # Populate combo box
-        self.populate_objects_combo("comboboxtext_bottomlayer")
-
-        # Point entry
-        self.point_entry = Gtk.Entry()
-        box = self.builder.get_object("box_pointbox")
-        for child in box.get_children():
-            box.remove(child)
-        box.pack_start(self.point_entry, False, False, 1)
-
-        # Show the "Tool" tab
-        # self.notebook.set_current_page(3)
-        self.ui.notebook.set_current_page(3)
-        sw.show_all()
-
-    def on_toggle_units(self, widget):
-        """
-        Callback for the Units radio-button change in the Options tab.
-        Changes the application's default units or the current project's units.
-        If changing the project's units, the change propagates to all of
-        the objects in the project.
-
-        :param widget: Ignored.
-        :return: None
-        """
-
-        if self.toggle_units_ignore:
-            return
-
-        # Options to scale
-        dimensions = ['gerber_isotooldia', 'gerber_cutoutmargin', 'gerber_cutoutgapsize',
-                      'gerber_noncoppermargin', 'gerber_bboxmargin', 'excellon_drillz',
-                      'excellon_travelz', 'excellon_feedrate', 'cncjob_tooldia',
-                      'geometry_cutz', 'geometry_travelz', 'geometry_feedrate',
-                      'geometry_cnctooldia', 'geometry_painttooldia', 'geometry_paintoverlap',
-                      'geometry_paintmargin']
-
-        def scale_options(sfactor):
-            for dim in dimensions:
-                self.options[dim] *= sfactor
-
-        # The scaling factor depending on choice of units.
-        factor = 1/25.4
-        if self.options_form.units_radio.get_value().upper() == 'MM':
-            factor = 25.4
-
-        # Changing project units. Warn user.
-        label = Gtk.Label("Changing the units of the project causes all geometrical \n" +
-                          "properties of all objects to be scaled accordingly. Continue?")
-        dialog = Gtk.Dialog("Changing Project Units", self.window, 0,
-                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                             Gtk.STOCK_OK, Gtk.ResponseType.OK))
-        dialog.set_default_size(150, 100)
-        dialog.set_modal(True)
-        box = dialog.get_content_area()
-        box.set_border_width(10)
-        box.add(label)
-        dialog.show_all()
-        response = dialog.run()
-        dialog.destroy()
-
-        if response == Gtk.ResponseType.OK:
-            self.options_read_form()
-            scale_options(factor)
-            self.options_write_form()
-            for obj in self.collection.get_list():
-                units = self.options_form.units_radio.get_value().upper()
-                obj.convert_units(units)
-            current = self.collection.get_active()
-            if current is not None:
-                current.to_form()
-            self.plot_all()
-        else:
-            # Undo toggling
-            self.toggle_units_ignore = True
-            if self.options_form.units_radio.get_value().upper() == 'MM':
-                self.options_form.units_radio.set_value('IN')
-            else:
-                self.options_form.units_radio.set_value('MM')
-            self.toggle_units_ignore = False
-
-        self.options_read_form()
-        self.info("Converted units to %s" % self.options["units"])
-        self.units_label.set_text("[" + self.options["units"] + "]")
-
-    def on_file_openproject(self, param):
-        """
-        Callback for menu item File->Open Project. Opens a file chooser and calls
-        ``self.open_project()`` after successful selection of a filename.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        def on_success(app_obj, filename):
-            app_obj.open_project(filename)
-
-        # Runs on_success on worker
-        self.file_chooser_action(on_success)
-
-    def on_file_saveproject(self, param):
-        """
-        Callback for menu item File->Save Project. Saves the project to
-        ``self.project_filename`` or calls ``self.on_file_saveprojectas()``
-        if set to None. The project is saved by calling ``self.save_project()``.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        if self.project_filename is None:
-            self.on_file_saveprojectas(None)
-        else:
-            self.save_project(self.project_filename)
-            self.register_recent("project", self.project_filename)
-            self.info("Project saved to: " + self.project_filename)
-
-    def on_file_saveprojectas(self, param):
-        """
-        Callback for menu item File->Save Project As... Opens a file
-        chooser and saves the project to the given file via
-        ``self.save_project()``.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        def on_success(app_obj, filename):
-            assert isinstance(app_obj, App)
-
-            try:
-                f = open(filename, 'r')
-                f.close()
-                exists = True
-            except IOError:
-                exists = False
-
-            msg = "File exists. Overwrite?"
-            if exists and self.question_dialog("File exists", msg) == Gtk.ResponseType.CANCEL:
-                return
-
-            app_obj.save_project(filename)
-            self.project_filename = filename
-            self.register_recent("project", filename)
-            app_obj.info("Project saved to: " + filename)
-
-        self.file_chooser_save_action(on_success)
-
-    def on_file_saveprojectcopy(self, param):
-        """
-        Callback for menu item File->Save Project Copy... Opens a file
-        chooser and saves the project to the given file via
-        ``self.save_project``. It does not update ``self.project_filename`` so
-        subsequent save requests are done on the previous known filename.
-
-        :param param: Ignore.
-        :return: None
-        """
-
-        def on_success(app_obj, filename):
-            assert isinstance(app_obj, App)
-
-            try:
-                f = open(filename, 'r')
-                f.close()
-                exists = True
-            except IOError:
-                exists = False
-
-            msg = "File exists. Overwrite?"
-            if exists and self.question_dialog("File exists", msg) == Gtk.ResponseType.CANCEL:
-                return
-
-            app_obj.save_project(filename)
-            self.register_recent("project", filename)
-            app_obj.info("Project copy saved to: " + filename)
-
-        self.file_chooser_save_action(on_success)
-
-    def on_options_app2project(self, param):
-        """
-        Callback for Options->Transfer Options->App=>Project. Copies options
-        from application defaults to project defaults.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        self.defaults_read_form()
-        self.options.update(self.defaults)
-        self.options_write_form()
-
-    def on_options_project2app(self, param):
-        """
-        Callback for Options->Transfer Options->Project=>App. Copies options
-        from project defaults to application defaults.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        self.options_read_form()
-        self.defaults.update(self.options)
-        self.defaults_write_form()
-
-    def on_options_project2object(self, param):
-        """
-        Callback for Options->Transfer Options->Project=>Object. Copies options
-        from project defaults to the currently selected object.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        self.options_read_form()
-        obj = self.collection.get_active()
-        if obj is None:
-            self.info("WARNING: No object selected.")
-            return
-        for option in self.options:
-            if option.find(obj.kind + "_") == 0:
-                oname = option[len(obj.kind)+1:]
-                obj.options[oname] = self.options[option]
-        obj.to_form()  # Update UI
-
-    def on_options_object2project(self, param):
-        """
-        Callback for Options->Transfer Options->Object=>Project. Copies options
-        from the currently selected object to project defaults.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        obj = self.collection.get_active()
-        if obj is None:
-            self.info("WARNING: No object selected.")
-            return
-        obj.read_form()
-        for option in obj.options:
-            if option in ['name']:  # TODO: Handle this better...
-                continue
-            self.options[obj.kind + "_" + option] = obj.options[option]
-        self.options_write_form()
-
-    def on_options_object2app(self, param):
-        """
-        Callback for Options->Transfer Options->Object=>App. Copies options
-        from the currently selected object to application defaults.
-
-        :param param: Ignored.
-        :return: None
-        """
-        obj = self.collection.get_active()
-        if obj is None:
-            self.info("WARNING: No object selected.")
-            return
-        obj.read_form()
-        for option in obj.options:
-            if option in ['name']:  # TODO: Handle this better...
-                continue
-            self.defaults[obj.kind + "_" + option] = obj.options[option]
-        self.defaults_write_form()
-
-    def on_options_app2object(self, param):
-        """
-        Callback for Options->Transfer Options->App=>Object. Copies options
-        from application defaults to the currently selected object.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        self.defaults_read_form()
-        obj = self.collection.get_active()
-        if obj is None:
-            self.info("WARNING: No object selected.")
-            return
-        for option in self.defaults:
-            if option.find(obj.kind + "_") == 0:
-                oname = option[len(obj.kind)+1:]
-                obj.options[oname] = self.defaults[option]
-        obj.to_form()  # Update UI
-
-    def on_file_savedefaults(self, param):
-        """
-        Callback for menu item File->Save Defaults. Saves application default options
-        ``self.defaults`` to defaults.json.
-
-        :param param: Ignored.
-        :return: None
-        """
-
-        # Read options from file
-        try:
-            f = open("defaults.json")
-            options = f.read()
-            f.close()
-        except:
-            App.log.error("Could not load defaults file.")
-            self.info("ERROR: Could not load defaults file.")
-            return
-
-        try:
-            defaults = json.loads(options)
-        except:
-            e = sys.exc_info()[0]
-            App.log.error("Failed to parse defaults file.")
-            App.log.error(str(e))
-            self.info("ERROR: Failed to parse defaults file.")
-            return
-
-        # Update options
-        self.defaults_read_form()
-        defaults.update(self.defaults)
-
-        # Save update options
-        try:
-            f = open("defaults.json", "w")
-            json.dump(defaults, f)
-            f.close()
-        except:
-            self.info("ERROR: Failed to write defaults to file.")
-            return
-
-        self.info("Defaults saved.")
-
-    def on_options_combo_change(self, widget):
-        """
-        Called when the combo box to choose between application defaults and
-        project option changes value. The corresponding variables are
-        copied to the UI.
-
-        :param widget: The widget from which this was called. Ignore.
-        :return: None
-        """
-
-        combo_sel = self.ui.notebook.combo_options.get_active()
-        App.log.debug("Options --> %s" % combo_sel)
-
-        # Remove anything else in the box
-        # box_children = self.options_box.get_children()
-        box_children = self.ui.notebook.options_contents.get_children()
-        for child in box_children:
-            self.ui.notebook.options_contents.remove(child)
-
-        form = [self.options_form, self.defaults_form][combo_sel]
-        self.ui.notebook.options_contents.pack_start(form, False, False, 1)
-        form.show_all()
-
-        # self.options2form()
-
-    def on_canvas_configure(self, widget, event):
-        """
-        Called whenever the canvas changes size. The axes are updated such
-        as to use the whole canvas.
-
-        :param widget: Ignored.
-        :param event: Ignored.
-        :return: None
-        """
-
-        self.plotcanvas.auto_adjust_axes()
-
-    def on_row_activated(self, widget, path, col):
-        """
-        Callback for selection activation (Enter or double-click) on the Project list.
-        Switches the notebook page to the object properties form. Calls
-        ``self.notebook.set_current_page(1)``.
-
-        :param widget: Ignored.
-        :param path: Ignored.
-        :param col: Ignored.
-        :return: None
-        """
-        # self.notebook.set_current_page(1)
-        self.ui.notebook.set_current_page(1)
-
-    def on_update_plot(self, widget):
-        """
-        Callback for button on form for all kinds of objects.
-        Re-plots the current object only.
-
-        :param widget: The widget from which this was called. Ignored.
-        :return: None
-        """
-
-        obj = self.collection.get_active()
-        obj.read_form()
-
-        self.set_progress_bar(0.5, "Plotting...")
-
-        def thread_func(app_obj):
-            assert isinstance(app_obj, App)
-            obj.plot()
-            GLib.timeout_add(300, lambda: app_obj.set_progress_bar(0.0, "Idle"))
-
-        # Send to worker
-        self.worker.add_task(thread_func, [self])
-
-    def on_excellon_tool_choose(self, widget):
-        """
-        Callback for button on Excellon form to open up a window for
-        selecting tools.
-
-        :param widget: The widget from which this was called.
-        :return: None
-        """
-        excellon = self.collection.get_active()
-        assert isinstance(excellon, FlatCAMExcellon)
-        excellon.show_tool_chooser()
-
-    def on_entry_eval_activate(self, widget):
-        """
-        Called when an entry is activated (eg. by hitting enter) if
-        set to do so. Its text is eval()'d and set to the returned value.
-        The current object is updated.
-
-        :param widget:
-        :return:
-        """
-        self.on_eval_update(widget)
-        obj = self.collection.get_active()
-        assert isinstance(obj, FlatCAMObj)
-        obj.read_form()
-
-    def on_eval_update(self, widget):
-        """
-        Modifies the content of a Gtk.Entry by running
-        eval() on its contents and puting it back as a
-        string.
-
-        :param widget: The widget from which this was called.
-        :return: None
-        """
-        # TODO: error handling here
-        widget.set_text(str(eval(widget.get_text())))
-
-    # def on_cncjob_exportgcode(self, widget):
-    #     """
-    #     Called from button on CNCjob form to save the G-Code from the object.
-    #
-    #     :param widget: The widget from which this was called.
-    #     :return: None
-    #     """
-    #     def on_success(app_obj, filename):
-    #         cncjob = app_obj.collection.get_active()
-    #         f = open(filename, 'w')
-    #         f.write(cncjob.gcode)
-    #         f.close()
-    #         app_obj.info("Saved to: " + filename)
-    #
-    #     self.file_chooser_save_action(on_success)
-
-    def on_delete(self, widget):
-        """
-        Delete the currently selected FlatCAMObj.
-
-        :param widget: The widget from which this was called. Ignored.
-        :return: None
-        """
-
-        # Keep this for later
-        name = copy(self.collection.get_active().options["name"])
-
-        # Remove plot
-        self.plotcanvas.figure.delaxes(self.collection.get_active().axes)
-        self.plotcanvas.auto_adjust_axes()
-
-        # Clear form
-        self.setup_component_editor()
-
-        # Remove from dictionary
-        self.collection.delete_active()
-
-        self.info("Object deleted: %s" % name)
-
-    def on_toolbar_replot(self, widget):
-        """
-        Callback for toolbar button. Re-plots all objects.
-
-        :param widget: The widget from which this was called.
-        :return: None
-        """
-
-        try:
-            self.collection.get_active().read_form()
-        except AttributeError:
-            pass
-
-        self.plot_all()
-
-    def on_clear_plots(self, widget):
-        """
-        Callback for toolbar button. Clears all plots.
-
-        :param widget: The widget from which this was called.
-        :return: None
-        """
-        self.plotcanvas.clear()
-
-    def on_file_new(self, *param):
-        """
-        Callback for menu item File->New. Returns the application to its
-        startup state. This method is thread-safe.
-
-        :param param: Whatever is passed by the event. Ignore.
-        :return: None
-        """
-        # Remove everything from memory
-        App.log.debug("on_file_bew()")
-
-        # GUI things
-        def task():
-            # Clear plot
-            App.log.debug("   self.plotcanvas.clear()")
-            self.plotcanvas.clear()
-
-            # Delete data
-            App.log.debug("   self.collection.delete_all()")
-            self.collection.delete_all()
-
-            # Clear object editor
-            App.log.debug("   self.setup_component_editor()")
-            self.setup_component_editor()
-
-        GLib.idle_add(task)
-
-        # Clear project filename
-        self.project_filename = None
-
-        # Re-fresh project options
-        self.on_options_app2project(None)
-
-    def on_filequit(self, param):
-        """
-        Callback for menu item File->Quit. Closes the application.
-
-        :param param: Whatever is passed by the event. Ignore.
-        :return: None
-        """
-
-        self.window.destroy()
-        Gtk.main_quit()
-
-    def on_closewindow(self, param):
-        """
-        Callback for closing the main window.
-
-        :param param: Whatever is passed by the event. Ignore.
-        :return: None
-        """
-
-        self.window.destroy()
-        Gtk.main_quit()
-
-    def file_chooser_action(self, on_success):
-        """
-        Opens the file chooser and runs on_success on a separate thread
-        upon completion of valid file choice.
-
-        :param on_success: A function to run upon completion of a valid file
-            selection. Takes 2 parameters: The app instance and the filename.
-            Note that it is run on a separate thread, therefore it must take the
-            appropriate precautions  when accessing shared resources.
-        :type on_success: func
-        :return: None
-        """
-        dialog = Gtk.FileChooserDialog("Please choose a file", self.ui,
-                                       Gtk.FileChooserAction.OPEN,
-                                       (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                                        Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
-        response = dialog.run()
-
-        # Works here
-        # t = Gtk.TextView()
-        # print t
-
-        if response == Gtk.ResponseType.OK:
-            filename = dialog.get_filename()
-            dialog.destroy()
-            # Send to worker.
-            self.worker.add_task(on_success, [self, filename])
-        elif response == Gtk.ResponseType.CANCEL:
-            self.info("Open cancelled.")
-            dialog.destroy()
-
-        # Works here
-        # t = Gtk.TextView()
-        # print t
-
-    def file_chooser_save_action(self, on_success):
-        """
-        Opens the file chooser and runs on_success upon completion of valid file choice.
-
-        :param on_success: A function to run upon selection of a filename. Takes 2
-            parameters: The instance of the application (App) and the chosen filename. This
-            gets run immediately in the same thread.
-        :return: None
-        """
-        dialog = Gtk.FileChooserDialog("Save file", self.window,
-                                       Gtk.FileChooserAction.SAVE,
-                                       (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                                        Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
-        dialog.set_current_name("Untitled")
-        response = dialog.run()
-        if response == Gtk.ResponseType.OK:
-            filename = dialog.get_filename()
-            dialog.destroy()
-            on_success(self, filename)
-        elif response == Gtk.ResponseType.CANCEL:
-            self.info("Save cancelled.")  # print("Cancel clicked")
-            dialog.destroy()
-
-    def on_fileopengerber(self, param):
-        """
-        Callback for menu item File->Open Gerber. Defines a function that is then passed
-        to ``self.file_chooser_action()``. It requests the creation of a FlatCAMGerber object
-        and updates the progress bar throughout the process.
-
-        :param param: Ignore
-        :return: None
-        """
-
-        # This works here.
-        # t = Gtk.TextView()
-        # print t
-
-        self.file_chooser_action(lambda ao, filename: self.open_gerber(filename))
-
-    def on_fileopenexcellon(self, param):
-        """
-        Callback for menu item File->Open Excellon. Defines a function that is then passed
-        to ``self.file_chooser_action()``. It requests the creation of a FlatCAMExcellon object
-        and updates the progress bar throughout the process.
-
-        :param param: Ignore
-        :return: None
-        """
-
-        self.file_chooser_action(lambda ao, filename: self.open_excellon(filename))
-
-    def on_fileopengcode(self, param):
-        """
-        Callback for menu item File->Open G-Code. Defines a function that is then passed
-        to ``self.file_chooser_action()``. It requests the creation of a FlatCAMCNCjob object
-        and updates the progress bar throughout the process.
-
-        :param param: Ignore
-        :return: None
-        """
-
-        self.file_chooser_action(lambda ao, filename: self.open_gcode(filename))
-
-    def on_mouse_move_over_plot(self, event):
-        """
-        Callback for the mouse motion event over the plot. This event is generated
-        by the Matplotlib backend and has been registered in ``self.__init__()``.
-        For details, see: http://matplotlib.org/users/event_handling.html
-
-        :param event: Contains information about the event.
-        :return: None
-        """
-
-        try:  # May fail in case mouse not within axes
-            self.ui.position_label.set_label("X: %.4f   Y: %.4f" % (
-                event.xdata, event.ydata))
-            self.mouse = [event.xdata, event.ydata]
-
-            # for subscriber in self.plot_mousemove_subscribers:
-            #     self.plot_mousemove_subscribers[subscriber](event)
-
-        except:
-            self.ui.position_label.set_label("")
-            self.mouse = None
-
-    def on_click_over_plot(self, event):
-        """
-        Callback for the mouse click event over the plot. This event is generated
-        by the Matplotlib backend and has been registered in ``self.__init__()``.
-        For details, see: http://matplotlib.org/users/event_handling.html
-
-        Default actions are:
-
-        * Copy coordinates to clipboard. Ex.: (65.5473, -13.2679)
-
-        :param event: Contains information about the event, like which button
-            was clicked, the pixel coordinates and the axes coordinates.
-        :return: None
-        """
-
-        # So it can receive key presses
-        self.plotcanvas.canvas.grab_focus()
-
-        try:
-            App.log.debug('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' % (
-                event.button, event.x, event.y, event.xdata, event.ydata))
-
-            self.clipboard.set_text("(%.4f, %.4f)" % (event.xdata, event.ydata), -1)
-
-        except Exception, e:
-            App.log.debug("Outside plot?")
-            App.log.debug(str(e))
-
-    def on_zoom_in(self, event):
-        """
-        Callback for zoom-in request. This can be either from the corresponding
-        toolbar button or the '3' key when the canvas is focused. Calls ``self.zoom()``.
-
-        :param event: Ignored.
-        :return: None
-        """
-        self.plotcanvas.zoom(1.5)
-        return
-
-    def on_zoom_out(self, event):
-        """
-        Callback for zoom-out request. This can be either from the corresponding
-        toolbar button or the '2' key when the canvas is focused. Calls ``self.zoom()``.
-
-        :param event: Ignored.
-        :return: None
-        """
-        self.plotcanvas.zoom(1 / 1.5)
-
-    def on_zoom_fit(self, event):
-        """
-        Callback for zoom-out request. This can be either from the corresponding
-        toolbar button or the '1' key when the canvas is focused. Calls ``self.adjust_axes()``
-        with axes limits from the geometry bounds of all objects.
-
-        :param event: Ignored.
-        :return: None
-        """
-        xmin, ymin, xmax, ymax = self.collection.get_bounds()
-        width = xmax - xmin
-        height = ymax - ymin
-        xmin -= 0.05 * width
-        xmax += 0.05 * width
-        ymin -= 0.05 * height
-        ymax += 0.05 * height
-        self.plotcanvas.adjust_axes(xmin, ymin, xmax, ymax)
-
-    def on_key_over_plot(self, event):
-        """
-        Callback for the key pressed event when the canvas is focused. Keyboard
-        shortcuts are handled here. So far, these are the shortcuts:
-
-        ==========  ============================================
-        Key         Action
-        ==========  ============================================
-        '1'         Zoom-fit. Fits the axes limits to the data.
-        '2'         Zoom-out.
-        '3'         Zoom-in.
-        'm'         Toggle on-off the measuring tool.
-        ==========  ============================================
-
-        :param event: Ignored.
-        :return: None
-        """
-
-        if event.key == '1':  # 1
-            self.on_zoom_fit(None)
-            return
-
-        if event.key == '2':  # 2
-            self.plotcanvas.zoom(1 / 1.5, self.mouse)
-            return
-
-        if event.key == '3':  # 3
-            self.plotcanvas.zoom(1.5, self.mouse)
-            return
-
-        if event.key == 'm':
-            if self.measure.toggle_active():
-                self.info("Measuring tool ON")
-            else:
-                self.info("Measuring tool OFF")
-            return
-
-
-class BaseDraw:
-    def __init__(self, plotcanvas, name=None):
-        """
-
-        :param plotcanvas: The PlotCanvas where the drawing tool will operate.
-        :type plotcanvas: PlotCanvas
-        """
-
-        self.plotcanvas = plotcanvas
-
-        # Must have unique axes
-        charset = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"
-        self.name = name or [random.choice(charset) for i in range(20)]
-        self.axes = self.plotcanvas.new_axes(self.name)
-
-
-class DrawingObject(BaseDraw):
-    def __init__(self, plotcanvas, name=None):
-        """
-        Possible objects are:
-
-        * Point
-        * Line
-        * Rectangle
-        * Circle
-        * Polygon
-        """
-
-        BaseDraw.__init__(self, plotcanvas)
-        self.properties = {}
-
-    def plot(self):
-        return
-
-    def update_plot(self):
-        self.axes.cla()
-        self.plot()
-        self.plotcanvas.auto_adjust_axes()
-
-
-class DrawingPoint(DrawingObject):
-    def __init__(self, plotcanvas, name=None, coord=None):
-        DrawingObject.__init__(self, plotcanvas)
-
-        self.properties.update({
-            "coordinate": coord
-        })
-
-    def plot(self):
-        x, y = self.properties["coordinate"]
-        self.axes.plot(x, y, 'o')
-
-
-class Measurement:
-    def __init__(self, container, plotcanvas, update=None):
-        self.update = update
-        self.container = container
-        self.frame = None
-        self.label = None
-        self.point1 = None
-        self.point2 = None
-        self.active = False
-        self.plotcanvas = plotcanvas
-        self.click_subscription = None
-        self.move_subscription = None
-
-    def toggle_active(self, *args):
-        if self.active:  # Deactivate
-            self.active = False
-            self.container.remove(self.frame)
-            if self.update is not None:
-                self.update()
-            self.plotcanvas.mpl_disconnect(self.click_subscription)
-            self.plotcanvas.mpl_disconnect(self.move_subscription)
-            return False
-        else:  # Activate
-            App.log.debug("DEBUG: Activating Measurement Tool...")
-            self.active = True
-            self.click_subscription = self.plotcanvas.mpl_connect("button_press_event", self.on_click)
-            self.move_subscription = self.plotcanvas.mpl_connect('motion_notify_event', self.on_move)
-            self.frame = Gtk.Frame()
-            self.frame.set_margin_right(5)
-            self.frame.set_margin_top(3)
-            align = Gtk.Alignment()
-            align.set(0, 0.5, 0, 0)
-            align.set_padding(4, 4, 4, 4)
-            self.label = Gtk.Label()
-            self.label.set_label("Click on a reference point...")
-            abox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10)
-            abox.pack_start(Gtk.Image.new_from_file('share/measure16.png'), False, False, 0)
-            abox.pack_start(self.label, False, False, 0)
-            align.add(abox)
-            self.frame.add(align)
-            self.container.pack_end(self.frame, False, True, 1)
-            self.frame.show_all()
-            return True
-
-    def on_move(self, event):
-        if self.point1 is None:
-            self.label.set_label("Click on a reference point...")
-        else:
-            try:
-                dx = event.xdata - self.point1[0]
-                dy = event.ydata - self.point1[1]
-                d = sqrt(dx**2 + dy**2)
-                self.label.set_label("D = %.4f  D(x) = %.4f  D(y) = %.4f" % (d, dx, dy))
-            except TypeError:
-                pass
-        if self.update is not None:
-            self.update()
-
-    def on_click(self, event):
-            if self.point1 is None:
-                self.point1 = (event.xdata, event.ydata)
-            else:
-                self.point2 = copy(self.point1)
-                self.point1 = (event.xdata, event.ydata)
-            self.on_move(event)

+ 0 - 7
FlatCAM_GTK/FlatCAMException.py

@@ -1,7 +0,0 @@
-class FlatCAMException(Exception):
-    def __init__(self, message="An error occurred", detail=""):
-        self.message = message
-        self.detail = detail
-
-    def __str__(self):
-        return "FlatCAM ERROR:", self.message

+ 0 - 303
FlatCAM_GTK/FlatCAMGUI.py

@@ -1,303 +0,0 @@
-from gi.repository import Gtk
-
-from FlatCAM_GTK import FCNoteBook
-
-
-class FlatCAMGUI(Gtk.Window):
-
-    MENU = """
-    <ui>
-      <menubar name='MenuBar'>
-        <menu action='FileMenu'>
-          <menuitem action='FileNew'>
-          <separator />
-
-          <menuitem action='FileQuit' />
-        </menu>
-      </menubar>
-      <toolbar name='ToolBar'>
-        <toolitem action='FileNewStandard' />
-        <toolitem action='FileQuit' />
-      </toolbar>
-    </ui>
-    """
-
-    def __init__(self):
-        """
-
-        :return: The FlatCAM window.
-        :rtype: FlatCAM
-        """
-        Gtk.Window.__init__(self, title="FlatCAM - 0.5")
-        self.set_default_size(200, 200)
-
-        vbox1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-
-        ### Menu
-        # action_group = Gtk.ActionGroup("my_actions")
-        # self.add_file_menu_actions(action_group)
-        # #self.add_edit_menu_actions(action_group)
-        # #self.add_choices_menu_actions(action_group)
-        #
-        # uimanager = self.create_ui_manager()
-        # uimanager.insert_action_group(action_group)
-        #
-        # menubar = uimanager.get_widget("/MenuBar")
-        # vbox1.pack_start(menubar, False, False, 0)
-        #
-        # toolbar = uimanager.get_widget("/ToolBar")
-        # vbox1.pack_start(toolbar, False, False, 0)
-
-        menu = Gtk.MenuBar()
-
-        ## File
-        menufile = Gtk.MenuItem.new_with_label('File')
-        menufile_menu = Gtk.Menu()
-        menufile.set_submenu(menufile_menu)
-        # New
-        self.menufilenew = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_NEW, None)
-        menufile_menu.append(self.menufilenew)
-        menufile_menu.append(Gtk.SeparatorMenuItem())
-        # Open recent
-        self.menufilerecent = Gtk.ImageMenuItem("Open Recent", image=Gtk.Image(stock=Gtk.STOCK_OPEN))
-        menufile_menu.append(self.menufilerecent)
-        menufile_menu.append(Gtk.SeparatorMenuItem())
-        # Open Gerber ...
-        self.menufileopengerber = Gtk.ImageMenuItem("Open Gerber ...", image=Gtk.Image(stock=Gtk.STOCK_OPEN))
-        menufile_menu.append(self.menufileopengerber)
-        # Open Excellon ...
-        self.menufileopenexcellon = Gtk.ImageMenuItem("Open Excellon ...", image=Gtk.Image(stock=Gtk.STOCK_OPEN))
-        menufile_menu.append(self.menufileopenexcellon)
-        # Open G-Code ...
-        self.menufileopengcode = Gtk.ImageMenuItem("Open G-Code ...", image=Gtk.Image(stock=Gtk.STOCK_OPEN))
-        menufile_menu.append(self.menufileopengcode)
-        menufile_menu.append(Gtk.SeparatorMenuItem())
-        # Open Project ...
-        self.menufileopenproject = Gtk.ImageMenuItem("Open Project ...", image=Gtk.Image(stock=Gtk.STOCK_OPEN))
-        menufile_menu.append(self.menufileopenproject)
-        menufile_menu.append(Gtk.SeparatorMenuItem())
-        # Save Project
-        self.menufilesaveproject = Gtk.ImageMenuItem("Save Project", image=Gtk.Image(stock=Gtk.STOCK_SAVE))
-        menufile_menu.append(self.menufilesaveproject)
-        # Save Project As ...
-        self.menufilesaveprojectas = Gtk.ImageMenuItem("Save Project As ...", image=Gtk.Image(stock=Gtk.STOCK_SAVE_AS))
-        menufile_menu.append(self.menufilesaveprojectas)
-        # Save Project Copy ...
-        self.menufilesaveprojectcopy = Gtk.ImageMenuItem("Save Project Copy ...", image=Gtk.Image(stock=Gtk.STOCK_SAVE_AS))
-        menufile_menu.append(self.menufilesaveprojectcopy)
-        menufile_menu.append(Gtk.SeparatorMenuItem())
-        # Save Defaults
-        self.menufilesavedefaults = Gtk.ImageMenuItem("Save Defaults", image=Gtk.Image(stock=Gtk.STOCK_SAVE))
-        menufile_menu.append(self.menufilesavedefaults)
-        menufile_menu.append(Gtk.SeparatorMenuItem())
-        # Quit
-        self.menufilequit = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, None)
-        menufile_menu.append(self.menufilequit)
-        menu.append(menufile)
-
-        ## Edit
-        menuedit = Gtk.MenuItem.new_with_label('Edit')
-        menu.append(menuedit)
-        menuedit_menu = Gtk.Menu()
-        menuedit.set_submenu(menuedit_menu)
-        # Delete
-        self.menueditdelete = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_DELETE, None)
-        menuedit_menu.append(self.menueditdelete)
-
-        ## View
-        menuview = Gtk.MenuItem.new_with_label('View')
-        menu.append(menuview)
-        menuview_menu = Gtk.Menu()
-        menuview.set_submenu(menuview_menu)
-        # Disable all plots
-        self.menuviewdisableall = Gtk.ImageMenuItem("Disable all plots", image=Gtk.Image.new_from_file('share/clear_plot16.png'))
-        menuview_menu.append(self.menuviewdisableall)
-        self.menuviewdisableallbutthis = Gtk.ImageMenuItem("Disable all plots but this one", image=Gtk.Image.new_from_file('share/clear_plot16.png'))
-        menuview_menu.append(self.menuviewdisableallbutthis)
-        self.menuviewenableall = Gtk.ImageMenuItem("Enable all plots", image=Gtk.Image.new_from_file('share/replot16.png'))
-        menuview_menu.append(self.menuviewenableall)
-
-        ## Options
-        menuoptions = Gtk.MenuItem.new_with_label('Options')
-        menu.append(menuoptions)
-        menuoptions_menu = Gtk.Menu()
-        menuoptions.set_submenu(menuoptions_menu)
-        # Transfer Options
-        menutransferoptions = Gtk.ImageMenuItem("Transfer Options", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menuoptions_menu.append(menutransferoptions)
-        menutransferoptions_menu = Gtk.Menu()
-        menutransferoptions.set_submenu(menutransferoptions_menu)
-        self.menutransferoptions_p2a = Gtk.ImageMenuItem("Project to App", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menutransferoptions_menu.append(self.menutransferoptions_p2a)
-        self.menutransferoptions_a2p = Gtk.ImageMenuItem("App to Project", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menutransferoptions_menu.append(self.menutransferoptions_a2p)
-        self.menutransferoptions_o2p = Gtk.ImageMenuItem("Object to Project", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menutransferoptions_menu.append(self.menutransferoptions_o2p)
-        self.menutransferoptions_o2a = Gtk.ImageMenuItem("Object to App", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menutransferoptions_menu.append(self.menutransferoptions_o2a)
-        self.menutransferoptions_p2o = Gtk.ImageMenuItem("Project to Object", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menutransferoptions_menu.append(self.menutransferoptions_p2o)
-        self.menutransferoptions_a2o = Gtk.ImageMenuItem("App to Object", image=Gtk.Image.new_from_file('share/copy16.png'))
-        menutransferoptions_menu.append(self.menutransferoptions_a2o)
-
-        ## Tools
-        menutools = Gtk.MenuItem.new_with_label('Tools')
-        menu.append(menutools)
-        menutools_menu = Gtk.Menu()
-        menutools.set_submenu(menutools_menu)
-        # Double Sided PCB tool
-        self.menutools_dblsided = Gtk.ImageMenuItem("Double-Sided PCB Tool", image=Gtk.Image(stock=Gtk.STOCK_PREFERENCES))
-        menutools_menu.append(self.menutools_dblsided)
-
-        ## Help
-        menuhelp = Gtk.MenuItem.new_with_label('Help')
-        menu.append(menuhelp)
-        menuhelp_menu = Gtk.Menu()
-        menuhelp.set_submenu(menuhelp_menu)
-        # About
-        self.menuhelpabout = Gtk.ImageMenuItem("About", image=Gtk.Image(stock=Gtk.STOCK_ABOUT))
-        menuhelp_menu.append(self.menuhelpabout)
-        # Updates
-        self.menuhelpupdates = Gtk.ImageMenuItem("Check for updates", image=Gtk.Image(stock=Gtk.STOCK_DIALOG_INFO))
-        menuhelp_menu.append(self.menuhelpupdates)
-
-        vbox1.pack_start(menu, False, False, 0)
-        ### End of menu
-
-        ###############
-        ### Toolbar ###
-        ###############
-        self.toolbar = Gtk.Toolbar(toolbar_style=Gtk.ToolbarStyle.ICONS)
-        vbox1.pack_start(self.toolbar, False, False, 0)
-
-        # Zoom fit
-        zf_ico = Gtk.Image.new_from_file('share/zoom_fit32.png')
-        self.zoom_fit_btn = Gtk.ToolButton.new(zf_ico, "")
-        #zoom_fit.connect("clicked", self.on_zoom_fit)
-        self.zoom_fit_btn.set_tooltip_markup("Zoom Fit.\n(Click on plot and hit <b>1</b>)")
-        self.toolbar.insert(self.zoom_fit_btn, -1)
-
-        # Zoom out
-        zo_ico = Gtk.Image.new_from_file('share/zoom_out32.png')
-        self.zoom_out_btn = Gtk.ToolButton.new(zo_ico, "")
-        #zoom_out.connect("clicked", self.on_zoom_out)
-        self.zoom_out_btn.set_tooltip_markup("Zoom Out.\n(Click on plot and hit <b>2</b>)")
-        self.toolbar.insert(self.zoom_out_btn, -1)
-
-        # Zoom in
-        zi_ico = Gtk.Image.new_from_file('share/zoom_in32.png')
-        self.zoom_in_btn = Gtk.ToolButton.new(zi_ico, "")
-        #zoom_in.connect("clicked", self.on_zoom_in)
-        self.zoom_in_btn.set_tooltip_markup("Zoom In.\n(Click on plot and hit <b>3</b>)")
-        self.toolbar.insert(self.zoom_in_btn, -1)
-
-        # Clear plot
-        cp_ico = Gtk.Image.new_from_file('share/clear_plot32.png')
-        self.clear_plot_btn = Gtk.ToolButton.new(cp_ico, "")
-        #clear_plot.connect("clicked", self.on_clear_plots)
-        self.clear_plot_btn.set_tooltip_markup("Clear Plot")
-        self.toolbar.insert(self.clear_plot_btn, -1)
-
-        # Replot
-        rp_ico = Gtk.Image.new_from_file('share/replot32.png')
-        self.replot_btn = Gtk.ToolButton.new(rp_ico, "")
-        #replot.connect("clicked", self.on_toolbar_replot)
-        self.replot_btn.set_tooltip_markup("Re-plot all")
-        self.toolbar.insert(self.replot_btn, -1)
-
-        # Delete item
-        del_ico = Gtk.Image.new_from_file('share/delete32.png')
-        self.delete_btn = Gtk.ToolButton.new(del_ico, "")
-        #delete.connect("clicked", self.on_delete)
-        self.delete_btn.set_tooltip_markup("Delete selected\nobject.")
-        self.toolbar.insert(self.delete_btn, -1)
-
-        #############
-        ### Paned ###
-        #############
-        hpane = Gtk.Paned.new(Gtk.Orientation.HORIZONTAL)
-        vbox1.pack_start(hpane, expand=True, fill=True, padding=0)
-
-        ################
-        ### Notebook ###
-        ################
-        self.notebook = FCNoteBook()
-        hpane.pack1(self.notebook)
-
-        #################
-        ### Plot area ###
-        #################
-        # self.plotarea = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        self.plotarea = Gtk.Grid()
-        self.plotarea_super = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        self.plotarea_super.pack_start(self.plotarea, expand=True, fill=True, padding=0)
-        hpane.pack2(self.plotarea_super)
-
-        ################
-        ### Info bar ###
-        ################
-        infobox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
-        vbox1.pack_start(infobox, expand=False, fill=True, padding=0)
-        ## Frame
-        frame = Gtk.Frame(margin=2, hexpand=True, halign=0)
-        infobox.pack_start(frame, expand=True, fill=True, padding=0)
-        self.info_label = Gtk.Label("Not started.", margin=2, hexpand=True)
-        frame.add(self.info_label)
-        ## Coordinate Label
-        self.position_label = Gtk.Label("X: 0.0   Y: 0.0", margin_left=4, margin_right=4)
-        infobox.pack_start(self.position_label, expand=False, fill=False, padding=0)
-        ## Units label
-        self.units_label = Gtk.Label("[in]", margin_left=4, margin_right=4)
-        infobox.pack_start(self.units_label, expand=False, fill=False, padding=0)
-        ## Progress bar
-        self.progress_bar = Gtk.ProgressBar(margin=2)
-        infobox.pack_start(self.progress_bar, expand=False, fill=False, padding=0)
-
-        self.add(vbox1)
-        self.show_all()
-
-    # def create_ui_manager(self):
-    #     uimanager = Gtk.UIManager()
-    #
-    #     # Throws exception if something went wrong
-    #     uimanager.add_ui_from_string(FlatCAM.MENU)
-    #
-    #     # Add the accelerator group to the toplevel window
-    #     accelgroup = uimanager.get_accel_group()
-    #     self.add_accel_group(accelgroup)
-    #     return uimanager
-    #
-    # def add_file_menu_actions(self, action_group):
-    #     action_filemenu = Gtk.Action("FileMenu", "File", None, None)
-    #     action_group.add_action(action_filemenu)
-    #
-    #     action_filenewmenu = Gtk.Action("FileNew", None, None, Gtk.STOCK_NEW)
-    #     action_group.add_action(action_filenewmenu)
-    #
-    #     action_new = Gtk.Action("FileNewStandard", "_New",
-    #         "Create a new file", Gtk.STOCK_NEW)
-    #     action_new.connect("activate", self.on_menu_file_new_generic)
-    #     action_group.add_action_with_accel(action_new, None)
-    #
-    #     action_group.add_actions([
-    #         ("FileNewFoo", None, "New Foo", None, "Create new foo",
-    #          self.on_menu_file_new_generic),
-    #         ("FileNewGoo", None, "_New Goo", None, "Create new goo",
-    #          self.on_menu_file_new_generic),
-    #     ])
-    #
-    #     action_filequit = Gtk.Action("FileQuit", None, None, Gtk.STOCK_QUIT)
-    #     action_filequit.connect("activate", self.on_menu_file_quit)
-    #     action_group.add_action(action_filequit)
-    #
-    # def on_menu_file_new_generic(self, widget):
-    #     print("A File|New menu item was selected.")
-    #
-    # def on_menu_file_quit(self, widget):
-    #     Gtk.main_quit()
-
-
-
-if __name__ == "__main__":
-    flatcam = FlatCAMGUI()
-    Gtk.main()

+ 0 - 1007
FlatCAM_GTK/FlatCAMObj.py

@@ -1,1007 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-import inspect  # TODO: Remove
-
-from gi.repository import Gtk
-from gi.repository import GLib
-from gi.repository import GObject
-
-from camlib import *
-from ObjectUI import *
-
-
-class LoudDict(dict):
-    """
-    A Dictionary with a callback for
-    item changes.
-    """
-
-    def __init__(self, *args, **kwargs):
-        super(LoudDict, self).__init__(*args, **kwargs)
-        self.callback = lambda x: None
-        self.silence = False
-
-    def set_change_callback(self, callback):
-        """
-        Assigns a function as callback on item change. The callback
-        will receive the key of the object that was changed.
-
-        :param callback: Function to call on item change.
-        :type callback: func
-        :return: None
-        """
-
-        self.callback = callback
-
-    def __setitem__(self, key, value):
-        """
-        Overridden __setitem__ method. Will call self.callback
-        if the item was changed and self.silence is False.
-        """
-        super(LoudDict, self).__setitem__(key, value)
-        try:
-            if self.__getitem__(key) == value:
-                return
-        except KeyError:
-            pass
-        if self.silence:
-            return
-        self.callback(key)
-
-
-########################################
-##            FlatCAMObj              ##
-########################################
-class FlatCAMObj(GObject.GObject, object):
-    """
-    Base type of objects handled in FlatCAM. These become interactive
-    in the GUI, can be plotted, and their options can be modified
-    by the user in their respective forms.
-    """
-
-    # Instance of the application to which these are related.
-    # The app should set this value.
-    app = None
-
-    def __init__(self, name, ui):
-        """
-
-        :param name: Name of the object given by the user.
-        :param ui: User interface to interact with the object.
-        :type ui: ObjectUI
-        :return: FlatCAMObj
-        """
-        GObject.GObject.__init__(self)
-
-        # View
-        self.ui = ui
-
-        self.options = LoudDict(name=name)
-        self.options.set_change_callback(self.on_options_change)
-
-        self.form_fields = {"name": self.ui.name_entry}
-        self.radios = {}  # Name value pairs for radio sets
-        self.radios_inv = {}  # Inverse of self.radios
-        self.axes = None  # Matplotlib axes
-        self.kind = None  # Override with proper name
-
-        self.muted_ui = False
-
-        self.ui.name_entry.connect('activate', self.on_name_activate)
-        self.ui.offset_button.connect('clicked', self.on_offset_button_click)
-        self.ui.offset_button.connect('activate', self.on_offset_button_click)
-        self.ui.scale_button.connect('clicked', self.on_scale_button_click)
-        self.ui.scale_button.connect('activate', self.on_scale_button_click)
-
-    def __str__(self):
-        return "<FlatCAMObj({:12s}): {:20s}>".format(self.kind, self.options["name"])
-
-    def on_name_activate(self, *args):
-        old_name = copy(self.options["name"])
-        new_name = self.ui.name_entry.get_text()
-        self.options["name"] = self.ui.name_entry.get_text()
-        self.app.info("Name changed from %s to %s" % (old_name, new_name))
-
-    def on_offset_button_click(self, *args):
-        self.read_form()
-        vect = self.ui.offsetvector_entry.get_value()
-        self.offset(vect)
-        self.plot()
-
-    def on_scale_button_click(self, *args):
-        self.read_form()
-        factor = self.ui.scale_entry.get_value()
-        self.scale(factor)
-        self.plot()
-
-    def on_options_change(self, key):
-        self.form_fields[key].set_value(self.options[key])
-        return
-
-    def setup_axes(self, figure):
-        """
-        1) Creates axes if they don't exist. 2) Clears axes. 3) Attaches
-        them to figure if not part of the figure. 4) Sets transparent
-        background. 5) Sets 1:1 scale aspect ratio.
-
-        :param figure: A Matplotlib.Figure on which to add/configure axes.
-        :type figure: matplotlib.figure.Figure
-        :return: None
-        :rtype: None
-        """
-
-        if self.axes is None:
-            FlatCAMApp.App.log.debug("setup_axes(): New axes")
-            self.axes = figure.add_axes([0.05, 0.05, 0.9, 0.9],
-                                        label=self.options["name"])
-        elif self.axes not in figure.axes:
-            FlatCAMApp.App.log.debug("setup_axes(): Clearing and attaching axes")
-            self.axes.cla()
-            figure.add_axes(self.axes)
-        else:
-            FlatCAMApp.App.log.debug("setup_axes(): Clearing Axes")
-            self.axes.cla()
-
-        # Remove all decoration. The app's axes will have
-        # the ticks and grid.
-        self.axes.set_frame_on(False)  # No frame
-        self.axes.set_xticks([])  # No tick
-        self.axes.set_yticks([])  # No ticks
-        self.axes.patch.set_visible(False)  # No background
-        self.axes.set_aspect(1)
-
-    def to_form(self):
-        """
-        Copies options to the UI form.
-
-        :return: None
-        """
-        for option in self.options:
-            self.set_form_item(option)
-
-    def read_form(self):
-        """
-        Reads form into ``self.options``.
-
-        :return: None
-        :rtype: None
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.read_form()")
-        for option in self.options:
-            self.read_form_item(option)
-
-    def build_ui(self):
-        """
-        Sets up the UI/form for this object.
-
-        :return: None
-        :rtype: None
-        """
-
-        self.muted_ui = True
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> FlatCAMObj.build_ui()")
-
-        # Where the UI for this object is drawn
-        # box_selected = self.app.builder.get_object("box_selected")
-        # box_selected = self.app.builder.get_object("vp_selected")
-
-        # Remove anything else in the box
-        box_children = self.app.ui.notebook.selected_contents.get_children()
-        for child in box_children:
-            self.app.ui.notebook.selected_contents.remove(child)
-
-        # Put in the UI
-        # box_selected.pack_start(sw, True, True, 0)
-        self.app.ui.notebook.selected_contents.add(self.ui)
-        self.to_form()
-        GLib.idle_add(self.app.ui.notebook.selected_contents.show_all)
-        GLib.idle_add(self.ui.show_all)
-        self.muted_ui = False
-
-    def set_form_item(self, option):
-        """
-        Copies the specified option to the UI form.
-
-        :param option: Name of the option (Key in ``self.options``).
-        :type option: str
-        :return: None
-        """
-
-        try:
-            self.form_fields[option].set_value(self.options[option])
-        except KeyError:
-            self.app.log.warn("Tried to set an option or field that does not exist: %s" % option)
-
-    def read_form_item(self, option):
-        """
-        Reads the specified option from the UI form into ``self.options``.
-
-        :param option: Name of the option.
-        :type option: str
-        :return: None
-        """
-
-        try:
-            self.options[option] = self.form_fields[option].get_value()
-        except KeyError:
-            self.app.log.warning("Failed to read option from field: %s" % option)
-
-    def plot(self):
-        """
-        Plot this object (Extend this method to implement the actual plotting).
-        Axes get created, appended to canvas and cleared before plotting.
-        Call this in descendants before doing the plotting.
-
-        :return: Whether to continue plotting or not depending on the "plot" option.
-        :rtype: bool
-        """
-
-        # Axes must exist and be attached to canvas.
-        if self.axes is None or self.axes not in self.app.plotcanvas.figure.axes:
-            self.axes = self.app.plotcanvas.new_axes(self.options['name'])
-
-        if not self.options["plot"]:
-            self.axes.cla()
-            self.app.plotcanvas.auto_adjust_axes()
-            return False
-
-        # Clear axes or we will plot on top of them.
-        self.axes.cla()  # TODO: Thread safe?
-        # GLib.idle_add(self.axes.cla)
-        return True
-
-    def serialize(self):
-        """
-        Returns a representation of the object as a dictionary so
-        it can be later exported as JSON. Override this method.
-
-        :return: Dictionary representing the object
-        :rtype: dict
-        """
-        return
-
-    def deserialize(self, obj_dict):
-        """
-        Re-builds an object from its serialized version.
-
-        :param obj_dict: Dictionary representing a FlatCAMObj
-        :type obj_dict: dict
-        :return: None
-        """
-        return
-
-
-class FlatCAMGerber(FlatCAMObj, Gerber):
-    """
-    Represents Gerber code.
-    """
-
-    def __init__(self, name):
-        Gerber.__init__(self)
-        FlatCAMObj.__init__(self, name, GerberObjectUI())
-
-        self.kind = "gerber"
-
-        self.form_fields.update({
-            "plot": self.ui.plot_cb,
-            "multicolored": self.ui.multicolored_cb,
-            "solid": self.ui.solid_cb,
-            "isotooldia": self.ui.iso_tool_dia_entry,
-            "isopasses": self.ui.iso_width_entry,
-            "isooverlap": self.ui.iso_overlap_entry,
-            "cutouttooldia": self.ui.cutout_tooldia_entry,
-            "cutoutmargin": self.ui.cutout_margin_entry,
-            "cutoutgapsize": self.ui.cutout_gap_entry,
-            "gaps": self.ui.gaps_radio,
-            "noncoppermargin": self.ui.noncopper_margin_entry,
-            "noncopperrounded": self.ui.noncopper_rounded_cb,
-            "bboxmargin": self.ui.bbmargin_entry,
-            "bboxrounded": self.ui.bbrounded_cb
-        })
-
-        # The 'name' is already in self.options from FlatCAMObj
-        # Automatically updates the UI
-        self.options.update({
-            "plot": True,
-            "multicolored": False,
-            "solid": False,
-            "isotooldia": 0.016,
-            "isopasses": 1,
-            "isooverlap": 0.15,
-            "cutouttooldia": 0.07,
-            "cutoutmargin": 0.2,
-            "cutoutgapsize": 0.15,
-            "gaps": "tb",
-            "noncoppermargin": 0.0,
-            "noncopperrounded": False,
-            "bboxmargin": 0.0,
-            "bboxrounded": False
-        })
-
-        # Attributes to be included in serialization
-        # Always append to it because it carries contents
-        # from predecessors.
-        self.ser_attrs += ['options', 'kind']
-
-        assert isinstance(self.ui, GerberObjectUI)
-        self.ui.plot_cb.connect('clicked', self.on_plot_cb_click)
-        self.ui.plot_cb.connect('activate', self.on_plot_cb_click)
-        self.ui.solid_cb.connect('clicked', self.on_solid_cb_click)
-        self.ui.solid_cb.connect('activate', self.on_solid_cb_click)
-        self.ui.multicolored_cb.connect('clicked', self.on_multicolored_cb_click)
-        self.ui.multicolored_cb.connect('activate', self.on_multicolored_cb_click)
-        self.ui.generate_iso_button.connect('clicked', self.on_iso_button_click)
-        self.ui.generate_iso_button.connect('activate', self.on_iso_button_click)
-        self.ui.generate_cutout_button.connect('clicked', self.on_generatecutout_button_click)
-        self.ui.generate_cutout_button.connect('activate', self.on_generatecutout_button_click)
-        self.ui.generate_bb_button.connect('clicked', self.on_generatebb_button_click)
-        self.ui.generate_bb_button.connect('activate', self.on_generatebb_button_click)
-        self.ui.generate_noncopper_button.connect('clicked', self.on_generatenoncopper_button_click)
-        self.ui.generate_noncopper_button.connect('activate', self.on_generatenoncopper_button_click)
-
-    def on_generatenoncopper_button_click(self, *args):
-        self.read_form()
-        name = self.options["name"] + "_noncopper"
-
-        def geo_init(geo_obj, app_obj):
-            assert isinstance(geo_obj, FlatCAMGeometry)
-            bounding_box = self.solid_geometry.envelope.buffer(self.options["noncoppermargin"])
-            if not self.options["noncopperrounded"]:
-                bounding_box = bounding_box.envelope
-            non_copper = bounding_box.difference(self.solid_geometry)
-            geo_obj.solid_geometry = non_copper
-
-        # TODO: Check for None
-        self.app.new_object("geometry", name, geo_init)
-
-    def on_generatebb_button_click(self, *args):
-        self.read_form()
-        name = self.options["name"] + "_bbox"
-
-        def geo_init(geo_obj, app_obj):
-            assert isinstance(geo_obj, FlatCAMGeometry)
-            # Bounding box with rounded corners
-            bounding_box = self.solid_geometry.envelope.buffer(self.options["bboxmargin"])
-            if not self.options["bboxrounded"]:  # Remove rounded corners
-                bounding_box = bounding_box.envelope
-            geo_obj.solid_geometry = bounding_box
-
-        self.app.new_object("geometry", name, geo_init)
-
-    def on_generatecutout_button_click(self, *args):
-        self.read_form()
-        name = self.options["name"] + "_cutout"
-
-        def geo_init(geo_obj, app_obj):
-            margin = self.options["cutoutmargin"] + self.options["cutouttooldia"]/2
-            gap_size = self.options["cutoutgapsize"] + self.options["cutouttooldia"]
-            minx, miny, maxx, maxy = self.bounds()
-            minx -= margin
-            maxx += margin
-            miny -= margin
-            maxy += margin
-            midx = 0.5 * (minx + maxx)
-            midy = 0.5 * (miny + maxy)
-            hgap = 0.5 * gap_size
-            pts = [[midx - hgap, maxy],
-                   [minx, maxy],
-                   [minx, midy + hgap],
-                   [minx, midy - hgap],
-                   [minx, miny],
-                   [midx - hgap, miny],
-                   [midx + hgap, miny],
-                   [maxx, miny],
-                   [maxx, midy - hgap],
-                   [maxx, midy + hgap],
-                   [maxx, maxy],
-                   [midx + hgap, maxy]]
-            cases = {"tb": [[pts[0], pts[1], pts[4], pts[5]],
-                            [pts[6], pts[7], pts[10], pts[11]]],
-                     "lr": [[pts[9], pts[10], pts[1], pts[2]],
-                            [pts[3], pts[4], pts[7], pts[8]]],
-                     "4": [[pts[0], pts[1], pts[2]],
-                           [pts[3], pts[4], pts[5]],
-                           [pts[6], pts[7], pts[8]],
-                           [pts[9], pts[10], pts[11]]]}
-            cuts = cases[self.options['gaps']]
-            geo_obj.solid_geometry = cascaded_union([LineString(segment) for segment in cuts])
-
-        # TODO: Check for None
-        self.app.new_object("geometry", name, geo_init)
-
-    def on_iso_button_click(self, *args):
-        self.read_form()
-        dia = self.options["isotooldia"]
-        passes = int(self.options["isopasses"])
-        overlap = self.options["isooverlap"] * dia
-
-        for i in range(passes):
-
-            offset = (2*i + 1)/2.0 * dia - i*overlap
-            iso_name = self.options["name"] + "_iso%d" % (i+1)
-
-            # TODO: This is ugly. Create way to pass data into init function.
-            def iso_init(geo_obj, app_obj):
-                # Propagate options
-                geo_obj.options["cnctooldia"] = self.options["isotooldia"]
-
-                geo_obj.solid_geometry = self.isolation_geometry(offset)
-                app_obj.info("Isolation geometry created: %s" % geo_obj.options["name"])
-
-            # TODO: Do something if this is None. Offer changing name?
-            self.app.new_object("geometry", iso_name, iso_init)
-
-    def on_plot_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('plot')
-        self.plot()
-
-    def on_solid_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('solid')
-        self.plot()
-
-    def on_multicolored_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('multicolored')
-        self.plot()
-
-    def convert_units(self, units):
-        """
-        Converts the units of the object by scaling dimensions in all geometry
-        and options.
-
-        :param units: Units to which to convert the object: "IN" or "MM".
-        :type units: str
-        :return: None
-        :rtype: None
-        """
-
-        factor = Gerber.convert_units(self, units)
-
-        self.options['isotooldia'] *= factor
-        self.options['cutoutmargin'] *= factor
-        self.options['cutoutgapsize'] *= factor
-        self.options['noncoppermargin'] *= factor
-        self.options['bboxmargin'] *= factor
-
-    def plot(self):
-
-        # Does all the required setup and returns False
-        # if the 'ptint' option is set to False.
-        if not FlatCAMObj.plot(self):
-            return
-
-        # if self.options["mergepolys"]:
-        #     geometry = self.solid_geometry
-        # else:
-        #     geometry = self.buffered_paths + \
-        #                 [poly['polygon'] for poly in self.regions] + \
-        #                 self.flash_geometry
-        geometry = self.solid_geometry
-
-        # Make sure geometry is iterable.
-        try:
-            _ = iter(geometry)
-        except TypeError:
-            geometry = [geometry]
-
-        if self.options["multicolored"]:
-            linespec = '-'
-        else:
-            linespec = 'k-'
-
-        if self.options["solid"]:
-            for poly in geometry:
-                # TODO: Too many things hardcoded.
-                try:
-                    patch = PolygonPatch(poly,
-                                         facecolor="#BBF268",
-                                         edgecolor="#006E20",
-                                         alpha=0.75,
-                                         zorder=2)
-                    self.axes.add_patch(patch)
-                except AssertionError:
-                    FlatCAMApp.App.log.warning("A geometry component was not a polygon:")
-                    FlatCAMApp.App.log.warning(str(poly))
-        else:
-            for poly in geometry:
-                x, y = poly.exterior.xy
-                self.axes.plot(x, y, linespec)
-                for ints in poly.interiors:
-                    x, y = ints.coords.xy
-                    self.axes.plot(x, y, linespec)
-
-        # self.app.plotcanvas.auto_adjust_axes()
-        GLib.idle_add(self.app.plotcanvas.auto_adjust_axes)
-
-    def serialize(self):
-        return {
-            "options": self.options,
-            "kind": self.kind
-        }
-
-
-class FlatCAMExcellon(FlatCAMObj, Excellon):
-    """
-    Represents Excellon/Drill code.
-    """
-
-    def __init__(self, name):
-        Excellon.__init__(self)
-        FlatCAMObj.__init__(self, name, ExcellonObjectUI())
-
-        self.kind = "excellon"
-
-        self.form_fields.update({
-            "plot": self.ui.plot_cb,
-            "solid": self.ui.solid_cb,
-            "drillz": self.ui.cutz_entry,
-            "travelz": self.ui.travelz_entry,
-            "feedrate": self.ui.feedrate_entry,
-            "toolselection": self.ui.tools_entry
-        })
-
-        self.options.update({
-            "plot": True,
-            "solid": False,
-            "drillz": -0.1,
-            "travelz": 0.1,
-            "feedrate": 5.0,
-            "toolselection": ""
-        })
-
-        # TODO: Document this.
-        self.tool_cbs = {}
-
-        # Attributes to be included in serialization
-        # Always append to it because it carries contents
-        # from predecessors.
-        self.ser_attrs += ['options', 'kind']
-
-        assert isinstance(self.ui, ExcellonObjectUI)
-        self.ui.plot_cb.connect('clicked', self.on_plot_cb_click)
-        self.ui.plot_cb.connect('activate', self.on_plot_cb_click)
-        self.ui.solid_cb.connect('clicked', self.on_solid_cb_click)
-        self.ui.solid_cb.connect('activate', self.on_solid_cb_click)
-        self.ui.choose_tools_button.connect('clicked', lambda args: self.show_tool_chooser())
-        self.ui.choose_tools_button.connect('activate', lambda args: self.show_tool_chooser())
-        self.ui.generate_cnc_button.connect('clicked', self.on_create_cncjob_button_click)
-        self.ui.generate_cnc_button.connect('activate', self.on_create_cncjob_button_click)
-
-    def on_create_cncjob_button_click(self, *args):
-        self.read_form()
-        job_name = self.options["name"] + "_cnc"
-
-        # Object initialization function for app.new_object()
-        def job_init(job_obj, app_obj):
-            assert isinstance(job_obj, FlatCAMCNCjob)
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.2, "Creating CNC Job..."))
-            job_obj.z_cut = self.options["drillz"]
-            job_obj.z_move = self.options["travelz"]
-            job_obj.feedrate = self.options["feedrate"]
-            # There could be more than one drill size...
-            # job_obj.tooldia =   # TODO: duplicate variable!
-            # job_obj.options["tooldia"] =
-            job_obj.generate_from_excellon_by_tool(self, self.options["toolselection"])
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.5, "Parsing G-Code..."))
-            job_obj.gcode_parse()
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.6, "Creating New Geometry..."))
-            job_obj.create_geometry()
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.8, "Plotting..."))
-
-        # To be run in separate thread
-        def job_thread(app_obj):
-            app_obj.new_object("cncjob", job_name, job_init)
-            GLib.idle_add(lambda: app_obj.set_progress_bar(1.0, "Done!"))
-            GLib.timeout_add_seconds(1, lambda: app_obj.set_progress_bar(0.0, ""))
-
-        # Send to worker
-        self.app.worker.add_task(job_thread, [self.app])
-
-    def on_plot_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('plot')
-        self.plot()
-
-    def on_solid_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('solid')
-        self.plot()
-
-    def convert_units(self, units):
-        factor = Excellon.convert_units(self, units)
-
-        self.options['drillz'] *= factor
-        self.options['travelz'] *= factor
-        self.options['feedrate'] *= factor
-
-    def plot(self):
-
-        # Does all the required setup and returns False
-        # if the 'ptint' option is set to False.
-        if not FlatCAMObj.plot(self):
-            return
-
-        try:
-            _ = iter(self.solid_geometry)
-        except TypeError:
-            self.solid_geometry = [self.solid_geometry]
-
-        # Plot excellon (All polygons?)
-        if self.options["solid"]:
-            for geo in self.solid_geometry:
-                patch = PolygonPatch(geo,
-                                     facecolor="#C40000",
-                                     edgecolor="#750000",
-                                     alpha=0.75,
-                                     zorder=3)
-                self.axes.add_patch(patch)
-        else:
-            for geo in self.solid_geometry:
-                x, y = geo.exterior.coords.xy
-                self.axes.plot(x, y, 'r-')
-                for ints in geo.interiors:
-                    x, y = ints.coords.xy
-                    self.axes.plot(x, y, 'g-')
-
-        #self.app.plotcanvas.auto_adjust_axes()
-        GLib.idle_add(self.app.plotcanvas.auto_adjust_axes)
-
-    def show_tool_chooser(self):
-        win = Gtk.Window()
-        box = Gtk.Box(spacing=2)
-        box.set_orientation(Gtk.Orientation(1))
-        win.add(box)
-        for tool in self.tools:
-            self.tool_cbs[tool] = Gtk.CheckButton(label=tool + ": " + str(self.tools[tool]))
-            box.pack_start(self.tool_cbs[tool], False, False, 1)
-        button = Gtk.Button(label="Accept")
-        box.pack_start(button, False, False, 1)
-        win.show_all()
-
-        def on_accept(widget):
-            win.destroy()
-            tool_list = []
-            for toolx in self.tool_cbs:
-                if self.tool_cbs[toolx].get_active():
-                    tool_list.append(toolx)
-            self.options["toolselection"] = ", ".join(tool_list)
-            self.to_form()
-
-        button.connect("activate", on_accept)
-        button.connect("clicked", on_accept)
-
-import time
-
-class FlatCAMCNCjob(FlatCAMObj, CNCjob):
-    """
-    Represents G-Code.
-    """
-
-    def __init__(self, name, units="in", kind="generic", z_move=0.1,
-                 feedrate=3.0, z_cut=-0.002, tooldia=0.0):
-        FlatCAMApp.App.log.debug("Creating CNCJob object...")
-        CNCjob.__init__(self, units=units, kind=kind, z_move=z_move,
-                        feedrate=feedrate, z_cut=z_cut, tooldia=tooldia)
-        ui = CNCObjectUI()
-        FlatCAMApp.App.log.debug("... UI Created")
-        time.sleep(2)
-        FlatCAMApp.App.log.debug("... 2 seconds later")
-        FlatCAMObj.__init__(self, name, ui)
-        FlatCAMApp.App.log.debug("... UI Passed to parent")
-        self.kind = "cncjob"
-
-        self.options.update({
-            "plot": True,
-            "tooldia": 0.4 / 25.4,  # 0.4mm in inches
-            #"append": ""
-        })
-
-        self.form_fields.update({
-            "plot": self.ui.plot_cb,
-            "tooldia": self.ui.tooldia_entry,
-            #"append": self.ui.append_gtext
-        })
-        FlatCAMApp.App.log.debug("... Options")
-
-        # Attributes to be included in serialization
-        # Always append to it because it carries contents
-        # from predecessors.
-        self.ser_attrs += ['options', 'kind']
-
-        self.ui.plot_cb.connect('clicked', self.on_plot_cb_click)
-        self.ui.plot_cb.connect('activate', self.on_plot_cb_click)
-        self.ui.updateplot_button.connect('clicked', self.on_updateplot_button_click)
-        self.ui.updateplot_button.connect('activate', self.on_updateplot_button_click)
-        self.ui.export_gcode_button.connect('clicked', self.on_exportgcode_button_click)
-        self.ui.export_gcode_button.connect('activate', self.on_exportgcode_button_click)
-        FlatCAMApp.App.log.debug("... Callbacks. DONE")
-
-    def on_updateplot_button_click(self, *args):
-        """
-        Callback for the "Updata Plot" button. Reads the form for updates
-        and plots the object.
-        """
-        self.read_form()
-        self.plot()
-
-    def on_exportgcode_button_click(self, *args):
-        def on_success(app_obj, filename):
-            f = open(filename, 'w')
-            f.write(self.gcode)
-            f.close()
-            app_obj.info("Saved to: " + filename)
-
-        self.app.file_chooser_save_action(on_success)
-
-    def on_plot_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('plot')
-        self.plot()
-
-    def plot(self):
-
-        # Does all the required setup and returns False
-        # if the 'ptint' option is set to False.
-        if not FlatCAMObj.plot(self):
-            return
-
-        self.plot2(self.axes, tooldia=self.options["tooldia"])
-
-        #self.app.plotcanvas.auto_adjust_axes()
-        GLib.idle_add(self.app.plotcanvas.auto_adjust_axes)
-
-    def convert_units(self, units):
-        factor = CNCjob.convert_units(self, units)
-        FlatCAMApp.App.log.debug("FlatCAMCNCjob.convert_units()")
-        self.options["tooldia"] *= factor
-
-
-class FlatCAMGeometry(FlatCAMObj, Geometry):
-    """
-    Geometric object not associated with a specific
-    format.
-    """
-
-    def __init__(self, name):
-        FlatCAMObj.__init__(self, name, GeometryObjectUI())
-        Geometry.__init__(self)
-
-        self.kind = "geometry"
-
-        self.form_fields.update({
-            "plot": self.ui.plot_cb,
-            # "solid": self.ui.sol,
-            # "multicolored": self.ui.,
-            "cutz": self.ui.cutz_entry,
-            "travelz": self.ui.travelz_entry,
-            "feedrate": self.ui.cncfeedrate_entry,
-            "cnctooldia": self.ui.cnctooldia_entry,
-            "painttooldia": self.ui.painttooldia_entry,
-            "paintoverlap": self.ui.paintoverlap_entry,
-            "paintmargin": self.ui.paintmargin_entry
-        })
-
-        self.options.update({
-            "plot": True,
-            # "solid": False,
-            # "multicolored": False,
-            "cutz": -0.002,
-            "travelz": 0.1,
-            "feedrate": 5.0,
-            "cnctooldia": 0.4 / 25.4,
-            "painttooldia": 0.0625,
-            "paintoverlap": 0.15,
-            "paintmargin": 0.01
-        })
-
-        # self.form_kinds.update({
-        #     "plot": "cb",
-        #     "solid": "cb",
-        #     "multicolored": "cb",
-        #     "cutz": "entry_eval",
-        #     "travelz": "entry_eval",
-        #     "feedrate": "entry_eval",
-        #     "cnctooldia": "entry_eval",
-        #     "painttooldia": "entry_eval",
-        #     "paintoverlap": "entry_eval",
-        #     "paintmargin": "entry_eval"
-        # })
-
-        # Attributes to be included in serialization
-        # Always append to it because it carries contents
-        # from predecessors.
-        self.ser_attrs += ['options', 'kind']
-
-        assert isinstance(self.ui, GeometryObjectUI)
-        self.ui.plot_cb.connect('clicked', self.on_plot_cb_click)
-        self.ui.plot_cb.connect('activate', self.on_plot_cb_click)
-        self.ui.generate_cnc_button.connect('clicked', self.on_generatecnc_button_click)
-        self.ui.generate_cnc_button.connect('activate', self.on_generatecnc_button_click)
-        self.ui.generate_paint_button.connect('clicked', self.on_paint_button_click)
-        self.ui.generate_paint_button.connect('activate', self.on_paint_button_click)
-
-    def on_paint_button_click(self, *args):
-        self.app.info("Click inside the desired polygon.")
-        self.read_form()
-        tooldia = self.options["painttooldia"]
-        overlap = self.options["paintoverlap"]
-
-        # Connection ID for the click event
-        subscription = None
-
-        # To be called after clicking on the plot.
-        def doit(event):
-            self.app.plotcanvas.mpl_disconnect(subscription)
-            point = [event.xdata, event.ydata]
-            poly = find_polygon(self.solid_geometry, point)
-
-            # Initializes the new geometry object
-            def gen_paintarea(geo_obj, app_obj):
-                assert isinstance(geo_obj, FlatCAMGeometry)
-                #assert isinstance(app_obj, App)
-                cp = clear_poly(poly.buffer(-self.options["paintmargin"]), tooldia, overlap)
-                geo_obj.solid_geometry = cp
-                geo_obj.options["cnctooldia"] = tooldia
-
-            name = self.options["name"] + "_paint"
-            self.app.new_object("geometry", name, gen_paintarea)
-
-        subscription = self.app.plotcanvas.mpl_connect('button_press_event', doit)
-
-    def on_generatecnc_button_click(self, *args):
-        self.read_form()
-        job_name = self.options["name"] + "_cnc"
-
-        # Object initialization function for app.new_object()
-        # RUNNING ON SEPARATE THREAD!
-        def job_init(job_obj, app_obj):
-            assert isinstance(job_obj, FlatCAMCNCjob)
-            # Propagate options
-            job_obj.options["tooldia"] = self.options["cnctooldia"]
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.2, "Creating CNC Job..."))
-            job_obj.z_cut = self.options["cutz"]
-            job_obj.z_move = self.options["travelz"]
-            job_obj.feedrate = self.options["feedrate"]
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.4, "Analyzing Geometry..."))
-            # TODO: The tolerance should not be hard coded. Just for testing.
-            job_obj.generate_from_geometry(self, tolerance=0.0005)
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.5, "Parsing G-Code..."))
-            job_obj.gcode_parse()
-
-            # TODO: job_obj.create_geometry creates stuff that is not used.
-            #GLib.idle_add(lambda: app_obj.set_progress_bar(0.6, "Creating New Geometry..."))
-            #job_obj.create_geometry()
-
-            GLib.idle_add(lambda: app_obj.set_progress_bar(0.8, "Plotting..."))
-
-        # To be run in separate thread
-        def job_thread(app_obj):
-            app_obj.new_object("cncjob", job_name, job_init)
-            GLib.idle_add(lambda: app_obj.info("CNCjob created: %s" % job_name))
-            GLib.idle_add(lambda: app_obj.set_progress_bar(1.0, "Done!"))
-            GLib.timeout_add_seconds(1, lambda: app_obj.set_progress_bar(0.0, "Idle"))
-
-        # Send to worker
-        self.app.worker.add_task(job_thread, [self.app])
-
-    def on_plot_cb_click(self, *args):
-        if self.muted_ui:
-            return
-        self.read_form_item('plot')
-        self.plot()
-
-    def scale(self, factor):
-        """
-        Scales all geometry by a given factor.
-
-        :param factor: Factor by which to scale the object's geometry/
-        :type factor: float
-        :return: None
-        :rtype: None
-        """
-
-        if type(self.solid_geometry) == list:
-            self.solid_geometry = [affinity.scale(g, factor, factor, origin=(0, 0))
-                                   for g in self.solid_geometry]
-        else:
-            self.solid_geometry = affinity.scale(self.solid_geometry, factor, factor,
-                                                 origin=(0, 0))
-
-    def offset(self, vect):
-        """
-        Offsets all geometry by a given vector/
-
-        :param vect: (x, y) vector by which to offset the object's geometry.
-        :type vect: tuple
-        :return: None
-        :rtype: None
-        """
-
-        dx, dy = vect
-
-        if type(self.solid_geometry) == list:
-            self.solid_geometry = [affinity.translate(g, xoff=dx, yoff=dy)
-                                   for g in self.solid_geometry]
-        else:
-            self.solid_geometry = affinity.translate(self.solid_geometry, xoff=dx, yoff=dy)
-
-    def convert_units(self, units):
-        factor = Geometry.convert_units(self, units)
-
-        self.options['cutz'] *= factor
-        self.options['travelz'] *= factor
-        self.options['feedrate'] *= factor
-        self.options['cnctooldia'] *= factor
-        self.options['painttooldia'] *= factor
-        self.options['paintmargin'] *= factor
-
-        return factor
-
-    def plot(self):
-        """
-        Plots the object into its axes. If None, of if the axes
-        are not part of the app's figure, it fetches new ones.
-
-        :return: None
-        """
-
-        # Does all the required setup and returns False
-        # if the 'ptint' option is set to False.
-        if not FlatCAMObj.plot(self):
-            return
-
-        # Make sure solid_geometry is iterable.
-        try:
-            _ = iter(self.solid_geometry)
-        except TypeError:
-            self.solid_geometry = [self.solid_geometry]
-
-        for geo in self.solid_geometry:
-
-            if type(geo) == Polygon:
-                x, y = geo.exterior.coords.xy
-                self.axes.plot(x, y, 'r-')
-                for ints in geo.interiors:
-                    x, y = ints.coords.xy
-                    self.axes.plot(x, y, 'r-')
-                continue
-
-            if type(geo) == LineString or type(geo) == LinearRing:
-                x, y = geo.coords.xy
-                self.axes.plot(x, y, 'r-')
-                continue
-
-            if type(geo) == MultiPolygon:
-                for poly in geo:
-                    x, y = poly.exterior.coords.xy
-                    self.axes.plot(x, y, 'r-')
-                    for ints in poly.interiors:
-                        x, y = ints.coords.xy
-                        self.axes.plot(x, y, 'r-')
-                continue
-
-            FlatCAMApp.App.log.warning("Did not plot:", str(type(geo)))
-
-        #self.app.plotcanvas.auto_adjust_axes()
-        GLib.idle_add(self.app.plotcanvas.auto_adjust_axes)

+ 0 - 43
FlatCAM_GTK/FlatCAMWorker.py

@@ -1,43 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-import threading
-import Queue
-
-
-class Worker(threading.Thread):
-    """
-    Implements a queue of tasks to be carried out in order
-    in a single independent thread.
-    """
-
-    def __init__(self):
-        super(Worker, self).__init__()
-        self.queue = Queue.Queue()
-        self.stoprequest = threading.Event()
-
-    def run(self):
-        while not self.stoprequest.isSet():
-            try:
-                task = self.queue.get(True, 0.05)
-                self.do_task(task)
-            except Queue.Empty:
-                continue
-
-    @staticmethod
-    def do_task(task):
-        task['fcn'](*task['params'])
-        return
-
-    def add_task(self, target, params=list()):
-        self.queue.put({'fcn': target, 'params': params})
-        return
-
-    def join(self, timeout=None):
-        self.stoprequest.set()
-        super(Worker, self).join()

+ 0 - 249
FlatCAM_GTK/GUIElements.py

@@ -1,249 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-import re
-from copy import copy
-
-from gi.repository import Gtk
-
-from FlatCAM_GTK import FlatCAMApp
-
-
-class RadioSet(Gtk.Box):
-    def __init__(self, choices):
-        """
-        The choices are specified as a list of dictionaries containing:
-
-        * 'label': Shown in the UI
-        * 'value': The value returned is selected
-
-        :param choices: List of choices. See description.
-        :type choices: list
-        """
-        Gtk.Box.__init__(self)
-        self.choices = copy(choices)
-        self.group = None
-        for choice in self.choices:
-            if self.group is None:
-                choice['radio'] = Gtk.RadioButton.new_with_label(None, choice['label'])
-                self.group = choice['radio']
-            else:
-                choice['radio'] = Gtk.RadioButton.new_with_label_from_widget(self.group, choice['label'])
-            self.pack_start(choice['radio'], expand=True, fill=False, padding=2)
-            choice['radio'].connect('toggled', self.on_toggle)
-
-        self.group_toggle_fn = lambda x, y: None
-
-    def on_toggle(self, btn):
-        if btn.get_active():
-            self.group_toggle_fn(btn, self.get_value)
-        return
-
-    def get_value(self):
-        for choice in self.choices:
-            if choice['radio'].get_active():
-                return choice['value']
-        FlatCAMApp.App.log.error("No button was toggled in RadioSet.")
-        return None
-
-    def set_value(self, val):
-        for choice in self.choices:
-            if choice['value'] == val:
-                choice['radio'].set_active(True)
-                return
-        FlatCAMApp.App.log.error("Value given is not part of this RadioSet: %s" % str(val))
-
-
-class LengthEntry(Gtk.Entry):
-    """
-    A text entry that interprets its string as a
-    length, with or without specified units. When the user reads
-    the value, it is interpreted and replaced by a floating
-    point representation of the value in the default units. When
-    the entry is activated, its string is repalced by the interpreted
-    value.
-
-    Example:
-    Default units are 'IN', input is "1.0 mm", value returned
-    is 1.0/25.4 = 0.03937.
-    """
-
-    def __init__(self, output_units='IN'):
-        """
-
-        :param output_units: The default output units, 'IN' or 'MM'
-        :return: LengthEntry
-        """
-
-        Gtk.Entry.__init__(self)
-        self.output_units = output_units
-        self.format_re = re.compile(r"^([^\s]+)(?:\s([a-zA-Z]+))?$")
-
-        # Unit conversion table OUTPUT-INPUT
-        self.scales = {
-            'IN': {'IN': 1.0,
-                   'MM': 1/25.4},
-            'MM': {'IN': 25.4,
-                   'MM': 1.0}
-        }
-
-        self.connect('activate', self.on_activate)
-
-    def on_activate(self, *args):
-        """
-        Entry "activate" callback. Replaces the text in the
-        entry with the value returned by `get_value()`.
-
-        :param args: Ignored.
-        :return: None.
-        """
-        val = self.get_value()
-        if val is not None:
-            self.set_text(str(val))
-        else:
-            FlatCAMApp.App.log.warning("Could not interpret entry: %s" % self.get_text())
-
-    def get_value(self):
-        """
-        Fetches, interprets and returns the value in the entry. The text
-        is parsed to find the numerical expression and the (input) units (if any).
-        The numerical expression is interpreted and scaled acording to the
-        input and output units `self.output_units`.
-
-        :return: Floating point representation of the value in the entry.
-        :rtype: float
-        """
-
-        raw = self.get_text().strip(' ')
-        match = self.format_re.search(raw)
-        if not match:
-            return None
-        try:
-            if match.group(2) is not None and match.group(2).upper() in self.scales:
-                return float(eval(match.group(1)))*self.scales[self.output_units][match.group(2).upper()]
-            else:
-                return float(eval(match.group(1)))
-        except:
-            FlatCAMApp.App.log.warning("Could not parse value in entry: %s" % str(raw))
-            return None
-
-    def set_value(self, val):
-        self.set_text(str(val))
-
-
-class FloatEntry(Gtk.Entry):
-    def __init__(self):
-        Gtk.Entry.__init__(self)
-
-        self.connect('activate', self.on_activate)
-
-    def on_activate(self, *args):
-        val = self.get_value()
-        if val is not None:
-            self.set_text(str(val))
-        else:
-            FlatCAMApp.App.log.warning("Could not interpret entry: %s" % self.get_text())
-
-    def get_value(self):
-        raw = self.get_text().strip(' ')
-        try:
-            evaled = eval(raw)
-        except:
-            FlatCAMApp.App.log.error("Could not evaluate: %s" % str(raw))
-            return None
-
-        return float(evaled)
-
-    def set_value(self, val):
-        self.set_text(str(val))
-
-
-class IntEntry(Gtk.Entry):
-    def __init__(self):
-        Gtk.Entry.__init__(self)
-
-    def get_value(self):
-        return int(self.get_text())
-
-    def set_value(self, val):
-        self.set_text(str(val))
-
-
-class FCEntry(Gtk.Entry):
-    def __init__(self):
-        Gtk.Entry.__init__(self)
-
-    def get_value(self):
-        return self.get_text()
-
-    def set_value(self, val):
-        self.set_text(str(val))
-
-
-class EvalEntry(Gtk.Entry):
-    def __init__(self):
-        Gtk.Entry.__init__(self)
-
-    def on_activate(self, *args):
-        val = self.get_value()
-        if val is not None:
-            self.set_text(str(val))
-        else:
-            FlatCAMApp.App.log.warning("Could not interpret entry: %s" % self.get_text())
-
-    def get_value(self):
-        raw = self.get_text().strip(' ')
-        try:
-            return eval(raw)
-        except:
-            FlatCAMApp.App.log.error("Could not evaluate: %s" % str(raw))
-            return None
-
-    def set_value(self, val):
-        self.set_text(str(val))
-
-
-class FCCheckBox(Gtk.CheckButton):
-    def __init__(self, label=''):
-        Gtk.CheckButton.__init__(self, label=label)
-
-    def get_value(self):
-        return self.get_active()
-
-    def set_value(self, val):
-        self.set_active(val)
-
-
-
-
-class FCTextArea(Gtk.ScrolledWindow):
-    def __init__(self):
-        # Gtk.ScrolledWindow.__init__(self)
-        # FlatCAMApp.App.log.debug('Gtk.ScrolledWindow.__init__(self)')
-        super(FCTextArea, self).__init__()
-        FlatCAMApp.App.log.debug('super(FCTextArea, self).__init__()')
-        self.set_size_request(250, 100)
-        FlatCAMApp.App.log.debug('self.set_size_request(250, 100)')
-        textview = Gtk.TextView()
-        #print textview
-        #FlatCAMApp.App.log.debug('self.textview = Gtk.TextView()')
-        #self.textbuffer = self.textview.get_buffer()
-        #FlatCAMApp.App.log.debug('self.textbuffer = self.textview.get_buffer()')
-        #self.textbuffer.set_text("(Nothing here!)")
-        #FlatCAMApp.App.log.debug('self.textbuffer.set_text("(Nothing here!)")')
-        #self.add(self.textview)
-        #FlatCAMApp.App.log.debug('self.add(self.textview)')
-        #self.show()
-
-    def set_value(self, val):
-        #self.textbuffer.set_text(str(val))
-        return
-
-    def get_value(self):
-        #return self.textbuffer.get_text()
-        return ""

+ 0 - 261
FlatCAM_GTK/ObjectCollection.py

@@ -1,261 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 4/20/2014                                          #
-# MIT Licence                                              #
-############################################################
-
-import inspect  # TODO: Remove
-
-from gi.repository import Gtk, GdkPixbuf, GLib
-
-from FlatCAMObj import *
-from FlatCAM_GTK import FlatCAMApp
-
-
-class ObjectCollection:
-
-    classdict = {
-        "gerber": FlatCAMGerber,
-        "excellon": FlatCAMExcellon,
-        "cncjob": FlatCAMCNCjob,
-        "geometry": FlatCAMGeometry
-    }
-
-    icon_files = {
-        "gerber": "share/flatcam_icon16.png",
-        "excellon": "share/drill16.png",
-        "cncjob": "share/cnc16.png",
-        "geometry": "share/geometry16.png"
-    }
-
-    def __init__(self):
-
-        ### Icons for the list view
-        self.icons = {}
-        for kind in ObjectCollection.icon_files:
-            self.icons[kind] = GdkPixbuf.Pixbuf.new_from_file(ObjectCollection.icon_files[kind])
-
-        ### GUI List components
-        ## Model
-        self.store = Gtk.ListStore(FlatCAMObj)
-
-        ## View
-        self.view = Gtk.TreeView(model=self.store)
-        #self.view.connect("row_activated", self.on_row_activated)
-        self.tree_selection = self.view.get_selection()
-        self.change_subscription = self.tree_selection.connect("changed", self.on_list_selection_change)
-
-        ## Renderers
-        # Icon
-        renderer_pixbuf = Gtk.CellRendererPixbuf()
-        column_pixbuf = Gtk.TreeViewColumn("Type", renderer_pixbuf)
-
-        def _set_cell_icon(column, cell, model, it, data):
-            obj = model.get_value(it, 0)
-            cell.set_property('pixbuf', self.icons[obj.kind])
-
-        column_pixbuf.set_cell_data_func(renderer_pixbuf, _set_cell_icon)
-        self.view.append_column(column_pixbuf)
-
-        # Name
-        renderer_text = Gtk.CellRendererText()
-        column_text = Gtk.TreeViewColumn("Name", renderer_text)
-
-        def _set_cell_text(column, cell, model, it, data):
-            obj = model.get_value(it, 0)
-            cell.set_property('text', obj.options["name"])
-
-        column_text.set_cell_data_func(renderer_text, _set_cell_text)
-        self.view.append_column(column_text)
-
-    def print_list(self):
-        iterat = self.store.get_iter_first()
-        while iterat is not None:
-            obj = self.store[iterat][0]
-            print obj
-            iterat = self.store.iter_next(iterat)
-
-    def delete_all(self):
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_all()")
-        self.store.clear()
-
-    def delete_active(self):
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.delete_active()")
-        try:
-            model, treeiter = self.tree_selection.get_selected()
-            self.store.remove(treeiter)
-        except:
-            pass
-
-    def on_list_selection_change(self, selection):
-        """
-        Callback for change in selection on the objects' list.
-        Instructs the new selection to build the UI for its options.
-
-        :param selection: Ignored.
-        :return: None
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.on_list_selection_change()")
-
-        active = self.get_active()
-        active.build_ui()
-
-    def set_active(self, name):
-        """
-        Sets an object as the active object in the program. Same
-        as `set_list_selection()`.
-
-        :param name: Name of the object.
-        :type name: str
-        :return: None
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.set_active()")
-        self.set_list_selection(name)
-
-    def get_active(self):
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_active()")
-        try:
-            model, treeiter = self.tree_selection.get_selected()
-            return model[treeiter][0]
-        except (TypeError, ValueError):
-            return None
-
-    def set_list_selection(self, name):
-        """
-        Sets which object should be selected in the list.
-
-        :param name: Name of the object.
-        :rtype name: str
-        :return: None
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.set_list_selection()")
-        iterat = self.store.get_iter_first()
-        while iterat is not None and self.store[iterat][0].options["name"] != name:
-            iterat = self.store.iter_next(iterat)
-        self.tree_selection.select_iter(iterat)
-
-    def append(self, obj, active=False):
-        """
-        Add a FlatCAMObj the the collection. This method is thread-safe.
-
-        :param obj: FlatCAMObj to append
-        :type obj: FlatCAMObj
-        :param active: If it is to become the active object after appending
-        :type active: bool
-        :return: None
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.append()")
-
-        def guitask():
-            self.store.append([obj])
-            if active:
-                self.set_list_selection(obj.options["name"])
-        GLib.idle_add(guitask)
-
-    def get_names(self):
-        """
-        Gets a list of the names of all objects in the collection.
-
-        :return: List of names.
-        :rtype: list
-        """
-
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_names()")
-
-        names = []
-        iterat = self.store.get_iter_first()
-        while iterat is not None:
-            obj = self.store[iterat][0]
-            names.append(obj.options["name"])
-            iterat = self.store.iter_next(iterat)
-        return names
-
-    def get_bounds(self):
-        """
-        Finds coordinates bounding all objects in the collection.
-
-        :return: [xmin, ymin, xmax, ymax]
-        :rtype: list
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_bounds()")
-
-        # TODO: Move the operation out of here.
-
-        xmin = Inf
-        ymin = Inf
-        xmax = -Inf
-        ymax = -Inf
-
-        iterat = self.store.get_iter_first()
-        while iterat is not None:
-            obj = self.store[iterat][0]
-            try:
-                gxmin, gymin, gxmax, gymax = obj.bounds()
-                xmin = min([xmin, gxmin])
-                ymin = min([ymin, gymin])
-                xmax = max([xmax, gxmax])
-                ymax = max([ymax, gymax])
-            except:
-                FlatCAMApp.App.log.warning("DEV WARNING: Tried to get bounds of empty geometry.")
-            iterat = self.store.iter_next(iterat)
-        return [xmin, ymin, xmax, ymax]
-
-    def get_list(self):
-        """
-        Returns a list with all FlatCAMObj.
-
-        :return: List with all FlatCAMObj.
-        :rtype: list
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_list()")
-        collection_list = []
-        iterat = self.store.get_iter_first()
-        while iterat is not None:
-            obj = self.store[iterat][0]
-            collection_list.append(obj)
-            iterat = self.store.iter_next(iterat)
-        return collection_list
-
-    def get_by_name(self, name):
-        """
-        Fetches the FlatCAMObj with the given `name`.
-
-        :param name: The name of the object.
-        :type name: str
-        :return: The requested object or None if no such object.
-        :rtype: FlatCAMObj or None
-        """
-        FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + "--> OC.get_by_name()")
-
-        iterat = self.store.get_iter_first()
-        while iterat is not None:
-            obj = self.store[iterat][0]
-            if obj.options["name"] == name:
-                return obj
-            iterat = self.store.iter_next(iterat)
-        return None
-
-    # def change_name(self, old_name, new_name):
-    #     """
-    #     Changes the name of `FlatCAMObj` named `old_name` to `new_name`.
-    #
-    #     :param old_name: Name of the object to change.
-    #     :type old_name: str
-    #     :param new_name: New name.
-    #     :type new_name: str
-    #     :return: True if name change succeeded, False otherwise. Will fail
-    #        if no object with `old_name` is found.
-    #     :rtype: bool
-    #     """
-    #     print inspect.stack()[1][3], "--> OC.change_name()"
-    #     iterat = self.store.get_iter_first()
-    #     while iterat is not None:
-    #         obj = self.store[iterat][0]
-    #         if obj.options["name"] == old_name:
-    #             obj.options["name"] = new_name
-    #             self.store.row_changed(0, iterat)
-    #             return True
-    #         iterat = self.store.iter_next(iterat)
-    #     return False

+ 0 - 627
FlatCAM_GTK/ObjectUI.py

@@ -1,627 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-from gi.repository import Gtk
-
-from FlatCAM_GTK.GUIElements import *
-
-
-class ObjectUI(Gtk.VBox):
-    """
-    Base class for the UI of FlatCAM objects. Deriving classes should
-    put UI elements in ObjectUI.custom_box (Gtk.VBox).
-    """
-
-    def __init__(self, icon_file='share/flatcam_icon32.png', title='FlatCAM Object'):
-        Gtk.VBox.__init__(self, spacing=3, margin=5, vexpand=False)
-
-        ## Page Title box (spacing between children)
-        self.title_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 2)
-        self.pack_start(self.title_box, expand=False, fill=False, padding=2)
-
-        ## Page Title icon
-        self.icon = Gtk.Image.new_from_file(icon_file)
-        self.title_box.pack_start(self.icon, expand=False, fill=False, padding=2)
-
-        ## Title label
-        self.title_label = Gtk.Label()
-        self.title_label.set_markup("<b>" + title + "</b>")
-        self.title_label.set_justify(Gtk.Justification.CENTER)
-        self.title_box.pack_start(self.title_label, expand=False, fill=False, padding=2)
-
-        ## Object name
-        self.name_box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 2)
-        self.pack_start(self.name_box, expand=False, fill=False, padding=2)
-        name_label = Gtk.Label('Name:')
-        name_label.set_justify(Gtk.Justification.RIGHT)
-        self.name_box.pack_start(name_label,
-                                 expand=False, fill=False, padding=2)
-        self.name_entry = FCEntry()
-        self.name_box.pack_start(self.name_entry, expand=True, fill=False, padding=2)
-
-        ## Box box for custom widgets
-        self.custom_box = Gtk.VBox(spacing=3, margin=0, vexpand=False)
-        self.pack_start(self.custom_box, expand=False, fill=False, padding=0)
-
-        ## Common to all objects
-        ## Scale
-        self.scale_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.scale_label.set_markup('<b>Scale:</b>')
-        self.scale_label.set_tooltip_markup(
-            "Change the size of the object."
-        )
-        self.pack_start(self.scale_label, expand=False, fill=False, padding=2)
-
-        grid5 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid5, expand=False, fill=False, padding=2)
-
-        # Factor
-        l10 = Gtk.Label('Factor:', xalign=1)
-        l10.set_tooltip_markup(
-            "Factor by which to multiply\n"
-            "geometric features of this object."
-        )
-        grid5.attach(l10, 0, 0, 1, 1)
-        self.scale_entry = FloatEntry()
-        self.scale_entry.set_text("1.0")
-        grid5.attach(self.scale_entry, 1, 0, 1, 1)
-
-        # GO Button
-        self.scale_button = Gtk.Button(label='Scale')
-        self.scale_button.set_tooltip_markup(
-            "Perform scaling operation."
-        )
-        self.pack_start(self.scale_button, expand=False, fill=False, padding=2)
-
-        ## Offset
-        self.offset_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.offset_label.set_markup('<b>Offset:</b>')
-        self.offset_label.set_tooltip_markup(
-            "Change the position of this object."
-        )
-        self.pack_start(self.offset_label, expand=False, fill=False, padding=2)
-
-        grid6 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.pack_start(grid6, expand=False, fill=False, padding=2)
-
-        # Vector
-        l11 = Gtk.Label('Offset Vector:', xalign=1)
-        l11.set_tooltip_markup(
-            "Amount by which to move the object\n"
-            "in the x and y axes in (x, y) format."
-        )
-        grid6.attach(l11, 0, 0, 1, 1)
-        self.offsetvector_entry = EvalEntry()
-        self.offsetvector_entry.set_text("(0.0, 0.0)")
-        grid6.attach(self.offsetvector_entry, 1, 0, 1, 1)
-
-        self.offset_button = Gtk.Button(label='Scale')
-        self.offset_button.set_tooltip_markup(
-            "Perform the offset operation."
-        )
-        self.pack_start(self.offset_button, expand=False, fill=False, padding=2)
-
-    def set_field(self, name, value):
-        getattr(self, name).set_value(value)
-
-    def get_field(self, name):
-        return getattr(self, name).get_value()
-
-
-class CNCObjectUI(ObjectUI):
-    """
-    User interface for CNCJob objects.
-    """
-
-    def __init__(self):
-        ObjectUI.__init__(self, title='CNC Job Object', icon_file='share/cnc32.png')
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.custom_box.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid0, expand=False, fill=False, padding=2)
-
-        # Plot CB
-        self.plot_cb = FCCheckBox(label='Plot')
-        self.plot_cb.set_tooltip_markup(
-            "Plot (show) this object."
-        )
-        grid0.attach(self.plot_cb, 0, 0, 2, 1)
-
-        # Tool dia for plot
-        l1 = Gtk.Label('Tool dia:', xalign=1)
-        l1.set_tooltip_markup(
-            "Diameter of the tool to be\n"
-            "rendered in the plot."
-        )
-        grid0.attach(l1, 0, 1, 1, 1)
-        self.tooldia_entry = LengthEntry()
-        grid0.attach(self.tooldia_entry, 1, 1, 1, 1)
-
-        # Update plot button
-        self.updateplot_button = Gtk.Button(label='Update Plot')
-        self.updateplot_button.set_tooltip_markup(
-            "Update the plot."
-        )
-        self.custom_box.pack_start(self.updateplot_button, expand=False, fill=False, padding=2)
-
-        ## Export G-Code
-        self.export_gcode_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.export_gcode_label.set_markup("<b>Export G-Code:</b>")
-        self.export_gcode_label.set_tooltip_markup(
-            "Export and save G-Code to\n"
-            "make this object to a file."
-        )
-        self.custom_box.pack_start(self.export_gcode_label, expand=False, fill=False, padding=2)
-
-        # Append text to Gerber
-        l2 = Gtk.Label('Append to G-Code:')
-        l2.set_tooltip_markup(
-            "Type here any G-Code commands you would\n"
-            "like to append to the generated file.\n"
-            "I.e.: M2 (End of program)"
-        )
-        self.custom_box.pack_start(l2, expand=False, fill=False, padding=2)
-        #self.append_gtext = FCTextArea()
-        #self.custom_box.pack_start(self.append_gtext, expand=False, fill=False, padding=2)
-
-        # GO Button
-        self.export_gcode_button = Gtk.Button(label='Export G-Code')
-        self.export_gcode_button.set_tooltip_markup(
-            "Opens dialog to save G-Code\n"
-            "file."
-        )
-        self.custom_box.pack_start(self.export_gcode_button, expand=False, fill=False, padding=2)
-
-
-class GeometryObjectUI(ObjectUI):
-    """
-    User interface for Geometry objects.
-    """
-
-    def __init__(self):
-        ObjectUI.__init__(self, title='Geometry Object', icon_file='share/geometry32.png')
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.custom_box.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        # Plot CB
-        self.plot_cb = FCCheckBox(label='Plot')
-        self.plot_cb.set_tooltip_markup(
-            "Plot (show) this object."
-        )
-        grid0.attach(self.plot_cb, 0, 0, 1, 1)
-
-        ## Create CNC Job
-        self.cncjob_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.cncjob_label.set_markup('<b>Create CNC Job:</b>')
-        self.cncjob_label.set_tooltip_markup(
-            "Create a CNC Job object\n"
-            "tracing the contours of this\n"
-            "Geometry object."
-        )
-        self.custom_box.pack_start(self.cncjob_label, expand=True, fill=False, padding=2)
-
-        grid1 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid1, expand=True, fill=False, padding=2)
-
-        # Cut Z
-        l1 = Gtk.Label('Cut Z:', xalign=1)
-        l1.set_tooltip_markup(
-            "Cutting depth (negative)\n"
-            "below the copper surface."
-        )
-        grid1.attach(l1, 0, 0, 1, 1)
-        self.cutz_entry = LengthEntry()
-        grid1.attach(self.cutz_entry, 1, 0, 1, 1)
-
-        # Travel Z
-        l2 = Gtk.Label('Travel Z:', xalign=1)
-        l2.set_tooltip_markup(
-            "Height of the tool when\n"
-            "moving without cutting."
-        )
-        grid1.attach(l2, 0, 1, 1, 1)
-        self.travelz_entry = LengthEntry()
-        grid1.attach(self.travelz_entry, 1, 1, 1, 1)
-
-        l3 = Gtk.Label('Feed rate:', xalign=1)
-        l3.set_tooltip_markup(
-            "Cutting speed in the XY\n"
-            "plane in units per minute"
-        )
-        grid1.attach(l3, 0, 2, 1, 1)
-        self.cncfeedrate_entry = LengthEntry()
-        grid1.attach(self.cncfeedrate_entry, 1, 2, 1, 1)
-
-        l4 = Gtk.Label('Tool dia:', xalign=1)
-        l4.set_tooltip_markup(
-            "The diameter of the cutting\n"
-            "tool (just for display)."
-        )
-        grid1.attach(l4, 0, 3, 1, 1)
-        self.cnctooldia_entry = LengthEntry()
-        grid1.attach(self.cnctooldia_entry, 1, 3, 1, 1)
-
-        self.generate_cnc_button = Gtk.Button(label='Generate')
-        self.generate_cnc_button.set_tooltip_markup(
-            "Generate the CNC Job object."
-        )
-        self.custom_box.pack_start(self.generate_cnc_button, expand=True, fill=False, padding=2)
-
-        ## Paint Area
-        self.paint_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.paint_label.set_markup('<b>Paint Area:</b>')
-        self.paint_label.set_tooltip_markup(
-            "Creates tool paths to cover the\n"
-            "whole area of a polygon (remove\n"
-            "all copper). You will be asked\n"
-            "to click on the desired polygon."
-        )
-        self.custom_box.pack_start(self.paint_label, expand=True, fill=False, padding=2)
-
-        grid2 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid2, expand=True, fill=False, padding=2)
-
-        # Tool dia
-        l5 = Gtk.Label('Tool dia:', xalign=1)
-        l5.set_tooltip_markup(
-            "Diameter of the tool to\n"
-            "be used in the operation."
-        )
-        grid2.attach(l5, 0, 0, 1, 1)
-        self.painttooldia_entry = LengthEntry()
-        grid2.attach(self.painttooldia_entry, 1, 0, 1, 1)
-
-        # Overlap
-        l6 = Gtk.Label('Overlap:', xalign=1)
-        l6.set_tooltip_markup(
-            "How much (fraction) of the tool\n"
-            "width to overlap each tool pass."
-        )
-        grid2.attach(l6, 0, 1, 1, 1)
-        self.paintoverlap_entry = LengthEntry()
-        grid2.attach(self.paintoverlap_entry, 1, 1, 1, 1)
-
-        # Margin
-        l7 = Gtk.Label('Margin:', xalign=1)
-        l7.set_tooltip_markup(
-            "Distance by which to avoid\n"
-            "the edges of the polygon to\n"
-            "be painted."
-        )
-        grid2.attach(l7, 0, 2, 1, 1)
-        self.paintmargin_entry = LengthEntry()
-        grid2.attach(self.paintmargin_entry, 1, 2, 1, 1)
-
-        # GO Button
-        self.generate_paint_button = Gtk.Button(label='Generate')
-        self.generate_paint_button.set_tooltip_markup(
-            "After clicking here, click inside\n"
-            "the polygon you wish to be painted.\n"
-            "A new Geometry object with the tool\n"
-            "paths will be created."
-        )
-        self.custom_box.pack_start(self.generate_paint_button, expand=True, fill=False, padding=2)
-
-
-class ExcellonObjectUI(ObjectUI):
-    """
-    User interface for Excellon objects.
-    """
-
-    def __init__(self):
-        ObjectUI.__init__(self, title='Excellon Object', icon_file='share/drill32.png')
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.custom_box.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        self.plot_cb = FCCheckBox(label='Plot')
-        self.plot_cb.set_tooltip_markup(
-            "Plot (show) this object."
-        )
-        grid0.attach(self.plot_cb, 0, 0, 1, 1)
-
-        self.solid_cb = FCCheckBox(label='Solid')
-        self.solid_cb.set_tooltip_markup(
-            "Solid circles."
-        )
-        grid0.attach(self.solid_cb, 1, 0, 1, 1)
-
-        ## Create CNC Job
-        self.cncjob_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.cncjob_label.set_markup('<b>Create CNC Job</b>')
-        self.cncjob_label.set_tooltip_markup(
-            "Create a CNC Job object\n"
-            "for this drill object."
-        )
-        self.custom_box.pack_start(self.cncjob_label, expand=True, fill=False, padding=2)
-
-        grid1 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid1, expand=True, fill=False, padding=2)
-
-        l1 = Gtk.Label('Cut Z:', xalign=1)
-        l1.set_tooltip_markup(
-            "Drill depth (negative)\n"
-            "below the copper surface."
-        )
-        grid1.attach(l1, 0, 0, 1, 1)
-        self.cutz_entry = LengthEntry()
-        grid1.attach(self.cutz_entry, 1, 0, 1, 1)
-
-        l2 = Gtk.Label('Travel Z:', xalign=1)
-        l2.set_tooltip_markup(
-            "Tool height when travelling\n"
-            "across the XY plane."
-        )
-        grid1.attach(l2, 0, 1, 1, 1)
-        self.travelz_entry = LengthEntry()
-        grid1.attach(self.travelz_entry, 1, 1, 1, 1)
-
-        l3 = Gtk.Label('Feed rate:', xalign=1)
-        l3.set_tooltip_markup(
-            "Tool speed while drilling\n"
-            "(in units per minute)."
-        )
-        grid1.attach(l3, 0, 2, 1, 1)
-        self.feedrate_entry = LengthEntry()
-        grid1.attach(self.feedrate_entry, 1, 2, 1, 1)
-
-        l4 = Gtk.Label('Tools:', xalign=1)
-        l4.set_tooltip_markup(
-            "Which tools to include\n"
-            "in the CNC Job."
-        )
-        grid1.attach(l4, 0, 3, 1, 1)
-        boxt = Gtk.Box()
-        grid1.attach(boxt, 1, 3, 1, 1)
-        self.tools_entry = FCEntry()
-        boxt.pack_start(self.tools_entry, expand=True, fill=False, padding=2)
-        self.choose_tools_button = Gtk.Button(label='Choose...')
-        self.choose_tools_button.set_tooltip_markup(
-            "Choose the tools\n"
-            "from a list."
-        )
-        boxt.pack_start(self.choose_tools_button, expand=True, fill=False, padding=2)
-
-        self.generate_cnc_button = Gtk.Button(label='Generate')
-        self.generate_cnc_button.set_tooltip_markup(
-            "Generate the CNC Job."
-        )
-        self.custom_box.pack_start(self.generate_cnc_button, expand=True, fill=False, padding=2)
-
-
-class GerberObjectUI(ObjectUI):
-    """
-    User interface for Gerber objects.
-    """
-
-    def __init__(self):
-        ObjectUI.__init__(self, title='Gerber Object')
-
-        ## Plot options
-        self.plot_options_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.plot_options_label.set_markup("<b>Plot Options:</b>")
-        self.custom_box.pack_start(self.plot_options_label, expand=False, fill=True, padding=2)
-
-        grid0 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid0, expand=True, fill=False, padding=2)
-
-        # Plot CB
-        self.plot_cb = FCCheckBox(label='Plot')
-        self.plot_cb.set_tooltip_markup(
-            "Plot (show) this object."
-        )
-        grid0.attach(self.plot_cb, 0, 0, 1, 1)
-
-        # Solid CB
-        self.solid_cb = FCCheckBox(label='Solid')
-        self.solid_cb.set_tooltip_markup(
-            "Solid color polygons."
-        )
-        grid0.attach(self.solid_cb, 1, 0, 1, 1)
-
-        # Multicolored CB
-        self.multicolored_cb = FCCheckBox(label='Multicolored')
-        self.multicolored_cb.set_tooltip_markup(
-            "Draw polygons in different colors."
-        )
-        grid0.attach(self.multicolored_cb, 2, 0, 1, 1)
-
-        ## Isolation Routing
-        self.isolation_routing_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.isolation_routing_label.set_markup("<b>Isolation Routing:</b>")
-        self.isolation_routing_label.set_tooltip_markup(
-            "Create a Geometry object with\n"
-            "toolpaths to cut outside polygons."
-        )
-        self.custom_box.pack_start(self.isolation_routing_label, expand=True, fill=False, padding=2)
-
-        grid = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid, expand=True, fill=False, padding=2)
-
-        l1 = Gtk.Label('Tool diam:', xalign=1)
-        l1.set_tooltip_markup(
-            "Diameter of the cutting tool."
-        )
-        grid.attach(l1, 0, 0, 1, 1)
-        self.iso_tool_dia_entry = LengthEntry()
-        grid.attach(self.iso_tool_dia_entry, 1, 0, 1, 1)
-
-        l2 = Gtk.Label('Width (# passes):', xalign=1)
-        l2.set_tooltip_markup(
-            "Width of the isolation gap in\n"
-            "number (integer) of tool widths."
-        )
-        grid.attach(l2, 0, 1, 1, 1)
-        self.iso_width_entry = IntEntry()
-        grid.attach(self.iso_width_entry, 1, 1, 1, 1)
-
-        l3 = Gtk.Label('Pass overlap:', xalign=1)
-        l3.set_tooltip_markup(
-            "How much (fraction of tool width)\n"
-            "to overlap each pass."
-        )
-        grid.attach(l3, 0, 2, 1, 1)
-        self.iso_overlap_entry = FloatEntry()
-        grid.attach(self.iso_overlap_entry, 1, 2, 1, 1)
-
-        self.generate_iso_button = Gtk.Button(label='Generate Geometry')
-        self.generate_iso_button.set_tooltip_markup(
-            "Create the Geometry Object\n"
-            "for isolation routing."
-        )
-        self.custom_box.pack_start(self.generate_iso_button, expand=True, fill=False, padding=2)
-
-        ## Board cuttout
-        self.board_cutout_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.board_cutout_label.set_markup("<b>Board cutout:</b>")
-        self.board_cutout_label.set_tooltip_markup(
-            "Create toolpaths to cut around\n"
-            "the PCB and separate it from\n"
-            "the original board."
-        )
-        self.custom_box.pack_start(self.board_cutout_label, expand=True, fill=False, padding=2)
-
-        grid2 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid2, expand=True, fill=False, padding=2)
-
-        l4 = Gtk.Label('Tool dia:', xalign=1)
-        l4.set_tooltip_markup(
-            "Diameter of the cutting tool."
-        )
-        grid2.attach(l4, 0, 0, 1, 1)
-        self.cutout_tooldia_entry = LengthEntry()
-        grid2.attach(self.cutout_tooldia_entry, 1, 0, 1, 1)
-
-        l5 = Gtk.Label('Margin:', xalign=1)
-        l5.set_tooltip_markup(
-            "Distance from objects at which\n"
-            "to draw the cutout."
-        )
-        grid2.attach(l5, 0, 1, 1, 1)
-        self.cutout_margin_entry = LengthEntry()
-        grid2.attach(self.cutout_margin_entry, 1, 1, 1, 1)
-
-        l6 = Gtk.Label('Gap size:', xalign=1)
-        l6.set_tooltip_markup(
-            "Size of the gaps in the toolpath\n"
-            "that will remain to hold the\n"
-            "board in place."
-        )
-        grid2.attach(l6, 0, 2, 1, 1)
-        self.cutout_gap_entry = LengthEntry()
-        grid2.attach(self.cutout_gap_entry, 1, 2, 1, 1)
-
-        l7 = Gtk.Label('Gaps:', xalign=1)
-        l7.set_tooltip_markup(
-            "Where to place the gaps, Top/Bottom\n"
-            "Left/Rigt, or on all 4 sides."
-        )
-        grid2.attach(l7, 0, 3, 1, 1)
-        self.gaps_radio = RadioSet([{'label': '2 (T/B)', 'value': 'tb'},
-                                    {'label': '2 (L/R)', 'value': 'lr'},
-                                    {'label': '4', 'value': '4'}])
-        grid2.attach(self.gaps_radio, 1, 3, 1, 1)
-
-        self.generate_cutout_button = Gtk.Button(label='Generate Geometry')
-        self.generate_cutout_button.set_tooltip_markup(
-            "Generate the geometry for\n"
-            "the board cutout."
-        )
-        self.custom_box.pack_start(self.generate_cutout_button, expand=True, fill=False, padding=2)
-
-        ## Non-copper regions
-        self.noncopper_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.noncopper_label.set_markup("<b>Non-copper regions:</b>")
-        self.noncopper_label.set_tooltip_markup(
-            "Create polygons covering the\n"
-            "areas without copper on the PCB.\n"
-            "Equivalent to the inverse of this\n"
-            "object. Can be used to remove all\n"
-            "copper from a specified region."
-        )
-        self.custom_box.pack_start(self.noncopper_label, expand=True, fill=False, padding=2)
-
-        grid3 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid3, expand=True, fill=False, padding=2)
-
-        l8 = Gtk.Label('Boundary margin:', xalign=1)
-        l8.set_tooltip_markup(
-            "Specify the edge of the PCB\n"
-            "by drawing a box around all\n"
-            "objects with this minimum\n"
-            "distance."
-        )
-        grid3.attach(l8, 0, 0, 1, 1)
-        self.noncopper_margin_entry = LengthEntry()
-        grid3.attach(self.noncopper_margin_entry, 1, 0, 1, 1)
-
-        self.noncopper_rounded_cb = FCCheckBox(label="Rounded corners")
-        self.noncopper_rounded_cb.set_tooltip_markup(
-            "If the boundary of the board\n"
-            "is to have rounded corners\n"
-            "their radius is equal to the margin."
-        )
-        grid3.attach(self.noncopper_rounded_cb, 0, 1, 2, 1)
-
-        self.generate_noncopper_button = Gtk.Button(label='Generate Geometry')
-        self.generate_noncopper_button.set_tooltip_markup(
-            "Creates a Geometry objects with polygons\n"
-            "covering the copper-free areas of the PCB."
-        )
-        self.custom_box.pack_start(self.generate_noncopper_button, expand=True, fill=False, padding=2)
-
-        ## Bounding box
-        self.boundingbox_label = Gtk.Label(justify=Gtk.Justification.LEFT, xalign=0, margin_top=5)
-        self.boundingbox_label.set_markup('<b>Bounding Box:</b>')
-        self.boundingbox_label.set_tooltip_markup(
-            "Create a Geometry object with a rectangle\n"
-            "enclosing all polygons at a given distance."
-        )
-        self.custom_box.pack_start(self.boundingbox_label, expand=True, fill=False, padding=2)
-
-        grid4 = Gtk.Grid(column_spacing=3, row_spacing=2)
-        self.custom_box.pack_start(grid4, expand=True, fill=False, padding=2)
-
-        l9 = Gtk.Label('Boundary Margin:', xalign=1)
-        l9.set_tooltip_markup(
-            "Distance of the edges of the box\n"
-            "to the nearest polygon."
-        )
-        grid4.attach(l9, 0, 0, 1, 1)
-        self.bbmargin_entry = LengthEntry()
-        grid4.attach(self.bbmargin_entry, 1, 0, 1, 1)
-
-        self.bbrounded_cb = FCCheckBox(label="Rounded corners")
-        self.bbrounded_cb.set_tooltip_markup(
-            "If the bounding box is \n"
-            "to have rounded corners\n"
-            "their radius is equal to\n"
-            "the margin."
-        )
-        grid4.attach(self.bbrounded_cb, 0, 1, 2, 1)
-
-        self.generate_bb_button = Gtk.Button(label='Generate Geometry')
-        self.generate_bb_button.set_tooltip_markup(
-            "Genrate the Geometry object."
-        )
-        self.custom_box.pack_start(self.generate_bb_button, expand=True, fill=False, padding=2)

+ 0 - 318
FlatCAM_GTK/PlotCanvas.py

@@ -1,318 +0,0 @@
-############################################################
-# FlatCAM: 2D Post-processing for Manufacturing            #
-# http://caram.cl/software/flatcam                         #
-# Author: Juan Pablo Caram (c)                             #
-# Date: 2/5/2014                                           #
-# MIT Licence                                              #
-############################################################
-
-from gi.repository import Gdk
-from matplotlib.figure import Figure
-from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCanvas
-#from FlatCAMApp import *
-from FlatCAM_GTK import FlatCAMApp
-
-
-class PlotCanvas:
-    """
-    Class handling the plotting area in the application.
-    """
-
-    def __init__(self, container):
-        """
-        The constructor configures the Matplotlib figure that
-        will contain all plots, creates the base axes and connects
-        events to the plotting area.
-
-        :param container: The parent container in which to draw plots.
-        :rtype: PlotCanvas
-        """
-        # Options
-        self.x_margin = 15  # pixels
-        self.y_margin = 25  # Pixels
-
-        # Parent container
-        self.container = container
-
-        # Plots go onto a single matplotlib.figure
-        self.figure = Figure(dpi=50)  # TODO: dpi needed?
-        self.figure.patch.set_visible(False)
-
-        # These axes show the ticks and grid. No plotting done here.
-        # New axes must have a label, otherwise mpl returns an existing one.
-        self.axes = self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label="base", alpha=0.0)
-        self.axes.set_aspect(1)
-        self.axes.grid(True)
-
-        # The canvas is the top level container (Gtk.DrawingArea)
-        self.canvas = FigureCanvas(self.figure)
-        self.canvas.set_hexpand(1)
-        self.canvas.set_vexpand(1)
-        self.canvas.set_can_focus(True)  # For key press
-
-        # Attach to parent
-        self.container.attach(self.canvas, 0, 0, 600, 400)  # TODO: Height and width are num. columns??
-
-        # Events
-        self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
-        self.canvas.connect('configure-event', self.auto_adjust_axes)
-        self.canvas.add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK)
-        self.canvas.connect("scroll-event", self.on_scroll)
-        self.canvas.mpl_connect('key_press_event', self.on_key_down)
-        self.canvas.mpl_connect('key_release_event', self.on_key_up)
-
-        self.mouse = [0, 0]
-        self.key = None
-
-    def on_key_down(self, event):
-        """
-
-        :param event:
-        :return:
-        """
-        self.key = event.key
-
-    def on_key_up(self, event):
-        """
-
-        :param event:
-        :return:
-        """
-        self.key = None
-
-    def mpl_connect(self, event_name, callback):
-        """
-        Attach an event handler to the canvas through the Matplotlib interface.
-
-        :param event_name: Name of the event
-        :type event_name: str
-        :param callback: Function to call
-        :type callback: func
-        :return: Connection id
-        :rtype: int
-        """
-        return self.canvas.mpl_connect(event_name, callback)
-
-    def mpl_disconnect(self, cid):
-        """
-        Disconnect callback with the give id.
-        :param cid: Callback id.
-        :return: None
-        """
-        self.canvas.mpl_disconnect(cid)
-
-    def connect(self, event_name, callback):
-        """
-        Attach an event handler to the canvas through the native GTK interface.
-
-        :param event_name: Name of the event
-        :type event_name: str
-        :param callback: Function to call
-        :type callback: function
-        :return: Nothing
-        """
-        self.canvas.connect(event_name, callback)
-
-    def clear(self):
-        """
-        Clears axes and figure.
-
-        :return: None
-        """
-
-        # Clear
-        self.axes.cla()
-        try:
-            self.figure.clf()
-        except KeyError:
-            FlatCAMApp.App.log.warning("KeyError in MPL figure.clf()")
-
-        # Re-build
-        self.figure.add_axes(self.axes)
-        self.axes.set_aspect(1)
-        self.axes.grid(True)
-
-        # Re-draw
-        self.canvas.queue_draw()
-
-    def adjust_axes(self, xmin, ymin, xmax, ymax):
-        """
-        Adjusts all axes while maintaining the use of the whole canvas
-        and an aspect ratio to 1:1 between x and y axes. The parameters are an original
-        request that will be modified to fit these restrictions.
-
-        :param xmin: Requested minimum value for the X axis.
-        :type xmin: float
-        :param ymin: Requested minimum value for the Y axis.
-        :type ymin: float
-        :param xmax: Requested maximum value for the X axis.
-        :type xmax: float
-        :param ymax: Requested maximum value for the Y axis.
-        :type ymax: float
-        :return: None
-        """
-
-        FlatCAMApp.App.log.debug("PC.adjust_axes()")
-
-        width = xmax - xmin
-        height = ymax - ymin
-        try:
-            r = width / height
-        except ZeroDivisionError:
-            FlatCAMApp.App.log.error("Height is %f" % height)
-            return
-        canvas_w, canvas_h = self.canvas.get_width_height()
-        canvas_r = float(canvas_w) / canvas_h
-        x_ratio = float(self.x_margin) / canvas_w
-        y_ratio = float(self.y_margin) / canvas_h
-
-        if r > canvas_r:
-            ycenter = (ymin + ymax) / 2.0
-            newheight = height * r / canvas_r
-            ymin = ycenter - newheight / 2.0
-            ymax = ycenter + newheight / 2.0
-        else:
-            xcenter = (xmax + xmin) / 2.0
-            newwidth = width * canvas_r / r
-            xmin = xcenter - newwidth / 2.0
-            xmax = xcenter + newwidth / 2.0
-
-        # Adjust axes
-        for ax in self.figure.get_axes():
-            if ax._label != 'base':
-                ax.set_frame_on(False)  # No frame
-                ax.set_xticks([])  # No tick
-                ax.set_yticks([])  # No ticks
-                ax.patch.set_visible(False)  # No background
-                ax.set_aspect(1)
-            ax.set_xlim((xmin, xmax))
-            ax.set_ylim((ymin, ymax))
-            ax.set_position([x_ratio, y_ratio, 1 - 2 * x_ratio, 1 - 2 * y_ratio])
-
-        # Re-draw
-        self.canvas.queue_draw()
-
-    def auto_adjust_axes(self, *args):
-        """
-        Calls ``adjust_axes()`` using the extents of the base axes.
-
-        :rtype : None
-        :return: None
-        """
-
-        xmin, xmax = self.axes.get_xlim()
-        ymin, ymax = self.axes.get_ylim()
-        self.adjust_axes(xmin, ymin, xmax, ymax)
-
-    def zoom(self, factor, center=None):
-        """
-        Zooms the plot by factor around a given
-        center point. Takes care of re-drawing.
-
-        :param factor: Number by which to scale the plot.
-        :type factor: float
-        :param center: Coordinates [x, y] of the point around which to scale the plot.
-        :type center: list
-        :return: None
-        """
-
-        xmin, xmax = self.axes.get_xlim()
-        ymin, ymax = self.axes.get_ylim()
-        width = xmax - xmin
-        height = ymax - ymin
-
-        if center is None or center == [None, None]:
-            center = [(xmin + xmax) / 2.0, (ymin + ymax) / 2.0]
-
-        # For keeping the point at the pointer location
-        relx = (xmax - center[0]) / width
-        rely = (ymax - center[1]) / height
-
-        new_width = width / factor
-        new_height = height / factor
-
-        xmin = center[0] - new_width * (1 - relx)
-        xmax = center[0] + new_width * relx
-        ymin = center[1] - new_height * (1 - rely)
-        ymax = center[1] + new_height * rely
-
-        # Adjust axes
-        for ax in self.figure.get_axes():
-            ax.set_xlim((xmin, xmax))
-            ax.set_ylim((ymin, ymax))
-
-        # Re-draw
-        self.canvas.queue_draw()
-
-    def pan(self, x, y):
-        xmin, xmax = self.axes.get_xlim()
-        ymin, ymax = self.axes.get_ylim()
-        width = xmax - xmin
-        height = ymax - ymin
-
-        # Adjust axes
-        for ax in self.figure.get_axes():
-            ax.set_xlim((xmin + x*width, xmax + x*width))
-            ax.set_ylim((ymin + y*height, ymax + y*height))
-
-        # Re-draw
-        self.canvas.queue_draw()
-
-    def new_axes(self, name):
-        """
-        Creates and returns an Axes object attached to this object's Figure.
-
-        :param name: Unique label for the axes.
-        :return: Axes attached to the figure.
-        :rtype: Axes
-        """
-
-        return self.figure.add_axes([0.05, 0.05, 0.9, 0.9], label=name)
-
-    def on_scroll(self, canvas, event):
-        """
-        Scroll event handler.
-
-        :param canvas: The widget generating the event. Ignored.
-        :param event: Event object containing the event information.
-        :return: None
-        """
-
-        # So it can receive key presses
-        self.canvas.grab_focus()
-
-        # Event info
-        z, direction = event.get_scroll_direction()
-
-        if self.key is None:
-
-            if direction is Gdk.ScrollDirection.UP:
-                self.zoom(1.5, self.mouse)
-            else:
-                self.zoom(1/1.5, self.mouse)
-            return
-
-        if self.key == 'shift':
-
-            if direction is Gdk.ScrollDirection.UP:
-                self.pan(0.3, 0)
-            else:
-                self.pan(-0.3, 0)
-            return
-
-        if self.key == 'ctrl+control':
-
-            if direction is Gdk.ScrollDirection.UP:
-                self.pan(0, 0.3)
-            else:
-                self.pan(0, -0.3)
-            return
-
-    def on_mouse_move(self, event):
-        """
-        Mouse movement event hadler. Stores the coordinates.
-
-        :param event: Contains information about the event.
-        :return: None
-        """
-        self.mouse = [event.xdata, event.ydata]

+ 0 - 13
FlatCAM_GTK/setup_ubuntu.sh

@@ -1,13 +0,0 @@
-#!/bin/sh
-apt-get install libpng-dev
-apt-get install libfreetype6 libfreetype6-dev
-apt-get install python-dev
-apt-get install python-gi
-apt-get install libgtk-3-devel
-apt-get install python-numpy python-scipy python-matplotlib
-apt-get install libgeos-dev
-apt-get install python-shapely
-easy_install -U distribute
-apt-get install python-pip
-pip install --upgrade matplotlib
-pip install --upgrade Shapely