| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "ui/views/view.h" | 
|  | 6 | 
|  | 7 #include <algorithm> | 
|  | 8 #include <functional> | 
|  | 9 | 
|  | 10 #include "gfx/canvas.h" | 
|  | 11 #include "gfx/point.h" | 
|  | 12 #include "gfx/size.h" | 
|  | 13 #include "ui/base/dragdrop/drag_drop_types.h" | 
|  | 14 #include "ui/views/events/context_menu_controller.h" | 
|  | 15 #include "ui/views/events/drag_controller.h" | 
|  | 16 #include "ui/views/layout/layout_manager.h" | 
|  | 17 #include "ui/views/rendering/border.h" | 
|  | 18 #include "ui/views/widget/widget.h" | 
|  | 19 | 
|  | 20 namespace ui { | 
|  | 21 | 
|  | 22 namespace { | 
|  | 23 | 
|  | 24 // Saves gfx::Canvas state upon construction and automatically restores it when | 
|  | 25 // it goes out of scope. | 
|  | 26 class ScopedCanvasState { | 
|  | 27  public: | 
|  | 28   explicit ScopedCanvasState(gfx::Canvas* canvas) : canvas_(canvas) { | 
|  | 29     canvas_->Save(); | 
|  | 30   } | 
|  | 31   ~ScopedCanvasState() { | 
|  | 32     canvas_->Restore(); | 
|  | 33   } | 
|  | 34 | 
|  | 35  private: | 
|  | 36   gfx::Canvas* canvas_; | 
|  | 37   DISALLOW_COPY_AND_ASSIGN(ScopedCanvasState); | 
|  | 38 }; | 
|  | 39 | 
|  | 40 bool ExceededDragThreshold(const gfx::Point& press_point, | 
|  | 41                            const gfx::Point& event_point) { | 
|  | 42   // TODO(beng): implement | 
|  | 43   return true; | 
|  | 44 } | 
|  | 45 | 
|  | 46 }  // namespace | 
|  | 47 | 
|  | 48 //////////////////////////////////////////////////////////////////////////////// | 
|  | 49 // View, public: | 
|  | 50 | 
|  | 51 View::View() | 
|  | 52     : parent_(NULL), | 
|  | 53       parent_owned_(true), | 
|  | 54       visible_(true), | 
|  | 55       enabled_(true), | 
|  | 56       id_(-1), | 
|  | 57       group_(-1), | 
|  | 58       focusable_(false), | 
|  | 59       context_menu_controller_(NULL), | 
|  | 60       drag_controller_(NULL) { | 
|  | 61 } | 
|  | 62 | 
|  | 63 View::~View() { | 
|  | 64   if (parent_) | 
|  | 65     parent_->RemoveChildView(this); | 
|  | 66 | 
|  | 67   ViewVector::const_iterator it = children_.begin(); | 
|  | 68   for (; it != children_.end(); ++it) { | 
|  | 69     (*it)->parent_ = NULL; | 
|  | 70     if ((*it)->parent_owned()) | 
|  | 71       delete *it; | 
|  | 72   } | 
|  | 73 } | 
|  | 74 | 
|  | 75 // Size and disposition -------------------------------------------------------- | 
|  | 76 | 
|  | 77 void View::SetBounds(int x, int y, int width, int height) { | 
|  | 78   SetBoundsRect(gfx::Rect(x, y, std::max(0, width), std::max(0, height))); | 
|  | 79 } | 
|  | 80 | 
|  | 81 void View::SetBoundsRect(const gfx::Rect& bounds) { | 
|  | 82   gfx::Rect old_bounds = bounds_; | 
|  | 83   bounds_ = bounds; | 
|  | 84   // TODO(beng): investigate usage of needs_layout_ in old View code. | 
|  | 85   if (old_bounds != bounds_) { | 
|  | 86     OnBoundsChanged(); | 
|  | 87     Layout(); | 
|  | 88   } | 
|  | 89 } | 
|  | 90 | 
|  | 91 gfx::Rect View::GetVisibleBounds() const { | 
|  | 92   // TODO(beng): | 
|  | 93   return bounds(); | 
|  | 94 } | 
|  | 95 | 
|  | 96 void View::SetSize(const gfx::Size& size) { | 
|  | 97   SetBounds(x(), y(), size.width(), size.height()); | 
|  | 98 } | 
|  | 99 | 
|  | 100 void View::SetPosition(const gfx::Point& position) { | 
|  | 101   SetBounds(position.x(), position.y(), width(), height()); | 
|  | 102 } | 
|  | 103 | 
|  | 104 void View::SetBorder(Border* border) { | 
|  | 105   border_.reset(border); | 
|  | 106 } | 
|  | 107 | 
|  | 108 gfx::Rect View::GetContentsBounds() const { | 
|  | 109   if (border_.get()) { | 
|  | 110     return gfx::Rect( | 
|  | 111         border_->insets().left(), border_->insets().top(), | 
|  | 112         width() - border_->insets().right() - border_->insets().left(), | 
|  | 113         height() - border_->insets().bottom() - border_->insets().top()); | 
|  | 114   } | 
|  | 115   return gfx::Rect(0, 0, width(), height()); | 
|  | 116 } | 
|  | 117 | 
|  | 118 void View::OnBoundsChanged() { | 
|  | 119 } | 
|  | 120 | 
|  | 121 gfx::Size View::GetPreferredSize() const { | 
|  | 122   return gfx::Size(); | 
|  | 123 } | 
|  | 124 | 
|  | 125 gfx::Size View::GetMinimumSize() const { | 
|  | 126   return GetPreferredSize(); | 
|  | 127 } | 
|  | 128 | 
|  | 129 void View::SetLayoutManager(LayoutManager* layout_manager) { | 
|  | 130   layout_manager_.reset(layout_manager); | 
|  | 131 } | 
|  | 132 | 
|  | 133 void View::Layout() { | 
|  | 134   if (layout_manager_.get()) { | 
|  | 135     // Layout Manager handles laying out children. | 
|  | 136     layout_manager_->Layout(this); | 
|  | 137   } else { | 
|  | 138     // We handle laying out our own children. | 
|  | 139     ViewVector::iterator it = children_.begin(); | 
|  | 140     for (; it != children_.end(); ++it) | 
|  | 141       (*it)->Layout(); | 
|  | 142   } | 
|  | 143   // TODO(beng): needs_layout_? SchedulePaint()? | 
|  | 144 } | 
|  | 145 | 
|  | 146 void View::SetVisible(bool visible) { | 
|  | 147   if (visible != visible_) { | 
|  | 148     visible_ = visible; | 
|  | 149 | 
|  | 150     // InvaldateRect() checks for view visibility before proceeding, so we need | 
|  | 151     // to ask the parent to invalidate our bounds. | 
|  | 152     if (parent_) | 
|  | 153       parent_->InvalidateRect(bounds_); | 
|  | 154   } | 
|  | 155 } | 
|  | 156 | 
|  | 157 void View::SetEnabled(bool enabled) { | 
|  | 158   if (enabled != enabled_) { | 
|  | 159     enabled_ = enabled; | 
|  | 160     Invalidate(); | 
|  | 161   } | 
|  | 162 } | 
|  | 163 | 
|  | 164 // Coordinate conversion ------------------------------------------------------- | 
|  | 165 | 
|  | 166 // static | 
|  | 167 void View::ConvertPointToView(View* source, View* target, gfx::Point* point) { | 
|  | 168   View* inner = NULL; | 
|  | 169   View* outer = NULL; | 
|  | 170   if (source->Contains(target)) { | 
|  | 171     inner = target; | 
|  | 172     outer = source; | 
|  | 173   } else if (target->Contains(source)) { | 
|  | 174     inner = source; | 
|  | 175     outer = target; | 
|  | 176   } // Note that we cannot do a plain "else" here since |source| and |target| | 
|  | 177     // may be in different hierarchies with no relation. | 
|  | 178 | 
|  | 179   if (inner && outer) { | 
|  | 180     gfx::Point offset; | 
|  | 181     View* temp = inner; | 
|  | 182     while (temp != outer) { | 
|  | 183       offset.Offset(temp->x(), temp->y()); | 
|  | 184       temp = temp->parent(); | 
|  | 185     } | 
|  | 186     // When target is contained by source, we need to subtract the offset. | 
|  | 187     // When source is contained by target, we need to add the fofset. | 
|  | 188     int multiplier = inner == target ? -1 : 1; | 
|  | 189     point->Offset(multiplier * offset.x(), multiplier * offset.y()); | 
|  | 190   } | 
|  | 191 } | 
|  | 192 | 
|  | 193 // static | 
|  | 194 void View::ConvertPointToScreen(View* source, gfx::Point* point) { | 
|  | 195   Widget* widget = source->GetWidget(); | 
|  | 196   if (widget) { | 
|  | 197     ConvertPointToWidget(source, point); | 
|  | 198     gfx::Rect r = widget->GetClientAreaScreenBounds(); | 
|  | 199     point->Offset(r.x(), r.y()); | 
|  | 200   } | 
|  | 201 } | 
|  | 202 | 
|  | 203 // static | 
|  | 204 void View::ConvertPointToWidget(View* source, gfx::Point* point) { | 
|  | 205   for (View* v = source; v; v = v->parent()) | 
|  | 206     point->Offset(v->x(), v->y()); | 
|  | 207 } | 
|  | 208 | 
|  | 209 // Tree operations ------------------------------------------------------------- | 
|  | 210 | 
|  | 211 Widget* View::GetWidget() const { | 
|  | 212   return parent_ ? parent_->GetWidget() : NULL; | 
|  | 213 } | 
|  | 214 | 
|  | 215 void View::AddChildView(View* view) { | 
|  | 216   AddChildViewAt(view, children_.size()); | 
|  | 217 } | 
|  | 218 | 
|  | 219 void View::AddChildViewAt(View* view, size_t index) { | 
|  | 220   CHECK(view != this) << "A view cannot be its own child."; | 
|  | 221 | 
|  | 222   // Remove the child from its current parent if any. | 
|  | 223   if (view->parent()) | 
|  | 224     view->parent()->RemoveChildView(view); | 
|  | 225 | 
|  | 226   children_.insert(children_.begin() + index, view); | 
|  | 227   view->parent_ = this; | 
|  | 228 | 
|  | 229   // Notify the hierarchy. | 
|  | 230   NotifyHierarchyChanged(this, view, true); | 
|  | 231 | 
|  | 232   // TODO(beng): Notify other objects like tooltip, layout manager, etc. | 
|  | 233   //             Figure out RegisterChildrenForVisibleBoundsNotification. | 
|  | 234 } | 
|  | 235 | 
|  | 236 View* View::RemoveChildView(View* view) { | 
|  | 237   ViewVector::iterator it = find(children_.begin(), children_.end(), view); | 
|  | 238   if (it != children_.end()) { | 
|  | 239     View* old_parent = view->parent_; | 
|  | 240     view->parent_ = NULL; | 
|  | 241     children_.erase(it); | 
|  | 242     NotifyHierarchyChanged(old_parent, view, false); | 
|  | 243   } | 
|  | 244 | 
|  | 245   // TODO(beng): Notify other objects like tooltip, layout manager, etc. | 
|  | 246   return view; | 
|  | 247 } | 
|  | 248 | 
|  | 249 void View::RemoveAllChildViews(bool delete_children) { | 
|  | 250   // TODO(beng): use for_each. | 
|  | 251   ViewVector::iterator it = children_.begin(); | 
|  | 252   while (it != children_.end()) { | 
|  | 253     View* v = RemoveChildView(*it); | 
|  | 254     if (delete_children) | 
|  | 255       delete v; | 
|  | 256     // TODO(beng): view deletion is actually more complicated in the old view.cc | 
|  | 257     //             figure out why. (it uses a ScopedVector to accumulate a list | 
|  | 258     //             of views to delete). | 
|  | 259   } | 
|  | 260 } | 
|  | 261 | 
|  | 262 View* View::GetChildViewAt(size_t index) { | 
|  | 263   CHECK(index < child_count()); | 
|  | 264   return children_[index]; | 
|  | 265 } | 
|  | 266 | 
|  | 267 bool View::Contains(View* child) { | 
|  | 268   while (child) { | 
|  | 269     if (child == this) | 
|  | 270       return true; | 
|  | 271     child = child->parent(); | 
|  | 272   } | 
|  | 273   return false; | 
|  | 274 } | 
|  | 275 | 
|  | 276 View* View::GetViewForPoint(const gfx::Point& point) const { | 
|  | 277   ViewVector::const_reverse_iterator it = children_.rbegin(); | 
|  | 278   for (; it != children_.rend(); ++it) { | 
|  | 279     View* child = *it; | 
|  | 280     if (!child->visible()) | 
|  | 281       continue; | 
|  | 282 | 
|  | 283     gfx::Point point_in_child_coords(point); | 
|  | 284     View::ConvertPointToView(const_cast<View*>(this), child, | 
|  | 285                              &point_in_child_coords); | 
|  | 286     if (child->HitTest(point_in_child_coords)) | 
|  | 287       return child->GetViewForPoint(point_in_child_coords); | 
|  | 288   } | 
|  | 289   return const_cast<View*>(this); | 
|  | 290 } | 
|  | 291 | 
|  | 292 bool View::HitTest(const gfx::Point& point) const { | 
|  | 293   // TODO(beng): Hit test mask support. | 
|  | 294   return gfx::Rect(0, 0, width(), height()).Contains(point); | 
|  | 295 } | 
|  | 296 | 
|  | 297 View* View::GetViewById(int id) const { | 
|  | 298   if (id_ == id) | 
|  | 299     return const_cast<View*>(this); | 
|  | 300   ViewVector::const_iterator it = children_.begin(); | 
|  | 301   for (; it != children_.end(); ++it) { | 
|  | 302     View* view = (*it)->GetViewById(id); | 
|  | 303     if (view) | 
|  | 304       return view; | 
|  | 305   } | 
|  | 306   return NULL; | 
|  | 307 } | 
|  | 308 | 
|  | 309 void View::GetViewsWithGroup(int group, ViewVector* vec) const { | 
|  | 310   if (group_ == group) | 
|  | 311     vec->push_back(const_cast<View*>(this)); | 
|  | 312   ViewVector::const_iterator it = children_.begin(); | 
|  | 313   for (; it != children_.end(); ++it) | 
|  | 314     (*it)->GetViewsWithGroup(group, vec); | 
|  | 315 } | 
|  | 316 | 
|  | 317 void View::OnViewAdded(View* parent, View* child) { | 
|  | 318 } | 
|  | 319 | 
|  | 320 void View::OnViewRemoved(View* parent, View* child) { | 
|  | 321 } | 
|  | 322 | 
|  | 323 void View::OnViewAddedToWidget() { | 
|  | 324 } | 
|  | 325 | 
|  | 326 void View::OnViewRemovedFromWidget() { | 
|  | 327 } | 
|  | 328 | 
|  | 329 // Accelerators ---------------------------------------------------------------- | 
|  | 330 | 
|  | 331 void View::AddAccelerator(const Accelerator& accelerator) { | 
|  | 332 } | 
|  | 333 | 
|  | 334 void View::RemoveAccelerator(const Accelerator& accelerator) { | 
|  | 335 } | 
|  | 336 | 
|  | 337 void View::RemoveAllAccelerators() { | 
|  | 338 } | 
|  | 339 | 
|  | 340 bool View::OnAcceleratorPressed(const Accelerator& accelerator) { | 
|  | 341   return false; | 
|  | 342 } | 
|  | 343 | 
|  | 344 // Focus ----------------------------------------------------------------------- | 
|  | 345 | 
|  | 346 FocusManager* View::GetFocusManager() const { | 
|  | 347   return NULL; | 
|  | 348 } | 
|  | 349 | 
|  | 350 FocusTraversable* View::GetFocusTraversable() const { | 
|  | 351   return NULL; | 
|  | 352 } | 
|  | 353 | 
|  | 354 View* View::GetNextFocusableView() const { | 
|  | 355   return NULL; | 
|  | 356 } | 
|  | 357 | 
|  | 358 View* View::GetPreviousFocusableView() const { | 
|  | 359   return NULL; | 
|  | 360 } | 
|  | 361 | 
|  | 362 bool View::SkipDefaultKeyEventProcessing(const KeyEvent& event) const { | 
|  | 363   return false; | 
|  | 364 } | 
|  | 365 | 
|  | 366 bool View::IsFocusable() const { | 
|  | 367   return false; | 
|  | 368 } | 
|  | 369 | 
|  | 370 bool View::HasFocus() const { | 
|  | 371   return false; | 
|  | 372 } | 
|  | 373 | 
|  | 374 void View::RequestFocus() { | 
|  | 375 } | 
|  | 376 | 
|  | 377 void View::OnFocus(/* const FocusEvent& event */) { | 
|  | 378 } | 
|  | 379 | 
|  | 380 void View::OnBlur() { | 
|  | 381 } | 
|  | 382 | 
|  | 383 // Input ----------------------------------------------------------------------- | 
|  | 384 | 
|  | 385 bool View::OnKeyPressed(const KeyEvent& event) { | 
|  | 386   return true; | 
|  | 387 } | 
|  | 388 | 
|  | 389 bool View::OnKeyReleased(const KeyEvent& event) { | 
|  | 390   return true; | 
|  | 391 } | 
|  | 392 | 
|  | 393 bool View::OnMouseWheel(const MouseWheelEvent& event) { | 
|  | 394   return true; | 
|  | 395 } | 
|  | 396 | 
|  | 397 bool View::OnMousePressed(const MouseEvent& event) { | 
|  | 398   return true; | 
|  | 399 } | 
|  | 400 | 
|  | 401 bool View::OnMouseDragged(const MouseEvent& event) { | 
|  | 402   return true; | 
|  | 403 } | 
|  | 404 | 
|  | 405 void View::OnMouseReleased(const MouseEvent& event) { | 
|  | 406 | 
|  | 407 } | 
|  | 408 | 
|  | 409 void View::OnMouseCaptureLost() { | 
|  | 410 | 
|  | 411 } | 
|  | 412 | 
|  | 413 void View::OnMouseMoved(const MouseEvent& event) { | 
|  | 414 | 
|  | 415 } | 
|  | 416 | 
|  | 417 void View::OnMouseEntered(const MouseEvent& event) { | 
|  | 418 | 
|  | 419 } | 
|  | 420 | 
|  | 421 void View::OnMouseExited(const MouseEvent& event) { | 
|  | 422 | 
|  | 423 } | 
|  | 424 | 
|  | 425 gfx::NativeCursor View::GetCursorForPoint(const gfx::Point& point) { | 
|  | 426   return NULL; | 
|  | 427 } | 
|  | 428 | 
|  | 429 // Painting -------------------------------------------------------------------- | 
|  | 430 | 
|  | 431 void View::Invalidate() { | 
|  | 432   InvalidateRect(gfx::Rect(0, 0, width(), height())); | 
|  | 433 } | 
|  | 434 | 
|  | 435 void View::InvalidateRect(const gfx::Rect& invalid_rect) { | 
|  | 436   if (!visible_) | 
|  | 437     return; | 
|  | 438 | 
|  | 439   if (parent_) { | 
|  | 440     gfx::Rect r = invalid_rect; | 
|  | 441     r.Offset(bounds_.origin()); | 
|  | 442     parent_->InvalidateRect(r); | 
|  | 443   } | 
|  | 444 } | 
|  | 445 | 
|  | 446 void View::Paint(gfx::Canvas* canvas) { | 
|  | 447   // Invisible views are not painted. | 
|  | 448   if (!visible_) | 
|  | 449     return; | 
|  | 450 | 
|  | 451   ScopedCanvasState canvas_state(canvas); | 
|  | 452   if (canvas->ClipRectInt(x(), y(), width(), height())) { | 
|  | 453     canvas->TranslateInt(x(), y()); | 
|  | 454     // TODO(beng): RTL | 
|  | 455     ScopedCanvasState canvas_state(canvas); | 
|  | 456     OnPaint(canvas); | 
|  | 457     PaintChildren(canvas); | 
|  | 458   } | 
|  | 459 } | 
|  | 460 | 
|  | 461 void View::PaintChildren(gfx::Canvas* canvas) { | 
|  | 462   // TODO(beng): use for_each. | 
|  | 463   // std::for_each(children_.begin(), children_.end(), | 
|  | 464   //              std::bind2nd(std::mem_fun_ref(&View::Paint), canvas)); | 
|  | 465   ViewVector::iterator it = children_.begin(); | 
|  | 466   for (; it != children_.end(); ++it) | 
|  | 467     (*it)->Paint(canvas); | 
|  | 468 } | 
|  | 469 | 
|  | 470 void View::OnPaint(gfx::Canvas* canvas) { | 
|  | 471   // TODO(beng): investigate moving these function calls to Paint(). | 
|  | 472   OnPaintBackground(canvas); | 
|  | 473   OnPaintFocusBorder(canvas); | 
|  | 474   OnPaintBorder(canvas); | 
|  | 475 } | 
|  | 476 | 
|  | 477 void View::OnPaintBackground(gfx::Canvas* canvas) { | 
|  | 478 } | 
|  | 479 | 
|  | 480 void View::OnPaintBorder(gfx::Canvas* canvas) { | 
|  | 481   if (border_.get()) | 
|  | 482     border_->Paint(const_cast<const View*>(this), canvas); | 
|  | 483 } | 
|  | 484 | 
|  | 485 void View::OnPaintFocusBorder(gfx::Canvas* canvas) { | 
|  | 486 } | 
|  | 487 | 
|  | 488 // Resources ------------------------------------------------------------------- | 
|  | 489 | 
|  | 490 ThemeProvider* View::GetThemeProvider() const { | 
|  | 491   Widget* widget = GetWidget(); | 
|  | 492   return widget ? widget->GetThemeProvider() : NULL; | 
|  | 493 } | 
|  | 494 | 
|  | 495 //////////////////////////////////////////////////////////////////////////////// | 
|  | 496 // View, private: | 
|  | 497 | 
|  | 498 void View::DragInfo::Reset() { | 
|  | 499   possible_drag = false; | 
|  | 500   press_point = gfx::Point(); | 
|  | 501 } | 
|  | 502 | 
|  | 503 void View::DragInfo::PossibleDrag(const gfx::Point& point) { | 
|  | 504   possible_drag = true; | 
|  | 505   press_point = point; | 
|  | 506 } | 
|  | 507 | 
|  | 508 // Drag & Drop ----------------------------------------------------------------- | 
|  | 509 | 
|  | 510 int View::GetDragOperations(const gfx::Point& point) { | 
|  | 511   return drag_controller_ ? | 
|  | 512       drag_controller_->GetDragOperations(const_cast<View*>(this), point) : | 
|  | 513       DragDropTypes::DRAG_NONE; | 
|  | 514 } | 
|  | 515 | 
|  | 516 void View::WriteDragData(const gfx::Point& point, OSExchangeData* data) { | 
|  | 517   drag_controller_->WriteDragData(this, point, data); | 
|  | 518 } | 
|  | 519 | 
|  | 520 void View::StartShellDrag(const MouseEvent& event, | 
|  | 521                           const gfx::Point& press_point) { | 
|  | 522   // TODO(beng): system stuff. | 
|  | 523 } | 
|  | 524 | 
|  | 525 // RootView API ---------------------------------------------------------------- | 
|  | 526 | 
|  | 527 bool View::MousePressed(const MouseEvent& event, DragInfo* drag_info) { | 
|  | 528   bool handled = OnMousePressed(event); | 
|  | 529   // TODO(beng): deal with view deletion, see ProcessMousePressed() in old code. | 
|  | 530   if (!enabled_) | 
|  | 531     return handled; | 
|  | 532 | 
|  | 533   int drag_operations = | 
|  | 534       enabled_ && event.IsOnlyLeftMouseButton() && HitTest(event.location()) ? | 
|  | 535       GetDragOperations(event.location()) : DragDropTypes::DRAG_NONE; | 
|  | 536   if (drag_operations != DragDropTypes::DRAG_NONE) { | 
|  | 537     drag_info->PossibleDrag(event.location()); | 
|  | 538     return true; | 
|  | 539   } | 
|  | 540   bool has_context_menu = event.IsRightMouseButton() ? | 
|  | 541       !!context_menu_controller_ : NULL; | 
|  | 542   return has_context_menu || handled; | 
|  | 543 } | 
|  | 544 | 
|  | 545 bool View::MouseDragged(const MouseEvent& event, DragInfo* drag_info) { | 
|  | 546   if (drag_info->possible_drag && | 
|  | 547       ExceededDragThreshold(drag_info->press_point, event.location())) { | 
|  | 548     if (!drag_controller_ || | 
|  | 549         drag_controller_->CanStartDrag(this, drag_info->press_point, | 
|  | 550                                        event.location())) { | 
|  | 551       StartShellDrag(event, drag_info->press_point); | 
|  | 552     } | 
|  | 553   } else { | 
|  | 554     if (OnMouseDragged(event)) | 
|  | 555       return true; | 
|  | 556   } | 
|  | 557   // TODO(beng): Handle view deletion from OnMouseDragged(). | 
|  | 558   return !!context_menu_controller_ || drag_info->possible_drag; | 
|  | 559 } | 
|  | 560 | 
|  | 561 void View::MouseReleased(const MouseEvent& event) { | 
|  | 562   OnMouseReleased(event); | 
|  | 563   // TODO(beng): Handle view deletion from OnMouseReleased(). | 
|  | 564   if (context_menu_controller_ && event.IsOnlyRightMouseButton()) { | 
|  | 565     gfx::Point location(event.location()); | 
|  | 566     if (HitTest(location)) { | 
|  | 567       ConvertPointToScreen(this, &location); | 
|  | 568       context_menu_controller_->ShowContextMenu(this, location, true); | 
|  | 569     } | 
|  | 570   } | 
|  | 571 } | 
|  | 572 | 
|  | 573 // Tree operations ------------------------------------------------------------- | 
|  | 574 | 
|  | 575 void View::NotifyHierarchyChanged(View* parent, View* child, bool is_add) { | 
|  | 576   // Notify the child. Note that we call GetWidget() on the parent, not the | 
|  | 577   // child, since this method is called after the child is already removed from | 
|  | 578   // the hierarchy when |is_add| is false and so child->GetWidget() will always | 
|  | 579   // return NULL. | 
|  | 580   bool has_widget = parent->GetWidget() != NULL; | 
|  | 581   CallViewNotification(child, parent, child, is_add, has_widget); | 
|  | 582 | 
|  | 583   // Notify the hierarchy up. | 
|  | 584   NotifyHierarchyChangedUp(parent, child, is_add); | 
|  | 585 | 
|  | 586   // Notify the hierarchy down. | 
|  | 587   if (!is_add) { | 
|  | 588     // Because |child| has already been removed from |parent|'s child list, we | 
|  | 589     // need to notify its hierarchy manually. | 
|  | 590     child->NotifyHierarchyChangedDown(parent, child, is_add, has_widget); | 
|  | 591   } | 
|  | 592   NotifyHierarchyChangedDown(parent, child, is_add, has_widget); | 
|  | 593 } | 
|  | 594 | 
|  | 595 void View::NotifyHierarchyChangedUp(View* parent, View* child, bool is_add) { | 
|  | 596   for (View* v = parent; v; v = v->parent()) { | 
|  | 597     if (is_add) | 
|  | 598       v->OnViewAdded(parent, child); | 
|  | 599     else | 
|  | 600       v->OnViewRemoved(parent, child); | 
|  | 601   } | 
|  | 602 } | 
|  | 603 | 
|  | 604 void View::NotifyHierarchyChangedDown(View* parent, View* child, bool is_add, | 
|  | 605                                        bool has_widget) { | 
|  | 606   ViewVector::iterator it = children_.begin(); | 
|  | 607   for (; it != children_.end(); ++it) { | 
|  | 608     CallViewNotification(*it, parent, child, is_add, has_widget); | 
|  | 609     (*it)->NotifyHierarchyChangedDown(parent, child, is_add, has_widget); | 
|  | 610   } | 
|  | 611 } | 
|  | 612 | 
|  | 613 void View::CallViewNotification(View* target, | 
|  | 614                                 View* parent, | 
|  | 615                                 View* child, | 
|  | 616                                 bool is_add, | 
|  | 617                                 bool has_widget) { | 
|  | 618   if (is_add) { | 
|  | 619     target->OnViewAdded(parent, child); | 
|  | 620     if (has_widget) | 
|  | 621       target->OnViewAddedToWidget(); | 
|  | 622   } else { | 
|  | 623     target->OnViewRemoved(parent, child); | 
|  | 624     if (has_widget) | 
|  | 625       target->OnViewRemovedFromWidget(); | 
|  | 626   } | 
|  | 627 } | 
|  | 628 | 
|  | 629 }  // namespace ui | 
| OLD | NEW | 
|---|