Box.cpp revision 491e6111d447aded7b72e9ed85bafad024f2cc18
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
34BBox::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
46BBox::~BBox()
47{
48	ClearAnyLabel();
49}
50
51
52BBox::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
75BArchivable *
76BBox::Instantiate(BMessage *archive)
77{
78	if (validate_instantiation(archive, "BBox"))
79		return new BBox(archive);
80	else
81		return NULL;
82}
83
84
85status_t
86BBox::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
103void
104BBox::SetBorder(border_style border)
105{
106	fStyle = border;
107
108	if (Window() != NULL && LockLooper()) {
109		Invalidate();
110		UnlockLooper();
111	}
112}
113
114
115border_style
116BBox::Border() const
117{
118	return fStyle;
119}
120
121
122void
123BBox::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
143status_t
144BBox::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
166const char *
167BBox::Label() const
168{
169	return fLabel;
170}
171
172
173BView *
174BBox::LabelView() const
175{
176	return fLabelView;
177}
178
179
180void
181BBox::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
212void BBox::AttachedToWindow()
213{
214	if (Parent()) {
215		SetViewColor(Parent()->ViewColor());
216		SetLowColor(Parent()->ViewColor());
217	}
218}
219
220
221void
222BBox::DetachedFromWindow()
223{
224	BView::DetachedFromWindow();
225}
226
227
228void
229BBox::AllAttached()
230{
231	BView::AllAttached();
232}
233
234
235void
236BBox::AllDetached()
237{
238	BView::AllDetached();
239}
240
241
242void
243BBox::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
256void
257BBox::MessageReceived(BMessage *message)
258{
259	BView::MessageReceived(message);
260}
261
262
263void
264BBox::MouseDown(BPoint point)
265{
266	BView::MouseDown(point);
267}
268
269
270void
271BBox::MouseUp(BPoint point)
272{
273	BView::MouseUp(point);
274}
275
276
277void
278BBox::WindowActivated(bool active)
279{
280	BView::WindowActivated(active);
281}
282
283
284void
285BBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
286{
287	BView::MouseMoved(point, transit, message);
288}
289
290
291void
292BBox::FrameMoved(BPoint newLocation)
293{
294	BView::FrameMoved(newLocation);
295}
296
297
298BHandler *
299BBox::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
307void
308BBox::ResizeToPreferred()
309{
310	BView::ResizeToPreferred();
311}
312
313
314void
315BBox::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
332void
333BBox::MakeFocus(bool focused)
334{
335	BView::MakeFocus(focused);
336}
337
338
339status_t
340BBox::GetSupportedSuites(BMessage *message)
341{
342	return BView::GetSupportedSuites(message);
343}
344
345
346status_t
347BBox::Perform(perform_code d, void *arg)
348{
349	return BView::Perform(d, arg);
350}
351
352
353void BBox::_ReservedBox1() {}
354void BBox::_ReservedBox2() {}
355
356
357BBox &
358BBox::operator=(const BBox &)
359{
360	return *this;
361}
362
363
364void
365BBox::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
386void
387BBox::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
407void
408BBox::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
439void
440BBox::ClearAnyLabel()
441{
442	if (fLabel) {
443		free(fLabel);
444		fLabel = NULL;
445	} else if (fLabelView) {
446		fLabelView->RemoveSelf();
447		delete fLabelView;
448		fLabelView = NULL;
449	}
450}
451