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

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

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

Powered by Google App Engine
This is Rietveld 408576698