How to call method "copy:" of First Responder

Hello there, and greetings from Finland.

In my iTunes controller, I have added a way to copy track info to the clipboard by selecting Copy from Edit menu (Cmd+C). However, there’s also functionality to add lyrics to currently playing iTunes track. This pops up a simple panel with a text view, so user is able to edit lyrics (which are pulled from Safari’s highlighted via javascript) before saving them.

Here’s the thing: I need the standard copy functions to make possible copying text from the text view while editing. First I solved this by adding a second menu item for standard copy (“Copy Text”), but I didn’t like it because it used different shortcut (like Cmd+Opt+C) and I want the copying to behave like other Mac applications, so this is what I’m using right now:

on choose menu item theObject
-- other menu items here

-- this is called when user selects Copy from Edit menu (or hitting the shortcut):
if name of theObject is "copyTrackInfo" then -- the name "copyTrackInfo" was given before the menu item started to live secret double life
-- here we check the variable which defines if we should copy track info or selected text:
		if keyboardShortcutCopyText is false then
-- if false, get track info and send it to the clipboard:
			set theBox to box "b" of box "boxTrigger" of window "main"
			set myArtist to content of text field "artistField" of theBox
			set mySong to content of text field "songField" of theBox
			set the clipboard to (myArtist & " - " & mySong)
-- if true, call method to copy text:
			call method "copy:" of object (text view "lyricsField" of scroll view "lyricsView" of window "saveLyrics")
		end if
	end if

-- other menu items here
end choose menu item

keyboardShortcutCopyText is set to true when edit window opens, and set to false again when it closes. This is working (and I can use the familiar shortcut), but it’s restricted to this one and only text view.

I was wondering how to make First Responder to do the copying, so this would work with any selectable text (whenever that previously mentioned variable is set to true)?

I hope you got something out of this. Thanks in advance :slight_smile:

First responder does automatically handle this, there’s nothing for you to do. But you have to have the edit menu in your menu bar, because the edit menu has the copy menu item and the normal cmd-c keyboard shortcut. When you have some text highlighted it automatically responds as the first responder no matter which text field it’s in.

You can link your copy command (if you don’t want the standard edit menu) to first responder. Just open your menu, control-click and drag from your copy command to the first responder in your nib file. When you release the mouse a small window will pop-up, where you select the command you want to link to your menu item. Find the “copy” command, I forget exactly what it’s called but it contains copy, and select it.

You’ll see that there are a lot of things you can link directly to the first responder, not just copy. This method of linking saves writing a lot of code and adds a lot of functionality! Actually many of the items in your nib file can be linked to menu items or buttons in this way. Just try a few and see what you can link. Experiment! For example, to link the preferences window menu item to a preferences window, control-drag from the menu item to the preferences window in your nib and select “makeKeyAndOrderFront:”. Then your preferences window will auto-open when you select the menu item.

You can unlink 2 things at any time by looking at the “Connections” section of the inspector window.

Hope that helps!

Thanks for the reply, regulus6633! I made a workaroud for copying text. Instead of doing the copy methods directly in my script, I added a hidden button into the interface (and connected it to First Responder as you described in your post). This button gets clicked by the script and copying now works as I planned.

I’m really glad that works for you and that now you understand how to hook things up! That’s an innovative way to get it to work for your particular situation.

I’ve been thinking about what you want and there’s probably an easier way. I figured out how to get the selected text from a text view directly. Although your way works this may be easier. Try this…

set text_content to content of myTextView --> this gets all the text from the text view
set _selectedRange to call method "selectedRange" of myTextView --> this gets the range of the selection

-- then using those two you can get the selected text like this...
set text_selection to call method "substringWithRange:" of text_content with parameter _selectedRange

Maybe that will make it easier or maybe you’re happy with your solution, it’s up to you.