Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfManager/XspfMLibraryViewController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 549 - (hide annotations) (download)
Sun Feb 6 16:17:22 2011 UTC (13 years, 2 months ago) by masakih
File size: 18246 byte(s)
[Mod] 使用していないテストコードをコメントアウト。
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 381 #import "XspfMPreferences.h"
69 masakih 366
70 masakih 381
71 masaki 43 @interface XspfMLibraryViewController (HMPrivate)
72     - (NSArray *)sortDescriptors;
73     - (void)setupXspfList;
74 masakih 366 - (void)setupRules;
75 masakih 380
76     - (NSNumber *)orderForNewItem;
77    
78     - (void)moveItemOfIndexSet:(NSIndexSet *)indexSet afterIndex:(NSInteger)afterIndex;
79 masaki 43 @end
80 masaki 41
81 masaki 113 enum {
82     kLibraryOrder = 0,
83     kFavoritesOrder,
84     kSmartLibraryOrder,
85     };
86    
87 masakih 380 const NSInteger initialOrder = 10000;
88     const NSInteger orderStep = 10000;
89    
90     static NSString *const XspfMLibItemPbardType = @"XspfMLibItemPbardType";
91    
92 masaki 41 @implementation XspfMLibraryViewController
93 masaki 113
94 masaki 41 - (id)init
95     {
96     [super initWithNibName:@"LibraryView" bundle:nil];
97    
98 masaki 43 [self setupXspfList];
99 masakih 366 [self setupRules];
100 masaki 43
101 masaki 41 return self;
102     }
103    
104 masakih 381 - (void)dealloc
105     {
106     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
107     [nc removeObserver:self];
108    
109     [super dealloc];
110     }
111    
112 masaki 43 - (void)awakeFromNib
113     {
114     [[self representedObject] setSortDescriptors:[self sortDescriptors]];
115 masakih 380
116     [tableView registerForDraggedTypes:[NSArray arrayWithObject:XspfMLibItemPbardType]];
117     [tableView setDraggingSourceOperationMask:NSDragOperationMove forLocal:YES];
118 masakih 381
119    
120     [self performSelector:@selector(delayExcute:) withObject:self afterDelay:0.02];
121 masaki 43 }
122 masakih 381 - (void)delayExcute:(id)dummy
123     {
124     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
125     [nc addObserver:self
126     selector:@selector(windowWillClose:)
127     name:NSWindowWillCloseNotification
128     object:[self.view window]];
129    
130     XspfMPreferences *pref = [XspfMPreferences sharedPreference];
131     [xspfListController setSelectionIndex:pref.libraryLastSelectedIndexSet];
132     }
133    
134 masaki 41 - (NSArray *)sortDescriptors
135     {
136 masaki 61 id desc = [[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES];
137     return [NSArray arrayWithObject:[desc autorelease]];
138 masaki 41 }
139 masaki 43
140 masaki 113 - (void)addSmartLibrary:(NSString *)name predicate:(NSPredicate *)predicate order:(NSInteger)order
141     {
142     id obj = [NSEntityDescription insertNewObjectForEntityForName:@"XspfList"
143     inManagedObjectContext:[self managedObjectContext]];
144     [obj setValue:predicate forKey:@"predicate"];
145     [obj setValue:name forKey:@"name"];
146 masakih 380 [obj setValue:[self orderForNewItem] forKey:@"order"];
147 masaki 113 }
148 masaki 43 - (void)setupXspfList
149     {
150 masaki 48 NSManagedObjectContext *moc = [self managedObjectContext];
151 masaki 43 NSError *error = nil;
152     NSFetchRequest *fetch;
153     NSInteger num;
154    
155     fetch = [[[NSFetchRequest alloc] init] autorelease];
156     [fetch setEntity:[NSEntityDescription entityForName:@"XspfList"
157     inManagedObjectContext:moc]];
158     num = [moc countForFetchRequest:fetch
159     error:&error];
160     if(num != 0) return;
161    
162     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"urlString <> %@", @""];
163 masaki 268 [self addSmartLibrary:@"Library"
164 masaki 113 predicate:predicate
165     order:kLibraryOrder];
166 masaki 43
167     predicate = [NSPredicate predicateWithFormat:@"favorites = %@", [NSNumber numberWithBool:YES]];
168 masaki 268 [self addSmartLibrary:@"Favorites"
169 masaki 113 predicate:predicate
170     order:kFavoritesOrder];
171 masaki 43 }
172    
173 masakih 366 - (void)setupRules
174     {
175     [XspfMRuleEditorDelegate registerStringTypeKeyPaths:[NSArray arrayWithObjects:@"title", @"information.voiceActorsList", @"information.productsList", nil]];
176     [XspfMRuleEditorDelegate registerDateTypeKeyPaths:[NSArray arrayWithObjects:@"lastPlayDate", @"modificationDate", @"creationDate", nil]];
177     [XspfMRuleEditorDelegate setUseRating:YES];
178     [XspfMRuleEditorDelegate setUseLablel:YES];
179     }
180    
181 masaki 235 - (BOOL)mouseInTableView
182     {
183     NSEvent *event = [[[self view] window] currentEvent];
184     NSPoint mouse = [[tableView superview] convertPoint:[event locationInWindow] fromView:nil];
185    
186     return NSPointInRect(mouse, [tableView visibleRect]);
187     }
188 masaki 113 - (XspfMXspfListObject *)targetObject
189     {
190     id array = [[self representedObject] arrangedObjects];
191    
192     NSInteger row = [tableView clickedRow];
193     if(row >= 0 && [array count] > row) {
194     return [array objectAtIndex:row];
195     }
196 masaki 235
197     if(![self mouseInTableView]) {
198     NSArray *selection = [[self representedObject] selectedObjects];
199     if([selection count] != 0) {
200     return [selection objectAtIndex:0];
201     }
202     }
203 masaki 113 return nil;
204     }
205 masaki 235
206    
207 masaki 116 - (BOOL)canUseNewSmartLibraryName:(NSString *)newName
208     {
209     NSManagedObjectContext *moc = [self managedObjectContext];
210     NSError *error = nil;
211     NSFetchRequest *fetch;
212     NSPredicate *predicate;
213     NSInteger num;
214    
215     fetch = [[[NSFetchRequest alloc] init] autorelease];
216     [fetch setEntity:[NSEntityDescription entityForName:@"XspfList"
217     inManagedObjectContext:moc]];
218     predicate = [NSPredicate predicateWithFormat:@"name = %@", newName];
219     [fetch setPredicate:predicate];
220     num = [moc countForFetchRequest:fetch
221     error:&error];
222    
223     return num == 0;
224     }
225 masakih 393 - (NSString *)usableSmartLibraryName
226 masaki 116 {
227     NSString *template = NSLocalizedString(@"Untitled Library", @"Untitled Library");
228    
229     if([self canUseNewSmartLibraryName:template]) return template;
230    
231     NSInteger i = 1;
232     do {
233     NSString *name = [NSString stringWithFormat:@"%@ %d", template, i];
234     if([self canUseNewSmartLibraryName:name]) return name;
235     } while (i++ < INT_MAX);
236    
237     return @"hoge";
238     }
239 masakih 483
240     #pragma mark #### Actions ####
241 masakih 393 - (IBAction)createPredicate:(id)sender
242 masaki 43 {
243 masaki 112 if([editor numberOfRows] == 0) {
244     [editor addRow:self];
245     }
246 masaki 147
247 masakih 393 [nameField setStringValue:[self usableSmartLibraryName]];
248 masaki 113 [nameField selectText:self];
249    
250 masaki 112 [NSApp beginSheet:predicatePanel
251     modalForWindow:[tableView window]
252     modalDelegate:self
253     didEndSelector:@selector(didEndEditPredicate:returnCode:contextInfo:)
254     contextInfo:@"Createion"];
255 masaki 43 }
256 masaki 113 - (IBAction)editPredicate:(id)sender
257     {
258 masaki 235 XspfMXspfListObject *obj = [sender representedObject];
259     if(!obj) {
260     HMLog(HMLogLevelError, @"-[%@ %@] paramater's representedObject is nil.",
261     NSStringFromClass([self class]), NSStringFromSelector(_cmd));
262     return;
263     }
264 masaki 113 [nameField setStringValue:obj.name];
265     [nameField selectText:self];
266    
267 masaki 123 [ruleEditorDelegate setPredicate:obj.predicate];
268 masaki 113
269     [NSApp beginSheet:predicatePanel
270     modalForWindow:[tableView window]
271     modalDelegate:self
272     didEndSelector:@selector(didEndEditPredicate:returnCode:contextInfo:)
273     contextInfo:obj];
274     }
275     - (IBAction)deletePredicate:(id)sender
276     {
277 masaki 235 XspfMXspfListObject *obj = [sender representedObject];
278     if(!obj) {
279     HMLog(HMLogLevelError, @"-[%@ %@] paramater's representedObject is nil.",
280     NSStringFromClass([self class]), NSStringFromSelector(_cmd));
281     return;
282     }
283 masaki 113 NSBeginInformationalAlertSheet(nil, nil, @"Cancel", nil, [[self view] window],
284     self, @selector(didEndAskDelete:::), Nil, obj,
285 masaki 118 NSLocalizedString(@"Do you really delete smart library \"%@\"?", @"Do you really delete smart library \"%@\"?"),
286     obj.name);
287 masaki 113 }
288 masaki 112 - (IBAction)didEndEditPredicate:(id)sender
289     {
290     [predicatePanel orderOut:self];
291     [NSApp endSheet:predicatePanel returnCode:[sender tag]];
292     }
293 masakih 483 - (void)moveUp:(id)sender
294     {
295     NSUInteger row = [tableView selectedRow];
296     if(row == 0) return;
297    
298     NSIndexSet *newSelection = [NSIndexSet indexSetWithIndex:row - 1];
299     [tableView selectRowIndexes:newSelection byExtendingSelection:NO];
300     }
301     - (void)moveDown:(id)sender
302     {
303     NSUInteger row = [tableView selectedRow];
304     if(row == [tableView numberOfRows] - 1) return;
305    
306     NSIndexSet *newSelection = [NSIndexSet indexSetWithIndex:row + 1];
307     [tableView selectRowIndexes:newSelection byExtendingSelection:NO];
308     }
309 masaki 118
310     - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
311     {
312     SEL action = [menuItem action];
313     if(action == @selector(editPredicate:)
314     || action == @selector(deletePredicate:)) {
315     XspfMXspfListObject *obj = [self targetObject];
316     if(!obj) return NO;
317     if(obj.order == kLibraryOrder || obj.order == kFavoritesOrder) return NO;
318 masaki 235 [menuItem setRepresentedObject:obj];
319 masaki 118 }
320    
321     return YES;
322     }
323 masakih 362
324 masaki 112 - (void)didEndEditPredicate:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
325     {
326     if(returnCode == NSCancelButton) return;
327    
328 masaki 147 [editor reloadPredicate];
329     NSPredicate *predicate = [editor predicate];
330 masaki 122
331 masaki 125 if(!predicate || ![predicate isKindOfClass:[NSPredicate class]]) {
332 masaki 188 HMLog(HMLogLevelError, @"Could not create NSPredicate.");
333 masaki 125 NSBeep();
334     return;
335     }
336 masaki 126 if(![predicate isKindOfClass:[NSCompoundPredicate class]]) {
337     predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:predicate]];
338     }
339 masakih 380
340 masaki 113 NSString *name = [nameField stringValue];
341     if([name length] == 0) {
342     NSBeep();
343     NSBeginAlertSheet(nil, nil, nil, nil, [[self view] window],
344     self, @selector(retryEditPredicate:::), Nil, contextInfo,
345 masaki 118 NSLocalizedString(@"Name must not be empty.", @"Name must not be empty."));
346 masaki 116 return;
347 masaki 113 }
348 masaki 112
349 masaki 113 if([(id)contextInfo isKindOfClass:[NSString class]]) {
350     [self addSmartLibrary:name predicate:predicate order:kSmartLibraryOrder];
351     } else {
352     XspfMXspfListObject *obj = contextInfo;
353     obj.name = name;
354     obj.predicate = predicate;
355     }
356 masaki 112 }
357 masaki 113 - (void)retryEditPredicate:(NSWindow *)sheet :(NSInteger)returnCode :(void *)contextInfo
358     {
359     if([(id)contextInfo isKindOfClass:[NSString class]]) {
360 masakih 393 [self performSelector:@selector(createPredicate:) withObject:nil afterDelay:0.0];
361 masaki 113 } else {
362     [self performSelector:@selector(editPredicate:) withObject:nil afterDelay:0.0];
363     }
364     }
365     - (void)didEndAskDelete:(NSWindow *)sheet :(NSInteger)returnCode :(void *)contextInfo
366     {
367     if(returnCode == NSCancelButton) return;
368    
369     [[self managedObjectContext] deleteObject:contextInfo];
370     }
371 masaki 120
372 masakih 380 #pragma mark#### NSTableView Data Source ####
373     - (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
374     {
375     if([rowIndexes containsIndex:0] || [rowIndexes containsIndex:1]) return NO;
376    
377     [pboard declareTypes:[NSArray arrayWithObject:XspfMLibItemPbardType] owner:self];
378    
379     return [pboard setData:[NSKeyedArchiver archivedDataWithRootObject:rowIndexes] forType:XspfMLibItemPbardType];
380     }
381    
382     - (NSDragOperation)tableView:(NSTableView*)aTableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation
383     {
384     if(row == 0 || row == 1) return NSDragOperationNone;
385    
386     if(dropOperation == NSTableViewDropOn) {
387     [aTableView setDropRow:row
388     dropOperation:NSTableViewDropAbove];
389     }
390    
391     return NSDragOperationMove;
392     }
393    
394     - (BOOL)tableView:(NSTableView*)aTableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation
395     {
396     NSPasteboard *pboard = [info draggingPasteboard];
397     NSIndexSet *indexSet = [NSKeyedUnarchiver unarchiveObjectWithData:[pboard dataForType:XspfMLibItemPbardType]];
398    
399     [self moveItemOfIndexSet:indexSet afterIndex:row - 1];
400     [xspfListController rearrangeObjects];
401    
402     return YES;
403     }
404    
405    
406     #pragma mark-
407     - (void)packOrder
408     {
409     NSManagedObjectContext *moc = [self managedObjectContext];
410     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"order <> %@ AND order <> %@",
411     [NSNumber numberWithInt:kLibraryOrder], [NSNumber numberWithInt:kFavoritesOrder]];
412     NSEntityDescription *entry = [NSEntityDescription entityForName:@"XspfList"
413     inManagedObjectContext:moc];
414     NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
415     [fetch setEntity:entry];
416     [fetch setPredicate:predicate];
417     [fetch setSortDescriptors:[self sortDescriptors]];
418    
419     NSError *error = nil;
420     NSArray *objects = [moc executeFetchRequest:fetch error:&error];
421     if(!objects) {
422     if(error) {
423     HMLog(HMLogLevelError, @"fail fetch reason -> %@", error);
424     }
425     }
426    
427     NSInteger newOrder = initialOrder;
428     for(XspfMXspfListObject *obj in objects) {
429     obj.order = newOrder;
430     newOrder += orderStep;
431     }
432     }
433    
434     - (NSNumber *)orderForNewItem
435     {
436     NSManagedObjectContext *moc = [self managedObjectContext];
437     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"order <> %@ AND order <> %@",
438     [NSNumber numberWithInt:kLibraryOrder], [NSNumber numberWithInt:kFavoritesOrder]];
439     NSEntityDescription *entry = [NSEntityDescription entityForName:@"XspfList"
440     inManagedObjectContext:moc];
441     NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
442     [fetch setEntity:entry];
443     [fetch setPredicate:predicate];
444     [fetch setSortDescriptors:[NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"order" ascending:NO] autorelease]]];
445     [fetch setFetchLimit:1];
446    
447     NSError *error = nil;
448     NSArray *objects = [moc executeFetchRequest:fetch error:&error];
449     if(!objects) {
450     if(error) {
451     HMLog(HMLogLevelError, @"fail fetch reason -> %@", error);
452     }
453     }
454     HMLog(HMLogLevelDebug, @"objects -> %@", objects);
455    
456     if(!objects && [objects count] == 0) return [NSNumber numberWithInteger:initialOrder];
457     XspfMXspfListObject *last = [objects lastObject];
458    
459     return [NSNumber numberWithInteger:last.order + orderStep];
460     }
461    
462     - (void)moveToLastFromIndexSet:(NSIndexSet *)indexSet
463     {
464     id array = [[self representedObject] arrangedObjects];
465     XspfMXspfListObject *afterItem = [array lastObject];
466     NSInteger insertPoint = afterItem.order + orderStep;
467     NSUInteger targetIndex = [indexSet firstIndex];
468     while(targetIndex != NSNotFound) {
469     XspfMXspfListObject *targetItem = [array objectAtIndex:targetIndex];
470     targetItem.order = insertPoint;
471     insertPoint += orderStep;
472    
473     targetIndex = [indexSet indexGreaterThanIndex:targetIndex];
474     }
475     }
476     - (void)moveItemOfIndexSet:(NSIndexSet *)indexSet afterIndex:(NSInteger)afterIndex
477     {
478     id array = [[self representedObject] arrangedObjects];
479    
480     if([array count] <= afterIndex + 1) {
481     [self moveToLastFromIndexSet:indexSet];
482     return;
483     }
484    
485     XspfMXspfListObject *afterItem = [array objectAtIndex:afterIndex];
486     XspfMXspfListObject *beforeItem = [array objectAtIndex:afterIndex + 1];
487    
488     NSInteger diff = beforeItem.order - afterItem.order;
489     if(diff - 1 < [indexSet count]) {
490     [self packOrder];
491     [self moveItemOfIndexSet:indexSet afterIndex:afterIndex];
492     return;
493     }
494    
495     NSInteger step = diff / ([indexSet count] + 1);
496     NSInteger insertPoint = afterItem.order + step;
497     NSUInteger targetIndex = [indexSet firstIndex];
498     while(targetIndex != NSNotFound) {
499     XspfMXspfListObject *targetItem = [array objectAtIndex:targetIndex];
500     targetItem.order = insertPoint;
501     insertPoint += step;
502    
503     targetIndex = [indexSet indexGreaterThanIndex:targetIndex];
504     }
505    
506     [self packOrder];
507     }
508    
509 masakih 381 #pragma mark#### NSWindow Delegate ####
510     - (void)windowWillClose:(NSNotification *)notification
511     {
512     if(self.view.window != notification.object) return;
513    
514     XspfMPreferences *pref = [XspfMPreferences sharedPreference];
515     pref.libraryLastSelectedIndexSet = xspfListController.selectionIndex;
516     }
517    
518 masakih 380 #pragma mark-
519    
520 masakih 549 //- (IBAction)test01:(id)sender
521     //{
522 masaki 147 // NSArray *array = [editor rowTemplates];
523 masaki 112
524     // for(id templ in array) {
525 masaki 188 // HMLog(HMLogLevelDebug @"Views -> %@", [templ templateViews]);
526 masaki 112 // for(id v in [templ templateViews]) {
527     // if([v respondsToSelector:@selector(tag)]) {
528 masaki 188 // HMLog(HMLogLevelDebug, @"tag -> %d", [v tag]);
529 masaki 112 // }
530     // }
531     // }
532 masaki 147 // for(id templ in array) {
533 masaki 188 // HMLog(HMLogLevelDebug, @"template -> %@", templ);
534 masaki 147 // }
535 masakih 549 //}
536 masaki 43
537 masaki 41 @end

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