flatcam/FlatCAM_GTK/GUIElements.py

249 lines
7.5 KiB
Python

############################################################
# 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 ""