xref: /haiku/src/apps/icon-o-matic/generic/property/view/specific_properties/OptionValueView.cpp (revision 16d5c24e533eb14b7b8a99ee9f3ec9ba66335b1e)
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 "OptionValueView.h"
10 
11 #include <stdio.h>
12 
13 #include <Font.h>
14 #include <MenuItem.h>
15 #include <Message.h>
16 #include <PopUpMenu.h>
17 #include <Region.h>
18 
19 enum {
20 	MSG_OPTION_CHANGED = 'opch',
21 };
22 
23 // constructor
24 OptionValueView::OptionValueView(OptionProperty* property)
25 	: PropertyEditorView(),
26 	  fProperty(property),
27 	  fCurrentOption(""),
28 	  fEnabled(true)
29 {
30 	if (fProperty)
31 		fProperty->GetCurrentOption(&fCurrentOption);
32 }
33 
34 // destructor
35 OptionValueView::~OptionValueView()
36 {
37 }
38 
39 // Draw
40 void
41 OptionValueView::Draw(BRect updateRect)
42 {
43 	BRect b(Bounds());
44 	// focus indication
45 	if (IsFocus()) {
46 		SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
47 		StrokeRect(b);
48 		b.InsetBy(1.0, 1.0);
49 		BRegion clipping;
50 		clipping.Include(b);
51 		ConstrainClippingRegion(&clipping);
52 		b.left --;
53 	}
54 	// background
55 	FillRect(b, B_SOLID_LOW);
56 
57 	rgb_color labelColor = LowColor();
58 	if (fEnabled)
59 		labelColor = tint_color(labelColor, B_DARKEN_MAX_TINT);
60 	else
61 		labelColor = tint_color(labelColor, B_DISABLED_LABEL_TINT);
62 
63 	SetHighColor(labelColor);
64 
65 	b.InsetBy(2.0, 1.0);
66 
67 	float center = floorf(b.top + b.Height() / 2.0);
68 
69 	BPoint arrow[3];
70 	arrow[0] = BPoint(b.left, center - 3.0);
71 	arrow[1] = BPoint(b.left, center + 3.0);
72 	arrow[2] = BPoint(b.left + 3.0, center);
73 
74 	FillPolygon(arrow, 3);
75 
76 	b.left += 6.0;
77 
78 	BFont font;
79 	GetFont(&font);
80 
81 	font_height fh;
82 	font.GetHeight(&fh);
83 
84 	BString truncated(fCurrentOption);
85 	font.TruncateString(&truncated, B_TRUNCATE_END, b.Width());
86 
87 	DrawString(fCurrentOption.String(), BPoint(b.left, floorf(center + fh.ascent / 2.0)));
88 }
89 
90 // FrameResized
91 void
92 OptionValueView::FrameResized(float width, float height)
93 {
94 /*	float radius = ceilf((height - 6.0) / 2.0);
95 	float centerX = floorf(Bounds().left + width / 2.0);
96 	float centerY = floorf(Bounds().top + height / 2.0);
97 	fCheckBoxRect.Set(centerX - radius, centerY - radius,
98 					  centerX + radius, centerY + radius);*/
99 }
100 
101 // MakeFocus
102 void
103 OptionValueView::MakeFocus(bool focused)
104 {
105 	PropertyEditorView::MakeFocus(focused);
106 	Invalidate();
107 }
108 
109 // MessageReceived
110 void
111 OptionValueView::MessageReceived(BMessage* message)
112 {
113 	switch (message->what) {
114 		case MSG_OPTION_CHANGED:
115 			if (fProperty) {
116 				int32 id;
117 				if (message->FindInt32("id", &id) >= B_OK) {
118 					fProperty->SetCurrentOptionID(id);
119 					ValueChanged();
120 				}
121 			}
122 			break;
123 		default:
124 			PropertyEditorView::MessageReceived(message);
125 			break;
126 	}
127 }
128 
129 // MouseDown
130 void
131 OptionValueView::MouseDown(BPoint where)
132 {
133 	if (BView* parent = Parent())
134 		parent->MouseDown(ConvertToParent(where));
135 
136 	if (fProperty) {
137 		BPopUpMenu* menu = new BPopUpMenu("option popup", false, false);
138 		BString name;
139 		int32 id;
140 		for (int32 i = 0; fProperty->GetOption(i, &name, &id); i++) {
141 			BMessage* message = new BMessage(MSG_OPTION_CHANGED);
142 			message->AddInt32("id", id);
143 			BMenuItem* item = new BMenuItem(name.String(), message);
144 			menu->AddItem(item);
145 			if (id == fProperty->CurrentOptionID())
146 				item->SetMarked(true);
147 		}
148 		menu->SetTargetForItems(this);
149 		menu->SetAsyncAutoDestruct(true);
150 		menu->SetFont(be_plain_font);
151 		menu->SetEnabled(fEnabled);
152 
153 		where = ConvertToScreen(where);
154 		BRect mouseRect(where, where);
155 		mouseRect.InsetBy(-10.0, -10.0);
156 		where += BPoint(5.0, 5.0);
157 		menu->Go(where, true, false, mouseRect, true);
158 	}
159 }
160 
161 // KeyDown
162 void
163 OptionValueView::KeyDown(const char* bytes, int32 numBytes)
164 {
165 	bool handled = fEnabled;
166 	if (fEnabled && numBytes > 0) {
167 		switch (bytes[0]) {
168 			case B_LEFT_ARROW:
169 			case B_UP_ARROW:
170 				fProperty->SetOptionAtOffset(-1);
171 				ValueChanged();
172 				break;
173 
174 			case B_RIGHT_ARROW:
175 			case B_DOWN_ARROW:
176 				fProperty->SetOptionAtOffset(1);
177 				ValueChanged();
178 				break;
179 			default:
180 				handled = false;
181 				break;
182 		}
183 	}
184 	if (!handled)
185 		PropertyEditorView::KeyDown(bytes, numBytes);
186 }
187 
188 // SetEnabled
189 void
190 OptionValueView::SetEnabled(bool enabled)
191 {
192 	if (fEnabled != enabled) {
193 		fEnabled = enabled;
194 		Invalidate();
195 	}
196 }
197 
198 // ValueChanged
199 void
200 OptionValueView::ValueChanged()
201 {
202 	if (fProperty) {
203 		fProperty->GetCurrentOption(&fCurrentOption);
204 		BRect b(Bounds());
205 		b.InsetBy(1.0, 1.0);
206 		b.left += 5.0;
207 		Invalidate(b);
208 	}
209 	PropertyEditorView::ValueChanged();
210 }
211 
212 // AdoptProperty
213 bool
214 OptionValueView::AdoptProperty(Property* property)
215 {
216 	OptionProperty* p = dynamic_cast<OptionProperty*>(property);
217 	if (p) {
218 		BString currentOption;
219 		p->GetCurrentOption(&currentOption);
220 		if (currentOption != fCurrentOption) {
221 			fCurrentOption = currentOption;
222 			BRect b(Bounds());
223 			b.InsetBy(1.0, 1.0);
224 			b.left += 5.0;
225 			Invalidate(b);
226 		}
227 		fProperty = p;
228 		return true;
229 	}
230 	return false;
231 }
232 
233 // GetProperty
234 Property*
235 OptionValueView::GetProperty() const
236 {
237 	return fProperty;
238 }
239 
240