[go: up one dir, main page]

blob: cc6da2832ccb179cdb552fb10b26bb922b4093be [file] [log] [blame]
// Copyright 2019 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 ASH_WM_DESKS_DESKS_BAR_VIEW_H_
#define ASH_WM_DESKS_DESKS_BAR_VIEW_H_
#include <memory>
#include <vector>
#include "ash/ash_export.h"
#include "ash/wm/desks/desks_controller.h"
#include "base/macros.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/view.h"
namespace ash {
class DesksBarScrollViewLayout;
class DeskBarHoverObserver;
class DeskDragProxy;
class DeskMiniView;
class ExpandedDesksBarButton;
class GradientLayerDelegate;
class NewDeskButton;
class OverviewGrid;
class PersistentDesksBarVerticalDotsButton;
class ScrollArrowButton;
class ZeroStateDefaultDeskButton;
class ZeroStateIconButton;
// A bar that resides at the top portion of the overview mode's ShieldView,
// which contains the virtual desks mini_views, as well as the new desk button.
class ASH_EXPORT DesksBarView : public views::View,
public DesksController::Observer,
public views::ScrollView::Observer {
public:
explicit DesksBarView(OverviewGrid* overview_grid);
DesksBarView(const DesksBarView&) = delete;
DesksBarView& operator=(const DesksBarView&) = delete;
~DesksBarView() override;
static constexpr int kZeroStateBarHeight = 40;
// Returns the height of the expanded desks bar that exists on `root`. The
// height of zero state desks bar is `kZeroStateBarHeight`.
static int GetExpandedBarHeight(aura::Window* root);
// Creates and returns the widget that contains the DeskBarView in overview
// mode. The returned widget has no content view yet, and hasn't been shown
// yet.
static std::unique_ptr<views::Widget> CreateDesksWidget(
aura::Window* root,
const gfx::Rect& bounds);
void set_is_bounds_animation_on_going(bool value) {
is_bounds_animation_on_going_ = value;
}
ZeroStateDefaultDeskButton* zero_state_default_desk_button() const {
return zero_state_default_desk_button_;
}
ZeroStateIconButton* zero_state_new_desk_button() const {
return zero_state_new_desk_button_;
}
ExpandedDesksBarButton* expanded_state_new_desk_button() const {
return expanded_state_new_desk_button_;
}
ZeroStateIconButton* zero_state_desks_templates_button() const {
return zero_state_desks_templates_button_;
}
ExpandedDesksBarButton* expanded_state_desks_templates_button() const {
return expanded_state_desks_templates_button_;
}
const std::vector<DeskMiniView*>& mini_views() const { return mini_views_; }
const gfx::Point& last_dragged_item_screen_location() const {
return last_dragged_item_screen_location_;
}
bool dragged_item_over_bar() const { return dragged_item_over_bar_; }
void set_should_name_nudge(bool should_name_nudge) {
should_name_nudge_ = should_name_nudge;
}
// Initializes and creates mini_views for any pre-existing desks, before the
// bar was created. This should only be called after this view has been added
// to a widget, as it needs to call `GetWidget()` when it's performing a
// layout.
void Init();
// Returns true if a desk name is being modified using its mini view's
// DeskNameView on this bar.
bool IsDeskNameBeingModified() const;
// Get the index of a desk mini view in the |mini_views|.
int GetMiniViewIndex(const DeskMiniView* mini_view) const;
// Updates the visibility state of the close buttons on all the mini_views as
// a result of mouse and gesture events.
void OnHoverStateMayHaveChanged();
void OnGestureTap(const gfx::Rect& screen_rect, bool is_long_gesture);
// Called when an item is being dragged in overview mode to update whether it
// is currently intersecting with this view, and the |screen_location| of the
// current drag position.
void SetDragDetails(const gfx::Point& screen_location,
bool dragged_item_over_bar);
// Returns true if it is in zero state. It is the state of the desks bar when
// there's only a single desk available, in which case the bar is shown in a
// minimized state.
bool IsZeroState() const;
// Handle the mouse press event from a desk preview.
void HandlePressEvent(DeskMiniView* mini_view, const ui::LocatedEvent& event);
// Handle the gesture long press event from a desk preview.
void HandleLongPressEvent(DeskMiniView* mini_view,
const ui::LocatedEvent& event);
// Handle the drag event from a desk preview.
void HandleDragEvent(DeskMiniView* mini_view, const ui::LocatedEvent& event);
// Handle the release event from a desk preview. Return true if a drag event
// is ended.
bool HandleReleaseEvent(DeskMiniView* mini_view,
const ui::LocatedEvent& event);
// Finalize any unfinished drag & drop. Initialize a new drag proxy.
void InitDragDesk(DeskMiniView* mini_view,
const gfx::PointF& location_in_screen);
// Start to drag. Scale up the drag proxy.
void StartDragDesk(DeskMiniView* mini_view,
const gfx::PointF& location_in_screen);
// Reorder desks according to the drag proxy's location.
void ContinueDragDesk(DeskMiniView* mini_view,
const gfx::PointF& location_in_screen);
// If the desk is dropped by user (|end_by_user| = true), scale down and snap
// back the drag proxy. Otherwise, directly finalize the drag & drop. Note
// that when we want to end the current drag immediately, if the drag is
// initialized but did not start, |FinalizeDragDesk| should be use; if the
// drag started, |EndDragDesk| should be used with |end_by_user| = false.
void EndDragDesk(DeskMiniView* mini_view, bool end_by_user);
// Reset the drag view and the drag proxy.
void FinalizeDragDesk();
// If a desk is in a drag & drop cycle.
bool IsDraggingDesk() const;
// views::View:
const char* GetClassName() const override;
void Layout() override;
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnThemeChanged() override;
// DesksController::Observer:
void OnDeskAdded(const Desk* desk) override;
void OnDeskRemoved(const Desk* desk) override;
void OnDeskReordered(int old_index, int new_index) override;
void OnDeskActivationChanged(const Desk* activated,
const Desk* deactivated) override;
void OnDeskSwitchAnimationLaunching() override;
void OnDeskSwitchAnimationFinished() override;
void OnDeskNameChanged(const Desk* desk,
const std::u16string& new_name) override;
// views::ScrollView::Observer:
void OnContentsScrolled() override;
void OnContentsScrollEnded() override;
// This is called on initialization, creating a new desk through the
// NewDeskButton or ExpandedDesksBarButton, or expanding from zero state
// bar to the expanded desks bar. Performs the expanding animation if
// |expanding_bar_view| is true, otherwise animates the mini_views (also the
// ExpandedDesksBarButton) to their final positions if
// |initializing_bar_view| is false.
void UpdateNewMiniViews(bool initializing_bar_view, bool expanding_bar_view);
// If the focused |mini_view| is outside of the scroll view's visible bounds,
// scrolls the bar to make sure it can always be seen.
void ScrollToShowMiniViewIfNecessary(const DeskMiniView* mini_view);
void OnNewDeskButtonPressed(
DesksCreationRemovalSource desks_creation_removal_source);
private:
friend class DesksBarScrollViewLayout;
friend class DesksTestApi;
// Determine the new index of the dragged desk at the position of
// |location_in_screen|.
int DetermineMoveIndex(int location_in_screen) const;
// If drag a desk over a scroll button (i.e., the desk intersects the button),
// scroll the desk bar. If the desk is dropped or leaves the button, end
// scroll. Return true if the scroll is triggered. Return false if the scroll
// is ended.
bool MaybeScrollByDraggedDesk();
// Returns the mini_view associated with |desk| or nullptr if no mini_view
// has been created for it yet.
DeskMiniView* FindMiniViewForDesk(const Desk* desk) const;
// Returns the X offset of the first mini_view on the left (if there's one),
// or the X offset of this view's center point when there are no mini_views.
// This offset is used to calculate the amount by which the mini_views should
// be moved when performing the mini_view creation or deletion animations.
int GetFirstMiniViewXOffset() const;
// Updates the visibility of the two buttons inside the zero state desks bar
// and the ExpandedDesksBarButton on the desk bar's state.
void UpdateDeskButtonsVisibility();
// Updates the visibility of |left_scroll_button_| and |right_scroll_button_|.
// Show |left_scroll_button_| if there are contents outside of the left edge
// of the |scroll_view_|, the same for |right_scroll_button_| based on the
// right side of the |scroll_view_|.
void UpdateScrollButtonsVisibility();
// We will show a fade in gradient besides |left_scroll_button_| and a fade
// out gradient besides |right_scroll_button_|. Show the gradient only when
// the corresponding scroll button is visible.
void UpdateGradientZone();
// Scrolls the desks bar to the previous or next page. The page size is the
// width of the scroll view, the contents that are outside of the scroll view
// will be clipped and can not be seen.
void ScrollToPreviousPage();
void ScrollToNextPage();
// Gets the adjusted scroll position based on |position| to make sure no desk
// preview is cropped at the start position of the scrollable bar.
int GetAdjustedUncroppedScrollPosition(int position) const;
void OnDesksTemplatesButtonPressed();
// The views representing desks mini_views. They're owned by views hierarchy.
std::vector<DeskMiniView*> mini_views_;
// Observes mouse events on the desks bar widget and updates the states of the
// mini_views accordingly.
std::unique_ptr<DeskBarHoverObserver> hover_observer_;
// The screen location of the most recent drag position. This value is valid
// only when the below `dragged_item_on_bar_` is true.
gfx::Point last_dragged_item_screen_location_;
// True when the drag location of the overview item is intersecting with this
// view.
bool dragged_item_over_bar_ = false;
// The OverviewGrid that contains this object.
OverviewGrid* overview_grid_;
// Puts the contents in a ScrollView to support scrollable desks.
views::ScrollView* scroll_view_ = nullptr;
// Contents of `scroll_view_`, which includes `mini_views_`,
// `expanded_state_new_desk_button_` and optionally
// `expanded_state_desks_templates_button_` currently.
views::View* scroll_view_contents_ = nullptr;
// If this is true, when `UpdateNewMiniViews()` is called, the newly created
// mini view's name view will be focused and |should_name_nudge_| will be
// reset.
bool should_name_nudge_ = false;
// True if the `DesksBarBoundsAnimation` is started and hasn't finished yet.
// It will be used to hold `Layout` until the bounds animation is completed.
// `Layout` is expensive and will be called on bounds changes, which means it
// will be called lots of times during the bounds changes animation. This is
// done to eliminate the unnecessary `Layout` calls during the animation.
bool is_bounds_animation_on_going_ = false;
ZeroStateDefaultDeskButton* zero_state_default_desk_button_ = nullptr;
ZeroStateIconButton* zero_state_new_desk_button_ = nullptr;
ExpandedDesksBarButton* expanded_state_new_desk_button_ = nullptr;
// Buttons to show the desks templates grid.
ZeroStateIconButton* zero_state_desks_templates_button_ = nullptr;
ExpandedDesksBarButton* expanded_state_desks_templates_button_ = nullptr;
ScrollArrowButton* left_scroll_button_ = nullptr;
ScrollArrowButton* right_scroll_button_ = nullptr;
// Mini view whose preview is being dragged.
DeskMiniView* drag_view_ = nullptr;
// Drag proxy for the dragged desk.
std::unique_ptr<DeskDragProxy> drag_proxy_;
// The layer delegate used for |scroll_view_|'s mask layer, with left and
// right gradient asides the scroll buttons.
std::unique_ptr<GradientLayerDelegate> gradient_layer_delegate_;
// A circular button which when clicked will open the context menu of the
// persistent desks bar. Note that this button will only be created when
// BentoBar is enabled.
PersistentDesksBarVerticalDotsButton* vertical_dots_button_ = nullptr;
};
} // namespace ash
#endif // ASH_WM_DESKS_DESKS_BAR_VIEW_H_