commit d4afde065d53bae70fafbf0154410e164a4671ea Author: Denis Date: Sun Jul 21 20:41:51 2024 +0700 legacy project initial commit diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..722043f --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..9c62da1 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + HitboxDrawboxEditor + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..223b166 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,14 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=15 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=15 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=15 diff --git a/bin/gui/CustomIcon.class b/bin/gui/CustomIcon.class new file mode 100644 index 0000000..acb0a5d Binary files /dev/null and b/bin/gui/CustomIcon.class differ diff --git a/bin/gui/DrawboxEditor.class b/bin/gui/DrawboxEditor.class new file mode 100644 index 0000000..633801c Binary files /dev/null and b/bin/gui/DrawboxEditor.class differ diff --git a/bin/gui/Editable.class b/bin/gui/Editable.class new file mode 100644 index 0000000..8a062bf Binary files /dev/null and b/bin/gui/Editable.class differ diff --git a/bin/gui/HitboxCircleEditor.class b/bin/gui/HitboxCircleEditor.class new file mode 100644 index 0000000..ea0cbeb Binary files /dev/null and b/bin/gui/HitboxCircleEditor.class differ diff --git a/bin/gui/HitboxPoligonEditor.class b/bin/gui/HitboxPoligonEditor.class new file mode 100644 index 0000000..4596ec9 Binary files /dev/null and b/bin/gui/HitboxPoligonEditor.class differ diff --git a/bin/gui/HitboxRectangleEditor.class b/bin/gui/HitboxRectangleEditor.class new file mode 100644 index 0000000..0d36f0a Binary files /dev/null and b/bin/gui/HitboxRectangleEditor.class differ diff --git a/bin/gui/ListGUI$ListEntityRenderer.class b/bin/gui/ListGUI$ListEntityRenderer.class new file mode 100644 index 0000000..668643a Binary files /dev/null and b/bin/gui/ListGUI$ListEntityRenderer.class differ diff --git a/bin/gui/ListGUI.class b/bin/gui/ListGUI.class new file mode 100644 index 0000000..9cf779a Binary files /dev/null and b/bin/gui/ListGUI.class differ diff --git a/bin/gui/MainGUI.class b/bin/gui/MainGUI.class new file mode 100644 index 0000000..2f3596c Binary files /dev/null and b/bin/gui/MainGUI.class differ diff --git a/bin/gui/PropertyFrameAddElement.class b/bin/gui/PropertyFrameAddElement.class new file mode 100644 index 0000000..b690d0d Binary files /dev/null and b/bin/gui/PropertyFrameAddElement.class differ diff --git a/bin/launch/Launcher.class b/bin/launch/Launcher.class new file mode 100644 index 0000000..212fc9c Binary files /dev/null and b/bin/launch/Launcher.class differ diff --git a/bin/listeners/AddListElementEntityListener.class b/bin/listeners/AddListElementEntityListener.class new file mode 100644 index 0000000..244ea73 Binary files /dev/null and b/bin/listeners/AddListElementEntityListener.class differ diff --git a/bin/listeners/CopyImageToFile.class b/bin/listeners/CopyImageToFile.class new file mode 100644 index 0000000..c81e148 Binary files /dev/null and b/bin/listeners/CopyImageToFile.class differ diff --git a/bin/listeners/CreateFrameAddElementListener.class b/bin/listeners/CreateFrameAddElementListener.class new file mode 100644 index 0000000..c79016e Binary files /dev/null and b/bin/listeners/CreateFrameAddElementListener.class differ diff --git a/bin/listeners/OpenXMLFileButtonListener.class b/bin/listeners/OpenXMLFileButtonListener.class new file mode 100644 index 0000000..6dacc1a Binary files /dev/null and b/bin/listeners/OpenXMLFileButtonListener.class differ diff --git a/bin/listeners/RemoveListElementEntityListener.class b/bin/listeners/RemoveListElementEntityListener.class new file mode 100644 index 0000000..93b2bcf Binary files /dev/null and b/bin/listeners/RemoveListElementEntityListener.class differ diff --git a/bin/model/Drawbox.class b/bin/model/Drawbox.class new file mode 100644 index 0000000..cae7a81 Binary files /dev/null and b/bin/model/Drawbox.class differ diff --git a/bin/model/Entity.class b/bin/model/Entity.class new file mode 100644 index 0000000..c4a0f23 Binary files /dev/null and b/bin/model/Entity.class differ diff --git a/bin/model/Formatter.class b/bin/model/Formatter.class new file mode 100644 index 0000000..f5b57d8 Binary files /dev/null and b/bin/model/Formatter.class differ diff --git a/bin/model/FormatterCircle.class b/bin/model/FormatterCircle.class new file mode 100644 index 0000000..fc01d5e Binary files /dev/null and b/bin/model/FormatterCircle.class differ diff --git a/bin/model/FormatterRectangle.class b/bin/model/FormatterRectangle.class new file mode 100644 index 0000000..fe598b0 Binary files /dev/null and b/bin/model/FormatterRectangle.class differ diff --git a/bin/model/Hitbox.class b/bin/model/Hitbox.class new file mode 100644 index 0000000..ed8283f Binary files /dev/null and b/bin/model/Hitbox.class differ diff --git a/bin/model/Point.class b/bin/model/Point.class new file mode 100644 index 0000000..6df5717 Binary files /dev/null and b/bin/model/Point.class differ diff --git a/bin/repository/Project.class b/bin/repository/Project.class new file mode 100644 index 0000000..2109a97 Binary files /dev/null and b/bin/repository/Project.class differ diff --git a/res/TopHome.png b/res/TopHome.png new file mode 100644 index 0000000..3894c81 Binary files /dev/null and b/res/TopHome.png differ diff --git a/res/add.png b/res/add.png new file mode 100644 index 0000000..cd2fee1 Binary files /dev/null and b/res/add.png differ diff --git a/res/addbutton.png b/res/addbutton.png new file mode 100644 index 0000000..a55a090 Binary files /dev/null and b/res/addbutton.png differ diff --git a/res/circle.png b/res/circle.png new file mode 100644 index 0000000..a95bb3c Binary files /dev/null and b/res/circle.png differ diff --git a/res/deletebutton.png b/res/deletebutton.png new file mode 100644 index 0000000..bbb410e Binary files /dev/null and b/res/deletebutton.png differ diff --git a/res/destroy.png b/res/destroy.png new file mode 100644 index 0000000..547ac60 Binary files /dev/null and b/res/destroy.png differ diff --git a/res/download.png b/res/download.png new file mode 100644 index 0000000..58773e0 Binary files /dev/null and b/res/download.png differ diff --git a/res/formless.png b/res/formless.png new file mode 100644 index 0000000..fb98373 Binary files /dev/null and b/res/formless.png differ diff --git a/res/image/256х1431 lantern.png b/res/image/256х1431 lantern.png new file mode 100644 index 0000000..7ea8700 Binary files /dev/null and b/res/image/256х1431 lantern.png differ diff --git a/res/image/256х148 fountain.png b/res/image/256х148 fountain.png new file mode 100644 index 0000000..6ea898e Binary files /dev/null and b/res/image/256х148 fountain.png differ diff --git a/res/image/256х168 merchant3.png b/res/image/256х168 merchant3.png new file mode 100644 index 0000000..e919850 Binary files /dev/null and b/res/image/256х168 merchant3.png differ diff --git a/res/image/256х178 merchant1.png b/res/image/256х178 merchant1.png new file mode 100644 index 0000000..bde1eb9 Binary files /dev/null and b/res/image/256х178 merchant1.png differ diff --git a/res/image/256х184 seat.png b/res/image/256х184 seat.png new file mode 100644 index 0000000..c18167f Binary files /dev/null and b/res/image/256х184 seat.png differ diff --git a/res/image/256х204 merchant2.png b/res/image/256х204 merchant2.png new file mode 100644 index 0000000..7157b3d Binary files /dev/null and b/res/image/256х204 merchant2.png differ diff --git a/res/image/256х209 box.png b/res/image/256х209 box.png new file mode 100644 index 0000000..54a909a Binary files /dev/null and b/res/image/256х209 box.png differ diff --git a/res/image/256х232 hay.png b/res/image/256х232 hay.png new file mode 100644 index 0000000..4714882 Binary files /dev/null and b/res/image/256х232 hay.png differ diff --git a/res/image/256х238 tent2.png b/res/image/256х238 tent2.png new file mode 100644 index 0000000..6ab2f60 Binary files /dev/null and b/res/image/256х238 tent2.png differ diff --git a/res/image/256х281 barrel.png b/res/image/256х281 barrel.png new file mode 100644 index 0000000..683f129 Binary files /dev/null and b/res/image/256х281 barrel.png differ diff --git a/res/image/256х362 tree.png b/res/image/256х362 tree.png new file mode 100644 index 0000000..90d0036 Binary files /dev/null and b/res/image/256х362 tree.png differ diff --git a/res/image/256х512 label.png b/res/image/256х512 label.png new file mode 100644 index 0000000..01f8fc0 Binary files /dev/null and b/res/image/256х512 label.png differ diff --git a/res/image/256х530 well2.png b/res/image/256х530 well2.png new file mode 100644 index 0000000..903ebd8 Binary files /dev/null and b/res/image/256х530 well2.png differ diff --git a/res/image/256х582 fider.png b/res/image/256х582 fider.png new file mode 100644 index 0000000..a5a49dc Binary files /dev/null and b/res/image/256х582 fider.png differ diff --git a/res/image/256х616 flag.png b/res/image/256х616 flag.png new file mode 100644 index 0000000..166430b Binary files /dev/null and b/res/image/256х616 flag.png differ diff --git a/res/image/256х675 tent1.png b/res/image/256х675 tent1.png new file mode 100644 index 0000000..5037e30 Binary files /dev/null and b/res/image/256х675 tent1.png differ diff --git a/res/image/256х675 tent3.png b/res/image/256х675 tent3.png new file mode 100644 index 0000000..7233b1a Binary files /dev/null and b/res/image/256х675 tent3.png differ diff --git a/res/image/256х679 well.png b/res/image/256х679 well.png new file mode 100644 index 0000000..47671bd Binary files /dev/null and b/res/image/256х679 well.png differ diff --git a/res/image/256х830 label2.png b/res/image/256х830 label2.png new file mode 100644 index 0000000..a5de310 Binary files /dev/null and b/res/image/256х830 label2.png differ diff --git a/res/image/CoffeeToffee.png b/res/image/CoffeeToffee.png new file mode 100644 index 0000000..0bbba90 Binary files /dev/null and b/res/image/CoffeeToffee.png differ diff --git a/res/image/Stone.png b/res/image/Stone.png new file mode 100644 index 0000000..aa1c853 Binary files /dev/null and b/res/image/Stone.png differ diff --git a/res/image/TopHome.png b/res/image/TopHome.png new file mode 100644 index 0000000..3894c81 Binary files /dev/null and b/res/image/TopHome.png differ diff --git a/res/image/ada/ada pony line without whitesapce.png b/res/image/ada/ada pony line without whitesapce.png new file mode 100644 index 0000000..4a143b8 Binary files /dev/null and b/res/image/ada/ada pony line without whitesapce.png differ diff --git a/res/image/ada/ada pony line without whitesapce3.png b/res/image/ada/ada pony line without whitesapce3.png new file mode 100644 index 0000000..5168ee3 Binary files /dev/null and b/res/image/ada/ada pony line without whitesapce3.png differ diff --git a/res/image/bagApples.png b/res/image/bagApples.png new file mode 100644 index 0000000..dd5a94c Binary files /dev/null and b/res/image/bagApples.png differ diff --git a/res/image/bulletinBoard.png b/res/image/bulletinBoard.png new file mode 100644 index 0000000..f80c078 Binary files /dev/null and b/res/image/bulletinBoard.png differ diff --git a/res/image/chair.png b/res/image/chair.png new file mode 100644 index 0000000..e03390c Binary files /dev/null and b/res/image/chair.png differ diff --git a/res/image/coffee toffee.png b/res/image/coffee toffee.png new file mode 100644 index 0000000..3aeabe3 Binary files /dev/null and b/res/image/coffee toffee.png differ diff --git a/res/image/coffee toffee2.png b/res/image/coffee toffee2.png new file mode 100644 index 0000000..a7bbe6b Binary files /dev/null and b/res/image/coffee toffee2.png differ diff --git a/res/image/decoration collection 2.png b/res/image/decoration collection 2.png new file mode 100644 index 0000000..5718c3d Binary files /dev/null and b/res/image/decoration collection 2.png differ diff --git a/res/image/decoration collection.png b/res/image/decoration collection.png new file mode 100644 index 0000000..25cfe24 Binary files /dev/null and b/res/image/decoration collection.png differ diff --git a/res/image/merchant4.png b/res/image/merchant4.png new file mode 100644 index 0000000..1e546fb Binary files /dev/null and b/res/image/merchant4.png differ diff --git a/res/image/merchants collection.png b/res/image/merchants collection.png new file mode 100644 index 0000000..8b775ee Binary files /dev/null and b/res/image/merchants collection.png differ diff --git a/res/image/misato.png b/res/image/misato.png new file mode 100644 index 0000000..ef5278a Binary files /dev/null and b/res/image/misato.png differ diff --git a/res/image/spell2.png b/res/image/spell2.png new file mode 100644 index 0000000..2e0aa8b Binary files /dev/null and b/res/image/spell2.png differ diff --git a/res/image/spell3.png b/res/image/spell3.png new file mode 100644 index 0000000..8f0e904 Binary files /dev/null and b/res/image/spell3.png differ diff --git a/res/image/starlight.png b/res/image/starlight.png new file mode 100644 index 0000000..3a369be Binary files /dev/null and b/res/image/starlight.png differ diff --git a/res/image/tavern.png b/res/image/tavern.png new file mode 100644 index 0000000..c201ee7 Binary files /dev/null and b/res/image/tavern.png differ diff --git a/res/image/tents collection.png b/res/image/tents collection.png new file mode 100644 index 0000000..4ad2656 Binary files /dev/null and b/res/image/tents collection.png differ diff --git a/res/image/wells collection.png b/res/image/wells collection.png new file mode 100644 index 0000000..50fe029 Binary files /dev/null and b/res/image/wells collection.png differ diff --git a/res/image/wood.png b/res/image/wood.png new file mode 100644 index 0000000..f80832f Binary files /dev/null and b/res/image/wood.png differ diff --git a/res/misato.png b/res/misato.png new file mode 100644 index 0000000..ef5278a Binary files /dev/null and b/res/misato.png differ diff --git a/res/naga.png b/res/naga.png new file mode 100644 index 0000000..d3f890c Binary files /dev/null and b/res/naga.png differ diff --git a/res/objecttypes.xml b/res/objecttypes.xml new file mode 100644 index 0000000..93b9ada --- /dev/null +++ b/res/objecttypes.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/square.png b/res/square.png new file mode 100644 index 0000000..5ef41e8 Binary files /dev/null and b/res/square.png differ diff --git a/res/starlight.png b/res/starlight.png new file mode 100644 index 0000000..3a369be Binary files /dev/null and b/res/starlight.png differ diff --git a/res/tavern.png b/res/tavern.png new file mode 100644 index 0000000..c201ee7 Binary files /dev/null and b/res/tavern.png differ diff --git a/res/test.png b/res/test.png new file mode 100644 index 0000000..41bd60f Binary files /dev/null and b/res/test.png differ diff --git a/res/xml.png b/res/xml.png new file mode 100644 index 0000000..10d8668 Binary files /dev/null and b/res/xml.png differ diff --git a/src/gui/CustomIcon.java b/src/gui/CustomIcon.java new file mode 100644 index 0000000..284f930 --- /dev/null +++ b/src/gui/CustomIcon.java @@ -0,0 +1,65 @@ +package gui; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; + +import javax.swing.Icon; + +public class CustomIcon implements Icon { + private BufferedImage image; + private int width, heigth; + + public CustomIcon(Image image, int width, int height) { + this.image = toBufferedImage(image); + this.width = width; + this.heigth = height; + } + + private final Color color = new Color(1f, 0.82f, 0.45f, 0.4f); + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2d = (Graphics2D) g.create(); + int imageWidth = image.getWidth(), + imageHeigth = image.getHeight(); + // setting image position to center + int resultX = x + (width-imageWidth)/2, + resultY = y + (heigth-imageHeigth)/2; + //g2d.drawRect(x, y, width, heigth); + g2d.setColor(color); + g2d.fillOval(x, y, width, heigth); + g2d.drawImage(image, resultX, resultY, null); + } + + private BufferedImage toBufferedImage(Image img) + { + if (img instanceof BufferedImage) + { + return (BufferedImage) img; + } + + // Create a buffered image with transparency + BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); + + // Draw the image on to the buffered image + Graphics2D bGr = bimage.createGraphics(); + bGr.drawImage(img, 0, 0, null); + bGr.dispose(); + + return bimage; + } + + @Override + public int getIconWidth() { + return width; + } + + @Override + public int getIconHeight() { + return heigth; + } + +} diff --git a/src/gui/DrawboxEditor.java b/src/gui/DrawboxEditor.java new file mode 100644 index 0000000..b4b589c --- /dev/null +++ b/src/gui/DrawboxEditor.java @@ -0,0 +1,118 @@ +package gui; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.JTabbedPane; + +import model.Drawbox; +import model.Point; + +public class DrawboxEditor extends Editable { + + private List drawboxPoints; + private List basePoints; + Logger logger = Logger.getLogger("gui.DrawboxRectangleEditor"); + + Point currentPoint = new Point(0, 0); + + DrawboxEditor(ListGUI listGUI) { + super(listGUI); + + logger.setLevel(Level.CONFIG); + } + + + + @Override + public void drawing(Graphics2D g) { + Drawbox drawbox = entity.getDrawbox(); + drawboxPoints = drawbox.getDrawboxlistPoints(); + basePoints = drawbox.getbaseListPoints(); + logger.finest("drawbox point size: "+ drawboxPoints.size()); + for(Point p: drawboxPoints) + logger.finest("DrawBoxPoint: ["+ p.x + ":"+p.y+"]"); + for(Point p: basePoints) + logger.finest("BasePoint: ["+ p.x + ":"+p.y+"]"); + + if(drawboxPoints.size() >= 1 && drawboxPoints.size() < 4) { + Point lastPoint = drawboxPoints.get(drawboxPoints.size()-1); + g.drawLine((int)lastPoint.x, (int)lastPoint.y, (int)currentPoint.x, (int)currentPoint.y); + for(int i = 0; i < drawboxPoints.size()-1;i++) { + int x1 = (int)drawboxPoints.get(i).x; + int y1 = (int)drawboxPoints.get(i).y; + int x2 = (int)drawboxPoints.get(i+1).x; + int y2 = (int)drawboxPoints.get(i+1).y; + g.drawLine(x1, y1, x2, y2); + } + } else { + for(int i = 0; i < drawboxPoints.size();i++) { + int x1 = (int)drawboxPoints.get(i % drawboxPoints.size()).x; + int y1 = (int)drawboxPoints.get(i % drawboxPoints.size()).y; + int x2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).x; + int y2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).y; + g.drawLine(x1, y1, x2, y2); + } +// ОТРИСОВКА ОСНОВАНИЯ + g.setColor(Color.BLUE); + for(int i = 0; i < basePoints.size()-1;i++) { + int x1 = (int)basePoints.get(i).x; + int y1 = (int)basePoints.get(i).y; + int x2 = (int)basePoints.get(i+1).x; + int y2 = (int)basePoints.get(i+1).y; + g.drawLine(x1, y1+3, x2, y2+3); + } + } + } + + @Override + public void saveDataInEntity() { } + + + @Override + public void mousePressed(MouseEvent e) { + if(drawboxPoints.size() < 4) { + Point p = new Point(e.getX(), e.getY()); + drawboxPoints.add(p); + if(drawboxPoints.size() == 4) { + Point baseStart = drawboxPoints.get(0), + baseEnd = drawboxPoints.get(1); + for(Point pseudo: drawboxPoints) { // если не будет цикла в цикле - не выйдет сравнить всех со всеми + for(Point vertex: drawboxPoints) { // что приведёт к артефактам построения основания + if(vertex != baseStart && vertex != baseEnd) { + if(vertex.y >= baseStart.y) baseStart = vertex; + else if(vertex.y >= baseEnd.y) baseEnd = vertex; + } + } + } + basePoints.add(baseStart); + basePoints.add(baseEnd); + } + } + } + + @Override + public void mouseMoved(MouseEvent e) { + currentPoint.x = e.getX(); + currentPoint.y = e.getY(); + repaint(); + } + + @Override + public void actionPerformed(ActionEvent e) { + JTabbedPane parent = (JTabbedPane) getParent(); + if(parent.getSelectedComponent() == this){ + if(entity != null) { + entity.getDrawbox().getDrawboxlistPoints().clear(); + entity.getDrawbox().getbaseListPoints().clear(); + repaint(); + } + } + } + +} diff --git a/src/gui/Editable.java b/src/gui/Editable.java new file mode 100644 index 0000000..ef9f6f2 --- /dev/null +++ b/src/gui/Editable.java @@ -0,0 +1,111 @@ +package gui; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import model.Entity; +import repository.Project; + +public abstract class Editable extends JPanel implements MouseListener, MouseMotionListener, ListSelectionListener, ActionListener { + + protected ListGUI listGUI; + protected Entity entity; + protected String name; + protected BufferedImage image; + JPanel drawPanel; + + private static Logger logger = Logger.getLogger("gui.Editable"); + + + Editable(ListGUI listGUI){ + this.listGUI = listGUI; + + addMouseListener(this); + addMouseMotionListener(this); + + // РАСКОММЕНТИТЬ ЕСЛИ НУЖНО ВЫВОДИТЬ ПОДРОБНЫЕ ЛОГИ + logger.setLevel(Level.ALL); + } + + + //Абстрактные методы + + public abstract void drawing(Graphics2D g); + public abstract void saveDataInEntity(); + + + + //методы родительского класса Editable + + //get,set для name + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + //заполнить текущую сущность по имени. + public void setEntityByName(String name) throws Exception { + entity = Project.getInstance().getEntityByName(name); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.drawImage(image, 0, 0, this); + if(entity != null) { + drawing((Graphics2D)g); + } + } + + // из mouse motion listener'a + @Override + public void mouseDragged(MouseEvent e) {} + + // этих ребят нас обязывает создать MouseListener, так что они здесь + @Override + public void mouseClicked(MouseEvent e) {} + @Override + public void mousePressed(MouseEvent e) {} + @Override + public void mouseEntered(MouseEvent e) {} + @Override + public void mouseExited(MouseEvent e) {} + @Override + public void mouseReleased(MouseEvent e) {} + + @Override + public void valueChanged(ListSelectionEvent e) { + logger.log(Level.FINEST, "entering method {0} of class {1}", new Object[]{"MouseClicked()" , this.getClass().getName()}); + //logger.entering(this.getClass().getName(), "MouseClicked()"); + if(e.getSource() instanceof JList) { + //TODO: надо бы элегантнее пробросить сюда ListGUI - просто передача его в аргументах немножко громоздкая + // как-то обыграть это через события? + // ps. попытки обратиться к eventSource проваливаются - ListGUI это панель, уже внутри которой лежит JList + name = listGUI.getSelectedName(); + try { + entity = Project.getInstance().getEntityByName(name); + } catch (Exception e1) { + logger.severe("Entity with name '"+name+"' was not found! Cannot display it on panel!"); + } + image = Project.getInstance().loadImageByName(name); + //TODO: if(image == null) вызов FileChooser'a и выбор изображения + + this.repaint(); + } + } +} diff --git a/src/gui/HitboxCircleEditor.java b/src/gui/HitboxCircleEditor.java new file mode 100644 index 0000000..eab02c5 --- /dev/null +++ b/src/gui/HitboxCircleEditor.java @@ -0,0 +1,47 @@ +package gui; + +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; + +import javax.swing.JPanel; + +public class HitboxCircleEditor extends Editable { + + HitboxCircleEditor(ListGUI listGUI) { + super(listGUI); + // TODO Auto-generated constructor stub + } + + + @Override + public void drawing(Graphics2D g) { + // TODO Auto-generated method stub + + } + + @Override + public void saveDataInEntity() { + // TODO Auto-generated method stub + + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseMoved(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/gui/HitboxPoligonEditor.java b/src/gui/HitboxPoligonEditor.java new file mode 100644 index 0000000..cf22388 --- /dev/null +++ b/src/gui/HitboxPoligonEditor.java @@ -0,0 +1,48 @@ +package gui; + +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; + +import javax.swing.JPanel; + +public class HitboxPoligonEditor extends Editable { + + HitboxPoligonEditor(ListGUI listGUI) { + super(listGUI); + // TODO Auto-generated constructor stub + } + + + + @Override + public void drawing(Graphics2D g) { + // TODO Auto-generated method stub + + } + + @Override + public void saveDataInEntity() { + // TODO Auto-generated method stub + + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseMoved(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/gui/HitboxRectangleEditor.java b/src/gui/HitboxRectangleEditor.java new file mode 100644 index 0000000..2d6f5f7 --- /dev/null +++ b/src/gui/HitboxRectangleEditor.java @@ -0,0 +1,53 @@ +package gui; + +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; + +public class HitboxRectangleEditor extends Editable { + + HitboxRectangleEditor(ListGUI listGUI) { + super(listGUI); + // TODO Auto-generated constructor stub + } + + @Override + public void drawing(Graphics2D g) { + // TODO Auto-generated method stub + + } + + @Override + public void saveDataInEntity() { + // TODO Auto-generated method stub + + } + + @Override + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseMoved(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + + } + + +} diff --git a/src/gui/ListGUI.java b/src/gui/ListGUI.java new file mode 100644 index 0000000..0ae529c --- /dev/null +++ b/src/gui/ListGUI.java @@ -0,0 +1,219 @@ +package gui; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Image; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionListener; +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.SAXException; + +import listeners.CreateFrameAddElementListener; +import listeners.RemoveListElementEntityListener; +import model.Drawbox; +import model.Entity; +import model.Hitbox; +import model.Point; +import repository.Project; + +public class ListGUI extends JPanel { + private Map iconMap = new HashMap<>(); + JButton addListElementEntity; + JButton removeListElementEntity; + JButton addPicEntity; + String pathImage; + JList list; + JScrollPane scroll; + ActionListener removeEntity; + ActionListener addEntity; + DefaultListModel testModel; + + private static Logger logger = Logger.getLogger("gui.ListGUI"); + + public ListGUI() { + try { + Project.getInstance().load(); + } catch (SAXException | IOException | ParserConfigurationException e) { + // TODO: сделать нормальную обработку исключений - ситуации когда файл не существует, случилась ошибка парсинга и тд должны обрабатываться отдельно + // в идеале должны появляться разные окошки, которые обрисуют в чём проблема и предложения что делать + JOptionPane.showMessageDialog(this, "Parser exception, cause: "+e); + } + String[] nameList = createNameList(); + + testModel = new DefaultListModel<>(); + + list = new JList(testModel); + list.setCellRenderer(new ListEntityRenderer()); + + addEntity = new CreateFrameAddElementListener(this); + removeEntity = new RemoveListElementEntityListener(this); + + scroll = new JScrollPane(list); + scroll.setSize(new Dimension(223, 638)); + scroll.setLocation(5, 5); + this.add(scroll); + + list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + addListElementEntity = createButton(5,645, addEntity,"res/addbutton.png"); + removeListElementEntity = createButton(117,645,removeEntity,"res/deletebutton.png"); + + + /// ЧТОБЫ ОТКЛЮЧИТЬ ИЗБЫТОЧНЫЙ ВЫВОД В КОНСОЛЬ - НУЖНО СМЕНИТЬ УРОВЕНЬ ЛОГГИРОВАНИЯ В СТРОКЕ НИЖЕ + logger.setLevel(Level.FINEST); + // в идеале достаточно уровня WARNING, но если нужна более точна информация о модуле - можно снизить уровень + + updateList(); + } + + public String getSelectedName() { + return (String) list.getSelectedValue(); + } + + public void addListElement(String name,String solid) { + // плейсхолдеры для новых хитбоксов и дроубоксов, иначе всё валится с NPE + List hitboxPoints = new LinkedList(); + List drawboxPoints = new LinkedList(); + Hitbox hitbox = new Hitbox("Rectangle", hitboxPoints); + Drawbox drawbox = new Drawbox(drawboxPoints); + + // а тут уже создание новой сущности + Entity e = new Entity(name, hitbox, drawbox); + e.setType(solid); + logger.finer("Entity \""+name+"\" was created."); + Project.getInstance().addEntity(e); + updateList(); + } + + public void updateList() { + String[] nameList = createNameList(); + testModel.removeAllElements(); + for (String name : nameList) + testModel.addElement(name); + + pathImage = Project.getInstance().getXMLPath(); + createImageMap(nameList); + list.updateUI(); + } + + /** + * Функция, формирующая список имён сущностей для JList, чтобы сформировать его итемы + * */ + private String[] createNameList() { + //TODO: meh, хочется избавиться от использования списка - нехорошее это дело, лучше работать через интерфейс Project + int index = 0, + size = Project.getInstance().getListEntity().size(); + String[] names = new String[size]; + for(Entity e: Project.getInstance()) + names[index++] = e.getName(); + //TODO: не будет ли лучше хранить в JList не только имена, но и ссылки на сущности? + //было бы удобно по нажатию на итем JList'а сразу дёргать из него нужную сущность а + //из неё её хитбоксы и дроубоксы вместо вызовов по типу "Project.getInstance().getEntityByName(jListItem.getText())" + //НО! текущий вариант не требует написания кастомного JList, без которого в него целую сущность не запихать... + + return names; + } + private final float iconMaxWidth = 40, iconMaxHeight = 40; + + public Icon imageScaling(BufferedImage image) { + CustomIcon icon = null; + try { + int imageWidth = image.getWidth(), imageHeight = image.getHeight(); + float scaleFactorX = iconMaxWidth / imageWidth, scaleFactorY = iconMaxHeight / imageHeight, + scaleFactor = scaleFactorX < scaleFactorY ? scaleFactorX : scaleFactorY; + // debug print + // System.out.printf("ImageWidth: %d, ImageHeight: %d, scaleFactorX: %f, + // scaleFactorY: %f, scaleFactor: %f \n", imageWidth, imageHeight, scaleFactorX, + // scaleFactorY, scaleFactor); + Image scaledImage = image.getScaledInstance((int) (imageWidth * scaleFactor), + (int) (imageHeight * scaleFactor), Image.SCALE_SMOOTH); + icon = new CustomIcon(scaledImage, (int) iconMaxWidth, (int) iconMaxHeight); + } catch (NullPointerException npe) { + logger.log(Level.WARNING, "Cannot scale icon for list item - the reference is null"); + } + return icon; + } + + public class ListEntityRenderer extends DefaultListCellRenderer + { + Font font = new Font("helvitica", Font.BOLD, 14); + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) + { + int iconTextOffset = 10; + + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + Entity e = null; + try { + e = Project.getInstance().getEntityByName((String)value); + String text = label.getText(); + text = ""+text+"
"+""+e.getType()+""; + label.setText(text); + } catch (Exception e1) { + e1.printStackTrace(); + } + Icon icon = iconMap.get((String) value); + if(icon != null) { + label.setIcon(icon); + label.setIconTextGap((int)iconMaxWidth - icon.getIconWidth() + iconTextOffset); + } + label.setFont(font); + return label; + } + } + + 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); + button.setLocation(width, height); + button.addActionListener(listener); + button.setContentAreaFilled(false); + button.setFocusPainted(false); + this.add(button); + return button; + } + + /** + * Немного костыль, который позволяет зарегестрировать слушатель мыши на списке компонентов + * не создавая излишне тесных связей между компонентами + * */ + public void registerJListListener(ListSelectionListener ml) { + list.addListSelectionListener(ml); + } + + public void printNameList(String[] nameList) { + System.out.println("вызван принт лист: "+nameList.length); + for(int i = 0;i listEditorPanel = new ArrayList(); + DrawboxEditor drawBoxPanel; + HitboxCircleEditor hitboxCirclePanel; + HitboxRectangleEditor hitboxRectanglePanel; + HitboxPoligonEditor hitboxPoligonPanel; + + + + public MainGUI() { + + setTitle("Hitbox/Drawbox Editor"); + setLayout(null); + setSize(1200,780); + setLocationRelativeTo(null); + setResizable(false); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + + list = new ListGUI(); + this.add(list); + list.setLayout(null); + list.setSize(230, 691); + list.setLocation(0, 47); + list.setVisible(true); + + drawBoxPanel = new DrawboxEditor(list); + hitboxCirclePanel = new HitboxCircleEditor(list); + hitboxRectanglePanel = new HitboxRectangleEditor(list); + hitboxPoligonPanel = new HitboxPoligonEditor(list); + listEditorPanel.add(drawBoxPanel); + listEditorPanel.add(hitboxCirclePanel); + listEditorPanel.add(hitboxRectanglePanel); + listEditorPanel.add(hitboxPoligonPanel); + + list.registerJListListener(drawBoxPanel); + list.registerJListListener(hitboxCirclePanel); + list.registerJListListener(hitboxPoligonPanel); + list.registerJListListener(hitboxRectanglePanel); + + OpenXMLFileButtonListener = new OpenXMLFileButtonListener(list); + + openXMLJButton = createButton("XML",5,5, OpenXMLFileButtonListener,"res/xml.png"); + saveXMLJButton = createButton("Save",80,5,null,"res/download.png"); + clearLinesJButton = createButton("Clear lines",155,5,null,"res/destroy.png"); + + clearLinesJButton.addActionListener(drawBoxPanel); + clearLinesJButton.addActionListener(hitboxCirclePanel); + clearLinesJButton.addActionListener(hitboxPoligonPanel); + clearLinesJButton.addActionListener(hitboxRectanglePanel); + + repaint(); + + this.add(editorPane = createPane(editorPane, 230, 50)); + + editorPane.addTab("Hitbox", hitdrawPane = createPane(hitdrawPane,10, 10)); + editorPane.addTab("Drawbox", drawBoxPanel); + hitdrawPane.addTab(null, new ImageIcon("res/square.png"),hitboxRectanglePanel, null); + hitdrawPane.addTab(null, new ImageIcon("res/circle.png"),hitboxCirclePanel, null); + hitdrawPane.addTab(null, new ImageIcon("res/formless.png"),hitboxPoligonPanel, null); + hitdrawPane.setTabPlacement(JTabbedPane.LEFT); + + } + @Override + public void paint(Graphics g){ + super.paint(g); + g.drawLine(0, 72, 1200, 72); + } + + + public JTabbedPane createPane(JTabbedPane pane, int x, int y) { + pane = new JTabbedPane(); + pane.setSize(new Dimension(950, 688)); + pane.setLocation(new Point(x, y)); + pane.setVisible(true); + return pane; + } + + private JButton createButton(String text,int width,int height,ActionListener listener,String pathImage) { + JButton button = new JButton(new ImageIcon(pathImage)); + button.setSize(68, 34); + button.setLocation(width, height); + button.addActionListener(listener); + button.setContentAreaFilled(false); + button.setFocusPainted(false); + this.add(button); + return button; + } +} diff --git a/src/gui/PropertyFrameAddElement.java b/src/gui/PropertyFrameAddElement.java new file mode 100644 index 0000000..204599e --- /dev/null +++ b/src/gui/PropertyFrameAddElement.java @@ -0,0 +1,90 @@ +package gui; + +import java.awt.FlowLayout; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import listeners.AddListElementEntityListener; +import listeners.CopyImageToFile; + +public class PropertyFrameAddElement extends JFrame { + + JPanel contents; + JButton acceptSettingsJButton; + JButton addPuthImage; + JTextField nameTextField,typeTextField; + ActionListener acceptSettingListener; + ActionListener copyImageToFile; + JLabel nameLabel,typeLabel,imageLabel; + public PropertyFrameAddElement(ListGUI listGUI) { + + this.setTitle("Add Entity"); + this.setLayout(null); + this.setSize(400,250); + this.setLocationRelativeTo(null); + this.setResizable(false); + this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + + nameLabel = new JLabel("Введите имя сущности:"); + nameLabel.setSize(150,20); + nameLabel.setLocation(20, 20); + typeLabel = new JLabel("Введите тип сущности:"); + typeLabel.setSize(150,20); + typeLabel.setLocation(20, 50); + imageLabel = new JLabel("Для выбора нажмите:"); + imageLabel.setSize(150,20); + imageLabel.setLocation(20, 108); + + nameTextField = new JTextField(); + nameTextField.setSize(200,20); + nameTextField.setLocation(160, 20); + typeTextField = new JTextField(); + typeTextField.setSize(200,20); + typeTextField.setLocation(160, 50); + + + contents = new JPanel(new FlowLayout(FlowLayout.LEFT)); + contents.setLayout(null); + contents.setSize(600,400); + contents.add(nameLabel); + contents.add(typeLabel); + contents.add(imageLabel); + contents.add(nameTextField); + contents.add(typeTextField); + acceptSettingListener = new AddListElementEntityListener(listGUI,this); + copyImageToFile = new CopyImageToFile(this); + acceptSettingsJButton = createButton("Accept", 148, 170, acceptSettingListener, null); + addPuthImage = createButton("Добавить image", 160, 100, copyImageToFile, null); + addPuthImage.setSize(160, 40); + contents.add(acceptSettingsJButton); + contents.add(addPuthImage); + setContentPane(contents); + } + + + + private JButton createButton(String text,int width,int height,ActionListener listener,String pathImage) { + JButton button = new JButton(text); + button.setSize(90, 40); + button.setLocation(width, height); + button.addActionListener(listener); + button.setContentAreaFilled(false); + button.setFocusPainted(false); + this.add(button); + return button; + } + + public String getInputName() { + String name = nameTextField.getText(); + return name; + } + public String getInputType() { + String type = typeTextField.getText(); + return type; + } +} diff --git a/src/launch/Launcher.java b/src/launch/Launcher.java new file mode 100644 index 0000000..e0874af --- /dev/null +++ b/src/launch/Launcher.java @@ -0,0 +1,37 @@ +package launch; + +import java.io.IOException; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.SAXException; + +import gui.MainGUI; + +public class Launcher { + + public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException { + // Настройка системы логгирования + // Указываем, в каком формате выводится строка в консоль + System.setProperty("java.util.logging.SimpleFormatter.format", + "[%1$tF %1$tT] [%4$-7s] %5$s %n"); + + Logger rootLogger = LogManager.getLogManager().getLogger(""); + //указываем, какой уровень логгирования учитывается при выводе - всё что меньше заданного уровня откидывается + //p.s. уровень вывода и уровень регистрации (handler.level | logging.level) это не одно и то же + Handler[] handlers = rootLogger.getHandlers(); + Level lv = Level.FINE; + for(int i = 0; i < handlers.length; i++) { + handlers[i].setLevel(lv); + } + rootLogger.info("Root Handler Logging level is "+lv.getName()); + + MainGUI gui = new MainGUI(); + gui.setVisible(true); + } + +} diff --git a/src/listeners/AddListElementEntityListener.java b/src/listeners/AddListElementEntityListener.java new file mode 100644 index 0000000..a37ca4c --- /dev/null +++ b/src/listeners/AddListElementEntityListener.java @@ -0,0 +1,30 @@ +package listeners; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JTextField; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +import gui.ListGUI; +import gui.PropertyFrameAddElement; + +public class AddListElementEntityListener implements ActionListener +{ + ListGUI listGUI; + PropertyFrameAddElement propertyFrame; + public AddListElementEntityListener(ListGUI listGUI,PropertyFrameAddElement propetry) { + this.listGUI = listGUI; + propertyFrame = propetry; + } + + @Override + public void actionPerformed(ActionEvent e) { + listGUI.addListElement(propertyFrame.getInputName(),propertyFrame.getInputType()); + propertyFrame.dispose(); + } +} diff --git a/src/listeners/CopyImageToFile.java b/src/listeners/CopyImageToFile.java new file mode 100644 index 0000000..6d717f6 --- /dev/null +++ b/src/listeners/CopyImageToFile.java @@ -0,0 +1,59 @@ +package listeners; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileNameExtensionFilter; + +import gui.PropertyFrameAddElement; +import repository.Project; + +public class CopyImageToFile extends JFileChooser implements ActionListener { + File source; + File dest; + PropertyFrameAddElement propertyFrame; + public String directory = "res/"; + public String file = "objecttypes.xml"; + + public CopyImageToFile(PropertyFrameAddElement propFrame){ + propertyFrame = propFrame; + } + + @Override + public void actionPerformed(ActionEvent e) { + + dest = new File(Project.getInstance().getXMLPath()+propertyFrame.getInputName()+".png"); + this.setDialogTitle("Choose file"); + this.setFileSelectionMode(JFileChooser.FILES_ONLY); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Image PNG", "png"); + this.setFileFilter(filter); + int result = this.showOpenDialog(CopyImageToFile.this); + System.out.println("propertyFrame.getInputName() = "+propertyFrame.getInputName()); + if (result == JFileChooser.APPROVE_OPTION && propertyFrame.getInputName()!=null) + { + System.out.println("Выбрали!!!!!!!!!!!!"); + directory = this.getCurrentDirectory().toString()+'/'; + file = this.getName(getSelectedFile()).toString(); + source = new File(directory+file); + try { + copyFileUsingJava7Files(source,dest); + System.out.println("ФАЙЛ ВРОДЕ КАК ДОЛЖЕН БЫЛ СОЗДАТЬСЯ, ИДИ ПРОВЕРЬ"); + } catch (IOException e1) { + JOptionPane.showMessageDialog(null, "Выбранное изображение уже существует!"); + e1.printStackTrace(); + } + } + + } + + + // простой и удобный метод копирования файла в Java 7 + private static void copyFileUsingJava7Files(File source, File dest) throws IOException { + Files.copy(source.toPath(), dest.toPath()); + } +} diff --git a/src/listeners/CreateFrameAddElementListener.java b/src/listeners/CreateFrameAddElementListener.java new file mode 100644 index 0000000..7691375 --- /dev/null +++ b/src/listeners/CreateFrameAddElementListener.java @@ -0,0 +1,24 @@ +package listeners; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import gui.ListGUI; +import gui.PropertyFrameAddElement; + +public class CreateFrameAddElementListener implements ActionListener { + + PropertyFrameAddElement frameProperty; + ListGUI listGUI; + + public CreateFrameAddElementListener(ListGUI listGUI) { + this.listGUI = listGUI; + } + + @Override + public void actionPerformed(ActionEvent e) { + frameProperty = new PropertyFrameAddElement(listGUI); + frameProperty.setVisible(true); + } + +} diff --git a/src/listeners/OpenXMLFileButtonListener.java b/src/listeners/OpenXMLFileButtonListener.java new file mode 100644 index 0000000..2be82bc --- /dev/null +++ b/src/listeners/OpenXMLFileButtonListener.java @@ -0,0 +1,44 @@ +package listeners; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; + +import gui.ListGUI; +import repository.Project; + +public class OpenXMLFileButtonListener extends JFileChooser implements ActionListener +{ + //public String directory = "C:\\Users\\sivan\\Desktop\\Диплом\\GUI-Collision&Drawing-Metadata-Editor\\res\\"; + public String directory = "res/"; + public String file = "objecttypes.xml"; + + ListGUI listGUI; + + public OpenXMLFileButtonListener(ListGUI listGUI) { + this.listGUI = listGUI; + } + + @Override + public void actionPerformed(ActionEvent e) + { + this.setDialogTitle("Choose file"); + this.setFileSelectionMode(JFileChooser.FILES_ONLY); + FileNameExtensionFilter filter = new FileNameExtensionFilter("Xml File", "xml"); + this.setFileFilter(filter); + int result = this.showOpenDialog(OpenXMLFileButtonListener.this); + if (result == JFileChooser.APPROVE_OPTION ) + { + directory = this.getCurrentDirectory().toString()+'/'; + file = this.getName(getSelectedFile()).toString(); + Project.getInstance().load(directory, file); + listGUI.updateList(); + + //Debug + System.out.println(directory + file); + } + } + + +} diff --git a/src/listeners/RemoveListElementEntityListener.java b/src/listeners/RemoveListElementEntityListener.java new file mode 100644 index 0000000..3832118 --- /dev/null +++ b/src/listeners/RemoveListElementEntityListener.java @@ -0,0 +1,32 @@ +package listeners; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import gui.ListGUI; +import model.Entity; +import repository.Project; + +public class RemoveListElementEntityListener implements ActionListener{ + + ListGUI listGUI; + + public RemoveListElementEntityListener(ListGUI listGUI) { + this.listGUI = listGUI; + } + + @Override + public void actionPerformed(ActionEvent event) { + String name = listGUI.getSelectedName(); + if(name == null) return; +// System.out.println(name); + try { + Entity e = Project.getInstance().getEntityByName(name); + Project.getInstance().removeEntity(e); + listGUI.updateList(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + +} diff --git a/src/model/Drawbox.java b/src/model/Drawbox.java new file mode 100644 index 0000000..f7a699c --- /dev/null +++ b/src/model/Drawbox.java @@ -0,0 +1,71 @@ +package model; + +import java.util.ArrayList; +import java.util.List; + +public class Drawbox { + private List drawboxlistPoints ;//для прямоугольника дравбокса. + private List baseListPoints ;//2 точки для линии основания + + public Drawbox(List drawboxlistPoints){ + this.drawboxlistPoints = new ArrayList(drawboxlistPoints) ; + createBasePoint(); + } + + public Drawbox(String informationDrawbox){ + + if(informationDrawbox!= null) { + drawboxlistPoints = new ArrayList(); + baseListPoints = new ArrayList(); + String[] informations = informationDrawbox.split(" "); + parseStringToDrawbox(informations); + createBasePoint(); + } + } + + private void parseStringToDrawbox(String[] informations) { + //составляем точки по которым строится прямоугольник, и запихиваем их в лист с точками + for(int i = 0;i(); + if(drawboxlistPoints.size()>2) { + for(int i = 0;i<2;i++) { + float x = drawboxlistPoints.get(drawboxlistPoints.size()-i-1).x; + float y = drawboxlistPoints.get(drawboxlistPoints.size()-i-1).y+3; + Point point = new Point(x, y); + baseListPoints.add(point); + } + } + } + + public List getDrawboxlistPoints() { + return drawboxlistPoints; + } + + public List getbaseListPoints() { + return baseListPoints; + } + public void Print() { + System.out.println("|||Drawbox:"); + if(baseListPoints!=null&&drawboxlistPoints!=null) { + System.out.println("drawboxlistPoints:"); + for(Point point: drawboxlistPoints) { + System.out.print("("+point.x+";"+point.y+") "); + } + System.out.println(); + System.out.println("baseListPoints:"); + for(Point point: baseListPoints) { + System.out.print("("+point.x+";"+point.y+") "); + } + }else { + System.out.println("null"); + } + } +} diff --git a/src/model/Entity.java b/src/model/Entity.java new file mode 100644 index 0000000..192b88d --- /dev/null +++ b/src/model/Entity.java @@ -0,0 +1,77 @@ +package model; + +public class Entity { + private String thisName; + private Drawbox thisDrawbox; + private Hitbox thisHitbox; + private Formatter formaterHitbox; + private Formatter formaterDrawbox; + private String type; + + public Entity(String name,String drawbox,String hitbox) { + thisName = new String(name); + thisDrawbox = new Drawbox(drawbox); + thisHitbox = new Hitbox(hitbox); + } + + public Entity(String name, Hitbox hitbox, Drawbox drawbox) { + this.thisName = name; + this.thisHitbox = hitbox; + this.thisDrawbox = drawbox; + } + + public void setName(String outName) { + thisName = outName; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setDrawbox(Drawbox outDrawbox) { + thisDrawbox = outDrawbox; + }; + + public void setHitbox(Hitbox outHitbox) { + thisHitbox = outHitbox; + }; + + public void setFormaterHitbox(Formatter outFormaterHitbox) { + formaterHitbox = outFormaterHitbox; + }; + + public void setFormaterDrawbox(Formatter outFormaterDrawbox) { + formaterDrawbox = outFormaterDrawbox; + }; + + public String getName() { + return thisName; + }; + + public Drawbox getDrawbox() { + return thisDrawbox; + }; + + public Hitbox getHitbox() { + return thisHitbox; + }; + + public Formatter getFormaterHitbox() { + return formaterHitbox; + }; + + public Formatter getFormaterDrawbox() { + return formaterDrawbox; + }; + public void PrintEntity() { + System.out.println("---------------------"); + System.out.println("Name: "+thisName); + this.thisDrawbox.Print(); + this.thisHitbox.Print(); + System.out.println("---------------------"); + } +} diff --git a/src/model/Formatter.java b/src/model/Formatter.java new file mode 100644 index 0000000..edc4086 --- /dev/null +++ b/src/model/Formatter.java @@ -0,0 +1,5 @@ +package model; + +public interface Formatter { + +} diff --git a/src/model/FormatterCircle.java b/src/model/FormatterCircle.java new file mode 100644 index 0000000..6c0553a --- /dev/null +++ b/src/model/FormatterCircle.java @@ -0,0 +1,5 @@ +package model; + +public class FormatterCircle implements Formatter { + +} diff --git a/src/model/FormatterRectangle.java b/src/model/FormatterRectangle.java new file mode 100644 index 0000000..ea3854e --- /dev/null +++ b/src/model/FormatterRectangle.java @@ -0,0 +1,5 @@ +package model; + +public class FormatterRectangle implements Formatter { + +} diff --git a/src/model/Hitbox.java b/src/model/Hitbox.java new file mode 100644 index 0000000..0beebc3 --- /dev/null +++ b/src/model/Hitbox.java @@ -0,0 +1,83 @@ +package model; + +import java.util.ArrayList; +import java.util.List; + +public class Hitbox { + private String shape = null;// shape - Форма хитбокса. Понадобится при написании сохранения. Один из параметров в xml-file. + private List listPoints = null;//для прямоугольника - 4 точки. Для круга - надо посмотреть. + + public Hitbox(String shape,List listPoints){ + this.shape = new String(shape); + this.listPoints = new ArrayList(listPoints) ; + } + + public Hitbox(String informationHitbox){ + if(informationHitbox!= null) { + listPoints = new ArrayList(); + String[] informations = informationHitbox.split(" "); + //в 0-м индексе всегда идет название фигуры.Так сделан наш xml. + shape = new String(informations[0]); + //заполняем лист точками. Пока что делаю тупо и топорно. Хардкод. Потом можно переделать. + if(shape.equals("Rectangle")) { + parseStringToRectangleHitbox(informations); + }else if(shape.equals("Circle")) { + parseStringToCircleHitbox(informations); + } + } + } + + private void parseStringToRectangleHitbox(String[] informations) { + //составляем точки по которым строится прямоугольник, и запихиваем их в лист с точками + for(int i = 1;i getListPoints() { + return listPoints; + } + public void Print() { + System.out.println(); + System.out.println("|||Hitbox:"); + if(shape!=null&&listPoints!=null) { + System.out.println("shape: " + shape); + for(Point point: listPoints) { + System.out.print("("+point.x+";"+point.y+") "); + } + System.out.println(); + }else { + System.out.println("null"); + } + } + //дописать функцию возвращения listPonts и shape(форма), если будет нужно. + // так же при написании функции возвращения нужных координат, надо их сделать целочисленными. +} diff --git a/src/model/Point.java b/src/model/Point.java new file mode 100644 index 0000000..a0221b7 --- /dev/null +++ b/src/model/Point.java @@ -0,0 +1,11 @@ +package model; + +public class Point { + public float x; + public float y; + + public Point(float mainX,float mainY){ + x = mainX; + y = mainY; + } +} diff --git a/src/repository/ListEntity.class b/src/repository/ListEntity.class new file mode 100644 index 0000000..615a48f Binary files /dev/null and b/src/repository/ListEntity.class differ diff --git a/src/repository/Project.java b/src/repository/Project.java new file mode 100644 index 0000000..ec120d9 --- /dev/null +++ b/src/repository/Project.java @@ -0,0 +1,328 @@ +package repository; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import javax.imageio.ImageIO; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import model.Entity; + + +/** + * Класс данных, который оперирует их сохранением, загрузкой, и хранением в памяти. + * Он нужен для отделения Модели от Представления (см. MVC), чтобы их можно было менять независимо друг от друга. + * Например, при добавлении новой кнопки данные можно будет получить через существующий интерфейс класса не меняя код. + * + * ВАЖНО: данный класс хранит так же актуальную копию XML-представления файла + * */ +public class Project implements Iterable { + + /** + * Путь к XML по-умолчанию. + * Просто заглушка, обычно заменяется актуальным путём в ходе изменения программы.
+ * Cм. {@link #setXMLPath(String)} и {@link #getXMLPath()} + * */ + public static final String DEFAULT_XML_PATH = "res/"; + public static final String DEFAULT_XML_FILENAME = "objecttypes.xml"; + + static Project thisProject; + private List listEntity = new ArrayList(); + private String path = DEFAULT_XML_PATH; + private String fileName = DEFAULT_XML_FILENAME; + // Получение фабрики, чтобы после получить билдер документов. + private DocumentBuilderFactory factory; + // Получили из фабрики билдер, который парсит XML, создает структуру Document в виде иерархического дерева. + private DocumentBuilder builder; + // Запарсили XML, создав структуру Document. Теперь у нас есть доступ ко всем элементам, каким нам нужно. + private Document document; + + private static Logger logger = Logger.getLogger("repository.Project"); + + //!!!РЕАЛИЗАЦИЯ СИНГЛИТОНА!НАЧАЛО!!! + private Project(){}; + + public static Project getInstance() { + if(thisProject == null) { + thisProject = new Project(); + } + return thisProject; + }; + //!!!РЕАЛИЗАЦИЯ СИНГЛИТОНА!ОКОНЧАНИЕ!!! + + /** + * Устанавливает значение пути к XML. Все операции загрузки и сохранения будут работать с этой директорией.
+ * По-умолчанию - {@link #DEFAULT_XML_PATH} + * @param newPath - абсолютный или относительный адрес папки в виде строки. + *
например: "C:/User/map/" или "/home/username/map/" или "res/map" (относительный путь рассчитывается от корня проекта) + * */ + public void setXMLPath(String newPath) { + path = newPath; + } + + /** + * Возвращает актуальный путь к директории, в которой лежит XML-файл с типами объектов, а так же папки с ресурсами.
+ * ps. считается, что ресурсы находятся в той же папке что XML-файл + * */ + public String getXMLPath() { + return path; + } + + /** + * Устанавливает имя файла, из которого загружаются сущности. Ещё нужен путь (см. {@link #getXMLPath()}) + * */ + public void setXMLFileName(String name) { + this.fileName = name; + } + + /** + * Возвращает имя файла, из которого загружаются ресурсы. Нужен для контроля доступа к нему, а так же избавления от жёстких зависимостей.
+ * Например, если fileName в какой-то момент со String сменится на URL достаточно будет адаптировать геттер а не переписывать + * все места где происходят к нему обращения. + * */ + public String getXMLFileName() { + return fileName; + } + + /** + * Перегрузка {@link #load()}.
+ * Использует {@link #setXMLFileName(String)} и {@link #setXMLPath(String)} для того, чтобы сохранить новый путь к XML-файлу и его имя. + * Повторно вызывать их вручную не обязательно. + * + * @param directory - папка где хранится XML-файл и ресурсы (см. {@link #getXMLPath()}) + * @param name - имя XML-файла с определениями типов сущностей + * */ + public void load(String directory, String name) { + setXMLPath(directory); + setXMLFileName(name); + try { + load(); + } catch (SAXException | IOException | ParserConfigurationException e) { + System.err.println("Failed to load project! Cause: "+e.getMessage()); + } + } + + /** + * Загружает типы сущностей из файла с заданным именем и расположением.
+ * */ + public void load() throws SAXException, IOException, ParserConfigurationException { + listEntity.clear(); + factory = DocumentBuilderFactory.newInstance(); + builder = factory.newDocumentBuilder(); + document = builder.parse(new File(path+fileName)); + // Получение списка всех элементов objecttype внутри корневого элемента (getDocumentElement возвращает ROOT элемент XML файла). + NodeList objecttypeElements = document.getDocumentElement().getElementsByTagName("objecttype"); + for(int i = 0; i < objecttypeElements.getLength(); i++) { + //System.out.println("---------------------"); + Node objecttype = objecttypeElements.item(i); + NamedNodeMap attributesObject = objecttype.getAttributes(); + String entityName = new String(attributesObject.getNamedItem("name").getNodeValue()); + //System.out.println("Name: "+entityName); + parsingElementXMLtoElementList(entityName,objecttype); + //System.out.println("---------------------"); + } + } + + // эта колбаса парсит сущности из XML в программные объекты внутри модели, является частью внутренней кухни так что обычно её не нужно трогать + private void parsingElementXMLtoElementList(String entityName,Node objecttype) { + String newDrawbox = null; + String newHitbox = null; + String type = null; + Element element = (Element)objecttype; + NodeList propertyElements = element.getElementsByTagName("property"); + if(propertyElements!=null) { + for(int i = 0; i < propertyElements.getLength(); i++) { + Element property = (Element)propertyElements.item(i); + String propertyName = property.getAttribute("name"); + String defaultProperty = property.getAttribute("default"); + switch(propertyName) { + case "drawbox": + newDrawbox = defaultProperty; + break; + case "hitbox": + newHitbox = defaultProperty; + break; + case "class": + type = defaultProperty; + break; + } + } + Entity e = new Entity(entityName,newDrawbox,newHitbox); + e.setType(type); + listEntity.add(e); + } + } + + /** + * Загружает с диска изображение с заданным именем. Подразумевается, что изображение находится {@link #path там же} где + * XML-файл. Возвращает null если изображение не найдено. + * */ + public BufferedImage loadImageByName(String name) { + //TODO: сделать кеширование - не дело подгружать одну и ту же картинку по десять раз! + + String path = Project.getInstance().getXMLPath(); + String extension = "png"; + // TODO: изображения следует подгружать в отдельном потоке! + + try { + File imageFile = new File(path + name + '.' + extension); + if (!imageFile.exists()) + throw new FileNotFoundException(); + BufferedImage image = ImageIO.read(imageFile); + return image; + } catch (FileNotFoundException fe) { + logger.warning("Image file \""+path+name+'.'+extension+"\" is not found!"); + } catch (IOException e) { + logger.warning("Cannot read file \""+path+name+'.'+extension+"\"!"); + } + return null; + } + /* + * Добавляется обьект как в список всех сущностей, так и в xml-метаданные дерева(element objecttype) + * Это лишь добавление в метаданные, а не парсинг в файл! не путать! + * Для парсинга будет сделана отдельная функция! + */ + public void addEntity(Entity e) { + listEntity.add(e); + Element objecttype = document.createElement("objecttype"); + objecttype.setAttribute("name", e.getName()); + objecttype.setAttribute("color", "000000");//color of entity, needed by Tiled editor + document.getElementsByTagName("objecttypes").item(0).appendChild(objecttype); + /* + * TODO: set "class" property too (code below) + Element property = document.createElement("property"); + objecttype.appendChild(property); + document.appendChild(objecttype); + property.setAttribute("name", "class"); + property.setAttribute("type", "string"); + property.setAttribute("default", e.getType()); + + * creating hitbox or drowbox attributes in advance is insufficient + * they will be added while saving + */ + } + + /* + * Удаляется обьект из списка всех сущностей, и из xml-дерева + */ + public void removeEntity(Entity e) { + listEntity.remove(e); + NodeList nl = document.getElementsByTagName("objecttype"); + for(int i = 0; i < nl.getLength(); i++) { + Node objecttype = nl.item(i); + if(objecttype.getAttributes().getNamedItem("name").getNodeValue().equals(e.getName())) + document.getElementsByTagName("objecttypes").item(0).removeChild(objecttype); + } + } + + public Entity getEntity(int id) { + return listEntity.get(id); + } + + /** + * Возвращает объект сущности с заданным именем, или вбрасывает исключение, если такой сущности не существует. + * */ + public Entity getEntityByName(String name) throws Exception { + //debug print + //System.out.println("----- session started ------"); + for(Entity e: listEntity) { + //System.out.println("we need "+ name +" we got "+e.getName()); + if(e.getName().equals(name)) + return e; + } + + // можно было бы и просто null возвращать, но обращение за несуществующей сущностью само по себе нехороший прецедент + // так что исключение призвано обратить внимание пользователя, если такое действительно случится + throw new Exception("No entity with such name!"); + } + + public void save() { + /* + * thanks to addEntity() and removeEntity() our Document and listEntity + * are interchangeable - they content exactly the same set of objects. + * So we'll iterate over Document instead listEntity. It's more convient + * in this case. + * */ + NodeList objecttypes = document.getElementsByTagName("objecttype"); + for(int i = 0; i < objecttypes.getLength(); i++) { + Node objecttype = objecttypes.item(i); + NodeList propertiesList = objecttype.getChildNodes(); + for(int j = 0; j < objecttypes.getLength(); j++) { + Element property = (Element) propertiesList.item(j); + NamedNodeMap attributes = property.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + Entity entity = null; + try { + entity = getEntityByName(name); + + } catch (Exception e) { + //if there is no entity with such name we'll skip further parsing + System.err.println("Entity "+name+" is not found"); + } + } + } + + // parsing complete, writing to file now + writeXML(); + } + + private void writeXML() { + try { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(new FileOutputStream(path)); + transformer.transform(source, result); + } catch (TransformerException | FileNotFoundException e) { + System.err.println("Saving project is unsuccsessfull! Erorr is: "+e); + } + } + + public void PrintEntitys() { + // TODO Auto-generated method stub + for(Entity ent:listEntity) { + ent.PrintEntity(); + } + + } + + @Override + public Iterator iterator() { + return listEntity.iterator(); + } + + /** + * Лучше бы пользоваться этой функцией поменьше - почти всю работу вполне можно сделать через интерфейс Project
+ * Например, если нужно перебрать все сущности, стоит использовать цикл foreach с использованием инстанса Project, например:
+ * {@code for(Entity e: Project.getInstance()){ *тут клиентский код* }} + * */ + @Deprecated + public List getListEntity() { + return listEntity; + } +} +//в момент окончания рисования, в зависимости в какой мы рисуем вкладке хитбокса, +//в зависимости от того в какой панельке(jpanel)и подклассе интерфейса Editable +//мы дорисовали фигуру, такой форматер и создается. +//хотя не стоит забывать про сейв(не знаю зачем, но стоит подумать, когда сяду снова делать) \ No newline at end of file