339 lines
8.8 KiB
Java
339 lines
8.8 KiB
Java
package speiger.src.coreengine.rendering.gui.components;
|
|
|
|
import speiger.src.collections.objects.functions.function.Object2FloatFunction;
|
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
|
import speiger.src.collections.objects.lists.ObjectList;
|
|
import speiger.src.coreengine.math.misc.ColorUtils;
|
|
import speiger.src.coreengine.math.misc.Facing;
|
|
import speiger.src.coreengine.rendering.gui.GuiComponent;
|
|
import speiger.src.coreengine.rendering.gui.base.IButtonComponent;
|
|
import speiger.src.coreengine.rendering.gui.helper.Align;
|
|
import speiger.src.coreengine.rendering.gui.helper.constrains.Constrain.Target;
|
|
import speiger.src.coreengine.rendering.gui.helper.constrains.Constrains;
|
|
import speiger.src.coreengine.rendering.gui.helper.constrains.DynamicConstrain;
|
|
import speiger.src.coreengine.utils.functions.FloatSupplier;
|
|
|
|
public class TabbedPanelComponent extends PanelComponent
|
|
{
|
|
PanelComponent selection = new PanelComponent();
|
|
ObjectList<Tab> tabs = new ObjectArrayList<>();
|
|
int selectedTab = -1;
|
|
float tabScale = 1F;
|
|
|
|
Facing facing;
|
|
int backgroundColor = ColorUtils.GRAY;
|
|
int unselectedColor = ColorUtils.GRAY;
|
|
int selectedColor = ColorUtils.DARK_GRAY;
|
|
float padding = 30F;
|
|
|
|
public TabbedPanelComponent()
|
|
{
|
|
this(Facing.NORTH);
|
|
}
|
|
|
|
public TabbedPanelComponent(Facing facing)
|
|
{
|
|
this(0F, 0F, 0F, 0F, facing);
|
|
}
|
|
|
|
public TabbedPanelComponent(float x, float y, float width, float height)
|
|
{
|
|
this(x, y, width, height, Facing.NORTH);
|
|
}
|
|
|
|
public TabbedPanelComponent(float x, float y, float width, float height, Facing facing)
|
|
{
|
|
super(x, y, width, height);
|
|
this.facing = facing;
|
|
}
|
|
|
|
public TabbedPanelComponent setFacing(Facing facing)
|
|
{
|
|
this.facing = facing;
|
|
updateConstrains(selection, createView());
|
|
for(Tab tab : tabs)
|
|
{
|
|
updateConstrains(tab.align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)), createConstraint(tab));
|
|
updateConstrains(tab.getPanel(), createPanel());
|
|
}
|
|
onChanged(true);
|
|
return this;
|
|
}
|
|
|
|
public TabbedPanelComponent setPadding(float padding)
|
|
{
|
|
this.padding = padding;
|
|
for(Tab tab : tabs)
|
|
{
|
|
tab.updatePadding();
|
|
}
|
|
onChanged(true);
|
|
return this;
|
|
}
|
|
|
|
public Facing getFacing()
|
|
{
|
|
return facing;
|
|
}
|
|
|
|
public PanelComponent addTab(String name)
|
|
{
|
|
Tab newTab = new Tab(name).align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM));
|
|
tabs.add(newTab);
|
|
if(selectedTab == -1) {
|
|
selectedTab = tabs.size()-1;
|
|
newTab.getPanel().setVisible(true);
|
|
}
|
|
newTab.onAction(() -> selectTab(newTab));
|
|
selection.addChild(newTab, createConstraint(newTab));
|
|
addChild(newTab.getPanel(), createPanel());
|
|
onChanged(true);
|
|
return newTab.getPanel();
|
|
}
|
|
|
|
public int findTab(String name)
|
|
{
|
|
for(int i = 0,m=tabs.size();i<m;i++) {
|
|
if(tabs.get(i).name.equals(name)) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public int getActiveIndex()
|
|
{
|
|
return selectedTab;
|
|
}
|
|
|
|
public PanelComponent getActiveTab()
|
|
{
|
|
return selectedTab == -1 ? null : tabs.get(selectedTab).getPanel();
|
|
}
|
|
|
|
@Override
|
|
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
getRenderer().drawQuad(selection.getBox(), backgroundColor);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void init()
|
|
{
|
|
addChild(selection, createView());
|
|
super.init();
|
|
}
|
|
|
|
@Override
|
|
protected void repaint()
|
|
{
|
|
if(facing.isZAxis())
|
|
{
|
|
float room = getBox().getBaseWidth();
|
|
float requiredSpace = 0F;
|
|
for(int i = 0,m=tabs.size();i<m;i++)
|
|
{
|
|
Tab tab = tabs.get(i);
|
|
float width = tab.getWidth() * tab.getTextScale();
|
|
if(i == selectedTab) room -= width;
|
|
else requiredSpace += width;
|
|
}
|
|
tabScale = Math.min(1F, room / requiredSpace);
|
|
}
|
|
else
|
|
{
|
|
tabScale = 0F;
|
|
for(int i = 0,m=tabs.size();i<m;i++)
|
|
{
|
|
Tab tab = tabs.get(i);
|
|
tabScale = Math.max(tabScale, tab.getWidth() * tab.getTextScale());
|
|
}
|
|
tabScale *= getBox().getScale();
|
|
tabScale += 1F;
|
|
}
|
|
}
|
|
|
|
protected Constrains createView()
|
|
{
|
|
switch(facing)
|
|
{
|
|
case NORTH: return Constrains.parent(Target.X).parent(Target.Y).parent(Target.WIDTH).height(7.5F).build();
|
|
case SOUTH: return Constrains.parent(Target.X).invParent(7.7F, Target.Y).parent(Target.WIDTH).height(7.5F).build();
|
|
case EAST: return Constrains.xPos(new DynamicConstrain(this::getXOffset).setInverted(true)).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build();
|
|
case WEST: return Constrains.parent(Target.X).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build();
|
|
default: return Constrains.parent();
|
|
}
|
|
}
|
|
|
|
protected Constrains createPanel()
|
|
{
|
|
switch(facing)
|
|
{
|
|
case NORTH: return Constrains.parent(0F, 7.2F, 0F, 3.6F);
|
|
case SOUTH: return Constrains.parent(0F, 0F, 0F, 3.6F);
|
|
case EAST: return Constrains.parent(Target.X).parent(Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build();
|
|
case WEST: return Constrains.dynamic(this::getXOffset, Target.X).parent(0F, Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build();
|
|
default: return Constrains.parent();
|
|
}
|
|
}
|
|
|
|
protected Constrains createConstraint(Tab tab)
|
|
{
|
|
if(facing.isZAxis()) return Constrains.parent(Target.Y).parent(Target.HEIGHT).dynamic(new DynamicTab(tab, this::getOffset), Target.X).dynamic(new DynamicTab(tab, this::getWidth), Target.WIDTH).build();
|
|
return Constrains.parent(Target.X).dynamic(new DynamicTab(tab, this::getOffset), Target.Y).parent(Target.WIDTH).height(7.5F).build();
|
|
}
|
|
|
|
protected void selectTab(Tab tab)
|
|
{
|
|
selectTab(tabs.indexOf(tab));
|
|
}
|
|
|
|
public boolean selectTab(int index)
|
|
{
|
|
if(index < 0 || index >= tabs.size()) return false;
|
|
if(selectedTab == index) return false;
|
|
if(selectedTab != -1) tabs.get(selectedTab).getPanel().setVisible(false);
|
|
selectedTab = index;
|
|
tabs.get(selectedTab).getPanel().setVisible(true);
|
|
onChanged(true);
|
|
return true;
|
|
}
|
|
|
|
protected float getOffset(Tab tab)
|
|
{
|
|
int index = tabs.indexOf(tab);
|
|
float offset = 0F;
|
|
for(int i = 0;i<index;i++)
|
|
{
|
|
Tab entry = tabs.get(i);
|
|
if(facing.isZAxis()) offset += entry.getWidth() * (i == selectedTab ? 1F : tabScale) * entry.getTextScale();
|
|
else offset += tab.getBox().getBaseHeight();
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
protected float getPanelOffset()
|
|
{
|
|
return facing == Facing.EAST ? 0F : tabScale + 0.25F;
|
|
}
|
|
|
|
protected float getPanelWidth()
|
|
{
|
|
return tabScale + 0.25F;
|
|
}
|
|
|
|
protected float getXOffset()
|
|
{
|
|
return tabScale + 0.25F;
|
|
}
|
|
|
|
protected float getWidth(Tab tab)
|
|
{
|
|
return facing.isZAxis() ? tab.getWidth() * (selectedTab == tabs.indexOf(tab) ? 1F : tabScale) * tab.getTextScale() : tabScale;
|
|
}
|
|
|
|
private static class DynamicTab implements FloatSupplier
|
|
{
|
|
Tab tab;
|
|
Object2FloatFunction<Tab> function;
|
|
|
|
public DynamicTab(Tab tab, Object2FloatFunction<Tab> function)
|
|
{
|
|
this.tab = tab;
|
|
this.function = function;
|
|
}
|
|
|
|
@Override
|
|
public float getAsFloat()
|
|
{
|
|
return function.getFloat(tab);
|
|
}
|
|
}
|
|
|
|
private class Tab extends GuiComponent implements IButtonComponent
|
|
{
|
|
String name;
|
|
float width = -1F;
|
|
TextComponent comp;
|
|
PanelComponent panel = new PanelComponent().setScissors(true).setVisible(false).cast();
|
|
|
|
public Tab(String name)
|
|
{
|
|
super(0F, 0F, 100F, 7.5F);
|
|
this.name = name;
|
|
comp = new TextComponent(name).setTextScale(0.4F).singleLine(true).horizontal(Align.LEFT_TOP);
|
|
setFlag(FLAG_SUPPORT_BINDING);
|
|
}
|
|
|
|
public Tab align(Align align)
|
|
{
|
|
comp.horizontal(align);
|
|
return this;
|
|
}
|
|
|
|
public void updatePadding()
|
|
{
|
|
if(getGui() != null) width = getFont().width(name)+padding;
|
|
}
|
|
|
|
@Override
|
|
public void init()
|
|
{
|
|
addChild(comp, Constrains.parent());
|
|
updatePadding();
|
|
}
|
|
|
|
public float getWidth()
|
|
{
|
|
return width;
|
|
}
|
|
|
|
public float getTextScale()
|
|
{
|
|
return comp.getTextScale();
|
|
}
|
|
|
|
@Override
|
|
protected void repaint()
|
|
{
|
|
String s = name;
|
|
float scale = comp.getTextScale();
|
|
float width = (this.width-padding)*scale;
|
|
float desiredWidth = getBox().getBaseWidth();
|
|
if(width > desiredWidth) {
|
|
while(s.length() >= 1 && getFont().width(s+"...") * scale > desiredWidth) {
|
|
s = s.substring(0, s.length()-1);
|
|
}
|
|
comp.setText(s+"...");
|
|
return;
|
|
}
|
|
comp.setText(s);
|
|
}
|
|
|
|
public PanelComponent getPanel()
|
|
{
|
|
return panel;
|
|
}
|
|
|
|
@Override
|
|
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
boolean notSelected = tabs.indexOf(this) != selectedTab;
|
|
getRenderer().drawQuad(getBox(), notSelected ? unselectedColor : selectedColor);
|
|
if(notSelected) getRenderer().drawFrame(getBox(), selectedColor);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void onRelease(int button, int mouseX, int mouseY)
|
|
{
|
|
notifyListeners(LISTENER_USER_ACTION);
|
|
}
|
|
|
|
@Override
|
|
protected boolean onUserKey()
|
|
{
|
|
notifyListeners(LISTENER_USER_ACTION);
|
|
return true;
|
|
}
|
|
}
|
|
} |