// 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_MANAGER_H_
#define CHROME_BROWSER_UI_PANELS_PANEL_MANAGER_H_
#include <list>
#include <vector>
#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/panels/display_settings_provider.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_collection.h"
#include "chrome/browser/ui/panels/panel_constants.h"
#include "ui/gfx/rect.h"
class DetachedPanelCollection;
class DockedPanelCollection;
class GURL;
class PanelDragController;
class PanelResizeController;
class PanelMouseWatcher;
class StackedPanelCollection;
// This class manages a set of panels.
class PanelManager : public DisplaySettingsProvider::DisplayObserver,
public DisplaySettingsProvider::FullScreenObserver {
public:
typedef std::list<StackedPanelCollection*> Stacks;
enum CreateMode {
CREATE_AS_DOCKED, // Creates a docked panel. The default.
CREATE_AS_DETACHED // Creates a detached panel.
};
// Returns a single instance.
static PanelManager* GetInstance();
// Tells PanelManager to use |provider| for testing purpose. This has to be
// called before GetInstance.
static void SetDisplaySettingsProviderForTesting(
DisplaySettingsProvider* provider);
// Returns true if panels should be used for the extension.
static bool ShouldUsePanels(const std::string& extension_id);
// Returns true if panel stacking support is enabled.
static bool IsPanelStackingEnabled();
// Returns true if a panel can be system-minimized by the desktop
// environment. Some desktop environment, like Unity, does not trigger the
// "window-state-event" which prevents the minimize and unminimize from
// working.
static bool CanUseSystemMinimize();
// Returns the default top-left position for a detached panel.
gfx::Point GetDefaultDetachedPanelOrigin();
// Creates a panel and returns it. The panel might be queued for display
// later.
// |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.
// |requested_bounds| is the desired bounds for the panel, but actual
// bounds may differ after panel layout depending on create |mode|.
// |mode| indicates whether panel should be created as docked or detached.
Panel* CreatePanel(const std::string& app_name,
Profile* profile,
const GURL& url,
const gfx::Rect& requested_bounds,
CreateMode mode);
// Close all panels (asynchronous). Panels will be removed after closing.
void CloseAll();
// Asynchronous confirmation of panel having been closed.
void OnPanelClosed(Panel* panel);
// Creates a StackedPanelCollection and returns it.
StackedPanelCollection* CreateStack();
// Deletes |stack|. The stack must be empty at the time of deletion.
void RemoveStack(StackedPanelCollection* stack);
// Returns the maximum size that panel can be auto-resized or resized by the
// API.
int GetMaxPanelWidth(const gfx::Rect& work_area) const;
int GetMaxPanelHeight(const gfx::Rect& work_area) const;
// Drags the given panel.
// |mouse_location| is in screen coordinate system.
void StartDragging(Panel* panel, const gfx::Point& mouse_location);
void Drag(const gfx::Point& mouse_location);
void EndDragging(bool cancelled);
// Resizes the given panel.
// |mouse_location| is in screen coordinate system.
void StartResizingByMouse(Panel* panel, const gfx::Point& mouse_location,
panel::ResizingSides sides);
void ResizeByMouse(const gfx::Point& mouse_location);
void EndResizingByMouse(bool cancelled);
// Invoked when a panel's expansion state changes.
void OnPanelExpansionStateChanged(Panel* panel);
// Moves the |panel| to a different collection.
void MovePanelToCollection(Panel* panel,
PanelCollection* target_collection,
PanelCollection::PositioningMask positioning_mask);
// Returns true if we should bring up the titlebars, given the current mouse
// point.
bool ShouldBringUpTitlebars(int mouse_x, int mouse_y) const;
// Brings up or down the titlebars for all minimized panels.
void BringUpOrDownTitlebars(bool bring_up);
std::vector<Panel*> GetDetachedAndStackedPanels() const;
int num_panels() const;
std::vector<Panel*> panels() const;
const Stacks& stacks() const { return stacks_; }
int num_stacks() const { return stacks_.size(); }
PanelDragController* drag_controller() const {
return drag_controller_.get();
}
#ifdef UNIT_TEST
PanelResizeController* resize_controller() const {
return resize_controller_.get();
}
#endif
DisplaySettingsProvider* display_settings_provider() const {
return display_settings_provider_.get();
}
PanelMouseWatcher* mouse_watcher() const {
return panel_mouse_watcher_.get();
}
DetachedPanelCollection* detached_collection() const {
return detached_collection_.get();
}
DockedPanelCollection* docked_collection() const {
return docked_collection_.get();
}
// Reduces time interval in tests to shorten test run time.
// Wrapper should be used around all time intervals in panels code.
static inline double AdjustTimeInterval(double interval) {
if (shorten_time_intervals_)
return interval / 500.0;
else
return interval;
}
bool auto_sizing_enabled() const {
return auto_sizing_enabled_;
}
// Called from native level when panel animation ends.
void OnPanelAnimationEnded(Panel* panel);
#ifdef UNIT_TEST
static void shorten_time_intervals_for_testing() {
shorten_time_intervals_ = true;
}
void set_display_settings_provider(
DisplaySettingsProvider* display_settings_provider) {
display_settings_provider_.reset(display_settings_provider);
}
void enable_auto_sizing(bool enabled) {
auto_sizing_enabled_ = enabled;
}
void SetMouseWatcherForTesting(PanelMouseWatcher* watcher) {
SetMouseWatcher(watcher);
}
#endif
private:
friend struct base::DefaultLazyInstanceTraits<PanelManager>;
PanelManager();
virtual ~PanelManager();
void Initialize(DisplaySettingsProvider* provider);
// Overridden from DisplaySettingsProvider::DisplayObserver:
virtual void OnDisplayChanged() OVERRIDE;
// Overridden from DisplaySettingsProvider::FullScreenObserver:
virtual void OnFullScreenModeChanged(bool is_full_screen) OVERRIDE;
// Returns the collection to which a new panel should add. The new panel
// is expected to be created with |bounds| and |mode|. The size of |bounds|
// could be used to determine which collection is more appropriate to have
// the new panel. Upon return, |positioning_mask| contains the required mask
// to be applied when the new panel is being added to the collection.
PanelCollection* GetCollectionForNewPanel(
Panel* new_panel,
const gfx::Rect& bounds,
CreateMode mode,
PanelCollection::PositioningMask* positioning_mask);
// Tests may want to use a mock panel mouse watcher.
void SetMouseWatcher(PanelMouseWatcher* watcher);
// Tests may want to shorten time intervals to reduce running time.
static bool shorten_time_intervals_;
scoped_ptr<DetachedPanelCollection> detached_collection_;
scoped_ptr<DockedPanelCollection> docked_collection_;
Stacks stacks_;
scoped_ptr<PanelDragController> drag_controller_;
scoped_ptr<PanelResizeController> resize_controller_;
// Use a mouse watcher to know when to bring up titlebars to "peek" at
// minimized panels. Mouse movement is only tracked when there is a minimized
// panel.
scoped_ptr<PanelMouseWatcher> panel_mouse_watcher_;
scoped_ptr<DisplaySettingsProvider> display_settings_provider_;
// Whether or not bounds will be updated when the preferred content size is
// changed. The testing code could set this flag to false so that other tests
// will not be affected.
bool auto_sizing_enabled_;
DISALLOW_COPY_AND_ASSIGN(PanelManager);
};
#endif // CHROME_BROWSER_UI_PANELS_PANEL_MANAGER_H_