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