1/*
2 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * Copyright 2015, Haiku, Inc.
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6
7#include <SplitView.h>
8
9#include <stdio.h>
10
11#include <Archivable.h>
12#include <ControlLook.h>
13#include <Cursor.h>
14
15#include "SplitLayout.h"
16
17
18BSplitView::BSplitView(orientation orientation, float spacing)
19	:
20	BView(NULL,
21		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INVALIDATE_AFTER_LAYOUT,
22		fSplitLayout = new BSplitLayout(orientation, spacing))
23{
24}
25
26
27BSplitView::BSplitView(BMessage* from)
28	:
29	BView(BUnarchiver::PrepareArchive(from)),
30	fSplitLayout(NULL)
31{
32	BUnarchiver(from).Finish();
33}
34
35
36BSplitView::~BSplitView()
37{
38}
39
40
41void
42BSplitView::SetInsets(float left, float top, float right, float bottom)
43{
44	left = BControlLook::ComposeSpacing(left);
45	top = BControlLook::ComposeSpacing(top);
46	right = BControlLook::ComposeSpacing(right);
47	bottom = BControlLook::ComposeSpacing(bottom);
48
49	fSplitLayout->SetInsets(left, top, right, bottom);
50}
51
52
53void
54BSplitView::SetInsets(float horizontal, float vertical)
55{
56	horizontal = BControlLook::ComposeSpacing(horizontal);
57	vertical = BControlLook::ComposeSpacing(vertical);
58	fSplitLayout->SetInsets(horizontal, vertical, horizontal, vertical);
59}
60
61
62void
63BSplitView::SetInsets(float insets)
64{
65	insets = BControlLook::ComposeSpacing(insets);
66	fSplitLayout->SetInsets(insets, insets, insets, insets);
67}
68
69
70void
71BSplitView::GetInsets(float* left, float* top, float* right,
72	float* bottom) const
73{
74	fSplitLayout->GetInsets(left, top, right, bottom);
75}
76
77
78float
79BSplitView::Spacing() const
80{
81	return fSplitLayout->Spacing();
82}
83
84
85void
86BSplitView::SetSpacing(float spacing)
87{
88	fSplitLayout->SetSpacing(spacing);
89}
90
91
92orientation
93BSplitView::Orientation() const
94{
95	return fSplitLayout->Orientation();
96}
97
98
99void
100BSplitView::SetOrientation(orientation orientation)
101{
102	fSplitLayout->SetOrientation(orientation);
103}
104
105
106float
107BSplitView::SplitterSize() const
108{
109	return fSplitLayout->SplitterSize();
110}
111
112
113void
114BSplitView::SetSplitterSize(float size)
115{
116	fSplitLayout->SetSplitterSize(size);
117}
118
119
120int32
121BSplitView::CountItems() const
122{
123	return fSplitLayout->CountItems();
124}
125
126
127float
128BSplitView::ItemWeight(int32 index) const
129{
130	return fSplitLayout->ItemWeight(index);
131}
132
133
134float
135BSplitView::ItemWeight(BLayoutItem* item) const
136{
137	return fSplitLayout->ItemWeight(item);
138}
139
140
141void
142BSplitView::SetItemWeight(int32 index, float weight, bool invalidateLayout)
143{
144	fSplitLayout->SetItemWeight(index, weight, invalidateLayout);
145}
146
147
148void
149BSplitView::SetItemWeight(BLayoutItem* item, float weight)
150{
151	fSplitLayout->SetItemWeight(item, weight);
152}
153
154
155bool
156BSplitView::IsCollapsible(int32 index) const
157{
158	return fSplitLayout->IsCollapsible(index);
159}
160
161
162void
163BSplitView::SetCollapsible(bool collapsible)
164{
165	fSplitLayout->SetCollapsible(collapsible);
166}
167
168
169void
170BSplitView::SetCollapsible(int32 index, bool collapsible)
171{
172	fSplitLayout->SetCollapsible(index, collapsible);
173}
174
175
176void
177BSplitView::SetCollapsible(int32 first, int32 last, bool collapsible)
178{
179	fSplitLayout->SetCollapsible(first, last, collapsible);
180}
181
182
183bool
184BSplitView::IsItemCollapsed(int32 index) const
185{
186	return fSplitLayout->IsItemCollapsed(index);
187}
188
189
190void
191BSplitView::SetItemCollapsed(int32 index, bool collapsed)
192{
193	fSplitLayout->SetItemCollapsed(index, collapsed);
194}
195
196
197void
198BSplitView::AddChild(BView* child, BView* sibling)
199{
200	BView::AddChild(child, sibling);
201}
202
203
204bool
205BSplitView::AddChild(BView* child, float weight)
206{
207	return fSplitLayout->AddView(child, weight);
208}
209
210
211bool
212BSplitView::AddChild(int32 index, BView* child, float weight)
213{
214	return fSplitLayout->AddView(index, child, weight);
215}
216
217
218bool
219BSplitView::AddChild(BLayoutItem* child)
220{
221	return fSplitLayout->AddItem(child);
222}
223
224
225bool
226BSplitView::AddChild(BLayoutItem* child, float weight)
227{
228	return fSplitLayout->AddItem(child, weight);
229}
230
231
232bool
233BSplitView::AddChild(int32 index, BLayoutItem* child, float weight)
234{
235	return fSplitLayout->AddItem(index, child, weight);
236}
237
238
239void
240BSplitView::AttachedToWindow()
241{
242	AdoptParentColors();
243}
244
245
246void
247BSplitView::Draw(BRect updateRect)
248{
249	// draw the splitters
250	int32 draggedSplitterIndex = fSplitLayout->DraggedSplitter();
251	int32 count = fSplitLayout->CountItems();
252	for (int32 i = 0; i < count - 1; i++) {
253		BRect frame = fSplitLayout->SplitterItemFrame(i);
254		DrawSplitter(frame, updateRect, Orientation(),
255			draggedSplitterIndex == i);
256	}
257}
258
259
260void
261BSplitView::DrawAfterChildren(BRect r)
262{
263	return BView::DrawAfterChildren(r);
264}
265
266
267void
268BSplitView::MouseDown(BPoint where)
269{
270	SetMouseEventMask(B_POINTER_EVENTS,
271		B_LOCK_WINDOW_FOCUS | B_SUSPEND_VIEW_FOCUS);
272
273	if (fSplitLayout->StartDraggingSplitter(where))
274		Invalidate();
275}
276
277
278void
279BSplitView::MouseUp(BPoint where)
280{
281	if (fSplitLayout->StopDraggingSplitter()) {
282		Relayout();
283		Invalidate();
284	}
285}
286
287
288void
289BSplitView::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
290{
291	BCursor cursor(B_CURSOR_ID_SYSTEM_DEFAULT);
292
293	int32 splitterIndex = fSplitLayout->DraggedSplitter();
294
295	if (splitterIndex >= 0 || fSplitLayout->IsAboveSplitter(where)) {
296		if (Orientation() == B_VERTICAL)
297			cursor = BCursor(B_CURSOR_ID_RESIZE_NORTH_SOUTH);
298		else
299			cursor = BCursor(B_CURSOR_ID_RESIZE_EAST_WEST);
300	}
301
302	if (splitterIndex >= 0) {
303		BRect oldFrame = fSplitLayout->SplitterItemFrame(splitterIndex);
304		if (fSplitLayout->DragSplitter(where)) {
305			Invalidate(oldFrame);
306			Invalidate(fSplitLayout->SplitterItemFrame(splitterIndex));
307		}
308	}
309
310	SetViewCursor(&cursor, true);
311}
312
313
314void
315BSplitView::MessageReceived(BMessage* message)
316{
317	return BView::MessageReceived(message);
318}
319
320
321void
322BSplitView::SetLayout(BLayout* layout)
323{
324	// not allowed
325}
326
327
328status_t
329BSplitView::Archive(BMessage* into, bool deep) const
330{
331	return BView::Archive(into, deep);
332}
333
334
335status_t
336BSplitView::AllArchived(BMessage* archive) const
337{
338	return BView::AllArchived(archive);
339}
340
341
342status_t
343BSplitView::AllUnarchived(const BMessage* from)
344{
345	status_t err = BView::AllUnarchived(from);
346	if (err == B_OK) {
347		fSplitLayout = dynamic_cast<BSplitLayout*>(GetLayout());
348		if (!fSplitLayout && GetLayout())
349			return B_BAD_TYPE;
350		else if (!fSplitLayout)
351			return B_ERROR;
352	}
353	return err;
354}
355
356
357BArchivable*
358BSplitView::Instantiate(BMessage* from)
359{
360	if (validate_instantiation(from, "BSplitView"))
361		return new BSplitView(from);
362	return NULL;
363}
364
365
366void
367BSplitView::DrawSplitter(BRect frame, const BRect& updateRect,
368	orientation orientation, bool pressed)
369{
370	_DrawDefaultSplitter(this, frame, updateRect, orientation, pressed);
371}
372
373
374void
375BSplitView::_DrawDefaultSplitter(BView* view, BRect frame,
376	const BRect& updateRect, orientation orientation, bool pressed)
377{
378	uint32 flags = pressed ? BControlLook::B_ACTIVATED : 0;
379	be_control_look->DrawSplitter(view, frame, updateRect, view->ViewColor(),
380		orientation, flags, 0);
381}
382
383
384status_t
385BSplitView::Perform(perform_code d, void* arg)
386{
387	return BView::Perform(d, arg);
388}
389
390
391void BSplitView::_ReservedSplitView1() {}
392void BSplitView::_ReservedSplitView2() {}
393void BSplitView::_ReservedSplitView3() {}
394void BSplitView::_ReservedSplitView4() {}
395void BSplitView::_ReservedSplitView5() {}
396void BSplitView::_ReservedSplitView6() {}
397void BSplitView::_ReservedSplitView7() {}
398void BSplitView::_ReservedSplitView8() {}
399void BSplitView::_ReservedSplitView9() {}
400void BSplitView::_ReservedSplitView10() {}
401
402