Package org.terasology.rendering.nui.layouts.relative

Source Code of org.terasology.rendering.nui.layouts.relative.RelativeLayout$WidgetInfo

/*
* Copyright 2014 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering.nui.layouts.relative;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.math.Rect2i;
import org.terasology.math.Vector2i;
import org.terasology.rendering.nui.Canvas;
import org.terasology.rendering.nui.CoreLayout;
import org.terasology.rendering.nui.HorizontalAlign;
import org.terasology.rendering.nui.UIWidget;
import org.terasology.rendering.nui.VerticalAlign;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* @author Immortius
*/
public class RelativeLayout extends CoreLayout<RelativeLayoutHint> {

    private static final Logger logger = LoggerFactory.getLogger(RelativeLayout.class);

    private Map<String, WidgetInfo> contentLookup = Maps.newHashMap();
    private List<WidgetInfo> contents = Lists.newArrayList();

    private Map<WidgetInfo, Rect2i> cachedRegions = Maps.newHashMap();

    private String loopDetectionId = "";

    @Override
    public void addWidget(UIWidget widget, RelativeLayoutHint hint) {
        if (widget != null && hint != null) {
            WidgetInfo info = new WidgetInfo(widget, hint);
            contents.add(info);
            if (!widget.getId().isEmpty()) {
                contentLookup.put(widget.getId(), info);
            }
        } else if (widget != null) {
            logger.error("Attempted to add widget '{}' of type '{}' with no layout hint", widget.getId(), widget.getClass().getSimpleName());
        }
    }

    public void addWidget(UIWidget widget, HorizontalHint horizontal, VerticalHint vertical) {
        addWidget(widget, new RelativeLayoutHint(horizontal, vertical));
    }

    @Override
    public void onDraw(Canvas canvas) {
        for (WidgetInfo element : contents) {
            Rect2i drawRegion = getRegion(element, canvas);
            canvas.drawWidget(element.widget, drawRegion);
        }
        cachedRegions.clear();
    }

    private Rect2i getRegion(WidgetInfo element, Canvas canvas) {
        Rect2i cachedRegion = cachedRegions.get(element);
        if (cachedRegion != null) {
            return cachedRegion;
        }

        int left = 0;
        int right = canvas.size().x;
        int center = canvas.size().x / 2;
        if (element.layoutHint.getPositionCenterHorizontal() != null) {
            HorizontalInfo info = element.layoutHint.getPositionCenterHorizontal();
            Rect2i targetRegion = getTargetRegion(info.getWidget(), canvas);
            HorizontalAlign align = (info.getTarget() != null) ? info.getTarget() : HorizontalAlign.CENTER;
            center = align.getStart(targetRegion) + info.getOffset();
        }
        if (element.layoutHint.getPositionLeft() != null) {
            HorizontalInfo info = element.layoutHint.getPositionLeft();
            Rect2i targetRegion = getTargetRegion(info.getWidget(), canvas);
            HorizontalAlign align = (info.getTarget() != null) ? info.getTarget() : HorizontalAlign.LEFT;
            left = align.getStart(targetRegion) + info.getOffset();
        }
        if (element.layoutHint.getPositionRight() != null) {
            HorizontalInfo info = element.layoutHint.getPositionRight();
            Rect2i targetRegion = getTargetRegion(info.getWidget(), canvas);
            HorizontalAlign align = (info.getTarget() != null) ? info.getTarget() : HorizontalAlign.RIGHT;
            right = align.getStart(targetRegion) - info.getOffset();
        }

        int top = 0;
        int bottom = canvas.size().y;
        int vcenter = canvas.size().y / 2;
        if (element.layoutHint.getPositionCenterVertical() != null) {
            VerticalInfo info = element.layoutHint.getPositionCenterVertical();
            Rect2i targetRegion = getTargetRegion(info.getWidget(), canvas);
            VerticalAlign align = (info.getTarget() != null) ? info.getTarget() : VerticalAlign.MIDDLE;
            vcenter = align.getStart(targetRegion) + info.getOffset();
        }
        if (element.layoutHint.getPositionTop() != null) {
            VerticalInfo info = element.layoutHint.getPositionTop();
            Rect2i targetRegion = getTargetRegion(info.getWidget(), canvas);
            VerticalAlign align = (info.getTarget() != null) ? info.getTarget() : VerticalAlign.TOP;
            top = align.getStart(targetRegion) + info.getOffset();
        }
        if (element.layoutHint.getPositionBottom() != null) {
            VerticalInfo info = element.layoutHint.getPositionBottom();
            Rect2i targetRegion = getTargetRegion(info.getWidget(), canvas);
            VerticalAlign align = (info.getTarget() != null) ? info.getTarget() : VerticalAlign.BOTTOM;
            bottom = align.getStart(targetRegion) - info.getOffset();
        }

        int width = element.layoutHint.getWidth();
        if (width == 0 && element.layoutHint.isUsingContentWidth()) {
            width = canvas.calculateRestrictedSize(element.widget, new Vector2i(right - left, bottom - top)).x;
        }
        if (width == 0) {
            width = right - left;
        } else {
            if (element.layoutHint.getPositionCenterHorizontal() != null) {
                left = center - width / 2;
            } else if (element.layoutHint.getPositionRight() != null) {
                if (element.layoutHint.getPositionLeft() != null) {
                    center = left + (right - left) / 2;
                    left = center - width / 2;
                } else {
                    left = right - width;
                }
            }
        }

        int height = element.layoutHint.getHeight();
        if (height == 0 && element.layoutHint.isUsingContentHeight()) {
            height = canvas.calculateRestrictedSize(element.widget, new Vector2i(width, bottom - top)).y;
        }
        if (height == 0) {
            height = bottom - top;
        } else {
            if (element.layoutHint.getPositionCenterVertical() != null) {
                top = vcenter - height / 2;
            } else if (element.layoutHint.getPositionBottom() != null) {
                if (element.layoutHint.getPositionTop() != null) {
                    vcenter = top + (bottom - top) / 2;
                    top = vcenter - height / 2;
                } else {
                    top = bottom - height;
                }
            }
        }
        Rect2i region = Rect2i.createFromMinAndSize(left, top, width, height);
        cachedRegions.put(element, region);
        return region;
    }

    private Rect2i getTargetRegion(String id, Canvas canvas) {
        if (id != null && !id.isEmpty()) {
            if (loopDetectionId.equals(id)) {
                logger.warn("Infinite loop detected resolving layout of element {}", loopDetectionId);
                loopDetectionId = "";
                return canvas.getRegion();
            } else if (loopDetectionId.isEmpty()) {
                loopDetectionId = id;
            }
            WidgetInfo target = contentLookup.get(id);
            if (target != null) {
                Rect2i region = getRegion(target, canvas);
                loopDetectionId = "";
                return region;
            }
        }
        loopDetectionId = "";
        return canvas.getRegion();
    }

    @Override
    public Vector2i getPreferredContentSize(Canvas canvas, Vector2i sizeHint) {
        return new Vector2i();
    }

    @Override
    public Vector2i getMaxContentSize(Canvas canvas) {
        return new Vector2i(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    @Override
    public Iterator<UIWidget> iterator() {
        List<UIWidget> widgets = Lists.newArrayListWithCapacity(contents.size());
        for (WidgetInfo info : contents) {
            widgets.add(info.widget);
        }
        return widgets.iterator();
    }

    private static final class WidgetInfo {
        private UIWidget widget;
        private RelativeLayoutHint layoutHint;

        private WidgetInfo(UIWidget widget, RelativeLayoutHint layoutHint) {
            this.widget = widget;
            this.layoutHint = layoutHint;
        }
    }
}
TOP

Related Classes of org.terasology.rendering.nui.layouts.relative.RelativeLayout$WidgetInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.