diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-24 23:22:23 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-24 23:22:23 +0000 |
commit | d50e877baf62f4b553fee834e88941d864527797 (patch) | |
tree | bf4f6173a891bc1d9df1e7ed771f5f3f64036ce2 /chrome/browser/cocoa | |
parent | 3cfcae2bed49e80e31fbedf4e2ed45c594e7b941 (diff) | |
download | chromium_src-d50e877baf62f4b553fee834e88941d864527797.zip chromium_src-d50e877baf62f4b553fee834e88941d864527797.tar.gz chromium_src-d50e877baf62f4b553fee834e88941d864527797.tar.bz2 |
Mac: make bookmark bar drag buttons prettier.
(In particular, clip them to their rounded rectangle.)
BUG=28593
TEST=Drag bookmark bar buttons with a wide variety of themes; make sure edges/corners are correctly clipped from drag images.
Review URL: http://codereview.chromium.org/435028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32995 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa')
-rw-r--r-- | chrome/browser/cocoa/bookmark_button.mm | 69 | ||||
-rw-r--r-- | chrome/browser/cocoa/gradient_button_cell.h | 6 | ||||
-rw-r--r-- | chrome/browser/cocoa/gradient_button_cell.mm | 89 |
3 files changed, 138 insertions, 26 deletions
diff --git a/chrome/browser/cocoa/bookmark_button.mm b/chrome/browser/cocoa/bookmark_button.mm index 8ef0682..40a1e0a 100644 --- a/chrome/browser/cocoa/bookmark_button.mm +++ b/chrome/browser/cocoa/bookmark_button.mm @@ -2,17 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #import "base/scoped_nsobject.h" #import "chrome/browser/cocoa/bookmark_button.h" +#import "chrome/browser/cocoa/bookmark_button_cell.h" +#import "third_party/GTM/AppKit/GTMTheme.h" NSString* kBookmarkButtonDragType = @"ChromiumBookmarkButtonDragType"; -// http://codereview.chromium.org/180036/diff/3001/3004 namespace { + +// Code taken from <http://codereview.chromium.org/180036/diff/3001/3004>. +// TODO(viettrungluu): Do we want common, standard code for drag hysteresis? const CGFloat kWebDragStartHysteresisX = 5.0; const CGFloat kWebDragStartHysteresisY = 5.0; + +// The opacity of the bookmark button drag image. +const CGFloat kDragImageOpacity = 0.8; + } +@interface BookmarkButton(Private) + +// Make a drag image for the button. +- (NSImage*)dragImage; + +@end // @interface BookmarkButton(Private) + @implementation BookmarkButton @synthesize draggable = draggable_; @@ -41,25 +57,13 @@ const CGFloat kWebDragStartHysteresisY = 5.0; [pboard setData:[NSData dataWithBytes:&self length:sizeof(self)] forType:kBookmarkButtonDragType]; - // This won't work if the source view is clipped. Fortunately, we - // don't display clipped bookmark buttons. - [[self superview] lockFocus]; - scoped_nsobject<NSBitmapImageRep> - bitmapImage([[NSBitmapImageRep alloc] - initWithFocusedViewRect:[self frame]]); - - [[self superview] unlockFocus]; - scoped_nsobject<NSImage> imageDrag([[NSImage alloc] - initWithSize:[bitmapImage size]]); - [imageDrag addRepresentation:bitmapImage]; - // At the moment, moving bookmarks causes their buttons (like me!) // to be destroyed and rebuilt. Make sure we don't go away while on // the stack. [self retain]; CGFloat yAt = [self bounds].size.height; - [self dragImage:imageDrag at:NSMakePoint(0, yAt) offset:dragOffset + [self dragImage:[self dragImage] at:NSMakePoint(0, yAt) offset:dragOffset event:event pasteboard:pboard source:self slideBack:YES]; // And we're done. @@ -128,3 +132,40 @@ const CGFloat kWebDragStartHysteresisY = 5.0; } @end + +@implementation BookmarkButton(Private) + +- (NSImage*)dragImage { + NSRect bounds = [self bounds]; + + // Grab the image from the screen and put it in an |NSImage|. We can't use + // this directly since we need to clip it and set its opacity. This won't work + // if the source view is clipped. Fortunately, we don't display clipped + // bookmark buttons. + [self lockFocus]; + scoped_nsobject<NSBitmapImageRep> + bitmap([[NSBitmapImageRep alloc] initWithFocusedViewRect:bounds]); + [self unlockFocus]; + scoped_nsobject<NSImage> image([[NSImage alloc] initWithSize:[bitmap size]]); + [image addRepresentation:bitmap]; + + // Make an autoreleased |NSImage|, which will be returned, and draw into it. + // By default, the |NSImage| will be completely transparent. + NSImage* dragImage = + [[[NSImage alloc] initWithSize:[bitmap size]] autorelease]; + [dragImage lockFocus]; + + // Draw the image with the appropriate opacity, clipping it tightly. + GradientButtonCell* cell = static_cast<GradientButtonCell*>([self cell]); + DCHECK([cell isKindOfClass:[GradientButtonCell class]]); + [[cell clipPathForFrame:bounds inView:self] setClip]; + [image drawAtPoint:NSMakePoint(0, 0) + fromRect:NSMakeRect(0, 0, NSWidth(bounds), NSHeight(bounds)) + operation:NSCompositeSourceOver + fraction:kDragImageOpacity]; + + [dragImage unlockFocus]; + return dragImage; +} + +@end // @implementation BookmarkButton(Private) diff --git a/chrome/browser/cocoa/gradient_button_cell.h b/chrome/browser/cocoa/gradient_button_cell.h index 23dc5d1..e9d09bd 100644 --- a/chrome/browser/cocoa/gradient_button_cell.h +++ b/chrome/browser/cocoa/gradient_button_cell.h @@ -62,6 +62,12 @@ typedef NSInteger ButtonType; // the current hoverAlpha_ based on these events. - (void)setMouseInside:(BOOL)flag animate:(BOOL)animate; +// Gets the path which tightly bounds the outside of the button. This is needed +// to produce images of clear buttons which only include the area inside, since +// the background of the button is drawn by someone else. +- (NSBezierPath*)clipPathForFrame:(NSRect)cellFrame + inView:(NSView*)controlView; + @property(assign, nonatomic)CGFloat hoverAlpha; @end diff --git a/chrome/browser/cocoa/gradient_button_cell.mm b/chrome/browser/cocoa/gradient_button_cell.mm index d0aaed9..838397c8 100644 --- a/chrome/browser/cocoa/gradient_button_cell.mm +++ b/chrome/browser/cocoa/gradient_button_cell.mm @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #import "base/scoped_nsobject.h" #include "chrome/browser/cocoa/gradient_button_cell.h" #import "third_party/GTM/AppKit/GTMTheme.h" @@ -11,6 +12,20 @@ - (void)sharedInit; - (void)drawUnderlayImageWithFrame:(NSRect)cellFrame inView:(NSView*)controlView; + +// Get drawing parameters for a given cell frame in a given view. The inner +// frame is the one required by |-drawInteriorWithFrame:inView:|. The inner and +// outer paths are the ones required by |-drawBorderAndFillForTheme:...|. The +// outer path also gives the area in which to clip. Any of the |return...| +// arguments may be NULL (in which case the given parameter won't be returned). +// If |returnInnerPath| or |returnOuterPath|, |*returnInnerPath| or +// |*returnOuterPath| should be nil, respectively. +- (void)getDrawParamsForFrame:(NSRect)cellFrame + inView:(NSView*)controlView + innerFrame:(NSRect*)returnInnerFrame + innerPath:(NSBezierPath**)returnInnerPath + outerPath:(NSBezierPath**)returnOuterPath + clipPath:(NSBezierPath**)returnClipPath; @end static const NSTimeInterval kAnimationShowDuration = 0.2; @@ -258,11 +273,20 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; [innerPath stroke]; } -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { +// TODO(viettrungluu): clean this up. +// (Private) +- (void)getDrawParamsForFrame:(NSRect)cellFrame + inView:(NSView*)controlView + innerFrame:(NSRect*)returnInnerFrame + innerPath:(NSBezierPath**)returnInnerPath + outerPath:(NSBezierPath**)returnOuterPath + clipPath:(NSBezierPath**)returnClipPath { // Constants from Cole. Will kConstant them once the feedback loop // is complete. NSRect drawFrame = NSInsetRect(cellFrame, 1.5, 1.5); NSRect innerFrame = NSInsetRect(cellFrame, 2, 1); + const CGFloat radius = 3.5; + ButtonType type = [[(NSControl*)controlView cell] tag]; switch (type) { case kMiddleButtonType: @@ -280,23 +304,52 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; default: break; } + if (type == kLeftButtonWithShadowType) + innerFrame.size.width -= 1.0; + + // Return results if |return...| not null. + if (returnInnerFrame) + *returnInnerFrame = innerFrame; + if (returnInnerPath) { + DCHECK(*returnInnerPath == nil); + *returnInnerPath = [NSBezierPath bezierPathWithRoundedRect:drawFrame + xRadius:radius + yRadius:radius]; + } + if (returnOuterPath) { + DCHECK(*returnOuterPath == nil); + NSRect outerPathRect = NSInsetRect(drawFrame, -1, -1); + *returnOuterPath = [NSBezierPath bezierPathWithRoundedRect:outerPathRect + xRadius:radius + 1 + yRadius:radius + 1]; + } + if (returnClipPath) { + DCHECK(*returnClipPath == nil); + NSRect clipPathRect = NSInsetRect(drawFrame, -0.5, -0.5); + *returnClipPath = [NSBezierPath bezierPathWithRoundedRect:clipPathRect + xRadius:radius + 0.5 + yRadius:radius + 0.5]; + } +} + +// TODO(viettrungluu): clean this up. +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + NSRect innerFrame; + NSBezierPath* innerPath = nil; + NSBezierPath* outerPath = nil; + [self getDrawParamsForFrame:cellFrame + inView:controlView + innerFrame:&innerFrame + innerPath:&innerPath + outerPath:&outerPath + clipPath:NULL]; - const float radius = 3.5; BOOL pressed = [self isHighlighted]; NSWindow* window = [controlView window]; BOOL active = [window isKeyWindow] || [window isMainWindow]; GTMTheme* theme = [controlView gtm_theme]; - NSBezierPath* innerPath = - [NSBezierPath bezierPathWithRoundedRect:drawFrame - xRadius:radius - yRadius:radius]; - NSBezierPath* outerPath = - [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(drawFrame, -1, -1) - xRadius:radius + 1 - yRadius:radius + 1]; - // Stroke the borders and appropriate fill gradient. If we're borderless, // the only time we want to draw the inner gradient is if we're highlighted. if (([self isBordered] && ![self showsBorderOnlyWhileMouseInside]) || @@ -316,6 +369,7 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; } // If this is the left side of a segmented button, draw a slight shadow. + ButtonType type = [[(NSControl*)controlView cell] tag]; if (type == kLeftButtonWithShadowType) { NSRect borderRect, contentRect; NSDivideRect(cellFrame, &borderRect, &contentRect, 1.0, NSMaxXEdge); @@ -324,7 +378,6 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; [[stroke colorWithAlphaComponent:0.2] set]; NSRectFillUsingOperation(NSInsetRect(borderRect, 0, 2), NSCompositeSourceOver); - innerFrame.size.width -= 1.0; } [self drawInteriorWithFrame:innerFrame inView:controlView]; } @@ -396,4 +449,16 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; } } +- (NSBezierPath*)clipPathForFrame:(NSRect)cellFrame + inView:(NSView*)controlView { + NSBezierPath* boundingPath = nil; + [self getDrawParamsForFrame:cellFrame + inView:controlView + innerFrame:NULL + innerPath:NULL + outerPath:NULL + clipPath:&boundingPath]; + return boundingPath; +} + @end |