22#
33# SPDX-License-Identifier: MIT
44
5+ import os
56import json
67import time
78
4647 b"s" : "save" ,
4748 b"o" : "open" ,
4849 b"a" : "add" ,
50+ b"i" : "import" ,
4951 b"\x08 " : "remove" , # backspace
5052 b"\x1b [3~" : "remove" , # delete
5153}
7476# maximum number of connectors allowed on workspace
7577MAX_CONNECTORS = 5
7678
79+
7780class Workspace :
7881 """
7982 A scrollable area to place logic gates and other Entities. Handles interactions with the user
@@ -141,7 +144,8 @@ def __init__(self, neopixels, buttons, hotkeys=None):
141144 width = 26 ,
142145 height = 18 ,
143146 tile_width = 24 ,
144- tile_height = 24 )
147+ tile_height = 24 ,
148+ )
145149
146150 self .group .append (self .overlay_tilegrid )
147151
@@ -201,6 +205,7 @@ def __init__(self, neopixels, buttons, hotkeys=None):
201205 # variables for message control
202206 self .waiting_for_save_slot_input = False
203207 self .waiting_for_open_slot_input = False
208+ self .waiting_for_import_slot_input = False
204209 self .hide_message_at = None
205210
206211 def add_entity (self , entity ):
@@ -224,7 +229,7 @@ def remove_entity(self, entity):
224229
225230 # Special case for SignalTransmitter to clear its input wire tap overlay
226231 if isinstance (entity , SignalTransmitter ):
227- if isinstance (entity .input_entity ,Wire ):
232+ if isinstance (entity .input_entity , Wire ):
228233 self .overlay_tilegrid [entity .input_entity_location ] = EMPTY
229234
230235 def _set_mouse_moving_tiles (self , entity ):
@@ -249,8 +254,10 @@ def _clear_cursor(self):
249254 self .available_connectors .sort ()
250255 # Remove connections from SignalReceivers pointing to this SignalTransmitter
251256 for entity in self .entities :
252- if isinstance (entity , SignalReceiver ) and \
253- entity .connector_number == self .moving_entity .connector_number :
257+ if (
258+ isinstance (entity , SignalReceiver )
259+ and entity .connector_number == self .moving_entity .connector_number
260+ ):
254261
255262 entity .connector_number = None
256263 entity .input_one = None
@@ -364,6 +371,7 @@ def handle_key_press(self, key_bytes, mouse_x, mouse_y):
364371 Handle keyboard key press events sent from code.py.
365372 Also receives the current mouse location.
366373 """
374+ # pylint: disable=too-many-locals
367375
368376 # if we're waiting for user to input the save slot number
369377 if self .waiting_for_save_slot_input :
@@ -410,6 +418,35 @@ def handle_key_press(self, key_bytes, mouse_x, mouse_y):
410418 self .waiting_for_open_slot_input = False
411419 return
412420
421+ # if we're waiting for user to input the import slot number
422+ if self .waiting_for_import_slot_input :
423+ # convert keypress to string
424+ key_str = key_bytes .decode ("utf-8" )
425+ # if the entered value is a valid save slot 0-9
426+ if key_str in VALID_SAVE_SLOTS :
427+ # update the message to the user with the value they typed
428+ self .message_lbl .text += key_str
429+ if "logic_gates_import.json" in os .listdir ("/" ):
430+ with open ("/logic_gates_import.json" , "r" ) as f :
431+ import_data = f .read ()
432+ # write JSON data to the save file with slot number in filename
433+ with open (f"/saves/logic_gates_{ key_str } .json" , "w" ) as f :
434+ f .write (import_data )
435+ # update the message to user with save success
436+ self .message_lbl .text = f"Imported to slot: { key_str } "
437+ # set the time to hide the message to user
438+ self .hide_message_at = time .monotonic () + 2.0
439+ # set flag back to not waiting for import slot input
440+ self .waiting_for_import_slot_input = False
441+ else :
442+ self .message_lbl .text = "logic_gates_import.json not found"
443+ # set the time to hide the message to user
444+ self .hide_message_at = time .monotonic () + 2.0
445+ # set flag back to not waiting for import slot input
446+ self .waiting_for_import_slot_input = False
447+
448+ return
449+
413450 # lookup the pressed key int he hotkey map
414451 action = self .hotkeys .get (key_bytes , None )
415452 # if the pressed key doesn't map to any actions
@@ -452,6 +489,13 @@ def handle_key_press(self, key_bytes, mouse_x, mouse_y):
452489 # keep message showing until user responds
453490 self .hide_message_at = None
454491
492+ # import action, ask user for slot to import to
493+ elif action == "import" :
494+ self .waiting_for_import_slot_input = True
495+ self .message_lbl .text = "Import To Slot: "
496+ # keep message showing until user responds
497+ self .hide_message_at = None
498+
455499 # add action, show the ToolBox to select a new entity to add
456500 elif action == "add" :
457501 if self .moving_entity is None :
@@ -481,7 +525,9 @@ def handle_key_press(self, key_bytes, mouse_x, mouse_y):
481525 target_entity = self .entity_at ((tile_x , tile_y ))
482526
483527 # special case only limited number of SignalTransmitters
484- if target_entity is not None and isinstance (target_entity , SignalTransmitter ):
528+ if target_entity is not None and isinstance (
529+ target_entity , SignalTransmitter
530+ ):
485531 num_SignalTransmitters = 0
486532 for entity in self .entities :
487533 if isinstance (entity , SignalTransmitter ):
@@ -583,13 +629,17 @@ def create_entity_from_json(self, entity_json, add_to_workspace=True):
583629 location , self , entity_json ["state" ], add_to_workspace = add_to_workspace
584630 )
585631 # special case Connectors need the connector number
586- elif entity_json ["class" ] == "SignalReceiver" or \
587- entity_json ["class" ] == "SignalTransmitter" :
632+ elif (
633+ entity_json ["class" ] == "SignalReceiver"
634+ or entity_json ["class" ] == "SignalTransmitter"
635+ ):
588636
589637 if entity_json .get ("connector_number" ) is not None :
590638 new_entity = ENTITY_CLASS_CONSTRUCTOR_MAP [entity_json ["class" ]](
591- location , self , entity_json ["connector_number" ],
592- add_to_workspace = add_to_workspace
639+ location ,
640+ self ,
641+ entity_json ["connector_number" ],
642+ add_to_workspace = add_to_workspace ,
593643 )
594644 else :
595645 new_entity = ENTITY_CLASS_CONSTRUCTOR_MAP [entity_json ["class" ]](
@@ -629,13 +679,15 @@ def load_from_json(self, json_data):
629679
630680 # Connect any connectors
631681 for entity in self .entities :
632- if isinstance (entity ,SignalTransmitter ):
682+ if isinstance (entity , SignalTransmitter ):
633683 if entity .connector_number in self .available_connectors :
634684 self .available_connectors .remove (entity .connector_number )
635685 for entity_in in self .entities :
636- if isinstance (entity_in ,SignalReceiver ) and \
637- entity_in .connector_number is not None and \
638- entity .connector_number == entity_in .connector_number :
686+ if (
687+ isinstance (entity_in , SignalReceiver )
688+ and entity_in .connector_number is not None
689+ and entity .connector_number == entity_in .connector_number
690+ ):
639691
640692 entity_in .input_one = entity
641693
0 commit comments