source: trunk/macosx/GroupsWindowController.m @ 4190

Last change on this file since 4190 was 4190, checked in by livings124, 15 years ago

allow Groups table to be reordered

File size: 14.6 KB
Line 
1/******************************************************************************
2 * $Id$
3 *
4 * Copyright (c) 2007 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 "GroupsWindowController.h"
26#import "GradientCell.h"
27#import "CTGradient.h"
28#import "NSBezierPathAdditions.h"
29#import "NSApplicationAdditions.h"
30
31#define GROUP_TABLE_VIEW_DATA_TYPE @"GroupTableViewDataType"
32
33typedef enum
34{
35    ADD_TAG = 0,
36    REMOVE_TAG = 1
37} controlTag;
38
39@interface GroupsWindowController (Private)
40
41- (void) saveGroups;
42
43- (CTGradient *) gradientForColor: (NSColor *) color;
44- (void) changeColor: (id) sender;
45
46@end
47
48@implementation GroupsWindowController
49
50GroupsWindowController * fGroupsWindowInstance = nil;
51+ (GroupsWindowController *) groupsController
52{
53    if (!fGroupsWindowInstance)
54        fGroupsWindowInstance = [[GroupsWindowController alloc] init];
55    return fGroupsWindowInstance;
56}
57
58- (id) init
59{
60    if ((self = [super initWithWindowNibName: @"GroupsWindow"]))
61    {
62        NSData * data;
63        if ((data = [[NSUserDefaults standardUserDefaults] dataForKey: @"Groups"]))
64            fGroups = [[NSUnarchiver unarchiveObjectWithData: data] retain];
65        else
66        {
67            //default groups
68            NSMutableDictionary * red = [NSMutableDictionary dictionaryWithObjectsAndKeys:
69                                            [NSColor redColor], @"Color",
70                                            NSLocalizedString(@"Red", "Groups -> Name"), @"Name",
71                                            [NSNumber numberWithInt: 0], @"Index", nil];
72           
73            NSMutableDictionary * orange = [NSMutableDictionary dictionaryWithObjectsAndKeys:
74                                            [NSColor orangeColor], @"Color",
75                                            NSLocalizedString(@"Orange", "Groups -> Name"), @"Name",
76                                            [NSNumber numberWithInt: 1], @"Index", nil];
77           
78            NSMutableDictionary * yellow = [NSMutableDictionary dictionaryWithObjectsAndKeys:
79                                            [NSColor yellowColor], @"Color",
80                                            NSLocalizedString(@"Yellow", "Groups -> Name"), @"Name",
81                                            [NSNumber numberWithInt: 2], @"Index", nil];
82           
83            NSMutableDictionary * green = [NSMutableDictionary dictionaryWithObjectsAndKeys:
84                                            [NSColor greenColor], @"Color",
85                                            NSLocalizedString(@"Green", "Groups -> Name"), @"Name",
86                                            [NSNumber numberWithInt: 3], @"Index", nil];
87           
88            NSMutableDictionary * blue = [NSMutableDictionary dictionaryWithObjectsAndKeys:
89                                            [NSColor blueColor], @"Color",
90                                            NSLocalizedString(@"Blue", "Groups -> Name"), @"Name",
91                                            [NSNumber numberWithInt: 4], @"Index", nil];
92           
93            NSMutableDictionary * purple = [NSMutableDictionary dictionaryWithObjectsAndKeys:
94                                            [NSColor purpleColor], @"Color",
95                                            NSLocalizedString(@"Purple", "Groups -> Name"), @"Name",
96                                            [NSNumber numberWithInt: 5], @"Index", nil];
97           
98            NSMutableDictionary * gray = [NSMutableDictionary dictionaryWithObjectsAndKeys:
99                                            [NSColor grayColor], @"Color",
100                                            NSLocalizedString(@"Gray", "Groups -> Name"), @"Name",
101                                            [NSNumber numberWithInt: 6], @"Index", nil];
102           
103            fGroups = [[NSMutableArray alloc] initWithObjects: red, orange, yellow, green, blue, purple, gray, nil];
104            [self saveGroups]; //make sure this is saved right away
105        }
106    }
107   
108    return self;
109}
110
111- (void) awakeFromNib
112{
113    GradientCell * cell = [[GradientCell alloc] init];
114    [[fTableView tableColumnWithIdentifier: @"Color"] setDataCell: cell];
115    [cell release];
116   
117    [fTableView registerForDraggedTypes: [NSArray arrayWithObject: GROUP_TABLE_VIEW_DATA_TYPE]];
118   
119    if ([NSApp isOnLeopardOrBetter])
120        [[self window] setContentBorderThickness: [[fTableView enclosingScrollView] frame].origin.y forEdge: NSMinYEdge];
121   
122    [fAddRemoveControl setEnabled: NO forSegment: REMOVE_TAG];
123}
124
125- (void) dealloc
126{
127    [fGroups release];
128    [super dealloc];
129}
130
131- (CTGradient *) gradientForIndex: (int) index
132{
133    if (index < 0)
134        return nil;
135   
136    NSEnumerator * enumerator = [fGroups objectEnumerator];
137    NSDictionary * dict;
138    while ((dict = [enumerator nextObject]))
139        if ([[dict objectForKey: @"Index"] intValue] == index)
140            return [self gradientForColor: [dict objectForKey: @"Color"]];
141   
142    return nil;
143}
144
145- (int) orderValueForIndex: (int) index
146{
147    if (index != -1)
148    {
149        int i;
150        for (i = 0; i < [fGroups count]; i++)
151            if (index == [[[fGroups objectAtIndex: i] objectForKey: @"Index"] intValue])
152                return i;
153    }
154    return -1;
155}
156
157- (NSInteger) numberOfRowsInTableView: (NSTableView *) tableview
158{
159    return [fGroups count];
160}
161
162- (id) tableView: (NSTableView *) tableView objectValueForTableColumn: (NSTableColumn *) tableColumn row: (NSInteger) row
163{
164    NSString * identifier = [tableColumn identifier];
165    if ([identifier isEqualToString: @"Color"])
166        return [self gradientForColor: [[fGroups objectAtIndex: row] objectForKey: @"Color"]];
167    else
168        return [[fGroups objectAtIndex: row] objectForKey: @"Name"];
169}
170
171- (void) tableView: (NSTableView *) tableView setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn
172    row: (NSInteger) row
173{
174    NSString * identifier = [tableColumn identifier];
175    if ([identifier isEqualToString: @"Name"])
176    {
177        [[fGroups objectAtIndex: row] setObject: object forKey: @"Name"];
178        [self saveGroups];
179    }
180    else if ([identifier isEqualToString: @"Button"])
181    {
182        fCurrentColorDict = [fGroups objectAtIndex: row];
183       
184        NSColorPanel * colorPanel = [NSColorPanel sharedColorPanel];
185        [colorPanel setContinuous: YES];
186        [colorPanel setColor: [[fGroups objectAtIndex: row] objectForKey: @"Color"]];
187       
188        [colorPanel setTarget: self];
189        [colorPanel setAction: @selector(changeColor:)];
190       
191        [colorPanel orderFront: self];
192    }
193    else;
194}
195
196- (void) tableViewSelectionDidChange: (NSNotification *) notification
197{
198    [fAddRemoveControl setEnabled: [fTableView numberOfSelectedRows] > 0 forSegment: REMOVE_TAG];
199}
200
201- (BOOL) tableView: (NSTableView *) tableView writeRowsWithIndexes: (NSIndexSet *) rowIndexes toPasteboard: (NSPasteboard *) pboard
202{
203    [pboard declareTypes: [NSArray arrayWithObject: GROUP_TABLE_VIEW_DATA_TYPE] owner: self];
204    [pboard setData: [NSKeyedArchiver archivedDataWithRootObject: rowIndexes] forType: GROUP_TABLE_VIEW_DATA_TYPE];
205    return YES;
206}
207
208- (NSDragOperation) tableView: (NSTableView *) tableView validateDrop: (id <NSDraggingInfo>) info
209    proposedRow: (int) row proposedDropOperation: (NSTableViewDropOperation) operation
210{
211    NSPasteboard * pasteboard = [info draggingPasteboard];
212    if ([[pasteboard types] containsObject: GROUP_TABLE_VIEW_DATA_TYPE])
213    {
214        [fTableView setDropRow: row dropOperation: NSTableViewDropAbove];
215        return NSDragOperationGeneric;
216    }
217   
218    return NSDragOperationNone;
219}
220
221- (BOOL) tableView: (NSTableView *) t acceptDrop: (id <NSDraggingInfo>) info
222    row: (int) newRow dropOperation: (NSTableViewDropOperation) operation
223{
224    NSPasteboard * pasteboard = [info draggingPasteboard];
225    if ([[pasteboard types] containsObject: GROUP_TABLE_VIEW_DATA_TYPE])
226    {
227        NSIndexSet * indexes = [NSKeyedUnarchiver unarchiveObjectWithData: [pasteboard dataForType: GROUP_TABLE_VIEW_DATA_TYPE]];
228       
229        NSArray * selectedGroups = [fGroups objectsAtIndexes: [fTableView selectedRowIndexes]];
230       
231        //determine where to move them
232        int i;
233        for (i = [indexes firstIndex]; i < newRow && i != NSNotFound; i = [indexes indexGreaterThanIndex: i])
234            newRow--;
235       
236        //remove objects to reinsert
237        NSArray * movingGroups = [[fGroups objectsAtIndexes: indexes] retain];
238        [fGroups removeObjectsAtIndexes: indexes];
239       
240        //insert objects at new location
241        for (i = 0; i < [movingGroups count]; i++)
242            [fGroups insertObject: [movingGroups objectAtIndex: i] atIndex: newRow + i];
243       
244        [movingGroups release];
245       
246        if ([selectedGroups count] > 0)
247        {
248            NSEnumerator * enumerator = [selectedGroups objectEnumerator];
249            NSMutableIndexSet * indexSet = [[NSMutableIndexSet alloc] init];
250            NSDictionary * dict;
251            while ((dict = [enumerator nextObject]))
252                [indexSet addIndex: [fGroups indexOfObject: dict]];
253           
254            [fTableView selectRowIndexes: indexSet byExtendingSelection: NO];
255            [indexSet release];
256        }
257       
258        [fTableView reloadData];
259       
260        [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: self];
261    }
262   
263    return YES;
264}
265
266- (void) addRemoveGroup: (id) sender
267{
268    NSEnumerator * enumerator;
269    NSDictionary * dict;
270    int index;
271    BOOL found;
272    NSIndexSet * rowIndexes;
273    NSMutableIndexSet * indexes;
274   
275    switch ([[sender cell] tagForSegment: [sender selectedSegment]])
276    {
277        case ADD_TAG:
278           
279            //find the lowest index
280            for (index = 0; index < [fGroups count]; index++)
281            {
282                found = NO;
283                enumerator = [fGroups objectEnumerator];
284                while ((dict = [enumerator nextObject]))
285                    if ([[dict objectForKey: @"Index"] intValue] == index)
286                    {
287                        found = YES;
288                        break;
289                    }
290               
291                if (!found)
292                    break;
293            }
294           
295            [fGroups addObject: [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: index], @"Index",
296                                    [NSColor cyanColor], @"Color", @"", @"Name", nil]];
297            [fTableView reloadData];
298            [fTableView deselectAll: self];
299           
300            [fTableView editColumn: [fTableView columnWithIdentifier: @"Name"] row: [fTableView numberOfRows]-1 withEvent: nil
301                        select: NO];
302            break;
303       
304        case REMOVE_TAG:
305           
306            rowIndexes = [fTableView selectedRowIndexes];
307            indexes = [NSMutableIndexSet indexSet];
308            for (index = [rowIndexes firstIndex]; index != NSNotFound; index = [rowIndexes indexGreaterThanIndex: index])
309                [indexes addIndex: [[[fGroups objectAtIndex: index] objectForKey: @"Index"] intValue]];
310           
311            [fGroups removeObjectsAtIndexes: rowIndexes];
312            [fTableView deselectAll: self];
313            [fTableView reloadData];
314           
315            [[NSNotificationCenter defaultCenter] postNotificationName: @"GroupValueRemoved" object: self userInfo:
316                [NSDictionary dictionaryWithObject: indexes forKey: @"Indexes"]];
317            break;
318       
319        default:
320            return;
321    }
322   
323    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: self];
324    [self saveGroups];
325}
326
327- (NSMenu *) groupMenuWithTarget: (id) target action: (SEL) action
328{
329    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"Groups"];
330   
331    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: @"None" action: action keyEquivalent: @""];
332    [item setTarget: target];
333    [item setRepresentedObject: [NSNumber numberWithInt: -1]];
334    [menu addItem: item];
335    [item release];
336   
337    [menu addItem: [NSMenuItem separatorItem]];
338   
339    NSBezierPath * bp = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(0.0, 0.0, 16.0, 16.0) radius: 4.0];
340   
341    NSEnumerator * enumerator = [fGroups objectEnumerator];
342    NSDictionary * dict;
343    while ((dict = [enumerator nextObject]))
344    {
345        item = [[NSMenuItem alloc] initWithTitle: [dict objectForKey: @"Name"] action: action keyEquivalent: @""];
346        [item setTarget: target];
347       
348        NSImage * icon = [[NSImage alloc] initWithSize: NSMakeSize(16.0, 16.0)];
349       
350        [icon lockFocus];
351        [[self gradientForColor: [dict objectForKey: @"Color"]] fillBezierPath: bp angle: 90];
352        [icon unlockFocus];
353       
354        [item setImage: icon];
355        [icon release];
356       
357        [item setRepresentedObject: [dict objectForKey: @"Index"]];
358       
359        [menu addItem: item];
360        [item release];
361    }
362   
363    return [menu autorelease];
364}
365
366@end
367
368@implementation GroupsWindowController (Private)
369
370- (void) saveGroups
371{
372    [[NSUserDefaults standardUserDefaults] setObject: [NSArchiver archivedDataWithRootObject: fGroups] forKey: @"Groups"];
373}
374
375- (CTGradient *) gradientForColor: (NSColor *) color
376{
377    return [CTGradient gradientWithBeginningColor: [color blendedColorWithFraction: 0.7 ofColor: [NSColor whiteColor]]
378            endingColor: [color blendedColorWithFraction: 0.4 ofColor: [NSColor whiteColor]]];
379}
380
381- (void) changeColor: (id) sender
382{
383    [fCurrentColorDict setObject: [sender color] forKey: @"Color"];
384    [fTableView reloadData];
385   
386    [self saveGroups];
387    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: self];
388}
389
390@end
Note: See TracBrowser for help on using the repository browser.