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

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

Issue 3159001: Mac tabpose: Add favicons and titles. (Closed)
Patch Set: comments Created 10 years, 4 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
« no previous file with comments | « chrome/browser/cocoa/tabpose_window.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/cocoa/tabpose_window.h" 5 #import "chrome/browser/cocoa/tabpose_window.h"
6 6
7 #import <QuartzCore/QuartzCore.h> 7 #import <QuartzCore/QuartzCore.h>
8 8
9 #include "app/resource_bundle.h"
10 #include "base/mac_util.h"
11 #include "base/sys_string_conversions.h"
9 #import "chrome/browser/cocoa/browser_window_controller.h" 12 #import "chrome/browser/cocoa/browser_window_controller.h"
10 #import "chrome/browser/cocoa/tab_strip_controller.h" 13 #import "chrome/browser/cocoa/tab_strip_controller.h"
14 #include "chrome/browser/tab_contents/tab_contents.h"
15 #include "grit/app_resources.h"
16 #include "skia/ext/skia_utils_mac.h"
11 17
12 const int kTopGradientHeight = 15; 18 const int kTopGradientHeight = 15;
13 19
14 NSString* const kAnimationIdKey = @"AnimationId"; 20 NSString* const kAnimationIdKey = @"AnimationId";
15 NSString* const kAnimationIdFadeIn = @"FadeIn"; 21 NSString* const kAnimationIdFadeIn = @"FadeIn";
16 NSString* const kAnimationIdFadeOut = @"FadeOut"; 22 NSString* const kAnimationIdFadeOut = @"FadeOut";
17 23
18 const CGFloat kDefaultAnimationDuration = 0.25; // In seconds. 24 const CGFloat kDefaultAnimationDuration = 0.25; // In seconds.
19 const CGFloat kSlomoFactor = 4; 25 const CGFloat kSlomoFactor = 4;
20 26
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 // title, favicon, thumbnail image, and pre- and postanimation rects. 108 // title, favicon, thumbnail image, and pre- and postanimation rects.
103 // TODO(thakis): Right now, it only consists of a thumb rect. 109 // TODO(thakis): Right now, it only consists of a thumb rect.
104 class Tile { 110 class Tile {
105 public: 111 public:
106 // Returns the rectangle this thumbnail is at at the beginning of the zoom-in 112 // Returns the rectangle this thumbnail is at at the beginning of the zoom-in
107 // animation. |tile| is the rectangle that's covering the whole tab area when 113 // animation. |tile| is the rectangle that's covering the whole tab area when
108 // the animation starts. 114 // the animation starts.
109 NSRect GetStartRectRelativeTo(const Tile& tile) const; 115 NSRect GetStartRectRelativeTo(const Tile& tile) const;
110 NSRect thumb_rect() const { return thumb_rect_; } 116 NSRect thumb_rect() const { return thumb_rect_; }
111 117
118 NSRect favicon_rect() const { return favicon_rect_; }
119 SkBitmap favicon() const;
120
121 // This changes |title_rect| and |favicon_rect| such that the favicon is on
122 // the font's baseline and that the minimum distance between thumb rect and
123 // favicon and title rects doesn't change.
124 // The view code
125 // 1. queries desired font size by calling |title_font_size()|
126 // 2. loads that font
127 // 3. calls |set_font_metrics()| which updates the title rect
128 // 4. receives the title rect and puts the title on it with the font from 2.
129 void set_font_metrics(CGFloat ascender, CGFloat descender);
130 CGFloat title_font_size() const { return title_font_size_; }
131
132 NSRect title_rect() const { return title_rect_; }
133
134 // Returns an unelided title. The view logic is responsible for eliding.
135 const string16& title() const { return contents_->GetTitle(); }
112 private: 136 private:
113 friend class TileSet; 137 friend class TileSet;
114 138
115 // The thumb rect includes infobars, detached thumbnail bar, web contents, 139 // The thumb rect includes infobars, detached thumbnail bar, web contents,
116 // and devtools. 140 // and devtools.
117 NSRect thumb_rect_; 141 NSRect thumb_rect_;
118 NSRect start_thumb_rect_; 142 NSRect start_thumb_rect_;
143
144 NSRect favicon_rect_;
145
146 CGFloat title_font_size_;
147 NSRect title_rect_;
148
149 TabContents* contents_; // weak
119 }; 150 };
120 151
121 NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const { 152 NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const {
122 NSRect rect = start_thumb_rect_; 153 NSRect rect = start_thumb_rect_;
123 rect.origin.x -= tile.start_thumb_rect_.origin.x; 154 rect.origin.x -= tile.start_thumb_rect_.origin.x;
124 rect.origin.y -= tile.start_thumb_rect_.origin.y; 155 rect.origin.y -= tile.start_thumb_rect_.origin.y;
125 return rect; 156 return rect;
126 } 157 }
127 158
159 SkBitmap Tile::favicon() const {
160 if (contents_->is_app()) {
161 SkBitmap* icon = contents_->GetExtensionAppIcon();
162 if (icon)
163 return *icon;
164 }
165 return contents_->GetFavIcon();
166 }
167
168 // Changes |title_rect| and |favicon_rect| such that the favicon is on the
169 // font's baseline and that the minimum distance between thumb rect and
170 // favicon and title rects doesn't change.
171 void Tile::set_font_metrics(CGFloat ascender, CGFloat descender) {
172 title_rect_.origin.y -= ascender + descender - NSHeight(title_rect_);
173 title_rect_.size.height = ascender + descender;
174
175 if (NSHeight(favicon_rect_) < ascender) {
176 // Move favicon down.
177 favicon_rect_.origin.y = title_rect_.origin.y + descender;
178 } else {
179 // Move title down.
180 title_rect_.origin.y = favicon_rect_.origin.y - descender;
181 }
182 }
183
128 // A tileset is responsible for owning and laying out all |Tile|s shown in a 184 // A tileset is responsible for owning and laying out all |Tile|s shown in a
129 // tabpose window. 185 // tabpose window.
130 class TileSet { 186 class TileSet {
131 public: 187 public:
132 // Fills in |tiles_|. 188 // Fills in |tiles_|.
133 void Build(TabStripModel* source_model); 189 void Build(TabStripModel* source_model);
134 190
135 // Computes coordinates for |tiles_|. 191 // Computes coordinates for |tiles_|.
136 void Layout(NSRect containing_rect); 192 void Layout(NSRect containing_rect);
137 193
138 int selected_index() const { return selected_index_; } 194 int selected_index() const { return selected_index_; }
139 void set_selected_index(int index); 195 void set_selected_index(int index);
140 void ResetSelectedIndex() { selected_index_ = initial_index_; } 196 void ResetSelectedIndex() { selected_index_ = initial_index_; }
141 197
142 const Tile& selected_tile() const { return tiles_[selected_index()]; } 198 const Tile& selected_tile() const { return *tiles_[selected_index()]; }
143 const Tile& tile_at(int index) const { return tiles_[index]; } 199 Tile& tile_at(int index) { return *tiles_[index]; }
200 const Tile& tile_at(int index) const { return *tiles_[index]; }
144 201
145 private: 202 private:
146 std::vector<Tile> tiles_; // Doesn't change often, hence values are fine. 203 std::vector<Tile*> tiles_;
147 204
148 int selected_index_; 205 int selected_index_;
149 int initial_index_; 206 int initial_index_;
150 }; 207 };
151 208
152 void TileSet::Build(TabStripModel* source_model) { 209 void TileSet::Build(TabStripModel* source_model) {
153 selected_index_ = initial_index_ = source_model->selected_index(); 210 selected_index_ = initial_index_ = source_model->selected_index();
154 tiles_.resize(source_model->count()); 211 tiles_.resize(source_model->count());
212 for (size_t i = 0; i < tiles_.size(); ++i) {
213 tiles_[i] = new Tile;
214 tiles_[i]->contents_ = source_model->GetTabContentsAt(i);
215 }
155 } 216 }
156 217
157 void TileSet::Layout(NSRect containing_rect) { 218 void TileSet::Layout(NSRect containing_rect) {
158 int tile_count = tiles_.size(); 219 int tile_count = tiles_.size();
159 220
160 // Room around the tiles insde of |containing_rect|. 221 // Room around the tiles insde of |containing_rect|.
161 const int kSmallPaddingTop = 30; 222 const int kSmallPaddingTop = 30;
162 const int kSmallPaddingLeft = 30; 223 const int kSmallPaddingLeft = 30;
163 const int kSmallPaddingRight = 30; 224 const int kSmallPaddingRight = 30;
164 const int kSmallPaddingBottom = 30; 225 const int kSmallPaddingBottom = 30;
165 226
227 // Favicon / title area.
228 const int kThumbTitlePaddingY = 6;
229 const int kFaviconSize = 16;
230 const int kTitleHeight = 14; // Font size.
231 const int kTitleExtraHeight = kThumbTitlePaddingY + kTitleHeight;
232 const int kFaviconExtraHeight = kThumbTitlePaddingY + kFaviconSize;
233 const int kFaviconTitleDistanceX = 6;
234 const int kFooterExtraHeight =
235 std::max(kFaviconExtraHeight, kTitleExtraHeight);
236
166 // Room between the tiles. 237 // Room between the tiles.
167 const int kSmallPaddingX = 15; 238 const int kSmallPaddingX = 15;
168 const int kSmallPaddingY = 13; 239 const int kSmallPaddingY = kFooterExtraHeight;
169 240
170 // Aspect ratio of the containing rect. 241 // Aspect ratio of the containing rect.
171 CGFloat aspect = NSWidth(containing_rect) / NSHeight(containing_rect); 242 CGFloat aspect = NSWidth(containing_rect) / NSHeight(containing_rect);
172 243
173 // Room left in container after the outer padding is removed. 244 // Room left in container after the outer padding is removed.
174 double container_width = 245 double container_width =
175 NSWidth(containing_rect) - kSmallPaddingLeft - kSmallPaddingRight; 246 NSWidth(containing_rect) - kSmallPaddingLeft - kSmallPaddingRight;
176 double container_height = 247 double container_height =
177 NSHeight(containing_rect) - kSmallPaddingTop - kSmallPaddingBottom; 248 NSHeight(containing_rect) - kSmallPaddingTop - kSmallPaddingBottom;
178 249
179 // The tricky part is figuring out the size of a tab thumbnail, or since the 250 // The tricky part is figuring out the size of a tab thumbnail, or since the
180 // size of the containing rect is known, the number of tiles in x and y 251 // size of the containing rect is known, the number of tiles in x and y
181 // direction. 252 // direction.
182 // Given are the size of the containing rect, and the number of thumbnails 253 // Given are the size of the containing rect, and the number of thumbnails
183 // that need to fit into that rect. The aspect ratio of the thumbnails needs 254 // that need to fit into that rect. The aspect ratio of the thumbnails needs
184 // to be the same as that of |containing_rect|, else they will look distorted. 255 // to be the same as that of |containing_rect|, else they will look distorted.
185 // The thumbnails need to be distributed such that 256 // The thumbnails need to be distributed such that
186 // |count_x * count_y >= tile_count|, and such that wasted space is minimized. 257 // |count_x * count_y >= tile_count|, and such that wasted space is minimized.
187 // See the comments in 258 // See the comments in
188 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more 259 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more
189 // detailed discussion. 260 // detailed discussion.
190 // TODO(thakis): It might be good enough to choose |count_x| and |count_y| 261 // TODO(thakis): It might be good enough to choose |count_x| and |count_y|
191 // such that count_x / count_y is roughly equal to |aspect|? 262 // such that count_x / count_y is roughly equal to |aspect|?
192 double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding( 263 double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding(
193 tile_count, aspect, container_width, container_height, 264 tile_count, aspect,
194 kSmallPaddingX, kSmallPaddingY); 265 container_width, container_height - kFooterExtraHeight,
266 kSmallPaddingX, kSmallPaddingY + kFooterExtraHeight);
195 int count_y(roundf(fny)); 267 int count_y(roundf(fny));
196 int count_x(ceilf(tile_count / float(count_y))); 268 int count_x(ceilf(tile_count / float(count_y)));
197 int last_row_count_x = tile_count - count_x * (count_y - 1); 269 int last_row_count_x = tile_count - count_x * (count_y - 1);
198 270
199 // Now that |count_x| and |count_y| are known, it's straightforward to compute 271 // Now that |count_x| and |count_y| are known, it's straightforward to compute
200 // thumbnail width/height. See comment in 272 // thumbnail width/height. See comment in
201 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation 273 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation
202 // of these two formulas. 274 // of these two formulas.
203 int small_width = 275 int small_width =
204 floor((container_width + kSmallPaddingX) / float(count_x) - 276 floor((container_width + kSmallPaddingX) / float(count_x) -
205 kSmallPaddingX); 277 kSmallPaddingX);
206 int small_height = 278 int small_height =
207 floor((container_height + kSmallPaddingY) / float(count_y) - 279 floor((container_height + kSmallPaddingY) / float(count_y) -
208 kSmallPaddingY); 280 (kSmallPaddingY + kFooterExtraHeight));
209 281
210 // |small_width / small_height| has only roughly an aspect ratio of |aspect|. 282 // |small_width / small_height| has only roughly an aspect ratio of |aspect|.
211 // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add 283 // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add
212 // the extra space won by shrinking to the outer padding. 284 // the extra space won by shrinking to the outer padding.
213 int smallExtraPaddingLeft = 0; 285 int smallExtraPaddingLeft = 0;
214 int smallExtraPaddingTop = 0; 286 int smallExtraPaddingTop = 0;
215 if (aspect > small_width/float(small_height)) { 287 if (aspect > small_width/float(small_height)) {
216 small_height = small_width / aspect; 288 small_height = small_width / aspect;
217 CGFloat all_tiles_height = 289 CGFloat all_tiles_height =
218 (small_height + kSmallPaddingY) * count_y - kSmallPaddingY; 290 (small_height + kSmallPaddingY + kFooterExtraHeight) * count_y -
291 (kSmallPaddingY + kFooterExtraHeight);
219 smallExtraPaddingTop = (container_height - all_tiles_height)/2; 292 smallExtraPaddingTop = (container_height - all_tiles_height)/2;
220 } else { 293 } else {
221 small_width = small_height * aspect; 294 small_width = small_height * aspect;
222 CGFloat all_tiles_width = 295 CGFloat all_tiles_width =
223 (small_width + kSmallPaddingX) * count_x - kSmallPaddingX; 296 (small_width + kSmallPaddingX) * count_x - kSmallPaddingX;
224 smallExtraPaddingLeft = (container_width - all_tiles_width)/2; 297 smallExtraPaddingLeft = (container_width - all_tiles_width)/2;
225 } 298 }
226 299
227 // Compute inter-tile padding in the zoomed-out view. 300 // Compute inter-tile padding in the zoomed-out view.
228 CGFloat scale_small_to_big = NSWidth(containing_rect) / float(small_width); 301 CGFloat scale_small_to_big = NSWidth(containing_rect) / float(small_width);
229 CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big; 302 CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big;
230 CGFloat big_padding_y = kSmallPaddingY * scale_small_to_big; 303 CGFloat big_padding_y =
304 (kSmallPaddingY + kFooterExtraHeight) * scale_small_to_big;
231 305
232 // Now all dimensions are known. Lay out all tiles on a regular grid: 306 // Now all dimensions are known. Lay out all tiles on a regular grid:
233 // X X X X 307 // X X X X
234 // X X X X 308 // X X X X
235 // X X 309 // X X
236 for (int row = 0, i = 0; i < tile_count; ++row) { 310 for (int row = 0, i = 0; i < tile_count; ++row) {
237 for (int col = 0; col < count_x && i < tile_count; ++col, ++i) { 311 for (int col = 0; col < count_x && i < tile_count; ++col, ++i) {
238 // Compute the smalled, zoomed-out thumbnail rect. 312 // Compute the smalled, zoomed-out thumbnail rect.
239 tiles_[i].thumb_rect_.size = NSMakeSize(small_width, small_height); 313 tiles_[i]->thumb_rect_.size = NSMakeSize(small_width, small_height);
240 314
241 int small_x = col * (small_width + kSmallPaddingX) + 315 int small_x = col * (small_width + kSmallPaddingX) +
242 kSmallPaddingLeft + smallExtraPaddingLeft; 316 kSmallPaddingLeft + smallExtraPaddingLeft;
243 int small_y = row * (small_height + kSmallPaddingY) + 317 int small_y = row * (small_height + kSmallPaddingY + kFooterExtraHeight) +
244 kSmallPaddingTop + smallExtraPaddingTop; 318 kSmallPaddingTop + smallExtraPaddingTop;
245 319
246 tiles_[i].thumb_rect_.origin = NSMakePoint( 320 tiles_[i]->thumb_rect_.origin = NSMakePoint(
247 small_x, NSHeight(containing_rect) - small_y - small_height); 321 small_x, NSHeight(containing_rect) - small_y - small_height);
248 322
323 tiles_[i]->favicon_rect_.size = NSMakeSize(kFaviconSize, kFaviconSize);
324 tiles_[i]->favicon_rect_.origin = NSMakePoint(
325 small_x,
326 NSHeight(containing_rect) -
327 (small_y + small_height + kFaviconExtraHeight));
328
329 // Align lower left corner of title rect with lower left corner of favicon
330 // for now. The final position is computed later by
331 // |Tile::set_font_metrics()|.
332 tiles_[i]->title_font_size_ = kTitleHeight;
333 tiles_[i]->title_rect_.origin = NSMakePoint(
334 NSMaxX(tiles_[i]->favicon_rect()) + kFaviconTitleDistanceX,
335 NSMinY(tiles_[i]->favicon_rect()));
336 tiles_[i]->title_rect_.size = NSMakeSize(
337 small_width -
338 NSWidth(tiles_[i]->favicon_rect()) - kFaviconTitleDistanceX,
339 kTitleHeight);
340
249 // Compute the big, pre-zoom thumbnail rect. 341 // Compute the big, pre-zoom thumbnail rect.
250 tiles_[i].start_thumb_rect_.size = containing_rect.size; 342 tiles_[i]->start_thumb_rect_.size = containing_rect.size;
251 343
252 int big_x = col * (NSWidth(containing_rect) + big_padding_x); 344 int big_x = col * (NSWidth(containing_rect) + big_padding_x);
253 int big_y = row * (NSHeight(containing_rect) + big_padding_y); 345 int big_y = row * (NSHeight(containing_rect) + big_padding_y);
254 tiles_[i].start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); 346 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y);
255 } 347 }
256 } 348 }
257 349
258 // Go through last row and center it: 350 // Go through last row and center it:
259 // X X X X 351 // X X X X
260 // X X X X 352 // X X X X
261 // X X 353 // X X
262 int last_row_empty_tiles_x = count_x - last_row_count_x; 354 int last_row_empty_tiles_x = count_x - last_row_count_x;
263 CGFloat small_last_row_shift_x = 355 CGFloat small_last_row_shift_x =
264 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2; 356 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2;
265 CGFloat big_last_row_shift_x = 357 CGFloat big_last_row_shift_x =
266 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2; 358 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2;
267 for (int i = tile_count - last_row_count_x; i < tile_count; ++i) { 359 for (int i = tile_count - last_row_count_x; i < tile_count; ++i) {
268 tiles_[i].thumb_rect_.origin.x += small_last_row_shift_x; 360 tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x;
269 tiles_[i].start_thumb_rect_.origin.x += big_last_row_shift_x; 361 tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x;
362 tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x;
363 tiles_[i]->title_rect_.origin.x += small_last_row_shift_x;
270 } 364 }
271 } 365 }
272 366
273 void TileSet::set_selected_index(int index) { 367 void TileSet::set_selected_index(int index) {
274 CHECK_GE(index, 0); 368 CHECK_GE(index, 0);
275 CHECK_LT(index, static_cast<int>(tiles_.size())); 369 CHECK_LT(index, static_cast<int>(tiles_.size()));
276 selected_index_ = index; 370 selected_index_ = index;
277 } 371 }
278 372
279 } // namespace tabpose 373 } // namespace tabpose
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 } 464 }
371 465
372 - (CALayer*)selectedLayer { 466 - (CALayer*)selectedLayer {
373 return [allThumbnailLayers_ objectAtIndex:tileSet_->selected_index()]; 467 return [allThumbnailLayers_ objectAtIndex:tileSet_->selected_index()];
374 } 468 }
375 469
376 - (void)selectTileAtIndex:(int)newIndex { 470 - (void)selectTileAtIndex:(int)newIndex {
377 ScopedCAActionDisabler disabler; 471 ScopedCAActionDisabler disabler;
378 const tabpose::Tile& tile = tileSet_->tile_at(newIndex); 472 const tabpose::Tile& tile = tileSet_->tile_at(newIndex);
379 selectionHighlight_.frame = 473 selectionHighlight_.frame =
380 NSRectToCGRect(NSInsetRect(tile.thumb_rect(), -6, -6)); 474 NSRectToCGRect(NSInsetRect(tile.thumb_rect(), -5, -5));
381 475
382 tileSet_->set_selected_index(newIndex); 476 tileSet_->set_selected_index(newIndex);
383 } 477 }
384 478
385 - (void)setUpLayers:(NSRect)bgLayerRect slomo:(BOOL)slomo { 479 - (void)setUpLayers:(NSRect)bgLayerRect slomo:(BOOL)slomo {
386 // Root layer -- covers whole window. 480 // Root layer -- covers whole window.
387 rootLayer_ = [CALayer layer]; 481 rootLayer_ = [CALayer layer];
388 [[self contentView] setLayer:rootLayer_]; 482 [[self contentView] setLayer:rootLayer_];
389 [[self contentView] setWantsLayer:YES]; 483 [[self contentView] setWantsLayer:YES];
390 484
(...skipping 21 matching lines...) Expand all
412 NSHeight(bgLayerRect) - kTopGradientHeight, 506 NSHeight(bgLayerRect) - kTopGradientHeight,
413 NSWidth(bgLayerRect), 507 NSWidth(bgLayerRect),
414 kTopGradientHeight); 508 kTopGradientHeight);
415 [gradientLayer setNeedsDisplay]; // Draw once. 509 [gradientLayer setNeedsDisplay]; // Draw once.
416 [bgLayer_ addSublayer:gradientLayer]; 510 [bgLayer_ addSublayer:gradientLayer];
417 511
418 // Layers for the tab thumbnails. 512 // Layers for the tab thumbnails.
419 tileSet_->Build(tabStripModel_); 513 tileSet_->Build(tabStripModel_);
420 tileSet_->Layout(bgLayerRect); 514 tileSet_->Layout(bgLayerRect);
421 515
516 NSImage* defaultFavIcon = ResourceBundle::GetSharedInstance().GetNSImageNamed(
517 IDR_DEFAULT_FAVICON);
518
422 allThumbnailLayers_.reset( 519 allThumbnailLayers_.reset(
423 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]); 520 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
521 allFaviconLayers_.reset(
522 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
523 allTitleLayers_.reset(
524 [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
424 for (int i = 0; i < tabStripModel_->count(); ++i) { 525 for (int i = 0; i < tabStripModel_->count(); ++i) {
526 const tabpose::Tile& tile = tileSet_->tile_at(i);
425 CALayer* layer = [CALayer layer]; 527 CALayer* layer = [CALayer layer];
426 528
427 // Background color as placeholder for now. 529 // Background color as placeholder for now.
428 layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite); 530 layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite);
429 531
430 AnimateCALayerFrameFromTo( 532 AnimateCALayerFrameFromTo(
431 layer, 533 layer,
432 tileSet_->tile_at(i).GetStartRectRelativeTo(tileSet_->selected_tile()), 534 tile.GetStartRectRelativeTo(tileSet_->selected_tile()),
433 tileSet_->tile_at(i).thumb_rect(), 535 tile.thumb_rect(),
434 kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1), 536 kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1),
435 i == tileSet_->selected_index() ? self : nil); 537 i == tileSet_->selected_index() ? self : nil);
436 538
437 // Add a delegate to one of the animations to get a notification once the 539 // Add a delegate to one of the animations to get a notification once the
438 // animations are done. 540 // animations are done.
439 if (i == tileSet_->selected_index()) { 541 if (i == tileSet_->selected_index()) {
440 CAAnimation* animation = [layer animationForKey:@"bounds"]; 542 CAAnimation* animation = [layer animationForKey:@"bounds"];
441 DCHECK(animation); 543 DCHECK(animation);
442 [animation setValue:kAnimationIdFadeIn forKey:kAnimationIdKey]; 544 [animation setValue:kAnimationIdFadeIn forKey:kAnimationIdKey];
443 } 545 }
444 546
445 layer.shadowRadius = 10; 547 layer.shadowRadius = 10;
446 layer.shadowOffset = CGSizeMake(0, -10); 548 layer.shadowOffset = CGSizeMake(0, -10);
447 549
448 [bgLayer_ addSublayer:layer]; 550 [bgLayer_ addSublayer:layer];
449 [allThumbnailLayers_ addObject:layer]; 551 [allThumbnailLayers_ addObject:layer];
552
553 // Favicon and title.
554 NSFont* font = [NSFont systemFontOfSize:tile.title_font_size()];
555 tileSet_->tile_at(i).set_font_metrics([font ascender], -[font descender]);
556
557 NSImage* ns_favicon = gfx::SkBitmapToNSImage(tile.favicon());
558 // Either we don't have a valid favicon or there was some issue converting
559 // it from an SkBitmap. Either way, just show the default.
560 if (!ns_favicon)
561 ns_favicon = defaultFavIcon;
562 scoped_cftyperef<CGImageRef> favicon(
563 mac_util::CopyNSImageToCGImage(ns_favicon));
564
565 CALayer* faviconLayer = [CALayer layer];
566 faviconLayer.frame = NSRectToCGRect(tile.favicon_rect());
567 faviconLayer.contents = (id)favicon.get();
568 faviconLayer.zPosition = 1; // On top of the thumb shadow.
569 faviconLayer.hidden = YES;
570 [bgLayer_ addSublayer:faviconLayer];
571 [allFaviconLayers_ addObject:faviconLayer];
572
573 CATextLayer* titleLayer = [CATextLayer layer];
574 titleLayer.frame = NSRectToCGRect(tile.title_rect());
575 titleLayer.string = base::SysUTF16ToNSString(tile.title());
576 titleLayer.fontSize = [font pointSize];
577 titleLayer.truncationMode = kCATruncationEnd;
578 titleLayer.font = font;
579 titleLayer.zPosition = 1; // On top of the thumb shadow.
580 titleLayer.hidden = YES;
581 [bgLayer_ addSublayer:titleLayer];
582 [allTitleLayers_ addObject:titleLayer];
450 } 583 }
451 [self selectTileAtIndex:tileSet_->selected_index()]; 584 [self selectTileAtIndex:tileSet_->selected_index()];
452 } 585 }
453 586
454 - (BOOL)canBecomeKeyWindow { 587 - (BOOL)canBecomeKeyWindow {
455 return YES; 588 return YES;
456 } 589 }
457 590
458 - (void)keyDown:(NSEvent*)event { 591 - (void)keyDown:(NSEvent*)event {
459 // Overridden to prevent beeps. 592 // Overridden to prevent beeps.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 tabStripModel_->SelectTabContentsAt(tileSet_->selected_index(), 664 tabStripModel_->SelectTabContentsAt(tileSet_->selected_index(),
532 /*user_gesture=*/true); 665 /*user_gesture=*/true);
533 666
534 { 667 {
535 ScopedCAActionDisabler disableCAActions; 668 ScopedCAActionDisabler disableCAActions;
536 669
537 // Move the selected layer on top of all other layers. 670 // Move the selected layer on top of all other layers.
538 [self selectedLayer].zPosition = 1; 671 [self selectedLayer].zPosition = 1;
539 672
540 selectionHighlight_.hidden = YES; 673 selectionHighlight_.hidden = YES;
674 for (CALayer* layer in allFaviconLayers_.get())
675 layer.hidden = YES;
676 for (CALayer* layer in allTitleLayers_.get())
677 layer.hidden = YES;
541 678
542 // Running animations with shadows is slow, so turn shadows off before 679 // Running animations with shadows is slow, so turn shadows off before
543 // running the exit animation. 680 // running the exit animation.
544 for (CALayer* layer in allThumbnailLayers_.get()) 681 for (CALayer* layer in allThumbnailLayers_.get())
545 layer.shadowOpacity = 0.0; 682 layer.shadowOpacity = 0.0;
546 } 683 }
547 684
548 // Animate layers out, all in one transaction. 685 // Animate layers out, all in one transaction.
549 CGFloat duration = kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1); 686 CGFloat duration = kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1);
550 ScopedCAActionSetDuration durationSetter(duration); 687 ScopedCAActionSetDuration durationSetter(duration);
(...skipping 21 matching lines...) Expand all
572 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { 709 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
573 NSString* animationId = [animation valueForKey:kAnimationIdKey]; 710 NSString* animationId = [animation valueForKey:kAnimationIdKey];
574 if ([animationId isEqualToString:kAnimationIdFadeIn]) { 711 if ([animationId isEqualToString:kAnimationIdFadeIn]) {
575 if (finished) { 712 if (finished) {
576 // If the user clicks while the fade in animation is still running, 713 // If the user clicks while the fade in animation is still running,
577 // |state_| is already kFadingOut. In that case, don't do anything. 714 // |state_| is already kFadingOut. In that case, don't do anything.
578 DCHECK_EQ(tabpose::kFadingIn, state_); 715 DCHECK_EQ(tabpose::kFadingIn, state_);
579 state_ = tabpose::kFadedIn; 716 state_ = tabpose::kFadedIn;
580 717
581 selectionHighlight_.hidden = NO; 718 selectionHighlight_.hidden = NO;
719 for (CALayer* layer in allFaviconLayers_.get())
720 layer.hidden = NO;
721 for (CALayer* layer in allTitleLayers_.get())
722 layer.hidden = NO;
582 723
583 // Running animations with shadows is slow, so turn shadows on only after 724 // Running animations with shadows is slow, so turn shadows on only after
584 // the animation is done. 725 // the animation is done.
585 ScopedCAActionDisabler disableCAActions; 726 ScopedCAActionDisabler disableCAActions;
586 for (CALayer* layer in allThumbnailLayers_.get()) 727 for (CALayer* layer in allThumbnailLayers_.get())
587 layer.shadowOpacity = 0.5; 728 layer.shadowOpacity = 0.5;
588 } 729 }
589 } else if ([animationId isEqualToString:kAnimationIdFadeOut]) { 730 } else if ([animationId isEqualToString:kAnimationIdFadeOut]) {
590 DCHECK_EQ(tabpose::kFadingOut, state_); 731 DCHECK_EQ(tabpose::kFadingOut, state_);
591 [self close]; 732 [self close];
592 } 733 }
593 } 734 }
594 735
595 @end 736 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/tabpose_window.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698