xref: /haiku/src/apps/icon-o-matic/generic/gui/IconOptionsControl.cpp (revision 128277c969aa806add78941cd2972754c37a1572)
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