# Click and drag on windows/compents that have scroll bars

**URL:** <https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492>\
**Category:** Ignition\
**Tags:** vision\
**Created:** [January 19, 2024, 10:33am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492 "2024-01-19T10:33:15Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rodrigo\_Domingues](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@Rodrigo\_Domingues](https://forum.inductiveautomation.com/u/Rodrigo_Domingues)\
**Post date:** [January 19, 2024, 10:33am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/1 "2024-01-19T10:33:15Z")

</div>

Hi,

Is it possible through scripting to use a click and drag feature to navigate through a window or object that has the hability scroll bars? I am using a template canvas object that enables/shows the scroll bars everytime the instances have x and y bigger than the size of the template canvas object. Instead of using scroll bars to search for my template instances, I would like to click and drag.  
Is it possible?

---

<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:** [January 19, 2024, 10:53am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/2 "2024-01-19T10:53:10Z")

</div>

This is possible, and I can imagine several ways to approach this with various degrees of complexity. The main question is where to consume the click event. Do you have components in your template that use mouse clicks? Can you share more about the nature of the components that are displayed in the canvas?

---

<div class="post-metadata">

**Author:** ![Rodrigo\_Domingues](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@Rodrigo\_Domingues](https://forum.inductiveautomation.com/u/Rodrigo_Domingues)\
**Post date:** [January 19, 2024, 11:14am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/3 "2024-01-19T11:14:21Z")

</div>

Yes. I have a transparent button with the same size as the whole template which has mouse and mouse motion events. The template canvas is in a root container that also has mouse and mouse motion events.

---

<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:** [January 19, 2024, 12:37pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/4 "2024-01-19T12:37:04Z")

</div>

> [@Rodrigo\_Domingues](#):
>
> I have a transparent button with the same size as the whole template which has mouse and mouse motion events

The transparent component is overlaying the template canvas or is it overlaying each template within the canvas? This is import an important distinction because the method for getting the scroll pane differs if it's a parent vs if it's a child.

Also, while this approach is perhaps simpler than adding your own listener(s) at run time, it will consume the mouse event, so in case I wasn't clear in my original question, if there are buttons or components underneath the overlay that need to be clicked, that functionality will break. Is this the case, or will the overlay approach work for your application?

> [@Rodrigo\_Domingues](#):
>
> The template canvas is in a root container that also has mouse and mouse motion events

This approach won't work because _(again)_ any inner swing component that is listening for a mouse event will consume the root container's mouse event.

---

<div class="post-metadata">

**Author:** ![Rodrigo\_Domingues](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@Rodrigo\_Domingues](https://forum.inductiveautomation.com/u/Rodrigo_Domingues)\
**Post date:** [January 19, 2024, 1:15pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/5 "2024-01-19T13:15:50Z")

</div>

It's overlaying each template within the canvas.

Answering to your 2nd question: No. I have a single button in my template, all the other objects are simply for visualization. And in that button I'm only using a 'property change event'

---

<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:** [January 19, 2024, 5:00pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/6 "2024-01-19T17:00:08Z")

</div>

I've developed a way to do this using your specified overlay component.  
**Here is the result:**  
 ![Screen Recording 2024-01-19 at 10.17.03 AM](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/5/355ea15ac8dbd3aaafaef3225f087b29b763c36d.gif)

**Here is the procedure:**  
First create project library scripts for locating the template Canvas's  
viewport and adjusting its position.  
In my project, I simply nested the functions under `componentScripts`:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/e/6e157832562de2b27315f02177aed1d9032bb3a3.png)

```auto
from javax.swing import SwingUtilities, JViewport
from java.awt import Point

# Function to get the parent viewPosition of a viewport of a given event
def getViewPosition(event):
	return SwingUtilities.getAncestorOfClass(JViewport, event.source).viewPosition
	
# Function to set the view postion during a mouse dragged event according to how far the mouse has moved from its initial position
def setViewPosition(event, x, y, initialMouseX, initialMouseY, initialViewX, initialViewY):
	'''
	Arguments:
		event: a mouse dragged event
		x, y: the calculated coordinates of the event
		...x and y are averaged to smooth out the mouse movemnents
		initialMouseX, initialMouseY: The position of the mouse pointer during the initial mousePressed event
		initioalViewX, initialViewY: the coordinates of the viewport during the initial mousePressed event
	'''
	# Get the parent viewport of the component the event originated from
	viewport = SwingUtilities.getAncestorOfClass(JViewport, event.source)
	
	# Calulate each coordinate by adding the difference between the current coordinate position and the initial coordinate position to the initial coordinate position
	# ...Make sure the new position is not out of bounds using max and min
	newX = max(0, min(initialViewX + (initialMouseX - x), viewport.view.width - viewport.viewRect.width))
	newY = max(0, min(initialViewY + (initialMouseY - y), viewport.view.height - viewport.viewRect.height))
	
	# Set the new view postion
	viewport.setViewPosition(Point(newX, newY))

```

Next, add the following custom properties the template overlay:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/c/8cf7eb8b003b0e305ad9add0409210b8aefbc8ad.png)

This script is needed on the overlay's mousePressed event to capture initial positions:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/3/e37153c944caa7c4f01a66da3d7be6d419c73b45.png)

```auto
# Capture and set the initial values of the mouse event on the overlay's custom properties
viewPosition = componentScripts.getViewPosition(event)
event.source.initialMouseX = event.x
event.source.initialMouseY = event.y
event.source.oldX = event.x
event.source.oldY = event.y
event.source.initialViewX = viewPosition.x
event.source.initialViewY = viewPosition.y

```

Finally, add this script to the overlay component's mouseDragged event handler:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/1/a146eb07c7d575cbafc7b86b902cae39d5771dcb.png)

```auto
# Calculate the event coordinates by averaging the current position and the previous position
# During initial testing, the scroll movements were jittery, but
# ...adding this smoothed the movements out
eventX = (event.x + event.source.oldX)/2
eventY = (event.y + event.source.oldY)/2

# Call the setViewPosition library script to move the viewport
componentScripts.setViewPosition(event, eventX, eventY, event.source.initialMouseX, event.source.initialMouseY, event.source.initialViewX, event.source.initialViewY)

# Update the oldX and oldY properties with this iterations averaged value
event.source.oldX = eventX
event.source.oldY = eventY

```

---

<div class="post-metadata">

**Author:** ![Rodrigo\_Domingues](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@Rodrigo\_Domingues](https://forum.inductiveautomation.com/u/Rodrigo_Domingues)\
**Post date:** [January 22, 2024, 9:23am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/7 "2024-01-22T09:23:44Z")

</div>

The code you provided me works perfectly!!! Thank you!  
Although I found a problem due to my application. Sometimes, my template canvas viewport doesn't have any of my template instances showing which is very difficult to click and drag. What do I need to do to have the same effect of click and drag but instead of needing a template instance, any point in the canvas would work

---

<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:** [January 22, 2024, 3:02pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/8 "2024-01-22T15:02:32Z")

</div>

> [@Rodrigo\_Domingues](#):
>
> Sometimes, my template canvas viewport doesn't have any of my template instances showing

There are so many ways to approach this, but it sounds like the overlay should be over the template canvas instead of over the templates in the canvas. If the overlay were moved to over the canvas and the overlay over the template was done away with, the only difference would be getting the viewport. This could be done with a library script or a custom method on the overlay itself.

Here is how the viewport could be obtained from using a custom method on the canvas overlay:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/d/7d199d93a03ecbda009e3698d61ab1bef628a743.png)

```auto
# def getViewportFromCanvas(self, canvas):
	for component in canvas.components:
		if component. __class__. __name__ == 'TemplateCanvas$1':
			return component.viewport

```

**To move the scrollbars:**  
On the `mousePressed` event:

```auto
# get the template canvas
canvas = event.source.parent.getComponent('Template Canvas')

# Capture and set the initial values of the mouse event on the overlay's custom properties
viewPosition = event.source.getViewportFromCanvas(canvas).viewPosition
event.source.initialMouseX = event.x
event.source.initialMouseY = event.y
event.source.oldX = event.x
event.source.oldY = event.y
event.source.initialViewX = viewPosition.x
event.source.initialViewY = viewPosition.y

```

On the `mouseDragged` event:

```auto
from java.awt import Point

# Get the canvas and its viewport
canvas = event.source.parent.getComponent('Template Canvas')
viewport = event.source.getViewportFromCanvas(canvas)

# Calculate the event coordinates by averaging the current position and the previous position
# During initial testing, the scroll movements were jittery, but
# ...adding this smoothed the movements out
eventX = (event.x + event.source.oldX)/2
eventY = (event.y + event.source.oldY)/2

# Calulate each coordinate by adding the difference between the current coordinate position and the initial coordinate position to the initial coordinate position
# ...Make sure the new position is not out of bounds using max and min
newX = max(0, min(event.source.initialViewX + (event.source.initialMouseX - eventX), viewport.view.width - viewport.viewRect.width))
newY = max(0, min(event.source.initialViewY + (event.source.initialMouseY - eventY), viewport.view.height - viewport.viewRect.height))

# Set the new view postion
viewport.setViewPosition(Point(newX, newY))

# Update the oldX and oldY properties with this iterations averaged value
event.source.oldX = eventX
event.source.oldY = eventY

```

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [January 22, 2024, 3:51pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/9 "2024-01-22T15:51:18Z")

</div>

what is the origin of those space ships 👀

---

<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:** [January 22, 2024, 3:56pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/10 "2024-01-22T15:56:22Z")

</div>

It was a demo I put together to showcase my [Component Spotlight](https://inductiveautomation.com/exchange/2566/overview) resource's ability to move scroll bars in order to spotlight components that are off screen.

> [@Introducing the Component Spotlight](https://forum.inductiveautomation.com/t/introducing-the-component-spotlight/80552):
>
> Description Simply drop [the template](https://inductiveautomation.com/exchange/2566/overview) anywhere in a window, and it will automatically populate with a list of every component within the window when the window is opened. [Screen Shot 2023-09-20 at 11.40.30 AM] Selecting a component from the dropdown will cause a spotlight to illuminate the component showing the user where it is in the window. [Component Spotlight Demo 01] If the component is nested in something with a scroll pane such as a template repeater or a template canvas, and the comp…

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 22, 2024, 4:11pm UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/11 "2024-01-22T16:11:48Z")

</div>

> [@victordcq](#):
>
> space ships

Pretty sure it's this one:

> **[Spaceship Size Comparison Updated! by Moreorlesser on DeviantArt](https://www.deviantart.com/moreorlesser/art/Spaceship-Size-Comparison-Updated-V22-903959442)**

---

<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:** [January 23, 2024, 7:02am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/12 "2024-01-23T07:02:53Z")

</div>

It's not that one.

The templates I used to create the ships were obtained from [this image:](https://www.breakoutcards.co.uk/vorcha-attack-cruiser---the-klingon-fleet---star-trek-fact-file-fold-out-page#gallery)

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/8/e809c6176ff3a11d46f7a87cdb4fadf37deed27d.jpeg)

Appropriately named path based vision shapes were used to autopopulate the dropdown with spotlightable components.

The space background is just some arbitrary image of space. The oversized image and canvas backgrounds were made transparent, and the space background was layered underneath. This is why when the ships move in the scroll pane, the movement is contrasted by the static space background.

It's a cool look. I liked the way it turned out:  
 ![Screen Recording 2024-01-19 at 10.17.03 AM](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/5/355ea15ac8dbd3aaafaef3225f087b29b763c36d.gif)

---

<div class="post-metadata">

**Author:** ![Rodrigo\_Domingues](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@Rodrigo\_Domingues](https://forum.inductiveautomation.com/u/Rodrigo_Domingues)\
**Post date:** [January 23, 2024, 8:42am UTC](https://forum.inductiveautomation.com/t/click-and-drag-on-windows-compents-that-have-scroll-bars/84492/13 "2024-01-23T08:42:29Z")

</div>

Both those ways work perfectly! Thank you so much for the trouble. You saved me quite some hours!
