diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 09fb699c..2de0f10f 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -19,23 +19,41 @@ 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): - if self.silence: - return + """ + 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) @@ -53,8 +71,6 @@ class FlatCAMObj(GObject.GObject, object): # The app should set this value. app = None - # name = GObject.property(type=str) - def __init__(self, name, ui): """ @@ -706,10 +722,15 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): 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) + def on_updateplot_button_click(self, *args): + self.read_form() + self.plot() + def on_exportgcode_button_click(self, *args): def on_success(app_obj, filename): f = open(filename, 'w') diff --git a/GUIElements.py b/GUIElements.py index d8b55ef1..c42cb452 100644 --- a/GUIElements.py +++ b/GUIElements.py @@ -58,20 +58,48 @@ class RadioSet(Gtk.Box): 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': {'MM': 1/25.4}, - 'MM': {'IN': 25.4} + '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)) @@ -79,17 +107,27 @@ class LengthEntry(Gtk.Entry): 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(match.group(1))*self.scales[self.output_units][match.group(2).upper()] + return float(eval(match.group(1)))*self.scales[self.output_units][match.group(2).upper()] else: - return float(match.group(1)) + return float(eval(match.group(1))) except: - FlatCAMApp.App.log.error("Could not parse value in entry: %s" % str(raw)) + FlatCAMApp.App.log.warning("Could not parse value in entry: %s" % str(raw)) return None def set_value(self, val): diff --git a/ObjectCollection.py b/ObjectCollection.py index 00674560..8a2d1406 100644 --- a/ObjectCollection.py +++ b/ObjectCollection.py @@ -195,7 +195,7 @@ class ObjectCollection: xmax = max([xmax, gxmax]) ymax = max([ymax, gymax]) except: - FlatCAMApp.App.log.waring("DEV WARNING: Tried to get bounds of empty geometry.") + FlatCAMApp.App.log.warning("DEV WARNING: Tried to get bounds of empty geometry.") iterat = self.store.iter_next(iterat) return [xmin, ymin, xmax, ymax]