1 /*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Stephan Aßmus <superstippi@gmx.de>
7 */
8
9 #include "IconOptionsControl.h"
10
11 #include <stdio.h>
12
13 #include <Window.h>
14
15 #include "IconButton.h"
16
17 #define LABEL_DIST 8.0
18
19 // constructor
IconOptionsControl(const char * name,const char * label,BMessage * message,BHandler * target)20 IconOptionsControl::IconOptionsControl(const char* name,
21 const char* label,
22 BMessage* message,
23 BHandler* target)
24 : MView(),
25 BControl(BRect(0.0, 0.0, 10.0, 10.0), name, label, message,
26 B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
27 fTargetCache(target)
28 {
29 if (Label()) {
30 labelwidth = StringWidth(Label()) + LABEL_DIST;
31 } else {
32 labelwidth = 0.0;
33 }
34 }
35
36 // destructor
~IconOptionsControl()37 IconOptionsControl::~IconOptionsControl()
38 {
39 }
40
41 // layoutprefs
42 minimax
layoutprefs()43 IconOptionsControl::layoutprefs()
44 {
45 // sanity checks
46 if (rolemodel)
47 labelwidth = rolemodel->LabelWidth();
48 if (labelwidth < LabelWidth())
49 labelwidth = LabelWidth();
50
51 mpm.mini.x = 0.0 + labelwidth + 5.0;
52 mpm.mini.y = 0.0;
53
54 for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
55 minimax childPrefs = button->layoutprefs();
56 mpm.mini.x += childPrefs.mini.x + 1;
57 if (mpm.mini.y < childPrefs.mini.y + 1)
58 mpm.mini.y = childPrefs.mini.y + 1;
59 }
60
61 mpm.maxi.x = mpm.mini.x;
62 mpm.maxi.y = mpm.mini.y;
63
64 mpm.weight = 1.0;
65
66 return mpm;
67 }
68
69 // layout
70 BRect
layout(BRect frame)71 IconOptionsControl::layout(BRect frame)
72 {
73 if (frame.Width() < mpm.mini.x + 1)
74 frame.right = frame.left + mpm.mini.x + 1;
75
76 MoveTo(frame.LeftTop());
77 ResizeTo(frame.Width(), frame.Height());
78
79 return Frame();
80 }
81
82 // LabelWidth
83 float
LabelWidth()84 IconOptionsControl::LabelWidth()
85 {
86 float width = ceilf(StringWidth(Label()));
87 if (width > 0.0)
88 width += LABEL_DIST;
89 return width;
90 }
91
92 // SetLabel
93 void
SetLabel(const char * label)94 IconOptionsControl::SetLabel(const char* label)
95 {
96 BControl::SetLabel(label);
97 float width = LabelWidth();
98 if (rolemodel)
99 labelwidth = rolemodel->LabelWidth() > labelwidth ?
100 rolemodel->LabelWidth() : labelwidth;
101
102 labelwidth = width > labelwidth ? width : labelwidth;
103
104 _TriggerRelayout();
105 }
106
107 // AttachedToWindow
108 void
AttachedToWindow()109 IconOptionsControl::AttachedToWindow()
110 {
111 BControl::AttachedToWindow();
112
113 SetViewColor(B_TRANSPARENT_32_BIT);
114 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
115 }
116
117 // AllAttached
118 void
AllAttached()119 IconOptionsControl::AllAttached()
120 {
121 for (int32 i = 0; IconButton* button = _FindIcon(i); i++)
122 button->SetTarget(this);
123 if (fTargetCache)
124 SetTarget(fTargetCache);
125 }
126
127 // Draw
128 void
Draw(BRect updateRect)129 IconOptionsControl::Draw(BRect updateRect)
130 {
131 FillRect(updateRect, B_SOLID_LOW);
132
133 if (Label()) {
134 if (!IsEnabled())
135 SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT));
136 else
137 SetHighColor(tint_color(LowColor(), B_DARKEN_MAX_TINT));
138
139 font_height fh;
140 GetFontHeight(&fh);
141 BPoint p(Bounds().LeftTop());
142 p.y += floorf(Bounds().Height() / 2.0 + (fh.ascent + fh.descent) / 2.0) - 2.0;
143 DrawString(Label(), p);
144 }
145 }
146
147 // FrameResized
148 void
FrameResized(float width,float height)149 IconOptionsControl::FrameResized(float width, float height)
150 {
151 _LayoutIcons(Bounds());
152 }
153
154 // SetValue
155 void
SetValue(int32 value)156 IconOptionsControl::SetValue(int32 value)
157 {
158 if (IconButton* valueButton = _FindIcon(value)) {
159 for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
160 button->SetPressed(button == valueButton);
161 }
162 }
163 }
164
165 // Value
166 int32
Value() const167 IconOptionsControl::Value() const
168 {
169 for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
170 if (button->IsPressed())
171 return i;
172 }
173 return -1;
174 }
175
176 // SetEnabled
177 void
SetEnabled(bool enable)178 IconOptionsControl::SetEnabled(bool enable)
179 {
180 for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
181 button->SetEnabled(enable);
182 }
183 BControl::SetEnabled(enable);
184 Invalidate();
185 }
186
187 // MessageReceived
188 void
MessageReceived(BMessage * message)189 IconOptionsControl::MessageReceived(BMessage* message)
190 {
191 // catch a message from the attached IconButtons to
192 // handle switching the pressed icon
193 BView* source;
194 if (message->FindPointer("be:source", (void**)&source) >= B_OK) {
195 if (IconButton* sourceIcon = dynamic_cast<IconButton*>(source)) {
196 for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
197 if (button == sourceIcon) {
198 SetValue(i);
199 break;
200 }
201 }
202 // forward the message
203 Invoke(message);
204 return;
205 }
206 }
207 BControl::MessageReceived(message);
208 }
209
210 // Invoke
211 status_t
Invoke(BMessage * message)212 IconOptionsControl::Invoke(BMessage* message)
213 {
214 return BInvoker::Invoke(message);
215 }
216
217 // AddOption
218 void
AddOption(IconButton * icon)219 IconOptionsControl::AddOption(IconButton* icon)
220 {
221 if (icon) {
222 if (!_FindIcon(0)) {
223 // first icon added, mark it
224 icon->SetPressed(true);
225 }
226 AddChild(icon);
227 icon->SetTarget(this);
228 layoutprefs();
229 _TriggerRelayout();
230 }
231 }
232
233 // _FindIcon
234 IconButton*
_FindIcon(int32 index) const235 IconOptionsControl::_FindIcon(int32 index) const
236 {
237 if (BView* view = ChildAt(index))
238 return dynamic_cast<IconButton*>(view);
239 return NULL;
240 }
241
242 // _TriggerRelayout
243 void
_TriggerRelayout()244 IconOptionsControl::_TriggerRelayout()
245 {
246 if (!Parent())
247 return;
248
249 MView* mParent = dynamic_cast<MView*>(Parent());
250 if (mParent) {
251 if (BWindow* window = Window()) {
252 window->PostMessage(M_RECALCULATE_SIZE);
253 }
254 } else {
255 _LayoutIcons(Bounds());
256 }
257 }
258
259 // _LayoutIcons
260 void
_LayoutIcons(BRect frame)261 IconOptionsControl::_LayoutIcons(BRect frame)
262 {
263 BPoint lt = frame.LeftTop();
264
265 // sanity checks
266 if (rolemodel)
267 labelwidth = rolemodel->LabelWidth();
268 if (labelwidth < LabelWidth())
269 labelwidth = LabelWidth();
270
271 lt.x += labelwidth;
272
273 for (int32 i = 0; IconButton* button = _FindIcon(i); i++) {
274 if (i == 0) {
275 lt.y = ceilf((frame.top + frame.bottom - button->mpm.mini.y) / 2.0);
276 }
277 button->MoveTo(lt);
278 button->ResizeTo(button->mpm.mini.x, button->mpm.mini.y);
279 lt = button->Frame().RightTop() + BPoint(1.0, 0.0);
280 }
281 }
282