xref: /haiku/src/apps/webpositive/tabview/TabView.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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 <Window.h>
20 
21 #include "TabContainerView.h"
22 
23 
24 // #pragma mark - TabView
25 
26 
27 TabView::TabView()
28 	:
29 	fContainerView(NULL),
30 	fLayoutItem(new TabLayoutItem(this)),
31 	fLabel()
32 {
33 }
34 
35 
36 TabView::~TabView()
37 {
38 	// The layout item is deleted for us by the layout which contains it.
39 	if (!fContainerView)
40 		delete fLayoutItem;
41 }
42 
43 
44 BSize
45 TabView::MinSize()
46 {
47 	BSize size(MaxSize());
48 	size.width = 60.0f;
49 	return size;
50 }
51 
52 
53 BSize
54 TabView::PreferredSize()
55 {
56 	return MaxSize();
57 }
58 
59 
60 BSize
61 TabView::MaxSize()
62 {
63 	float extra = be_control_look->DefaultLabelSpacing();
64 	float labelWidth = 300.0f;
65 	return BSize(labelWidth, _LabelHeight() + extra);
66 }
67 
68 
69 void
70 TabView::Draw(BRect updateRect)
71 {
72 	BRect frame(fLayoutItem->Frame());
73 	if (fIsFront) {
74 		// Extend the front tab outward left/right in order to merge
75 		// the frames of adjacent tabs.
76 		if (!fIsFirst)
77 			frame.left--;
78 		if (!fIsLast)
79 			frame.right++;
80 	}
81 	frame.bottom++;
82 
83 	DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast,
84 		fIsFront);
85 
86 	if (fIsFront) {
87 		frame.top += 3.0f;
88 		if (!fIsFirst)
89 			frame.left++;
90 		if (!fIsLast)
91 			frame.right--;
92 	} else
93 		frame.top += 6.0f;
94 
95 	float spacing = be_control_look->DefaultLabelSpacing();
96 	frame.InsetBy(spacing, spacing / 2);
97 	DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast,
98 		fIsFront);
99 }
100 
101 
102 void
103 TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect,
104 	bool isFirst, bool isLast, bool isFront)
105 {
106 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
107 	uint32 borders = BControlLook::B_TOP_BORDER
108 		| BControlLook::B_BOTTOM_BORDER;
109 
110 	if (isFirst)
111 		borders |= BControlLook::B_LEFT_BORDER;
112 	if (isLast)
113 		borders |= BControlLook::B_RIGHT_BORDER;
114 	if (isFront) {
115 		be_control_look->DrawActiveTab(owner, frame, updateRect, base,
116 			0, borders);
117 	} else {
118 		be_control_look->DrawInactiveTab(owner, frame, updateRect, base,
119 			0, borders);
120 	}
121 }
122 
123 
124 void
125 TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect,
126 	bool isFirst, bool isLast, bool isFront)
127 {
128 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
129 	be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect,
130 		base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE));
131 }
132 
133 
134 void
135 TabView::MouseDown(BPoint where, uint32 buttons)
136 {
137 	fContainerView->SelectTab(this);
138 }
139 
140 
141 void
142 TabView::MouseUp(BPoint where)
143 {
144 }
145 
146 
147 void
148 TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
149 {
150 }
151 
152 
153 void
154 TabView::SetIsFront(bool isFront)
155 {
156 	Update(fIsFirst, fIsLast, isFront);
157 }
158 
159 
160 bool
161 TabView::IsFront() const
162 {
163 	return fIsFront;
164 }
165 
166 
167 void
168 TabView::SetIsLast(bool isLast)
169 {
170 	Update(fIsFirst, isLast, fIsFront);
171 }
172 
173 
174 void
175 TabView::Update(bool isFirst, bool isLast, bool isFront)
176 {
177 	if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront)
178 		return;
179 	fIsFirst = isFirst;
180 	fIsLast = isLast;
181 	fIsFront = isFront;
182 
183 	fLayoutItem->InvalidateContainer();
184 }
185 
186 
187 void
188 TabView::SetContainerView(TabContainerView* containerView)
189 {
190 	fContainerView = containerView;
191 }
192 
193 
194 TabContainerView*
195 TabView::ContainerView() const
196 {
197 	return fContainerView;
198 }
199 
200 
201 BLayoutItem*
202 TabView::LayoutItem() const
203 {
204 	return fLayoutItem;
205 }
206 
207 
208 void
209 TabView::SetLabel(const char* label)
210 {
211 	if (fLabel == label)
212 		return;
213 	fLabel = label;
214 	fLayoutItem->InvalidateLayout();
215 }
216 
217 
218 const BString&
219 TabView::Label() const
220 {
221 	return fLabel;
222 }
223 
224 
225 BRect
226 TabView::Frame() const
227 {
228 	return fLayoutItem->Frame();
229 }
230 
231 
232 float
233 TabView::_LabelHeight() const
234 {
235 	font_height fontHeight;
236 	fContainerView->GetFontHeight(&fontHeight);
237 	return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
238 }
239 
240 
241 // #pragma mark - TabLayoutItem
242 
243 
244 TabLayoutItem::TabLayoutItem(TabView* parent)
245 	:
246 	fParent(parent),
247 	fVisible(true)
248 {
249 }
250 
251 
252 bool
253 TabLayoutItem::IsVisible()
254 {
255 	return fVisible;
256 }
257 
258 
259 void
260 TabLayoutItem::SetVisible(bool visible)
261 {
262 	if (fVisible == visible)
263 		return;
264 
265 	fVisible = visible;
266 
267 	InvalidateContainer();
268 	fParent->ContainerView()->InvalidateLayout();
269 }
270 
271 
272 BRect
273 TabLayoutItem::Frame()
274 {
275 	return fFrame;
276 }
277 
278 
279 void
280 TabLayoutItem::SetFrame(BRect frame)
281 {
282 	BRect dirty = fFrame;
283 	fFrame = frame;
284 	dirty = dirty | fFrame;
285 	InvalidateContainer(dirty);
286 }
287 
288 
289 BView*
290 TabLayoutItem::View()
291 {
292 	return NULL;
293 }
294 
295 
296 BSize
297 TabLayoutItem::BaseMinSize()
298 {
299 	return fParent->MinSize();
300 }
301 
302 
303 BSize
304 TabLayoutItem::BaseMaxSize()
305 {
306 	return fParent->MaxSize();
307 }
308 
309 
310 BSize
311 TabLayoutItem::BasePreferredSize()
312 {
313 	return fParent->PreferredSize();
314 }
315 
316 
317 BAlignment
318 TabLayoutItem::BaseAlignment()
319 {
320 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
321 }
322 
323 
324 TabView*
325 TabLayoutItem::Parent() const
326 {
327 	return fParent;
328 }
329 
330 
331 void
332 TabLayoutItem::InvalidateContainer()
333 {
334 	InvalidateContainer(Frame());
335 }
336 
337 
338 void
339 TabLayoutItem::InvalidateContainer(BRect frame)
340 {
341 	// Invalidate more than necessary, to help the TabContainerView
342 	// redraw the parts outside any tabs...
343 	frame.bottom++;
344 	frame.right++;
345 	fParent->ContainerView()->Invalidate(frame);
346 }
347