title: How to receive mouseDown messages in a NSTableViewCell?
body: <p>I am trying to make a table view cell that shows ratings for songs in a playlist.  I have successfully created the cell so that it shows the current number of stars, and also an indication of how a new setting will be when you hover your mouse cursor over a cell to give a new rating.</p>
  
  <p>The problem is that while <code>mouseEnter</code>, <code>mouseExit</code> and <code>mouseMove</code> works like a charm, I get no messages for <code>mouseDown</code>, which is required to actually change the value of the cell.</p>
  
  <p>I have searched all over the Internet, but I can't find any solution to how to solve this problem anywhere. I have spent so many hours trying to sort this. I hope anyone have any answer or hint what I can do.  Thank you.</p>
  
  <p>The full code for the current implementation is as follows:</p>
  
  <pre><code>#import "FavouriteCellView.h"
  
  @implementation FavouriteCellView {
      NSTrackingArea *_trackingArea;
      int _starsRated; //The current rating value
      BOOL _hovering; //YES if the mouse is currently hovering over this cell
      int _starsHovering; //The number of stars hovering, if the mouse is hovering over this cell
  }
  
  - (void)awakeFromNib {
      [super awakeFromNib];
      _starsRated = 1;
      _hovering = NO;
      _starsHovering = 0;
      [self createTrackingArea];
  }
  
  - (void)createTrackingArea
  {
      _trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited |NSTrackingActiveInActiveApp | NSTrackingMouseMoved owner:self userInfo:nil];
      [self addTrackingArea:_trackingArea];
  }
  
  - (void)updateTrackingAreas{
      [self removeTrackingArea:_trackingArea];
      _trackingArea = nil;
      [self createTrackingArea];
  }
  
  - (void)drawRect:(NSRect)dirtyRect {
      [super drawRect:dirtyRect];
  
  //    CGFloat middleX = [self bounds].size.width / 2.0f;
      CGFloat middleY = [self bounds].size.height / 2.0f;
  
      CGFloat starDivs = [self bounds].size.width / 5.0f;;
  
      NSColor *starSelectedColor = [NSColor colorWithDeviceRed:0.8f green:0.0f blue:0.4f alpha:1.0f];
      NSColor *starUnselectedColor = [NSColor colorWithDeviceRed:0.5f green:0.5f blue:0.5f alpha:1.0f];
      NSColor *starHoverColor = [NSColor colorWithDeviceRed:1.0f green:0.843f blue:0.0f alpha:1.0f];
      NSColor *starHoverColorSelected = [NSColor colorWithDeviceRed:0.9f green:0.843f blue:0.6f alpha:1.0f];
  
      for (int i = 0; i &lt; 5; i++) {
  
          NSColor *useColor = [NSColor redColor];
  
          if (_hovering &amp;&amp; (i &lt;= _starsHovering)) {
              if (i &lt;= _starsRated) {
                  useColor = starHoverColorSelected;
              } else {
                  useColor = starHoverColor;
              }
          } else if (i &lt;= _starsRated) {
              useColor = starSelectedColor;
          } else {
              useColor = starUnselectedColor;
          }
  
          [self star:NSMakePoint((starDivs / 2.0f) + starDivs * i, middleY) color:useColor];
      }
  }
  
  -(void)star:(NSPoint)center color:(NSColor *)color {
      [color set];
  
      CGFloat t = (2.0f * M_PI) / 10.0f;
  
      NSBezierPath *path = [[NSBezierPath alloc] init];
  
      CGFloat radii1 = 12.0f;
      CGFloat radii2 = 4.0f;
  
      CGFloat rot = M_PI / 2.0f;
  
      BOOL first = YES;
      for (int i = 0; i &lt; 10; i++) {
          CGFloat pointX = cos(t * i + rot) * radii1 + center.x;
          CGFloat pointY = sin(t * i + rot) * radii1 + center.y;
  
          CGFloat tempRadii = radii1;
          radii1 = radii2;
          radii2 = tempRadii;
  
          if (first) {
              first = NO;
              [path moveToPoint:NSMakePoint(pointX, pointY)];
          }
          else {
              [path lineToPoint:NSMakePoint(pointX, pointY)];
          }
      }
  
      [path closePath];
      [path fill];
  
  /*
      [[NSColor blackColor] set];
      [path setLineWidth:0.25f];
      [path stroke];
  */
  }
  
  -(NSView *)hitTest:(NSPoint)aPoint {
      //THIS GETS CALLED
      return self;
  }
  
  -(BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event {
      printf("$");  //DOES NOT GET CALLED
      return YES;
  }
  
  -(BOOL)acceptsFirstResponder {
      printf("!");  //DOES NOT GET CALLED
      return YES;
  }
  
  -(BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
      printf("8");  //DOES NOT GET CALLED
      return YES;
  }
  
  -(void)mouseDown:(NSEvent *)theEvent {
      printf("o");  //DOES NOT GET CALLED
      _starsRated = _starsHovering;
  }
  
  -(void)mouseUp:(NSEvent *)theEvent {
      printf("O");  //DOES NOT GET CALLED
  }
  
  -(void)mouseEntered:(NSEvent *)theEvent {
      //DOES GET CALLED
      _hovering = YES;
      [self setNeedsDisplay:YES];
  }
  
  -(void)mouseExited:(NSEvent *)theEvent {
      //DOES GET CALLED
      _hovering = NO;
      [self setNeedsDisplay:YES];
  }
  
  -(void)mouseMoved:(NSEvent *)theEvent {
      //DOES GET CALLED
      NSPoint mouseLocation = [[self window] mouseLocationOutsideOfEventStream];
      mouseLocation = [self convertPoint: mouseLocation
                            fromView: nil];
  
      int newStarsHoveringValue = mouseLocation.x / ([self bounds].size.width / 5.0f);
  
      if (newStarsHoveringValue != _starsHovering) {
          _starsHovering = newStarsHoveringValue;
          [self setNeedsDisplay:YES];
      }
  }
  
  @end
  </code></pre>