2006-05-04 Eric Seidel <eseidel@apple.com>
authoreseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2006 18:26:27 +0000 (18:26 +0000)
committereseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 May 2006 18:26:27 +0000 (18:26 +0000)
        Reviewed by timo.

        Add drag & drop support to <input type="file">
        http://bugzilla.opendarwin.org/show_bug.cgi?id=8733

        Test: manual/input-type-file-drag-drop.html

        * kwq/KWQFileButton.mm:
        (-[WebFileChooserButton initWithWidget::]):
        (-[WebCoreFileButton initWithWidget:]):
        (-[WebCoreFileButton drawRect:]):
        (-[WebCoreFileButton updateLabel]):
        (-[WebCoreFileButton setFilename:]):
        (-[WebCoreFileButton changeFilename:]):
        (-[WebCoreFileButton chooseFilename:]):
        (validFilenameFromPasteboard):
        (-[WebCoreFileButton draggingEntered:]):
        (-[WebCoreFileButton draggingExited:]):
        (-[WebCoreFileButton performDragOperation:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14182 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/kwq/KWQFileButton.mm
WebCore/manual-tests/input-type-file-drag-drop.html [new file with mode: 0644]

index 67b9eb0ed35b2664ed461f2eb4c705d2e6a10965..c7735c89b0d00a1f27779675757899161f882744 100644 (file)
@@ -1,3 +1,25 @@
+2006-05-04  Eric Seidel  <eseidel@apple.com>
+
+        Reviewed by timo.
+
+        Add drag & drop support to <input type="file">
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=8733
+
+        Test: manual/input-type-file-drag-drop.html
+
+        * kwq/KWQFileButton.mm:
+        (-[WebFileChooserButton initWithWidget::]):
+        (-[WebCoreFileButton initWithWidget:]):
+        (-[WebCoreFileButton drawRect:]):
+        (-[WebCoreFileButton updateLabel]):
+        (-[WebCoreFileButton setFilename:]):
+        (-[WebCoreFileButton changeFilename:]):
+        (-[WebCoreFileButton chooseFilename:]):
+        (validFilenameFromPasteboard):
+        (-[WebCoreFileButton draggingEntered:]):
+        (-[WebCoreFileButton draggingExited:]):
+        (-[WebCoreFileButton performDragOperation:]):
+
 2006-05-04  Beth Dakin  <bdakin@apple.com>
 
         Reviewed by Hyatt.
index d15ced2eac4ea71c87bbd91c391b79b5fccaf2a8..f33b5350e2f5837b1ca87893bf223b2e0915471f 100644 (file)
@@ -68,6 +68,7 @@ using namespace WebCore;
     NSString *_label;
     BOOL _inNextValidKeyView;
     KWQFileButton *_widget;
+    BOOL _isCurrentDragTarget;
 }
 - (void)setFilename:(NSString *)filename;
 - (void)performClick;
@@ -92,6 +93,7 @@ using namespace WebCore;
     self = [super init];
     if (!self)
         return nil;
+    [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
 
     _widget = widget;
     return self;
@@ -139,6 +141,11 @@ using namespace WebCore;
     
     [NSGraphicsContext saveGraphicsState];
     NSRectClip(NSIntersectionRect(bounds, rect));
+    
+    if (_isCurrentDragTarget) {
+        [[NSColor colorWithCalibratedWhite:0.0 alpha:0.25f] set];
+        NSRectFillUsingOperation([self bounds], NSCompositeSourceOver);
+    }
 
     float left = NSMaxX([_button frame]) + AFTER_BUTTON_SPACING;
 
@@ -163,16 +170,14 @@ using namespace WebCore;
     [_label release];
     
     NSString *label;
-    if ([_filename length]) {
+    if ([_filename length])
         label = _filename;
-    } else {
+    else
         label = [[WebCoreViewFactory sharedFactory] fileButtonNoFileSelectedLabel];
-    }
     
     float left = NSMaxX([_button frame]) + AFTER_BUTTON_SPACING;
-    if (_icon) {
+    if (_icon)
         left += ICON_WIDTH + ICON_FILENAME_SPACING;
-    }
     float labelWidth = [self bounds].size.width - left;
 
     _label = labelWidth <= 0 ? nil : [[WebCoreStringTruncator centerTruncateString:
@@ -187,9 +192,9 @@ using namespace WebCore;
     _filename = copy;
     
     [_icon release];
-    if ([_filename length] == 0 || [_filename characterAtIndex:0] != '/') {
+    if ([_filename length] == 0 || [_filename characterAtIndex:0] != '/')
         _icon = nil;
-    else {
+    else {
         _icon = [[[NSWorkspace sharedWorkspace] iconForFile:_filename] retain];
         // I'm not sure why this has any effect, but including this line of code seems to make
         // the image appear right-side-up. As far as I know, the drawInRect method used above
@@ -266,7 +271,7 @@ using namespace WebCore;
     [bridge runOpenPanelForFileButtonWithResultListener:self];
 }
 
-- (void)chooseFilename:(NSString *)filename
+- (void)changeFilename:(NSString *)filename
 {
     // The != check here makes sure we don't consider a change from nil to nil as a change.
     if (_filename != filename && ![_filename isEqualToString:filename]) {
@@ -274,6 +279,11 @@ using namespace WebCore;
         if (_widget)
             _widget->filenameChanged(DeprecatedString::fromNSString(filename));
     }
+}
+
+- (void)chooseFilename:(NSString *)filename
+{
+    [self changeFilename:filename];
     WebCoreFrameBridge *bridge = FrameMac::bridgeForWidget(_widget);
     [bridge release];
 }
@@ -351,6 +361,48 @@ using namespace WebCore;
     [_button performClick:nil];
 }
 
+static NSString *validFilenameFromPasteboard(NSPasteboard* pBoard)
+{
+    NSArray *filenames = [pBoard propertyListForType:NSFilenamesPboardType];
+    if ([filenames count] == 1) {
+        NSString *filename = [filenames objectAtIndex:0];
+        NSDictionary *fileAttributes = [[NSFileManager defaultManager] fileAttributesAtPath:filename traverseLink:YES];
+        if ([[fileAttributes fileType] isEqualToString:NSFileTypeRegular])
+            return filename;
+    }
+    return nil;
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+    if (validFilenameFromPasteboard([sender draggingPasteboard])) {
+        _isCurrentDragTarget = YES;
+        [self setNeedsDisplay:YES];
+        return NSDragOperationCopy;
+    }
+    return NSDragOperationNone;
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender
+{
+    if (_isCurrentDragTarget) {
+        _isCurrentDragTarget = NO;
+        [self setNeedsDisplay:YES];
+    }
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+    _isCurrentDragTarget = NO;
+    NSString *filename = validFilenameFromPasteboard([sender draggingPasteboard]);
+    if (filename) {
+        [self changeFilename:filename];
+        [self setNeedsDisplay:YES];
+        return YES;
+    }
+    return NO;
+}
+
 @end
 
 @implementation WebFileChooserButton
diff --git a/WebCore/manual-tests/input-type-file-drag-drop.html b/WebCore/manual-tests/input-type-file-drag-drop.html
new file mode 100644 (file)
index 0000000..eccc6e8
--- /dev/null
@@ -0,0 +1,18 @@
+<body>
+<div style="background-color: black;" width="300">
+<input type=file>
+</div>
+<div style="background-color: blue;" width="300">
+<input type=file>
+</div>
+<input type=file>
+<p>
+&lt;input type="file"&gt; should be able to support drag and drop of files.  Use the above controls to demonstrate:
+</p>
+<ol>
+<li> Accepting normal file drags (indicating accpetance during hover).
+<li> Rejecting diretory and non-normal file drags.
+<li> Dropping a symlink'd file should accpect/show/upload the target, not the symlink itself.
+<li> Rejecting of file-promise drags (this is probably a bug, not a feature).
+</ol>
+</body>
\ No newline at end of file