1 /* 2 * Copyright 2006-2012, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "SwatchGroup.h" 10 11 #include <stdio.h> 12 13 #include "support_ui.h" 14 #include "ui_defines.h" 15 #include "rgb_hsv.h" 16 17 #include "AlphaSlider.h" 18 #include "ColorField.h" 19 #include "ColorPickerPanel.h" 20 #include "ColorSlider.h" 21 #include "CurrentColor.h" 22 #include "Group.h" 23 #include "SwatchView.h" 24 25 26 enum { 27 MSG_SET_COLOR = 'stcl', 28 MSG_COLOR_PICKER = 'clpk', 29 MSG_ALPHA_SLIDER = 'alps', 30 }; 31 32 33 #define SWATCH_VIEW_WIDTH 20 34 #define SWATCH_VIEW_HEIGHT 15 35 36 37 SwatchGroup::SwatchGroup(BRect frame) 38 : 39 BView(frame, "style view", B_FOLLOW_NONE, 0), 40 41 fCurrentColor(NULL), 42 fIgnoreNotifications(false), 43 44 fColorPickerPanel(NULL), 45 fColorPickerMode(H_SELECTED), 46 fColorPickerFrame(100.0, 100.0, 200.0, 200.0) 47 { 48 frame = BRect(0, 0, 100, 15); 49 fTopSwatchViews = new Group(frame, "top swatch group"); 50 fBottomSwatchViews = new Group(frame, "bottom swatch group"); 51 52 // create swatch views with rainbow default palette 53 float h = 0; 54 float s = 1.0; 55 float v = 1.0; 56 rgb_color color; 57 color.alpha = 255; 58 float r = 0.0f; 59 float g = 0.0f; 60 float b = 0.0f; 61 for (int32 i = 0; i < 20; i++) { 62 if (i < 10) { 63 h = ((float)i / 9.0) * 6.0; 64 } else { 65 h = ((float)(i - 9) / 10.0) * 6.0; 66 v = 0.5; 67 } 68 69 HSV_to_RGB(h, s, v, r, g, b); 70 color.red = (uint8)(255.0 * r); 71 color.green = (uint8)(255.0 * g); 72 color.blue = (uint8)(255.0 * b); 73 fSwatchViews[i] = new SwatchView("swatch", new BMessage(MSG_SET_COLOR), 74 this, color, SWATCH_VIEW_WIDTH, SWATCH_VIEW_HEIGHT); 75 76 fSwatchViews[i]->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 77 78 if (i < 10) 79 fTopSwatchViews->AddChild(fSwatchViews[i]); 80 else 81 fBottomSwatchViews->AddChild(fSwatchViews[i]); 82 } 83 84 // create current color swatch view 85 fCurrentColorSV = new SwatchView("current swatch", 86 new BMessage(MSG_COLOR_PICKER), this, color, 28.0, 28.0); 87 88 // When the color of this swatch changes via drag&drop, we want to 89 // adopt it as current color. 90 fCurrentColorSV->SetDroppedMessage(new BMessage(MSG_SET_COLOR)); 91 92 // create color field and slider 93 fColorField = new ColorField(BPoint(0.0, 0.0), H_SELECTED, 94 1.0, B_HORIZONTAL); 95 fColorSlider = new ColorSlider(BPoint(0.0, 0.0), H_SELECTED, 96 1.0, 1.0, B_HORIZONTAL); 97 fAlphaSlider = new AlphaSlider(B_HORIZONTAL, 98 new BMessage(MSG_ALPHA_SLIDER)); 99 100 // layout gui 101 fTopSwatchViews->SetSpacing(0, 0); 102 fTopSwatchViews->ResizeToPreferred(); 103 fTopSwatchViews->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 104 fBottomSwatchViews->SetSpacing(0, 0); 105 fBottomSwatchViews->ResizeToPreferred(); 106 fBottomSwatchViews->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 107 108 float paletteHeight = fBottomSwatchViews->Frame().Height() 109 + fTopSwatchViews->Frame().Height() + 1; 110 111 fTopSwatchViews->MoveTo(paletteHeight + 2, 4); 112 fBottomSwatchViews->MoveTo(paletteHeight + 2, 113 fTopSwatchViews->Frame().bottom + 1); 114 115 fCurrentColorSV->MoveTo(0, fTopSwatchViews->Frame().top); 116 fCurrentColorSV->ResizeTo(paletteHeight, paletteHeight); 117 fCurrentColorSV->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 118 119 float width = fTopSwatchViews->Frame().right 120 - fCurrentColorSV->Frame().left; 121 122 fColorField->ResizeTo(width, 40); 123 fColorField->FrameResized(width, 40); 124 fColorSlider->ResizeTo(width, 11); 125 fColorSlider->FrameResized(width, 11); 126 fAlphaSlider->ResizeTo(width, 11); 127 fAlphaSlider->FrameResized(width, 11); 128 129 fColorField->MoveTo(0, fBottomSwatchViews->Frame().bottom + 3); 130 fColorSlider->MoveTo(0, fColorField->Frame().bottom + 1); 131 fAlphaSlider->MoveTo(0, fColorSlider->Frame().bottom + 1); 132 fAlphaSlider->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 133 134 // configure self 135 ResizeTo(width, fAlphaSlider->Frame().bottom + 4); 136 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 137 138 // add views 139 AddChild(fCurrentColorSV); 140 AddChild(fTopSwatchViews); 141 AddChild(fBottomSwatchViews); 142 AddChild(fColorField); 143 AddChild(fColorSlider); 144 AddChild(fAlphaSlider); 145 } 146 147 148 SwatchGroup::~SwatchGroup() 149 { 150 SetCurrentColor(NULL); 151 } 152 153 154 void 155 SwatchGroup::ObjectChanged(const Observable* object) 156 { 157 if (object != fCurrentColor || fIgnoreNotifications) 158 return; 159 160 rgb_color color = fCurrentColor->Color(); 161 162 float h, s, v; 163 RGB_to_HSV(color.red / 255.0, color.green / 255.0, color.blue / 255.0, 164 h, s, v); 165 166 _SetColor(h, s, v, color.alpha); 167 } 168 169 170 // #pragma mark - 171 172 173 void 174 SwatchGroup::AttachedToWindow() 175 { 176 fColorField->SetTarget(this); 177 fColorSlider->SetTarget(this); 178 fAlphaSlider->SetTarget(this); 179 } 180 181 182 void 183 SwatchGroup::MessageReceived(BMessage* message) 184 { 185 switch (message->what) { 186 case MSG_SET_COLOR: 187 { 188 rgb_color color; 189 if (restore_color_from_message(message, color) == B_OK) { 190 // TODO: fix color picker panel to respect alpha 191 if (message->HasRect("panel frame")) 192 color.alpha = fAlphaSlider->Value(); 193 // 194 if (fCurrentColor != NULL) 195 fCurrentColor->SetColor(color); 196 } 197 // if message contains these fields, 198 // then it comes from the color picker panel. 199 // it also means the panel has died. 200 BRect frame; 201 SelectedColorMode mode; 202 if (message->FindRect("panel frame", &frame) == B_OK 203 && message->FindInt32("panel mode", (int32*)&mode) == B_OK) { 204 // message came from the color picker panel 205 // we remember the settings of the panel for later 206 fColorPickerFrame = frame; 207 fColorPickerMode = mode; 208 // color picker panel has quit 209 fColorPickerPanel = NULL; 210 } 211 break; 212 } 213 214 case MSG_COLOR_FIELD: 215 { 216 // get h from color slider 217 float h = ((255 - fColorSlider->Value()) / 255.0) * 6.0; 218 float s, v; 219 // s and v are comming from the message 220 if (message->FindFloat("value", &s) == B_OK 221 && message->FindFloat("value", 1, &v) == B_OK) { 222 _SetColor(h, s, v, fAlphaSlider->Value()); 223 } 224 break; 225 } 226 227 case MSG_COLOR_SLIDER: 228 { 229 float h; 230 float s, v; 231 fColorSlider->GetOtherValues(&s, &v); 232 // h is comming from the message 233 if (message->FindFloat("value", &h) == B_OK) 234 _SetColor(h, s, v, fAlphaSlider->Value()); 235 break; 236 } 237 238 case MSG_ALPHA_SLIDER: 239 { 240 float h = (1.0 - (float)fColorSlider->Value() / 255.0) * 6; 241 float s, v; 242 fColorSlider->GetOtherValues(&s, &v); 243 _SetColor(h, s, v, fAlphaSlider->Value()); 244 break; 245 } 246 247 case MSG_COLOR_PICKER: 248 { 249 rgb_color color; 250 if (restore_color_from_message(message, color) < B_OK) 251 break; 252 253 if (fColorPickerPanel == NULL) { 254 fColorPickerPanel = new ColorPickerPanel(fColorPickerFrame, 255 color, fColorPickerMode, Window(), 256 new BMessage(MSG_SET_COLOR), this); 257 fColorPickerPanel->Show(); 258 } else { 259 if (fColorPickerPanel->Lock()) { 260 fColorPickerPanel->SetColor(color); 261 fColorPickerPanel->Activate(); 262 fColorPickerPanel->Unlock(); 263 } 264 } 265 break; 266 } 267 268 default: 269 BView::MessageReceived(message); 270 break; 271 } 272 } 273 274 275 // #pragma mark - 276 277 278 void 279 SwatchGroup::SetCurrentColor(CurrentColor* color) 280 { 281 if (fCurrentColor == color) 282 return; 283 284 if (fCurrentColor != NULL) 285 fCurrentColor->RemoveObserver(this); 286 287 fCurrentColor = color; 288 289 if (fCurrentColor != NULL) { 290 fCurrentColor->AddObserver(this); 291 292 ObjectChanged(fCurrentColor); 293 } 294 } 295 296 297 // #pragma mark - 298 299 300 void 301 SwatchGroup::_SetColor(rgb_color color) 302 { 303 fCurrentColorSV->SetColor(color); 304 } 305 306 307 void 308 SwatchGroup::_SetColor(float h, float s, float v, uint8 a) 309 { 310 float r = 0.0f; 311 float g = 0.0f; 312 float b = 0.0f; 313 HSV_to_RGB(h, s, v, r, g, b); 314 315 rgb_color color; 316 color.red = (uint8)(r * 255.0); 317 color.green = (uint8)(g * 255.0); 318 color.blue = (uint8)(b * 255.0); 319 color.alpha = a; 320 321 if (!fColorField->IsTracking()) { 322 fColorField->SetFixedValue(h); 323 fColorField->SetMarkerToColor(color); 324 } 325 if (!fColorSlider->IsTracking()) { 326 fColorSlider->SetOtherValues(s, v); 327 fColorSlider->SetValue(255 - (int32)((h / 6.0) * 255.0 + 0.5)); 328 } 329 if (!fAlphaSlider->IsTracking()) { 330 fAlphaSlider->SetColor(color); 331 fAlphaSlider->SetValue(a); 332 } 333 334 fIgnoreNotifications = true; 335 336 if (fCurrentColor) 337 fCurrentColor->SetColor(color); 338 _SetColor(color); 339 340 fIgnoreNotifications = false; 341 } 342