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.
4
5#import <Cocoa/Cocoa.h>
6#include <vector>
7#import "chrome/browser/ui/cocoa/draggable_button.h"
8#include "ui/base/window_open_disposition.h"
9
10@class BookmarkBarFolderController;
11@class BookmarkButton;
12class BookmarkModel;
13class BookmarkNode;
14@class BrowserWindowController;
15class ThemeService;
16
17// Protocol for a BookmarkButton's delegate, responsible for doing
18// things on behalf of a bookmark button.
19@protocol BookmarkButtonDelegate
20
21// Fill the given pasteboard with appropriate data when the given button is
22// dragged. Since the delegate has no way of providing pasteboard data later,
23// all data must actually be put into the pasteboard and not merely promised.
24- (void)fillPasteboard:(NSPasteboard*)pboard
25       forDragOfButton:(BookmarkButton*)button;
26
27// Bookmark buttons pass mouseEntered: and mouseExited: events to
28// their delegate.  This allows the delegate to decide (for example)
29// which one, if any, should perform a hover-open.
30- (void)mouseEnteredButton:(id)button event:(NSEvent*)event;
31- (void)mouseExitedButton:(id)button event:(NSEvent*)event;
32
33// Returns YES if a drag operation should lock the fullscreen overlay bar
34// visibility before starting.  For example, dragging a bookmark button should
35// not lock the overlay if the bookmark bar is currently showing in detached
36// mode on the NTP.
37- (BOOL)dragShouldLockBarVisibility;
38
39// Returns the top-level window for this button.
40- (NSWindow*)browserWindow;
41
42// Returns YES if the bookmark button can be dragged to the trash, NO otherwise.
43- (BOOL)canDragBookmarkButtonToTrash:(BookmarkButton*)button;
44
45// This is called after the user has dropped the bookmark button on the trash.
46// The delegate can use this event to delete the bookmark.
47- (void)didDragBookmarkToTrash:(BookmarkButton*)button;
48
49// This is called after the drag has finished, for any reason.
50// We particularly need this so we can hide bookmark folder menus and stop
51// doing that hover thing.
52- (void)bookmarkDragDidEnd:(BookmarkButton*)button
53                 operation:(NSDragOperation)operation;
54
55@end
56
57
58// Protocol to be implemented by controllers that logically own
59// bookmark buttons.  The controller may be either an NSViewController
60// or NSWindowController.  The BookmarkButton doesn't use this
61// protocol directly; it is used when BookmarkButton controllers talk
62// to each other.
63//
64// Other than the top level owner (the bookmark bar), all bookmark
65// button controllers have a parent controller.
66@protocol BookmarkButtonControllerProtocol
67
68// Close all bookmark folders, walking up the ownership chain.
69- (void)closeAllBookmarkFolders;
70
71// Close just my bookmark folder.
72- (void)closeBookmarkFolder:(id)sender;
73
74// Return the bookmark model for this controller.
75- (BookmarkModel*)bookmarkModel;
76
77// Perform drag enter/exit operations, such as hover-open and hover-close.
78- (BOOL)draggingAllowed:(id<NSDraggingInfo>)info;
79- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info;
80- (void)draggingExited:(id<NSDraggingInfo>)info;
81
82// Returns YES if a drag operation should lock the fullscreen overlay bar
83// visibility before starting.  For example, dragging a bookmark button should
84// not lock the overlay if the bookmark bar is currently showing in detached
85// mode on the NTP.
86- (BOOL)dragShouldLockBarVisibility;
87
88// Perform the actual DnD of a bookmark or bookmark button.
89
90// |point| is in the base coordinate system of the destination window;
91// |it comes from an id<NSDraggingInfo>. |copy| is YES if a copy is to be
92// made and inserted into the new location while leaving the bookmark in
93// the old location, otherwise move the bookmark by removing from its old
94// location and inserting into the new location.
95- (BOOL)dragButton:(BookmarkButton*)sourceButton
96                to:(NSPoint)point
97              copy:(BOOL)copy;
98
99// Determine if the pasteboard from |info| has dragging data containing
100// bookmark(s) and perform the drag and return YES, otherwise return NO.
101- (BOOL)dragBookmarkData:(id<NSDraggingInfo>)info;
102
103// Determine if the drag pasteboard has any drag data of type
104// kBookmarkDictionaryListPboardType and, if so, return those elements
105// otherwise return an empty vector.
106- (std::vector<const BookmarkNode*>)retrieveBookmarkNodeData;
107
108// Return YES if we should show the drop indicator, else NO.  In some
109// cases (e.g. hover open) we don't want to show the drop indicator.
110// |point| is in the base coordinate system of the destination window;
111// |it comes from an id<NSDraggingInfo>.
112- (BOOL)shouldShowIndicatorShownForPoint:(NSPoint)point;
113
114// The x or y coordinate of (the middle of) the indicator to draw for
115// a drag of the source button to the given point (given in window
116// coordinates).
117// |point| is in the base coordinate system of the destination window;
118// |it comes from an id<NSDraggingInfo>.
119// TODO(viettrungluu,jrg): instead of this, make buttons move around.
120// http://crbug.com/35968
121- (CGFloat)indicatorPosForDragToPoint:(NSPoint)point;
122
123// Used to tell the controller that room should be made for a drop.
124- (void)setDropInsertionPos:(CGFloat)where;
125
126// Used to tell the controller to stop making room for a drop.
127- (void)clearDropInsertionPos;
128
129// Return the theme service associated with this browser window.
130- (ThemeService*)themeService;
131
132// Called just before a child folder puts itself on screen.
133- (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child;
134
135// Called just before a child folder closes.
136- (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child;
137
138// Return a controller's folder controller for a subfolder, or nil.
139- (BookmarkBarFolderController*)folderController;
140
141// Add a new folder controller as triggered by the given folder button.
142// If there is a current folder controller, close it.
143- (void)addNewFolderControllerWithParentButton:(BookmarkButton*)parentButton;
144
145// Open all of the nodes for the given node with disposition.
146- (void)openAll:(const BookmarkNode*)node
147    disposition:(WindowOpenDisposition)disposition;
148
149// There are several operations which may affect the contents of a bookmark
150// button controller after it has been created, primary of which are
151// cut/paste/delete and drag/drop. Such changes may involve coordinating
152// the bookmark button contents of two controllers (such as when a bookmark is
153// dragged from one folder to another).  The bookmark bar controller
154// coordinates in response to notifications propagated by the bookmark model
155// through BookmarkBarBridge calls. The following three functions are
156// implemented by the controllers and are dispatched by the bookmark bar
157// controller in response to notifications coming in from the BookmarkBarBridge.
158
159// Add a button for the given node to the bar or folder menu. This is safe
160// to call when a folder menu window is open as that window will be updated.
161// And index of -1 means to append to the end (bottom).
162- (void)addButtonForNode:(const BookmarkNode*)node
163                 atIndex:(NSInteger)buttonIndex;
164
165// Given a list or |urls| and |titles|, create new bookmark nodes and add
166// them to the bookmark model such that they will be 1) added to the folder
167// represented by the button at |point| if it is a folder, or 2) inserted
168// into the parent of the non-folder bookmark at |point| in front of that
169// button. Returns YES if at least one bookmark was added.
170- (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point;
171
172// Move a button from one place in the menu to another. This is safe
173// to call when a folder menu window is open as that window will be updated.
174- (void)moveButtonFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex;
175
176// Remove the bookmark button at the given index. Show the poof animation
177// if |animate:| is YES.  It may be obvious, but this is safe
178// to call when a folder menu window is open as that window will be updated.
179- (void)removeButton:(NSInteger)buttonIndex animate:(BOOL)poof;
180
181// Determine the controller containing the button representing |node|, if any.
182- (id<BookmarkButtonControllerProtocol>)controllerForNode:
183      (const BookmarkNode*)node;
184
185@end  // @protocol BookmarkButtonControllerProtocol
186
187
188// Class for bookmark bar buttons that can be drag sources.
189@interface BookmarkButton : DraggableButton {
190 @private
191  IBOutlet NSObject<BookmarkButtonDelegate>* delegate_;  // Weak.
192
193  // Saved pointer to the BWC for the browser window that contains this button.
194  // Used to lock and release bar visibility during a drag.  The pointer is
195  // saved because the bookmark button is no longer a part of a window at the
196  // end of a drag operation (or, in fact, can be dragged to a completely
197  // different window), so there is no way to retrieve the same BWC object after
198  // a drag.
199  BrowserWindowController* visibilityDelegate_;  // weak
200
201  NSPoint dragMouseOffset_;
202  NSPoint dragEndScreenLocation_;
203  BOOL dragPending_;
204  BOOL acceptsTrackIn_;
205  NSTrackingArea* area_;
206}
207
208@property(assign, nonatomic) NSObject<BookmarkButtonDelegate>* delegate;
209@property(assign, nonatomic) BOOL acceptsTrackIn;
210
211// Return the bookmark node associated with this button, or NULL.
212- (const BookmarkNode*)bookmarkNode;
213
214// Return YES if this is a folder button (the node has subnodes).
215- (BOOL)isFolder;
216
217- (void)mouseDragged:(NSEvent*)theEvent;
218
219- (BOOL)acceptsTrackInFrom:(id)sender;
220
221// At this time we represent an empty folder (e.g. the string
222// '(empty)') as a disabled button with no associated node.
223//
224// TODO(jrg): improve; things work but are slightly ugly since "empty"
225// and "one disabled button" are not the same thing.
226// http://crbug.com/35967
227- (BOOL)isEmpty;
228
229// Turn on or off pulsing of a bookmark button.
230// Triggered by the bookmark bubble.
231- (void)setIsContinuousPulsing:(BOOL)flag;
232
233// Return continuous pulse state.
234- (BOOL)isContinuousPulsing;
235
236// Return the location in screen coordinates where the remove animation should
237// be displayed.
238- (NSPoint)screenLocationForRemoveAnimation;
239
240// The BookmarkButton which is currently being dragged, if any.
241+ (BookmarkButton*)draggedButton;
242
243
244@end  // @interface BookmarkButton
245
246
247@interface BookmarkButton(TestingAPI)
248- (void)beginDrag:(NSEvent*)event;
249@end
250
251namespace bookmark_button {
252
253// Notifications for pulsing of bookmarks.
254extern NSString* const kPulseBookmarkButtonNotification;
255
256// Key for userInfo dict of a kPulseBookmarkButtonNotification.
257// Value is a [NSValue valueWithPointer:]; pointer is a (const BookmarkNode*).
258extern NSString* const kBookmarkKey;
259
260// Key for userInfo dict of a kPulseBookmarkButtonNotification.
261// Value is a [NSNumber numberWithBool:] to turn pulsing on or off.
262extern NSString* const kBookmarkPulseFlagKey;
263
264};
265