Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfManager/XspfMCoverFlowViewController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 567 - (hide annotations) (download)
Mon Jun 27 15:25:36 2011 UTC (12 years, 9 months ago) by masakih
File size: 12808 byte(s)
[Mod] キーイベントハンドリングの方法を変更。
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 masakih 483 - (NSUInteger)selectedIndex;
79 masaki 325
80 masakih 483 - (NSUInteger)numberOfItemsInImageFlow:(id)imageFlowView;
81    
82 masaki 325 - (void)IKCleanTimedOutCache;
83 masaki 301 @end
84    
85 masaki 281 @implementation XspfMCoverFlowViewController
86    
87     - (id)init
88     {
89     self = [super initWithNibName:@"XspfMCoverFlowView" bundle:nil];
90    
91     return self;
92     }
93    
94     - (void)awakeFromNib
95     {
96     NSArrayController *rep = [self representedObject];
97    
98 masaki 301 [coverFlow setShowSplitter:YES];
99 masaki 302 if([coverFlow respondsToSelector:@selector(setInlinePreviewEnabled:)]) {
100     [coverFlow setInlinePreviewEnabled:YES];
101     }
102 masaki 301 [coverFlow setDataSource:self];
103     [coverFlow setDelegate:self];
104 masaki 281
105     listViewController = [[XspfMListViewController alloc] init];
106     [listViewController view];
107     [listViewController setRepresentedObject:rep];
108     [listViewController recalculateKeyViewLoop];
109     [listPlaceHolder addSubview:[listViewController view]];
110     [[listViewController view] setFrame:[listPlaceHolder bounds]];
111     [self recalculateKeyViewLoop];
112    
113 masaki 294 [splitView setDelegate:self];
114 masakih 440
115     [[NSNotificationCenter defaultCenter] addObserver:self
116     selector:@selector(windowDidUpdate:)
117     name:NSWindowDidUpdateNotification
118     object:nil];
119 masaki 281 }
120    
121 masakih 440 - (void)windowDidUpdate:(id)notification
122 masakih 436 {
123 masakih 440 NSWindow *window = [notification object];
124    
125     if(window == [[self view] window]) {
126 masakih 554 [window addObserver:self forKeyPath:@"firstResponder" options:0 context:NULL];
127 masakih 440 [[NSNotificationCenter defaultCenter] removeObserver:self name:[notification name] object:nil];
128     }
129 masakih 436 }
130    
131 masaki 281 - (void)setRepresentedObject:(id)representedObject
132     {
133 masaki 301 id oldRep = [self representedObject];
134     if([oldRep isEqual:representedObject]) return;
135 masaki 329
136 masaki 281 if(representedObject) {
137 masaki 301 [representedObject addObserver:self forKeyPath:@"arrangedObjects" options:0 context:NULL];
138     [representedObject addObserver:self forKeyPath:@"selectionIndex" options:0 context:NULL];
139     [coverFlow setSelectedIndex:[representedObject selectionIndex]];
140 masaki 281 }
141 masaki 301
142     [super setRepresentedObject:representedObject];
143     [listViewController setRepresentedObject:representedObject];
144     [coverFlow reloadData];
145 masaki 281 }
146 masaki 329 - (void)recalculateKeyViewLoop
147     {
148 masakih 430 // [coverFlow setNextKeyView:[listViewController firstKeyView]];
149 masaki 329
150     // TODO: change key view loop if list view is not visible.
151 masakih 430 // lastKeyView = [listViewController lastKeyView];
152    
153     firstKeyView = [listViewController firstKeyView];
154     initialFirstResponder = [listViewController firstKeyView];
155 masaki 329 }
156 masaki 281
157 masaki 301 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
158 masaki 281 {
159 masaki 301 if([keyPath isEqualToString:@"arrangedObjects"]) {
160     [coverFlow reloadData];
161     return;
162     }
163     if([keyPath isEqualToString:@"selectionIndex"]) {
164     [coverFlow setSelectedIndex:[[self representedObject] selectionIndex]];
165 masakih 430 [listViewController scrollToSelection:self];
166 masaki 301 return;
167     }
168 masakih 436 if([keyPath isEqualToString:@"firstResponder"]) {
169     id firstResponder = [[splitView window] firstResponder];
170     if(firstResponder == coverFlow) {
171     [[splitView window] makeFirstResponder:[listViewController view]];
172     }
173     return;
174     }
175 masaki 281
176 masaki 301 [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
177 masaki 281 }
178    
179 masakih 430 - (void)keyDown:(NSEvent *)theEvent
180     {
181 masakih 567 NSString *charactor = [theEvent charactersIgnoringModifiers];
182     if([charactor length] == 0) return;
183    
184     unichar uc = [charactor characterAtIndex:0];
185     switch(uc) {
186     case NSLeftArrowFunctionKey:
187     case NSRightArrowFunctionKey:
188 masakih 430 return [coverFlow keyDown:theEvent];
189     break;
190     }
191     NSBeep();
192     }
193 masaki 301
194 masaki 325 - (IBAction)clearCoverFlowCache:(id)sender
195     {
196     if(![coverFlow respondsToSelector:@selector(cacheManager)]) {
197     NSBeep();
198     return;
199     }
200     id cacheManager = [coverFlow cacheManager];
201     if(![cacheManager respondsToSelector:@selector(IKCleanTimedOutCache)]) {
202     NSBeep();
203     return;
204     }
205     [cacheManager IKCleanTimedOutCache];
206     }
207 masakih 483 - (IBAction)moveLeft:(id)sender
208     {
209     NSUInteger selection = [coverFlow selectedIndex];
210     if(selection == 0) return;
211    
212     [coverFlow setSelectedIndex:selection - 1];
213     }
214     - (IBAction)moveRight:(id)sender
215     {
216     NSUInteger selection = [coverFlow selectedIndex];
217     if(selection == [self numberOfItemsInImageFlow:coverFlow] - 1) return;
218    
219     [coverFlow setSelectedIndex:selection + 1];
220     }
221    
222    
223 masakih 554 //- (IBAction)test01:(id)sender
224     //{
225     // [self clearCoverFlowCache:sender];
226     //}
227 masaki 325
228 masaki 301 - (NSUInteger)numberOfItemsInImageFlow:(id)imageFlowView
229     {
230     return [[[self representedObject] arrangedObjects] count];
231     }
232     - (id)imageFlow:(id)imageFlowView itemAtIndex:(NSUInteger)index
233     {
234     return [[[self representedObject] arrangedObjects] objectAtIndex:index];
235     }
236    
237 masakih 430 - (void)setRepSelectedIndex:(NSNumber *)indexValue
238     {
239     [[self representedObject] setSelectionIndex:[indexValue unsignedIntegerValue]];
240     }
241 masaki 301 - (void)imageFlow:(id)imageFlowView didSelectItemAtIndex:(NSUInteger)index
242     {
243 masakih 430 // [[self representedObject] setSelectionIndex:index];
244    
245     [NSObject cancelPreviousPerformRequestsWithTarget:self];
246     [self performSelector:@selector(setRepSelectedIndex:)
247     withObject:[NSNumber numberWithUnsignedInteger:index]
248     afterDelay:0.5];
249 masaki 301 }
250     - (void)imageFlow:(id)imageFlowView cellWasDoubleClickedAtIndex:(NSUInteger)index
251     {
252     [NSApp sendAction:@selector(openXspf:) to:nil from:nil];
253     }
254     - (void)imageFlow:(id)imageFlowView startResizingWithEvent:(NSEvent *)theEvent
255     {
256 masakih 345 NSPoint offset = [imageFlowView convertPoint:[theEvent locationInWindow] fromView:nil];
257    
258 masaki 301 NSWindow *window = [imageFlowView window];
259 masakih 345 while (theEvent = [window nextEventMatchingMask:NSLeftMouseDraggedMask | NSLeftMouseUpMask]) {
260     if(NSEventMaskFromType([theEvent type]) == NSLeftMouseUpMask) break;
261    
262     NSPoint p = [splitView convertPoint:[theEvent locationInWindow] fromView:nil];
263     [splitView setPosition:p.y+offset.y ofDividerAtIndex:0];
264     }
265 masaki 301 }
266    
267 masakih 429 - (IBAction)scrollToSelection:(id)sender
268     {
269     [listViewController scrollToSelection:sender];
270     }
271 masaki 301
272 masaki 304 // QLPreviewPanel support
273     - (NSRect)selectionItemRect
274     {
275     NSRect rect = [coverFlow selectedImageFrame];
276     rect = [coverFlow convertRectToBase:rect];
277     rect.origin = [[coverFlow window] convertBaseToScreen:rect.origin];
278     return rect;
279     }
280    
281 masaki 294 #pragma mark#### NSSplitView Delegate ####
282     - (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex
283     {
284     return 130;
285     }
286 masakih 437 - (void)splitView:(NSSplitView *)aSplitView resizeSubviewsWithOldSize:(NSSize)oldSize
287     {
288     NSView *rightView = [[splitView subviews] objectAtIndex:1];
289     NSRect newsplitViewFrame = [splitView frame];
290     NSRect coverFlowFrame = [coverFlow frame];
291     NSRect listFrame = [rightView frame];
292     CGFloat dividerThickness = [splitView dividerThickness];
293    
294     coverFlowFrame.size.width = newsplitViewFrame.size.width;
295     listFrame.size.width = newsplitViewFrame.size.width;
296    
297     coverFlowFrame.size.height = newsplitViewFrame.size.height - listFrame.size.height - dividerThickness;
298    
299     if(listFrame.size.height < 0) {
300     listFrame.size.height = 0;
301     coverFlowFrame.size = newsplitViewFrame.size;
302     }
303    
304     coverFlowFrame.origin.y = 0;
305     listFrame.origin.y = NSMaxY(coverFlowFrame) + dividerThickness;
306    
307     [coverFlow setFrame:coverFlowFrame];
308     [rightView setFrame:listFrame];
309     }
310 masaki 281
311 masaki 301 @end
312 masaki 294
313    
314 masaki 301 @implementation XspfMXspfObject(XspfMIKImageBrowserItem)
315     /*!
316     @method imageUID
317     @abstract Returns a unique string that identify this data source item (required).
318     @discussion The image browser uses this identifier to keep the correspondance between its cache and the data source item
319     */
320     - (NSString *) imageUID
321     {
322 masakih 562 return self.filePath;
323 masaki 301 }
324    
325     /*!
326     @method imageRepresentationType
327     @abstract Returns the representation of the image to display (required).
328     @discussion Keys for imageRepresentationType are defined below.
329     */
330     - (NSString *) imageRepresentationType
331     {
332     return IKImageBrowserQuickLookPathRepresentationType;
333     }
334    
335     /*!
336     @method imageRepresentation
337     @abstract Returns the image to display (required). Can return nil if the item has no image to display.
338     @discussion This methods is called frequently, so the receiver should cache the returned instance.
339     */
340     - (id) imageRepresentation
341     {
342     return self.url;
343     }
344    
345     /*!
346     @method imageVersion
347     @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
348     */
349     //- (NSUInteger) imageVersion;
350    
351     /*!
352     @method imageTitle
353     @abstract Returns the title to display as a NSString. Use setValue:forKey: with IKImageBrowserCellTitleAttribute to set text attributes.
354     */
355     - (NSString *) imageTitle
356     {
357     return self.title;
358     }
359    
360     /*!
361     @method imageSubtitle
362     @abstract Returns the subtitle to display as a NSString. Use setValue:forKey: with IKImageBrowserCellSubtitleAttribute to set text attributes.
363     */
364     - (NSString *) imageSubtitle
365     {
366     return [NSString stringWithFormat:
367     NSLocalizedString(@"%@ Movies", @"%@ Movies"),
368     self.movieNum];
369     }
370    
371     /*!
372     @method isSelectable
373     @abstract Returns whether this item is selectable.
374     @discussion The receiver can implement this methods to forbid selection of this item by returning NO.
375     */
376     //- (BOOL) isSelectable;
377    
378 masaki 281 @end

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