0
votes

This is for a Mac app written with Cocoa and Objective-C.

I have a custom NSView class that essentially works as a collection of buttons and stores the value of the selected button. Sort of like an NSSlider that snaps to the tick marks but with buttons instead of a slider. The image below on the left is what it looks like.

Now what I want to do is make it so that when the mouse moves over each button, it covers that button with a semi-transparent blue color that then stays there when it is clicked. I've made a few attempts and you can see the latest result in the image on the right:

exampleexample2

This is what happens after mousing over all the buttons. For some reason it draws using the window's origin instead of drawing inside the MyButtonView. Also, it is not semi-transparent. I haven't yet worried about redrawing the normal button when the mouse leaves the rectangle since this part isn't working yet anyway.

Now here's the pertinent code.

Inside the initWithFrame method of the MyButtonView class:

for (int i = 0; i < 12; i++) {
        yOrigin = kBorderSize + (buttonHeight * i) + (kSeparatorSize * i);
        NSRect newRect = { {xOrigin, yOrigin}, {buttonWidth, buttonHeight} };
        [buttonRectangles addObject:NSStringFromRect(newRect)];
        [self addTrackingRect:newRect owner:self userData:NULL assumeInside:NO];
    }

The methods that draw the blue rectangles:

- (void)mouseEntered:(NSEvent *)theEvent {
    NSRect rect = [[theEvent trackingArea] rect];
    [self drawHoverRect:rect withColor:hoverBlue];
}

- (void)drawHoverRect:(NSRect)rect withColor:(NSColor *)color {
    [color set];
    NSRectFill(rect);
    [self displayRect:rect];
}

I have no idea how to do this. I've been poring over Apple's documentation for a few hours and can't figure it out. Obviously though, I'm no veteran to Cocoa or Objective-C so I would love some help.

1

1 Answers

1
votes

One fundamental problem you have is that you are bypassing the normal drawing mechanisms and trying to force the drawing yourself. This is a common mistake for first timers. Before you go any further, you should read Apple's View Programming Guide: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaViewsGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40002978

If you have trouble with that, then you might need to back up and start with some of the more fundamental Objective-C/Cocoa guides and documentation.

Back to your actual view, one thing that you are going to have to do in this view is do all your drawing in the drawRect: method. You should be tracking the state of your mouse movements via some kind of data structure and then drawing according to that data structure in your drawRect: method. You will call

[self setNeedsDisplay:YES];

in your mouse tracking method(s), after you've recorded whatever change has occurred in your data structure. If you only want to ever draw one button highlighted at a time, then your data structure could be as simple as an NSInteger whose value you set to the index of your selected button (or -1 or whatever to indicate no selection).

For the sake of learning, the reason your blue boxes are currently drawing from the window's origin is that you are calling drawing code outside of the "context" that's normally setup for your view when drawRect: is called by the system. That "context" would include a translation to move the current origin to the origin of your view, rather than the origin of the window.