1 /* 2 * Copyright 2002-2016 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * DarkWyrm, darkwyrm@earthlink.net 7 * John Scipione, jscipione@gmail.com 8 */ 9 10 11 #include "ColorPreview.h" 12 13 #include <algorithm> 14 15 #include <stdio.h> 16 17 #include <Bitmap.h> 18 #include <Message.h> 19 #include <MessageRunner.h> 20 #include <String.h> 21 #include <View.h> 22 #include <Window.h> 23 24 #include "defs.h" 25 26 27 28 static const int32 kMsgMessageRunner = 'MsgR'; 29 30 31 // #pragma mark - ColorPreview 32 33 34 ColorPreview::ColorPreview(BRect frame, BMessage* message, uint32 resizingMode, 35 uint32 flags) 36 : 37 BControl(frame, "ColorPreview", "", message, resizingMode, 38 flags | B_WILL_DRAW), 39 fColor(ui_color(B_PANEL_BACKGROUND_COLOR)), 40 fDisabledColor((rgb_color){ 128, 128, 128 }), 41 fMessageRunner(NULL), 42 fIsRectangle(true) 43 { 44 SetViewColor(B_TRANSPARENT_COLOR); 45 SetLowColor(0, 0, 0); 46 } 47 48 49 ColorPreview::~ColorPreview(void) 50 { 51 } 52 53 54 void 55 ColorPreview::Draw(BRect updateRect) 56 { 57 rgb_color color; 58 if (IsEnabled()) 59 color = fColor; 60 else 61 color = fDisabledColor; 62 63 if (fIsRectangle) { 64 if (IsEnabled()) { 65 rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); 66 rgb_color shadow = tint_color(background, B_DARKEN_1_TINT); 67 rgb_color darkShadow = tint_color(background, B_DARKEN_3_TINT); 68 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT); 69 70 BRect bounds(Bounds()); 71 72 BeginLineArray(4); 73 AddLine(BPoint(bounds.left, bounds.bottom), 74 BPoint(bounds.left, bounds.top), shadow); 75 AddLine(BPoint(bounds.left + 1.0, bounds.top), 76 BPoint(bounds.right, bounds.top), shadow); 77 AddLine(BPoint(bounds.right, bounds.top + 1.0), 78 BPoint(bounds.right, bounds.bottom), light); 79 AddLine(BPoint(bounds.right - 1.0, bounds.bottom), 80 BPoint(bounds.left + 1.0, bounds.bottom), light); 81 EndLineArray(); 82 bounds.InsetBy(1.0, 1.0); 83 84 BeginLineArray(4); 85 AddLine(BPoint(bounds.left, bounds.bottom), 86 BPoint(bounds.left, bounds.top), darkShadow); 87 AddLine(BPoint(bounds.left + 1.0, bounds.top), 88 BPoint(bounds.right, bounds.top), darkShadow); 89 AddLine(BPoint(bounds.right, bounds.top + 1.0), 90 BPoint(bounds.right, bounds.bottom), background); 91 AddLine(BPoint(bounds.right - 1.0, bounds.bottom), 92 BPoint(bounds.left + 1.0, bounds.bottom), background); 93 EndLineArray(); 94 bounds.InsetBy(1.0, 1.0); 95 96 SetHighColor(color); 97 FillRect(bounds); 98 } else { 99 SetHighColor(color); 100 FillRect(Bounds()); 101 } 102 } else { 103 // fill background 104 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 105 FillRect(updateRect); 106 107 SetHighColor(color); 108 FillEllipse(Bounds()); 109 110 if (IsEnabled()) 111 StrokeEllipse(Bounds(), B_SOLID_LOW); 112 } 113 } 114 115 116 void 117 ColorPreview::MessageReceived(BMessage* message) 118 { 119 // If we received a dropped message, see if it contains color data 120 if (message->WasDropped()) { 121 rgb_color* color; 122 ssize_t size; 123 if (message->FindData(kRGBColor, B_RGB_COLOR_TYPE, 124 (const void**)&color, &size) == B_OK) { 125 BMessage setColorMessage(SET_CURRENT_COLOR); 126 setColorMessage.AddData(kRGBColor, B_RGB_COLOR_TYPE, color, 127 sizeof(rgb_color)); 128 Invoke(&setColorMessage); 129 } 130 } else if ((int32)message->what == kMsgMessageRunner) { 131 BPoint where; 132 uint32 buttons; 133 GetMouse(&where, &buttons); 134 135 _DragColor(where); 136 } 137 138 BControl::MessageReceived(message); 139 } 140 141 142 void 143 ColorPreview::MouseDown(BPoint where) 144 { 145 BWindow* window = Window(); 146 if (window != NULL) 147 window->Activate(); 148 149 fMessageRunner = new BMessageRunner(this, new BMessage(kMsgMessageRunner), 150 300000, 1); 151 152 SetMouseEventMask(B_POINTER_EVENTS, 153 B_SUSPEND_VIEW_FOCUS | B_LOCK_WINDOW_FOCUS); 154 155 BRect rect = Bounds().InsetByCopy(2.0f, 2.0f); 156 rect.top = roundf(rect.bottom / 2.0f + 1); 157 158 if (rect.Contains(where)) { 159 Invalidate(); 160 Invoke(); 161 } 162 163 BControl::MouseDown(where); 164 } 165 166 167 void 168 ColorPreview::MouseMoved(BPoint where, uint32 transit, const BMessage* message) 169 { 170 if (fMessageRunner != NULL) 171 _DragColor(where); 172 173 BControl::MouseMoved(where, transit, message); 174 } 175 176 177 void 178 ColorPreview::MouseUp(BPoint where) 179 { 180 delete fMessageRunner; 181 fMessageRunner = NULL; 182 183 BControl::MouseUp(where); 184 } 185 186 187 rgb_color 188 ColorPreview::Color(void) const 189 { 190 return fColor; 191 } 192 193 194 void 195 ColorPreview::SetColor(rgb_color color) 196 { 197 color.alpha = 255; 198 199 SetHighColor(color); 200 fColor = color; 201 202 Invalidate(); 203 Invoke(); 204 } 205 206 207 void 208 ColorPreview::SetColor(uint8 red, uint8 green, uint8 blue) 209 { 210 SetHighColor(red, green, blue); 211 fColor.red = red; 212 fColor.green = green; 213 fColor.blue = blue; 214 fColor.alpha = 255; 215 216 Invalidate(); 217 Invoke(); 218 } 219 220 221 void 222 ColorPreview::SetMode(bool rectangle) 223 { 224 fIsRectangle = rectangle; 225 } 226 227 228 // #pragma mark - ColorPreview private methods 229 230 231 void 232 ColorPreview::_DragColor(BPoint where) 233 { 234 BString hexStr; 235 hexStr.SetToFormat("#%.2X%.2X%.2X", fColor.red, fColor.green, fColor.blue); 236 237 BMessage message(B_PASTE); 238 message.AddData("text/plain", B_MIME_TYPE, hexStr.String(), 239 hexStr.Length()); 240 message.AddData(kRGBColor, B_RGB_COLOR_TYPE, &fColor, sizeof(fColor)); 241 242 BRect rect(0.0f, 0.0f, 20.0f, 20.0f); 243 244 BBitmap* bitmap = new BBitmap(rect, B_RGB32, true); 245 if (bitmap->Lock()) { 246 BView* view = new BView(rect, "", B_FOLLOW_NONE, B_WILL_DRAW); 247 bitmap->AddChild(view); 248 249 view->SetHighColor(B_TRANSPARENT_COLOR); 250 view->FillRect(view->Bounds()); 251 252 ++rect.top; 253 ++rect.left; 254 255 view->SetHighColor(0, 0, 0, 100); 256 view->FillRect(rect); 257 rect.OffsetBy(-1.0f, -1.0f); 258 259 view->SetHighColor(std::min(255, (int)(1.2 * fColor.red + 40)), 260 std::min(255, (int)(1.2 * fColor.green + 40)), 261 std::min(255, (int)(1.2 * fColor.blue + 40))); 262 view->StrokeRect(rect); 263 264 ++rect.left; 265 ++rect.top; 266 267 view->SetHighColor((int32)(0.8 * fColor.red), 268 (int32)(0.8 * fColor.green), 269 (int32)(0.8 * fColor.blue)); 270 view->StrokeRect(rect); 271 272 --rect.right; 273 --rect.bottom; 274 275 view->SetHighColor(fColor.red, fColor.green, fColor.blue); 276 view->FillRect(rect); 277 view->Sync(); 278 279 bitmap->Unlock(); 280 } 281 282 DragMessage(&message, bitmap, B_OP_ALPHA, BPoint(14.0f, 14.0f)); 283 284 MouseUp(where); 285 } 286