001package squidpony.squidgrid.gui.gdx;
002
003import squidpony.squidmath.Coord;
004
005/**
006 * A container that keeps tracks of the sizes of margins and cells. It is at the
007 * screen-level, i.e. it is intended to keep track of the full screen, not of a
008 * nested panel. Given the screen's size and the desired cell size, it computes
009 * the margins around the usable part of the screen, and hence the position of
010 * the full-screen SquidPanel ({@code (leftMargin,botMargin)}).
011 * 
012 * @author smelC
013 */
014public class ScreenSizeManager {
015
016        /** The screen's width, as given at creation time. */
017        public final int screenWidth;
018        /** The screen's height, as given at creation time. */
019        public final int screenHeight;
020
021        /** The top margin */
022        public final int topMargin;
023        /**
024         * The bottom margin, which has at most a 1 pixel difference with
025         * {@link #topMargin}.
026         */
027        public final int botMargin;
028        /** The left margin */
029        public final int leftMargin;
030        /**
031         * The right margin, which has at most a 1 pixel difference with
032         * {@link #leftMargin}.
033         */
034        public final int rightMargin;
035
036        /** A cell's width, as given at creation time. */
037        public final int cellWidth;
038
039        /** A cell's height, as given at creation time. */
040        public final int cellHeight;
041
042        /** The number of cells, horizontally */
043        public final int wCells;
044
045        /** The number of cells, vertically */
046        public final int hCells;
047
048        /**
049         * A fresh size manager, for the given screen size and the given cell size.
050         * 
051         * @param screenWidth
052         * @param screenHeight
053         * @param cellWidth
054         *            The desired cell width.
055         * @param cellHeight
056         *            The desired cell height.
057         * @throws IllegalStateException
058         *             If a size is negative.
059         */
060        public ScreenSizeManager(int screenWidth, int screenHeight, int cellWidth, int cellHeight) {
061                this.screenWidth = screenWidth;
062                if (this.screenWidth < 0)
063                        throw new IllegalStateException("Screen width should not be negative");
064                this.screenHeight = screenHeight;
065                if (this.screenHeight < 0)
066                        throw new IllegalStateException("Screen height should not be negative");
067
068                if (cellWidth < 0)
069                        throw new IllegalStateException("Cell width should not be negative");
070                this.cellWidth = cellWidth;
071
072                if (cellHeight < 0)
073                        throw new IllegalStateException("Cell height should not be negative");
074                this.cellHeight = cellHeight;
075
076                {
077                        this.wCells = screenWidth / cellWidth;
078                        final int xmargin = screenWidth - (wCells * cellWidth);
079                        assert 0 <= xmargin;
080                        final int xmargindiv2 = xmargin / 2;
081                        if (isEven(xmargin)) {
082                                this.leftMargin = xmargindiv2;
083                                this.rightMargin = xmargindiv2;
084                        } else {
085                                this.leftMargin = xmargindiv2;
086                                this.rightMargin = xmargindiv2 + 1;
087                        }
088
089                        assert leftMargin + rightMargin == xmargin;
090                }
091
092                {
093                        this.hCells = screenHeight / cellHeight;
094                        final int ymargin = screenHeight - (hCells * cellHeight);
095                        assert 0 <= ymargin;
096                        final int ymargindiv2 = ymargin / 2;
097                        if (isEven(ymargin)) {
098                                this.topMargin = ymargindiv2;
099                                this.botMargin = ymargindiv2;
100                        } else {
101                                this.topMargin = ymargindiv2;
102                                this.botMargin = ymargindiv2 + 1;
103                        }
104
105                        assert topMargin + botMargin == ymargin;
106                }
107
108                assert leftMargin + (wCells * cellWidth) + rightMargin == screenWidth;
109                assert botMargin + (hCells * cellHeight) + topMargin == screenHeight;
110        }
111
112        public void log() {
113                /*
114                Gdx.app.log(SquidTags.LAYOUT, String.format("Screen size: %dx%d", screenWidth, screenHeight));
115                Gdx.app.log(SquidTags.LAYOUT,
116                                String.format("Displaying %d cells horizontally and %d cells vertically", wCells, hCells));
117                Gdx.app.log(SquidTags.LAYOUT,
118                                String.format("Margins (in pixels): left:%d, right:%d, top:%d, bottom:%d", leftMargin,
119                                                rightMargin, topMargin, botMargin));
120                */
121        }
122
123        public Coord toScreenSize() {
124                return Coord.get(screenWidth, screenHeight);
125        }
126
127        public ScreenSizeManager changeScreenSize(int x, int y) {
128                return new ScreenSizeManager(x, y, cellWidth, cellHeight);
129        }
130
131        private static boolean isEven(int i) {
132                return (i & 1) == 0;
133        }
134}