summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorsky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-24 22:58:08 +0000
committersky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-24 22:58:08 +0000
commit62ca321dd5cd95b7e4fc9de922c2ca0703971361 (patch)
treece782f196bd0933352bffae1130fd365a626ce25 /chrome
parent9d6326fae66278988d0eb3f9d5b44e7d9f31870e (diff)
downloadchromium_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.h2
-rw-r--r--chrome/views/native_control.cc8
-rw-r--r--chrome/views/native_control.h2
-rw-r--r--chrome/views/table_view.cc69
-rw-r--r--chrome/views/table_view.h11
-rw-r--r--chrome/views/table_view_unittest.cc15
-rw-r--r--chrome/views/tree_view.cc52
-rw-r--r--chrome/views/tree_view.h21
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__
-