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