Component Scripting Window Default Size

If anybody is interested, I've also developed a way to apply this script automatically when the designer is opened, so there is no need to ever run the script from the script console.

To do this, simply package the code into a library script, and call it from a Vision client tag using the value changed event. For the client tag, I'm using the data type DateTime with the expression now(0). Since the polling rate is set to zero, the expression changes the value only once when the designer is first opened triggering the value changed event to apply the changes at that time.

Example:

#def valueChanged(tag, [...], missedEvents):
	# If this is the first event after initial subscription and if the event is in the designer environment,
	# ...patch the designer bug
	if initialChange and system.tag.readBlocking(['[System]Client/System/SystemFlags'])[0].value < 4:
		libraryScripts.setEditorPreferences()

Additionally, I'm now minimizing the property pane at the bottom of the editor, and I'm setting the default tab to the script editor tab instead of the navigation tab.

Here is an updated version of the library script
from java.awt import Toolkit, AWTEvent, Dimension
from java.awt.event import AWTEventListener
def setEditorPreferences(width = 1000, height = 600):
	'''
	• This function only works for the duration of the session it was called from [designer scope]
	• Fixes bug that pushes the ok, apply, and cancel buttons off the comppnent editor window in the designer
	• Sets the default size of the window to 1000 x 600, or the dimensions can be passed in when the function is called
	'''
	# RUN ONLY ONCE DURING A DESIGNER SESSION
	# ...prior to opening any script editors
	class WindowMonitor(AWTEventListener):
		def eventDispatched(self, event):
			if event.__class__.__name__ == 'WindowEvent' and event.ID == event.WINDOW_OPENED: 
				window = event.window
				if window.__class__.__name__ == 'ComponentScriptEditor': 
					# Fix the split pane divider and button off screen bug
					# ...by setting the right JPanel's minimum size to 0
					splitPane = self.getSplitPane(window)
					splitPane.rightComponent.minimumSize = Dimension(0,0)
					
					# Change the default tab from navigation to the script editor
					self.getTabbedPane(splitPane.rightComponent).selectedIndex = 4
					
					# Minimize the documentation pane at the bottom of the editor
					self.minimizeDocPane(window)
					
					# Specify a desired default window size and apply it
					windowSize = Dimension(width, height)
					window.preferredSize = windowSize
					window.size = windowSize
	    
	    # Recursively finds the highest level split pane within a given window
		def getSplitPane(self, window):
			for component in window.components:
				if component.__class__.__name__ == 'JSplitPane': 
					return component
				else:
					splitPane = self.getSplitPane(component)
					if splitPane:
						return self.getSplitPane(component) 
		
		# Locates the minimize button for the documentation pane, and fires its click logic
		def minimizeDocPane(self, window):
			for component in window.components:
			
				# There are three SynthSplitPaneDivider in a component editor,
				# ...but the documentation pane's is the only one is horizontal [wider that it is tall]
				if component.__class__.__name__ == 'SynthSplitPaneDivider' and component.width > component.height:
					rightButton = component.components[1] # The SynthSplitPaneDivider only contains two sub components: a left and right button
					rightButton.doClick()
					break
				else:
					self.minimizeDocPane(component)
		
		# Finds the tabbed pane and returns it
		def getTabbedPane(self, jpanel):
			for component in jpanel.components:
				if component.__class__.__name__ == 'JTabbedPane':
					return component
				else:
					tabbedPane = self.getTabbedPane(component)
					if tabbedPane:
						return tabbedPane

	# added logic to prevent multiple of the same listener from being inadvertently added
	toolkit = Toolkit.getDefaultToolkit()
	for proxy in toolkit.AWTEventListeners:
		if proxy.listener.__class__.__name__ == 'WindowMonitor':
			toolkit.removeAWTEventListener(proxy.listener)
	toolkit.addAWTEventListener(WindowMonitor(), AWTEvent.WINDOW_EVENT_MASK)

This has become a fun rabbit hole to explore because it opens the possibility of saving other user preferences that are currently not remembered by the designer such as column widths on the tag browser [which I've also already created a script for]. By adding parameters to the library scripts, these changes can be made user specific, and I can imagine using things like event.ID == event.WINDOW_CLOSED to save last used properties for the next use.

6 Likes