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

Side by Side Diff: ui/views/controls/tabbed_pane/tabbed_pane.cc

Issue 12221130: Revert 181798 for excessive leaks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 10 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/tabbed_pane/tabbed_pane.h" 5 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "ui/base/accessibility/accessible_view_state.h" 8 #include "ui/base/accessibility/accessible_view_state.h"
9 #include "ui/base/keycodes/keyboard_codes.h" 9 #include "ui/base/keycodes/keyboard_codes.h"
10 #include "ui/gfx/canvas.h" 10 #include "ui/views/controls/native/native_view_host.h"
11 #include "ui/gfx/font.h" 11 #include "ui/views/controls/tabbed_pane/native_tabbed_pane_views.h"
12 #include "ui/views/controls/label.h" 12 #include "ui/views/controls/tabbed_pane/native_tabbed_pane_wrapper.h"
13 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h" 13 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
14 #include "ui/views/layout/layout_manager.h"
15 #include "ui/views/widget/widget.h" 14 #include "ui/views/widget/widget.h"
16 15
16 // TODO(markusheintz): This should be removed once the native Windows tabbed
17 // pane is not used anymore (http://crbug.com/138059).
18 #if defined(OS_WIN) && !defined(USE_AURA)
19 #include "ui/views/controls/tabbed_pane/native_tabbed_pane_win.h"
20 #endif
21
17 namespace { 22 namespace {
18 23
19 const char kViewClassName[] = "views/TabbedPane"; 24 views::NativeTabbedPaneWrapper* CreateNativeWrapper(
20 25 views::TabbedPane* tabbed_pane) {
21 // TODO(markusheintz|msw): Use NativeTheme colors. 26 #if defined(OS_WIN) && !defined(USE_AURA)
22 const SkColor kTabTitleColor_Inactive = SkColorSetRGB(0x66, 0x66, 0x66); 27 if (tabbed_pane->use_native_win_control())
23 const SkColor kTabTitleColor_Active = SkColorSetRGB(0x20, 0x20, 0x20); 28 return new views::NativeTabbedPaneWin(tabbed_pane);
24 const SkColor kTabTitleColor_Pressed = SkColorSetRGB(0x33, 0x33, 0x33); 29 #endif
25 const SkColor kTabTitleColor_Hovered = SkColorSetRGB(0x22, 0x22, 0x22); 30 return new views::NativeTabbedPaneViews(tabbed_pane);
26 const SkColor kTabBackgroundColor = SK_ColorWHITE; 31 }
27 const SkColor kTabBorderColor = SkColorSetRGB(0xCC, 0xCC, 0xCC);
28 const SkScalar kTabBorderThickness = 1.0f;
29 const SkScalar kTabBorderRadius = 2.0f;
30 32
31 } // namespace 33 } // namespace
32 34
33 namespace views { 35 namespace views {
34 36
35 // The tab view shown in the tab strip. 37 // static
36 class Tab : public View { 38 const char TabbedPane::kViewClassName[] = "views/TabbedPane";
37 public:
38 Tab(TabbedPane* tabbed_pane, const string16& title, View* contents);
39 virtual ~Tab();
40 39
41 View* contents() const { return contents_; } 40 TabbedPane::TabbedPane()
42 41 : native_tabbed_pane_(NULL),
43 bool selected() const { return contents_->visible(); } 42 #if defined(OS_WIN) && !defined(USE_AURA)
44 void SetSelected(bool selected); 43 use_native_win_control_(false),
45 44 #endif
46 // Overridden from View: 45 listener_(NULL) {
47 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 46 set_focusable(true);
48 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
49 virtual void OnMouseCaptureLost() OVERRIDE;
50 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
51 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
52 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
53 virtual gfx::Size GetPreferredSize() OVERRIDE;
54 virtual void Layout() OVERRIDE;
55 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
56
57 private:
58 void SetTitleColor(SkColor color);
59 void PaintTabBorder(gfx::Canvas* canvas);
60
61 TabbedPane* tabbed_pane_;
62 Label* title_;
63 // The content view associated with this tab.
64 View* contents_;
65
66 DISALLOW_COPY_AND_ASSIGN(Tab);
67 };
68
69 // The tab strip shown above the tab contents.
70 class TabStrip : public View {
71 public:
72 TabStrip();
73 virtual ~TabStrip();
74
75 // Overridden from View:
76 virtual gfx::Size GetPreferredSize() OVERRIDE;
77 virtual void Layout() OVERRIDE;
78 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
79
80 private:
81 DISALLOW_COPY_AND_ASSIGN(TabStrip);
82 };
83
84 Tab::Tab(TabbedPane* tabbed_pane, const string16& title, View* contents)
85 : tabbed_pane_(tabbed_pane),
86 title_(new Label(title, gfx::Font().DeriveFont(0, gfx::Font::BOLD))),
87 contents_(contents) {
88 SetTitleColor(kTabTitleColor_Inactive);
89 AddChildView(title_);
90 } 47 }
91 48
92 Tab::~Tab() {} 49 TabbedPane::~TabbedPane() {
93
94 void Tab::SetSelected(bool selected) {
95 contents_->SetVisible(selected);
96 SetTitleColor(selected ? kTabTitleColor_Active : kTabTitleColor_Inactive);
97 } 50 }
98 51
99 bool Tab::OnMousePressed(const ui::MouseEvent& event) { 52 int TabbedPane::GetTabCount() {
100 SetTitleColor(kTabTitleColor_Pressed); 53 return native_tabbed_pane_->GetTabCount();
101 return true;
102 } 54 }
103 55
104 void Tab::OnMouseReleased(const ui::MouseEvent& event) { 56 int TabbedPane::GetSelectedTabIndex() {
105 SetTitleColor(selected() ? kTabTitleColor_Active : kTabTitleColor_Hovered); 57 return native_tabbed_pane_->GetSelectedTabIndex();
106 if (GetLocalBounds().Contains(event.location()))
107 tabbed_pane_->SelectTab(this);
108 }
109
110 void Tab::OnMouseCaptureLost() {
111 SetTitleColor(kTabTitleColor_Inactive);
112 }
113
114 void Tab::OnMouseEntered(const ui::MouseEvent& event) {
115 SetTitleColor(selected() ? kTabTitleColor_Active : kTabTitleColor_Hovered);
116 }
117
118 void Tab::OnMouseExited(const ui::MouseEvent& event) {
119 SetTitleColor(selected() ? kTabTitleColor_Active : kTabTitleColor_Inactive);
120 }
121
122 void Tab::OnGestureEvent(ui::GestureEvent* event) {
123 switch (event->type()) {
124 case ui::ET_GESTURE_TAP_DOWN:
125 SetTitleColor(kTabTitleColor_Pressed);
126 break;
127 case ui::ET_GESTURE_TAP:
128 // SelectTab also sets the right tab color.
129 tabbed_pane_->SelectTab(this);
130 break;
131 case ui::ET_GESTURE_TAP_CANCEL:
132 SetTitleColor(selected() ?
133 kTabTitleColor_Active : kTabTitleColor_Inactive);
134 break;
135 default:
136 break;
137 }
138 event->SetHandled();
139 }
140
141 gfx::Size Tab::GetPreferredSize() {
142 gfx::Size size(title_->GetPreferredSize());
143 size.Enlarge(30, 10);
144 const int kTabMinWidth = 54;
145 if (size.width() < kTabMinWidth)
146 size.set_width(kTabMinWidth);
147 return size;
148 }
149
150 void Tab::Layout() {
151 gfx::Rect bounds = GetLocalBounds();
152 bounds.ClampToCenteredSize(title_->GetPreferredSize());
153 title_->SetBoundsRect(bounds);
154 }
155
156 void Tab::OnPaint(gfx::Canvas* canvas) {
157 if (selected()) {
158 canvas->DrawColor(kTabBackgroundColor);
159 PaintTabBorder(canvas);
160 }
161 View::OnPaint(canvas);
162 }
163
164 void Tab::SetTitleColor(SkColor color) {
165 title_->SetEnabledColor(color);
166 SchedulePaint();
167 }
168
169 void Tab::PaintTabBorder(gfx::Canvas* canvas) {
170 SkPath path;
171 // Clip the bottom of the border by extending its rect height beyond the tab.
172 const int tab_height = height() + kTabBorderThickness;
173 SkRect bounds = { 0, 0, SkIntToScalar(width()), SkIntToScalar(tab_height) };
174 SkScalar radii[8] = { kTabBorderRadius, kTabBorderRadius,
175 kTabBorderRadius, kTabBorderRadius,
176 0, 0,
177 0, 0 };
178 path.addRoundRect(bounds, radii, SkPath::kCW_Direction);
179
180 SkPaint paint;
181 paint.setAntiAlias(true);
182 paint.setStyle(SkPaint::kStroke_Style);
183 paint.setColor(kTabBorderColor);
184 paint.setStrokeWidth(kTabBorderThickness * 2);
185 canvas->DrawPath(path, paint);
186 }
187
188 TabStrip::TabStrip() {
189 const int kCount = 4;
190 // This gradient is designed to mach WebUI tabbed panes.
191 SkColor colors[kCount] = {
192 SkColorSetRGB(0xff, 0xff, 0xff),
193 SkColorSetRGB(0xff, 0xff, 0xff),
194 SkColorSetRGB(0xfa, 0xfa, 0xfa),
195 SkColorSetRGB(0xf2, 0xf2, 0xf2)
196 };
197 SkScalar pos[kCount] = { 0.0f, 0.6f, 0.8f, 1.0f };
198 set_background(Background::CreateVerticalMultiColorGradientBackground(
199 colors, pos, kCount));
200 }
201
202 TabStrip::~TabStrip() {}
203
204 gfx::Size TabStrip::GetPreferredSize() {
205 gfx::Size size;
206 for (int i = 0; i < child_count(); ++i) {
207 const gfx::Size child_size = child_at(i)->GetPreferredSize();
208 size.SetSize(size.width() + child_size.width(),
209 std::max(size.height(), child_size.height()));
210 }
211 return size;
212 }
213
214 void TabStrip::Layout() {
215 const int kTabOffset = 18;
216 int x = kTabOffset; // Layout tabs with an offset to the tabstrip border.
217 for (int i = 0; i < child_count(); ++i) {
218 gfx::Size ps = child_at(i)->GetPreferredSize();
219 child_at(i)->SetBounds(x, 0, ps.width(), ps.height());
220 x = child_at(i)->bounds().right();
221 }
222 }
223
224 void TabStrip::OnPaint(gfx::Canvas* canvas) {
225 OnPaintBackground(canvas);
226
227 // Draw the TabStrip border.
228 SkPaint paint;
229 paint.setColor(kTabBorderColor);
230 paint.setStrokeWidth(kTabBorderThickness);
231 SkScalar line_y = SkIntToScalar(height()) - kTabBorderThickness;
232 SkScalar line_width = SkIntToScalar(width());
233 canvas->sk_canvas()->drawLine(0, line_y, line_width, line_y, paint);
234 }
235
236 TabbedPane::TabbedPane()
237 : listener_(NULL),
238 tab_strip_(new TabStrip()),
239 contents_(new View()),
240 selected_tab_index_(-1) {
241 set_focusable(true);
242 AddChildView(tab_strip_);
243 AddChildView(contents_);
244 }
245
246 TabbedPane::~TabbedPane() {}
247
248 int TabbedPane::GetTabCount() {
249 DCHECK_EQ(tab_strip_->child_count(), contents_->child_count());
250 return contents_->child_count();
251 } 58 }
252 59
253 View* TabbedPane::GetSelectedTab() { 60 View* TabbedPane::GetSelectedTab() {
254 return selected_tab_index() < 0 ? 61 return native_tabbed_pane_->GetSelectedTab();
255 NULL : GetTabAt(selected_tab_index())->contents();
256 } 62 }
257 63
258 void TabbedPane::AddTab(const string16& title, View* contents) { 64 void TabbedPane::AddTab(const string16& title, View* contents) {
259 AddTabAtIndex(tab_strip_->child_count(), title, contents); 65 native_tabbed_pane_->AddTab(title, contents);
66 PreferredSizeChanged();
260 } 67 }
261 68
262 void TabbedPane::AddTabAtIndex(int index, 69 void TabbedPane::AddTabAtIndex(int index,
263 const string16& title, 70 const string16& title,
264 View* contents) { 71 View* contents,
265 DCHECK(index >= 0 && index <= GetTabCount()); 72 bool select_if_first_tab) {
266 contents->set_owned_by_client(); 73 native_tabbed_pane_->AddTabAtIndex(index, title, contents,
267 contents->SetVisible(false); 74 select_if_first_tab);
268
269 tab_strip_->AddChildViewAt(new Tab(this, title, contents), index);
270 contents_->AddChildViewAt(contents, index);
271 if (selected_tab_index() < 0)
272 SelectTabAt(index);
273
274 PreferredSizeChanged(); 75 PreferredSizeChanged();
275 } 76 }
276 77
277 void TabbedPane::SelectTabAt(int index) { 78 View* TabbedPane::RemoveTabAtIndex(int index) {
278 DCHECK(index >= 0 && index < GetTabCount()); 79 View* tab = native_tabbed_pane_->RemoveTabAtIndex(index);
279 if (index == selected_tab_index()) 80 PreferredSizeChanged();
280 return; 81 return tab;
281
282 if (selected_tab_index() >= 0)
283 GetTabAt(selected_tab_index())->SetSelected(false);
284
285 selected_tab_index_ = index;
286 Tab* tab = GetTabAt(index);
287 tab->SetSelected(true);
288 tab_strip_->SchedulePaint();
289
290 FocusManager* focus_manager = tab->contents()->GetFocusManager();
291 if (focus_manager) {
292 const View* focused_view = focus_manager->GetFocusedView();
293 if (focused_view && contents_->Contains(focused_view) &&
294 !tab->contents()->Contains(focused_view))
295 focus_manager->SetFocusedView(tab->contents());
296 }
297
298 if (listener())
299 listener()->TabSelectedAt(index);
300 } 82 }
301 83
302 void TabbedPane::SelectTab(Tab* tab) { 84 void TabbedPane::SelectTabAt(int index) {
303 const int index = tab_strip_->GetIndexOf(tab); 85 native_tabbed_pane_->SelectTabAt(index);
304 if (index >= 0) 86 }
305 SelectTabAt(index); 87
88 void TabbedPane::SetAccessibleName(const string16& name) {
89 accessible_name_ = name;
306 } 90 }
307 91
308 gfx::Size TabbedPane::GetPreferredSize() { 92 gfx::Size TabbedPane::GetPreferredSize() {
309 gfx::Size size; 93 return native_tabbed_pane_ ?
310 for (int i = 0; i < contents_->child_count(); ++i) 94 native_tabbed_pane_->GetPreferredSize() : gfx::Size();
311 size.ClampToMin(contents_->child_at(i)->GetPreferredSize());
312 size.Enlarge(0, tab_strip_->GetPreferredSize().height());
313 return size;
314 } 95 }
315 96
316 Tab* TabbedPane::GetTabAt(int index) { 97 void TabbedPane::LoadAccelerators() {
317 return static_cast<Tab*>(tab_strip_->child_at(index)); 98 // Ctrl+Shift+Tab
99 AddAccelerator(ui::Accelerator(ui::VKEY_TAB,
100 ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN));
101 // Ctrl+Tab
102 AddAccelerator(ui::Accelerator(ui::VKEY_TAB, ui::EF_CONTROL_DOWN));
318 } 103 }
319 104
320 void TabbedPane::Layout() { 105 void TabbedPane::Layout() {
321 const gfx::Size size = tab_strip_->GetPreferredSize(); 106 if (native_tabbed_pane_)
322 tab_strip_->SetBounds(0, 0, width(), size.height()); 107 native_tabbed_pane_->GetView()->SetBounds(0, 0, width(), height());
323 contents_->SetBounds(0, tab_strip_->bounds().bottom(), width(),
324 std::max(0, height() - size.height()));
325 for (int i = 0; i < contents_->child_count(); ++i)
326 contents_->child_at(i)->SetSize(contents_->size());
327 } 108 }
328 109
329 void TabbedPane::ViewHierarchyChanged(bool is_add, View* parent, View* child) { 110 void TabbedPane::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
330 if (is_add) { 111 if (is_add && !native_tabbed_pane_) {
331 // Support navigating tabs by Ctrl+Tab and Ctrl+Shift+Tab. 112 // The native wrapper's lifetime will be managed by the view hierarchy after
332 AddAccelerator(ui::Accelerator(ui::VKEY_TAB, 113 // we call AddChildView.
333 ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN)); 114 native_tabbed_pane_ = CreateNativeWrapper(this);
334 AddAccelerator(ui::Accelerator(ui::VKEY_TAB, ui::EF_CONTROL_DOWN)); 115 AddChildView(native_tabbed_pane_->GetView());
116 LoadAccelerators();
335 } 117 }
336 } 118 }
337 119
338 bool TabbedPane::AcceleratorPressed(const ui::Accelerator& accelerator) { 120 bool TabbedPane::AcceleratorPressed(const ui::Accelerator& accelerator) {
339 // Handle Ctrl+Tab and Ctrl+Shift+Tab navigation of pages. 121 // We only accept Ctrl+Tab keyboard events.
340 DCHECK(accelerator.key_code() == ui::VKEY_TAB && accelerator.IsCtrlDown()); 122 DCHECK(accelerator.key_code() == ui::VKEY_TAB && accelerator.IsCtrlDown());
341 const int tab_count = GetTabCount(); 123
124 int tab_count = GetTabCount();
342 if (tab_count <= 1) 125 if (tab_count <= 1)
343 return false; 126 return false;
344 const int increment = accelerator.IsShiftDown() ? -1 : 1; 127 int selected_tab_index = GetSelectedTabIndex();
345 int next_tab_index = (selected_tab_index() + increment) % tab_count; 128 int next_tab_index = accelerator.IsShiftDown() ?
129 (selected_tab_index - 1) % tab_count :
130 (selected_tab_index + 1) % tab_count;
346 // Wrap around. 131 // Wrap around.
347 if (next_tab_index < 0) 132 if (next_tab_index < 0)
348 next_tab_index += tab_count; 133 next_tab_index += tab_count;
349 SelectTabAt(next_tab_index); 134 SelectTabAt(next_tab_index);
350 return true; 135 return true;
351 } 136 }
352 137
353 std::string TabbedPane::GetClassName() const { 138 std::string TabbedPane::GetClassName() const {
354 return kViewClassName; 139 return kViewClassName;
355 } 140 }
356 141
357 void TabbedPane::OnFocus() { 142 void TabbedPane::OnFocus() {
358 View::OnFocus(); 143 // Forward the focus to the wrapper.
144 if (native_tabbed_pane_) {
145 native_tabbed_pane_->SetFocus();
359 146
360 View* selected_tab = GetSelectedTab(); 147 View* selected_tab = GetSelectedTab();
361 if (selected_tab) { 148 if (selected_tab) {
362 selected_tab->GetWidget()->NotifyAccessibilityEvent( 149 selected_tab->GetWidget()->NotifyAccessibilityEvent(
363 selected_tab, ui::AccessibilityTypes::EVENT_FOCUS, true); 150 selected_tab, ui::AccessibilityTypes::EVENT_FOCUS, true);
151 }
152 } else {
153 View::OnFocus(); // Will focus the RootView window (so we still get
154 // keyboard messages).
364 } 155 }
365 } 156 }
366 157
158 void TabbedPane::OnPaintFocusBorder(gfx::Canvas* canvas) {
159 if (NativeViewHost::kRenderNativeControlFocus)
160 View::OnPaintFocusBorder(canvas);
161 }
162
367 void TabbedPane::GetAccessibleState(ui::AccessibleViewState* state) { 163 void TabbedPane::GetAccessibleState(ui::AccessibleViewState* state) {
368 state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST; 164 state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST;
165 state->name = accessible_name_;
369 } 166 }
370 167
371 } // namespace views 168 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/tabbed_pane/tabbed_pane.h ('k') | ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698