// 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_UI_COCOA_STATUS_BUBBLE_MAC_H_
#define CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_
#pragma once
#include <string>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#include "base/string16.h"
#include "base/task.h"
#include "chrome/browser/ui/status_bubble.h"
#include "googleurl/src/gurl.h"
class GURL;
class StatusBubbleMacTest;
class StatusBubbleMac : public StatusBubble {
public:
// The various states that a status bubble may be in. Public for delegate
// access (for testing).
enum StatusBubbleState {
kBubbleHidden, // Fully hidden
kBubbleShowingTimer, // Waiting to fade in
kBubbleShowingFadeIn, // In a fade-in transition
kBubbleShown, // Fully visible
kBubbleHidingTimer, // Waiting to fade out
kBubbleHidingFadeOut // In a fade-out transition
};
StatusBubbleMac(NSWindow* parent, id delegate);
virtual ~StatusBubbleMac();
// StatusBubble implementation.
virtual void SetStatus(const string16& status);
virtual void SetURL(const GURL& url, const string16& languages);
virtual void Hide();
virtual void MouseMoved(const gfx::Point& location, bool left_content);
virtual void UpdateDownloadShelfVisibility(bool visible);
// Mac-specific method: Update the size and position of the status bubble to
// match the parent window. Safe to call even when the status bubble does not
// exist.
void UpdateSizeAndPosition();
// Mac-specific method: Change the parent window of the status bubble. Safe to
// call even when the status bubble does not exist.
void SwitchParentWindow(NSWindow* parent);
// Delegate method called when a fade-in or fade-out transition has
// completed. This is public so that it may be visible to the CAAnimation
// delegate, which is an Objective-C object.
void AnimationDidStop(CAAnimation* animation, bool finished);
// Expand the bubble to fit a URL too long for the standard bubble size.
void ExpandBubble();
private:
friend class StatusBubbleMacTest;
// Setter for state_. Use this instead of writing to state_ directly so
// that state changes can be observed by unit tests.
void SetState(StatusBubbleState state);
// Sets the bubble text for SetStatus and SetURL.
void SetText(const string16& text, bool is_url);
// Construct the window/widget if it does not already exist. (Safe to call if
// it does.)
void Create();
// Attaches the status bubble window to its parent window. Safe to call even
// when already attached.
void Attach();
// Detaches the status bubble window from its parent window.
void Detach();
// Is the status bubble attached to the browser window? It should be attached
// when shown and during any fades, but should be detached when hidden.
bool is_attached() { return [window_ parentWindow] != nil; }
// Begins fading the status bubble window in or out depending on the value
// of |show|. This must be called from the appropriate fade state,
// kBubbleShowingFadeIn or kBubbleHidingFadeOut, or from the appropriate
// fully-shown/hidden state, kBubbleShown or kBubbleHidden. This may be
// called at any point during a fade-in or fade-out; it is even possible to
// reverse a transition before it has completed.
void Fade(bool show);
// One-shot timer operations to manage the delays associated with the
// kBubbleShowingTimer and kBubbleHidingTimer states. StartTimer and
// TimerFired must be called from one of these states. StartTimer may be
// called while the timer is still running; in that case, the timer will be
// reset. CancelTimer may be called from any state.
void StartTimer(int64 time_ms);
void CancelTimer();
void TimerFired();
// Begin the process of showing or hiding the status bubble. These may be
// called from any state, and will take the appropriate action to initiate
// any state changes that may be needed.
void StartShowing();
void StartHiding();
// Cancel the expansion timer.
void CancelExpandTimer();
// The timer factory used for show and hide delay timers.
ScopedRunnableMethodFactory<StatusBubbleMac> timer_factory_;
// The timer factory used for the expansion delay timer.
ScopedRunnableMethodFactory<StatusBubbleMac> expand_timer_factory_;
// Calculate the appropriate frame for the status bubble window. If
// |expanded_width|, use entire width of parent frame.
NSRect CalculateWindowFrame(bool expanded_width);
// The window we attach ourselves to.
NSWindow* parent_; // WEAK
// The object that we query about our vertical offset for positioning.
id delegate_; // 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_;
// The status bubble's current state. Do not write to this field directly;
// use SetState().
StatusBubbleState state_;
// True if operations are to be performed immediately rather than waiting
// for delays and transitions. Normally false, this should only be set to
// true for testing.
bool immediate_;
// True if the status bubble has been expanded. If the bubble is in the
// expanded state and encounters a new URL, change size immediately,
// with no hover delay.
bool is_expanded_;
// The original, non-elided URL.
GURL url_;
// Needs to be passed to ElideURL if the original URL string is wider than
// the standard bubble width.
string16 languages_;
DISALLOW_COPY_AND_ASSIGN(StatusBubbleMac);
};
// Delegate interface
@interface NSObject(StatusBubbleDelegate)
// Called to query the delegate about the frame StatusBubble should position
// itself in. Frame is returned in the parent window coordinates.
- (NSRect)statusBubbleBaseFrame;
// Called from SetState to notify the delegate of state changes.
- (void)statusBubbleWillEnterState:(StatusBubbleMac::StatusBubbleState)state;
@end
#endif // CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_