1 /* 2 * Copyright 2006-2012, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "SwatchView.h" 10 11 #include <new> 12 #include <stdio.h> 13 14 #include <Bitmap.h> 15 #include <Cursor.h> 16 #include <Looper.h> 17 #include <Message.h> 18 #include <TypeConstants.h> 19 #include <Window.h> 20 21 #include "cursors.h" 22 #include "ui_defines.h" 23 #include "support.h" 24 #include "support_ui.h" 25 26 27 #define DRAG_INIT_DIST 10.0 28 29 30 SwatchView::SwatchView(const char* name, BMessage* message, BHandler* target, 31 rgb_color color, float width, float height) 32 : 33 BView(BRect(0.0, 0.0, width, height), name, B_FOLLOW_NONE, B_WILL_DRAW), 34 fColor(color), 35 fTrackingStart(-1.0, -1.0), 36 fActive(false), 37 fDropInvokes(false), 38 fClickMessage(message), 39 fDroppedMessage(NULL), 40 fTarget(target), 41 fWidth(width), 42 fHeight(height) 43 { 44 SetViewColor(B_TRANSPARENT_32_BIT); 45 SetHighColor(fColor); 46 } 47 48 49 SwatchView::~SwatchView() 50 { 51 delete fClickMessage; 52 delete fDroppedMessage; 53 } 54 55 56 inline void 57 blend_color(rgb_color& a, const rgb_color& b, float alpha) 58 { 59 float alphaInv = 1.0 - alpha; 60 a.red = (uint8)(b.red * alphaInv + a.red * alpha); 61 a.green = (uint8)(b.green * alphaInv + a.green * alpha); 62 a.blue = (uint8)(b.blue * alphaInv + a.blue * alpha); 63 } 64 65 66 void 67 SwatchView::Draw(BRect updateRect) 68 { 69 BRect r(Bounds()); 70 71 rgb_color colorLight = tint_color(fColor, B_LIGHTEN_2_TINT); 72 rgb_color colorShadow = tint_color(fColor, B_DARKEN_2_TINT); 73 74 if (fColor.alpha < 255) { 75 // left/top 76 float alpha = fColor.alpha / 255.0; 77 78 rgb_color h = colorLight; 79 blend_color(h, kAlphaHigh, alpha); 80 rgb_color l = colorLight; 81 blend_color(l, kAlphaLow, alpha); 82 83 SetHighColor(h); 84 SetLowColor(l); 85 86 StrokeLine(BPoint(r.left, r.bottom - 1), 87 BPoint(r.left, r.top), kDottedBig); 88 StrokeLine(BPoint(r.left + 1, r.top), 89 BPoint(r.right, r.top), kDottedBig); 90 91 // right/bottom 92 h = colorShadow; 93 blend_color(h, kAlphaHigh, alpha); 94 l = colorShadow; 95 blend_color(l, kAlphaLow, alpha); 96 97 SetHighColor(h); 98 SetLowColor(l); 99 100 StrokeLine(BPoint(r.right, r.top + 1), 101 BPoint(r.right, r.bottom), kDottedBig); 102 StrokeLine(BPoint(r.right - 1, r.bottom), 103 BPoint(r.left, r.bottom), kDottedBig); 104 105 // fill 106 r.InsetBy(1.0, 1.0); 107 108 h = fColor; 109 blend_color(h, kAlphaHigh, alpha); 110 l = fColor; 111 blend_color(l, kAlphaLow, alpha); 112 113 SetHighColor(h); 114 SetLowColor(l); 115 116 FillRect(r, kDottedBig); 117 } else { 118 _StrokeRect(r, colorLight, colorShadow); 119 r.InsetBy(1.0, 1.0); 120 SetHighColor(fColor); 121 FillRect(r); 122 } 123 } 124 125 126 void 127 SwatchView::MessageReceived(BMessage* message) 128 { 129 switch (message->what) { 130 case B_PASTE: 131 { 132 rgb_color color; 133 if (restore_color_from_message(message, color) == B_OK) { 134 SetColor(color); 135 _Invoke(fDroppedMessage); 136 } 137 break; 138 } 139 140 default: 141 BView::MessageReceived(message); 142 break; 143 } 144 } 145 146 147 void 148 SwatchView::MouseDown(BPoint where) 149 { 150 if (Bounds().Contains(where)) 151 fTrackingStart = where; 152 } 153 154 155 void 156 SwatchView::MouseUp(BPoint where) 157 { 158 if (Bounds().Contains(where) && Bounds().Contains(fTrackingStart)) 159 _Invoke(fClickMessage); 160 161 fTrackingStart.x = -1.0; 162 fTrackingStart.y = -1.0; 163 } 164 165 166 void 167 SwatchView::MouseMoved(BPoint where, uint32 transit, 168 const BMessage* dragMessage) 169 { 170 if (transit == B_ENTERED_VIEW) { 171 BCursor cursor(kDropperCursor); 172 SetViewCursor(&cursor, true); 173 } 174 175 if (Bounds().Contains(fTrackingStart)) { 176 if (point_point_distance(where, fTrackingStart) > DRAG_INIT_DIST 177 || transit == B_EXITED_VIEW) { 178 _DragColor(); 179 fTrackingStart.x = -1.0; 180 fTrackingStart.y = -1.0; 181 } 182 } 183 } 184 185 186 void 187 SwatchView::SetColor(rgb_color color) 188 { 189 fColor = color; 190 SetHighColor(fColor); 191 Invalidate(); 192 } 193 194 195 void 196 SwatchView::SetClickedMessage(BMessage* message) 197 { 198 if (message != fClickMessage) 199 delete fClickMessage; 200 fClickMessage = message; 201 } 202 203 204 void 205 SwatchView::SetDroppedMessage(BMessage* message) 206 { 207 if (message != fDroppedMessage) 208 delete fDroppedMessage; 209 fDroppedMessage = message; 210 } 211 212 213 void 214 SwatchView::_Invoke(const BMessage* _message) 215 { 216 if (_message == NULL) 217 return; 218 219 BHandler* target = fTarget; 220 if (target == NULL) 221 target = Window(); 222 223 if (target == NULL) 224 return; 225 226 BLooper* looper = target->Looper(); 227 if (looper == NULL) 228 return; 229 230 BMessage message(*_message); 231 message.AddPointer("be:source", (void*)this); 232 message.AddInt64("be:when", system_time()); 233 message.AddBool("begin", true); 234 store_color_in_message(&message, fColor); 235 looper->PostMessage(&message, target); 236 } 237 238 239 void 240 SwatchView::_StrokeRect(BRect r, rgb_color leftTop, rgb_color rightBottom) 241 { 242 BeginLineArray(4); 243 244 AddLine(BPoint(r.left, r.bottom - 1), BPoint(r.left, r.top), leftTop); 245 AddLine(BPoint(r.left + 1, r.top), BPoint(r.right, r.top), leftTop); 246 AddLine(BPoint(r.right, r.top + 1), BPoint(r.right, r.bottom), 247 rightBottom); 248 AddLine(BPoint(r.right - 1, r.bottom), BPoint(r.left, r.bottom), 249 rightBottom); 250 251 EndLineArray(); 252 } 253 254 255 void 256 SwatchView::_DragColor() 257 { 258 BBitmap* bitmap = new(std::nothrow) BBitmap(BRect(0.0, 0.0, 15.0, 15.0), 259 B_RGB32); 260 261 BMessage message = make_color_drop_message(fColor, bitmap); 262 263 DragMessage(&message, bitmap, B_OP_ALPHA, BPoint(9.0, 9.0)); 264 } 265 266