source: trunk/macosx/GroupsController.m @ 7189

Last change on this file since 7189 was 7189, checked in by livings124, 12 years ago

fix a whoops with group row removal; when removing a row, select the row below it

  • Property svn:keywords set to Date Rev Author Id
File size: 12.9 KB
Line 
1/******************************************************************************
2 * $Id: GroupsController.m 7189 2008-11-29 21:29:06Z livings124 $
3 *
4 * Copyright (c) 2007-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "GroupsController.h"
26#import "CTGradient.h"
27#import "NSBezierPathAdditions.h"
28
29#define ICON_WIDTH 16.0
30#define ICON_WIDTH_SMALL 12.0
31
32@interface GroupsController (Private)
33
34- (void) saveGroups;
35
36- (NSImage *) imageForGroup: (NSMutableDictionary *) dict;
37
38@end
39
40@implementation GroupsController
41
42GroupsController * fGroupsInstance = nil;
43+ (GroupsController *) groups
44{
45    if (!fGroupsInstance)
46        fGroupsInstance = [[GroupsController alloc] init];
47    return fGroupsInstance;
48}
49
50- (id) init
51{
52    if ((self = [super init]))
53    {
54        NSData * data;
55        if ((data = [[NSUserDefaults standardUserDefaults] dataForKey: @"Groups"]))
56            fGroups = [[NSUnarchiver unarchiveObjectWithData: data] retain];
57        else
58        {
59            //default groups
60            NSMutableDictionary * red = [NSMutableDictionary dictionaryWithObjectsAndKeys:
61                                            [NSColor redColor], @"Color",
62                                            NSLocalizedString(@"Red", "Groups -> Name"), @"Name",
63                                            [NSNumber numberWithInt: 0], @"Index", nil];
64           
65            NSMutableDictionary * orange = [NSMutableDictionary dictionaryWithObjectsAndKeys:
66                                            [NSColor orangeColor], @"Color",
67                                            NSLocalizedString(@"Orange", "Groups -> Name"), @"Name",
68                                            [NSNumber numberWithInt: 1], @"Index", nil];
69           
70            NSMutableDictionary * yellow = [NSMutableDictionary dictionaryWithObjectsAndKeys:
71                                            [NSColor yellowColor], @"Color",
72                                            NSLocalizedString(@"Yellow", "Groups -> Name"), @"Name",
73                                            [NSNumber numberWithInt: 2], @"Index", nil];
74           
75            NSMutableDictionary * green = [NSMutableDictionary dictionaryWithObjectsAndKeys:
76                                            [NSColor greenColor], @"Color",
77                                            NSLocalizedString(@"Green", "Groups -> Name"), @"Name",
78                                            [NSNumber numberWithInt: 3], @"Index", nil];
79           
80            NSMutableDictionary * blue = [NSMutableDictionary dictionaryWithObjectsAndKeys:
81                                            [NSColor blueColor], @"Color",
82                                            NSLocalizedString(@"Blue", "Groups -> Name"), @"Name",
83                                            [NSNumber numberWithInt: 4], @"Index", nil];
84           
85            NSMutableDictionary * purple = [NSMutableDictionary dictionaryWithObjectsAndKeys:
86                                            [NSColor purpleColor], @"Color",
87                                            NSLocalizedString(@"Purple", "Groups -> Name"), @"Name",
88                                            [NSNumber numberWithInt: 5], @"Index", nil];
89           
90            NSMutableDictionary * gray = [NSMutableDictionary dictionaryWithObjectsAndKeys:
91                                            [NSColor grayColor], @"Color",
92                                            NSLocalizedString(@"Gray", "Groups -> Name"), @"Name",
93                                            [NSNumber numberWithInt: 6], @"Index", nil];
94           
95            fGroups = [[NSMutableArray alloc] initWithObjects: red, orange, yellow, green, blue, purple, gray, nil];
96            [self saveGroups]; //make sure this is saved right away
97        }
98    }
99   
100    return self;
101}
102
103- (void) dealloc
104{
105    [fGroups release];
106    [super dealloc];
107}
108
109- (NSInteger) numberOfGroups
110{
111    return [fGroups count];
112}
113
114- (NSInteger) rowValueForIndex: (NSInteger) index
115{
116    if (index != -1)
117    {
118        for (NSInteger i = 0; i < [fGroups count]; i++)
119            if (index == [[[fGroups objectAtIndex: i] objectForKey: @"Index"] intValue])
120                return i;
121    }
122    return -1;
123}
124
125- (NSInteger) indexForRow: (NSInteger) row
126{
127    return [[[fGroups objectAtIndex: row] objectForKey: @"Index"] intValue];
128}
129
130- (NSString *) nameForIndex: (NSInteger) index
131{
132    NSInteger orderIndex = [self rowValueForIndex: index];
133    return orderIndex != -1 ? [[fGroups objectAtIndex: orderIndex] objectForKey: @"Name"] : nil;
134}
135
136- (void) setName: (NSString *) name forIndex: (NSInteger) index
137{
138    NSInteger orderIndex = [self rowValueForIndex: index];
139    [[fGroups objectAtIndex: orderIndex] setObject: name forKey: @"Name"];
140    [self saveGroups];
141   
142    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
143}
144
145- (NSImage *) imageForIndex: (NSInteger) index
146{
147    NSInteger orderIndex = [self rowValueForIndex: index];
148    return orderIndex != -1 ? [self imageForGroup: [fGroups objectAtIndex: orderIndex]]
149                            : [NSImage imageNamed: @"GroupsNoneTemplate.png"];
150}
151
152- (NSColor *) colorForIndex: (NSInteger) index
153{
154    NSInteger orderIndex = [self rowValueForIndex: index];
155    return orderIndex != -1 ? [[fGroups objectAtIndex: orderIndex] objectForKey: @"Color"] : nil;
156}
157
158- (void) setColor: (NSColor *) color forIndex: (NSInteger) index
159{
160    NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
161    [dict removeObjectForKey: @"Icon"];
162   
163    [dict setObject: color forKey: @"Color"];
164   
165    [[GroupsController groups] saveGroups];
166    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
167}
168
169- (void) addNewGroup
170{
171    //find the lowest index
172    NSInteger index;
173    for (index = 0; index < [fGroups count]; index++)
174    {
175        BOOL found = NO;
176        NSEnumerator * enumerator = [fGroups objectEnumerator];
177        NSDictionary * dict;
178        while ((dict = [enumerator nextObject]))
179            if ([[dict objectForKey: @"Index"] intValue] == index)
180            {
181                found = YES;
182                break;
183            }
184       
185        if (!found)
186            break;
187    }
188   
189    [fGroups addObject: [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: index], @"Index",
190                            [NSColor cyanColor], @"Color", @"", @"Name", nil]];
191   
192    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
193    [self saveGroups];
194}
195
196- (void) removeGroupWithRowIndex: (NSInteger) row
197{
198    NSInteger index = [[[fGroups objectAtIndex: row] objectForKey: @"Index"] intValue];
199    [fGroups removeObjectAtIndex: row];
200   
201    [[NSNotificationCenter defaultCenter] postNotificationName: @"GroupValueRemoved" object: self userInfo:
202        [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: index] forKey: @"Index"]];
203   
204    if (index == [[NSUserDefaults standardUserDefaults] integerForKey: @"FilterGroup"])
205        [[NSUserDefaults standardUserDefaults] setInteger: -2 forKey: @"FilterGroup"];
206   
207    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
208    [self saveGroups];
209}
210
211#warning rework for single row?
212- (NSIndexSet *) moveGroupsAtRowIndexes: (NSIndexSet *) indexes toRow: (NSInteger) newRow oldSelected: (NSIndexSet *) selectedIndexes
213{
214    NSArray * selectedGroups = [fGroups objectsAtIndexes: selectedIndexes];
215   
216    //determine where to move them
217    for (NSInteger i = [indexes firstIndex], startRow = newRow; i < startRow && i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
218        newRow--;
219   
220    //remove objects to reinsert
221    NSArray * movingGroups = [[fGroups objectsAtIndexes: indexes] retain];
222    [fGroups removeObjectsAtIndexes: indexes];
223   
224    //insert objects at new location
225    for (NSInteger i = 0; i < [movingGroups count]; i++)
226        [fGroups insertObject: [movingGroups objectAtIndex: i] atIndex: newRow + i];
227   
228    [movingGroups release];
229   
230    [self saveGroups];
231    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
232   
233    NSMutableIndexSet * newSelectedIndexes = nil;
234    if ([selectedGroups count] > 0)
235    {
236        newSelectedIndexes = [NSMutableIndexSet indexSet];
237        NSEnumerator * enumerator = [selectedGroups objectEnumerator];
238        NSDictionary * dict;
239        while ((dict = [enumerator nextObject]))
240            [newSelectedIndexes addIndex: [fGroups indexOfObject: dict]];
241    }
242   
243    return newSelectedIndexes;
244}
245
246- (NSMenu *) groupMenuWithTarget: (id) target action: (SEL) action isSmall: (BOOL) small
247{
248    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"Groups"];
249   
250    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"None", "Groups -> Menu") action: action
251                            keyEquivalent: @""];
252    [item setTarget: target];
253    [item setTag: -1];
254   
255    NSImage * icon = [NSImage imageNamed: @"GroupsNoneTemplate.png"];
256    if (small)
257    {
258        icon = [icon copy];
259        [icon setScalesWhenResized: YES];
260        [icon setSize: NSMakeSize(ICON_WIDTH_SMALL, ICON_WIDTH_SMALL)];
261       
262        [item setImage: icon];
263        [icon release];
264    }
265    else
266        [item setImage: icon];
267   
268    [menu addItem: item];
269    [item release];
270   
271    NSEnumerator * enumerator = [fGroups objectEnumerator];
272    NSMutableDictionary * dict;
273    while ((dict = [enumerator nextObject]))
274    {
275        item = [[NSMenuItem alloc] initWithTitle: [dict objectForKey: @"Name"] action: action keyEquivalent: @""];
276        [item setTarget: target];
277       
278        [item setTag: [[dict objectForKey: @"Index"] intValue]];
279       
280        NSImage * icon = [self imageForGroup: dict];
281        if (small)
282        {
283            icon = [icon copy];
284            [icon setScalesWhenResized: YES];
285            [icon setSize: NSMakeSize(ICON_WIDTH_SMALL, ICON_WIDTH_SMALL)];
286           
287            [item setImage: icon];
288            [icon release];
289        }
290        else
291            [item setImage: icon];
292       
293        [menu addItem: item];
294        [item release];
295    }
296   
297    return [menu autorelease];
298}
299
300@end
301
302@implementation GroupsController (Private)
303
304- (void) saveGroups
305{
306    //don't archive the icon
307    NSMutableArray * groups = [NSMutableArray arrayWithCapacity: [fGroups count]];
308    NSEnumerator * enumerator = [fGroups objectEnumerator];
309    NSDictionary * dict;
310    while ((dict = [enumerator nextObject]))
311    {
312        NSMutableDictionary * tempDict = [dict mutableCopy];
313        [tempDict removeObjectForKey: @"Icon"];
314        [groups addObject: tempDict];
315        [tempDict release];
316    }
317   
318    [[NSUserDefaults standardUserDefaults] setObject: [NSArchiver archivedDataWithRootObject: groups] forKey: @"Groups"];
319}
320
321- (NSImage *) imageForGroup: (NSMutableDictionary *) dict
322{
323    NSImage * image;
324    if ((image = [dict objectForKey: @"Icon"]))
325        return image;
326   
327    NSRect rect = NSMakeRect(0.0, 0.0, ICON_WIDTH, ICON_WIDTH);
328   
329    NSBezierPath * bp = [NSBezierPath bezierPathWithRoundedRect: rect radius: 3.0];
330    NSImage * icon = [[NSImage alloc] initWithSize: rect.size];
331   
332    NSColor * color = [dict objectForKey: @"Color"];
333   
334    [icon lockFocus];
335   
336    //border
337    CTGradient * gradient = [CTGradient gradientWithBeginningColor: [color blendedColorWithFraction: 0.45 ofColor:
338                                [NSColor whiteColor]] endingColor: color];
339    [gradient fillBezierPath: bp angle: 270.0];
340   
341    //inside
342    bp = [NSBezierPath bezierPathWithRoundedRect: NSInsetRect(rect, 1.0, 1.0) radius: 3.0];
343    gradient = [CTGradient gradientWithBeginningColor: [color blendedColorWithFraction: 0.75 ofColor: [NSColor whiteColor]]
344                endingColor: [color blendedColorWithFraction: 0.2 ofColor: [NSColor whiteColor]]];
345    [gradient fillBezierPath: bp angle: 270.0];
346   
347    [icon unlockFocus];
348   
349    [dict setObject: icon forKey: @"Icon"];
350    [icon release];
351   
352    return icon;
353}
354
355@end
Note: See TracBrowser for help on using the repository browser.