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