Box.cpp revision ef5fcc06377af577dd52e0aad83ad0087d26099e
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	BRect r;
247
248	if(fBounds.right < bounds.right)
249	{
250		r.left = fBounds.right;
251		r.top = 0;
252		r.right = bounds.right;
253
254		if(fBounds.bottom < bounds.bottom)
255			r.bottom = bounds.bottom;
256		else
257			r.bottom = fBounds.bottom;
258
259		Invalidate(r);
260	}
261
262	if(fBounds.bottom < bounds.bottom)
263	{
264		r.left = 0;
265		r.top = fBounds.bottom;
266		r.right = bounds.right;
267		r.bottom = bounds.bottom;
268
269		Invalidate(r);
270	}
271
272	fBounds.right = bounds.right;
273	fBounds.bottom = bounds.bottom;
274}
275
276
277void
278BBox::MessageReceived(BMessage *message)
279{
280	BView::MessageReceived(message);
281}
282
283
284void
285BBox::MouseDown(BPoint point)
286{
287	BView::MouseDown(point);
288}
289
290
291void
292BBox::MouseUp(BPoint point)
293{
294	BView::MouseUp(point);
295}
296
297
298void
299BBox::WindowActivated(bool active)
300{
301	BView::WindowActivated(active);
302}
303
304
305void
306BBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
307{
308	BView::MouseMoved(point, transit, message);
309}
310
311
312void
313BBox::FrameMoved(BPoint newLocation)
314{
315	BView::FrameMoved(newLocation);
316}
317
318
319BHandler *
320BBox::ResolveSpecifier(BMessage *message, int32 index,
321								 BMessage *specifier, int32 what,
322								 const char *property)
323{
324	return BView::ResolveSpecifier(message, index, specifier, what, property);
325}
326
327
328void
329BBox::ResizeToPreferred()
330{
331	BView::ResizeToPreferred();
332}
333
334
335void
336BBox::GetPreferredSize(float *width, float *height)
337{
338/*	BRect rect(0,0,99,99);
339
340	if (Parent())
341	{
342		rect = Parent()->Bounds();
343		rect.InsetBy(10,10);
344	}
345
346	*width = rect.Width();
347	*height = rect.Height();*/
348
349	BView::GetPreferredSize(width, height);
350}
351
352
353void
354BBox::MakeFocus(bool focused)
355{
356	BView::MakeFocus(focused);
357}
358
359
360status_t
361BBox::GetSupportedSuites(BMessage *message)
362{
363	return BView::GetSupportedSuites(message);
364}
365
366
367status_t
368BBox::Perform(perform_code d, void *arg)
369{
370	return BView::Perform(d, arg);
371}
372
373
374void BBox::_ReservedBox1() {}
375void BBox::_ReservedBox2() {}
376
377
378BBox &
379BBox::operator=(const BBox &)
380{
381	return *this;
382}
383
384
385void
386BBox::InitObject(BMessage *data)
387{
388	fLabel = NULL;
389	fBounds = Bounds();
390	fLabelView = NULL;
391
392	int32 flags = 0;
393
394	BFont font(be_bold_font);
395
396	if (!data || !data->HasString("_fname"))
397		flags = B_FONT_FAMILY_AND_STYLE;
398
399	if (!data || !data->HasFloat("_fflt"))
400		flags |= B_FONT_SIZE;
401
402	if (flags != 0)
403		SetFont(&font, flags);
404}
405
406
407void
408BBox::DrawPlain()
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(4);
416		AddLine(BPoint(r.left, r.bottom),
417				BPoint(r.left, r.top), light);
418		AddLine(BPoint(r.left + 1.0f, r.top),
419				BPoint(r.right, r.top), light);
420		AddLine(BPoint(r.left + 1.0f, r.bottom),
421				BPoint(r.right, r.bottom), shadow);
422		AddLine(BPoint(r.right, r.bottom - 1.0f),
423				BPoint(r.right, r.top + 1.0f), shadow);
424	EndLineArray();
425}
426
427
428void
429BBox::DrawFancy()
430{
431	BRect r = fBounds;
432
433	rgb_color light = tint_color(ViewColor(), B_LIGHTEN_MAX_TINT);
434	rgb_color shadow = tint_color(ViewColor(), B_DARKEN_3_TINT);
435
436	BeginLineArray(8);
437		AddLine(BPoint(r.left, r.bottom),
438				BPoint(r.left, r.top), shadow);
439		AddLine(BPoint(r.left + 1.0f, r.top),
440				BPoint(r.right, r.top), shadow);
441		AddLine(BPoint(r.left + 1.0f, r.bottom),
442				BPoint(r.right, r.bottom), light);
443		AddLine(BPoint(r.right, r.bottom - 1.0f),
444				BPoint(r.right, r.top + 1.0f), light);
445
446		r.InsetBy(1.0, 1.0);
447
448		AddLine(BPoint(r.left, r.bottom),
449				BPoint(r.left, r.top), light);
450		AddLine(BPoint(r.left + 1.0f, r.top),
451				BPoint(r.right, r.top), light);
452		AddLine(BPoint(r.left + 1.0f, r.bottom),
453				BPoint(r.right, r.bottom), shadow);
454		AddLine(BPoint(r.right, r.bottom - 1.0f),
455				BPoint(r.right, r.top + 1.0f), shadow);
456	EndLineArray();
457}
458
459
460void
461BBox::ClearAnyLabel()
462{
463	fBounds.top = 0;
464
465	if (fLabel) {
466		free(fLabel);
467		fLabel = NULL;
468	} else if (fLabelView) {
469		fLabelView->RemoveSelf();
470		delete fLabelView;
471		fLabelView = NULL;
472	}
473}
474