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

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

Issue 155668: Refactoring of tabbed-pane component so it can be ported to Linux toolkit_view (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 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
« no previous file with comments | « views/controls/tabbed_pane.h ('k') | views/controls/tabbed_pane/native_tabbed_pane_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "views/controls/tabbed_pane.h"
6
7 #include <vssym32.h>
8
9 #include "app/gfx/canvas.h"
10 #include "app/gfx/font.h"
11 #include "app/l10n_util_win.h"
12 #include "app/resource_bundle.h"
13 #include "base/gfx/native_theme.h"
14 #include "base/logging.h"
15 #include "base/stl_util-inl.h"
16 #include "skia/ext/skia_utils_win.h"
17 #include "third_party/skia/include/core/SkColor.h"
18 #include "views/background.h"
19 #include "views/fill_layout.h"
20 #include "views/widget/root_view.h"
21 #include "views/widget/widget_win.h"
22
23 namespace views {
24
25 // A background object that paints the tab panel background which may be
26 // rendered by the system visual styles system.
27 class TabBackground : public Background {
28 public:
29 explicit TabBackground() {
30 // TMT_FILLCOLORHINT returns a color value that supposedly
31 // approximates the texture drawn by PaintTabPanelBackground.
32 SkColor tab_page_color =
33 gfx::NativeTheme::instance()->GetThemeColorWithDefault(
34 gfx::NativeTheme::TAB, TABP_BODY, 0, TMT_FILLCOLORHINT,
35 COLOR_3DFACE);
36 SetNativeControlColor(tab_page_color);
37 }
38 virtual ~TabBackground() {}
39
40 virtual void Paint(gfx::Canvas* canvas, View* view) const {
41 HDC dc = canvas->beginPlatformPaint();
42 RECT r = {0, 0, view->width(), view->height()};
43 gfx::NativeTheme::instance()->PaintTabPanelBackground(dc, &r);
44 canvas->endPlatformPaint();
45 }
46
47 private:
48 DISALLOW_EVIL_CONSTRUCTORS(TabBackground);
49 };
50
51 TabbedPane::TabbedPane() : content_window_(NULL), listener_(NULL) {
52 }
53
54 TabbedPane::~TabbedPane() {
55 // We own the tab views, let's delete them.
56 STLDeleteContainerPointers(tab_views_.begin(), tab_views_.end());
57 }
58
59 void TabbedPane::SetListener(Listener* listener) {
60 listener_ = listener;
61 }
62
63 void TabbedPane::AddTab(const std::wstring& title, View* contents) {
64 AddTabAtIndex(static_cast<int>(tab_views_.size()), title, contents, true);
65 }
66
67 void TabbedPane::AddTabAtIndex(int index,
68 const std::wstring& title,
69 View* contents,
70 bool select_if_first_tab) {
71 DCHECK(index <= static_cast<int>(tab_views_.size()));
72 contents->SetParentOwned(false);
73 tab_views_.insert(tab_views_.begin() + index, contents);
74
75 TCITEM tcitem;
76 tcitem.mask = TCIF_TEXT;
77
78 // If the locale is RTL, we set the TCIF_RTLREADING so that BiDi text is
79 // rendered properly on the tabs.
80 if (UILayoutIsRightToLeft()) {
81 tcitem.mask |= TCIF_RTLREADING;
82 }
83
84 tcitem.pszText = const_cast<wchar_t*>(title.c_str());
85 int result = TabCtrl_InsertItem(tab_control_, index, &tcitem);
86 DCHECK(result != -1);
87
88 if (!contents->background()) {
89 contents->set_background(new TabBackground);
90 }
91
92 if (tab_views_.size() == 1 && select_if_first_tab) {
93 // If this is the only tab displayed, make sure the contents is set.
94 content_window_->GetRootView()->AddChildView(contents);
95 }
96
97 // The newly added tab may have made the contents window smaller.
98 ResizeContents(tab_control_);
99 }
100
101 View* TabbedPane::RemoveTabAtIndex(int index) {
102 int tab_count = static_cast<int>(tab_views_.size());
103 DCHECK(index >= 0 && index < tab_count);
104
105 if (index < (tab_count - 1)) {
106 // Select the next tab.
107 SelectTabAt(index + 1);
108 } else {
109 // We are the last tab, select the previous one.
110 if (index > 0) {
111 SelectTabAt(index - 1);
112 } else {
113 // That was the last tab. Remove the contents.
114 content_window_->GetRootView()->RemoveAllChildViews(false);
115 }
116 }
117 TabCtrl_DeleteItem(tab_control_, index);
118
119 // The removed tab may have made the contents window bigger.
120 ResizeContents(tab_control_);
121
122 std::vector<View*>::iterator iter = tab_views_.begin() + index;
123 View* removed_tab = *iter;
124 tab_views_.erase(iter);
125
126 return removed_tab;
127 }
128
129 void TabbedPane::SelectTabAt(int index) {
130 DCHECK((index >= 0) && (index < static_cast<int>(tab_views_.size())));
131 TabCtrl_SetCurSel(tab_control_, index);
132 DoSelectTabAt(index);
133 }
134
135 void TabbedPane::SelectTabForContents(const View* contents) {
136 SelectTabAt(GetIndexForContents(contents));
137 }
138
139 int TabbedPane::GetTabCount() {
140 return TabCtrl_GetItemCount(tab_control_);
141 }
142
143 HWND TabbedPane::CreateNativeControl(HWND parent_container) {
144 // Create the tab control.
145 //
146 // Note that we don't follow the common convention for NativeControl
147 // subclasses and we don't pass the value returned from
148 // NativeControl::GetAdditionalExStyle() as the dwExStyle parameter. Here is
149 // why: on RTL locales, if we pass NativeControl::GetAdditionalExStyle() when
150 // we basically tell Windows to create our HWND with the WS_EX_LAYOUTRTL. If
151 // we do that, then the HWND we create for |content_window_| below will
152 // inherit the WS_EX_LAYOUTRTL property and this will result in the contents
153 // being flipped, which is not what we want (because we handle mirroring in
154 // views without the use of Windows' support for mirroring). Therefore,
155 // we initially create our HWND without the aforementioned property and we
156 // explicitly set this property our child is created. This way, on RTL
157 // locales, our tabs will be nicely rendered from right to left (by virtue of
158 // Windows doing the right thing with the TabbedPane HWND) and each tab
159 // contents will use an RTL layout correctly (by virtue of the mirroring
160 // infrastructure in views doing the right thing with each View we put
161 // in the tab).
162 tab_control_ = ::CreateWindowEx(0,
163 WC_TABCONTROL,
164 L"",
165 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
166 0, 0, width(), height(),
167 parent_container, NULL, NULL, NULL);
168
169 HFONT font = ResourceBundle::GetSharedInstance().
170 GetFont(ResourceBundle::BaseFont).hfont();
171 SendMessage(tab_control_, WM_SETFONT, reinterpret_cast<WPARAM>(font), FALSE);
172
173 // Create the view container which is a child of the TabControl.
174 content_window_ = new WidgetWin();
175 content_window_->Init(tab_control_, gfx::Rect());
176
177 // Explicitly setting the WS_EX_LAYOUTRTL property for the HWND (see above
178 // for a thorough explanation regarding why we waited until |content_window_|
179 // if created before we set this property for the tabbed pane's HWND).
180 if (UILayoutIsRightToLeft()) {
181 l10n_util::HWNDSetRTLLayout(tab_control_);
182 }
183
184 RootView* root_view = content_window_->GetRootView();
185 root_view->SetLayoutManager(new FillLayout());
186 DWORD sys_color = ::GetSysColor(COLOR_3DHILIGHT);
187 SkColor color = SkColorSetRGB(GetRValue(sys_color), GetGValue(sys_color),
188 GetBValue(sys_color));
189 root_view->set_background(Background::CreateSolidBackground(color));
190
191 content_window_->SetFocusTraversableParentView(this);
192 ResizeContents(tab_control_);
193 return tab_control_;
194 }
195
196 LRESULT TabbedPane::OnNotify(int w_param, LPNMHDR l_param) {
197 if (static_cast<LPNMHDR>(l_param)->code == TCN_SELCHANGE) {
198 int selected_tab = TabCtrl_GetCurSel(tab_control_);
199 DCHECK(selected_tab != -1);
200 DoSelectTabAt(selected_tab);
201 return TRUE;
202 }
203 return FALSE;
204 }
205
206 void TabbedPane::DoSelectTabAt(int index) {
207 RootView* content_root = content_window_->GetRootView();
208
209 // Clear the focus if the focused view was on the tab.
210 FocusManager* focus_manager = GetFocusManager();
211 DCHECK(focus_manager);
212 View* focused_view = focus_manager->GetFocusedView();
213 if (focused_view && content_root->IsParentOf(focused_view))
214 focus_manager->ClearFocus();
215
216 content_root->RemoveAllChildViews(false);
217 content_root->AddChildView(tab_views_[index]);
218 content_root->Layout();
219 if (listener_)
220 listener_->TabSelectedAt(index);
221 }
222
223 int TabbedPane::GetIndexForContents(const View* contents) const {
224 std::vector<View*>::const_iterator i =
225 std::find(tab_views_.begin(), tab_views_.end(), contents);
226 DCHECK(i != tab_views_.end());
227 return static_cast<int>(i - tab_views_.begin());
228 }
229
230 void TabbedPane::Layout() {
231 NativeControl::Layout();
232 ResizeContents(GetNativeControlHWND());
233 }
234
235 RootView* TabbedPane::GetContentsRootView() {
236 return content_window_->GetRootView();
237 }
238
239 FocusTraversable* TabbedPane::GetFocusTraversable() {
240 return content_window_;
241 }
242
243 void TabbedPane::ViewHierarchyChanged(bool is_add, View *parent, View *child) {
244 NativeControl::ViewHierarchyChanged(is_add, parent, child);
245
246 if (is_add && (child == this) && content_window_) {
247 // We have been added to a view hierarchy, update the FocusTraversable
248 // parent.
249 content_window_->SetFocusTraversableParent(GetRootView());
250 }
251 }
252
253 void TabbedPane::ResizeContents(HWND tab_control) {
254 DCHECK(tab_control);
255 CRect content_bounds;
256 if (!GetClientRect(tab_control, &content_bounds))
257 return;
258 TabCtrl_AdjustRect(tab_control, FALSE, &content_bounds);
259 content_window_->MoveWindow(content_bounds.left, content_bounds.top,
260 content_bounds.Width(), content_bounds.Height(),
261 TRUE);
262 }
263
264 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/tabbed_pane.h ('k') | views/controls/tabbed_pane/native_tabbed_pane_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698