Getting font from font panel?

I’ve searched both here and through the AS Studio mailing list for an answer to this, so I’m hoping that someone who reads this has figured out a way to do this. I have gotten enough code to get and set a font for a text view via:

on setFont(fontString, theView)
	-- assumes font string is in the form "Monaco 14"
	set fontSize to (last word of fontString) as number
	set fontName to (words 1 thru ((count words of fontString) - 1) of fontString) as text
	set theFont to {fontName, fontSize}
	call method "setFont:" of theView with parameter (call method "fontWithName:size:" of class "NSFont" with parameters theFont)
end setFont

on getFont(theTextView)
	set theFont to call method "font" of theTextView
	set theFontName to call method "displayName" of theFont
	set thePointSize to call method "pointSize" of theFont
	-- returns font string in the form "Monaco 14"
	return (theFontName & " " & thePointSize as string)
end getFont

However, those don’t do me much good if I can’t select a font via the font panel, and it looks like that’s the situation. While the AS Studio Term. Ref. defines the font-panel class to have both an enabled and font properties, the simple command:

set theFont to font of font panel

generates the error:
<NSFontPanel 0x1896e00> valueForUndefinedKey:]: this class is not key value coding-compliant for the key font.

(Hang on, I’m getting to the questions…) While I understand that the ASS Term. Ref. defines font but then says it’s not available through ASS 1.4, how come I can get the font shoved into a variable using call method? And is there a way (via call method, perhaps) to get the current selected font in the font panel? I’ve cruised through the NSFontPanel class and don’t see any way to get it; the docs say that (in Cocoa) those messages are sent between the panel and the text view.

Um, ideas?

Model: 466mhz DA G4 tower (“Morpheus”) with 512mb
AppleScript: 1.10
Browser: Safari 2.0.4 (419.3)
Operating System: Mac OS X (10.4)

NSFontPanel piggy-backs on the NSFontManager class, where its shared instance is the object used to actually track font changes.

The AppKit NSFontManager docs recommend this for getting the current font (in Objective-C):

NSFontManager *fontManager = [NSFontManager sharedFontManager]; panelFont = [fontManager convertFont:[fontManager selectedFont]];
I imagine this can be translated into something like:

set fontManager to call method "sharedFontManager" of class "NSFontManager"
set theFont to call method "convertFont:" of fontManager with parameter (call method "selectedFont" of fontManager)

Thanks Qwerty, I’ll give that a try and post results back.

OK, we’re getting close, I feel. I tried your code as written and got an error on the second line:
Can’t make current application into type anything. (-1700)
Which in my experience is the equivalent of AS saying “what?” Realizing that sometimes call method calls don’t seem to nest very well, I broke the font selection code into another variable like this:

set fontManager to call method "sharedFontManager" of class "NSFontManager"
set fontSelection to call method "selectedFont" of fontManager
set theFont to call method "convertFont:" of fontManager with parameter (fontSelection)

Tracking the statements, it works up until the last one, then it gives new error message:
The variable fontSelection is not defined. (-2753)
So at that point, thinking that maybe it was getting a null result because I hadn’t had a chance to choose any fonts yet, I put the “convertFont” call within a try. end try block. I hoped that once I chose a font it would quit causing an error and return a value, but no dice.

I’m about out of ideas. Any ideas? What about (maybe) coding an Obj-c “add-on” and calling that. Do you think I’d get any different answer?

Yeah, I’m out of ideas too! You could try, as you say, adding a category like so:

In a file called NSFontPanel+SelectedFont.h:

[code]// NSFontPanel+SelectedFont.h
// Objective-C header.

#import <Cocoa/Cocoa.h>

@interface NSFontPanel (ASStudioSelectedFontFix)

  • (NSFont *)ASStudio_selectedFont;

@end[/code]
In a file called NSFontPanel+SelectedFont.m:

[code]// NSFontPanel+SelectedFont.m
// Objective-C implementation.

#import “NSFontPanel+SelectedFont.h”

@implementation NSFontPanel (ASStudioSelectedFontFix)

  • (NSFont *)ASStudio_selectedFont
    {
    return [self convertFont:[self selectedFont]]
    }

@end[/code]
Then in Studio, do something along the lines of:

set fontManager to call method "sharedFontManager" of class "NSFontManager"
set theFont to call method "ASStudio_selectedFont" of fontManager

Hopefully that should get closer!
Not that I necessarily want to encourage you to, but I moved to Cocoa because I found doing some things in AS Studio to be more complicated and limited than what the equivalent was in Cocoa.

Qwerty,

Thanks, I may give that a try. At this point I’m wondering if I need to supply the full font panel anyway. I’m thinking I only want to provide monospaced fonts anyway (for appearance sake) and may just make it a popup button and leave it at that, rather than try to force a square peg in a round hole.

I understand your comments re: Cocoa, I’ve begun thinking that way myself. For some reason I have a hard time getting my head around Obj-c’s structure, even though I’m fluent in C++ and C. (I think the brackets throw me off somehow). And while there are plenty of Cocoa tutorials out there, I wish I could find JUST an Obj-C reference or manual that gives me the whole language at a glance rather than a tutorial that limits me to what the tutorial application uses. Know of anything like that?

Studio, for me, is very seductive because, being very fluent in AS, it is very easy to throw together an interface and begin coding, but then I get into a bind (like this one) and regret starting the project in Studio.

Apple’s The Objective-C Programming Language is a reasonably thorough reference for Objective-C if you want something formal. The Objective-C syntax is quite simple, partially due to that the language is a strict-subset of C ” it is fully compatible with C, unlike C++.

(NB. I only knew the basics of C when I started, learning structs, pointers, what the stack was, unions as I went along, all of which is important in making Cocoa applications too. I don’t know C++ well at all.)

In order to make an application, you use the Cocoa framework. Cocoa is simply a name for two frameworks: Foundation, and AppKit, which are interfaced in Objective-C and some C.
Foundation is the ‘standard’ library, containing fundamental classes such as NSString, NSArray, NSDictionary, NSDate, NSData, and NSThread. It can be used to make command-line tools.
AppKit builds on Foundation, and is used for making GUI applications. It encompasses classes for windows views, mouse and key events, drawing, etc. This is basically what AppleScript Studio provides a wrapper around, so you might already know the interface to half these classes already!

You should definitely take a look at Cocoa fundamentals and memory management for getting started.
Xcode’s reference library and Apple’s developer website provides guides, sample code, and tech notes. (Some of which comes installed with Xcode).
Just as valuable is the CocoaDev wiki, Cocoa Builder mailing list archive, and other developers’ blogs and source code.