1 // Copyright (c) 2009 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 #ifndef CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_ 6 #define CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_ 7 #pragma once 8 9 #include <string> 10 11 #import <Cocoa/Cocoa.h> 12 #import <QuartzCore/QuartzCore.h> 13 14 #include "base/string16.h" 15 #include "base/task.h" 16 #include "chrome/browser/ui/status_bubble.h" 17 #include "googleurl/src/gurl.h" 18 19 class GURL; 20 class StatusBubbleMacTest; 21 22 class StatusBubbleMac : public StatusBubble { 23 public: 24 // The various states that a status bubble may be in. Public for delegate 25 // access (for testing). 26 enum StatusBubbleState { 27 kBubbleHidden, // Fully hidden 28 kBubbleShowingTimer, // Waiting to fade in 29 kBubbleShowingFadeIn, // In a fade-in transition 30 kBubbleShown, // Fully visible 31 kBubbleHidingTimer, // Waiting to fade out 32 kBubbleHidingFadeOut // In a fade-out transition 33 }; 34 35 StatusBubbleMac(NSWindow* parent, id delegate); 36 virtual ~StatusBubbleMac(); 37 38 // StatusBubble implementation. 39 virtual void SetStatus(const string16& status); 40 virtual void SetURL(const GURL& url, const string16& languages); 41 virtual void Hide(); 42 virtual void MouseMoved(const gfx::Point& location, bool left_content); 43 virtual void UpdateDownloadShelfVisibility(bool visible); 44 45 // Mac-specific method: Update the size and position of the status bubble to 46 // match the parent window. Safe to call even when the status bubble does not 47 // exist. 48 void UpdateSizeAndPosition(); 49 50 // Mac-specific method: Change the parent window of the status bubble. Safe to 51 // call even when the status bubble does not exist. 52 void SwitchParentWindow(NSWindow* parent); 53 54 // Delegate method called when a fade-in or fade-out transition has 55 // completed. This is public so that it may be visible to the CAAnimation 56 // delegate, which is an Objective-C object. 57 void AnimationDidStop(CAAnimation* animation, bool finished); 58 59 // Expand the bubble to fit a URL too long for the standard bubble size. 60 void ExpandBubble(); 61 62 private: 63 friend class StatusBubbleMacTest; 64 65 // Setter for state_. Use this instead of writing to state_ directly so 66 // that state changes can be observed by unit tests. 67 void SetState(StatusBubbleState state); 68 69 // Sets the bubble text for SetStatus and SetURL. 70 void SetText(const string16& text, bool is_url); 71 72 // Construct the window/widget if it does not already exist. (Safe to call if 73 // it does.) 74 void Create(); 75 76 // Attaches the status bubble window to its parent window. Safe to call even 77 // when already attached. 78 void Attach(); 79 80 // Detaches the status bubble window from its parent window. 81 void Detach(); 82 83 // Is the status bubble attached to the browser window? It should be attached 84 // when shown and during any fades, but should be detached when hidden. is_attached()85 bool is_attached() { return [window_ parentWindow] != nil; } 86 87 // Begins fading the status bubble window in or out depending on the value 88 // of |show|. This must be called from the appropriate fade state, 89 // kBubbleShowingFadeIn or kBubbleHidingFadeOut, or from the appropriate 90 // fully-shown/hidden state, kBubbleShown or kBubbleHidden. This may be 91 // called at any point during a fade-in or fade-out; it is even possible to 92 // reverse a transition before it has completed. 93 void Fade(bool show); 94 95 // One-shot timer operations to manage the delays associated with the 96 // kBubbleShowingTimer and kBubbleHidingTimer states. StartTimer and 97 // TimerFired must be called from one of these states. StartTimer may be 98 // called while the timer is still running; in that case, the timer will be 99 // reset. CancelTimer may be called from any state. 100 void StartTimer(int64 time_ms); 101 void CancelTimer(); 102 void TimerFired(); 103 104 // Begin the process of showing or hiding the status bubble. These may be 105 // called from any state, and will take the appropriate action to initiate 106 // any state changes that may be needed. 107 void StartShowing(); 108 void StartHiding(); 109 110 // Cancel the expansion timer. 111 void CancelExpandTimer(); 112 113 // The timer factory used for show and hide delay timers. 114 ScopedRunnableMethodFactory<StatusBubbleMac> timer_factory_; 115 116 // The timer factory used for the expansion delay timer. 117 ScopedRunnableMethodFactory<StatusBubbleMac> expand_timer_factory_; 118 119 // Calculate the appropriate frame for the status bubble window. If 120 // |expanded_width|, use entire width of parent frame. 121 NSRect CalculateWindowFrame(bool expanded_width); 122 123 // The window we attach ourselves to. 124 NSWindow* parent_; // WEAK 125 126 // The object that we query about our vertical offset for positioning. 127 id delegate_; // WEAK 128 129 // The window we own. 130 NSWindow* window_; 131 132 // The status text we want to display when there are no URLs to display. 133 NSString* status_text_; 134 135 // The url we want to display when there is no status text to display. 136 NSString* url_text_; 137 138 // The status bubble's current state. Do not write to this field directly; 139 // use SetState(). 140 StatusBubbleState state_; 141 142 // True if operations are to be performed immediately rather than waiting 143 // for delays and transitions. Normally false, this should only be set to 144 // true for testing. 145 bool immediate_; 146 147 // True if the status bubble has been expanded. If the bubble is in the 148 // expanded state and encounters a new URL, change size immediately, 149 // with no hover delay. 150 bool is_expanded_; 151 152 // The original, non-elided URL. 153 GURL url_; 154 155 // Needs to be passed to ElideURL if the original URL string is wider than 156 // the standard bubble width. 157 string16 languages_; 158 159 DISALLOW_COPY_AND_ASSIGN(StatusBubbleMac); 160 }; 161 162 // Delegate interface 163 @interface NSObject(StatusBubbleDelegate) 164 // Called to query the delegate about the frame StatusBubble should position 165 // itself in. Frame is returned in the parent window coordinates. 166 - (NSRect)statusBubbleBaseFrame; 167 168 // Called from SetState to notify the delegate of state changes. 169 - (void)statusBubbleWillEnterState:(StatusBubbleMac::StatusBubbleState)state; 170 @end 171 172 #endif // CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_ 173