Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Unified Diff: ui/views/controls/tree/tree_view.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/controls/tree/tree_view.h ('k') | ui/views/controls/tree/tree_view_controller.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/tree/tree_view.cc
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
deleted file mode 100644
index 46506209f6e4dd99cedfcda5d2576013b96e1741..0000000000000000000000000000000000000000
--- a/ui/views/controls/tree/tree_view.cc
+++ /dev/null
@@ -1,1044 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/tree/tree_view.h"
-
-#include <algorithm>
-
-#include "base/i18n/rtl.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/accessibility/ax_view_state.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/skia_util.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/views/controls/prefix_selector.h"
-#include "ui/views/controls/scroll_view.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/controls/tree/tree_view_controller.h"
-#include "ui/views/ime/input_method.h"
-
-using ui::TreeModel;
-using ui::TreeModelNode;
-
-namespace views {
-
-// Insets around the view.
-static const int kHorizontalInset = 2;
-static const int kVerticalInset = 2;
-// Padding before/after the image.
-static const int kImagePadding = 4;
-// Size of the arrow region.
-static const int kArrowRegionSize = 12;
-// Padding around the text (on each side).
-static const int kTextVerticalPadding = 3;
-static const int kTextHorizontalPadding = 2;
-// How much children are indented from their parent.
-static const int kIndent = 20;
-
-// static
-const char TreeView::kViewClassName[] = "TreeView";
-
-namespace {
-
-// Returns the color id for the background of selected text. |has_focus|
-// indicates if the tree has focus.
-ui::NativeTheme::ColorId text_background_color_id(bool has_focus) {
- return has_focus ?
- ui::NativeTheme::kColorId_TreeSelectionBackgroundFocused :
- ui::NativeTheme::kColorId_TreeSelectionBackgroundUnfocused;
-}
-
-// Returns the color id for text. |has_focus| indicates if the tree has focus
-// and |is_selected| is true if the item is selected.
-ui::NativeTheme::ColorId text_color_id(bool has_focus, bool is_selected) {
- if (is_selected) {
- if (has_focus)
- return ui::NativeTheme::kColorId_TreeSelectedText;
- return ui::NativeTheme::kColorId_TreeSelectedTextUnfocused;
- }
- return ui::NativeTheme::kColorId_TreeText;
-}
-
-} // namespace
-
-TreeView::TreeView()
- : model_(NULL),
- selected_node_(NULL),
- editing_(false),
- editor_(NULL),
- focus_manager_(NULL),
- auto_expand_children_(false),
- editable_(true),
- controller_(NULL),
- root_shown_(true),
- row_height_(font_list_.GetHeight() + kTextVerticalPadding * 2) {
- SetFocusable(true);
- closed_icon_ = *ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- (base::i18n::IsRTL() ? IDR_FOLDER_CLOSED_RTL
- : IDR_FOLDER_CLOSED)).ToImageSkia();
- open_icon_ = *ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- (base::i18n::IsRTL() ? IDR_FOLDER_OPEN_RTL
- : IDR_FOLDER_OPEN)).ToImageSkia();
- text_offset_ = closed_icon_.width() + kImagePadding + kImagePadding +
- kArrowRegionSize;
-}
-
-TreeView::~TreeView() {
- if (model_)
- model_->RemoveObserver(this);
- if (focus_manager_) {
- focus_manager_->RemoveFocusChangeListener(this);
- focus_manager_ = NULL;
- }
-}
-
-View* TreeView::CreateParentIfNecessary() {
- ScrollView* scroll_view = ScrollView::CreateScrollViewWithBorder();
- scroll_view->SetContents(this);
- return scroll_view;
-}
-
-void TreeView::SetModel(TreeModel* model) {
- if (model == model_)
- return;
- if (model_)
- model_->RemoveObserver(this);
-
- CancelEdit();
-
- model_ = model;
- selected_node_ = NULL;
- icons_.clear();
- if (model_) {
- model_->AddObserver(this);
- model_->GetIcons(&icons_);
-
- root_.RemoveAll();
- ConfigureInternalNode(model_->GetRoot(), &root_);
- LoadChildren(&root_);
- root_.set_is_expanded(true);
- if (root_shown_)
- selected_node_ = &root_;
- else if (root_.child_count())
- selected_node_ = root_.GetChild(0);
- }
- DrawnNodesChanged();
-}
-
-void TreeView::SetEditable(bool editable) {
- if (editable == editable_)
- return;
- editable_ = editable;
- CancelEdit();
-}
-
-void TreeView::StartEditing(TreeModelNode* node) {
- DCHECK(node);
- // Cancel the current edit.
- CancelEdit();
- // Make sure all ancestors are expanded.
- if (model_->GetParent(node))
- Expand(model_->GetParent(node));
- // Select the node, else if the user commits the edit the selection reverts.
- SetSelectedNode(node);
- if (GetSelectedNode() != node)
- return; // Selection failed for some reason, don't start editing.
- DCHECK(!editing_);
- editing_ = true;
- if (!editor_) {
- editor_ = new Textfield;
- // Add the editor immediately as GetPreferredSize returns the wrong thing if
- // not parented.
- AddChildView(editor_);
- editor_->SetFontList(font_list_);
- empty_editor_size_ = editor_->GetPreferredSize();
- editor_->set_controller(this);
- }
- editor_->SetText(selected_node_->model_node()->GetTitle());
- LayoutEditor();
- editor_->SetVisible(true);
- SchedulePaintForNode(selected_node_);
- editor_->RequestFocus();
- editor_->SelectAll(false);
-
- // Listen for focus changes so that we can cancel editing.
- focus_manager_ = GetFocusManager();
- if (focus_manager_)
- focus_manager_->AddFocusChangeListener(this);
-
- // Accelerators to commit/cancel edit.
- AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
- AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
-}
-
-void TreeView::CancelEdit() {
- if (!editing_)
- return;
-
- // WARNING: don't touch |selected_node_|, it may be bogus.
-
- editing_ = false;
- if (focus_manager_) {
- focus_manager_->RemoveFocusChangeListener(this);
- focus_manager_ = NULL;
- }
- editor_->SetVisible(false);
- SchedulePaint();
-
- RemoveAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
- RemoveAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
-}
-
-void TreeView::CommitEdit() {
- if (!editing_)
- return;
-
- DCHECK(selected_node_);
- const bool editor_has_focus = editor_->HasFocus();
- model_->SetTitle(GetSelectedNode(), editor_->text());
- CancelEdit();
- if (editor_has_focus)
- RequestFocus();
-}
-
-TreeModelNode* TreeView::GetEditingNode() {
- return editing_ ? selected_node_->model_node() : NULL;
-}
-
-void TreeView::SetSelectedNode(TreeModelNode* model_node) {
- if (editing_ || model_node != selected_node_)
- CancelEdit();
- if (model_node && model_->GetParent(model_node))
- Expand(model_->GetParent(model_node));
- if (model_node && model_node == root_.model_node() && !root_shown_)
- return; // Ignore requests to select the root when not shown.
- InternalNode* node = model_node ? GetInternalNodeForModelNode(
- model_node, CREATE_IF_NOT_LOADED) : NULL;
- bool was_empty_selection = (selected_node_ == NULL);
- bool changed = (selected_node_ != node);
- if (changed) {
- SchedulePaintForNode(selected_node_);
- selected_node_ = node;
- if (selected_node_ == &root_ && !root_shown_)
- selected_node_ = NULL;
- if (selected_node_ && selected_node_ != &root_)
- Expand(model_->GetParent(selected_node_->model_node()));
- SchedulePaintForNode(selected_node_);
- }
-
- if (selected_node_)
- ScrollRectToVisible(GetBoundsForNode(selected_node_));
-
- // Notify controller if the old selection was empty to handle the case of
- // remove explicitly resetting selected_node_ before invoking this.
- if (controller_ && (changed || was_empty_selection))
- controller_->OnTreeViewSelectionChanged(this);
-
- if (changed) {
- // TODO(dmazzoni): Decide if EVENT_SELECTION_CHANGED is a better choice for
- // sub-item selection event.
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
- }
-}
-
-TreeModelNode* TreeView::GetSelectedNode() {
- return selected_node_ ? selected_node_->model_node() : NULL;
-}
-
-void TreeView::Collapse(ui::TreeModelNode* model_node) {
- // Don't collapse the root if the root isn't shown, otherwise nothing is
- // displayed.
- if (model_node == root_.model_node() && !root_shown_)
- return;
- InternalNode* node =
- GetInternalNodeForModelNode(model_node, DONT_CREATE_IF_NOT_LOADED);
- if (!node)
- return;
- bool was_expanded = IsExpanded(model_node);
- if (node->is_expanded()) {
- if (selected_node_ && selected_node_->HasAncestor(node))
- SetSelectedNode(model_node);
- node->set_is_expanded(false);
- }
- if (was_expanded)
- DrawnNodesChanged();
-}
-
-void TreeView::Expand(TreeModelNode* node) {
- if (ExpandImpl(node))
- DrawnNodesChanged();
- // TODO: need to support auto_expand_children_.
-}
-
-void TreeView::ExpandAll(TreeModelNode* node) {
- DCHECK(node);
- // Expand the node.
- bool expanded_at_least_one = ExpandImpl(node);
- // And recursively expand all the children.
- for (int i = model_->GetChildCount(node) - 1; i >= 0; --i) {
- TreeModelNode* child = model_->GetChild(node, i);
- if (ExpandImpl(child))
- expanded_at_least_one = true;
- }
- if (expanded_at_least_one)
- DrawnNodesChanged();
-}
-
-bool TreeView::IsExpanded(TreeModelNode* model_node) {
- if (!model_node) {
- // NULL check primarily for convenience for uses in this class so don't have
- // to add NULL checks every where we look up the parent.
- return true;
- }
- InternalNode* node = GetInternalNodeForModelNode(
- model_node, DONT_CREATE_IF_NOT_LOADED);
- if (!node)
- return false;
-
- while (node) {
- if (!node->is_expanded())
- return false;
- node = node->parent();
- }
- return true;
-}
-
-void TreeView::SetRootShown(bool root_shown) {
- if (root_shown_ == root_shown)
- return;
- root_shown_ = root_shown;
- if (!root_shown_ && selected_node_ == &root_) {
- if (model_->GetChildCount(root_.model_node()))
- SetSelectedNode(model_->GetChild(root_.model_node(), 0));
- else
- SetSelectedNode(NULL);
- }
- DrawnNodesChanged();
-}
-
-ui::TreeModelNode* TreeView::GetNodeForRow(int row) {
- int depth = 0;
- InternalNode* node = GetNodeByRow(row, &depth);
- return node ? node->model_node() : NULL;
-}
-
-int TreeView::GetRowForNode(ui::TreeModelNode* node) {
- InternalNode* internal_node =
- GetInternalNodeForModelNode(node, DONT_CREATE_IF_NOT_LOADED);
- if (!internal_node)
- return -1;
- int depth = 0;
- return GetRowForInternalNode(internal_node, &depth);
-}
-
-void TreeView::Layout() {
- int width = preferred_size_.width();
- int height = preferred_size_.height();
- if (parent()) {
- width = std::max(parent()->width(), width);
- height = std::max(parent()->height(), height);
- }
- SetBounds(x(), y(), width, height);
- LayoutEditor();
-}
-
-gfx::Size TreeView::GetPreferredSize() const {
- return preferred_size_;
-}
-
-bool TreeView::AcceleratorPressed(const ui::Accelerator& accelerator) {
- if (accelerator.key_code() == ui::VKEY_RETURN) {
- CommitEdit();
- } else {
- DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code());
- CancelEdit();
- RequestFocus();
- }
- return true;
-}
-
-bool TreeView::OnMousePressed(const ui::MouseEvent& event) {
- return OnClickOrTap(event);
-}
-
-ui::TextInputClient* TreeView::GetTextInputClient() {
- if (!selector_)
- selector_.reset(new PrefixSelector(this));
- return selector_.get();
-}
-
-void TreeView::OnGestureEvent(ui::GestureEvent* event) {
- if (event->type() == ui::ET_GESTURE_TAP) {
- if (OnClickOrTap(*event))
- event->SetHandled();
- }
-}
-
-void TreeView::ShowContextMenu(const gfx::Point& p,
- ui::MenuSourceType source_type) {
- if (!model_)
- return;
- if (source_type == ui::MENU_SOURCE_MOUSE) {
- // Only invoke View's implementation (which notifies the
- // ContextMenuController) if over a node.
- gfx::Point local_point(p);
- ConvertPointFromScreen(this, &local_point);
- int row = (local_point.y() - kVerticalInset) / row_height_;
- int depth = 0;
- InternalNode* node = GetNodeByRow(row, &depth);
- if (!node)
- return;
- gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth));
- if (!bounds.Contains(local_point))
- return;
- }
- View::ShowContextMenu(p, source_type);
-}
-
-void TreeView::GetAccessibleState(ui::AXViewState* state) {
- state->role = ui::AX_ROLE_TREE;
- state->AddStateFlag(ui::AX_STATE_READ_ONLY);
- if (!selected_node_)
- return;
-
- // Get selected item info.
- state->role = ui::AX_ROLE_TREE_ITEM;
- state->name = selected_node_->model_node()->GetTitle();
-}
-
-const char* TreeView::GetClassName() const {
- return kViewClassName;
-}
-
-void TreeView::TreeNodesAdded(TreeModel* model,
- TreeModelNode* parent,
- int start,
- int count) {
- InternalNode* parent_node =
- GetInternalNodeForModelNode(parent, DONT_CREATE_IF_NOT_LOADED);
- if (!parent_node || !parent_node->loaded_children())
- return;
- for (int i = 0; i < count; ++i) {
- InternalNode* child = new InternalNode;
- ConfigureInternalNode(model_->GetChild(parent, start + i), child);
- parent_node->Add(child, start + i);
- }
- if (IsExpanded(parent))
- DrawnNodesChanged();
-}
-
-void TreeView::TreeNodesRemoved(TreeModel* model,
- TreeModelNode* parent,
- int start,
- int count) {
- InternalNode* parent_node =
- GetInternalNodeForModelNode(parent, DONT_CREATE_IF_NOT_LOADED);
- if (!parent_node || !parent_node->loaded_children())
- return;
- bool reset_selection = false;
- for (int i = 0; i < count; ++i) {
- InternalNode* child_removing = parent_node->GetChild(start);
- if (selected_node_ && selected_node_->HasAncestor(child_removing))
- reset_selection = true;
- delete parent_node->Remove(child_removing);
- }
- if (reset_selection) {
- // selected_node_ is no longer valid (at the time we enter this function
- // its model_node() is likely deleted). Explicitly NULL out the field
- // rather than invoking SetSelectedNode() otherwise, we'll try and use a
- // deleted value.
- selected_node_ = NULL;
- TreeModelNode* to_select = parent;
- if (parent == root_.model_node() && !root_shown_) {
- to_select = model_->GetChildCount(parent) > 0 ?
- model_->GetChild(parent, 0) : NULL;
- }
- SetSelectedNode(to_select);
- }
- if (IsExpanded(parent))
- DrawnNodesChanged();
-}
-
-void TreeView::TreeNodeChanged(TreeModel* model, TreeModelNode* model_node) {
- InternalNode* node =
- GetInternalNodeForModelNode(model_node, DONT_CREATE_IF_NOT_LOADED);
- if (!node)
- return;
- int old_width = node->text_width();
- UpdateNodeTextWidth(node);
- if (old_width != node->text_width() &&
- ((node == &root_ && root_shown_) ||
- (node != &root_ && IsExpanded(node->parent()->model_node())))) {
- DrawnNodesChanged();
- }
-}
-
-void TreeView::ContentsChanged(Textfield* sender,
- const base::string16& new_contents) {
-}
-
-bool TreeView::HandleKeyEvent(Textfield* sender,
- const ui::KeyEvent& key_event) {
- switch (key_event.key_code()) {
- case ui::VKEY_RETURN:
- CommitEdit();
- return true;
-
- case ui::VKEY_ESCAPE:
- CancelEdit();
- RequestFocus();
- return true;
-
- default:
- return false;
- }
-}
-
-void TreeView::OnWillChangeFocus(View* focused_before, View* focused_now) {
-}
-
-void TreeView::OnDidChangeFocus(View* focused_before, View* focused_now) {
- CommitEdit();
-}
-
-int TreeView::GetRowCount() {
- int row_count = root_.NumExpandedNodes();
- if (!root_shown_)
- row_count--;
- return row_count;
-}
-
-int TreeView::GetSelectedRow() {
- ui::TreeModelNode* model_node = GetSelectedNode();
- return model_node ? GetRowForNode(model_node) : -1;
-}
-
-void TreeView::SetSelectedRow(int row) {
- SetSelectedNode(GetNodeForRow(row));
-}
-
-base::string16 TreeView::GetTextForRow(int row) {
- return GetNodeForRow(row)->GetTitle();
-}
-
-gfx::Point TreeView::GetKeyboardContextMenuLocation() {
- int y = height() / 2;
- if (selected_node_) {
- gfx::Rect node_bounds(GetBoundsForNode(selected_node_));
- gfx::Rect vis_bounds(GetVisibleBounds());
- if (node_bounds.y() >= vis_bounds.y() &&
- node_bounds.y() < vis_bounds.bottom()) {
- y = node_bounds.y();
- }
- }
- gfx::Point screen_loc(0, y);
- if (base::i18n::IsRTL())
- screen_loc.set_x(width());
- ConvertPointToScreen(this, &screen_loc);
- return screen_loc;
-}
-
-bool TreeView::OnKeyPressed(const ui::KeyEvent& event) {
- if (!HasFocus())
- return false;
-
- switch (event.key_code()) {
- case ui::VKEY_F2:
- if (!editing_) {
- TreeModelNode* selected_node = GetSelectedNode();
- if (selected_node && (!controller_ ||
- controller_->CanEdit(this, selected_node))) {
- StartEditing(selected_node);
- }
- }
- return true;
-
- case ui::VKEY_UP:
- case ui::VKEY_DOWN:
- IncrementSelection(event.key_code() == ui::VKEY_UP ?
- INCREMENT_PREVIOUS : INCREMENT_NEXT);
- return true;
-
- case ui::VKEY_LEFT:
- if (base::i18n::IsRTL())
- ExpandOrSelectChild();
- else
- CollapseOrSelectParent();
- return true;
-
- case ui::VKEY_RIGHT:
- if (base::i18n::IsRTL())
- CollapseOrSelectParent();
- else
- ExpandOrSelectChild();
- return true;
-
- default:
- break;
- }
- return false;
-}
-
-void TreeView::OnPaint(gfx::Canvas* canvas) {
- // Don't invoke View::OnPaint so that we can render our own focus border.
- canvas->DrawColor(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_TreeBackground));
-
- int min_y, max_y;
- {
- SkRect sk_clip_rect;
- if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect)) {
- // Pixels partially inside the clip rect should be included.
- gfx::Rect clip_rect = gfx::ToEnclosingRect(
- gfx::SkRectToRectF(sk_clip_rect));
- min_y = clip_rect.y();
- max_y = clip_rect.bottom();
- } else {
- gfx::Rect vis_bounds = GetVisibleBounds();
- min_y = vis_bounds.y();
- max_y = vis_bounds.bottom();
- }
- }
-
- int min_row = std::max(0, (min_y - kVerticalInset) / row_height_);
- int max_row = (max_y - kVerticalInset) / row_height_;
- if ((max_y - kVerticalInset) % row_height_ != 0)
- max_row++;
- int current_row = root_row();
- PaintRows(canvas, min_row, max_row, &root_, root_depth(), &current_row);
-}
-
-void TreeView::OnFocus() {
- GetInputMethod()->OnFocus();
- View::OnFocus();
- SchedulePaintForNode(selected_node_);
-
- // Notify the InputMethod so that it knows to query the TextInputClient.
- if (GetInputMethod())
- GetInputMethod()->OnCaretBoundsChanged(this);
-}
-
-void TreeView::OnBlur() {
- GetInputMethod()->OnBlur();
- SchedulePaintForNode(selected_node_);
- if (selector_)
- selector_->OnViewBlur();
-}
-
-bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) {
- CommitEdit();
- RequestFocus();
-
- int row = (event.y() - kVerticalInset) / row_height_;
- int depth = 0;
- InternalNode* node = GetNodeByRow(row, &depth);
- if (node) {
- gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth));
- if (bounds.Contains(event.location())) {
- int relative_x = event.x() - bounds.x();
- if (base::i18n::IsRTL())
- relative_x = bounds.width() - relative_x;
- if (relative_x < kArrowRegionSize &&
- model_->GetChildCount(node->model_node())) {
- if (node->is_expanded())
- Collapse(node->model_node());
- else
- Expand(node->model_node());
- } else if (relative_x > kArrowRegionSize) {
- SetSelectedNode(node->model_node());
- bool should_toggle = false;
- if (event.type() == ui::ET_GESTURE_TAP) {
- const ui::GestureEvent& gesture =
- static_cast<const ui::GestureEvent&>(event);
- should_toggle = gesture.details().tap_count() == 2;
- } else {
- should_toggle = (event.flags() & ui::EF_IS_DOUBLE_CLICK) != 0;
- }
- if (should_toggle) {
- if (node->is_expanded())
- Collapse(node->model_node());
- else
- Expand(node->model_node());
- }
- }
- }
- }
- return true;
-}
-
-void TreeView::LoadChildren(InternalNode* node) {
- DCHECK_EQ(0, node->child_count());
- DCHECK(!node->loaded_children());
- node->set_loaded_children(true);
- for (int i = 0, child_count = model_->GetChildCount(node->model_node());
- i < child_count; ++i) {
- InternalNode* child = new InternalNode;
- ConfigureInternalNode(model_->GetChild(node->model_node(), i), child);
- node->Add(child, node->child_count());
- }
-}
-
-void TreeView::ConfigureInternalNode(TreeModelNode* model_node,
- InternalNode* node) {
- node->Reset(model_node);
- UpdateNodeTextWidth(node);
-}
-
-void TreeView::UpdateNodeTextWidth(InternalNode* node) {
- int width = 0, height = 0;
- gfx::Canvas::SizeStringInt(node->model_node()->GetTitle(), font_list_,
- &width, &height, 0, gfx::Canvas::NO_ELLIPSIS);
- node->set_text_width(width);
-}
-
-void TreeView::DrawnNodesChanged() {
- UpdatePreferredSize();
- PreferredSizeChanged();
- SchedulePaint();
-}
-
-void TreeView::UpdatePreferredSize() {
- preferred_size_ = gfx::Size();
- if (!model_)
- return;
-
- preferred_size_.SetSize(
- root_.GetMaxWidth(text_offset_, root_shown_ ? 1 : 0) +
- kTextHorizontalPadding * 2,
- row_height_ * GetRowCount() + kVerticalInset * 2);
-}
-
-void TreeView::LayoutEditor() {
- if (!editing_)
- return;
-
- DCHECK(selected_node_);
- // Position the editor so that its text aligns with the text we drew.
- gfx::Rect row_bounds = GetBoundsForNode(selected_node_);
- row_bounds.set_x(
- GetMirroredXWithWidthInView(row_bounds.x(), row_bounds.width()));
- row_bounds.set_x(row_bounds.x() + text_offset_);
- row_bounds.set_width(row_bounds.width() - text_offset_);
- row_bounds.Inset(kTextHorizontalPadding, kTextVerticalPadding);
- row_bounds.Inset(-empty_editor_size_.width() / 2,
- -(empty_editor_size_.height() - font_list_.GetHeight()) / 2);
- // Give a little extra space for editing.
- row_bounds.set_width(row_bounds.width() + 50);
- editor_->SetBoundsRect(row_bounds);
- editor_->Layout();
-}
-
-void TreeView::SchedulePaintForNode(InternalNode* node) {
- if (!node)
- return; // Explicitly allow NULL to be passed in.
- SchedulePaintInRect(GetBoundsForNode(node));
-}
-
-void TreeView::PaintRows(gfx::Canvas* canvas,
- int min_row,
- int max_row,
- InternalNode* node,
- int depth,
- int* row) {
- if (*row >= max_row)
- return;
-
- if (*row >= min_row && *row < max_row)
- PaintRow(canvas, node, *row, depth);
- (*row)++;
- if (!node->is_expanded())
- return;
- depth++;
- for (int i = 0; i < node->child_count() && *row < max_row; ++i)
- PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row);
-}
-
-void TreeView::PaintRow(gfx::Canvas* canvas,
- InternalNode* node,
- int row,
- int depth) {
- gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth));
-
- if (model_->GetChildCount(node->model_node()))
- PaintExpandControl(canvas, bounds, node->is_expanded());
-
- // Paint the icon.
- gfx::ImageSkia icon;
- int icon_index = model_->GetIconIndex(node->model_node());
- if (icon_index != -1)
- icon = icons_[icon_index];
- else if (node == selected_node_)
- icon = open_icon_;
- else
- icon = closed_icon_;
- int icon_x = kArrowRegionSize + kImagePadding +
- (open_icon_.width() - icon.width()) / 2;
- if (base::i18n::IsRTL())
- icon_x = bounds.right() - icon_x - open_icon_.width();
- else
- icon_x += bounds.x();
- canvas->DrawImageInt(
- icon, icon_x,
- bounds.y() + (bounds.height() - icon.height()) / 2);
-
- if (!editing_ || node != selected_node_) {
- gfx::Rect text_bounds(bounds.x() + text_offset_, bounds.y(),
- bounds.width() - text_offset_, bounds.height());
- if (base::i18n::IsRTL())
- text_bounds.set_x(bounds.x());
- if (node == selected_node_) {
- const SkColor bg_color = GetNativeTheme()->GetSystemColor(
- text_background_color_id(HasFocus()));
- canvas->FillRect(text_bounds, bg_color);
- if (HasFocus())
- canvas->DrawFocusRect(text_bounds);
- }
- const ui::NativeTheme::ColorId color_id =
- text_color_id(HasFocus(), node == selected_node_);
- const gfx::Rect internal_bounds(
- text_bounds.x() + kTextHorizontalPadding,
- text_bounds.y() + kTextVerticalPadding,
- text_bounds.width() - kTextHorizontalPadding * 2,
- text_bounds.height() - kTextVerticalPadding * 2);
- canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_,
- GetNativeTheme()->GetSystemColor(color_id),
- internal_bounds);
- }
-}
-
-void TreeView::PaintExpandControl(gfx::Canvas* canvas,
- const gfx::Rect& node_bounds,
- bool expanded) {
- int center_x;
- if (base::i18n::IsRTL()) {
- center_x = node_bounds.right() - kArrowRegionSize +
- (kArrowRegionSize - 4) / 2;
- } else {
- center_x = node_bounds.x() + (kArrowRegionSize - 4) / 2;
- }
- int center_y = node_bounds.y() + node_bounds.height() / 2;
- const SkColor arrow_color = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_TreeArrow);
- // TODO: this should come from an image.
- if (!expanded) {
- int delta = base::i18n::IsRTL() ? 1 : -1;
- for (int i = 0; i < 4; ++i) {
- canvas->FillRect(gfx::Rect(center_x + delta * (2 - i),
- center_y - (3 - i), 1, (3 - i) * 2 + 1),
- arrow_color);
- }
- } else {
- center_y -= 2;
- for (int i = 0; i < 4; ++i) {
- canvas->FillRect(gfx::Rect(center_x - (3 - i), center_y + i,
- (3 - i) * 2 + 1, 1), arrow_color);
- }
- }
-}
-
-TreeView::InternalNode* TreeView::GetInternalNodeForModelNode(
- ui::TreeModelNode* model_node,
- GetInternalNodeCreateType create_type) {
- if (model_node == root_.model_node())
- return &root_;
- InternalNode* parent_internal_node =
- GetInternalNodeForModelNode(model_->GetParent(model_node), create_type);
- if (!parent_internal_node)
- return NULL;
- if (!parent_internal_node->loaded_children()) {
- if (create_type == DONT_CREATE_IF_NOT_LOADED)
- return NULL;
- LoadChildren(parent_internal_node);
- }
- return parent_internal_node->GetChild(
- model_->GetIndexOf(parent_internal_node->model_node(), model_node));
-}
-
-gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) {
- int row, depth;
- row = GetRowForInternalNode(node, &depth);
- return GetBoundsForNodeImpl(node, row, depth);
-}
-
-gfx::Rect TreeView::GetBoundsForNodeImpl(InternalNode* node,
- int row,
- int depth) {
- gfx::Rect rect(depth * kIndent + kHorizontalInset,
- row * row_height_ + kVerticalInset,
- text_offset_ + node->text_width() +
- kTextHorizontalPadding * 2,
- row_height_);
- rect.set_x(GetMirroredXWithWidthInView(rect.x(), rect.width()));
- return rect;
-}
-
-int TreeView::GetRowForInternalNode(InternalNode* node, int* depth) {
- DCHECK(!node->parent() || IsExpanded(node->parent()->model_node()));
- *depth = -1;
- int row = -1;
- InternalNode* tmp_node = node;
- while (tmp_node->parent()) {
- int index_in_parent = tmp_node->parent()->GetIndexOf(tmp_node);
- (*depth)++;
- row++; // For node.
- for (int i = 0; i < index_in_parent; ++i)
- row += tmp_node->parent()->GetChild(i)->NumExpandedNodes();
- tmp_node = tmp_node->parent();
- }
- if (root_shown_) {
- (*depth)++;
- row++;
- }
- return row;
-}
-
-TreeView::InternalNode* TreeView::GetNodeByRow(int row, int* depth) {
- int current_row = root_row();
- *depth = 0;
- return GetNodeByRowImpl(&root_, row, root_depth(), &current_row, depth);
-}
-
-TreeView::InternalNode* TreeView::GetNodeByRowImpl(InternalNode* node,
- int target_row,
- int current_depth,
- int* current_row,
- int* node_depth) {
- if (*current_row == target_row) {
- *node_depth = current_depth;
- return node;
- }
- (*current_row)++;
- if (node->is_expanded()) {
- current_depth++;
- for (int i = 0; i < node->child_count(); ++i) {
- InternalNode* result = GetNodeByRowImpl(
- node->GetChild(i), target_row, current_depth, current_row,
- node_depth);
- if (result)
- return result;
- }
- }
- return NULL;
-}
-
-void TreeView::IncrementSelection(IncrementType type) {
- if (!model_)
- return;
-
- if (!GetSelectedNode()) {
- // If nothing is selected select the first or last node.
- if (!root_.child_count())
- return;
- if (type == INCREMENT_PREVIOUS) {
- int row_count = GetRowCount();
- int depth = 0;
- DCHECK(row_count);
- InternalNode* node = GetNodeByRow(row_count - 1, &depth);
- SetSelectedNode(node->model_node());
- } else if (root_shown_) {
- SetSelectedNode(root_.model_node());
- } else {
- SetSelectedNode(root_.GetChild(0)->model_node());
- }
- return;
- }
-
- int depth = 0;
- int delta = type == INCREMENT_PREVIOUS ? -1 : 1;
- int row = GetRowForInternalNode(selected_node_, &depth);
- int new_row = std::min(GetRowCount() - 1, std::max(0, row + delta));
- if (new_row == row)
- return; // At the end/beginning.
- SetSelectedNode(GetNodeByRow(new_row, &depth)->model_node());
-}
-
-void TreeView::CollapseOrSelectParent() {
- if (selected_node_) {
- if (selected_node_->is_expanded())
- Collapse(selected_node_->model_node());
- else if (selected_node_->parent())
- SetSelectedNode(selected_node_->parent()->model_node());
- }
-}
-
-void TreeView::ExpandOrSelectChild() {
- if (selected_node_) {
- if (!selected_node_->is_expanded())
- Expand(selected_node_->model_node());
- else if (selected_node_->child_count())
- SetSelectedNode(selected_node_->GetChild(0)->model_node());
- }
-}
-
-bool TreeView::ExpandImpl(TreeModelNode* model_node) {
- TreeModelNode* parent = model_->GetParent(model_node);
- if (!parent) {
- // Node should be the root.
- DCHECK_EQ(root_.model_node(), model_node);
- bool was_expanded = root_.is_expanded();
- root_.set_is_expanded(true);
- return !was_expanded;
- }
-
- // Expand all the parents.
- bool return_value = ExpandImpl(parent);
- InternalNode* internal_node =
- GetInternalNodeForModelNode(model_node, CREATE_IF_NOT_LOADED);
- DCHECK(internal_node);
- if (!internal_node->is_expanded()) {
- if (!internal_node->loaded_children())
- LoadChildren(internal_node);
- internal_node->set_is_expanded(true);
- return_value = true;
- }
- return return_value;
-}
-
-// InternalNode ----------------------------------------------------------------
-
-TreeView::InternalNode::InternalNode()
- : model_node_(NULL),
- loaded_children_(false),
- is_expanded_(false),
- text_width_(0) {
-}
-
-TreeView::InternalNode::~InternalNode() {
-}
-
-void TreeView::InternalNode::Reset(ui::TreeModelNode* node) {
- model_node_ = node;
- loaded_children_ = false;
- is_expanded_ = false;
- text_width_ = 0;
-}
-
-int TreeView::InternalNode::NumExpandedNodes() const {
- int result = 1; // For this.
- if (!is_expanded_)
- return result;
- for (int i = 0; i < child_count(); ++i)
- result += GetChild(i)->NumExpandedNodes();
- return result;
-}
-
-int TreeView::InternalNode::GetMaxWidth(int indent, int depth) {
- int max_width = text_width_ + indent * depth;
- if (!is_expanded_)
- return max_width;
- for (int i = 0; i < child_count(); ++i) {
- max_width = std::max(max_width,
- GetChild(i)->GetMaxWidth(indent, depth + 1));
- }
- return max_width;
-}
-
-} // namespace views
« no previous file with comments | « ui/views/controls/tree/tree_view.h ('k') | ui/views/controls/tree/tree_view_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698