Add support for window inflating
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package com.bartlomiejpluta.base.api.game.gui.base;
|
package com.bartlomiejpluta.base.api.game.gui.base;
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
||||||
|
import com.bartlomiejpluta.base.api.game.gui.window.Window;
|
||||||
import com.bartlomiejpluta.base.api.game.input.KeyEventHandler;
|
import com.bartlomiejpluta.base.api.game.input.KeyEventHandler;
|
||||||
import com.bartlomiejpluta.base.api.internal.gc.Disposable;
|
import com.bartlomiejpluta.base.api.internal.gc.Disposable;
|
||||||
import com.bartlomiejpluta.base.api.internal.render.Renderable;
|
import com.bartlomiejpluta.base.api.internal.render.Renderable;
|
||||||
@@ -23,6 +24,8 @@ public interface GUI extends Renderable, Disposable, KeyEventHandler {
|
|||||||
|
|
||||||
Component inflateComponent(String widgetUid);
|
Component inflateComponent(String widgetUid);
|
||||||
|
|
||||||
|
Window inflateWindow(String widgetUid);
|
||||||
|
|
||||||
Widget getRoot();
|
Widget getRoot();
|
||||||
|
|
||||||
void setRoot(Widget root);
|
void setRoot(Widget root);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.bartlomiejpluta.base.api.game.gui.window;
|
package com.bartlomiejpluta.base.api.game.gui.window;
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.api.game.context.Context;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.base.BaseWidget;
|
import com.bartlomiejpluta.base.api.game.gui.base.BaseWidget;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
|
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
||||||
@@ -9,9 +10,29 @@ import com.bartlomiejpluta.base.api.game.screen.Screen;
|
|||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
public abstract class BaseWindow extends BaseWidget implements Window {
|
public abstract class BaseWindow extends BaseWidget implements Window {
|
||||||
|
protected Context context;
|
||||||
|
protected GUI gui;
|
||||||
protected Component content;
|
protected Component content;
|
||||||
protected WindowPosition windowPosition;
|
protected WindowPosition windowPosition;
|
||||||
|
|
||||||
|
protected BaseWindow(Context context, GUI gui) {
|
||||||
|
this.context = context;
|
||||||
|
this.gui = gui;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContent(Component component) {
|
||||||
|
if (this.content != null) {
|
||||||
|
this.content.setParent(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.content = component;
|
||||||
|
|
||||||
|
if (component != null) {
|
||||||
|
component.setParent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WindowPosition getWindowPosition() {
|
public WindowPosition getWindowPosition() {
|
||||||
return windowPosition;
|
return windowPosition;
|
||||||
@@ -38,16 +59,6 @@ public abstract class BaseWindow extends BaseWidget implements Window {
|
|||||||
content.draw(screen, gui);
|
content.draw(screen, gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOpen(WindowManager manager) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClose(WindowManager manager) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleKeyEvent(KeyEvent event) {
|
public void handleKeyEvent(KeyEvent event) {
|
||||||
content.handleKeyEvent(event);
|
content.handleKeyEvent(event);
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
package com.bartlomiejpluta.base.api.game.gui.window;
|
package com.bartlomiejpluta.base.api.game.gui.window;
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.api.game.gui.base.Widget;
|
import com.bartlomiejpluta.base.api.game.gui.base.Widget;
|
||||||
|
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
||||||
|
|
||||||
public interface Window extends Widget {
|
public interface Window extends Widget {
|
||||||
|
void setContent(Component component);
|
||||||
|
|
||||||
WindowPosition getWindowPosition();
|
WindowPosition getWindowPosition();
|
||||||
|
|
||||||
void setWindowPosition(WindowPosition windowPosition);
|
void setWindowPosition(WindowPosition windowPosition);
|
||||||
|
|
||||||
void onOpen(WindowManager manager);
|
default void onOpen(WindowManager manager) {
|
||||||
|
// do nothing
|
||||||
void onClose(WindowManager manager);
|
}
|
||||||
|
|
||||||
|
default void onClose(WindowManager manager) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import com.bartlomiejpluta.base.engine.context.model.DefaultContext;
|
|||||||
import com.bartlomiejpluta.base.engine.core.engine.GameEngine;
|
import com.bartlomiejpluta.base.engine.core.engine.GameEngine;
|
||||||
import com.bartlomiejpluta.base.engine.gui.manager.FontManager;
|
import com.bartlomiejpluta.base.engine.gui.manager.FontManager;
|
||||||
import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager;
|
import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager;
|
||||||
import com.bartlomiejpluta.base.engine.gui.xml.inflater.ComponentInflater;
|
import com.bartlomiejpluta.base.engine.gui.xml.inflater.Inflater;
|
||||||
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
|
||||||
import com.bartlomiejpluta.base.engine.project.serial.ProjectDeserializer;
|
import com.bartlomiejpluta.base.engine.project.serial.ProjectDeserializer;
|
||||||
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
||||||
@@ -35,7 +35,7 @@ public class DefaultContextManager implements ContextManager {
|
|||||||
private final FontManager fontManager;
|
private final FontManager fontManager;
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
private final ComponentInflater inflater;
|
private final Inflater inflater;
|
||||||
private final WidgetDefinitionManager widgetDefinitionManager;
|
private final WidgetDefinitionManager widgetDefinitionManager;
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import com.bartlomiejpluta.base.engine.core.engine.GameEngine;
|
|||||||
import com.bartlomiejpluta.base.engine.gui.manager.FontManager;
|
import com.bartlomiejpluta.base.engine.gui.manager.FontManager;
|
||||||
import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager;
|
import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager;
|
||||||
import com.bartlomiejpluta.base.engine.gui.render.NanoVGGUI;
|
import com.bartlomiejpluta.base.engine.gui.render.NanoVGGUI;
|
||||||
import com.bartlomiejpluta.base.engine.gui.xml.inflater.ComponentInflater;
|
import com.bartlomiejpluta.base.engine.gui.xml.inflater.Inflater;
|
||||||
import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager;
|
import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
|
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
|
||||||
@@ -48,7 +48,7 @@ public class DefaultContext implements Context {
|
|||||||
private final FontManager fontManager;
|
private final FontManager fontManager;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final ComponentInflater inflater;
|
private final Inflater inflater;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final WidgetDefinitionManager widgetDefinitionManager;
|
private final WidgetDefinitionManager widgetDefinitionManager;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.bartlomiejpluta.base.api.game.camera.Camera;
|
|||||||
import com.bartlomiejpluta.base.api.game.context.Context;
|
import com.bartlomiejpluta.base.api.game.context.Context;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.base.*;
|
import com.bartlomiejpluta.base.api.game.gui.base.*;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
||||||
|
import com.bartlomiejpluta.base.api.game.gui.window.Window;
|
||||||
import com.bartlomiejpluta.base.api.game.input.KeyEvent;
|
import com.bartlomiejpluta.base.api.game.input.KeyEvent;
|
||||||
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
||||||
import com.bartlomiejpluta.base.api.internal.render.ShaderManager;
|
import com.bartlomiejpluta.base.api.internal.render.ShaderManager;
|
||||||
@@ -11,7 +12,7 @@ import com.bartlomiejpluta.base.engine.error.AppException;
|
|||||||
import com.bartlomiejpluta.base.engine.gui.manager.FontManager;
|
import com.bartlomiejpluta.base.engine.gui.manager.FontManager;
|
||||||
import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager;
|
import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager;
|
||||||
import com.bartlomiejpluta.base.engine.gui.widget.ScreenWidget;
|
import com.bartlomiejpluta.base.engine.gui.widget.ScreenWidget;
|
||||||
import com.bartlomiejpluta.base.engine.gui.xml.inflater.ComponentInflater;
|
import com.bartlomiejpluta.base.engine.gui.xml.inflater.Inflater;
|
||||||
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -35,7 +36,7 @@ public class NanoVGGUI implements GUI {
|
|||||||
private final Context context;
|
private final Context context;
|
||||||
private final FontManager fontManager;
|
private final FontManager fontManager;
|
||||||
private final ImageManager imageManager;
|
private final ImageManager imageManager;
|
||||||
private final ComponentInflater inflater;
|
private final Inflater inflater;
|
||||||
private final WidgetDefinitionManager widgetDefinitionManager;
|
private final WidgetDefinitionManager widgetDefinitionManager;
|
||||||
|
|
||||||
private long nvg;
|
private long nvg;
|
||||||
@@ -69,7 +70,14 @@ public class NanoVGGUI implements GUI {
|
|||||||
public Component inflateComponent(String widgetUid) {
|
public Component inflateComponent(String widgetUid) {
|
||||||
log.info("Inflating component by widget definition with UID: [{}]", widgetUid);
|
log.info("Inflating component by widget definition with UID: [{}]", widgetUid);
|
||||||
var is = widgetDefinitionManager.loadObject(widgetUid);
|
var is = widgetDefinitionManager.loadObject(widgetUid);
|
||||||
return inflater.inflate(is, context, this);
|
return inflater.inflateComponent(is, context, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Window inflateWindow(String widgetUid) {
|
||||||
|
log.info("Inflating window by widget definition with UID: [{}]", widgetUid);
|
||||||
|
var is = widgetDefinitionManager.loadObject(widgetUid);
|
||||||
|
return inflater.inflateWindow(is, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import com.bartlomiejpluta.base.api.game.context.Context;
|
|||||||
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
|
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.base.SizeMode;
|
import com.bartlomiejpluta.base.api.game.gui.base.SizeMode;
|
||||||
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
import com.bartlomiejpluta.base.api.game.gui.component.Component;
|
||||||
|
import com.bartlomiejpluta.base.api.game.gui.window.Window;
|
||||||
|
import com.bartlomiejpluta.base.api.game.gui.window.WindowPosition;
|
||||||
|
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||||
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.codehaus.janino.ExpressionEvaluator;
|
import org.codehaus.janino.ExpressionEvaluator;
|
||||||
@@ -18,14 +21,17 @@ import java.io.InputStream;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@org.springframework.stereotype.Component
|
@org.springframework.stereotype.Component
|
||||||
public class ComponentInflater {
|
public class Inflater {
|
||||||
private static final String[] IMPORTS = Stream.of(GUI.class, SizeMode.class).map(Class::getCanonicalName).toArray(String[]::new);
|
private static final String[] IMPORTS = Stream.of(GUI.class, SizeMode.class, WindowPosition.class)
|
||||||
|
.map(Class::getCanonicalName)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
|
||||||
private final DocumentBuilder builder;
|
private final DocumentBuilder builder;
|
||||||
private final ClassLoader loader;
|
private final ClassLoader loader;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public ComponentInflater(ClassLoader loader) {
|
public Inflater(ClassLoader loader) {
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
|
|
||||||
var factory = DocumentBuilderFactory.newInstance();
|
var factory = DocumentBuilderFactory.newInstance();
|
||||||
@@ -34,21 +40,98 @@ public class ComponentInflater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public Component inflate(String xml, Context context, GUI gui) {
|
public Component inflateComponent(String xml, Context context, GUI gui) {
|
||||||
var document = builder.parse(xml);
|
var document = builder.parse(xml);
|
||||||
return parseNode(document.getDocumentElement(), context, gui);
|
return inflateComponent(document.getDocumentElement(), context, gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public Component inflate(File file, Context context, GUI gui) {
|
public Component inflateComponent(File file, Context context, GUI gui) {
|
||||||
var document = builder.parse(file);
|
var document = builder.parse(file);
|
||||||
return parseNode(document.getDocumentElement(), context, gui);
|
return inflateComponent(document.getDocumentElement(), context, gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public Component inflate(InputStream is, Context context, GUI gui) {
|
public Component inflateComponent(InputStream is, Context context, GUI gui) {
|
||||||
var document = builder.parse(is);
|
var document = builder.parse(is);
|
||||||
return parseNode(document.getDocumentElement(), context, gui);
|
return inflateComponent(document.getDocumentElement(), context, gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public Window inflateWindow(String xml, Context context, GUI gui) {
|
||||||
|
var document = builder.parse(xml);
|
||||||
|
return inflateWindow(document.getDocumentElement(), context, gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public Window inflateWindow(File file, Context context, GUI gui) {
|
||||||
|
var document = builder.parse(file);
|
||||||
|
return inflateWindow(document.getDocumentElement(), context, gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public Window inflateWindow(InputStream is, Context context, GUI gui) {
|
||||||
|
var document = builder.parse(is);
|
||||||
|
return inflateWindow(document.getDocumentElement(), context, gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private Window inflateWindow(Node root, Context context, GUI gui) {
|
||||||
|
var uri = root.getNamespaceURI();
|
||||||
|
var name = root.getLocalName();
|
||||||
|
|
||||||
|
if (uri != null) {
|
||||||
|
name = uri + "." + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
var canonicalName = name.replaceAll("\\*", "").replaceAll("\\.+", ".");
|
||||||
|
|
||||||
|
var windowClass = loader.loadClass(canonicalName);
|
||||||
|
|
||||||
|
var window = (Window) windowClass.getConstructor(Context.class, GUI.class).newInstance(context, gui);
|
||||||
|
var attributes = root.getAttributes();
|
||||||
|
|
||||||
|
// Set attributes via setter methods
|
||||||
|
for (int i = 0; i < attributes.getLength(); ++i) {
|
||||||
|
var attribute = attributes.item(i);
|
||||||
|
|
||||||
|
// Ignore namespaces definitions
|
||||||
|
if ("xmlns".equals(attribute.getPrefix())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var setterName = createSetterMethodName(attribute.getLocalName());
|
||||||
|
var value = parseValue(attribute.getNodeValue());
|
||||||
|
var setter = windowClass.getMethod(setterName, value.getClass());
|
||||||
|
setter.invoke(window, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse window content
|
||||||
|
var children = root.getChildNodes();
|
||||||
|
|
||||||
|
boolean hasContent = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < children.getLength(); ++i) {
|
||||||
|
var child = children.item(i);
|
||||||
|
|
||||||
|
if (child.getNodeType() != Node.ELEMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasContent) {
|
||||||
|
throw new AppException("Window can have at most 1 child");
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = parseNode(child, context, gui);
|
||||||
|
window.setContent(content);
|
||||||
|
hasContent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component inflateComponent(Node root, Context context, GUI gui) {
|
||||||
|
return parseNode(root, context, gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
Reference in New Issue
Block a user