Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfManager/XspfMLibraryViewController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 380 - (hide annotations) (download)
Sun Jun 6 09:15:24 2010 UTC (13 years, 10 months ago) by masakih
File size: 17130 byte(s)
ライブラリを並べ替えられるようにした。(#20747)
1 masaki 41 //
2     // XspfMLibraryViewController.m
3     // XspfManager
4     //
5     // Created by Hori,Masaki on 09/11/08.
6     //
7    
8 masakih 350 /*
9 masakih 365 This source code is release under the New BSD License.
10 masakih 350 Copyright (c) 2009-2010, masakih
11     All rights reserved.
12    
13 masakih 365 ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満たす場合に
14     限り、再頒布および使用が許可されます。
15    
16     1, ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項を含
17     めること。
18     2, バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作権表
19     示、本条件一覧、および下記免責条項を含めること。
20     3, 書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進に、
21     コントリビューターの名前を使用してはならない。
22     本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供されており、
23     明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性に関する暗黙の保証
24     も含め、またそれに限定されない、いかなる保証もありません。著作権者もコントリビューター
25     も、事由のいかんを問わず、 損害発生の原因いかんを問わず、かつ責任の根拠が契約であるか
26     厳格責任であるか(過失その他の)不法行為であるかを問わず、仮にそのような損害が発生する
27     可能性を知らされていたとしても、本ソフトウェアの使用によって発生した(代替品または代用
28     サービスの調達、使用の喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定
29     されない)直接損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害につい
30     て、一切責任を負わないものとします。
31 masakih 350 -------------------------------------------------------------------
32     Copyright (c) 2009-2010, masakih
33     All rights reserved.
34    
35 masakih 365 Redistribution and use in source and binary forms, with or without
36     modification, are permitted provided that the following conditions
37     are met:
38 masakih 350
39 masakih 365 1, Redistributions of source code must retain the above copyright
40     notice, this list of conditions and the following disclaimer.
41     2, Redistributions in binary form must reproduce the above copyright
42     notice, this list of conditions and the following disclaimer in
43     the documentation and/or other materials provided with the
44     distribution.
45     3, The names of its contributors may be used to endorse or promote
46     products derived from this software without specific prior
47     written permission.
48     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
51     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
52     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
53     INCIDENTAL, SPECIAL,EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
54     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
56     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
58     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59     POSSIBILITY OF SUCH DAMAGE.
60 masakih 350 */
61    
62 masaki 41 #import "XspfMLibraryViewController.h"
63    
64 masaki 113 #import "XspfMXspfListObject.h"
65    
66 masakih 366 #import "XspfMRuleEditorDelegate.h"
67 masaki 113
68 masakih 366
69 masaki 43 @interface XspfMLibraryViewController (HMPrivate)
70     - (NSArray *)sortDescriptors;
71     - (void)setupXspfList;
72 masakih 366 - (void)setupRules;
73 masakih 380
74     - (NSNumber *)orderForNewItem;
75    
76     - (void)moveItemOfIndexSet:(NSIndexSet *)indexSet afterIndex:(NSInteger)afterIndex;
77 masaki 43 @end
78 masaki 41
79 masaki 113 enum {
80     kLibraryOrder = 0,
81     kFavoritesOrder,
82     kSmartLibraryOrder,
83     };
84    
85 masakih 380 const NSInteger initialOrder = 10000;
86     const NSInteger orderStep = 10000;
87    
88     static NSString *const XspfMLibItemPbardType = @"XspfMLibItemPbardType";
89    
90 masaki 41 @implementation XspfMLibraryViewController
91 masaki 113
92 masaki 41 - (id)init
93     {
94     [super initWithNibName:@"LibraryView" bundle:nil];
95    
96 masaki 43 [self setupXspfList];
97 masakih 366 [self setupRules];
98 masaki 43
99 masaki 41 return self;
100     }
101    
102 masaki 43 - (void)awakeFromNib
103     {
104     [[self representedObject] setSortDescriptors:[self sortDescriptors]];
105 masakih 380
106     [tableView registerForDraggedTypes:[NSArray arrayWithObject:XspfMLibItemPbardType]];
107     [tableView setDraggingSourceOperationMask:NSDragOperationMove forLocal:YES];
108 masaki 43 }
109 masaki 41 - (NSArray *)sortDescriptors
110     {
111 masaki 61 id desc = [[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES];
112     return [NSArray arrayWithObject:[desc autorelease]];
113 masaki 41 }
114 masaki 43
115 masaki 113 - (void)addSmartLibrary:(NSString *)name predicate:(NSPredicate *)predicate order:(NSInteger)order
116     {
117     id obj = [NSEntityDescription insertNewObjectForEntityForName:@"XspfList"
118     inManagedObjectContext:[self managedObjectContext]];
119     [obj setValue:predicate forKey:@"predicate"];
120     [obj setValue:name forKey:@"name"];
121 masakih 380 [obj setValue:[self orderForNewItem] forKey:@"order"];
122 masaki 113 }
123 masaki 43 - (void)setupXspfList
124     {
125 masaki 48 NSManagedObjectContext *moc = [self managedObjectContext];
126 masaki 43 NSError *error = nil;
127     NSFetchRequest *fetch;
128     NSInteger num;
129    
130     fetch = [[[NSFetchRequest alloc] init] autorelease];
131     [fetch setEntity:[NSEntityDescription entityForName:@"XspfList"
132     inManagedObjectContext:moc]];
133     num = [moc countForFetchRequest:fetch
134     error:&error];
135     if(num != 0) return;
136    
137     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"urlString <> %@", @""];
138 masaki 268 [self addSmartLibrary:@"Library"
139 masaki 113 predicate:predicate
140     order:kLibraryOrder];
141 masaki 43
142     predicate = [NSPredicate predicateWithFormat:@"favorites = %@", [NSNumber numberWithBool:YES]];
143 masaki 268 [self addSmartLibrary:@"Favorites"
144 masaki 113 predicate:predicate
145     order:kFavoritesOrder];
146 masaki 43 }
147    
148 masakih 366 - (void)setupRules
149     {
150     [XspfMRuleEditorDelegate registerStringTypeKeyPaths:[NSArray arrayWithObjects:@"title", @"information.voiceActorsList", @"information.productsList", nil]];
151     [XspfMRuleEditorDelegate registerDateTypeKeyPaths:[NSArray arrayWithObjects:@"lastPlayDate", @"modificationDate", @"creationDate", nil]];
152     [XspfMRuleEditorDelegate setUseRating:YES];
153     [XspfMRuleEditorDelegate setUseLablel:YES];
154     }
155    
156 masaki 235 - (BOOL)mouseInTableView
157     {
158     NSEvent *event = [[[self view] window] currentEvent];
159     NSPoint mouse = [[tableView superview] convertPoint:[event locationInWindow] fromView:nil];
160    
161     return NSPointInRect(mouse, [tableView visibleRect]);
162     }
163 masaki 113 - (XspfMXspfListObject *)targetObject
164     {
165     id array = [[self representedObject] arrangedObjects];
166    
167     NSInteger row = [tableView clickedRow];
168     if(row >= 0 && [array count] > row) {
169     return [array objectAtIndex:row];
170     }
171 masaki 235
172     if(![self mouseInTableView]) {
173     NSArray *selection = [[self representedObject] selectedObjects];
174     if([selection count] != 0) {
175     return [selection objectAtIndex:0];
176     }
177     }
178 masaki 113 return nil;
179     }
180 masaki 235
181    
182 masaki 116 - (BOOL)canUseNewSmartLibraryName:(NSString *)newName
183     {
184     NSManagedObjectContext *moc = [self managedObjectContext];
185     NSError *error = nil;
186     NSFetchRequest *fetch;
187     NSPredicate *predicate;
188     NSInteger num;
189    
190     fetch = [[[NSFetchRequest alloc] init] autorelease];
191     [fetch setEntity:[NSEntityDescription entityForName:@"XspfList"
192     inManagedObjectContext:moc]];
193     predicate = [NSPredicate predicateWithFormat:@"name = %@", newName];
194     [fetch setPredicate:predicate];
195     num = [moc countForFetchRequest:fetch
196     error:&error];
197    
198     return num == 0;
199     }
200     - (NSString *)newSmartLibraryName
201     {
202     NSString *template = NSLocalizedString(@"Untitled Library", @"Untitled Library");
203    
204     if([self canUseNewSmartLibraryName:template]) return template;
205    
206     NSInteger i = 1;
207     do {
208     NSString *name = [NSString stringWithFormat:@"%@ %d", template, i];
209     if([self canUseNewSmartLibraryName:name]) return name;
210     } while (i++ < INT_MAX);
211    
212     return @"hoge";
213     }
214 masaki 112 - (IBAction)newPredicate:(id)sender
215 masaki 43 {
216 masaki 112 if([editor numberOfRows] == 0) {
217     [editor addRow:self];
218     }
219 masaki 147
220 masaki 116 [nameField setStringValue:[self newSmartLibraryName]];
221 masaki 113 [nameField selectText:self];
222    
223 masaki 112 [NSApp beginSheet:predicatePanel
224     modalForWindow:[tableView window]
225     modalDelegate:self
226     didEndSelector:@selector(didEndEditPredicate:returnCode:contextInfo:)
227     contextInfo:@"Createion"];
228 masaki 43 }
229 masaki 113 - (IBAction)editPredicate:(id)sender
230     {
231 masaki 235 XspfMXspfListObject *obj = [sender representedObject];
232     if(!obj) {
233     HMLog(HMLogLevelError, @"-[%@ %@] paramater's representedObject is nil.",
234     NSStringFromClass([self class]), NSStringFromSelector(_cmd));
235     return;
236     }
237 masaki 113 [nameField setStringValue:obj.name];
238     [nameField selectText:self];
239    
240 masaki 123 [ruleEditorDelegate setPredicate:obj.predicate];
241 masaki 113
242     [NSApp beginSheet:predicatePanel
243     modalForWindow:[tableView window]
244     modalDelegate:self
245     didEndSelector:@selector(didEndEditPredicate:returnCode:contextInfo:)
246     contextInfo:obj];
247     }
248     - (IBAction)deletePredicate:(id)sender
249     {
250 masaki 235 XspfMXspfListObject *obj = [sender representedObject];
251     if(!obj) {
252     HMLog(HMLogLevelError, @"-[%@ %@] paramater's representedObject is nil.",
253     NSStringFromClass([self class]), NSStringFromSelector(_cmd));
254     return;
255     }
256 masaki 113 NSBeginInformationalAlertSheet(nil, nil, @"Cancel", nil, [[self view] window],
257     self, @selector(didEndAskDelete:::), Nil, obj,
258 masaki 118 NSLocalizedString(@"Do you really delete smart library \"%@\"?", @"Do you really delete smart library \"%@\"?"),
259     obj.name);
260 masaki 113 }
261 masaki 112 - (IBAction)didEndEditPredicate:(id)sender
262     {
263     [predicatePanel orderOut:self];
264     [NSApp endSheet:predicatePanel returnCode:[sender tag]];
265     }
266 masaki 118
267     - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
268     {
269     SEL action = [menuItem action];
270     if(action == @selector(editPredicate:)
271     || action == @selector(deletePredicate:)) {
272     XspfMXspfListObject *obj = [self targetObject];
273     if(!obj) return NO;
274     if(obj.order == kLibraryOrder || obj.order == kFavoritesOrder) return NO;
275 masaki 235 [menuItem setRepresentedObject:obj];
276 masaki 118 }
277    
278     return YES;
279     }
280 masakih 362
281 masaki 112 - (void)didEndEditPredicate:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
282     {
283     if(returnCode == NSCancelButton) return;
284    
285 masaki 147 [editor reloadPredicate];
286     NSPredicate *predicate = [editor predicate];
287 masaki 122
288 masaki 125 if(!predicate || ![predicate isKindOfClass:[NSPredicate class]]) {
289 masaki 188 HMLog(HMLogLevelError, @"Could not create NSPredicate.");
290 masaki 125 NSBeep();
291     return;
292     }
293 masaki 126 if(![predicate isKindOfClass:[NSCompoundPredicate class]]) {
294     predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:predicate]];
295     }
296 masakih 380
297 masaki 113 NSString *name = [nameField stringValue];
298     if([name length] == 0) {
299     NSBeep();
300     NSBeginAlertSheet(nil, nil, nil, nil, [[self view] window],
301     self, @selector(retryEditPredicate:::), Nil, contextInfo,
302 masaki 118 NSLocalizedString(@"Name must not be empty.", @"Name must not be empty."));
303 masaki 116 return;
304 masaki 113 }
305 masaki 112
306 masaki 113 if([(id)contextInfo isKindOfClass:[NSString class]]) {
307     [self addSmartLibrary:name predicate:predicate order:kSmartLibraryOrder];
308     } else {
309     XspfMXspfListObject *obj = contextInfo;
310     obj.name = name;
311     obj.predicate = predicate;
312     }
313 masaki 112 }
314 masaki 113 - (void)retryEditPredicate:(NSWindow *)sheet :(NSInteger)returnCode :(void *)contextInfo
315     {
316     if([(id)contextInfo isKindOfClass:[NSString class]]) {
317     [self performSelector:@selector(newPredicate:) withObject:nil afterDelay:0.0];
318     } else {
319     [self performSelector:@selector(editPredicate:) withObject:nil afterDelay:0.0];
320     }
321     }
322     - (void)didEndAskDelete:(NSWindow *)sheet :(NSInteger)returnCode :(void *)contextInfo
323     {
324     if(returnCode == NSCancelButton) return;
325    
326     [[self managedObjectContext] deleteObject:contextInfo];
327     }
328 masaki 120
329 masakih 380 #pragma mark#### NSTableView Data Source ####
330     - (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
331     {
332     if([rowIndexes containsIndex:0] || [rowIndexes containsIndex:1]) return NO;
333    
334     [pboard declareTypes:[NSArray arrayWithObject:XspfMLibItemPbardType] owner:self];
335    
336     return [pboard setData:[NSKeyedArchiver archivedDataWithRootObject:rowIndexes] forType:XspfMLibItemPbardType];
337     }
338    
339     - (NSDragOperation)tableView:(NSTableView*)aTableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation
340     {
341     if(row == 0 || row == 1) return NSDragOperationNone;
342    
343     if(dropOperation == NSTableViewDropOn) {
344     [aTableView setDropRow:row
345     dropOperation:NSTableViewDropAbove];
346     }
347    
348     return NSDragOperationMove;
349     }
350    
351     - (BOOL)tableView:(NSTableView*)aTableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation
352     {
353     NSPasteboard *pboard = [info draggingPasteboard];
354     NSIndexSet *indexSet = [NSKeyedUnarchiver unarchiveObjectWithData:[pboard dataForType:XspfMLibItemPbardType]];
355    
356     NSLog(@"row -> %ld", (long)row);
357     // [self willChangeValueForKey:@"representedObject.arrangedObjects"];
358     // [self willChangeValueForKey:@"representedObject.selectionIndexes"];
359     [self moveItemOfIndexSet:indexSet afterIndex:row - 1];
360     // [self didChangeValueForKey:@"representedObject.selectionIndexes"];
361     // [self didChangeValueForKey:@"representedObject.arrangedObjects"];
362    
363     // [aTableView reloadData];
364     [xspfListController rearrangeObjects];
365    
366     return YES;
367     }
368    
369    
370     #pragma mark-
371     - (void)packOrder
372     {
373     NSManagedObjectContext *moc = [self managedObjectContext];
374     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"order <> %@ AND order <> %@",
375     [NSNumber numberWithInt:kLibraryOrder], [NSNumber numberWithInt:kFavoritesOrder]];
376     NSEntityDescription *entry = [NSEntityDescription entityForName:@"XspfList"
377     inManagedObjectContext:moc];
378     NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
379     [fetch setEntity:entry];
380     [fetch setPredicate:predicate];
381     [fetch setSortDescriptors:[self sortDescriptors]];
382    
383     NSError *error = nil;
384     NSArray *objects = [moc executeFetchRequest:fetch error:&error];
385     if(!objects) {
386     if(error) {
387     HMLog(HMLogLevelError, @"fail fetch reason -> %@", error);
388     }
389     }
390    
391     NSInteger newOrder = initialOrder;
392     for(XspfMXspfListObject *obj in objects) {
393     obj.order = newOrder;
394     newOrder += orderStep;
395     }
396     }
397    
398     - (NSNumber *)orderForNewItem
399     {
400     NSManagedObjectContext *moc = [self managedObjectContext];
401     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"order <> %@ AND order <> %@",
402     [NSNumber numberWithInt:kLibraryOrder], [NSNumber numberWithInt:kFavoritesOrder]];
403     NSEntityDescription *entry = [NSEntityDescription entityForName:@"XspfList"
404     inManagedObjectContext:moc];
405     NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
406     [fetch setEntity:entry];
407     [fetch setPredicate:predicate];
408     [fetch setSortDescriptors:[NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"order" ascending:NO] autorelease]]];
409     [fetch setFetchLimit:1];
410    
411     NSError *error = nil;
412     NSArray *objects = [moc executeFetchRequest:fetch error:&error];
413     if(!objects) {
414     if(error) {
415     HMLog(HMLogLevelError, @"fail fetch reason -> %@", error);
416     }
417     }
418     HMLog(HMLogLevelDebug, @"objects -> %@", objects);
419    
420     if(!objects && [objects count] == 0) return [NSNumber numberWithInteger:initialOrder];
421     XspfMXspfListObject *last = [objects lastObject];
422    
423     return [NSNumber numberWithInteger:last.order + orderStep];
424     }
425    
426     - (void)moveToLastFromIndexSet:(NSIndexSet *)indexSet
427     {
428     id array = [[self representedObject] arrangedObjects];
429     XspfMXspfListObject *afterItem = [array lastObject];
430     NSInteger insertPoint = afterItem.order + orderStep;
431     NSUInteger targetIndex = [indexSet firstIndex];
432     while(targetIndex != NSNotFound) {
433     XspfMXspfListObject *targetItem = [array objectAtIndex:targetIndex];
434     targetItem.order = insertPoint;
435     insertPoint += orderStep;
436    
437     targetIndex = [indexSet indexGreaterThanIndex:targetIndex];
438     }
439     }
440     - (void)moveItemOfIndexSet:(NSIndexSet *)indexSet afterIndex:(NSInteger)afterIndex
441     {
442     id array = [[self representedObject] arrangedObjects];
443    
444     if([array count] <= afterIndex + 1) {
445     [self moveToLastFromIndexSet:indexSet];
446     return;
447     }
448    
449     XspfMXspfListObject *afterItem = [array objectAtIndex:afterIndex];
450     XspfMXspfListObject *beforeItem = [array objectAtIndex:afterIndex + 1];
451    
452     NSInteger diff = beforeItem.order - afterItem.order;
453     if(diff - 1 < [indexSet count]) {
454     [self packOrder];
455     [self moveItemOfIndexSet:indexSet afterIndex:afterIndex];
456     return;
457     }
458    
459     NSInteger step = diff / ([indexSet count] + 1);
460     NSInteger insertPoint = afterItem.order + step;
461     NSUInteger targetIndex = [indexSet firstIndex];
462     while(targetIndex != NSNotFound) {
463     XspfMXspfListObject *targetItem = [array objectAtIndex:targetIndex];
464     targetItem.order = insertPoint;
465     insertPoint += step;
466    
467     targetIndex = [indexSet indexGreaterThanIndex:targetIndex];
468     }
469    
470     [self packOrder];
471     }
472    
473     #pragma mark-
474    
475 masaki 112 - (IBAction)test01:(id)sender
476     {
477 masaki 147 // NSArray *array = [editor rowTemplates];
478 masaki 112
479     // for(id templ in array) {
480 masaki 188 // HMLog(HMLogLevelDebug @"Views -> %@", [templ templateViews]);
481 masaki 112 // for(id v in [templ templateViews]) {
482     // if([v respondsToSelector:@selector(tag)]) {
483 masaki 188 // HMLog(HMLogLevelDebug, @"tag -> %d", [v tag]);
484 masaki 112 // }
485     // }
486     // }
487 masaki 147 // for(id templ in array) {
488 masaki 188 // HMLog(HMLogLevelDebug, @"template -> %@", templ);
489 masaki 147 // }
490 masaki 112 }
491 masaki 43
492 masaki 41 @end

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26