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