Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfManager/XspfMCoverFlowViewController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 437 - (hide annotations) (download)
Sat Aug 14 14:22:08 2010 UTC (13 years, 8 months ago) by masakih
File size: 12878 byte(s)
[Fix] CoverFlowモードのスプリットビューの分割位置が正しく保存/再生されていなかったのを修正。
1 masaki 281 //
2     // XspfMCoverFlowViewController.m
3     // XspfManager
4     //
5     // Created by Hori,Masaki on 10/01/21.
6     //
7    
8 masakih 350 /*
9 masakih 365 This source code is release under the New BSD License.
10 masakih 355 Copyright (c) 2010, masakih
11 masakih 350 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 masakih 355 Copyright (c) 2010, masakih
33 masakih 350 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 281 #import "XspfMCoverFlowViewController.h"
63    
64     #import "XspfMListViewController.h"
65    
66 masaki 301 #import "XspfMXspfObject.h"
67     #import <Quartz/Quartz.h>
68 masaki 281
69 masaki 301 #import <objc/runtime.h>
70 masaki 281
71 masaki 301 @interface NSObject(XpsfMIKImageFlowViewSupport)
72     - (void)setShowSplitter:(BOOL)flag;
73     - (void)setInlinePreviewEnabled:(BOOL)flag;
74     - (void)setSelectedIndex:(NSUInteger)index;
75 masaki 304 - (NSRect)selectedImageFrame;
76 masaki 325 - (id)cacheManager;
77    
78    
79     - (void)IKCleanTimedOutCache;
80 masaki 301 @end
81    
82 masaki 281 @implementation XspfMCoverFlowViewController
83    
84 masaki 301 static IMP originalKeyDown = NULL;
85     + (void)initialize
86     {
87     static BOOL isFirst = YES;
88     if(isFirst) {
89     isFirst = NO;
90    
91     Method originalMethod = class_getInstanceMethod(NSClassFromString(@"IKImageFlowView"), @selector(keyDown:));
92 masakih 345 Method replacedMethod = class_getInstanceMethod(self, @selector(hackKeyDown:));
93 masaki 301 IMP replacedIMP = method_getImplementation(replacedMethod);
94 masakih 345 originalKeyDown = method_setImplementation(originalMethod, replacedIMP);
95 masaki 301 }
96     }
97     - (void)hackKeyDown:(NSEvent *)theEvent
98     {
99     if([theEvent isARepeat]) goto finish;
100 masaki 329
101     #define kRETURN_KEY 36
102     #define kENTER_KEY 52
103 masaki 301 unsigned short code = [theEvent keyCode];
104     switch(code) {
105 masaki 329 case kRETURN_KEY:
106     case kENTER_KEY:
107     [NSApp sendAction:@selector(openXspf:) to:nil from:nil];
108     return;
109 masaki 301 case 49:
110     [NSApp sendAction:@selector(togglePreviewPanel:) to:nil from:nil];
111     return;
112     }
113     finish:
114     originalKeyDown(self, _cmd, theEvent);
115     }
116    
117 masaki 281 - (id)init
118     {
119     self = [super initWithNibName:@"XspfMCoverFlowView" bundle:nil];
120    
121     return self;
122     }
123    
124     - (void)awakeFromNib
125     {
126     NSArrayController *rep = [self representedObject];
127    
128 masaki 301 [coverFlow setShowSplitter:YES];
129 masaki 302 if([coverFlow respondsToSelector:@selector(setInlinePreviewEnabled:)]) {
130     [coverFlow setInlinePreviewEnabled:YES];
131     }
132 masaki 301 [coverFlow setDataSource:self];
133     [coverFlow setDelegate:self];
134 masaki 281
135     listViewController = [[XspfMListViewController alloc] init];
136     [listViewController view];
137     [listViewController setRepresentedObject:rep];
138     [listViewController recalculateKeyViewLoop];
139     [listPlaceHolder addSubview:[listViewController view]];
140     [[listViewController view] setFrame:[listPlaceHolder bounds]];
141     [self recalculateKeyViewLoop];
142    
143 masaki 294 [splitView setDelegate:self];
144 masaki 281 }
145    
146 masakih 436 - (void)setupLate
147     {
148     [[NSApp mainWindow] addObserver:self forKeyPath:@"firstResponder" options:0 context:NULL];
149     }
150    
151 masaki 281 - (void)setRepresentedObject:(id)representedObject
152     {
153 masaki 301 id oldRep = [self representedObject];
154     if([oldRep isEqual:representedObject]) return;
155 masaki 329
156 masaki 281 if(representedObject) {
157 masaki 301 [representedObject addObserver:self forKeyPath:@"arrangedObjects" options:0 context:NULL];
158     [representedObject addObserver:self forKeyPath:@"selectionIndex" options:0 context:NULL];
159     [coverFlow setSelectedIndex:[representedObject selectionIndex]];
160 masaki 281 }
161 masaki 301
162     [super setRepresentedObject:representedObject];
163     [listViewController setRepresentedObject:representedObject];
164     [coverFlow reloadData];
165 masakih 436
166     [self performSelector:@selector(setupLate) withObject:nil afterDelay:0.5];
167 masaki 281 }
168 masaki 329 - (void)recalculateKeyViewLoop
169     {
170 masakih 430 // [coverFlow setNextKeyView:[listViewController firstKeyView]];
171 masaki 329
172     // TODO: change key view loop if list view is not visible.
173 masakih 430 // lastKeyView = [listViewController lastKeyView];
174    
175     firstKeyView = [listViewController firstKeyView];
176     initialFirstResponder = [listViewController firstKeyView];
177 masaki 329 }
178 masaki 281
179 masaki 301 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
180 masaki 281 {
181 masaki 301 if([keyPath isEqualToString:@"arrangedObjects"]) {
182     [coverFlow reloadData];
183     return;
184     }
185     if([keyPath isEqualToString:@"selectionIndex"]) {
186     [coverFlow setSelectedIndex:[[self representedObject] selectionIndex]];
187 masakih 430 [listViewController scrollToSelection:self];
188 masaki 301 return;
189     }
190 masakih 436 if([keyPath isEqualToString:@"firstResponder"]) {
191     id firstResponder = [[splitView window] firstResponder];
192     if(firstResponder == coverFlow) {
193     [[splitView window] makeFirstResponder:[listViewController view]];
194     }
195     return;
196     }
197 masaki 281
198 masaki 301 [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
199 masaki 281 }
200    
201 masakih 430 - (void)keyDown:(NSEvent *)theEvent
202     {
203     unsigned short code = [theEvent keyCode];
204     #define kLEFT_ARROW_KEY 123
205     #define kRIGHT_ARROW_KEY 124
206     switch(code) {
207     case kLEFT_ARROW_KEY:
208     case kRIGHT_ARROW_KEY:
209     return [coverFlow keyDown:theEvent];
210     break;
211     }
212     NSBeep();
213     }
214 masaki 301
215 masaki 325 - (IBAction)clearCoverFlowCache:(id)sender
216     {
217     if(![coverFlow respondsToSelector:@selector(cacheManager)]) {
218     NSBeep();
219     return;
220     }
221     id cacheManager = [coverFlow cacheManager];
222     if(![cacheManager respondsToSelector:@selector(IKCleanTimedOutCache)]) {
223     NSBeep();
224     return;
225     }
226     [cacheManager IKCleanTimedOutCache];
227     }
228     - (IBAction)test01:(id)sender
229     {
230     [self clearCoverFlowCache:sender];
231     }
232    
233 masaki 301 - (NSUInteger)numberOfItemsInImageFlow:(id)imageFlowView
234     {
235     return [[[self representedObject] arrangedObjects] count];
236     }
237     - (id)imageFlow:(id)imageFlowView itemAtIndex:(NSUInteger)index
238     {
239     return [[[self representedObject] arrangedObjects] objectAtIndex:index];
240     }
241    
242 masakih 430 - (void)setRepSelectedIndex:(NSNumber *)indexValue
243     {
244     [[self representedObject] setSelectionIndex:[indexValue unsignedIntegerValue]];
245     }
246 masaki 301 - (void)imageFlow:(id)imageFlowView didSelectItemAtIndex:(NSUInteger)index
247     {
248 masakih 430 // [[self representedObject] setSelectionIndex:index];
249    
250     [NSObject cancelPreviousPerformRequestsWithTarget:self];
251     [self performSelector:@selector(setRepSelectedIndex:)
252     withObject:[NSNumber numberWithUnsignedInteger:index]
253     afterDelay:0.5];
254 masaki 301 }
255     - (void)imageFlow:(id)imageFlowView cellWasDoubleClickedAtIndex:(NSUInteger)index
256     {
257     [NSApp sendAction:@selector(openXspf:) to:nil from:nil];
258     }
259     - (void)imageFlow:(id)imageFlowView startResizingWithEvent:(NSEvent *)theEvent
260     {
261 masakih 345 NSPoint offset = [imageFlowView convertPoint:[theEvent locationInWindow] fromView:nil];
262    
263 masaki 301 NSWindow *window = [imageFlowView window];
264 masakih 345 while (theEvent = [window nextEventMatchingMask:NSLeftMouseDraggedMask | NSLeftMouseUpMask]) {
265     if(NSEventMaskFromType([theEvent type]) == NSLeftMouseUpMask) break;
266    
267     NSPoint p = [splitView convertPoint:[theEvent locationInWindow] fromView:nil];
268     [splitView setPosition:p.y+offset.y ofDividerAtIndex:0];
269     }
270 masaki 301 }
271    
272 masakih 429 - (IBAction)scrollToSelection:(id)sender
273     {
274     [listViewController scrollToSelection:sender];
275     }
276 masaki 301
277 masaki 304 // QLPreviewPanel support
278     - (NSRect)selectionItemRect
279     {
280     NSRect rect = [coverFlow selectedImageFrame];
281     rect = [coverFlow convertRectToBase:rect];
282     rect.origin = [[coverFlow window] convertBaseToScreen:rect.origin];
283     return rect;
284     }
285    
286 masaki 294 #pragma mark#### NSSplitView Delegate ####
287     - (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex
288     {
289     return 130;
290     }
291 masakih 437 - (void)splitView:(NSSplitView *)aSplitView resizeSubviewsWithOldSize:(NSSize)oldSize
292     {
293     NSView *rightView = [[splitView subviews] objectAtIndex:1];
294     NSRect newsplitViewFrame = [splitView frame];
295     NSRect coverFlowFrame = [coverFlow frame];
296     NSRect listFrame = [rightView frame];
297     CGFloat dividerThickness = [splitView dividerThickness];
298    
299     coverFlowFrame.size.width = newsplitViewFrame.size.width;
300     listFrame.size.width = newsplitViewFrame.size.width;
301    
302     coverFlowFrame.size.height = newsplitViewFrame.size.height - listFrame.size.height - dividerThickness;
303    
304     if(listFrame.size.height < 0) {
305     listFrame.size.height = 0;
306     coverFlowFrame.size = newsplitViewFrame.size;
307     }
308    
309     coverFlowFrame.origin.y = 0;
310     listFrame.origin.y = NSMaxY(coverFlowFrame) + dividerThickness;
311    
312     [coverFlow setFrame:coverFlowFrame];
313     [rightView setFrame:listFrame];
314     }
315 masaki 281
316 masaki 301 @end
317 masaki 294
318    
319 masaki 301 @implementation XspfMXspfObject(XspfMIKImageBrowserItem)
320     /*!
321     @method imageUID
322     @abstract Returns a unique string that identify this data source item (required).
323     @discussion The image browser uses this identifier to keep the correspondance between its cache and the data source item
324     */
325     - (NSString *) imageUID
326     {
327     return self.urlString;
328     }
329    
330     /*!
331     @method imageRepresentationType
332     @abstract Returns the representation of the image to display (required).
333     @discussion Keys for imageRepresentationType are defined below.
334     */
335     - (NSString *) imageRepresentationType
336     {
337     return IKImageBrowserQuickLookPathRepresentationType;
338     }
339    
340     /*!
341     @method imageRepresentation
342     @abstract Returns the image to display (required). Can return nil if the item has no image to display.
343     @discussion This methods is called frequently, so the receiver should cache the returned instance.
344     */
345     - (id) imageRepresentation
346     {
347     return self.url;
348     }
349    
350     /*!
351     @method imageVersion
352     @abstract Returns a version of this item. The receiver can return a new version to let the image browser knows that it shouldn't use its cache for this item
353     */
354     //- (NSUInteger) imageVersion;
355    
356     /*!
357     @method imageTitle
358     @abstract Returns the title to display as a NSString. Use setValue:forKey: with IKImageBrowserCellTitleAttribute to set text attributes.
359     */
360     - (NSString *) imageTitle
361     {
362     return self.title;
363     }
364    
365     /*!
366     @method imageSubtitle
367     @abstract Returns the subtitle to display as a NSString. Use setValue:forKey: with IKImageBrowserCellSubtitleAttribute to set text attributes.
368     */
369     - (NSString *) imageSubtitle
370     {
371     return [NSString stringWithFormat:
372     NSLocalizedString(@"%@ Movies", @"%@ Movies"),
373     self.movieNum];
374     }
375    
376     /*!
377     @method isSelectable
378     @abstract Returns whether this item is selectable.
379     @discussion The receiver can implement this methods to forbid selection of this item by returning NO.
380     */
381     //- (BOOL) isSelectable;
382    
383 masaki 281 @end

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