From 141e584b31dfe09bbd64b1641a78f4da5bb670f0 Mon Sep 17 00:00:00 2001 From: UnlimitedCookies Date: Tue, 12 Jan 2021 16:23:20 +0100 Subject: [PATCH] Initial commit --- Logbuch.md | 78 +++ Logbuch.pdf | Bin 0 -> 28458 bytes src/Bed.java | 66 +++ src/Canvas.java | 671 ++++++++++++++++++++++++++ src/Chair.java | 65 +++ src/Closet.java | 65 +++ src/Furniture.java | 212 ++++++++ src/MOUSEMovementTest.java | 41 ++ src/Recliner.java | 61 +++ src/Table.java | 55 +++ src/icons/icons8-add-48.png | Bin 0 -> 999 bytes src/icons/icons8-armchair-48.png | Bin 0 -> 488 bytes src/icons/icons8-bed-48.png | Bin 0 -> 881 bytes src/icons/icons8-chair-48.png | Bin 0 -> 793 bytes src/icons/icons8-closet-48.png | Bin 0 -> 325 bytes src/icons/icons8-drag-48.png | Bin 0 -> 445 bytes src/icons/icons8-edit-48.png | Bin 0 -> 741 bytes src/icons/icons8-exit-48.png | Bin 0 -> 650 bytes src/icons/icons8-file-48.png | Bin 0 -> 256 bytes src/icons/icons8-help-48.png | Bin 0 -> 1399 bytes src/icons/icons8-info-48.png | Bin 0 -> 1076 bytes src/icons/icons8-invert-colors-48.png | Bin 0 -> 1074 bytes src/icons/icons8-opened-folder-48.png | Bin 0 -> 578 bytes src/icons/icons8-original-size-48.png | Bin 0 -> 411 bytes src/icons/icons8-paint-palette-48.png | Bin 0 -> 1493 bytes src/icons/icons8-reset-48.png | Bin 0 -> 1559 bytes src/icons/icons8-rotate-48.png | Bin 0 -> 1382 bytes src/icons/icons8-save-48.png | Bin 0 -> 423 bytes src/icons/icons8-table-48.png | Bin 0 -> 210 bytes src/icons/icons8-trash-48.png | Bin 0 -> 456 bytes 30 files changed, 1314 insertions(+) create mode 100644 Logbuch.md create mode 100644 Logbuch.pdf create mode 100644 src/Bed.java create mode 100644 src/Canvas.java create mode 100644 src/Chair.java create mode 100644 src/Closet.java create mode 100644 src/Furniture.java create mode 100644 src/MOUSEMovementTest.java create mode 100644 src/Recliner.java create mode 100644 src/Table.java create mode 100644 src/icons/icons8-add-48.png create mode 100644 src/icons/icons8-armchair-48.png create mode 100644 src/icons/icons8-bed-48.png create mode 100644 src/icons/icons8-chair-48.png create mode 100644 src/icons/icons8-closet-48.png create mode 100644 src/icons/icons8-drag-48.png create mode 100644 src/icons/icons8-edit-48.png create mode 100644 src/icons/icons8-exit-48.png create mode 100644 src/icons/icons8-file-48.png create mode 100644 src/icons/icons8-help-48.png create mode 100644 src/icons/icons8-info-48.png create mode 100644 src/icons/icons8-invert-colors-48.png create mode 100644 src/icons/icons8-opened-folder-48.png create mode 100644 src/icons/icons8-original-size-48.png create mode 100644 src/icons/icons8-paint-palette-48.png create mode 100644 src/icons/icons8-reset-48.png create mode 100644 src/icons/icons8-rotate-48.png create mode 100644 src/icons/icons8-save-48.png create mode 100644 src/icons/icons8-table-48.png create mode 100644 src/icons/icons8-trash-48.png diff --git a/Logbuch.md b/Logbuch.md new file mode 100644 index 0000000..1b9a9ac --- /dev/null +++ b/Logbuch.md @@ -0,0 +1,78 @@ +# Generelle Informationen +- Englische Kommentare Stammen von mir +- Ich hab sehr viel Zeit zuhause verbracht die Sprache zu lernen und verstehen + +### Das Programm bietet folgende Funktionen: +- Speichern und Öffnen der Möbelobjekte +- Selektion von Möbelobjekten durch einfaches klicken +- Bewegen der Möbelstücke durch Drag and Drop +- Durch scrollen können Möbelobjekte rotiert werden +- Bei betätigter STRG-Taste beim scrollen kann die Gräöße verändert werden +- Alle manuell veränderten Attribute können auf den Standardwwer zurückgesetzt werden +- Menüleiste / Menubar mit Icons +- Das Ändern der Farbe eines Möbelonjekts +- Und vieles mehr... + +(In den Logbucheinträgen sind nicht alle Details festgehalten; die meisten Erklärungen befinden sich im Code selbst) +# Logbucheinträge +## Donnerstag 09/01/2020 Informatikunterricht +Änderungen: +- Farbänderungen bei Auswahl von einem Objekt zu schwarz + +Heute habe ich versucht die Funktion des Fabwechsels mit einhergehender Auswahl fertigzustellen. Diese sind noch nicht voll funktionsfähig. +Leider bin ich an einen Kopellierfehler hängen geblieben. Ich habe noch nicht ganz verstanden, was den Fehler auslöst. +Deshalb bin ich leider etwas frustriert. + +## 1Donnerstag 6/01/2020 Informatikunterricht +Den Fehler aus der letzen Unterricht konnte ich beheben: Der Fehler lag in der Änderung der Farbe, welche ohne weiteres nicht direkt geändert werden konnte. Deshalb hab ich eine Methode zum Ändern der Farbe in der Furniture Klasse erstellt. Ich habe eine neue Variable erstellt, welche den Farbzustand des Objekts speichert, sodass ich bei der Deselektion des Objekts den vorherigen Farbzustand wiederherstellen kann. + + +Den Rest der Unterrichtszeit habe ich damit verbracht mir anzuschauen wie die JMenuBar funktioniert und die Bar in meinem Programm implementiert. +Dabei habe ich noch nicht ganz verstanden, wie die dahinterstehende Funktion ausgelöst wird. In den Beispielen wird nämlich eine kompliziert aussehende eigene Klasse erstellt, welche mit einem ActionListener erweitert wird. Die JMenuItems führen also noch nichts aus und sind somit "dumm". + + +## Dienstag 21/01/2020 + +Ich habe heute die grundlegenden Funktionen der GUI.java in Leinwand.java implementiert (sprich main function und JPanel). +Da die Funktionen von dem vorherigen JButton Panel (u.a. Objekte erzeugen und Objekte bewegen) nicht mehr benötigt werden und diese Funktionalität durch JMenuBAr übernommen wurde. Bei dem Prozess musste ich einige Methoden anpassen oder teilweise auch neue, bessere oder effizientere Methoden schreiben. +Bei der Übernahme hatte ich teilweise Probleme mit statischen und nicht-statischen Funktionen und da häufig eine Kette von Methoden voneinander abhängig ist wirkt sich eine Veränderung (z.B. Veränderung von statisch zu nicht-statisch) sofort auf alle anderen aus. Dies macht die Fehlersuche schwierig. + +## Datum unbekannt: Ab hier habe ich mich regelmäßig nachmittags hingesetzt und weitergearbeitetet +Ich habe heute ziemlich viel Zeit mit der Drag and Drop Funktion verrbracht. Die Schwierigkeit liegt in dem sofortigen verschieben des Objects, da mit einer Bewegung der Maus auch eine Bewegung des dementsprechenden Objekts auslösen soll. Ich habe mich an einem Codeblock von Stackoverflow orientiert, welchen ich auch als Demo in meinem Programm eingebaut habe. Jedoch musste ich noch eine Menge Modifikationen durchführen, um diesen mit meinen Raumplaner funktioniert, da der Codeblock davon ausgeht, dass das verschobene Objekt nach dem verschieben an einer neuen Stelle ist. Beim Raumplaner kann man allerdings den ActionListener nur zur Leinwand hinzufügen und da sich dieses Objekt nicht bewegt musste ich eine Veränderung duchführen. Beim Klicken wird die Position des Möbelstücks sowie die Position des Cursors in einer Variable festgehalten. Sobald man die Maus bewegt wird die neue Position des ausgewählten Objekts wie folgt festgelegt: Position des Objekts beim Klickvorgang + Aktuelle Cursorposition - Cursorposition beim Klickvorgang. Somit wird also im Prinzip die Differenz der von der Maus zurückgelegten Strecke zu der Position addiert/subtrahiert. Und dies passiert bei jedem Mal, wenn der MouseListener eine Bewegung registriert - so kommt das Drag and Drop Gefühl zu Stande. + +## Neuer Tag (Datum unbekannt) +Ich habe heute den ColorChanger implementiert, dabei habe ich ein kurzes YouTube Tutorial geschaut und danach verstanden wie dies funktioniert. +Um die Farbe auch abspeichern zu können, habe ich den Typ des color Attributs von Typ String auf Typ Color geändert. +Damit man wieder auf die ursprüngliche Farbe zurückkehren kann, speichert jedes Objekt zudem noch die Farbe beim erstellen des Objekts. + +Zudem habe ich heute den MouseWheelListener so implementiert, sodass bei Bewegung des Mausrads das Objekt gedreht wird. Die Idee stammt von dem Raumplaner, welcher im Informatik Ordner als Vorbild abgelegt war. Der MouseWheelListener gibt entweder 1 oder -1 aus, abhängig von der Richtung. Diesen Wert kann ich einfach mit 10 multiplizieren und diesen dann zum aktuellen Rotationswert addiereDamit auch die Größe geändert werden kann habe ich die einfache Option hinzugeüft, dass beim gedrückt halten des STRG-Knopfes die Größe entweder vergrößert oder verkleinert wird. Dabei wird der aktuelle Größenwert des Objekts durch 10 geteilt und dann entweder addiert oder subtrahiert. Das bedeutet also, dass entweder 10 addiert oder subtrahiert wird. + + +## Neuer Tag (Datum unbekannt) +Heute habe ich die Speicherfunktion implementiert. Zur Hilfe habe ich einige Anleitungen sowie Beispiele mir angeschaut. +Dabei habe ich auch einen Codeblock übernommen und stark modifiziert, sodass er passt. Vor dem Speichern wird überprüft, ob es eine derartige Datei bereits gibt und es wird eine Dateiendung angehängt, sofern dies nicht bereits von Nutzer passiert ist. Zudem müssen hier einige try/catch Blöcke verwendet werden, damit bei einem Fehler das Programm nicht abstürzt, sondern nur die jeweilige Funktion mit einem Fehler beendet. Beim Speichern werden einfach alle Objekte mit einem for-loop abgespeichert. Das Speichern funktionierte am Ende auch taddellos, allerdings wird beim laden nur das erste Objekt geladen. + + + + +## Freitag 21/02/2020 +Ich konnte heute den Fehler des Abspeicherns lösen: Der EOFFile Boolean löste zu früh aus und somit wurde immmer nur das erste Objekt importiert. Durch Veränderung des Mechanismus zur Erkennung, ob die Datei zu Ende ist konnte ich das Problem lösen. +Heute habe ich das Aussehen etwas durch das hinzufügen von Icons aufpoliert. Damit die Icons nicht gigantisch angezeigt werden, musste ich mithilfe eines Codeblocks von Stackoverflow die Icons vorher auf die richtige Auflösung herunterskalieren. Die Icons verbessern das Erlebnis erheblich. +Zudem habe ich noch ein About Reiter sowie die MouseMovementDemo in mein Programm integriert. + + +# Verwendete Hilfestellung +Dabei habe ich mithilfe folgender (Video-) Tutorials gearbeitet und teilweise Code Blöcke daraus übernommen: + +* Die offiziellen Java Dokumentation [Java Docs](https://docs.oracle.com/javase/7/docs/api/) +* Dieses Video half mit mit dem JMenu [Youtube](https://www.youtube.com/watch?v=HY8jYkiBPU8) +* Ich habe den Codeblock vom MouseListener hier entnommen: [Stackoverflow](https://stackoverflow.com/questions/9036730/) +* Hilfe mit dem JFileChooser und Codeblöcke [Youtube](https://www.youtube.com/watch?v=rOrJ5TGzyeA) +* Hilfe mit dem JFileChooser-Filtering [Stackoverflow](https://stackoverflow.com/questions/18575655/) +* Codeblock für die infoBox [Stackoverflow](https://stackoverflow.com/questions/7080205/) +* Zum speichern in einer Datei von [Coderanch](https://coderanch.com/t/524426/java/save-array-file) +* Grundlegende Erkennung der MouseRadRotation abgeschaut von [Stackoverflow](https://stackoverflow.com/questions/35259118/) +* Filefilter, welcher die Endung anhängt: [Stackoverflow](https://stackoverflow.com/questions/8713968/) +* Hilfe mit der JMenuBar von [Stackoverflow](https://stackoverflow.com/questions/12527092/) +* Dieser Codeblock transformiert die Icons auf die richtige Größe [Stackoverflow](https://stackoverflow.com/questions/25593949/) +* Die Icons stammen von [Icons8](https://icons8.com) \ No newline at end of file diff --git a/Logbuch.pdf b/Logbuch.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bba48c5fc8383148cc84ed3b8fdf7a44692559a1 GIT binary patch literal 28458 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

wLT9n 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 NKKEaLsU214{vXP(?im08 literal 0 HcmV?d00001 diff --git a/src/Bed.java b/src/Bed.java new file mode 100644 index 0000000..15e9465 --- /dev/null +++ b/src/Bed.java @@ -0,0 +1,66 @@ +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.awt.geom.Line2D; + +/** + * Ein Bett, das manipuliert werden kann und sich selbst auf einer Leinwand + * zeichnet. + * + * @author Claus Albowski + * @version 2.3 (sept 07) + */ +public class Bed extends Furniture { + private static final long serialVersionUID = 1L; + + /** + * Erzeuge ein neues Bett mit einer Standardfarbe und Standardgroesse an einer + * Standardposition. (Standardkonstruktor) + */ + public Bed() { + xPosition = 10; + yPosition = 180; + color = Color.magenta; + orientation = 0; + isVisible = false; + width = 200; + depth = 200; + } + + /** + * Erzeuge ein neues Bett. + */ + public Bed(int xPosition, int yPosition, Color color, int orientation, int width, int depth) { + this.xPosition = xPosition; + this.yPosition = yPosition; + this.color = color; + this.currentColor = color; // the default color is set to the initial color + this.defaultColor = color; // the default color is set to the initial color + this.defaultWidth = width; // the default width is set to the initial width + this.defaultDepth = depth; // the default width is set to the initial depth + this.orientation = orientation; + isVisible = false; + this.width = width; + this.depth = depth; + } + + /** + * Berechnet das zu zeichnende Shape anhand der gegebenen Daten [ Zum Anzeigen + * der Attributwerte ueber Inspect muss hier die Sichtbarkeit auf public gesetzt + * werden. ] + */ + protected Shape getCurrentFigure() { + // einen GeneralPath definieren + GeneralPath bed = new GeneralPath(); + Rectangle2D frame = new Rectangle2D.Double(0, 0, width, depth); + bed.append(frame, false); + Line2D fold1 = new Line2D.Double(0, 0, width, depth / 2); + bed.append(fold1, false); + Line2D mid = new Line2D.Double(0, depth / 2, width, depth / 2); + bed.append(mid, false); + Line2D fold2 = new Line2D.Double(0, depth, width, depth / 2); + bed.append(fold2, false); + return transform(bed); + } +} diff --git a/src/Canvas.java b/src/Canvas.java new file mode 100644 index 0000000..194ece6 --- /dev/null +++ b/src/Canvas.java @@ -0,0 +1,671 @@ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.*; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JFileChooser; +import javax.swing.ImageIcon; +import javax.swing.JColorChooser; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.awt.BorderLayout; + +/** + * Leinwand ist eine Klasse, die einfache Zeichenoperationen auf einer + * leinwandartigen Zeichenfl�che erm�glicht. Sie ist eine vereinfachte Version + * der Klasse Canvas (englisch f�r Leinwand) des JDK und wurde speziell f�r das + * Projekt "Figuren" geschrieben. + * + * + * @author: Bruce Quig + * @author: Michael K�lling (mik) + * @author: Axel Schmolitzky + * + * @author: �nderungen von + * @Java-MS Groupies + * @hier: Uwe Debacher + * + * @version: 3.0 (2020/02/18) + * + * Finale Änderungen durch: + * @author: Kevin Dorner + */ +public class Canvas { + // Hinweis: Die Implementierung dieser Klasse (insbesondere die + // Verwaltung der Farben und Identit�ten der Figuren) ist etwas + // komplizierter als notwendig. Dies ist absichtlich so, weil damit + // die Schnittstellen und Exemplarvariablen der Figuren-Klassen + // f�r den Lernanspruch dieses Projekts einfacher und klarer + // sein k�nnen. + + private static Canvas leinwandSingleton; + public static ArrayList allFurniture = new ArrayList<>(); // array that contains all furniture + private volatile int draggedAtX, draggedAtY; // variables for drag and drop + + /** + * Fabrikmetlor color;hode, die eine Referenz auf das einzige Exemplar dieser + * Klasse zur�ckliefert. Wenn es von einer Klasse nur genau ein Exemplar gibt, + * wird dieses als 'Singleton' bezeichnet. + */ + public static Canvas getCanvas() { + if (leinwandSingleton == null) { + leinwandSingleton = new Canvas("Furniture Planner", Color.white); + + } + leinwandSingleton.setVisibility(true); + return leinwandSingleton; + } + + // ----- Exemplarvariablen ----- + + private JFrame window; + private DrawingSurface drawingSurface; + private Graphics2D graphic; + private Color backgroundcolor; + private Image canvasImage; + private List figures; + private Map figureToShape; // Abbildung von Figuren zu Shapes + private Furniture selectedFurniture = null; // used to track the selected furniture + private Furniture previousSelectedFurniture = null; // used to track the previously selected furniture + private volatile int selectedFurniturePosX, selectedFurniturePosY; + + /** + * Erzeuge eine Leinwand. + * + * @param title Titel, der im Rahmen der Leinwand angezeigt wird + * @param width die gew�nschte Breite der Leinwand + * @param height die gew�nschte H�he der Leinwand + * @param baseColor die Hintergrundfarbe der Leinwand + */ + private Canvas(String title, Color baseColor) { + window = new JFrame(); + drawingSurface = new DrawingSurface(); + int width = 600; + int height = 600; + window.setTitle(title); + window.setLocationRelativeTo(null); // spawns the window in the center of the screen + drawingSurface.setPreferredSize(new Dimension(width, height)); + window.setLayout(new BorderLayout()); + window.add(drawingSurface, BorderLayout.CENTER); + backgroundcolor = baseColor; + window.pack(); + figures = new ArrayList(); // contains the figure objects in an array + figureToShape = new HashMap(); // contains the shapes + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // exits when window is closed + createmenubar(); // adds menubar + MouseListener(); // adds MouseListener for drag and drop functionality + WheelListener(); // adds WheelListener for resize/rotate functionality + } + + /** + * Setze, ob diese Leinwand sichtbar sein soll oder nicht. Wenn die Leinwand + * sichtbar gemacht wird, wird ihr Fenster in den Vordergrund geholt. Diese + * Operation kann auch benutzt werden, um ein bereits sichtbares Leinwandfenster + * in den Vordergrund (vor andere Fenster) zu holen. + * + * @param sichtbar boolean f�r die gew�nschte Sichtbarkeit: true f�r sichtbar, + * false f�r nicht sichtbar. + */ + public void setVisibility(boolean sichtbar) { + if (graphic == null) { + // erstmaliger Aufruf: erzeuge das Bildschirm-Image und f�lle + // es mit der Hintergrundfarb e + Dimension size = drawingSurface.getSize(); + canvasImage = drawingSurface.createImage(size.width, size.height); + graphic = (Graphics2D) canvasImage.getGraphics(); + graphic.setColor(backgroundcolor); + graphic.fillRect(0, 0, size.width, size.height); + graphic.setColor(Color.black); + } + window.setVisible(sichtbar); + } + + /** + * Zeichne f�r das gegebene Figur-Objekt eine Java-Figur (einen Shape) auf die + * Leinwand. + * + * @param figure das Figur-Objekt, f�r das ein Shape gezeichnet werden soll + * @param color die Farbe der Figur + * @param shape ein Objekt der Klasse Shape, das tats�chlich gezeichnet wird + */ + public void drawFigure(Object figure, Color color, Shape shape) { + figures.remove(figure); // entfernen, falls schon eingetragen + figures.add(figure); // am Ende hinzuf�gen + figureToShape.put(figure, new ShapeWithColor(shape, color)); + reDraw(); + } + + /** + * Entferne die gegebene Figur von der Leinwand. + * + * @param figure die Figur, deren Shape entfernt werden soll + */ + public void removeFigure(Object figure) { + figures.remove(figure); // entfernen,falls schon eingetragen + figureToShape.remove(figure); + reDraw(); + } + + /** + * Warte f�r die angegebenen Millisekunden. Mit dieser Operation wird eine + * Verz�gerung definiert, die f�r animierte Zeichnungen benutzt werden kann. + * + * @param milliseconds die zu wartenden Millisekunden + */ + public void wait(int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (Exception e) { + // Exception ignorieren + } + } + + /** + * Zeichne erneut alle Figuren auf der Leinwand. + */ + private void reDraw() { + deleteCanvas(); + for (Iterator i = figures.iterator(); i.hasNext();) { + ((ShapeWithColor) figureToShape.get(i.next())).draw(graphic); + } + drawingSurface.repaint(); + } + + /** + * L�sche die gesamte Leinwand. + */ + private void deleteCanvas() { + Color original = graphic.getColor(); + graphic.setColor(backgroundcolor); + Dimension size = drawingSurface.getSize(); + graphic.fill(new Rectangle(0, 0, size.width, size.height)); + graphic.setColor(original); + } + + public void MouseListener() { + drawingSurface.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { // When the mouse button is pressed the x and y values are parsed to + // variable + draggedAtX = e.getX(); // remembers position when mouse button is pressed + draggedAtY = e.getY(); // remembers position when mouse button is pressed + if (allFurniture.size() != 0) { // only executes once the array is not empty + objectClickCheck(); + } + } + }); + + drawingSurface.addMouseMotionListener(new MouseMotionAdapter() { + public void mouseDragged(MouseEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + selectedFurniture.setPos(selectedFurniturePosX + e.getX() - draggedAtX, // + selectedFurniturePosY + e.getY() - draggedAtY); + // DEBUG: + System.out.println("x: " + (selectedFurniturePosX + e.getX() - draggedAtX) + " y: " + + (selectedFurniturePosY + e.getY() - draggedAtY)); + System.out.println("x calc: " + selectedFurniturePosX + " + " + e.getX() + " - " + draggedAtX); + System.out.println("y calc: " + selectedFurniturePosY + " + " + e.getY() + " - " + draggedAtY); + } + } + }); + } + + public void WheelListener() { + drawingSurface.addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + if (!e.isControlDown()) { // only execute when ctrl is not pressed + selectedFurniture.rotateAdd((e.getWheelRotation() * 10)); // the wheel rotation is multiplied with 10 and + // added to the selectedFurniture + } else { // the wheelRotation returns either 1 or -1 depending on the direction + selectedFurniture.changeObjectSize(e.getWheelRotation()); + } + } else { + System.out.println("Nothing selected."); + } + } + }); + } + + public void objectClickCheck() { + for (Furniture furniture : allFurniture) { // check is executed for the number of furniture in the array + if (furniture.getCurrentFigure().contains(draggedAtX, draggedAtY)) { + selectFurniture(furniture); + return; + } else { + unselectFurniture(); + } + } + } + + public void selectFurniture(Furniture furniture) { + selectedFurniture = furniture; // selects the furniture by moving its id to the selected variable + restoreColor(previousSelectedFurniture); // prevents the color from not changing when clicking between objects + previousSelectedFurniture = furniture; // remembers the previously selected furniture + System.out.println("SELECTED: " + furniture); //// DEBUG + selectedFurniturePosX = furniture.xPosition; // remembers the furnitures position when clicked + selectedFurniturePosY = furniture.yPosition; + furniture.changeCurrentColor(Color.black); + } + + public void unselectFurniture() { + selectedFurniture = null; + System.out.println("UNSELECTED"); //// DEBUG + restoreColor(previousSelectedFurniture); + } + + public void restoreColor(Furniture furniture) { + if (furniture != null) { + furniture.changeCurrentColor(furniture.getColor()); // restores the color to the previous one + } + } + + /************************************************************************ + * Interne Klasse Zeichenflaeche - die Klasse f�r die GUI-Komponente, die + * tats�chlich im Leinwand-Fenster angezeigt wird. Diese Klasse definiert ein + * JPanel mit der zus�tzlichen M�glichkeit, das auf ihm gezeichnet Image + * aufzufrischen (erneut zu zeichnen). + */ + private class DrawingSurface extends JPanel { + private static final long serialVersionUID = 1L; // Sets serial version that prevents file version incompatibility + + public void paint(Graphics g) { + g.drawImage(canvasImage, 0, 0, null); + } + } + + /************************************************************************ + * Interne Klasse ShapeMitFarbe - Da die Klasse Shape des JDK nicht auch eine + * Farbe mitverwalten kann, muss mit dieser Klasse die Verkn�pfung modelliert + * werden. graphic.fill() durch graphic.draw() ersetzt von Uwe Debacher am + * 5.12.2003 + */ + private class ShapeWithColor { + private Shape shape; + private Color color; + + public ShapeWithColor(Shape shape, Color color) { + this.shape = shape; + this.color = color; + } + + public void draw(Graphics2D graphic) { + graphic.setColor(color); + graphic.draw(shape); + } + } + + public static void saveProject() { + FileNameExtensionFilter filter = new FileNameExtensionFilter("Furniture Planner Projects (*.fpp)", "fpp"); + JFileChooser filechooser = new JFileChooser(); // creates the Filechoose object + filechooser.setFileFilter(filter); // sets the file filter for the file chooser + File file = filechooser.getSelectedFile(); + int returnVal = filechooser.showSaveDialog(null); // opens the file chooser dialog -- null centers the dialog + if (!filechooser.getSelectedFile().getAbsolutePath().endsWith(".fpp")) { + file = new File(filechooser.getSelectedFile() + ".fpp"); // adds the file name extension to the + } else { + file = filechooser.getSelectedFile(); + } + if (returnVal == JFileChooser.APPROVE_OPTION) { // executed once open button is pressed + String fileName = file.getName(); // filename to string + System.out.println("FileName: " + fileName); + System.out.println("Saving to " + file.getAbsolutePath() + " ..."); + try { + if (!file.exists()) { + write(file.getAbsolutePath()); + } else if (confirmDialog("The file " + fileName + " already exsists. Do you want to overwrite it?", + "Warning")) { + file.delete(); + write(file.getAbsolutePath()); + } else { + System.out.println("Operation denied!"); + return; + } + } catch (IOException e) { + infoBox("An Error occured. Please try again. (IOException)", "Furniture Planner"); + e.printStackTrace(); + } + } else if (returnVal == JFileChooser.CANCEL_OPTION) { // executed when the operation is cancelled + return; + } else if (returnVal == JFileChooser.ERROR_OPTION) { // executed on error + infoBox("An Error occured. Please try again.", "Furniture Planner"); + } + + } + + public static void write(String filepath) throws IOException { + ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(filepath)); + + for (Furniture furniture : allFurniture) { + objOut.writeObject(furniture); + System.out.println("Writing object: " + furniture); + } + objOut.close(); // prevents any leakage + } + + public void openProject() { + FileNameExtensionFilter filter = new FileNameExtensionFilter("Furniture Planner Projects (*.fpp)", "fpp"); + JFileChooser filechooser = new JFileChooser(); // creates the Filechoose object + filechooser.setFileFilter(filter); + + int returnVal = filechooser.showOpenDialog(null); // opens the file chooser dialog + File file = filechooser.getSelectedFile(); + if (returnVal == JFileChooser.APPROVE_OPTION) { // executed once open button is pressed + System.out.println(file.getPath()); + try { + try { + read(file.getAbsolutePath()); + } catch (ClassNotFoundException e) { + infoBox("An Error occured. Please try again. (ClassNotFoundException)", "Furniture Planner"); + e.printStackTrace(); + } + } catch (IOException e) { + infoBox("An Error occured. Please try again. (IOException)", "Furniture Planner"); + e.printStackTrace(); + } + } else if (returnVal == JFileChooser.CANCEL_OPTION) { // executed when the operation is cancelled + return; + } else if (returnVal == JFileChooser.ERROR_OPTION) { // executed on error + infoBox("An Error occured. Please try again.", "Furniture Planner"); + } + } + + public void read(String filepath) throws IOException, ClassNotFoundException { + if (confirmDialog("All unsaved data will be lost! Are you sure?", "Warning")) { + boolean EOLreached = false; + ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(filepath)); + for (Furniture importedFurniture : allFurniture) { + importedFurniture.hide(); + } + Canvas.allFurniture.clear(); // clears the array + Furniture importedFurniture = null; + do { // is at least executed once + try { + importedFurniture = (Furniture) objIn.readObject(); + System.out.println("Imported " + importedFurniture); //// DEBUG + } catch (EOFException e) { + System.out.println("EOL reached"); //// DEBUG + EOLreached = true; + } + if (EOLreached) { + objIn.close(); // closes once the end is reached + } else { + Canvas.allFurniture.add(importedFurniture); + importedFurniture.hide(); + importedFurniture.show(); + } + } while (!EOLreached); // keeps repeating until EOF is reached + } else { + System.out.println("Operation denied!"); + return; + } + drawingSurface.repaint(); // repaint is triggered + System.out.println("Repaint triggered "); //// DEBUG + } + + public static void infoBox(String infoMessage, String titleBar) { // method for creating an infobox + JOptionPane.showMessageDialog(null, infoMessage, titleBar, JOptionPane.INFORMATION_MESSAGE); + } + + public static boolean confirmDialog(String Message, String titleBar) { + int reply = JOptionPane.showConfirmDialog(null, Message, titleBar, JOptionPane.YES_NO_OPTION); + if (reply == JOptionPane.YES_OPTION) { + return true; + } else { + return false; + } + } + + public void createmenubar() { + + JMenuBar menubar = new JMenuBar(); // create menubar + + JMenu file = new JMenu("File"); // creates the file tab + menubar.add(file); + file.setIcon(imageScaler("icons/icons8-file-48.png")); + + JMenuItem open = new JMenuItem("Open Project", imageScaler("icons/icons8-opened-folder-48.png")); + file.add(open); + + JMenuItem save = new JMenuItem("Save Project", imageScaler("icons/icons8-save-48.png")); + file.add(save); + + JMenuItem exit = new JMenuItem("Exit", imageScaler("icons/icons8-exit-48.png")); // creates the exit entry + file.add(exit); // adds the exit entry to the file tab + + JMenu edit = new JMenu("Edit"); // creates the edit tab + menubar.add(edit); + edit.setIcon(imageScaler("icons/icons8-edit-48.png")); + + JMenuItem changeColor = new JMenuItem("Change Color", imageScaler("icons/icons8-paint-palette-48.png")); + edit.add(changeColor); + + JMenuItem resetColor = new JMenuItem("Reset Color", imageScaler("icons/icons8-invert-colors-48.png")); + edit.add(resetColor); + + JMenuItem resetSize = new JMenuItem("Reset Size", imageScaler("icons/icons8-original-size-48.png")); + edit.add(resetSize); + + JMenuItem resetRotation = new JMenuItem("Reset Rotation", imageScaler("icons/icons8-rotate-48.png")); + edit.add(resetRotation); + + JMenuItem delete = new JMenuItem("Delete", imageScaler("icons/icons8-trash-48.png")); + edit.add(delete); + + JMenu addbar = new JMenu("Add"); + menubar.add(addbar); + addbar.setIcon(imageScaler("icons/icons8-add-48.png")); + + JMenuItem table = new JMenuItem("Table", imageScaler("icons/icons8-table-48.png")); + addbar.add(table); + + JMenuItem chair = new JMenuItem("Chair", imageScaler("icons/icons8-chair-48.png")); + addbar.add(chair); + + JMenuItem recliner = new JMenuItem("Armchair", imageScaler("icons/icons8-armchair-48.png")); + addbar.add(recliner); + + JMenuItem closet = new JMenuItem("Closet", imageScaler("icons/icons8-closet-48.png")); + addbar.add(closet); + + JMenuItem bed = new JMenuItem("Bed", imageScaler("icons/icons8-bed-48.png")); + addbar.add(bed); + + JMenu help = new JMenu("Help"); // creates the help tab + menubar.add(help); // adds the help tab to the menubar + help.setIcon(imageScaler("icons/icons8-help-48.png")); + + JMenuItem about = new JMenuItem("About", imageScaler("icons/icons8-info-48.png")); + help.add(about); // adds the about entry to the help tab + + JMenuItem mouseMovement = new JMenuItem("Mouse Movement Demo", imageScaler("icons/icons8-drag-48.png")); + help.add(mouseMovement); + + exit.addActionListener(new exitaction()); // add actionListener to the exit entry + table.addActionListener(new tableaction()); + delete.addActionListener(new deleteaction()); + open.addActionListener(new openaction()); + save.addActionListener(new saveaction()); + about.addActionListener(new aboutaction()); + chair.addActionListener(new chairaction()); + recliner.addActionListener(new reclineraction()); + closet.addActionListener(new closetaction()); + bed.addActionListener(new bedaction()); + resetRotation.addActionListener(new resetrotationaction()); + changeColor.addActionListener(new changecoloraction()); + resetColor.addActionListener(new resetcoloraction()); + resetSize.addActionListener(new resetsizeaction()); + mouseMovement.addActionListener(new mousemovementdemoaction()); + + window.setJMenuBar(menubar); // assigns the menubar to the Jframe + } + + public ImageIcon imageScaler(String icon) { + ImageIcon i = new ImageIcon((getClass().getResource(icon))); + Image image = i.getImage(); // transform it + Image newimg = image.getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH); // scale it the smooth way to 20x20 + // pixels + i = new ImageIcon(newimg); // transform it back + return i; + } + + // Main Function is executed with class + public static void main(String[] args) { + getCanvas(); + + } + + // Action classes that implement the ActionListener that execute once clicked + class exitaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + } + + class tableaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + Furniture table = new Table(10, 10, Color.red, 0, 100, 60); + table.show(); + Canvas.allFurniture.add(table); + } + } + + class chairaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + Furniture chair = new Chair(10, 10, Color.blue, 0); + chair.show(); + Canvas.allFurniture.add(chair); + } + } + + class reclineraction implements ActionListener { + public void actionPerformed(ActionEvent e) { + Furniture recliner = new Recliner(10, 10, Color.green, 0); + recliner.show(); + Canvas.allFurniture.add(recliner); + } + } + + class closetaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + Furniture closet = new Closet(10, 10, Color.orange, 0, 60, 37); + closet.show(); + Canvas.allFurniture.add(closet); + } + } + + class bedaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + Furniture bed = new Bed(10, 10, Color.magenta, 0, 60, 60); + bed.show(); + Canvas.allFurniture.add(bed); + } + } + + class openaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + openProject(); + } + } + + class saveaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + saveProject(); + } + } + + class mousemovementdemoaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + MOUSEMovementTest.MouseMovementTester(); + } + } + + class resetsizeaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + selectedFurniture.resetObjectSize(); + } else { + System.out.println("Nothing Selected."); + } + } + } + + class deleteaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + Furniture x = selectedFurniture; + selectedFurniture.hide(); + selectedFurniture.resetCanvas(); + removeFigure(x); // removes from canvas + allFurniture.remove(x); // removes from array + System.out.println("REMOVED: " + x); //// DEBUG + System.out.println("New array: " + allFurniture); //// DEBUG + } else { + System.out.println("Nothing Selected."); + } + } + } + + class changecoloraction implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + Color color = selectedFurniture.getColor(); + color = JColorChooser.showDialog(null, "Choose new color", color); + selectedFurniture.changeGeneralColor(color); // changes the general color of the object + selectedFurniture.changeCurrentColor(color); // changes the current/changing-with-selection color of the object + } else { + System.out.println("Nothing Selected."); + } + } + } + + class resetcoloraction implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + Color color = selectedFurniture.getDefaultColor(); + selectedFurniture.changeGeneralColor(color); + selectedFurniture.changeCurrentColor(color); + } else { + System.out.println("Nothing Selected."); + } + } + } + + class resetrotationaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (allFurniture.size() != 0 && selectedFurniture != null) { // only executes once the array is not empty + selectedFurniture.resetRotation(); + } + ; + } + } + +} + +class aboutaction implements ActionListener { + public void actionPerformed(ActionEvent e) { + Canvas.infoBox( + "Furniture Planner v3.0\nby Kevin Dorner\n\nInformatics 2020\n\nIcons from ICONS8\n\nContributors:\nBruce Quig\nMichael Koelling\nAxel Schmolitzky\nUwe Debacher", + "About"); + } +} \ No newline at end of file diff --git a/src/Chair.java b/src/Chair.java new file mode 100644 index 0000000..041ef04 --- /dev/null +++ b/src/Chair.java @@ -0,0 +1,65 @@ +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +/** + * Ein Stuhl, der manipuliert werden kann und sich selbst auf einer Leinwand + * zeichnet. + * + * @author Claus Albowski + * @version 2.3 (sept 07) + */ +public class Chair extends Furniture { + private static final long serialVersionUID = 1L; + + /** + * Erzeuge einen neuen Stuhl mit einer Standardfarbe und Standardgroesse an + * einer Standardposition. (Standardkonstruktor) + */ + public Chair() { + xPosition = 60; + yPosition = 80; + orientation = 270; + color = Color.blue; + isVisible = false; + width = 40; + depth = 40; + } + + /** + * Erzeuge einen neuen Stuhl mit einer Standardgroesse. + */ + public Chair(int xPosition, int yPosition, Color color, int orientation) { + this.xPosition = xPosition; + this.yPosition = yPosition; + this.color = color; + this.currentColor = color; // the default color is set to the initial color + this.defaultColor = color; // the default color is set to the initial color + this.orientation = orientation; + isVisible = false; + width = 40; + depth = 40; + this.defaultWidth = width; // the default width is set to the initial width + this.defaultDepth = depth; // the default width is set to the initial depth + } + + /** + * Berechnet das zu zeichnende Shape anhand der gegebenen Daten [ Zum Anzeigen + * der Attributwerte ueber Inspect muss hier die Sichtbarkeit auf public gesetzt + * werden. ] + */ + protected Shape getCurrentFigure() { + // einen GeneralPath definieren + GeneralPath chair = new GeneralPath(); + chair.moveTo(0, 0); + chair.lineTo(width, 0); + chair.lineTo(width + (width / 20 + 1), depth); + chair.lineTo(-(width / 20 + 1), depth); + chair.lineTo(0, 0); + // Das ist die Umrandung. Das Stuhl bekommt noch eine Lehne: + chair.moveTo(0, (width / 10 + 1)); + chair.lineTo(width, (width / 10 + 1)); + return transform(chair); + } + +} diff --git a/src/Closet.java b/src/Closet.java new file mode 100644 index 0000000..8f89f89 --- /dev/null +++ b/src/Closet.java @@ -0,0 +1,65 @@ +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.awt.geom.Line2D; + +/** + * Ein Schrank, der manipuliert werden kann und sich selbst auf einer Leinwand + * zeichnet. + * + * @author Claus Albowski + * @version 2.3 (sept 07) + */ +public class Closet extends Furniture { + + private static final long serialVersionUID = 1L; + + /** + * Erzeuge einen neuen Schrank mit einer Standardfarbe und Standardgroesse an + * einer Standardposition. (Standardkonstruktor) + */ + public Closet() { + xPosition = 10; + yPosition = 10; + color = Color.yellow; + orientation = 0; + isVisible = false; + width = 60; + depth = 37; + } + + /** + * Erzeuge einen neuen Schrank. + */ + public Closet(int xPosition, int yPosition, Color color, int orientation, int width, int depth) { + this.xPosition = xPosition; + this.yPosition = yPosition; + this.color = color; + this.currentColor = color; // the default color is set to the initial color + this.defaultColor = color; // the default color is set to the initial color + this.defaultWidth = width; // the default width is set to the initial width + this.defaultDepth = depth; // the default width is set to the initial depth + this.orientation = orientation; + isVisible = false; + this.width = width; + this.depth = depth; + } + + /** + * Berechnet das zu zeichnende Shape anhand der gegebenen Daten [ Zum Anzeigen + * der Attributwerte ueber Inspect muss hier die Sichtbarkeit auf public gesetzt + * werden. ] + */ + protected Shape getCurrentFigure() { + // einen GeneralPath definieren + GeneralPath schrank = new GeneralPath(); + Rectangle2D rahmen = new Rectangle2D.Double(0, 0, width, depth); + schrank.append(rahmen, false); + Line2D diagonale1 = new Line2D.Double(0, 0, width, depth); + schrank.append(diagonale1, false); + Line2D diagonale2 = new Line2D.Double(0, depth, width, 0); + schrank.append(diagonale2, false); + return transform(schrank); + } +} diff --git a/src/Furniture.java b/src/Furniture.java new file mode 100644 index 0000000..1ab490e --- /dev/null +++ b/src/Furniture.java @@ -0,0 +1,212 @@ +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.Color; +import java.io.Serializable; + +/** + * Die Klasse Moebel definiert die gemeinsamen Eigenschaften aller + * Moebelklassen. + * + * @author Claus Albowski + * @version 2.2 (aug 07) + */ +public abstract class Furniture implements Serializable { + + private static final long serialVersionUID = 1L; // default serialID + protected int xPosition; + protected int yPosition; + protected int orientation; + protected Color color; + protected Color currentColor; // this is copied from color once created + protected Color defaultColor; // this is copied from color once created + protected boolean isVisible; + protected int width; + protected int depth; + protected int defaultWidth; + protected int defaultDepth; + + // Kein Konstruktor !!!! + + /** + * Diese Methode ist der Kern der Abstraktion. + */ + protected abstract Shape getCurrentFigure(); + + /** + * Mache dieses Objekt sichtbar. Wenn es bereits sichtbar ist, tue nichts. + */ + public void show() { + if (!isVisible) { + isVisible = true; + draw(); + } + } + + /** + * transformiert das aktuelle Shape. + */ + protected Shape transform(Shape shape) { + AffineTransform t = new AffineTransform(); + t.translate(xPosition, yPosition); + Rectangle2D umriss = shape.getBounds2D(); + t.rotate(Math.toRadians(orientation), umriss.getX() + umriss.getWidth() / 2, + umriss.getY() + umriss.getHeight() / 2); + return t.createTransformedShape(shape); + } + + /** + * Mache dieses Objekt unsichtbar. Wenn es bereits unsichtbar ist, tue nichts. + */ + public void hide() { + delete(); // "tue nichts" wird in delete() abgefangen. + isVisible = false; + } + + /** + * Drehe auf den angegebenen Winkel + */ + public void rotateTo(int newAngle) { + delete(); + orientation = newAngle; + draw(); + } + + public void resetCanvas() { + delete(); + draw(); + } + + public void rotateAdd(int angleDifference) { + delete(); + orientation += angleDifference; + draw(); + } + + public void resetRotation() { + delete(); + orientation = 0; + draw(); + } + + public void changeObjectSize(int scrollDirection) { // scrollDirection is 1 or -1 depending of scrolled direction + delete(); + if (scrollDirection == 1) { + width += width / 15; + depth += depth / 15; + } else if (scrollDirection == -1 && width > 30 && depth > 30) { // depth or width shall not be under 30 to set a + // minimum size + width -= width / 15; + depth -= depth / 15; + } + draw(); + } + + public void resetObjectSize() { + delete(); + width = defaultWidth; + depth = defaultDepth; + draw(); + } + + /** + * Bewege dieses Objekt horizontal um 'entfernung' Bildschirmpunkte. + */ + public void moveHorizontal(int distance) { + delete(); + xPosition += distance; + draw(); + } + + /** + * Bewege dieses objekt vertikal um 'entfernung' Bildschirmpunkte. + */ + public void moveVertical(int distance) { + delete(); + yPosition += distance; + draw(); + } + + /** + * Sets new x and y positions. + */ + public void setPos(int xPos, int yPos) { + delete(); + xPosition = xPos; + yPosition = yPos; + draw(); + } + + /** + * Gets x position. + */ + public int getXPos() { + return xPosition; + } + + /** + * Gets y position. + */ + public int getYPos() { + return yPosition; + } + + /** + * Aendere die Farbe dieses Objektes in 'neueFarbe'. Gueltige Angaben sind + * "rot", "gelb", "blau", "gruen", "lila" und "schwarz". + */ + public void changeCurrentColor(Color newColor) { + delete(); + currentColor = newColor; + draw(); + } + + public void changeGeneralColor(Color newColor) { + color = newColor; + } + + /** + * Gets the color assigned to an object. + */ + public Color getColor() { + return color; + } + + /** + * Gets the current color of an object. + */ + public Color getCurrentColor() { + return currentColor; + } + + /** + * Gets the default color of an object. + */ + public Color getDefaultColor() { + return defaultColor; + } + + /** + * Zeichne dieses Objekt mit seinen aktuellen Werten auf den Bildschirm. + */ + private void draw() { + if (isVisible) { + Shape figur = getCurrentFigure(); + Canvas canvas = Canvas.getCanvas(); + canvas.drawFigure(this, // leinwand kennt das Objekt + currentColor, // defines the current color + figur); // definiert seinen grafischen Aspekt + canvas.wait(10); + } + } + + /** + * Loesche dieses Objekt vom Bildschirm. + */ + private void delete() { + if (isVisible) { + Canvas leinwand = Canvas.getCanvas(); + leinwand.removeFigure(this); + } + } +} diff --git a/src/MOUSEMovementTest.java b/src/MOUSEMovementTest.java new file mode 100644 index 0000000..9939683 --- /dev/null +++ b/src/MOUSEMovementTest.java @@ -0,0 +1,41 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +public class MOUSEMovementTest extends JButton { + private static final long serialVersionUID = 1L; + private volatile int draggedAtX, draggedAtY; + + public MOUSEMovementTest(String text) { + super(text); + setDoubleBuffered(false); + setMargin(new Insets(0, 0, 0, 0)); + setSize(125, 25); + setPreferredSize(new Dimension(25, 25)); + + addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + draggedAtX = e.getX(); + draggedAtY = e.getY(); + } + }); + + addMouseMotionListener(new MouseMotionAdapter() { + public void mouseDragged(MouseEvent e) { + setLocation(e.getX() - draggedAtX + getLocation().x, e.getY() - draggedAtY + getLocation().y); + System.out.println(e.getX() + " " + draggedAtX + " " + getLocation().x); + } + }); + } + + public static void MouseMovementTester() { + JFrame frame = new JFrame("DragButton"); + frame.setLayout(null); + frame.getContentPane().add(new MOUSEMovementTest("Thanks")); + frame.getContentPane().add(new MOUSEMovementTest("for")); + frame.getContentPane().add(new MOUSEMovementTest("using!")); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} \ No newline at end of file diff --git a/src/Recliner.java b/src/Recliner.java new file mode 100644 index 0000000..3d523ad --- /dev/null +++ b/src/Recliner.java @@ -0,0 +1,61 @@ +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; + +/** + * Ein Sessel, der manipuliert werden kann und sich selbst auf einer Leinwand + * zeichnet. + * + * @author Claus Albowski + * @version 2.2 (aug 07) + */ +public class Recliner extends Furniture { + private static final long serialVersionUID = 1L; + + /** + * Erzeuge einen neuen Sessel mit einer Standardfarbe und Standardgroesse an + * einer Standardposition. (Standardkonstruktor) + */ + public Recliner() { + xPosition = 250; + yPosition = 70; + color = Color.green; + orientation = 90; + isVisible = false; + width = 60; + depth = 60; + } + + public Recliner(int xPosition, int yPosition, Color color, int orientation) { + this.xPosition = xPosition; + this.yPosition = yPosition; + this.color = color; + this.currentColor = color; // the default color is set to the initial color + this.defaultColor = color; // the default color is set to the initial color + this.orientation = orientation; + isVisible = false; + width = 60; + depth = 60; + this.defaultWidth = width; // the default width is set to the initial width + this.defaultDepth = depth; // the default width is set to the initial depth + } + + /** + * Berechnet das zu zeichnende Shape anhand der gegebenen Daten + */ + protected Shape getCurrentFigure() { + // einen GeneralPath definieren + GeneralPath recliner = new GeneralPath(); + Rectangle2D leftArmRest = new Rectangle2D.Double(0, 0, width / 6, depth); + Rectangle2D rightArmRest = new Rectangle2D.Double(5 * width / 6, 0, width / 6, depth); + Rectangle2D sittingArea = new Rectangle2D.Double(width / 6, depth / 6, 2 * width / 3, depth - depth / 6); + Rectangle2D back = new Rectangle2D.Double(width / 6, 0, 2 * width / 3, depth / 6); + recliner.append(leftArmRest, false); + recliner.append(rightArmRest, false); + recliner.append(sittingArea, false); + recliner.append(back, false); + return transform(recliner); + } + +} diff --git a/src/Table.java b/src/Table.java new file mode 100644 index 0000000..079bade --- /dev/null +++ b/src/Table.java @@ -0,0 +1,55 @@ +import java.awt.Color; +import java.awt.Shape; +import java.awt.geom.Ellipse2D; + +/** + * Ein Tisch, der manipuliert werden kann und sich selbst auf einer Leinwand + * zeichnet. + * + * @author Claus Albowski + * @version 2.3 (sept 07) + */ +public class Table extends Furniture { + private static final long serialVersionUID = 1L; + + /** + * Erzeuge einen neuen Tisch mit einer Standardfarbe und Standardgroesse an + * einer Standardposition. (Standardkonstruktor) + */ + public Table() { + xPosition = 120; + yPosition = 50; + orientation = 0; + color = Color.red; + isVisible = false; + width = 120; + depth = 100; + } + + /** + * Erzeuge einen neuen Tisch. + */ + public Table(int xPosition, int yPosition, Color color, int orientation, int width, int depth) { + this.xPosition = xPosition; + this.yPosition = yPosition; + this.color = color; + this.currentColor = color; // the default color is set to the initial color + this.defaultColor = color; // the default color is set to the initial color + this.orientation = orientation; + isVisible = false; + this.width = width; + this.depth = depth; + this.defaultWidth = width; // the default width is set to the initial width + this.defaultDepth = depth; // the default width is set to the initial depth + } + + /** + * Berechnet das zu zeichnende Shape anhand der gegebenen Daten [ Zum Anzeigen + * der Attributwerte ueber Inspect muss hier die Sichtbarkeit auf public gesetzt + * werden. ] + */ + protected Shape getCurrentFigure() { + Shape tisch = new Ellipse2D.Double(0, 0, width, depth); + return transform(tisch); + } +} diff --git a/src/icons/icons8-add-48.png b/src/icons/icons8-add-48.png new file mode 100644 index 0000000000000000000000000000000000000000..6d226504de5d3c8339f8f3f2c006f4e45906f3b6 GIT binary patch literal 999 zcmVRfuM z^NC>?PQCB0%Rsi6-R(HaAOj~r+$!088N_3@tri{~nOcsjA(DZfiF~t`s$ON_6o96v zFaJpe#CJ$_E}OdfQMR$P0lk<#&P+D|Y?o~t!Y5`Ln(dpuC(}sSKzj5{s-<~#1jMK1 zwTZ(_qwiOnFD#zDT@|SpGN7CKCbrc30D9_DC(c9C?7XR)-@^)(u!8jHnN-5!0pKuO z>P&tjANv0aHPF($I)Y@y|KiYEQ{{SCQOzNgnaT}-cq~3m5gYW)6Oa~=$Q@I^g z;^zQ%Hbj^>pGmXZgFdl=L&ze&hQBW!0Jb}pdL=07+XFoh`r1^*d4)PADYJL_kKcMR z7xhs9P$A9UW9sH>cfz*^G~yxDKf}gJ6Whvpzl6ttVHgS%4>VqrB#v@2Kap46VUK}@ z&SwV!v?U@+2IAJWR5k4mdknDRbS0xm9%AZt$2kdjP=R1hhngh}+#U z&0EDSq7QU`Dx=nleqtH$X!GlV&BCgZXNx-!x|sXd@iS0PT!lE_+yU=@fN2H9Lfge! zV>jld1OR}56?e?92VU0wrUt=GFWfP|iEJSmIr8{v^B7QUbuJk>^7v`<7)UR5J^}D1 z5k+#mPA_#Xx`TeJQ3u3#lhGu_UB9D9-+92c)dGM@!zGEc4$Ug~B?9-vnPT=Pn9em$ zlN7_HT=9ZmB5)?IR+=sWkUpzy0G~*+1NX#%1|IiMer6_L*Ga-m=W8AM)?5qC_D$bo zrqTFi2|`?$?VFygRT8?G+hl2j0E)4R5`>6n%Ui!*466$@Fxfw8lV%S9co>T^F-lOK z{`szXE38mxIc@6Z_mvO3dO>`ver+KT7s}hd2U2@9BPG>SiEK#O(~U;`jc#45noOFIjOGeqOUK#&ONM!3O_3KLEG2 VG>e!8Z-4**002ovPDHLkV1j0%(c}OC literal 0 HcmV?d00001 diff --git a/src/icons/icons8-armchair-48.png b/src/icons/icons8-armchair-48.png new file mode 100644 index 0000000000000000000000000000000000000000..dbea00e181f8ca8933bd281e1dd21bd97b4b301f GIT binary patch literal 488 zcmVP)k9-7sHF-ff`wXH zXfK#pm|AS|0=B^iu#2R#vlB6hkq})Q(d3eFHzDU5*st4RXXgKJ_Kv#)i^XCwiIQwC zEtH&EbMzGSIxsU}Eswy}M7VLBuB01&lfse?wWf0d`amqrAG5$=t?2+9`ArH5n`{X8 z_rs=Sv(&(#k4-nGC7Y!N{vFnUX{-U$SOcc%`6_W&sOpZ`MKxG8-z@DWJ7d{oSFJ-o z0c*fC)_`e5-vd*NF;ba1Mq?v^h?z>^b@cKOk)k0#@F9zT_lI*{5L>e?XWjUA^MU$ zkZlR&)HVgLJbx3=thTKcHxhBa2)Syyd-hE8K%Wr>mRmw~6t^OAet4w}y#1^dE4s*- zSDN<(##w=uLYlJLYH2he)IN1+yD(97+lA|jw}H<;I6l2<`#47429&GFM}P*jtG2th e#bUAiJH7x5s7d3P@~W@^0000DL6iFC|pX#qnK3X$oqQ-~^H)6~OZq_U!D0mXR<&>L> zAjlq6P|yWIM9&@+Z+i10UUvV01uqM`dx?Sw35pRRQInX2iJ8&vo~k`$Z6`B5+tU-B z&PYF}>bKsi{{6bXx*HM_5)$G>lm;I5KeV!5(+yC^fvy-d1u+fW-(WabN1u&4#T72C2OH(;!p3L*+?>XitvQ_CS+lB7!{#}*cbl>@2I{MnH^~&7S1;*}7_(syZ zY<@c1OJ*QKAI}yUyFFg^Fiua5tkN7hg$~~wjwBu+GnnS^&EZvjL=g{=>2F`vMAL6x(CbQVW{;!7utjfgOvOT9Ei37scCXBP`$*1nJMkqDAbcgR|EkLOK553IEix zf7=m{nlT7(L&y0gv3 zt$)J3TQ|CJq05Sb(5)X-5D|1EwqlFW&yc3jX3``x$3^Z;rb(-220AI7XEUAKbM8Iw zeb3x50|^NUhZ+f!q|fL_xr%ZHID?Qy83g))6p%5Y-gP5zb%0fbWt3%L0pT0MSGmVp zyS1dl2*71^*S-ETqgl|UqA?F0d4aWxKjyKA|v4peK#0Wl7E zzX=kf0PzF}edgWmKhVR$0+q2&&9Ar65yKMvznd(E7j^iz?HID*mEsL2h8qi zqZk{&(N+PD=YWY(tDYmV3TU*DSB!10tu5s4K7}x@Nk_KO9uA0Q#>5wy0dQk(p#rqF z5PLY_Hb2DTJ5Y#HLo@-6BhYK1GJslpIAB~+ZEB%7k5Q*)7B{-me@bMxbGPV}zaP?4-{_mv#y*bad=vQ(;iyt}*5gR-=>J@Dbe z`Pa8ko&4UrwsC3r=Bp=P4phL?p_kWOi$}oquyX`Z;G?V7gZn@3d}=p2R13M5JO@UI zUOZ-w5lh?`VUj~W19~=G-d{NvCh5q&k#!7_dU)w>2? z(l3jn&rAfR#aC;Gz9^FI=<7b}ej@5MbH`uyV~g3X4qkTMTez`e!A6*l?AnG0vv<@8 zE}gV0`04&|g;MSdELTM**wuyx*0t1BY}aroHP=$zBAvU0J2Odq(=k1fV|pwNu`jk? z{iXM$(e>M*gHJU~)E+Ic&f2U{ae)6POUwRw=Av7E#GW) Q1%?8Hr>mdKI;Vst0220xtpET3 literal 0 HcmV?d00001 diff --git a/src/icons/icons8-drag-48.png b/src/icons/icons8-drag-48.png new file mode 100644 index 0000000000000000000000000000000000000000..ea580f7027ce0585ef659c18dbf9f6c170922233 GIT binary patch literal 445 zcmV;u0Yd(XP)K#16ASk=?}c zPnfBV@Y^L)Jl~Tn&%{8ZQ7>}PN{$~F&KiPiVL51J1YUlMi2k*^f99yeBH)I%g?J>$ z1$^OcF?tD7flzo`kXC|BASJvlN+&@gkQ3e(rjcMfg&s$3+~>FMz*6guW6@jE1WMBc zO7lMiKI&nyXIy}HMO86u=!UK%6 nkSoCzo*g-8RpMH*(a7K%acaUvvC%;700000NkvXXu0mjfoVK-= literal 0 HcmV?d00001 diff --git a/src/icons/icons8-edit-48.png b/src/icons/icons8-edit-48.png new file mode 100644 index 0000000000000000000000000000000000000000..c45b94c56107c076c88d5fb80afd8cb2ea9e21ff GIT binary patch literal 741 zcmVgr0 zi5n0GqpmI_u$T@Gx;Z$YBN0Nt1SN6Q#MUSYQ2!8(sl^~_`_6#^wZ6Xcr+x1<{Vp&0 z-Q6#r&%4VF2h~(l%|9LCG(cgJy}hkMhz9~vF2gt*7#fFM*KNmwlJ&k z|a6!R8&Xf`^rz*t<0SA-5C1O2LDT0y0J`8e>4M)x4GC^gN!_yUuq< zk6XfnO-HEIpD#!ngD!EElJH=IKqcX!!UC0shYAYV0S^@tunQh4AYdmvlv%)TcqpTQ z6Yx+b0jJ=h3<6HV!!`w+hKFqkr~nUJ6i@{owjiJqJZw@xHF(&BfQs<2K>=0aVFLmx z!$S!H)#1V7T}Y1X+Q&|DABEw;>S4=coTQ~@H*S$E(Zex#uo4hPCxS*=YJ`P^qwrw) zv?!u0pP~|u!$T2)+cyt|Cli6@wZh*LO29)Afz-15;`K*|nRp#oFRn|xQUxB02rMjm zIx|^~8xPkcW;A*O==0D4C X;GHa}1k7)N00000NkvXXu0mjfvXDtn literal 0 HcmV?d00001 diff --git a/src/icons/icons8-exit-48.png b/src/icons/icons8-exit-48.png new file mode 100644 index 0000000000000000000000000000000000000000..4aa53acce68e75f43d686b555a4b2f241f6bb727 GIT binary patch literal 650 zcmV;50(Jd~P)sU#Tu|X z7ybbkZu|k=77<(tf-8|$5kX6}b&=3gaS`13g+al(5fVZTen6bLT|`9}b2E1)$sNmm zwsX$O`^?N4CId($wjiv7%PCr?D3_xE!T_qum?H;@RTt4ly6Zi=JdK6|SK&7R)Yy(^ zK1^2A)s{$*{4v|37#=8``HF=H01EhA%H=1X9zy{XZkvijfe24MOQ4+hJd0|cVwS+Y zKnjRP3W!DuSmEpJ7BrofWR?(tZmJl10_KM^6N!x@l~->X9^VXQJsA2>RlRQ6**bJ z6sqU|46;O_{qecz4_1*g1+JDjK39B+EkA|qz+~qG% zv9SQfs_iJ2pvyefh5|04jS#@}Yi)_hsG572r@>I5yWX>_>1qoBz5qC}9gWQiKtHRR k`s`(h9F_UEB$C_w0~+p?C#WEvyZ`_I07*qoM6N<$g8qIY^Z)<= literal 0 HcmV?d00001 diff --git a/src/icons/icons8-file-48.png b/src/icons/icons8-file-48.png new file mode 100644 index 0000000000000000000000000000000000000000..c16c9edd9f07a2cd1a6884af37e9526125b623ef GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCwj^(N7l!{JxM1({$v}~d$}h=``anLLQYH(XSKh1a&R(y5-?(T zqOgRaL-`3qhhi7QfeIHx28nhJE{6FX`+nZk@2h(Mt76$(t#|BgX$@A)S0oplV<=@? rVeBxM@fA-%I*QQU`^+ng<*zN47NjNqTY``fBM?InO$-lh zA_O%O`PqU76P_?xqwzuCsNGs4Pt*q+5+AHS5KrH|EyspLjQU@L=K6`+NIl>jR4 zX`~n!2XIvZUliaUN8*(i5Fz2!wWk2qbfs4@i7>!>8K{%=9AiPfnyz$RI~t6+<=`rS zwI`EHbqyZ_coTr%t@C@xF>op`_=6iAl?mC&(g8F@Q?E0)6F{}>TpJ{q5grMLzLA;a zIDpn3_D$)jD1iOa)FeQ_7mvm(j{Fp%fR_B5Ybj*i`FB`+5y0e$HX! zAID92NnWQ2fDWrc%N`?GV@qpz^EHu#pi4Ob98qGvr7r^g-3H&xLkj@*4E)5de*4q}C*$8MX!d3(303xg~ z@g5oL+gBUO7X;98HjDSpWpI2TgMIxOB#TyiOTDw*`kyH8Lm!(anF457k$fJEdKu%5 zj~LCIAJy^aP5u6Je1>s;R5$3X49R`PFi_W+m~JhWn*vY-wn|yX-4}Q^VoCE0n##*s zHG@Fgie;umB&H24`HA;JuWiT2Gs}%@HGEtCSAaqGJ0J+_q%GT^twlp~wb9iN*Y!EH z=S6d|z!U)8{gWygUVTi%;Z|coyBycie@(8N0RY&{&8m!6Sjb#qXOoKeH~OK>O352Z zffMI*5RO}b0ij}n?Z=#3JYJ*X_~w9t{MfX>yXUgFm2t=33RVH6N@4h&XEms^$p4*Y zbezp1KI4gevRGgWfPo1w9sr=+M|f(PvFCjBYtH-1lbM^<4qWx-1!$;J468qp68IzT zs_GcQxKb>#s6u?ntDg#=aixcDmnP@gf}5$4F?fJHo_AfC5RRIgEEHA;OtNCZNWAg_ zfU%N$_m0t_$)ITmEWSobFw@swJgEe{@uUx5yOUs(BbOFe@ z^|ZTL!`n~$u&!FcrdkD`Z4Y3P<|!?+c~YZR1C{|?I~t5JaLTQ>=T;a?=;AWM>MBpW z@TJw?7%)#KF8IX>0F!RKO%ydNT>$a4>x1Y-PVk3w4bB-rY=6}h6OOv^c=~c4R}yy# z7X;9GF^9w*m!*_(aK1xd+r(^&Cc7Cp=*IWrGD0fP$h+@hox_Ji^Dd%oVh+_*bP(fP zH{Ne$ypX5TP-K1YI`^s&}aGp-sP5#9O%1zro26NjPBTJIw}q02PoYTFMo}J zZtvu5(b*6$-|d7v;NpU#u{+rYMi(Sb?HnQwMtC?JIwLblx;PIX3iajvq8UIJfUN9% z3uFLv>d;$c$paoQ`RcpVbsCE>f%gJfB{_W*gwutB5*<5IKJJ!7X|7o#tTZm4-aw#j z_l`cA!KlNmYgPa;5C)m~qQdIH&}8sZDXv);uz-gh{{rg{#-kiKA?^SG002ovPDHLk FV1i@zkf{Iw literal 0 HcmV?d00001 diff --git a/src/icons/icons8-info-48.png b/src/icons/icons8-info-48.png new file mode 100644 index 0000000000000000000000000000000000000000..b002707abe3900225d748c581de4032685ff375e GIT binary patch literal 1076 zcmV-41k3x0P)kp_u2)Fpck`P!^S-AU@65abw%Fpsh5{L7lI6}y^-D>|Ne1;vKraLP0L0fkY7EQ) zcue3tgQtq+_Gt{0?l-ir1P*8F2blCUz!w-u2u3ckPUDIuW&XPwD|yx6DS_@A)xDa6 z>j1t75cL{-jV1xVD>DByn{0n6+F3Y(u59f)2LB3Rw`gAnmY6VDOsTg;I=N1uFUOIJ zR?7moBrHt;V&rxy@u7T@R$TeJaoV5b*mkY@2ZPS|ljja*zSmULZ|0Izck-2-9Qtw` z2~#`(5YgFfTJ6uzCfV`-<(NQ4t7XF!zmC(dU)Fwca@uqWb&b`|GxKo5SY zdqt-ayGF|y=)O_!&=l=|c-*AE*e7G++>Up@89@Kt*O-~tybK2bO_G%(h2)N>#sK%@6jJdGzq`h2 z{s(2VHmh%2+`{(0pc)OnKF;q0RtW?!*Da%JG?)@#U_Klz9w4(eQvwoWHXJpccx*J7 zXMlJn94+E7o3&XiA)X3HjyMv_CT*q!isklc0M9~EB*xRiVk~boTAW5nXQo@BND_cS zx2#H$mivIBNf`jmmaB44W0jQ<5+aHdWVS4`WNN~`l}(g^#@Yi1%SCE)%PgsIRbw3FV2xn zXSwZbH{t;g4;%+G)qWz3BKVTyB7n5hnl~bRp(&=-iKfoIAY=hFMEhIN0Aq9|s`rYD z2Yf#Ab&S;$imngR+d|j@!S2r(G`>nwrj&|3_o^Y7XVzhs4t=tGf*{&vM~^32<}3W%^O86Ya^LST!#NZaWz;?^PSfV z5z1yc=RN1-cb9z6d!Fav-EA<=-s^V`Df)$d8ke;TrQXUSkn>G^k#8% z^4d=MbgV#+JR8h6#3J+cdVzok zZ1oJfzc?}dPzZ1D0+mXo8=4ME=a^}BWF+qK_4h8Y9Hn*xxY=Pe(_GVf*4N*wz+AO@ z13;4=OH3D@iu-*scok6SngMW)#}a)i-P+@q!I6bpZ6kr7@G%Df0>+9vXEwRcI~QP9 z`v7#i&aWWNik&w%rvmfmFAM^B%+>Ttc(^z|eXGl)+Z`ai-+A``iI~Xgok1Mp+gfci zh=OcFmoemW7sLe;R#Pr>Hd!>O=fp!2@z<4$>j69>HL-=j!^Mfo0m+Q0KuRUg14xTf z$w;w|c1Z@T3!G~-)`9T2Jd+T@=%Zs(Yi;G$1yqYi;J54A(zl#a!?t4U0u0{amPd{T zo&-QPTB`!(^WSd;!D*v$fq>l5_zQR0Xsrsc!gjw%a)@-%MrT(5DEP&ZL!fOoI%9!_ z?=Ic~V1sueIRg)m&ty#^V*w4lHB25kZA$JjX^aJkkO>pV0a8Y9i)TQu3z5YIV!qy_ zF&1E`r7&?^pr%P-ETEu&3=>8UfqyV*%nz}`e3&?LnDv55V=T~fJOUZTms=>TcxwdO9u|aG5o(v1)|Yt^fp_`gG{&&P`48}!@zYf9exKO s{+*br417VL(^oI1P8~ZI{}sabAG}-_LuX-EhyVZp07*qoM6N<$f`T;rUH||9 literal 0 HcmV?d00001 diff --git a/src/icons/icons8-opened-folder-48.png b/src/icons/icons8-opened-folder-48.png new file mode 100644 index 0000000000000000000000000000000000000000..a4621c34da5c567dbf33a3f72e78ddab797f7018 GIT binary patch literal 578 zcmV-I0=@l-P)b&Y3$GJRXn7 z^FJe_aNVd=$v|kUufjLHQw6M0Ls>xB)VEBfon%=cW*lWL?cgv7z(2mr zVG$ThJ1{H)sf5l~h`{6ojE%yrV#>d~`{-Bx0$aecJo^46jyqOBU}hR_PeQSO$zM_d z=70^|y89#!x(SR{p*qs#yqpQq;FW5WyPH6*+LMfOaEHx%v*0RFF83sxTol4{a1juR z`rZP{F%Nftfr~(?6iHY>sEb5=u7K*`7! z0!|1j`>lbS1xiIbTL^Sd9(+4%jdT(?x;C@4{v+G%k)(jIacyp?|5ZM;hdNbY3HW_A zvm@|{AA29$g9!n7#y-M*;5~3O&^?d>jm9BOR%skB$WzV-myE~b@pvq90o@f}$%qVS Q{Qv*}07*qoM6N<$f;x8lCjbBd literal 0 HcmV?d00001 diff --git a/src/icons/icons8-original-size-48.png b/src/icons/icons8-original-size-48.png new file mode 100644 index 0000000000000000000000000000000000000000..16bfe9e15d960c88bde0d35e45da29cbc49b637c GIT binary patch literal 411 zcmV;M0c8G(P)UqK~!jg?boqN!%!3k;QyYciU9*UiBMmmqTr+;3UPN7`vBr7LKh!F z`V?BRFQ7xLkKiQK*;R`bgJN@!LqVL%?M>?KrRSS6gg^h`o&*92A%qY@OfLlhaWk!C zni~ui13d4#)Ntw@;DmKnZ`Y!ZikoSrulWJMqU&lS>IS5$lxc3jzw!XE(ARuUgSGM2 z9!>tv4;7K?26>G%K$(EGr4o+UXVBW8E3}Ahc3^VT_DTs`l>i&dgs`lvOO7MkXn?cL z*^z^jgYfry_cARs`!AyvdV1Bkdi=)e-B+%MjU(IW1deV#t-}8!+h_nA!`7xq)Abph zMBWcDws*kvGn$w8C*b`6YUkpEU6;ti`xBtSKc=_d2;jtZ3v0}`#5$`3=(_G=;YEW^ zs9lRX0jVm07J#1XRt9=tzSgW(?+?Rg*JXqdLI@#T`T-_1Us9>H89x93002ovPDHLk FV1h`(yPp66 literal 0 HcmV?d00001 diff --git a/src/icons/icons8-paint-palette-48.png b/src/icons/icons8-paint-palette-48.png new file mode 100644 index 0000000000000000000000000000000000000000..b9728745ccbcf05e749a45d08eba5411b793deb2 GIT binary patch literal 1493 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 JPDHLkV1lO3>~R19 literal 0 HcmV?d00001 diff --git a/src/icons/icons8-rotate-48.png b/src/icons/icons8-rotate-48.png new file mode 100644 index 0000000000000000000000000000000000000000..7deadf3851d2f252e68e4b24060d118b9a3fbf75 GIT binary patch literal 1382 zcmV-s1)2JZP)OZX%TA}q{=*a&D`_5 z7)>hDJ6tDazVS?KyK2KnV7vjqR_frZSZ3gCQt+uij#kYTo2=w&WN?o!7(cD$d;{@A zsuefEIE?be13(1+0o`?rlg&ScW;9)SXlEw0) zvLfzOSGfKGfcfS4R@ElF5VV_!S{Y~q;Lf5b=$UaHzv`!yX$DpUCm3ij2pcDG-^!Bv ztLbi9EM(By5IZW=*g=4L05lrN8cr@bUoE7+f(;m80Yo2oW}KfD`fJH(39)TXjdc^K z7eIw1?V=~*d@*0&r5gB6A-puv?*6G5!P(Fdi0&1j3n0`;O@VNS`)ID*oG)>XwC~Ik z4*(OLRo|1<`V;`U&rWYJ_DW7Ar41>%0iSCi(Hmre} z6FU=NT+(vPv|on?iIb=f{uvnC^j^NBolT{|X!B|qu zdm=7dsfV?4K}pv|+~ymW;&dEGPetRjrej46rR;Em1K!Cc^*& ze`=qTf_-w#dO>BOADi^r0OJ`L*F6c^ZK|qbK#Dx}xEx}zHS?IR5299+Wfcr!Jg0qT z)@uU{3<&TQT@uh%8)Ap~@^Yg&5OD$Yyp~hgG9t%i7`Pp&8U;aHXmY17;OmP8syqm= zQ$tNn&N{BkahdOcp9BjU)RWZH5@IuIKn0=k3|9ao7t{ugN|ArK#U2w!NiofsAS_pzG#fq-VI zsXyH5KA$T$??KHo<2nw|MIA|~5lokT!RR~9Lu}8InitJOZ1)DE?=sP406X-pH0+7E z@-7?&RV5zzgez@Z5?=%Sf2;n?N~_I(vdk&&YVoX} zt#@|BKLya4B_s~UB~~y3Rot*xl<<~q>GJy0Tzspl3NIAp2?AQvJFIS#(xTrJadn$g zUN^#Otug>$d$GBB5CNkz-+x|4(U+BQhx?nPUF-tmbLcm_Qn3V}Uxm7>Sn)uamASh9 zM6J~#Isv>6psvXDDGQ(E-1;;o79Ay6xWS^zYG@h~)>SpiIg@GCQq oDQp>;oON6`<1_0fHgUh>UrF}b%M6Er2mk;807*qoM6N<$f|^Kwp8x;= literal 0 HcmV?d00001 diff --git a/src/icons/icons8-save-48.png b/src/icons/icons8-save-48.png new file mode 100644 index 0000000000000000000000000000000000000000..9bf58eea7f1357b645894951687b994920e52711 GIT binary patch literal 423 zcmV;Y0a*TtP)QetD1H@9;!K{<(3$- zqdHG#s8$f8kBMq7pd$Fsz))^F<8}uzYFTLQ7#JukDMsOU_4MLZ5A_5Cp_mwyF#rR^ z#KfTX00RSIPYikwFfc$oflF>kcmN+5^}s-bA@2dA>H$V(7KZ`gPr{p9~*={v+FR1_p@Zx4z;fTR%}Tz|79Yz$Ge& zA^wzsfnoAPvhAh{81i{w)B^(zMm;dlfT&VvZh#Dfo;U}s-GTxxzWBkAvhfK)bwtGg zy&ccMz`&p{L7bfdGYR8JRIaPDs%TjLaAq%>z^fqj_MU z!Dt>BXfT=w1{x6Mfr~GG(Apgs-~y3$5|xCAX_pTa81hMI6pVsVFbW11002wWOp74~ RfTjQd002ovPDHLkV1nqvr-}do literal 0 HcmV?d00001 diff --git a/src/icons/icons8-table-48.png b/src/icons/icons8-table-48.png new file mode 100644 index 0000000000000000000000000000000000000000..39a95492871ee15636968f8744bdc772770417fd GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCwj^(N7l!{JxM1({$v}~IPZ!6K zjK;TDPIERG2)JH!VR4M!AbxwJK=%gO>Wyp%L+?l#{`hWKaNe)UV7fse9|OY!v-wsW z&Vv7Bo^<3tyBoQAKYOJ#W7bL82=2Yz-x8(vOD@xQZ$~ z!66Xv3Vi_r4h!Xu;>Zn#CKT>^JM7Zs$b4qSKeIbu_SPJrD2n0}a=BT5cX$BC{;V2i zKI)#V?YTPBnSjag6I@Cd30$7tZy?JC09q~%HQ<3k+nZaqLrUHK!(If8f4EeVP`Ap}yZ9G@yZ$JfnQ+a`!P4j5