/*
* Copyright 2016 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.contextMenu;
import com.google.common.collect.Lists;
import org.terasology.assets.ResourceUrn;
import org.terasology.math.geom.Rect2i;
import org.terasology.math.geom.Vector2i;
import org.terasology.rendering.nui.BaseInteractionListener;
import org.terasology.rendering.nui.Canvas;
import org.terasology.rendering.nui.CoreScreenLayer;
import org.terasology.rendering.nui.InteractionListener;
import org.terasology.rendering.nui.events.NUIMouseClickEvent;
import org.terasology.rendering.nui.events.NUIMouseWheelEvent;
import org.terasology.rendering.nui.widgets.UIList;
import java.util.List;
/**
* A generic context menu, implemented as a {@link CoreScreenLayer} spanning the canvas area it should be created within.
*/
public class ContextMenuScreen extends CoreScreenLayer {
public static final ResourceUrn ASSET_URI = new ResourceUrn("engine:contextMenuScreen");
/**
* A list of widgets to be used to draw the context menu.
*/
private List<UIList<AbstractContextMenuItem>> menuWidgets = Lists.newArrayList();
/**
* The initial position of the menu.
*/
private Vector2i position;
private InteractionListener mainListener = new BaseInteractionListener() {
@Override
public boolean onMouseClick(NUIMouseClickEvent event) {
// Close the context menu on click outside it.
getManager().closeScreen(ASSET_URI);
return false;
}
@Override
public boolean onMouseWheel(NUIMouseWheelEvent event) {
// Close the context menu on mouse wheel scroll outside it.
getManager().closeScreen(ASSET_URI);
// Consume the event to prevent awkward rendering if the menu is within a scrollable widget.
return true;
}
};
@Override
public void initialise() {
find("menu", UIList.class).setCanBeFocus(false);
}
@Override
public void onDraw(Canvas canvas) {
canvas.addInteractionRegion(mainListener);
Vector2i currentPosition = null;
int currentWidth = 0;
for (UIList<AbstractContextMenuItem> level : menuWidgets) {
if (level.isVisible()) {
if (currentPosition == null) {
currentPosition = new Vector2i(position);
} else {
currentPosition.addX(currentWidth);
}
Rect2i region = Rect2i.createFromMinAndSize(currentPosition,
canvas.calculatePreferredSize(level));
double percentageThreshold = 0.9;
if (region.maxY() > canvas.getRegion().height() * percentageThreshold) {
region = Rect2i.createFromMinAndMax(region.minX(),
region.minY()
- (region.maxY()
- canvas.getRegion().height())
- (int) (canvas.getRegion().height() * (1 - percentageThreshold)),
region.maxX(),
canvas.getRegion().height());
}
currentWidth = canvas.calculatePreferredSize(level).getX() - 8;
canvas.drawWidget(level, region);
}
}
}
public void setMenuWidgets(List<UIList<AbstractContextMenuItem>> levels) {
menuWidgets = levels;
}
public void setPosition(Vector2i position) {
this.position = position;
}
}