# Get Project Property 'Dock Axis Precedence' In Scripting

**URL:** <https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961>\
**Category:** Ignition\
**Tags:** vision, scripting, ignition80\
**Created:** [January 24, 2023, 11:59am UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961 "2023-01-24T11:59:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kevin\_Hens](https://avatars.discourse-cdn.com/v4/letter/k/53a042/32.png) [@Kevin\_Hens](https://forum.inductiveautomation.com/u/Kevin_Hens)\
**Post date:** [January 24, 2023, 11:59am UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/1 "2023-01-24T11:59:16Z")

</div>

Hi, for resizing purposes I would like to get the value of the 'Docking Axis Precedence' in the 'Project Properties'.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/8/68a8cea115c1b7232bd15cff999151dc98303494.png)

I found a topic where it was possible to found the project description using folowing code:  
_print(str(event.source.parent.getAppContext().getProject().getDescription()))_

Thanks in advance

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 24, 2023, 4:33pm UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/2 "2023-01-24T16:33:19Z")

</div>

This is probably a bad idea, and I would encourage you to not try to rely on specific information like this from the runtime when designing your windows. That said...

`print(str(event.source.parent.getAppContext().getPrimaryDesktop().getAxisPrecedence()))`

---

<div class="post-metadata">

**Author:** ![Kevin\_Hens](https://avatars.discourse-cdn.com/v4/letter/k/53a042/32.png) [@Kevin\_Hens](https://forum.inductiveautomation.com/u/Kevin_Hens)\
**Post date:** [January 25, 2023, 9:31am UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/3 "2023-01-25T09:31:47Z")

</div>

Thanks,

The reason I would like to use this is cause I use floating non maximized windows that I resize accordingly to be for instance a 'west overlay' that functions like an overlay (not cropping the main window) instead of a docked window that crops the main window. See screenshot:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/3/931ee0f02e0b42f072b208acdd17bc077466ecc0.png)

I've written some project scripting functions (getOverlayWidth, getOverlayHeight and getLeftTop ect.) to detirmine sizes and points in my framework. These functions depend on 2 ignition docked windows, a north and a west one with a dock index of -1. Whenever the client starts I open these windows: north with a height of 0 and west with a width of 0, so you dont actually see them. Afterwards I use those windows to determine the width (north docked window) and height (west docked window) of the actual client runtime.

In my example you can see that my dock axis precedence is set to 'North/South' so to determine my actual overlay width I take the width of my north docked window and subtract it with the width of all my other open east or west windows:

```auto
# Get west and east docks width
winDockEastWidth = 0
winDockWestWidth = 0
for window in system.gui.getOpenedWindows():
	if window.getComponentForPath('_parent').dockPosition == winDockLocationEast:
		winDockEastWidth = winDockEastWidth + window.width
	if window.getComponentForPath('_parent').dockPosition == winDockLocationWest:
		winDockWestWidth = winDockWestWidth + window.width

# Get overlay width
return system.gui.getWindow(winPathClientDockSizeWidth).width - winDockEastWidth - winDockWestWidth

```

Whenever for some reason somebody changes this axis precedence, there is no need to subtract the east nor west dock. Thats why I like to know the axis precedence.

Now I realize this is a tricky way of working around the Ignition Vision posibilities, and after testing I've also noticed that I get other values for the axis precedence in 'Designer Testing' (play button) gives me 'North / South' and the actual Ignition client gives me 'Â¿AxisPrecedence.NorthSouth?'. It stil give me north and south so I can get it out but this might change in future Ignition updates.

So, if you have a better solid option to get the actual client runtime width and height (red line A in the screenshot) so I don't need to use the trick with hidden docked windows that would make my day and probably be a better solution. I tried playing around with code I found at:  
[https://forum.inductiveautomation.com/t/how-to-get-vision-client-resolution/27328/4](https://forum.inductiveautomation.com/t/how-to-get-vision-client-resolution/27328/4).  
But this ends up in giving me the display resolution and not the actual client drawing resolution.

Next to this one more question. I got your solution working from a button, but how do i get to the getAppContext() from within project scripting?

Big thanks upfront already.

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [January 25, 2023, 12:10pm UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/4 "2023-01-25T12:10:36Z")

</div>

To get the client size. You will actaually want the root's contentPane, as the JFrame size includes the border.

I stuck this on a button, but it should work in the internalFrameActivated event as well.

```python
from javax.swing import SwingUtilities
component = event.source

# Get the root JFrame
root = SwingUtilities.getRoot(component)
JFrameSize = root.size
JFrameWidth = JFrameSize.width
JFrameHeight = JFrameSize.height

# Get the ContentPane (Inside the borders)
contentPane = root.getContentPane()
contentPaneSize = contentPane.size
contentPaneWidth = contentPaneSize.width
contentPaneHeight = contentPaneSize.height

print 'JFrame: {} x {}'.format(JFrameWidth, JFrameHeight)
print 'ContentPane: {} x {}'.format(contentPaneWidth, contentPaneHeight)

```

---

<div class="post-metadata">

**Author:** ![Kevin\_Hens](https://avatars.discourse-cdn.com/v4/letter/k/53a042/32.png) [@Kevin\_Hens](https://forum.inductiveautomation.com/u/Kevin_Hens)\
**Post date:** [January 25, 2023, 3:18pm UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/5 "2023-01-25T15:18:56Z")

</div>

Hi Jordan, thanks for the reply. It indeed works. Although I have still one problem.  
Whenever en update is available and the update message underneath the windows commands pops up, it doesn't change in height value. Which does work with using hidden windows. Is there a way to catch this?

Thanks

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [January 26, 2023, 11:11am UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/6 "2023-01-26T11:11:02Z")

</div>

No idea, as it doesn't change the dimensions of the root JFrame.

@paul-griffith, can we catch the project update message in a vision client?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 26, 2023, 4:15pm UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/7 "2023-01-26T16:15:38Z")

</div>

> [@Detect project update from client in notify mode](https://forum.inductiveautomation.com/t/detect-project-update-from-client-in-notify-mode/21424):
>
> Continuing the discussion from [Update Project Programmatically](http://forum.inductiveautomation.com/t/update-project-programmatically/11692/3): I just tried implementing @WillMT10’s solution to detect a newer project version ([System]Client/System/EditCount higher than it was when client was opened) in Ignition 7.9.9. It’s not working as it turns out this tag–at least in this version–reflects the edit count when client was opened/updated, not the edit count in available project update. Is there another way to detect from client scripting that a project update is available? …

Another option, if on 8.1.24, is to skip using our project update banner and provide your own (or disable it completely):

> [@Nightly 8.1 Changelogs - 2022](https://forum.inductiveautomation.com/t/nightly-8-1-changelogs-2022/54636/179):
>
> Weekly Changelog: 8.1.24-b20221214 Visualization 5835: Vision: Ability to detect when available and to trigger a project update Added a new Update Mode for vision: "None". This allows the project designer to handle delivering updates to running clients manually with the help of a new boolean Vision Client system tag named ProjectUpdateAvailable and a companion scripting function system.vision.updateProject() which will actually perform the project update on the Vision Client. 6861: Perspecti…

---

<div class="post-metadata">

**Author:** ![Kevin\_Hens](https://avatars.discourse-cdn.com/v4/letter/k/53a042/32.png) [@Kevin\_Hens](https://forum.inductiveautomation.com/u/Kevin_Hens)\
**Post date:** [March 2, 2023, 2:34pm UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/8 "2023-03-02T14:34:32Z")

</div>

Hi Jordan,

Turns out there is a way.

```auto
parent = event.source
while parent is not None:
	print "=============================="
	print parent
	print type(parent)
	# Get next parent
	parent = parent.parent

```

Ive put this on a button, which prints the entire graphical buildup until your object.

```auto
==============================
PMIButton: Print Parent Component Tree
<type 'com.inductiveautomation.factorypmi.application.components.PMIButton'>
==============================
Root Container
<type 'com.inductiveautomation.factorypmi.application.components.BasicContainer'>
==============================
javax.swing.JLayeredPane[null.layeredPane,0,0,1594x900,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,optimizedDrawingPossible=true]
<type 'javax.swing.JLayeredPane'>
==============================
javax.swing.JRootPane[,5,22,1594x900,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@11e69176,flags=449,maximumSize=,minimumSize=,preferredSize=]
<type 'javax.swing.JRootPane'>
==============================
winDevTestScreen
<type 'com.inductiveautomation.factorypmi.application.FPMIWindow'>
==============================
VisionApp[Airtec_PRODUCTION]
<type 'com.inductiveautomation.factorypmi.application.FPMIApp'>
==============================
javax.swing.JViewport[,1,1,1851x1028,invalid,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=java.awt.Point[x=0,y=0],scrollUnderway=false]
<type 'javax.swing.JViewport'>
==============================
javax.swing.JScrollPane[,0,0,1853x1030,invalid,layout=javax.swing.ScrollPaneLayout$UIResource,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@684ea065,flags=320,maximumSize=,minimumSize=,preferredSize=,columnHeader=,horizontalScrollBar=javax.swing.JScrollPane$ScrollBar[,1,1016,1851x13,hidden,layout=javax.swing.plaf.synth.SynthScrollBarUI,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@5c9f5ee0,flags=4194560,maximumSize=,minimumSize=,preferredSize=,blockIncrement=10,orientation=HORIZONTAL,unitIncrement=1],horizontalScrollBarPolicy=HORIZONTAL_SCROLLBAR_AS_NEEDED,lowerLeft=,lowerRight=,rowHeader=,upperLeft=,upperRight=,verticalScrollBar=javax.swing.JScrollPane$ScrollBar[,1839,1,13x1007,hidden,layout=javax.swing.plaf.synth.SynthScrollBarUI,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@2fb7cea2,flags=4194560,maximumSize=,minimumSize=,preferredSize=,blockIncrement=10,orientation=VERTICAL,unitIncrement=1],verticalScrollBarPolicy=VERTICAL_SCROLLBAR_AS_NEEDED,viewport=javax.swing.JViewport[,1,1,1851x1028,invalid,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=java.awt.Point[x=0,y=0],scrollUnderway=false],viewportBorder=javax.swing.plaf.synth.SynthScrollPaneUI$ViewportBorder@219ff1fb]
<type 'javax.swing.JScrollPane'>
==============================
com.inductiveautomation.factorypmi.application.runtime.ClientPanel[,0,27,1853x1030,invalid,layout=java.awt.BorderLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@409d49db,flags=9,maximumSize=,minimumSize=,preferredSize=]
<type 'com.inductiveautomation.factorypmi.application.runtime.ClientPanel'>
==============================
javax.swing.JLayeredPane[null.layeredPane,0,0,1853x1057,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,optimizedDrawingPossible=true]
<type 'javax.swing.JLayeredPane'>
==============================
javax.swing.JRootPane[,8,31,1853x1057,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@617f516c,flags=16777673,maximumSize=,minimumSize=,preferredSize=]
<type 'javax.swing.JRootPane'>
==============================
javax.swing.JFrame[frame1,59,-8,1869x1096,invalid,layout=java.awt.BorderLayout,title=Airtec_PRODUCTION - Development: Test Screen,resizable,maximized,defaultCloseOperation=DO_NOTHING_ON_CLOSE,rootPane=javax.swing.JRootPane[,8,31,1853x1057,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@617f516c,flags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
<type 'javax.swing.JFrame'>

```

Turns out that the \<type 'javax.swing.JViewport'\> gives the exact width and height without update notifications nor scrollbars.  
If you would like to include scrollbars, you can also use \<type 'javax.swing.JScrollPane'\>.

So to fetch these objects I use your script to go from the root back down to the viewport object as following.

```auto
from javax.swing import SwingUtilities
from javax.swing import JScrollPane

# Get component
component = event.source

# Get the root JFrame
root = SwingUtilities.getRoot(component)

# Get the ContentPane (Inside the borders)
contentPane = root.getContentPane()

# Get the inner viewport (Inside the borders and inside the scrollpane)
for component in contentPane.getComponents():	
	if type(component) == JScrollPane:
		viewport = component.getViewport()
		viewportSize = viewport.size
		viewportWidth = viewportSize.width
		viewportHeight = viewportSize.height
		print 'Viewport: {} x {}'.format(viewportWidth, viewportHeight)

```

Do you maybe know if its possible, and how to add some kind of listener to this object that triggers something when the size values change?

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [March 3, 2023, 2:29am UTC](https://forum.inductiveautomation.com/t/get-project-property-dock-axis-precedence-in-scripting/68961/9 "2023-03-03T02:29:16Z")

</div>

> [@Kevin\_Hens](#):
>
> how to add some kind of listener to this object that triggers something when the size values change

This can be done using the internalFrameOpened event handler of the parent window. Here is an example script:

```auto
from java.awt.event import ComponentAdapter
from javax.swing import JViewport
class ViewportSizeChangeListener(ComponentAdapter):
	def __init__ (self, viewport):
		self.viewport = viewport
	def componentResized(self, event):
		width = self.viewport.size.width
		height = self.viewport.size.height
		print 'Viewport size changed to %d x %d' % (width, height)
def getViewport(component):
	if component.componentCount > 0:
		for subComponent in component.getComponents():
			if isinstance(subComponent, JViewport):
				return subComponent
			else:
				viewport = getViewport(subComponent)
				if viewport is not None:
					return viewport
	return None
viewport = getViewport(event.source)
viewport.addComponentListener(ViewportSizeChangeListener(viewport))

```

Output during various popup window size changes:

```auto
Viewport size changed to 678 x 536
Viewport size changed to 881 x 681
Viewport size changed to 1087 x 840

```
