// Copyright (c) 2010 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_AEROPEEK_MANAGER_H_
#define CHROME_BROWSER_AEROPEEK_MANAGER_H_
#pragma once

#include <windows.h>

#include <list>

#include "chrome/browser/tabs/tab_strip_model_observer.h"
#include "ui/gfx/insets.h"

namespace gfx {
class Size;
}
class AeroPeekWindow;
class SkBitmap;
class TabContents;

// A class which defines interfaces called from AeroPeekWindow.
// This class is used for dispatching an event received by a thumbnail window
// and for retrieving information from Chrome.
// An AeroPeek window receives the following events:
// * A user clicks an AeroPeek thumbnail.
//   We need to select a tab associated with this window.
// * A user closes an AeroPeek thumbnail.
//   We need to close a tab associated with this window.
// * A user clicks a toolbar button in an AeroPeek window.
//   We may need to dispatch this button event to a tab associated with this
//   thumbnail window.
//   <http://msdn.microsoft.com/en-us/library/dd378460(VS.85).aspx#thumbbars>.
// Also, it needs the following information of the browser:
// * The bitmap of a tab associated with this window.
//   This bitmap is used for creating thumbnail and preview images.
// * The rectangle of a browser frame.
//   This rectangle is used for pasting the above bitmap to the right position
//   and for marking the tab-content area as opaque.
// We assume these functions are called only from a UI thread (i.e.
// Chrome_BrowserMain).
class AeroPeekWindowDelegate {
 public:
  virtual void ActivateTab(int tab_id) = 0;
  virtual void CloseTab(int tab_id) = 0;
  virtual void GetContentInsets(gfx::Insets* insets) = 0;
  virtual bool GetTabThumbnail(int tab_id, SkBitmap* thumbnail) = 0;
  virtual bool GetTabPreview(int tab_id, SkBitmap* preview) = 0;

 protected:
  virtual ~AeroPeekWindowDelegate() {}
};

// A class that implements AeroPeek of Windows 7:
// <http://msdn.microsoft.com/en-us/library/dd378460(VS.85).aspx#thumbnails>.
// Windows 7 can dispay a thumbnail image of each tab to its taskbar so that
// a user can preview the contents of a tab (AeroPeek), choose a tab, close
// a tab, etc.
// This class implements the TabStripModelObserver interface to receive the
// following events sent from TabStripModel and dispatch them to Windows:
// * A tab is added.
//   This class adds a thumbnail window for this tab to the thumbnail list
//   of Windows.
// * A tab is being closed.
//   This class deletes the thumbnail window associated with this tab from the
//   thumbnail list of Windows.
// * A tab has been updated.
//   This class updates the image of the thumbnail window associated with this
//   tab.
// Also, this class receives events sent from Windows via thumbnail windows to
// TabStripModel:
// * A thumbnail window is closed.
//   Ask TabStrip to close the tab associated with this thumbnail window.
// * A thumbnail window is selected.
//   Ask TabStrip to activate the tab associated with this thumbnail window.
//
// The simplest usage of this class is:
// 1. Create an instance of TabThumbnailManager.
// 2. Add this instance to the observer list of a TabStrip object.
//
//      scoped_ptr<TabThumbnailManager> manager;
//      manager.reset(new TabThumbnailManager(
//          frame_->GetWindow()->GetNativeWindow(),
//          border_left,
//          border_top,
//          toolbar_top));
//      g_browser->tabstrip_model()->AddObserver(manager);
//
// 3. Remove this instance from the observer list of the TabStrip object when
//    we don't need it.
//
//      g_browser->tabstrip_model()->RemoveObserver(manager);
//
class AeroPeekManager : public TabStripModelObserver,
                        public AeroPeekWindowDelegate {
 public:
  explicit AeroPeekManager(HWND application_window);
  virtual ~AeroPeekManager();

  // Sets the margins of the "user-perceived content area".
  // (See comments of |content_insets_|).
  void SetContentInsets(const gfx::Insets& insets);

  // Returns whether or not we should enable Tab Thumbnailing and Aero Peek
  // of Windows 7.
  static bool Enabled();

  // Overridden from TabStripModelObserver:
  virtual void TabInsertedAt(TabContentsWrapper* contents,
                             int index,
                             bool foreground);
  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
                             TabContentsWrapper* new_contents,
                             int index,
                             bool user_gesture);
  virtual void TabMoved(TabContentsWrapper* contents,
                        int from_index,
                        int to_index,
                        bool pinned_state_changed);
  virtual void TabChangedAt(TabContentsWrapper* contents,
                            int index,
                            TabChangeType change_type);
  virtual void TabReplacedAt(TabStripModel* tab_strip_model,
                             TabContentsWrapper* old_contents,
                             TabContentsWrapper* new_contents,
                             int index);

  // Overriden from TabThumbnailWindowDelegate:
  virtual void CloseTab(int tab_id);
  virtual void ActivateTab(int tab_id);
  virtual void GetContentInsets(gfx::Insets* insets);
  virtual bool GetTabThumbnail(int tab_id, SkBitmap* thumbnail);
  virtual bool GetTabPreview(int tab_id, SkBitmap* preview);

 private:
  // Deletes the TabThumbnailWindow object associated with the specified
  // Tab ID.
  void DeleteAeroPeekWindow(int tab_id);

  // If there is an AeroPeekWindow associated with |tab| it is removed and
  // deleted.
  void DeleteAeroPeekWindowForTab(TabContentsWrapper* tab);

  // Retrieves the AeroPeekWindow object associated with the specified
  // Tab ID.
  AeroPeekWindow* GetAeroPeekWindow(int tab_id) const;

  // If an AeroPeekWindow hasn't been created for |tab| yet, one is created.
  // |foreground| is true if the tab is selected.
  void CreateAeroPeekWindowIfNecessary(TabContentsWrapper* tab,
                                       bool foreground);

  // Returns a rectangle that fits into the destination rectangle and keeps
  // the pixel-aspect ratio of the source one.
  // (This function currently uses the longer-fit algorithm as IE8 does.)
  void GetOutputBitmapSize(const gfx::Size& destination,
                           const gfx::Size& source,
                           gfx::Size* output) const;

  // Returns the TabContents object associated with the specified Tab ID only
  // if it is alive.
  // Since Windows cannot send AeroPeek events directly to Chrome windows, we
  // use a place-holder window to receive AeroPeek events. So, when Windows
  // sends an AeroPeek event, the corresponding tab (and TabContents) may have
  // been deleted by Chrome. To prevent us from accessing deleted TabContents,
  // we need to check if the tab is still alive.
  TabContents* GetTabContents(int tab_id) const;

  // Returns the tab ID from the specified TabContents.
  int GetTabID(TabContents* contents) const;

 private:
  // The parent window of the place-holder windows used by AeroPeek.
  // In the case of Chrome, this window becomes a browser frame.
  HWND application_window_;

  // The list of the place-holder windows used by AeroPeek.
  std::list<AeroPeekWindow*> tab_list_;

  // The left and top borders of the frame window.
  // When we create a preview bitmap, we use these values for preventing from
  // over-writing the area of the browser frame.
  int border_left_;
  int border_top_;

  // The top position of the toolbar.
  // This value is used for setting the alpha values of the frame area so a
  // preview image can use transparent colors only in the frame area.
  int toolbar_top_;

  // The margins of the "user-perceived content area".
  // This value is used for pasting a tab image onto this "user-perceived
  // content area" when creating a preview image.
  gfx::Insets content_insets_;
};

#endif  // CHROME_BROWSER_AEROPEEK_MANAGER_H_