xref: /haiku/src/kits/interface/SplitView.cpp (revision 239222b2369c39dc52df52b0a7cdd6cc0a91bc92)
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 <ControlLook.h>
11 #include <Cursor.h>
12 
13 #include "SplitLayout.h"
14 
15 
16 static const unsigned char kHSplitterCursor[] = {
17 	16, 1, 8, 8,
18 	0x03, 0xc0, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
19 	0x1a, 0x58, 0x2a, 0x54, 0x4a, 0x52, 0x8a, 0x51,
20 	0x8a, 0x51, 0x4a, 0x52, 0x2a, 0x54, 0x1a, 0x58,
21 	0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0xc0,
22 
23 	0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0,
24 	0x1b, 0xd8, 0x3b, 0xdc, 0x7b, 0xde, 0xfb, 0xdf,
25 	0xfb, 0xdf, 0x7b, 0xde, 0x3b, 0xdc, 0x1b, 0xd8,
26 	0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0
27 };
28 
29 static const unsigned char kVSplitterCursor[] = {
30 	16, 1, 8, 8,
31 	0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, 0x10,
32 	0x0f, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x80, 0x01,
33 	0x80, 0x01, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xf0,
34 	0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, 0x80,
35 
36 	0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0,
37 	0x0f, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
38 	0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0xf0,
39 	0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80
40 };
41 
42 
43 // constructor
44 BSplitView::BSplitView(enum orientation orientation, float spacing)
45 	:
46 	BView(NULL,
47 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INVALIDATE_AFTER_LAYOUT,
48 		fSplitLayout = new BSplitLayout(orientation, spacing))
49 {
50 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
51 }
52 
53 // destructor
54 BSplitView::~BSplitView()
55 {
56 }
57 
58 // SetInsets
59 void
60 BSplitView::SetInsets(float left, float top, float right, float bottom)
61 {
62 	fSplitLayout->SetInsets(left, top, right, bottom);
63 }
64 
65 // GetInsets
66 void
67 BSplitView::GetInsets(float* left, float* top, float* right,
68 	float* bottom) const
69 {
70 	fSplitLayout->GetInsets(left, top, right, bottom);
71 }
72 
73 // Spacing
74 float
75 BSplitView::Spacing() const
76 {
77 	return fSplitLayout->Spacing();
78 }
79 
80 // SetSpacing
81 void
82 BSplitView::SetSpacing(float spacing)
83 {
84 	fSplitLayout->SetSpacing(spacing);
85 }
86 
87 // Orientation
88 orientation
89 BSplitView::Orientation() const
90 {
91 	return fSplitLayout->Orientation();
92 }
93 
94 // SetOrientation
95 void
96 BSplitView::SetOrientation(enum orientation orientation)
97 {
98 	fSplitLayout->SetOrientation(orientation);
99 }
100 
101 // SplitterSize
102 float
103 BSplitView::SplitterSize() const
104 {
105 	return fSplitLayout->SplitterSize();
106 }
107 
108 // SetSplitterSize
109 void
110 BSplitView::SetSplitterSize(float size)
111 {
112 	fSplitLayout->SetSplitterSize(size);
113 }
114 
115 // SetCollapsible
116 void
117 BSplitView::SetCollapsible(bool collapsible)
118 {
119 	fSplitLayout->SetCollapsible(collapsible);
120 }
121 
122 // SetCollapsible
123 void
124 BSplitView::SetCollapsible(int32 index, bool collapsible)
125 {
126 	fSplitLayout->SetCollapsible(index, collapsible);
127 }
128 
129 // SetCollapsible
130 void
131 BSplitView::SetCollapsible(int32 first, int32 last, bool collapsible)
132 {
133 	fSplitLayout->SetCollapsible(first, last, collapsible);
134 }
135 
136 // AddChild
137 void
138 BSplitView::AddChild(BView* child, BView* sibling)
139 {
140 	BView::AddChild(child, sibling);
141 }
142 
143 // AddChild
144 bool
145 BSplitView::AddChild(BView* child, float weight)
146 {
147 	return fSplitLayout->AddView(child, weight);
148 }
149 
150 // AddChild
151 bool
152 BSplitView::AddChild(int32 index, BView* child, float weight)
153 {
154 	return fSplitLayout->AddView(index, child, weight);
155 }
156 
157 // AddChild
158 bool
159 BSplitView::AddChild(BLayoutItem* child)
160 {
161 	return fSplitLayout->AddItem(child);
162 }
163 
164 // AddChild
165 bool
166 BSplitView::AddChild(BLayoutItem* child, float weight)
167 {
168 	return fSplitLayout->AddItem(child, weight);
169 }
170 
171 // AddChild
172 bool
173 BSplitView::AddChild(int32 index, BLayoutItem* child, float weight)
174 {
175 	return fSplitLayout->AddItem(index, child, weight);
176 }
177 
178 // Draw
179 void
180 BSplitView::Draw(BRect updateRect)
181 {
182 	// draw the splitters
183 	int32 draggedSplitterIndex = fSplitLayout->DraggedSplitter();
184 	int32 count = fSplitLayout->CountItems();
185 	for (int32 i = 0; i < count - 1; i++) {
186 		BRect frame = fSplitLayout->SplitterItemFrame(i);
187 		DrawSplitter(frame, updateRect, Orientation(),
188 			draggedSplitterIndex == i);
189 	}
190 }
191 
192 // MouseDown
193 void
194 BSplitView::MouseDown(BPoint where)
195 {
196 	SetMouseEventMask(B_POINTER_EVENTS,
197 		B_LOCK_WINDOW_FOCUS | B_SUSPEND_VIEW_FOCUS);
198 
199 	if (fSplitLayout->StartDraggingSplitter(where))
200 		Invalidate();
201 }
202 
203 // MouseUp
204 void
205 BSplitView::MouseUp(BPoint where)
206 {
207 	if (fSplitLayout->StopDraggingSplitter()) {
208 		Relayout();
209 		Invalidate();
210 	}
211 }
212 
213 // MouseMoved
214 void
215 BSplitView::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
216 {
217 	BCursor cursor(B_CURSOR_SYSTEM_DEFAULT);
218 
219 	int32 splitterIndex = fSplitLayout->DraggedSplitter();
220 
221 	if (splitterIndex >= 0 || fSplitLayout->IsAboveSplitter(where)) {
222 		if (Orientation() == B_VERTICAL)
223 			cursor = BCursor(kVSplitterCursor);
224 		else
225 			cursor = BCursor(kHSplitterCursor);
226 	}
227 
228 	if (splitterIndex >= 0) {
229 		BRect oldFrame = fSplitLayout->SplitterItemFrame(splitterIndex);
230 		if (fSplitLayout->DragSplitter(where)) {
231 			Invalidate(oldFrame);
232 			Invalidate(fSplitLayout->SplitterItemFrame(splitterIndex));
233 		}
234 	}
235 
236 	SetViewCursor(&cursor, true);
237 }
238 
239 // SetLayout
240 void
241 BSplitView::SetLayout(BLayout* layout)
242 {
243 	// not allowed
244 }
245 
246 // DrawSplitter
247 void
248 BSplitView::DrawSplitter(BRect frame, const BRect& updateRect,
249 	enum orientation orientation, bool pressed)
250 {
251 	_DrawDefaultSplitter(this, frame, updateRect, orientation, pressed);
252 }
253 
254 // _DrawDefaultSplitter
255 void
256 BSplitView::_DrawDefaultSplitter(BView* view, BRect frame,
257 	const BRect& updateRect, enum orientation orientation, bool pressed)
258 {
259 	uint32 flags = pressed ? BControlLook::B_ACTIVATED : 0;
260 	be_control_look->DrawSplitter(view, frame, updateRect, view->ViewColor(),
261 		orientation, flags, 0);
262 }
263