1/*
2   MPDCon
3
4   Copyright (C) 2006, 2007 Guenther Noack <guenther@unix-ag.uni-kl.de>
5   Copyright (C) 2009  GNUstep Application Team
6                       Riccardo Mottola
7
8   Adapted from Grr GNRatingCell.m
9
10   This application is free software; you can redistribute it and/or
11   modify it under the terms of the GNU General Public
12   License as published by the Free Software Foundation; either
13   version 3 of the License, or (at your option) any later version.
14
15   This application is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   Library General Public License for more details.
19
20   You should have received a copy of the GNU General Public
21   License along with this library; if not, write to the Free
22   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
23*/
24
25#import "SongRatingCell.h"
26
27#ifdef __APPLE__
28#import "GNUstep.h"
29#endif
30
31/**
32 * This cell shows a rating displayed as 0 to 5 horizontally aligned stars. You can
33 * modify the rating by clicking the desired position of the rightmost star. A click
34 * left or right beyond the borders of the rectangle that would surround five stars
35 * sets the number of stars to the maximum 5 or the minimum 0.
36 *
37 */
38@implementation SongRatingCell
39
40// ----------------------------------------------------------------
41//    initializers
42// ----------------------------------------------------------------
43
44-(id) initTextCell: (NSString*) text
45{
46    return [self initImageCell: [NSImage imageNamed: @"Star"]];
47}
48
49-(id) initImageCell: (NSImage*) image
50{
51    if ((self = [super initImageCell: image]) != nil) {
52        ASSIGN(star, image);
53    }
54
55    return self;
56}
57
58// ----------------------------------------------------------------
59//    mouse tracking
60// ----------------------------------------------------------------
61
62-(BOOL) trackMouse: (NSEvent*) theEvent
63            inRect: (NSRect) cellFrame
64            ofView: (NSView*) controlView
65      untilMouseUp: (BOOL) flag
66{
67    // Just remember the rect of the cell, then go on with tracking
68    // and wait for the call to stopTracking:at:inView:mouseIsUp:
69    _currentTrackingRect = cellFrame;
70
71    return [super trackMouse: theEvent
72                      inRect: cellFrame
73                      ofView: controlView
74                untilMouseUp: flag];
75}
76
77- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
78{
79    return YES;
80}
81
82-(void) stopTracking: (NSPoint)lastPoint
83                  at: (NSPoint)stopPoint
84              inView: (NSView*)aView
85           mouseIsUp: (BOOL)isUpFlag
86{
87    if (isUpFlag) {
88        NSSize size = [star size];
89
90        // The field _currentTrackingRect is set by the trackMouse:inRect:ofView:untilMouseUp:
91        // method before it calls the stopTracking:at:inView:mouseIsUp: (this) method. At the
92        // moment I just trust nobody will call stopTracking:... manually.
93        float leftestStarX = NSMidX(_currentTrackingRect) - size.width * 2.5;
94        float rightestStarX = leftestStarX + size.width * 5.0;
95
96        if (stopPoint.x <= leftestStarX) {
97            [self setIntValue: 0];
98        } else if (stopPoint.x <= rightestStarX) {
99            float res = ((stopPoint.x - leftestStarX) / size.width) + 1.0;
100            [self setFloatValue: res];
101        } else {
102            [self setIntValue: 5];
103        }
104    }
105}
106
107
108// ----------------------------------------------------------------
109//    GNUstep workaround for buggy NSTableView behaviour
110// ----------------------------------------------------------------
111#ifdef GNUSTEP
112/*
113 * According to Matt Rice, switching off editability for a cell
114 * lets the mouse tracking still work. As long as the table column
115 * is still editable, updating changed table cells works, too.
116 * This is undefined behaviour, though, and may not work in future
117 * releases of GNUstep.
118 *
119 * This doesn't work for me on GNUstep stable in Nov 2006. It's
120 * probably different for the SVN version.
121 */
122-(BOOL) isEditable {
123    return NO;
124}
125#endif
126
127// ----------------------------------------------------------------
128//    drawing
129// ----------------------------------------------------------------
130
131-(void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
132{
133    NSSize size;
134    NSPoint position;
135    int i;
136    int num;
137
138    if (star == nil) {
139        // init didn't take place, let's do something about it fast!
140        ASSIGN(star, [NSImage imageNamed: @"Star"]);
141    }
142
143    size = [star size];
144
145    position.x = MAX(NSMidX(cellFrame) - (size.width * 2.5),  0.0);
146    position.y = MAX(NSMidY(cellFrame) - (size.height / 2.0), 0.0);
147
148    if ([controlView isFlipped]) {
149        position.y += size.height;
150    }
151
152    num = [self intValue];
153
154    for (i=0; i<num; i++) {
155        [star compositeToPoint: position
156                     operation: NSCompositeSourceOver];
157
158        position.x += size.width;
159    }
160
161    for (;i<5;i++) {
162        [star dissolveToPoint: position
163                     fraction: 0.2];
164
165        position.x += size.width;
166    }
167}
168
169@end
170
171