source: trunk/macosx/GroupsWindowController.m @ 4225

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

initial group filtering

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