xref: /haiku/src/kits/interface/SplitView.cpp (revision 481f986b59e7782458dcc5fe98ad59a57480e5db)
1 /*
2  * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include <SplitView.h>
7 
8 #include <stdio.h>
9 
10 #include <Archivable.h>
11 #include <ControlLook.h>
12 #include <Cursor.h>
13 
14 #include "SplitLayout.h"
15 
16 
17 BSplitView::BSplitView(enum orientation orientation, float spacing)
18 	:
19 	BView(NULL,
20 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INVALIDATE_AFTER_LAYOUT,
21 		fSplitLayout = new BSplitLayout(orientation, spacing))
22 {
23 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
24 }
25 
26 
27 BSplitView::BSplitView(BMessage* from)
28 	:
29 	BView(BUnarchiver::PrepareArchive(from)),
30 	fSplitLayout(NULL)
31 {
32 	BUnarchiver(from).Finish();
33 }
34 
35 
36 BSplitView::~BSplitView()
37 {
38 }
39 
40 
41 void
42 BSplitView::SetInsets(float left, float top, float right, float bottom)
43 {
44 	fSplitLayout->SetInsets(left, top, right, bottom);
45 }
46 
47 
48 void
49 BSplitView::GetInsets(float* left, float* top, float* right,
50 	float* bottom) const
51 {
52 	fSplitLayout->GetInsets(left, top, right, bottom);
53 }
54 
55 
56 float
57 BSplitView::Spacing() const
58 {
59 	return fSplitLayout->Spacing();
60 }
61 
62 
63 void
64 BSplitView::SetSpacing(float spacing)
65 {
66 	fSplitLayout->SetSpacing(spacing);
67 }
68 
69 
70 orientation
71 BSplitView::Orientation() const
72 {
73 	return fSplitLayout->Orientation();
74 }
75 
76 
77 void
78 BSplitView::SetOrientation(enum orientation orientation)
79 {
80 	fSplitLayout->SetOrientation(orientation);
81 }
82 
83 
84 float
85 BSplitView::SplitterSize() const
86 {
87 	return fSplitLayout->SplitterSize();
88 }
89 
90 
91 void
92 BSplitView::SetSplitterSize(float size)
93 {
94 	fSplitLayout->SetSplitterSize(size);
95 }
96 
97 
98 void
99 BSplitView::SetCollapsible(bool collapsible)
100 {
101 	fSplitLayout->SetCollapsible(collapsible);
102 }
103 
104 
105 void
106 BSplitView::SetCollapsible(int32 index, bool collapsible)
107 {
108 	fSplitLayout->SetCollapsible(index, collapsible);
109 }
110 
111 
112 void
113 BSplitView::SetCollapsible(int32 first, int32 last, bool collapsible)
114 {
115 	fSplitLayout->SetCollapsible(first, last, collapsible);
116 }
117 
118 
119 void
120 BSplitView::AddChild(BView* child, BView* sibling)
121 {
122 	BView::AddChild(child, sibling);
123 }
124 
125 
126 bool
127 BSplitView::AddChild(BView* child, float weight)
128 {
129 	return fSplitLayout->AddView(child, weight);
130 }
131 
132 
133 bool
134 BSplitView::AddChild(int32 index, BView* child, float weight)
135 {
136 	return fSplitLayout->AddView(index, child, weight);
137 }
138 
139 
140 bool
141 BSplitView::AddChild(BLayoutItem* child)
142 {
143 	return fSplitLayout->AddItem(child);
144 }
145 
146 
147 bool
148 BSplitView::AddChild(BLayoutItem* child, float weight)
149 {
150 	return fSplitLayout->AddItem(child, weight);
151 }
152 
153 
154 bool
155 BSplitView::AddChild(int32 index, BLayoutItem* child, float weight)
156 {
157 	return fSplitLayout->AddItem(index, child, weight);
158 }
159 
160 
161 void
162 BSplitView::Draw(BRect updateRect)
163 {
164 	// draw the splitters
165 	int32 draggedSplitterIndex = fSplitLayout->DraggedSplitter();
166 	int32 count = fSplitLayout->CountItems();
167 	for (int32 i = 0; i < count - 1; i++) {
168 		BRect frame = fSplitLayout->SplitterItemFrame(i);
169 		DrawSplitter(frame, updateRect, Orientation(),
170 			draggedSplitterIndex == i);
171 	}
172 }
173 
174 
175 void
176 BSplitView::MouseDown(BPoint where)
177 {
178 	SetMouseEventMask(B_POINTER_EVENTS,
179 		B_LOCK_WINDOW_FOCUS | B_SUSPEND_VIEW_FOCUS);
180 
181 	if (fSplitLayout->StartDraggingSplitter(where))
182 		Invalidate();
183 }
184 
185 
186 void
187 BSplitView::MouseUp(BPoint where)
188 {
189 	if (fSplitLayout->StopDraggingSplitter()) {
190 		Relayout();
191 		Invalidate();
192 	}
193 }
194 
195 
196 void
197 BSplitView::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
198 {
199 	BCursor cursor(B_CURSOR_ID_SYSTEM_DEFAULT);
200 
201 	int32 splitterIndex = fSplitLayout->DraggedSplitter();
202 
203 	if (splitterIndex >= 0 || fSplitLayout->IsAboveSplitter(where)) {
204 		if (Orientation() == B_VERTICAL)
205 			cursor = BCursor(B_CURSOR_ID_RESIZE_NORTH_SOUTH);
206 		else
207 			cursor = BCursor(B_CURSOR_ID_RESIZE_EAST_WEST);
208 	}
209 
210 	if (splitterIndex >= 0) {
211 		BRect oldFrame = fSplitLayout->SplitterItemFrame(splitterIndex);
212 		if (fSplitLayout->DragSplitter(where)) {
213 			Invalidate(oldFrame);
214 			Invalidate(fSplitLayout->SplitterItemFrame(splitterIndex));
215 		}
216 	}
217 
218 	SetViewCursor(&cursor, true);
219 }
220 
221 
222 void
223 BSplitView::SetLayout(BLayout* layout)
224 {
225 	// not allowed
226 }
227 
228 
229 status_t
230 BSplitView::Archive(BMessage* into, bool deep) const
231 {
232 	return BView::Archive(into, deep);
233 }
234 
235 
236 status_t
237 BSplitView::AllUnarchived(const BMessage* from)
238 {
239 	status_t err = BView::AllUnarchived(from);
240 	if (err == B_OK) {
241 		fSplitLayout = dynamic_cast<BSplitLayout*>(GetLayout());
242 		if (!fSplitLayout && GetLayout())
243 			return B_BAD_TYPE;
244 		else if (!fSplitLayout)
245 			return B_ERROR;
246 	}
247 	return err;
248 }
249 
250 
251 BArchivable*
252 BSplitView::Instantiate(BMessage* from)
253 {
254 	if (validate_instantiation(from, "BSplitView"))
255 		return new BSplitView(from);
256 	return NULL;
257 }
258 
259 
260 void
261 BSplitView::DrawSplitter(BRect frame, const BRect& updateRect,
262 	enum orientation orientation, bool pressed)
263 {
264 	_DrawDefaultSplitter(this, frame, updateRect, orientation, pressed);
265 }
266 
267 
268 void
269 BSplitView::_DrawDefaultSplitter(BView* view, BRect frame,
270 	const BRect& updateRect, enum orientation orientation, bool pressed)
271 {
272 	uint32 flags = pressed ? BControlLook::B_ACTIVATED : 0;
273 	be_control_look->DrawSplitter(view, frame, updateRect, view->ViewColor(),
274 		orientation, flags, 0);
275 }
276