Commit 32e5d362 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

mac: Delete more unused Cocoa controls and utilities.

Bug: 832676
Change-Id: I1e386194f2925fd6b8d5ce594bb2372c2a6422ff
Reviewed-on: https://chromium-review.googlesource.com/1246727
Commit-Queue: Nico Weber <thakis@chromium.org>
Reviewed-by: default avatarNico Weber <thakis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594511}
parent 952e8d59
......@@ -46,12 +46,6 @@ jumbo_split_static_library("ui") {
# TODO(ellyjones): Remove this variable once 804950 and 802257 are fixed.
if (is_mac) {
cocoa_browser_sources = [
"cocoa/animatable_image.h",
"cocoa/animatable_image.mm",
"cocoa/animatable_view.h",
"cocoa/animatable_view.mm",
"cocoa/background_gradient_view.h",
"cocoa/background_gradient_view.mm",
"cocoa/browser_dialogs_views_mac.cc",
"cocoa/browser_dialogs_views_mac.h",
"cocoa/browser_window_cocoa.h",
......@@ -74,8 +68,6 @@ jumbo_split_static_library("ui") {
"cocoa/chrome_browser_window.mm",
"cocoa/chrome_event_processing_window.h",
"cocoa/chrome_event_processing_window.mm",
"cocoa/cocoa_util.h",
"cocoa/cocoa_util.mm",
"cocoa/constrained_window/constrained_window_control_utils.h",
"cocoa/constrained_window/constrained_window_control_utils.mm",
"cocoa/constrained_window/constrained_window_custom_sheet.h",
......@@ -121,8 +113,6 @@ jumbo_split_static_library("ui") {
"cocoa/main_menu_item.h",
"cocoa/nsview_additions.h",
"cocoa/nsview_additions.mm",
"cocoa/rect_path_utils.h",
"cocoa/rect_path_utils.mm",
"cocoa/restart_browser.h",
"cocoa/restart_browser.mm",
"cocoa/simple_message_box_cocoa.h",
......@@ -131,11 +121,6 @@ jumbo_split_static_library("ui") {
"cocoa/single_web_contents_dialog_manager_cocoa.mm",
"cocoa/ssl_client_certificate_selector_cocoa.h",
"cocoa/ssl_client_certificate_selector_cocoa.mm",
"cocoa/spinner_util.h",
"cocoa/styled_text_field.h",
"cocoa/styled_text_field.mm",
"cocoa/styled_text_field_cell.h",
"cocoa/styled_text_field_cell.mm",
"cocoa/tab_contents/favicon_util_mac.h",
"cocoa/tab_contents/favicon_util_mac.mm",
"cocoa/tab_contents/overlayable_contents_controller.h",
......
// 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.
#ifndef CHROME_BROWSER_UI_COCOA_ANIMATABLE_IMAGE_H_
#define CHROME_BROWSER_UI_COCOA_ANIMATABLE_IMAGE_H_
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#include "base/mac/scoped_nsobject.h"
// This class helps animate an NSImage's frame and opacity. It works by creating
// a blank NSWindow in the size specified and giving it a layer on which the
// image can be animated. Clients are free to embed this object as a child
// window for easier window management. This class will clean itself up when
// the animation has finished. Clients that install this as a child window
// should listen for the NSWindowWillCloseNotification to perform any additional
// cleanup.
@interface AnimatableImage : NSWindow {
@private
// The image to animate.
base::scoped_nsobject<NSImage> image_;
}
// The frame of the image before and after the animation. This is in this
// window's coordinate system.
@property(nonatomic) CGRect startFrame;
@property(nonatomic) CGRect endFrame;
// Opacity values for the animation.
@property(nonatomic) CGFloat startOpacity;
@property(nonatomic) CGFloat endOpacity;
// The amount of time it takes to animate the image.
@property(nonatomic) CGFloat duration;
// The timing function to use for the animation.
@property(nonatomic, assign) CAMediaTimingFunction* timingFunction;
// Designated initializer. Do not use any other NSWindow initializers. Creates
// but does not show the blank animation window of the given size. The
// |animationFrame| should usually be big enough to contain the |startFrame|
// and |endFrame| properties of the animation.
- (id)initWithImage:(NSImage*)image
animationFrame:(NSRect)animationFrame;
// Begins the animation.
- (void)startAnimation;
@end
#endif // CHROME_BROWSER_UI_COCOA_ANIMATABLE_IMAGE_H_
// 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 "chrome/browser/ui/cocoa/animatable_image.h"
#include "base/logging.h"
#import "base/mac/sdk_forward_declarations.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h"
@interface AnimatableImage (Private) <CAAnimationDelegate>
@end
@implementation AnimatableImage
@synthesize startFrame = startFrame_;
@synthesize endFrame = endFrame_;
@synthesize startOpacity = startOpacity_;
@synthesize endOpacity = endOpacity_;
@synthesize duration = duration_;
@synthesize timingFunction = timingFunction_;
- (id)initWithImage:(NSImage*)image
animationFrame:(NSRect)animationFrame {
if ((self = [super initWithContentRect:animationFrame
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO])) {
DCHECK(image);
image_.reset([image retain]);
duration_ = 1.0;
timingFunction_ =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
startOpacity_ = 1.0;
endOpacity_ = 1.0;
[self setOpaque:NO];
[self setBackgroundColor:[NSColor clearColor]];
[self setIgnoresMouseEvents:YES];
// Must be set or else self will be leaked.
[self setReleasedWhenClosed:YES];
}
return self;
}
- (void)startAnimation {
// Set up the root layer. By calling -setLayer: followed by -setWantsLayer:
// the view becomes a layer hosting view as opposed to a layer backed view.
NSView* view = [self contentView];
CALayer* rootLayer = [CALayer layer];
[view setLayer:rootLayer];
[view setWantsLayer:YES];
// Create the layer that will be animated.
CALayer* layer = [CALayer layer];
[layer setContents:image_.get()];
[layer setAnchorPoint:CGPointMake(0, 1)];
[layer setFrame:[self startFrame]];
[layer setNeedsDisplayOnBoundsChange:YES];
[rootLayer addSublayer:layer];
// Animate the bounds only if the image is resized.
CABasicAnimation* boundsAnimation = nil;
if (CGRectGetWidth([self startFrame]) != CGRectGetWidth([self endFrame]) ||
CGRectGetHeight([self startFrame]) != CGRectGetHeight([self endFrame])) {
boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"];
NSRect startRect = NSMakeRect(0, 0,
CGRectGetWidth([self startFrame]),
CGRectGetHeight([self startFrame]));
[boundsAnimation setFromValue:[NSValue valueWithRect:startRect]];
NSRect endRect = NSMakeRect(0, 0,
CGRectGetWidth([self endFrame]),
CGRectGetHeight([self endFrame]));
[boundsAnimation setToValue:[NSValue valueWithRect:endRect]];
[boundsAnimation gtm_setDuration:[self duration]
eventMask:NSLeftMouseUpMask];
[boundsAnimation setTimingFunction:timingFunction_];
}
// Positional animation.
CABasicAnimation* positionAnimation =
[CABasicAnimation animationWithKeyPath:@"position"];
[positionAnimation setFromValue:
[NSValue valueWithPoint:NSPointFromCGPoint([self startFrame].origin)]];
[positionAnimation setToValue:
[NSValue valueWithPoint:NSPointFromCGPoint([self endFrame].origin)]];
[positionAnimation gtm_setDuration:[self duration]
eventMask:NSLeftMouseUpMask];
[positionAnimation setTimingFunction:timingFunction_];
// Opacity animation.
CABasicAnimation* opacityAnimation =
[CABasicAnimation animationWithKeyPath:@"opacity"];
[opacityAnimation setFromValue:
[NSNumber numberWithFloat:[self startOpacity]]];
[opacityAnimation setToValue:[NSNumber numberWithFloat:[self endOpacity]]];
[opacityAnimation gtm_setDuration:[self duration]
eventMask:NSLeftMouseUpMask];
[opacityAnimation setTimingFunction:timingFunction_];
// Set the delegate just for one of the animations so that this window can
// be closed upon completion.
[opacityAnimation setDelegate:self];
// The CAAnimations only affect the presentational value of a layer, not the
// model value. This means that after the animation is done, it can flicker
// back to the original values. To avoid this, create an implicit animation of
// the values, which are then overridden with the CABasicAnimations.
//
// Ideally, a call to |-setBounds:| should be here, but, for reasons that
// are not understood, doing so causes the animation to break.
[layer setPosition:[self endFrame].origin];
[layer setOpacity:[self endOpacity]];
// Start the animations.
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:[self duration]]
forKey:kCATransactionAnimationDuration];
if (boundsAnimation) {
[layer addAnimation:boundsAnimation forKey:@"bounds"];
}
[layer addAnimation:positionAnimation forKey:@"position"];
[layer addAnimation:opacityAnimation forKey:@"opacity"];
[CATransaction commit];
}
- (void)animationDidStart:(CAAnimation*)animation {
}
// CAAnimation delegate method called when the animation is complete.
- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)flag {
// Close the window, releasing self.
[self close];
}
@end
// 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>
#import "chrome/browser/ui/cocoa/animatable_image.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace {
class AnimatableImageTest : public CocoaTest {
public:
AnimatableImageTest() {
NSRect frame = NSMakeRect(0, 0, 500, 500);
NSImage* image = [NSImage imageNamed:NSImageNameComputer];
animation_ = [[AnimatableImage alloc] initWithImage:image
animationFrame:frame];
}
AnimatableImage* animation_;
};
TEST_F(AnimatableImageTest, BasicAnimation) {
[animation_ setStartFrame:CGRectMake(0, 0, 10, 10)];
[animation_ setEndFrame:CGRectMake(500, 500, 100, 100)];
[animation_ setStartOpacity:0.1];
[animation_ setEndOpacity:1.0];
[animation_ setDuration:0.5];
[animation_ startAnimation];
}
TEST_F(AnimatableImageTest, CancelAnimation) {
[animation_ setStartFrame:CGRectMake(0, 0, 10, 10)];
[animation_ setEndFrame:CGRectMake(500, 500, 100, 100)];
[animation_ setStartOpacity:0.1];
[animation_ setEndOpacity:1.0];
[animation_ setDuration:5.0]; // Long enough to be able to test cancelling.
[animation_ startAnimation];
[animation_ close];
}
} // namespace
// Copyright (c) 2012 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_UI_COCOA_ANIMATABLE_VIEW_H_
#define CHROME_BROWSER_UI_COCOA_ANIMATABLE_VIEW_H_
#import <Cocoa/Cocoa.h>
#import "base/mac/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/background_gradient_view.h"
#import "chrome/browser/ui/cocoa/view_resizer.h"
// A view that provides an animatable height property. Provides methods to
// animate to a new height, set a new height immediately, or cancel any running
// animations.
//
// AnimatableView sends an |animationDidEnd:| message to its delegate when the
// animation ends normally and an |animationDidStop:| message when the animation
// was canceled (even when canceled as a result of a new animation starting).
@interface AnimatableView : BackgroundGradientView<NSAnimationDelegate> {
@protected
IBOutlet id delegate_; // weak, used to send animation ended messages.
@private
base::scoped_nsobject<NSAnimation> currentAnimation_;
id<ViewResizer> resizeDelegate_; // weak, usually owns us
}
// Properties for bindings.
@property(assign, nonatomic) id delegate;
@property(assign, nonatomic) id<ViewResizer> resizeDelegate;
// Gets the current height of the view. If an animation is currently running,
// this will give the current height at the time of the call, not the target
// height at the end of the animation.
- (CGFloat)height;
// Sets the height of the view immediately. Cancels any running animations.
- (void)setHeight:(CGFloat)newHeight;
// Starts a new animation to the given |newHeight| for the given |duration|.
// Cancels any running animations.
- (void)animateToNewHeight:(CGFloat)newHeight
duration:(NSTimeInterval)duration;
// Cancels any running animations, leaving the view at its current
// (mid-animation) height.
- (void)stopAnimation;
// Gets the progress of any current animation.
- (NSAnimationProgress)currentAnimationProgress;
@end
#endif // CHROME_BROWSER_UI_COCOA_ANIMATABLE_VIEW_H_
// Copyright (c) 2009 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>
#import <QuartzCore/QuartzCore.h>
#import "chrome/browser/ui/cocoa/animatable_view.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h"
// NSAnimation subclass that animates the height of an AnimatableView. Allows
// the caller to start and cancel the animation as desired.
@interface HeightAnimation : NSAnimation {
@private
AnimatableView* view_; // weak, owns us.
CGFloat startHeight_;
CGFloat endHeight_;
}
// Initialize a new height animation for the given view. The animation will not
// start until startAnimation: is called.
- (id)initWithView:(AnimatableView*)view
finalHeight:(CGFloat)height
duration:(NSTimeInterval)duration;
@end
@implementation HeightAnimation
- (id)initWithView:(AnimatableView*)view
finalHeight:(CGFloat)height
duration:(NSTimeInterval)duration {
if ((self = [super gtm_initWithDuration:duration
eventMask:NSLeftMouseUpMask
animationCurve:NSAnimationEaseIn])) {
view_ = view;
startHeight_ = [view_ height];
endHeight_ = height;
[self setAnimationBlockingMode:NSAnimationNonblocking];
[self setDelegate:view_];
}
return self;
}
// Overridden to call setHeight for each progress tick.
- (void)setCurrentProgress:(NSAnimationProgress)progress {
[super setCurrentProgress:progress];
[view_ setHeight:((progress * (endHeight_ - startHeight_)) + startHeight_)];
}
@end
@implementation AnimatableView
@synthesize delegate = delegate_;
@synthesize resizeDelegate = resizeDelegate_;
- (void)dealloc {
// Stop the animation if it is running, since it holds a pointer to this view.
[self stopAnimation];
[super dealloc];
}
- (CGFloat)height {
return [self frame].size.height;
}
- (void)setHeight:(CGFloat)newHeight {
// Force the height to be an integer because some animations look terrible
// with non-integer intermediate heights. We only ever set integer heights
// for our views, so this shouldn't be a limitation in practice.
int height = floor(newHeight);
[resizeDelegate_ resizeView:self newHeight:height];
}
- (void)animateToNewHeight:(CGFloat)newHeight
duration:(NSTimeInterval)duration {
[currentAnimation_ stopAnimation];
currentAnimation_.reset([[HeightAnimation alloc] initWithView:self
finalHeight:newHeight
duration:duration]);
if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
[resizeDelegate_ setAnimationInProgress:YES];
[currentAnimation_ startAnimation];
}
- (void)stopAnimation {
[currentAnimation_ stopAnimation];
}
- (NSAnimationProgress)currentAnimationProgress {
return [currentAnimation_ currentProgress];
}
- (void)animationDidStop:(NSAnimation*)animation {
if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
[resizeDelegate_ setAnimationInProgress:NO];
if ([delegate_ respondsToSelector:@selector(animationDidStop:)])
[delegate_ animationDidStop:animation];
currentAnimation_.reset(nil);
}
- (void)animationDidEnd:(NSAnimation*)animation {
if ([resizeDelegate_ respondsToSelector:@selector(setAnimationInProgress:)])
[resizeDelegate_ setAnimationInProgress:NO];
if ([delegate_ respondsToSelector:@selector(animationDidEnd:)])
[delegate_ animationDidEnd:animation];
currentAnimation_.reset(nil);
}
@end
// 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/mac/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/animatable_view.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#import "chrome/browser/ui/cocoa/view_resizer_pong.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace {
class AnimatableViewTest : public CocoaTest {
public:
AnimatableViewTest() {
NSRect frame = NSMakeRect(0, 0, 100, 100);
view_.reset([[AnimatableView alloc] initWithFrame:frame]);
[[test_window() contentView] addSubview:view_.get()];
resizeDelegate_.reset([[ViewResizerPong alloc] init]);
[view_ setResizeDelegate:resizeDelegate_.get()];
}
base::scoped_nsobject<ViewResizerPong> resizeDelegate_;
base::scoped_nsobject<AnimatableView> view_;
};
// Basic view tests (AddRemove, Display).
TEST_VIEW(AnimatableViewTest, view_);
TEST_F(AnimatableViewTest, GetAndSetHeight) {
// Make sure the view's height starts out at 100.
NSRect initialFrame = [view_ frame];
ASSERT_EQ(100, initialFrame.size.height);
EXPECT_EQ(initialFrame.size.height, [view_ height]);
// Set it directly to 50 and make sure it takes effect.
[resizeDelegate_ setHeight:-1];
[view_ setHeight:50];
EXPECT_EQ(50, [resizeDelegate_ height]);
}
// TODO(rohitrao): Find a way to unittest the animations and delegate messages.
} // 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.
#ifndef CHROME_BROWSER_UI_COCOA_BACKGROUND_GRADIENT_VIEW_H_
#define CHROME_BROWSER_UI_COCOA_BACKGROUND_GRADIENT_VIEW_H_
#import <Cocoa/Cocoa.h>
#import "chrome/browser/ui/cocoa/themed_window.h"
// A custom view that draws a 'standard' background gradient.
// Base class for other Chromium views.
@interface BackgroundGradientView : NSView<ThemedWindowDrawing>
// Controls whether the bar draws a dividing line.
@property(nonatomic, assign) BOOL showsDivider;
// Controls where the bar draws a dividing line.
@property(nonatomic, assign) NSRectEdge dividerEdge;
// The color used for the bottom stroke. Public so subclasses can use.
- (NSColor*)strokeColor;
// The pattern phase that will be used by -drawBackground:.
// Defaults to align the top of the theme image with the top of the tabs.
// Views that draw at the bottom of the window (download bar) can override to
// change the pattern phase.
- (NSPoint)patternPhase;
// Draws the background image into the current NSGraphicsContext.
- (void)drawBackground:(NSRect)dirtyRect;
@end
#endif // CHROME_BROWSER_UI_COCOA_BACKGROUND_GRADIENT_VIEW_H_
// Copyright (c) 2012 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.
#include "chrome/browser/ui/cocoa/background_gradient_view.h"
#import "chrome/browser/themes/theme_properties.h"
#import "chrome/browser/themes/theme_service.h"
#import "chrome/browser/ui/cocoa/themed_window.h"
#include "chrome/grit/theme_resources.h"
#import "ui/base/cocoa/nsgraphics_context_additions.h"
#import "ui/base/cocoa/nsview_additions.h"
#include "ui/base/material_design/material_design_controller.h"
@implementation BackgroundGradientView
@synthesize showsDivider = showsDivider_;
@synthesize dividerEdge = dividerEdge_;
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder*)decoder {
if ((self = [super initWithCoder:decoder])) {
[self commonInit];
}
return self;
}
- (void)commonInit {
showsDivider_ = YES;
dividerEdge_ = NSMinYEdge;
}
- (void)setShowsDivider:(BOOL)show {
if (showsDivider_ == show)
return;
showsDivider_ = show;
[self setNeedsDisplay:YES];
}
- (void)setDividerEdge:(NSRectEdge)dividerEdge {
if (dividerEdge_ == dividerEdge)
return;
dividerEdge_ = dividerEdge;
[self setNeedsDisplay:YES];
}
- (NSPoint)patternPhase {
return [[self window]
themeImagePositionForAlignment:THEME_IMAGE_ALIGN_WITH_TAB_STRIP];
}
- (void)drawBackground:(NSRect)dirtyRect {
[[NSGraphicsContext currentContext]
cr_setPatternPhase:[self patternPhase]
forView:[self cr_viewBeingDrawnTo]];
const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
if (themeProvider && !themeProvider->UsingSystemTheme()) {
// If the background image is semi transparent then we need something
// to blend against. Using 20% black gives us a color similar to Windows.
[[NSColor colorWithCalibratedWhite:0.2 alpha:1.0] set];
NSRectFill(dirtyRect);
}
[[self backgroundImageColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);
if (showsDivider_) {
// Draw stroke
NSRect borderRect, contentRect;
NSDivideRect([self bounds], &borderRect, &contentRect, [self cr_lineWidth],
dividerEdge_);
if (NSIntersectsRect(borderRect, dirtyRect)) {
[[self strokeColor] set];
NSRectFillUsingOperation(NSIntersectionRect(borderRect, dirtyRect),
NSCompositeSourceOver);
}
}
}
- (NSColor*)strokeColor {
NSWindow* window = [self window];
// Some views have a child NSWindow between them and the window that is
// active (e.g, OmniboxPopupTopSeparatorView). For these, check the status
// of parentWindow instead. Note that this is not tracked correctly (but
// the views that do this appear to be removed when the window loses focus
// anyway).
if ([window parentWindow])
window = [window parentWindow];
const ui::ThemeProvider* themeProvider = [window themeProvider];
if (!themeProvider)
return [NSColor blackColor];
if (themeProvider->ShouldIncreaseContrast()) {
if ([window hasDarkTheme])
return [NSColor whiteColor];
else
return [NSColor blackColor];
}
return themeProvider->GetNSColor(
ThemeProperties::COLOR_TOOLBAR_CONTENT_AREA_SEPARATOR);
}
- (NSColor*)backgroundImageColor {
const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
if (!themeProvider)
return [[self window] backgroundColor];
// Themes don't have an inactive image so only look for one if there's no
// theme.
BOOL isActive = [[self window] isMainWindow];
if (!isActive && themeProvider->UsingSystemTheme()) {
NSColor* color = themeProvider->GetNSImageColorNamed(
IDR_THEME_TOOLBAR_INACTIVE);
if (color)
return color;
}
return themeProvider->GetNSImageColorNamed(IDR_THEME_TOOLBAR);
}
- (void)viewDidMoveToWindow {
[super viewDidMoveToWindow];
if ([self window]) {
// The new window for the view may have a different focus state than the
// last window this view was part of.
// This happens when the view is moved into a TabWindowOverlayWindow for
// tab dragging.
[self windowDidChangeActive];
}
}
- (void)viewWillStartLiveResize {
[super viewWillStartLiveResize];
const ui::ThemeProvider* themeProvider = [[self window] themeProvider];
if (themeProvider && themeProvider->UsingSystemTheme()) {
// The default theme's background image is a subtle texture pattern that
// we can scale without being easily noticed. Optimize this case by
// skipping redraws during live resize.
[self setLayerContentsRedrawPolicy:
NSViewLayerContentsRedrawOnSetNeedsDisplay];
}
}
- (void)viewDidEndLiveResize {
[super viewDidEndLiveResize];
if ([self layerContentsRedrawPolicy] !=
NSViewLayerContentsRedrawDuringViewResize) {
// If we have been scaling the layer during live resize, now is the time to
// redraw the layer.
[self setLayerContentsRedrawPolicy:
NSViewLayerContentsRedrawDuringViewResize];
[self setNeedsDisplay:YES];
}
}
- (void)setFrameOrigin:(NSPoint)origin {
// The background color depends on the view's vertical position. This impacts
// any child views that draw using this view's functions.
// When resizing the window, the view's vertical position (NSMinY) may change
// even though our relative position to the nearest window edge is still the
// same. Don't redraw unnecessarily in this case.
if (![self inLiveResize] && NSMinY([self frame]) != origin.y)
[self cr_recursivelySetNeedsDisplay:YES];
[super setFrameOrigin:origin];
}
// ThemedWindowDrawing implementation.
- (void)windowDidChangeTheme {
[self setNeedsDisplay:YES];
}
- (void)windowDidChangeActive {
[self setNeedsDisplay:YES];
}
@end
// 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/mac/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/background_gradient_view.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
// Since BackgroundGradientView doesn't do any drawing by default, we
// create a subclass to call its draw method for us.
@interface BackgroundGradientSubClassTest : BackgroundGradientView
@end
@implementation BackgroundGradientSubClassTest
- (void)drawRect:(NSRect)dirtyRect {
[self drawBackground:dirtyRect];
}
@end
namespace {
class BackgroundGradientViewTest : public CocoaTest {
public:
BackgroundGradientViewTest() {
NSRect frame = NSMakeRect(0, 0, 100, 30);
base::scoped_nsobject<BackgroundGradientSubClassTest> view(
[[BackgroundGradientSubClassTest alloc] initWithFrame:frame]);
view_ = view.get();
[[test_window() contentView] addSubview:view_];
}
BackgroundGradientSubClassTest* view_;
};
TEST_VIEW(BackgroundGradientViewTest, view_)
// Test drawing, mostly to ensure nothing leaks or crashes.
TEST_F(BackgroundGradientViewTest, DisplayWithDivider) {
[view_ setShowsDivider:YES];
[view_ display];
}
} // namespace
......@@ -39,7 +39,6 @@
#include "chrome/browser/ui/browser_instant_controller.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window_state.h"
#import "chrome/browser/ui/cocoa/background_gradient_view.h"
#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h"
#import "chrome/browser/ui/cocoa/browser_window_cocoa.h"
#import "chrome/browser/ui/cocoa/browser_window_command_handler.h"
......
// Copyright 2018 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_UI_COCOA_COCOA_UTIL_H_
#define CHROME_BROWSER_UI_COCOA_COCOA_UTIL_H_
#import <Cocoa/Cocoa.h>
#include <limits>
#include "base/mac/foundation_util.h"
namespace cocoa_util {
// The minimum representable time interval. This can be used as the value
// passed to +[NSAnimationContext setDuration:] to stop an in-progress
// animation as quickly as possible.
const NSTimeInterval kMinimumTimeInterval =
std::numeric_limits<NSTimeInterval>::min();
// Remove underlining from the specified range of characters in a text view.
void RemoveUnderlining(NSTextView* textView, int offset, int length);
CGFloat LineWidthFromContext(CGContextRef context);
} // namespace cocoa_util
#endif // CHROME_BROWSER_UI_COCOA_COCOA_UTIL_H_
// Copyright 2018 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.
#include "chrome/browser/ui/cocoa/cocoa_util.h"
namespace cocoa_util {
void RemoveUnderlining(NSTextView* textView, int offset, int length) {
// Clear the default link attributes that were set by the
// HyperlinkTextView, otherwise removing the underline doesn't matter.
[textView setLinkTextAttributes:nil];
NSTextStorage* text = [textView textStorage];
NSRange range = NSMakeRange(offset, length);
[text addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleNone]
range:range];
}
CGFloat LineWidthFromContext(CGContextRef context) {
CGRect unitRect = CGRectMake(0.0, 0.0, 1.0, 1.0);
CGRect deviceRect = CGContextConvertRectToDeviceSpace(context, unitRect);
return 1.0 / deviceRect.size.height;
}
} // namespace cocoa_util
// Copyright (c) 2013 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_UI_COCOA_RECT_PATH_UTILS_H_
#define CHROME_BROWSER_UI_COCOA_RECT_PATH_UTILS_H_
#import <Cocoa/Cocoa.h>
namespace rect_path_utils {
enum RoundedCornerFlags {
RoundedCornerAll = 0,
RoundedCornerLeft = 1
};
NSBezierPath *RectPathWithInset(RoundedCornerFlags roundedCornerFlags,
const NSRect frame,
const CGFloat insetX,
const CGFloat insetY,
const CGFloat outerRadius);
void FillRectWithInset(RoundedCornerFlags roundedCornerFlags,
const NSRect frame,
const CGFloat insetX,
const CGFloat insetY,
const CGFloat outerRadius,
NSColor *color);
void FrameRectWithInset(RoundedCornerFlags roundedCornerFlags,
const NSRect frame,
const CGFloat insetX,
const CGFloat insetY,
const CGFloat outerRadius,
const CGFloat lineWidth,
NSColor *color);
} // namespace rect_path_utils
#endif // CHROME_BROWSER_UI_COCOA_RECT_PATH_UTILS_H_
// Copyright (c) 2013 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 "chrome/browser/ui/cocoa/rect_path_utils.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSBezierPath+RoundRect.h"
namespace rect_path_utils {
NSBezierPath* RectPathWithInset(RoundedCornerFlags roundedCornerFlags,
const NSRect frame,
const CGFloat insetX,
const CGFloat insetY,
const CGFloat outerRadius) {
NSRect insetFrame = NSInsetRect(frame, insetX, insetY);
if (outerRadius > 0.0) {
CGFloat leftRadius = outerRadius - insetX;
CGFloat rightRadius =
(roundedCornerFlags == RoundedCornerLeft) ? 0 : leftRadius;
return [NSBezierPath gtm_bezierPathWithRoundRect:insetFrame
topLeftCornerRadius:leftRadius
topRightCornerRadius:rightRadius
bottomLeftCornerRadius:leftRadius
bottomRightCornerRadius:rightRadius];
} else {
return [NSBezierPath bezierPathWithRect:insetFrame];
}
}
// Similar to |NSRectFill()|, additionally sets |color| as the fill
// color. |outerRadius| greater than 0.0 uses rounded corners, with
// inset backed out of the radius.
void FillRectWithInset(RoundedCornerFlags roundedCornerFlags,
const NSRect frame,
const CGFloat insetX,
const CGFloat insetY,
const CGFloat outerRadius,
NSColor* color) {
NSBezierPath* path =
RectPathWithInset(roundedCornerFlags, frame, insetX, insetY, outerRadius);
[color setFill];
[path fill];
}
// Similar to |NSFrameRectWithWidth()|, additionally sets |color| as
// the stroke color (as opposed to the fill color). |outerRadius|
// greater than 0.0 uses rounded corners, with inset backed out of the
// radius.
void FrameRectWithInset(RoundedCornerFlags roundedCornerFlags,
const NSRect frame,
const CGFloat insetX,
const CGFloat insetY,
const CGFloat outerRadius,
const CGFloat lineWidth,
NSColor* color) {
const CGFloat finalInsetX = insetX + (lineWidth / 2.0);
const CGFloat finalInsetY = insetY + (lineWidth / 2.0);
NSBezierPath* path =
RectPathWithInset(roundedCornerFlags, frame, finalInsetX, finalInsetY,
outerRadius);
[color setStroke];
[path setLineWidth:lineWidth];
[path stroke];
}
} // namespace rect_path_utils
// Copyright 2018 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_UI_COCOA_SPINNER_UTIL_H_
#define CHROME_BROWSER_UI_COCOA_SPINNER_UTIL_H_
#include "ui/gfx/geometry/angle_conversions.h"
namespace cocoa_spinner_util {
constexpr CGFloat kDegrees90 = gfx::DegToRad(90.0f);
constexpr CGFloat kDegrees135 = gfx::DegToRad(135.0f);
constexpr CGFloat kDegrees180 = gfx::DegToRad(180.0f);
constexpr CGFloat kDegrees270 = gfx::DegToRad(270.0f);
constexpr CGFloat kDegrees360 = gfx::DegToRad(360.0f);
constexpr CGFloat kSpinnerViewUnitWidth = 28.0;
constexpr CGFloat kSpinnerUnitInset = 2.0;
constexpr CGFloat kArcDiameter =
(kSpinnerViewUnitWidth - kSpinnerUnitInset * 2.0);
constexpr CGFloat kArcRadius = kArcDiameter / 2.0;
constexpr CGFloat kArcLength =
kDegrees135 * kArcDiameter; // 135 degrees of circumference.
constexpr CGFloat kArcStrokeWidth = 3.0;
constexpr CGFloat kArcAnimationTime = 1.333;
constexpr CGFloat kRotationTime = 1.56863;
NSString* const kSpinnerAnimationName = @"SpinnerAnimationName";
NSString* const kRotationAnimationName = @"RotationAnimationName";
constexpr CGFloat kWaitingStrokeAlpha = 0.5;
} // namespace cocoa_spinner_util
#endif // CHROME_BROWSER_UI_COCOA_SPINNER_UTIL_H_
// Copyright (c) 2009 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_UI_COCOA_STYLED_TEXT_FIELD_H_
#define CHROME_BROWSER_UI_COCOA_STYLED_TEXT_FIELD_H_
#import <Cocoa/Cocoa.h>
@class StyledTextFieldCell;
// An implementation of NSTextField that is designed to work with
// StyledTextFieldCell. Provides methods to redraw the field when cell
// decorations have changed and overrides |mouseDown:| to properly handle clicks
// in sections of the cell with decorations.
@interface StyledTextField : NSTextField {
}
// Repositions and redraws the field editor. Call this method when the cell's
// text frame has changed (whenever changing cell decorations).
- (void)resetFieldEditorFrameIfNeeded;
// Returns the amount of the field's width which is not being taken up
// by the text contents. May be negative if the contents are large
// enough to scroll.
- (CGFloat)availableDecorationWidth;
@end
@interface StyledTextField (ExposedForTesting)
- (StyledTextFieldCell*)styledTextFieldCell;
@end
#endif // CHROME_BROWSER_UI_COCOA_STYLED_TEXT_FIELD_H_
// 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 "chrome/browser/ui/cocoa/styled_text_field.h"
#include "base/logging.h"
#import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
@implementation StyledTextField
- (StyledTextFieldCell*)styledTextFieldCell {
DCHECK([[self cell] isKindOfClass:[StyledTextFieldCell class]]);
return static_cast<StyledTextFieldCell*>([self cell]);
}
// Cocoa text fields are edited by placing an NSTextView as subview,
// positioned by the cell's -editWithFrame:inView:... method. Using
// the standard -makeFirstResponder: machinery to reposition the field
// editor results in resetting the field editor's editing state, which
// OmniboxViewMac monitors. This causes problems because
// editing can require the field editor to be repositioned, which
// could disrupt editing. This code repositions the subview directly,
// which causes no editing-state changes.
- (void)resetFieldEditorFrameIfNeeded {
// No action if not editing.
NSText* editor = [self currentEditor];
if (!editor) {
return;
}
// When editing, we should have exactly one subview, which is a
// clipview containing the editor (for purposes of scrolling).
NSArray* subviews = [self subviews];
DCHECK_EQ([subviews count], 1U);
DCHECK([editor isDescendantOf:self]);
if ([subviews count] == 0) {
return;
}
// If the frame is already right, don't make any visible changes.
StyledTextFieldCell* cell = [self styledTextFieldCell];
const NSRect frame([cell drawingRectForBounds:[self bounds]]);
NSView* subview = [subviews objectAtIndex:0];
if (NSEqualRects(frame, [subview frame])) {
return;
}
[subview setFrame:frame];
// Make sure the selection remains visible.
[editor scrollRangeToVisible:[editor selectedRange]];
}
- (CGFloat)availableDecorationWidth {
NSAttributedString* as = [self attributedStringValue];
const NSSize size([as size]);
const NSRect bounds([self bounds]);
return NSWidth(bounds) - size.width;
}
- (NSFocusRingType)focusRingType {
// This is taken care of by the custom drawing code in the cell.
return NSFocusRingTypeNone;
}
// Due to theming, parts of the field are transparent.
- (BOOL)isOpaque {
return NO;
}
@end
// Copyright (c) 2009 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_UI_COCOA_STYLED_TEXT_FIELD_CELL_H_
#define CHROME_BROWSER_UI_COCOA_STYLED_TEXT_FIELD_CELL_H_
#import <Cocoa/Cocoa.h>
#import "chrome/browser/ui/cocoa/rect_path_utils.h"
// StyledTextFieldCell customizes the look of the standard Cocoa text field.
// The border and focus ring are modified, as is the drawing rect. Subclasses
// can override |drawInteriorWithFrame:inView:| to provide custom drawing for
// decorations, but they must make sure to call the superclass' implementation
// with a modified frame after performing any custom drawing.
@interface StyledTextFieldCell : NSTextFieldCell {
}
@end
// Methods intended to be overridden by subclasses, not part of the public API
// and should not be called outside of subclasses.
@interface StyledTextFieldCell (ProtectedMethods)
// Return the portion of the cell to show the text cursor over. The default
// implementation returns the full |cellFrame|. Subclasses should override this
// method if they add any decorations.
- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame;
// Return the portion of the cell to use for text display. This corresponds to
// the frame with our added decorations sliced off. The default implementation
// returns the full |cellFrame|, as by default there are no decorations.
// Subclasses should override this method if they add any decorations.
- (NSRect)textFrameForFrame:(NSRect)cellFrame;
// Offset from the top of the cell frame to the text frame. Defaults to 0.
// Subclasses should
- (CGFloat)topTextFrameOffset;
// Offset from the bottom of the cell frame to the text frame. Defaults to 0.
// Subclasses should
- (CGFloat)bottomTextFrameOffset;
// Radius of the corners of the field. Defaults to square corners (0.0).
- (CGFloat)cornerRadius;
// Which corners of the field to round. Defaults to RoundedAll.
- (rect_path_utils::RoundedCornerFlags)roundedFlags;
// Returns YES if a light themed bezel should be drawn under the text field.
// Default implementation returns NO.
- (BOOL)shouldDrawBezel;
@end
#endif // CHROME_BROWSER_UI_COCOA_STYLED_TEXT_FIELD_CELL_H_
// 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 "chrome/browser/ui/cocoa/styled_text_field_cell.h"
#include "base/logging.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service.h"
#import "chrome/browser/ui/cocoa/themed_window.h"
#include "chrome/grit/theme_resources.h"
#import "ui/base/cocoa/nsgraphics_context_additions.h"
#import "ui/base/cocoa/nsview_additions.h"
#include "ui/base/cocoa/scoped_cg_context_smooth_fonts.h"
#include "ui/gfx/font.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
@implementation StyledTextFieldCell
- (CGFloat)topTextFrameOffset {
return 0.0;
}
- (CGFloat)bottomTextFrameOffset {
return 0.0;
}
- (CGFloat)cornerRadius {
return 0.0;
}
- (rect_path_utils::RoundedCornerFlags)roundedCornerFlags {
return rect_path_utils::RoundedCornerAll;
}
- (BOOL)shouldDrawBezel {
return NO;
}
- (NSRect)textFrameForFrameInternal:(NSRect)cellFrame {
CGFloat topOffset = [self topTextFrameOffset];
NSRect textFrame = cellFrame;
textFrame.origin.y += topOffset;
textFrame.size.height -= topOffset + [self bottomTextFrameOffset];
return textFrame;
}
// Returns the same value as textCursorFrameForFrame, but does not call it
// directly to avoid potential infinite loops.
- (NSRect)textFrameForFrame:(NSRect)cellFrame {
return [self textFrameForFrameInternal:cellFrame];
}
// Returns the same value as textFrameForFrame, but does not call it directly to
// avoid potential infinite loops.
- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame {
return [self textFrameForFrameInternal:cellFrame];
}
// Override to show the I-beam cursor only in the area given by
// |textCursorFrameForFrame:|.
- (void)resetCursorRect:(NSRect)cellFrame inView:(NSView *)controlView {
[super resetCursorRect:[self textCursorFrameForFrame:cellFrame]
inView:controlView];
}
// For NSTextFieldCell this is the area within the borders. For our
// purposes, we count the info decorations as being part of the
// border.
- (NSRect)drawingRectForBounds:(NSRect)theRect {
return [super drawingRectForBounds:[self textFrameForFrame:theRect]];
}
// TODO(shess): This code is manually drawing the cell's border area,
// but otherwise the cell assumes -setBordered:YES for purposes of
// calculating things like the editing area. This is probably
// incorrect. I know that this affects -drawingRectForBounds:.
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
const CGFloat lineWidth = [controlView cr_lineWidth];
const CGFloat halfLineWidth = lineWidth / 2.0;
DCHECK([controlView isFlipped]);
rect_path_utils::RoundedCornerFlags roundedCornerFlags =
[self roundedCornerFlags];
// TODO(shess): This inset is also reflected by |kFieldVisualInset|
// in omnibox_popup_view_mac.mm.
const NSRect frame = NSInsetRect(cellFrame, 0, lineWidth);
const CGFloat radius = [self cornerRadius];
// Paint button background image if there is one (otherwise the border won't
// look right).
const ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
if (themeProvider) {
NSColor* backgroundImageColor = nil;
if (themeProvider->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND)) {
backgroundImageColor =
themeProvider->GetNSImageColorNamed(IDR_THEME_BUTTON_BACKGROUND);
}
if (backgroundImageColor) {
// Set the phase to match window.
NSRect trueRect = [controlView convertRect:cellFrame toView:nil];
NSPoint midPoint = NSMakePoint(NSMinX(trueRect), NSMaxY(trueRect));
[[NSGraphicsContext currentContext] cr_setPatternPhase:midPoint
forView:controlView];
// NOTE(shess): This seems like it should be using a 0.0 inset,
// but AFAICT using a halfLineWidth inset is important in mixing the
// toolbar background and the omnibox background.
rect_path_utils::FillRectWithInset(roundedCornerFlags, frame,
halfLineWidth, halfLineWidth, radius,
backgroundImageColor);
}
// Draw the outer stroke (over the background).
BOOL active = [[controlView window] isMainWindow];
NSColor* strokeColor = themeProvider->GetNSColor(
active ? ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE :
ThemeProperties::COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE);
rect_path_utils::FrameRectWithInset(roundedCornerFlags, frame, 0.0, 0.0,
radius, lineWidth, strokeColor);
}
// Fill interior with background color.
rect_path_utils::FillRectWithInset(roundedCornerFlags, frame, lineWidth,
lineWidth, radius,
[self backgroundColor]);
// Draw the shadow. For the rounded-rect case, the shadow needs to
// slightly turn in at the corners. |shadowFrame| is at the same
// midline as the inner border line on the top and left, but at the
// outer border line on the bottom and right. The clipping change
// will clip the bottom and right edges (and corner).
{
gfx::ScopedNSGraphicsContextSaveGState state;
[rect_path_utils::RectPathWithInset(roundedCornerFlags, frame, lineWidth,
lineWidth, radius) addClip];
const NSRect shadowFrame =
NSOffsetRect(frame, halfLineWidth, halfLineWidth);
NSColor* shadowShade = [NSColor colorWithCalibratedWhite:0.0
alpha:0.05 / lineWidth];
rect_path_utils::FrameRectWithInset(roundedCornerFlags, shadowFrame,
halfLineWidth, halfLineWidth,
radius - halfLineWidth, lineWidth,
shadowShade);
}
// Draw optional bezel below bottom stroke.
if ([self shouldDrawBezel] && themeProvider &&
themeProvider->UsingSystemTheme()) {
NSColor* bezelColor = themeProvider->GetNSColor(
ThemeProperties::COLOR_TOOLBAR_BEZEL);
[[bezelColor colorWithAlphaComponent:0.5 / lineWidth] set];
NSRect bezelRect = NSMakeRect(cellFrame.origin.x,
NSMaxY(cellFrame) - lineWidth,
NSWidth(cellFrame),
lineWidth);
bezelRect = NSInsetRect(bezelRect, radius - halfLineWidth, 0.0);
NSRectFillUsingOperation(bezelRect, NSCompositeSourceOver);
}
// Draw the interior before the focus ring, to make sure nothing overlaps it.
ui::ScopedCGContextSmoothFonts fontSmoothing;
[self drawInteriorWithFrame:cellFrame inView:controlView];
// Draw the focus ring if needed.
if ([self showsFirstResponder]) {
NSColor* color = [[NSColor keyboardFocusIndicatorColor]
colorWithAlphaComponent:0.5 / lineWidth];
rect_path_utils::FrameRectWithInset(roundedCornerFlags, frame, 0.0, 0.0,
radius, lineWidth * 2, color);
}
}
@end
// 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/mac/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#import "chrome/browser/ui/cocoa/test/styled_text_field_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace {
// Width of the field so that we don't have to ask |field_| for it all
// the time.
const CGFloat kWidth(300.0);
class StyledTextFieldCellTest : public CocoaTest {
public:
StyledTextFieldCellTest() {
// Make sure this is wide enough to play games with the cell
// decorations.
const NSRect frame = NSMakeRect(0, 0, kWidth, 30);
base::scoped_nsobject<StyledTextFieldTestCell> cell(
[[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]);
cell_ = cell.get();
[cell_ setEditable:YES];
[cell_ setBordered:YES];
base::scoped_nsobject<NSTextField> view(
[[NSTextField alloc] initWithFrame:frame]);
view_ = view.get();
[view_ setCell:cell_];
[[test_window() contentView] addSubview:view_];
}
NSTextField* view_;
StyledTextFieldTestCell* cell_;
};
// Basic view tests (AddRemove, Display).
TEST_VIEW(StyledTextFieldCellTest, view_);
// Test drawing, mostly to ensure nothing leaks or crashes.
TEST_F(StyledTextFieldCellTest, FocusedDisplay) {
[view_ display];
// Test focused drawing.
[test_window() makePretendKeyWindowAndSetFirstResponder:view_];
[view_ display];
[test_window() clearPretendKeyWindowAndFirstResponder];
// Test display of various cell configurations.
[cell_ setLeftMargin:5];
[view_ display];
[cell_ setRightMargin:15];
[view_ display];
}
// The editor frame should be slightly inset from the text frame.
TEST_F(StyledTextFieldCellTest, DrawingRectForBounds) {
const NSRect bounds = [view_ bounds];
NSRect textFrame = [cell_ textFrameForFrame:bounds];
NSRect drawingRect = [cell_ drawingRectForBounds:bounds];
EXPECT_FALSE(NSIsEmptyRect(drawingRect));
EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1)));
[cell_ setLeftMargin:10];
textFrame = [cell_ textFrameForFrame:bounds];
drawingRect = [cell_ drawingRectForBounds:bounds];
EXPECT_FALSE(NSIsEmptyRect(drawingRect));
EXPECT_TRUE(NSContainsRect(textFrame, NSInsetRect(drawingRect, 1, 1)));
[cell_ setRightMargin:20];
textFrame = [cell_ textFrameForFrame:bounds];
drawingRect = [cell_ drawingRectForBounds:bounds];
EXPECT_FALSE(NSIsEmptyRect(drawingRect));
EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect));
[cell_ setLeftMargin:0];
textFrame = [cell_ textFrameForFrame:bounds];
drawingRect = [cell_ drawingRectForBounds:bounds];
EXPECT_FALSE(NSIsEmptyRect(drawingRect));
EXPECT_TRUE(NSContainsRect(NSInsetRect(textFrame, 1, 1), drawingRect));
}
} // namespace
// Copyright (c) 2012 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/mac/scoped_nsobject.h"
#import "chrome/browser/ui/cocoa/styled_text_field.h"
#import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#import "chrome/browser/ui/cocoa/test/styled_text_field_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
namespace {
// Width of the field so that we don't have to ask |field_| for it all
// the time.
static const CGFloat kWidth(300.0);
class StyledTextFieldTest : public CocoaTest {
public:
StyledTextFieldTest() {
// Make sure this is wide enough to play games with the cell
// decorations.
NSRect frame = NSMakeRect(0, 0, kWidth, 30);
base::scoped_nsobject<StyledTextFieldTestCell> cell(
[[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]);
cell_ = cell.get();
[cell_ setEditable:YES];
[cell_ setBordered:YES];
base::scoped_nsobject<StyledTextField> field(
[[StyledTextField alloc] initWithFrame:frame]);
field_ = field.get();
[field_ setCell:cell_];
[[test_window() contentView] addSubview:field_];
}
// Helper to return the field-editor frame being used w/in |field_|.
NSRect EditorFrame() {
EXPECT_TRUE([field_ currentEditor]);
EXPECT_EQ([[field_ subviews] count], 1U);
if ([[field_ subviews] count] > 0) {
return [[[field_ subviews] objectAtIndex:0] frame];
} else {
// Return something which won't work so the caller can soldier
// on.
return NSZeroRect;
}
}
StyledTextField* field_;
StyledTextFieldTestCell* cell_;
};
// Basic view tests (AddRemove, Display).
TEST_VIEW(StyledTextFieldTest, field_);
// Test that we get the same cell from -cell and
// -styledTextFieldCell.
TEST_F(StyledTextFieldTest, Cell) {
StyledTextFieldCell* cell = [field_ styledTextFieldCell];
EXPECT_EQ(cell, [field_ cell]);
EXPECT_TRUE(cell != nil);
}
// Test that becoming first responder sets things up correctly.
TEST_F(StyledTextFieldTest, FirstResponder) {
EXPECT_EQ(nil, [field_ currentEditor]);
EXPECT_EQ([[field_ subviews] count], 0U);
[test_window() makePretendKeyWindowAndSetFirstResponder:field_];
EXPECT_FALSE(nil == [field_ currentEditor]);
EXPECT_EQ([[field_ subviews] count], 1U);
EXPECT_TRUE([[field_ currentEditor] isDescendantOf:field_]);
}
TEST_F(StyledTextFieldTest, AvailableDecorationWidth) {
// A fudge factor to account for how much space the border takes up.
// The test shouldn't be too dependent on the field's internals, but
// it also shouldn't let deranged cases fall through the cracks
// (like nothing available with no text, or everything available
// with some text).
const CGFloat kBorderWidth = 20.0;
// With no contents, almost the entire width is available for
// decorations.
[field_ setStringValue:@""];
CGFloat availableWidth = [field_ availableDecorationWidth];
EXPECT_LE(availableWidth, kWidth);
EXPECT_GT(availableWidth, kWidth - kBorderWidth);
// With minor contents, most of the remaining width is available for
// decorations.
NSDictionary* attributes =
[NSDictionary dictionaryWithObject:[field_ font]
forKey:NSFontAttributeName];
NSString* string = @"Hello world";
const NSSize size([string sizeWithAttributes:attributes]);
[field_ setStringValue:string];
availableWidth = [field_ availableDecorationWidth];
EXPECT_LE(availableWidth, kWidth - size.width);
EXPECT_GT(availableWidth, kWidth - size.width - kBorderWidth);
// With huge contents, nothing at all is left for decorations.
string = @"A long string which is surely wider than field_ can hold.";
[field_ setStringValue:string];
availableWidth = [field_ availableDecorationWidth];
EXPECT_LT(availableWidth, 0.0);
}
// Test drawing, mostly to ensure nothing leaks or crashes.
TEST_F(StyledTextFieldTest, Display) {
[field_ display];
// Test focused drawing.
[test_window() makePretendKeyWindowAndSetFirstResponder:field_];
[field_ display];
}
// Test that the field editor gets the same bounds when focus is delivered by
// the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded.
TEST_F(StyledTextFieldTest, ResetFieldEditorBase) {
// Capture the editor frame resulting from the standard focus machinery.
[test_window() makePretendKeyWindowAndSetFirstResponder:field_];
const NSRect baseEditorFrame(EditorFrame());
// Setting a hint should result in a strictly smaller editor frame.
EXPECT_EQ(0, [cell_ leftMargin]);
EXPECT_EQ(0, [cell_ rightMargin]);
[cell_ setLeftMargin:10];
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_NSNE(baseEditorFrame, EditorFrame());
EXPECT_TRUE(NSContainsRect(baseEditorFrame, EditorFrame()));
// Resetting the margin and using -resetFieldEditorFrameIfNeeded should result
// in the same frame as the standard focus machinery.
[cell_ setLeftMargin:0];
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_NSEQ(baseEditorFrame, EditorFrame());
}
// Test that the field editor gets the same bounds when focus is delivered by
// the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded.
TEST_F(StyledTextFieldTest, ResetFieldEditorLeftMargin) {
const CGFloat kLeftMargin = 20;
// Start the cell off with a non-zero left margin.
[cell_ setLeftMargin:kLeftMargin];
[cell_ setRightMargin:0];
// Capture the editor frame resulting from the standard focus machinery.
[test_window() makePretendKeyWindowAndSetFirstResponder:field_];
const NSRect baseEditorFrame(EditorFrame());
// Clearing the margin should result in a strictly larger editor frame.
[cell_ setLeftMargin:0];
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_NSNE(baseEditorFrame, EditorFrame());
EXPECT_TRUE(NSContainsRect(EditorFrame(), baseEditorFrame));
// Setting the same margin and using -resetFieldEditorFrameIfNeeded should
// result in the same frame as the standard focus machinery.
[cell_ setLeftMargin:kLeftMargin];
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_NSEQ(baseEditorFrame, EditorFrame());
}
// Test that the field editor gets the same bounds when focus is delivered by
// the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded.
TEST_F(StyledTextFieldTest, ResetFieldEditorRightMargin) {
const CGFloat kRightMargin = 20;
// Start the cell off with a non-zero right margin.
[cell_ setLeftMargin:0];
[cell_ setRightMargin:kRightMargin];
// Capture the editor frame resulting from the standard focus machinery.
[test_window() makePretendKeyWindowAndSetFirstResponder:field_];
const NSRect baseEditorFrame(EditorFrame());
// Clearing the margin should result in a strictly larger editor frame.
[cell_ setRightMargin:0];
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_NSNE(baseEditorFrame, EditorFrame());
EXPECT_TRUE(NSContainsRect(EditorFrame(), baseEditorFrame));
// Setting the same margin and using -resetFieldEditorFrameIfNeeded should
// result in the same frame as the standard focus machinery.
[cell_ setRightMargin:kRightMargin];
[field_ resetFieldEditorFrameIfNeeded];
EXPECT_NSEQ(baseEditorFrame, EditorFrame());
}
} // namespace
// Copyright (c) 2009 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_UI_COCOA_TEST_STYLED_TEXT_FIELD_TEST_HELPER_H_
#define CHROME_BROWSER_UI_COCOA_TEST_STYLED_TEXT_FIELD_TEST_HELPER_H_
#import <Cocoa/Cocoa.h>
#import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
// Subclass of StyledTextFieldCell that allows you to slice off sections on the
// left and right of the cell.
@interface StyledTextFieldTestCell : StyledTextFieldCell {
CGFloat leftMargin_;
CGFloat rightMargin_;
}
@property(nonatomic, assign) CGFloat leftMargin;
@property(nonatomic, assign) CGFloat rightMargin;
@end
#endif // CHROME_BROWSER_UI_COCOA_TEST_STYLED_TEXT_FIELD_TEST_HELPER_H_
// Copyright (c) 2009 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>
#import "chrome/browser/ui/cocoa/test/styled_text_field_test_helper.h"
@implementation StyledTextFieldTestCell
@synthesize leftMargin = leftMargin_;
@synthesize rightMargin = rightMargin_;
- (NSRect)textFrameForFrame:(NSRect)frame {
NSRect textFrame = [super textFrameForFrame:frame];
textFrame.origin.x += leftMargin_;
textFrame.size.width -= (leftMargin_ + rightMargin_);
return textFrame;
}
@end
......@@ -4115,9 +4115,6 @@ test("unit_tests") {
# the place this variable is used below.
if (true) {
cocoa_test_sources = [
"../browser/ui/cocoa/animatable_image_unittest.mm",
"../browser/ui/cocoa/animatable_view_unittest.mm",
"../browser/ui/cocoa/background_gradient_view_unittest.mm",
"../browser/ui/cocoa/bookmarks/bookmark_menu_bridge_unittest.mm",
"../browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller_unittest.mm",
"../browser/ui/cocoa/browser_window_cocoa_unittest.mm",
......@@ -4144,14 +4141,10 @@ test("unit_tests") {
"../browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm",
"../browser/ui/cocoa/scoped_menu_bar_lock_unittest.mm",
"../browser/ui/cocoa/status_icons/status_icon_mac_unittest.mm",
"../browser/ui/cocoa/styled_text_field_cell_unittest.mm",
"../browser/ui/cocoa/styled_text_field_unittest.mm",
"../browser/ui/cocoa/tabbed_browser_window_unittest.mm",
"../browser/ui/cocoa/test/cocoa_profile_test.h",
"../browser/ui/cocoa/test/cocoa_profile_test.mm",
"../browser/ui/cocoa/test/run_loop_testing_unittest.mm",
"../browser/ui/cocoa/test/styled_text_field_test_helper.h",
"../browser/ui/cocoa/test/styled_text_field_test_helper.mm",
"../browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm",
"../browser/ui/cocoa/touchbar/credit_card_autofill_touch_bar_controller_unittest.mm",
"../browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm",
......
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