1 /* 2 * Copyright 2015 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * John Scipione, jscipione@gmail.com 7 */ 8 9 10 #include <Spinner.h> 11 12 #include <stdint.h> 13 #include <stdlib.h> 14 15 #include <PropertyInfo.h> 16 #include <String.h> 17 #include <TextView.h> 18 19 20 static property_info sProperties[] = { 21 { 22 "MaxValue", 23 { B_GET_PROPERTY, 0 }, 24 { B_DIRECT_SPECIFIER, 0 }, 25 "Returns the maximum value of the spinner.", 26 0, 27 { B_INT32_TYPE } 28 }, 29 { 30 "MaxValue", 31 { B_SET_PROPERTY, 0 }, 32 { B_DIRECT_SPECIFIER, 0}, 33 "Sets the maximum value of the spinner.", 34 0, 35 { B_INT32_TYPE } 36 }, 37 38 { 39 "MinValue", 40 { B_GET_PROPERTY, 0 }, 41 { B_DIRECT_SPECIFIER, 0 }, 42 "Returns the minimum value of the spinner.", 43 0, 44 { B_INT32_TYPE } 45 }, 46 { 47 "MinValue", 48 { B_SET_PROPERTY, 0 }, 49 { B_DIRECT_SPECIFIER, 0}, 50 "Sets the minimum value of the spinner.", 51 0, 52 { B_INT32_TYPE } 53 }, 54 55 { 56 "Value", 57 { B_GET_PROPERTY, 0 }, 58 { B_DIRECT_SPECIFIER, 0 }, 59 "Returns the value of the spinner.", 60 0, 61 { B_INT32_TYPE } 62 }, 63 { 64 "Value", 65 { B_SET_PROPERTY, 0 }, 66 { B_DIRECT_SPECIFIER, 0}, 67 "Sets the value of the spinner.", 68 0, 69 { B_INT32_TYPE } 70 }, 71 72 { 0 } 73 }; 74 75 76 // #pragma mark - BSpinner 77 78 79 BSpinner::BSpinner(BRect frame, const char* name, const char* label, 80 BMessage* message, uint32 resizingMode, uint32 flags) 81 : 82 BAbstractSpinner(frame, name, label, message, resizingMode, flags) 83 { 84 _InitObject(); 85 } 86 87 88 BSpinner::BSpinner(const char* name, const char* label, 89 BMessage* message, uint32 flags) 90 : 91 BAbstractSpinner(name, label, message, flags) 92 { 93 _InitObject(); 94 } 95 96 97 BSpinner::BSpinner(BMessage* data) 98 : 99 BAbstractSpinner(data) 100 { 101 _InitObject(); 102 103 if (data->FindInt32("_min", &fMinValue) != B_OK) 104 fMinValue = INT32_MIN; 105 106 if (data->FindInt32("_max", &fMaxValue) != B_OK) 107 fMaxValue = INT32_MAX; 108 } 109 110 111 BSpinner::~BSpinner() 112 { 113 } 114 115 116 BArchivable* 117 BSpinner::Instantiate(BMessage* data) 118 { 119 if (validate_instantiation(data, "Spinner")) 120 return new BSpinner(data); 121 122 return NULL; 123 } 124 125 126 status_t 127 BSpinner::Archive(BMessage* data, bool deep) const 128 { 129 status_t status = BAbstractSpinner::Archive(data, deep); 130 data->AddString("class", "Spinner"); 131 132 if (status == B_OK) 133 status = data->AddInt32("_min", fMinValue); 134 135 if (status == B_OK) 136 status = data->AddInt32("_max", fMaxValue); 137 138 return status; 139 } 140 141 142 status_t 143 BSpinner::GetSupportedSuites(BMessage* message) 144 { 145 message->AddString("suites", "suite/vnd.Haiku-intenger-spinner"); 146 147 BPropertyInfo prop_info(sProperties); 148 message->AddFlat("messages", &prop_info); 149 150 return BView::GetSupportedSuites(message); 151 } 152 153 154 void 155 BSpinner::AttachedToWindow() 156 { 157 SetValue(Value()); 158 159 BAbstractSpinner::AttachedToWindow(); 160 } 161 162 163 void 164 BSpinner::Decrement() 165 { 166 SetValue(Value() - 1); 167 } 168 169 170 void 171 BSpinner::Increment() 172 { 173 SetValue(Value() + 1); 174 } 175 176 177 void 178 BSpinner::SetEnabled(bool enable) 179 { 180 if (IsEnabled() == enable) 181 return; 182 183 SetIncrementEnabled(enable && Value() < fMaxValue); 184 SetDecrementEnabled(enable && Value() > fMinValue); 185 186 BAbstractSpinner::SetEnabled(enable); 187 } 188 189 190 void 191 BSpinner::SetMinValue(int32 min) 192 { 193 fMinValue = min; 194 SetValue(Value()); 195 } 196 197 198 void 199 BSpinner::SetMaxValue(int32 max) 200 { 201 fMaxValue = max; 202 SetValue(Value()); 203 } 204 205 206 void 207 BSpinner::Range(int32* min, int32* max) 208 { 209 *min = fMinValue; 210 *max = fMaxValue; 211 } 212 213 214 void 215 BSpinner::SetRange(int32 min, int32 max) 216 { 217 SetMinValue(min); 218 SetMaxValue(max); 219 } 220 221 222 void 223 BSpinner::SetValue(int32 value) 224 { 225 // clip to range 226 if (value < fMinValue) 227 value = fMinValue; 228 else if (value > fMaxValue) 229 value = fMaxValue; 230 231 // update the text view 232 BString valueString; 233 valueString << value; 234 TextView()->SetText(valueString.String()); 235 236 // update the up and down arrows 237 SetIncrementEnabled(IsEnabled() && value < fMaxValue); 238 SetDecrementEnabled(IsEnabled() && value > fMinValue); 239 240 if (value == Value()) 241 return; 242 243 BControl::SetValue(value); 244 ((int32*)_reserved)[0] = Value(); 245 246 ValueChanged(); 247 248 Invoke(); 249 Invalidate(); 250 } 251 252 253 void 254 BSpinner::SetValueFromText() 255 { 256 SetValue(atol(TextView()->Text())); 257 } 258 259 260 // #pragma mark - BSpinner private methods 261 262 263 void 264 BSpinner::_InitObject() 265 { 266 fMinValue = INT32_MIN; 267 fMaxValue = INT32_MAX; 268 269 TextView()->SetAlignment(B_ALIGN_RIGHT); 270 for (uint32 c = 0; c <= 42; c++) 271 TextView()->DisallowChar(c); 272 273 TextView()->DisallowChar(','); 274 275 for (uint32 c = 46; c <= 47; c++) 276 TextView()->DisallowChar(c); 277 278 for (uint32 c = 58; c <= 127; c++) 279 TextView()->DisallowChar(c); 280 } 281 282 283 // FBC padding 284 285 void BSpinner::_ReservedSpinner20() {} 286 void BSpinner::_ReservedSpinner19() {} 287 void BSpinner::_ReservedSpinner18() {} 288 void BSpinner::_ReservedSpinner17() {} 289 void BSpinner::_ReservedSpinner16() {} 290 void BSpinner::_ReservedSpinner15() {} 291 void BSpinner::_ReservedSpinner14() {} 292 void BSpinner::_ReservedSpinner13() {} 293 void BSpinner::_ReservedSpinner12() {} 294 void BSpinner::_ReservedSpinner11() {} 295 void BSpinner::_ReservedSpinner10() {} 296 void BSpinner::_ReservedSpinner9() {} 297 void BSpinner::_ReservedSpinner8() {} 298 void BSpinner::_ReservedSpinner7() {} 299 void BSpinner::_ReservedSpinner6() {} 300 void BSpinner::_ReservedSpinner5() {} 301 void BSpinner::_ReservedSpinner4() {} 302 void BSpinner::_ReservedSpinner3() {} 303 void BSpinner::_ReservedSpinner2() {} 304 void BSpinner::_ReservedSpinner1() {} 305