diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-24 22:58:08 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-24 22:58:08 +0000 |
commit | 62ca321dd5cd95b7e4fc9de922c2ca0703971361 (patch) | |
tree | ce782f196bd0933352bffae1130fd365a626ce25 /chrome | |
parent | 9d6326fae66278988d0eb3f9d5b44e7d9f31870e (diff) | |
download | chromium_src-62ca321dd5cd95b7e4fc9de922c2ca0703971361.zip chromium_src-62ca321dd5cd95b7e4fc9de922c2ca0703971361.tar.gz chromium_src-62ca321dd5cd95b7e4fc9de922c2ca0703971361.tar.bz2 |
Handful of changes to NativeControl, TreeView and TableView I'm going
to need for the bookmark manager. Specifically:
. NativeController now delegates OnContextMenu to the
ContextMenuController.
. TableView allows a NULL model.
. TableView::SetColumns was buggy.
. Added a method that TableView invokes after painting.
. Added methods to TreeView for getting various state information.
BUG=674
TEST=make sure the various places in the UI we uses trees and table
work fine: cookies table, passwords table, task manager, bookmark
editor, search engines.
Review URL: http://codereview.chromium.org/8145
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3956 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/views/event.h | 2 | ||||
-rw-r--r-- | chrome/views/native_control.cc | 8 | ||||
-rw-r--r-- | chrome/views/native_control.h | 2 | ||||
-rw-r--r-- | chrome/views/table_view.cc | 69 | ||||
-rw-r--r-- | chrome/views/table_view.h | 11 | ||||
-rw-r--r-- | chrome/views/table_view_unittest.cc | 15 | ||||
-rw-r--r-- | chrome/views/tree_view.cc | 52 | ||||
-rw-r--r-- | chrome/views/tree_view.h | 21 |
8 files changed, 149 insertions, 31 deletions
diff --git a/chrome/views/event.h b/chrome/views/event.h index 91e8d36..35ebfbe 100644 --- a/chrome/views/event.h +++ b/chrome/views/event.h @@ -111,7 +111,7 @@ class Event { // // LocatedEvent class // -// A generifc event that is used for any events that is located at a specific +// A generic event that is used for any events that is located at a specific // position in the screen. // //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/views/native_control.cc b/chrome/views/native_control.cc index 8fdcb39..04a23fd 100644 --- a/chrome/views/native_control.cc +++ b/chrome/views/native_control.cc @@ -254,6 +254,14 @@ void NativeControl::Layout() { } } +void NativeControl::OnContextMenu(const CPoint& location) { + if (!GetContextMenuController()) + return; + + GetContextMenuController()->ShowContextMenu( + this, location.x, location.y, true); +} + void NativeControl::Focus() { if (container_) { DCHECK(container_->GetControl()); diff --git a/chrome/views/native_control.h b/chrome/views/native_control.h index 68529b9..d96da23 100644 --- a/chrome/views/native_control.h +++ b/chrome/views/native_control.h @@ -54,7 +54,7 @@ class NativeControl : public View { virtual LRESULT OnCommand(UINT code, int id, HWND source) { return 0; } // Invoked when the appropriate gesture for a context menu is issued. - virtual void OnContextMenu(const CPoint& location) {} + virtual void OnContextMenu(const CPoint& location); // Overridden so to set the native focus to the native control. virtual void Focus(); diff --git a/chrome/views/table_view.cc b/chrome/views/table_view.cc index fe4a40e..bf35e1b 100644 --- a/chrome/views/table_view.cc +++ b/chrome/views/table_view.cc @@ -98,7 +98,6 @@ TableView::TableView(TableModel* model, table_view_wrapper_(this), custom_cell_font_(NULL), content_offset_(0) { - DCHECK(model); for (std::vector<TableColumn>::const_iterator i = columns.begin(); i != columns.end(); ++i) { AddColumn(*i); @@ -116,8 +115,15 @@ TableView::~TableView() { } void TableView::SetModel(TableModel* model) { + if (model == model_) + return; + + if (list_view_ && model_) + model_->SetObserver(NULL); model_ = model; - if (model_) + if (list_view_ && model_) + model_->SetObserver(this); + if (list_view_) OnModelChanged(); } @@ -303,7 +309,7 @@ void TableView::OnModelChanged() { int current_row_count = ListView_GetItemCount(list_view_); if (current_row_count > 0) OnItemsRemoved(0, current_row_count); - if (model_->RowCount()) + if (model_ && model_->RowCount()) OnItemsAdded(0, model_->RowCount()); } @@ -377,8 +383,14 @@ void TableView::OnItemsRemoved(int start, int length) { SendMessage(list_view_, WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0); - // We don't seem to get notification in this case. - if (table_view_observer_ && had_selection && RowCount() == 0) + // If the row count goes to zero and we had a selection LVN_ITEMCHANGED isn't + // invoked, so we handle it here. + // + // When the model is set to NULL all the rows are removed. We don't notify + // the delegate in this case as setting the model to NULL is usually done as + // the last step before being deleted and callers shouldn't have to deal with + // getting a selection change when the model is being reset. + if (model_ && table_view_observer_ && had_selection && RowCount() == 0) table_view_observer_->OnSelectionChanged(); } @@ -388,7 +400,11 @@ void TableView::AddColumn(const TableColumn& col) { } void TableView::SetColumns(const std::vector<TableColumn>& columns) { - all_columns_.empty(); + // Remove the currently visible columns. + while (!visible_columns_.empty()) + SetColumnVisibility(visible_columns_.front(), false); + + all_columns_.clear(); for (std::vector<TableColumn>::const_iterator i = columns.begin(); i != columns.end(); ++i) { AddColumn(*i); @@ -514,6 +530,13 @@ LRESULT CALLBACK TableView::TableWndProc(HWND window, // resizing. return 1; + case WM_PAINT: { + LRESULT result = CallWindowProc(table_view->original_handler_, window, + message, w_param, l_param); + table_view->PostPaint(); + return result; + } + default: break; } @@ -565,7 +588,6 @@ HWND TableView::CreateNativeControl(HWND parent_container) { style, 0, 0, width(), height(), parent_container, NULL, NULL, NULL); - model_->SetObserver(this); // Make the selection extend across the row. // Reduce overdraw/flicker artifacts by double buffering. @@ -584,8 +606,11 @@ HWND TableView::CreateNativeControl(HWND parent_container) { static_cast<int>(i - visible_columns_.begin())); } + if (model_) + model_->SetObserver(this); + // Add the groups. - if (model_->HasGroups() && + if (model_ && model_->HasGroups() && win_util::GetWinVersion() > win_util::WINVERSION_2000) { ListView_EnableGroupView(list_view_, true); @@ -602,7 +627,8 @@ HWND TableView::CreateNativeControl(HWND parent_container) { } // Set the # of rows. - UpdateListViewCache(0, model_->RowCount(), true); + if (model_) + UpdateListViewCache(0, model_->RowCount(), true); if (table_type_ == ICON_AND_TEXT) { HIMAGELIST image_list = @@ -791,7 +817,10 @@ void TableView::InsertColumn(const TableColumn& tc, int index) { } } -LRESULT TableView::OnNotify(int w_param, NMHDR* hdr) { +LRESULT TableView::OnNotify(int w_param, LPNMHDR hdr) { + if (!model_) + return 0; + switch (hdr->code) { case NM_CUSTOMDRAW: { // Draw notification. dwDragState indicates the current stage of drawing. @@ -898,6 +927,19 @@ int TableView::CompareRows(int model_row1, int model_row2) { return SwapCompareResult(sort_result, sort_descriptors_[0].ascending); } +int TableView::GetColumnWidth(int column_id) { + if (!list_view_) + return -1; + + std::vector<int>::const_iterator i = + std::find(visible_columns_.begin(), visible_columns_.end(), column_id); + if (i == visible_columns_.end()) + return -1; + + return ListView_GetColumnWidth( + list_view_, static_cast<int>(i - visible_columns_.begin())); +} + LRESULT TableView::OnCustomDraw(NMLVCUSTOMDRAW* draw_info) { switch (draw_info->nmcd.dwDrawStage) { case CDDS_PREPAINT: { @@ -975,11 +1017,14 @@ LRESULT TableView::OnCustomDraw(NMLVCUSTOMDRAW* draw_info) { // It seems the state in nmcd.uItemState is not correct. // We'll retrieve it explicitly. - int selected = ListView_GetItemState(list_view_, view_index, - LVIS_SELECTED); + int selected = ListView_GetItemState( + list_view_, view_index, LVIS_SELECTED | LVIS_DROPHILITED); + bool drop_highlight = ((selected & LVIS_DROPHILITED) != 0); int bg_color_index; if (!IsEnabled()) bg_color_index = COLOR_3DFACE; + else if (drop_highlight) + bg_color_index = COLOR_HIGHLIGHT; else if (selected) bg_color_index = HasFocus() ? COLOR_HIGHLIGHT : COLOR_3DFACE; else diff --git a/chrome/views/table_view.h b/chrome/views/table_view.h index ab92a86..10c4b65 100644 --- a/chrome/views/table_view.h +++ b/chrome/views/table_view.h @@ -333,6 +333,7 @@ class TableView : public NativeControl, // should be called in the containing view's destructor to avoid destruction // issues when the model needs to be deleted before the table. void SetModel(TableModel* model); + TableModel* model() const { return model_; } // Resorts the contents. void SetSortDescriptors(const SortDescriptors& sort_descriptors); @@ -455,6 +456,7 @@ class TableView : public NativeControl, // Subclasses can implement in this method extra-painting for cells. virtual void PostPaint(int model_row, int column, bool selected, const CRect& bounds, HDC device_context) { } + virtual void PostPaint() {} virtual HWND CreateNativeControl(HWND parent_container); @@ -472,6 +474,14 @@ class TableView : public NativeControl, // that need to cache state used during sorting. virtual void PrepareForSort() {} + // Returns the width of the specified column by id, or -1 if the column isn't + // visible. + int GetColumnWidth(int column_id); + + // Returns the offset from the top of the client area to the start of the + // content. + int content_offset() const { return content_offset_; } + private: // Direction of a sort. enum SortDirection { @@ -630,7 +640,6 @@ class TableView : public NativeControl, // The preferred size of the table view. gfx::Size preferred_size_; - // The offset from the top of the client area to the start of the content. int content_offset_; // Current sort. diff --git a/chrome/views/table_view_unittest.cc b/chrome/views/table_view_unittest.cc index 5b4c509..9ef53da 100644 --- a/chrome/views/table_view_unittest.cc +++ b/chrome/views/table_view_unittest.cc @@ -212,6 +212,16 @@ TestTableModel* TableViewTest::CreateModel() { return new TestTableModel(); } +// NullModelTableViewTest ------------------------------------------------------ + +class NullModelTableViewTest : public TableViewTest { + protected: + // Creates the model. + TestTableModel* CreateModel() { + return NULL; + } +}; + // Tests ----------------------------------------------------------------------- // Tests various sorting permutations. @@ -363,3 +373,8 @@ TEST_F(TableViewTest, PersistMultiSelectionOnAdd) { VerifySelectedRows(1, 0, -1); } + +TEST_F(NullModelTableViewTest, NullModel) { + // There's nothing explicit to test. If there is a bug in TableView relating + // to a NULL model we'll crash. +} diff --git a/chrome/views/tree_view.cc b/chrome/views/tree_view.cc index 43f3d24..2719970 100644 --- a/chrome/views/tree_view.cc +++ b/chrome/views/tree_view.cc @@ -60,7 +60,8 @@ TreeView::TreeView() show_context_menu_only_when_node_selected_(true), select_on_right_mouse_down_(true), wrapper_(this), - original_handler_(NULL) { + original_handler_(NULL), + drag_enabled_(false) { } TreeView::~TreeView() { @@ -177,6 +178,17 @@ void TreeView::ExpandAll() { ExpandAll(model_->GetRoot()); } +bool TreeView::IsExpanded(TreeModelNode* node) { + TreeModelNode* parent = model_->GetParent(node); + if (!parent) + return true; + if (!IsExpanded(parent)) + return false; + NodeDetails* details = GetNodeDetails(node); + return (TreeView_GetItemState(tree_view_, details->tree_item, TVIS_EXPANDED) & + TVIS_EXPANDED) != 0; +} + void TreeView::SetRootShown(bool root_shown) { if (root_shown_ == root_shown) return; @@ -282,8 +294,9 @@ void TreeView::TreeNodeChanged(TreeModel* model, TreeModelNode* node) { } HWND TreeView::CreateNativeControl(HWND parent_container) { - int style = WS_CHILD | TVS_DISABLEDRAGDROP | TVS_HASBUTTONS | - TVS_HASLINES | TVS_SHOWSELALWAYS; + int style = WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS; + if (!drag_enabled_) + style |= TVS_DISABLEDRAGDROP; if (editable_) style |= TVS_EDITLABELS; tree_view_ = ::CreateWindowEx(WS_EX_CLIENTEDGE | GetAdditionalExStyle(), @@ -473,6 +486,16 @@ void TreeView::OnContextMenu(const CPoint& location) { } } +TreeModelNode* TreeView::GetNodeForTreeItem(HTREEITEM tree_item) { + NodeDetails* details = GetNodeDetailsByTreeItem(tree_item); + return details ? details->node : NULL; +} + +HTREEITEM TreeView::GetTreeItemForNode(TreeModelNode* node) { + NodeDetails* details = GetNodeDetails(node); + return details ? details->tree_item : NULL; +} + void TreeView::ExpandAll(TreeModelNode* node) { DCHECK(node); // Expand the node. @@ -575,15 +598,19 @@ LRESULT CALLBACK TreeView::TreeWndProc(HWND window, GetWindowLongPtr(window, GWLP_USERDATA)); DCHECK(wrapper); TreeView* tree = wrapper->tree_view; - if (message == WM_RBUTTONDOWN && tree->select_on_right_mouse_down_) { - TVHITTESTINFO hit_info; - hit_info.pt.x = GET_X_LPARAM(l_param); - hit_info.pt.y = GET_Y_LPARAM(l_param); - HTREEITEM hit_item = TreeView_HitTest(window, &hit_info); - if (hit_item && (hit_info.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT | - TVHT_ONITEMINDENT)) != 0) - TreeView_SelectItem(tree->tree_view_, hit_item); - // Fall through and let the default handler process as well. + switch (message) { + case WM_RBUTTONDOWN: + if (tree->select_on_right_mouse_down_) { + TVHITTESTINFO hit_info; + hit_info.pt.x = GET_X_LPARAM(l_param); + hit_info.pt.y = GET_Y_LPARAM(l_param); + HTREEITEM hit_item = TreeView_HitTest(window, &hit_info); + if (hit_item && (hit_info.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT | + TVHT_ONITEMINDENT)) != 0) + TreeView_SelectItem(tree->tree_view_, hit_item); + } + // Fall through and let the default handler process as well. + break; } WNDPROC handler = tree->original_handler_; DCHECK(handler); @@ -591,4 +618,3 @@ LRESULT CALLBACK TreeView::TreeWndProc(HWND window, } } // namespace views - diff --git a/chrome/views/tree_view.h b/chrome/views/tree_view.h index 09d046a3..a219f52 100644 --- a/chrome/views/tree_view.h +++ b/chrome/views/tree_view.h @@ -95,13 +95,18 @@ class TreeViewController { // TreeView displays hierarchical data as returned from a TreeModel. The user // can expand, collapse and edit the items. A Controller may be attached to // receive notification of selection changes and restrict editing. -class TreeView : public NativeControl, public TreeModelObserver { +class TreeView : public NativeControl, TreeModelObserver { public: TreeView(); virtual ~TreeView(); + // Is dragging enabled? The default is false. + void set_drag_enabled(bool drag_enabled) { drag_enabled_ = drag_enabled; } + bool drag_enabled() const { return drag_enabled_; } + // Sets the model. TreeView does not take ownership of the model. void SetModel(TreeModel* model); + TreeModel* model() const { return model_; } // Sets whether the user can edit the nodes. The default is true. If true, // the Controller is queried to determine if a particular node can be edited. @@ -133,6 +138,9 @@ class TreeView : public NativeControl, public TreeModelObserver { // Convenience to expand ALL nodes in the tree. void ExpandAll(); + // Returns true if the specified node is expanded. + bool IsExpanded(TreeModelNode* node); + // Sets whether the root is shown. If true, the root node of the tree is // shown, if false only the children of the root are shown. The default is // true. @@ -200,6 +208,12 @@ class TreeView : public NativeControl, public TreeModelObserver { virtual void OnContextMenu(const CPoint& location); + // Returns the TreeModelNode for |tree_item|. + TreeModelNode* GetNodeForTreeItem(HTREEITEM tree_item); + + // Returns the tree item for |node|. + HTREEITEM GetTreeItemForNode(TreeModelNode* node); + private: // See notes in TableView::TableViewWrapper for why this is needed. struct TreeViewWrapper { @@ -319,10 +333,11 @@ class TreeView : public NativeControl, public TreeModelObserver { // Original handler installed on the TreeView. WNDPROC original_handler_; - DISALLOW_EVIL_CONSTRUCTORS(TreeView); + bool drag_enabled_; + + DISALLOW_COPY_AND_ASSIGN(TreeView); }; } // namespace views #endif // CHROME_VIEWS_TREE_VIEW_H__ - |