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