summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/bookmark_bar_controller.h
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/bookmark_bar_controller.h')
-rw-r--r--chrome/browser/cocoa/bookmark_bar_controller.h375
1 files changed, 375 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.h b/chrome/browser/cocoa/bookmark_bar_controller.h
new file mode 100644
index 0000000..8060385
--- /dev/null
+++ b/chrome/browser/cocoa/bookmark_bar_controller.h
@@ -0,0 +1,375 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COCOA_BOOKMARK_BAR_CONTROLLER_H_
+#define CHROME_BROWSER_COCOA_BOOKMARK_BAR_CONTROLLER_H_
+
+#import <Cocoa/Cocoa.h>
+#include <map>
+
+#import "base/chrome_application_mac.h"
+#include "base/scoped_nsobject.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/cocoa/bookmark_bar_bridge.h"
+#import "chrome/browser/cocoa/bookmark_bar_state.h"
+#import "chrome/browser/cocoa/bookmark_bar_toolbar_view.h"
+#import "chrome/browser/cocoa/bookmark_button.h"
+#include "chrome/browser/cocoa/tab_strip_model_observer_bridge.h"
+#include "webkit/glue/window_open_disposition.h"
+
+@class BookmarkBarController;
+@class BookmarkBarFolderController;
+@class BookmarkBarView;
+@class BookmarkButton;
+@class BookmarkButtonCell;
+@class BookmarkFolderTarget;
+class BookmarkModel;
+@class BookmarkMenu;
+class BookmarkNode;
+class Browser;
+class GURL;
+class PrefService;
+class Profile;
+class TabContents;
+@class ToolbarController;
+@protocol ViewResizer;
+
+namespace bookmarks {
+
+// Magic numbers from Cole
+// TODO(jrg): create an objc-friendly version of bookmark_bar_constants.h?
+
+// Used as a maximum width for buttons on the bar.
+const CGFloat kDefaultBookmarkWidth = 150.0;
+
+// TODO(jrg): http://crbug.com/36276 to get final sizes.
+// Used as a min/max width for buttons on menus (not on the bar).
+const CGFloat kBookmarkMenuButtonMinimumWidth = 100.0;
+const CGFloat kBookmarkMenuButtonMaximumWidth = 485.0;
+
+const CGFloat kBookmarkVerticalPadding = 2.0;
+const CGFloat kBookmarkHorizontalPadding = 1.0;
+const CGFloat kBookmarkHorizontalScreenPadding = 8.0;
+
+// Our NSScrollView is supposed to be just barely big enough to fit its
+// contentView. It is actually a hair too small.
+// This turns on horizontal scrolling which, although slight, is awkward.
+// Make sure our window (and NSScrollView) are wider than its documentView
+// by at least this much.
+const CGFloat kScrollViewContentWidthMargin = 2;
+
+// Make subfolder menus overlap their parent menu a bit to give a better
+// perception of a menuing system.
+const CGFloat kBookmarkMenuOverlap = 1.0;
+
+// Delay before opening a subfolder (and closing the previous one)
+// when hovering over a folder button.
+const NSTimeInterval kHoverOpenDelay = 0.3;
+
+// Delay on hover before a submenu opens when dragging.
+// Experimentally a drag hover open delay needs to be bigger than a
+// normal (non-drag) menu hover open such as used in the bookmark folder.
+// TODO(jrg): confirm feel of this constant with ui-team.
+// http://crbug.com/36276
+const NSTimeInterval kDragHoverOpenDelay = 0.7;
+
+// Notes on use of kDragHoverCloseDelay in
+// -[BookmarkBarFolderController draggingEntered:].
+//
+// We have an implicit delay on stop-hover-open before a submenu
+// closes. This cannot be zero since it's nice to move the mouse in a
+// direct line from "current position" to "position of item in
+// submenu". However, by doing so, it's possible to overlap a
+// different button on the current menu. Example:
+//
+// Folder1
+// Folder2 ---> Sub1
+// Folder3 Sub2
+// Sub3
+//
+// If you hover over the F in Folder2 to open the sub, and then want to
+// select Sub3, a direct line movement of the mouse may cross over
+// Folder3. Without this delay, that'll cause Sub to be closed before
+// you get there, since a "hover over" of Folder3 gets activated.
+// It's subtle but without the delay it feels broken.
+//
+// This is only really a problem with vertical menu --> vertical menu
+// movement; the bookmark bar (horizontal menu, sort of) seems fine,
+// perhaps because mouse move direction is purely vertical so there is
+// no opportunity for overlap.
+const NSTimeInterval kDragHoverCloseDelay = 0.4;
+
+} // namespace bookmarks
+
+// The interface for the bookmark bar controller's delegate. Currently, the
+// delegate is the BWC and is responsible for ensuring that the toolbar is
+// displayed correctly (as specified by |-getDesiredToolbarHeightCompression|
+// and |-toolbarDividerOpacity|) at the beginning and at the end of an animation
+// (or after a state change).
+@protocol BookmarkBarControllerDelegate
+
+// Sent when the state has changed (after any animation), but before the final
+// display update.
+- (void)bookmarkBar:(BookmarkBarController*)controller
+ didChangeFromState:(bookmarks::VisualState)oldState
+ toState:(bookmarks::VisualState)newState;
+
+// Sent before the animation begins.
+- (void)bookmarkBar:(BookmarkBarController*)controller
+willAnimateFromState:(bookmarks::VisualState)oldState
+ toState:(bookmarks::VisualState)newState;
+
+@end
+
+// A controller for the bookmark bar in the browser window. Handles showing
+// and hiding based on the preference in the given profile.
+@interface BookmarkBarController :
+ NSViewController<BookmarkBarState,
+ BookmarkBarToolbarViewController,
+ BookmarkButtonDelegate,
+ BookmarkButtonControllerProtocol,
+ CrApplicationEventHookProtocol,
+ NSUserInterfaceValidations> {
+ @private
+ // The visual state of the bookmark bar. If an animation is running, this is
+ // set to the "destination" and |lastVisualState_| is set to the "original"
+ // state. This is set to |kInvalidState| on initialization (when the
+ // appropriate state is not yet known).
+ bookmarks::VisualState visualState_;
+
+ // The "original" state of the bookmark bar if an animation is running,
+ // otherwise it should be |kInvalidState|.
+ bookmarks::VisualState lastVisualState_;
+
+ Browser* browser_; // weak; owned by its window
+ BookmarkModel* bookmarkModel_; // weak; part of the profile owned by the
+ // top-level Browser object.
+
+ // Our initial view width, which is applied in awakeFromNib.
+ CGFloat initialWidth_;
+
+ // BookmarkNodes have a 64bit id. NSMenuItems have a 32bit tag used
+ // to represent the bookmark node they refer to. This map provides
+ // a mapping from one to the other, so we can properly identify the
+ // node from the item. When adding items in, we start with seedId_.
+ int32 seedId_;
+ std::map<int32,int64> menuTagMap_;
+
+ // Our bookmark buttons, ordered from L-->R.
+ scoped_nsobject<NSMutableArray> buttons_;
+
+ // The folder image so we can use one copy for all buttons
+ scoped_nsobject<NSImage> folderImage_;
+
+ // The default image, so we can use one copy for all buttons.
+ scoped_nsobject<NSImage> defaultImage_;
+
+ // If the bar is disabled, we hide it and ignore show/hide commands.
+ // Set when using fullscreen mode.
+ BOOL barIsEnabled_;
+
+ // Bridge from Chrome-style C++ notifications (e.g. derived from
+ // BookmarkModelObserver)
+ scoped_ptr<BookmarkBarBridge> bridge_;
+
+ // Delegate that is informed about state changes in the bookmark bar.
+ id<BookmarkBarControllerDelegate> delegate_; // weak
+
+ // Delegate that can resize us.
+ id<ViewResizer> resizeDelegate_; // weak
+
+ // Logic for dealing with a click on a bookmark folder button.
+ scoped_nsobject<BookmarkFolderTarget> folderTarget_;
+
+ // A controller for a pop-up bookmark folder window (custom menu).
+ // This is not a scoped_nsobject because it owns itself (when its
+ // window closes the controller gets autoreleased).
+ BookmarkBarFolderController* folderController_;
+
+ // Are watching for a "click outside" or other event which would
+ // signal us to close the bookmark bar folder menus?
+ BOOL watchingForExitEvent_;
+
+ IBOutlet BookmarkBarView* buttonView_; // Contains 'no items' text fields.
+ IBOutlet BookmarkButton* offTheSideButton_; // aka the chevron.
+ IBOutlet NSMenu* buttonContextMenu_;
+
+ NSRect originalNoItemsRect_; // Original, pre-resized field rect.
+ NSRect originalImportBookmarksRect_; // Original, pre-resized field rect.
+
+ // "Other bookmarks" button on the right side.
+ scoped_nsobject<NSButton> otherBookmarksButton_;
+
+ // We have a special menu for folder buttons. This starts as a copy
+ // of the bar menu.
+ scoped_nsobject<BookmarkMenu> buttonFolderContextMenu_;
+
+ // When doing a drag, this is folder button "hovered over" which we
+ // may want to open after a short delay. There are cases where a
+ // mouse-enter can open a folder (e.g. if the menus are "active")
+ // but that doesn't use this variable or need a delay so "hover" is
+ // the wrong term.
+ scoped_nsobject<BookmarkButton> hoverButton_;
+
+ // We save the view width when we add bookmark buttons. This lets
+ // us avoid a rebuild until we've grown the window bigger than our
+ // initial build.
+ CGFloat savedFrameWidth_;
+
+ // The number of buttons we display in the bookmark bar. This does
+ // not include the "off the side" chevron or the "Other Bookmarks"
+ // button. We use this number to determine if we need to display
+ // the chevron, and to know what to place in the chevron's menu.
+ // Since we create everything before doing layout we can't be sure
+ // that all bookmark buttons we create will be visible. Thus,
+ // [buttons_ count] isn't a definitive check.
+ int displayedButtonCount_;
+
+ // A state flag which tracks when the bar's folder menus should be shown.
+ // An initial click in any of the folder buttons turns this on and
+ // one of the following will turn it off: another click in the button,
+ // the window losing focus, a click somewhere other than in the bar
+ // or a folder menu.
+ BOOL showFolderMenus_;
+
+ // Set to YES to prevent any node animations. Useful for unit testing so that
+ // incomplete animations do not cause valgrind complaints.
+ BOOL ignoreAnimations_;
+}
+
+@property(readonly, nonatomic) bookmarks::VisualState visualState;
+@property(readonly, nonatomic) bookmarks::VisualState lastVisualState;
+@property(assign, nonatomic) id<BookmarkBarControllerDelegate> delegate;
+
+// Initializes the bookmark bar controller with the given browser
+// profile and delegates.
+- (id)initWithBrowser:(Browser*)browser
+ initialWidth:(CGFloat)initialWidth
+ delegate:(id<BookmarkBarControllerDelegate>)delegate
+ resizeDelegate:(id<ViewResizer>)resizeDelegate;
+
+// Updates the bookmark bar (from its current, possibly in-transition) state to
+// the one appropriate for the new conditions.
+- (void)updateAndShowNormalBar:(BOOL)showNormalBar
+ showDetachedBar:(BOOL)showDetachedBar
+ withAnimation:(BOOL)animate;
+
+// Update the visible state of the bookmark bar.
+- (void)updateVisibility;
+
+// Turn on or off the bookmark bar and prevent or reallow its appearance. On
+// disable, toggle off if shown. On enable, show only if needed. App and popup
+// windows do not show a bookmark bar.
+- (void)setBookmarkBarEnabled:(BOOL)enabled;
+
+// Returns the amount by which the toolbar above should be compressed.
+- (CGFloat)getDesiredToolbarHeightCompression;
+
+// Gets the appropriate opacity for the toolbar's divider; 0 means that it
+// shouldn't be shown.
+- (CGFloat)toolbarDividerOpacity;
+
+// Updates the sizes and positions of the subviews.
+// TODO(viettrungluu): I'm not convinced this should be public, but I currently
+// need it for animations. Try not to propagate its use.
+- (void)layoutSubviews;
+
+// Called by our view when it is moved to a window.
+- (void)viewDidMoveToWindow;
+
+// Import bookmarks from another browser.
+- (IBAction)importBookmarks:(id)sender;
+
+// Provide a favIcon for a bookmark node. May return nil.
+- (NSImage*)favIconForNode:(const BookmarkNode*)node;
+
+// Used for situations where the bookmark bar folder menus should no longer
+// be actively popping up. Called when the window loses focus, a click has
+// occured outside the menus or a bookmark has been activated. (Note that this
+// differs from the behavior of the -[BookmarkButtonControllerProtocol
+// closeAllBookmarkFolders] method in that the latter does not terminate menu
+// tracking since it may be being called in response to actions (such as
+// dragging) where a 'stale' menu presentation should first be collapsed before
+// presenting a new menu.)
+- (void)closeFolderAndStopTrackingMenus;
+
+// Actions for manipulating bookmarks.
+// Open a normal bookmark or folder from a button, ...
+- (IBAction)openBookmark:(id)sender;
+- (IBAction)openBookmarkFolderFromButton:(id)sender;
+// From the "off the side" button, ...
+- (IBAction)openOffTheSideFolderFromButton:(id)sender;
+// From a context menu over the button, ...
+- (IBAction)openBookmarkInNewForegroundTab:(id)sender;
+- (IBAction)openBookmarkInNewWindow:(id)sender;
+- (IBAction)openBookmarkInIncognitoWindow:(id)sender;
+- (IBAction)editBookmark:(id)sender;
+- (IBAction)cutBookmark:(id)sender;
+- (IBAction)copyBookmark:(id)sender;
+- (IBAction)pasteBookmark:(id)sender;
+- (IBAction)deleteBookmark:(id)sender;
+// From a context menu over the bar, ...
+- (IBAction)openAllBookmarks:(id)sender;
+- (IBAction)openAllBookmarksNewWindow:(id)sender;
+- (IBAction)openAllBookmarksIncognitoWindow:(id)sender;
+// Or from a context menu over either the bar or a button.
+- (IBAction)addPage:(id)sender;
+- (IBAction)addFolder:(id)sender;
+
+@end
+
+// Redirects from BookmarkBarBridge, the C++ object which glues us to
+// the rest of Chromium. Internal to BookmarkBarController.
+@interface BookmarkBarController(BridgeRedirect)
+- (void)loaded:(BookmarkModel*)model;
+- (void)beingDeleted:(BookmarkModel*)model;
+- (void)nodeAdded:(BookmarkModel*)model
+ parent:(const BookmarkNode*)oldParent index:(int)index;
+- (void)nodeChanged:(BookmarkModel*)model
+ node:(const BookmarkNode*)node;
+- (void)nodeMoved:(BookmarkModel*)model
+ oldParent:(const BookmarkNode*)oldParent oldIndex:(int)oldIndex
+ newParent:(const BookmarkNode*)newParent newIndex:(int)newIndex;
+- (void)nodeRemoved:(BookmarkModel*)model
+ parent:(const BookmarkNode*)oldParent index:(int)index;
+- (void)nodeFavIconLoaded:(BookmarkModel*)model
+ node:(const BookmarkNode*)node;
+- (void)nodeChildrenReordered:(BookmarkModel*)model
+ node:(const BookmarkNode*)node;
+@end
+
+// These APIs should only be used by unit tests (or used internally).
+@interface BookmarkBarController(InternalOrTestingAPI)
+- (BookmarkBarView*)buttonView;
+- (NSMutableArray*)buttons;
+- (NSMenu*)offTheSideMenu;
+- (NSButton*)offTheSideButton;
+- (BOOL)offTheSideButtonIsHidden;
+- (NSButton*)otherBookmarksButton;
+- (BookmarkBarFolderController*)folderController;
+- (id)folderTarget;
+- (int)displayedButtonCount;
+- (void)openURL:(GURL)url disposition:(WindowOpenDisposition)disposition;
+- (void)clearBookmarkBar;
+- (BookmarkButtonCell*)cellForBookmarkNode:(const BookmarkNode*)node;
+- (NSRect)frameForBookmarkButtonFromCell:(NSCell*)cell xOffset:(int*)xOffset;
+- (void)checkForBookmarkButtonGrowth:(NSButton*)button;
+- (void)frameDidChange;
+- (int64)nodeIdFromMenuTag:(int32)tag;
+- (int32)menuTagFromNodeId:(int64)menuid;
+- (const BookmarkNode*)nodeFromMenuItem:(id)sender;
+- (void)updateTheme:(ThemeProvider*)themeProvider;
+- (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point;
+- (BOOL)isEventAnExitEvent:(NSEvent*)event;
+- (BOOL)shrinkOrHideView:(NSView*)view forMaxX:(CGFloat)maxViewX;
+
+// The following are for testing purposes only and are not used internally.
+- (NSMenu *)menuForFolderNode:(const BookmarkNode*)node;
+- (NSMenu*)buttonContextMenu;
+- (void)setButtonContextMenu:(id)menu;
+// Set to YES in order to prevent animations.
+- (void)setIgnoreAnimations:(BOOL)ignore;
+@end
+
+#endif // CHROME_BROWSER_COCOA_BOOKMARK_BAR_CONTROLLER_H_