Commit c537af28 authored by rsesek@chromium.org's avatar rsesek@chromium.org

[Mac] Replace the custom bookmark menus with native NSMenus.

This replaces a lot of custom code with an implementation that reuses the
architecture of the menubar Bookmarks menu.

This CL introduces two minor regressions (bugs pending):
* Hover state is lost after menu is opened. Mousing out/back over fixes.
* The off-the-side menu contains all items from the bookmark bar.

BUG=78151
TEST=Click on a bookmark folder button. A menu opens.

Review URL: http://codereview.chromium.org/7465090

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95609 0039d316-1c4b-4281-b951-d872f2087c98
parent a007e737
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
......@@ -46,80 +46,10 @@ const CGFloat kBookmarkHorizontalPadding = 1.0;
// Vertical frame inset for buttons in the bookmark bar.
const CGFloat kBookmarkVerticalPadding = 2.0;
// Used as a min/max width for buttons on menus (not on the bar).
const CGFloat kBookmarkMenuButtonMinimumWidth = 100.0;
const CGFloat kBookmarkMenuButtonMaximumWidth = 485.0;
// The minimum separation between a folder menu and the edge of the screen.
// If the menu gets closer to the edge of the screen (either right or left)
// then it is pops up in the opposite direction.
// (See -[BookmarkBarFolderController childFolderWindowLeftForWidth:]).
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 = 2.0;
// When constraining a scrolling bookmark bar folder window to the
// screen, shrink the "constrain" by this much vertically. Currently
// this is 0.0 to avoid a problem with tracking areas leaving the
// window, but should probably be 8.0 or something.
const CGFloat kScrollWindowVerticalMargin = 6.0;
// How far to offset a folder menu from the top of the bookmark bar. This
// is set just above the bar so that it become distinctive when drawn.
const CGFloat kBookmarkBarMenuOffset = 2.0;
// How far to offset a folder menu's left edge horizontally in relation to
// the left edge of the button from which it springs. Because of drawing
// differences, simply aligning the |frame| of each does not render the
// pproper result, so we have to offset.
const CGFloat kBookmarkBarButtonOffset = 2.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
......
// Copyright (c) 2011 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.
#import <Cocoa/Cocoa.h>
#include "base/memory/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
// Hover state machine. Encapsulates the hover state for
// BookmarkBarFolderController.
// A strict call order is implied with these calls. It is ONLY valid to make
// the following state transitions:
// From: To: Via:
// closed opening scheduleOpen...:
// opening closed cancelPendingOpen...: or
// open scheduleOpen...: completes.
// open closing scheduleClose...:
// closing open cancelPendingClose...: or
// closed scheduleClose...: completes.
//
@interface BookmarkBarFolderHoverState : NSObject {
@private
// Enumeration of the valid states that the |hoverButton_| member can be in.
// Because the opening and closing of hover views can be done asyncronously
// there are periods where the hover state is in transtion between open and
// closed. During those times of transition the opening or closing operation
// can be cancelled. We serialize the opening and closing of the
// |hoverButton_| using this state information. This serialization is to
// avoid race conditions where one hover button is being opened while another
// is closing.
enum HoverState {
kHoverStateClosed = 0,
kHoverStateOpening = 1,
kHoverStateOpen = 2,
kHoverStateClosing = 3
};
// Like normal menus, hovering over a folder button causes it to
// open. This variable is set when a hover is initiated (but has
// not necessarily fired yet).
scoped_nsobject<BookmarkButton> hoverButton_;
// We model hover state as a state machine with specific allowable
// transitions. |hoverState_| is the state of this machine at any
// given time.
HoverState hoverState_;
}
// Designated initializer.
- (id)init;
// The BookmarkBarFolderHoverState decides when it is appropriate to hide
// and show the button that the BookmarkBarFolderController drags over.
- (NSDragOperation)draggingEnteredButton:(BookmarkButton*)button;
// The BookmarkBarFolderHoverState decides the fate of the hover button
// when the BookmarkBarFolderController's view is exited.
- (void)draggingExited;
@end
// Exposing these for unit testing purposes. They are used privately in the
// implementation as well.
@interface BookmarkBarFolderHoverState(PrivateAPI)
// State change APIs.
- (void)scheduleCloseBookmarkFolderOnHoverButton;
- (void)cancelPendingCloseBookmarkFolderOnHoverButton;
- (void)scheduleOpenBookmarkFolderOnHoverButton:(BookmarkButton*)hoverButton;
- (void)cancelPendingOpenBookmarkFolderOnHoverButton;
@end
// Exposing these for unit testing purposes. They are used only in tests.
@interface BookmarkBarFolderHoverState(TestingAPI)
// Accessors and setters for button and hover state.
- (BookmarkButton*)hoverButton;
- (HoverState)hoverState;
@end
// 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.
#import <Cocoa/Cocoa.h>
#include "base/message_loop.h"
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_hover_state.h"
#import "chrome/browser/ui/cocoa/browser_test_helper.h"
#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
namespace {
typedef CocoaTest BookmarkBarFolderHoverStateTest;
// Hover state machine interface.
// A strict call order is implied with these calls. It is ONLY valid to make
// these specific state transitions.
TEST(BookmarkBarFolderHoverStateTest, HoverState) {
BrowserTestHelper helper;
scoped_nsobject<BookmarkBarFolderHoverState> bbfhs;
bbfhs.reset([[BookmarkBarFolderHoverState alloc] init]);
// Initial state.
EXPECT_FALSE([bbfhs hoverButton]);
ASSERT_EQ(kHoverStateClosed, [bbfhs hoverState]);
scoped_nsobject<BookmarkButton> button;
button.reset([[BookmarkButton alloc] initWithFrame:NSMakeRect(0, 0, 20, 20)]);
// Test transition from closed to opening.
ASSERT_EQ(kHoverStateClosed, [bbfhs hoverState]);
[bbfhs scheduleOpenBookmarkFolderOnHoverButton:button];
ASSERT_EQ(kHoverStateOpening, [bbfhs hoverState]);
// Test transition from opening to closed (aka cancel open).
[bbfhs cancelPendingOpenBookmarkFolderOnHoverButton];
ASSERT_EQ(kHoverStateClosed, [bbfhs hoverState]);
ASSERT_EQ(nil, [bbfhs hoverButton]);
// Test transition from closed to opening.
ASSERT_EQ(kHoverStateClosed, [bbfhs hoverState]);
[bbfhs scheduleOpenBookmarkFolderOnHoverButton:button];
ASSERT_EQ(kHoverStateOpening, [bbfhs hoverState]);
// Test transition from opening to opened.
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
new MessageLoop::QuitTask,
bookmarks::kDragHoverOpenDelay * 1000.0 * 1.5);
MessageLoop::current()->Run();
ASSERT_EQ(kHoverStateOpen, [bbfhs hoverState]);
ASSERT_EQ(button, [bbfhs hoverButton]);
// Test transition from opening to opened.
[bbfhs scheduleCloseBookmarkFolderOnHoverButton];
ASSERT_EQ(kHoverStateClosing, [bbfhs hoverState]);
// Test transition from closing to open (aka cancel close).
[bbfhs cancelPendingCloseBookmarkFolderOnHoverButton];
ASSERT_EQ(kHoverStateOpen, [bbfhs hoverState]);
ASSERT_EQ(button, [bbfhs hoverButton]);
// Test transition from closing to closed.
[bbfhs scheduleCloseBookmarkFolderOnHoverButton];
ASSERT_EQ(kHoverStateClosing, [bbfhs hoverState]);
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
new MessageLoop::QuitTask,
bookmarks::kDragHoverCloseDelay * 1000.0 * 1.5);
MessageLoop::current()->Run();
ASSERT_EQ(kHoverStateClosed, [bbfhs hoverState]);
ASSERT_EQ(nil, [bbfhs hoverButton]);
}
} // namespace
// Copyright (c) 2011 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.
#import <Cocoa/Cocoa.h>
@protocol BookmarkButtonControllerProtocol;
@class BookmarkBarFolderController;
// Main content view for a bookmark bar folder "menu" window. This is
// logically similar to a BookmarkBarView but is oriented vertically.
@interface BookmarkBarFolderView : NSView {
@private
BOOL inDrag_; // Are we in the middle of a drag?
BOOL dropIndicatorShown_;
CGFloat dropIndicatorPosition_; // y position
// The following |controller_| is weak; used for testing only. See the imple-
// mentation comment for - (id<BookmarkButtonControllerProtocol>)controller.
id<BookmarkButtonControllerProtocol> controller_;
}
@end
......@@ -133,12 +133,6 @@ class ThemeProvider;
// Return the theme provider associated with this browser window.
- (ui::ThemeProvider*)themeProvider;
// Called just before a child folder puts itself on screen.
- (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child;
// Called just before a child folder closes.
- (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child;
// Return a controller's folder controller for a subfolder, or nil.
- (BookmarkBarFolderController*)folderController;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment