summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/bookmark_bar_folder_controller.mm
diff options
context:
space:
mode:
authorjrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-16 05:03:02 +0000
committerjrg@chromium.org <jrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-16 05:03:02 +0000
commit8351fb10c903690cdb2c225eadb1da4a7466c2fa (patch)
treef0f28478d06cbbdce63c72ff03611601aa0c2dd6 /chrome/browser/cocoa/bookmark_bar_folder_controller.mm
parent2e4d1f8ddc079e16787209040a4ca16b87d0ce1e (diff)
downloadchromium_src-8351fb10c903690cdb2c225eadb1da4a7466c2fa.zip
chromium_src-8351fb10c903690cdb2c225eadb1da4a7466c2fa.tar.gz
chromium_src-8351fb10c903690cdb2c225eadb1da4a7466c2fa.tar.bz2
Quick and dirty bookmark folder/menu scrolling for Beta.
Intended as a temporary fix. BUG=36225 Review URL: http://codereview.chromium.org/998004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41678 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa/bookmark_bar_folder_controller.mm')
-rw-r--r--chrome/browser/cocoa/bookmark_bar_folder_controller.mm125
1 files changed, 125 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/bookmark_bar_folder_controller.mm b/chrome/browser/cocoa/bookmark_bar_folder_controller.mm
index 2ad3081..f972bdf 100644
--- a/chrome/browser/cocoa/bookmark_bar_folder_controller.mm
+++ b/chrome/browser/cocoa/bookmark_bar_folder_controller.mm
@@ -13,8 +13,24 @@
#import "chrome/browser/cocoa/bookmark_button_cell.h"
#import "chrome/browser/cocoa/browser_window_controller.h"
+namespace {
+
+// Frequency of the scrolling timer in seconds.
+const NSTimeInterval kBookmarkBarFolderScrollInterval = 0.2;
+
+// Amount to scroll by per timer fire. We scroll rather slowly; to
+// accomodate we do 2 at a time.
+const CGFloat kBookmarkBarFolderScrollAmount =
+ 2 * (bookmarks::kBookmarkButtonHeight +
+ bookmarks::kBookmarkVerticalPadding);
+}
+
@interface BookmarkBarFolderController(Private)
- (void)configureWindow;
+- (void)addScrollTracking;
+- (void)removeScrollTracking;
+- (void)endScroll;
+- (void)addScrollTimerWithDelta:(CGFloat)delta;
- (IBAction)openBookmarkFolderFromButton:(id)sender;
@end
@@ -39,11 +55,14 @@
object:nil];
[self configureWindow];
+ [self addScrollTracking];
}
return self;
}
- (void)dealloc {
+ [self removeScrollTracking];
+ [self endScroll];
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Note: we don't need to
// [NSObject cancelPreviousPerformRequestsWithTarget:self];
@@ -272,10 +291,116 @@
[[self window] setFrame:windowFrame display:YES];
+ // This is what we want, but it won't work so long as we're a child
+ // window of something at a different level. To fix (make not a
+ // child) would break other things (e.g. Expose'). I really need a
+ // modal loop for the bookmark menus. TODO(jrg)
+ // [[self window] setLevel:NSPopUpMenuWindowLevel];
+
[[parentController_ parentWindow] addChildWindow:[self window]
ordered:NSWindowAbove];
}
+// Start a "scroll up" timer.
+- (void)beginScrollWindowUp {
+ [self addScrollTimerWithDelta:kBookmarkBarFolderScrollAmount];
+}
+
+// Start a "scroll down" timer.
+- (void)beginScrollWindowDown {
+ [self addScrollTimerWithDelta:-kBookmarkBarFolderScrollAmount];
+}
+
+// End a scrolling timer. Can be called excessively with no harm.
+- (void)endScroll {
+ if (scrollTimer_) {
+ [scrollTimer_ invalidate];
+ scrollTimer_ = nil;
+ verticalScrollDelta_ = 0;
+ }
+}
+
+// Perform a scroll of the window on the screen.
+// Called by a timer when scrolling.
+- (void)performScroll:(NSTimer*)timer {
+ NSRect frame = [[self window] frame];
+ NSRect newFrame = frame;
+ newFrame.origin.y += verticalScrollDelta_;
+ [[self window] setFrameOrigin:newFrame.origin];
+
+ // If we've just move a border of the window from offscreen to
+ // onscreen, stop scrolling.
+ NSRect screenRect = [[[self window] screen] frame];
+ if ((!NSPointInRect(frame.origin, screenRect) &&
+ NSPointInRect(newFrame.origin, screenRect)) ||
+ ((NSMaxY(frame) >= NSMaxY(screenRect)) &&
+ (NSMaxY(newFrame) < NSMaxY(screenRect)))) {
+ [self endScroll];
+ }
+}
+
+// Add a timer to fire at a regular interveral which scrolls the
+// window vertically |delta|.
+- (void)addScrollTimerWithDelta:(CGFloat)delta {
+ if (scrollTimer_ && verticalScrollDelta_ == delta)
+ return;
+ [self endScroll];
+ verticalScrollDelta_ = delta;
+ scrollTimer_ =
+ [NSTimer scheduledTimerWithTimeInterval:kBookmarkBarFolderScrollInterval
+ target:self
+ selector:@selector(performScroll:)
+ userInfo:nil
+ repeats:YES];
+}
+
+// Called as a result of our tracking area. Warning: on the main
+// screen (of a single-screened machine), the minimum mouse y value is
+// 1, not 0. Also, we do not get events when the mouse is above the
+// menubar (to be fixed by setting the proper window level; see
+// initializer).
+- (void)mouseMoved:(NSEvent*)theEvent {
+ DCHECK([theEvent window] == [self window]);
+
+ NSPoint eventScreenLocation =
+ [[theEvent window] convertBaseToScreen:[theEvent locationInWindow]];
+
+ NSRect screenRect = [[[self window] screen] frame];
+ CGFloat closeToTopOfScreen = NSMaxY(screenRect) -
+ kBookmarkBarFolderScrollAmount;
+ if (eventScreenLocation.y <= (NSMinY(screenRect) + 1)) {
+ [self beginScrollWindowUp];
+ } else if (eventScreenLocation.y > closeToTopOfScreen) {
+ [self beginScrollWindowDown];
+ } else {
+ [self endScroll];
+ }
+}
+
+// Add a tracking area so we know when the mouse is pinned to the top
+// or bottom of the screen. If that happens, and if the mouse
+// position overlaps the window, scroll it. To be clear, "scroll it"
+// means "move the window vertically", not scroll it's contents with
+// an NSScrollView.
+- (void)addScrollTracking {
+ NSView* view = [[self window] contentView];
+ scrollTrackingArea_.reset([[NSTrackingArea alloc]
+ initWithRect:[view bounds]
+ options:(NSTrackingMouseMoved |
+ NSTrackingActiveAlways)
+ owner:self
+ userInfo:nil]);
+ [view addTrackingArea:scrollTrackingArea_];
+}
+
+// Remove the tracking area associated with scrolling.
+- (void)removeScrollTracking {
+ if (scrollTrackingArea_.get()) {
+ [[[self window] contentView] removeTrackingArea:scrollTrackingArea_];
+ }
+ scrollTrackingArea_.reset();
+}
+
- (ThemeProvider*)themeProvider {
return [parentController_ themeProvider];
}