0
\$\begingroup\$

I appreciate the GridBagLayout of Java very much. But, it has one huge disadvantage: it is very much boilerplate code. You have to type too much.

I would like to use the GridBagLayout of Java in the most comfortable way. I want to type as little as possible but also have good code readability.

My current state is like this:

    // New Layout with IGrid

    // Here are definitions of components matchView, commentsSp, commandsSp, autorollCp, and matchMenu.

    var grid = IGrid.create();
    
    grid.rect(0, 0, 2, 1);
    grid.weight().x(10);
    grid.weight().y(3);
    grid.fill().both();
    grid.add(matchView);
    
    grid.rect(2, 0, 1, 1);
    grid.weight().x(1);
    grid.weight().y(1);
    grid.add(commentsSp);

    grid.rect(3, 0, 1, 1);
    grid.weight().x(0);
    grid.weight().y(0);
    grid.add(commandsSp);

    grid.rect(0, 1, 1, 1);
    grid.fill().none();
    grid.insets().left(15);
    grid.add(autorollCb);

    grid.rect(1, 1, 3, 1);
    grid.weight().x(1);
    grid.insets().top(15);
    grid.insets().left(15);
    grid.insets().right(15);
    grid.insets().bottom(15);
    grid.add(matchMenu);

    setContentPane(grid.asComponent());

The API therefore is as follows:

import javax.swing.JComponent;

public interface IGrid {
    public static IGrid create() {
        return new Grid();
    }

    JComponent asComponent();
    void add(JComponent comp);
    void x(int v);
    void y(int v);
    void w(int v);
    void h(int v);
    void rect(int x, int y, int w, int h);
    public IWeight weight();
    public IFill fill();
    public IInsets insets();

    interface IWeight {
        void x(int v);
        void y(int v);
    }

    interface IFill {
        void none();
        void horizontal();
        void vertical();
        void both();
    }

    interface IInsets {
        void top(int v);
        void left(int v);
        void right(int v);
        void bottom(int v);
    }
}

Still, I feel there might be some room for improvement, shorter API or better code readability. Do you have suggestions how to improve the API above?

\$\endgroup\$
6
  • \$\begingroup\$ Just want to mention the later JavaFX (OpenJFX) and its GridPane. I love using swing too, but JavaFX is objectively better: API, events & bnding, CSS styles, and so on. Disadvantage: the somewhat obfuscating lambda usage. \$\endgroup\$ Commented Sep 16 at 9:34
  • \$\begingroup\$ Thank you, I will check JavaFX. \$\endgroup\$ Commented Sep 17 at 6:23
  • 1
    \$\begingroup\$ That doesn't really seem to reduce boilerplate at all. Could you also include a before/after example, and the concrete implementation? \$\endgroup\$ Commented Sep 17 at 11:25
  • \$\begingroup\$ It's not clear to me what the contract is of this code. What happens when a rect() method is called? Which values are set? Why do you need x(int) if rect() already sets it? Personally I don't like this setup at all, as it seems you need to change the values for each rectange, but your doing this not for a rectangle but for the entire IGrid. That breaks all kind of encapsulation rules. A builder pattern, possibly augmented with templates would be much more logical. \$\endgroup\$ Commented Oct 1 at 12:02
  • \$\begingroup\$ OK you maybe got me here. Yes, definitely I should have added a comment that rect sets GridBagConstraints.gridx, gridy, gridwidth and gridheight. And also there: first, I planned to only provide x(), y(), w(), h(). Then, I learnt it is too inconvenient and better to have one method for all 4 of them because the typical use case is to set them all. But, I did not want to force the user to use rect. This is why I kept also the single setters x, y, w, h. :-) - And yes, a builder pattern would be more logical to 99% of users, I see now. For me, it is so very nice to code now, probably only for me. \$\endgroup\$ Commented Oct 6 at 6:32

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.