Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #import "chrome/browser/ui/cocoa/autofill/autofill_loading_shield_controller.h" | |
| 6 | |
| 7 #include <cmath> | |
| 8 | |
| 9 #include "base/strings/sys_string_conversions.h" | |
|
groby-ooo-7-16
2013/11/15 23:03:38
base/mac/scoped_nsobject.h
Ilya Sherman
2013/11/16 00:31:13
Already included in the header, and this #include
| |
| 10 #include "chrome/browser/ui/autofill/loading_animation.h" | |
| 11 #include "ui/base/resource/resource_bundle.h" | |
| 12 #include "ui/gfx/animation/animation_delegate.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 // Horizontal spacing between the animated dots. | |
| 17 const CGFloat kDotsHorizontalPadding = 3; | |
| 18 | |
| 19 } // namespace | |
| 20 | |
| 21 | |
| 22 // A C++ bridge class for driving the animation. | |
| 23 class AutofillLoadingAnimationBridge : public gfx::AnimationDelegate { | |
| 24 public: | |
| 25 AutofillLoadingAnimationBridge(AutofillLoadingShieldController* controller) | |
| 26 : animation_(this), | |
| 27 controller_(controller) {} | |
| 28 virtual ~AutofillLoadingAnimationBridge() {} | |
| 29 | |
| 30 // gfx::AnimationDelegate implementation. | |
| 31 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE { | |
| 32 DCHECK_EQ(animation, &animation_); | |
| 33 [controller_ performLayout]; | |
|
groby-ooo-7-16
2013/11/15 23:03:38
performLayoutWithAnimation:
You always need the a
Ilya Sherman
2013/11/16 00:31:13
Done.
| |
| 34 } | |
| 35 | |
| 36 autofill::LoadingAnimation* animation() { return &animation_; } | |
| 37 | |
| 38 private: | |
| 39 autofill::LoadingAnimation animation_; | |
| 40 AutofillLoadingShieldController* const controller_; | |
|
groby-ooo-7-16
2013/11/15 23:03:38
Probably worth pointing out it's not owned.
Ilya Sherman
2013/11/16 00:31:13
Done.
| |
| 41 }; | |
| 42 | |
| 43 | |
| 44 // A simple opaque view for drawing the background of the loading shield. | |
| 45 @interface AutofillOpaqueView : NSView | |
|
groby-ooo-7-16
2013/11/15 23:03:38
Kill this, use NSBox.
Needs a few items set:
[box
Ilya Sherman
2013/11/16 00:31:13
Done.
| |
| 46 @end | |
| 47 | |
| 48 @implementation AutofillOpaqueView | |
| 49 | |
| 50 - (BOOL)isOpaque { | |
| 51 return YES; | |
| 52 } | |
| 53 | |
| 54 - (void)drawRect:(NSRect)dirtyRect { | |
| 55 [[[self window] backgroundColor] setFill]; | |
| 56 [NSBezierPath fillRect:[self bounds]]; | |
| 57 } | |
| 58 | |
| 59 @end | |
| 60 | |
| 61 | |
| 62 @implementation AutofillLoadingShieldController | |
| 63 | |
| 64 - (id)init { | |
| 65 if (self = [super initWithNibName:nil bundle:nil]) { | |
| 66 animationDriver_.reset(new AutofillLoadingAnimationBridge(self)); | |
| 67 | |
| 68 base::scoped_nsobject<NSView> view( | |
| 69 [[AutofillOpaqueView alloc] initWithFrame:NSZeroRect]); | |
| 70 | |
| 71 message_.reset([[NSTextField alloc] initWithFrame:NSZeroRect]); | |
| 72 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 73 NSFont* font = | |
| 74 rb.GetFont(ui::ResourceBundle::BaseFont).DeriveFont(15).GetNativeFont(); | |
| 75 [message_ setFont:font]; | |
| 76 [message_ setEditable:NO]; | |
| 77 [message_ setBordered:NO]; | |
| 78 [message_ setDrawsBackground:NO]; | |
| 79 [view addSubview:message_]; | |
| 80 | |
| 81 dots_.reset([[NSArray alloc] initWithArray:@[ | |
| 82 [[NSTextField alloc] initWithFrame:NSZeroRect], | |
| 83 [[NSTextField alloc] initWithFrame:NSZeroRect], | |
| 84 [[NSTextField alloc] initWithFrame:NSZeroRect] ]]); | |
| 85 for (NSTextField* dot in dots_.get()) { | |
| 86 [dot setFont:font]; | |
| 87 [dot setEditable:NO]; | |
| 88 [dot setBordered:NO]; | |
| 89 [dot setDrawsBackground:NO]; | |
| 90 [dot setStringValue:@"."]; | |
| 91 [dot sizeToFit]; | |
| 92 [view addSubview:dot]; | |
| 93 } | |
| 94 | |
| 95 [self setView:view]; | |
| 96 } | |
| 97 return self; | |
| 98 } | |
| 99 | |
| 100 - (NSString*)message { | |
| 101 return [message_ stringValue]; | |
| 102 } | |
| 103 | |
| 104 - (void)setMessage:(NSString*)message { | |
| 105 [message_ setStringValue:message]; | |
| 106 [message_ sizeToFit]; | |
| 107 | |
| 108 if ([message length] > 0) | |
| 109 animationDriver_->animation()->Start(); | |
| 110 else | |
| 111 animationDriver_->animation()->Reset(); | |
|
groby-ooo-7-16
2013/11/15 23:03:38
You probably want a performLayout here. In general
Ilya Sherman
2013/11/16 00:31:13
This hides the shield, so there's not much reason
| |
| 112 } | |
| 113 | |
| 114 - (NSSize)preferredSize { | |
| 115 NOTREACHED(); // Only implemented as part of AutofillLayout protocol. | |
| 116 return NSZeroSize; | |
| 117 } | |
| 118 | |
| 119 - (void)performLayout { | |
| 120 if ([[self view] isHidden]) | |
| 121 return; | |
| 122 | |
| 123 NSRect bounds = [[self view] bounds]; | |
| 124 NSRect messageFrame = [message_ frame]; | |
| 125 | |
| 126 CGFloat width = NSWidth(messageFrame); | |
| 127 CGFloat height = NSHeight(messageFrame); | |
| 128 for (NSView* dot in dots_.get()) { | |
| 129 width += NSWidth([dot frame]) + kDotsHorizontalPadding; | |
| 130 height = std::max(height, NSHeight([dot frame])); | |
| 131 } | |
|
groby-ooo-7-16
2013/11/15 23:03:38
We should be able to compute this up front, in set
Ilya Sherman
2013/11/16 00:31:13
performLayout is now only ever called by the windo
| |
| 132 | |
| 133 // The message + dots should be centered in the view. | |
| 134 messageFrame.origin.x = std::ceil((NSWidth(bounds) - width) / 2.0); | |
| 135 messageFrame.origin.y = std::ceil((NSHeight(bounds) - height) / 2.0); | |
| 136 [message_ setFrame:messageFrame]; | |
|
groby-ooo-7-16
2013/11/15 23:03:38
[message setFrameOrigin:...]
Ilya Sherman
2013/11/16 00:31:13
Done.
| |
| 137 for (size_t i = 0; i < [dots_ count]; ++i) { | |
|
groby-ooo-7-16
2013/11/15 23:03:38
Avoid manual iteration over NSArray. You need the
Ilya Sherman
2013/11/16 00:31:13
Done.
| |
| 138 NSView* dot = [dots_ objectAtIndex:i]; | |
| 139 NSView* previousView = i == 0 ? message_ : [dots_ objectAtIndex:i - 1]; | |
| 140 | |
| 141 NSPoint dotFrameOrigin = NSMakePoint( | |
| 142 NSMaxX([previousView frame]) + kDotsHorizontalPadding, | |
| 143 messageFrame.origin.y - | |
| 144 animationDriver_->animation()->GetCurrentValueForDot(i)); | |
| 145 [dot setFrameOrigin:dotFrameOrigin]; | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 @end | |
| OLD | NEW |