From e0186b3eb88ed991588c6765063429a1d2a271df Mon Sep 17 00:00:00 2001 From: OldTeaOwl Date: Tue, 12 Nov 2024 15:26:55 +0700 Subject: [PATCH] Storing sprites in Entity objects now, moderate ListGUI refactoring to simplify list icons creation. See more in the task description https://trello.com/c/tkAjRpcG --- src/gui/ListGUI.java | 25 +++++++++---------------- src/model/Entity.java | 16 ++++++++++++++++ src/repository/Project.java | 28 ++++++++++++++++++---------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/gui/ListGUI.java b/src/gui/ListGUI.java index c703bb5..22f324f 100644 --- a/src/gui/ListGUI.java +++ b/src/gui/ListGUI.java @@ -43,7 +43,6 @@ public class ListGUI extends JPanel { JButton addListElementEntity; JButton removeListElementEntity; JButton addPicEntity; - String pathImage; JList list; JScrollPane scroll; ActionListener removeEntity; @@ -91,7 +90,7 @@ public class ListGUI extends JPanel { return (String) list.getSelectedValue(); } - public void addListElement(String name,String solid) throws DuplicateEntryException { + public void addListElement(String name, String solid) throws DuplicateEntryException { // плейсхолдеры для новых хитбоксов и дроубоксов, иначе всё валится с NPE List hitboxPoints = new LinkedList(); List drawboxPoints = new LinkedList(); @@ -107,13 +106,15 @@ public class ListGUI extends JPanel { } public void updateList() { - String[] nameList = createNameList(); testModel.removeAllElements(); - for (String name : nameList) - testModel.addElement(name); + + for (Entity e: Project.getInstance()) { + testModel.addElement(e.getName()); - pathImage = Project.getInstance().getXMLPath(); - createImageMap(nameList); + // Create and store JList items icons in a map to prevent their unneccessary re-creation + iconMap.put(e.getName(), createListIconFromSprite( e.getImage() )); + } + list.updateUI(); } @@ -136,7 +137,7 @@ public class ListGUI extends JPanel { } private final float iconMaxWidth = 40, iconMaxHeight = 40; - public Icon imageScaling(BufferedImage image) { + private Icon createListIconFromSprite(BufferedImage image) { CustomIcon icon = null; try { int imageWidth = image.getWidth(), imageHeight = image.getHeight(); @@ -184,14 +185,6 @@ public class ListGUI extends JPanel { } } - private void createImageMap(String[] nameList) { - for (int i = 0; i < nameList.length; i++) { - String name = nameList[i]; - BufferedImage image = Project.getInstance().loadImageByName(name); - iconMap.put(name, imageScaling(image)); - } - } - private JButton createButton(int width,int height,ActionListener listener,String pathImage) { JButton button = new JButton(new ImageIcon(pathImage)); button.setSize(110, 46); diff --git a/src/model/Entity.java b/src/model/Entity.java index 82786ec..608cdef 100644 --- a/src/model/Entity.java +++ b/src/model/Entity.java @@ -1,10 +1,13 @@ package model; +import java.awt.image.BufferedImage; + public class Entity { private String thisName; private Drawbox thisDrawbox; private Hitbox thisHitbox; private String type; + private BufferedImage sprite; public Entity(String name,String drawbox,String hitbox) { thisName = new String(name); @@ -50,6 +53,19 @@ public class Entity { return thisHitbox; }; + public Drawbox getThisDrawbox() { + return thisDrawbox; + } + + /** @return BufferedImage object or null if an image is not set */ + public BufferedImage getImage() { + return sprite; + } + + public void setImage(BufferedImage sprite) { + this.sprite = sprite; + } + public void PrintEntity() { System.out.println("---------------------"); System.out.println("Name: "+thisName); diff --git a/src/repository/Project.java b/src/repository/Project.java index 3223def..11087e0 100644 --- a/src/repository/Project.java +++ b/src/repository/Project.java @@ -132,6 +132,7 @@ public class Project implements Iterable, EntityDrawboxChangedListener { factory = DocumentBuilderFactory.newInstance(); builder = factory.newDocumentBuilder(); document = builder.parse(new File(path+fileName)); + // TODO: remove this from Project, it should not know SHIT about MainGUI if(Launcher.getMainGUI() != null) // at the first program launch, main gui creates list gui before static link to main gui is set Launcher.getMainGUI().setTitle("Hitbox/Drawbox Editor: " + path + fileName); // Получение списка всех элементов objecttype внутри корневого элемента (getDocumentElement возвращает ROOT элемент XML файла). @@ -144,14 +145,18 @@ public class Project implements Iterable, EntityDrawboxChangedListener { } } - // эта колбаса парсит сущности из XML в программные объекты внутри модели, является частью внутренней кухни так что обычно её не нужно трогать - private void parsingElementXMLtoElementList(String entityName,Node objecttype) { + private void parsingElementXMLtoElementList(String entityName, Node objecttype) { String newDrawbox = null; String newHitbox = null; - String type = null; + String type = null; + BufferedImage sprite = null; Element element = (Element)objecttype; NodeList propertyElements = element.getElementsByTagName("property"); - if(propertyElements!=null) { + if(propertyElements != null) { + + // do not lazy load images here - Hitbox parser needs real image sizes + sprite = loadImageByName(entityName); + for(int i = 0; i < propertyElements.getLength(); i++) { Element property = (Element)propertyElements.item(i); String propertyName = property.getAttribute("name"); @@ -168,8 +173,10 @@ public class Project implements Iterable, EntityDrawboxChangedListener { break; } } - Entity e = new Entity(entityName,newDrawbox,newHitbox); + + Entity e = new Entity(entityName, newDrawbox, newHitbox); e.setType(type); + e.setImage(sprite); listEntity.add(e); } } @@ -179,9 +186,6 @@ public class Project implements Iterable, EntityDrawboxChangedListener { * XML-файл. Возвращает null если изображение не найдено. * */ public BufferedImage loadImageByName(String name) { - //TODO: сделать кеширование - не дело подгружать одну и ту же картинку по десять раз! - - String path = Project.getInstance().getXMLPath(); String extension = "png"; // TODO: изображения следует подгружать в отдельном потоке! @@ -209,6 +213,9 @@ public class Project implements Iterable, EntityDrawboxChangedListener { if(getEntityByName(e.getName()) != null) throw new DuplicateEntryException("The entity with the name '" + e.getName() + "' already exists!"); + //TODO: move image loading to AddListElementEntityListener and make it lazy + e.setImage(loadImageByName(e.getName())); + listEntity.add(e); Element objecttypeElement = document.createElement("objecttype"); @@ -365,8 +372,9 @@ public class Project implements Iterable, EntityDrawboxChangedListener { return null; } - //https://stackoverflow.com/a/64659614/6929164 - public static void stripEmptyElements(Node node) + // https://stackoverflow.com/a/64659614/6929164 + // new empty lines will appear on every XML save without this function + private static void stripEmptyElements(Node node) { NodeList children = node.getChildNodes(); for(int i = 0; i < children.getLength(); ++i) {