1 // Copyright (c) 2011 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.
5 #ifndef CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_
6 #define CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_
10 #import <Cocoa/Cocoa.h>
11 #import <QuartzCore/QuartzCore.h>
13 #include "base/compiler_specific.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/strings/string16.h"
16 #include "chrome/browser/ui/status_bubble.h"
19 class StatusBubbleMacTest
;
20 @
class StatusBubbleWindow
;
22 class StatusBubbleMac
: public StatusBubble
{
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
35 StatusBubbleMac(NSWindow
* parent
, id delegate
);
36 ~StatusBubbleMac() override
;
38 // StatusBubble implementation.
39 void SetStatus(const base::string16
& status
) override
;
40 void SetURL(const GURL
& url
, const std::string
& languages
) override
;
42 void MouseMoved(const gfx::Point
& location
, bool left_content
) override
;
43 void UpdateDownloadShelfVisibility(bool visible
) override
;
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
48 void UpdateSizeAndPosition();
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
);
54 // Expand the bubble to fit a URL too long for the standard bubble size.
58 // Get the current location of the mouse. Protected so that it can be
59 // stubbed out for testing.
60 virtual gfx::Point
GetMouseLocation();
63 friend class StatusBubbleMacTest
;
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
);
69 // Sets the bubble text for SetStatus and SetURL.
70 void SetText(const base::string16
& text
, bool is_url
);
72 // Construct the window/widget if it does not already exist. (Safe to call if
76 // Attaches the status bubble window to its parent window. Safe to call even
77 // when already attached.
80 // Detaches the status bubble window from its parent window.
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.
85 bool is_attached() { return [window_ parentWindow
] != nil
; }
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.
95 // Starts an animation of the bubble window to a specific alpha value over a
96 // specific period of time.
97 void AnimateWindowAlpha(CGFloat alpha
, NSTimeInterval duration
);
99 // Method called from the completion callbacks when a fade-in or fade-out
100 // transition has completed.
101 void AnimationDidStop();
103 // One-shot timer operations to manage the delays associated with the
104 // kBubbleShowingTimer and kBubbleHidingTimer states. StartTimer and
105 // TimerFired must be called from one of these states. StartTimer may be
106 // called while the timer is still running; in that case, the timer will be
107 // reset. CancelTimer may be called from any state.
108 void StartTimer(int64 time_ms
);
112 // Begin the process of showing or hiding the status bubble. These may be
113 // called from any state, and will take the appropriate action to initiate
114 // any state changes that may be needed.
118 // Cancel the expansion timer.
119 void CancelExpandTimer();
121 // Sets the frame of the status bubble window to |window_frame|, adjusting
122 // for the given mouse position if necessary. Protected for use in tests.
123 void SetFrameAvoidingMouse(NSRect window_frame
, const gfx::Point
& mouse_pos
);
125 // Calculate the appropriate frame for the status bubble window. If
126 // |expanded_width|, use entire width of parent frame.
127 NSRect
CalculateWindowFrame(bool expanded_width
);
129 // Returns the flags to be used to round the corners of the status bubble.
130 // Before 10.7, windows have square bottom corners, but in 10.7, the bottom
131 // corners are rounded. This method considers the bubble's placement (as
132 // proposed in window_frame) relative to its parent window in determining
133 // which flags to return. This function may choose to round any corner,
134 // including top corners. Note that there may be other reasons that a
135 // status bubble's corner may be rounded in addition to those dependent on
136 // OS version, and flags will be set or unset elsewhere to address these
138 unsigned long OSDependentCornerFlags(NSRect window_frame
);
140 // The window we attach ourselves to.
141 NSWindow
* parent_
; // WEAK
143 // The object that we query about our vertical offset for positioning.
144 id delegate_
; // WEAK
146 // The window we own.
147 StatusBubbleWindow
* window_
;
149 // The status text we want to display when there are no URLs to display.
150 NSString
* status_text_
;
152 // The url we want to display when there is no status text to display.
155 // The status bubble's current state. Do not write to this field directly;
157 StatusBubbleState state_
;
159 // True if operations are to be performed immediately rather than waiting
160 // for delays and transitions. Normally false, this should only be set to
164 // True if the status bubble has been expanded. If the bubble is in the
165 // expanded state and encounters a new URL, change size immediately,
166 // with no hover delay.
169 // The original, non-elided URL.
172 // Needs to be passed to ElideURL if the original URL string is wider than
173 // the standard bubble width.
174 std::string languages_
;
176 // The factory used to generate weak pointers for the show and hide delay
178 base::WeakPtrFactory
<StatusBubbleMac
> timer_factory_
;
180 // The factory used to generate weak pointers for the expansion delay timer.
181 base::WeakPtrFactory
<StatusBubbleMac
> expand_timer_factory_
;
183 // The factory used to generate weak pointers for the CAAnimation completion
185 base::WeakPtrFactory
<StatusBubbleMac
> completion_handler_factory_
;
187 DISALLOW_COPY_AND_ASSIGN(StatusBubbleMac
);
190 // Delegate interface
191 @interface
NSObject(StatusBubbleDelegate
)
192 // Called to query the delegate about the frame StatusBubble should position
193 // itself in. Frame is returned in the parent window coordinates.
194 - (NSRect
)statusBubbleBaseFrame
;
196 // Called from SetState to notify the delegate of state changes.
197 - (void)statusBubbleWillEnterState
:(StatusBubbleMac::StatusBubbleState
)state
;
200 #endif // CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_