xref: /haiku/src/apps/webpositive/tabview/TabView.cpp (revision e85e399fd7b229b8bc92f28928a059876d7216d3)
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.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "TabView.h"
30 
31 #include <stdio.h>
32 
33 #include <Application.h>
34 #include <Bitmap.h>
35 #include <Button.h>
36 #include <CardLayout.h>
37 #include <ControlLook.h>
38 #include <GroupView.h>
39 #include <MenuBar.h>
40 #include <SpaceLayoutItem.h>
41 #include <Window.h>
42 
43 #include "TabContainerView.h"
44 
45 
46 // #pragma mark - TabView
47 
48 
49 TabView::TabView()
50 	:
51 	fContainerView(NULL),
52 	fLayoutItem(new TabLayoutItem(this)),
53 	fLabel()
54 {
55 }
56 
57 
58 TabView::~TabView()
59 {
60 	// The layout item is deleted for us by the layout which contains it.
61 	if (!fContainerView)
62 		delete fLayoutItem;
63 }
64 
65 
66 BSize
67 TabView::MinSize()
68 {
69 	BSize size(MaxSize());
70 	size.width = 60.0f;
71 	return size;
72 }
73 
74 
75 BSize
76 TabView::PreferredSize()
77 {
78 	return MaxSize();
79 }
80 
81 
82 BSize
83 TabView::MaxSize()
84 {
85 	float extra = be_control_look->DefaultLabelSpacing();
86 	float labelWidth = 300.0f;
87 	return BSize(labelWidth, _LabelHeight() + extra);
88 }
89 
90 
91 void
92 TabView::Draw(BRect updateRect)
93 {
94 	BRect frame(fLayoutItem->Frame());
95 	if (fIsFront) {
96 		// Extend the front tab outward left/right in order to merge
97 		// the frames of adjacent tabs.
98 		if (!fIsFirst)
99 			frame.left--;
100 		if (!fIsLast)
101 			frame.right++;
102 
103 		frame.bottom++;
104 	}
105 
106 	DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast,
107 		fIsFront);
108 
109 	if (fIsFront) {
110 		frame.top += 3.0f;
111 		if (!fIsFirst)
112 			frame.left++;
113 		if (!fIsLast)
114 			frame.right--;
115 	} else
116 		frame.top += 6.0f;
117 
118 	float spacing = be_control_look->DefaultLabelSpacing();
119 	frame.InsetBy(spacing, spacing / 2);
120 	DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast,
121 		fIsFront);
122 }
123 
124 
125 void
126 TabView::DrawBackground(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 	uint32 borders = BControlLook::B_TOP_BORDER
131 		| BControlLook::B_BOTTOM_BORDER;
132 
133 	if (isFirst)
134 		borders |= BControlLook::B_LEFT_BORDER;
135 	if (isLast)
136 		borders |= BControlLook::B_RIGHT_BORDER;
137 	if (isFront) {
138 		be_control_look->DrawActiveTab(owner, frame, updateRect, base,
139 			0, borders);
140 	} else {
141 		be_control_look->DrawInactiveTab(owner, frame, updateRect, base,
142 			0, borders);
143 	}
144 }
145 
146 
147 void
148 TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect,
149 	bool isFirst, bool isLast, bool isFront)
150 {
151 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
152 	be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect,
153 		base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE));
154 }
155 
156 
157 void
158 TabView::MouseDown(BPoint where, uint32 buttons)
159 {
160 	fContainerView->SelectTab(this);
161 }
162 
163 
164 void
165 TabView::MouseUp(BPoint where)
166 {
167 }
168 
169 
170 void
171 TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
172 {
173 }
174 
175 
176 void
177 TabView::SetIsFront(bool isFront)
178 {
179 	Update(fIsFirst, fIsLast, isFront);
180 }
181 
182 
183 bool
184 TabView::IsFront() const
185 {
186 	return fIsFront;
187 }
188 
189 
190 void
191 TabView::SetIsLast(bool isLast)
192 {
193 	Update(fIsFirst, isLast, fIsFront);
194 }
195 
196 
197 void
198 TabView::Update(bool isFirst, bool isLast, bool isFront)
199 {
200 	if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront)
201 		return;
202 	fIsFirst = isFirst;
203 	fIsLast = isLast;
204 	fIsFront = isFront;
205 
206 	fLayoutItem->InvalidateContainer();
207 }
208 
209 
210 void
211 TabView::SetContainerView(TabContainerView* containerView)
212 {
213 	fContainerView = containerView;
214 }
215 
216 
217 TabContainerView*
218 TabView::ContainerView() const
219 {
220 	return fContainerView;
221 }
222 
223 
224 BLayoutItem*
225 TabView::LayoutItem() const
226 {
227 	return fLayoutItem;
228 }
229 
230 
231 void
232 TabView::SetLabel(const char* label)
233 {
234 	if (fLabel == label)
235 		return;
236 	fLabel = label;
237 	fLayoutItem->InvalidateLayout();
238 }
239 
240 
241 const BString&
242 TabView::Label() const
243 {
244 	return fLabel;
245 }
246 
247 
248 BRect
249 TabView::Frame() const
250 {
251 	return fLayoutItem->Frame();
252 }
253 
254 
255 float
256 TabView::_LabelHeight() const
257 {
258 	font_height fontHeight;
259 	fContainerView->GetFontHeight(&fontHeight);
260 	return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
261 }
262 
263 
264 // #pragma mark - TabLayoutItem
265 
266 
267 TabLayoutItem::TabLayoutItem(TabView* parent)
268 	:
269 	fParent(parent),
270 	fVisible(true)
271 {
272 }
273 
274 
275 bool
276 TabLayoutItem::IsVisible()
277 {
278 	return fVisible;
279 }
280 
281 
282 void
283 TabLayoutItem::SetVisible(bool visible)
284 {
285 	if (fVisible == visible)
286 		return;
287 
288 	fVisible = visible;
289 
290 	InvalidateContainer();
291 	fParent->ContainerView()->InvalidateLayout();
292 }
293 
294 
295 BRect
296 TabLayoutItem::Frame()
297 {
298 	return fFrame;
299 }
300 
301 
302 void
303 TabLayoutItem::SetFrame(BRect frame)
304 {
305 	BRect dirty = fFrame;
306 	fFrame = frame;
307 	dirty = dirty | fFrame;
308 	InvalidateContainer(dirty);
309 }
310 
311 
312 BView*
313 TabLayoutItem::View()
314 {
315 	return NULL;
316 }
317 
318 
319 BSize
320 TabLayoutItem::BaseMinSize()
321 {
322 	return fParent->MinSize();
323 }
324 
325 
326 BSize
327 TabLayoutItem::BaseMaxSize()
328 {
329 	return fParent->MaxSize();
330 }
331 
332 
333 BSize
334 TabLayoutItem::BasePreferredSize()
335 {
336 	return fParent->PreferredSize();
337 }
338 
339 
340 BAlignment
341 TabLayoutItem::BaseAlignment()
342 {
343 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
344 }
345 
346 
347 TabView*
348 TabLayoutItem::Parent() const
349 {
350 	return fParent;
351 }
352 
353 
354 void
355 TabLayoutItem::InvalidateContainer()
356 {
357 	InvalidateContainer(Frame());
358 }
359 
360 
361 void
362 TabLayoutItem::InvalidateContainer(BRect frame)
363 {
364 	// Invalidate more than necessary, to help the TabContainerView
365 	// redraw the parts outside any tabs...
366 	frame.bottom++;
367 	frame.right++;
368 	fParent->ContainerView()->Invalidate(frame);
369 }
370