Skip to content

Commit 0066c71

Browse files
committed
Update UILoader.
1 parent df5530b commit 0066c71

File tree

1 file changed

+76
-29
lines changed

1 file changed

+76
-29
lines changed

sierra/src/main/java/org/httprpc/sierra/UILoader.java

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,13 @@
6767
import java.io.File;
6868
import java.io.FileOutputStream;
6969
import java.io.IOException;
70+
import java.io.InputStream;
7071
import java.io.Writer;
7172
import java.lang.reflect.Field;
7273
import java.lang.reflect.InvocationTargetException;
74+
import java.net.MalformedURLException;
75+
import java.net.URL;
76+
import java.nio.file.Path;
7377
import java.util.ArrayList;
7478
import java.util.Comparator;
7579
import java.util.Deque;
@@ -299,6 +303,8 @@ void declareAttributeList(String tag, Class<?> type, Writer writer) throws IOExc
299303
private String name;
300304
private ResourceBundle resourceBundle;
301305

306+
private Path path;
307+
302308
private Map<String, Field> fields = new HashMap<>();
303309
private Map<String, ButtonGroup> groups = new HashMap<>();
304310

@@ -586,16 +592,20 @@ private UILoader(Object owner, String name, ResourceBundle resourceBundle) {
586592
this.resourceBundle = resourceBundle;
587593
}
588594

589-
private JComponent load() {
590-
var type = owner.getClass();
595+
private UILoader(Path path) {
596+
this.path = path;
597+
}
591598

592-
var fields = type.getDeclaredFields();
599+
private JComponent load() {
600+
if (owner != null) {
601+
var fields = owner.getClass().getDeclaredFields();
593602

594-
for (var i = 0; i < fields.length; i++) {
595-
var field = fields[i];
603+
for (var i = 0; i < fields.length; i++) {
604+
var field = fields[i];
596605

597-
if (JComponent.class.isAssignableFrom(field.getType())) {
598-
this.fields.put(field.getName(), field);
606+
if (JComponent.class.isAssignableFrom(field.getType())) {
607+
this.fields.put(field.getName(), field);
608+
}
599609
}
600610
}
601611

@@ -605,7 +615,7 @@ private JComponent load() {
605615
xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
606616
xmlInputFactory.setProperty("javax.xml.stream.supportDTD", false);
607617

608-
try (var inputStream = type.getResourceAsStream(name)) {
618+
try (var inputStream = open()) {
609619
if (inputStream == null) {
610620
throw new UnsupportedOperationException("Named resource does not exist.");
611621
}
@@ -631,6 +641,14 @@ private JComponent load() {
631641
return root;
632642
}
633643

644+
private InputStream open() throws IOException {
645+
if (owner != null) {
646+
return owner.getClass().getResourceAsStream(name);
647+
} else {
648+
return path.toUri().toURL().openStream();
649+
}
650+
}
651+
634652
private void processStartElement(XMLStreamReader xmlStreamReader) {
635653
var tag = xmlStreamReader.getLocalName();
636654

@@ -660,22 +678,24 @@ private void processStartElement(XMLStreamReader xmlStreamReader) {
660678
if (name.equals(NAME)) {
661679
component.setName(value);
662680

663-
var field = fields.get(value);
681+
if (owner != null) {
682+
var field = fields.get(value);
664683

665-
if (field == null) {
666-
throw new UnsupportedOperationException(String.format("Invalid field name (%s).", value));
667-
}
684+
if (field == null) {
685+
throw new UnsupportedOperationException(String.format("Invalid field name (%s).", value));
686+
}
668687

669-
field.setAccessible(true);
688+
field.setAccessible(true);
670689

671-
try {
672-
if (field.get(owner) != null) {
673-
throw new UnsupportedOperationException(String.format("Field is already assigned (%s).", value));
674-
}
690+
try {
691+
if (field.get(owner) != null) {
692+
throw new UnsupportedOperationException(String.format("Field is already assigned (%s).", value));
693+
}
675694

676-
field.set(owner, component);
677-
} catch (IllegalAccessException exception) {
678-
throw new UnsupportedOperationException(exception);
695+
field.set(owner, component);
696+
} catch (IllegalAccessException exception) {
697+
throw new UnsupportedOperationException(exception);
698+
}
679699
}
680700
} else if (name.equals(GROUP)) {
681701
if (!(component instanceof AbstractButton button)) {
@@ -797,25 +817,33 @@ private String getText(String value) {
797817
}
798818

799819
private Icon getIcon(String value) {
800-
return icons.computeIfAbsent(value, key -> {
801-
if (value.endsWith(".svg")) {
802-
return new FlatSVGIcon(owner.getClass().getResource(value));
803-
} else {
804-
throw new UnsupportedOperationException("Unsupported icon type.");
805-
}
806-
});
820+
return icons.computeIfAbsent(value, key -> new FlatSVGIcon(getURL(value)));
807821
}
808822

809823
private Image getImage(String value) {
810824
return images.computeIfAbsent(value, key -> {
811825
try {
812-
return ImageIO.read(owner.getClass().getResource(value));
826+
return ImageIO.read(getURL(value));
813827
} catch (IOException exception) {
814-
throw new UnsupportedOperationException(exception);
828+
throw new RuntimeException(exception);
815829
}
816830
});
817831
}
818832

833+
private URL getURL(String value) {
834+
if (owner != null) {
835+
return owner.getClass().getResource(value);
836+
} else {
837+
var uri = path.getParent().resolve(value).toUri();
838+
839+
try {
840+
return uri.toURL();
841+
} catch (MalformedURLException exception) {
842+
throw new RuntimeException(exception);
843+
}
844+
}
845+
}
846+
819847
private void processEndElement() {
820848
root = components.pop();
821849
}
@@ -861,6 +889,25 @@ public static JComponent load(Object owner, String name, ResourceBundle resource
861889
return uiLoader.load();
862890
}
863891

892+
/**
893+
* Deserializes a component hierarchy from a markup document.
894+
*
895+
* @param path
896+
* The document's path.
897+
*
898+
* @return
899+
* The deserialized component hierarchy.
900+
*/
901+
public static JComponent load(Path path) {
902+
if (path == null) {
903+
throw new IllegalArgumentException();
904+
}
905+
906+
var uiLoader = new UILoader(path);
907+
908+
return uiLoader.load();
909+
}
910+
864911
/**
865912
* Associates a markup tag with a component type.
866913
*

0 commit comments

Comments
 (0)