summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authoravi@google.com <avi@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-17 19:15:22 +0000
committeravi@google.com <avi@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-17 19:15:22 +0000
commitdef8e9a494c0b7fd2034c4cd90d7e9b7c08073e9 (patch)
treed74d87ef1b5d21d943650db47a1ae3b4f37216cf /chrome/browser
parente382a69f617ee0c196f7fe4b2f61ba6decd29b29 (diff)
downloadchromium_src-def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9.zip
chromium_src-def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9.tar.gz
chromium_src-def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9.tar.bz2
First pass at Mac status bubble.
Review URL: http://codereview.chromium.org/48070 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11895 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_window.h4
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.h6
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm6
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.h50
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.mm236
5 files changed, 300 insertions, 2 deletions
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h
index 2151717..b779ba1 100644
--- a/chrome/browser/browser_window.h
+++ b/chrome/browser/browser_window.h
@@ -29,7 +29,9 @@ class Rect;
// NOTE: All getters except GetTabStrip() may return NULL.
class BrowserWindow {
public:
- // Initialize the frame.
+ // Initialize the frame. This is called on Windows via the views system. It
+ // doesn't get called on other platforms so don't do stuff here on other
+ // platforms.
virtual void Init() = 0;
// Show the window, or activates it if it's already visible.
diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h
index df1eb42..a74ed8f 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/cocoa/browser_window_cocoa.h
@@ -5,11 +5,14 @@
#ifndef CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_
#define CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_
+#include "base/scoped_ptr.h"
#include "chrome/browser/browser_window.h"
@class BrowserWindowController;
@class NSWindow;
+class StatusBubbleMac;
+
// An implementation of BrowserWindow for Cocoa. Bridges between C++ and
// the Cocoa NSWindow. Cross-platform code will interact with this object when
// it needs to manipulate the window.
@@ -66,6 +69,9 @@ class BrowserWindowCocoa : public BrowserWindow {
private:
BrowserWindowController* controller_; // weak, owns us
NSWindow* window_; // weak, owned by |controller_|
+
+ // The status bubble manager. Always non-NULL.
+ scoped_ptr<StatusBubbleMac> status_bubble_;
};
#endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index 1163f1e5..b062a4f 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -6,16 +6,20 @@
#include "base/logging.h"
#include "chrome/browser/cocoa/browser_window_cocoa.h"
#include "chrome/browser/cocoa/browser_window_controller.h"
+#include "chrome/browser/cocoa/status_bubble_mac.h"
BrowserWindowCocoa::BrowserWindowCocoa(BrowserWindowController* controller,
NSWindow* window)
: controller_(controller), window_(window) {
+ status_bubble_.reset(new StatusBubbleMac(window_));
}
BrowserWindowCocoa::~BrowserWindowCocoa() {
}
void BrowserWindowCocoa::Init() {
+ // Remember, no code here. This doesn't get called on the Mac. Put code into
+ // the constructor, above, instead.
}
void BrowserWindowCocoa::Show() {
@@ -61,7 +65,7 @@ BrowserWindowTesting* BrowserWindowCocoa::GetBrowserWindowTesting() {
}
StatusBubble* BrowserWindowCocoa::GetStatusBubble() {
- return NULL;
+ return status_bubble_.get();
}
void BrowserWindowCocoa::SelectedTabToolbarSizeChanged(bool is_animating) {
diff --git a/chrome/browser/cocoa/status_bubble_mac.h b/chrome/browser/cocoa/status_bubble_mac.h
new file mode 100644
index 0000000..6581ac7
--- /dev/null
+++ b/chrome/browser/cocoa/status_bubble_mac.h
@@ -0,0 +1,50 @@
+// 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.
+
+#ifndef CHROME_BROWSER_COCOA_STATUS_BUBBLE_MAC_H_
+#define CHROME_BROWSER_COCOA_STATUS_BUBBLE_MAC_H_
+
+#include <string>
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/status_bubble.h"
+
+class GURL;
+
+class StatusBubbleMac : public StatusBubble {
+ public:
+ StatusBubbleMac(NSWindow* parent);
+ virtual ~StatusBubbleMac();
+
+ // StatusBubble implementation.
+ virtual void SetStatus(const std::wstring& status);
+ virtual void SetURL(const GURL& url, const std::wstring& languages);
+ virtual void Hide();
+ virtual void MouseMoved();
+
+ private:
+ void SetStatus(NSString* status, bool is_url);
+
+ // Construct the window/widget if it does not already exist. (Safe to call if
+ // it does.)
+ void Create();
+
+ void FadeIn();
+ void FadeOut();
+
+ // The window we attach ourselves to.
+ NSWindow* parent_; // WEAK
+
+ // The window we own.
+ NSWindow* window_;
+
+ // The status text we want to display when there are no URLs to display.
+ NSString* status_text_;
+
+ // The url we want to display when there is no status text to display.
+ NSString* url_text_;
+};
+
+#endif // #ifndef CHROME_BROWSER_COCOA_STATUS_BUBBLE_MAC_H_
diff --git a/chrome/browser/cocoa/status_bubble_mac.mm b/chrome/browser/cocoa/status_bubble_mac.mm
new file mode 100644
index 0000000..b6b4922
--- /dev/null
+++ b/chrome/browser/cocoa/status_bubble_mac.mm
@@ -0,0 +1,236 @@
+// 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.
+
+#include "chrome/browser/cocoa/status_bubble_mac.h"
+
+#include "base/string_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/common/gfx/text_elider.h"
+#include "googleurl/src/gurl.h"
+#import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
+
+namespace {
+
+const int kWindowHeight = 18;
+// The width of the bubble in relation to the width of the parent window.
+const float kWindowWidthPercent = 1.0f/3.0f;
+
+const int kTextPadding = 3;
+const int kTextPositionX = 4;
+const int kTextPositionY = 2;
+
+const float kWindowFill = 0.8f;
+const float kWindowEdge = 0.7f;
+
+// The roundedness of the edges of our bubble.
+const int kBubbleCornerRadius = 4.0f;
+
+// How long each fade should last for.
+const int kShowFadeDuration = 0.120f;
+const int kHideFadeDuration = 0.200f;
+
+}
+
+// TODO(avi):
+// - move in response to overlapping mouse
+// - do display delay
+// - figure out why the show/fade durations aren't working
+
+@interface StatusBubbleViewCocoa : NSView {
+ @private
+ NSString* content_;
+}
+
+- (void)setContent:(NSString*)content;
+- (NSFont*)font;
+@end
+
+StatusBubbleMac::StatusBubbleMac(NSWindow* parent)
+ : parent_(parent),
+ window_(nil),
+ status_text_(nil),
+ url_text_(nil) {
+}
+
+StatusBubbleMac::~StatusBubbleMac() {
+ Hide();
+}
+
+void StatusBubbleMac::SetStatus(const std::wstring& status) {
+ Create();
+
+ NSString* status_ns = base::SysWideToNSString(status);
+
+ SetStatus(status_ns, false);
+}
+
+void StatusBubbleMac::SetURL(const GURL& url, const std::wstring& languages) {
+ Create();
+
+ NSRect frame = [window_ frame];
+ int text_width = static_cast<int>(frame.size.width -
+ kTextPositionX -
+ kTextPadding);
+ NSFont* font = [[window_ contentView] font];
+ ChromeFont font_chr =
+ ChromeFont::CreateFont(base::SysNSStringToWide([font fontName]),
+ [font pointSize]);
+
+ std::wstring status = gfx::ElideUrl(url, font_chr, text_width, languages);
+ NSString* status_ns = base::SysWideToNSString(status);
+
+ SetStatus(status_ns, true);
+}
+
+void StatusBubbleMac::SetStatus(NSString* status, bool is_url) {
+ NSString** main;
+ NSString** backup;
+
+ if (is_url) {
+ main = &url_text_;
+ backup = &status_text_;
+ } else {
+ main = &status_text_;
+ backup = &url_text_;
+ }
+
+ if ([status isEqualToString:*main])
+ return;
+
+ [*main release];
+ *main = [status retain];
+ if ([*main length] > 0) {
+ [[window_ contentView] setContent:*main];
+ } else if ([*backup length] > 0) {
+ [[window_ contentView] setContent:*backup];
+ } else {
+ Hide();
+ }
+
+ FadeIn();
+}
+
+void StatusBubbleMac::Hide() {
+ FadeOut();
+
+ if (window_) {
+ [parent_ removeChildWindow:window_];
+ [window_ release];
+ window_ = nil;
+ }
+
+ [status_text_ release];
+ status_text_ = nil;
+ [url_text_ release];
+ url_text_ = nil;
+}
+
+void StatusBubbleMac::MouseMoved() {
+}
+
+void StatusBubbleMac::Create() {
+ if (window_)
+ return;
+
+ NSRect rect = [parent_ frame];
+ rect.size.height = kWindowHeight;
+ rect.size.width = static_cast<int>(kWindowWidthPercent * rect.size.width);
+ // TODO(avi):fix this for RTL
+ window_ = [[NSWindow alloc] initWithContentRect:rect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+ [window_ setMovableByWindowBackground:NO];
+ [window_ setBackgroundColor:[NSColor clearColor]];
+ [window_ setLevel:NSNormalWindowLevel];
+ [window_ setOpaque:NO];
+ [window_ setHasShadow:NO];
+
+ NSView* view =
+ [[[StatusBubbleViewCocoa alloc] initWithFrame:NSZeroRect] autorelease];
+ [window_ setContentView:view];
+
+ [parent_ addChildWindow:window_ ordered:NSWindowAbove];
+
+ [window_ setAlphaValue:0.0f];
+ [window_ orderFront:nil];
+}
+
+void StatusBubbleMac::FadeIn() {
+ [NSAnimationContext beginGrouping];
+ [[NSAnimationContext currentContext] setDuration:kShowFadeDuration];
+ [[window_ animator] setAlphaValue:1.0f];
+ [NSAnimationContext endGrouping];
+}
+
+void StatusBubbleMac::FadeOut() {
+ [NSAnimationContext beginGrouping];
+ [[NSAnimationContext currentContext] setDuration:kHideFadeDuration];
+ [[window_ animator] setAlphaValue:0.0f];
+ [NSAnimationContext endGrouping];
+}
+
+@implementation StatusBubbleViewCocoa
+
+- (void)dealloc {
+ [content_ release];
+ [super dealloc];
+}
+
+- (void)setContent:(NSString*)content {
+ [content_ autorelease];
+ content_ = [content copy];
+ [self setNeedsDisplay:YES];
+}
+
+- (NSFont*)font {
+ return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
+}
+
+- (void)drawRect:(NSRect)rect {
+ // Decide on which corners to round
+ // TODO(avi): decide properly
+ float tl_radius = 0.0f;
+ float tr_radius = kBubbleCornerRadius;
+ float bl_radius = 0.0f;
+ float br_radius = 0.0f;
+
+ // Background / Edge
+
+ NSRect bounds = [self bounds];
+ NSBezierPath *border = [NSBezierPath gtm_bezierPathWithRoundRect:bounds
+ topLeftCornerRadius:tl_radius
+ topRightCornerRadius:tr_radius
+ bottomLeftCornerRadius:bl_radius
+ bottomRightCornerRadius:br_radius];
+
+ [[NSColor colorWithDeviceWhite:kWindowFill alpha:1.0f] set];
+ [border fill];
+
+ border = [NSBezierPath gtm_bezierPathWithRoundRect:bounds
+ topLeftCornerRadius:tl_radius
+ topRightCornerRadius:tr_radius
+ bottomLeftCornerRadius:bl_radius
+ bottomRightCornerRadius:br_radius];
+
+ [[NSColor colorWithDeviceWhite:kWindowEdge alpha:1.0f] set];
+ [border stroke];
+
+ // Text
+
+ NSFont* textFont = [self font];
+ NSShadow* textShadow = [[[NSShadow alloc] init] autorelease];
+ [textShadow setShadowBlurRadius:1.5f];
+ [textShadow setShadowColor:[NSColor whiteColor]];
+ [textShadow setShadowOffset:NSMakeSize(0.0f, -1.0f)];
+
+ NSDictionary* textDict = [NSDictionary dictionaryWithObjectsAndKeys:
+ textFont, NSFontAttributeName,
+ textShadow, NSShadowAttributeName,
+ nil];
+ [content_ drawAtPoint:NSMakePoint(kTextPositionX, kTextPositionY)
+ withAttributes:textDict];
+}
+
+@end