diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-05 00:38:59 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-05 00:38:59 +0000 |
commit | 2df3cc9dfb4505948bd47b3ef8b8f180bffe30f9 (patch) | |
tree | 474ec6d896489a23c5b4cc6811751ec0d0e287ee /views/view.cc | |
parent | d7f0642692c2ac6de15cd1e713e0c88dd740b58e (diff) | |
download | chromium_src-2df3cc9dfb4505948bd47b3ef8b8f180bffe30f9.zip chromium_src-2df3cc9dfb4505948bd47b3ef8b8f180bffe30f9.tar.gz chromium_src-2df3cc9dfb4505948bd47b3ef8b8f180bffe30f9.tar.bz2 |
Sort the methods in views into sections, and make .cc order match .h
This is the first phase of upgrading views::View to the V2 API.
BUG=none
TEST=none
TBR=sky
Review URL: http://codereview.chromium.org/6413001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73881 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/view.cc')
-rw-r--r-- | views/view.cc | 1809 |
1 files changed, 909 insertions, 900 deletions
diff --git a/views/view.cc b/views/view.cc index a20de82..65fc624 100644 --- a/views/view.cc +++ b/views/view.cc @@ -44,33 +44,37 @@ char View::kViewClassName[] = "views/View"; // static const int View::kShowFolderDropMenuDelay = 400; -///////////////////////////////////////////////////////////////////////////// -// -// View - constructors, destructors, initialization -// -///////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// View, public: + +// TO BE MOVED ----------------------------------------------------------------- + +void View::SetHotTracked(bool flag) { +} + + +// Creation and lifetime ------------------------------------------------------- View::View() - : id_(0), + : enabled_(true), + id_(0), group_(-1), - enabled_(true), focusable_(false), accessibility_focusable_(false), - bounds_(0, 0, 0, 0), - needs_layout_(true), + is_parent_owned_(true), parent_(NULL), is_visible_(true), - is_parent_owned_(true), notify_when_visible_bounds_in_root_changes_(false), registered_for_visible_bounds_notification_(false), + needs_layout_(true), + flip_canvas_on_paint_for_rtl_ui_(false), accelerator_registration_delayed_(false), - next_focusable_view_(NULL), - previous_focusable_view_(NULL), accelerator_focus_manager_(NULL), registered_accelerator_count_(0), + next_focusable_view_(NULL), + previous_focusable_view_(NULL), context_menu_controller_(NULL), - drag_controller_(NULL), - flip_canvas_on_paint_for_rtl_ui_(false) { + drag_controller_(NULL) { } View::~View() { @@ -90,11 +94,119 @@ View::~View() { #endif } -///////////////////////////////////////////////////////////////////////////// -// -// View - sizing -// -///////////////////////////////////////////////////////////////////////////// +// Tree operations ------------------------------------------------------------- + +void View::AddChildView(View* v) { + AddChildView(static_cast<int>(child_views_.size()), v); +} + +void View::AddChildView(int index, View* v) { + CHECK(v != this) << "You cannot add a view as its own child"; + + // Remove the view from its current parent if any. + if (v->GetParent()) + v->GetParent()->RemoveChildView(v); + + // Sets the prev/next focus views. + InitFocusSiblings(v, index); + + // Let's insert the view. + child_views_.insert(child_views_.begin() + index, v); + v->SetParent(this); + + for (View* p = this; p; p = p->GetParent()) + p->ViewHierarchyChangedImpl(false, true, this, v); + + v->PropagateAddNotifications(this, v); + UpdateTooltip(); + RootView* root = GetRootView(); + if (root) + RegisterChildrenForVisibleBoundsNotification(root, v); + + if (layout_manager_.get()) + layout_manager_->ViewAdded(this, v); +} + +View* View::GetChildViewAt(int index) const { + return index < GetChildViewCount() ? child_views_[index] : NULL; +} + +void View::RemoveChildView(View* a_view) { + DoRemoveChildView(a_view, true, true, false); +} + +void View::RemoveAllChildViews(bool delete_views) { + ViewList::iterator iter; + while ((iter = child_views_.begin()) != child_views_.end()) { + DoRemoveChildView(*iter, false, false, delete_views); + } + UpdateTooltip(); +} + +int View::GetChildViewCount() const { + return static_cast<int>(child_views_.size()); +} + +bool View::HasChildView(View* a_view) { + return find(child_views_.begin(), + child_views_.end(), + a_view) != child_views_.end(); +} + +Widget* View::GetWidget() const { + // The root view holds a reference to this view hierarchy's Widget. + return parent_ ? parent_->GetWidget() : NULL; +} + +Window* View::GetWindow() const { + Widget* widget = GetWidget(); + return widget ? widget->GetWindow() : NULL; +} + +bool View::ContainsNativeView(gfx::NativeView native_view) const { + for (int i = 0, count = GetChildViewCount(); i < count; ++i) { + if (GetChildViewAt(i)->ContainsNativeView(native_view)) + return true; + } + return false; +} + +// Get the containing RootView +RootView* View::GetRootView() { + Widget* widget = GetWidget(); + return widget ? widget->GetRootView() : NULL; +} + +int View::GetChildIndex(const View* v) const { + for (int i = 0, count = GetChildViewCount(); i < count; i++) { + if (v == GetChildViewAt(i)) + return i; + } + return -1; +} + +bool View::IsParentOf(View* v) const { + DCHECK(v); + View* parent = v->GetParent(); + while (parent) { + if (this == parent) + return true; + parent = parent->GetParent(); + } + return false; +} + +#ifndef NDEBUG +void View::PrintViewHierarchy() { + PrintViewHierarchyImp(0); +} + +void View::PrintFocusHierarchy() { + PrintFocusHierarchyImp(0); +} +#endif + +// Size and disposition -------------------------------------------------------- gfx::Rect View::GetBounds(PositionMirroringSettings settings) const { gfx::Rect bounds(bounds_); @@ -108,12 +220,6 @@ gfx::Rect View::GetBounds(PositionMirroringSettings settings) const { return bounds; } -// y(), width() and height() are agnostic to the RTL UI layout of the -// parent view. x(), on the other hand, is not. -int View::GetX(PositionMirroringSettings settings) const { - return settings == IGNORE_MIRRORING_TRANSFORMATION ? x() : MirroredX(); -} - void View::SetBounds(const gfx::Rect& bounds) { if (bounds == bounds_) { if (needs_layout_) { @@ -137,6 +243,12 @@ void View::SetBounds(const gfx::Rect& bounds) { } } +// y(), width() and height() are agnostic to the RTL UI layout of the +// parent view. x(), on the other hand, is not. +int View::GetX(PositionMirroringSettings settings) const { + return settings == IGNORE_MIRRORING_TRANSFORMATION ? x() : MirroredX(); +} + gfx::Rect View::GetLocalBounds(bool include_border) const { if (include_border || !border_.get()) return gfx::Rect(0, 0, width(), height()); @@ -148,6 +260,49 @@ gfx::Rect View::GetLocalBounds(bool include_border) const { std::max(0, height() - insets.height())); } +gfx::Insets View::GetInsets() const { + gfx::Insets insets; + if (border_.get()) + border_->GetInsets(&insets); + return insets; +} + +gfx::Rect View::GetVisibleBounds() { + if (!IsVisibleInRootView()) + return gfx::Rect(); + gfx::Rect vis_bounds(0, 0, width(), height()); + gfx::Rect ancestor_bounds; + View* view = this; + int root_x = 0; + int root_y = 0; + while (view != NULL && !vis_bounds.IsEmpty()) { + root_x += view->GetX(APPLY_MIRRORING_TRANSFORMATION); + root_y += view->y(); + vis_bounds.Offset(view->GetX(APPLY_MIRRORING_TRANSFORMATION), view->y()); + View* ancestor = view->GetParent(); + if (ancestor != NULL) { + ancestor_bounds.SetRect(0, 0, ancestor->width(), + ancestor->height()); + vis_bounds = vis_bounds.Intersect(ancestor_bounds); + } else if (!view->GetWidget()) { + // If the view has no Widget, we're not visible. Return an empty rect. + return gfx::Rect(); + } + view = ancestor; + } + if (vis_bounds.IsEmpty()) + return vis_bounds; + // Convert back to this views coordinate system. + vis_bounds.Offset(-root_x, -root_y); + return vis_bounds; +} + +gfx::Rect View::GetScreenBounds() const { + gfx::Point origin; + View::ConvertPointToScreen(this, &origin); + return gfx::Rect(origin, size()); +} + gfx::Point View::GetPosition() const { return gfx::Point(GetX(APPLY_MIRRORING_TRANSFORMATION), y()); } @@ -168,12 +323,6 @@ void View::SizeToPreferredSize() { SetBounds(x(), y(), prefsize.width(), prefsize.height()); } -void View::PreferredSizeChanged() { - InvalidateLayout(); - if (parent_) - parent_->ChildPreferredSizeChanged(this); -} - gfx::Size View::GetMinimumSize() { return GetPreferredSize(); } @@ -190,23 +339,56 @@ void View::DidChangeBounds(const gfx::Rect& previous, Layout(); } -void View::ScrollRectToVisible(const gfx::Rect& rect) { +void View::SetVisible(bool flag) { + if (flag != is_visible_) { + // If the tab is currently visible, schedule paint to + // refresh parent + if (IsVisible()) + SchedulePaint(); + + is_visible_ = flag; + + // This notifies all subviews recursively. + PropagateVisibilityNotifications(this, flag); + + // If we are newly visible, schedule paint. + if (IsVisible()) + SchedulePaint(); + } +} + +bool View::IsVisibleInRootView() const { View* parent = GetParent(); + if (IsVisible() && parent) + return parent->IsVisibleInRootView(); + else + return false; +} - // We must take RTL UI mirroring into account when adjusting the position of - // the region. - if (parent) { - gfx::Rect scroll_rect(rect); - scroll_rect.Offset(GetX(APPLY_MIRRORING_TRANSFORMATION), y()); - parent->ScrollRectToVisible(scroll_rect); +void View::SetEnabled(bool state) { + if (enabled_ != state) { + enabled_ = state; + SchedulePaint(); } } -///////////////////////////////////////////////////////////////////////////// -// -// View - layout -// -///////////////////////////////////////////////////////////////////////////// +bool View::IsEnabled() const { + return enabled_; +} + +// RTL positioning ------------------------------------------------------------- + +int View::MirroredX() const { + View* parent = GetParent(); + return parent ? parent->MirroredLeftPointForRect(bounds_) : x(); +} + +int View::MirroredLeftPointForRect(const gfx::Rect& bounds) const { + return base::i18n::IsRTL() ? + (width() - bounds.x() - bounds.width()) : bounds.x(); +} + +// Layout ---------------------------------------------------------------------- void View::Layout() { needs_layout_ = false; @@ -253,87 +435,113 @@ void View::SetLayoutManager(LayoutManager* layout_manager) { layout_manager_->Installed(this); } -//////////////////////////////////////////////////////////////////////////////// -// -// View - Right-to-left UI layout -// -//////////////////////////////////////////////////////////////////////////////// +// Attributes ------------------------------------------------------------------ -int View::MirroredX() const { - View* parent = GetParent(); - return parent ? parent->MirroredLeftPointForRect(bounds_) : x(); +std::string View::GetClassName() const { + return kViewClassName; } -int View::MirroredLeftPointForRect(const gfx::Rect& bounds) const { - return base::i18n::IsRTL() ? - (width() - bounds.x() - bounds.width()) : bounds.x(); +View* View::GetAncestorWithClassName(const std::string& name) { + for (View* view = this; view; view = view->GetParent()) { + if (view->GetClassName() == name) + return view; + } + return NULL; } -//////////////////////////////////////////////////////////////////////////////// -// -// View - states -// -//////////////////////////////////////////////////////////////////////////////// +View* View::GetViewByID(int id) const { + if (id == id_) + return const_cast<View*>(this); -bool View::IsEnabled() const { - return enabled_; + for (int i = 0, count = GetChildViewCount(); i < count; ++i) { + View* child = GetChildViewAt(i); + View* view = child->GetViewByID(id); + if (view) + return view; + } + return NULL; } -void View::SetEnabled(bool state) { - if (enabled_ != state) { - enabled_ = state; - SchedulePaint(); - } +void View::SetID(int id) { + id_ = id; } -void View::SetFocusable(bool focusable) { - focusable_ = focusable; +int View::GetID() const { + return id_; } -bool View::IsFocusableInRootView() const { - return IsFocusable() && IsVisibleInRootView(); +void View::SetGroup(int gid) { + // Don't change the group id once it's set. + DCHECK(group_ == -1 || group_ == gid); + group_ = gid; } -bool View::IsAccessibilityFocusableInRootView() const { - return (focusable_ || accessibility_focusable_) && IsEnabled() && - IsVisibleInRootView(); +int View::GetGroup() const { + return group_; } -FocusManager* View::GetFocusManager() { - Widget* widget = GetWidget(); - return widget ? widget->GetFocusManager() : NULL; +void View::GetViewsWithGroup(int group_id, std::vector<View*>* out) { + if (group_ == group_id) + out->push_back(this); + + for (int i = 0, count = GetChildViewCount(); i < count; ++i) + GetChildViewAt(i)->GetViewsWithGroup(group_id, out); } -bool View::HasFocus() { - FocusManager* focus_manager = GetFocusManager(); - if (focus_manager) - return focus_manager->GetFocusedView() == this; - return false; +View* View::GetSelectedViewForGroup(int group_id) { + std::vector<View*> views; + GetRootView()->GetViewsWithGroup(group_id, &views); + if (views.size() > 0) + return views[0]; + else + return NULL; } -void View::Focus() { - // By default, we clear the native focus. This ensures that no visible native - // view as the focus and that we still receive keyboard inputs. - FocusManager* focus_manager = GetFocusManager(); - if (focus_manager) - focus_manager->ClearNativeFocus(); +// Coordinate conversion ------------------------------------------------------- - // Notify assistive technologies of the focus change. - NotifyAccessibilityEvent(AccessibilityTypes::EVENT_FOCUS); +// static +void View::ConvertPointToView(const View* src, + const View* dst, + gfx::Point* point) { + ConvertPointToView(src, dst, point, true); } -void View::NotifyAccessibilityEvent(AccessibilityTypes::Event event_type) { - NotifyAccessibilityEvent(event_type, true); +// static +void View::ConvertPointToWidget(const View* src, gfx::Point* p) { + DCHECK(src); + DCHECK(p); + + gfx::Point offset; + for (const View* v = src; v; v = v->GetParent()) { + offset.set_x(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION)); + offset.set_y(offset.y() + v->y()); + } + p->SetPoint(p->x() + offset.x(), p->y() + offset.y()); } -void View::SetHotTracked(bool flag) { +// static +void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { + gfx::Point t; + ConvertPointToWidget(dest, &t); + p->SetPoint(p->x() - t.x(), p->y() - t.y()); } -///////////////////////////////////////////////////////////////////////////// -// -// View - painting -// -///////////////////////////////////////////////////////////////////////////// +// static +void View::ConvertPointToScreen(const View* src, gfx::Point* p) { + DCHECK(src); + DCHECK(p); + + // If the view is not connected to a tree, there's nothing we can do. + Widget* widget = src->GetWidget(); + if (widget) { + ConvertPointToWidget(src, p); + gfx::Rect r; + widget->GetBounds(&r, false); + p->SetPoint(p->x() + r.x(), p->y() + r.y()); + } +} + +// Painting -------------------------------------------------------------------- void View::SchedulePaint(const gfx::Rect& r, bool urgent) { if (!IsVisible()) @@ -373,15 +581,13 @@ void View::PaintFocusBorder(gfx::Canvas* canvas) { canvas->DrawFocusRect(0, 0, width(), height()); } -void View::PaintChildren(gfx::Canvas* canvas) { - for (int i = 0, count = GetChildViewCount(); i < count; ++i) { - View* child = GetChildViewAt(i); - if (!child) { - NOTREACHED() << "Should not have a NULL child View for index in bounds"; - continue; - } - child->ProcessPaint(canvas); - } +void View::PaintNow() { + if (!IsVisible()) + return; + + View* view = GetParent(); + if (view) + view->PaintNow(); } void View::ProcessPaint(gfx::Canvas* canvas) { @@ -425,20 +631,38 @@ void View::ProcessPaint(gfx::Canvas* canvas) { canvas->Restore(); } -void View::PaintNow() { - if (!IsVisible()) - return; +void View::PaintChildren(gfx::Canvas* canvas) { + for (int i = 0, count = GetChildViewCount(); i < count; ++i) { + View* child = GetChildViewAt(i); + if (!child) { + NOTREACHED() << "Should not have a NULL child View for index in bounds"; + continue; + } + child->ProcessPaint(canvas); + } +} - View* view = GetParent(); - if (view) - view->PaintNow(); +ThemeProvider* View::GetThemeProvider() const { + Widget* widget = GetWidget(); + return widget ? widget->GetThemeProvider() : NULL; } -gfx::Insets View::GetInsets() const { - gfx::Insets insets; - if (border_.get()) - border_->GetInsets(&insets); - return insets; +// Input ----------------------------------------------------------------------- + +View* View::GetViewForPoint(const gfx::Point& point) { + // Walk the child Views recursively looking for the View that most + // tightly encloses the specified point. + for (int i = GetChildViewCount() - 1; i >= 0; --i) { + View* child = GetChildViewAt(i); + if (!child->IsVisible()) + continue; + + gfx::Point point_in_child_coords(point); + View::ConvertPointToView(this, child, &point_in_child_coords); + if (child->HitTest(point_in_child_coords)) + return child->GetViewForPoint(point_in_child_coords); + } + return this; } gfx::NativeCursor View::GetCursorForPoint(Event::EventType event_type, @@ -467,309 +691,307 @@ bool View::HitTest(const gfx::Point& l) const { return false; } -void View::SetContextMenuController(ContextMenuController* menu_controller) { - context_menu_controller_ = menu_controller; +bool View::OnMousePressed(const MouseEvent& e) { + return false; } -void View::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) { - if (!context_menu_controller_) - return; +bool View::OnMouseDragged(const MouseEvent& e) { + return false; +} - context_menu_controller_->ShowContextMenu(this, p, is_mouse_gesture); +void View::OnMouseReleased(const MouseEvent& e, bool canceled) { } -///////////////////////////////////////////////////////////////////////////// -// -// View - tree -// -///////////////////////////////////////////////////////////////////////////// +void View::OnMouseMoved(const MouseEvent& e) { +} -bool View::ProcessMousePressed(const MouseEvent& e, DragInfo* drag_info) { - const bool enabled = IsEnabled(); - int drag_operations = - (enabled && e.IsOnlyLeftMouseButton() && HitTest(e.location())) ? - GetDragOperations(e.location()) : 0; - ContextMenuController* context_menu_controller = e.IsRightMouseButton() ? - context_menu_controller_ : 0; +void View::OnMouseEntered(const MouseEvent& e) { +} - const bool result = OnMousePressed(e); - // WARNING: we may have been deleted, don't use any View variables; +void View::OnMouseExited(const MouseEvent& e) { +} - if (!enabled) - return result; +#if defined(TOUCH_UI) +View::TouchStatus View::OnTouchEvent(const TouchEvent& event) { + DVLOG(1) << "visited the OnTouchEvent"; + return TOUCH_STATUS_UNKNOWN; +} +#endif - if (drag_operations != ui::DragDropTypes::DRAG_NONE) { - drag_info->PossibleDrag(e.location()); - return true; - } - return !!context_menu_controller || result; +void View::SetMouseHandler(View *new_mouse_handler) { + // It is valid for new_mouse_handler to be NULL + if (parent_) + parent_->SetMouseHandler(new_mouse_handler); } -bool View::ProcessMouseDragged(const MouseEvent& e, DragInfo* drag_info) { - // Copy the field, that way if we're deleted after drag and drop no harm is - // done. - ContextMenuController* context_menu_controller = context_menu_controller_; - const bool possible_drag = drag_info->possible_drag; - if (possible_drag && ExceededDragThreshold(drag_info->start_pt.x() - e.x(), - drag_info->start_pt.y() - e.y())) { - if (!drag_controller_ || - drag_controller_->CanStartDrag(this, drag_info->start_pt, e.location())) - DoDrag(e, drag_info->start_pt); - } else { - if (OnMouseDragged(e)) - return true; - // Fall through to return value based on context menu controller. - } - // WARNING: we may have been deleted. - return (context_menu_controller != NULL) || possible_drag; +bool View::OnKeyPressed(const KeyEvent& e) { + return false; } -void View::ProcessMouseReleased(const MouseEvent& e, bool canceled) { - if (!canceled && context_menu_controller_ && e.IsOnlyRightMouseButton()) { - // Assume that if there is a context menu controller we won't be deleted - // from mouse released. - gfx::Point location(e.location()); - OnMouseReleased(e, canceled); - if (HitTest(location)) { - ConvertPointToScreen(this, &location); - ShowContextMenu(location, true); - } - } else { - OnMouseReleased(e, canceled); +bool View::OnKeyReleased(const KeyEvent& e) { + return false; +} + +bool View::OnMouseWheel(const MouseWheelEvent& e) { + return false; +} + +// Accelerators ---------------------------------------------------------------- + +void View::AddAccelerator(const Accelerator& accelerator) { + if (!accelerators_.get()) + accelerators_.reset(new std::vector<Accelerator>()); + + std::vector<Accelerator>::iterator iter = + std::find(accelerators_->begin(), accelerators_->end(), accelerator); + DCHECK(iter == accelerators_->end()) + << "Registering the same accelerator multiple times"; + + accelerators_->push_back(accelerator); + RegisterPendingAccelerators(); +} + +void View::RemoveAccelerator(const Accelerator& accelerator) { + std::vector<Accelerator>::iterator iter; + if (!accelerators_.get() || + ((iter = std::find(accelerators_->begin(), accelerators_->end(), + accelerator)) == accelerators_->end())) { + NOTREACHED() << "Removing non-existing accelerator"; + return; + } + + size_t index = iter - accelerators_->begin(); + accelerators_->erase(iter); + if (index >= registered_accelerator_count_) { + // The accelerator is not registered to FocusManager. + return; + } + --registered_accelerator_count_; + + RootView* root_view = GetRootView(); + if (!root_view) { + // We are not part of a view hierarchy, so there is nothing to do as we + // removed ourselves from accelerators_, we won't be registered when added + // to one. + return; + } + + // If accelerator_focus_manager_ is NULL then we did not registered + // accelerators so there is nothing to unregister. + if (accelerator_focus_manager_) { + accelerator_focus_manager_->UnregisterAccelerator(accelerator, this); } - // WARNING: we may have been deleted. } -#if defined(TOUCH_UI) -View::TouchStatus View::ProcessTouchEvent(const TouchEvent& e) { - // TODO(rjkroege): Implement a grab scheme similar to as - // as is found in MousePressed. - return OnTouchEvent(e); +void View::ResetAccelerators() { + if (accelerators_.get()) + UnregisterAccelerators(false); } -#endif -void View::AddChildView(View* v) { - AddChildView(static_cast<int>(child_views_.size()), v); +// Focus ----------------------------------------------------------------------- + +bool View::HasFocus() { + FocusManager* focus_manager = GetFocusManager(); + if (focus_manager) + return focus_manager->GetFocusedView() == this; + return false; } -void View::AddChildView(int index, View* v) { - CHECK(v != this) << "You cannot add a view as its own child"; +View* View::GetNextFocusableView() { + return next_focusable_view_; +} - // Remove the view from its current parent if any. - if (v->GetParent()) - v->GetParent()->RemoveChildView(v); +View* View::GetPreviousFocusableView() { + return previous_focusable_view_; +} - // Sets the prev/next focus views. - InitFocusSiblings(v, index); +void View::SetNextFocusableView(View* view) { + view->previous_focusable_view_ = this; + next_focusable_view_ = view; +} - // Let's insert the view. - child_views_.insert(child_views_.begin() + index, v); - v->SetParent(this); +void View::SetFocusable(bool focusable) { + focusable_ = focusable; +} - for (View* p = this; p; p = p->GetParent()) - p->ViewHierarchyChangedImpl(false, true, this, v); +bool View::IsFocusableInRootView() const { + return IsFocusable() && IsVisibleInRootView(); +} - v->PropagateAddNotifications(this, v); - UpdateTooltip(); - RootView* root = GetRootView(); - if (root) - RegisterChildrenForVisibleBoundsNotification(root, v); +bool View::IsAccessibilityFocusableInRootView() const { + return (focusable_ || accessibility_focusable_) && IsEnabled() && + IsVisibleInRootView(); +} - if (layout_manager_.get()) - layout_manager_->ViewAdded(this, v); +FocusManager* View::GetFocusManager() { + Widget* widget = GetWidget(); + return widget ? widget->GetFocusManager() : NULL; } -View* View::GetChildViewAt(int index) const { - return index < GetChildViewCount() ? child_views_[index] : NULL; +void View::RequestFocus() { + RootView* rv = GetRootView(); + if (rv && IsFocusableInRootView()) + rv->FocusView(this); } -int View::GetChildViewCount() const { - return static_cast<int>(child_views_.size()); +void View::WillGainFocus() { } -bool View::HasChildView(View* a_view) { - return find(child_views_.begin(), - child_views_.end(), - a_view) != child_views_.end(); +void View::DidGainFocus() { } -void View::RemoveChildView(View* a_view) { - DoRemoveChildView(a_view, true, true, false); +void View::WillLoseFocus() { } -void View::RemoveAllChildViews(bool delete_views) { - ViewList::iterator iter; - while ((iter = child_views_.begin()) != child_views_.end()) { - DoRemoveChildView(*iter, false, false, delete_views); - } - UpdateTooltip(); +// Tooltips -------------------------------------------------------------------- + +bool View::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { + return false; } -void View::DoDrag(const MouseEvent& e, const gfx::Point& press_pt) { - int drag_operations = GetDragOperations(press_pt); - if (drag_operations == ui::DragDropTypes::DRAG_NONE) - return; +bool View::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) { + return false; +} - OSExchangeData data; - WriteDragData(press_pt, &data); +// Context menus --------------------------------------------------------------- - // Message the RootView to do the drag and drop. That way if we're removed - // the RootView can detect it and avoid calling us back. - RootView* root_view = GetRootView(); - root_view->StartDragForViewFromMouseEvent(this, data, drag_operations); +void View::SetContextMenuController(ContextMenuController* menu_controller) { + context_menu_controller_ = menu_controller; } -void View::DoRemoveChildView(View* a_view, - bool update_focus_cycle, - bool update_tool_tip, - bool delete_removed_view) { -#ifndef NDEBUG - DCHECK(!IsProcessingPaint()) << "Should not be removing a child view " << - "during a paint, this will seriously " << - "mess things up!"; -#endif - DCHECK(a_view); - const ViewList::iterator i = find(child_views_.begin(), - child_views_.end(), - a_view); - scoped_ptr<View> view_to_be_deleted; - if (i != child_views_.end()) { - if (update_focus_cycle) { - // Let's remove the view from the focus traversal. - View* next_focusable = a_view->next_focusable_view_; - View* prev_focusable = a_view->previous_focusable_view_; - if (prev_focusable) - prev_focusable->next_focusable_view_ = next_focusable; - if (next_focusable) - next_focusable->previous_focusable_view_ = prev_focusable; - } +void View::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) { + if (!context_menu_controller_) + return; - RootView* root = GetRootView(); - if (root) - UnregisterChildrenForVisibleBoundsNotification(root, a_view); - a_view->PropagateRemoveNotifications(this); - a_view->SetParent(NULL); + context_menu_controller_->ShowContextMenu(this, p, is_mouse_gesture); +} - if (delete_removed_view && a_view->IsParentOwned()) - view_to_be_deleted.reset(a_view); +// Drag and drop --------------------------------------------------------------- - child_views_.erase(i); - } +void View::SetDragController(DragController* drag_controller) { + drag_controller_ = drag_controller; +} - if (update_tool_tip) - UpdateTooltip(); +DragController* View::GetDragController() { + return drag_controller_; +} - if (layout_manager_.get()) - layout_manager_->ViewRemoved(this, a_view); +bool View::GetDropFormats( + int* formats, + std::set<OSExchangeData::CustomFormat>* custom_formats) { + return false; } -void View::PropagateRemoveNotifications(View* parent) { - for (int i = 0, count = GetChildViewCount(); i < count; ++i) - GetChildViewAt(i)->PropagateRemoveNotifications(parent); +bool View::AreDropTypesRequired() { + return false; +} - for (View* v = this; v; v = v->GetParent()) - v->ViewHierarchyChangedImpl(true, false, parent, this); +bool View::CanDrop(const OSExchangeData& data) { + // TODO(sky): when I finish up migration, this should default to true. + return false; } -void View::PropagateAddNotifications(View* parent, View* child) { - for (int i = 0, count = GetChildViewCount(); i < count; ++i) - GetChildViewAt(i)->PropagateAddNotifications(parent, child); - ViewHierarchyChangedImpl(true, true, parent, child); +void View::OnDragEntered(const DropTargetEvent& event) { } -bool View::IsFocusable() const { - return focusable_ && IsEnabled() && IsVisible(); +int View::OnDragUpdated(const DropTargetEvent& event) { + return ui::DragDropTypes::DRAG_NONE; } -void View::PropagateThemeChanged() { - for (int i = GetChildViewCount() - 1; i >= 0; --i) - GetChildViewAt(i)->PropagateThemeChanged(); - OnThemeChanged(); +void View::OnDragExited() { } -void View::PropagateLocaleChanged() { - for (int i = GetChildViewCount() - 1; i >= 0; --i) - GetChildViewAt(i)->PropagateLocaleChanged(); - OnLocaleChanged(); +int View::OnPerformDrop(const DropTargetEvent& event) { + return ui::DragDropTypes::DRAG_NONE; } -#ifndef NDEBUG -bool View::IsProcessingPaint() const { - return GetParent() && GetParent()->IsProcessingPaint(); +// static +bool View::ExceededDragThreshold(int delta_x, int delta_y) { + return (abs(delta_x) > GetHorizontalDragThreshold() || + abs(delta_y) > GetVerticalDragThreshold()); } -#endif -gfx::Point View::GetKeyboardContextMenuLocation() { - gfx::Rect vis_bounds = GetVisibleBounds(); - gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2, - vis_bounds.y() + vis_bounds.height() / 2); - ConvertPointToScreen(this, &screen_point); - return screen_point; +// Accessibility --------------------------------------------------------------- + +void View::NotifyAccessibilityEvent(AccessibilityTypes::Event event_type) { + NotifyAccessibilityEvent(event_type, true); } -bool View::HasHitTestMask() const { - return false; +bool View::GetAccessibleName(string16* name) { + DCHECK(name); + + if (accessible_name_.empty()) + return false; + *name = accessible_name_; + return true; } -void View::GetHitTestMask(gfx::Path* mask) const { - DCHECK(mask); +AccessibilityTypes::Role View::GetAccessibleRole() { + return AccessibilityTypes::ROLE_CLIENT; } -void View::ViewHierarchyChanged(bool is_add, - View* parent, - View* child) { +void View::SetAccessibleName(const string16& name) { + accessible_name_ = name; } -void View::ViewHierarchyChangedImpl(bool register_accelerators, - bool is_add, - View* parent, - View* child) { - if (register_accelerators) { - if (is_add) { - // If you get this registration, you are part of a subtree that has been - // added to the view hierarchy. - if (GetFocusManager()) { - RegisterPendingAccelerators(); - } else { - // Delay accelerator registration until visible as we do not have - // focus manager until then. - accelerator_registration_delayed_ = true; - } - } else { - if (child == this) - UnregisterAccelerators(true); - } +// Scrolling ------------------------------------------------------------------- + +void View::ScrollRectToVisible(const gfx::Rect& rect) { + View* parent = GetParent(); + + // We must take RTL UI mirroring into account when adjusting the position of + // the region. + if (parent) { + gfx::Rect scroll_rect(rect); + scroll_rect.Offset(GetX(APPLY_MIRRORING_TRANSFORMATION), y()); + parent->ScrollRectToVisible(scroll_rect); } +} - ViewHierarchyChanged(is_add, parent, child); - parent->needs_layout_ = true; +int View::GetPageScrollIncrement(ScrollView* scroll_view, + bool is_horizontal, bool is_positive) { + return 0; } -void View::PropagateVisibilityNotifications(View* start, bool is_visible) { - for (int i = 0, count = GetChildViewCount(); i < count; ++i) - GetChildViewAt(i)->PropagateVisibilityNotifications(start, is_visible); - VisibilityChangedImpl(start, is_visible); +int View::GetLineScrollIncrement(ScrollView* scroll_view, + bool is_horizontal, bool is_positive) { + return 0; } -void View::VisibilityChangedImpl(View* starting_from, bool is_visible) { - if (is_visible) - RegisterPendingAccelerators(); - else - UnregisterAccelerators(true); - VisibilityChanged(starting_from, is_visible); +//////////////////////////////////////////////////////////////////////////////// +// View, protected: + +// Size and disposition -------------------------------------------------------- + +void View::PreferredSizeChanged() { + InvalidateLayout(); + if (parent_) + parent_->ChildPreferredSizeChanged(this); } -void View::VisibilityChanged(View* starting_from, bool is_visible) { +void View::SetNotifyWhenVisibleBoundsInRootChanges(bool value) { + if (notify_when_visible_bounds_in_root_changes_ == value) + return; + notify_when_visible_bounds_in_root_changes_ = value; + RootView* root = GetRootView(); + if (root) { + if (value) + root->RegisterViewForVisibleBoundsNotification(this); + else + root->UnregisterViewForVisibleBoundsNotification(this); + } } -void View::PropagateNativeViewHierarchyChanged(bool attached, - gfx::NativeView native_view, - RootView* root_view) { - for (int i = 0, count = GetChildViewCount(); i < count; ++i) - GetChildViewAt(i)->PropagateNativeViewHierarchyChanged(attached, - native_view, - root_view); - NativeViewHierarchyChanged(attached, native_view, root_view); +bool View::GetNotifyWhenVisibleBoundsInRootChanges() { + return notify_when_visible_bounds_in_root_changes_; +} + +// Tree operations ------------------------------------------------------------- + +void View::ViewHierarchyChanged(bool is_add, View* parent, View* child) { +} + +void View::VisibilityChanged(View* starting_from, bool is_visible) { } void View::NativeViewHierarchyChanged(bool attached, @@ -790,202 +1012,196 @@ void View::NativeViewHierarchyChanged(bool attached, } } -void View::SetNotifyWhenVisibleBoundsInRootChanges(bool value) { - if (notify_when_visible_bounds_in_root_changes_ == value) - return; - notify_when_visible_bounds_in_root_changes_ = value; - RootView* root = GetRootView(); - if (root) { - if (value) - root->RegisterViewForVisibleBoundsNotification(this); - else - root->UnregisterViewForVisibleBoundsNotification(this); - } -} +// Painting -------------------------------------------------------------------- -bool View::GetNotifyWhenVisibleBoundsInRootChanges() { - return notify_when_visible_bounds_in_root_changes_; +#ifndef NDEBUG +bool View::IsProcessingPaint() const { + return GetParent() && GetParent()->IsProcessingPaint(); } +#endif -View* View::GetViewForPoint(const gfx::Point& point) { - // Walk the child Views recursively looking for the View that most - // tightly encloses the specified point. - for (int i = GetChildViewCount() - 1; i >= 0; --i) { - View* child = GetChildViewAt(i); - if (!child->IsVisible()) - continue; +// Input ----------------------------------------------------------------------- - gfx::Point point_in_child_coords(point); - View::ConvertPointToView(this, child, &point_in_child_coords); - if (child->HitTest(point_in_child_coords)) - return child->GetViewForPoint(point_in_child_coords); - } - return this; +bool View::HasHitTestMask() const { + return false; } -Widget* View::GetWidget() const { - // The root view holds a reference to this view hierarchy's Widget. - return parent_ ? parent_->GetWidget() : NULL; +void View::GetHitTestMask(gfx::Path* mask) const { + DCHECK(mask); } -Window* View::GetWindow() const { - Widget* widget = GetWidget(); - return widget ? widget->GetWindow() : NULL; +// Focus ----------------------------------------------------------------------- + +bool View::IsFocusable() const { + return focusable_ && IsEnabled() && IsVisible(); } -bool View::ContainsNativeView(gfx::NativeView native_view) const { - for (int i = 0, count = GetChildViewCount(); i < count; ++i) { - if (GetChildViewAt(i)->ContainsNativeView(native_view)) - return true; - } - return false; +void View::Focus() { + // By default, we clear the native focus. This ensures that no visible native + // view as the focus and that we still receive keyboard inputs. + FocusManager* focus_manager = GetFocusManager(); + if (focus_manager) + focus_manager->ClearNativeFocus(); + + // Notify assistive technologies of the focus change. + NotifyAccessibilityEvent(AccessibilityTypes::EVENT_FOCUS); } -// Get the containing RootView -RootView* View::GetRootView() { +// Tooltips -------------------------------------------------------------------- + +void View::TooltipTextChanged() { Widget* widget = GetWidget(); - return widget ? widget->GetRootView() : NULL; + if (widget && widget->GetTooltipManager()) + widget->GetTooltipManager()->TooltipTextChanged(this); } -View* View::GetViewByID(int id) const { - if (id == id_) - return const_cast<View*>(this); +// Context menus --------------------------------------------------------------- - for (int i = 0, count = GetChildViewCount(); i < count; ++i) { - View* child = GetChildViewAt(i); - View* view = child->GetViewByID(id); - if (view) - return view; - } - return NULL; +gfx::Point View::GetKeyboardContextMenuLocation() { + gfx::Rect vis_bounds = GetVisibleBounds(); + gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2, + vis_bounds.y() + vis_bounds.height() / 2); + ConvertPointToScreen(this, &screen_point); + return screen_point; } -void View::GetViewsWithGroup(int group_id, std::vector<View*>* out) { - if (group_ == group_id) - out->push_back(this); +// Drag and drop --------------------------------------------------------------- - for (int i = 0, count = GetChildViewCount(); i < count; ++i) - GetChildViewAt(i)->GetViewsWithGroup(group_id, out); +int View::GetDragOperations(const gfx::Point& press_pt) { + return drag_controller_ ? + drag_controller_->GetDragOperations(this, press_pt) : + ui::DragDropTypes::DRAG_NONE; } -View* View::GetSelectedViewForGroup(int group_id) { - std::vector<View*> views; - GetRootView()->GetViewsWithGroup(group_id, &views); - if (views.size() > 0) - return views[0]; - else - return NULL; +void View::WriteDragData(const gfx::Point& press_pt, OSExchangeData* data) { + DCHECK(drag_controller_); + drag_controller_->WriteDragData(this, press_pt, data); } -void View::SetID(int id) { - id_ = id; +void View::OnDragDone() { } -int View::GetID() const { - return id_; +bool View::InDrag() { + RootView* root_view = GetRootView(); + return root_view ? (root_view->GetDragView() == this) : false; } -void View::SetGroup(int gid) { - // Don't change the group id once it's set. - DCHECK(group_ == -1 || group_ == gid); - group_ = gid; -} +//////////////////////////////////////////////////////////////////////////////// +// View, private: -int View::GetGroup() const { - return group_; +// DropInfo -------------------------------------------------------------------- + +void View::DragInfo::Reset() { + possible_drag = false; + start_pt = gfx::Point(); } -void View::SetParent(View* parent) { - if (parent != parent_) - parent_ = parent; +void View::DragInfo::PossibleDrag(const gfx::Point& p) { + possible_drag = true; + start_pt = p; } -bool View::IsParentOf(View* v) const { - DCHECK(v); - View* parent = v->GetParent(); - while (parent) { - if (this == parent) - return true; - parent = parent->GetParent(); +// Tree operations ------------------------------------------------------------- + +void View::DoRemoveChildView(View* a_view, + bool update_focus_cycle, + bool update_tool_tip, + bool delete_removed_view) { +#ifndef NDEBUG + DCHECK(!IsProcessingPaint()) << "Should not be removing a child view " << + "during a paint, this will seriously " << + "mess things up!"; +#endif + DCHECK(a_view); + const ViewList::iterator i = find(child_views_.begin(), + child_views_.end(), + a_view); + scoped_ptr<View> view_to_be_deleted; + if (i != child_views_.end()) { + if (update_focus_cycle) { + // Let's remove the view from the focus traversal. + View* next_focusable = a_view->next_focusable_view_; + View* prev_focusable = a_view->previous_focusable_view_; + if (prev_focusable) + prev_focusable->next_focusable_view_ = next_focusable; + if (next_focusable) + next_focusable->previous_focusable_view_ = prev_focusable; + } + + RootView* root = GetRootView(); + if (root) + UnregisterChildrenForVisibleBoundsNotification(root, a_view); + a_view->PropagateRemoveNotifications(this); + a_view->SetParent(NULL); + + if (delete_removed_view && a_view->IsParentOwned()) + view_to_be_deleted.reset(a_view); + + child_views_.erase(i); } - return false; + + if (update_tool_tip) + UpdateTooltip(); + + if (layout_manager_.get()) + layout_manager_->ViewRemoved(this, a_view); } -int View::GetChildIndex(const View* v) const { - for (int i = 0, count = GetChildViewCount(); i < count; i++) { - if (v == GetChildViewAt(i)) - return i; - } - return -1; +void View::SetParent(View* parent) { + if (parent != parent_) + parent_ = parent; } -/////////////////////////////////////////////////////////////////////////////// -// -// View - focus -// -/////////////////////////////////////////////////////////////////////////////// +void View::PropagateRemoveNotifications(View* parent) { + for (int i = 0, count = GetChildViewCount(); i < count; ++i) + GetChildViewAt(i)->PropagateRemoveNotifications(parent); -View* View::GetNextFocusableView() { - return next_focusable_view_; + for (View* v = this; v; v = v->GetParent()) + v->ViewHierarchyChangedImpl(true, false, parent, this); } -View* View::GetPreviousFocusableView() { - return previous_focusable_view_; +void View::PropagateAddNotifications(View* parent, View* child) { + for (int i = 0, count = GetChildViewCount(); i < count; ++i) + GetChildViewAt(i)->PropagateAddNotifications(parent, child); + ViewHierarchyChangedImpl(true, true, parent, child); } -void View::SetNextFocusableView(View* view) { - view->previous_focusable_view_ = this; - next_focusable_view_ = view; +void View::PropagateNativeViewHierarchyChanged(bool attached, + gfx::NativeView native_view, + RootView* root_view) { + for (int i = 0, count = GetChildViewCount(); i < count; ++i) + GetChildViewAt(i)->PropagateNativeViewHierarchyChanged(attached, + native_view, + root_view); + NativeViewHierarchyChanged(attached, native_view, root_view); } -void View::InitFocusSiblings(View* v, int index) { - int child_count = static_cast<int>(child_views_.size()); - - if (child_count == 0) { - v->next_focusable_view_ = NULL; - v->previous_focusable_view_ = NULL; - } else { - if (index == child_count) { - // We are inserting at the end, but the end of the child list may not be - // the last focusable element. Let's try to find an element with no next - // focusable element to link to. - View* last_focusable_view = NULL; - for (std::vector<View*>::iterator iter = child_views_.begin(); - iter != child_views_.end(); ++iter) { - if (!(*iter)->next_focusable_view_) { - last_focusable_view = *iter; - break; - } - } - if (last_focusable_view == NULL) { - // Hum... there is a cycle in the focus list. Let's just insert ourself - // after the last child. - View* prev = child_views_[index - 1]; - v->previous_focusable_view_ = prev; - v->next_focusable_view_ = prev->next_focusable_view_; - prev->next_focusable_view_->previous_focusable_view_ = v; - prev->next_focusable_view_ = v; +void View::ViewHierarchyChangedImpl(bool register_accelerators, + bool is_add, + View* parent, + View* child) { + if (register_accelerators) { + if (is_add) { + // If you get this registration, you are part of a subtree that has been + // added to the view hierarchy. + if (GetFocusManager()) { + RegisterPendingAccelerators(); } else { - last_focusable_view->next_focusable_view_ = v; - v->next_focusable_view_ = NULL; - v->previous_focusable_view_ = last_focusable_view; + // Delay accelerator registration until visible as we do not have + // focus manager until then. + accelerator_registration_delayed_ = true; } } else { - View* prev = child_views_[index]->GetPreviousFocusableView(); - v->previous_focusable_view_ = prev; - v->next_focusable_view_ = child_views_[index]; - if (prev) - prev->next_focusable_view_ = v; - child_views_[index]->previous_focusable_view_ = v; + if (child == this) + UnregisterAccelerators(true); } } -} -#ifndef NDEBUG -void View::PrintViewHierarchy() { - PrintViewHierarchyImp(0); + ViewHierarchyChanged(is_add, parent, child); + parent->needs_layout_ = true; } +#ifndef NDEBUG void View::PrintViewHierarchyImp(int indent) { std::wostringstream buf; int ind = indent; @@ -1007,11 +1223,6 @@ void View::PrintViewHierarchyImp(int indent) { GetChildViewAt(i)->PrintViewHierarchyImp(indent + 2); } - -void View::PrintFocusHierarchy() { - PrintFocusHierarchyImp(0); -} - void View::PrintFocusHierarchyImp(int indent) { std::wostringstream buf; int ind = indent; @@ -1037,164 +1248,62 @@ void View::PrintFocusHierarchyImp(int indent) { } #endif -//////////////////////////////////////////////////////////////////////////////// -// -// View - accelerators -// -//////////////////////////////////////////////////////////////////////////////// - -void View::AddAccelerator(const Accelerator& accelerator) { - if (!accelerators_.get()) - accelerators_.reset(new std::vector<Accelerator>()); - - std::vector<Accelerator>::iterator iter = - std::find(accelerators_->begin(), accelerators_->end(), accelerator); - DCHECK(iter == accelerators_->end()) - << "Registering the same accelerator multiple times"; - - accelerators_->push_back(accelerator); - RegisterPendingAccelerators(); -} - -void View::RemoveAccelerator(const Accelerator& accelerator) { - std::vector<Accelerator>::iterator iter; - if (!accelerators_.get() || - ((iter = std::find(accelerators_->begin(), accelerators_->end(), - accelerator)) == accelerators_->end())) { - NOTREACHED() << "Removing non-existing accelerator"; - return; - } - - size_t index = iter - accelerators_->begin(); - accelerators_->erase(iter); - if (index >= registered_accelerator_count_) { - // The accelerator is not registered to FocusManager. - return; - } - --registered_accelerator_count_; - - RootView* root_view = GetRootView(); - if (!root_view) { - // We are not part of a view hierarchy, so there is nothing to do as we - // removed ourselves from accelerators_, we won't be registered when added - // to one. - return; - } - - // If accelerator_focus_manager_ is NULL then we did not registered - // accelerators so there is nothing to unregister. - if (accelerator_focus_manager_) { - accelerator_focus_manager_->UnregisterAccelerator(accelerator, this); - } -} - -void View::ResetAccelerators() { - if (accelerators_.get()) - UnregisterAccelerators(false); -} - -void View::RegisterPendingAccelerators() { - if (!accelerators_.get() || - registered_accelerator_count_ == accelerators_->size()) { - // No accelerators are waiting for registration. - return; - } - - RootView* root_view = GetRootView(); - if (!root_view) { - // We are not yet part of a view hierarchy, we'll register ourselves once - // added to one. - return; - } - - accelerator_focus_manager_ = GetFocusManager(); - if (!accelerator_focus_manager_) { - // Some crash reports seem to show that we may get cases where we have no - // focus manager (see bug #1291225). This should never be the case, just - // making sure we don't crash. - - // TODO(jcampan): This fails for a view under WidgetGtk with TYPE_CHILD. - // (see http://crbug.com/21335) reenable NOTREACHED assertion and - // verify accelerators works as expected. -#if defined(OS_WIN) - NOTREACHED(); -#endif - return; - } - // Only register accelerators if we are visible. - if (!IsVisibleInRootView()) - return; - std::vector<Accelerator>::const_iterator iter; - for (iter = accelerators_->begin() + registered_accelerator_count_; - iter != accelerators_->end(); ++iter) { - accelerator_focus_manager_->RegisterAccelerator(*iter, this); - } - registered_accelerator_count_ = accelerators_->size(); -} - -void View::UnregisterAccelerators(bool leave_data_intact) { - if (!accelerators_.get()) - return; - - RootView* root_view = GetRootView(); - if (root_view) { - if (accelerator_focus_manager_) { - // We may not have a FocusManager if the window containing us is being - // closed, in which case the FocusManager is being deleted so there is - // nothing to unregister. - accelerator_focus_manager_->UnregisterAccelerators(this); - accelerator_focus_manager_ = NULL; - } - if (!leave_data_intact) { - accelerators_->clear(); - accelerators_.reset(); - } - registered_accelerator_count_ = 0; - } -} - -int View::GetDragOperations(const gfx::Point& press_pt) { - return drag_controller_ ? - drag_controller_->GetDragOperations(this, press_pt) : - ui::DragDropTypes::DRAG_NONE; -} +// Size and disposition -------------------------------------------------------- -void View::WriteDragData(const gfx::Point& press_pt, OSExchangeData* data) { - DCHECK(drag_controller_); - drag_controller_->WriteDragData(this, press_pt, data); +void View::PropagateVisibilityNotifications(View* start, bool is_visible) { + for (int i = 0, count = GetChildViewCount(); i < count; ++i) + GetChildViewAt(i)->PropagateVisibilityNotifications(start, is_visible); + VisibilityChangedImpl(start, is_visible); } -void View::OnDragDone() { +void View::VisibilityChangedImpl(View* starting_from, bool is_visible) { + if (is_visible) + RegisterPendingAccelerators(); + else + UnregisterAccelerators(true); + VisibilityChanged(starting_from, is_visible); } -bool View::InDrag() { - RootView* root_view = GetRootView(); - return root_view ? (root_view->GetDragView() == this) : false; +// static +void View::RegisterChildrenForVisibleBoundsNotification( + RootView* root, View* view) { + DCHECK(root && view); + if (view->GetNotifyWhenVisibleBoundsInRootChanges()) + root->RegisterViewForVisibleBoundsNotification(view); + for (int i = 0; i < view->GetChildViewCount(); ++i) + RegisterChildrenForVisibleBoundsNotification(root, view->GetChildViewAt(i)); } -bool View::GetAccessibleName(string16* name) { - DCHECK(name); - - if (accessible_name_.empty()) - return false; - *name = accessible_name_; - return true; +// static +void View::UnregisterChildrenForVisibleBoundsNotification( + RootView* root, View* view) { + DCHECK(root && view); + if (view->GetNotifyWhenVisibleBoundsInRootChanges()) + root->UnregisterViewForVisibleBoundsNotification(view); + for (int i = 0; i < view->GetChildViewCount(); ++i) + UnregisterChildrenForVisibleBoundsNotification(root, + view->GetChildViewAt(i)); } -AccessibilityTypes::Role View::GetAccessibleRole() { - return AccessibilityTypes::ROLE_CLIENT; +void View::AddDescendantToNotify(View* view) { + DCHECK(view); + if (!descendants_to_notify_.get()) + descendants_to_notify_.reset(new ViewList()); + descendants_to_notify_->push_back(view); } -void View::SetAccessibleName(const string16& name) { - accessible_name_ = name; +void View::RemoveDescendantToNotify(View* view) { + DCHECK(view && descendants_to_notify_.get()); + ViewList::iterator i = find(descendants_to_notify_->begin(), + descendants_to_notify_->end(), + view); + DCHECK(i != descendants_to_notify_->end()); + descendants_to_notify_->erase(i); + if (descendants_to_notify_->empty()) + descendants_to_notify_.reset(); } -// static -void View::ConvertPointToView(const View* src, - const View* dst, - gfx::Point* point) { - ConvertPointToView(src, dst, point, true); -} +// Coordinate conversion ------------------------------------------------------- // static void View::ConvertPointToView(const View* src, @@ -1238,202 +1347,194 @@ void View::ConvertPointToView(const View* src, } } -// static -void View::ConvertPointToWidget(const View* src, gfx::Point* p) { - DCHECK(src); - DCHECK(p); +// Input ----------------------------------------------------------------------- - gfx::Point offset; - for (const View* v = src; v; v = v->GetParent()) { - offset.set_x(offset.x() + v->GetX(APPLY_MIRRORING_TRANSFORMATION)); - offset.set_y(offset.y() + v->y()); - } - p->SetPoint(p->x() + offset.x(), p->y() + offset.y()); -} +bool View::ProcessMousePressed(const MouseEvent& e, DragInfo* drag_info) { + const bool enabled = IsEnabled(); + int drag_operations = + (enabled && e.IsOnlyLeftMouseButton() && HitTest(e.location())) ? + GetDragOperations(e.location()) : 0; + ContextMenuController* context_menu_controller = e.IsRightMouseButton() ? + context_menu_controller_ : 0; -// static -void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { - gfx::Point t; - ConvertPointToWidget(dest, &t); - p->SetPoint(p->x() - t.x(), p->y() - t.y()); -} + const bool result = OnMousePressed(e); + // WARNING: we may have been deleted, don't use any View variables; -// static -void View::ConvertPointToScreen(const View* src, gfx::Point* p) { - DCHECK(src); - DCHECK(p); + if (!enabled) + return result; - // If the view is not connected to a tree, there's nothing we can do. - Widget* widget = src->GetWidget(); - if (widget) { - ConvertPointToWidget(src, p); - gfx::Rect r; - widget->GetBounds(&r, false); - p->SetPoint(p->x() + r.x(), p->y() + r.y()); + if (drag_operations != ui::DragDropTypes::DRAG_NONE) { + drag_info->PossibleDrag(e.location()); + return true; } + return !!context_menu_controller || result; } -gfx::Rect View::GetScreenBounds() const { - gfx::Point origin; - View::ConvertPointToScreen(this, &origin); - return gfx::Rect(origin, size()); -} - -///////////////////////////////////////////////////////////////////////////// -// -// View - event handlers -// -///////////////////////////////////////////////////////////////////////////// - -bool View::OnMousePressed(const MouseEvent& e) { - return false; -} - -bool View::OnMouseDragged(const MouseEvent& e) { - return false; -} - -void View::OnMouseReleased(const MouseEvent& e, bool canceled) { -} - -void View::OnMouseMoved(const MouseEvent& e) { -} - -void View::OnMouseEntered(const MouseEvent& e) { +bool View::ProcessMouseDragged(const MouseEvent& e, DragInfo* drag_info) { + // Copy the field, that way if we're deleted after drag and drop no harm is + // done. + ContextMenuController* context_menu_controller = context_menu_controller_; + const bool possible_drag = drag_info->possible_drag; + if (possible_drag && ExceededDragThreshold(drag_info->start_pt.x() - e.x(), + drag_info->start_pt.y() - e.y())) { + if (!drag_controller_ || + drag_controller_->CanStartDrag(this, drag_info->start_pt, e.location())) + DoDrag(e, drag_info->start_pt); + } else { + if (OnMouseDragged(e)) + return true; + // Fall through to return value based on context menu controller. + } + // WARNING: we may have been deleted. + return (context_menu_controller != NULL) || possible_drag; } -void View::OnMouseExited(const MouseEvent& e) { +void View::ProcessMouseReleased(const MouseEvent& e, bool canceled) { + if (!canceled && context_menu_controller_ && e.IsOnlyRightMouseButton()) { + // Assume that if there is a context menu controller we won't be deleted + // from mouse released. + gfx::Point location(e.location()); + OnMouseReleased(e, canceled); + if (HitTest(location)) { + ConvertPointToScreen(this, &location); + ShowContextMenu(location, true); + } + } else { + OnMouseReleased(e, canceled); + } + // WARNING: we may have been deleted. } #if defined(TOUCH_UI) -View::TouchStatus View::OnTouchEvent(const TouchEvent& event) { - DVLOG(1) << "visited the OnTouchEvent"; - return TOUCH_STATUS_UNKNOWN; +View::TouchStatus View::ProcessTouchEvent(const TouchEvent& e) { + // TODO(rjkroege): Implement a grab scheme similar to as + // as is found in MousePressed. + return OnTouchEvent(e); } #endif -void View::SetMouseHandler(View *new_mouse_handler) { - // It is valid for new_mouse_handler to be NULL - if (parent_) - parent_->SetMouseHandler(new_mouse_handler); -} - -void View::SetVisible(bool flag) { - if (flag != is_visible_) { - // If the tab is currently visible, schedule paint to - // refresh parent - if (IsVisible()) - SchedulePaint(); - - is_visible_ = flag; - - // This notifies all subviews recursively. - PropagateVisibilityNotifications(this, flag); +// Accelerators ---------------------------------------------------------------- - // If we are newly visible, schedule paint. - if (IsVisible()) - SchedulePaint(); +void View::RegisterPendingAccelerators() { + if (!accelerators_.get() || + registered_accelerator_count_ == accelerators_->size()) { + // No accelerators are waiting for registration. + return; } -} - -bool View::IsVisibleInRootView() const { - View* parent = GetParent(); - if (IsVisible() && parent) - return parent->IsVisibleInRootView(); - else - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -// View - keyboard and focus -// -///////////////////////////////////////////////////////////////////////////// - -void View::RequestFocus() { - RootView* rv = GetRootView(); - if (rv && IsFocusableInRootView()) - rv->FocusView(this); -} - -void View::WillGainFocus() { -} - -void View::DidGainFocus() { -} - -void View::WillLoseFocus() { -} -bool View::OnKeyPressed(const KeyEvent& e) { - return false; -} - -bool View::OnKeyReleased(const KeyEvent& e) { - return false; -} - -bool View::OnMouseWheel(const MouseWheelEvent& e) { - return false; -} - -void View::SetDragController(DragController* drag_controller) { - drag_controller_ = drag_controller; -} - -DragController* View::GetDragController() { - return drag_controller_; -} + RootView* root_view = GetRootView(); + if (!root_view) { + // We are not yet part of a view hierarchy, we'll register ourselves once + // added to one. + return; + } -bool View::GetDropFormats( - int* formats, - std::set<OSExchangeData::CustomFormat>* custom_formats) { - return false; -} + accelerator_focus_manager_ = GetFocusManager(); + if (!accelerator_focus_manager_) { + // Some crash reports seem to show that we may get cases where we have no + // focus manager (see bug #1291225). This should never be the case, just + // making sure we don't crash. -bool View::AreDropTypesRequired() { - return false; + // TODO(jcampan): This fails for a view under WidgetGtk with TYPE_CHILD. + // (see http://crbug.com/21335) reenable NOTREACHED assertion and + // verify accelerators works as expected. +#if defined(OS_WIN) + NOTREACHED(); +#endif + return; + } + // Only register accelerators if we are visible. + if (!IsVisibleInRootView()) + return; + std::vector<Accelerator>::const_iterator iter; + for (iter = accelerators_->begin() + registered_accelerator_count_; + iter != accelerators_->end(); ++iter) { + accelerator_focus_manager_->RegisterAccelerator(*iter, this); + } + registered_accelerator_count_ = accelerators_->size(); } -bool View::CanDrop(const OSExchangeData& data) { - // TODO(sky): when I finish up migration, this should default to true. - return false; -} +void View::UnregisterAccelerators(bool leave_data_intact) { + if (!accelerators_.get()) + return; -void View::OnDragEntered(const DropTargetEvent& event) { + RootView* root_view = GetRootView(); + if (root_view) { + if (accelerator_focus_manager_) { + // We may not have a FocusManager if the window containing us is being + // closed, in which case the FocusManager is being deleted so there is + // nothing to unregister. + accelerator_focus_manager_->UnregisterAccelerators(this); + accelerator_focus_manager_ = NULL; + } + if (!leave_data_intact) { + accelerators_->clear(); + accelerators_.reset(); + } + registered_accelerator_count_ = 0; + } } -int View::OnDragUpdated(const DropTargetEvent& event) { - return ui::DragDropTypes::DRAG_NONE; -} +// Focus ----------------------------------------------------------------------- -void View::OnDragExited() { -} +void View::InitFocusSiblings(View* v, int index) { + int child_count = static_cast<int>(child_views_.size()); -int View::OnPerformDrop(const DropTargetEvent& event) { - return ui::DragDropTypes::DRAG_NONE; + if (child_count == 0) { + v->next_focusable_view_ = NULL; + v->previous_focusable_view_ = NULL; + } else { + if (index == child_count) { + // We are inserting at the end, but the end of the child list may not be + // the last focusable element. Let's try to find an element with no next + // focusable element to link to. + View* last_focusable_view = NULL; + for (std::vector<View*>::iterator iter = child_views_.begin(); + iter != child_views_.end(); ++iter) { + if (!(*iter)->next_focusable_view_) { + last_focusable_view = *iter; + break; + } + } + if (last_focusable_view == NULL) { + // Hum... there is a cycle in the focus list. Let's just insert ourself + // after the last child. + View* prev = child_views_[index - 1]; + v->previous_focusable_view_ = prev; + v->next_focusable_view_ = prev->next_focusable_view_; + prev->next_focusable_view_->previous_focusable_view_ = v; + prev->next_focusable_view_ = v; + } else { + last_focusable_view->next_focusable_view_ = v; + v->next_focusable_view_ = NULL; + v->previous_focusable_view_ = last_focusable_view; + } + } else { + View* prev = child_views_[index]->GetPreviousFocusableView(); + v->previous_focusable_view_ = prev; + v->next_focusable_view_ = child_views_[index]; + if (prev) + prev->next_focusable_view_ = v; + child_views_[index]->previous_focusable_view_ = v; + } + } } -// static -bool View::ExceededDragThreshold(int delta_x, int delta_y) { - return (abs(delta_x) > GetHorizontalDragThreshold() || - abs(delta_y) > GetVerticalDragThreshold()); -} +// System events --------------------------------------------------------------- -// Tooltips ----------------------------------------------------------------- -bool View::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { - return false; +void View::PropagateThemeChanged() { + for (int i = GetChildViewCount() - 1; i >= 0; --i) + GetChildViewAt(i)->PropagateThemeChanged(); + OnThemeChanged(); } -bool View::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) { - return false; +void View::PropagateLocaleChanged() { + for (int i = GetChildViewCount() - 1; i >= 0; --i) + GetChildViewAt(i)->PropagateLocaleChanged(); + OnLocaleChanged(); } -void View::TooltipTextChanged() { - Widget* widget = GetWidget(); - if (widget && widget->GetTooltipManager()) - widget->GetTooltipManager()->TooltipTextChanged(this); -} +// Tooltips -------------------------------------------------------------------- void View::UpdateTooltip() { Widget* widget = GetWidget(); @@ -1441,112 +1542,20 @@ void View::UpdateTooltip() { widget->GetTooltipManager()->UpdateTooltip(); } -std::string View::GetClassName() const { - return kViewClassName; -} - -View* View::GetAncestorWithClassName(const std::string& name) { - for (View* view = this; view; view = view->GetParent()) { - if (view->GetClassName() == name) - return view; - } - return NULL; -} - -gfx::Rect View::GetVisibleBounds() { - if (!IsVisibleInRootView()) - return gfx::Rect(); - gfx::Rect vis_bounds(0, 0, width(), height()); - gfx::Rect ancestor_bounds; - View* view = this; - int root_x = 0; - int root_y = 0; - while (view != NULL && !vis_bounds.IsEmpty()) { - root_x += view->GetX(APPLY_MIRRORING_TRANSFORMATION); - root_y += view->y(); - vis_bounds.Offset(view->GetX(APPLY_MIRRORING_TRANSFORMATION), view->y()); - View* ancestor = view->GetParent(); - if (ancestor != NULL) { - ancestor_bounds.SetRect(0, 0, ancestor->width(), - ancestor->height()); - vis_bounds = vis_bounds.Intersect(ancestor_bounds); - } else if (!view->GetWidget()) { - // If the view has no Widget, we're not visible. Return an empty rect. - return gfx::Rect(); - } - view = ancestor; - } - if (vis_bounds.IsEmpty()) - return vis_bounds; - // Convert back to this views coordinate system. - vis_bounds.Offset(-root_x, -root_y); - return vis_bounds; -} - -int View::GetPageScrollIncrement(ScrollView* scroll_view, - bool is_horizontal, bool is_positive) { - return 0; -} - -int View::GetLineScrollIncrement(ScrollView* scroll_view, - bool is_horizontal, bool is_positive) { - return 0; -} - -ThemeProvider* View::GetThemeProvider() const { - Widget* widget = GetWidget(); - return widget ? widget->GetThemeProvider() : NULL; -} - -// static -void View::RegisterChildrenForVisibleBoundsNotification( - RootView* root, View* view) { - DCHECK(root && view); - if (view->GetNotifyWhenVisibleBoundsInRootChanges()) - root->RegisterViewForVisibleBoundsNotification(view); - for (int i = 0; i < view->GetChildViewCount(); ++i) - RegisterChildrenForVisibleBoundsNotification(root, view->GetChildViewAt(i)); -} - -// static -void View::UnregisterChildrenForVisibleBoundsNotification( - RootView* root, View* view) { - DCHECK(root && view); - if (view->GetNotifyWhenVisibleBoundsInRootChanges()) - root->UnregisterViewForVisibleBoundsNotification(view); - for (int i = 0; i < view->GetChildViewCount(); ++i) - UnregisterChildrenForVisibleBoundsNotification(root, - view->GetChildViewAt(i)); -} +// Drag and drop --------------------------------------------------------------- -void View::AddDescendantToNotify(View* view) { - DCHECK(view); - if (!descendants_to_notify_.get()) - descendants_to_notify_.reset(new ViewList()); - descendants_to_notify_->push_back(view); -} - -void View::RemoveDescendantToNotify(View* view) { - DCHECK(view && descendants_to_notify_.get()); - ViewList::iterator i = find(descendants_to_notify_->begin(), - descendants_to_notify_->end(), - view); - DCHECK(i != descendants_to_notify_->end()); - descendants_to_notify_->erase(i); - if (descendants_to_notify_->empty()) - descendants_to_notify_.reset(); -} - -// DropInfo -------------------------------------------------------------------- +void View::DoDrag(const MouseEvent& e, const gfx::Point& press_pt) { + int drag_operations = GetDragOperations(press_pt); + if (drag_operations == ui::DragDropTypes::DRAG_NONE) + return; -void View::DragInfo::Reset() { - possible_drag = false; - start_pt = gfx::Point(); -} + OSExchangeData data; + WriteDragData(press_pt, &data); -void View::DragInfo::PossibleDrag(const gfx::Point& p) { - possible_drag = true; - start_pt = p; + // Message the RootView to do the drag and drop. That way if we're removed + // the RootView can detect it and avoid calling us back. + RootView* root_view = GetRootView(); + root_view->StartDragForViewFromMouseEvent(this, data, drag_operations); } -} // namespace +} // namespace views |