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