Commit 71e95f98 authored by Nico Weber's avatar Nico Weber Committed by Commit Bot

mac: Remove some unused controls.

Bug: 832676
Change-Id: I9b56c47523765af4b33a997b65fe2a48a9da7f29
Reviewed-on: https://chromium-review.googlesource.com/1246324Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Commit-Queue: Nico Weber <thakis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594375}
parent 9a5603c1
......@@ -126,8 +126,6 @@ jumbo_split_static_library("ui") {
"cocoa/fullscreen_window.h",
"cocoa/fullscreen_window.mm",
"cocoa/has_weak_browser_pointer.h",
"cocoa/hover_close_button.h",
"cocoa/hover_close_button.mm",
"cocoa/javascript_app_modal_dialog_cocoa.h",
"cocoa/javascript_app_modal_dialog_cocoa.mm",
"cocoa/location_bar/location_bar_view_mac.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.
#ifndef CHROME_BROWSER_UI_COCOA_HOVER_CLOSE_BUTTON_H_
#define CHROME_BROWSER_UI_COCOA_HOVER_CLOSE_BUTTON_H_
#import <Cocoa/Cocoa.h>
#include "third_party/skia/include/core/SkColor.h"
#import "ui/base/cocoa/hover_button.h"
@class GTMKeyValueAnimation;
// The standard close button for our Mac UI which is the "x" that changes to a
// dark circle with the "x" when you hover over it. Used to close tabs.
@interface HoverCloseButton : HoverButtonCocoa<NSAnimationDelegate> {
@private
GTMKeyValueAnimation* fadeOutAnimation_;
CloseButtonHoverState previousState_;
}
// The color of the icon in its idle (not-hovering) state.
@property(nonatomic) SkColor iconColor;
@end
// A version of HoverCloseButton with the "x" icon changed to match the WebUI
// look.
@interface WebUIHoverCloseButton : HoverCloseButton
@end
#endif // CHROME_BROWSER_UI_COCOA_HOVER_CLOSE_BUTTON_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.
#import "chrome/browser/ui/cocoa/hover_close_button.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMKeyValueAnimation.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/image/image_skia_util_mac.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/resources/grit/ui_resources.h"
namespace {
const CGFloat kFramesPerSecond = 16; // Determined experimentally to look good.
const CGFloat kCloseAnimationDuration = 0.1;
const int kTabCloseButtonSize = 16;
// Strings that are used for all close buttons. Set up in +initialize.
NSString* gBasicAccessibilityTitle = nil;
NSString* gTooltip = nil;
// If this string is changed, the setter (currently setFadeOutValue:) must
// be changed as well to match.
NSString* const kFadeOutValueKeyPath = @"fadeOutValue";
const SkColor kDefaultIconColor = SkColorSetARGB(0xA0, 0x00, 0x00, 0x00);
class HighlightImage : public gfx::CanvasImageSource {
public:
explicit HighlightImage(const int image_size, SkColor color)
: CanvasImageSource(gfx::Size(image_size, image_size),
/*is_opaque =*/true),
color_(color) {}
~HighlightImage() override {}
private:
void Draw(gfx::Canvas* canvas) override {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(color_);
canvas->DrawCircle(
gfx::RectF(size().width(), size().height()).CenterPoint(),
kTabCloseButtonSize / 2, flags);
}
SkColor color_;
DISALLOW_COPY_AND_ASSIGN(HighlightImage);
};
} // namespace
@interface HoverCloseButton ()
// Common initialization routine called from initWithFrame and awakeFromNib.
- (void)commonInit;
// Called by |fadeOutAnimation_| when animated value changes.
- (void)setFadeOutValue:(CGFloat)value;
// Gets the image for the given hover state.
- (NSImage*)imageForHoverState:(CloseButtonHoverState)hoverState;
@end
@implementation HoverCloseButton
@synthesize iconColor = iconColor_;
+ (void)initialize {
// Grab some strings that are used by all close buttons.
if (!gBasicAccessibilityTitle) {
gBasicAccessibilityTitle = [l10n_util::GetNSStringWithFixup(
IDS_ACCNAME_CLOSE) copy];
}
if (!gTooltip)
gTooltip = [l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_CLOSE_TAB) copy];
}
- (void)commonInit {
[super commonInit];
[self setAccessibilityTitle:nil];
// Add a tooltip. Using 'owner:self' means that
// -view:stringForToolTip:point:userData: will be called to provide the
// tooltip contents immediately before showing it.
[self addToolTipRect:[self bounds] owner:self userData:NULL];
previousState_ = kHoverStateNone;
iconColor_ = kDefaultIconColor;
}
- (void)removeFromSuperview {
// -stopAnimation will call the animationDidStop: delegate method
// which will release our animation.
[fadeOutAnimation_ stopAnimation];
[super removeFromSuperview];
}
- (void)animationDidStop:(NSAnimation*)animation {
DCHECK(animation == fadeOutAnimation_);
[fadeOutAnimation_ setDelegate:nil];
[fadeOutAnimation_ release];
fadeOutAnimation_ = nil;
}
- (void)animationDidEnd:(NSAnimation*)animation {
[self animationDidStop:animation];
}
- (void)drawRect:(NSRect)dirtyRect {
NSImage* image = [self imageForHoverState:[self hoverState]];
// Close boxes align left horizontally, and align center vertically.
// http:crbug.com/14739 requires this.
NSRect imageRect = NSZeroRect;
imageRect.size = [image size];
NSRect destRect = [self bounds];
destRect.origin.y = floor((NSHeight(destRect) / 2)
- (NSHeight(imageRect) / 2));
destRect.size = imageRect.size;
switch(self.hoverState) {
case kHoverStateMouseOver:
case kHoverStateMouseDown:
[image drawInRect:destRect
fromRect:imageRect
operation:NSCompositeSourceOver
fraction:1.0
respectFlipped:YES
hints:nil];
break;
case kHoverStateNone: {
CGFloat value = 1.0;
if (fadeOutAnimation_) {
value = [fadeOutAnimation_ currentValue];
NSImage* previousImage = nil;
if (previousState_ == kHoverStateMouseOver)
previousImage = [self imageForHoverState:kHoverStateMouseOver];
else
previousImage = [self imageForHoverState:kHoverStateMouseDown];
[previousImage drawInRect:destRect
fromRect:imageRect
operation:NSCompositeSourceOver
fraction:1.0 - value
respectFlipped:YES
hints:nil];
}
[image drawInRect:destRect
fromRect:imageRect
operation:NSCompositeSourceOver
fraction:value
respectFlipped:YES
hints:nil];
break;
}
}
}
- (void)drawFocusRingMask {
// Match the hover image's shape.
NSRect circleRect = NSInsetRect([self bounds], 2, 2);
[[NSBezierPath bezierPathWithOvalInRect:circleRect] fill];
}
- (void)setFadeOutValue:(CGFloat)value {
[self setNeedsDisplay];
}
- (NSImage*)imageForHoverState:(CloseButtonHoverState)hoverState {
SkColor vectorIconColor = gfx::kPlaceholderColor;
switch (hoverState) {
case kHoverStateNone:
break;
case kHoverStateMouseOver:
// For mouse over, the icon color is the fill color of the circle.
vectorIconColor = SkColorSetARGB(0xFF, 0xDB, 0x44, 0x37);
break;
case kHoverStateMouseDown:
// For mouse pressed, the icon color is the fill color of the circle.
vectorIconColor = SkColorSetARGB(0xFF, 0xA8, 0x35, 0x2A);
break;
}
const gfx::ImageSkia iconImage = gfx::CreateVectorIcon(
kTabCloseNormalIcon, kTabCloseButtonSize,
hoverState != kHoverStateNone ? SK_ColorWHITE : iconColor_);
if (hoverState != kHoverStateNone) {
const gfx::ImageSkia highlight =
gfx::CanvasImageSource::MakeImageSkia<HighlightImage>(
kTabCloseButtonSize, vectorIconColor);
return NSImageFromImageSkia(
gfx::ImageSkiaOperations::CreateSuperimposedImage(highlight,
iconImage));
}
return NSImageFromImageSkia(iconImage);
}
- (void)setHoverState:(CloseButtonHoverState)state {
if (state != self.hoverState) {
previousState_ = self.hoverState;
[super setHoverState:state];
// Only animate the HoverStateNone case and only if this is still in the
// view hierarchy.
if (state == kHoverStateNone && [self superview] != nil) {
DCHECK(fadeOutAnimation_ == nil);
fadeOutAnimation_ =
[[GTMKeyValueAnimation alloc] initWithTarget:self
keyPath:kFadeOutValueKeyPath];
[fadeOutAnimation_ setDuration:kCloseAnimationDuration];
[fadeOutAnimation_ setFrameRate:kFramesPerSecond];
[fadeOutAnimation_ setDelegate:self];
[fadeOutAnimation_ startAnimation];
} else {
// -stopAnimation will call the animationDidStop: delegate method
// which will clean up the animation.
[fadeOutAnimation_ stopAnimation];
}
}
}
// Called each time a tooltip is about to be shown.
- (NSString*)view:(NSView*)view
stringForToolTip:(NSToolTipTag)tag
point:(NSPoint)point
userData:(void*)userData {
if (self.hoverState == kHoverStateMouseOver) {
// In some cases (e.g. the download tray), the button is still in the
// hover state, but is outside the bounds of its parent and not visible.
// Don't show the tooltip in that case.
NSRect buttonRect = [self frame];
NSRect parentRect = [[self superview] bounds];
if (NSIntersectsRect(buttonRect, parentRect))
return gTooltip;
}
return nil; // Do not show the tooltip.
}
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle {
if (!accessibilityTitle) {
[super setAccessibilityTitle:gBasicAccessibilityTitle];
return;
}
NSString* extendedTitle = l10n_util::GetNSStringFWithFixup(
IDS_ACCNAME_CLOSE_TAB,
base::SysNSStringToUTF16(accessibilityTitle));
[super setAccessibilityTitle:extendedTitle];
}
- (void)setIconColor:(SkColor)iconColor {
if (iconColor != iconColor_) {
iconColor_ = iconColor;
[self setNeedsDisplay:YES];
}
}
@end
@implementation WebUIHoverCloseButton
- (NSImage*)imageForHoverState:(CloseButtonHoverState)hoverState {
int imageID = IDR_CLOSE_DIALOG;
switch (hoverState) {
case kHoverStateNone:
imageID = IDR_CLOSE_DIALOG;
break;
case kHoverStateMouseOver:
imageID = IDR_CLOSE_DIALOG_H;
break;
case kHoverStateMouseDown:
imageID = IDR_CLOSE_DIALOG_P;
break;
}
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
return bundle.GetNativeImageNamed(imageID).ToNSImage();
}
@end
// 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/hover_close_button.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
class HoverCloseButtonTest : public CocoaTest {
public:
HoverCloseButtonTest() {
NSRect content_frame = [[test_window() contentView] frame];
button_.reset([[HoverCloseButton alloc] initWithFrame:content_frame]);
[[test_window() contentView] addSubview:button_];
}
protected:
base::scoped_nsobject<HoverCloseButton> button_;
};
class WebUIHoverCloseButtonTest : public CocoaTest {
public:
WebUIHoverCloseButtonTest() {
NSRect content_frame = [[test_window() contentView] frame];
button_.reset([[WebUIHoverCloseButton alloc] initWithFrame:content_frame]);
[[test_window() contentView] addSubview:button_];
}
protected:
base::scoped_nsobject<WebUIHoverCloseButton> button_;
};
TEST_VIEW(HoverCloseButtonTest, button_)
TEST_VIEW(WebUIHoverCloseButtonTest, button_)
......@@ -4138,7 +4138,6 @@ test("unit_tests") {
"../browser/ui/cocoa/history_menu_bridge_unittest.mm",
"../browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm",
"../browser/ui/cocoa/history_overlay_controller_unittest.mm",
"../browser/ui/cocoa/hover_close_button_unittest.mm",
"../browser/ui/cocoa/main_menu_builder_unittest.mm",
"../browser/ui/cocoa/media_picker/desktop_media_picker_controller_unittest.mm",
"../browser/ui/cocoa/notifications/notification_builder_mac_unittest.mm",
......
......@@ -89,8 +89,6 @@ jumbo_component("base") {
"clipboard/clipboard_win.cc",
"clipboard/clipboard_win.h",
"clipboard/custom_data_helper_mac.mm",
"cocoa/a11y_util.h",
"cocoa/a11y_util.mm",
"cocoa/accessibility_hostable.h",
"cocoa/animation_utils.h",
"cocoa/appkit_utils.h",
......@@ -105,12 +103,6 @@ jumbo_component("base") {
"cocoa/constrained_window/constrained_window_animation.mm",
"cocoa/controls/button_utils.h",
"cocoa/controls/button_utils.mm",
"cocoa/controls/hyperlink_button_cell.h",
"cocoa/controls/hyperlink_button_cell.mm",
"cocoa/controls/hyperlink_text_view.h",
"cocoa/controls/hyperlink_text_view.mm",
"cocoa/controls/imageview_utils.h",
"cocoa/controls/imageview_utils.mm",
"cocoa/controls/textfield_utils.h",
"cocoa/controls/textfield_utils.mm",
"cocoa/defaults_utils.h",
......@@ -868,8 +860,6 @@ test("ui_base_unittests") {
"cocoa/bubble_closer_unittest.mm",
"cocoa/cocoa_base_utils_unittest.mm",
"cocoa/constrained_window/constrained_window_animation_unittest.mm",
"cocoa/controls/hyperlink_button_cell_unittest.mm",
"cocoa/controls/hyperlink_text_view_unittest.mm",
"cocoa/focus_tracker_unittest.mm",
"cocoa/hover_button_unittest.mm",
"cocoa/hover_image_button_unittest.mm",
......
// Copyright 2016 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 UI_BASE_COCOA_A11Y_UTIL_H
#define UI_BASE_COCOA_A11Y_UTIL_H
#import <Cocoa/Cocoa.h>
#include "ui/base/ui_base_export.h"
namespace ui {
namespace a11y_util {
// Hides the given |view| from the accessibility order for Voice Over. This
// should be used when the view provides no additional information with
// voice over (i.e., an icon next to a written description of the icon).
UI_BASE_EXPORT void HideImageFromAccessibilityOrder(NSImageView* view);
// Ask VoiceOver to play a sound for |object|, generally a view or window
// (undocumented). Built-in apps seem to use this to indicate that something
// interesting has happened, like a failed download or available completions.
UI_BASE_EXPORT void PlayElementUpdatedSound(id source);
} // namespace a11y_util
} // namespace ui
#endif // UI_BASE_COCOA_A11Y_UTIL_H
// Copyright 2016 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 "ui/base/cocoa/a11y_util.h"
namespace ui {
namespace a11y_util {
void HideImageFromAccessibilityOrder(NSImageView* view) {
// This is the minimum change necessary to get VoiceOver to skip the image
// (instead of reading the word "image"). Accessibility mechanisms in OSX
// change once in a while, so this may be fragile.
[[view cell] accessibilitySetOverrideValue:@""
forAttribute:NSAccessibilityRoleAttribute];
}
void PlayElementUpdatedSound(id source) {
NSAccessibilityPostNotificationWithUserInfo(
source, @"AXPlaySound",
@{@"AXSoundIdentifier" : @"AXElementUpdatedSound"});
}
} // namespace a11y_util
} // namespace ui
......@@ -22,9 +22,6 @@ UI_BASE_EXPORT
+ (NSButton*)checkboxWithTitle:(NSString*)title;
+ (NSButton*)linkWithTitle:(NSString*)title
action:(SEL)action
target:(id)target;
@end
#endif // UI_BASE_COCOA_CONTROLS_BUTTON_UTILS_H_
......@@ -4,8 +4,6 @@
#import "ui/base/cocoa/controls/button_utils.h"
#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
@implementation ButtonUtils
+ (NSButton*)buttonWithTitle:(NSString*)title
......@@ -31,18 +29,4 @@
return button;
}
+ (NSButton*)linkWithTitle:(NSString*)title
action:(SEL)action
target:(id)target {
NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
// The cell has to be replaced before doing any of the other setup, or it will
// not get the new configuration.
[button setCell:[[[HyperlinkButtonCell alloc] init] autorelease]];
[button setAction:action];
[button setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
[button setTarget:target];
[button setTitle:title];
return button;
}
@end
// Copyright 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 UI_BASE_COCOA_CONTROLS_HYPERLINK_BUTTON_CELL_H_
#define UI_BASE_COCOA_CONTROLS_HYPERLINK_BUTTON_CELL_H_
#import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
#include "ui/base/ui_base_export.h"
// A HyperlinkButtonCell is used to create an NSButton that looks and acts
// like a hyperlink. The default styling is to look like blue (#3367D6) text
// with no underline and to have the pointingHand cursor on mouse over.
//
// To use in Interface Builder:
// 1. Drag out an NSButton.
// 2. Double click on the button so you have the cell component selected.
// 3. In the Identity panel of the inspector, set the custom class to this.
// 4. In the Attributes panel, change the Bezel to Square.
// 5. In the Size panel, set the Height to 16.
//
// Use this if all of your text is a link. If you need text that contains
// embedded links but also regular text, use HyperlinkTextView.
namespace hyperlink_button_cell {
enum class UI_BASE_EXPORT UnderlineBehavior {
ALWAYS,
NEVER,
ON_HOVER,
};
} // namespace hyperlink_button_cell
UI_BASE_EXPORT
@interface HyperlinkButtonCell : NSButtonCell {
base::scoped_nsobject<NSColor> textColor_;
hyperlink_button_cell::UnderlineBehavior underlineBehavior_;
BOOL mouseIsInside_;
}
@property(nonatomic, retain) NSColor* textColor;
@property(nonatomic, assign) hyperlink_button_cell::UnderlineBehavior
underlineBehavior;
+ (NSColor*)defaultTextColor;
// Helper function to create a button with HyperLinkButtonCell as its cell.
+ (NSButton*)buttonWithString:(NSString*)string;
@end
@interface HyperlinkButtonCell (ExposedForTesting)
- (NSDictionary*)linkAttributes;
@end
#endif // UI_BASE_COCOA_CONTROLS_HYPERLINK_BUTTON_CELL_H_
// Copyright 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 "ui/base/cocoa/controls/hyperlink_button_cell.h"
using hyperlink_button_cell::UnderlineBehavior;
@interface HyperlinkButtonCell ()
- (void)customizeButtonCell;
@end
@implementation HyperlinkButtonCell
@dynamic textColor;
@synthesize underlineBehavior = underlineBehavior_;
+ (NSColor*)defaultTextColor {
// Equates to rgb(51, 103, 214) or #3367D6.
return [NSColor colorWithCalibratedRed:51.0/255.0
green:103.0/255.0
blue:214.0/255.0
alpha:1.0];
}
+ (NSButton*)buttonWithString:(NSString*)string {
NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
base::scoped_nsobject<HyperlinkButtonCell> cell(
[[HyperlinkButtonCell alloc] initTextCell:string]);
[cell setAlignment:NSLeftTextAlignment];
[button setCell:cell.get()];
[button setBezelStyle:NSRegularSquareBezelStyle];
return button;
}
// Designated initializer.
- (id)init {
if ((self = [super init])) {
[self customizeButtonCell];
}
return self;
}
// Initializer called when the cell is loaded from the NIB.
- (id)initWithCoder:(NSCoder*)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self customizeButtonCell];
}
return self;
}
// Initializer for code-based creation.
- (id)initTextCell:(NSString*)title {
if ((self = [super initTextCell:title])) {
[self customizeButtonCell];
}
return self;
}
- (id)copyWithZone:(NSZone*)zone {
NSColor* color = textColor_.release();
HyperlinkButtonCell* cell = [super copyWithZone:zone];
cell->textColor_.reset([color copy]);
textColor_.reset(color);
return cell;
}
// Because an NSButtonCell has multiple initializers, this method performs the
// common cell customization code.
- (void)customizeButtonCell {
[self setBordered:NO];
[self setTextColor:[HyperlinkButtonCell defaultTextColor]];
[self setUnderlineBehavior:UnderlineBehavior::NEVER];
CGFloat fontSize = [NSFont systemFontSizeForControlSize:[self controlSize]];
NSFont* font = [NSFont controlContentFontOfSize:fontSize];
[self setFont:font];
// Do not change button appearance when we are pushed.
[self setHighlightsBy:NSNoCellMask];
// We need to set this so that we can override |-mouseEntered:| and
// |-mouseExited:| to change the cursor style on hover states.
[self setShowsBorderOnlyWhileMouseInside:YES];
}
- (void)setControlSize:(NSControlSize)size {
[super setControlSize:size];
[self customizeButtonCell]; // recompute |font|.
}
// Creates the NSDictionary of attributes for the attributed string.
- (NSDictionary*)linkAttributes {
NSUInteger underlineMask = NSUnderlineStyleNone;
if (underlineBehavior_ == UnderlineBehavior::ALWAYS ||
(mouseIsInside_ && [self isEnabled] &&
underlineBehavior_ == UnderlineBehavior::ON_HOVER)) {
underlineMask = NSUnderlinePatternSolid | NSUnderlineStyleSingle;
}
base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
[[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
[paragraphStyle setAlignment:[self alignment]];
[paragraphStyle setLineBreakMode:[self lineBreakMode]];
return [NSDictionary dictionaryWithObjectsAndKeys:
[self textColor], NSForegroundColorAttributeName,
[NSNumber numberWithInt:underlineMask], NSUnderlineStyleAttributeName,
[self font], NSFontAttributeName,
[NSCursor pointingHandCursor], NSCursorAttributeName,
paragraphStyle.get(), NSParagraphStyleAttributeName,
nil
];
}
// Override the drawing for the cell so that the custom style attributes
// can always be applied and so that ellipses will appear when appropriate.
- (NSRect)drawTitle:(NSAttributedString*)title
withFrame:(NSRect)frame
inView:(NSView*)controlView {
NSDictionary* linkAttributes = [self linkAttributes];
NSString* plainTitle = [title string];
[plainTitle drawWithRect:frame
options:(NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingTruncatesLastVisibleLine)
attributes:linkAttributes];
return frame;
}
// Override the default behavior to draw the border. Instead, change the cursor.
- (void)mouseEntered:(NSEvent*)event {
mouseIsInside_ = YES;
if ([self isEnabled])
[[NSCursor pointingHandCursor] push];
else
[[NSCursor currentCursor] push];
if (underlineBehavior_ == UnderlineBehavior::ON_HOVER)
[[self controlView] setNeedsDisplay:YES];
}
- (void)mouseExited:(NSEvent*)event {
mouseIsInside_ = NO;
[NSCursor pop];
if (underlineBehavior_ == UnderlineBehavior::ON_HOVER)
[[self controlView] setNeedsDisplay:YES];
}
// Setters and getters.
- (NSColor*)textColor {
if ([self isEnabled])
return textColor_.get();
else
return [NSColor disabledControlTextColor];
}
- (void)setTextColor:(NSColor*)color {
textColor_.reset([color retain]);
}
// Override so that |-sizeToFit| works better with this type of cell.
- (NSSize)cellSize {
NSSize size = [super cellSize];
size.width += 2;
return size;
}
@end
// Copyright 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 "ui/base/cocoa/controls/hyperlink_button_cell.h"
#import <Cocoa/Cocoa.h>
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_nsobject.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
#import "ui/base/test/cocoa_helper.h"
#include "ui/events/test/cocoa_test_event_utils.h"
namespace ui {
namespace {
class HyperlinkButtonCellTest : public CocoaTest {
public:
HyperlinkButtonCellTest() {
NSRect frame = NSMakeRect(0, 0, 50, 30);
base::scoped_nsobject<NSButton> view(
[[NSButton alloc] initWithFrame:frame]);
view_ = view.get();
base::scoped_nsobject<HyperlinkButtonCell> cell(
[[HyperlinkButtonCell alloc] initTextCell:@"Testing"]);
cell_ = cell.get();
[view_ setCell:cell_];
[[test_window() contentView] addSubview:view_];
}
void TestCellCustomization(HyperlinkButtonCell* cell) {
EXPECT_FALSE([cell isBordered]);
EXPECT_EQ(NSNoCellMask, [cell_ highlightsBy]);
EXPECT_TRUE([cell showsBorderOnlyWhileMouseInside]);
EXPECT_TRUE([cell textColor]);
}
protected:
bool HasUnderlineAttribute(NSDictionary* attributes) {
NSNumber* number = base::mac::ObjCCastStrict<NSNumber>(
[attributes objectForKey:NSUnderlineStyleAttributeName]);
return [number unsignedIntegerValue] != 0;
}
NSButton* view_;
HyperlinkButtonCell* cell_;
};
TEST_VIEW(HyperlinkButtonCellTest, view_)
// Tests the three designated intializers.
TEST_F(HyperlinkButtonCellTest, Initializers) {
TestCellCustomization(cell_); // |-initTextFrame:|
base::scoped_nsobject<HyperlinkButtonCell> cell(
[[HyperlinkButtonCell alloc] init]);
TestCellCustomization(cell.get());
// Need to create a dummy archiver to test |-initWithCoder:|.
NSData* emptyData = [NSKeyedArchiver archivedDataWithRootObject:@""];
NSCoder* coder =
[[[NSKeyedUnarchiver alloc] initForReadingWithData:emptyData] autorelease];
cell.reset([[HyperlinkButtonCell alloc] initWithCoder:coder]);
TestCellCustomization(cell);
}
// Test set color.
TEST_F(HyperlinkButtonCellTest, SetTextColor) {
NSColor* textColor = [NSColor redColor];
EXPECT_NE(textColor, [cell_ textColor]);
[cell_ setTextColor:textColor];
EXPECT_EQ(textColor, [cell_ textColor]);
}
// Test mouse events.
TEST_F(HyperlinkButtonCellTest, MouseHover) {
[[NSCursor disappearingItemCursor] push]; // Set a known state.
[cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_EQ([NSCursor pointingHandCursor], [NSCursor currentCursor]);
[cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_EQ([NSCursor disappearingItemCursor], [NSCursor currentCursor]);
[NSCursor pop];
}
// Test mouse events when button is disabled. {
TEST_F(HyperlinkButtonCellTest, MouseHoverWhenDisabled) {
[cell_ setEnabled:NO];
[[NSCursor disappearingItemCursor] push]; // Set a known state.
[cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_EQ([NSCursor disappearingItemCursor], [NSCursor currentCursor]);
[cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_EQ([NSCursor disappearingItemCursor], [NSCursor currentCursor]);
[NSCursor pop];
[NSCursor pop];
}
// Test underline on hover.
TEST_F(HyperlinkButtonCellTest, UnderlineOnHover) {
// Default is for no underline.
EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
[cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
[cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
// Setting behavior to ALWAYS will result in always having an underline.
[cell_ setUnderlineBehavior:hyperlink_button_cell::UnderlineBehavior::ALWAYS];
EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
[cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
[cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
// Setting behavior to ON_HOVER will result in only underlining when the
// mouse is hovering over the link.
[cell_ setUnderlineBehavior:
hyperlink_button_cell::UnderlineBehavior::ON_HOVER];
EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
[cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
[cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
}
TEST_F(HyperlinkButtonCellTest, Copy) {
base::scoped_nsobject<HyperlinkButtonCell> cell1([[HyperlinkButtonCell alloc]
initTextCell:@"Cell"]);
[cell1 setTextColor:[NSColor redColor]];
base::scoped_nsobject<HyperlinkButtonCell> cell2([cell1 copy]);
EXPECT_NSEQ([cell1 textColor], [cell2 textColor]);
[cell1 setTextColor:[NSColor purpleColor]];
[cell2 setTextColor:[NSColor greenColor]];
}
} // namespace
} // namespace ui
// 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 "ui/base/ui_base_export.h"
@class NSColor;
// HyperlinkTextView is an NSTextView subclass for unselectable, linkable text.
// This subclass doesn't show the text caret or IBeamCursor, whereas the base
// class NSTextView displays both with full keyboard accessibility enabled.
UI_BASE_EXPORT
@interface HyperlinkTextView : NSTextView {
@private
BOOL refusesFirstResponder_;
BOOL drawsBackgroundUsingSuperview_;
BOOL isValidLink_;
}
@property(nonatomic, assign) BOOL drawsBackgroundUsingSuperview;
// Set the |message| displayed by the HyperlinkTextView, using |font| and
// |messageColor|.
- (void)setMessage:(NSString*)message
withFont:(NSFont*)font
messageColor:(NSColor*)messageColor;
// Marks a |range| within the given message as a link. Pass nil as the url to
// create a link that can neither be copied nor dragged.
- (void)addLinkRange:(NSRange)range
withURL:(NSString*)url
linkColor:(NSColor*)linkColor;
// This is NO (by default) if the view rejects first responder status.
- (void)setRefusesFirstResponder:(BOOL)refusesFirstResponder;
@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 "ui/base/cocoa/controls/hyperlink_text_view.h"
#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
#include "ui/base/cocoa/nsview_additions.h"
// The baseline shift for text in the NSTextView.
const float kTextBaselineShift = -1.0;
@interface HyperlinkTextView(Private)
// Initialize the NSTextView properties for this subclass.
- (void)configureTextView;
// Change the current IBeamCursor to an arrowCursor.
- (void)fixupCursor;
@end
@implementation HyperlinkTextView
@synthesize drawsBackgroundUsingSuperview = drawsBackgroundUsingSuperview_;
- (id)initWithCoder:(NSCoder*)decoder {
if ((self = [super initWithCoder:decoder]))
[self configureTextView];
return self;
}
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect]))
[self configureTextView];
return self;
}
- (BOOL)acceptsFirstResponder {
return !refusesFirstResponder_;
}
- (void)drawViewBackgroundInRect:(NSRect)rect {
if (drawsBackgroundUsingSuperview_)
[self cr_drawUsingAncestor:[self superview] inRect:rect];
else
[super drawViewBackgroundInRect:rect];
}
// Never draw the insertion point (otherwise, it shows up without any user
// action if full keyboard accessibility is enabled).
- (BOOL)shouldDrawInsertionPoint {
return NO;
}
- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
granularity:(NSSelectionGranularity)granularity {
// Return a range of length 0 to prevent text selection. Note that the start
// of the range (the first argument) is treated as the position of the
// subsequent click so it must not be 0. If it is, links that begin at a
// non-zero position in the text will not function correctly when they are
// clicked in such a way as to look like a possible text selection.
return NSMakeRange(proposedSelRange.location, 0);
}
// Convince NSTextView to not show an I-Beam cursor when the cursor is over the
// text view but not over actual text.
//
// http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
// "NSTextView sets the cursor over itself dynamically, based on considerations
// including the text under the cursor. It does so in -mouseEntered:,
// -mouseMoved:, and -cursorUpdate:, so those would be points to consider
// overriding."
- (void)mouseMoved:(NSEvent*)e {
[super mouseMoved:e];
[self fixupCursor];
}
- (void)mouseEntered:(NSEvent*)e {
[super mouseEntered:e];
[self fixupCursor];
}
- (void)cursorUpdate:(NSEvent*)e {
[super cursorUpdate:e];
[self fixupCursor];
}
- (void)configureTextView {
[self setEditable:NO];
[self setDrawsBackground:NO];
[self setHorizontallyResizable:NO];
[self setVerticallyResizable:NO];
// When text is rendered, linkTextAttributes override anything set via
// addAttributes for text that has NSLinkAttributeName. Set to nil to allow
// custom attributes to take precedence.
[self setLinkTextAttributes:nil];
[self setDisplaysLinkToolTips:NO];
refusesFirstResponder_ = NO;
drawsBackgroundUsingSuperview_ = NO;
isValidLink_ = NO;
}
- (void)fixupCursor {
if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
[[NSCursor arrowCursor] set];
}
// Only allow contextual menus (which allow copying of the link URL) if the link
// is a valid one.
- (NSMenu*)menuForEvent:(NSEvent*)e {
if (isValidLink_)
return [super menuForEvent:e];
return nil;
}
// Only allow dragging of valid links.
- (BOOL)dragSelectionWithEvent:(NSEvent*)event
offset:(NSSize)mouseOffset
slideBack:(BOOL)slideBack {
if (isValidLink_) {
return [super dragSelectionWithEvent:event
offset:mouseOffset
slideBack:slideBack];
}
return NO;
}
- (void)setMessage:(NSString*)message
withFont:(NSFont*)font
messageColor:(NSColor*)messageColor {
// Create an attributes dictionary for the message and link.
NSDictionary* attributes = @{
NSForegroundColorAttributeName : messageColor,
NSCursorAttributeName : [NSCursor arrowCursor],
NSFontAttributeName : font,
NSBaselineOffsetAttributeName : @(kTextBaselineShift)
};
// Create the attributed string for the message.
base::scoped_nsobject<NSAttributedString> attributedMessage(
[[NSMutableAttributedString alloc] initWithString:message
attributes:attributes]);
// Update the text view with the new text.
[[self textStorage] setAttributedString:attributedMessage];
}
- (void)addLinkRange:(NSRange)range
withURL:(NSString*)url
linkColor:(NSColor*)linkColor {
// If a URL is provided, make sure it is a valid one.
if (url) {
DCHECK_GT([url length], 0u);
DCHECK([NSURL URLWithString:url]);
isValidLink_ = YES;
} else {
url = @"";
isValidLink_ = NO;
}
NSDictionary* attributes = @{
NSForegroundColorAttributeName : linkColor,
NSUnderlineStyleAttributeName : @(YES),
NSCursorAttributeName : [NSCursor pointingHandCursor],
NSLinkAttributeName : url,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle)
};
[[self textStorage] addAttributes:attributes range:range];
}
- (void)setRefusesFirstResponder:(BOOL)refusesFirstResponder {
refusesFirstResponder_ = refusesFirstResponder;
}
@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 "ui/base/cocoa/controls/hyperlink_text_view.h"
#include "base/mac/scoped_nsobject.h"
#include "testing/gtest_mac.h"
#import "ui/base/test/cocoa_helper.h"
namespace {
class HyperlinkTextViewTest : public ui::CocoaTest {
public:
HyperlinkTextViewTest() {
NSRect frame = NSMakeRect(0, 0, 50, 50);
base::scoped_nsobject<HyperlinkTextView> view(
[[HyperlinkTextView alloc] initWithFrame:frame]);
view_ = view.get();
[[test_window() contentView] addSubview:view_];
}
NSFont* GetDefaultFont() {
return [NSFont labelFontOfSize:
[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
}
NSDictionary* GetDefaultTextAttributes() {
const float kTextBaselineShift = -1.0;
return @{
NSForegroundColorAttributeName : [NSColor blackColor],
NSCursorAttributeName : [NSCursor arrowCursor],
NSFontAttributeName : GetDefaultFont(),
NSBaselineOffsetAttributeName : @(kTextBaselineShift)
};
}
NSMutableDictionary* GetDefaultLinkAttributes() {
if (!linkAttributes_.get()) {
linkAttributes_.reset(
[[NSMutableDictionary dictionaryWithDictionary:
GetDefaultTextAttributes()] retain]);
[linkAttributes_ addEntriesFromDictionary:@{
NSForegroundColorAttributeName : [NSColor blueColor],
NSUnderlineStyleAttributeName : @(YES),
NSCursorAttributeName : [NSCursor pointingHandCursor],
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle),
NSLinkAttributeName : @""
}];
}
return [NSMutableDictionary dictionaryWithDictionary:linkAttributes_];
}
HyperlinkTextView* view_;
private:
base::scoped_nsobject<NSMutableDictionary> linkAttributes_;
};
TEST_VIEW(HyperlinkTextViewTest, view_);
TEST_F(HyperlinkTextViewTest, TestSelectionRange) {
NSRange actualRange;
// The length of the selection range should be 0.
actualRange = [view_ selectionRangeForProposedRange:NSMakeRange(0, 20)
granularity:NSSelectByCharacter];
EXPECT_TRUE(NSEqualRanges(NSMakeRange(0, 0), actualRange));
// While the location should always match the location of the proposed range.
actualRange = [view_ selectionRangeForProposedRange:NSMakeRange(50, 100)
granularity:NSSelectByCharacter];
EXPECT_TRUE(NSEqualRanges(NSMakeRange(50, 0), actualRange));
}
TEST_F(HyperlinkTextViewTest, TestViewConfiguration) {
EXPECT_FALSE([view_ isEditable]);
EXPECT_FALSE([view_ drawsBackground]);
EXPECT_FALSE([view_ isHorizontallyResizable]);
EXPECT_FALSE([view_ isVerticallyResizable]);
}
TEST_F(HyperlinkTextViewTest, TestSetMessage) {
// Verifies setMessage sets text and attributes properly.
NSString* message = @"Test message";
[view_ setMessage:message
withFont:GetDefaultFont()
messageColor:[NSColor blackColor]];
EXPECT_NSEQ(@"Test message", [[view_ textStorage] string]);
NSDictionary* attributes;
NSRange rangeLimit = NSMakeRange(0, [message length]);
NSRange range;
attributes = [[view_ textStorage] attributesAtIndex:0
longestEffectiveRange:&range
inRange:rangeLimit];
EXPECT_EQ(0U, range.location);
EXPECT_EQ([message length], range.length);
EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
}
TEST_F(HyperlinkTextViewTest, TestAddLinkRange) {
NSString* message = @"One Two Three Four";
[view_ setMessage:message
withFont:GetDefaultFont()
messageColor:[NSColor blackColor]];
NSColor* blue = [NSColor blueColor];
[view_ addLinkRange:NSMakeRange(4,3) withURL:@"http://2" linkColor:blue];
[view_ addLinkRange:NSMakeRange(14,4) withURL:@"http://4" linkColor:blue];
NSDictionary* attributes;
NSRange rangeLimit = NSMakeRange(0, [message length]);
NSRange range;
attributes = [[view_ textStorage] attributesAtIndex:0
longestEffectiveRange:&range
inRange:rangeLimit];
EXPECT_EQ(0U, range.location);
EXPECT_EQ(4U, range.length);
EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
NSMutableDictionary* linkAttributes = GetDefaultLinkAttributes();
[linkAttributes setObject:@"http://2" forKey:NSLinkAttributeName];
attributes = [[view_ textStorage] attributesAtIndex:4
longestEffectiveRange:&range
inRange:rangeLimit];
EXPECT_EQ(4U, range.location);
EXPECT_EQ(3U, range.length);
EXPECT_NSEQ(linkAttributes, attributes);
attributes = [[view_ textStorage] attributesAtIndex:7
longestEffectiveRange:&range
inRange:rangeLimit];
EXPECT_EQ(7U, range.location);
EXPECT_EQ(7U, range.length);
EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
[linkAttributes setObject:@"http://4" forKey:NSLinkAttributeName];
attributes = [[view_ textStorage] attributesAtIndex:14
longestEffectiveRange:&range
inRange:rangeLimit];
EXPECT_EQ(14U, range.location);
EXPECT_EQ(4U, range.length);
EXPECT_NSEQ(linkAttributes, attributes);
}
TEST_F(HyperlinkTextViewTest, FirstResponderBehavior) {
// By default, accept.
EXPECT_TRUE([view_ acceptsFirstResponder]);
[view_ setRefusesFirstResponder:YES];
EXPECT_FALSE([view_ acceptsFirstResponder]);
}
} // namespace
// Copyright 2017 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 UI_BASE_COCOA_CONTROLS_IMAGEVIEW_UTILS_H_
#define UI_BASE_COCOA_CONTROLS_IMAGEVIEW_UTILS_H_
#include "ui/base/ui_base_export.h"
#include <Cocoa/Cocoa.h>
UI_BASE_EXPORT
@interface ImageViewUtils : NSObject
// These methods are a polyfill for convenience constructors that exist on
// NSImageView in macOS 10.12+.
// TODO(ellyjones): once we target only 10.12+, delete these and migrate
// callers over to NSImageView directly.
+ (NSImageView*)imageViewWithImage:(NSImage*)image;
@end
#endif // UI_BASE_COCOA_CONTROLS_IMAGEVIEW_UTILS_H_
// Copyright 2017 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 "ui/base/cocoa/controls/imageview_utils.h"
@implementation ImageViewUtils
+ (NSImageView*)imageViewWithImage:(NSImage*)image {
NSImageView* imageView = [[[NSImageView alloc] init] autorelease];
[imageView setImage:image];
return imageView;
}
@end
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