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.