1c97796c2SIngo Weinhold /*
2c97796c2SIngo Weinhold * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3c97796c2SIngo Weinhold * Copyright 2009, Stephan Aßmus, superstippi@gmx.de.
4c97796c2SIngo Weinhold * Distributed under the terms of the MIT License.
5c97796c2SIngo Weinhold */
6c97796c2SIngo Weinhold
7c97796c2SIngo Weinhold
8c97796c2SIngo Weinhold #include "HeaderView.h"
9c97796c2SIngo Weinhold
10c97796c2SIngo Weinhold #include <stdio.h>
11c97796c2SIngo Weinhold
12c97796c2SIngo Weinhold #include <algorithm>
13c97796c2SIngo Weinhold #include <new>
14c97796c2SIngo Weinhold
15c97796c2SIngo Weinhold #include <ControlLook.h>
16c97796c2SIngo Weinhold #include <LayoutUtils.h>
17c5c59496SIngo Weinhold #include <Looper.h>
18c97796c2SIngo Weinhold
19c97796c2SIngo Weinhold
20c97796c2SIngo Weinhold // #pragma mark - HeaderRenderer
21c97796c2SIngo Weinhold
22c97796c2SIngo Weinhold
~HeaderRenderer()23c97796c2SIngo Weinhold HeaderRenderer::~HeaderRenderer()
24c97796c2SIngo Weinhold {
25c97796c2SIngo Weinhold }
26c97796c2SIngo Weinhold
27c97796c2SIngo Weinhold
28d4dd240bSIngo Weinhold void
DrawHeaderBackground(BView * view,BRect frame,BRect updateRect,uint32 flags)29d4dd240bSIngo Weinhold HeaderRenderer::DrawHeaderBackground(BView* view, BRect frame, BRect updateRect,
30d4dd240bSIngo Weinhold uint32 flags)
31d4dd240bSIngo Weinhold {
32d4dd240bSIngo Weinhold BRect bgRect = frame;
33d4dd240bSIngo Weinhold
34d4dd240bSIngo Weinhold rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
35d4dd240bSIngo Weinhold view->SetHighColor(tint_color(base, B_DARKEN_2_TINT));
36d4dd240bSIngo Weinhold view->StrokeLine(bgRect.LeftBottom(), bgRect.RightBottom());
37d4dd240bSIngo Weinhold
38d4dd240bSIngo Weinhold bgRect.bottom--;
39d4dd240bSIngo Weinhold bgRect.right--;
40d4dd240bSIngo Weinhold
41d4dd240bSIngo Weinhold // if ((flags & CLICKED) != 0)
42d4dd240bSIngo Weinhold // base = tint_color(base, B_DARKEN_1_TINT);
43d4dd240bSIngo Weinhold
44d4dd240bSIngo Weinhold be_control_look->DrawButtonBackground(view, bgRect, updateRect, base, 0,
45d4dd240bSIngo Weinhold BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER);
46d4dd240bSIngo Weinhold
47d4dd240bSIngo Weinhold view->StrokeLine(frame.RightTop(), frame.RightBottom());
48d4dd240bSIngo Weinhold }
49d4dd240bSIngo Weinhold
50d4dd240bSIngo Weinhold
51c97796c2SIngo Weinhold // #pragma mark - DefaultHeaderRenderer
52c97796c2SIngo Weinhold
53c97796c2SIngo Weinhold
DefaultHeaderRenderer()54c97796c2SIngo Weinhold DefaultHeaderRenderer::DefaultHeaderRenderer()
55c97796c2SIngo Weinhold {
56c97796c2SIngo Weinhold }
57c97796c2SIngo Weinhold
58c97796c2SIngo Weinhold
~DefaultHeaderRenderer()59c97796c2SIngo Weinhold DefaultHeaderRenderer::~DefaultHeaderRenderer()
60c97796c2SIngo Weinhold {
61c97796c2SIngo Weinhold }
62c97796c2SIngo Weinhold
63c97796c2SIngo Weinhold
64c97796c2SIngo Weinhold float
HeaderHeight(BView * view,const Header * header)65c97796c2SIngo Weinhold DefaultHeaderRenderer::HeaderHeight(BView* view, const Header* header)
66c97796c2SIngo Weinhold {
67c97796c2SIngo Weinhold BVariant value;
68c97796c2SIngo Weinhold if (!header->GetValue(value))
69c97796c2SIngo Weinhold return 0;
70c97796c2SIngo Weinhold
71c97796c2SIngo Weinhold if (value.Type() == B_STRING_TYPE) {
72a7948191SStephan Aßmus font_height fontHeight;
73a7948191SStephan Aßmus view->GetFontHeight(&fontHeight);
74a7948191SStephan Aßmus return ceilf((fontHeight.ascent + fontHeight.descent) * 1.2f) + 2.0f;
75a7948191SStephan Aßmus } else {
76a7948191SStephan Aßmus // TODO: Support more value types.
77c97796c2SIngo Weinhold return 0;
78c97796c2SIngo Weinhold }
79a7948191SStephan Aßmus }
80a7948191SStephan Aßmus
81a7948191SStephan Aßmus
82a7948191SStephan Aßmus float
PreferredHeaderWidth(BView * view,const Header * header)83a7948191SStephan Aßmus DefaultHeaderRenderer::PreferredHeaderWidth(BView* view, const Header* header)
84a7948191SStephan Aßmus {
85a7948191SStephan Aßmus BVariant value;
86a7948191SStephan Aßmus if (!header->GetValue(value))
87a7948191SStephan Aßmus return 0;
88a7948191SStephan Aßmus
89a7948191SStephan Aßmus if (value.Type() == B_STRING_TYPE) {
90a7948191SStephan Aßmus float width = view->StringWidth(value.ToString());
91a7948191SStephan Aßmus return width + be_control_look->DefaultLabelSpacing() * 2.0f;
92a7948191SStephan Aßmus } else {
93a7948191SStephan Aßmus // TODO: Support more value types.
94a7948191SStephan Aßmus return 0;
95a7948191SStephan Aßmus }
96a7948191SStephan Aßmus }
97c97796c2SIngo Weinhold
98c97796c2SIngo Weinhold
99c97796c2SIngo Weinhold void
DrawHeader(BView * view,BRect frame,BRect updateRect,const Header * header,uint32 flags)100c97796c2SIngo Weinhold DefaultHeaderRenderer::DrawHeader(BView* view, BRect frame, BRect updateRect,
101c97796c2SIngo Weinhold const Header* header, uint32 flags)
102c97796c2SIngo Weinhold {
103a7948191SStephan Aßmus DrawHeaderBackground(view, frame, updateRect, flags);
104a7948191SStephan Aßmus
105c97796c2SIngo Weinhold BVariant value;
106c97796c2SIngo Weinhold if (!header->GetValue(value))
107c97796c2SIngo Weinhold return;
108c97796c2SIngo Weinhold
109a7948191SStephan Aßmus frame.InsetBy(be_control_look->DefaultLabelSpacing(), 0);
110a7948191SStephan Aßmus
111c97796c2SIngo Weinhold if (value.Type() == B_STRING_TYPE) {
112c97796c2SIngo Weinhold be_control_look->DrawLabel(view, value.ToString(), frame, updateRect,
113c97796c2SIngo Weinhold view->LowColor(), 0);
114c97796c2SIngo Weinhold }
115c97796c2SIngo Weinhold }
116c97796c2SIngo Weinhold
117c97796c2SIngo Weinhold
118c97796c2SIngo Weinhold // #pragma mark - HeaderListener
119c97796c2SIngo Weinhold
120c97796c2SIngo Weinhold
~HeaderListener()121c97796c2SIngo Weinhold HeaderListener::~HeaderListener()
122c97796c2SIngo Weinhold {
123c97796c2SIngo Weinhold }
124c97796c2SIngo Weinhold
125c97796c2SIngo Weinhold
126e558530eSIngo Weinhold void
HeaderWidthChanged(Header * header)127e558530eSIngo Weinhold HeaderListener::HeaderWidthChanged(Header* header)
128e558530eSIngo Weinhold {
129e558530eSIngo Weinhold }
130e558530eSIngo Weinhold
131e558530eSIngo Weinhold
132e558530eSIngo Weinhold void
HeaderWidthRestrictionsChanged(Header * header)133e558530eSIngo Weinhold HeaderListener::HeaderWidthRestrictionsChanged(Header* header)
134e558530eSIngo Weinhold {
135e558530eSIngo Weinhold }
136e558530eSIngo Weinhold
137e558530eSIngo Weinhold
138e558530eSIngo Weinhold void
HeaderValueChanged(Header * header)139e558530eSIngo Weinhold HeaderListener::HeaderValueChanged(Header* header)
140e558530eSIngo Weinhold {
141e558530eSIngo Weinhold }
142e558530eSIngo Weinhold
143e558530eSIngo Weinhold
144e558530eSIngo Weinhold void
HeaderRendererChanged(Header * header)145e558530eSIngo Weinhold HeaderListener::HeaderRendererChanged(Header* header)
146e558530eSIngo Weinhold {
147e558530eSIngo Weinhold }
148e558530eSIngo Weinhold
149e558530eSIngo Weinhold
150c97796c2SIngo Weinhold // #pragma mark - Header
151c97796c2SIngo Weinhold
152c97796c2SIngo Weinhold
Header(int32 modelIndex)153c97796c2SIngo Weinhold Header::Header(int32 modelIndex)
154c97796c2SIngo Weinhold :
155c97796c2SIngo Weinhold fWidth(100),
156c97796c2SIngo Weinhold fMinWidth(0),
157c97796c2SIngo Weinhold fMaxWidth(10000),
158c97796c2SIngo Weinhold fPreferredWidth(100),
159c97796c2SIngo Weinhold fValue(),
160c97796c2SIngo Weinhold fRenderer(NULL),
161c97796c2SIngo Weinhold fModelIndex(modelIndex),
162c97796c2SIngo Weinhold fResizable(true)
163c97796c2SIngo Weinhold {
164c97796c2SIngo Weinhold }
165c97796c2SIngo Weinhold
166c97796c2SIngo Weinhold
Header(float width,float minWidth,float maxWidth,float preferredWidth,int32 modelIndex)167c97796c2SIngo Weinhold Header::Header(float width, float minWidth, float maxWidth,
168c97796c2SIngo Weinhold float preferredWidth, int32 modelIndex)
169c97796c2SIngo Weinhold :
170c97796c2SIngo Weinhold fWidth(width),
171c97796c2SIngo Weinhold fMinWidth(minWidth),
172c97796c2SIngo Weinhold fMaxWidth(maxWidth),
173c97796c2SIngo Weinhold fPreferredWidth(preferredWidth),
174c97796c2SIngo Weinhold fValue(),
175c97796c2SIngo Weinhold fRenderer(NULL),
176c97796c2SIngo Weinhold fModelIndex(modelIndex),
177c97796c2SIngo Weinhold fResizable(true)
178c97796c2SIngo Weinhold {
179c97796c2SIngo Weinhold }
180c97796c2SIngo Weinhold
181c97796c2SIngo Weinhold
182c97796c2SIngo Weinhold float
Width() const183c97796c2SIngo Weinhold Header::Width() const
184c97796c2SIngo Weinhold {
185c97796c2SIngo Weinhold return fWidth;
186c97796c2SIngo Weinhold }
187c97796c2SIngo Weinhold
188c97796c2SIngo Weinhold
189c97796c2SIngo Weinhold float
MinWidth() const190c97796c2SIngo Weinhold Header::MinWidth() const
191c97796c2SIngo Weinhold {
192c97796c2SIngo Weinhold return fMinWidth;
193c97796c2SIngo Weinhold }
194c97796c2SIngo Weinhold
195c97796c2SIngo Weinhold
196c97796c2SIngo Weinhold float
MaxWidth() const197c97796c2SIngo Weinhold Header::MaxWidth() const
198c97796c2SIngo Weinhold {
199c97796c2SIngo Weinhold return fMaxWidth;
200c97796c2SIngo Weinhold }
201c97796c2SIngo Weinhold
202c97796c2SIngo Weinhold
203c97796c2SIngo Weinhold float
PreferredWidth() const204c97796c2SIngo Weinhold Header::PreferredWidth() const
205c97796c2SIngo Weinhold {
206c97796c2SIngo Weinhold return fPreferredWidth;
207c97796c2SIngo Weinhold }
208c97796c2SIngo Weinhold
209c97796c2SIngo Weinhold
210c97796c2SIngo Weinhold void
SetWidth(float width)211c97796c2SIngo Weinhold Header::SetWidth(float width)
212c97796c2SIngo Weinhold {
213c97796c2SIngo Weinhold if (width != fWidth) {
214c97796c2SIngo Weinhold fWidth = width;
215e558530eSIngo Weinhold NotifyWidthChanged();
216c97796c2SIngo Weinhold }
217c97796c2SIngo Weinhold }
218c97796c2SIngo Weinhold
219c97796c2SIngo Weinhold
220c97796c2SIngo Weinhold void
SetMinWidth(float width)221c97796c2SIngo Weinhold Header::SetMinWidth(float width)
222c97796c2SIngo Weinhold {
223c97796c2SIngo Weinhold if (width != fMinWidth) {
224c97796c2SIngo Weinhold fMinWidth = width;
225e558530eSIngo Weinhold NotifyWidthRestrictionsChanged();
226c97796c2SIngo Weinhold }
227c97796c2SIngo Weinhold }
228c97796c2SIngo Weinhold
229c97796c2SIngo Weinhold
230c97796c2SIngo Weinhold void
SetMaxWidth(float width)231c97796c2SIngo Weinhold Header::SetMaxWidth(float width)
232c97796c2SIngo Weinhold {
233c97796c2SIngo Weinhold if (width != fMaxWidth) {
234c97796c2SIngo Weinhold fMaxWidth = width;
235e558530eSIngo Weinhold NotifyWidthRestrictionsChanged();
236c97796c2SIngo Weinhold }
237c97796c2SIngo Weinhold }
238c97796c2SIngo Weinhold
239c97796c2SIngo Weinhold
240c97796c2SIngo Weinhold void
SetPreferredWidth(float width)241c97796c2SIngo Weinhold Header::SetPreferredWidth(float width)
242c97796c2SIngo Weinhold {
243c97796c2SIngo Weinhold if (width != fPreferredWidth) {
244c97796c2SIngo Weinhold fPreferredWidth = width;
245e558530eSIngo Weinhold NotifyWidthRestrictionsChanged();
246c97796c2SIngo Weinhold }
247c97796c2SIngo Weinhold }
248c97796c2SIngo Weinhold
249c97796c2SIngo Weinhold
250c97796c2SIngo Weinhold bool
IsResizable() const251c97796c2SIngo Weinhold Header::IsResizable() const
252c97796c2SIngo Weinhold {
253c97796c2SIngo Weinhold return fResizable;
254c97796c2SIngo Weinhold }
255c97796c2SIngo Weinhold
256c97796c2SIngo Weinhold
257c97796c2SIngo Weinhold void
SetResizable(bool resizable)258c97796c2SIngo Weinhold Header::SetResizable(bool resizable)
259c97796c2SIngo Weinhold {
260c97796c2SIngo Weinhold if (resizable != fResizable) {
261c97796c2SIngo Weinhold fResizable = resizable;
262e558530eSIngo Weinhold NotifyWidthRestrictionsChanged();
263c97796c2SIngo Weinhold }
264c97796c2SIngo Weinhold }
265c97796c2SIngo Weinhold
266c97796c2SIngo Weinhold
267c97796c2SIngo Weinhold bool
GetValue(BVariant & _value) const268c97796c2SIngo Weinhold Header::GetValue(BVariant& _value) const
269c97796c2SIngo Weinhold {
270c97796c2SIngo Weinhold _value = fValue;
271c97796c2SIngo Weinhold return true;
272c97796c2SIngo Weinhold }
273c97796c2SIngo Weinhold
274c97796c2SIngo Weinhold
275c97796c2SIngo Weinhold void
SetValue(const BVariant & value)276c97796c2SIngo Weinhold Header::SetValue(const BVariant& value)
277c97796c2SIngo Weinhold {
278c97796c2SIngo Weinhold fValue = value;
279e558530eSIngo Weinhold NotifyValueChanged();
280c97796c2SIngo Weinhold }
281c97796c2SIngo Weinhold
282c97796c2SIngo Weinhold
283c97796c2SIngo Weinhold int32
ModelIndex() const284c97796c2SIngo Weinhold Header::ModelIndex() const
285c97796c2SIngo Weinhold {
286c97796c2SIngo Weinhold return fModelIndex;
287c97796c2SIngo Weinhold }
288c97796c2SIngo Weinhold
289c97796c2SIngo Weinhold
290c97796c2SIngo Weinhold void
SetModelIndex(int32 index)291c97796c2SIngo Weinhold Header::SetModelIndex(int32 index)
292c97796c2SIngo Weinhold {
293c97796c2SIngo Weinhold fModelIndex = index;
294c97796c2SIngo Weinhold }
295c97796c2SIngo Weinhold
296c97796c2SIngo Weinhold
297c97796c2SIngo Weinhold HeaderRenderer*
GetHeaderRenderer() const298c97796c2SIngo Weinhold Header::GetHeaderRenderer() const
299c97796c2SIngo Weinhold {
300c97796c2SIngo Weinhold return fRenderer;
301c97796c2SIngo Weinhold }
302c97796c2SIngo Weinhold
303c97796c2SIngo Weinhold
304c97796c2SIngo Weinhold void
SetHeaderRenderer(HeaderRenderer * renderer)305c97796c2SIngo Weinhold Header::SetHeaderRenderer(HeaderRenderer* renderer)
306c97796c2SIngo Weinhold {
307c97796c2SIngo Weinhold if (renderer != fRenderer) {
308c97796c2SIngo Weinhold fRenderer = renderer;
309e558530eSIngo Weinhold NotifyRendererChanged();
310c97796c2SIngo Weinhold }
311c97796c2SIngo Weinhold }
312c97796c2SIngo Weinhold
313c97796c2SIngo Weinhold
314c97796c2SIngo Weinhold void
AddListener(HeaderListener * listener)315c97796c2SIngo Weinhold Header::AddListener(HeaderListener* listener)
316c97796c2SIngo Weinhold {
317c97796c2SIngo Weinhold fListeners.AddItem(listener);
318c97796c2SIngo Weinhold }
319c97796c2SIngo Weinhold
320c97796c2SIngo Weinhold
321c97796c2SIngo Weinhold void
RemoveListener(HeaderListener * listener)322c97796c2SIngo Weinhold Header::RemoveListener(HeaderListener* listener)
323c97796c2SIngo Weinhold {
324c97796c2SIngo Weinhold fListeners.RemoveItem(listener);
325c97796c2SIngo Weinhold }
326c97796c2SIngo Weinhold
327c97796c2SIngo Weinhold
328c97796c2SIngo Weinhold void
NotifyWidthChanged()329e558530eSIngo Weinhold Header::NotifyWidthChanged()
330c97796c2SIngo Weinhold {
331c97796c2SIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
332c97796c2SIngo Weinhold HeaderListener* listener = fListeners.ItemAt(i);
333e558530eSIngo Weinhold listener->HeaderWidthChanged(this);
334e558530eSIngo Weinhold }
335e558530eSIngo Weinhold }
336e558530eSIngo Weinhold
337e558530eSIngo Weinhold
338e558530eSIngo Weinhold void
NotifyWidthRestrictionsChanged()339e558530eSIngo Weinhold Header::NotifyWidthRestrictionsChanged()
340e558530eSIngo Weinhold {
341e558530eSIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
342e558530eSIngo Weinhold HeaderListener* listener = fListeners.ItemAt(i);
343e558530eSIngo Weinhold listener->HeaderWidthRestrictionsChanged(this);
344e558530eSIngo Weinhold }
345e558530eSIngo Weinhold }
346e558530eSIngo Weinhold
347e558530eSIngo Weinhold
348e558530eSIngo Weinhold void
NotifyValueChanged()349e558530eSIngo Weinhold Header::NotifyValueChanged()
350e558530eSIngo Weinhold {
351e558530eSIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
352e558530eSIngo Weinhold HeaderListener* listener = fListeners.ItemAt(i);
353e558530eSIngo Weinhold listener->HeaderValueChanged(this);
354e558530eSIngo Weinhold }
355e558530eSIngo Weinhold }
356e558530eSIngo Weinhold
357e558530eSIngo Weinhold
358e558530eSIngo Weinhold void
NotifyRendererChanged()359e558530eSIngo Weinhold Header::NotifyRendererChanged()
360e558530eSIngo Weinhold {
361e558530eSIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
362e558530eSIngo Weinhold HeaderListener* listener = fListeners.ItemAt(i);
363e558530eSIngo Weinhold listener->HeaderRendererChanged(this);
364c97796c2SIngo Weinhold }
365c97796c2SIngo Weinhold }
366c97796c2SIngo Weinhold
367c97796c2SIngo Weinhold
368c97796c2SIngo Weinhold // #pragma mark - HeaderModelListener
369c97796c2SIngo Weinhold
370c97796c2SIngo Weinhold
~HeaderModelListener()371c97796c2SIngo Weinhold HeaderModelListener::~HeaderModelListener()
372c97796c2SIngo Weinhold {
373c97796c2SIngo Weinhold }
374c97796c2SIngo Weinhold
375c97796c2SIngo Weinhold
376c97796c2SIngo Weinhold void
HeaderAdded(HeaderModel * model,int32 index)377c97796c2SIngo Weinhold HeaderModelListener::HeaderAdded(HeaderModel* model, int32 index)
378c97796c2SIngo Weinhold {
379c97796c2SIngo Weinhold }
380c97796c2SIngo Weinhold
381c97796c2SIngo Weinhold
382c97796c2SIngo Weinhold void
HeaderRemoved(HeaderModel * model,int32 index)383c97796c2SIngo Weinhold HeaderModelListener::HeaderRemoved(HeaderModel* model, int32 index)
384c97796c2SIngo Weinhold {
385c97796c2SIngo Weinhold }
386c97796c2SIngo Weinhold
387c97796c2SIngo Weinhold
388c97796c2SIngo Weinhold void
HeaderMoved(HeaderModel * model,int32 fromIndex,int32 toIndex)389c97796c2SIngo Weinhold HeaderModelListener::HeaderMoved(HeaderModel* model, int32 fromIndex,
390c97796c2SIngo Weinhold int32 toIndex)
391c97796c2SIngo Weinhold {
392c97796c2SIngo Weinhold }
393c97796c2SIngo Weinhold
394c97796c2SIngo Weinhold
395c97796c2SIngo Weinhold // #pragma mark - HeaderModel
396c97796c2SIngo Weinhold
397c97796c2SIngo Weinhold
HeaderModel()398c97796c2SIngo Weinhold HeaderModel::HeaderModel()
399c97796c2SIngo Weinhold {
400c97796c2SIngo Weinhold }
401c97796c2SIngo Weinhold
402c97796c2SIngo Weinhold
~HeaderModel()403c97796c2SIngo Weinhold HeaderModel::~HeaderModel()
404c97796c2SIngo Weinhold {
405c97796c2SIngo Weinhold }
406c97796c2SIngo Weinhold
407c97796c2SIngo Weinhold
408c97796c2SIngo Weinhold int32
CountHeaders() const409c97796c2SIngo Weinhold HeaderModel::CountHeaders() const
410c97796c2SIngo Weinhold {
411c97796c2SIngo Weinhold return fHeaders.CountItems();
412c97796c2SIngo Weinhold }
413c97796c2SIngo Weinhold
414c97796c2SIngo Weinhold
415c97796c2SIngo Weinhold Header*
HeaderAt(int32 index) const416c97796c2SIngo Weinhold HeaderModel::HeaderAt(int32 index) const
417c97796c2SIngo Weinhold {
418c97796c2SIngo Weinhold return fHeaders.ItemAt(index);
419c97796c2SIngo Weinhold }
420c97796c2SIngo Weinhold
421c97796c2SIngo Weinhold
422c97796c2SIngo Weinhold int32
IndexOfHeader(Header * header) const423c97796c2SIngo Weinhold HeaderModel::IndexOfHeader(Header* header) const
424c97796c2SIngo Weinhold {
425c97796c2SIngo Weinhold return fHeaders.IndexOf(header);
426c97796c2SIngo Weinhold }
427c97796c2SIngo Weinhold
428c97796c2SIngo Weinhold
429c97796c2SIngo Weinhold bool
AddHeader(Header * header)430c97796c2SIngo Weinhold HeaderModel::AddHeader(Header* header)
431c97796c2SIngo Weinhold {
432c97796c2SIngo Weinhold if (!fHeaders.AddItem(header))
433c97796c2SIngo Weinhold return false;
434c97796c2SIngo Weinhold
435c97796c2SIngo Weinhold NotifyHeaderAdded(fHeaders.CountItems() - 1);
436c97796c2SIngo Weinhold
437c97796c2SIngo Weinhold return true;
438c97796c2SIngo Weinhold }
439c97796c2SIngo Weinhold
440c97796c2SIngo Weinhold
441c97796c2SIngo Weinhold Header*
RemoveHeader(int32 index)442c97796c2SIngo Weinhold HeaderModel::RemoveHeader(int32 index)
443c97796c2SIngo Weinhold {
444c97796c2SIngo Weinhold Header* header = fHeaders.RemoveItemAt(index);
445c97796c2SIngo Weinhold if (header != NULL)
446c97796c2SIngo Weinhold return NULL;
447c97796c2SIngo Weinhold
448c97796c2SIngo Weinhold NotifyHeaderRemoved(index);
449c97796c2SIngo Weinhold
450c97796c2SIngo Weinhold return header;
451c97796c2SIngo Weinhold }
452c97796c2SIngo Weinhold
453c97796c2SIngo Weinhold
454c97796c2SIngo Weinhold void
RemoveHeader(Header * header)455c97796c2SIngo Weinhold HeaderModel::RemoveHeader(Header* header)
456c97796c2SIngo Weinhold {
457c97796c2SIngo Weinhold RemoveHeader(fHeaders.IndexOf(header));
458c97796c2SIngo Weinhold }
459c97796c2SIngo Weinhold
460c97796c2SIngo Weinhold
461c97796c2SIngo Weinhold bool
MoveHeader(int32 fromIndex,int32 toIndex)462c97796c2SIngo Weinhold HeaderModel::MoveHeader(int32 fromIndex, int32 toIndex)
463c97796c2SIngo Weinhold {
464c97796c2SIngo Weinhold int32 headerCount = fHeaders.CountItems();
465c97796c2SIngo Weinhold if (fromIndex < 0 || fromIndex >= headerCount
466c97796c2SIngo Weinhold || toIndex < 0 || toIndex >= headerCount) {
467c97796c2SIngo Weinhold return false;
468c97796c2SIngo Weinhold }
469c97796c2SIngo Weinhold
470c97796c2SIngo Weinhold if (fromIndex == toIndex)
471c97796c2SIngo Weinhold return true;
472c97796c2SIngo Weinhold
473c97796c2SIngo Weinhold Header* header = fHeaders.RemoveItemAt(fromIndex);
474c97796c2SIngo Weinhold fHeaders.AddItem(header, toIndex);
475c97796c2SIngo Weinhold // TODO: Might fail.
476c97796c2SIngo Weinhold
477c97796c2SIngo Weinhold NotifyHeaderMoved(fromIndex, toIndex);
478c97796c2SIngo Weinhold
479c97796c2SIngo Weinhold return true;
480c97796c2SIngo Weinhold }
481c97796c2SIngo Weinhold
482c97796c2SIngo Weinhold
483c97796c2SIngo Weinhold void
AddListener(HeaderModelListener * listener)484c97796c2SIngo Weinhold HeaderModel::AddListener(HeaderModelListener* listener)
485c97796c2SIngo Weinhold {
486c97796c2SIngo Weinhold fListeners.AddItem(listener);
487c97796c2SIngo Weinhold }
488c97796c2SIngo Weinhold
489c97796c2SIngo Weinhold
490c97796c2SIngo Weinhold void
RemoveListener(HeaderModelListener * listener)491c97796c2SIngo Weinhold HeaderModel::RemoveListener(HeaderModelListener* listener)
492c97796c2SIngo Weinhold {
493c97796c2SIngo Weinhold fListeners.RemoveItem(listener);
494c97796c2SIngo Weinhold }
495c97796c2SIngo Weinhold
496c97796c2SIngo Weinhold
497c97796c2SIngo Weinhold void
NotifyHeaderAdded(int32 index)498c97796c2SIngo Weinhold HeaderModel::NotifyHeaderAdded(int32 index)
499c97796c2SIngo Weinhold {
500c97796c2SIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
501c97796c2SIngo Weinhold HeaderModelListener* listener = fListeners.ItemAt(i);
502c97796c2SIngo Weinhold listener->HeaderAdded(this, index);
503c97796c2SIngo Weinhold }
504c97796c2SIngo Weinhold }
505c97796c2SIngo Weinhold
506c97796c2SIngo Weinhold
507c97796c2SIngo Weinhold void
NotifyHeaderRemoved(int32 index)508c97796c2SIngo Weinhold HeaderModel::NotifyHeaderRemoved(int32 index)
509c97796c2SIngo Weinhold {
510c97796c2SIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
511c97796c2SIngo Weinhold HeaderModelListener* listener = fListeners.ItemAt(i);
512c97796c2SIngo Weinhold listener->HeaderRemoved(this, index);
513c97796c2SIngo Weinhold }
514c97796c2SIngo Weinhold }
515c97796c2SIngo Weinhold
516c97796c2SIngo Weinhold
517c97796c2SIngo Weinhold void
NotifyHeaderMoved(int32 fromIndex,int32 toIndex)518c97796c2SIngo Weinhold HeaderModel::NotifyHeaderMoved(int32 fromIndex, int32 toIndex)
519c97796c2SIngo Weinhold {
520c97796c2SIngo Weinhold for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
521c97796c2SIngo Weinhold HeaderModelListener* listener = fListeners.ItemAt(i);
522c97796c2SIngo Weinhold listener->HeaderMoved(this, fromIndex, toIndex);
523c97796c2SIngo Weinhold }
524c97796c2SIngo Weinhold }
525c97796c2SIngo Weinhold
526c97796c2SIngo Weinhold
527c97796c2SIngo Weinhold // #pragma mark - HeaderEntry
528c97796c2SIngo Weinhold
529c97796c2SIngo Weinhold
530c97796c2SIngo Weinhold struct HeaderView::HeaderEntry {
531c97796c2SIngo Weinhold Header* header;
532c97796c2SIngo Weinhold float position;
533c97796c2SIngo Weinhold float width;
534c97796c2SIngo Weinhold
HeaderEntryHeaderView::HeaderEntry535c97796c2SIngo Weinhold HeaderEntry(Header* header)
536c97796c2SIngo Weinhold :
537c97796c2SIngo Weinhold header(header)
538c97796c2SIngo Weinhold {
539c97796c2SIngo Weinhold }
540c97796c2SIngo Weinhold };
541c97796c2SIngo Weinhold
542c97796c2SIngo Weinhold
543c5c59496SIngo Weinhold // #pragma mark - States
544a7948191SStephan Aßmus
545a7948191SStephan Aßmus
546c5c59496SIngo Weinhold class HeaderView::State {
547a7948191SStephan Aßmus public:
State(HeaderView * parent)548c5c59496SIngo Weinhold State(HeaderView* parent)
549c5c59496SIngo Weinhold :
550c5c59496SIngo Weinhold fParent(parent)
551a7948191SStephan Aßmus {
552a7948191SStephan Aßmus }
553a7948191SStephan Aßmus
~State()554c5c59496SIngo Weinhold virtual ~State()
555c5c59496SIngo Weinhold {
556c5c59496SIngo Weinhold }
557a7948191SStephan Aßmus
Entering(State * previousState)558c5c59496SIngo Weinhold virtual void Entering(State* previousState)
559c5c59496SIngo Weinhold {
560c5c59496SIngo Weinhold }
561c5c59496SIngo Weinhold
Leaving(State * nextState)562c5c59496SIngo Weinhold virtual void Leaving(State* nextState)
563c5c59496SIngo Weinhold {
564c5c59496SIngo Weinhold }
565c5c59496SIngo Weinhold
MouseDown(BPoint where,uint32 buttons,uint32 modifiers)566c5c59496SIngo Weinhold virtual void MouseDown(BPoint where, uint32 buttons, uint32 modifiers)
567c5c59496SIngo Weinhold {
568c5c59496SIngo Weinhold }
569c5c59496SIngo Weinhold
MouseUp(BPoint where,uint32 buttons,uint32 modifiers)570c5c59496SIngo Weinhold virtual void MouseUp(BPoint where, uint32 buttons, uint32 modifiers)
571c5c59496SIngo Weinhold {
572c5c59496SIngo Weinhold }
573c5c59496SIngo Weinhold
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)574c5c59496SIngo Weinhold virtual void MouseMoved(BPoint where, uint32 transit,
575c5c59496SIngo Weinhold const BMessage* dragMessage)
576c5c59496SIngo Weinhold {
577c5c59496SIngo Weinhold }
578c5c59496SIngo Weinhold
579c5c59496SIngo Weinhold protected:
580c5c59496SIngo Weinhold HeaderView* fParent;
581a7948191SStephan Aßmus };
582a7948191SStephan Aßmus
583a7948191SStephan Aßmus
584c5c59496SIngo Weinhold class HeaderView::DefaultState : public State {
585c5c59496SIngo Weinhold public:
586c5c59496SIngo Weinhold DefaultState(HeaderView* parent);
587c5c59496SIngo Weinhold
588c5c59496SIngo Weinhold virtual void MouseDown(BPoint where, uint32 buttons,
589c5c59496SIngo Weinhold uint32 modifiers);
590c5c59496SIngo Weinhold virtual void MouseMoved(BPoint where, uint32 transit,
591c5c59496SIngo Weinhold const BMessage* dragMessage);
592c5c59496SIngo Weinhold };
593c5c59496SIngo Weinhold
594c5c59496SIngo Weinhold
595c5c59496SIngo Weinhold class HeaderView::ResizeState : public State {
596c5c59496SIngo Weinhold public:
597c5c59496SIngo Weinhold virtual void Entering(State* previousState);
598c5c59496SIngo Weinhold virtual void Leaving(State* nextState);
599c5c59496SIngo Weinhold
600c5c59496SIngo Weinhold ResizeState(HeaderView* parent,
601c5c59496SIngo Weinhold int32 headerIndex, BPoint startPoint);
602c5c59496SIngo Weinhold
603c5c59496SIngo Weinhold virtual void MouseUp(BPoint where, uint32 buttons,
604c5c59496SIngo Weinhold uint32 modifiers);
605c5c59496SIngo Weinhold virtual void MouseMoved(BPoint where, uint32 transit,
606c5c59496SIngo Weinhold const BMessage* dragMessage);
607c5c59496SIngo Weinhold
608c5c59496SIngo Weinhold private:
609c5c59496SIngo Weinhold Header* fHeader;
610c5c59496SIngo Weinhold float fStartX;
611c5c59496SIngo Weinhold float fStartWidth;
612c5c59496SIngo Weinhold };
613c5c59496SIngo Weinhold
614c5c59496SIngo Weinhold
615c5c59496SIngo Weinhold // #pragma mark - DefaultState
616c5c59496SIngo Weinhold
617c5c59496SIngo Weinhold
DefaultState(HeaderView * parent)618c5c59496SIngo Weinhold HeaderView::DefaultState::DefaultState(HeaderView* parent)
619c5c59496SIngo Weinhold :
620c5c59496SIngo Weinhold State(parent)
621c5c59496SIngo Weinhold {
622c5c59496SIngo Weinhold }
623c5c59496SIngo Weinhold
624c5c59496SIngo Weinhold
625c5c59496SIngo Weinhold void
MouseDown(BPoint where,uint32 buttons,uint32 modifiers)626c5c59496SIngo Weinhold HeaderView::DefaultState::MouseDown(BPoint where, uint32 buttons,
627c5c59496SIngo Weinhold uint32 modifiers)
628c5c59496SIngo Weinhold {
629c5c59496SIngo Weinhold HeaderModel* model = fParent->Model();
630c5c59496SIngo Weinhold if (model == NULL)
631c5c59496SIngo Weinhold return;
632c5c59496SIngo Weinhold
633c5c59496SIngo Weinhold if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0)
634c5c59496SIngo Weinhold return;
635c5c59496SIngo Weinhold
636c5c59496SIngo Weinhold int32 headerIndex = fParent->HeaderIndexAt(where);
637c5c59496SIngo Weinhold if (headerIndex < 0) {
638c5c59496SIngo Weinhold int32 headerCount = model->CountHeaders();
639c5c59496SIngo Weinhold if (headerCount == 0)
640c5c59496SIngo Weinhold return;
641c5c59496SIngo Weinhold
642c5c59496SIngo Weinhold headerIndex = headerCount - 1;
643c5c59496SIngo Weinhold }
644c5c59496SIngo Weinhold
645c5c59496SIngo Weinhold // Check whether the mouse is close to the left or the right side of the
646c5c59496SIngo Weinhold // header.
647c5c59496SIngo Weinhold BRect headerFrame = fParent->HeaderFrame(headerIndex);
648c5c59496SIngo Weinhold if (fabs(headerFrame.left - where.x) <= 3) {
649c5c59496SIngo Weinhold if (headerIndex == 0)
650c5c59496SIngo Weinhold return;
651c5c59496SIngo Weinhold headerIndex--;
652c5c59496SIngo Weinhold } else if (fabs(headerFrame.right + 1 - where.x) > 3)
653c5c59496SIngo Weinhold return;
654c5c59496SIngo Weinhold
655c5c59496SIngo Weinhold // start resizing the header
656c5c59496SIngo Weinhold fParent->_SwitchState(new ResizeState(fParent, headerIndex, where));
657c5c59496SIngo Weinhold }
658c5c59496SIngo Weinhold
659c5c59496SIngo Weinhold
660c5c59496SIngo Weinhold void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)661c5c59496SIngo Weinhold HeaderView::DefaultState::MouseMoved(BPoint where, uint32 transit,
662c5c59496SIngo Weinhold const BMessage* dragMessage)
663c5c59496SIngo Weinhold {
664c5c59496SIngo Weinhold }
665c5c59496SIngo Weinhold
666c5c59496SIngo Weinhold
667c5c59496SIngo Weinhold // #pragma mark - ResizeState
668c5c59496SIngo Weinhold
669c5c59496SIngo Weinhold
670c5c59496SIngo Weinhold void
Entering(State * previousState)671c5c59496SIngo Weinhold HeaderView::ResizeState::Entering(State* previousState)
672c5c59496SIngo Weinhold {
673c5c59496SIngo Weinhold fParent->SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
674c5c59496SIngo Weinhold }
675c5c59496SIngo Weinhold
676c5c59496SIngo Weinhold
677c5c59496SIngo Weinhold void
Leaving(State * nextState)678c5c59496SIngo Weinhold HeaderView::ResizeState::Leaving(State* nextState)
679c5c59496SIngo Weinhold {
680c5c59496SIngo Weinhold fParent->SetEventMask(0, 0);
681c5c59496SIngo Weinhold }
682c5c59496SIngo Weinhold
683c5c59496SIngo Weinhold
ResizeState(HeaderView * parent,int32 headerIndex,BPoint startPoint)684c5c59496SIngo Weinhold HeaderView::ResizeState::ResizeState(HeaderView* parent, int32 headerIndex,
685c5c59496SIngo Weinhold BPoint startPoint)
686c5c59496SIngo Weinhold :
687c5c59496SIngo Weinhold State(parent),
688c5c59496SIngo Weinhold fHeader(parent->Model()->HeaderAt(headerIndex)),
689c5c59496SIngo Weinhold fStartX(startPoint.x),
690c5c59496SIngo Weinhold fStartWidth(fHeader->Width())
691c5c59496SIngo Weinhold {
692c5c59496SIngo Weinhold }
693c5c59496SIngo Weinhold
694c5c59496SIngo Weinhold
695c5c59496SIngo Weinhold void
MouseUp(BPoint where,uint32 buttons,uint32 modifiers)696c5c59496SIngo Weinhold HeaderView::ResizeState::MouseUp(BPoint where, uint32 buttons,
697c5c59496SIngo Weinhold uint32 modifiers)
698c5c59496SIngo Weinhold {
699c5c59496SIngo Weinhold if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0)
700c5c59496SIngo Weinhold fParent->_SwitchState(NULL);
701c5c59496SIngo Weinhold }
702c5c59496SIngo Weinhold
703c5c59496SIngo Weinhold
704c5c59496SIngo Weinhold void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)705c5c59496SIngo Weinhold HeaderView::ResizeState::MouseMoved(BPoint where, uint32 transit,
706c5c59496SIngo Weinhold const BMessage* dragMessage)
707c5c59496SIngo Weinhold {
708c5c59496SIngo Weinhold float width = fStartWidth + where.x - fStartX;
709c5c59496SIngo Weinhold width = std::max(width, fHeader->MinWidth());
710c5c59496SIngo Weinhold width = std::min(width, fHeader->MaxWidth());
711c5c59496SIngo Weinhold fHeader->SetWidth(width);
712c5c59496SIngo Weinhold }
713c5c59496SIngo Weinhold
714c5c59496SIngo Weinhold
715c97796c2SIngo Weinhold // #pragma mark - HeaderView
716c97796c2SIngo Weinhold
717c97796c2SIngo Weinhold
HeaderView()718c97796c2SIngo Weinhold HeaderView::HeaderView()
719c97796c2SIngo Weinhold :
7207f1bf82cSIngo Weinhold BView("header view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
721c97796c2SIngo Weinhold fModel(NULL),
722c97796c2SIngo Weinhold fHeaderEntries(10, true),
723c5c59496SIngo Weinhold fLayoutValid(false),
724c5c59496SIngo Weinhold fDefaultState(new DefaultState(this)),
725c5c59496SIngo Weinhold fState(fDefaultState)
726c97796c2SIngo Weinhold {
727c97796c2SIngo Weinhold HeaderModel* model = new(std::nothrow) HeaderModel;
728*c3e066cfSIngo Weinhold BReference<HeaderModel> modelReference(model, true);
729c97796c2SIngo Weinhold SetModel(model);
730ea35acabSIngo Weinhold
731ea35acabSIngo Weinhold SetViewColor(B_TRANSPARENT_32_BIT);
732c97796c2SIngo Weinhold }
733c97796c2SIngo Weinhold
734c97796c2SIngo Weinhold
~HeaderView()735c97796c2SIngo Weinhold HeaderView::~HeaderView()
736c97796c2SIngo Weinhold {
737c97796c2SIngo Weinhold SetModel(NULL);
738c5c59496SIngo Weinhold
739c5c59496SIngo Weinhold _SwitchState(NULL);
740c5c59496SIngo Weinhold delete fDefaultState;
741c97796c2SIngo Weinhold }
742c97796c2SIngo Weinhold
743c97796c2SIngo Weinhold
744c97796c2SIngo Weinhold void
Draw(BRect updateRect)745c97796c2SIngo Weinhold HeaderView::Draw(BRect updateRect)
746c97796c2SIngo Weinhold {
747c97796c2SIngo Weinhold if (fModel == NULL)
748c97796c2SIngo Weinhold return;
749c97796c2SIngo Weinhold
750c97796c2SIngo Weinhold _ValidateHeadersLayout();
751c97796c2SIngo Weinhold
752c97796c2SIngo Weinhold DefaultHeaderRenderer defaultRenderer;
753c97796c2SIngo Weinhold float bottom = Bounds().Height();
754a7948191SStephan Aßmus float left = 0.0f;
755c97796c2SIngo Weinhold
756c97796c2SIngo Weinhold for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++) {
757c97796c2SIngo Weinhold if (Header* header = fModel->HeaderAt(i)) {
758c97796c2SIngo Weinhold HeaderRenderer* renderer = header->GetHeaderRenderer();
759c97796c2SIngo Weinhold if (renderer == NULL)
760c97796c2SIngo Weinhold renderer = &defaultRenderer;
761c97796c2SIngo Weinhold
762c97796c2SIngo Weinhold BRect frame(entry->position, 0, entry->position + entry->width - 1,
763c97796c2SIngo Weinhold bottom);
764c97796c2SIngo Weinhold renderer->DrawHeader(this, frame, updateRect, header, 0);
765c97796c2SIngo Weinhold // TODO: flags!
766a7948191SStephan Aßmus
767a7948191SStephan Aßmus left = entry->position + entry->width;
768c97796c2SIngo Weinhold }
769c97796c2SIngo Weinhold }
770a7948191SStephan Aßmus
771a7948191SStephan Aßmus // TODO: We are not using any custom renderer here.
772a7948191SStephan Aßmus defaultRenderer.DrawHeaderBackground(this,
773a7948191SStephan Aßmus BRect(left, 0, Bounds().right + 1, bottom), updateRect, 0);
774c97796c2SIngo Weinhold }
775c97796c2SIngo Weinhold
776c97796c2SIngo Weinhold
777c97796c2SIngo Weinhold BSize
MinSize()778c97796c2SIngo Weinhold HeaderView::MinSize()
779c97796c2SIngo Weinhold {
780c97796c2SIngo Weinhold _ValidateHeadersLayout();
781c97796c2SIngo Weinhold
782c97796c2SIngo Weinhold return BLayoutUtils::ComposeSize(ExplicitMinSize(),
783c97796c2SIngo Weinhold BSize(100, fPreferredHeight - 1));
784c97796c2SIngo Weinhold }
785c97796c2SIngo Weinhold
786c97796c2SIngo Weinhold
787c97796c2SIngo Weinhold BSize
MaxSize()788c97796c2SIngo Weinhold HeaderView::MaxSize()
789c97796c2SIngo Weinhold {
790c97796c2SIngo Weinhold _ValidateHeadersLayout();
791c97796c2SIngo Weinhold
792c97796c2SIngo Weinhold return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
793c97796c2SIngo Weinhold BSize(B_SIZE_UNLIMITED, fPreferredHeight - 1));
794c97796c2SIngo Weinhold }
795c97796c2SIngo Weinhold
796c97796c2SIngo Weinhold
797c97796c2SIngo Weinhold BSize
PreferredSize()798c97796c2SIngo Weinhold HeaderView::PreferredSize()
799c97796c2SIngo Weinhold {
800c97796c2SIngo Weinhold _ValidateHeadersLayout();
801c97796c2SIngo Weinhold
802c97796c2SIngo Weinhold return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
803c97796c2SIngo Weinhold BSize(fPreferredWidth - 1, fPreferredHeight - 1));
804c97796c2SIngo Weinhold }
805c97796c2SIngo Weinhold
806c97796c2SIngo Weinhold
807c97796c2SIngo Weinhold HeaderModel*
Model() const808c97796c2SIngo Weinhold HeaderView::Model() const
809c97796c2SIngo Weinhold {
810c97796c2SIngo Weinhold return fModel;
811c97796c2SIngo Weinhold }
812c97796c2SIngo Weinhold
813c97796c2SIngo Weinhold
814a7948191SStephan Aßmus void
MouseDown(BPoint where)815a7948191SStephan Aßmus HeaderView::MouseDown(BPoint where)
816a7948191SStephan Aßmus {
817c5c59496SIngo Weinhold // get buttons and modifiers
818c5c59496SIngo Weinhold BMessage* message = Looper()->CurrentMessage();
819c5c59496SIngo Weinhold int32 buttons;
820c5c59496SIngo Weinhold if (message == NULL || message->FindInt32("buttons", &buttons) != B_OK)
821c5c59496SIngo Weinhold buttons = 0;
822c5c59496SIngo Weinhold int32 modifiers;
823c5c59496SIngo Weinhold if (message == NULL || message->FindInt32("modifiers", &modifiers) != B_OK)
824c5c59496SIngo Weinhold modifiers = 0;
825c5c59496SIngo Weinhold
826c5c59496SIngo Weinhold fState->MouseDown(where, buttons, modifiers);
827a7948191SStephan Aßmus }
828a7948191SStephan Aßmus
829a7948191SStephan Aßmus
830a7948191SStephan Aßmus void
MouseUp(BPoint where)831a7948191SStephan Aßmus HeaderView::MouseUp(BPoint where)
832a7948191SStephan Aßmus {
833c5c59496SIngo Weinhold // get buttons and modifiers
834c5c59496SIngo Weinhold BMessage* message = Looper()->CurrentMessage();
835c5c59496SIngo Weinhold int32 buttons;
836c5c59496SIngo Weinhold if (message == NULL || message->FindInt32("buttons", &buttons) != B_OK)
837c5c59496SIngo Weinhold buttons = 0;
838c5c59496SIngo Weinhold int32 modifiers;
839c5c59496SIngo Weinhold if (message == NULL || message->FindInt32("modifiers", &modifiers) != B_OK)
840c5c59496SIngo Weinhold modifiers = 0;
841c5c59496SIngo Weinhold
842c5c59496SIngo Weinhold fState->MouseUp(where, buttons, modifiers);
843a7948191SStephan Aßmus }
844a7948191SStephan Aßmus
845a7948191SStephan Aßmus
846a7948191SStephan Aßmus void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)847a7948191SStephan Aßmus HeaderView::MouseMoved(BPoint where, uint32 transit,
848a7948191SStephan Aßmus const BMessage* dragMessage)
849a7948191SStephan Aßmus {
850c5c59496SIngo Weinhold fState->MouseMoved(where, transit, dragMessage);
851a7948191SStephan Aßmus }
852a7948191SStephan Aßmus
853a7948191SStephan Aßmus
854c97796c2SIngo Weinhold status_t
SetModel(HeaderModel * model)855c97796c2SIngo Weinhold HeaderView::SetModel(HeaderModel* model)
856c97796c2SIngo Weinhold {
857c97796c2SIngo Weinhold if (model == fModel)
858c97796c2SIngo Weinhold return B_OK;
859c97796c2SIngo Weinhold
860c5c59496SIngo Weinhold _SwitchState(NULL);
861c5c59496SIngo Weinhold
862c97796c2SIngo Weinhold if (fModel != NULL) {
863c97796c2SIngo Weinhold // remove all headers
864c97796c2SIngo Weinhold for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++)
865c97796c2SIngo Weinhold entry->header->RemoveListener(this);
866c97796c2SIngo Weinhold fHeaderEntries.MakeEmpty();
867c97796c2SIngo Weinhold
868c97796c2SIngo Weinhold fModel->RemoveListener(this);
869c97796c2SIngo Weinhold fModel->ReleaseReference();
870c97796c2SIngo Weinhold }
871c97796c2SIngo Weinhold
872c97796c2SIngo Weinhold fModel = model;
873c97796c2SIngo Weinhold
874c97796c2SIngo Weinhold if (fModel != NULL) {
875c97796c2SIngo Weinhold fModel->AcquireReference();
876c97796c2SIngo Weinhold fModel->AddListener(this);
877c97796c2SIngo Weinhold
878c97796c2SIngo Weinhold // create header entries
879c97796c2SIngo Weinhold int32 headerCount = fModel->CountHeaders();
880c97796c2SIngo Weinhold for (int32 i = 0; i < headerCount; i++) {
881c97796c2SIngo Weinhold HeaderEntry* entry = new(std::nothrow) HeaderEntry(
882c97796c2SIngo Weinhold fModel->HeaderAt(i));
883c97796c2SIngo Weinhold if (entry == NULL || !fHeaderEntries.AddItem(entry)) {
884c97796c2SIngo Weinhold delete entry;
885c97796c2SIngo Weinhold return B_NO_MEMORY;
886c97796c2SIngo Weinhold }
887c97796c2SIngo Weinhold
888c97796c2SIngo Weinhold entry->header->AddListener(this);
889c97796c2SIngo Weinhold }
890c97796c2SIngo Weinhold }
891c97796c2SIngo Weinhold
892c97796c2SIngo Weinhold _InvalidateHeadersLayout(0);
893c97796c2SIngo Weinhold Invalidate();
894c97796c2SIngo Weinhold
895c97796c2SIngo Weinhold return B_OK;
896c97796c2SIngo Weinhold }
897c97796c2SIngo Weinhold
898c97796c2SIngo Weinhold
899c5c59496SIngo Weinhold BRect
HeaderFrame(int32 index) const900c5c59496SIngo Weinhold HeaderView::HeaderFrame(int32 index) const
901c5c59496SIngo Weinhold {
902c5c59496SIngo Weinhold float bottom = Bounds().Height();
903c5c59496SIngo Weinhold
904c5c59496SIngo Weinhold if (HeaderEntry* entry = fHeaderEntries.ItemAt(index)) {
905c5c59496SIngo Weinhold return BRect(entry->position, 0, entry->position + entry->width - 1,
906c5c59496SIngo Weinhold bottom);
907c5c59496SIngo Weinhold }
908c5c59496SIngo Weinhold
909c5c59496SIngo Weinhold return BRect();
910c5c59496SIngo Weinhold }
911c5c59496SIngo Weinhold
912c5c59496SIngo Weinhold
913c5c59496SIngo Weinhold int32
HeaderIndexAt(BPoint point) const914c5c59496SIngo Weinhold HeaderView::HeaderIndexAt(BPoint point) const
915c5c59496SIngo Weinhold {
916c5c59496SIngo Weinhold float x = point.x;
917c5c59496SIngo Weinhold
918c5c59496SIngo Weinhold for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++) {
919c5c59496SIngo Weinhold if (x >= entry->position && x < entry->position + entry->width)
920c5c59496SIngo Weinhold return i;
921c5c59496SIngo Weinhold }
922c5c59496SIngo Weinhold
923c5c59496SIngo Weinhold return -1;
924c5c59496SIngo Weinhold }
925c5c59496SIngo Weinhold
926c5c59496SIngo Weinhold
927c97796c2SIngo Weinhold void
AddListener(HeaderViewListener * listener)928c97796c2SIngo Weinhold HeaderView::AddListener(HeaderViewListener* listener)
929c97796c2SIngo Weinhold {
930c97796c2SIngo Weinhold fListeners.AddItem(listener);
931c97796c2SIngo Weinhold }
932c97796c2SIngo Weinhold
933c97796c2SIngo Weinhold
934c97796c2SIngo Weinhold void
RemoveListener(HeaderViewListener * listener)935c97796c2SIngo Weinhold HeaderView::RemoveListener(HeaderViewListener* listener)
936c97796c2SIngo Weinhold {
937c97796c2SIngo Weinhold fListeners.RemoveItem(listener);
938c97796c2SIngo Weinhold }
939c97796c2SIngo Weinhold
940c97796c2SIngo Weinhold
941c97796c2SIngo Weinhold void
HeaderAdded(HeaderModel * model,int32 index)942c97796c2SIngo Weinhold HeaderView::HeaderAdded(HeaderModel* model, int32 index)
943c97796c2SIngo Weinhold {
944c97796c2SIngo Weinhold if (Header* header = fModel->HeaderAt(index)) {
945c97796c2SIngo Weinhold HeaderEntry* entry = new(std::nothrow) HeaderEntry(
946c97796c2SIngo Weinhold fModel->HeaderAt(index));
947c97796c2SIngo Weinhold if (entry == NULL || !fHeaderEntries.AddItem(entry)) {
948c97796c2SIngo Weinhold delete entry;
949c97796c2SIngo Weinhold return;
950c97796c2SIngo Weinhold }
951c97796c2SIngo Weinhold
952c97796c2SIngo Weinhold header->AddListener(this);
953c97796c2SIngo Weinhold _InvalidateHeadersLayout(index);
954c97796c2SIngo Weinhold }
955c97796c2SIngo Weinhold }
956c97796c2SIngo Weinhold
957c97796c2SIngo Weinhold
958c97796c2SIngo Weinhold void
HeaderRemoved(HeaderModel * model,int32 index)959c97796c2SIngo Weinhold HeaderView::HeaderRemoved(HeaderModel* model, int32 index)
960c97796c2SIngo Weinhold {
961c97796c2SIngo Weinhold if (HeaderEntry* entry = fHeaderEntries.RemoveItemAt(index)) {
962c97796c2SIngo Weinhold entry->header->RemoveListener(this);
963c97796c2SIngo Weinhold _InvalidateHeadersLayout(index);
964c97796c2SIngo Weinhold }
965c97796c2SIngo Weinhold }
966c97796c2SIngo Weinhold
967c97796c2SIngo Weinhold
968c97796c2SIngo Weinhold void
HeaderMoved(HeaderModel * model,int32 fromIndex,int32 toIndex)969c97796c2SIngo Weinhold HeaderView::HeaderMoved(HeaderModel* model, int32 fromIndex, int32 toIndex)
970c97796c2SIngo Weinhold {
971c97796c2SIngo Weinhold _InvalidateHeadersLayout(std::min(fromIndex, toIndex));
972c97796c2SIngo Weinhold }
973c97796c2SIngo Weinhold
974c97796c2SIngo Weinhold
975c97796c2SIngo Weinhold void
HeaderWidthChanged(Header * header)976e558530eSIngo Weinhold HeaderView::HeaderWidthChanged(Header* header)
977e558530eSIngo Weinhold {
978e558530eSIngo Weinhold _HeaderPropertiesChanged(header, true, true);
979e558530eSIngo Weinhold }
980e558530eSIngo Weinhold
981e558530eSIngo Weinhold
982e558530eSIngo Weinhold void
HeaderWidthRestrictionsChanged(Header * header)983e558530eSIngo Weinhold HeaderView::HeaderWidthRestrictionsChanged(Header* header)
984e558530eSIngo Weinhold {
985e558530eSIngo Weinhold // TODO:...
986e558530eSIngo Weinhold }
987e558530eSIngo Weinhold
988e558530eSIngo Weinhold
989e558530eSIngo Weinhold void
HeaderValueChanged(Header * header)990e558530eSIngo Weinhold HeaderView::HeaderValueChanged(Header* header)
991e558530eSIngo Weinhold {
992e558530eSIngo Weinhold _HeaderPropertiesChanged(header, true, false);
993e558530eSIngo Weinhold }
994e558530eSIngo Weinhold
995e558530eSIngo Weinhold
996e558530eSIngo Weinhold void
HeaderRendererChanged(Header * header)997e558530eSIngo Weinhold HeaderView::HeaderRendererChanged(Header* header)
998e558530eSIngo Weinhold {
999e558530eSIngo Weinhold _HeaderPropertiesChanged(header, true, true);
1000e558530eSIngo Weinhold }
1001e558530eSIngo Weinhold
1002e558530eSIngo Weinhold
1003e558530eSIngo Weinhold void
_HeaderPropertiesChanged(Header * header,bool redrawNeeded,bool relayoutNeeded)1004e558530eSIngo Weinhold HeaderView::_HeaderPropertiesChanged(Header* header, bool redrawNeeded,
1005c97796c2SIngo Weinhold bool relayoutNeeded)
1006c97796c2SIngo Weinhold {
1007c97796c2SIngo Weinhold if (!redrawNeeded && !relayoutNeeded)
1008c97796c2SIngo Weinhold return;
1009c97796c2SIngo Weinhold
1010c97796c2SIngo Weinhold int32 index = fModel->IndexOfHeader(header);
1011c97796c2SIngo Weinhold
1012c97796c2SIngo Weinhold if (relayoutNeeded)
1013c97796c2SIngo Weinhold _InvalidateHeadersLayout(index);
1014c97796c2SIngo Weinhold else if (redrawNeeded)
1015c97796c2SIngo Weinhold _InvalidateHeaders(index, index + 1);
1016c97796c2SIngo Weinhold }
1017c97796c2SIngo Weinhold
1018c97796c2SIngo Weinhold
1019c97796c2SIngo Weinhold void
_InvalidateHeadersLayout(int32 firstIndex)1020c97796c2SIngo Weinhold HeaderView::_InvalidateHeadersLayout(int32 firstIndex)
1021c97796c2SIngo Weinhold {
1022c97796c2SIngo Weinhold if (!fLayoutValid)
1023c97796c2SIngo Weinhold return;
1024c97796c2SIngo Weinhold
1025c97796c2SIngo Weinhold fLayoutValid = false;
1026c97796c2SIngo Weinhold InvalidateLayout();
1027c97796c2SIngo Weinhold Invalidate();
1028c97796c2SIngo Weinhold }
1029c97796c2SIngo Weinhold
1030c97796c2SIngo Weinhold
1031c97796c2SIngo Weinhold void
_InvalidateHeaders(int32 firstIndex,int32 endIndex)1032c97796c2SIngo Weinhold HeaderView::_InvalidateHeaders(int32 firstIndex, int32 endIndex)
1033c97796c2SIngo Weinhold {
1034c97796c2SIngo Weinhold Invalidate();
1035c97796c2SIngo Weinhold // TODO: Be less lazy!
1036c97796c2SIngo Weinhold }
1037c97796c2SIngo Weinhold
1038c97796c2SIngo Weinhold
1039c97796c2SIngo Weinhold void
_ValidateHeadersLayout()1040c97796c2SIngo Weinhold HeaderView::_ValidateHeadersLayout()
1041c97796c2SIngo Weinhold {
1042c97796c2SIngo Weinhold if (fLayoutValid)
1043c97796c2SIngo Weinhold return;
1044c97796c2SIngo Weinhold
1045c97796c2SIngo Weinhold DefaultHeaderRenderer defaultRenderer;
1046c97796c2SIngo Weinhold
1047c97796c2SIngo Weinhold int32 headerCount = fHeaderEntries.CountItems();
1048c97796c2SIngo Weinhold float position = 0;
1049c97796c2SIngo Weinhold fPreferredWidth = 0;
1050c97796c2SIngo Weinhold fPreferredHeight = 0;
1051c97796c2SIngo Weinhold
1052c97796c2SIngo Weinhold for (int32 i = 0; i < headerCount; i++) {
1053c97796c2SIngo Weinhold HeaderEntry* entry = fHeaderEntries.ItemAt(i);
1054c97796c2SIngo Weinhold entry->position = position;
1055c97796c2SIngo Weinhold if (Header* header = fModel->HeaderAt(i)) {
1056c97796c2SIngo Weinhold entry->width = header->Width();
1057c97796c2SIngo Weinhold fPreferredWidth += header->PreferredWidth();
1058c97796c2SIngo Weinhold } else
1059c97796c2SIngo Weinhold entry->width = 0;
1060c97796c2SIngo Weinhold
1061c97796c2SIngo Weinhold position = entry->position + entry->width;
1062c97796c2SIngo Weinhold
1063c97796c2SIngo Weinhold if (Header* header = fModel->HeaderAt(i)) {
1064c97796c2SIngo Weinhold HeaderRenderer* renderer = header->GetHeaderRenderer();
1065c97796c2SIngo Weinhold if (renderer == NULL)
1066c97796c2SIngo Weinhold renderer = &defaultRenderer;
1067c97796c2SIngo Weinhold
1068c97796c2SIngo Weinhold float height = renderer->HeaderHeight(this, header);
1069c97796c2SIngo Weinhold if (height > fPreferredHeight)
1070c97796c2SIngo Weinhold fPreferredHeight = height;
1071c97796c2SIngo Weinhold }
1072c97796c2SIngo Weinhold }
1073c97796c2SIngo Weinhold
1074c97796c2SIngo Weinhold fLayoutValid = true;
1075c97796c2SIngo Weinhold }
1076c97796c2SIngo Weinhold
1077c97796c2SIngo Weinhold
1078c5c59496SIngo Weinhold void
_SwitchState(State * newState)1079c5c59496SIngo Weinhold HeaderView::_SwitchState(State* newState)
1080c5c59496SIngo Weinhold {
1081c5c59496SIngo Weinhold if (newState == NULL)
1082c5c59496SIngo Weinhold newState = fDefaultState;
1083c5c59496SIngo Weinhold
1084c5c59496SIngo Weinhold fState->Leaving(newState);
1085c5c59496SIngo Weinhold newState->Entering(fState);
1086c5c59496SIngo Weinhold
1087c5c59496SIngo Weinhold if (fState != fDefaultState)
1088c5c59496SIngo Weinhold delete fState;
1089c5c59496SIngo Weinhold
1090c5c59496SIngo Weinhold fState = newState;
1091c5c59496SIngo Weinhold }
1092c5c59496SIngo Weinhold
1093c5c59496SIngo Weinhold
1094c97796c2SIngo Weinhold // #pragma mark - HeaderViewListener
1095c97796c2SIngo Weinhold
1096c97796c2SIngo Weinhold
~HeaderViewListener()1097c97796c2SIngo Weinhold HeaderViewListener::~HeaderViewListener()
1098c97796c2SIngo Weinhold {
1099c97796c2SIngo Weinhold }
1100