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