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

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

Powered by Google App Engine
This is Rietveld 408576698