feat(renderer): add MultiLineTextArea control implementation and data structure for enhanced text input capabilities
This commit is contained in:
@@ -14,6 +14,7 @@ import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont;
|
|||||||
import de.extio.game_engine.renderer.g2d.control.impl.G2DBaseControlImpl;
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DBaseControlImpl;
|
||||||
import de.extio.game_engine.renderer.g2d.control.impl.G2DButtonControlImpl;
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DButtonControlImpl;
|
||||||
import de.extio.game_engine.renderer.g2d.control.impl.G2DLabelControlImpl;
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DLabelControlImpl;
|
||||||
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DMultiLineTextAreaControlImpl;
|
||||||
import de.extio.game_engine.renderer.g2d.control.impl.G2DSetFocusControl;
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DSetFocusControl;
|
||||||
import de.extio.game_engine.renderer.g2d.control.impl.G2DSliderControlImpl;
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DSliderControlImpl;
|
||||||
import de.extio.game_engine.renderer.g2d.control.impl.G2DSwitchControlImpl;
|
import de.extio.game_engine.renderer.g2d.control.impl.G2DSwitchControlImpl;
|
||||||
@@ -64,6 +65,8 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
|
|
||||||
private TextfieldData textfieldData;
|
private TextfieldData textfieldData;
|
||||||
|
|
||||||
|
private MultiLineTextAreaData multiLineTextAreaData;
|
||||||
|
|
||||||
private SliderData sliderData;
|
private SliderData sliderData;
|
||||||
|
|
||||||
private TableData tableData;
|
private TableData tableData;
|
||||||
@@ -140,6 +143,9 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
else if (data instanceof final TextfieldData textfieldData) {
|
else if (data instanceof final TextfieldData textfieldData) {
|
||||||
this.textfieldData = textfieldData;
|
this.textfieldData = textfieldData;
|
||||||
}
|
}
|
||||||
|
else if (data instanceof final MultiLineTextAreaData multiLineTextAreaData) {
|
||||||
|
this.multiLineTextAreaData = multiLineTextAreaData;
|
||||||
|
}
|
||||||
else if (data instanceof final SliderData sliderData) {
|
else if (data instanceof final SliderData sliderData) {
|
||||||
this.sliderData = sliderData;
|
this.sliderData = sliderData;
|
||||||
}
|
}
|
||||||
@@ -229,6 +235,9 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
else if (this.clazz == TextfieldControl.class) {
|
else if (this.clazz == TextfieldControl.class) {
|
||||||
control = new G2DTextfieldControlImpl2();
|
control = new G2DTextfieldControlImpl2();
|
||||||
}
|
}
|
||||||
|
else if (this.clazz == MultiLineTextAreaControl.class) {
|
||||||
|
control = new G2DMultiLineTextAreaControlImpl();
|
||||||
|
}
|
||||||
else if (this.clazz == ToggleButtonControl.class) {
|
else if (this.clazz == ToggleButtonControl.class) {
|
||||||
control = new G2DToggleButtonControlImpl();
|
control = new G2DToggleButtonControlImpl();
|
||||||
}
|
}
|
||||||
@@ -355,6 +364,12 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
tfc2.setLastCaptionUpdateTime(this.lastCaptionUpdateTime);
|
tfc2.setLastCaptionUpdateTime(this.lastCaptionUpdateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (this.clazz == MultiLineTextAreaControl.class && this.multiLineTextAreaData != null) {
|
||||||
|
((MultiLineTextAreaControl) control).setCustomData(this.multiLineTextAreaData);
|
||||||
|
if (control instanceof final G2DMultiLineTextAreaControlImpl mtac) {
|
||||||
|
mtac.setLastCaptionUpdateTime(this.lastCaptionUpdateTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
for (final var customControlConfiguration : this.customControlConfigurations) {
|
for (final var customControlConfiguration : this.customControlConfigurations) {
|
||||||
if (customControlConfiguration.getControlClass().equals(this.clazz)) {
|
if (customControlConfiguration.getControlClass().equals(this.clazz)) {
|
||||||
@@ -383,6 +398,7 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
this.windowCloseButtonData = o.windowCloseButtonData;
|
this.windowCloseButtonData = o.windowCloseButtonData;
|
||||||
this.windowPanelData = o.windowPanelData;
|
this.windowPanelData = o.windowPanelData;
|
||||||
this.textfieldData = o.textfieldData;
|
this.textfieldData = o.textfieldData;
|
||||||
|
this.multiLineTextAreaData = o.multiLineTextAreaData;
|
||||||
this.sliderData = o.sliderData;
|
this.sliderData = o.sliderData;
|
||||||
this.tableData = o.tableData;
|
this.tableData = o.tableData;
|
||||||
this.popupMenuData = o.popupMenuData;
|
this.popupMenuData = o.popupMenuData;
|
||||||
@@ -414,6 +430,7 @@ public class G2DDrawControl extends G2DAbstractRenderingBo implements ControlRen
|
|||||||
this.windowCloseButtonData = null;
|
this.windowCloseButtonData = null;
|
||||||
this.windowPanelData = null;
|
this.windowPanelData = null;
|
||||||
this.textfieldData = null;
|
this.textfieldData = null;
|
||||||
|
this.multiLineTextAreaData = null;
|
||||||
this.sliderData = null;
|
this.sliderData = null;
|
||||||
this.tableData = null;
|
this.tableData = null;
|
||||||
this.popupMenuData = null;
|
this.popupMenuData = null;
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
package de.extio.game_engine.renderer.g2d.control.impl;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
|
||||||
|
import de.extio.game_engine.renderer.RendererData;
|
||||||
|
import de.extio.game_engine.renderer.g2d.G2DRenderer;
|
||||||
|
import de.extio.game_engine.renderer.g2d.control.components.CustomMultiLineTextArea;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.BaseControl;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.MultiLineTextAreaControl;
|
||||||
|
import de.extio.game_engine.renderer.model.bo.ControlRenderingBo.MultiLineTextAreaData;
|
||||||
|
import de.extio.game_engine.renderer.model.color.RgbaColor;
|
||||||
|
import de.extio.game_engine.renderer.model.event.UiControlEvent;
|
||||||
|
|
||||||
|
public class G2DMultiLineTextAreaControlImpl extends G2DBaseControlImpl implements MultiLineTextAreaControl {
|
||||||
|
|
||||||
|
private CustomMultiLineTextArea textArea;
|
||||||
|
|
||||||
|
private boolean readonly;
|
||||||
|
|
||||||
|
private long lastCaptionUpdateTime;
|
||||||
|
|
||||||
|
private long lastCaptionUpdateTimeInternal;
|
||||||
|
|
||||||
|
private String lastText = "";
|
||||||
|
|
||||||
|
private RgbaColor backgroundColor;
|
||||||
|
|
||||||
|
private boolean scrollPositionModified;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCustomData(final MultiLineTextAreaData data) {
|
||||||
|
if (data != null) {
|
||||||
|
this.setReadonly(data.readonly());
|
||||||
|
this.setBackgroundColor(data.backgroundColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public G2DMultiLineTextAreaControlImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBackgroundColor(final RgbaColor color) {
|
||||||
|
this.modified |= (color == null) ? this.backgroundColor != null : !color.equals(this.backgroundColor);
|
||||||
|
this.backgroundColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setReadonly(final boolean readonly) {
|
||||||
|
this.modified |= readonly != this.readonly;
|
||||||
|
this.readonly = readonly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseControl setCaption(final String caption) {
|
||||||
|
this.caption = caption;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastCaptionUpdateTime(final long lastCaptionUpdateTime) {
|
||||||
|
this.modified |= this.lastCaptionUpdateTime != lastCaptionUpdateTime;
|
||||||
|
this.lastCaptionUpdateTime = lastCaptionUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build() {
|
||||||
|
super.build();
|
||||||
|
|
||||||
|
this.textArea = new CustomMultiLineTextArea(this.rendererData.getThemeManager(), text -> {
|
||||||
|
this.lastText = text;
|
||||||
|
this.lastCaptionUpdateTimeInternal = System.currentTimeMillis();
|
||||||
|
this.rendererData.getEventService().fire(new UiControlEvent(this.id, text));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.textArea.setName(this.id);
|
||||||
|
this.textArea.setFocusable(true);
|
||||||
|
this.initControl();
|
||||||
|
|
||||||
|
final var mainFrame = ((G2DRenderer) this.rendererData.getRenderer()).getMainFrame();
|
||||||
|
mainFrame.add(this.textArea);
|
||||||
|
this.updateAllComponentZOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
if (this.lastCaptionUpdateTime > this.lastCaptionUpdateTimeInternal && this.caption != null && !this.caption.equals(this.lastText)) {
|
||||||
|
this.textArea.setText(this.caption);
|
||||||
|
this.lastText = this.caption;
|
||||||
|
this.lastCaptionUpdateTimeInternal = this.lastCaptionUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean componentDirty = this.textArea.isDirty();
|
||||||
|
if (this.modified || componentDirty || this.scrollPositionModified) {
|
||||||
|
this.rebuildBufferedImage();
|
||||||
|
this.bufferedImageGraphics.setClip(0, 0, this.bufferedImage.getWidth(), this.bufferedImage.getHeight());
|
||||||
|
this.textArea.setSize(this.bufferedImage.getWidth(), this.bufferedImage.getHeight());
|
||||||
|
if (this.modified || componentDirty) {
|
||||||
|
this.initControl();
|
||||||
|
}
|
||||||
|
this.textArea.paint(this.bufferedImageGraphics);
|
||||||
|
this.textArea.setDirty(false);
|
||||||
|
this.scrollPositionModified = false;
|
||||||
|
this.updateAllComponentZOrder();
|
||||||
|
}
|
||||||
|
else if (this.positionModified) {
|
||||||
|
this.textArea.setLocation(this.x, this.y);
|
||||||
|
this.positionModified = false;
|
||||||
|
this.updateAllComponentZOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.textArea.paint(this.bufferedImageGraphics);
|
||||||
|
|
||||||
|
super.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (this.textArea.isFocusOwner()) {
|
||||||
|
((G2DRenderer) this.rendererData.getRenderer()).getMainFrame().requestFocus();
|
||||||
|
}
|
||||||
|
this.textArea.setVisible(false);
|
||||||
|
this.textArea.invalidate();
|
||||||
|
((G2DRenderer) this.rendererData.getRenderer()).getMainFrame().remove(this.textArea);
|
||||||
|
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initControl() {
|
||||||
|
final var theme = this.rendererData.getThemeManager().getCurrentTheme();
|
||||||
|
final var bgColor = this.backgroundColor != null ? this.backgroundColor.toAwtColor() : theme.getBackgroundNormal().toColor();
|
||||||
|
final var fgColor = theme.getTextNormal().toColor();
|
||||||
|
|
||||||
|
this.textArea.setBackgroundColor(bgColor);
|
||||||
|
this.textArea.setForegroundColor(fgColor);
|
||||||
|
this.textArea.setFontSize(this.fontSize);
|
||||||
|
this.textArea.setScaleFactor(this.scaleFactor);
|
||||||
|
this.textArea.setLocation(this.x, this.y);
|
||||||
|
this.textArea.setSize(this.width, this.height);
|
||||||
|
this.positionModified = false;
|
||||||
|
this.textArea.setVisible(this.visible);
|
||||||
|
this.textArea.setEnabled(this.enabled);
|
||||||
|
this.textArea.setReadonly(this.readonly);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public G2DBaseControlImpl setScaleFactor(final double scaleFactor) {
|
||||||
|
return super.setScaleFactor(scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseControl setControlGroup(final String controlGroup) {
|
||||||
|
return super.setControlGroup(controlGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseControl setRendererData(final RendererData RendererData) {
|
||||||
|
return super.setRendererData(RendererData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public G2DBaseControlImpl setMainFrameGraphics(final Graphics2D graphics) {
|
||||||
|
return super.setMainFrameGraphics(graphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseControl setControlId(final String id) {
|
||||||
|
return super.setControlId(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,7 +24,9 @@ public interface ControlRenderingBo extends RenderingBoHasDimension {
|
|||||||
|
|
||||||
record WindowPanelData(boolean thickBorder, RgbaColor color) {}
|
record WindowPanelData(boolean thickBorder, RgbaColor color) {}
|
||||||
|
|
||||||
record TextfieldData(boolean multiLine, boolean readonly, RgbaColor backgroundColor) {}
|
record TextfieldData(boolean readonly, RgbaColor backgroundColor) {}
|
||||||
|
|
||||||
|
record MultiLineTextAreaData(boolean readonly, RgbaColor backgroundColor) {}
|
||||||
|
|
||||||
record SliderData(boolean horizontal, double value, double value2, RgbaColor color) {}
|
record SliderData(boolean horizontal, double value, double value2, RgbaColor color) {}
|
||||||
|
|
||||||
@@ -163,6 +165,15 @@ public interface ControlRenderingBo extends RenderingBoHasDimension {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multi-line text area (Java2D-based, no Swing)
|
||||||
|
*/
|
||||||
|
public static interface MultiLineTextAreaControl extends BaseControl {
|
||||||
|
|
||||||
|
void setCustomData(MultiLineTextAreaData data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slider
|
* Slider
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user