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(¤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* 235 OptionValueView::GetProperty() const 236 { 237 return fProperty; 238 } 239 240