summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-19 01:49:15 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-19 01:49:15 +0000
commitd4208dd1717889212bc7749168d1a7b8dea44ebe (patch)
tree14c1171fda2c8777f9de5a98c871d2048273b62b
parent2044b609f742ff9cd3f4dbbc27d8573c9bff4084 (diff)
downloadchromium_src-d4208dd1717889212bc7749168d1a7b8dea44ebe.zip
chromium_src-d4208dd1717889212bc7749168d1a7b8dea44ebe.tar.gz
chromium_src-d4208dd1717889212bc7749168d1a7b8dea44ebe.tar.bz2
When adding a TabbedPane to anther TabbedPane at 2nd place or later,
a wrapper is not created b/c the content is added to the hieracy only when the content is visible. This cause a crash when a tab is added to this child tabbed pane. This CL fix this case. Review URL: http://codereview.chromium.org/211018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26645 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--views/controls/tabbed_pane/native_tabbed_pane_win.cc97
-rw-r--r--views/controls/tabbed_pane/native_tabbed_pane_win.h19
-rw-r--r--views/controls/tabbed_pane/tabbed_pane.cc4
3 files changed, 85 insertions, 35 deletions
diff --git a/views/controls/tabbed_pane/native_tabbed_pane_win.cc b/views/controls/tabbed_pane/native_tabbed_pane_win.cc
index 8ae054c..b2ee503 100644
--- a/views/controls/tabbed_pane/native_tabbed_pane_win.cc
+++ b/views/controls/tabbed_pane/native_tabbed_pane_win.cc
@@ -52,7 +52,8 @@ class TabBackground : public Background {
NativeTabbedPaneWin::NativeTabbedPaneWin(TabbedPane* tabbed_pane)
: NativeControlWin(),
tabbed_pane_(tabbed_pane),
- content_window_(NULL) {
+ content_window_(NULL),
+ selected_index_(-1) {
// Associates the actual HWND with the tabbed-pane so the tabbed-pane is
// the one considered as having the focus (not the wrapper) when the HWND is
// focused directly (with a click for example).
@@ -77,7 +78,30 @@ void NativeTabbedPaneWin::AddTabAtIndex(int index, const std::wstring& title,
DCHECK(index <= static_cast<int>(tab_views_.size()));
contents->SetParentOwned(false);
tab_views_.insert(tab_views_.begin() + index, contents);
+ tab_titles_.insert(tab_titles_.begin() + index, title);
+ if (!contents->background())
+ contents->set_background(new TabBackground);
+
+ if (tab_views_.size() == 1 && select_if_first_tab) {
+ // If this is the only tab displayed, make sure the contents is set.
+ selected_index_ = 0;
+ if (content_window_)
+ content_window_->GetRootView()->AddChildView(contents);
+ }
+
+ // Add native tab only if the native control is alreay created.
+ if (content_window_) {
+ AddNativeTab(index, title, contents);
+
+ // The newly added tab may have made the contents window smaller.
+ ResizeContents();
+ }
+}
+
+void NativeTabbedPaneWin::AddNativeTab(int index,
+ const std::wstring &title,
+ views::View* contents) {
TCITEM tcitem;
tcitem.mask = TCIF_TEXT;
@@ -90,17 +114,6 @@ void NativeTabbedPaneWin::AddTabAtIndex(int index, const std::wstring& title,
tcitem.pszText = const_cast<wchar_t*>(title.c_str());
int result = TabCtrl_InsertItem(native_view(), index, &tcitem);
DCHECK(result != -1);
-
- if (!contents->background())
- contents->set_background(new TabBackground);
-
- if (tab_views_.size() == 1 && select_if_first_tab) {
- // If this is the only tab displayed, make sure the contents is set.
- content_window_->GetRootView()->AddChildView(contents);
- }
-
- // The newly added tab may have made the contents window smaller.
- ResizeContents();
}
View* NativeTabbedPaneWin::RemoveTabAtIndex(int index) {
@@ -114,7 +127,7 @@ View* NativeTabbedPaneWin::RemoveTabAtIndex(int index) {
// We are the last tab, select the previous one.
if (index > 0) {
SelectTabAt(index - 1);
- } else {
+ } else if (content_window_) {
// That was the last tab. Remove the contents.
content_window_->GetRootView()->RemoveAllChildViews(false);
}
@@ -127,14 +140,16 @@ View* NativeTabbedPaneWin::RemoveTabAtIndex(int index) {
std::vector<View*>::iterator iter = tab_views_.begin() + index;
View* removed_tab = *iter;
tab_views_.erase(iter);
+ tab_titles_.erase(tab_titles_.begin() + index);
return removed_tab;
}
void NativeTabbedPaneWin::SelectTabAt(int index) {
DCHECK((index >= 0) && (index < static_cast<int>(tab_views_.size())));
- TabCtrl_SetCurSel(native_view(), index);
- DoSelectTabAt(index);
+ if (native_view())
+ TabCtrl_SetCurSel(native_view(), index);
+ DoSelectTabAt(index, true);
}
int NativeTabbedPaneWin::GetTabCount() {
@@ -146,7 +161,9 @@ int NativeTabbedPaneWin::GetSelectedTabIndex() {
}
View* NativeTabbedPaneWin::GetSelectedTab() {
- return content_window_->GetRootView()->GetChildViewAt(0);
+ if (selected_index_ < 0)
+ return NULL;
+ return tab_views_[selected_index_];
}
View* NativeTabbedPaneWin::GetView() {
@@ -214,9 +231,17 @@ void NativeTabbedPaneWin::CreateNativeControl() {
root_view->set_background(Background::CreateSolidBackground(color));
content_window_->SetFocusTraversableParentView(this);
- ResizeContents();
NativeControlCreated(tab_control);
+
+ // Add tabs that are already added if any.
+ if (tab_views_.size() > 0) {
+ InitializeTabs();
+ if (selected_index_ >= 0)
+ DoSelectTabAt(selected_index_, false);
+ }
+
+ ResizeContents();
}
bool NativeTabbedPaneWin::ProcessMessage(UINT message,
@@ -227,7 +252,7 @@ bool NativeTabbedPaneWin::ProcessMessage(UINT message,
reinterpret_cast<LPNMHDR>(l_param)->code == TCN_SELCHANGE) {
int selected_tab = TabCtrl_GetCurSel(native_view());
DCHECK(selected_tab != -1);
- DoSelectTabAt(selected_tab);
+ DoSelectTabAt(selected_tab, true);
return TRUE;
}
return NativeControlWin::ProcessMessage(message, w_param, l_param, result);
@@ -260,21 +285,29 @@ void NativeTabbedPaneWin::ViewHierarchyChanged(bool is_add,
////////////////////////////////////////////////////////////////////////////////
// NativeTabbedPaneWin, private:
-void NativeTabbedPaneWin::DoSelectTabAt(int index) {
- RootView* content_root = content_window_->GetRootView();
-
- // Clear the focus if the focused view was on the tab.
- FocusManager* focus_manager = GetFocusManager();
- DCHECK(focus_manager);
- View* focused_view = focus_manager->GetFocusedView();
- if (focused_view && content_root->IsParentOf(focused_view))
- focus_manager->ClearFocus();
-
- content_root->RemoveAllChildViews(false);
- content_root->AddChildView(tab_views_[index]);
- content_root->Layout();
+void NativeTabbedPaneWin::InitializeTabs() {
+ for (size_t i = 0; i < tab_views_.size(); ++i) {
+ AddNativeTab(i, tab_titles_[i], tab_views_[i]);
+ }
+}
- if (tabbed_pane_->listener())
+void NativeTabbedPaneWin::DoSelectTabAt(int index, boolean invoke_listener) {
+ selected_index_ = index;
+ if (content_window_) {
+ RootView* content_root = content_window_->GetRootView();
+
+ // Clear the focus if the focused view was on the tab.
+ FocusManager* focus_manager = GetFocusManager();
+ DCHECK(focus_manager);
+ View* focused_view = focus_manager->GetFocusedView();
+ if (focused_view && content_root->IsParentOf(focused_view))
+ focus_manager->ClearFocus();
+
+ content_root->RemoveAllChildViews(false);
+ content_root->AddChildView(tab_views_[index]);
+ content_root->Layout();
+ }
+ if (invoke_listener && tabbed_pane_->listener())
tabbed_pane_->listener()->TabSelectedAt(index);
}
diff --git a/views/controls/tabbed_pane/native_tabbed_pane_win.h b/views/controls/tabbed_pane/native_tabbed_pane_win.h
index be55d15..a7423f5 100644
--- a/views/controls/tabbed_pane/native_tabbed_pane_win.h
+++ b/views/controls/tabbed_pane/native_tabbed_pane_win.h
@@ -5,6 +5,8 @@
#ifndef VIEWS_CONTROLS_TABBED_PANE_NATIVE_TABBED_PANE_WIN_H_
#define VIEWS_CONTROLS_TABBED_PANE_NATIVE_TABBED_PANE_WIN_H_
+#include <vector>
+
#include "views/controls/native_control_win.h"
#include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h"
@@ -46,8 +48,17 @@ class NativeTabbedPaneWin : public NativeControlWin,
virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
private:
+ // Called upon creation of native control to initialize tabs that are added
+ // before the native control is created.
+ void InitializeTabs();
+
+ // Adds a tab with the given content to native control at the given index.
+ void AddNativeTab(int index, const std::wstring& title, View* contents);
+
// Changes the contents view to the view associated with the tab at |index|.
- void DoSelectTabAt(int index);
+ // |invoke_listener| controls if this methold should invoke the
+ // Listener::TabSelectedAt callback.
+ void DoSelectTabAt(int index, boolean invoke_listener);
// Resizes the HWND control to macth the size of the containing view.
void ResizeContents();
@@ -58,6 +69,12 @@ class NativeTabbedPaneWin : public NativeControlWin,
// The views associated with the different tabs.
std::vector<View*> tab_views_;
+ // The tab's title strings.
+ std::vector<const std::wstring> tab_titles_;
+
+ // The index of the selected tab.
+ int selected_index_;
+
// The window displayed in the tab.
WidgetWin* content_window_;
diff --git a/views/controls/tabbed_pane/tabbed_pane.cc b/views/controls/tabbed_pane/tabbed_pane.cc
index 5ea39cf..d7db00d 100644
--- a/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/views/controls/tabbed_pane/tabbed_pane.cc
@@ -49,7 +49,7 @@ View* TabbedPane::RemoveTabAtIndex(int index) {
}
void TabbedPane::SelectTabAt(int index) {
- native_tabbed_pane_->SelectTabAt(index);
+ native_tabbed_pane_->SelectTabAt(index);
}
int TabbedPane::GetTabCount() {
@@ -66,7 +66,7 @@ std::string TabbedPane::GetClassName() const {
}
void TabbedPane::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
- if (is_add && !native_tabbed_pane_ && GetWidget()) {
+ if (is_add && !native_tabbed_pane_) {
CreateWrapper();
AddChildView(native_tabbed_pane_->GetView());
LoadAccelerators();