| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h" | 5 #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 | 8 |
| 9 #include <cmath> | |
| 10 | |
| 11 #include "base/memory/scoped_nsobject.h" | |
| 12 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
| 13 #include "chrome/browser/bookmarks/bookmark_model.h" | 10 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 14 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | |
| 15 #include "chrome/browser/profiles/profile.h" | |
| 16 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" | |
| 17 #include "grit/ui_resources.h" | |
| 18 #include "ui/base/resource/resource_bundle.h" | |
| 19 #include "ui/gfx/mac/nsimage_cache.h" | |
| 20 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | |
| 21 | 11 |
| 22 NSString* const kBookmarkDictionaryListPboardType = | 12 NSString* const kBookmarkDictionaryListPboardType = |
| 23 @"BookmarkDictionaryListPboardType"; | 13 @"BookmarkDictionaryListPboardType"; |
| 24 | 14 |
| 25 namespace { | 15 namespace { |
| 26 | 16 |
| 27 // An unofficial standard pasteboard title type to be provided alongside the | 17 // An unofficial standard pasteboard title type to be provided alongside the |
| 28 // |NSURLPboardType|. | 18 // |NSURLPboardType|. |
| 29 NSString* const kNSURLTitlePboardType = | 19 NSString* const kNSURLTitlePboardType = |
| 30 @"public.url-name"; | 20 @"public.url-name"; |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 type_string = NSGeneralPboard; | 228 type_string = NSGeneralPboard; |
| 239 break; | 229 break; |
| 240 case bookmark_pasteboard_helper_mac::kDragPasteboard: | 230 case bookmark_pasteboard_helper_mac::kDragPasteboard: |
| 241 type_string = NSDragPboard; | 231 type_string = NSDragPboard; |
| 242 break; | 232 break; |
| 243 } | 233 } |
| 244 | 234 |
| 245 return [NSPasteboard pasteboardWithName:type_string]; | 235 return [NSPasteboard pasteboardWithName:type_string]; |
| 246 } | 236 } |
| 247 | 237 |
| 248 // Make a drag image from the drop data. | |
| 249 NSImage* MakeDragImage(BookmarkModel* model, | |
| 250 const std::vector<const BookmarkNode*>& nodes) { | |
| 251 if (nodes.size() == 1) { | |
| 252 const BookmarkNode* node = nodes[0]; | |
| 253 const gfx::Image& favicon = model->GetFavicon(node); | |
| 254 return bookmark_pasteboard_helper_mac::DragImageForBookmark( | |
| 255 favicon.IsEmpty() ? nil : favicon.ToNSImage(), node->GetTitle()); | |
| 256 } else { | |
| 257 // TODO(feldstein): Do something better than this. Should have badging | |
| 258 // and a single drag image. | |
| 259 // http://crbug.com/37264 | |
| 260 return [NSImage imageNamed:NSImageNameMultipleDocuments]; | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 // Draws string |title| within box |frame|, positioning it at the origin. | |
| 265 // Truncates text with fading if it is too long to fit horizontally. | |
| 266 // Based on code from GradientButtonCell but simplified where possible. | |
| 267 void DrawTruncatedTitle(NSAttributedString* title, NSRect frame) { | |
| 268 NSSize size = [title size]; | |
| 269 if (std::floor(size.width) <= NSWidth(frame)) { | |
| 270 [title drawAtPoint:frame.origin]; | |
| 271 return; | |
| 272 } | |
| 273 | |
| 274 // Gradient is about twice our line height long. | |
| 275 CGFloat gradient_width = std::min(size.height * 2, NSWidth(frame) / 4); | |
| 276 NSRect solid_part, gradient_part; | |
| 277 NSDivideRect(frame, &gradient_part, &solid_part, gradient_width, NSMaxXEdge); | |
| 278 CGContextRef context = static_cast<CGContextRef>( | |
| 279 [[NSGraphicsContext currentContext] graphicsPort]); | |
| 280 CGContextBeginTransparencyLayerWithRect(context, NSRectToCGRect(frame), 0); | |
| 281 { // Draw text clipped to frame. | |
| 282 gfx::ScopedNSGraphicsContextSaveGState scoped_state; | |
| 283 [NSBezierPath clipRect:frame]; | |
| 284 [title drawAtPoint:frame.origin]; | |
| 285 } | |
| 286 | |
| 287 NSColor* color = [NSColor blackColor]; | |
| 288 NSColor* alpha_color = [color colorWithAlphaComponent:0.0]; | |
| 289 scoped_nsobject<NSGradient> mask( | |
| 290 [[NSGradient alloc] initWithStartingColor:color | |
| 291 endingColor:alpha_color]); | |
| 292 // Draw the gradient mask. | |
| 293 CGContextSetBlendMode(context, kCGBlendModeDestinationIn); | |
| 294 [mask drawFromPoint:NSMakePoint(NSMaxX(frame) - gradient_width, | |
| 295 NSMinY(frame)) | |
| 296 toPoint:NSMakePoint(NSMaxX(frame), | |
| 297 NSMinY(frame)) | |
| 298 options:NSGradientDrawsBeforeStartingLocation]; | |
| 299 CGContextEndTransparencyLayer(context); | |
| 300 } | |
| 301 | |
| 302 } // namespace | 238 } // namespace |
| 303 | 239 |
| 304 namespace bookmark_pasteboard_helper_mac { | 240 namespace bookmark_pasteboard_helper_mac { |
| 305 | 241 |
| 306 void WriteToPasteboard(PasteboardType type, | 242 void WriteToPasteboard(PasteboardType type, |
| 307 const std::vector<BookmarkNodeData::Element>& elements, | 243 const std::vector<BookmarkNodeData::Element>& elements, |
| 308 FilePath::StringType profile_path) { | 244 FilePath::StringType profile_path) { |
| 309 if (elements.empty()) | 245 if (elements.empty()) |
| 310 return; | 246 return; |
| 311 | 247 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 342 NSPasteboard* pb = PasteboardFromType(type); | 278 NSPasteboard* pb = PasteboardFromType(type); |
| 343 | 279 |
| 344 NSArray* availableTypes = | 280 NSArray* availableTypes = |
| 345 [NSArray arrayWithObjects:kBookmarkDictionaryListPboardType, | 281 [NSArray arrayWithObjects:kBookmarkDictionaryListPboardType, |
| 346 kCrWebURLsWithTitlesPboardType, | 282 kCrWebURLsWithTitlesPboardType, |
| 347 NSURLPboardType, | 283 NSURLPboardType, |
| 348 nil]; | 284 nil]; |
| 349 return [pb availableTypeFromArray:availableTypes] != nil; | 285 return [pb availableTypeFromArray:availableTypes] != nil; |
| 350 } | 286 } |
| 351 | 287 |
| 352 NSImage* DragImageForBookmark(NSImage* favicon, const string16& title) { | |
| 353 // If no favicon, use a default. | |
| 354 if (!favicon) { | |
| 355 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 356 favicon = rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).ToNSImage(); | |
| 357 } | |
| 358 | |
| 359 // If no title, just use icon. | |
| 360 if (title.empty()) | |
| 361 return favicon; | |
| 362 NSString* ns_title = base::SysUTF16ToNSString(title); | |
| 363 | |
| 364 // Set the look of the title. | |
| 365 NSDictionary* attrs = | |
| 366 [NSDictionary dictionaryWithObject:[NSFont systemFontOfSize: | |
| 367 [NSFont smallSystemFontSize]] | |
| 368 forKey:NSFontAttributeName]; | |
| 369 scoped_nsobject<NSAttributedString> rich_title( | |
| 370 [[NSAttributedString alloc] initWithString:ns_title | |
| 371 attributes:attrs]); | |
| 372 | |
| 373 // Set up sizes and locations for rendering. | |
| 374 const CGFloat kIconMargin = 2.0; // Gap between icon and text. | |
| 375 CGFloat text_left = [favicon size].width + kIconMargin; | |
| 376 NSSize drag_image_size = [favicon size]; | |
| 377 NSSize text_size = [rich_title size]; | |
| 378 CGFloat max_text_width = bookmarks::kDefaultBookmarkWidth - text_left; | |
| 379 text_size.width = std::min(text_size.width, max_text_width); | |
| 380 drag_image_size.width = text_left + text_size.width; | |
| 381 | |
| 382 // Render the drag image. | |
| 383 NSImage* drag_image = | |
| 384 [[[NSImage alloc] initWithSize:drag_image_size] autorelease]; | |
| 385 [drag_image lockFocus]; | |
| 386 [favicon drawAtPoint:NSMakePoint(0, 0) | |
| 387 fromRect:NSZeroRect | |
| 388 operation:NSCompositeSourceOver | |
| 389 fraction:0.7]; | |
| 390 NSRect target_text_rect = NSMakeRect(text_left, 0, | |
| 391 text_size.width, drag_image_size.height); | |
| 392 DrawTruncatedTitle(rich_title, target_text_rect); | |
| 393 [drag_image unlockFocus]; | |
| 394 | |
| 395 return drag_image; | |
| 396 } | |
| 397 | |
| 398 void StartDrag(Profile* profile, | |
| 399 const std::vector<const BookmarkNode*>& nodes, | |
| 400 gfx::NativeView view) { | |
| 401 | |
| 402 std::vector<BookmarkNodeData::Element> elements; | |
| 403 for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin(); | |
| 404 it != nodes.end(); ++it) { | |
| 405 elements.push_back(BookmarkNodeData::Element(*it)); | |
| 406 } | |
| 407 | |
| 408 WriteToPasteboard(kDragPasteboard, elements, profile->GetPath().value()); | |
| 409 | |
| 410 // Synthesize an event for dragging, since we can't be sure that | |
| 411 // [NSApp currentEvent] will return a valid dragging event. | |
| 412 NSWindow* window = [view window]; | |
| 413 NSPoint position = [window mouseLocationOutsideOfEventStream]; | |
| 414 NSTimeInterval event_time = [[NSApp currentEvent] timestamp]; | |
| 415 NSEvent* drag_event = [NSEvent mouseEventWithType:NSLeftMouseDragged | |
| 416 location:position | |
| 417 modifierFlags:NSLeftMouseDraggedMask | |
| 418 timestamp:event_time | |
| 419 windowNumber:[window windowNumber] | |
| 420 context:nil | |
| 421 eventNumber:0 | |
| 422 clickCount:1 | |
| 423 pressure:1.0]; | |
| 424 | |
| 425 // TODO(avi): Do better than this offset. | |
| 426 NSImage* drag_image = | |
| 427 MakeDragImage(BookmarkModelFactory::GetForProfile(profile), nodes); | |
| 428 NSSize image_size = [drag_image size]; | |
| 429 position.x -= std::floor(image_size.width / 2); | |
| 430 position.y -= std::floor(image_size.height / 5); | |
| 431 [window dragImage:drag_image | |
| 432 at:position | |
| 433 offset:NSZeroSize | |
| 434 event:drag_event | |
| 435 pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard] | |
| 436 source:nil | |
| 437 slideBack:YES]; | |
| 438 } | |
| 439 | |
| 440 } // namespace bookmark_pasteboard_helper_mac | 288 } // namespace bookmark_pasteboard_helper_mac |
| OLD | NEW |