Redefine the SelectTool cursor


#1

How to do this for a selec tool plugin?


#2

bump :slight_smile:


#3

What do you try to do? Just change the default cursor? Then you have to overwrite standardCursor()

def standardCursor(self):
    return self.myCursor

#4

Like instead of a mouse cursor pointer I want to use a small crosshair, how do I specify a PDF or asset for the cursor?


#5

Please check the documentation of NSCursor: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSCursor_Class/#//apple_ref/occ/instm/NSCursor/initWithImage:hotSpot:


#6

ah sorry i don’t know objective c… @Mark do you know how it’s done? :sweat_smile:


#7

If the standard system crosshair is enough, just return NSCursor.crosshairCursor.

If you want your own, then you don’t need to learn Objective C, you just need to read the Cocoa documentation and translate the ObjC method names into Python names (by changing : into _). So Georg pointed you at the NSCursor.initWithImage_hotSpot_ method; that requires you to pass in an NSImage. When reading the documentation for initWithImage:hotSpot: you can click on NSImage, which will take you to the NSImage documentation, and the first method on that page is initByReferencingFile:, or in Python terminology NSImage.initByReferencingFile_.

See if you can get the rest of the way from there. :slight_smile:


#8

@SimonC made a very good explanation. Nothing to add. Maybe just this: If you get a NameError, that any ‘NS…’ class is not defined, import it from AppKit.


#9

Hey thanks for your thorough explanation, this worked :slight_smile: :

def standardCursor(self):
    return NSCursor.crosshairCursor()

but if want to turn off the cursor I tried to return None, or pass but it didn’t work, any ideas?


#10

Maybe the method hide works? Note: »If another cursor becomes current, that cursor will be invisible, too. It will remain invisible until you invoke the unhide method.«


#11

Why you like to hide the cursor?


#12

Im creating a plugin that replaces the cursor with a circle, the circle is then used to measure a stroke. The mouse would get in the way sometimes :red_circle: :red_circle: :red_circle:


#13

Why not use the image of the circle as the cursor? You can dynamically change it.


#14

so using a vector image of a circle that is scaled? i have absolutely no idea how to do that and the documentation still doesn’t make sense… if i had some time i would try to learn some pyobjc… but not now unfortunately :frowning:


#15

You need to get an NSImage and use it to set up a cursor.

from Foundation import *
image = NSImage.alloc().initWithSize_(NSMakeSize(100, 100))
image.lockFocus()
rect = NSMakeRect(1, 1, 98, 98)
NSBezierPath.bezierPathWithOvalInRect_(rect).fill()
image.unlockFocus()
cursor = NSCursor.alloc().initWithImage_hotSpot_(image, NSMakePoint(50, 50))

#16

It doens’t work unfortunately?

Traceback (most recent call last):
  File "<string>", line 7, in <module>
TypeError: Expecting instance of NSCursor as self, got one of NSImage

#17

Sorry, add an .alloc() after NSCursor (updated the code above).


#18

thanks! so is the circles diameter actually 100? why does the rect start at 1,1 and is only 98 wide and high??


#19

I’m trying to make it scale according to the zoom but this doesn’t work:

	x, y = 100,100
	Scale = Glyphs.font.currentTab.scale

	try:
		circleCursorImage = NSImage.alloc().initWithSize_(NSMakeSize(x*Scale, y*Scale))
		circleCursorImage.lockFocus()
		rect = NSMakeRect(1, 1, x*Scale-2, y*Scale-2)
		circleCursorColor = 0.5, 0.5, 0.5, 0.9
		NSColor.colorWithCalibratedRed_green_blue_alpha_( *circleCursorColor ).set()
		NSBezierPath.bezierPathWithOvalInRect_(rect).fill()
		circleCursorImage.unlockFocus()
		circleCursor = NSCursor.alloc().initWithImage_hotSpot_(circleCursorImage, NSMakePoint(x/2*Scale, y/2*Scale))
	except Exception as e:
		self.logToConsole( "gaugeTooln circleCursorImage: %s" % str(e) )

it seems to have a problem with the line Scale = Glyphs.font.currentTab.scale ?


#20

You can change the size as you like. You might make the image one pixel bigger to not crop the gray pixels from the anti aliasing (thats why I made the circle 98 pt wide, I should have made the image 102 pt).

The scale works for me. Put it in a try/except block in case there is no open tab.