OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "ui/views/controls/tabbed_pane/native_tabbed_pane_gtk.h" | |
6 | |
7 #include <gtk/gtk.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/stl_util.h" | |
11 #include "base/utf_string_conversions.h" | |
12 #include "ui/gfx/canvas.h" | |
13 #include "ui/gfx/font.h" | |
14 #include "ui/gfx/skia_utils_gtk.h" | |
15 #include "ui/views/background.h" | |
16 #include "ui/views/controls/tabbed_pane/tabbed_pane.h" | |
17 #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h" | |
18 #include "ui/views/layout/fill_layout.h" | |
19 #include "ui/views/widget/native_widget.h" | |
20 #include "ui/views/widget/widget.h" | |
21 | |
22 namespace views { | |
23 | |
24 //////////////////////////////////////////////////////////////////////////////// | |
25 // NativeTabbedPaneGtk, public: | |
26 | |
27 NativeTabbedPaneGtk::NativeTabbedPaneGtk(TabbedPane* tabbed_pane) | |
28 : NativeControlGtk(), | |
29 tabbed_pane_(tabbed_pane) { | |
30 set_focus_view(tabbed_pane); | |
31 } | |
32 | |
33 NativeTabbedPaneGtk::~NativeTabbedPaneGtk() { | |
34 } | |
35 | |
36 //////////////////////////////////////////////////////////////////////////////// | |
37 // NativeTabbedPaneGtk, NativeControlGtk implementation: | |
38 | |
39 void NativeTabbedPaneGtk::CreateNativeControl() { | |
40 GtkWidget* widget = gtk_notebook_new(); | |
41 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(widget), GTK_POS_TOP); | |
42 g_signal_connect(widget, "switch-page", | |
43 G_CALLBACK(CallSwitchPage), this); | |
44 NativeControlCreated(widget); | |
45 } | |
46 | |
47 //////////////////////////////////////////////////////////////////////////////// | |
48 // NativeTabbedPaneGtk, NativeTabbedPaneWrapper implementation: | |
49 | |
50 void NativeTabbedPaneGtk::AddTab(const string16& title, View* contents) { | |
51 AddTabAtIndex(GetTabCount(), title, contents, true); | |
52 } | |
53 | |
54 void NativeTabbedPaneGtk::AddTabAtIndex(int index, | |
55 const string16& title, | |
56 View* contents, | |
57 bool select_if_first_tab) { | |
58 DCHECK(native_view()); | |
59 DoAddTabAtIndex(index, title, contents, select_if_first_tab); | |
60 } | |
61 | |
62 View* NativeTabbedPaneGtk::RemoveTabAtIndex(int index) { | |
63 int tab_count = GetTabCount(); | |
64 DCHECK(index >= 0 && index < tab_count); | |
65 | |
66 if (index < (tab_count - 1)) { | |
67 // Select the next tab. | |
68 SelectTabAt(index + 1); | |
69 } else { | |
70 // We are the last tab, select the previous one. | |
71 if (index > 0) { | |
72 SelectTabAt(index - 1); | |
73 } else { | |
74 // last tab. nothing to select. | |
75 } | |
76 } | |
77 | |
78 GtkWidget* page = | |
79 gtk_notebook_get_nth_page(GTK_NOTEBOOK(native_view()), index); | |
80 Widget* widget = Widget::GetWidgetForNativeView(page); | |
81 | |
82 // detach the content view from widget so that we can delete widget | |
83 // without destroying the content view. | |
84 View* removed_tab = GetTabViewAt(index); | |
85 widget->GetRootView()->RemoveChildView(removed_tab); | |
86 | |
87 // widget delete itself when native_view is deleted. | |
88 gtk_notebook_remove_page(GTK_NOTEBOOK(native_view()), index); | |
89 | |
90 // Removing a tab might change the size of the tabbed pane. | |
91 if (GetWidget()) | |
92 GetWidget()->GetRootView()->Layout(); | |
93 | |
94 return removed_tab; | |
95 } | |
96 | |
97 void NativeTabbedPaneGtk::SelectTabAt(int index) { | |
98 DCHECK((index >= 0) && (index < GetTabCount())); | |
99 gtk_notebook_set_current_page(GTK_NOTEBOOK(native_view()), index); | |
100 } | |
101 | |
102 int NativeTabbedPaneGtk::GetTabCount() { | |
103 return gtk_notebook_get_n_pages(GTK_NOTEBOOK(native_view())); | |
104 } | |
105 | |
106 int NativeTabbedPaneGtk::GetSelectedTabIndex() { | |
107 return gtk_notebook_get_current_page(GTK_NOTEBOOK(native_view())); | |
108 } | |
109 | |
110 View* NativeTabbedPaneGtk::GetSelectedTab() { | |
111 return GetTabViewAt(GetSelectedTabIndex()); | |
112 } | |
113 | |
114 View* NativeTabbedPaneGtk::GetView() { | |
115 return this; | |
116 } | |
117 | |
118 void NativeTabbedPaneGtk::SetFocus() { | |
119 OnFocus(); | |
120 } | |
121 | |
122 gfx::Size NativeTabbedPaneGtk::GetPreferredSize() { | |
123 if (!native_view()) | |
124 return gfx::Size(); | |
125 | |
126 // For some strange reason (or maybe it's a bug), the requisition is not | |
127 // returned in the passed requisition parameter, but instead written to the | |
128 // widget's requisition field. | |
129 GtkRequisition requisition = { 0, 0 }; | |
130 gtk_widget_size_request(GTK_WIDGET(native_view()), &requisition); | |
131 GtkRequisition& size(GTK_WIDGET(native_view())->requisition); | |
132 return gfx::Size(size.width, size.height); | |
133 } | |
134 | |
135 gfx::NativeView NativeTabbedPaneGtk::GetTestingHandle() const { | |
136 return native_view(); | |
137 } | |
138 | |
139 //////////////////////////////////////////////////////////////////////////////// | |
140 // NativeTabbedPaneGtk, View implementation: | |
141 | |
142 FocusTraversable* NativeTabbedPaneGtk::GetFocusTraversable() { | |
143 return GetWidgetAt(GetSelectedTabIndex()); | |
144 } | |
145 | |
146 //////////////////////////////////////////////////////////////////////////////// | |
147 // NativeTabbedPaneGtk, private: | |
148 void NativeTabbedPaneGtk::DoAddTabAtIndex(int index, | |
149 const string16& title, | |
150 View* contents, | |
151 bool select_if_first_tab) { | |
152 int tab_count = GetTabCount(); | |
153 DCHECK(index <= tab_count); | |
154 | |
155 Widget* page_container = new Widget; | |
156 page_container->Init( | |
157 Widget::InitParams(Widget::InitParams::TYPE_CONTROL)); | |
158 page_container->SetContentsView(contents); | |
159 page_container->SetFocusTraversableParent(GetWidget()->GetFocusTraversable()); | |
160 page_container->SetFocusTraversableParentView(this); | |
161 page_container->Show(); | |
162 | |
163 if (!contents->background()) { | |
164 GtkStyle* window_style = | |
165 gtk_widget_get_style(page_container->GetNativeView()); | |
166 contents->set_background( | |
167 Background::CreateSolidBackground( | |
168 gfx::GdkColorToSkColor(window_style->bg[GTK_STATE_NORMAL]))); | |
169 } | |
170 | |
171 GtkWidget* page = page_container->GetNativeView(); | |
172 // increment ref count not to delete on remove below | |
173 g_object_ref(page); | |
174 // detach parent from the page so that we can add it to notebook | |
175 GtkWidget* parent = gtk_widget_get_parent(page); | |
176 gtk_container_remove(GTK_CONTAINER(parent), page); | |
177 | |
178 GtkWidget* label = gtk_label_new(UTF16ToUTF8(title).c_str()); | |
179 gtk_widget_show(label); | |
180 gtk_notebook_insert_page(GTK_NOTEBOOK(native_view()), | |
181 page, | |
182 label, | |
183 index); | |
184 g_object_unref(page); | |
185 | |
186 if (tab_count == 0 && select_if_first_tab) | |
187 gtk_notebook_set_current_page(GTK_NOTEBOOK(native_view()), 0); | |
188 | |
189 // Relayout the hierarchy, since the added tab might require more space. | |
190 if (GetWidget()) | |
191 GetWidget()->GetRootView()->Layout(); | |
192 } | |
193 | |
194 Widget* NativeTabbedPaneGtk::GetWidgetAt(int index) { | |
195 DCHECK(index <= GetTabCount()); | |
196 GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(native_view()), | |
197 index); | |
198 Widget* widget = Widget::GetWidgetForNativeView(page); | |
199 DCHECK(widget); | |
200 return widget; | |
201 } | |
202 | |
203 View* NativeTabbedPaneGtk::GetTabViewAt(int index) { | |
204 Widget* widget = GetWidgetAt(index); | |
205 DCHECK(widget); | |
206 DCHECK_EQ(1, widget->GetRootView()->child_count()); | |
207 return widget->GetRootView()->child_at(0); | |
208 } | |
209 | |
210 void NativeTabbedPaneGtk::OnSwitchPage(int selected_tab_index) { | |
211 TabbedPaneListener* listener = tabbed_pane_->listener(); | |
212 if (listener != NULL) | |
213 listener->TabSelectedAt(selected_tab_index); | |
214 } | |
215 | |
216 // static | |
217 void NativeTabbedPaneGtk::CallSwitchPage(GtkNotebook* widget, | |
218 GtkNotebookPage* page, | |
219 guint selected_tab_index, | |
220 NativeTabbedPaneGtk* tabbed_pane) { | |
221 tabbed_pane->OnSwitchPage(selected_tab_index); | |
222 } | |
223 | |
224 //////////////////////////////////////////////////////////////////////////////// | |
225 // NativeTabbedPaneWrapper, public: | |
226 | |
227 // static | |
228 NativeTabbedPaneWrapper* NativeTabbedPaneWrapper::CreateNativeWrapper( | |
229 TabbedPane* tabbed_pane) { | |
230 return new NativeTabbedPaneGtk(tabbed_pane); | |
231 } | |
232 | |
233 } // namespace views | |
OLD | NEW |