+ state = StringProperty("")
+
+ def __init__(self, key, **kwargs):
+ self.key = key
+
+ Machine(model=self, states=self.STATES,
+ transitions=self.TRANSITIONS, initial='initial',
+ ignore_invalid_triggers=True, queued=True)
+ super(KeyMachine, self).__init__(**kwargs)
+
+ # Machine states / events
+ def is_loaded_or_failed(self):
+ return self.is_loaded(allow_substates=True) or self.is_failed()
+
+ def is_loaded_inactive(self):
+ return self.is_loaded_no_config() or self.is_loaded_no_actions()
+
+ def on_enter_configuring(self):
+ if self.key.key_sym in self.key.parent.key_config:
+ self.key.config = self.key.parent.key_config[self.key.key_sym]
+
+ self.key.actions = []
+ for key_action in self.key.config['actions']:
+ self.key.add_action(key_action[0], **key_action[1])
+
+ if 'description' in self.key.config['properties']:
+ self.key.set_description(self.key.config['properties']['description'])
+ else:
+ self.key.unset_description()
+ if 'color' in self.key.config['properties']:
+ self.key.set_color(self.key.config['properties']['color'])
+ else:
+ self.key.unset_color()
+ self.success()
+ else:
+ self.no_config()
+
+ def on_enter_loading(self):
+ if len(self.key.actions) > 0:
+ for action in self.key.actions:
+ action.load()
+ else:
+ self.no_actions()
+
+ def run_actions(self, modifiers):
+ self.key.parent.parent.ids['KeyList'].append(self.key.key_sym)
+ debug_print("running actions for {}".format(self.key.key_sym))
+ start_time = time.time()
+ self.key.parent.start_running(self, start_time)
+ for self.key.current_action in self.key.actions:
+ if self.key.parent.keep_running(self, start_time):
+ self.key.list_actions()
+ self.key.current_action.run(start_time)
+ self.key.list_actions(last_action_finished=True)
+
+ self.key.parent.finished_running(self, start_time)
+
+ def on_enter_loaded_protecting_repeat(self, modifiers):
+ if 'repeat_delay' in self.key.config['properties']:
+ self.key.protecting_repeat_timer = threading.Timer(
+ self.key.config['properties']['repeat_delay'],
+ self.key.repeat_protection_finished)
+ self.key.protecting_repeat_timer.start()
+ else:
+ self.key.repeat_protection_finished()
+
+ # Callbacks
+ def key_loaded_callback(self):
+ self.key.parent.key_loaded_callback()
+
+
+class Key(ButtonBehavior, Widget):
+