Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / bookmarks / bookmark_bar_view.mm
blob651f35dd026fafca1bab597b9e44e4cd75889bd4
1 // Copyright (c) 2011 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.
5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h"
7 #include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
8 #include "chrome/browser/profiles/profile.h"
9 #import "chrome/browser/themes/theme_properties.h"
10 #import "chrome/browser/themes/theme_service.h"
11 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
12 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
13 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_context_menu_cocoa_controller.h"
14 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h"
15 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
16 #import "chrome/browser/ui/cocoa/themed_window.h"
17 #import "chrome/browser/ui/cocoa/view_id_util.h"
18 #include "content/public/browser/user_metrics.h"
19 #import "third_party/mozilla/NSPasteboard+Utils.h"
21 using base::UserMetricsAction;
23 @interface BookmarkBarView (Private)
24 - (void)themeDidChangeNotification:(NSNotification*)aNotification;
25 - (void)updateTheme:(ui::ThemeProvider*)themeProvider;
26 @end
28 @implementation BookmarkBarView
30 @synthesize dropIndicatorShown = dropIndicatorShown_;
31 @synthesize dropIndicatorPosition = dropIndicatorPosition_;
32 @synthesize noItemContainer = noItemContainer_;
35 - (void)dealloc {
36   [[NSNotificationCenter defaultCenter] removeObserver:self];
37   // This probably isn't strictly necessary, but can't hurt.
38   [self unregisterDraggedTypes];
39   [super dealloc];
41   // To be clear, our controller_ is an IBOutlet and owns us, so we
42   // don't deallocate it explicitly.  It is owned by the browser
43   // window controller, so gets deleted with a browser window is
44   // closed.
47 - (void)awakeFromNib {
48   NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
49   [defaultCenter addObserver:self
50                     selector:@selector(themeDidChangeNotification:)
51                         name:kBrowserThemeDidChangeNotification
52                       object:nil];
54   DCHECK(controller_) << "Expected this to be hooked up via Interface Builder";
55   NSArray* types = [NSArray arrayWithObjects:
56                     NSStringPboardType,
57                     NSHTMLPboardType,
58                     NSURLPboardType,
59                     kBookmarkButtonDragType,
60                     kBookmarkDictionaryListPboardType,
61                     nil];
62   [self registerForDraggedTypes:types];
65 // We need the theme to color the bookmark buttons properly.  But our
66 // controller desn't have access to it until it's placed in the view
67 // hierarchy.  This is the spot where we close the loop.
68 - (void)viewWillMoveToWindow:(NSWindow*)window {
69   ui::ThemeProvider* themeProvider = [window themeProvider];
70   [self updateTheme:themeProvider];
71   [controller_ updateTheme:themeProvider];
72   [super viewWillMoveToWindow:window];
75 - (void)viewDidMoveToWindow {
76   [controller_ viewDidMoveToWindow];
79 // Called after a theme change took place, possibly for a different profile.
80 - (void)themeDidChangeNotification:(NSNotification*)notification {
81   [self updateTheme:[[self window] themeProvider]];
84 // Adapt appearance to the current theme. Called after theme changes and before
85 // this is shown for the first time.
86 - (void)updateTheme:(ui::ThemeProvider*)themeProvider {
87   if (!themeProvider)
88     return;
90   NSColor* color =
91       themeProvider->GetNSColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
92   [noItemTextfield_ setTextColor:color];
95 // Mouse down events on the bookmark bar should not allow dragging the parent
96 // window around.
97 - (BOOL)mouseDownCanMoveWindow {
98   return NO;
101 - (BookmarkBarTextField*)noItemTextfield {
102   return noItemTextfield_;
105 - (NSButton*)importBookmarksButton {
106   return importBookmarksButton_;
109 - (BookmarkBarController*)controller {
110   return controller_;
113 // Internal method, needs to be called whenever a change has been made to
114 // dropIndicatorShown_ or dropIndicatorPosition_ so it can get the controller
115 // to reflect the change by moving buttons around.
116 - (void)dropIndicatorChanged {
117   if (dropIndicatorShown_)
118     [controller_ setDropInsertionPos:dropIndicatorPosition_];
119   else
120     [controller_ clearDropInsertionPos];
123 // NSDraggingDestination methods
125 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
126   if (![controller_ draggingAllowed:info])
127     return NSDragOperationNone;
128   if ([[info draggingPasteboard] dataForType:kBookmarkButtonDragType] ||
129       PasteboardContainsBookmarks(ui::CLIPBOARD_TYPE_DRAG) ||
130       [[info draggingPasteboard] containsURLData]) {
131     // We only show the drop indicator if we're not in a position to
132     // perform a hover-open since it doesn't make sense to do both.
133     BOOL showIt = [controller_ shouldShowIndicatorShownForPoint:
134                    [info draggingLocation]];
135     if (!showIt) {
136       if (dropIndicatorShown_) {
137         dropIndicatorShown_ = NO;
138         [self dropIndicatorChanged];
139       }
140     } else {
141       CGFloat x =
142       [controller_ indicatorPosForDragToPoint:[info draggingLocation]];
143       // Need an update if the indicator wasn't previously shown or if it has
144       // moved.
145       if (!dropIndicatorShown_ || dropIndicatorPosition_ != x) {
146         dropIndicatorShown_ = YES;
147         dropIndicatorPosition_ = x;
148         [self dropIndicatorChanged];
149       }
150     }
152     [controller_ draggingEntered:info];  // allow hover-open to work.
153     return [[info draggingSource] isKindOfClass: [BookmarkButton class]] ?
154         NSDragOperationMove : NSDragOperationCopy;
155   }
156   return NSDragOperationNone;
159 - (void)draggingExited:(id<NSDraggingInfo>)info {
160   [controller_ draggingExited:info];
162   // Regardless of the type of dragging which ended, we need to get rid of the
163   // drop indicator if one was shown.
164   if (dropIndicatorShown_) {
165     dropIndicatorShown_ = NO;
166     [self dropIndicatorChanged];
167   }
170 - (void)draggingEnded:(id<NSDraggingInfo>)info {
171   [controller_ draggingEnded:info];
173   [[BookmarkButton draggedButton] setHidden:NO];
174   if (dropIndicatorShown_) {
175     dropIndicatorShown_ = NO;
176     [self dropIndicatorChanged];
177   }
178   [controller_ draggingEnded:info];
181 - (BOOL)wantsPeriodicDraggingUpdates {
182   return YES;
185 - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info {
186   // For now it's the same as draggingEntered:.
187   return [self draggingEntered:info];
190 - (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)info {
191   return YES;
194 // Implement NSDraggingDestination protocol method
195 // performDragOperation: for URLs.
196 - (BOOL)performDragOperationForURL:(id<NSDraggingInfo>)info {
197   NSPasteboard* pboard = [info draggingPasteboard];
198   DCHECK([pboard containsURLData]);
200   NSArray* urls = nil;
201   NSArray* titles = nil;
202   [pboard getURLs:&urls andTitles:&titles convertingFilenames:YES];
204   return [controller_ addURLs:urls
205                    withTitles:titles
206                            at:[info draggingLocation]];
209 // Implement NSDraggingDestination protocol method
210 // performDragOperation: for bookmark buttons.
211 - (BOOL)performDragOperationForBookmarkButton:(id<NSDraggingInfo>)info {
212   BOOL rtn = NO;
213   NSData* data = [[info draggingPasteboard]
214                   dataForType:kBookmarkButtonDragType];
215   // [info draggingSource] is nil if not the same application.
216   if (data && [info draggingSource]) {
217     BookmarkButton* button = nil;
218     [data getBytes:&button length:sizeof(button)];
220     // If we're dragging from one profile to another, disallow moving (only
221     // allow copying). Each profile has its own bookmark model, so one way to
222     // check whether we are dragging across profiles is to see if the
223     // |BookmarkNode| corresponding to |button| exists in this profile. If it
224     // does, we're dragging within a profile; otherwise, we're dragging across
225     // profiles.
226     const BookmarkModel* const model = [[self controller] bookmarkModel];
227     const BookmarkNode* const source_node = [button bookmarkNode];
228     const BookmarkNode* const target_node =
229         model->GetNodeByID(source_node->id());
231     BOOL copy =
232         !([info draggingSourceOperationMask] & NSDragOperationMove) ||
233         (source_node != target_node);
234     rtn = [controller_ dragButton:button
235                                to:[info draggingLocation]
236                              copy:copy];
237     content::RecordAction(UserMetricsAction("BookmarkBar_DragEnd"));
238   }
239   return rtn;
242 - (BOOL)performDragOperation:(id<NSDraggingInfo>)info {
243   if ([controller_ dragBookmarkData:info])
244     return YES;
245   NSPasteboard* pboard = [info draggingPasteboard];
246   if ([pboard dataForType:kBookmarkButtonDragType]) {
247     if ([self performDragOperationForBookmarkButton:info])
248       return YES;
249     // Fall through....
250   }
251   if ([pboard containsURLData]) {
252     if ([self performDragOperationForURL:info])
253       return YES;
254   }
255   return NO;
258 - (NSMenu*)menu {
259   return [[controller_ menuController] menuForBookmarkBar];
262 - (void)setController:(id)controller {
263   controller_ = controller;
266 - (ViewID)viewID {
267   return VIEW_ID_BOOKMARK_BAR;
270 @end  // @implementation BookmarkBarView
272 @implementation BookmarkBarTextField
274 - (NSMenu*)menu {
275   return [barView_ menu];
278 @end  // @implementation BookmarkBarTextField
280 @implementation BookmarkBarItemContainer
282 - (NSMenu*)menu {
283   return [barView_ menu];
286 @end  // @implementation BookmarkBarItemContainer