source: trunk/macosx/FilterBarController.m @ 11998

Last change on this file since 11998 was 11998, checked in by livings124, 11 years ago

restore cmd-option-f to select the search filter field when the torrent table view is selected

File size: 14.0 KB
Line 
1/******************************************************************************
2 * $Id$
3 *
4 * Copyright (c) 2011 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 "FilterBarController.h"
26#import "FilterButton.h"
27#import "GroupsController.h"
28
29#define FILTER_TYPE_TAG_NAME    401
30#define FILTER_TYPE_TAG_TRACKER 402
31
32#define SEARCH_MIN_WIDTH 48.0
33#define SEARCH_MAX_WIDTH 95.0
34
35@interface FilterBarController (Private)
36
37- (void) resizeBar;
38- (void) updateGroupsButton;
39- (void) updateGroups: (NSNotification *) notification;
40
41@end
42
43@implementation FilterBarController
44
45- (id) init
46{
47    return (self = [super initWithNibName: @"FilterBar" bundle: nil]);
48}
49
50- (void) awakeFromNib
51{
52    //localizations
53    [fNoFilterButton setTitle: NSLocalizedString(@"All", "Filter Bar -> filter button")];
54    [fActiveFilterButton setTitle: NSLocalizedString(@"Active", "Filter Bar -> filter button")];
55    [fDownloadFilterButton setTitle: NSLocalizedString(@"Downloading", "Filter Bar -> filter button")];
56    [fSeedFilterButton setTitle: NSLocalizedString(@"Seeding", "Filter Bar -> filter button")];
57    [fPauseFilterButton setTitle: NSLocalizedString(@"Paused", "Filter Bar -> filter button")];
58   
59    [[[[fSearchField cell] searchMenuTemplate] itemWithTag: FILTER_TYPE_TAG_NAME] setTitle:
60        NSLocalizedString(@"Name", "Filter Bar -> filter menu")];
61    [[[[fSearchField cell] searchMenuTemplate] itemWithTag: FILTER_TYPE_TAG_TRACKER] setTitle:
62        NSLocalizedString(@"Tracker", "Filter Bar -> filter menu")];
63   
64    [[[fGroupsButton menu] itemWithTag: GROUP_FILTER_ALL_TAG] setTitle:
65        NSLocalizedString(@"All Groups", "Filter Bar -> group filter menu")];
66   
67    [self resizeBar];
68   
69    //set current filter
70    NSString * filterType = [[NSUserDefaults standardUserDefaults] stringForKey: @"Filter"];
71   
72    NSButton * currentFilterButton;
73    if ([filterType isEqualToString: FILTER_ACTIVE])
74        currentFilterButton = fActiveFilterButton;
75    else if ([filterType isEqualToString: FILTER_PAUSE])
76        currentFilterButton = fPauseFilterButton;
77    else if ([filterType isEqualToString: FILTER_SEED])
78        currentFilterButton = fSeedFilterButton;
79    else if ([filterType isEqualToString: FILTER_DOWNLOAD])
80        currentFilterButton = fDownloadFilterButton;
81    else
82    {
83        //safety
84        if (![filterType isEqualToString: FILTER_NONE])
85            [[NSUserDefaults standardUserDefaults] setObject: FILTER_NONE forKey: @"Filter"];
86        currentFilterButton = fNoFilterButton;
87    }
88    [currentFilterButton setState: NSOnState];
89   
90    //set filter search type
91    NSString * filterSearchType = [[NSUserDefaults standardUserDefaults] stringForKey: @"FilterSearchType"];
92   
93    NSMenu * filterSearchMenu = [[fSearchField cell] searchMenuTemplate];
94    NSString * filterSearchTypeTitle;
95    if ([filterSearchType isEqualToString: FILTER_TYPE_TRACKER])
96        filterSearchTypeTitle = [[filterSearchMenu itemWithTag: FILTER_TYPE_TAG_TRACKER] title];
97    else
98    {
99        //safety
100        if (![filterType isEqualToString: FILTER_TYPE_NAME])
101            [[NSUserDefaults standardUserDefaults] setObject: FILTER_TYPE_NAME forKey: @"FilterSearchType"];
102        filterSearchTypeTitle = [[filterSearchMenu itemWithTag: FILTER_TYPE_TAG_NAME] title];
103    }
104    [[fSearchField cell] setPlaceholderString: filterSearchTypeTitle];
105   
106    [self updateGroupsButton];
107   
108    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(resizeBar)
109        name: NSWindowDidResizeNotification object: [[self view] window]];
110   
111    //update when groups change
112    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(updateGroups:)
113        name: @"UpdateGroups" object: nil];
114}
115
116- (void) dealloc
117{
118    [[NSNotificationCenter defaultCenter] removeObserver: self];
119   
120    [super dealloc];
121}
122
123- (void) setFilter: (id) sender
124{
125    NSString * oldFilterType = [[NSUserDefaults standardUserDefaults] stringForKey: @"Filter"];
126   
127    NSButton * prevFilterButton;
128    if ([oldFilterType isEqualToString: FILTER_PAUSE])
129        prevFilterButton = fPauseFilterButton;
130    else if ([oldFilterType isEqualToString: FILTER_ACTIVE])
131        prevFilterButton = fActiveFilterButton;
132    else if ([oldFilterType isEqualToString: FILTER_SEED])
133        prevFilterButton = fSeedFilterButton;
134    else if ([oldFilterType isEqualToString: FILTER_DOWNLOAD])
135        prevFilterButton = fDownloadFilterButton;
136    else
137        prevFilterButton = fNoFilterButton;
138   
139    if (sender != prevFilterButton)
140    {
141        [prevFilterButton setState: NSOffState];
142        [sender setState: NSOnState];
143
144        NSString * filterType;
145        if (sender == fActiveFilterButton)
146            filterType = FILTER_ACTIVE;
147        else if (sender == fDownloadFilterButton)
148            filterType = FILTER_DOWNLOAD;
149        else if (sender == fPauseFilterButton)
150            filterType = FILTER_PAUSE;
151        else if (sender == fSeedFilterButton)
152            filterType = FILTER_SEED;
153        else
154            filterType = FILTER_NONE;
155
156        [[NSUserDefaults standardUserDefaults] setObject: filterType forKey: @"Filter"];
157    }
158    else
159        [sender setState: NSOnState];
160   
161    [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplyFilter" object: nil];
162}
163
164- (void) switchFilter: (BOOL) right
165{
166    NSString * filterType = [[NSUserDefaults standardUserDefaults] stringForKey: @"Filter"];
167   
168    NSButton * button;
169    if ([filterType isEqualToString: FILTER_NONE])
170        button = right ? fActiveFilterButton : fPauseFilterButton;
171    else if ([filterType isEqualToString: FILTER_ACTIVE])
172        button = right ? fDownloadFilterButton : fNoFilterButton;
173    else if ([filterType isEqualToString: FILTER_DOWNLOAD])
174        button = right ? fSeedFilterButton : fActiveFilterButton;
175    else if ([filterType isEqualToString: FILTER_SEED])
176        button = right ? fPauseFilterButton : fDownloadFilterButton;
177    else if ([filterType isEqualToString: FILTER_PAUSE])
178        button = right ? fNoFilterButton : fSeedFilterButton;
179    else
180        button = fNoFilterButton;
181   
182    [self setFilter: button];
183}
184
185- (void) setSearchText: (id) sender
186{
187    [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplyFilter" object: nil];
188}
189
190- (void) focusSearchField
191{
192    [[[self view] window] makeFirstResponder: fSearchField];
193}
194
195- (void) setSearchType: (id) sender
196{
197    NSString * oldFilterType = [[NSUserDefaults standardUserDefaults] stringForKey: @"FilterSearchType"];
198   
199    NSInteger prevTag, currentTag = [sender tag];
200    if ([oldFilterType isEqualToString: FILTER_TYPE_TRACKER])
201        prevTag = FILTER_TYPE_TAG_TRACKER;
202    else
203        prevTag = FILTER_TYPE_TAG_NAME;
204   
205    if (currentTag != prevTag)
206    {
207        NSString * filterType;
208        if (currentTag == FILTER_TYPE_TAG_TRACKER)
209            filterType = FILTER_TYPE_TRACKER;
210        else
211            filterType = FILTER_TYPE_NAME;
212       
213        [[NSUserDefaults standardUserDefaults] setObject: filterType forKey: @"FilterSearchType"];
214       
215        [[fSearchField cell] setPlaceholderString: [sender title]];
216    }
217   
218    [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplyFilter" object: nil];
219}
220
221- (void) setGroupFilter: (id) sender
222{
223    [[NSUserDefaults standardUserDefaults] setInteger: [sender tag] forKey: @"FilterGroup"];
224    [self updateGroupsButton];
225   
226    [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplyFilter" object: nil];
227}
228
229- (NSString *) searchString
230{
231    return [fSearchField stringValue];
232}
233
234- (void) setCountAll: (NSUInteger) all active: (NSUInteger) active downloading: (NSUInteger) downloading
235        seeding: (NSUInteger) seeding paused: (NSUInteger) paused
236{
237    [fNoFilterButton setCount: all];
238    [fActiveFilterButton setCount: active];
239    [fDownloadFilterButton setCount: downloading];
240    [fSeedFilterButton setCount: seeding];
241    [fPauseFilterButton setCount: paused];
242}
243
244- (void) menuNeedsUpdate: (NSMenu *) menu
245{
246    if (menu == [fGroupsButton menu])
247    {
248        for (NSInteger i = [menu numberOfItems]-1; i >= 3; i--)
249            [menu removeItemAtIndex: i];
250       
251        NSMenu * groupMenu = [[GroupsController groups] groupMenuWithTarget: self action: @selector(setGroupFilter:) isSmall: YES];
252       
253        const NSInteger groupMenuCount = [groupMenu numberOfItems];
254        for (NSInteger i = 0; i < groupMenuCount; i++)
255        {
256            NSMenuItem * item = [[groupMenu itemAtIndex: 0] retain];
257            [groupMenu removeItemAtIndex: 0];
258            [menu addItem: item];
259            [item release];
260        }
261    }
262}
263
264- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
265{
266    const SEL action = [menuItem action];
267   
268    //check proper filter search item
269    if (action == @selector(setSearchType:))
270    {
271        NSString * filterType = [[NSUserDefaults standardUserDefaults] stringForKey: @"FilterSearchType"];
272       
273        BOOL state;
274        if ([menuItem tag] == FILTER_TYPE_TAG_TRACKER)
275            state = [filterType isEqualToString: FILTER_TYPE_TRACKER];
276        else
277            state = [filterType isEqualToString: FILTER_TYPE_NAME];
278       
279        [menuItem setState: state ? NSOnState : NSOffState];
280        return YES;
281    }
282   
283    if (action == @selector(setGroupFilter:))
284    {
285        [menuItem setState: [menuItem tag] == [[NSUserDefaults standardUserDefaults] integerForKey: @"FilterGroup"]
286                                                ? NSOnState : NSOffState];
287        return YES;
288    }
289   
290    return YES;
291}
292
293@end
294
295@implementation FilterBarController (Private)
296
297- (void) resizeBar
298{
299    //replace all buttons
300    [fNoFilterButton sizeToFit];
301    [fActiveFilterButton sizeToFit];
302    [fDownloadFilterButton sizeToFit];
303    [fSeedFilterButton sizeToFit];
304    [fPauseFilterButton sizeToFit];
305   
306    NSRect allRect = [fNoFilterButton frame];
307    NSRect activeRect = [fActiveFilterButton frame];
308    NSRect downloadRect = [fDownloadFilterButton frame];
309    NSRect seedRect = [fSeedFilterButton frame];
310    NSRect pauseRect = [fPauseFilterButton frame];
311   
312    //size search filter to not overlap buttons
313    NSRect searchFrame = [fSearchField frame];
314    searchFrame.origin.x = NSMaxX(pauseRect) + 5.0;
315    searchFrame.size.width = NSWidth([[self view] frame]) - searchFrame.origin.x - 5.0;
316   
317    //make sure it is not too long
318    if (NSWidth(searchFrame) > SEARCH_MAX_WIDTH)
319    {
320        searchFrame.origin.x += NSWidth(searchFrame) - SEARCH_MAX_WIDTH;
321        searchFrame.size.width = SEARCH_MAX_WIDTH;
322    }
323    else if (NSWidth(searchFrame) < SEARCH_MIN_WIDTH)
324    {
325        searchFrame.origin.x += NSWidth(searchFrame) - SEARCH_MIN_WIDTH;
326        searchFrame.size.width = SEARCH_MIN_WIDTH;
327       
328        //calculate width the buttons can take up
329        const CGFloat allowedWidth = (searchFrame.origin.x - 5.0) - allRect.origin.x;
330        const CGFloat currentWidth = NSWidth(allRect) + NSWidth(activeRect) + NSWidth(downloadRect) + NSWidth(seedRect)
331                                        + NSWidth(pauseRect) + 4.0; //add 4 for space between buttons
332        const CGFloat ratio = allowedWidth / currentWidth;
333       
334        //decrease button widths proportionally
335        allRect.size.width  = NSWidth(allRect) * ratio;
336        activeRect.size.width = NSWidth(activeRect) * ratio;
337        downloadRect.size.width = NSWidth(downloadRect) * ratio;
338        seedRect.size.width = NSWidth(seedRect) * ratio;
339        pauseRect.size.width = NSWidth(pauseRect) * ratio;
340    }
341    else;
342   
343    activeRect.origin.x = NSMaxX(allRect) + 1.0;
344    downloadRect.origin.x = NSMaxX(activeRect) + 1.0;
345    seedRect.origin.x = NSMaxX(downloadRect) + 1.0;
346    pauseRect.origin.x = NSMaxX(seedRect) + 1.0;
347   
348    [fNoFilterButton setFrame: allRect];
349    [fActiveFilterButton setFrame: activeRect];
350    [fDownloadFilterButton setFrame: downloadRect];
351    [fSeedFilterButton setFrame: seedRect];
352    [fPauseFilterButton setFrame: pauseRect];
353   
354    [fSearchField setFrame: searchFrame];
355}
356
357- (void) updateGroupsButton
358{
359    const NSInteger groupIndex = [[NSUserDefaults standardUserDefaults] integerForKey: @"FilterGroup"];
360   
361    NSImage * icon;
362    NSString * toolTip;
363    if (groupIndex == GROUP_FILTER_ALL_TAG)
364    {
365        icon = [NSImage imageNamed: @"PinTemplate.png"];
366        toolTip = NSLocalizedString(@"All Groups", "Groups -> Button");
367    }
368    else
369    {
370        icon = [[GroupsController groups] imageForIndex: groupIndex];
371        NSString * groupName = groupIndex != -1 ? [[GroupsController groups] nameForIndex: groupIndex]
372                                                : NSLocalizedString(@"None", "Groups -> Button");
373        toolTip = [NSLocalizedString(@"Group", "Groups -> Button") stringByAppendingFormat: @": %@", groupName];
374    }
375   
376    [[[fGroupsButton menu] itemAtIndex: 0] setImage: icon];
377    [fGroupsButton setToolTip: toolTip];
378}
379
380- (void) updateGroups: (NSNotification *) notification
381{
382    [self updateGroupsButton];
383   
384    [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplyFilter" object: nil];
385}
386
387@end
Note: See TracBrowser for help on using the repository browser.