Hexworks / zircon

Zircon is an extensible and user-friendly, multiplatform tile engine.
https://hexworks.org/projects/zircon/
Apache License 2.0
753 stars 137 forks source link

Implement "Log" Component #46

Closed William-Lake closed 6 years ago

William-Lake commented 7 years ago

Summary

A "Log" refers to a GUI component, often used in roguelike games to display information to the user about a variety of events.

A dedicated "Log" Component would be a useful way to easily provide this functionality in a GUI.

Example

The Orc's attack hits! The Orc attacks you! You missed... You attacked the Orc!

Work Around

The current work around is to use a TextImage:

  1. Create TextImage for your preferred size
  2. Draw a box around it via BoxBuilder
  3. Update TextImage with each of your log messages via TextImage's putText() method

For Example

public class Playground {

    public static void main(String[] args) {
        final Terminal terminal = TerminalBuilder.newBuilder()
                .font(CP437TilesetResource.REX_PAINT_20X20.toFont())
                .initialTerminalSize(Size.of(10, 5))
                .build();

        final TextImage img = TextImageBuilder.newBuilder()
                .size(Size.of(10, 5))
                .build(); // we create a new image to draw onto the terminal

        img.setForegroundColor(ANSITextColor.WHITE);
        img.setBackgroundColor(ANSITextColor.BLUE); // `putText` will use these

        BoxBuilder.newBuilder()
                .boxType(BoxType.DOUBLE)
                .size(Size.of(10, 5))
                .style(StyleSetBuilder.newBuilder()
                        .foregroundColor(ANSITextColor.CYAN)
                        .backgroundColor(ANSITextColor.BLUE)
                        .build())
                .build()
                .drawOnto(img, Position.DEFAULT_POSITION); // we create a box and draw it onto the image

        final List<String> logElements = new ArrayList<>();
        logElements.add("foo");
        logElements.add("bar"); // our log entries

        for(int i = 0; i < logElements.size(); i++) {
            img.putText(logElements.get(i), Position.OFFSET_1x1.withRelativeRow(i)); // we have to offset because of the box
        }

        terminal.draw(img, Position.DEFAULT_POSITION); // you have to draw each time the image changes

        terminal.flush();
    }
}

coldwarrl commented 7 years ago

Would that log-component support scrolling ?

adam-arold commented 7 years ago

Yep, it will implement Scrollable so it will get the scroll behavior from the get-go but no scrollbars yet (we haven't implemented that component yet).

So basically there will be a binding between the log component and a List you supply an you can either scroll up-down programmatically (for example you can add a key listener to the ArrowUp and ArrowDown keys when the component when it is focused) but by default the last n elements are displayed.

Let's discuss this over our discord channel if you have any specific ideas!

coldwarrl commented 6 years ago

I guess it makes sense (at least I want this for my game), to have the possibility to add different styles (e.g. color/underline (would work as link)). So instead of a simple List/collection, maybe having a small API to add log content would be better. After I got re-familiarized with Zircon again, @adam-arold I would discuss it with you, maybe I can then build a prototype :)...

adam-arold commented 6 years ago

Definitely a good idea! This was made for a Software Design course. Source is here.

I only perused it so it probably needs some improvement. I also think that for a preliminary implementation we'll do fine without a scrollbar.

adam-arold commented 6 years ago

@coldwarrl do you think you can give a story point estimate?

William-Lake commented 6 years ago

Hi All! Just saw the post on /r/roguelikedev and am so excited to see this control in Zircon! I know I'm preaching to the choir here but, great work- on everything!

adam-arold commented 6 years ago

Thanks, you can now use it!