import adsk.core, adsk.fusion, adsk.cam, traceback import threading, time, json from datetime import datetime import ctypes handlers = [] _app = adsk.core.Application.cast(None) _ui = adsk.core.UserInterface.cast(None) _tableInput = adsk.core.TableCommandInput.cast(None) _cmdDef = adsk.core.CommandDefinition.cast(None) _workerThread = None myCustomEvent = 'MyDialogDataEvent' # The event handler that responds when the custom event is fired. class DialogDataEventHandler(adsk.core.CustomEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CustomEventArgs.cast(args) # Get the data passed through event. In this case it is # formatted as JSON so it extracts the values named # "label" and "value". dialogData = eventArgs.additionalInfo valueData = json.loads(dialogData) label = valueData['label'] value = valueData['value'] # Set the value of a string value input using the data passed in. stringInput = adsk.core.StringValueCommandInput.cast(_tableInput.getInputAtPosition(int(label), 1)) stringInput.value = value except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # The worker thread class. class GetDialogInfoThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.isStopped = False def run(self): try: # Iterate 5 steps to fill each of the 5 rows in the table. for i in range(5): # Check to see if the thread has been stopped. if not self.isStopped: # Simulate calling a web service that will take some # time and returns some data by sleeping and building # some data using the current time. time.sleep(2) date_object = datetime.now() current_time = date_object.strftime('%H:%M:%S') returnInfo = {'label': str(i), 'value': current_time} returnJson = json.dumps(returnInfo) # Fire the custom event to allow the add-in to update the dialog. _app.fireCustomEvent(myCustomEvent, returnJson) else: return except: ctypes.windll.user32.MessageBoxW(0, 'Failed:\n{}'.format(traceback.format_exc()), "Failed", 1) # Method to allow the thread to be stopped. def stop(self): self.isStopped = True # Event handler that is called when the add-in is destroyed. The custom event is # unregistered here and the thread is stopped. class MyDestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandEventArgs.cast(args) _app.unregisterCustomEvent(myCustomEvent) _workerThread.stop() except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # Event handler to handle when the command is run by the user. class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandCreatedEventArgs.cast(args) inputs = eventArgs.command.commandInputs # Create a table command input and add five rows of two columns of string # command inputs. The first column is populated with values and the # second is left empty to be populated later as the data is obtained. global _tableInput _tableInput = inputs.addTableCommandInput('table', 'Info', 2, '1:2') _tableInput.maximumVisibleRows = 5 for i in range(5): labelText = inputs.addStringValueInput('label' + str(i), 'Label ' + str(i), 'Item ' + str(i)) labelText.isReadOnly = True _tableInput.addCommandInput(labelText, i, 0, 0, 0) valueText = inputs.addStringValueInput('value' + str(i), 'Value ' + str(i), '') valueText.isReadOnly = True _tableInput.addCommandInput(valueText, i, 1, 0, 0) # Register the custom event and connect the handler. customEvent = _app.registerCustomEvent(myCustomEvent) onDialogData = DialogDataEventHandler() customEvent.add(onDialogData) handlers.append(onDialogData) # Connect a handler to the command destroyed event. onDestroy = MyDestroyHandler() inputs.command.destroy.add(onDestroy) handlers.append(onDestroy) # Start the seperate thread that will collect the data to populate # the second column of the dialog. global _workerThread _workerThread = GetDialogInfoThread() _workerThread.start() except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def run(context): try: global _app, _ui, _cmdDef _app = adsk.core.Application.get() _ui = _app.userInterface # Create a new command and add it to the ADD-INS panel in the model workspace. _cmdDef = _ui.commandDefinitions.addButtonDefinition('ThreadTestCmd', 'Thread Test', 'Thread Test') addInsPanel = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') buttonControl = addInsPanel.controls.addCommand(_cmdDef) # Connect the command created handler to the event. onCommandCreated = MyCommandCreatedHandler() _cmdDef.commandCreated.add(onCommandCreated) handlers.append(onCommandCreated) except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def stop(context): try: # Clean up the command. addInsPanel = _ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') cntrl = addInsPanel.controls.itemById('ThreadTestCmd') if cntrl: cntrl.deleteMe() if _cmdDef: _cmdDef.deleteMe() except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))