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
OptionValueView(OptionProperty * property)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
~OptionValueView()35 OptionValueView::~OptionValueView()
36 {
37 }
38
39 // Draw
40 void
Draw(BRect updateRect)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
FrameResized(float width,float height)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
MakeFocus(bool focused)103 OptionValueView::MakeFocus(bool focused)
104 {
105 PropertyEditorView::MakeFocus(focused);
106 Invalidate();
107 }
108
109 // MessageReceived
110 void
MessageReceived(BMessage * message)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
MouseDown(BPoint where)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
KeyDown(const char * bytes,int32 numBytes)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
SetEnabled(bool enabled)190 OptionValueView::SetEnabled(bool enabled)
191 {
192 if (fEnabled != enabled) {
193 fEnabled = enabled;
194 Invalidate();
195 }
196 }
197
198 // ValueChanged
199 void
ValueChanged()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
AdoptProperty(Property * property)214 OptionValueView::AdoptProperty(Property* property)
215 {
216 OptionProperty* p = dynamic_cast<OptionProperty*>(property);
217 if (p) {
218 BString currentOption;
219 p->GetCurrentOption(¤tOption);
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*
GetProperty() const235 OptionValueView::GetProperty() const
236 {
237 return fProperty;
238 }
239
240