#define ATHENA_WM_SPLIT_VIEW_CONTROLLER_H_
#include "athena/athena_export.h"
+#include "athena/util/drag_handle.h"
#include "athena/wm/bezel_controller.h"
+#include "athena/wm/public/window_manager_observer.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
namespace gfx {
+class Rect;
class Transform;
}
+namespace aura {
+class ScopedWindowTargeter;
+class Window;
+class WindowTargeter;
+}
+
+namespace views {
+class ViewTargeterDelegate;
+class Widget;
+}
+
namespace athena {
class WindowListProvider;
// Responsible for entering split view mode, exiting from split view mode, and
// laying out the windows in split view mode.
class ATHENA_EXPORT SplitViewController
- : public BezelController::ScrollDelegate {
+ : public BezelController::ScrollDelegate,
+ public DragHandleScrollDelegate,
+ public WindowManagerObserver {
public:
SplitViewController(aura::Window* container,
WindowListProvider* window_list_provider);
virtual ~SplitViewController();
+ bool CanActivateSplitViewMode() const;
bool IsSplitViewModeActive() const;
// Activates split-view mode with |left| and |right| windows. If |left| and/or
// |right| is NULL, then the first window in the window-list (which is neither
- // |left| nor |right|) is selected instead.
- void ActivateSplitMode(aura::Window* left, aura::Window* right);
-
- // Resets the internal state to an inactive state. Calling this does not
- // change the window bounds/transforms etc. The caller must take care of
- // making any necessary changes.
+ // |left| nor |right|) is selected instead. |to_activate| indicates which of
+ // |left| or |right| should be activated. If |to_activate| is NULL, the
+ // currently active window is kept active if it is one of the split-view
+ // windows.
+ void ActivateSplitMode(aura::Window* left,
+ aura::Window* right,
+ aura::Window* to_activate);
+
+ // Resets the internal state to an inactive state.
void DeactivateSplitMode();
+ // Replaces |window| in split-view mode with |replace_with|. Adjusts
+ // |replace_with|'s visibility, transform and bounds. Resets |window|'s
+ // visibility and transform but does not change its bounds.
void ReplaceWindow(aura::Window* window,
aura::Window* replace_with);
+ // Returns the bounds of the left and right parts of the |container_| based
+ // on the current value of |divider_position_|.
+ gfx::Rect GetLeftAreaBounds();
+ gfx::Rect GetRightAreaBounds();
+
aura::Window* left_window() { return left_window_; }
aura::Window* right_window() { return right_window_; }
// NULL.
INACTIVE,
// Two windows |left_window_| and |right_window| are shown side by side and
- // there is a horizontal scroll in progress which is dragging the separator
+ // there is a horizontal scroll in progress which is dragging the divider
// between the two windows.
SCROLLING,
// Split View mode is active with |left_window_| and |right_window| showing
ACTIVE
};
+ void SetState(State state);
+
+ void InitializeDivider();
+ void HideDivider();
+ void ShowDivider();
+
void UpdateLayout(bool animate);
- void SetWindowTransform(aura::Window* left_window,
- const gfx::Transform& transform,
- bool animate);
+ void SetWindowTransforms(const gfx::Transform& left_transform,
+ const gfx::Transform& right_transform,
+ const gfx::Transform& divider_transform,
+ bool animate);
- void OnAnimationCompleted(aura::Window* window);
+ // Called when the animation initiated by SetWindowTransforms() completes.
+ void OnAnimationCompleted();
- void UpdateSeparatorPositionFromScrollDelta(float delta);
+ // Returns the default divider position for when the split view mode is
+ // active and the divider is not being dragged.
+ int GetDefaultDividerPosition();
// BezelController::ScrollDelegate:
- virtual void ScrollBegin(BezelController::Bezel bezel, float delta) OVERRIDE;
- virtual void ScrollEnd() OVERRIDE;
- virtual void ScrollUpdate(float delta) OVERRIDE;
- virtual bool CanScroll() OVERRIDE;
+ virtual void BezelScrollBegin(BezelController::Bezel bezel,
+ float delta) OVERRIDE;
+ virtual void BezelScrollEnd() OVERRIDE;
+ virtual void BezelScrollUpdate(float delta) OVERRIDE;
+ virtual bool BezelCanScroll() OVERRIDE;
+
+ // DragHandleScrollDelegate:
+ virtual void HandleScrollBegin(float delta) OVERRIDE;
+ virtual void HandleScrollEnd() OVERRIDE;
+ virtual void HandleScrollUpdate(float delta) OVERRIDE;
+
+ // WindowManagerObserver:
+ virtual void OnOverviewModeEnter() OVERRIDE;
+ virtual void OnOverviewModeExit() OVERRIDE;
+ virtual void OnSplitViewModeEnter() OVERRIDE;
+ virtual void OnSplitViewModeExit() OVERRIDE;
State state_;
aura::Window* left_window_;
aura::Window* right_window_;
- // Position of the separator between left_window_ and right_window_ in
- // container_ coordinates (along the x axis).
- int separator_position_;
+ // X-Coordinate of the (center of the) divider between left_window_ and
+ // right_window_ in |container_| coordinates.
+ int divider_position_;
+
+ // Meaningful only when state_ is SCROLLING.
+ // X-Coordinate of the divider when the scroll started.
+ int divider_scroll_start_position_;
+
+ // Visually separates the windows and contains the drag handle.
+ views::Widget* divider_widget_;
+
+ // The drag handle which can be used when split view is active to exit the
+ // split view mode.
+ views::View* drag_handle_;
+
+ scoped_ptr<aura::ScopedWindowTargeter> window_targeter_;
+ scoped_ptr<views::ViewTargeterDelegate> view_targeter_delegate_;
+
+ // Windows which should be hidden when the animation initiated by
+ // UpdateLayout() completes.
+ std::vector<aura::Window*> to_hide_;
base::WeakPtrFactory<SplitViewController> weak_factory_;