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