Rollovers - Need For Speeeeeeeeeeeeed!

Hi All,

I have a number of rollovers in a custom graphic interface. Everything works fine except they are a little laggy (especially if you run the mouse over multiple buttons).

Here is how my code looks (the example has just one of the buttons, I have about 12 total):


------------------------------------------------------------------------------------
-- On Mouse Entered --
------------------------------------------------------------------------------------
		if name of theObject is "OK_BUTTON" then
			play (some item of KEY_SOUNDS)
			set visible of image view "ROLLOVER_OK" of window "MAIN" to true
			set position of image view "ACTIVE_ARROW" of window "MAIN" to {252, 47}
		else
			set visible of image view "ROLLOVER_OK" of window "MAIN" to false
		end if
------------------------------------------------------------------------------------
-- On Mouse Exited --
------------------------------------------------------------------------------------
		if name of theObject is "OK_BUTTON" then set visible of image view "ROLLOVER_OK" of window "MAIN" to false

Is there a better way to handle this? Obj-C?

CarbonQuark

Yes, this is something better-suited to Cocoa.

Are you just trying to change the image of a button? I can’t really tell what you’re trying to do. What is the purpose of hiding/unhiding an image view?

Hi Mikey,

I have a base graphic that fills the entire main window. This base graphic contains all the custom user interface elements including all the custom buttons in their inactive state in one flat graphic. When a users rolls over one of the base graphic buttons the code is unhiding a small active (rollover) graphic in an image view that pertains to that button. I have a transparent IB button over top of the base graphic to act as the “real” button. I hope this makes sense.

Thanks,
CarbonQuark

Mikey, BTW I am not that familiar with Cocoa/Obj-C. I want to learn. I have been reading up on Cocoa/Obj-C and it might be awhile before I understand it enough to actual apply it. Thanks, CarbonQuark

Why are you faking your interface with transparent controls? Is it some kind of game? More details, please.

Your speed problem:

  1. You’re using AppleScript. (I’m not crapping on AS, but that’s one of your bottlenecks right now. It just ain’t built for speeeeeed.)
  2. You’re redrawing the entire view every time you enter the tracking rect, and redrawing it again when you exit. Futhermore, you have to wait for the redraw before the next redraw.

Hi Mikey,

It’s not a game. However, the interface needs to be custom (the standard look of the buttons and controls that Apple provides won’t work). One note, when a user rolls over a button the code unhides a rollover graphic that is only the size of that button (I don’t have the entire background changing).

If I was using Obj-C to perform this, would the redraw wait still be as laggy?

Thanks,
CarbonQuark

Just change the image of the button.

You should run Quartz Debug to see what parts of the screen are being redrawn. You may not be telling the entire background to redraw, but maybe you’re doing something that’s making it happen. Rule it out.

Your speed problems are probably just AppleScript, if you’re not redrawing the entire background.

Edit for future searchers: See NSButton subclass below, and my note below it. This is how it’s done.

Thanks Mikey… I will check out this option. CarbonQuark

Hi Carbon,

sorry for answering late … if your buttons don’t need a third state (mouse out, over and down) then you can use this simple NSButton subclass to make the buttons show their alternate image (as set in Interface Builder - set behaviour ‘momentary change’) on mouseover:

MyRolloverButton.h:

#import <Cocoa/Cocoa.h> @interface MyRolloverButton : NSButton{} @end
MyRolloverButton.m:

[code]#import “MyRolloverButton.h”

@implementation MyRolloverButton
-(void)awakeFromNib{
[self addTrackingRect:[self bounds]
owner:self
userData:nil
assumeInside:NO];
}

  • (void)mouseEntered:(NSEvent *)theEvent{
    [self highlight:YES];
    }

  • (void)mouseExited:(NSEvent *)theEvent{
    [self highlight:NO];
    }
    @end[/code]
    Dominik

Hi Dominik,

Thanks for the help. I made my best attempt to get your suggestion to work. Unfortunatly, I am lost at the moment at implementing a custom subclass. I am still learning just the basics of Obj-C. I’m not sure how to get all the conections hooked up.

Thanks,
CarbonQuark

It’s usually considered better to implement -[NSView viewDidMoveToSuperview] and add the tracking rect there instead of -awakeFromNib (or -initWithFrame:).

Hi Carbon,

if you already have added the subclass files to your Xcode project - then …

  1. drag&drop the subclasses .h file on the document window of your nib in Interface Builder
  2. select the button you want to become a rollover button
  3. select ‘custom class’ of Interface Builder’s Inspector (or hit Apple+5) and select our new subclass
  4. add the two images as ‘icon’ & ‘alt icon’ and set behaviour to ‘momentary change’

repeat steps 2-4 for every rollover button

or if you haven’t added the code:

  1. select the classes tab of the document window in IB and select a button - you’ll see ‘NSButton’
  2. Ctrl-Click or Rightmousebutton click on NSButton and select ‘Subclass’ from it’s context menu - name the new class MyRolloverButton (for example)
  3. Crtl-Click on the new Subclass and select ‘Create files’
  4. proceed with steps 2-4 of the above description
  5. edit the subclass files in Xcode

D.

Dominik,

Thanks for spelling it out for me… I’m almost there.

How do I do this:

CarbonQuark

Dominik,

How do I add the following Applescript code as Obj-C to the “- (void)mouseEntered:(NSEvent *)theEvent{” in the .m file (syntax).


 play (some item of KEY_SOUNDS)

KEY_SOUNDS is a list of 5 sounds. A random sound from this list needs to play on mouseEntered.

Thanks,
CarbonQuark

Dominik,

NEVERMIND the following:

I have it working now. Thanks so much for your help. CarbonQuark

If your audio files are AIFF, WAV, or NeXT audio, you can use NSSound to initialize and play them:

http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSSound_Class/index.html

You should not have your button play the sounds, however, because that requires you to initialize an instance of each sound for each button, which is a waste of memory (unless each button has a unique sound pool, but even then, it might be a bit of a MVC violation).

What you might consider doing is initializing your five random sounds when your application controller awakens. Add them to an NSArray so you can pick one later. Have the button call back to your controller to play a random sound when -mouseEntered: is triggered.

Dominik,

Now that my rollover buttons use the new subclass they don’t seem to be connecting to my Applescript via “mouse entered” and “mouse exited” to run my other tasks (see below). It seems that the code "[self addTrackingRect:[self bounds] " might be keeping the button from connecting to my Applescript. Any thoughts?

CarbonQuark


		if name of theObject is "BUTTON_1" then
			set position of image view "ACTIVE_ARROW" of window "MAIN" to {9, 47}
			if SOUNDS_SWITCH is 1 then play (some item of KEY_SOUNDS)
		end if

Mikey-San,

They are .aiff files. I will checkout the link.

Thanks for the info!

CarbonQuark

I would not be surprised if overriding -mouseEntered: and -mouseExited: prevents passing of the events to AppleScript connections. Normally, the two methods don’t do anything at all, but perhaps when you attach the AppleScript hooks, actions are added. Therefore, you may need to pass the NSEvent back to the superclass to get the AppleScript side to trigger. Try doing this:

[code]- (void)mouseEntered:(NSEvent *)theEvent{
[self highlight:YES];
[super mouseEntered];
}

  • (void)mouseExited:(NSEvent *)theEvent{
    [self highlight:NO];
    [super mouseExited];
    }[/code]
    This is just a guess, however, as I have never been in a situation where I’ve needed to handle this.

Edit: Or you could always dive further and reimplement those two AppleScript Studio parts in Cocoa, now that your buttons are set up. :wink:

Mikey,

Adding “[super mouseEntered]; & [super mouseExited];” worked!

I really would like to implement the two AppleScript Studio parts in the custom class. However, at the moment I’m a Cocoa n00b. I don’t believe learning Cocoa is beyond my abilities I just need experience and time with it.

Thank you,
CarbonQuark