Home | History | Annotate | Download | only in cocoa
      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.
      4 
      5 #ifndef CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_
      6 #define CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_
      7 
      8 #include <string>
      9 
     10 #import <Cocoa/Cocoa.h>
     11 #import <QuartzCore/QuartzCore.h>
     12 
     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"
     17 #include "url/gurl.h"
     18 
     19 class StatusBubbleMacTest;
     20 @class StatusBubbleWindow;
     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 base::string16& status) OVERRIDE;
     40   virtual void SetURL(const GURL& url, const std::string& languages) OVERRIDE;
     41   virtual void Hide() OVERRIDE;
     42   virtual void MouseMoved(const gfx::Point& location,
     43                           bool left_content) OVERRIDE;
     44   virtual void UpdateDownloadShelfVisibility(bool visible) OVERRIDE;
     45 
     46   // Mac-specific method: Update the size and position of the status bubble to
     47   // match the parent window. Safe to call even when the status bubble does not
     48   // exist.
     49   void UpdateSizeAndPosition();
     50 
     51   // Mac-specific method: Change the parent window of the status bubble. Safe to
     52   // call even when the status bubble does not exist.
     53   void SwitchParentWindow(NSWindow* parent);
     54 
     55   // Expand the bubble to fit a URL too long for the standard bubble size.
     56   void ExpandBubble();
     57 
     58  protected:
     59   // Get the current location of the mouse. Protected so that it can be
     60   // stubbed out for testing.
     61   virtual gfx::Point GetMouseLocation();
     62 
     63  private:
     64   friend class StatusBubbleMacTest;
     65 
     66   // Setter for state_.  Use this instead of writing to state_ directly so
     67   // that state changes can be observed by unit tests.
     68   void SetState(StatusBubbleState state);
     69 
     70   // Sets the bubble text for SetStatus and SetURL.
     71   void SetText(const base::string16& text, bool is_url);
     72 
     73   // Construct the window/widget if it does not already exist. (Safe to call if
     74   // it does.)
     75   void Create();
     76 
     77   // Attaches the status bubble window to its parent window. Safe to call even
     78   // when already attached.
     79   void Attach();
     80 
     81   // Detaches the status bubble window from its parent window.
     82   void Detach();
     83 
     84   // Is the status bubble attached to the browser window? It should be attached
     85   // when shown and during any fades, but should be detached when hidden.
     86   bool is_attached() { return [window_ parentWindow] != nil; }
     87 
     88   // Begins fading the status bubble window in or out depending on the value
     89   // of |show|.  This must be called from the appropriate fade state,
     90   // kBubbleShowingFadeIn or kBubbleHidingFadeOut, or from the appropriate
     91   // fully-shown/hidden state, kBubbleShown or kBubbleHidden.  This may be
     92   // called at any point during a fade-in or fade-out; it is even possible to
     93   // reverse a transition before it has completed.
     94   void Fade(bool show);
     95 
     96   // Starts an animation of the bubble window to a specific alpha value over a
     97   // specific period of time.
     98   void AnimateWindowAlpha(CGFloat alpha, NSTimeInterval duration);
     99 
    100   // Method called from the completion callbacks when a fade-in or fade-out
    101   // transition has completed.
    102   void AnimationDidStop();
    103 
    104   // One-shot timer operations to manage the delays associated with the
    105   // kBubbleShowingTimer and kBubbleHidingTimer states.  StartTimer and
    106   // TimerFired must be called from one of these states.  StartTimer may be
    107   // called while the timer is still running; in that case, the timer will be
    108   // reset. CancelTimer may be called from any state.
    109   void StartTimer(int64 time_ms);
    110   void CancelTimer();
    111   void TimerFired();
    112 
    113   // Begin the process of showing or hiding the status bubble.  These may be
    114   // called from any state, and will take the appropriate action to initiate
    115   // any state changes that may be needed.
    116   void StartShowing();
    117   void StartHiding();
    118 
    119   // Cancel the expansion timer.
    120   void CancelExpandTimer();
    121 
    122   // Sets the frame of the status bubble window to |window_frame|, adjusting
    123   // for the given mouse position if necessary. Protected for use in tests.
    124   void SetFrameAvoidingMouse(NSRect window_frame, const gfx::Point& mouse_pos);
    125 
    126   // Calculate the appropriate frame for the status bubble window. If
    127   // |expanded_width|, use entire width of parent frame.
    128   NSRect CalculateWindowFrame(bool expanded_width);
    129 
    130   // Returns the flags to be used to round the corners of the status bubble.
    131   // Before 10.7, windows have square bottom corners, but in 10.7, the bottom
    132   // corners are rounded. This method considers the bubble's placement (as
    133   // proposed in window_frame) relative to its parent window in determining
    134   // which flags to return. This function may choose to round any corner,
    135   // including top corners. Note that there may be other reasons that a
    136   // status bubble's corner may be rounded in addition to those dependent on
    137   // OS version, and flags will be set or unset elsewhere to address these
    138   // concerns.
    139   unsigned long OSDependentCornerFlags(NSRect window_frame);
    140 
    141   // The window we attach ourselves to.
    142   NSWindow* parent_;  // WEAK
    143 
    144   // The object that we query about our vertical offset for positioning.
    145   id delegate_;  // WEAK
    146 
    147   // The window we own.
    148   StatusBubbleWindow* window_;
    149 
    150   // The status text we want to display when there are no URLs to display.
    151   NSString* status_text_;
    152 
    153   // The url we want to display when there is no status text to display.
    154   NSString* url_text_;
    155 
    156   // The status bubble's current state.  Do not write to this field directly;
    157   // use SetState().
    158   StatusBubbleState state_;
    159 
    160   // True if operations are to be performed immediately rather than waiting
    161   // for delays and transitions.  Normally false, this should only be set to
    162   // true for testing.
    163   bool immediate_;
    164 
    165   // True if the status bubble has been expanded. If the bubble is in the
    166   // expanded state and encounters a new URL, change size immediately,
    167   // with no hover delay.
    168   bool is_expanded_;
    169 
    170   // The original, non-elided URL.
    171   GURL url_;
    172 
    173   // Needs to be passed to ElideURL if the original URL string is wider than
    174   // the standard bubble width.
    175   std::string languages_;
    176 
    177   // The factory used to generate weak pointers for the show and hide delay
    178   // timers.
    179   base::WeakPtrFactory<StatusBubbleMac> timer_factory_;
    180 
    181   // The factory used to generate weak pointers for the expansion delay timer.
    182   base::WeakPtrFactory<StatusBubbleMac> expand_timer_factory_;
    183 
    184   // The factory used to generate weak pointers for the CAAnimation completion
    185   // handlers.
    186   base::WeakPtrFactory<StatusBubbleMac> completion_handler_factory_;
    187 
    188   DISALLOW_COPY_AND_ASSIGN(StatusBubbleMac);
    189 };
    190 
    191 // Delegate interface
    192 @interface NSObject(StatusBubbleDelegate)
    193 // Called to query the delegate about the frame StatusBubble should position
    194 // itself in. Frame is returned in the parent window coordinates.
    195 - (NSRect)statusBubbleBaseFrame;
    196 
    197 // Called from SetState to notify the delegate of state changes.
    198 - (void)statusBubbleWillEnterState:(StatusBubbleMac::StatusBubbleState)state;
    199 @end
    200 
    201 #endif  // CHROME_BROWSER_UI_COCOA_STATUS_BUBBLE_MAC_H_
    202