b2171cf66f5efd815c9f2b605262254b435983f0
[WebKit-https.git] / WebKit / WebView.subproj / WebImageView.m
1 /*      
2     WebImageView.m
3     Copyright 2002, Apple, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebImageView.h>
7
8 #import <WebKit/WebAssertions.h>
9 #import <WebKit/WebDataSource.h>
10 #import <WebKit/WebDocument.h>
11 #import <WebKit/WebFrameViewPrivate.h>
12 #import <WebKit/WebImageRenderer.h>
13 #import <WebKit/WebImageRendererFactory.h>
14 #import <WebKit/WebImageRepresentation.h>
15 #import <WebKit/WebNSPasteboardExtras.h>
16 #import <WebKit/WebNSViewExtras.h>
17 #import <WebKit/WebViewPrivate.h>
18
19 #import <WebCore/WebCoreImageRenderer.h>
20
21 #import <Foundation/NSFileManager_NSURLExtras.h>
22
23 @implementation WebImageView
24
25 + (void)initialize
26 {
27     [NSApp registerServicesMenuSendTypes:[NSArray arrayWithObject:NSTIFFPboardType] returnTypes:nil];
28 }
29
30 + (NSArray *)supportedImageMIMETypes
31 {
32     return [[WebImageRendererFactory sharedFactory] supportedMIMETypes];
33 }
34
35 - (id)initWithFrame:(NSRect)frame
36 {
37     self = [super initWithFrame:frame];
38     [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
39     return self;
40 }
41
42 - (void)dealloc
43 {
44     [[rep image] stopAnimation];
45     [rep release];
46     
47     [super dealloc];
48 }
49
50 - (BOOL)haveCompleteImage
51 {
52     NSSize imageSize = [[rep image] size];
53     return [rep doneLoading] && imageSize.width > 0 && imageSize.width > 0;
54 }
55
56 - (BOOL)isFlipped 
57 {
58     return YES;
59 }
60
61 - (BOOL)acceptsFirstResponder
62 {
63     // Being first responder is useful for scrolling from the keyboard at least.
64     return YES;
65 }
66
67 - (NSRect)drawingRect
68 {
69     NSSize imageSize = [[rep image] size];
70     return NSMakeRect(0, 0, imageSize.width, imageSize.height);
71 }
72
73 - (void)drawRect:(NSRect)rect
74 {
75     if (needsLayout) {
76         [self layout];
77     }
78     
79     [[NSColor whiteColor] set];
80     NSRectFill(rect);
81     
82     NSRect drawingRect = [self drawingRect];
83     [[rep image] drawImageInRect:drawingRect fromRect:drawingRect];
84 }
85
86 - (void)adjustFrameSize
87 {
88     NSSize size = [[rep image] size];
89     
90     // When drawing on screen, ensure that the view always fills the content area 
91     // (so we draw over the entire previous page), and that the view is at least 
92     // as large as the image.. Otherwise we're printing, and we want the image to 
93     // fill the view so that the printed size doesn't depend on the window size.
94     if ([NSGraphicsContext currentContextDrawingToScreen]) {
95         NSSize clipViewSize = [[self _web_superviewOfClass:[NSClipView class]] frame].size;
96         size.width = MAX(size.width, clipViewSize.width);
97         size.height = MAX(size.height, clipViewSize.height);
98     }
99     
100     [super setFrameSize:size];
101 }
102
103 - (void)setFrameSize:(NSSize)size
104 {
105     [self adjustFrameSize];
106 }
107
108 - (void)layout
109 {
110     [self adjustFrameSize];    
111     needsLayout = NO;
112 }
113
114 - (void)beginDocument
115 {
116     [self adjustFrameSize];
117     [super beginDocument];
118 }
119
120 - (void)endDocument
121 {
122     [super endDocument];
123     [self adjustFrameSize];
124 }
125
126 - (void)setDataSource:(WebDataSource *)dataSource
127 {
128     ASSERT(!rep);
129     rep = [[dataSource representation] retain];
130 }
131
132 - (void)dataSourceUpdated:(WebDataSource *)dataSource
133 {
134     NSSize imageSize = [[rep image] size];
135     if (imageSize.width > 0 && imageSize.height > 0) {
136         [self setNeedsLayout:YES];
137         [self setNeedsDisplay:YES];
138     }
139 }
140
141 - (void)setNeedsLayout: (BOOL)flag
142 {
143     needsLayout = flag;
144 }
145
146 - (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
147 {
148
149 }
150
151 - (void)viewDidMoveToHostWindow
152 {
153
154 }
155
156 - (void)viewDidMoveToWindow
157 {
158     if (![self window]){
159         [[rep image] stopAnimation];
160     }
161     
162     [super viewDidMoveToWindow];
163 }
164
165 - (WebView *)webView
166 {
167     return [[self _web_parentWebFrameView] _webView];
168 }
169
170 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
171 {
172     if ([item action] == @selector(copy:)){
173         return [self haveCompleteImage];
174     }
175
176     return YES;
177 }
178
179 - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType
180 {
181     if (sendType && [sendType isEqualToString:NSTIFFPboardType]){
182         return self;
183     }
184
185     return [super validRequestorForSendType:sendType returnType:returnType];
186 }
187
188 - (BOOL)writeImageToPasteboard:(NSPasteboard *)pasteboard
189 {    
190     if ([self haveCompleteImage]) {
191         [pasteboard declareTypes:[NSArray arrayWithObjects:NSRTFDPboardType, NSTIFFPboardType, nil] owner:nil];
192         [pasteboard _web_writeFileWrapperAsRTFDAttachment:[rep fileWrapper]];
193         [pasteboard setData:[[rep image] TIFFRepresentation] forType:NSTIFFPboardType];
194         return YES;
195     }
196     
197     return NO;
198 }
199
200 - (void)copy:(id)sender
201 {
202     [self writeImageToPasteboard:[NSPasteboard generalPasteboard]];
203 }
204
205 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pasteboard types:(NSArray *)types
206 {
207     return [self writeImageToPasteboard:pasteboard];
208 }
209
210 - (NSMenu *)menuForEvent:(NSEvent *)theEvent
211 {
212     WebFrameView *webFrameView = [self _web_parentWebFrameView];
213     WebView *webView = [webFrameView _webView];
214     WebFrame *frame = [webFrameView webFrame];
215
216     ASSERT(frame);
217     ASSERT(webView);
218     
219     NSDictionary *element = [NSDictionary dictionaryWithObjectsAndKeys:
220         [rep image],                            WebElementImageKey,
221         [NSValue valueWithRect:[self bounds]],  WebElementImageRectKey,
222         [rep URL],                              WebElementImageURLKey,
223         [NSNumber numberWithBool:NO],           WebElementIsSelectedKey,
224         frame,                                  WebElementFrameKey, nil];
225         
226     return [webView _menuForElement:element];
227 }
228
229 - (void)mouseDown:(NSEvent *)event
230 {
231     ignoringMouseDraggedEvents = NO;
232     [super mouseDown:event];
233 }
234
235 - (void)mouseDragged:(NSEvent *)event
236 {
237     if (ignoringMouseDraggedEvents || ![self haveCompleteImage]) {
238         return;
239     }
240     
241     // Don't allow drags to be accepted by this WebFrameView.
242     [[[self _web_parentWebFrameView] _webView] unregisterDraggedTypes];
243
244     // Retain this view during the drag because it may be released before the drag ends.
245     [self retain];
246
247     [self _web_dragImage:[rep image]
248              fileWrapper:[rep fileWrapper]
249                     rect:[self drawingRect]
250                      URL:[rep URL]
251                    title:nil
252                    event:event];
253 }
254
255 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
256 {
257     // FIXME: Report an error if we fail to create a file.
258     NSString *path = [[dropDestination path] stringByAppendingPathComponent:[rep filename]];
259     path = [[NSFileManager defaultManager] _web_pathWithUniqueFilenameForPath:path];
260     [[rep data] writeToFile:path atomically:NO];
261     return [NSArray arrayWithObject:[path lastPathComponent]];
262 }
263
264 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
265 {
266     // Prevent queued mouseDragged events from coming after the drag which can cause a double drag.
267     ignoringMouseDraggedEvents = YES;
268     
269     // Reregister for drag types because they were unregistered before the drag.
270     [[[self _web_parentWebFrameView] _webView] _registerDraggedTypes];
271
272     // Balance the previous retain from when the drag started.
273     [self release];
274 }
275
276 - (NSImage *)image
277 {
278     return [rep image];
279 }
280
281 @end