text: // Copyright (c) 2012 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_PANELS_PANEL_H_
  #define CHROME_BROWSER_UI_PANELS_PANEL_H_
  
  #include <string>
  
  #include "base/gtest_prod_util.h"
  #include "base/memory/scoped_ptr.h"
  #include "base/memory/weak_ptr.h"
  #include "base/strings/string16.h"
  #include "chrome/browser/command_updater.h"
  #include "chrome/browser/command_updater_delegate.h"
  #include "chrome/browser/sessions/session_id.h"
  #include "chrome/browser/ui/panels/panel_constants.h"
  #include "content/public/browser/notification_observer.h"
  #include "content/public/browser/notification_registrar.h"
  #include "ui/base/base_window.h"
  #include "ui/gfx/image/image.h"
  #include "ui/gfx/rect.h"
  
  class GURL;
  class NativePanel;
  class PanelCollection;
  class PanelHost;
  class PanelManager;
  class Profile;
  class StackedPanelCollection;
  
  namespace content {
  class WebContents;
  struct NativeWebKeyboardEvent;
  }
  
  namespace extensions {
  class Extension;
  class WindowController;
  }
  
  // A platform independent implementation of ui::BaseWindow for Panels.
  // This class gets the first crack at all the ui::BaseWindow calls for Panels
  // and does one or more of the following:
  // - Do nothing.  The function is not relevant to Panels.
  // - Do Panel specific platform independent processing and then invoke the
  //   function on the platform specific member. For example, restrict panel
  //   size to certain limits.
  // - Invoke an appropriate PanelManager function to do stuff that might affect
  //   other Panels. For example deleting a panel would rearrange other panels.
  class Panel : public ui::BaseWindow,
                public CommandUpdaterDelegate,
                public content::NotificationObserver {
   public:
    enum ExpansionState {
      // The panel is fully expanded with both title-bar and the client-area.
      EXPANDED,
      // The panel is shown with the title-bar only.
      TITLE_ONLY,
      // The panel is shown with 3-pixel line.
      MINIMIZED
    };
  
    // Controls how the attention should be drawn.
    enum AttentionMode {
      // Uses the panel attention. The panel's titlebar would be painted
      // differently to attract the user's attention. This is the default mode.
      USE_PANEL_ATTENTION = 0x01,
      // Uses the system attention. On Windows or Linux (depending on Window
      // Manager), the app icon on taskbar will be flashed. On MacOS, the dock
      // icon will jump once.
      USE_SYSTEM_ATTENTION = 0x02
    };
  
    virtual ~Panel();
  
    // Returns the PanelManager associated with this panel.
    PanelManager* manager() const;
  
    const std::string& app_name() const { return app_name_; }
    const gfx::Image& app_icon() const { return app_icon_; }
    const SessionID& session_id() const { return session_id_; }
    extensions::WindowController* extension_window_controller() const {
      return extension_window_controller_.get();
    }
    const std::string extension_id() const;
  
    CommandUpdater* command_updater();
    Profile* profile() const;
  
    const extensions::Extension* GetExtension() const;
  
    // Returns web contents of the panel, if any. There may be none if web
    // contents have not been added to the panel yet.
    content::WebContents* GetWebContents() const;
  
    void SetExpansionState(ExpansionState new_expansion_state);
  
    bool IsDrawingAttention() const;
  
    // This function will only get called by PanelManager when full screen mode
    // changes i.e it gets called when an app goes into full screen mode or when
    // an app exits full screen mode. Panel should respond by making sure
    // a) it does not go on top when some app enters full screen mode.
    // b) it remains on top when an app exits full screen mode.
    void FullScreenModeChanged(bool is_full_screen);
  
    int TitleOnlyHeight() const;
  
    // Returns true if the panel can show minimize or restore button in its
    // titlebar, depending on its state.
    bool CanShowMinimizeButton() const;
    bool CanShowRestoreButton() const;
  
    // ui::BaseWindow overrides.
    virtual bool IsActive() const OVERRIDE;
    virtual bool IsMaximized() const OVERRIDE;
    virtual bool IsMinimized() const OVERRIDE;
    virtual bool IsFullscreen() const OVERRIDE;
    virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
    virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
    virtual ui::WindowShowState GetRestoredState() const OVERRIDE;
    virtual gfx::Rect GetBounds() const OVERRIDE;
    virtual void Show() OVERRIDE;
    virtual void Hide() OVERRIDE;
    virtual void ShowInactive() OVERRIDE;
    virtual void Close() OVERRIDE;
    virtual void Activate() OVERRIDE;
    virtual void Deactivate() OVERRIDE;
    virtual void Maximize() OVERRIDE;
    virtual void Minimize() OVERRIDE;
    virtual void Restore() OVERRIDE;
    virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
    virtual void FlashFrame(bool flash) OVERRIDE;
    virtual bool IsAlwaysOnTop() const OVERRIDE;
  
    // Overridden from CommandUpdaterDelegate:
    virtual void ExecuteCommandWithDisposition(
        int id,
        WindowOpenDisposition disposition) OVERRIDE;
  
    // content::NotificationObserver overrides.
    virtual void Observe(int type,
                         const content::NotificationSource& source,
                         const content::NotificationDetails& details) OVERRIDE;
  
    // Construct a native panel implementation.
    static NativePanel* CreateNativePanel(Panel* panel,
                                          const gfx::Rect& bounds,
                                          bool always_on_top);
  
    NativePanel* native_panel() const { return native_panel_; }
  
    // Invoked when the native panel has detected a mouse click on the
    // panel's titlebar, minimize or restore buttons. Behavior of the
    // click may be modified as indicated by |modifier|.
    void OnTitlebarClicked(panel::ClickModifier modifier);
    void OnMinimizeButtonClicked(panel::ClickModifier modifier);
    void OnRestoreButtonClicked(panel::ClickModifier modifier);
  
    // Used on platforms where the panel cannot determine its window size
    // until the window has been created. (e.g. GTK)
    void OnWindowSizeAvailable();
  
    // Asynchronous completion of panel close request.
    void OnNativePanelClosed();
  
    // May be NULL if:
    // * panel is newly created and has not been positioned yet.
    // * panel is being closed asynchronously.
    // Please use it with caution.
    PanelCollection* collection() const { return collection_; }
  
    // Sets the current panel collection that contains this panel.
    void set_collection(PanelCollection* new_collection) {
      collection_ = new_collection;
    }
  
    StackedPanelCollection* stack() const;
  
    ExpansionState expansion_state() const { return expansion_state_; }
    const gfx::Size& min_size() const { return min_size_; }
    const gfx::Size& max_size() const { return max_size_; }
    bool auto_resizable() const { return auto_resizable_; }
  
    bool in_preview_mode() const { return in_preview_mode_; }
  
    panel::Resizability CanResizeByMouse() const;
  
    AttentionMode attention_mode() const { return attention_mode_; }
    void set_attention_mode(AttentionMode attention_mode) {
      attention_mode_ = attention_mode;
    }
  
    // The full size is the size of the panel when it is detached or expanded
    // in the docked collection and squeezing mode is not on.
    gfx::Size full_size() const { return full_size_; }
    void set_full_size(const gfx::Size& size) { full_size_ = size; }
  
    // Panel must be initialized to be "fully created" and ready for use.
    // Only called by PanelManager.
    bool initialized() const { return initialized_; }
    void Initialize(const GURL& url, const gfx::Rect& bounds, bool always_on_top);
  
    // This is different from BaseWindow::SetBounds():
    // * SetPanelBounds() is only called by PanelManager to manage its position.
    // * SetBounds() is called by the API to try to change the bounds, which may
    //   only change the size for Panel.
    void SetPanelBounds(const gfx::Rect& bounds);
  
    // Updates the panel bounds instantly without any animation.
    void SetPanelBoundsInstantly(const gfx::Rect& bounds);
  
    // Ensures that the panel's size does not exceed the work area by updating
    // maximum and full size of the panel. This is called each time when display
    // settings are changed. Note that bounds are not updated here and the call
    // of setting bounds or refreshing layout should be called after this.
    void LimitSizeToWorkArea(const gfx::Rect& work_area);
  
    // Sets whether the panel will auto resize according to its content.
    void SetAutoResizable(bool resizable);
  
    // Configures the web contents for auto resize, including configurations
    // on the renderer and detecting renderer changes.
    void EnableWebContentsAutoResize(content::WebContents* web_contents);
  
    // Invoked when the preferred window size of the given panel might need to
    // get changed due to the contents being auto-resized.
    void OnContentsAutoResized(const gfx::Size& new_content_size);
  
    // Resizes the panel and sets the origin. Invoked when the panel is resized
    // via the mouse.
    void OnWindowResizedByMouse(const gfx::Rect& new_bounds);
  
    // Sets minimum and maximum size for the panel.
    void SetSizeRange(const gfx::Size& min_size, const gfx::Size& max_size);
  
    // Updates the maximum size of the panel so that it's never smaller than the
    // panel's desired size. Note that even if the user resizes the panel smaller
    // later, the increased maximum size will still be in effect. Since it's not
    // possible currently to switch the panel back to autosizing from
    // user-resizable, it should not be a problem.
    void IncreaseMaxSize(const gfx::Size& desired_panel_size);
  
    // Handles keyboard events coming back from the renderer.
    void HandleKeyboardEvent(const content::NativeWebKeyboardEvent& event);
  
    // Whether the panel window is always on top.
    void SetAlwaysOnTop(bool on_top);
  
    // Sets whether the panel is shown in preview mode. When the panel is
    // being dragged, it is in preview mode.
    void SetPreviewMode(bool in_preview_mode);
  
    // Sets up the panel for being resizable by the user - for example,
    // enables the resize mouse cursors when mouse is hovering over the edges.
    void EnableResizeByMouse(bool enable);
  
    // Sets whether the minimize or restore button, if any, are visible.
    void UpdateMinimizeRestoreButtonVisibility();
  
    // Changes the preferred size to acceptable based on min_size() and max_size()
    gfx::Size ClampSize(const gfx::Size& size) const;
  
    // Called when the panel's active state changes.
    // |active| is true if panel became active.
    void OnActiveStateChanged(bool active);
  
    // Called when the panel starts/ends the user resizing.
    void OnPanelStartUserResizing();
    void OnPanelEndUserResizing();
  
    // Gives beforeunload handlers the chance to cancel the close.
    bool ShouldCloseWindow();
  
    // Invoked when the window containing us is closing. Performs the necessary
    // cleanup.
    void OnWindowClosing();
  
    // Executes a command if it's enabled.
    // Returns true if the command is executed.
    bool ExecuteCommandIfEnabled(int id);
  
    // Gets the title of the window from the web contents.
    string16 GetWindowTitle() const;
  
    // Gets the Favicon of the web contents.
    gfx::Image GetCurrentPageIcon() const;
  
    // Updates the title bar to display the current title and icon.
    void UpdateTitleBar();
  
    // Updates UI to reflect change in loading state.
    void LoadingStateChanged(bool is_loading);
  
    // Updates UI to reflect that the web cotents receives the focus.
    void WebContentsFocused(content::WebContents* contents);
  
    // Moves the panel by delta instantly.
    void MoveByInstantly(const gfx::Vector2d& delta_origin);
  
    // Applies |corner_style| to the panel window.
    void SetWindowCornerStyle(panel::CornerStyle corner_style);
  
    // Performs the system minimize for the panel, i.e. becoming iconic.
    void MinimizeBySystem();
  
    bool IsMinimizedBySystem() const;
  
    // Returns true if the panel is shown in the active desktop. The user could
    // create or use multiple desktops or workspaces.
    bool IsShownOnActiveDesktop() const;
  
    // Turns on/off the shadow effect around the window shape.
    void ShowShadow(bool show);
  
   protected:
    // Panel can only be created using PanelManager::CreatePanel() or subclass.
    // |app_name| is the default title for Panels when the page content does not
    // provide a title. For extensions, this is usually the application name
    // generated from the extension id.
    Panel(Profile* profile, const std::string& app_name,
          const gfx::Size& min_size, const gfx::Size& max_size);
  
   private:
    friend class PanelManager;
    friend class PanelBrowserTest;
  
    enum MaxSizePolicy {
      // Default maximum size is proportional to the work area.
      DEFAULT_MAX_SIZE,
      // Custom maximum size is used when the panel is resized by the user.
      CUSTOM_MAX_SIZE
    };
  
    void OnImageLoaded(const gfx::Image& image);
  
    // Initialize state for all supported commands.
    void InitCommandState();
  
    // Configures the renderer for auto resize (if auto resize is enabled).
    void ConfigureAutoResize(content::WebContents* web_contents);
  
    // Load the app's image, firing a load state change when loaded.
    void UpdateAppIcon();
  
    // Prepares a title string for display (removes embedded newlines, etc).
    static void FormatTitleForDisplay(string16* title);
  
    // The application name that is also the name of the window when the
    // page content does not provide a title.
    // This name should be set when the panel is created.
    const std::string app_name_;
  
    Profile* profile_;
  
    // Current collection of panels to which this panel belongs. This determines
    // the panel's screen layout.
    PanelCollection* collection_;  // Owned by PanelManager.
  
    bool initialized_;
  
    // Stores the full size of the panel so we can restore it after it's
    // been minimized or squeezed due to lack of space in the collection.
    gfx::Size full_size_;
  
    // This is the minimum size that the panel can shrink to.
    gfx::Size min_size_;
  
    // This is the size beyond which the panel is not going to grow to accomodate
    // the growing content and WebKit would add the scrollbars in such case.
    gfx::Size max_size_;
  
    MaxSizePolicy max_size_policy_;
  
    // True if this panel auto resizes based on content.
    bool auto_resizable_;
  
    // True if this panel is in preview mode. When in preview mode, panel bounds
    // should not be affected by layout refresh. This is currently used by drag
    // controller to add a panel to the collection without causing its bounds to
    // change.
    bool in_preview_mode_;
  
    // Platform specifc implementation for panels.  It'd be one of
    // PanelGtk/PanelView/PanelCocoa.
    NativePanel* native_panel_;  // Weak, owns us.
  
    AttentionMode attention_mode_;
  
    ExpansionState expansion_state_;
  
    // The CommandUpdater manages the window commands.
    CommandUpdater command_updater_;
  
    content::NotificationRegistrar registrar_;
    const SessionID session_id_;
    scoped_ptr<extensions::WindowController> extension_window_controller_;
    scoped_ptr<PanelHost> panel_host_;
  
    // Icon showed in the task bar.
    gfx::Image app_icon_;
  
    base::WeakPtrFactory<Panel> image_loader_ptr_factory_;
  
    DISALLOW_COPY_AND_ASSIGN(Panel);
  };
  
  #endif  // CHROME_BROWSER_UI_PANELS_PANEL_H_
  