summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-24 23:22:23 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-24 23:22:23 +0000
commitd50e877baf62f4b553fee834e88941d864527797 (patch)
treebf4f6173a891bc1d9df1e7ed771f5f3f64036ce2 /chrome/browser/cocoa
parent3cfcae2bed49e80e31fbedf4e2ed45c594e7b941 (diff)
downloadchromium_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.mm69
-rw-r--r--chrome/browser/cocoa/gradient_button_cell.h6
-rw-r--r--chrome/browser/cocoa/gradient_button_cell.mm89
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