Creating a Scrollable Container in SDL

How do I create a scrollable container for UI elements that exceed the window size?

Creating a scrollable container in SDL involves managing a viewport that shows only a portion of the total content. Here's how you can implement a basic scrollable container:

First, let's define a ScrollableContainer class:

#include <SDL.h>
#include <vector>

class ScrollableContainer {
private:
  SDL_Rect viewport;
  SDL_Rect content;
  int scrollY{0};
  std::vector<SDL_Rect> elements;

public:
  ScrollableContainer(int x, int y, int w,
                      int h)
    : viewport{x, y, w, h},
      content{0, 0, w, 0} {}

  void AddElement(const SDL_Rect& element) {
    elements.push_back(element);
    content.h = std::max(content.h,
                         element.y + element.h);
  }

  void Scroll(int amount) {
    scrollY += amount;
    scrollY = std::max(
        0, std::min(scrollY,
                    content.h - viewport.h));
  }

  void Render(SDL_Surface* surface) {
    SDL_Rect clipRect = viewport;
    SDL_SetClipRect(surface, &clipRect);

    for (const auto& element : elements) {
      SDL_Rect adjustedRect = element;
      adjustedRect.y -= scrollY;

      if (adjustedRect.y + adjustedRect.h > 0 &&
          adjustedRect.y < viewport.h) {
        SDL_FillRect(surface, &adjustedRect,
                     SDL_MapRGB(surface->format,
                       200, 200, 200));
      }
    }

    SDL_SetClipRect(surface, nullptr);
  }
};

Now, let's use this ScrollableContainer in our main loop:

#include <iostream>

int main() {
  // SDL initialization code...

  ScrollableContainer container{10, 10, 200,
    300};

  // Add some elements to the container
  for (int i = 0; i < 10; ++i) {
    container.AddElement({0, i * 60, 180, 50});
  }

  SDL_Event event;
  bool quit = false;

  while (!quit) {
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_QUIT) {
        quit = true;
      } else if (event.type == SDL_MOUSEWHEEL) {
        container.Scroll(-event.wheel.y *
                         20); 
        std::cout
            << "Scrolled "
            << (event.wheel.y > 0
                  ? "up"
                  : "down")
            << "\n";
      }
    }

    // Clear the screen
    SDL_FillRect(surface, nullptr,
                 SDL_MapRGB(surface->format,
                            255, 255, 255));

    // Render the scrollable container
    container.Render(surface);

    SDL_UpdateWindowSurface(window);
  }

  // SDL cleanup code...
  return 0;
}

This implementation creates a scrollable container that can hold multiple elements. The container uses SDL_SetClipRect() to ensure that only the visible portion of the content is rendered. The Scroll() method allows you to move the visible area up or down.

In the main loop, we're handling the SDL_MOUSEWHEEL event to allow scrolling with the mouse wheel. You could also implement scrolling via keyboard input or drag gestures for touch screens.

Remember to adjust the scrolling speed and behavior to suit your specific UI needs. You might also want to add visual indicators like scroll bars to show the current scroll position and the total content size.

This basic implementation can be extended to support horizontal scrolling, nested scrollable areas, or more complex layouts. As your UI becomes more complex, consider implementing a more robust UI framework or using an existing library that provides these features.

Structuring SDL Programs

Discover how to organize SDL components using manager classes, inheritance, and polymorphism for cleaner code.

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Using Inheritance Without Polymorphism in SDL/C++
Do I *have* to use polymorphism if I use inheritance?
Removing UI Components from a std::vector in SDL/C++
How would I remove a component from the UI manager's std::vector?
The virtual Keyword and Polymorphism in C++
What does the virtual keyword do, and why might I need it for polymorphism in SDL UI components?
How C++ Calls the Correct Method with virtual Functions (Dynamic Dispatch)
How does the computer know whether to call Rectangle::Render() or GreenRectangle::Render() when using pointers?
Controlling Drawing Order for Overlapping UI Components in SDL
How is the drawing order determined if components overlap in this UI structure?
Importance of Event Handling Order for UI Components in SDL
Does the order I call HandleEvent() on children matter?
Implementing Resizable UI Components in SDL
What's the best way to handle resizable UI components in SDL?
Implementing a Modal Dialog in SDL UI
How would I implement a modal dialog box using this component hierarchy?
Animated UI Transitions in SDL
How can I create animated transitions between different UI states or screens?
Ask Your Own Question
Temporarily unavailable while we roll out updates. Back in a few days!