From 1ae99501e0a15b85f0593a71c939063027c802d4 Mon Sep 17 00:00:00 2001
From: "pinkerton@chromium.org"
 <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Tue, 19 May 2009 20:46:37 +0000
Subject: Implement a status throbber on the mac, currently using the Win
 artwork. Made the tab cell use a generic NSView for showing the icon instead
 of relying on the NSButtonCell to draw it, so a NSImageView is in place by
 default. Remove un-needed outlets, bindings, and views from the nib.
 BUG=11916. TEST=loading pages, opening and closing tabs. Review URL:
 http://codereview.chromium.org/115527

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16410 0039d316-1c4b-4281-b951-d872f2087c98
---
 chrome/browser/cocoa/throbber_view.mm | 88 +++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 chrome/browser/cocoa/throbber_view.mm

(limited to 'chrome/browser/cocoa/throbber_view.mm')

diff --git a/chrome/browser/cocoa/throbber_view.mm b/chrome/browser/cocoa/throbber_view.mm
new file mode 100644
index 0000000..948dcb4
--- /dev/null
+++ b/chrome/browser/cocoa/throbber_view.mm
@@ -0,0 +1,88 @@
+// Copyright (c) 2009 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/cocoa/throbber_view.h"
+
+#include "base/logging.h"
+
+const float kAnimationIntervalSeconds = 0.03;  // 30ms, same as windows
+
+@interface ThrobberView(PrivateMethods)
+- (void)animate;
+@end
+
+// A very simple object that is the target for the animation timer so that
+// the view isn't. We do this to avoid retain cycles as the timer
+// retains its target.
+@interface TimerTarget : NSObject {
+ @private
+  ThrobberView* throbber_;  // Weak, owns us
+}
+- (id)initWithThrobber:(ThrobberView*)view;
+@end
+
+@implementation TimerTarget
+- (id)initWithThrobber:(ThrobberView*)view {
+  if ((self = [super init])) {
+    throbber_ = view;
+  }
+  return self;
+}
+
+- (void)animate:(NSTimer*)timer {
+  [throbber_ animate];
+}
+@end
+
+@implementation ThrobberView
+
+- (id)initWithFrame:(NSRect)frame image:(NSImage*)image {
+  if ((self = [super initWithFrame:frame])) {
+    // Ensure that the height divides evenly into the width. Cache the
+    // number of frames in the animation for later.
+    NSSize imageSize = [image size];
+    DCHECK(imageSize.height && imageSize.width);
+    if (!imageSize.height)
+      return nil;
+    DCHECK((int)imageSize.width % (int)imageSize.height == 0);
+    numFrames_ = (int)imageSize.width / (int)imageSize.height;
+    DCHECK(numFrames_);
+    image_.reset([image retain]);
+
+    // Start a timer for the animation frames.
+    target_.reset([[TimerTarget alloc] initWithThrobber:self]);
+    timer_ =
+        [NSTimer scheduledTimerWithTimeInterval:kAnimationIntervalSeconds
+                                         target:target_.get()
+                                       selector:@selector(animate:)
+                                       userInfo:nil
+                                        repeats:YES];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [timer_ invalidate];
+  [super dealloc];
+}
+
+// Called when the TimerTarget gets tickled by our timer. Increment the frame
+// counter and mark as needing display.
+- (void)animate {
+  animationFrame_ = ++animationFrame_ % numFrames_;
+  [self setNeedsDisplay:YES];
+}
+
+// Overridden to draw the appropriate frame in the image strip.
+- (void)drawRect:(NSRect)rect {
+  float imageDimension = [image_ size].height;
+  float xOffset = animationFrame_ * imageDimension;
+  NSRect sourceImageRect =
+      NSMakeRect(xOffset, 0, imageDimension, imageDimension);
+  [image_ compositeToPoint:NSMakePoint(0, 0)
+                  fromRect:sourceImageRect
+                 operation:NSCompositeSourceOver];
+}
+
+@end
-- 
cgit v1.1