summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/views/focus/focus_manager.cc300
-rw-r--r--ui/views/view.cc350
-rw-r--r--ui/views/view.h167
3 files changed, 420 insertions, 397 deletions
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 93c299f..501d270 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -69,7 +69,8 @@ FocusManager::WidgetFocusManager::GetInstance() {
return Singleton<WidgetFocusManager>::get();
}
-// FocusManager -----------------------------------------------------
+////////////////////////////////////////////////////////////////////////////////
+// FocusManager, public:
FocusManager::FocusManager(Widget* widget)
: widget_(widget),
@@ -154,13 +155,6 @@ bool FocusManager::OnKeyEvent(const KeyEvent& event) {
return true;
}
-void FocusManager::ValidateFocusedView() {
- if (focused_view_) {
- if (!ContainsView(focused_view_))
- ClearFocus();
- }
-}
-
bool FocusManager::ContainsView(View* view) const {
Widget* widget = view->GetWidget();
return widget ? widget->GetFocusManager() == this : false;
@@ -187,99 +181,6 @@ void FocusManager::AdvanceFocus(bool reverse) {
}
}
-View* FocusManager::GetNextFocusableView(View* original_starting_view,
- bool reverse,
- bool dont_loop) {
- FocusTraversable* focus_traversable = NULL;
-
- // Let's re-validate the focused view.
- ValidateFocusedView();
-
- View* starting_view = NULL;
- if (original_starting_view) {
- // Search up the containment hierarchy to see if a view is acting as
- // a pane, and wants to implement its own focus traversable to keep
- // the focus trapped within that pane.
- View* pane_search = original_starting_view;
- while (pane_search) {
- focus_traversable = pane_search->GetPaneFocusTraversable();
- if (focus_traversable) {
- starting_view = original_starting_view;
- break;
- }
- pane_search = pane_search->parent();
- }
-
- if (!focus_traversable) {
- if (!reverse) {
- // If the starting view has a focus traversable, use it.
- // This is the case with WidgetWins for example.
- focus_traversable = original_starting_view->GetFocusTraversable();
-
- // Otherwise default to the root view.
- if (!focus_traversable) {
- focus_traversable =
- original_starting_view->GetWidget()->GetFocusTraversable();
- starting_view = original_starting_view;
- }
- } else {
- // When you are going back, starting view's FocusTraversable
- // should not be used.
- focus_traversable =
- original_starting_view->GetWidget()->GetFocusTraversable();
- starting_view = original_starting_view;
- }
- }
- } else {
- focus_traversable = widget_->GetFocusTraversable();
- }
-
- // Traverse the FocusTraversable tree down to find the focusable view.
- View* v = FindFocusableView(focus_traversable, starting_view, reverse);
- if (v) {
- return v;
- } else {
- // Let's go up in the FocusTraversable tree.
- FocusTraversable* parent_focus_traversable =
- focus_traversable->GetFocusTraversableParent();
- starting_view = focus_traversable->GetFocusTraversableParentView();
- while (parent_focus_traversable) {
- FocusTraversable* new_focus_traversable = NULL;
- View* new_starting_view = NULL;
- // When we are going backward, the parent view might gain the next focus.
- bool check_starting_view = reverse;
- v = parent_focus_traversable->GetFocusSearch()->FindNextFocusableView(
- starting_view, reverse, FocusSearch::UP,
- check_starting_view, &new_focus_traversable, &new_starting_view);
-
- if (new_focus_traversable) {
- DCHECK(!v);
-
- // There is a FocusTraversable, traverse it down.
- v = FindFocusableView(new_focus_traversable, NULL, reverse);
- }
-
- if (v)
- return v;
-
- starting_view = focus_traversable->GetFocusTraversableParentView();
- parent_focus_traversable =
- parent_focus_traversable->GetFocusTraversableParent();
- }
-
- // If we get here, we have reached the end of the focus hierarchy, let's
- // loop. Make sure there was at least a view to start with, to prevent
- // infinitely looping in empty windows.
- if (!dont_loop && original_starting_view) {
- // Easy, just clear the selection and press tab again.
- // By calling with NULL as the starting view, we'll start from the
- // top_root_view.
- return GetNextFocusableView(NULL, reverse, true);
- }
- }
- return NULL;
-}
-
void FocusManager::SetFocusedViewWithReason(
View* view, FocusChangeReason reason) {
focus_change_reason_ = reason;
@@ -315,6 +216,13 @@ void FocusManager::ClearFocus() {
widget_->native_widget()->FocusNativeView(NULL);
}
+void FocusManager::ValidateFocusedView() {
+ if (focused_view_) {
+ if (!ContainsView(focused_view_))
+ ClearFocus();
+ }
+}
+
void FocusManager::StoreFocusedView() {
ViewStorage* view_storage = ViewStorage::GetInstance();
if (!view_storage) {
@@ -392,40 +300,6 @@ void FocusManager::ClearStoredFocusedView() {
view_storage->RemoveViewByID(stored_focused_view_storage_id_);
}
-// Find the next (previous if reverse is true) focusable view for the specified
-// FocusTraversable, starting at the specified view, traversing down the
-// FocusTraversable hierarchy.
-View* FocusManager::FindFocusableView(FocusTraversable* focus_traversable,
- View* starting_view,
- bool reverse) {
- FocusTraversable* new_focus_traversable = NULL;
- View* new_starting_view = NULL;
- View* v = focus_traversable->GetFocusSearch()->FindNextFocusableView(
- starting_view,
- reverse,
- FocusSearch::DOWN,
- false,
- &new_focus_traversable,
- &new_starting_view);
-
- // Let's go down the FocusTraversable tree as much as we can.
- while (new_focus_traversable) {
- DCHECK(!v);
- focus_traversable = new_focus_traversable;
- starting_view = new_starting_view;
- new_focus_traversable = NULL;
- starting_view = NULL;
- v = focus_traversable->GetFocusSearch()->FindNextFocusableView(
- starting_view,
- reverse,
- FocusSearch::DOWN,
- false,
- &new_focus_traversable,
- &new_starting_view);
- }
- return v;
-}
-
void FocusManager::RegisterAccelerator(
const Accelerator& accelerator,
AcceleratorTarget* target) {
@@ -477,6 +351,24 @@ bool FocusManager::ProcessAccelerator(const Accelerator& accelerator) {
return false;
}
+void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) {
+ DCHECK(std::find(focus_change_listeners_.begin(),
+ focus_change_listeners_.end(), listener) ==
+ focus_change_listeners_.end()) << "Adding a listener twice.";
+ focus_change_listeners_.push_back(listener);
+}
+
+void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) {
+ FocusChangeListenerList::iterator place =
+ std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(),
+ listener);
+ if (place == focus_change_listeners_.end()) {
+ NOTREACHED() << "Removing a listener that isn't registered.";
+ return;
+ }
+ focus_change_listeners_.erase(place);
+}
+
AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
const Accelerator& accelerator) const {
AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator);
@@ -507,22 +399,134 @@ FocusManager* FocusManager::GetFocusManagerForNativeWindow(
return native_widget ? native_widget->GetWidget()->GetFocusManager() : NULL;
}
-void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) {
- DCHECK(std::find(focus_change_listeners_.begin(),
- focus_change_listeners_.end(), listener) ==
- focus_change_listeners_.end()) << "Adding a listener twice.";
- focus_change_listeners_.push_back(listener);
+////////////////////////////////////////////////////////////////////////////////
+// FocusManager, private:
+
+View* FocusManager::GetNextFocusableView(View* original_starting_view,
+ bool reverse,
+ bool dont_loop) {
+ FocusTraversable* focus_traversable = NULL;
+
+ // Let's re-validate the focused view.
+ ValidateFocusedView();
+
+ View* starting_view = NULL;
+ if (original_starting_view) {
+ // Search up the containment hierarchy to see if a view is acting as
+ // a pane, and wants to implement its own focus traversable to keep
+ // the focus trapped within that pane.
+ View* pane_search = original_starting_view;
+ while (pane_search) {
+ focus_traversable = pane_search->GetPaneFocusTraversable();
+ if (focus_traversable) {
+ starting_view = original_starting_view;
+ break;
+ }
+ pane_search = pane_search->parent();
+ }
+
+ if (!focus_traversable) {
+ if (!reverse) {
+ // If the starting view has a focus traversable, use it.
+ // This is the case with WidgetWins for example.
+ focus_traversable = original_starting_view->GetFocusTraversable();
+
+ // Otherwise default to the root view.
+ if (!focus_traversable) {
+ focus_traversable =
+ original_starting_view->GetWidget()->GetFocusTraversable();
+ starting_view = original_starting_view;
+ }
+ } else {
+ // When you are going back, starting view's FocusTraversable
+ // should not be used.
+ focus_traversable =
+ original_starting_view->GetWidget()->GetFocusTraversable();
+ starting_view = original_starting_view;
+ }
+ }
+ } else {
+ focus_traversable = widget_->GetFocusTraversable();
+ }
+
+ // Traverse the FocusTraversable tree down to find the focusable view.
+ View* v = FindFocusableView(focus_traversable, starting_view, reverse);
+ if (v) {
+ return v;
+ } else {
+ // Let's go up in the FocusTraversable tree.
+ FocusTraversable* parent_focus_traversable =
+ focus_traversable->GetFocusTraversableParent();
+ starting_view = focus_traversable->GetFocusTraversableParentView();
+ while (parent_focus_traversable) {
+ FocusTraversable* new_focus_traversable = NULL;
+ View* new_starting_view = NULL;
+ // When we are going backward, the parent view might gain the next focus.
+ bool check_starting_view = reverse;
+ v = parent_focus_traversable->GetFocusSearch()->FindNextFocusableView(
+ starting_view, reverse, FocusSearch::UP,
+ check_starting_view, &new_focus_traversable, &new_starting_view);
+
+ if (new_focus_traversable) {
+ DCHECK(!v);
+
+ // There is a FocusTraversable, traverse it down.
+ v = FindFocusableView(new_focus_traversable, NULL, reverse);
+ }
+
+ if (v)
+ return v;
+
+ starting_view = focus_traversable->GetFocusTraversableParentView();
+ parent_focus_traversable =
+ parent_focus_traversable->GetFocusTraversableParent();
+ }
+
+ // If we get here, we have reached the end of the focus hierarchy, let's
+ // loop. Make sure there was at least a view to start with, to prevent
+ // infinitely looping in empty windows.
+ if (!dont_loop && original_starting_view) {
+ // Easy, just clear the selection and press tab again.
+ // By calling with NULL as the starting view, we'll start from the
+ // top_root_view.
+ return GetNextFocusableView(NULL, reverse, true);
+ }
+ }
+ return NULL;
}
-void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) {
- FocusChangeListenerList::iterator place =
- std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(),
- listener);
- if (place == focus_change_listeners_.end()) {
- NOTREACHED() << "Removing a listener that isn't registered.";
- return;
+// Find the next (previous if reverse is true) focusable view for the specified
+// FocusTraversable, starting at the specified view, traversing down the
+// FocusTraversable hierarchy.
+View* FocusManager::FindFocusableView(FocusTraversable* focus_traversable,
+ View* starting_view,
+ bool reverse) {
+ FocusTraversable* new_focus_traversable = NULL;
+ View* new_starting_view = NULL;
+ View* v = focus_traversable->GetFocusSearch()->FindNextFocusableView(
+ starting_view,
+ reverse,
+ FocusSearch::DOWN,
+ false,
+ &new_focus_traversable,
+ &new_starting_view);
+
+ // Let's go down the FocusTraversable tree as much as we can.
+ while (new_focus_traversable) {
+ DCHECK(!v);
+ focus_traversable = new_focus_traversable;
+ starting_view = new_starting_view;
+ new_focus_traversable = NULL;
+ starting_view = NULL;
+ v = focus_traversable->GetFocusSearch()->FindNextFocusableView(
+ starting_view,
+ reverse,
+ FocusSearch::DOWN,
+ false,
+ &new_focus_traversable,
+ &new_starting_view);
}
- focus_change_listeners_.erase(place);
+ return v;
}
} // namespace ui
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 671692c..cc92c35 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -49,12 +49,12 @@ bool ExceededDragThreshold(const gfx::Point& press_point,
// View, public:
View::View()
- : parent_(NULL),
- parent_owned_(true),
+ : parent_owned_(true),
visible_(true),
enabled_(true),
id_(-1),
group_(-1),
+ parent_(NULL),
focusable_(false),
next_focusable_view_(NULL),
prev_focusable_view_(NULL),
@@ -163,6 +163,33 @@ void View::SetEnabled(bool enabled) {
}
}
+// Attributes ------------------------------------------------------------------
+
+View* View::GetViewById(int id) const {
+ if (id_ == id)
+ return const_cast<View*>(this);
+ ViewVector::const_iterator it = children_.begin();
+ for (; it != children_.end(); ++it) {
+ View* view = (*it)->GetViewById(id);
+ if (view)
+ return view;
+ }
+ return NULL;
+}
+
+void View::GetViewsWithGroup(int group, ViewVector* vec) const {
+ if (group_ == group)
+ vec->push_back(const_cast<View*>(this));
+ ViewVector::const_iterator it = children_.begin();
+ for (; it != children_.end(); ++it)
+ (*it)->GetViewsWithGroup(group, vec);
+}
+
+View* View::GetSelectedViewForGroup(int group_id) {
+ // TODO(beng): implementme
+ return NULL;
+}
+
// Coordinate conversion -------------------------------------------------------
// static
@@ -278,31 +305,6 @@ bool View::Contains(View* child) {
return false;
}
-View* View::GetViewById(int id) const {
- if (id_ == id)
- return const_cast<View*>(this);
- ViewVector::const_iterator it = children_.begin();
- for (; it != children_.end(); ++it) {
- View* view = (*it)->GetViewById(id);
- if (view)
- return view;
- }
- return NULL;
-}
-
-void View::GetViewsWithGroup(int group, ViewVector* vec) const {
- if (group_ == group)
- vec->push_back(const_cast<View*>(this));
- ViewVector::const_iterator it = children_.begin();
- for (; it != children_.end(); ++it)
- (*it)->GetViewsWithGroup(group, vec);
-}
-
-View* View::GetSelectedViewForGroup(int group_id) {
- // TODO(beng): implementme
- return NULL;
-}
-
// Painting --------------------------------------------------------------------
void View::Invalidate() {
@@ -396,41 +398,33 @@ void View::OnViewAddedToWidget() {
void View::OnViewRemovedFromWidget() {
}
-// Accelerators ----------------------------------------------------------------
-
-bool View::OnAcceleratorPressed(const Accelerator& accelerator) {
- return false;
-}
-
-// Focus -----------------------------------------------------------------------
-
-bool View::SkipDefaultKeyEventProcessing(const KeyEvent& event) const {
- return false;
-}
-
-bool View::IsGroupFocusTraversable() const {
- return true;
-}
+// Painting --------------------------------------------------------------------
-bool View::IsFocusableInRootView() const {
- // TODO(beng): kill this, replace with direct check in focus manager.
- return IsFocusable();
+void View::PaintChildren(gfx::Canvas* canvas) {
+ // TODO(beng): use for_each.
+ // std::for_each(children_.begin(), children_.end(),
+ // std::bind2nd(std::mem_fun_ref(&View::Paint), canvas));
+ ViewVector::iterator it = children_.begin();
+ for (; it != children_.end(); ++it)
+ (*it)->Paint(canvas);
}
-bool View::IsAccessibilityFocusableInRootView() const {
- // TODO(beng): kill this, replace with direct check in focus manager.
- return false;
+void View::OnPaint(gfx::Canvas* canvas) {
+ // TODO(beng): investigate moving these function calls to Paint().
+ OnPaintBackground(canvas);
+ OnPaintFocusBorder(canvas);
+ OnPaintBorder(canvas);
}
-FocusTraversable* View::GetPaneFocusTraversable() const {
- // TODO(beng): figure out what to do about this.
- return NULL;
+void View::OnPaintBackground(gfx::Canvas* canvas) {
}
-void View::OnFocus(/* const FocusEvent& event */) {
+void View::OnPaintBorder(gfx::Canvas* canvas) {
+ if (border_.get())
+ border_->Paint(const_cast<const View*>(this), canvas);
}
-void View::OnBlur() {
+void View::OnPaintFocusBorder(gfx::Canvas* canvas) {
}
// Input -----------------------------------------------------------------------
@@ -495,33 +489,41 @@ void View::OnMouseExited(const MouseEvent& event) {
}
-// Painting --------------------------------------------------------------------
+// Accelerators ----------------------------------------------------------------
-void View::PaintChildren(gfx::Canvas* canvas) {
- // TODO(beng): use for_each.
- // std::for_each(children_.begin(), children_.end(),
- // std::bind2nd(std::mem_fun_ref(&View::Paint), canvas));
- ViewVector::iterator it = children_.begin();
- for (; it != children_.end(); ++it)
- (*it)->Paint(canvas);
+bool View::OnAcceleratorPressed(const Accelerator& accelerator) {
+ return false;
}
-void View::OnPaint(gfx::Canvas* canvas) {
- // TODO(beng): investigate moving these function calls to Paint().
- OnPaintBackground(canvas);
- OnPaintFocusBorder(canvas);
- OnPaintBorder(canvas);
+// Focus -----------------------------------------------------------------------
+
+bool View::SkipDefaultKeyEventProcessing(const KeyEvent& event) const {
+ return false;
}
-void View::OnPaintBackground(gfx::Canvas* canvas) {
+bool View::IsGroupFocusTraversable() const {
+ return true;
}
-void View::OnPaintBorder(gfx::Canvas* canvas) {
- if (border_.get())
- border_->Paint(const_cast<const View*>(this), canvas);
+bool View::IsFocusableInRootView() const {
+ // TODO(beng): kill this, replace with direct check in focus manager.
+ return IsFocusable();
}
-void View::OnPaintFocusBorder(gfx::Canvas* canvas) {
+bool View::IsAccessibilityFocusableInRootView() const {
+ // TODO(beng): kill this, replace with direct check in focus manager.
+ return false;
+}
+
+FocusTraversable* View::GetPaneFocusTraversable() const {
+ // TODO(beng): figure out what to do about this.
+ return NULL;
+}
+
+void View::OnFocus(/* const FocusEvent& event */) {
+}
+
+void View::OnBlur() {
}
////////////////////////////////////////////////////////////////////////////////
@@ -537,47 +539,59 @@ void View::DragInfo::PossibleDrag(const gfx::Point& point) {
press_point = point;
}
-// Focus -----------------------------------------------------------------------
+// Tree operations -------------------------------------------------------------
-// TODO(beng): Move to FocusManager.
-void View::InitFocusSiblings(View* view, size_t index) {
- if (child_count() == 0) {
- view->next_focusable_view_ = NULL;
- view->prev_focusable_view_ = NULL;
+void View::NotifyHierarchyChanged(View* parent, View* child, bool is_add) {
+ // Notify the child. Note that we call GetWidget() on the parent, not the
+ // child, since this method is called after the child is already removed from
+ // the hierarchy when |is_add| is false and so child->GetWidget() will always
+ // return NULL.
+ bool has_widget = parent->GetWidget() != NULL;
+ CallViewNotification(child, parent, child, is_add, has_widget);
+
+ // Notify the hierarchy up.
+ NotifyHierarchyChangedUp(parent, child, is_add);
+
+ // Notify the hierarchy down.
+ if (!is_add) {
+ // Because |child| has already been removed from |parent|'s child list, we
+ // need to notify its hierarchy manually.
+ child->NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+ }
+ NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+}
+
+void View::NotifyHierarchyChangedUp(View* parent, View* child, bool is_add) {
+ for (View* v = parent; v; v = v->parent()) {
+ if (is_add)
+ v->OnViewAdded(parent, child);
+ else
+ v->OnViewRemoved(parent, child);
+ }
+}
+
+void View::NotifyHierarchyChangedDown(View* parent, View* child, bool is_add,
+ bool has_widget) {
+ ViewVector::iterator it = children_.begin();
+ for (; it != children_.end(); ++it) {
+ CallViewNotification(*it, parent, child, is_add, has_widget);
+ (*it)->NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+ }
+}
+
+void View::CallViewNotification(View* target,
+ View* parent,
+ View* child,
+ bool is_add,
+ bool has_widget) {
+ if (is_add) {
+ target->OnViewAdded(parent, child);
+ if (has_widget)
+ target->OnViewAddedToWidget();
} 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 = children_.begin();
- iter != children_.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 = children_[index - 1];
- view->prev_focusable_view_ = prev;
- view->next_focusable_view_ = prev->next_focusable_view_;
- prev->next_focusable_view_->prev_focusable_view_ = view;
- prev->next_focusable_view_ = view;
- } else {
- last_focusable_view->next_focusable_view_ = view;
- view->next_focusable_view_ = NULL;
- view->prev_focusable_view_ = last_focusable_view;
- }
- } else {
- View* prev = children_[index]->GetPreviousFocusableView();
- view->prev_focusable_view_ = prev;
- view->next_focusable_view_ = children_[index];
- if (prev)
- prev->next_focusable_view_ = view;
- children_[index]->prev_focusable_view_ = view;
- }
+ target->OnViewRemoved(parent, child);
+ if (has_widget)
+ target->OnViewRemovedFromWidget();
}
}
@@ -598,24 +612,7 @@ void View::Paint(gfx::Canvas* canvas) {
}
}
-// Drag & Drop -----------------------------------------------------------------
-
-int View::GetDragOperations(const gfx::Point& point) {
- return drag_controller_ ?
- drag_controller_->GetDragOperations(const_cast<View*>(this), point) :
- DragDropTypes::DRAG_NONE;
-}
-
-void View::WriteDragData(const gfx::Point& point, OSExchangeData* data) {
- drag_controller_->WriteDragData(this, point, data);
-}
-
-void View::StartShellDrag(const MouseEvent& event,
- const gfx::Point& press_point) {
- // TODO(beng): system stuff.
-}
-
-// RootView API ----------------------------------------------------------------
+// Input -----------------------------------------------------------------------
bool View::MousePressed(const MouseEvent& event, DragInfo* drag_info) {
bool handled = OnMousePressed(event);
@@ -663,60 +660,65 @@ void View::MouseReleased(const MouseEvent& event) {
}
}
-// Tree operations -------------------------------------------------------------
-
-void View::NotifyHierarchyChanged(View* parent, View* child, bool is_add) {
- // Notify the child. Note that we call GetWidget() on the parent, not the
- // child, since this method is called after the child is already removed from
- // the hierarchy when |is_add| is false and so child->GetWidget() will always
- // return NULL.
- bool has_widget = parent->GetWidget() != NULL;
- CallViewNotification(child, parent, child, is_add, has_widget);
-
- // Notify the hierarchy up.
- NotifyHierarchyChangedUp(parent, child, is_add);
+// Focus -----------------------------------------------------------------------
- // Notify the hierarchy down.
- if (!is_add) {
- // Because |child| has already been removed from |parent|'s child list, we
- // need to notify its hierarchy manually.
- child->NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
+// TODO(beng): Move to FocusManager.
+void View::InitFocusSiblings(View* view, size_t index) {
+ if (child_count() == 0) {
+ view->next_focusable_view_ = NULL;
+ view->prev_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 = children_.begin();
+ iter != children_.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 = children_[index - 1];
+ view->prev_focusable_view_ = prev;
+ view->next_focusable_view_ = prev->next_focusable_view_;
+ prev->next_focusable_view_->prev_focusable_view_ = view;
+ prev->next_focusable_view_ = view;
+ } else {
+ last_focusable_view->next_focusable_view_ = view;
+ view->next_focusable_view_ = NULL;
+ view->prev_focusable_view_ = last_focusable_view;
+ }
+ } else {
+ View* prev = children_[index]->GetPreviousFocusableView();
+ view->prev_focusable_view_ = prev;
+ view->next_focusable_view_ = children_[index];
+ if (prev)
+ prev->next_focusable_view_ = view;
+ children_[index]->prev_focusable_view_ = view;
+ }
}
- NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
}
-void View::NotifyHierarchyChangedUp(View* parent, View* child, bool is_add) {
- for (View* v = parent; v; v = v->parent()) {
- if (is_add)
- v->OnViewAdded(parent, child);
- else
- v->OnViewRemoved(parent, child);
- }
+// Drag & Drop -----------------------------------------------------------------
+
+int View::GetDragOperations(const gfx::Point& point) {
+ return drag_controller_ ?
+ drag_controller_->GetDragOperations(const_cast<View*>(this), point) :
+ DragDropTypes::DRAG_NONE;
}
-void View::NotifyHierarchyChangedDown(View* parent, View* child, bool is_add,
- bool has_widget) {
- ViewVector::iterator it = children_.begin();
- for (; it != children_.end(); ++it) {
- CallViewNotification(*it, parent, child, is_add, has_widget);
- (*it)->NotifyHierarchyChangedDown(parent, child, is_add, has_widget);
- }
+void View::WriteDragData(const gfx::Point& point, OSExchangeData* data) {
+ drag_controller_->WriteDragData(this, point, data);
}
-void View::CallViewNotification(View* target,
- View* parent,
- View* child,
- bool is_add,
- bool has_widget) {
- if (is_add) {
- target->OnViewAdded(parent, child);
- if (has_widget)
- target->OnViewAddedToWidget();
- } else {
- target->OnViewRemoved(parent, child);
- if (has_widget)
- target->OnViewRemovedFromWidget();
- }
+void View::StartShellDrag(const MouseEvent& event,
+ const gfx::Point& press_point) {
+ // TODO(beng): system stuff.
}
} // namespace ui
diff --git a/ui/views/view.h b/ui/views/view.h
index 870ef92..931ea5d 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -104,6 +104,24 @@ class View {
bool enabled() const { return enabled_; }
void SetEnabled(bool enabled);
+ // Attributes ----------------------------------------------------------------
+
+ int id() const { return id_; }
+ void set_id(int id) { id_ = id; }
+ int group() const { return group_; }
+ void set_group(int group) { group_ = group; }
+
+ // Returns the View within this View's hierarchy whose id matches that
+ // specified.
+ View* GetViewById(int id) const;
+
+ // Populates a ViewVector with the Views within this View's hierarchy that
+ // match the specified group id.
+ void GetViewsWithGroup(int group, ViewVector* vec) const;
+
+ // TODO(beng): implementme
+ virtual View* GetSelectedViewForGroup(int group_id);
+
// Coordinate conversion -----------------------------------------------------
// Converts a point from the coordinate system of |source| to |target|.
@@ -148,22 +166,6 @@ class View {
// an indirect descendant. Will return true if child is also this View.
bool Contains(View* child);
- int id() const { return id_; }
- void set_id(int id) { id_ = id; }
- int group() const { return group_; }
- void set_group(int group) { group_ = group; }
-
- // Returns the View within this View's hierarchy whose id matches that
- // specified.
- View* GetViewById(int id) const;
-
- // Populates a ViewVector with the Views within this View's hierarchy that
- // match the specified group id.
- void GetViewsWithGroup(int group, ViewVector* vec) const;
-
- // TODO(beng): implementme
- virtual View* GetSelectedViewForGroup(int group_id);
-
// Painting ------------------------------------------------------------------
// Add all or part of a View's bounds to the enclosing Widget's invalid
@@ -224,20 +226,28 @@ class View {
virtual void OnViewAddedToWidget();
virtual void OnViewRemovedFromWidget();
- // Accelerators --------------------------------------------------------------
+ // Painting ------------------------------------------------------------------
- virtual bool OnAcceleratorPressed(const Accelerator& accelerator);
+ // Responsible for calling Paint() on child Views. Override to control the
+ // order child Views are painted.
+ virtual void PaintChildren(gfx::Canvas* canvas);
- // Focus ---------------------------------------------------------------------
- virtual bool SkipDefaultKeyEventProcessing(const KeyEvent& event) const;
- virtual bool IsGroupFocusTraversable() const;
- // TODO(beng): kill these, move to focus manager.
- virtual bool IsFocusableInRootView() const;
- virtual bool IsAccessibilityFocusableInRootView() const;
- virtual FocusTraversable* GetPaneFocusTraversable() const;
+ // Override to provide rendering in any part of the View's bounds. Typically
+ // this is the "contents" of the view. If you override this method you will
+ // have to call the subsequent OnPaint*() methods manually.
+ virtual void OnPaint(gfx::Canvas* canvas);
- virtual void OnFocus(/* const FocusEvent& event */);
- virtual void OnBlur();
+ // Override to paint a background before any content is drawn. Typically this
+ // is done if you are satisfied with a default OnPaint handler but wish to
+ // supply a different background.
+ virtual void OnPaintBackground(gfx::Canvas* canvas);
+
+ // Override to paint a border not specified by SetBorder().
+ virtual void OnPaintBorder(gfx::Canvas* canvas);
+
+ // Override to paint a focus border (usually a dotted rectangle) around
+ // relevant contents.
+ virtual void OnPaintFocusBorder(gfx::Canvas* canvas);
// Input ---------------------------------------------------------------------
@@ -264,28 +274,21 @@ class View {
virtual void OnMouseEntered(const MouseEvent& event);
virtual void OnMouseExited(const MouseEvent& event);
- // Painting ------------------------------------------------------------------
-
- // Responsible for calling Paint() on child Views. Override to control the
- // order child Views are painted.
- virtual void PaintChildren(gfx::Canvas* canvas);
+ // Accelerators --------------------------------------------------------------
- // Override to provide rendering in any part of the View's bounds. Typically
- // this is the "contents" of the view. If you override this method you will
- // have to call the subsequent OnPaint*() methods manually.
- virtual void OnPaint(gfx::Canvas* canvas);
+ virtual bool OnAcceleratorPressed(const Accelerator& accelerator);
- // Override to paint a background before any content is drawn. Typically this
- // is done if you are satisfied with a default OnPaint handler but wish to
- // supply a different background.
- virtual void OnPaintBackground(gfx::Canvas* canvas);
+ // Focus ---------------------------------------------------------------------
- // Override to paint a border not specified by SetBorder().
- virtual void OnPaintBorder(gfx::Canvas* canvas);
+ virtual bool SkipDefaultKeyEventProcessing(const KeyEvent& event) const;
+ virtual bool IsGroupFocusTraversable() const;
+ // TODO(beng): kill these, move to focus manager.
+ virtual bool IsFocusableInRootView() const;
+ virtual bool IsAccessibilityFocusableInRootView() const;
+ virtual FocusTraversable* GetPaneFocusTraversable() const;
- // Override to paint a focus border (usually a dotted rectangle) around
- // relevant contents.
- virtual void OnPaintFocusBorder(gfx::Canvas* canvas);
+ virtual void OnFocus(/* const FocusEvent& event */);
+ virtual void OnBlur();
private:
friend internal::RootView;
@@ -311,12 +314,16 @@ class View {
gfx::Point press_point;
};
- // Focus ---------------------------------------------------------------------
-
- // Called when |child| is inserted into this View's children_ at |index|.
- // Sets up next/previous focus views
- // TODO(beng): Move this to FocusManager.
- void InitFocusSiblings(View* child, size_t index);
+ // Tree operations -----------------------------------------------------------
+ void NotifyHierarchyChanged(View* parent, View* child, bool is_add);
+ void NotifyHierarchyChangedUp(View* parent, View* child, bool is_add);
+ void NotifyHierarchyChangedDown(View* parent, View* child, bool is_add,
+ bool has_widget);
+ void CallViewNotification(View* target,
+ View* parent,
+ View* child,
+ bool is_add,
+ bool has_widget);
// Painting ------------------------------------------------------------------
@@ -326,12 +333,7 @@ class View {
// the hierarchy beneath it.
void Paint(gfx::Canvas* canvas);
- // Drag & Drop ---------------------------------------------------------------
- int GetDragOperations(const gfx::Point& point);
- void WriteDragData(const gfx::Point& point, OSExchangeData* data);
- void StartShellDrag(const MouseEvent& event, const gfx::Point& press_point);
-
- // RootView API --------------------------------------------------------------
+ // Input --------------------------------------------------------------
// These methods are designed to be called by the RootView. The RootView
// should limit its interaction with the View to these methods and the public
// API.
@@ -339,30 +341,28 @@ class View {
bool MouseDragged(const MouseEvent& event, DragInfo* drag_info);
void MouseReleased(const MouseEvent& event);
- // Tree operations -----------------------------------------------------------
- void NotifyHierarchyChanged(View* parent, View* child, bool is_add);
- void NotifyHierarchyChangedUp(View* parent, View* child, bool is_add);
- void NotifyHierarchyChangedDown(View* parent, View* child, bool is_add,
- bool has_widget);
- void CallViewNotification(View* target,
- View* parent,
- View* child,
- bool is_add,
- bool has_widget);
+ // Focus ---------------------------------------------------------------------
- // TODO(beng): sort this section.
+ // Called when |child| is inserted into this View's children_ at |index|.
+ // Sets up next/previous focus views
+ // TODO(beng): Move this to FocusManager.
+ void InitFocusSiblings(View* child, size_t index);
- // The View's parent view. This is set and reset when the View is added and
- // removed from a hierarchy.
- View* parent_;
+ // Drag & Drop ---------------------------------------------------------------
+ int GetDragOperations(const gfx::Point& point);
+ void WriteDragData(const gfx::Point& point, OSExchangeData* data);
+ void StartShellDrag(const MouseEvent& event, const gfx::Point& press_point);
- // The View's children.
- ViewVector children_;
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Creation and lifetime -----------------------------------------------------
// True if the hierarchy (i.e. the parent View) is responsible for deleting
// this View. Default is true.
bool parent_owned_;
+ // Size and disposition ------------------------------------------------------
+
// The bounds of the View, in its parent's coordinates.
gfx::Rect bounds_;
@@ -376,12 +376,28 @@ class View {
// not propagate un-handled events beyond the View in the hierarchy.
bool enabled_;
+ // An optional helper that handles layout for child views.
+ scoped_ptr<LayoutManager> layout_manager_;
+
+ // Attributes ----------------------------------------------------------------
+
// An identifier for this View. Caller must guarantee uniqueness.
int id_;
// An identifier for a group of potentially related Views.
int group_;
+ // Tree operations -----------------------------------------------------------
+
+ // The View's parent view. This is set and reset when the View is added and
+ // removed from a hierarchy.
+ View* parent_;
+
+ // The View's children.
+ ViewVector children_;
+
+ // Focus ---------------------------------------------------------------------
+
// True if this View is focusable by the FocusManager.
bool focusable_;
@@ -389,12 +405,13 @@ class View {
View* next_focusable_view_;
View* prev_focusable_view_;
- // An optional helper that handles layout for child views.
- scoped_ptr<LayoutManager> layout_manager_;
+ // Context menus -------------------------------------------------------------
// Shows the context menu.
ContextMenuController* context_menu_controller_;
+ // Drag & drop ---------------------------------------------------------------
+
// Delegate for drag and drop related functionality.
DragController* drag_controller_;