29#define _Class _ScrollBar
37#pragma mark - Delegate callbacks
48 const SDL_Rect track = $((
View *) self,
bounds);
49 const SDL_Size content = $((
View *) self->scrollView->contentView,
size);
50 const SDL_Rect visible = $((
View *) self->scrollView,
bounds);
52 const int scrollRange = content.h - visible.h;
53 const int travel = track.h - ((
View *) self->handle)->frame.h;
55 if (scrollRange > 0 && travel > 0) {
57 SDL_Point offset = self->scrollView->contentOffset;
58 offset.y -= (int) (delta * ((
float) scrollRange / travel));
60 $(self->scrollView, scrollToOffset, &offset);
75 release(this->handle);
98 if (this->scrollView == NULL || this->scrollView->contentView == NULL) {
102 const SDL_Rect track = $(self,
bounds);
103 const SDL_Size content = $(this->scrollView->contentView,
size);
104 const SDL_Rect visible = $((
View *) this->scrollView,
bounds);
106 View *handle = (
View *) this->handle;
108 if (content.h <= visible.h || track.h <= 0) {
109 handle->
frame = (SDL_Rect) { 0, 0, track.w, track.h };
112 const int scrollRange = content.h - visible.h;
114 int handleH = (int) ((
float) track.h * visible.h / content.h);
115 handleH = clamp(handleH, handle->
minSize.h, track.h);
117 const int travel = track.h - handleH;
118 const float fraction = clamp((
float) (-this->scrollView->contentOffset.y) / scrollRange, 0.f, 1.f);
120 handle->
frame = (SDL_Rect) { 0, (int) (fraction * travel), track.w, handleH };
131 switch (event->type) {
133 case SDL_EVENT_MOUSE_BUTTON_DOWN:
134 if (this->scrollView) {
136 const SDL_Point point = MakePoint(event->button.x, event->button.y);
138 const SDL_Rect visible = $((
View *) this->scrollView,
bounds);
140 SDL_Point offset = this->scrollView->contentOffset;
142 if (point.y < handleFrame.y) {
143 offset.y += visible.h;
144 }
else if (point.y > handleFrame.y + handleFrame.h) {
145 offset.y -= visible.h;
148 $(this->scrollView, scrollToOffset, &offset);
153 case SDL_EVENT_MOUSE_BUTTON_UP:
157 case SDL_EVENT_MOUSE_MOTION:
167#pragma mark - ScrollBar
181 assert(self->handle);
182 self->handle->delegate.self = self;
203#pragma mark - Class lifecycle
210 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
212 ((ViewInterface *) clazz->interface)->init =
init;
214 ((ViewInterface *) clazz->interface)->respondToEvent =
respondToEvent;
229 clazz = _initialize(&(
const ClassDef) {
231 .superclass =
_View(),
233 .interfaceSize =
sizeof(ScrollBarInterface),
static Box * initWithFrame(Box *self, const SDL_Rect *frame)
static SDL_Size size(const Image *self)
static void addSubview(View *self, View *subview)
static void addClassName(View *self, const char *className)
static void resignTouchResponder(View *self)
static void setNeedsLayout(View *self)
static SDL_Rect renderFrame(const View *self)
static SDL_Rect bounds(const View *self)
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
SDL_Size minSize
The minimum size this View may be resized to during layout.
layoutSubviews(View *self)
Arranges this View's immediate subviews within its (already final) frame.
SDL_Rect frame
The frame, relative to the superview.