| Index: chrome/browser/ui/cocoa/location_bar/secure_verbose_bubble_decoration.mm
|
| diff --git a/chrome/browser/ui/cocoa/location_bar/secure_verbose_bubble_decoration.mm b/chrome/browser/ui/cocoa/location_bar/secure_verbose_bubble_decoration.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c0aa23e95c89c4784a532773bf68a4bbb564da0a
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/cocoa/location_bar/secure_verbose_bubble_decoration.mm
|
| @@ -0,0 +1,266 @@
|
| +// 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/location_bar/secure_verbose_bubble_decoration.h"
|
| +
|
| +#import "base/logging.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
|
| +#import "chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h"
|
| +#import "chrome/browser/ui/cocoa/themed_window.h"
|
| +#include "grit/theme_resources.h"
|
| +#include "skia/ext/skia_utils_mac.h"
|
| +#import "ui/base/cocoa/nsview_additions.h"
|
| +#include "ui/base/material_design/material_design_controller.h"
|
| +#include "ui/gfx/color_palette.h"
|
| +#include "ui/gfx/font_list.h"
|
| +#include "ui/gfx/text_elider.h"
|
| +
|
| +namespace {
|
| +
|
| +// This is used to increase the right margin of this decoration.
|
| +const CGFloat kRightSideMargin = 1.0;
|
| +
|
| +// TODO(shess): In general, decorations that don't fit in the
|
| +// available space are omitted. This one never goes to omitted, it
|
| +// sticks at 150px, which AFAICT follows the Windows code. Since the
|
| +// Layout() code doesn't take this into account, it's possible the
|
| +// control could end up with display artifacts, though things still
|
| +// work (and don't crash).
|
| +// http://crbug.com/49822
|
| +
|
| +// Minimum acceptable width for the ev bubble.
|
| +const CGFloat kMinElidedBubbleWidth = 150.0;
|
| +
|
| +// Maximum amount of available space to make the bubble, subject to
|
| +// |kMinElidedBubbleWidth|.
|
| +const float kMaxBubbleFraction = 0.5;
|
| +
|
| +// The info-bubble point should look like it points to the bottom of the lock
|
| +// icon. Determined with Pixie.app.
|
| +const CGFloat kPageInfoBubblePointYOffset = 6.0;
|
| +
|
| +// Duration of animation, 0.5 seconds.
|
| +const NSTimeInterval kAnimationDuration = 0.5;
|
| +
|
| +// Interval of the animation timer, 60Hz.
|
| +const NSTimeInterval kAnimationInterval = 1.0 / 60.0;
|
| +
|
| +// TODO(shess): This is ugly, find a better way. Using it right now
|
| +// so that I can crib from gtk and still be able to see that I'm using
|
| +// the same values easily.
|
| +NSColor* ColorWithRGBBytes(int rr, int gg, int bb) {
|
| + DCHECK_LE(rr, 255);
|
| + DCHECK_LE(bb, 255);
|
| + DCHECK_LE(gg, 255);
|
| + return [NSColor colorWithCalibratedRed:static_cast<float>(rr) / 255.0
|
| + green:static_cast<float>(gg) / 255.0
|
| + blue:static_cast<float>(bb) / 255.0
|
| + alpha:1.0];
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +@interface SecureVerboseAnimation : NSObject {
|
| + @private
|
| + SecureVerboseBubbleDecoration* owner_; // Weak, owns this.
|
| + double progress_; // Counter, [0..1], with aninmation progress.
|
| + NSTimer* timer_; // Animation timer. Owns this, owned by the run loop.
|
| +}
|
| +
|
| +// [0..1], the current progress of the animation. -animationState will return
|
| +// |kNoAnimation| when progress is <= 0 or >= 1. Useful when state is
|
| +// |kOpening| or |kClosing| as a multiplier for displaying width. Don't use
|
| +// to track state transitions, use -animationState instead.
|
| +@property(readonly, nonatomic) double progress;
|
| +
|
| +// Designated initializer. |owner| must not be nil. Animation timer will start
|
| +// as soon as the object is created.
|
| +- (id)initWithOwner:(SecureVerboseBubbleDecoration*)owner;
|
| +
|
| +// Call when |owner| is going away or the animation needs to be stopped.
|
| +// Ensures that any dangling references are cleared. Can be called multiple
|
| +// times.
|
| +- (void)stopAnimation;
|
| +
|
| +- (BOOL)isRunning;
|
| +
|
| +@end
|
| +
|
| +@implementation SecureVerboseAnimation
|
| +
|
| +@synthesize progress = progress_;
|
| +
|
| +- (id)initWithOwner:(SecureVerboseBubbleDecoration*)owner {
|
| + self = [super init];
|
| + if (self) {
|
| + owner_ = owner;
|
| + timer_ = [NSTimer scheduledTimerWithTimeInterval:kAnimationInterval
|
| + target:self
|
| + selector:@selector(timerFired:)
|
| + userInfo:nil
|
| + repeats:YES];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)dealloc {
|
| + DCHECK(!timer_);
|
| + [super dealloc];
|
| +}
|
| +
|
| +// Clear weak references and stop the timer.
|
| +- (void)stopAnimation {
|
| + owner_ = nil;
|
| + [timer_ invalidate];
|
| + timer_ = nil;
|
| +}
|
| +
|
| +- (BOOL)isRunning {
|
| + return timer_ != nil;
|
| +}
|
| +
|
| +- (void)timerFired:(NSTimer*)timer {
|
| + // Increment animation progress, normalized to [0..1].
|
| + progress_ += kAnimationInterval / kAnimationDuration;
|
| + progress_ = std::min(progress_, 1.0);
|
| + owner_->OnAnimationProgressed();
|
| + // Stop timer if it has reached the end of its life.
|
| + if (progress_ >= 1.0)
|
| + [self stopAnimation];
|
| +}
|
| +
|
| +@end
|
| +
|
| +SecureVerboseBubbleDecoration::SecureVerboseBubbleDecoration(
|
| + LocationIconDecoration* location_icon,
|
| + LocationBarViewMac* owner)
|
| + : location_icon_(location_icon), owner_(owner) {
|
| + if (ui::MaterialDesignController::IsModeMaterial()) {
|
| + // On Retina the text label is 1px above the Omnibox textfield's text
|
| + // baseline. If the Omnibox textfield also drew the label the baselines
|
| + // would align.
|
| + SetRetinaBaselineOffset(0.5);
|
| + } else {
|
| + // Color tuples stolen from location_bar_view_gtk.cc.
|
| + SetTextColor(ColorWithRGBBytes(0x07, 0x95, 0x00));
|
| + }
|
| +}
|
| +
|
| +SecureVerboseBubbleDecoration::~SecureVerboseBubbleDecoration() {}
|
| +
|
| +NSColor* SecureVerboseBubbleDecoration::GetBackgroundBorderColor() {
|
| + if (label_color_)
|
| + return label_color_.get();
|
| +
|
| + return skia::SkColorToSRGBNSColor(gfx::kGoogleGreen700);
|
| +}
|
| +
|
| +void SecureVerboseBubbleDecoration::SetFullLabel(NSString* label) {
|
| + full_label_.reset([label retain]);
|
| + SetLabel(full_label_);
|
| +}
|
| +
|
| +void SecureVerboseBubbleDecoration::SetLabelColor(NSColor* color) {
|
| + label_color_.reset([color retain]);
|
| +}
|
| +
|
| +void SecureVerboseBubbleDecoration::OnAnimationProgressed() {
|
| + owner_->Layout();
|
| +}
|
| +
|
| +void SecureVerboseBubbleDecoration::StartAnimation() {
|
| + animation_.reset([[SecureVerboseAnimation alloc] initWithOwner:this]);
|
| +}
|
| +
|
| +void SecureVerboseBubbleDecoration::DrawWithBackgroundInFrame(
|
| + NSRect background_frame,
|
| + NSRect frame,
|
| + NSView* control_view) {
|
| + if (!ui::MaterialDesignController::IsModeMaterial()) {
|
| + BubbleDecoration::DrawWithBackgroundInFrame(background_frame, frame,
|
| + control_view);
|
| + return;
|
| + }
|
| +
|
| + NSRect rect = NSInsetRect(background_frame, 0, 3);
|
| + rect.size.width -= kRightSideMargin;
|
| +
|
| + CGFloat line_width = [control_view cr_lineWidth];
|
| + bool in_dark_mode = [[control_view window] inIncognitoModeWithSystemTheme];
|
| + // Only adjust the path rect by 1/2 the line width if it's going to be
|
| + // stroked (so that the stroke lines fall along pixel lines).
|
| + if (!in_dark_mode) {
|
| + rect = NSInsetRect(rect, line_width / 2., line_width / 2.);
|
| + }
|
| +
|
| + DrawInFrame(frame, control_view);
|
| +}
|
| +
|
| +NSPoint SecureVerboseBubbleDecoration::GetBubblePointInFrame(NSRect frame) {
|
| + NSRect image_rect = GetImageRectInFrame(frame);
|
| + return NSMakePoint(NSMidX(image_rect),
|
| + NSMaxY(image_rect) - kPageInfoBubblePointYOffset);
|
| +}
|
| +
|
| +CGFloat SecureVerboseBubbleDecoration::GetWidthForSpace(CGFloat width) {
|
| + CGFloat progress = (!animation_.get() || ![animation_ isRunning])
|
| + ? 1.0
|
| + : [animation_ progress];
|
| +
|
| + // Limit with to not take up too much of the available width, but
|
| + // also don't let it shrink too much.
|
| + width = std::max(width * kMaxBubbleFraction, kMinElidedBubbleWidth);
|
| +
|
| + // Use the full label if it fits.
|
| + NSImage* image = GetImage();
|
| + const CGFloat all_width = GetWidthForImageAndLabel(image, full_label_);
|
| + if (all_width <= width) {
|
| + SetLabel(full_label_);
|
| + return all_width * progress;
|
| + }
|
| +
|
| + // Width left for laying out the label.
|
| + const CGFloat width_left = width - GetWidthForImageAndLabel(image, @"");
|
| +
|
| + // Middle-elide the label to fit |width_left|. This leaves the
|
| + // prefix and the trailing country code in place.
|
| + NSString* elided_label = base::SysUTF16ToNSString(gfx::ElideText(
|
| + base::SysNSStringToUTF16(full_label_),
|
| + gfx::FontList(gfx::Font(GetFont())), width_left, gfx::ELIDE_MIDDLE));
|
| +
|
| + // Use the elided label.
|
| + SetLabel(elided_label);
|
| + return GetWidthForImageAndLabel(image, elided_label) * progress;
|
| +}
|
| +
|
| +// Pass mouse operations through to location icon.
|
| +bool SecureVerboseBubbleDecoration::IsDraggable() {
|
| + return location_icon_->IsDraggable();
|
| +}
|
| +
|
| +NSPasteboard* SecureVerboseBubbleDecoration::GetDragPasteboard() {
|
| + return location_icon_->GetDragPasteboard();
|
| +}
|
| +
|
| +NSImage* SecureVerboseBubbleDecoration::GetDragImage() {
|
| + return location_icon_->GetDragImage();
|
| +}
|
| +
|
| +NSRect SecureVerboseBubbleDecoration::GetDragImageFrame(NSRect frame) {
|
| + return GetImageRectInFrame(frame);
|
| +}
|
| +
|
| +bool SecureVerboseBubbleDecoration::OnMousePressed(NSRect frame,
|
| + NSPoint location) {
|
| + return location_icon_->OnMousePressed(frame, location);
|
| +}
|
| +
|
| +bool SecureVerboseBubbleDecoration::AcceptsMousePress() {
|
| + return true;
|
| +}
|
| +
|
| +ui::NinePartImageIds SecureVerboseBubbleDecoration::GetBubbleImageIds() {
|
| + return IMAGE_GRID(IDR_OMNIBOX_EV_BUBBLE);
|
| +}
|
|
|