/******************************************************************************* * Copyright (c) 2015 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *******************************************************************************/ package jsettlers.graphics.ui; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import go.graphics.GLDrawContext; import jsettlers.common.images.ImageLink; import jsettlers.common.position.FloatRectangle; import jsettlers.graphics.action.Action; import jsettlers.graphics.image.Image; import jsettlers.graphics.map.draw.ImageProvider; /** * This is a panel that holds UI elements and can have a background. * <p> * All elements are positioned relatively. * * @author michael */ public class UIPanel implements UIElement { private final LinkedList<ChildLink> children = new LinkedList<UIPanel.ChildLink>(); private FloatRectangle position = new FloatRectangle(0, 0, 1, 1); private ImageLink background; private boolean attached = false; /** * Sets the background. file=-1 means no background * * @param file * @param settlerSeqIndex */ public void setBackground(ImageLink imageLink) { this.background = imageLink; } /** * Adds a child to the panel. * * @param child * The child to add. * @param left * relative left border (0..1). * @param bottom * relative bottom border (0..1). * @param right * relative right border (0..1). * @param top * relative top border (0..1). */ public void addChild(UIElement child, float left, float bottom, float right, float top) { if (child == null) { throw new NullPointerException(); } this.children.add(new ChildLink(child, left, bottom, right, top)); if (attached) { child.onAttach(); } } public void removeChild(UIElement child) { for (Iterator<ChildLink> iterator = children.iterator(); iterator.hasNext();) { ChildLink l = iterator.next(); if (l.child.equals(child)) { if (attached) { l.child.onDetach(); } iterator.remove(); break; } } } public List<UIElement> getChildren() { ArrayList<UIElement> list = new ArrayList<>(); for (ChildLink c : children) { list.add(c.child); } return list; } @Override public void drawAt(GLDrawContext gl) { drawBackground(gl); drawChildren(gl); } protected void drawChildren(GLDrawContext gl) { if (children.size() > 0) { gl.glPushMatrix(); gl.glTranslatef(position.getMinX(), position.getMinY(), 0); for (ChildLink link : children) { link.drawAt(gl, position.getWidth(), position.getHeight()); } gl.glPopMatrix(); } } protected void drawBackground(GLDrawContext gl) { ImageLink link = getBackgroundImage(); if (link != null) { FloatRectangle position = getPosition(); Image image = ImageProvider.getInstance().getImage(link, position.getWidth(), position.getHeight()); drawAtRect(gl, image, position); } } /** * Draws an image at a given rect * * @param gl * The context to use * @param image * The image to draw * @param position * The position to draw the image at */ protected void drawAtRect(GLDrawContext gl, Image image, FloatRectangle position) { gl.color(1, 1, 1, 1); float minX = position.getMinX(); float minY = position.getMinY(); float maxX = position.getMaxX(); float maxY = position.getMaxY(); image.drawImageAtRect(gl, minX, minY, maxX, maxY); } protected ImageLink getBackgroundImage() { return background; } private class ChildLink { private final UIElement child; private final float left; private final float right; private final float top; private final float bottom; public ChildLink(UIElement child, float left, float bottom, float right, float top) { this.child = child; this.left = left; this.right = right; this.top = top; this.bottom = bottom; } public void drawAt(GLDrawContext gl, float width, float height) { child.setPosition(new FloatRectangle((left * width), (bottom * height), (right * width), (top * height))); child.drawAt(gl); } public Action getActionRelative(float parentx, float parenty) { if (left <= parentx && parentx <= right && bottom <= parenty && parenty <= top) { float relativex = (parentx - left) / (right - left); float relativey = (parenty - bottom) / (top - bottom); return child.getAction(relativex, relativey); } else { return null; } } public String getDesctiptionRelative(float parentx, float parenty) { if (left <= parentx && parentx <= right && bottom <= parenty && parenty <= top) { float relativex = (parentx - left) / (right - left); float relativey = (parenty - bottom) / (top - bottom); return child.getDescription(relativex, relativey); } else { return null; } } } @Override public void setPosition(FloatRectangle position) { this.position = position; } public FloatRectangle getPosition() { return position; } public void removeAll() { if (attached) { for (ChildLink link : children) { link.child.onDetach(); } } this.children.clear(); } @Override public Action getAction(float relativex, float relativey) { for (ChildLink link : children) { Action action = link.getActionRelative(relativex, relativey); if (action != null) { return action; } } return null; } @Override public String getDescription(float relativex, float relativey) { for (ChildLink link : children) { String description = link.getDesctiptionRelative(relativex, relativey); if (description != null) { return description; } } return null; } @Override public void onAttach() { if (!attached) { for (ChildLink link : children) { link.child.onAttach(); } } attached = true; } @Override public void onDetach() { if (attached) { for (ChildLink link : children) { link.child.onDetach(); } } attached = false; } }