Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: chrome/browser/cocoa/disclosure_view_controller.mm

Issue 2673006: AutoFill Profiles dialog implemented according to new mocks on Mac (Closed)
Patch Set: Revisions based on review comments. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/cocoa/disclosure_view_controller.h"
6 #include "base/logging.h"
7
8 namespace {
9 const NSInteger kClosedBoxHeight = 20;
10 const CGFloat kDisclosureAnimationDurationSeconds = .2;
11 NSString* const kKVODisclosedKey = @"disclosed";
12 }
13
14 // This class externalizes the state of the disclosure control. When the
15 // disclosure control is pressed it changes the state of this object. In turn
16 // the KVO machinery detects the change to |disclosed| and signals the
17 // |observeValueForKeyPath| call in the |DisclosureViewController|.
18 @interface DisclosureViewState : NSObject {
19 @private
20 NSCellStateValue disclosed_;
21 }
22 @property (nonatomic) NSCellStateValue disclosed;
23 @end
24
25 @implementation DisclosureViewState
26 @synthesize disclosed = disclosed_;
27 @end
28
29 @interface DisclosureViewController(PrivateMethods)
30
31 - (void)initFrameSize:(NSCellStateValue)state;
32 - (NSRect)openStateFrameSize:(NSRect)startFrame;
33 - (NSRect)closedStateFrameSize:(NSRect)startFrame;
34 - (void)startAnimations:(NSView*)view
35 start:(NSRect)startFrame
36 end:(NSRect)endFrame;
37 - (void)discloseDetails:(NSCellStateValue)state;
38 - (void)setContentViewVisibility;
39 - (void)observeValueForKeyPath:(NSString*)keyPath
40 ofObject:(id)object
41 change:(NSDictionary*)change
42 context:(void*)context;
43
44 @end
45
46 @implementation DisclosureViewController
47
48 @synthesize disclosureState = disclosureState_;
49
50 - (void)awakeFromNib {
51 // Create the disclosure state.
52 [self setDisclosureState:[[[DisclosureViewState alloc] init] autorelease]];
53
54 // Set up the initial disclosure state before we install the observer.
55 // We don't want our animations firing before we're done initializing.
56 [disclosureState_ setValue:[NSNumber numberWithInt:initialDisclosureState_]
57 forKey:kKVODisclosedKey];
58
59 // Pick up "open" height from the initial state of the view in the nib.
60 openHeight_ = [[self view] frame].size.height;
61
62 // Set frame size according to initial disclosure state.
63 [self initFrameSize:initialDisclosureState_];
64
65 // Set content visibility according to initial disclosure state.
66 [self setContentViewVisibility];
67
68 // Setup observers so that when disclosure state changes we resize frame
69 // accordingly.
70 [disclosureState_ addObserver:self forKeyPath:kKVODisclosedKey
71 options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
72 context:nil];
73 }
74
75 - (id)initWithNibName:(NSString *)nibNameOrNil
76 bundle:(NSBundle *)nibBundleOrNil
77 disclosure:(NSCellStateValue)disclosureState {
78 if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
79 initialDisclosureState_ = disclosureState;
80 }
81 return self;
82 }
83
84 - (void)dealloc {
85 [disclosureState_ removeObserver:self forKeyPath:kKVODisclosedKey];
86 [animation_ stopAnimation];
87 [disclosureState_ release];
88 [super dealloc];
89 }
90
91 @end
92
93 @implementation DisclosureViewController(PrivateMethods)
94
95 // Initializes the view's frame geometry based on the input |state|.
96 // If the |state| is NSOnState then the frame size corresponds to "open".
97 // If the |state| is NSOffState then the frame size corresponds to "closed".
98 // The |origin.x| and |size.width| remain unchanged, but the |origin.y| and
99 // |size.height| may vary.
100 - (void)initFrameSize:(NSCellStateValue)state {
101 if (state == NSOnState) {
102 [[self view] setFrame:[self openStateFrameSize:[[self view] frame]]];
103 }
104 else if (state == NSOffState) {
105 [[self view] setFrame:[self closedStateFrameSize:[[self view] frame]]];
106 }
107 else {
108 NOTREACHED();
109 }
110 }
111
112 // Computes the frame geometry during the "open" state of the disclosure view.
113 - (NSRect)openStateFrameSize:(NSRect)startFrame {
114 return NSMakeRect(startFrame.origin.x,
115 startFrame.size.height - openHeight_ +
116 startFrame.origin.y,
117 startFrame.size.width,
118 openHeight_);
119 }
120
121 // Computes the frame geometry during the "closed" state of the disclosure view.
122 - (NSRect)closedStateFrameSize:(NSRect)startFrame {
123 return NSMakeRect(startFrame.origin.x,
124 startFrame.size.height - kClosedBoxHeight +
125 startFrame.origin.y,
126 startFrame.size.width,
127 kClosedBoxHeight);
128 }
129
130 // Animates the opening or closing of the disclosure view. The |startFrame|
131 // specifies the frame geometry at the beginning of the animation and the
132 // |endFrame| specifies the geometry at the end of the animation. The input
133 // |view| is view managed by this controller.
134 - (void)startAnimations:(NSView*)view
135 start:(NSRect)startFrame
136 end:(NSRect)endFrame
137 {
138 // Setup dictionary describing animation.
139 // Create the attributes dictionary for the first view.
140 NSMutableDictionary* dictionary;
141 dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
142 // Specify which view to modify.
143 view, NSViewAnimationTargetKey,
144 // Specify the starting position of the view.
145 [NSValue valueWithRect:startFrame], NSViewAnimationStartFrameKey,
146 // Change the ending position of the view.
147 [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey,
148 nil];
149
150 // Stop any existing animation.
151 [animation_ stopAnimation];
152
153 // Create the view animation object.
154 animation_.reset([[NSViewAnimation alloc] initWithViewAnimations:
155 [NSArray arrayWithObject:dictionary]]);
156
157 // Set some additional attributes for the animation.
158 [animation_ setDuration:kDisclosureAnimationDurationSeconds];
159 [animation_ setAnimationCurve:NSAnimationEaseIn];
160
161 // Set self as delegate so we can toggle visibility at end of animation.
162 [animation_ setDelegate:self];
163
164 // Run the animation.
165 [animation_ startAnimation];
166 }
167
168 // NSAnimationDelegate method. Before starting the animation we show the
169 // |detailedView_|.
170 - (BOOL)animationShouldStart:(NSAnimation*)animation {
171 [detailedView_ setHidden:NO];
172 return YES;
173 }
174
175 // NSAnimationDelegate method. If animation stops before ending we release
176 // our animation object.
177 - (void)animationDidStop:(NSAnimation*)animation {
178 animation_.reset();
179 }
180
181 // NSAnimationDelegate method. Once the disclosure animation is over we set
182 // content view visibility to match disclosure state.
183 // |animation_| reference is relinquished at end of animation.
184 - (void)animationDidEnd:(NSAnimation*)animation {
185 [self setContentViewVisibility];
186 animation_.reset();
187 }
188
189 // This method is invoked when the disclosure state changes. It computes
190 // the appropriate view frame geometry and then initiates the animation to
191 // change that geometry.
192 - (void)discloseDetails:(NSCellStateValue)state {
193 NSRect startFrame = [[self view] frame];
194 NSRect endFrame = startFrame;
195
196 if (state == NSOnState) {
197 endFrame = [self openStateFrameSize:startFrame];
198 } else if (state == NSOffState) {
199 endFrame = [self closedStateFrameSize:startFrame];
200 } else {
201 NOTREACHED();
202 return;
203 }
204
205 [self startAnimations:[self view] start:startFrame end:endFrame];
206 }
207
208 // Sets the "hidden" state of the content view according to the current
209 // disclosure state. We do this so that the view hierarchy knows to remove
210 // undisclosed content from the first responder chain.
211 - (void)setContentViewVisibility {
212 NSCellStateValue disclosed = [[disclosureState_ valueForKey:kKVODisclosedKey]
213 intValue];
214
215 if (disclosed == NSOnState) {
216 [detailedView_ setHidden:NO];
217 } else if (disclosed == NSOffState) {
218 [detailedView_ setHidden:YES];
219 } else {
220 NOTREACHED();
221 return;
222 }
223 }
224
225 // The |DisclosureViewController| is an observer of an instance of a
226 // |DisclosureViewState| object. This object lives within the controller's
227 // nib file. When the KVO machinery detects a change to the state
228 // it triggers this call and we initiate the change in frame geometry of the
229 // view.
230 - (void)observeValueForKeyPath:(NSString*)keyPath
231 ofObject:(id)object
232 change:(NSDictionary*)change
233 context:(void*)context {
234 if ([keyPath isEqualToString:kKVODisclosedKey]) {
235 NSCellStateValue newValue =
236 [[change objectForKey:NSKeyValueChangeNewKey] intValue];
237 NSCellStateValue oldValue =
238 [[change objectForKey:NSKeyValueChangeOldKey] intValue];
239
240 if (newValue != oldValue) {
241 [self discloseDetails:newValue];
242 }
243 }
244 }
245
246 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/disclosure_view_controller.h ('k') | chrome/browser/cocoa/disclosure_view_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698