1 /* 2 * Copyright 2010-2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * John Scipione <jscipione@gmail.com> 8 */ 9 10 11 #include "FakeScrollBar.h" 12 13 #include <Box.h> 14 #include <ControlLook.h> 15 #include <Message.h> 16 #include <ScrollBar.h> 17 #include <Shape.h> 18 #include <Size.h> 19 #include <Window.h> 20 21 22 typedef enum { 23 ARROW_LEFT = 0, 24 ARROW_RIGHT, 25 ARROW_UP, 26 ARROW_DOWN, 27 ARROW_NONE 28 } arrow_direction; 29 30 31 FakeScrollBar::FakeScrollBar(bool drawArrows, bool doubleArrows, 32 BMessage* message) 33 : 34 BControl("FakeScrollBar", NULL, message, B_WILL_DRAW | B_NAVIGABLE), 35 fDrawArrows(drawArrows), 36 fDoubleArrows(doubleArrows) 37 { 38 SetExplicitMinSize(BSize(160, 20)); 39 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 20)); 40 } 41 42 43 FakeScrollBar::~FakeScrollBar(void) 44 { 45 } 46 47 48 void 49 FakeScrollBar::Draw(BRect updateRect) 50 { 51 BRect bounds = Bounds(); 52 53 rgb_color normal = ui_color(B_PANEL_BACKGROUND_COLOR); 54 55 if (IsFocus()) { 56 // draw the focus indicator 57 SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); 58 StrokeRect(bounds); 59 bounds.InsetBy(1.0, 1.0); 60 61 // Draw the selected border (1px) 62 if (Value() == B_CONTROL_ON) 63 SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); 64 else 65 SetHighColor(normal); 66 67 StrokeRect(bounds); 68 bounds.InsetBy(1.0, 1.0); 69 } else { 70 // Draw the selected border (2px) 71 if (Value() == B_CONTROL_ON) 72 SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); 73 else 74 SetHighColor(normal); 75 76 StrokeRect(bounds); 77 bounds.InsetBy(1.0, 1.0); 78 StrokeRect(bounds); 79 bounds.InsetBy(1.0, 1.0); 80 } 81 82 // draw a gap (1px) 83 SetHighColor(normal); 84 StrokeRect(bounds); 85 bounds.InsetBy(1.0, 1.0); 86 87 // draw a border around control (1px) 88 SetHighColor(tint_color(normal, B_DARKEN_1_TINT)); 89 StrokeRect(bounds); 90 bounds.InsetBy(1.0, 1.0); 91 92 BRect thumbBG = bounds; 93 BRect bgRect = bounds; 94 95 if (fDrawArrows) { 96 // draw arrows 97 SetDrawingMode(B_OP_OVER); 98 99 BRect buttonFrame(bounds.left, bounds.top, 100 bounds.left + bounds.Height(), bounds.bottom); 101 102 _DrawArrowButton(ARROW_LEFT, buttonFrame, updateRect); 103 104 if (fDoubleArrows) { 105 buttonFrame.OffsetBy(bounds.Height() + 1, 0.0); 106 _DrawArrowButton(ARROW_RIGHT, buttonFrame, 107 updateRect); 108 109 buttonFrame.OffsetTo(bounds.right - ((bounds.Height() * 2) + 1), 110 bounds.top); 111 _DrawArrowButton(ARROW_LEFT, buttonFrame, 112 updateRect); 113 114 thumbBG.left += bounds.Height() * 2 + 2; 115 thumbBG.right -= bounds.Height() * 2 + 2; 116 } else { 117 thumbBG.left += bounds.Height() + 1; 118 thumbBG.right -= bounds.Height() + 1; 119 } 120 121 buttonFrame.OffsetTo(bounds.right - bounds.Height(), bounds.top); 122 _DrawArrowButton(ARROW_RIGHT, buttonFrame, updateRect); 123 124 SetDrawingMode(B_OP_COPY); 125 126 bgRect = bounds.InsetByCopy(48, 0); 127 } else 128 bgRect = bounds.InsetByCopy(16, 0); 129 130 // fill background besides the thumb 131 BRect leftOfThumb(thumbBG.left, thumbBG.top, bgRect.left - 1, 132 thumbBG.bottom); 133 BRect rightOfThumb(bgRect.right + 1, thumbBG.top, thumbBG.right, 134 thumbBG.bottom); 135 136 be_control_look->DrawScrollBarBackground(this, leftOfThumb, 137 rightOfThumb, updateRect, normal, 0, B_HORIZONTAL); 138 139 // Draw scroll thumb 140 141 // fill the clickable surface of the thumb 142 be_control_look->DrawButtonBackground(this, bgRect, updateRect, 143 normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL); 144 } 145 146 147 void 148 FakeScrollBar::MouseDown(BPoint point) 149 { 150 BControl::MouseDown(point); 151 } 152 153 154 void 155 FakeScrollBar::MouseMoved(BPoint point, uint32 transit, 156 const BMessage* message) 157 { 158 BControl::MouseMoved(point, transit, message); 159 } 160 161 162 void 163 FakeScrollBar::MouseUp(BPoint point) 164 { 165 SetValue(B_CONTROL_ON); 166 Invoke(); 167 168 Invalidate(); 169 170 BControl::MouseUp(point); 171 } 172 173 174 void 175 FakeScrollBar::SetValue(int32 value) 176 { 177 if (value != Value()) { 178 BControl::SetValueNoUpdate(value); 179 Invalidate(); 180 } 181 182 if (!value) 183 return; 184 185 BView* parent = Parent(); 186 BView* child = NULL; 187 188 if (parent != NULL) { 189 // If the parent is a BBox, the group parent is the parent of the BBox 190 BBox* box = dynamic_cast<BBox*>(parent); 191 192 if (box && box->LabelView() == this) 193 parent = box->Parent(); 194 195 if (parent != NULL) { 196 BBox* box = dynamic_cast<BBox*>(parent); 197 198 // If the parent is a BBox, skip the label if there is one 199 if (box && box->LabelView()) 200 child = parent->ChildAt(1); 201 else 202 child = parent->ChildAt(0); 203 } else 204 child = Window()->ChildAt(0); 205 } else if (Window()) 206 child = Window()->ChildAt(0); 207 208 while (child) { 209 FakeScrollBar* scrollbar = dynamic_cast<FakeScrollBar*>(child); 210 211 if (scrollbar != NULL && (scrollbar != this)) 212 scrollbar->SetValue(B_CONTROL_OFF); 213 else { 214 // If the child is a BBox, check if the label is a scrollbarbutton 215 BBox* box = dynamic_cast<BBox*>(child); 216 217 if (box && box->LabelView()) { 218 scrollbar = dynamic_cast<FakeScrollBar*>(box->LabelView()); 219 220 if (scrollbar != NULL && (scrollbar != this)) 221 scrollbar->SetValue(B_CONTROL_OFF); 222 } 223 } 224 225 child = child->NextSibling(); 226 } 227 228 //ASSERT(Value() == B_CONTROL_ON); 229 } 230 231 232 // #pragma mark - 233 234 235 void 236 FakeScrollBar::SetDoubleArrows(bool doubleArrows) 237 { 238 fDoubleArrows = doubleArrows; 239 Invalidate(); 240 } 241 242 243 void 244 FakeScrollBar::SetKnobStyle(uint32 knobStyle) 245 { 246 fKnobStyle = knobStyle; 247 Invalidate(); 248 } 249 250 251 void 252 FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info) 253 { 254 fDoubleArrows = info.double_arrows; 255 fKnobStyle = info.knob; 256 Invalidate(); 257 } 258 259 260 // #pragma mark - 261 262 263 void 264 FakeScrollBar::_DrawArrowButton(int32 direction, BRect rect, 265 const BRect& updateRect) 266 { 267 if (!updateRect.Intersects(rect)) 268 return; 269 270 uint32 flags = 0; 271 272 rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 273 B_LIGHTEN_1_TINT); 274 275 be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor, 276 flags, BControlLook::B_ALL_BORDERS, B_HORIZONTAL); 277 278 rect.InsetBy(-1, -1); 279 be_control_look->DrawArrowShape(this, rect, updateRect, 280 baseColor, direction, flags, B_DARKEN_MAX_TINT); 281 } 282