xref: /haiku/src/apps/webpositive/tabview/TabView.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
1 /*
2  * Copyright (C) 2010 Rene Gollent <rene@gollent.com>
3  * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
4  *
5  * All rights reserved. Distributed under the terms of the MIT License.
6  */
7 
8 #include "TabView.h"
9 
10 #include <stdio.h>
11 
12 #include <Application.h>
13 #include <Bitmap.h>
14 #include <Button.h>
15 #include <CardLayout.h>
16 #include <ControlLook.h>
17 #include <GroupView.h>
18 #include <SpaceLayoutItem.h>
19 #include <TabView.h>
20 #include <Window.h>
21 
22 #include "TabContainerView.h"
23 
24 
25 // #pragma mark - TabView
26 
27 
28 TabView::TabView()
29 	:
30 	fContainerView(NULL),
31 	fLayoutItem(new TabLayoutItem(this)),
32 	fLabel()
33 {
34 }
35 
36 
37 TabView::~TabView()
38 {
39 	// The layout item is deleted for us by the layout which contains it.
40 	if (fContainerView == NULL)
41 		delete fLayoutItem;
42 }
43 
44 
45 BSize
46 TabView::MinSize()
47 {
48 	BSize size(MaxSize());
49 	size.width = 60.0f;
50 	return size;
51 }
52 
53 
54 BSize
55 TabView::PreferredSize()
56 {
57 	return MaxSize();
58 }
59 
60 
61 BSize
62 TabView::MaxSize()
63 {
64 	float extra = be_control_look->DefaultLabelSpacing();
65 	float labelWidth = 300.0f;
66 	return BSize(labelWidth, _LabelHeight() + extra);
67 }
68 
69 
70 void
71 TabView::Draw(BRect updateRect)
72 {
73 	BRect frame(fLayoutItem->Frame());
74 	frame.right++;
75 	frame.bottom++;
76 
77 	int32 index = fContainerView->IndexOf(this);
78 
79 	// make room for tail of last tab
80 	bool isLast = index == fContainerView->LastTabIndex();
81 	if (isLast)
82 		frame.right -= 2;
83 
84 	DrawBackground(fContainerView, frame, updateRect);
85 
86 	bool isFront = index == fContainerView->SelectedTabIndex();
87 	if (isFront)
88 		frame.top += 3.0f;
89 	else
90 		frame.top += 6.0f;
91 
92 	float spacing = be_control_look->DefaultLabelSpacing();
93 	frame.InsetBy(spacing, spacing / 2);
94 	DrawContents(fContainerView, frame, updateRect);
95 }
96 
97 
98 void
99 TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect)
100 {
101 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
102 	uint32 flags = 0;
103 	uint32 borders = BControlLook::B_TOP_BORDER
104 		| BControlLook::B_BOTTOM_BORDER;
105 
106 	int32 index = fContainerView->IndexOf(this);
107 	int32 selected = fContainerView->SelectedTabIndex();
108 	int32 first = fContainerView->FirstTabIndex();
109 	int32 last = fContainerView->LastTabIndex();
110 
111 	if (index == selected) {
112 		be_control_look->DrawActiveTab(owner, frame, updateRect, base, flags,
113 			borders, BControlLook::B_TOP_BORDER, index, selected, first, last);
114 	} else {
115 		be_control_look->DrawInactiveTab(owner, frame, updateRect, base, flags,
116 			borders, BControlLook::B_TOP_BORDER, index, selected, first, last);
117 	}
118 }
119 
120 
121 void
122 TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect)
123 {
124 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
125 	be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect,
126 		base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE));
127 }
128 
129 
130 void
131 TabView::MouseDown(BPoint where, uint32 buttons)
132 {
133 	fContainerView->SelectTab(this);
134 }
135 
136 
137 void
138 TabView::MouseUp(BPoint where)
139 {
140 }
141 
142 
143 void
144 TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
145 {
146 }
147 
148 
149 void
150 TabView::Update()
151 {
152 	fLayoutItem->InvalidateContainer();
153 }
154 
155 
156 void
157 TabView::SetContainerView(TabContainerView* containerView)
158 {
159 	fContainerView = containerView;
160 }
161 
162 
163 TabContainerView*
164 TabView::ContainerView() const
165 {
166 	return fContainerView;
167 }
168 
169 
170 BLayoutItem*
171 TabView::LayoutItem() const
172 {
173 	return fLayoutItem;
174 }
175 
176 
177 void
178 TabView::SetLabel(const char* label)
179 {
180 	if (fLabel == label)
181 		return;
182 
183 	fLabel = label;
184 	fLayoutItem->InvalidateLayout();
185 }
186 
187 
188 const BString&
189 TabView::Label() const
190 {
191 	return fLabel;
192 }
193 
194 
195 BRect
196 TabView::Frame() const
197 {
198 	return fLayoutItem->Frame();
199 }
200 
201 
202 float
203 TabView::_LabelHeight() const
204 {
205 	font_height fontHeight;
206 	fContainerView->GetFontHeight(&fontHeight);
207 	return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
208 }
209 
210 
211 // #pragma mark - TabLayoutItem
212 
213 
214 TabLayoutItem::TabLayoutItem(TabView* parent)
215 	:
216 	fParent(parent),
217 	fVisible(true)
218 {
219 }
220 
221 
222 bool
223 TabLayoutItem::IsVisible()
224 {
225 	return fVisible;
226 }
227 
228 
229 void
230 TabLayoutItem::SetVisible(bool visible)
231 {
232 	if (fVisible == visible)
233 		return;
234 
235 	fVisible = visible;
236 
237 	InvalidateContainer();
238 	fParent->ContainerView()->InvalidateLayout();
239 }
240 
241 
242 BRect
243 TabLayoutItem::Frame()
244 {
245 	return fFrame;
246 }
247 
248 
249 void
250 TabLayoutItem::SetFrame(BRect frame)
251 {
252 	BRect dirty = fFrame;
253 	fFrame = frame;
254 	dirty = dirty | fFrame;
255 	InvalidateContainer(dirty);
256 }
257 
258 
259 BView*
260 TabLayoutItem::View()
261 {
262 	return NULL;
263 }
264 
265 
266 BSize
267 TabLayoutItem::BaseMinSize()
268 {
269 	return fParent->MinSize();
270 }
271 
272 
273 BSize
274 TabLayoutItem::BaseMaxSize()
275 {
276 	return fParent->MaxSize();
277 }
278 
279 
280 BSize
281 TabLayoutItem::BasePreferredSize()
282 {
283 	return fParent->PreferredSize();
284 }
285 
286 
287 BAlignment
288 TabLayoutItem::BaseAlignment()
289 {
290 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
291 }
292 
293 
294 TabView*
295 TabLayoutItem::Parent() const
296 {
297 	return fParent;
298 }
299 
300 
301 void
302 TabLayoutItem::InvalidateContainer()
303 {
304 	InvalidateContainer(Frame());
305 }
306 
307 
308 void
309 TabLayoutItem::InvalidateContainer(BRect frame)
310 {
311 	// Invalidate more than necessary, to help the TabContainerView
312 	// redraw the parts outside any tabs... need 2px
313 	frame.bottom += 2;
314 	frame.right += 2;
315 	fParent->ContainerView()->Invalidate(frame);
316 }
317