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