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 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 52 53 uint32 flags = BControlLook::B_PARTIALLY_ACTIVATED; 54 55 if (Value() == B_CONTROL_ON) 56 SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); 57 else 58 SetHighColor(base); 59 60 BRect rect(Bounds()); 61 62 // draw the selected border (2px) 63 StrokeRect(rect); 64 rect.InsetBy(1, 1); 65 StrokeRect(rect); 66 rect.InsetBy(1, 1); 67 68 // draw a 1px gap 69 SetHighColor(base); 70 StrokeRect(rect); 71 rect.InsetBy(1, 1); 72 73 // draw a 1px border around the entire scroll bar 74 be_control_look->DrawScrollBarBorder(this, rect, updateRect, base, flags, 75 B_HORIZONTAL); 76 77 // inset past border 78 rect.InsetBy(1, 1); 79 80 // draw arrow buttons 81 if (fDrawArrows) { 82 BRect buttonFrame(rect.left, rect.top, rect.left + rect.Height(), 83 rect.bottom); 84 be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect, 85 base, flags, BControlLook::B_LEFT_ARROW, B_HORIZONTAL); 86 if (fDoubleArrows) { 87 buttonFrame.OffsetBy(rect.Height() + 1, 0.0f); 88 be_control_look->DrawScrollBarButton(this, buttonFrame, 89 updateRect, base, flags, BControlLook::B_RIGHT_ARROW, 90 B_HORIZONTAL); 91 buttonFrame.OffsetTo(rect.right - ((rect.Height() * 2) + 1), 92 rect.top); 93 be_control_look->DrawScrollBarButton(this, buttonFrame, 94 updateRect, base, flags, BControlLook::B_LEFT_ARROW, 95 B_HORIZONTAL); 96 } 97 buttonFrame.OffsetTo(rect.right - rect.Height(), rect.top); 98 be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect, 99 base, flags, BControlLook::B_RIGHT_ARROW, B_HORIZONTAL); 100 } 101 102 // inset rect to make room for arrows 103 if (fDrawArrows) { 104 if (fDoubleArrows) 105 rect.InsetBy((rect.Height() + 1) * 2, 0.0f); 106 else 107 rect.InsetBy(rect.Height() + 1, 0.0f); 108 } 109 110 // draw background and thumb 111 float less = floorf(rect.Width() / 3); 112 BRect thumbRect(rect.left + less, rect.top, rect.right - less, 113 rect.bottom); 114 BRect leftOfThumb(rect.left, thumbRect.top, thumbRect.left - 1, 115 thumbRect.bottom); 116 BRect rightOfThumb(thumbRect.right + 1, thumbRect.top, rect.right, 117 thumbRect.bottom); 118 119 be_control_look->DrawScrollBarBackground(this, leftOfThumb, 120 rightOfThumb, updateRect, base, flags, B_HORIZONTAL); 121 be_control_look->DrawScrollBarThumb(this, thumbRect, updateRect, 122 ui_color(B_SCROLL_BAR_THUMB_COLOR), flags, B_HORIZONTAL, fKnobStyle); 123 } 124 125 126 void 127 FakeScrollBar::MouseDown(BPoint point) 128 { 129 BControl::MouseDown(point); 130 } 131 132 133 void 134 FakeScrollBar::MouseMoved(BPoint point, uint32 transit, 135 const BMessage* message) 136 { 137 BControl::MouseMoved(point, transit, message); 138 } 139 140 141 void 142 FakeScrollBar::MouseUp(BPoint point) 143 { 144 SetValue(B_CONTROL_ON); 145 Invoke(); 146 147 Invalidate(); 148 149 BControl::MouseUp(point); 150 } 151 152 153 void 154 FakeScrollBar::SetValue(int32 value) 155 { 156 if (value != Value()) { 157 BControl::SetValueNoUpdate(value); 158 Invalidate(); 159 } 160 161 if (!value) 162 return; 163 164 BView* parent = Parent(); 165 BView* child = NULL; 166 167 if (parent != NULL) { 168 // If the parent is a BBox, the group parent is the parent of the BBox 169 BBox* box = dynamic_cast<BBox*>(parent); 170 171 if (box && box->LabelView() == this) 172 parent = box->Parent(); 173 174 if (parent != NULL) { 175 BBox* box = dynamic_cast<BBox*>(parent); 176 177 // If the parent is a BBox, skip the label if there is one 178 if (box && box->LabelView()) 179 child = parent->ChildAt(1); 180 else 181 child = parent->ChildAt(0); 182 } else 183 child = Window()->ChildAt(0); 184 } else if (Window()) 185 child = Window()->ChildAt(0); 186 187 while (child) { 188 FakeScrollBar* scrollbar = dynamic_cast<FakeScrollBar*>(child); 189 190 if (scrollbar != NULL && (scrollbar != this)) 191 scrollbar->SetValue(B_CONTROL_OFF); 192 else { 193 // If the child is a BBox, check if the label is a scrollbarbutton 194 BBox* box = dynamic_cast<BBox*>(child); 195 196 if (box && box->LabelView()) { 197 scrollbar = dynamic_cast<FakeScrollBar*>(box->LabelView()); 198 199 if (scrollbar != NULL && (scrollbar != this)) 200 scrollbar->SetValue(B_CONTROL_OFF); 201 } 202 } 203 204 child = child->NextSibling(); 205 } 206 207 //ASSERT(Value() == B_CONTROL_ON); 208 } 209 210 211 // #pragma mark - 212 213 214 void 215 FakeScrollBar::SetDoubleArrows(bool doubleArrows) 216 { 217 fDoubleArrows = doubleArrows; 218 Invalidate(); 219 } 220 221 222 void 223 FakeScrollBar::SetKnobStyle(uint32 knobStyle) 224 { 225 fKnobStyle = knobStyle; 226 Invalidate(); 227 } 228 229 230 void 231 FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info) 232 { 233 fDoubleArrows = info.double_arrows; 234 fKnobStyle = info.knob; 235 Invalidate(); 236 } 237 238 239 // #pragma mark - 240 241 242 void 243 FakeScrollBar::_DrawArrowButton(int32 direction, BRect rect, 244 const BRect& updateRect) 245 { 246 if (!updateRect.Intersects(rect)) 247 return; 248 249 uint32 flags = 0; 250 251 rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 252 B_LIGHTEN_1_TINT); 253 254 be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor, 255 flags, BControlLook::B_ALL_BORDERS, B_HORIZONTAL); 256 257 rect.InsetBy(-1, -1); 258 be_control_look->DrawArrowShape(this, rect, updateRect, 259 baseColor, direction, flags, B_DARKEN_MAX_TINT); 260 } 261