Paintable canvas not translating negative values

So my conveyor belt canvas works good when I give it a positive angle but whenever I give it a negative angle to run by it won’t translate left to accommodate for the shift in positioning so it just gets cut off. I’m not sure if this is a bug in the system or an error in my code. I can’t seem to locate the error as everything makes sense logically as far as I can tell.

Also the calculations like angleCalc only need to be called when I change the template instance size so is there a way to store the values somehow so it only goes through the calculation the first time the client/page is opened and not when the color changes? Do custom methods already do this?

Repaint:

from java.lang import Math
from java.awt import Color
from java.awt import GradientPaint
from java.awt.geom import GeneralPath
from java.awt.geom import Rectangle2D
from java.awt.geom import Ellipse2D

g = event.graphics

'''
	Code Location
	
		Event Properties
			Width and Height Operator
		
		Initial Values
		
		Operators
			Back Color Conditional
			Indicator Color conditional
			Indicator Positions conditional
			
		Components
			Background
			Indicators
			Edges
			End Caps
			Direction
				
		Rotation and Translation
			
		Paint Shapes
			Paint Back and Indicators
			Paint Edges and Direction Triangle
			Paint end caps conditional
		
'''
#### Event Properties
#width = event.source.width
#height = event.source.height

Available = event.source.Available
Fault = event.source.Fault
FwdMOn = event.source.FwdMOn
RevMOn = event.source.RevMOn
MJog = event.source.MJog
MOff = event.source.MOff
On = event.source.On
Lcap = event.source.Lcap
Rcap = event.source.Rcap
angle = event.source.angleDegrees
left = event.source.Left
checkHeight = event.source.checkHeight

## Width and Height Operator
angleCalc = event.source.angleCalc(angle, event.source.width)
width = angleCalc[1]

#### Initial Values

if angle != 0:
	width = angleCalc[1]
backColor = Color(255, 255, 255)
indicatorColor = Color(153, 153, 153)
indLx = 0
indRx = width-10
#### Operators

## Back Color conditional
if Available == 0:
	backColor = Color(102, 102, 102)
elif Fault == 1:
	backColor = Color(250, 50, 50)
elif On == 1:
	backColor = Color(153, 153, 153)
	
## Indicator Color conditional
if Available == 0 and Fault ==1:
	indicatorColor = Color(250, 50, 50)
elif MJog == 1:
	indicatorColor = Color(255, 150, 0)
elif MOff == 1 or FwdMOn == 1 or RevMOn == 1:
	indicatorColor = Color(255, 245, 70)

## Indicator Positions conditional
if Lcap == 1:
	indLx = 4
if Rcap == 1:
	indRx = width-14

#### Components

## Background
back = Rectangle2D.Float(7,4, width-14,16)

## Indicators
indicatorL = event.source.Indicator(indLx)
indicatorR = event.source.Indicator(indRx)

## Edges
edgeT = event.source.Edge(0, width)
edgeB = event.source.Edge(16,width)

## End Caps
endL = event.source.EndCap(0)
endR = event.source.EndCap(width-4)

## Direction
direction = event.source.Direction(width, left)

#### Rotation and Translation
if angle != 0:
	g.translate(angleCalc[2], 0)
	g.rotate(Math.toRadians(angle), angleCalc[3], 0)
#### Paint Shapes

## Paint Back and Indicators
g.setColor(backColor)
g.fill(back)

g.setColor(indicatorColor)
g.fill(indicatorL)
g.fill(indicatorR)

## Paint Edges and Direction Triangle
g.setColor(Color(0, 0, 0))
g.fill(edgeT)
g.fill(edgeB)
g.fill(direction)

## Paint end caps conditional
if Lcap == 1:
	g.fill(endL)
if Rcap == 1:
	g.fill(endR)

## Draw Recommended Height Conditional
if checkHeight == 1:
	g.drawString(str(Math.round(angleCalc[0])), event.source.width/2, 35)

angleCalc:

def angleCalc(self, angle, width):
        from java.lang import Math
	"""
	Arguments:
		self: A reference to the component instance this method is invoked on. This argument
		  is automatic and should not be specified when invoking this method.
		angle: The angle that this operation will be running from.
		width: The width of the canvas.
	"""
	if angle == 0:
		Width = width
		height = 20
		translateX = 0
		pivotX = 0
	
	elif 45 >= angle > 0:
		rad = Math.toRadians(angle)
		sin = Math.sin(rad)
		cos = Math.cos(rad)
		tan = Math.tan(rad)
		
		Width = int(width/cos) - int(tan*20)
		height = int((tan*width)+(cos*20))
		translateX = int(sin*20)
		pivotX = 0
	
	elif -45 <= angle < 0:
		rad = Math.toRadians(Math.abs(angle))
		sin = Math.sin(rad)
		cos = Math.cos(rad)
		tan = Math.tan(rad)
		
		Width = int(width/cos) - int(tan*20)
		height = int((tan*width) + (cos*20))
		translateX = -int(sin*20)
		pivotX = width
	return [height, Width, translateX, pivotX]

Painting is complicated, for better or for worse. Are you sure about your coordinate system, scaling applied after, etc?
https://www.oracle.com/java/technologies/painting.html#callbacks

If you want to ‘cache’ an ephemeral value, you can use get or putClientProperty to store/retrieve arbitrary objects. They’ll be stored directly on your component instance (the paintable canvas in this case); since you’re sensitive to your component’s size, you might want to use the component dimensions as the cache key.

From what I can tell I am using the coordinate system correctly as the logic seems to fit but maybe switching up some code with similar functionality might work. I’ll check out your link on it and do some more research and testing. I didn’t use any scaling besides binding to the width.

So with the putClientProperty would I just put it in my angleCalc function as I define my values and call it in the repaint function using get?

Something like this where you current define angleCalc at the top of your code:

def getOrPut(angle, width):
	cached = event.source.getClientProperty((angle, width))
	if cached is not None:
		return cached
	else:
		newCalc = angleCalc(angle, width)
		event.source.putClientProperty((angle, width), newCalc)
		return newCalc

angleCalc = getOrPut(angle, event.source.width)

Okay I think I got it now. Thanks for your help.