Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop.mm

Issue 12475013: bookmarks: Extract PerformBookmarkDrop() function out of bookmark_utils.h (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: chromeos fixes Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop.h"
6
7 #import <Cocoa/Cocoa.h>
8
9 #include <cmath>
10
11 #include "base/logging.h"
12 #include "base/memory/scoped_nsobject.h"
13 #include "base/message_loop.h"
14 #include "base/string16.h"
15 #include "base/sys_string_conversions.h"
16 #include "chrome/browser/bookmarks/bookmark_model.h"
17 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
18 #include "chrome/browser/bookmarks/bookmark_node_data.h"
19 #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
22 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
23 #include "grit/ui_resources.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
26
27 namespace chrome {
28
29 namespace {
30
31 // Make a drag image from the drop data.
32 NSImage* MakeDragImage(BookmarkModel* model,
33 const std::vector<const BookmarkNode*>& nodes) {
34 if (nodes.size() == 1) {
35 const BookmarkNode* node = nodes[0];
36 const gfx::Image& favicon = model->GetFavicon(node);
37 return DragImageForBookmark(
38 favicon.IsEmpty() ? nil : favicon.ToNSImage(), node->GetTitle());
39 } else {
40 // TODO(feldstein): Do something better than this. Should have badging
41 // and a single drag image.
42 // http://crbug.com/37264
43 return [NSImage imageNamed:NSImageNameMultipleDocuments];
44 }
45 }
46
47 // Draws string |title| within box |frame|, positioning it at the origin.
48 // Truncates text with fading if it is too long to fit horizontally.
49 // Based on code from GradientButtonCell but simplified where possible.
50 void DrawTruncatedTitle(NSAttributedString* title, NSRect frame) {
51 NSSize size = [title size];
52 if (std::floor(size.width) <= NSWidth(frame)) {
53 [title drawAtPoint:frame.origin];
54 return;
55 }
56
57 // Gradient is about twice our line height long.
58 CGFloat gradient_width = std::min(size.height * 2, NSWidth(frame) / 4);
59 NSRect solid_part, gradient_part;
60 NSDivideRect(frame, &gradient_part, &solid_part, gradient_width, NSMaxXEdge);
61 CGContextRef context = static_cast<CGContextRef>(
62 [[NSGraphicsContext currentContext] graphicsPort]);
63 CGContextBeginTransparencyLayerWithRect(context, NSRectToCGRect(frame), 0);
64 { // Draw text clipped to frame.
65 gfx::ScopedNSGraphicsContextSaveGState scoped_state;
66 [NSBezierPath clipRect:frame];
67 [title drawAtPoint:frame.origin];
68 }
69
70 NSColor* color = [NSColor blackColor];
71 NSColor* alpha_color = [color colorWithAlphaComponent:0.0];
72 scoped_nsobject<NSGradient> mask(
73 [[NSGradient alloc] initWithStartingColor:color
74 endingColor:alpha_color]);
75 // Draw the gradient mask.
76 CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
77 [mask drawFromPoint:NSMakePoint(NSMaxX(frame) - gradient_width,
78 NSMinY(frame))
79 toPoint:NSMakePoint(NSMaxX(frame),
80 NSMinY(frame))
81 options:NSGradientDrawsBeforeStartingLocation];
82 CGContextEndTransparencyLayer(context);
83 }
84
85 } // namespace
86
87 NSImage* DragImageForBookmark(NSImage* favicon, const string16& title) {
88 // If no favicon, use a default.
89 if (!favicon) {
90 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
91 favicon = rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).ToNSImage();
92 }
93
94 // If no title, just use icon.
95 if (title.empty())
96 return favicon;
97 NSString* ns_title = base::SysUTF16ToNSString(title);
98
99 // Set the look of the title.
100 NSDictionary* attrs =
101 [NSDictionary dictionaryWithObject:[NSFont systemFontOfSize:
102 [NSFont smallSystemFontSize]]
103 forKey:NSFontAttributeName];
104 scoped_nsobject<NSAttributedString> rich_title(
105 [[NSAttributedString alloc] initWithString:ns_title
106 attributes:attrs]);
107
108 // Set up sizes and locations for rendering.
109 const CGFloat kIconMargin = 2.0; // Gap between icon and text.
110 CGFloat text_left = [favicon size].width + kIconMargin;
111 NSSize drag_image_size = [favicon size];
112 NSSize text_size = [rich_title size];
113 CGFloat max_text_width = bookmarks::kDefaultBookmarkWidth - text_left;
114 text_size.width = std::min(text_size.width, max_text_width);
115 drag_image_size.width = text_left + text_size.width;
116
117 // Render the drag image.
118 NSImage* drag_image =
119 [[[NSImage alloc] initWithSize:drag_image_size] autorelease];
120 [drag_image lockFocus];
121 [favicon drawAtPoint:NSMakePoint(0, 0)
122 fromRect:NSZeroRect
123 operation:NSCompositeSourceOver
124 fraction:0.7];
125 NSRect target_text_rect = NSMakeRect(text_left, 0,
126 text_size.width, drag_image_size.height);
127 DrawTruncatedTitle(rich_title, target_text_rect);
128 [drag_image unlockFocus];
129
130 return drag_image;
131 }
132
133 void DragBookmarks(Profile* profile,
134 const std::vector<const BookmarkNode*>& nodes,
135 gfx::NativeView view) {
136 DCHECK(!nodes.empty());
137
138 // Allow nested message loop so we get DnD events as we drag this around.
139 bool was_nested = MessageLoop::current()->IsNested();
140 MessageLoop::current()->SetNestableTasksAllowed(true);
141
142 std::vector<BookmarkNodeData::Element> elements;
143 for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin();
144 it != nodes.end(); ++it) {
145 elements.push_back(BookmarkNodeData::Element(*it));
146 }
147
148 bookmark_pasteboard_helper_mac::WriteToPasteboard(
149 bookmark_pasteboard_helper_mac::kDragPasteboard,
150 elements,
151 profile->GetPath(),
152 ui::Clipboard::SourceTag());
153
154 // Synthesize an event for dragging, since we can't be sure that
155 // [NSApp currentEvent] will return a valid dragging event.
156 NSWindow* window = [view window];
157 NSPoint position = [window mouseLocationOutsideOfEventStream];
158 NSTimeInterval event_time = [[NSApp currentEvent] timestamp];
159 NSEvent* drag_event = [NSEvent mouseEventWithType:NSLeftMouseDragged
160 location:position
161 modifierFlags:NSLeftMouseDraggedMask
162 timestamp:event_time
163 windowNumber:[window windowNumber]
164 context:nil
165 eventNumber:0
166 clickCount:1
167 pressure:1.0];
168
169 // TODO(avi): Do better than this offset.
170 NSImage* drag_image = chrome::MakeDragImage(
171 BookmarkModelFactory::GetForProfile(profile), nodes);
172 NSSize image_size = [drag_image size];
173 position.x -= std::floor(image_size.width / 2);
174 position.y -= std::floor(image_size.height / 5);
175 [window dragImage:drag_image
176 at:position
177 offset:NSZeroSize
178 event:drag_event
179 pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
180 source:nil
181 slideBack:YES];
182
183 MessageLoop::current()->SetNestableTasksAllowed(was_nested);
184 }
185
186 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop.h ('k') | chrome/browser/ui/cocoa/bookmarks/bookmark_drag_drop_cocoa.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698