Removed legacy GTK files.
This commit is contained in:
@@ -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"))
|
||||
@@ -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()
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
@@ -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 ""
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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]
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user