xref: /haiku/src/kits/interface/Box.cpp (revision aff60bb217827097c13d643275fdf1f1c66e7f17)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2005, Haiku, Inc.
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Box.cpp
23 //	Author:			Marc Flerackers (mflerackers@androme.be)
24 //	Description:	BBox objects group views together and draw a border
25 //                  around them.
26 //------------------------------------------------------------------------------
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <Box.h>
31 #include <Message.h>
32 
33 
34 BBox::BBox(BRect frame, const char *name, uint32 resizingMode, uint32 flags,
35 		   border_style border)
36 	:	BView(frame, name, resizingMode, flags | B_FRAME_EVENTS),
37 		fStyle(border)
38 {
39 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
40 	SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
41 
42 	InitObject();
43 }
44 
45 
46 BBox::~BBox()
47 {
48 	ClearAnyLabel();
49 }
50 
51 
52 BBox::BBox(BMessage *archive)
53 	:	BView(archive)
54 {
55 	InitObject(archive);
56 
57 	const char *string;
58 
59 	if (archive->FindString("_label", &string) == B_OK)
60 		SetLabel(string);
61 
62 	bool aBool;
63 	int32 anInt32;
64 
65 	if (archive->FindBool("_style", &aBool) == B_OK)
66 		fStyle = aBool ? B_FANCY_BORDER : B_PLAIN_BORDER;
67 	else if (archive->FindInt32("_style", &anInt32) == B_OK)
68 		fStyle = (border_style)anInt32;
69 
70 	if (archive->FindBool("_lblview", &aBool) == B_OK)
71 		fLabelView = ChildAt(0);
72 }
73 
74 
75 BArchivable *
76 BBox::Instantiate(BMessage *archive)
77 {
78 	if (validate_instantiation(archive, "BBox"))
79 		return new BBox(archive);
80 	else
81 		return NULL;
82 }
83 
84 
85 status_t
86 BBox::Archive(BMessage *archive, bool deep) const
87 {
88 	BView::Archive(archive, deep);
89 
90 	if (fLabel)
91 		 archive->AddString("_label", fLabel);
92 
93 	if (fLabelView)
94 		 archive->AddBool("_lblview", true);
95 
96 	if (fStyle != B_FANCY_BORDER)
97 		archive->AddInt32("_style", fStyle);
98 
99 	return B_OK;
100 }
101 
102 
103 void
104 BBox::SetBorder(border_style border)
105 {
106 	fStyle = border;
107 
108 	if (Window() != NULL && LockLooper()) {
109 		Invalidate();
110 		UnlockLooper();
111 	}
112 }
113 
114 
115 border_style
116 BBox::Border() const
117 {
118 	return fStyle;
119 }
120 
121 
122 void
123 BBox::SetLabel(const char *string)
124 {
125 	ClearAnyLabel();
126 
127 	if (string) {
128 		// Update fBounds
129 		fBounds = Bounds();
130 		font_height fh;
131 		GetFontHeight(&fh);
132 
133 		fBounds.top = (float)ceil((fh.ascent + fh.descent) / 2.0f);
134 
135 		fLabel = strdup(string);
136 	}
137 
138 	if (Window())
139 		Invalidate();
140 }
141 
142 
143 status_t
144 BBox::SetLabel(BView *viewLabel)
145 {
146 	ClearAnyLabel();
147 
148 	if (viewLabel) {
149 		// Update fBounds
150 		fBounds = Bounds();
151 
152 		fBounds.top = (float)ceil(viewLabel->Bounds().Height() / 2.0f);
153 
154 		fLabelView = viewLabel;
155 		fLabelView->MoveTo(10.0f, 0.0f);
156 		AddChild(fLabelView, ChildAt(0));
157 	}
158 
159 	if (Window())
160 		Invalidate();
161 
162 	return B_OK;
163 }
164 
165 
166 const char *
167 BBox::Label() const
168 {
169 	return fLabel;
170 }
171 
172 
173 BView *
174 BBox::LabelView() const
175 {
176 	return fLabelView;
177 }
178 
179 
180 void
181 BBox::Draw(BRect updateRect)
182 {
183 	switch (fStyle) {
184 		case B_FANCY_BORDER:
185 			DrawFancy();
186 			break;
187 
188 		case B_PLAIN_BORDER:
189 			DrawPlain();
190 			break;
191 
192 		default:
193 			break;
194 	}
195 
196 	if (fLabel) {
197 		font_height fh;
198 		GetFontHeight(&fh);
199 
200 		SetHighColor(ViewColor());
201 
202 		FillRect(BRect(6.0f, 1.0f, 12.0f + StringWidth(fLabel),
203 			(float)ceil(fh.ascent + fh.descent))/*, B_SOLID_LOW*/);
204 
205 		SetHighColor(0, 0, 0);
206 		DrawString(fLabel, BPoint(10.0f, (float)ceil(fh.ascent - fh.descent)
207 			+ 1.0f));
208 	}
209 }
210 
211 
212 void BBox::AttachedToWindow()
213 {
214 	if (Parent()) {
215 		SetViewColor(Parent()->ViewColor());
216 		SetLowColor(Parent()->ViewColor());
217 	}
218 }
219 
220 
221 void
222 BBox::DetachedFromWindow()
223 {
224 	BView::DetachedFromWindow();
225 }
226 
227 
228 void
229 BBox::AllAttached()
230 {
231 	BView::AllAttached();
232 }
233 
234 
235 void
236 BBox::AllDetached()
237 {
238 	BView::AllDetached();
239 }
240 
241 
242 void
243 BBox::FrameResized(float width, float height)
244 {
245 	BRect bounds(Bounds());
246 
247 	// TODO: only invalidate the part that really need redrawing!
248 
249 	fBounds.right = bounds.right;
250 	fBounds.bottom = bounds.bottom;
251 
252 	Invalidate();
253 }
254 
255 
256 void
257 BBox::MessageReceived(BMessage *message)
258 {
259 	BView::MessageReceived(message);
260 }
261 
262 
263 void
264 BBox::MouseDown(BPoint point)
265 {
266 	BView::MouseDown(point);
267 }
268 
269 
270 void
271 BBox::MouseUp(BPoint point)
272 {
273 	BView::MouseUp(point);
274 }
275 
276 
277 void
278 BBox::WindowActivated(bool active)
279 {
280 	BView::WindowActivated(active);
281 }
282 
283 
284 void
285 BBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
286 {
287 	BView::MouseMoved(point, transit, message);
288 }
289 
290 
291 void
292 BBox::FrameMoved(BPoint newLocation)
293 {
294 	BView::FrameMoved(newLocation);
295 }
296 
297 
298 BHandler *
299 BBox::ResolveSpecifier(BMessage *message, int32 index,
300 								 BMessage *specifier, int32 what,
301 								 const char *property)
302 {
303 	return BView::ResolveSpecifier(message, index, specifier, what, property);
304 }
305 
306 
307 void
308 BBox::ResizeToPreferred()
309 {
310 	BView::ResizeToPreferred();
311 }
312 
313 
314 void
315 BBox::GetPreferredSize(float *width, float *height)
316 {
317 /*	BRect rect(0,0,99,99);
318 
319 	if (Parent())
320 	{
321 		rect = Parent()->Bounds();
322 		rect.InsetBy(10,10);
323 	}
324 
325 	*width = rect.Width();
326 	*height = rect.Height();*/
327 
328 	BView::GetPreferredSize(width, height);
329 }
330 
331 
332 void
333 BBox::MakeFocus(bool focused)
334 {
335 	BView::MakeFocus(focused);
336 }
337 
338 
339 status_t
340 BBox::GetSupportedSuites(BMessage *message)
341 {
342 	return BView::GetSupportedSuites(message);
343 }
344 
345 
346 status_t
347 BBox::Perform(perform_code d, void *arg)
348 {
349 	return BView::Perform(d, arg);
350 }
351 
352 
353 void BBox::_ReservedBox1() {}
354 void BBox::_ReservedBox2() {}
355 
356 
357 BBox &
358 BBox::operator=(const BBox &)
359 {
360 	return *this;
361 }
362 
363 
364 void
365 BBox::InitObject(BMessage *data)
366 {
367 	fLabel = NULL;
368 	fBounds = Bounds();
369 	fLabelView = NULL;
370 
371 	int32 flags = 0;
372 
373 	BFont font(be_bold_font);
374 
375 	if (!data || !data->HasString("_fname"))
376 		flags = B_FONT_FAMILY_AND_STYLE;
377 
378 	if (!data || !data->HasFloat("_fflt"))
379 		flags |= B_FONT_SIZE;
380 
381 	if (flags != 0)
382 		SetFont(&font, flags);
383 }
384 
385 
386 void
387 BBox::DrawPlain()
388 {
389 	BRect r = fBounds;
390 
391 	rgb_color light = tint_color(ViewColor(), B_LIGHTEN_MAX_TINT);
392 	rgb_color shadow = tint_color(ViewColor(), B_DARKEN_3_TINT);
393 
394 	BeginLineArray(4);
395 		AddLine(BPoint(r.left, r.bottom),
396 				BPoint(r.left, r.top), light);
397 		AddLine(BPoint(r.left + 1.0f, r.top),
398 				BPoint(r.right, r.top), light);
399 		AddLine(BPoint(r.left + 1.0f, r.bottom),
400 				BPoint(r.right, r.bottom), shadow);
401 		AddLine(BPoint(r.right, r.bottom - 1.0f),
402 				BPoint(r.right, r.top + 1.0f), shadow);
403 	EndLineArray();
404 }
405 
406 
407 void
408 BBox::DrawFancy()
409 {
410 	BRect r = fBounds;
411 
412 	rgb_color light = tint_color(ViewColor(), B_LIGHTEN_MAX_TINT);
413 	rgb_color shadow = tint_color(ViewColor(), B_DARKEN_3_TINT);
414 
415 	BeginLineArray(8);
416 		AddLine(BPoint(r.left, r.bottom),
417 				BPoint(r.left, r.top), shadow);
418 		AddLine(BPoint(r.left + 1.0f, r.top),
419 				BPoint(r.right, r.top), shadow);
420 		AddLine(BPoint(r.left + 1.0f, r.bottom),
421 				BPoint(r.right, r.bottom), light);
422 		AddLine(BPoint(r.right, r.bottom - 1.0f),
423 				BPoint(r.right, r.top + 1.0f), light);
424 
425 		r.InsetBy(1.0, 1.0);
426 
427 		AddLine(BPoint(r.left, r.bottom),
428 				BPoint(r.left, r.top), light);
429 		AddLine(BPoint(r.left + 1.0f, r.top),
430 				BPoint(r.right, r.top), light);
431 		AddLine(BPoint(r.left + 1.0f, r.bottom),
432 				BPoint(r.right, r.bottom), shadow);
433 		AddLine(BPoint(r.right, r.bottom - 1.0f),
434 				BPoint(r.right, r.top + 1.0f), shadow);
435 	EndLineArray();
436 }
437 
438 
439 void
440 BBox::ClearAnyLabel()
441 {
442 	fBounds.top = 0;
443 
444 	if (fLabel) {
445 		free(fLabel);
446 		fLabel = NULL;
447 	} else if (fLabelView) {
448 		fLabelView->RemoveSelf();
449 		delete fLabelView;
450 		fLabelView = NULL;
451 	}
452 }
453